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) {
847 FIXME("Failed to create surface %p\n", object);
849 for (j = 0 ; j <= i ; j++) {
850 if(object->surfaces[j]) IWineD3DSurface_Release(object->surfaces[j]);
852 /* heap free object */
853 HeapFree(GetProcessHeap(), 0, object);
859 IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
860 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
861 /* calculate the next mipmap level */
862 tmpW = max(1, tmpW >> 1);
863 tmpH = max(1, tmpH >> 1);
866 TRACE("(%p) : Created texture %p\n", This, object);
870 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
871 UINT Width, UINT Height, UINT Depth,
872 UINT Levels, DWORD Usage,
873 WINED3DFORMAT Format, WINED3DPOOL Pool,
874 IWineD3DVolumeTexture **ppVolumeTexture,
875 HANDLE *pSharedHandle, IUnknown *parent,
876 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
878 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
879 IWineD3DVolumeTextureImpl *object;
885 /* TODO: It should only be possible to create textures for formats
886 that are reported as supported */
887 if (WINED3DFMT_UNKNOWN >= Format) {
888 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
889 return WINED3DERR_INVALIDCALL;
892 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
893 D3DINITIALIZEBASETEXTURE(object->baseTexture);
895 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
896 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
898 object->width = Width;
899 object->height = Height;
900 object->depth = Depth;
902 /* Calculate levels for mip mapping */
904 object->baseTexture.levels++;
908 while (tmpW > 1 || tmpH > 1 || tmpD > 1) {
909 tmpW = max(1, tmpW >> 1);
910 tmpH = max(1, tmpH >> 1);
911 tmpD = max(1, tmpD >> 1);
912 object->baseTexture.levels++;
914 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
917 /* Generate all the surfaces */
922 for (i = 0; i < object->baseTexture.levels; i++)
924 /* Create the volume */
925 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
926 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
928 /* Set it's container to this object */
929 IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
931 /* calcualte the next mipmap level */
932 tmpW = max(1, tmpW >> 1);
933 tmpH = max(1, tmpH >> 1);
934 tmpD = max(1, tmpD >> 1);
937 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
938 TRACE("(%p) : Created volume texture %p\n", This, object);
942 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
943 UINT Width, UINT Height, UINT Depth,
945 WINED3DFORMAT Format, WINED3DPOOL Pool,
946 IWineD3DVolume** ppVolume,
947 HANDLE* pSharedHandle, IUnknown *parent) {
949 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
950 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
952 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
954 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
955 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
957 object->currentDesc.Width = Width;
958 object->currentDesc.Height = Height;
959 object->currentDesc.Depth = Depth;
960 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
962 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
963 object->lockable = TRUE;
964 object->locked = FALSE;
965 memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
966 object->dirty = TRUE;
968 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
971 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
972 UINT Levels, DWORD Usage,
973 WINED3DFORMAT Format, WINED3DPOOL Pool,
974 IWineD3DCubeTexture **ppCubeTexture,
975 HANDLE *pSharedHandle, IUnknown *parent,
976 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
978 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
979 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
983 unsigned int pow2EdgeLength = EdgeLength;
985 /* TODO: It should only be possible to create textures for formats
986 that are reported as supported */
987 if (WINED3DFMT_UNKNOWN >= Format) {
988 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
989 return WINED3DERR_INVALIDCALL;
992 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
993 D3DINITIALIZEBASETEXTURE(object->baseTexture);
995 TRACE("(%p) Create Cube Texture\n", This);
997 /** Non-power2 support **/
999 /* Find the nearest pow2 match */
1001 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1003 object->edgeLength = EdgeLength;
1004 /* TODO: support for native non-power 2 */
1005 /* Precalculated scaling for 'faked' non power of two texture coords */
1006 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
1008 /* Calculate levels for mip mapping */
1010 object->baseTexture.levels++;
1013 tmpW = max(1, tmpW >> 1);
1014 object->baseTexture.levels++;
1016 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1019 /* Generate all the surfaces */
1021 for (i = 0; i < object->baseTexture.levels; i++) {
1023 /* Create the 6 faces */
1024 for (j = 0; j < 6; j++) {
1026 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1027 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1029 if(hr!= WINED3D_OK) {
1033 for (l = 0; l < j; l++) {
1034 IWineD3DSurface_Release(object->surfaces[j][i]);
1036 for (k = 0; k < i; k++) {
1037 for (l = 0; l < 6; l++) {
1038 IWineD3DSurface_Release(object->surfaces[l][j]);
1042 FIXME("(%p) Failed to create surface\n",object);
1043 HeapFree(GetProcessHeap(),0,object);
1044 *ppCubeTexture = NULL;
1047 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1048 TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1050 tmpW = max(1, tmpW >> 1);
1053 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1054 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1058 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1059 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1060 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1062 if (NULL == ppQuery) {
1063 /* Just a check to see if we support this type of query */
1064 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1066 case WINED3DQUERYTYPE_OCCLUSION:
1067 TRACE("(%p) occlusion query\n", This);
1068 if (GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY))
1071 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1073 case WINED3DQUERYTYPE_VCACHE:
1074 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1075 case WINED3DQUERYTYPE_VERTEXSTATS:
1076 case WINED3DQUERYTYPE_EVENT:
1077 case WINED3DQUERYTYPE_TIMESTAMP:
1078 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1079 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1080 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1081 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1082 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1083 case WINED3DQUERYTYPE_PIXELTIMINGS:
1084 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1085 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1087 FIXME("(%p) Unhandled query type %d\n", This, Type);
1092 D3DCREATEOBJECTINSTANCE(object, Query)
1093 object->type = Type;
1094 /* allocated the 'extended' data based on the type of query requested */
1096 case D3DQUERYTYPE_OCCLUSION:
1097 if(GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY)) {
1098 TRACE("(%p) Allocating data for an occlusion query\n", This);
1099 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1102 case D3DQUERYTYPE_VCACHE:
1103 case D3DQUERYTYPE_RESOURCEMANAGER:
1104 case D3DQUERYTYPE_VERTEXSTATS:
1105 case D3DQUERYTYPE_EVENT:
1106 case D3DQUERYTYPE_TIMESTAMP:
1107 case D3DQUERYTYPE_TIMESTAMPDISJOINT:
1108 case D3DQUERYTYPE_TIMESTAMPFREQ:
1109 case D3DQUERYTYPE_PIPELINETIMINGS:
1110 case D3DQUERYTYPE_INTERFACETIMINGS:
1111 case D3DQUERYTYPE_VERTEXTIMINGS:
1112 case D3DQUERYTYPE_PIXELTIMINGS:
1113 case D3DQUERYTYPE_BANDWIDTHTIMINGS:
1114 case D3DQUERYTYPE_CACHEUTILIZATION:
1116 object->extendedData = 0;
1117 FIXME("(%p) Unhandled query type %d\n",This , Type);
1119 TRACE("(%p) : Created Query %p\n", This, object);
1123 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1124 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1126 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1127 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1128 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1131 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1133 XVisualInfo template;
1134 GLXContext oldContext;
1135 Drawable oldDrawable;
1136 HRESULT hr = WINED3D_OK;
1138 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1140 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1141 * does a device hold a reference to a swap chain giving them a lifetime of the device
1142 * or does the swap chain notify the device of its destruction.
1143 *******************************/
1145 /* Check the params */
1146 if(*pPresentationParameters->BackBufferCount > 1) {
1147 ERR("App requested %d back buffers, this is not supported for now\n", *pPresentationParameters->BackBufferCount);
1148 return WINED3DERR_INVALIDCALL;
1151 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1153 /*********************
1154 * Lookup the window Handle and the relating X window handle
1155 ********************/
1157 /* Setup hwnd we are using, plus which display this equates to */
1158 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1159 if (!object->win_handle) {
1160 object->win_handle = This->createParms.hFocusWindow;
1163 object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1164 if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1165 ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1166 return WINED3DERR_NOTAVAILABLE;
1168 hDc = GetDC(object->win_handle);
1169 object->display = get_display(hDc);
1170 ReleaseDC(object->win_handle, hDc);
1171 TRACE("Using a display of %p %p\n", object->display, hDc);
1173 if (NULL == object->display || NULL == hDc) {
1174 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1175 return WINED3DERR_NOTAVAILABLE;
1178 if (object->win == 0) {
1179 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1180 return WINED3DERR_NOTAVAILABLE;
1183 * Create an opengl context for the display visual
1184 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1185 * use different properties after that point in time. FIXME: How to handle when requested format
1186 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1187 * it chooses is identical to the one already being used!
1188 **********************************/
1190 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1193 /* Create a new context for this swapchain */
1194 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1195 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1196 (or the best possible if none is requested) */
1197 TRACE("Found x visual ID : %ld\n", template.visualid);
1199 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1200 if (NULL == object->visInfo) {
1201 ERR("cannot really get XVisual\n");
1203 return WINED3DERR_NOTAVAILABLE;
1206 /* Write out some debug info about the visual/s */
1207 TRACE("Using x visual ID : %ld\n", template.visualid);
1208 TRACE(" visual info: %p\n", object->visInfo);
1209 TRACE(" num items : %d\n", num);
1210 for (n = 0;n < num; n++) {
1211 TRACE("=====item=====: %d\n", n + 1);
1212 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1213 TRACE(" screen : %d\n", object->visInfo[n].screen);
1214 TRACE(" depth : %u\n", object->visInfo[n].depth);
1215 TRACE(" class : %d\n", object->visInfo[n].class);
1216 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1217 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1218 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1219 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1220 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1221 /* log some extra glx info */
1222 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1223 TRACE(" gl_aux_buffers : %d\n", value);
1224 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1225 TRACE(" gl_buffer_size : %d\n", value);
1226 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1227 TRACE(" gl_red_size : %d\n", value);
1228 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1229 TRACE(" gl_green_size : %d\n", value);
1230 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1231 TRACE(" gl_blue_size : %d\n", value);
1232 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1233 TRACE(" gl_alpha_size : %d\n", value);
1234 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1235 TRACE(" gl_depth_size : %d\n", value);
1236 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1237 TRACE(" gl_stencil_size : %d\n", value);
1239 /* Now choose a simila visual ID*/
1241 #ifdef USE_CONTEXT_MANAGER
1243 /** TODO: use a context mamager **/
1247 IWineD3DSwapChain *implSwapChain;
1248 if (WINED3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1249 /* The first time around we create the context that is shared with all other swapchains and render targets */
1250 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1251 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1254 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1255 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1256 /* and create a new context with the implicit swapchains context as the shared context */
1257 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1258 IWineD3DSwapChain_Release(implSwapChain);
1263 XFree(object->visInfo);
1264 object->visInfo = NULL;
1266 if (NULL == object->glCtx) {
1267 ERR("cannot create glxContext\n");
1269 return WINED3DERR_NOTAVAILABLE;
1273 if (object->glCtx == NULL) {
1274 ERR("Error in context creation !\n");
1275 return WINED3DERR_INVALIDCALL;
1277 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1278 object->win_handle, object->glCtx, object->win, object->visInfo);
1281 /*********************
1282 * Windowed / Fullscreen
1283 *******************/
1286 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1287 * so we should really check to see if there is a fullscreen swapchain already
1288 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1289 **************************************/
1291 if (!*(pPresentationParameters->Windowed)) {
1297 /* Get info on the current display setup */
1298 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1299 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1302 /* Change the display settings */
1303 memset(&devmode, 0, sizeof(DEVMODEW));
1304 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1305 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1306 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1307 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1308 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1309 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1311 /* Make popup window */
1312 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1313 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1314 *(pPresentationParameters->BackBufferWidth),
1315 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1317 /* For GetDisplayMode */
1318 This->ddraw_width = devmode.dmPelsWidth;
1319 This->ddraw_height = devmode.dmPelsHeight;
1320 This->ddraw_format = *(pPresentationParameters->BackBufferFormat);
1324 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1325 * then the corresponding dimension of the client area of the hDeviceWindow
1326 * (or the focus window, if hDeviceWindow is NULL) is taken.
1327 **********************/
1329 if (*(pPresentationParameters->Windowed) &&
1330 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1331 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1334 GetClientRect(object->win_handle, &Rect);
1336 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1337 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1338 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1340 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1341 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1342 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1346 /*********************
1347 * finish off parameter initialization
1348 *******************/
1350 /* Put the correct figures in the presentation parameters */
1351 TRACE("Coppying accross presentaion paraneters\n");
1352 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1353 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1354 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1355 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1356 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1357 object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1358 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1359 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1360 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1361 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1362 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1363 object->presentParms.Flags = *(pPresentationParameters->Flags);
1364 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1365 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1368 /*********************
1369 * Create the back, front and stencil buffers
1370 *******************/
1372 TRACE("calling rendertarget CB\n");
1373 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1374 object->presentParms.BackBufferWidth,
1375 object->presentParms.BackBufferHeight,
1376 object->presentParms.BackBufferFormat,
1377 object->presentParms.MultiSampleType,
1378 object->presentParms.MultiSampleQuality,
1379 TRUE /* Lockable */,
1380 &object->frontBuffer,
1381 NULL /* pShared (always null)*/);
1382 if (object->frontBuffer != NULL)
1383 IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1384 if(object->presentParms.BackBufferCount > 0) {
1385 TRACE("calling rendertarget CB\n");
1386 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1387 object->presentParms.BackBufferWidth,
1388 object->presentParms.BackBufferHeight,
1389 object->presentParms.BackBufferFormat,
1390 object->presentParms.MultiSampleType,
1391 object->presentParms.MultiSampleQuality,
1392 TRUE /* Lockable */,
1393 &object->backBuffer,
1394 NULL /* pShared (always null)*/);
1396 object->backBuffer = NULL;
1399 if (object->backBuffer != NULL) {
1400 IWineD3DSurface_SetContainer(object->backBuffer, (IWineD3DBase *)object);
1402 glDrawBuffer(GL_BACK);
1403 checkGLcall("glDrawBuffer(GL_BACK)");
1406 /* Single buffering - draw to front buffer */
1408 glDrawBuffer(GL_FRONT);
1409 checkGLcall("glDrawBuffer(GL_FRONT)");
1413 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1414 if (pPresentationParameters->EnableAutoDepthStencil) {
1415 TRACE("Creating depth stencil buffer\n");
1416 if (This->depthStencilBuffer == NULL ) {
1417 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1418 object->presentParms.BackBufferWidth,
1419 object->presentParms.BackBufferHeight,
1420 object->presentParms.AutoDepthStencilFormat,
1421 object->presentParms.MultiSampleType,
1422 object->presentParms.MultiSampleQuality,
1423 FALSE /* FIXME: Discard */,
1424 &This->depthStencilBuffer,
1425 NULL /* pShared (always null)*/ );
1426 if (This->depthStencilBuffer != NULL)
1427 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1430 /** TODO: A check on width, height and multisample types
1431 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1432 ****************************/
1433 object->wantsDepthStencilBuffer = TRUE;
1435 object->wantsDepthStencilBuffer = FALSE;
1438 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1441 /*********************
1442 * init the default renderTarget management
1443 *******************/
1444 object->drawable = object->win;
1445 object->render_ctx = object->glCtx;
1447 if (hr == WINED3D_OK) {
1448 /*********************
1449 * Setup some defaults and clear down the buffers
1450 *******************/
1452 /** save current context and drawable **/
1453 oldContext = glXGetCurrentContext();
1454 oldDrawable = glXGetCurrentDrawable();
1456 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1457 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1458 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1460 checkGLcall("glXMakeCurrent");
1462 TRACE("Setting up the screen\n");
1463 /* Clear the screen */
1464 glClearColor(1.0, 0.0, 0.0, 0.0);
1465 checkGLcall("glClearColor");
1468 glClearStencil(0xffff);
1470 checkGLcall("glClear");
1472 glColor3f(1.0, 1.0, 1.0);
1473 checkGLcall("glColor3f");
1475 glEnable(GL_LIGHTING);
1476 checkGLcall("glEnable");
1478 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1479 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1481 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1482 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1484 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1485 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1487 /* switch back to the original context (if there was one)*/
1488 if (This->swapchains) {
1489 /** TODO: restore the context and drawable **/
1490 glXMakeCurrent(object->display, oldDrawable, oldContext);
1495 TRACE("Set swapchain to %p\n", object);
1496 } else { /* something went wrong so clean up */
1497 IUnknown* bufferParent;
1498 if (object->frontBuffer) {
1500 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1501 IUnknown_Release(bufferParent); /* once for the get parent */
1502 if (IUnknown_Release(bufferParent) > 0) {
1503 FIXME("(%p) Something's still holding the front buffer\n",This);
1506 if (object->backBuffer) {
1507 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1508 IUnknown_Release(bufferParent); /* once for the get parent */
1509 if (IUnknown_Release(bufferParent) > 0) {
1510 FIXME("(%p) Something's still holding the back buffer\n",This);
1513 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1514 /* Clean up the context */
1515 /* check that we are the current context first (we shouldn't be though!) */
1516 if (object->glCtx != 0) {
1517 if(glXGetCurrentContext() == object->glCtx) {
1518 glXMakeCurrent(object->display, None, NULL);
1520 glXDestroyContext(object->display, object->glCtx);
1522 HeapFree(GetProcessHeap(), 0, object);
1529 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1530 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1531 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1532 TRACE("(%p)\n", This);
1534 return This->NumberOfSwapChains;
1537 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1538 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1539 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1541 if(iSwapChain < This->NumberOfSwapChains) {
1542 *pSwapChain = This->swapchains[iSwapChain];
1543 IWineD3DSwapChain_AddRef(*pSwapChain);
1544 TRACE("(%p) returning %p\n", This, *pSwapChain);
1547 TRACE("Swapchain out of range\n");
1549 return WINED3DERR_INVALIDCALL;
1554 * Vertex Declaration
1556 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1557 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1558 IWineD3DVertexDeclarationImpl *object = NULL;
1559 HRESULT hr = WINED3D_OK;
1560 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1561 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1564 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1569 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1570 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1571 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1572 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1573 HRESULT hr = WINED3D_OK;
1574 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1575 object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1577 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1579 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1580 /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1581 if (pDeclaration != NULL) {
1582 IWineD3DVertexDeclaration *vertexDeclaration;
1583 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1584 if (WINED3D_OK == hr) {
1585 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1586 object->vertexDeclaration = vertexDeclaration;
1588 FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface);
1589 IWineD3DVertexShader_Release(*ppVertexShader);
1590 return WINED3DERR_INVALIDCALL;
1594 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1596 if (WINED3D_OK != hr) {
1597 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1598 IWineD3DVertexShader_Release(*ppVertexShader);
1599 return WINED3DERR_INVALIDCALL;
1602 #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. */
1603 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
1614 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1615 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1616 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1617 HRESULT hr = WINED3D_OK;
1619 D3DCREATEOBJECTINSTANCE(object, PixelShader)
1620 object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
1621 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1622 if (WINED3D_OK == hr) {
1623 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1625 WARN("(%p) : Failed to create pixel shader\n", This);
1631 HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DWORD Flags, PALETTEENTRY *PalEnt, IWineD3DPalette **Palette, IUnknown *Parent) {
1632 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1633 IWineD3DPaletteImpl *object;
1635 TRACE("(%p)->(%lx, %p, %p, %p)\n", This, Flags, PalEnt, Palette, Parent);
1637 /* Create the new object */
1638 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DPaletteImpl));
1640 ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
1641 return E_OUTOFMEMORY;
1644 object->lpVtbl = &IWineD3DPalette_Vtbl;
1646 object->Flags = Flags;
1647 object->parent = Parent;
1648 object->wineD3DDevice = This;
1649 object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
1651 object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
1654 HeapFree( GetProcessHeap(), 0, object);
1655 return E_OUTOFMEMORY;
1658 hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt);
1660 IWineD3DPalette_Release((IWineD3DPalette *) object);
1664 *Palette = (IWineD3DPalette *) object;
1669 HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
1670 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1671 IWineD3DSwapChainImpl *swapchain;
1673 TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain);
1674 if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1676 /* TODO: Test if OpenGL is compiled in and loaded */
1678 /* Setup the implicit swapchain */
1679 TRACE("Creating implicit swapchain\n");
1680 if (D3D_OK != D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain) || swapchain == NULL) {
1681 WARN("Failed to create implicit swapchain\n");
1682 return WINED3DERR_INVALIDCALL;
1685 This->NumberOfSwapChains = 1;
1686 This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
1687 if(!This->swapchains) {
1688 ERR("Out of memory!\n");
1689 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
1690 return E_OUTOFMEMORY;
1692 This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
1694 if(swapchain->backBuffer) {
1695 TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
1696 This->renderTarget = swapchain->backBuffer;
1699 TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
1700 This->renderTarget = swapchain->frontBuffer;
1702 IWineD3DSurface_AddRef(This->renderTarget);
1703 /* Depth Stencil support */
1704 This->stencilBufferTarget = This->depthStencilBuffer;
1705 if (NULL != This->stencilBufferTarget) {
1706 IWineD3DSurface_AddRef(This->stencilBufferTarget);
1709 /* Set up some starting GL setup */
1712 * Initialize openGL extension related variables
1713 * with Default values
1716 ((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps( &((IWineD3DImpl *) This->wineD3D)->gl_info, swapchain->display);
1717 /* Setup all the devices defaults */
1718 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
1720 IWineD3DImpl_CheckGraphicsMemory();
1724 { /* Set a default viewport */
1728 vp.Width = *(pPresentationParameters->BackBufferWidth);
1729 vp.Height = *(pPresentationParameters->BackBufferHeight);
1732 IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
1736 /* Determine shader mode to use based on GL caps */
1737 if (GL_SUPPORT(ARB_SHADING_LANGUAGE_100) && wined3d_settings.glslRequested
1738 && (wined3d_settings.vs_mode == VS_HW || wined3d_settings.ps_mode == PS_HW))
1739 wined3d_settings.shader_mode = SHADER_GLSL;
1740 else if ((GL_SUPPORT(ARB_VERTEX_PROGRAM) && wined3d_settings.vs_mode == VS_HW) ||
1741 (GL_SUPPORT(ARB_FRAGMENT_PROGRAM) && wined3d_settings.ps_mode == PS_HW))
1742 wined3d_settings.shader_mode = SHADER_ARB;
1744 wined3d_settings.shader_mode = SHADER_SW;
1746 /* Initialize the current view state */
1747 This->modelview_valid = 1;
1748 This->proj_valid = 0;
1749 This->view_ident = 1;
1750 This->last_was_rhw = 0;
1751 glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
1752 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
1754 /* Clear the screen */
1755 IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
1757 This->d3d_initialized = TRUE;
1761 HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface) {
1762 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1764 IUnknown* stencilBufferParent;
1765 IUnknown* swapChainParent;
1767 TRACE("(%p)\n", This);
1769 if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1771 for(texstage = 0; texstage < GL_LIMITS(textures); texstage++) {
1772 IWineD3DDevice_SetTexture(iface, texstage, NULL);
1775 /* Release the buffers (with sanity checks)*/
1776 TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
1777 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
1778 if(This->depthStencilBuffer != This->stencilBufferTarget)
1779 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
1781 This->stencilBufferTarget = NULL;
1783 TRACE("Releasing the render target at %p\n", This->renderTarget);
1784 if(IWineD3DSurface_Release(This->renderTarget) >0){
1785 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
1787 TRACE("Setting rendertarget to NULL\n");
1788 This->renderTarget = NULL;
1790 IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
1791 IUnknown_Release(stencilBufferParent); /* once for the get parent */
1792 if(IUnknown_Release(stencilBufferParent) >0){ /* the second time for when it was created */
1793 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
1795 This->depthStencilBuffer = NULL;
1797 for(i=0; i < This->NumberOfSwapChains; i++) {
1798 TRACE("Releasing the implicit swapchain %d\n", i);
1799 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
1800 IWineD3DSwapChain_GetParent(This->swapchains[i], &swapChainParent);
1801 IUnknown_Release(swapChainParent); /* once for the get parent */
1802 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
1803 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
1807 HeapFree(GetProcessHeap(), 0, This->swapchains);
1808 This->swapchains = NULL;
1809 This->NumberOfSwapChains = 0;
1811 This->d3d_initialized = FALSE;
1815 HRESULT WINAPI IWineD3DDeviceImpl_EnumDisplayModes(IWineD3DDevice *iface, DWORD Flags, UINT Width, UINT Height, WINED3DFORMAT pixelformat, LPVOID context, D3DCB_ENUMDISPLAYMODESCALLBACK callback) {
1816 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1821 TRACE("(%p)->(%lx,%d,%d,%d,%p,%p)\n", This, Flags, Width, Height, pixelformat, context, callback);
1823 for (i = 0; EnumDisplaySettingsExW(NULL, i, &DevModeW, 0); i++) {
1824 /* Ignore some modes if a description was passed */
1825 if ( (Width > 0) && (Width != DevModeW.dmPelsWidth)) continue;
1826 if ( (Height > 0) && (Height != DevModeW.dmPelsHeight)) continue;
1827 if ( (pixelformat != WINED3DFMT_UNKNOWN) && ( D3DFmtGetBpp(NULL, pixelformat) != DevModeW.dmBitsPerPel) ) continue;
1829 TRACE("Enumerating %ldx%ld@%s\n", DevModeW.dmPelsWidth, DevModeW.dmPelsHeight, debug_d3dformat(pixelformat_for_depth(DevModeW.dmBitsPerPel)));
1831 if (callback((IUnknown *) This, (UINT) DevModeW.dmPelsWidth, (UINT) DevModeW.dmPelsHeight, pixelformat_for_depth(DevModeW.dmBitsPerPel), 60.0, context) == DDENUMRET_CANCEL)
1838 HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
1840 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1843 TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1845 /* Resize the screen even without a window:
1846 * The app could have unset it with SetCooperativeLevel, but not called
1847 * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
1848 * but we don't have any hwnd
1851 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1852 devmode.dmBitsPerPel = D3DFmtGetBpp(This, pMode->Format) * 8;
1853 if(devmode.dmBitsPerPel == 24) devmode.dmBitsPerPel = 32;
1854 devmode.dmPelsWidth = pMode->Width;
1855 devmode.dmPelsHeight = pMode->Height;
1857 devmode.dmDisplayFrequency = pMode->RefreshRate;
1858 if (pMode->RefreshRate != 0) {
1859 devmode.dmFields |= DM_DISPLAYFREQUENCY;
1862 /* Only change the mode if necessary */
1863 if( (This->ddraw_width == pMode->Width) &&
1864 (This->ddraw_height == pMode->Height) &&
1865 (This->ddraw_format == pMode->Format) &&
1866 (pMode->RefreshRate == 0) ) {
1870 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
1871 if (ret != DISP_CHANGE_SUCCESSFUL) {
1872 if(devmode.dmDisplayFrequency != 0) {
1873 WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
1874 devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
1875 devmode.dmDisplayFrequency = 0;
1876 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
1878 if(ret != DISP_CHANGE_SUCCESSFUL) {
1879 return DDERR_INVALIDMODE;
1883 /* Store the new values */
1884 This->ddraw_width = pMode->Width;
1885 This->ddraw_height = pMode->Height;
1886 This->ddraw_format = pMode->Format;
1888 /* Only do this with a window of course */
1889 if(This->ddraw_window)
1890 MoveWindow(This->ddraw_window, 0, 0, pMode->Width, pMode->Height, TRUE);
1895 HRESULT WINAPI IWineD3DDeviceImpl_EnumZBufferFormats(IWineD3DDevice *iface, D3DCB_ENUMPIXELFORMATS Callback, void *Context) {
1896 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1899 WINED3DFORMAT FormatList[] = {
1906 WINED3DFMT_UNKNOWN /* Terminate the list */
1909 TRACE("(%p)->(%p,%p)\n", This, Callback, Context);
1911 while(FormatList[i] != WINED3DFMT_UNKNOWN) {
1912 TRACE("Enumerating %s\n", debug_d3dformat(FormatList[i]));
1913 ret = Callback((IUnknown *) This, FormatList[i], Context);
1914 if(ret != DDENUMRET_OK) {
1915 TRACE("Enumeration cancelled by Application\n");
1921 TRACE("End of Enumeration\n");
1926 HRESULT WINAPI IWineD3DDeviceImpl_EnumTextureFormats(IWineD3DDevice *iface, D3DCB_ENUMPIXELFORMATS Callback, void *Context) {
1927 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1932 * WINED3DFMT_A1R5G5B5 needs to be the first 16 bit format, as some dumb apps depend on this
1934 * Do not enumerate RGBA pixel formats: "some games choose the first 16 bit texture format
1935 * with alpha they find enumerated, others the last one. And both want to have the ARGB one."
1936 * But WineD3D doesn't support RGBA formats anyway...
1939 WINED3DFORMAT FormatList[] = {
1941 WINED3DFMT_A8R8G8B8,
1942 WINED3DFMT_X8R8G8B8,
1946 WINED3DFMT_A1R5G5B5,
1947 WINED3DFMT_A4R4G4B4,
1949 WINED3DFMT_X1R5G5B5,
1957 /* Terminate the list */
1961 TRACE("(%p)->(%p,%p)\n", This, Callback, Context);
1963 while(FormatList[i] != WINED3DFMT_UNKNOWN) {
1964 TRACE("Enumerating %s\n", debug_d3dformat(FormatList[i]));
1965 ret = Callback((IUnknown *) This, FormatList[i], Context);
1966 if(ret != DDENUMRET_OK) {
1967 TRACE("Enumeration cancelled by Application\n");
1973 TRACE("End of Enumeration\n");
1978 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
1979 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1980 *ppD3D= This->wineD3D;
1981 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1982 IWineD3D_AddRef(*ppD3D);
1986 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1987 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1988 * Into the video ram as possible and seeing how many fit
1989 * you can also get the correct initial value from via X and ATI's driver
1990 *******************/
1991 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1992 static BOOL showfixmes = TRUE;
1994 FIXME("(%p) : stub, emulating %dMB for now, returning %dMB\n", This, (emulated_textureram/(1024*1024)),
1995 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1998 TRACE("(%p) : emulating %dMB for now, returning %dMB\n", This, (emulated_textureram/(1024*1024)),
1999 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2000 /* videomemory is simulated videomemory + AGP memory left */
2001 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
2009 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
2010 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2011 HRESULT hr = WINED3D_OK;
2013 /* Update the current state block */
2014 This->updateStateBlock->fvf = fvf;
2015 This->updateStateBlock->changed.fvf = TRUE;
2016 This->updateStateBlock->set.fvf = TRUE;
2018 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
2021 /* clear down the vertex declaration
2022 NOTE: Axis and Allies doesn't work properly otherwise
2023 (may be a stateblock problem though!)
2025 hr = IWineD3DDevice_SetVertexDeclaration(iface, NULL);
2032 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
2033 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2034 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
2035 *pfvf = This->stateBlock->fvf;
2040 * Get / Set Stream Source
2042 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
2043 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2044 IWineD3DVertexBuffer *oldSrc;
2046 /**TODO: instance and index data, see
2047 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2049 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
2052 /* D3d9 only, but shouldn't hurt d3d8 */
2055 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2057 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2058 FIXME("stream index data not supported\n");
2060 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2061 FIXME("stream instance data not supported\n");
2065 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2067 if (StreamNumber >= MAX_STREAMS) {
2068 WARN("Stream out of range %d\n", StreamNumber);
2069 return WINED3DERR_INVALIDCALL;
2072 oldSrc = This->stateBlock->streamSource[StreamNumber];
2073 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
2075 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
2076 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
2077 This->updateStateBlock->streamStride[StreamNumber] = Stride;
2078 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
2079 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
2080 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
2082 /* Handle recording of state blocks */
2083 if (This->isRecordingState) {
2084 TRACE("Recording... not performing anything\n");
2088 /* Not recording... */
2089 /* Need to do a getParent and pass the reffs up */
2090 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
2091 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2092 so for now, just count internally */
2093 if (pStreamData != NULL) {
2094 IWineD3DVertexBuffer_AddRef(pStreamData);
2096 if (oldSrc != NULL) {
2097 IWineD3DVertexBuffer_Release(oldSrc);
2103 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2104 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2107 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
2108 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
2111 streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2113 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2114 FIXME("stream index data not supported\n");
2116 if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
2117 FIXME("stream instance data not supported\n");
2121 StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
2123 if (StreamNumber >= MAX_STREAMS) {
2124 WARN("Stream out of range %d\n", StreamNumber);
2125 return WINED3DERR_INVALIDCALL;
2127 *pStream = This->stateBlock->streamSource[StreamNumber];
2128 *pStride = This->stateBlock->streamStride[StreamNumber];
2129 *pOffset = This->stateBlock->streamOffset[StreamNumber];
2131 if (*pStream == NULL) {
2132 FIXME("Attempting to get an empty stream %d, returning WINED3DERR_INVALIDCALL\n", StreamNumber);
2133 return WINED3DERR_INVALIDCALL;
2136 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2140 /*Should be quite easy, just an extension of vertexdata
2142 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2144 The divider is a bit odd though
2146 VertexOffset = StartVertex / Divider * StreamStride +
2147 VertexIndex / Divider * StreamStride + StreamOffset
2150 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
2151 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2153 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2154 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA );
2156 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
2157 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
2158 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
2160 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
2161 FIXME("Stream indexing not fully supported\n");
2167 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
2168 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2170 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2171 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2173 TRACE("(%p) : returning %d\n", This, *Divider);
2179 * Get / Set & Multiply Transform
2181 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
2182 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2184 /* Most of this routine, comments included copied from ddraw tree initially: */
2185 TRACE("(%p) : Transform State=%d\n", This, d3dts);
2187 /* Handle recording of state blocks */
2188 if (This->isRecordingState) {
2189 TRACE("Recording... not performing anything\n");
2190 This->updateStateBlock->changed.transform[d3dts] = TRUE;
2191 This->updateStateBlock->set.transform[d3dts] = TRUE;
2192 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
2197 * If the new matrix is the same as the current one,
2198 * we cut off any further processing. this seems to be a reasonable
2199 * optimization because as was noticed, some apps (warcraft3 for example)
2200 * tend towards setting the same matrix repeatedly for some reason.
2202 * From here on we assume that the new matrix is different, wherever it matters.
2204 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
2205 TRACE("The app is setting the same matrix over again\n");
2208 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2212 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2213 where ViewMat = Camera space, WorldMat = world space.
2215 In OpenGL, camera and world space is combined into GL_MODELVIEW
2216 matrix. The Projection matrix stay projection matrix.
2219 /* Capture the times we can just ignore the change for now */
2220 if (d3dts == D3DTS_WORLDMATRIX(0)) {
2221 This->modelview_valid = FALSE;
2224 } else if (d3dts == D3DTS_PROJECTION) {
2225 This->proj_valid = FALSE;
2228 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
2229 /* Indexed Vertex Blending Matrices 256 -> 511 */
2230 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
2231 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
2235 /* Now we really are going to have to change a matrix */
2238 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
2239 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
2240 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
2243 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2244 * NOTE: We have to reset the positions even if the light/plane is not currently
2245 * enabled, since the call to enable it will not reset the position.
2246 * NOTE2: Apparently texture transforms do NOT need reapplying
2249 PLIGHTINFOEL *lightChain = NULL;
2250 This->modelview_valid = FALSE;
2251 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2253 glMatrixMode(GL_MODELVIEW);
2254 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2256 glLoadMatrixf((float *)lpmatrix);
2257 checkGLcall("glLoadMatrixf(...)");
2260 lightChain = This->stateBlock->lights;
2261 while (lightChain && lightChain->glIndex != -1) {
2262 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
2263 checkGLcall("glLightfv posn");
2264 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
2265 checkGLcall("glLightfv dirn");
2266 lightChain = lightChain->next;
2269 /* Reset Clipping Planes if clipping is enabled */
2270 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2271 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
2272 checkGLcall("glClipPlane");
2276 } else { /* What was requested!?? */
2277 WARN("invalid matrix specified: %i\n", d3dts);
2280 /* Release lock, all done */
2285 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
2286 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2287 TRACE("(%p) : for Transform State %d\n", This, State);
2288 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
2292 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
2293 D3DMATRIX *mat = NULL;
2296 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2297 * below means it will be recorded in a state block change, but it
2298 * works regardless where it is recorded.
2299 * If this is found to be wrong, change to StateBlock.
2301 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2302 TRACE("(%p) : For state %u\n", This, State);
2304 if (State < HIGHEST_TRANSFORMSTATE)
2306 mat = &This->updateStateBlock->transforms[State];
2308 FIXME("Unhandled transform state!!\n");
2311 multiply_matrix(&temp, mat, (D3DMATRIX *) pMatrix);
2313 /* Apply change via set transform - will reapply to eg. lights this way */
2314 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2319 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2321 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2322 you can reference any indexes you want as long as that number max are enabled at any
2323 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2324 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2325 but when recording, just build a chain pretty much of commands to be replayed. */
2327 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2329 PLIGHTINFOEL *object, *temp;
2331 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2332 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2334 /* If recording state block, just add to end of lights chain */
2335 if (This->isRecordingState) {
2336 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2337 if (NULL == object) {
2338 return WINED3DERR_OUTOFVIDEOMEMORY;
2340 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2341 object->OriginalIndex = Index;
2342 object->glIndex = -1;
2343 object->changed = TRUE;
2345 /* Add to the END of the chain of lights changes to be replayed */
2346 if (This->updateStateBlock->lights == NULL) {
2347 This->updateStateBlock->lights = object;
2349 temp = This->updateStateBlock->lights;
2350 while (temp->next != NULL) temp=temp->next;
2351 temp->next = object;
2353 TRACE("Recording... not performing anything more\n");
2357 /* Ok, not recording any longer so do real work */
2358 object = This->stateBlock->lights;
2359 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2361 /* If we didn't find it in the list of lights, time to add it */
2362 if (object == NULL) {
2363 PLIGHTINFOEL *insertAt,*prevPos;
2365 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2366 if (NULL == object) {
2367 return WINED3DERR_OUTOFVIDEOMEMORY;
2369 object->OriginalIndex = Index;
2370 object->glIndex = -1;
2372 /* Add it to the front of list with the idea that lights will be changed as needed
2373 BUT after any lights currently assigned GL indexes */
2374 insertAt = This->stateBlock->lights;
2376 while (insertAt != NULL && insertAt->glIndex != -1) {
2378 insertAt = insertAt->next;
2381 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2382 This->stateBlock->lights = object;
2383 } else if (insertAt == NULL) { /* End of list */
2384 prevPos->next = object;
2385 object->prev = prevPos;
2386 } else { /* Middle of chain */
2387 if (prevPos == NULL) {
2388 This->stateBlock->lights = object;
2390 prevPos->next = object;
2392 object->prev = prevPos;
2393 object->next = insertAt;
2394 insertAt->prev = object;
2398 /* Initialize the object */
2399 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,
2400 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2401 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2402 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2403 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2404 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2405 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2407 /* Save away the information */
2408 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2410 switch (pLight->Type) {
2411 case D3DLIGHT_POINT:
2413 object->lightPosn[0] = pLight->Position.x;
2414 object->lightPosn[1] = pLight->Position.y;
2415 object->lightPosn[2] = pLight->Position.z;
2416 object->lightPosn[3] = 1.0f;
2417 object->cutoff = 180.0f;
2421 case D3DLIGHT_DIRECTIONAL:
2423 object->lightPosn[0] = -pLight->Direction.x;
2424 object->lightPosn[1] = -pLight->Direction.y;
2425 object->lightPosn[2] = -pLight->Direction.z;
2426 object->lightPosn[3] = 0.0;
2427 object->exponent = 0.0f;
2428 object->cutoff = 180.0f;
2433 object->lightPosn[0] = pLight->Position.x;
2434 object->lightPosn[1] = pLight->Position.y;
2435 object->lightPosn[2] = pLight->Position.z;
2436 object->lightPosn[3] = 1.0;
2439 object->lightDirn[0] = pLight->Direction.x;
2440 object->lightDirn[1] = pLight->Direction.y;
2441 object->lightDirn[2] = pLight->Direction.z;
2442 object->lightDirn[3] = 1.0;
2445 * opengl-ish and d3d-ish spot lights use too different models for the
2446 * light "intensity" as a function of the angle towards the main light direction,
2447 * so we only can approximate very roughly.
2448 * however spot lights are rather rarely used in games (if ever used at all).
2449 * furthermore if still used, probably nobody pays attention to such details.
2451 if (pLight->Falloff == 0) {
2454 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2456 if (rho < 0.0001) rho = 0.0001f;
2457 object->exponent = -0.3/log(cos(rho/2));
2458 object->cutoff = pLight->Phi*90/M_PI;
2464 FIXME("Unrecognized light type %d\n", pLight->Type);
2467 /* Update the live definitions if the light is currently assigned a glIndex */
2468 if (object->glIndex != -1) {
2469 setup_light(iface, object->glIndex, object);
2474 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2475 PLIGHTINFOEL *lightInfo = NULL;
2476 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2477 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2479 /* Locate the light in the live lights */
2480 lightInfo = This->stateBlock->lights;
2481 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2483 if (lightInfo == NULL) {
2484 TRACE("Light information requested but light not defined\n");
2485 return WINED3DERR_INVALIDCALL;
2488 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2493 * Get / Set Light Enable
2494 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2496 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2497 PLIGHTINFOEL *lightInfo = NULL;
2498 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2499 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2501 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2502 if (This->isRecordingState) {
2503 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2504 if (NULL == lightInfo) {
2505 return WINED3DERR_OUTOFVIDEOMEMORY;
2507 lightInfo->OriginalIndex = Index;
2508 lightInfo->glIndex = -1;
2509 lightInfo->enabledChanged = TRUE;
2511 /* Add to the END of the chain of lights changes to be replayed */
2512 if (This->updateStateBlock->lights == NULL) {
2513 This->updateStateBlock->lights = lightInfo;
2515 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2516 while (temp->next != NULL) temp=temp->next;
2517 temp->next = lightInfo;
2519 TRACE("Recording... not performing anything more\n");
2523 /* Not recording... So, locate the light in the live lights */
2524 lightInfo = This->stateBlock->lights;
2525 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2527 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2528 if (lightInfo == NULL) {
2529 D3DLIGHT9 lightParms;
2530 /* Warning - untested code :-) Prob safe to change fixme to a trace but
2531 wait until someone confirms it seems to work! */
2532 TRACE("Light enabled requested but light not defined, so defining one!\n");
2533 lightParms.Type = D3DLIGHT_DIRECTIONAL;
2534 lightParms.Diffuse.r = 1.0;
2535 lightParms.Diffuse.g = 1.0;
2536 lightParms.Diffuse.b = 1.0;
2537 lightParms.Diffuse.a = 0.0;
2538 lightParms.Specular.r = 0.0;
2539 lightParms.Specular.g = 0.0;
2540 lightParms.Specular.b = 0.0;
2541 lightParms.Specular.a = 0.0;
2542 lightParms.Ambient.r = 0.0;
2543 lightParms.Ambient.g = 0.0;
2544 lightParms.Ambient.b = 0.0;
2545 lightParms.Ambient.a = 0.0;
2546 lightParms.Position.x = 0.0;
2547 lightParms.Position.y = 0.0;
2548 lightParms.Position.z = 0.0;
2549 lightParms.Direction.x = 0.0;
2550 lightParms.Direction.y = 0.0;
2551 lightParms.Direction.z = 1.0;
2552 lightParms.Range = 0.0;
2553 lightParms.Falloff = 0.0;
2554 lightParms.Attenuation0 = 0.0;
2555 lightParms.Attenuation1 = 0.0;
2556 lightParms.Attenuation2 = 0.0;
2557 lightParms.Theta = 0.0;
2558 lightParms.Phi = 0.0;
2559 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2561 /* Search for it again! Should be fairly quick as near head of list */
2562 lightInfo = This->stateBlock->lights;
2563 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2564 if (lightInfo == NULL) {
2565 FIXME("Adding default lights has failed dismally\n");
2566 return WINED3DERR_INVALIDCALL;
2570 /* OK, we now have a light... */
2571 if (Enable == FALSE) {
2573 /* If we are disabling it, check it was enabled, and
2574 still only do something if it has assigned a glIndex (which it should have!) */
2575 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2576 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2578 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2579 checkGLcall("glDisable GL_LIGHT0+Index");
2582 TRACE("Nothing to do as light was not enabled\n");
2584 lightInfo->lightEnabled = FALSE;
2587 /* We are enabling it. If it is enabled, it's really simple */
2588 if (lightInfo->lightEnabled) {
2590 TRACE("Nothing to do as light was enabled\n");
2592 /* If it already has a glIndex, it's still simple */
2593 } else if (lightInfo->glIndex != -1) {
2594 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2595 lightInfo->lightEnabled = TRUE;
2597 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2598 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2601 /* Otherwise got to find space - lights are ordered gl indexes first */
2603 PLIGHTINFOEL *bsf = NULL;
2604 PLIGHTINFOEL *pos = This->stateBlock->lights;
2605 PLIGHTINFOEL *prev = NULL;
2609 /* Try to minimize changes as much as possible */
2610 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2612 /* Try to remember which index can be replaced if necessary */
2613 if (bsf==NULL && pos->lightEnabled == FALSE) {
2614 /* Found a light we can replace, save as best replacement */
2618 /* Step to next space */
2624 /* If we have too many active lights, fail the call */
2625 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2626 FIXME("Program requests too many concurrent lights\n");
2627 return WINED3DERR_INVALIDCALL;
2629 /* If we have allocated all lights, but not all are enabled,
2630 reuse one which is not enabled */
2631 } else if (Index == This->maxConcurrentLights) {
2632 /* use bsf - Simply swap the new light and the BSF one */
2633 PLIGHTINFOEL *bsfNext = bsf->next;
2634 PLIGHTINFOEL *bsfPrev = bsf->prev;
2637 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2638 if (bsf->prev != NULL) {
2639 bsf->prev->next = lightInfo;
2641 This->stateBlock->lights = lightInfo;
2644 /* If not side by side, lots of chains to update */
2645 if (bsf->next != lightInfo) {
2646 lightInfo->prev->next = bsf;
2647 bsf->next->prev = lightInfo;
2648 bsf->next = lightInfo->next;
2649 bsf->prev = lightInfo->prev;
2650 lightInfo->next = bsfNext;
2651 lightInfo->prev = bsfPrev;
2655 bsf->prev = lightInfo;
2656 bsf->next = lightInfo->next;
2657 lightInfo->next = bsf;
2658 lightInfo->prev = bsfPrev;
2663 glIndex = bsf->glIndex;
2665 lightInfo->glIndex = glIndex;
2666 lightInfo->lightEnabled = TRUE;
2668 /* Finally set up the light in gl itself */
2669 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2671 setup_light(iface, glIndex, lightInfo);
2672 glEnable(GL_LIGHT0 + glIndex);
2673 checkGLcall("glEnable GL_LIGHT0 new setup");
2676 /* If we reached the end of the allocated lights, with space in the
2677 gl lights, setup a new light */
2678 } else if (pos->glIndex == -1) {
2680 /* We reached the end of the allocated gl lights, so already
2681 know the index of the next one! */
2683 lightInfo->glIndex = glIndex;
2684 lightInfo->lightEnabled = TRUE;
2686 /* In an ideal world, it's already in the right place */
2687 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2688 /* No need to move it */
2690 /* Remove this light from the list */
2691 lightInfo->prev->next = lightInfo->next;
2692 if (lightInfo->next != NULL) {
2693 lightInfo->next->prev = lightInfo->prev;
2696 /* Add in at appropriate place (inbetween prev and pos) */
2697 lightInfo->prev = prev;
2698 lightInfo->next = pos;
2700 This->stateBlock->lights = lightInfo;
2702 prev->next = lightInfo;
2705 pos->prev = lightInfo;
2709 /* Finally set up the light in gl itself */
2710 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2712 setup_light(iface, glIndex, lightInfo);
2713 glEnable(GL_LIGHT0 + glIndex);
2714 checkGLcall("glEnable GL_LIGHT0 new setup");
2723 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2725 PLIGHTINFOEL *lightInfo = NULL;
2726 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2727 TRACE("(%p) : for idx(%ld)\n", This, Index);
2729 /* Locate the light in the live lights */
2730 lightInfo = This->stateBlock->lights;
2731 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2733 if (lightInfo == NULL) {
2734 TRACE("Light enabled state requested but light not defined\n");
2735 return WINED3DERR_INVALIDCALL;
2737 *pEnable = lightInfo->lightEnabled;
2742 * Get / Set Clip Planes
2744 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2745 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2746 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2748 /* Validate Index */
2749 if (Index >= GL_LIMITS(clipplanes)) {
2750 TRACE("Application has requested clipplane this device doesn't support\n");
2751 return WINED3DERR_INVALIDCALL;
2754 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2755 This->updateStateBlock->set.clipplane[Index] = TRUE;
2756 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2757 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2758 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2759 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2761 /* Handle recording of state blocks */
2762 if (This->isRecordingState) {
2763 TRACE("Recording... not performing anything\n");
2771 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2772 glMatrixMode(GL_MODELVIEW);
2774 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2776 TRACE("Clipplane [%f,%f,%f,%f]\n",
2777 This->updateStateBlock->clipplane[Index][0],
2778 This->updateStateBlock->clipplane[Index][1],
2779 This->updateStateBlock->clipplane[Index][2],
2780 This->updateStateBlock->clipplane[Index][3]);
2781 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2782 checkGLcall("glClipPlane");
2790 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2791 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2792 TRACE("(%p) : for idx %ld\n", This, Index);
2794 /* Validate Index */
2795 if (Index >= GL_LIMITS(clipplanes)) {
2796 TRACE("Application has requested clipplane this device doesn't support\n");
2797 return WINED3DERR_INVALIDCALL;
2800 pPlane[0] = This->stateBlock->clipplane[Index][0];
2801 pPlane[1] = This->stateBlock->clipplane[Index][1];
2802 pPlane[2] = This->stateBlock->clipplane[Index][2];
2803 pPlane[3] = This->stateBlock->clipplane[Index][3];
2808 * Get / Set Clip Plane Status
2809 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2811 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2812 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2813 FIXME("(%p) : stub\n", This);
2814 if (NULL == pClipStatus) {
2815 return WINED3DERR_INVALIDCALL;
2817 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2818 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2822 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2823 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2824 FIXME("(%p) : stub\n", This);
2825 if (NULL == pClipStatus) {
2826 return WINED3DERR_INVALIDCALL;
2828 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2829 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2834 * Get / Set Material
2835 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2837 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2838 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2840 This->updateStateBlock->changed.material = TRUE;
2841 This->updateStateBlock->set.material = TRUE;
2842 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2844 /* Handle recording of state blocks */
2845 if (This->isRecordingState) {
2846 TRACE("Recording... not performing anything\n");
2851 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2852 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2853 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2854 pMaterial->Ambient.b, pMaterial->Ambient.a);
2855 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2856 pMaterial->Specular.b, pMaterial->Specular.a);
2857 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2858 pMaterial->Emissive.b, pMaterial->Emissive.a);
2859 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2861 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2862 checkGLcall("glMaterialfv(GL_AMBIENT)");
2863 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2864 checkGLcall("glMaterialfv(GL_DIFFUSE)");
2866 /* Only change material color if specular is enabled, otherwise it is set to black */
2867 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2868 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2869 checkGLcall("glMaterialfv(GL_SPECULAR");
2871 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2872 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2873 checkGLcall("glMaterialfv(GL_SPECULAR");
2875 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2876 checkGLcall("glMaterialfv(GL_EMISSION)");
2877 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2878 checkGLcall("glMaterialf(GL_SHININESS");
2884 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2885 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2886 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2887 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2888 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2889 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2890 pMaterial->Ambient.b, pMaterial->Ambient.a);
2891 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2892 pMaterial->Specular.b, pMaterial->Specular.a);
2893 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2894 pMaterial->Emissive.b, pMaterial->Emissive.a);
2895 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2903 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2904 UINT BaseVertexIndex) {
2905 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2906 IWineD3DIndexBuffer *oldIdxs;
2908 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2909 oldIdxs = This->updateStateBlock->pIndexData;
2911 This->updateStateBlock->changed.indices = TRUE;
2912 This->updateStateBlock->set.indices = TRUE;
2913 This->updateStateBlock->pIndexData = pIndexData;
2914 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2916 /* Handle recording of state blocks */
2917 if (This->isRecordingState) {
2918 TRACE("Recording... not performing anything\n");
2922 if (NULL != pIndexData) {
2923 IWineD3DIndexBuffer_AddRef(pIndexData);
2925 if (NULL != oldIdxs) {
2926 IWineD3DIndexBuffer_Release(oldIdxs);
2931 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2932 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2934 *ppIndexData = This->stateBlock->pIndexData;
2936 /* up ref count on ppindexdata */
2938 IWineD3DIndexBuffer_AddRef(*ppIndexData);
2939 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2940 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2942 TRACE("(%p) No index data set\n", This);
2944 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
2950 * Get / Set Viewports
2952 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2953 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2955 TRACE("(%p)\n", This);
2956 This->updateStateBlock->changed.viewport = TRUE;
2957 This->updateStateBlock->set.viewport = TRUE;
2958 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2960 /* Handle recording of state blocks */
2961 if (This->isRecordingState) {
2962 TRACE("Recording... not performing anything\n");
2965 This->viewport_changed = TRUE;
2969 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2970 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2972 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2973 checkGLcall("glDepthRange");
2974 /* Note: GL requires lower left, DirectX supplies upper left */
2975 /* TODO: replace usage of renderTarget with context management */
2976 glViewport(pViewport->X,
2977 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2978 pViewport->Width, pViewport->Height);
2980 checkGLcall("glViewport");
2988 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2989 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2990 TRACE("(%p)\n", This);
2991 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2996 * Get / Set Render States
2997 * TODO: Verify against dx9 definitions
2999 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
3001 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3002 DWORD OldValue = This->stateBlock->renderState[State];
3004 /* Simple way of referring to either a DWORD or a 4 byte float */
3010 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
3011 This->updateStateBlock->changed.renderState[State] = TRUE;
3012 This->updateStateBlock->set.renderState[State] = TRUE;
3013 This->updateStateBlock->renderState[State] = Value;
3015 /* Handle recording of state blocks */
3016 if (This->isRecordingState) {
3017 TRACE("Recording... not performing anything\n");
3024 case WINED3DRS_FILLMODE :
3025 switch ((D3DFILLMODE) Value) {
3026 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
3027 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
3028 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
3030 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
3032 checkGLcall("glPolygonMode (fillmode)");
3035 case WINED3DRS_LIGHTING :
3037 glEnable(GL_LIGHTING);
3038 checkGLcall("glEnable GL_LIGHTING");
3040 glDisable(GL_LIGHTING);
3041 checkGLcall("glDisable GL_LIGHTING");
3045 case WINED3DRS_ZENABLE :
3046 switch ((D3DZBUFFERTYPE) Value) {
3048 glDisable(GL_DEPTH_TEST);
3049 checkGLcall("glDisable GL_DEPTH_TEST");
3052 glEnable(GL_DEPTH_TEST);
3053 checkGLcall("glEnable GL_DEPTH_TEST");
3056 glEnable(GL_DEPTH_TEST);
3057 checkGLcall("glEnable GL_DEPTH_TEST");
3058 FIXME("W buffer is not well handled\n");
3061 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
3065 case WINED3DRS_CULLMODE :
3067 /* If we are culling "back faces with clockwise vertices" then
3068 set front faces to be counter clockwise and enable culling
3070 switch ((D3DCULL) Value) {
3072 glDisable(GL_CULL_FACE);
3073 checkGLcall("glDisable GL_CULL_FACE");
3076 glEnable(GL_CULL_FACE);
3077 checkGLcall("glEnable GL_CULL_FACE");
3078 if (This->renderUpsideDown) {
3080 checkGLcall("glFrontFace GL_CW");
3082 glFrontFace(GL_CCW);
3083 checkGLcall("glFrontFace GL_CCW");
3085 glCullFace(GL_BACK);
3088 glEnable(GL_CULL_FACE);
3089 checkGLcall("glEnable GL_CULL_FACE");
3090 if (This->renderUpsideDown) {
3091 glFrontFace(GL_CCW);
3092 checkGLcall("glFrontFace GL_CCW");
3095 checkGLcall("glFrontFace GL_CW");
3097 glCullFace(GL_BACK);
3100 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
3104 case WINED3DRS_SHADEMODE :
3105 switch ((D3DSHADEMODE) Value) {
3107 glShadeModel(GL_FLAT);
3108 checkGLcall("glShadeModel");
3110 case D3DSHADE_GOURAUD:
3111 glShadeModel(GL_SMOOTH);
3112 checkGLcall("glShadeModel");
3114 case D3DSHADE_PHONG:
3115 FIXME("D3DSHADE_PHONG isn't supported?\n");
3118 return WINED3DERR_INVALIDCALL;
3120 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
3124 case WINED3DRS_DITHERENABLE :
3126 glEnable(GL_DITHER);
3127 checkGLcall("glEnable GL_DITHER");
3129 glDisable(GL_DITHER);
3130 checkGLcall("glDisable GL_DITHER");
3134 case WINED3DRS_ZWRITEENABLE :
3137 checkGLcall("glDepthMask");
3140 checkGLcall("glDepthMask");
3144 case WINED3DRS_ZFUNC :
3146 int glParm = GL_LESS;
3148 switch ((D3DCMPFUNC) Value) {
3149 case D3DCMP_NEVER: glParm=GL_NEVER; break;
3150 case D3DCMP_LESS: glParm=GL_LESS; break;
3151 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
3152 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
3153 case D3DCMP_GREATER: glParm=GL_GREATER; break;
3154 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
3155 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
3156 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
3158 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3160 glDepthFunc(glParm);
3161 checkGLcall("glDepthFunc");
3165 case WINED3DRS_AMBIENT :
3168 D3DCOLORTOGLFLOAT4(Value, col);
3169 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
3170 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
3171 checkGLcall("glLightModel for MODEL_AMBIENT");
3176 case WINED3DRS_ALPHABLENDENABLE :
3179 checkGLcall("glEnable GL_BLEND");
3181 glDisable(GL_BLEND);
3182 checkGLcall("glDisable GL_BLEND");
3186 case WINED3DRS_SRCBLEND :
3187 case WINED3DRS_DESTBLEND :
3189 int newVal = GL_ZERO;
3191 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
3192 case D3DBLEND_ONE : newVal = GL_ONE; break;
3193 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
3194 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
3195 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
3196 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
3197 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
3198 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
3199 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
3200 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
3201 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
3203 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
3204 This->srcBlend = newVal;
3205 This->dstBlend = newVal;
3208 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
3209 This->srcBlend = newVal;
3210 This->dstBlend = newVal;
3213 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
3216 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
3217 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
3218 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
3219 glBlendFunc(This->srcBlend, This->dstBlend);
3221 checkGLcall("glBlendFunc");
3225 case WINED3DRS_ALPHATESTENABLE :
3226 case WINED3DRS_ALPHAFUNC :
3227 case WINED3DRS_ALPHAREF :
3228 case WINED3DRS_COLORKEYENABLE :
3231 float ref = GL_LESS;
3232 BOOL enable_ckey = FALSE;
3234 IWineD3DSurfaceImpl *surf;
3236 /* Find out if the texture on the first stage has a ckey set */
3237 if(This->stateBlock->textures[0]) {
3238 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)This->stateBlock->textures[0])->surfaces[0];
3239 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
3242 if (This->stateBlock->renderState[WINED3DRS_ALPHATESTENABLE] ||
3243 (This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
3244 glEnable(GL_ALPHA_TEST);
3245 checkGLcall("glEnable GL_ALPHA_TEST");
3247 glDisable(GL_ALPHA_TEST);
3248 checkGLcall("glDisable GL_ALPHA_TEST");
3249 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
3255 if(This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
3256 glParm = GL_NOTEQUAL;
3259 ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
3261 switch ((D3DCMPFUNC) This->stateBlock->renderState[WINED3DRS_ALPHAFUNC]) {
3262 case D3DCMP_NEVER: glParm = GL_NEVER; break;
3263 case D3DCMP_LESS: glParm = GL_LESS; break;
3264 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
3265 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
3266 case D3DCMP_GREATER: glParm = GL_GREATER; break;
3267 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
3268 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
3269 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
3271 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3274 This->alphafunc = glParm;
3275 glAlphaFunc(glParm, ref);
3276 checkGLcall("glAlphaFunc");
3280 case WINED3DRS_CLIPPLANEENABLE :
3281 case WINED3DRS_CLIPPING :
3283 /* Ensure we only do the changed clip planes */
3284 DWORD enable = 0xFFFFFFFF;
3285 DWORD disable = 0x00000000;
3287 /* If enabling / disabling all */
3288 if (State == WINED3DRS_CLIPPING) {
3290 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3293 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3297 enable = Value & ~OldValue;
3298 disable = ~Value & OldValue;
3301 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3302 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3303 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3304 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3305 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3306 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3308 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3309 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3310 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3311 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3312 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3313 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3315 /** update clipping status */
3317 This->stateBlock->clip_status.ClipUnion = 0;
3318 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3320 This->stateBlock->clip_status.ClipUnion = 0;
3321 This->stateBlock->clip_status.ClipIntersection = 0;
3326 case WINED3DRS_BLENDOP :
3328 int glParm = GL_FUNC_ADD;
3330 switch ((D3DBLENDOP) Value) {
3331 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3332 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3333 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3334 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3335 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3337 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3340 if(GL_SUPPORT(ARB_IMAGING)) {
3341 TRACE("glBlendEquation(%x)\n", glParm);
3342 GL_EXTCALL(glBlendEquation(glParm));
3343 checkGLcall("glBlendEquation");
3345 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
3350 case WINED3DRS_TEXTUREFACTOR :
3354 /* Note the texture color applies to all textures whereas
3355 GL_TEXTURE_ENV_COLOR applies to active only */
3357 D3DCOLORTOGLFLOAT4(Value, col);
3358 /* Set the default alpha blend color */
3359 if (GL_SUPPORT(ARB_IMAGING)) {
3360 GL_EXTCALL(glBlendColor(col[0], col[1], col[2], col[3]));
3361 checkGLcall("glBlendColor");
3363 WARN("Unsupported in local OpenGL implementation: glBlendColor\n");
3366 /* And now the default texture color as well */
3367 for (i = 0; i < GL_LIMITS(textures); i++) {
3369 /* Note the D3DRS value applies to all textures, but GL has one
3370 per texture, so apply it now ready to be used! */
3371 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3372 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
3373 checkGLcall("glActiveTextureARB");
3375 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3378 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3379 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3384 case WINED3DRS_SPECULARENABLE :
3386 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3387 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3388 specular color. This is wrong:
3389 Separate specular color means the specular colour is maintained separately, whereas
3390 single color means it is merged in. However in both cases they are being used to
3392 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3393 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3397 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3398 checkGLcall("glMaterialfv");
3399 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3400 glEnable(GL_COLOR_SUM_EXT);
3402 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3404 checkGLcall("glEnable(GL_COLOR_SUM)");
3406 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3408 /* for the case of enabled lighting: */
3409 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3410 checkGLcall("glMaterialfv");
3412 /* for the case of disabled lighting: */
3413 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3414 glDisable(GL_COLOR_SUM_EXT);
3416 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3418 checkGLcall("glDisable(GL_COLOR_SUM)");
3423 case WINED3DRS_STENCILENABLE :
3425 glEnable(GL_STENCIL_TEST);
3426 checkGLcall("glEnable GL_STENCIL_TEST");
3428 glDisable(GL_STENCIL_TEST);
3429 checkGLcall("glDisable GL_STENCIL_TEST");
3433 case WINED3DRS_STENCILFUNC :
3436 GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3437 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3440 switch ((D3DCMPFUNC)Value) {
3441 case D3DCMP_NEVER: func = GL_NEVER; break;
3442 case D3DCMP_LESS: func = GL_LESS; break;
3443 case D3DCMP_EQUAL: func = GL_EQUAL; break;
3444 case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
3445 case D3DCMP_GREATER: func = GL_GREATER; break;
3446 case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
3447 case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
3448 case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
3450 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3452 This->stencilfunc = func;
3453 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3454 #if 0 /* Don't use OpenGL 2.0 calls for now */
3455 if(GL_EXTCALL(glStencilFuncSeparate)) {
3456 GL_EXTCALL(glStencilFuncSeparate(GL_FRONT, func, ref, mask));
3457 checkGLcall("glStencilFuncSeparate(GL_FRONT,...)");
3461 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3462 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3463 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3464 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3465 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3466 glStencilFunc(func, ref, mask);
3467 checkGLcall("glStencilFunc(...)");
3469 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3470 GL_EXTCALL(glStencilFuncSeparateATI(GL_FRONT, func, ref, mask));
3471 checkGLcall("glStencilFuncSeparateATI(GL_FRONT,...)");
3473 TRACE("Separate stencil function not supported on this version of opengl");
3474 glStencilFunc(func, ref, mask);
3475 checkGLcall("glStencilFunc(...)");
3478 glStencilFunc(func, ref, mask);
3479 checkGLcall("glStencilFunc(...)");
3483 case WINED3DRS_STENCILREF :
3485 int glParm = This->stencilfunc;
3487 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3490 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3491 glStencilFunc(glParm, ref, mask);
3492 checkGLcall("glStencilFunc");
3496 case WINED3DRS_STENCILMASK :
3498 int glParm = This->stencilfunc;
3499 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3500 GLuint mask = Value;
3502 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3503 glStencilFunc(glParm, ref, mask);
3504 checkGLcall("glStencilFunc");
3508 case WINED3DRS_STENCILFAIL :
3509 case WINED3DRS_STENCILZFAIL :
3510 case WINED3DRS_STENCILPASS :
3516 GLint action = StencilOp(Value);
3518 glGetIntegerv(GL_STENCIL_FAIL, &stencilFail);
3519 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &depthFail);
3520 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &stencilPass);
3522 if(WINED3DRS_STENCILFAIL == State) {
3523 stencilFail = action;
3525 else if(WINED3DRS_STENCILZFAIL == State) {
3528 else if(WINED3DRS_STENCILPASS == State) {
3529 stencilPass = action;
3532 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3533 #if 0 /* Don't use OpenGL 2.0 calls for now */
3534 if(GL_EXTCALL(glStencilOpSeparate)) {
3535 GL_EXTCALL(glStencilOpSeparate(GL_FRONT, stencilFail, depthFail, stencilPass));
3536 checkGLcall("glStencilOpSeparate(GL_FRONT,...)");
3540 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3541 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3542 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3543 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3544 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3545 glStencilOp(stencilFail, depthFail, stencilPass);
3546 checkGLcall("glStencilOp(...)");
3548 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3549 GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
3550 checkGLcall("glStencilOpSeparateATI(GL_FRONT,...)");
3552 TRACE("Separate stencil operation not supported on this version of opengl");
3553 glStencilOp(stencilFail, depthFail, stencilPass);
3554 checkGLcall("glStencilOp(...)");
3557 glStencilOp(stencilFail, depthFail, stencilPass);
3558 checkGLcall("glStencilOp(...)");
3562 case WINED3DRS_STENCILWRITEMASK :
3564 glStencilMask(Value);
3565 TRACE("glStencilMask(%lu)\n", Value);
3566 checkGLcall("glStencilMask");
3570 case WINED3DRS_FOGENABLE :
3572 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
3574 checkGLcall("glEnable GL_FOG");
3577 checkGLcall("glDisable GL_FOG");
3582 case WINED3DRS_RANGEFOGENABLE :
3585 TRACE("Enabled RANGEFOG");
3587 TRACE("Disabled RANGEFOG");
3592 case WINED3DRS_FOGCOLOR :
3595 D3DCOLORTOGLFLOAT4(Value, col);
3596 /* Set the default alpha blend color */
3597 glFogfv(GL_FOG_COLOR, &col[0]);
3598 checkGLcall("glFog GL_FOG_COLOR");
3602 case WINED3DRS_FOGTABLEMODE :
3604 glHint(GL_FOG_HINT, GL_NICEST);
3607 if(This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] == D3DFOG_NONE) {
3608 glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
3610 /* Otherwise leave the vertex fog value */
3613 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3614 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3615 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3617 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3619 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3620 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3625 case WINED3DRS_FOGVERTEXMODE :
3627 glHint(GL_FOG_HINT, GL_FASTEST);
3628 /* 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." */
3629 if(This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == D3DFOG_NONE) {
3631 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3632 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3634 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3636 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3638 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3639 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3645 case WINED3DRS_FOGSTART :
3648 glFogfv(GL_FOG_START, &tmpvalue.f);
3649 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3650 TRACE("Fog Start == %f\n", tmpvalue.f);
3654 case WINED3DRS_FOGEND :
3657 glFogfv(GL_FOG_END, &tmpvalue.f);
3658 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3659 TRACE("Fog End == %f\n", tmpvalue.f);
3663 case WINED3DRS_FOGDENSITY :
3666 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3667 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3671 case WINED3DRS_VERTEXBLEND :
3673 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3674 TRACE("Vertex Blending state to %ld\n", Value);
3678 case WINED3DRS_TWEENFACTOR :
3681 This->updateStateBlock->tween_factor = tmpvalue.f;
3682 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3686 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3688 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3692 case WINED3DRS_COLORVERTEX :
3693 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3694 case WINED3DRS_SPECULARMATERIALSOURCE :
3695 case WINED3DRS_AMBIENTMATERIALSOURCE :
3696 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3698 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3700 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3701 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3702 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3703 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3704 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3705 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3707 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3708 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3709 Parm = GL_AMBIENT_AND_DIFFUSE;
3713 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3715 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3717 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3724 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3726 This->tracking_color = NEEDS_TRACKING;
3727 This->tracking_parm = Parm;
3731 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3736 case WINED3DRS_LINEPATTERN :
3742 tmppattern.d = Value;
3744 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3746 if (tmppattern.lp.wRepeatFactor) {
3747 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3748 checkGLcall("glLineStipple(repeat, linepattern)");
3749 glEnable(GL_LINE_STIPPLE);
3750 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3752 glDisable(GL_LINE_STIPPLE);
3753 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3758 case WINED3DRS_ZBIAS : /* D3D8 only */
3762 TRACE("ZBias value %f\n", tmpvalue.f);
3763 glPolygonOffset(0, -tmpvalue.f);
3764 checkGLcall("glPolygonOffset(0, -Value)");
3765 glEnable(GL_POLYGON_OFFSET_FILL);
3766 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3767 glEnable(GL_POLYGON_OFFSET_LINE);
3768 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3769 glEnable(GL_POLYGON_OFFSET_POINT);
3770 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3772 glDisable(GL_POLYGON_OFFSET_FILL);
3773 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3774 glDisable(GL_POLYGON_OFFSET_LINE);
3775 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3776 glDisable(GL_POLYGON_OFFSET_POINT);
3777 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3782 case WINED3DRS_NORMALIZENORMALS :
3784 glEnable(GL_NORMALIZE);
3785 checkGLcall("glEnable(GL_NORMALIZE);");
3787 glDisable(GL_NORMALIZE);
3788 checkGLcall("glDisable(GL_NORMALIZE);");
3792 case WINED3DRS_POINTSIZE :
3793 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
3795 TRACE("Set point size to %f\n", tmpvalue.f);
3796 glPointSize(tmpvalue.f);
3797 checkGLcall("glPointSize(...);");
3800 case WINED3DRS_POINTSIZE_MIN :
3801 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3803 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3804 checkGLcall("glPointParameterfEXT(...);");
3806 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3810 case WINED3DRS_POINTSIZE_MAX :
3811 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3813 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3814 checkGLcall("glPointParameterfEXT(...);");
3816 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3820 case WINED3DRS_POINTSCALE_A :
3821 case WINED3DRS_POINTSCALE_B :
3822 case WINED3DRS_POINTSCALE_C :
3823 case WINED3DRS_POINTSCALEENABLE :
3826 * POINTSCALEENABLE controls how point size value is treated. If set to
3827 * true, the point size is scaled with respect to height of viewport.
3828 * When set to false point size is in pixels.
3830 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
3833 /* Default values */
3834 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3837 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
3838 * This means that OpenGL will clamp really small point sizes to 1.0f.
3839 * To correct for this we need to multiply by the scale factor when sizes
3840 * are less than 1.0f. scale_factor = 1.0f / point_size.
3842 GLfloat pointSize = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSIZE]);
3843 if(pointSize > 0.0f) {
3844 GLfloat scaleFactor;
3846 if(pointSize < 1.0f) {
3847 scaleFactor = pointSize * pointSize;
3852 if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3853 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
3854 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3855 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
3856 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3857 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
3858 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3862 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
3863 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
3864 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
3866 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3867 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3868 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
3870 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
3874 case WINED3DRS_COLORWRITEENABLE :
3876 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3877 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3878 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3879 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3880 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3881 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3882 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3883 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3884 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3885 checkGLcall("glColorMask(...)");
3889 case WINED3DRS_LOCALVIEWER :
3891 GLint state = (Value) ? 1 : 0;
3892 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3893 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3897 case WINED3DRS_LASTPIXEL :
3900 TRACE("Last Pixel Drawing Enabled\n");
3902 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3907 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3910 TRACE("Software Processing Enabled\n");
3912 TRACE("Software Processing Disabled\n");
3917 /** not supported */
3918 case WINED3DRS_ZVISIBLE :
3921 return WINED3DERR_INVALIDCALL;
3923 case WINED3DRS_POINTSPRITEENABLE :
3925 /* TODO: NV_POINT_SPRITE */
3926 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
3927 TRACE("Point sprites not supported\n");
3932 * Point sprites are always enabled. Value controls texture coordinate
3933 * replacement mode. Must be set true for point sprites to use
3936 glEnable(GL_POINT_SPRITE_ARB);
3937 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
3940 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
3941 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
3943 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
3944 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
3948 case WINED3DRS_EDGEANTIALIAS :
3951 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3953 checkGLcall("glEnable(GL_BLEND)");
3954 glEnable(GL_LINE_SMOOTH);
3955 checkGLcall("glEnable(GL_LINE_SMOOTH)");
3957 glDisable(GL_BLEND);
3958 checkGLcall("glDisable(GL_BLEND)");
3959 glDisable(GL_LINE_SMOOTH);
3960 checkGLcall("glDisable(GL_LINE_SMOOTH)");
3964 case WINED3DRS_WRAP0 :
3965 case WINED3DRS_WRAP1 :
3966 case WINED3DRS_WRAP2 :
3967 case WINED3DRS_WRAP3 :
3968 case WINED3DRS_WRAP4 :
3969 case WINED3DRS_WRAP5 :
3970 case WINED3DRS_WRAP6 :
3971 case WINED3DRS_WRAP7 :
3972 case WINED3DRS_WRAP8 :
3973 case WINED3DRS_WRAP9 :
3974 case WINED3DRS_WRAP10 :
3975 case WINED3DRS_WRAP11 :
3976 case WINED3DRS_WRAP12 :
3977 case WINED3DRS_WRAP13 :
3978 case WINED3DRS_WRAP14 :
3979 case WINED3DRS_WRAP15 :
3981 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
3982 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
3983 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
3984 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
3985 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
3987 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
3989 TRACE("(%p)->(%s,%ld) Texture wraping not yet supported\n",This, debug_d3drenderstate(State), Value);
3991 case WINED3DRS_MULTISAMPLEANTIALIAS :
3993 if (!GL_SUPPORT(ARB_MULTISAMPLE)) {
3994 TRACE("Multisample antialiasing not supported\n");
3999 glEnable(GL_MULTISAMPLE_ARB);
4000 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
4002 glDisable(GL_MULTISAMPLE_ARB);
4003 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
4007 case WINED3DRS_SCISSORTESTENABLE :
4010 glEnable(GL_SCISSOR_TEST);
4011 checkGLcall("glEnable(GL_SCISSOR_TEST)");
4013 glDisable(GL_SCISSOR_TEST);
4014 checkGLcall("glDisable(GL_SCISSOR_TEST)");
4018 case WINED3DRS_SLOPESCALEDEPTHBIAS :
4022 glEnable(GL_POLYGON_OFFSET_FILL);
4023 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4024 glPolygonOffset(tmpvalue.f, *((float*)&This->stateBlock->renderState[WINED3DRS_DEPTHBIAS]));
4025 checkGLcall("glPolygonOffset(...)");
4027 glDisable(GL_POLYGON_OFFSET_FILL);
4028 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4032 case WINED3DRS_ANTIALIASEDLINEENABLE :
4035 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4037 checkGLcall("glEnable(GL_BLEND)");
4038 glEnable(GL_LINE_SMOOTH);
4039 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4041 glDisable(GL_BLEND);
4042 checkGLcall("glDisable(GL_BLEND)");
4043 glDisable(GL_LINE_SMOOTH);
4044 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4048 case WINED3DRS_TWOSIDEDSTENCILMODE :
4051 TRACE("Two-sided stencil mode enabled\n");
4053 TRACE("Two-sided stencil mode disabled\n");
4057 case WINED3DRS_CCW_STENCILFAIL :
4058 case WINED3DRS_CCW_STENCILZFAIL :
4059 case WINED3DRS_CCW_STENCILPASS :
4065 GLint action = StencilOp(Value);
4067 glGetIntegerv(GL_STENCIL_BACK_FAIL, &stencilFail);
4068 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &depthFail);
4069 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &stencilPass);
4071 if(WINED3DRS_CCW_STENCILFAIL == State) {
4072 stencilFail = action;
4074 else if(WINED3DRS_CCW_STENCILZFAIL == State) {
4077 else if(WINED3DRS_CCW_STENCILPASS == State) {
4078 stencilPass = action;
4081 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
4082 #if 0 /* Don't use OpenGL 2.0 calls for now */
4083 if(GL_EXTCALL(glStencilOpSeparate)) {
4084 GL_EXTCALL(glStencilOpSeparate(GL_BACK, stencilFail, depthFail, stencilPass));
4085 checkGLcall("glStencilOpSeparate(GL_BACK,...)");
4089 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
4090 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
4091 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
4092 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
4093 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
4094 glStencilOp(stencilFail, depthFail, stencilPass);
4095 checkGLcall("glStencilOp(...)");
4097 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
4098 GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail, depthFail, stencilPass));
4099 checkGLcall("glStencilOpSeparateATI(GL_BACK,...)");
4101 TRACE("Separate stencil operation not supported on this version of opengl");
4102 glStencilOp(stencilFail, depthFail, stencilPass);
4103 checkGLcall("glStencilOp(...)");
4106 glStencilOp(stencilFail, depthFail, stencilPass);
4107 checkGLcall("glStencilOp(...)");
4111 case WINED3DRS_CCW_STENCILFUNC :
4114 GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
4115 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
4118 switch ((D3DCMPFUNC)Value) {
4119 case D3DCMP_NEVER: func = GL_NEVER; break;
4120 case D3DCMP_LESS: func = GL_LESS; break;
4121 case D3DCMP_EQUAL: func = GL_EQUAL; break;
4122 case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
4123 case D3DCMP_GREATER: func = GL_GREATER; break;
4124 case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
4125 case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
4126 case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
4128 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
4130 This->stencilfunc = func;
4131 if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
4132 #if 0 /* Don't use OpenGL 2.0 calls for now */
4133 if(GL_EXTCALL(glStencilFuncSeparate)) {
4134 GL_EXTCALL(glStencilFuncSeparate(GL_BACK, func, ref, mask));
4135 checkGLcall("glStencilFuncSeparate(GL_BACK,...)");
4139 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
4140 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
4141 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
4142 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
4143 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
4144 glStencilFunc(func, ref, mask);
4145 checkGLcall("glStencilFunc(...)");
4147 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
4148 GL_EXTCALL(glStencilFuncSeparateATI(GL_BACK, func, ref, mask));
4149 checkGLcall("glStencilFuncSeparateATI(GL_BACK,...)");
4151 TRACE("Separate stencil function not supported on this version of opengl");
4152 glStencilFunc(func, ref, mask);
4153 checkGLcall("glStencilFunc(...)");
4156 glStencilFunc(func, ref, mask);
4157 checkGLcall("glStencilFunc(...)");
4161 case WINED3DRS_DEPTHBIAS :
4165 glEnable(GL_POLYGON_OFFSET_FILL);
4166 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4167 glPolygonOffset(*((float*)&This->stateBlock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]), tmpvalue.f);
4168 checkGLcall("glPolygonOffset(...)");
4170 glDisable(GL_POLYGON_OFFSET_FILL);
4171 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4176 case WINED3DRS_TEXTUREPERSPECTIVE :
4179 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
4181 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
4185 case WINED3DRS_STIPPLEDALPHA :
4188 ERR(" Stippled Alpha not supported yet.\n");
4191 case WINED3DRS_ANTIALIAS :
4194 ERR(" Antialias not supported yet.\n");
4198 FIXME("(%p)->(%s,%ld) not handled yet\n", This, debug_d3drenderstate(State), Value);
4206 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
4207 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4208 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
4209 *pValue = This->stateBlock->renderState[State];
4214 * Get / Set Sampler States
4215 * TODO: Verify against dx9 definitions
4218 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
4219 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4221 * SetSampler is designed to allow for more than the standard up to 8 textures
4222 * and Geforce has stopped supporting more than 6 standard textures in openGL.
4223 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
4225 * http://developer.nvidia.com/object/General_FAQ.html#t6
4227 * There are two new settings for GForce
4229 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
4230 * and the texture one:
4231 * GL_MAX_TEXTURE_COORDS_ARB.
4232 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
4234 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
4235 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
4237 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
4238 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
4239 return WINED3DERR_INVALIDCALL;
4241 TRACE("Setting sampler %ld %d to %ld\n", Sampler, Type, Value);
4242 This->updateStateBlock->samplerState[Sampler][Type] = Value;
4243 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
4244 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
4246 /* Handle recording of state blocks */
4247 if (This->isRecordingState) {
4248 TRACE("Recording... not performing anything\n");
4255 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
4256 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4257 /** TODO: check that sampler is in range **/
4258 *Value = This->updateStateBlock->samplerState[Sampler][Type];
4259 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
4264 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
4265 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4268 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4269 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4270 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
4276 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
4277 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4278 GLint scissorBox[4];
4281 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4282 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
4283 pRect->left = scissorBox[1];
4284 pRect->top = scissorBox[2];
4285 pRect->right = scissorBox[1] + scissorBox[3];
4286 pRect->bottom = scissorBox[2] + scissorBox[4];
4287 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4292 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
4293 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4294 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
4296 TRACE("(%p) : pDecl=%p\n", This, pDecl);
4298 This->updateStateBlock->vertexDecl = pDecl;
4299 This->updateStateBlock->changed.vertexDecl = TRUE;
4300 This->updateStateBlock->set.vertexDecl = TRUE;
4302 if (This->isRecordingState) {
4303 TRACE("Recording... not performing anything\n");
4306 if (NULL != pDecl) {
4307 IWineD3DVertexDeclaration_AddRef(pDecl);
4309 if (NULL != oldDecl) {
4310 IWineD3DVertexDeclaration_Release(oldDecl);
4315 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
4316 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4318 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
4320 *ppDecl = This->stateBlock->vertexDecl;
4321 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
4325 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
4326 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4327 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
4329 This->updateStateBlock->vertexShader = pShader;
4330 This->updateStateBlock->changed.vertexShader = TRUE;
4331 This->updateStateBlock->set.vertexShader = TRUE;
4333 if (This->isRecordingState) {
4334 TRACE("Recording... not performing anything\n");
4337 if (NULL != pShader) {
4338 IWineD3DVertexShader_AddRef(pShader);
4340 if (NULL != oldShader) {
4341 IWineD3DVertexShader_Release(oldShader);
4344 if (pShader != NULL && ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration != NULL) {
4345 TRACE("(%p) : setting vertexDeclaration(%p)\n", This, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4346 IWineD3DDevice_SetVertexDeclaration(iface, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4349 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4351 * TODO: merge HAL shaders context switching from prototype
4356 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
4357 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4359 if (NULL == ppShader) {
4360 return WINED3DERR_INVALIDCALL;
4362 *ppShader = This->stateBlock->vertexShader;
4363 if( NULL != *ppShader)
4364 IWineD3DVertexShader_AddRef(*ppShader);
4366 TRACE("(%p) : returning %p\n", This, *ppShader);
4370 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4371 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4374 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4376 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4377 iface, dstData, srcData, type, start, count, registersize);
4379 if (type != WINESHADERCNST_NONE) {
4380 if (srcData == NULL || cnt < 0) {
4381 return WINED3DERR_INVALIDCALL;
4384 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4387 for (i = start; i < cnt + start; ++i) {
4388 This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
4389 This->updateStateBlock->set.vertexShaderConstants[i] = TRUE;
4390 This->updateStateBlock->vertexShaderConstantT[i] = type;
4396 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4397 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4400 int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4402 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4403 iface, dstData, srcData, type, start, count, registersize);
4405 /* Verify that the requested shader constant was populated with the correct type */
4406 for (i = start; i < cnt + start; ++i) {
4407 if (This->updateStateBlock->vertexShaderConstantT[i] != type) {
4408 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning WINED3DERR_INVALIDCALL\n",
4409 This, type, This->updateStateBlock->vertexShaderConstantT[i]);
4410 return WINED3DERR_INVALIDCALL;
4414 if (dstData == NULL || cnt < 0) {
4415 return WINED3DERR_INVALIDCALL;
4418 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4423 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
4424 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4426 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4427 This->updateStateBlock->vertexShaderConstantB,
4429 WINESHADERCNST_BOOL,
4432 sizeof(*pConstantData));
4435 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
4436 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4438 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4440 This->updateStateBlock->vertexShaderConstantB,
4441 WINESHADERCNST_BOOL,
4444 sizeof(*pConstantData));
4447 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
4448 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4450 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4451 This->updateStateBlock->vertexShaderConstantI,
4453 WINESHADERCNST_INTEGER,
4456 4 * sizeof(*pConstantData));
4459 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
4460 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4462 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4464 This->updateStateBlock->vertexShaderConstantI,
4465 WINESHADERCNST_INTEGER,
4468 4 * sizeof(*pConstantData));
4472 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
4473 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4475 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4476 This->updateStateBlock->vertexShaderConstantF,
4478 WINESHADERCNST_FLOAT,
4481 4 * sizeof(*pConstantData));
4484 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
4485 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4487 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface,
4489 This->updateStateBlock->vertexShaderConstantF,
4490 WINESHADERCNST_FLOAT,
4493 4 * sizeof(*pConstantData));
4496 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4497 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface,
4500 WINESHADERCNST_NONE,
4506 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
4507 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4508 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
4509 This->updateStateBlock->pixelShader = pShader;
4510 This->updateStateBlock->changed.pixelShader = TRUE;
4511 This->updateStateBlock->set.pixelShader = TRUE;
4513 /* Handle recording of state blocks */
4514 if (This->isRecordingState) {
4515 TRACE("Recording... not performing anything\n");
4518 if (NULL != pShader) {
4519 IWineD3DPixelShader_AddRef(pShader);
4521 if (NULL != oldShader) {
4522 IWineD3DPixelShader_Release(oldShader);
4525 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4527 * TODO: merge HAL shaders context switching from prototype
4532 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4533 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4535 if (NULL == ppShader) {
4536 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4537 return WINED3DERR_INVALIDCALL;
4540 *ppShader = This->stateBlock->pixelShader;
4541 if (NULL != *ppShader) {
4542 IWineD3DPixelShader_AddRef(*ppShader);
4544 TRACE("(%p) : returning %p\n", This, *ppShader);
4548 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4549 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4552 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4554 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4555 iface, dstData, srcData, type, start, count, registersize);
4557 if (type != WINESHADERCNST_NONE) {
4558 if (srcData == NULL || cnt < 0) {
4559 return WINED3DERR_INVALIDCALL;
4562 CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4565 for (i = start; i < cnt + start; ++i) {
4566 This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
4567 This->updateStateBlock->set.pixelShaderConstants[i] = TRUE;
4568 This->updateStateBlock->pixelShaderConstantT[i] = type;
4574 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4575 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4578 int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4580 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4581 iface, dstData, srcData, type, start, count, registersize);
4583 /* Verify that the requested shader constant was populated with the correct type */
4584 for (i = start; i < cnt + start; ++i) {
4585 if (This->updateStateBlock->pixelShaderConstantT[i] != type) {
4586 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning WINED3DERR_INVALIDCALL\n",
4587 This, type, This->updateStateBlock->pixelShaderConstantT[i]);
4588 return WINED3DERR_INVALIDCALL;
4592 if (dstData == NULL || cnt < 0) {
4593 return WINED3DERR_INVALIDCALL;
4596 CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4601 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
4602 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4604 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4605 This->updateStateBlock->pixelShaderConstantB,
4607 WINESHADERCNST_BOOL,
4610 sizeof(*pConstantData));
4613 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
4614 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4616 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4618 This->updateStateBlock->pixelShaderConstantB,
4619 WINESHADERCNST_BOOL,
4622 sizeof(*pConstantData));
4625 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
4626 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4628 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4629 This->updateStateBlock->pixelShaderConstantI,
4631 WINESHADERCNST_INTEGER,
4634 4 * sizeof(*pConstantData));
4637 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
4638 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4640 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4642 This->updateStateBlock->pixelShaderConstantI,
4643 WINESHADERCNST_INTEGER,
4646 4 * sizeof(*pConstantData));
4649 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
4650 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4652 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4653 This->updateStateBlock->pixelShaderConstantF,
4655 WINESHADERCNST_FLOAT,
4658 4 * sizeof(*pConstantData));
4661 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
4662 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4664 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface,
4666 This->updateStateBlock->pixelShaderConstantF,
4667 WINESHADERCNST_FLOAT,
4670 4 * sizeof(*pConstantData));
4673 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4674 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface,
4677 WINESHADERCNST_NONE,
4683 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
4685 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
4688 DWORD DestFVF = dest->fvf;
4690 D3DMATRIX mat, proj_mat, view_mat, world_mat;
4694 if (SrcFVF & D3DFVF_NORMAL) {
4695 WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
4698 if ( (SrcFVF & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
4699 ERR("Source has no position mask\n");
4700 return WINED3DERR_INVALIDCALL;
4703 if (dest->resource.allocatedMemory == NULL) {
4704 ERR("Destination buffer has no memory allocated\n");
4705 return WINED3DERR_INVALIDCALL;
4709 * a) D3DRS_CLIPPING is enabled
4710 * b) WINED3DVOP_CLIP is passed
4712 if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
4713 static BOOL warned = FALSE;
4715 * The clipping code is not quite correct. Some things need
4716 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
4717 * so disable clipping for now.
4718 * (The graphics in Half-Life are broken, and my processvertices
4719 * test crashes with IDirect3DDevice3)
4725 FIXME("Clipping is broken and disabled for now\n");
4727 } else doClip = FALSE;
4728 dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
4730 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4733 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4736 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4737 D3DTS_WORLDMATRIX(0),
4740 TRACE("View mat: \n");
4741 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); \
4742 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); \
4743 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); \
4744 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); \
4746 TRACE("Proj mat: \n");
4747 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); \
4748 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); \
4749 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); \
4750 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); \
4752 TRACE("World mat: \n");
4753 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); \
4754 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); \
4755 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); \
4756 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); \
4758 /* Get the viewport */
4759 IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
4760 TRACE("Viewport: X=%ld, Y=%ld, Width=%ld, Height=%ld, MinZ=%f, MaxZ=%f\n",
4761 vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
4763 multiply_matrix(&mat,&view_mat,&world_mat);
4764 multiply_matrix(&mat,&proj_mat,&mat);
4766 numTextures = (DestFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
4768 for (i = 0; i < dwCount; i+= 1) {
4769 unsigned int tex_index;
4771 if ( ((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZ ) ||
4772 ((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW ) ) {
4773 /* The position first */
4775 (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
4777 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
4779 /* Multiplication with world, view and projection matrix */
4780 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);
4781 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);
4782 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);
4783 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);
4785 TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
4787 /* WARNING: The following things are taken from d3d7 and were not yet checked
4788 * against d3d8 or d3d9!
4791 /* Clipping conditions: From
4792 * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
4794 * A vertex is clipped if it does not match the following requirements
4798 * 0 < rhw ( Not in d3d7, but tested in d3d7)
4800 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
4801 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
4805 if( doClip == FALSE ||
4806 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
4807 (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) &&
4810 /* "Normal" viewport transformation (not clipped)
4811 * 1) The values are divided trough rhw
4812 * 2) The y axis is negative, so multiply it with -1
4813 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
4814 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
4815 * 4) Multiply x with Width/2 and add Width/2
4816 * 5) The same for the height
4817 * 6) Add the viewpoint X and Y to the 2D coordinates and
4818 * The minimum Z value to z
4819 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
4821 * Well, basically it's simply a linear transformation into viewport
4833 z *= vp.MaxZ - vp.MinZ;
4835 x += vp.Width / 2 + vp.X;
4836 y += vp.Height / 2 + vp.Y;
4841 /* That vertex got clipped
4842 * Contrary to OpenGL it is not dropped completely, it just
4843 * undergoes a different calculation.
4845 TRACE("Vertex got clipped\n");
4852 /* Msdn mentiones that Direct3D9 keeps a list of clipped vertices
4853 * outside of the main vertex buffer memory. That needs some more
4858 TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
4861 ( (float *) dest_ptr)[0] = x;
4862 ( (float *) dest_ptr)[1] = y;
4863 ( (float *) dest_ptr)[2] = z;
4864 ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
4866 dest_ptr += 3 * sizeof(float);
4868 if((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
4869 dest_ptr += sizeof(float);
4872 if (DestFVF & D3DFVF_PSIZE) {
4873 dest_ptr += sizeof(DWORD);
4875 if (DestFVF & D3DFVF_NORMAL) {
4877 (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
4878 /* AFAIK this should go into the lighting information */
4879 FIXME("Didn't expect the destination to have a normal\n");
4880 copy_and_next(dest_ptr, normal, 3 * sizeof(float));
4883 if (DestFVF & D3DFVF_DIFFUSE) {
4885 (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
4887 static BOOL warned = FALSE;
4889 if(warned == FALSE) {
4890 ERR("No diffuse color in source, but destination has one\n");
4894 *( (DWORD *) dest_ptr) = 0xffffffff;
4895 dest_ptr += sizeof(DWORD);
4898 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
4901 if (DestFVF & D3DFVF_SPECULAR) {
4902 /* What's the color value in the feedback buffer? */
4904 (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
4906 static BOOL warned = FALSE;
4908 if(warned == FALSE) {
4909 ERR("No specular color in source, but destination has one\n");
4913 *( (DWORD *) dest_ptr) = 0xFF000000;
4914 dest_ptr += sizeof(DWORD);
4917 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
4921 for (tex_index = 0; tex_index < numTextures; tex_index++) {
4923 (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) +
4924 i * lpStrideData->u.s.texCoords[tex_index].dwStride);
4926 ERR("No source texture, but destination requests one\n");
4927 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
4930 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
4937 #undef copy_and_next
4939 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
4940 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4941 IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
4942 WineDirect3DVertexStridedData strided;
4944 TRACE("(%p)->(%d,%d,%d,%p,%p,%ld\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
4946 hr = IWineD3DDevice_SetFVF(iface, SrcImpl->fvf);
4947 hr = IWineD3DDevice_SetStreamSource(iface, 0, pVertexDecl, get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, get_flexible_vertex_size(SrcImpl->fvf));
4949 memset(&strided, 0, sizeof(strided));
4950 primitiveConvertToStridedData(iface, &strided, 0);
4952 return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
4956 * Apply / Get / Set Texture Stage States
4957 * TODO: Verify against dx9 definitions
4960 /* 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 */
4961 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
4962 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4963 DWORD Value = This->updateStateBlock->textureState[Stage][Type];
4964 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4966 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4968 /* Check that the stage is within limits */
4969 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4970 TRACE("Attempt to access invalid texture rejected\n");
4977 case WINED3DTSS_ALPHAOP :
4978 case WINED3DTSS_COLOROP :
4979 /* nothing to do as moved to drawprim for now */
4981 case WINED3DTSS_ADDRESSW :
4982 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
4983 if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
4984 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
4987 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
4988 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
4989 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
4990 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
4993 case WINED3DTSS_TEXCOORDINDEX :
4995 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
4997 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
4998 one flag, you can still specify an index value, which the system uses to
4999 determine the texture wrapping mode.
5000 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
5001 means use the vertex position (camera-space) as the input texture coordinates
5002 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
5003 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
5004 to the TEXCOORDINDEX value */
5007 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
5009 switch (Value & 0xFFFF0000) {
5010 case D3DTSS_TCI_PASSTHRU:
5011 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
5012 glDisable(GL_TEXTURE_GEN_S);
5013 glDisable(GL_TEXTURE_GEN_T);
5014 glDisable(GL_TEXTURE_GEN_R);
5015 glDisable(GL_TEXTURE_GEN_Q);
5016 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
5019 case D3DTSS_TCI_CAMERASPACEPOSITION:
5020 /* CameraSpacePosition means use the vertex position, transformed to camera space,
5021 as the input texture coordinates for this stage's texture transformation. This
5022 equates roughly to EYE_LINEAR */
5024 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5025 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5026 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5027 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5028 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
5030 glMatrixMode(GL_MODELVIEW);
5033 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5034 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5035 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5036 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5039 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
5040 glEnable(GL_TEXTURE_GEN_S);
5041 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5042 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5043 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5044 glEnable(GL_TEXTURE_GEN_T);
5045 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5046 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5047 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5048 glEnable(GL_TEXTURE_GEN_R);
5049 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5050 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5051 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5055 case D3DTSS_TCI_CAMERASPACENORMAL:
5057 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5058 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5059 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5060 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5061 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5062 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
5064 glMatrixMode(GL_MODELVIEW);
5067 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5068 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5069 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5070 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5073 glEnable(GL_TEXTURE_GEN_S);
5074 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5075 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5076 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5077 glEnable(GL_TEXTURE_GEN_T);
5078 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5079 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5080 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5081 glEnable(GL_TEXTURE_GEN_R);
5082 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5083 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5084 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5089 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
5091 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5092 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5093 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5094 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5095 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5096 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
5098 glMatrixMode(GL_MODELVIEW);
5101 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5102 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5103 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5104 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5107 glEnable(GL_TEXTURE_GEN_S);
5108 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5109 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5110 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5111 glEnable(GL_TEXTURE_GEN_T);
5112 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5113 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5114 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5115 glEnable(GL_TEXTURE_GEN_R);
5116 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5117 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5118 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5123 /* Unhandled types: */
5126 /* ? disable GL_TEXTURE_GEN_n ? */
5127 glDisable(GL_TEXTURE_GEN_S);
5128 glDisable(GL_TEXTURE_GEN_T);
5129 glDisable(GL_TEXTURE_GEN_R);
5130 glDisable(GL_TEXTURE_GEN_Q);
5131 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
5138 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
5139 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);
5142 case WINED3DTSS_BUMPENVMAT00 :
5143 case WINED3DTSS_BUMPENVMAT01 :
5144 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
5146 case WINED3DTSS_BUMPENVMAT10 :
5147 case WINED3DTSS_BUMPENVMAT11 :
5148 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
5151 case WINED3DTSS_BUMPENVLSCALE :
5152 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5155 case WINED3DTSS_BUMPENVLOFFSET :
5156 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5159 case WINED3DTSS_RESULTARG :
5160 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5164 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
5165 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
5174 * Get / Set Texture Stage States
5175 * TODO: Verify against dx9 definitions
5177 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
5178 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5180 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5182 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5184 /* Reject invalid texture units */
5185 if (Stage >= GL_LIMITS(textures)) {
5186 TRACE("Attempt to access invalid texture rejected\n");
5187 return WINED3DERR_INVALIDCALL;
5190 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
5191 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
5192 This->updateStateBlock->textureState[Stage][Type] = Value;
5197 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
5198 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5199 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
5200 *pValue = This->updateStateBlock->textureState[Stage][Type];
5207 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
5209 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5210 IWineD3DBaseTexture *oldTexture;
5212 oldTexture = This->updateStateBlock->textures[Stage];
5213 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
5215 #if 0 /* TODO: check so vertex textures */
5216 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
5217 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
5222 /* Reject invalid texture units */
5223 if (Stage >= GL_LIMITS(textures) || Stage < 0) {
5224 WARN("Attempt to access invalid texture rejected\n");
5225 return WINED3DERR_INVALIDCALL;
5228 if(pTexture != NULL) {
5229 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH;
5231 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
5232 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
5233 return WINED3DERR_INVALIDCALL;
5237 oldTexture = This->updateStateBlock->textures[Stage];
5238 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
5239 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
5241 This->updateStateBlock->set.textures[Stage] = TRUE;
5242 This->updateStateBlock->changed.textures[Stage] = TRUE;
5243 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
5244 This->updateStateBlock->textures[Stage] = pTexture;
5246 /* Handle recording of state blocks */
5247 if (This->isRecordingState) {
5248 TRACE("Recording... not performing anything\n");
5252 /** NOTE: MSDN says that setTexture increases the reference count,
5253 * and the the application nust set the texture back to null (or have a leaky application),
5254 * This means we should pass the refcount up to the parent
5255 *******************************/
5256 if (NULL != This->updateStateBlock->textures[Stage]) {
5257 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
5260 if (NULL != oldTexture) {
5261 IWineD3DBaseTexture_Release(oldTexture);
5264 /* Reset color keying */
5265 if(Stage == 0 && This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE]) {
5266 BOOL enable_ckey = FALSE;
5269 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)pTexture)->surfaces[0];
5270 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
5274 glAlphaFunc(GL_NOTEQUAL, 0.0);
5275 checkGLcall("glAlphaFunc");
5282 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
5283 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5284 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
5286 /* Reject invalid texture units */
5287 if (Stage >= GL_LIMITS(textures)) {
5288 TRACE("Attempt to access invalid texture rejected\n");
5289 return WINED3DERR_INVALIDCALL;
5291 *ppTexture=This->updateStateBlock->textures[Stage];
5293 IWineD3DBaseTexture_AddRef(*ppTexture);
5295 return WINED3DERR_INVALIDCALL;
5302 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
5303 IWineD3DSurface **ppBackBuffer) {
5304 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5305 IWineD3DSwapChain *swapChain;
5308 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
5310 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5311 if (hr == WINED3D_OK) {
5312 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
5313 IWineD3DSwapChain_Release(swapChain);
5315 *ppBackBuffer = NULL;
5320 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
5321 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5322 WARN("(%p) : stub, calling idirect3d for now\n", This);
5323 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
5326 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
5327 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5328 IWineD3DSwapChain *swapChain;
5331 if(iSwapChain > 0) {
5332 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5333 if (hr == WINED3D_OK) {
5334 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
5335 IWineD3DSwapChain_Release(swapChain);
5337 FIXME("(%p) Error getting display mode\n", This);
5340 /* Don't read the real display mode,
5341 but return the stored mode instead. X11 can't change the color
5342 depth, and some apps are pretty angry if they SetDisplayMode from
5343 24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
5345 Also don't relay to the swapchain because with ddraw it's possible
5346 that there isn't a swapchain at all */
5347 pMode->Width = This->ddraw_width;
5348 pMode->Height = This->ddraw_height;
5349 pMode->Format = This->ddraw_format;
5350 pMode->RefreshRate = 0;
5357 HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
5358 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5359 TRACE("(%p)->(%p)\n", This, hWnd);
5361 This->ddraw_window = hWnd;
5365 HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
5366 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5367 TRACE("(%p)->(%p)\n", This, hWnd);
5369 *hWnd = This->ddraw_window;
5374 * Stateblock related functions
5377 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
5378 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5379 IWineD3DStateBlockImpl *object;
5380 TRACE("(%p)", This);
5382 if (This->isRecordingState) {
5383 return WINED3DERR_INVALIDCALL;
5386 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
5387 if (NULL == object ) {
5388 FIXME("(%p)Error allocating memory for stateblock\n", This);
5389 return E_OUTOFMEMORY;
5391 TRACE("(%p) creted object %p\n", This, object);
5392 object->wineD3DDevice= This;
5393 /** FIXME: object->parent = parent; **/
5394 object->parent = NULL;
5395 object->blockType = WINED3DSBT_ALL;
5397 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
5399 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
5400 This->updateStateBlock = object;
5401 This->isRecordingState = TRUE;
5403 TRACE("(%p) recording stateblock %p\n",This , object);
5407 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
5408 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5410 if (!This->isRecordingState) {
5411 FIXME("(%p) not recording! returning error\n", This);
5412 *ppStateBlock = NULL;
5413 return WINED3DERR_INVALIDCALL;
5416 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
5417 This->isRecordingState = FALSE;
5418 This->updateStateBlock = This->stateBlock;
5419 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
5420 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
5421 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
5426 * Scene related functions
5428 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
5429 /* At the moment we have no need for any functionality at the beginning
5431 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5432 TRACE("(%p) : stub\n", This);
5436 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
5437 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5438 TRACE("(%p)\n", This);
5440 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
5442 checkGLcall("glFlush");
5444 TRACE("End Scene\n");
5445 if(This->renderTarget != NULL) {
5447 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
5448 IUnknown *targetContainer = NULL;
5449 if (WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
5450 || WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
5451 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
5452 /** always dirtify for now. we must find a better way to see that surface have been modified
5453 (Modifications should will only occur via draw-primitive, but we do need better locking
5454 switching to render-to-texture should remove the overhead though.
5456 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
5457 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
5458 IWineD3DSurface_PreLoad(This->renderTarget);
5459 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
5460 IUnknown_Release(targetContainer);
5463 This->sceneEnded = TRUE;
5468 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
5469 CONST RECT* pSourceRect, CONST RECT* pDestRect,
5470 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
5471 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5472 IWineD3DSwapChain *swapChain = NULL;
5474 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
5476 TRACE("(%p) Presenting the frame\n", This);
5478 for(i = 0 ; i < swapchains ; i ++) {
5480 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
5481 TRACE("presentinng chain %d, %p\n", i, swapChain);
5482 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
5483 IWineD3DSwapChain_Release(swapChain);
5489 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
5490 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
5491 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5493 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
5494 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
5495 when the depth-buffer format does not contain stencil buffer information, this method fails. */
5496 GLbitfield glMask = 0;
5497 GLboolean old_ztest;
5498 GLfloat old_z_clear_value;
5499 GLint old_stencil_clear_value;
5500 GLfloat old_color_clear_value[4];
5502 CONST D3DRECT* curRect;
5504 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
5505 Count, pRects, Flags, Z, Stencil);
5509 glEnable(GL_SCISSOR_TEST);
5510 checkGLcall("glEnable GL_SCISSOR_TEST");
5512 if (Count > 0 && pRects) {
5518 /* Only set the values up once, as they are not changing */
5519 if (Flags & D3DCLEAR_STENCIL) {
5520 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
5521 glClearStencil(Stencil);
5522 checkGLcall("glClearStencil");
5523 glMask = glMask | GL_STENCIL_BUFFER_BIT;
5524 glStencilMask(0xFFFFFFFF);
5527 if (Flags & D3DCLEAR_ZBUFFER) {
5528 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
5529 glDepthMask(GL_TRUE);
5530 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
5532 checkGLcall("glClearDepth");
5533 glMask = glMask | GL_DEPTH_BUFFER_BIT;
5536 if (Flags & D3DCLEAR_TARGET) {
5537 TRACE("Clearing screen with glClear to color %lx\n", Color);
5538 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
5539 glClearColor(D3DCOLOR_R(Color),
5543 checkGLcall("glClearColor");
5545 /* Clear ALL colors! */
5546 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5547 glMask = glMask | GL_COLOR_BUFFER_BIT;
5550 /* Now process each rect in turn */
5551 for (i = 0; i < Count || i == 0; i++) {
5554 /* Note gl uses lower left, width/height */
5555 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
5556 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
5557 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
5558 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
5559 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
5560 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
5561 checkGLcall("glScissor");
5563 glScissor(This->stateBlock->viewport.X,
5564 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
5565 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
5566 This->stateBlock->viewport.Width,
5567 This->stateBlock->viewport.Height);
5568 checkGLcall("glScissor");
5571 /* Clear the selected rectangle (or full screen) */
5573 checkGLcall("glClear");
5575 /* Step to the next rectangle */
5576 if (curRect) curRect = curRect + sizeof(D3DRECT);
5579 /* Restore the old values (why..?) */
5580 if (Flags & D3DCLEAR_STENCIL) {
5581 glClearStencil(old_stencil_clear_value);
5582 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
5584 if (Flags & D3DCLEAR_ZBUFFER) {
5585 glDepthMask(old_ztest);
5586 glClearDepth(old_z_clear_value);
5588 if (Flags & D3DCLEAR_TARGET) {
5589 glClearColor(old_color_clear_value[0],
5590 old_color_clear_value[1],
5591 old_color_clear_value[2],
5592 old_color_clear_value[3]);
5593 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
5594 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
5595 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
5596 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
5599 glDisable(GL_SCISSOR_TEST);
5600 checkGLcall("glDisable");
5609 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
5610 UINT PrimitiveCount) {
5612 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5613 This->stateBlock->streamIsUP = FALSE;
5615 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
5616 debug_d3dprimitivetype(PrimitiveType),
5617 StartVertex, PrimitiveCount);
5618 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
5619 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */, NULL);
5625 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
5626 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
5627 D3DPRIMITIVETYPE PrimitiveType,
5628 INT baseVIndex, UINT minIndex,
5629 UINT NumVertices, UINT startIndex, UINT primCount) {
5631 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5633 IWineD3DIndexBuffer *pIB;
5634 WINED3DINDEXBUFFER_DESC IdxBufDsc;
5636 pIB = This->stateBlock->pIndexData;
5637 This->stateBlock->streamIsUP = FALSE;
5639 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
5640 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5641 minIndex, NumVertices, startIndex, baseVIndex, primCount);
5643 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
5644 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
5650 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
5651 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex, NULL);
5656 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5657 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
5658 UINT VertexStreamZeroStride) {
5659 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5661 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
5662 debug_d3dprimitivetype(PrimitiveType),
5663 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
5665 /* release the stream source */
5666 if (This->stateBlock->streamSource[0] != NULL) {
5667 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5670 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5671 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5672 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5673 This->stateBlock->streamIsUP = TRUE;
5675 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
5676 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */, NULL);
5678 /* MSDN specifies stream zero settings must be set to NULL */
5679 This->stateBlock->streamStride[0] = 0;
5680 This->stateBlock->streamSource[0] = NULL;
5682 /*stream zero settings set to null at end, as per the msdn */
5686 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5687 UINT MinVertexIndex, UINT NumVertices,
5688 UINT PrimitiveCount, CONST void* pIndexData,
5689 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
5690 UINT VertexStreamZeroStride) {
5692 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5694 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
5695 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5696 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
5697 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
5699 if (IndexDataFormat == WINED3DFMT_INDEX16) {
5705 /* release the stream and index data */
5706 if (This->stateBlock->streamSource[0] != NULL) {
5707 IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5709 if (This->stateBlock->pIndexData) {
5710 IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
5713 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5714 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5715 This->stateBlock->streamIsUP = TRUE;
5716 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5718 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex, NULL);
5720 /* MSDN specifies stream zero settings and index buffer must be set to NULL */
5721 This->stateBlock->streamSource[0] = NULL;
5722 This->stateBlock->streamStride[0] = 0;
5723 This->stateBlock->pIndexData = NULL;
5728 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
5730 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0, DrawPrimStrideData);
5733 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
5734 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
5735 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5736 HRESULT hr = WINED3D_OK;
5737 WINED3DRESOURCETYPE sourceType;
5738 WINED3DRESOURCETYPE destinationType;
5741 /* TODO: think about moving the code into IWineD3DBaseTexture */
5743 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
5745 /* verify that the source and destination textures aren't NULL */
5746 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
5747 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
5748 This, pSourceTexture, pDestinationTexture);
5749 hr = WINED3DERR_INVALIDCALL;
5752 if (pSourceTexture == pDestinationTexture) {
5753 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
5754 This, pSourceTexture, pDestinationTexture);
5755 hr = WINED3DERR_INVALIDCALL;
5757 /* Verify that the source and destination textures are the same type */
5758 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
5759 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
5761 if (sourceType != destinationType) {
5762 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
5764 hr = WINED3DERR_INVALIDCALL;
5767 /* check that both textures have the identical numbers of levels */
5768 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
5769 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
5770 hr = WINED3DERR_INVALIDCALL;
5773 if (WINED3D_OK == hr) {
5775 /* Make sure that the destination texture is loaded */
5776 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
5778 /* Update every surface level of the texture */
5779 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
5781 switch (sourceType) {
5782 case WINED3DRTYPE_TEXTURE:
5784 IWineD3DSurface *srcSurface;
5785 IWineD3DSurface *destSurface;
5787 for (i = 0 ; i < levels ; ++i) {
5788 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
5789 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
5790 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5791 IWineD3DSurface_Release(srcSurface);
5792 IWineD3DSurface_Release(destSurface);
5793 if (WINED3D_OK != hr) {
5794 WARN("(%p) : Call to update surface failed\n", This);
5800 case WINED3DRTYPE_CUBETEXTURE:
5802 IWineD3DSurface *srcSurface;
5803 IWineD3DSurface *destSurface;
5804 WINED3DCUBEMAP_FACES faceType;
5806 for (i = 0 ; i < levels ; ++i) {
5807 /* Update each cube face */
5808 for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
5809 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
5810 if (WINED3D_OK != hr) {
5811 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5813 TRACE("Got srcSurface %p\n", srcSurface);
5815 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
5816 if (WINED3D_OK != hr) {
5817 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5819 TRACE("Got desrSurface %p\n", destSurface);
5821 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5822 IWineD3DSurface_Release(srcSurface);
5823 IWineD3DSurface_Release(destSurface);
5824 if (WINED3D_OK != hr) {
5825 WARN("(%p) : Call to update surface failed\n", This);
5832 #if 0 /* TODO: Add support for volume textures */
5833 case WINED3DRTYPE_VOLUMETEXTURE:
5835 IWineD3DVolume srcVolume = NULL;
5836 IWineD3DSurface destVolume = NULL;
5838 for (i = 0 ; i < levels ; ++i) {
5839 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
5840 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
5841 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
5842 IWineD3DVolume_Release(srcSurface);
5843 IWineD3DVolume_Release(destSurface);
5844 if (WINED3D_OK != hr) {
5845 WARN("(%p) : Call to update volume failed\n", This);
5853 FIXME("(%p) : Unsupported source and destination type\n", This);
5854 hr = WINED3DERR_INVALIDCALL;
5861 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
5862 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
5863 CONST RECT* pDestRect, WINED3DTEXTUREFILTERTYPE Filter) {
5864 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5866 TRACE("(%p) : stub\n", This);
5869 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
5870 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5871 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
5872 * NOTE It may be best to move the code into surface to occomplish this
5873 ****************************************/
5875 WINED3DSURFACE_DESC surfaceDesc;
5876 unsigned int surfaceWidth, surfaceHeight;
5877 glDescriptor *targetGlDescription = NULL;
5878 glDescriptor *surfaceGlDescription = NULL;
5879 IWineD3DSwapChainImpl *container = NULL;
5881 IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
5882 IWineD3DSurface_GetGlDesc(pSurface, &surfaceGlDescription);
5883 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5885 surfaceDesc.Width = &surfaceWidth;
5886 surfaceDesc.Height = &surfaceHeight;
5887 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5888 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
5890 /* Ok, I may need to setup some kind of active swapchain reference on the device */
5891 IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
5893 /* TODO: opengl Context switching for swapchains etc... */
5894 if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
5895 if (NULL != container && (pRenderTarget == container->backBuffer)) {
5896 glReadBuffer(GL_BACK);
5897 vcheckGLcall("glReadBuffer(GL_BACK)");
5898 } else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
5899 glReadBuffer(GL_FRONT);
5900 vcheckGLcall("glReadBuffer(GL_FRONT)");
5901 } else if (pRenderTarget == This->depthStencilBuffer) {
5902 FIXME("Reading of depthstencil not yet supported\n");
5905 glReadPixels(surfaceGlDescription->target,
5906 surfaceGlDescription->level,
5909 surfaceGlDescription->glFormat,
5910 surfaceGlDescription->glType,
5911 (void *)IWineD3DSurface_GetData(pSurface));
5912 vcheckGLcall("glReadPixels(...)");
5913 if(NULL != container ){
5914 IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
5917 IWineD3DBaseTexture *container;
5918 GLenum textureDimensions = GL_TEXTURE_2D;
5920 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
5921 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
5922 IWineD3DBaseTexture_Release(container);
5924 /* TODO: 2D -> Cube surface coppies etc.. */
5925 if (surfaceGlDescription->target != textureDimensions) {
5926 FIXME("(%p) : Texture dimension mismatch\n", This);
5928 glEnable(textureDimensions);
5929 vcheckGLcall("glEnable(GL_TEXTURE_...)");
5930 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
5931 glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
5932 vcheckGLcall("glBindTexture");
5933 glGetTexImage(surfaceGlDescription->target,
5934 surfaceGlDescription->level,
5935 surfaceGlDescription->glFormat,
5936 surfaceGlDescription->glType,
5937 (void *)IWineD3DSurface_GetData(pSurface));
5938 glDisable(textureDimensions);
5939 vcheckGLcall("glDisable(GL_TEXTURE_...)");
5946 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5947 IWineD3DSwapChain *swapChain;
5949 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
5950 if(hr == WINED3D_OK) {
5951 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5952 IWineD3DSwapChain_Release(swapChain);
5957 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5958 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5959 /* return a sensible default */
5961 /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
5962 FIXME("(%p) : stub\n", This);
5966 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5967 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5969 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5970 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5971 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5972 return WINED3DERR_INVALIDCALL;
5974 for (j = 0; j < 256; ++j) {
5975 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
5976 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5977 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
5978 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5980 TRACE("(%p) : returning\n", This);
5984 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5985 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5987 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5988 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5989 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5990 return WINED3DERR_INVALIDCALL;
5992 for (j = 0; j < 256; ++j) {
5993 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
5994 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5995 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
5996 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5998 TRACE("(%p) : returning\n", This);
6002 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
6003 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6004 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6005 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6006 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6007 return WINED3DERR_INVALIDCALL;
6009 /*TODO: stateblocks */
6010 This->currentPalette = PaletteNumber;
6011 TRACE("(%p) : returning\n", This);
6015 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
6016 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6017 if (PaletteNumber == NULL) {
6018 WARN("(%p) : returning Invalid Call\n", This);
6019 return WINED3DERR_INVALIDCALL;
6021 /*TODO: stateblocks */
6022 *PaletteNumber = This->currentPalette;
6023 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
6027 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
6028 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6029 static BOOL showFixmes = TRUE;
6031 FIXME("(%p) : stub\n", This);
6035 This->softwareVertexProcessing = bSoftware;
6040 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
6041 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6042 static BOOL showFixmes = TRUE;
6044 FIXME("(%p) : stub\n", This);
6047 return This->softwareVertexProcessing;
6051 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
6052 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6053 IWineD3DSwapChain *swapChain;
6056 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
6058 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
6059 if(hr == WINED3D_OK){
6060 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
6061 IWineD3DSwapChain_Release(swapChain);
6063 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
6069 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
6070 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6071 static BOOL showfixmes = TRUE;
6072 if(nSegments != 0.0f) {
6074 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
6081 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
6082 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6083 static BOOL showfixmes = TRUE;
6085 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
6091 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
6092 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6093 /** TODO: remove casts to IWineD3DSurfaceImpl
6094 * NOTE: move code to surface to accomplish this
6095 ****************************************/
6096 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
6097 int srcWidth, srcHeight;
6098 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
6099 WINED3DFORMAT destFormat, srcFormat;
6101 int destLeft, destTop;
6102 WINED3DPOOL srcPool, destPool;
6104 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
6105 glDescriptor *glDescription = NULL;
6106 GLenum textureDimensions = GL_TEXTURE_2D;
6107 IWineD3DBaseTexture *baseTexture;
6109 WINED3DSURFACE_DESC winedesc;
6111 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
6112 memset(&winedesc, 0, sizeof(winedesc));
6113 winedesc.Width = &srcSurfaceWidth;
6114 winedesc.Height = &srcSurfaceHeight;
6115 winedesc.Pool = &srcPool;
6116 winedesc.Format = &srcFormat;
6118 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6120 winedesc.Width = &destSurfaceWidth;
6121 winedesc.Height = &destSurfaceHeight;
6122 winedesc.Pool = &destPool;
6123 winedesc.Format = &destFormat;
6124 winedesc.Size = &destSize;
6126 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6128 if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool != WINED3DPOOL_DEFAULT){
6129 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
6130 return WINED3DERR_INVALIDCALL;
6133 if (destFormat == WINED3DFMT_UNKNOWN) {
6134 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6135 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6137 /* Get the update surface description */
6138 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6141 /* Make sure the surface is loaded and up to date */
6142 IWineD3DSurface_PreLoad(pDestinationSurface);
6144 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
6148 /* this needs to be done in lines if the sourceRect != the sourceWidth */
6149 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
6150 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
6151 destLeft = pDestPoint ? pDestPoint->x : 0;
6152 destTop = pDestPoint ? pDestPoint->y : 0;
6155 /* This function doesn't support compressed textures
6156 the pitch is just bytesPerPixel * width */
6157 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
6158 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
6159 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
6160 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
6162 /* TODO DXT formats */
6164 if(pSourceRect != NULL && pSourceRect->top != 0){
6165 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
6167 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
6169 ,glDescription->level
6174 ,glDescription->glFormat
6175 ,glDescription->glType
6176 ,IWineD3DSurface_GetData(pSourceSurface)
6180 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
6182 /* need to lock the surface to get the data */
6183 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
6186 /* TODO: Cube and volume support */
6188 /* not a whole row so we have to do it a line at a time */
6191 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
6192 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
6194 for(j = destTop ; j < (srcHeight + destTop) ; j++){
6196 glTexSubImage2D(glDescription->target
6197 ,glDescription->level
6202 ,glDescription->glFormat
6203 ,glDescription->glType
6204 ,data /* could be quicker using */
6209 } else { /* Full width, so just write out the whole texture */
6211 if (WINED3DFMT_DXT1 == destFormat ||
6212 WINED3DFMT_DXT2 == destFormat ||
6213 WINED3DFMT_DXT3 == destFormat ||
6214 WINED3DFMT_DXT4 == destFormat ||
6215 WINED3DFMT_DXT5 == destFormat) {
6216 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
6217 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
6218 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
6219 FIXME("Updating part of a compressed texture is not supported at the moment\n");
6220 } if (destFormat != srcFormat) {
6221 FIXME("Updating mixed format compressed texture is not curretly support\n");
6223 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
6224 glDescription->level,
6225 glDescription->glFormatInternal,
6230 IWineD3DSurface_GetData(pSourceSurface));
6233 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
6238 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
6240 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
6241 to repack the data from pow2Width/Height to expected Width,Height, this makes the
6242 data returned by GetData non-power2 width/height with hardware non-power2
6243 pow2Width/height are set to surface width height, repacking isn't needed so it
6244 doesn't matter which function gets called. */
6245 glTexSubImage2D(glDescription->target
6246 ,glDescription->level
6251 ,glDescription->glFormat
6252 ,glDescription->glType
6253 ,IWineD3DSurface_GetData(pSourceSurface)
6257 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
6258 glTexSubImage2D(glDescription->target
6259 ,glDescription->level
6262 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
6263 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
6264 ,glDescription->glFormat
6265 ,glDescription->glType
6266 ,IWineD3DSurface_GetData(pSourceSurface)
6272 checkGLcall("glTexSubImage2D");
6274 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
6275 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
6276 * surface bigger than it needs to be hmm.. */
6277 if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
6278 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
6279 IWineD3DBaseTexture_Release(baseTexture);
6282 glDisable(textureDimensions); /* This needs to be managed better.... */
6288 /* Used by DirectX 8 */
6289 HRESULT WINAPI IWineD3DDeviceImpl_CopyRects(IWineD3DDevice *iface,
6290 IWineD3DSurface* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
6291 IWineD3DSurface* pDestinationSurface, CONST POINT* pDestPointsArray) {
6293 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6294 HRESULT hr = WINED3D_OK;
6295 WINED3DFORMAT srcFormat, destFormat;
6296 UINT srcWidth, destWidth;
6297 UINT srcHeight, destHeight;
6299 WINED3DSURFACE_DESC winedesc;
6301 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
6302 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
6305 /* Check that the source texture is in WINED3DPOOL_SYSTEMMEM and the destination texture is in WINED3DPOOL_DEFAULT */
6306 memset(&winedesc, 0, sizeof(winedesc));
6308 winedesc.Format = &srcFormat;
6309 winedesc.Width = &srcWidth;
6310 winedesc.Height = &srcHeight;
6311 winedesc.Size = &srcSize;
6312 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6314 winedesc.Format = &destFormat;
6315 winedesc.Width = &destWidth;
6316 winedesc.Height = &destHeight;
6317 winedesc.Size = NULL;
6318 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6320 /* Check that the source and destination formats match */
6321 if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat) {
6322 WARN("(%p) source %p format must match the dest %p format, returning WINED3DERR_INVALIDCALL\n", This, pSourceSurface, pDestinationSurface);
6323 return WINED3DERR_INVALIDCALL;
6324 } else if (WINED3DFMT_UNKNOWN == destFormat) {
6325 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6326 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6327 destFormat = srcFormat;
6330 /* Quick if complete copy ... */
6331 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
6333 if (srcWidth == destWidth && srcHeight == destHeight) {
6334 WINED3DLOCKED_RECT lrSrc;
6335 WINED3DLOCKED_RECT lrDst;
6336 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, NULL, WINED3DLOCK_READONLY);
6337 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, NULL, 0L);
6338 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", srcWidth, srcHeight);
6340 memcpy(lrDst.pBits, lrSrc.pBits, srcSize);
6342 IWineD3DSurface_UnlockRect(pSourceSurface);
6343 IWineD3DSurface_UnlockRect(pDestinationSurface);
6344 TRACE("Unlocked src and dst\n");
6348 FIXME("Wanted to copy all surfaces but size not compatible, returning WINED3DERR_INVALIDCALL\n");
6349 hr = WINED3DERR_INVALIDCALL;
6354 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
6356 int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
6359 /* Copy rect by rect */
6360 for (i = 0; i < cRects; ++i) {
6361 CONST RECT* r = &pSourceRectsArray[i];
6362 CONST POINT* p = &pDestPointsArray[i];
6365 WINED3DLOCKED_RECT lrSrc;
6366 WINED3DLOCKED_RECT lrDst;
6369 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
6370 if (srcFormat == WINED3DFMT_DXT1) {
6371 copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
6373 copyperline = ((r->right - r->left) * bytesPerPixel);
6376 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
6377 dest_rect.left = p->x;
6378 dest_rect.top = p->y;
6379 dest_rect.right = p->x + (r->right - r->left);
6380 dest_rect.bottom= p->y + (r->bottom - r->top);
6381 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
6382 TRACE("Locked src and dst\n");
6384 /* Find where to start */
6385 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
6386 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
6388 IWineD3DSurface_UnlockRect(pSourceSurface);
6389 IWineD3DSurface_UnlockRect(pDestinationSurface);
6390 TRACE("Unlocked src and dst\n");
6393 FIXME("Wanted to copy partial surfaces not implemented, returning WINED3DERR_INVALIDCALL\n");
6394 hr = WINED3DERR_INVALIDCALL;
6401 /* Implementation details at http://developer.nvidia.com/attach/6494
6403 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
6404 hmm.. no longer supported use
6405 OpenGL evaluators or tessellate surfaces within your application.
6408 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
6409 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
6410 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6411 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
6412 FIXME("(%p) : Stub\n", This);
6417 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
6418 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
6419 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6420 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
6421 FIXME("(%p) : Stub\n", This);
6425 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
6426 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6427 TRACE("(%p) Handle(%d)\n", This, Handle);
6428 FIXME("(%p) : Stub\n", This);
6432 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
6433 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
6434 fill a surface with a block of color! */
6435 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6436 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
6437 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
6438 IWineD3DSwapChainImpl *container = NULL;
6439 BOOL isRenderTarget = FALSE;
6440 unsigned int width, height;
6441 unsigned int top, left;
6444 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
6446 if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
6447 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
6448 return WINED3DERR_INVALIDCALL;
6451 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
6452 if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
6453 if (WINED3DUSAGE_RENDERTARGET & surface->resource.usage) {
6454 /* TODO: make sure we set everything back to the way it was, and context management!
6455 glGetIntegerv(GL_READ_BUFFER, &prev_read);
6456 vcheckGLcall("glIntegerv");
6457 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
6458 vcheckGLcall("glIntegerv");
6460 TRACE("Color fill to render targets may cause some graphics issues\n");
6461 if (pSurface == container->frontBuffer) {
6462 glDrawBuffer(GL_FRONT);
6464 glDrawBuffer(GL_BACK);
6467 if (WINED3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
6468 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld\n", surface, surface->resource.usage);
6470 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
6472 if (container != NULL) {
6473 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
6475 /* we can use GL_STENCIL_INDEX etc...*/
6478 if (container != NULL) {
6479 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
6481 isRenderTarget = TRUE;
6483 /* TODO: drawing to GL_FRONT and GL_BACK */
6484 /* TODO: see if things can be speeded up by using the correct
6485 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
6486 if (pRect == NULL) {
6489 width = surface->currentDesc.Width;
6490 height = surface->currentDesc.Height;
6494 width = pRect->x2 - left;
6495 height = pRect->y2 - top;
6498 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
6499 /* Create a 'line' of color color, in the correct format for the surface */
6500 for (u = 0 ; u < width ; u ++) {
6505 if (isRenderTarget == FALSE) {
6506 glDescriptor *glDesc;
6507 IWineD3DSurface_PreLoad(pSurface);
6509 /* draw a block of the coloured line on the sufrace */
6510 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
6511 for (v = 0 ; v< height;v++) {
6512 glTexSubImage2D(glDesc->target
6513 ,glDesc->level /* level */
6523 checkGLcall("glTexSubImage2D");
6525 glDisable(glDesc->target);
6527 /** FIXME: Using GLClear may be faster **/
6528 glRasterPos2i(left, top);
6529 glPixelZoom((float)width ,(float)height);
6530 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
6531 checkGLcall("glDrawPixels");
6533 HeapFree(GetProcessHeap(), 0, data);
6539 /* rendertarget and deptth stencil functions */
6540 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
6541 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6543 /* FIXME: Implelent RenderTargetIndex >0 */
6544 if(RenderTargetIndex > 0)
6545 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
6547 *ppRenderTarget = This->renderTarget;
6548 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
6549 /* Note inc ref on returned surface */
6550 if(*ppRenderTarget != NULL)
6551 IWineD3DSurface_AddRef(*ppRenderTarget);
6555 HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
6556 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6557 IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
6558 IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
6559 IWineD3DSwapChainImpl *Swapchain;
6562 TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
6564 hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
6565 if(hr != WINED3D_OK) {
6566 ERR("Can't get the swapchain\n");
6570 /* Make sure to release the swapchain */
6571 IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
6573 if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
6574 ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6575 return WINED3DERR_INVALIDCALL;
6577 else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
6578 ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6579 return WINED3DERR_INVALIDCALL;
6582 if(Swapchain->frontBuffer != Front) {
6583 TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
6585 if(Swapchain->frontBuffer)
6586 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
6587 Swapchain->frontBuffer = Front;
6589 if(Swapchain->frontBuffer) {
6590 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
6593 if(Swapchain->backBuffer != Back) {
6594 TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
6596 if(!Swapchain->backBuffer) {
6597 /* GL was told to draw to the front buffer at creation,
6600 glDrawBuffer(GL_BACK);
6601 checkGLcall("glDrawBuffer(GL_BACK)");
6603 /* That makes problems - disable for now */
6604 /* glDrawBuffer(GL_FRONT); */
6605 checkGLcall("glDrawBuffer(GL_FRONT)");
6609 if(Swapchain->backBuffer)
6610 IWineD3DSurface_SetContainer(Swapchain->backBuffer, NULL);
6611 Swapchain->backBuffer = Back;
6613 if(Swapchain->backBuffer) {
6614 IWineD3DSurface_SetContainer(Swapchain->backBuffer, (IWineD3DBase *) Swapchain);
6622 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
6623 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6624 *ppZStencilSurface = This->depthStencilBuffer;
6625 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
6627 if(*ppZStencilSurface != NULL) {
6628 /* Note inc ref on returned surface */
6629 IWineD3DSurface_AddRef(*ppZStencilSurface);
6634 /* internal static helper functions */
6635 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6636 IWineD3DSurface *RenderSurface);
6638 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
6639 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6640 HRESULT hr = WINED3D_OK;
6641 WINED3DVIEWPORT viewport;
6643 TRACE("(%p) Swapping rendertarget\n",This);
6644 if (RenderTargetIndex > 0) {
6645 FIXME("(%p) Render targets other than the first are not supported\n",This);
6646 RenderTargetIndex = 0;
6649 /* MSDN says that null disables the render target
6650 but a device must always be associated with a render target
6651 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
6653 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
6656 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
6657 FIXME("Trying to set render target 0 to NULL\n");
6658 return WINED3DERR_INVALIDCALL;
6660 /* TODO: replace Impl* usage with interface usage */
6661 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
6662 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);
6663 return WINED3DERR_INVALIDCALL;
6665 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
6666 * builds, but I think wine counts as a 'debug' build for now.
6667 ******************************/
6668 /* If we are trying to set what we already have, don't bother */
6669 if (pRenderTarget == This->renderTarget) {
6670 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6672 /* Otherwise, set the render target up */
6674 if (FALSE == This->sceneEnded) {
6675 IWineD3DDevice_EndScene(iface);
6677 TRACE("clearing renderer\n");
6678 /* IWineD3DDeviceImpl_CleanRender(iface); */
6679 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6680 depending on the renter target implementation being used.
6681 A shared context implementation will share all buffers between all rendertargets (including swapchains),
6682 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6683 stencil buffer and incure an extra memory overhead */
6684 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
6687 if (SUCCEEDED(hr)) {
6688 /* Finally, reset the viewport as the MSDN states. */
6689 /* TODO: Replace impl usage */
6690 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
6691 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
6694 viewport.MaxZ = 1.0f;
6695 viewport.MinZ = 0.0f;
6696 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
6698 FIXME("Unknown error setting the render target\n");
6700 This->sceneEnded = FALSE;
6704 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
6705 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6706 HRESULT hr = WINED3D_OK;
6707 IWineD3DSurface *tmp;
6709 TRACE("(%p) Swapping z-buffer\n",This);
6711 if (pNewZStencil == This->stencilBufferTarget) {
6712 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6714 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6715 * depending on the renter target implementation being used.
6716 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
6717 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6718 * stencil buffer and incure an extra memory overhead
6719 ******************************************************/
6722 tmp = This->stencilBufferTarget;
6723 This->stencilBufferTarget = pNewZStencil;
6724 /* should we be calling the parent or the wined3d surface? */
6725 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
6726 if (NULL != tmp) IWineD3DSurface_Release(tmp);
6728 /** TODO: glEnable/glDisable on depth/stencil depending on
6729 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
6730 **********************************************************/
6737 #ifdef GL_VERSION_1_3
6738 /* Internal functions not in DirectX */
6739 /** TODO: move this off to the opengl context manager
6740 *(the swapchain doesn't need to know anything about offscreen rendering!)
6741 ****************************************************/
6743 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
6745 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6747 TRACE("(%p), %p\n", This, swapchain);
6749 if (swapchain->win != swapchain->drawable) {
6750 /* Set everything back the way it ws */
6751 swapchain->render_ctx = swapchain->glCtx;
6752 swapchain->drawable = swapchain->win;
6757 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
6758 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
6759 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6762 unsigned int height;
6763 WINED3DFORMAT format;
6764 WINED3DSURFACE_DESC surfaceDesc;
6765 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6766 surfaceDesc.Width = &width;
6767 surfaceDesc.Height = &height;
6768 surfaceDesc.Format = &format;
6769 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6771 /* I need a get width/height function (and should do something with the format) */
6772 for (i = 0; i < CONTEXT_CACHE; ++i) {
6773 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
6774 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
6775 the pSurface can be set to 0 allowing it to be reused from cache **/
6776 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
6777 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
6778 *context = &This->contextCache[i];
6781 if (This->contextCache[i].Width == 0) {
6782 This->contextCache[i].pSurface = pSurface;
6783 This->contextCache[i].Width = width;
6784 This->contextCache[i].Height = height;
6785 *context = &This->contextCache[i];
6789 if (i == CONTEXT_CACHE) {
6790 int minUsage = 0x7FFFFFFF; /* MAX_INT */
6791 glContext *dropContext = 0;
6792 for (i = 0; i < CONTEXT_CACHE; i++) {
6793 if (This->contextCache[i].usedcount < minUsage) {
6794 dropContext = &This->contextCache[i];
6795 minUsage = This->contextCache[i].usedcount;
6798 /* clean up the context (this doesn't work for ATI at the moment */
6800 glXDestroyContext(swapchain->display, dropContext->context);
6801 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
6804 dropContext->Width = 0;
6805 dropContext->pSurface = pSurface;
6806 *context = dropContext;
6808 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
6809 for (i = 0; i < CONTEXT_CACHE; i++) {
6810 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
6814 if (*context != NULL)
6817 return E_OUTOFMEMORY;
6821 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
6822 * the functionality needs splitting up so that we don't do more than we should do.
6823 * this only seems to impact performance a little.
6824 ******************************/
6825 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6826 IWineD3DSurface *RenderSurface) {
6827 HRESULT ret = WINED3DERR_INVALIDCALL;
6830 * Currently only active for GLX >= 1.3
6831 * for others versions we'll have to use GLXPixmaps
6833 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
6834 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
6835 * so only check OpenGL version
6836 * ..........................
6837 * I don't believe that it is a problem with NVidia headers,
6838 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
6839 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
6841 * Your application will report GLX version 1.2 on glXQueryVersion.
6842 * However, it is safe to call the GLX 1.3 functions as described below.
6844 #if defined(GL_VERSION_1_3)
6846 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6847 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
6848 IWineD3DSurface *tmp;
6849 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
6850 GLXFBConfig* cfgs = NULL;
6854 IWineD3DSwapChain *currentSwapchain;
6855 IWineD3DSwapChainImpl *swapchain;
6856 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
6857 * but switch them off if the StencilSurface is set to NULL
6858 ** *********************************************************/
6859 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
6860 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
6863 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
6864 it StencilSurface != NULL && zBufferTarget == NULL switch it on
6867 #define PUSH1(att) attribs[nAttribs++] = (att);
6868 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
6870 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
6872 /** TODO: remove the reff to Impl (context manager should fix this!) **/
6873 IWineD3DSwapChainImpl *impSwapChain;
6874 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
6875 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
6876 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
6881 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
6882 PUSH2(GLX_X_RENDERABLE, TRUE);
6883 PUSH2(GLX_DOUBLEBUFFER, TRUE);
6884 TRACE("calling makeglcfg\n");
6885 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
6888 TRACE("calling chooseFGConfig\n");
6889 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6892 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
6893 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
6894 why we failed and only show this message once! */
6895 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"); /**/
6897 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
6898 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
6899 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
6900 PUSH2(GLX_DOUBLEBUFFER, FALSE);
6901 TRACE("calling makeglcfg\n");
6902 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
6904 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6911 for (i = 0; i < nCfgs; ++i) {
6912 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
6913 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
6914 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
6917 if (NULL != This->renderTarget) {
6919 vcheckGLcall("glFlush");
6920 /** This is only useful if the old render target was a swapchain,
6921 * we need to supercede this with a function that displays
6922 * the current buffer on the screen. This is easy to do in glx1.3 but
6923 * we need to do copy-write pixels in glx 1.2.
6924 ************************************************/
6925 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
6927 printf("Hit Enter to get next frame ...\n");
6933 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain) != WINED3D_OK) {
6934 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
6935 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
6939 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
6940 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
6941 **********************************************************************/
6942 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == WINED3D_OK) {
6943 /* We also need to make sure that the lights &co are also in the context of the swapchains */
6944 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
6945 TRACE("making swapchain active\n");
6946 if (RenderSurface != This->renderTarget) {
6947 if (RenderSurface == swapchain->backBuffer) {
6949 /* This could be flagged so that some operations work directly with the front buffer */
6950 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
6952 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
6954 TRACE("Error in setting current context: context %p drawable %ld !\n",
6955 impSwapChain->glCtx, impSwapChain->win);
6958 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6960 checkGLcall("glXMakeContextCurrent");
6962 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
6964 else if (pbuffer_support && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
6966 /** ********************************************************************
6967 * This is a quickly hacked out implementation of offscreen textures.
6968 * It will work in most cases but there may be problems if the client
6969 * modifies the texture directly, or expects the contents of the rendertarget
6972 * There are some real speed vs compatibility issues here:
6973 * we should really use a new context for every texture, but that eats ram.
6974 * we should also be restoring the texture to the pbuffer but that eats CPU
6975 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
6976 * but if this means reusing the display backbuffer then we need to make sure that
6977 * states are correctly preserved.
6978 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
6979 * and gain a good performance increase at the cost of compatibility.
6980 * I would suggest that, when this is the case, a user configurable flag be made
6981 * available, allowing the user to choose the best emulated experience for them.
6982 *********************************************************************/
6984 XVisualInfo *visinfo;
6985 glContext *newContext;
6987 /* Here were using a shared context model */
6988 if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
6989 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6992 /* If the context doesn't exist then create a new one */
6993 /* TODO: This should really be part of findGlContext */
6994 if (NULL == newContext->context) {
6996 TRACE("making new buffer\n");
6998 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
6999 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
7002 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
7004 /** ****************************************
7005 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
7007 * In future releases, we may provide the calls glXCreateNewContext,
7008 * glXQueryDrawable and glXMakeContextCurrent.
7009 * so until then we have to use glXGetVisualFromFBConfig &co..
7010 ********************************************/
7013 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
7015 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
7017 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
7021 if (NULL == newContext || NULL == newContext->context) {
7022 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7024 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
7025 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
7026 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
7029 /* Clean up the old context */
7030 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
7031 /* Set the current context of the swapchain to the new context */
7032 impSwapChain->drawable = newContext->drawable;
7033 impSwapChain->render_ctx = newContext->context;
7037 #if 1 /* Apply the stateblock to the new context
7038 FIXME: This is a bit of a hack, each context should know it's own state,
7039 the directX current directX state should then be applied to the context */
7042 IWineD3DStateBlockImpl *oldUpdateStateBlock;
7043 oldUpdateStateBlock = This->updateStateBlock;
7044 oldRecording= This->isRecordingState;
7045 This->isRecordingState = FALSE;
7046 This->updateStateBlock = This->stateBlock;
7047 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
7049 This->isRecordingState = oldRecording;
7050 This->updateStateBlock = oldUpdateStateBlock;
7055 /* clean up the current rendertargets swapchain (if it belonged to one) */
7056 if (currentSwapchain != NULL) {
7057 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
7060 /* Were done with the opengl context management, setup the rendertargets */
7062 tmp = This->renderTarget;
7063 This->renderTarget = RenderSurface;
7064 IWineD3DSurface_AddRef(This->renderTarget);
7065 IWineD3DSurface_Release(tmp);
7071 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
7072 /* Check that the container is not a swapchain member */
7074 IWineD3DSwapChain *tmpSwapChain;
7075 if (WINED3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
7076 This->renderUpsideDown = TRUE;
7078 This->renderUpsideDown = FALSE;
7079 IWineD3DSwapChain_Release(tmpSwapChain);
7081 /* Force updating the cull mode */
7082 TRACE("setting render state\n");
7083 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
7084 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
7086 /* Force updating projection matrix */
7087 This->last_was_rhw = FALSE;
7088 This->proj_valid = FALSE;
7096 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
7097 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
7102 if ( NULL != impSwapChain) {
7103 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
7111 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
7112 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
7113 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7114 /* TODO: the use of Impl is deprecated. */
7115 /* some basic validation checks */
7116 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
7118 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
7120 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
7121 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
7122 return WINED3DERR_INVALIDCALL;
7124 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
7125 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
7126 return WINED3DERR_INVALIDCALL;
7128 /* TODO: make the cursor 'real' */
7130 This->xHotSpot = XHotSpot;
7131 This->yHotSpot = YHotSpot;
7136 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
7137 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7138 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
7140 This->xScreenSpace = XScreenSpace;
7141 This->yScreenSpace = YScreenSpace;
7147 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
7148 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7149 TRACE("(%p) : visible(%d)\n", This, bShow);
7151 This->bCursorVisible = bShow;
7156 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
7157 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7158 TRACE("(%p) : state (%lu)\n", This, This->state);
7159 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
7160 switch (This->state) {
7163 case WINED3DERR_DEVICELOST:
7165 ResourceList *resourceList = This->resources;
7166 while (NULL != resourceList) {
7167 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
7168 return WINED3DERR_DEVICENOTRESET;
7169 resourceList = resourceList->next;
7171 return WINED3DERR_DEVICELOST;
7173 case WINED3DERR_DRIVERINTERNALERROR:
7174 return WINED3DERR_DRIVERINTERNALERROR;
7178 return WINED3DERR_DRIVERINTERNALERROR;
7182 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
7183 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7184 /** FIXME: Resource tracking needs to be done,
7185 * The closes we can do to this is set the priorities of all managed textures low
7186 * and then reset them.
7187 ***********************************************************/
7188 FIXME("(%p) : stub\n", This);
7192 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
7193 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7194 /** FIXME: Resource trascking needs to be done.
7195 * in effect this pulls all non only default
7196 * textures out of video memory and deletes all glTextures (glDeleteTextures)
7197 * and should clear down the context and set it up according to pPresentationParameters
7198 ***********************************************************/
7199 FIXME("(%p) : stub\n", This);
7203 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
7204 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7205 /** FIXME: always true at the moment **/
7206 if(bEnableDialogs == FALSE) {
7207 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
7213 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
7214 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7215 TRACE("(%p) : pParameters %p\n", This, pParameters);
7217 *pParameters = This->createParms;
7221 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
7222 IWineD3DSwapChain *swapchain;
7223 HRESULT hrc = WINED3D_OK;
7225 TRACE("Relaying to swapchain\n");
7227 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7228 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
7229 IWineD3DSwapChain_Release(swapchain);
7234 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
7235 IWineD3DSwapChain *swapchain;
7236 HRESULT hrc = WINED3D_OK;
7238 TRACE("Relaying to swapchain\n");
7240 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7241 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
7242 IWineD3DSwapChain_Release(swapchain);
7248 /** ********************************************************
7249 * Notification functions
7250 ** ********************************************************/
7251 /** This function must be called in the release of a resource when ref == 0,
7252 * the contents of resource must still be correct,
7253 * any handels to other resource held by the caller must be closed
7254 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
7255 *****************************************************/
7256 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7257 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7258 ResourceList* resourceList;
7260 TRACE("(%p) : resource %p\n", This, resource);
7262 EnterCriticalSection(&resourceStoreCriticalSection);
7264 /* add a new texture to the frot of the linked list */
7265 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
7266 resourceList->resource = resource;
7268 /* Get the old head */
7269 resourceList->next = This->resources;
7271 This->resources = resourceList;
7272 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
7275 LeaveCriticalSection(&resourceStoreCriticalSection);
7280 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7281 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7282 ResourceList* resourceList = NULL;
7283 ResourceList* previousResourceList = NULL;
7285 TRACE("(%p) : resource %p\n", This, resource);
7288 EnterCriticalSection(&resourceStoreCriticalSection);
7290 resourceList = This->resources;
7292 while (resourceList != NULL) {
7293 if(resourceList->resource == resource) break;
7294 previousResourceList = resourceList;
7295 resourceList = resourceList->next;
7298 if (resourceList == NULL) {
7299 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
7301 LeaveCriticalSection(&resourceStoreCriticalSection);
7305 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
7307 /* make sure we don't leave a hole in the list */
7308 if (previousResourceList != NULL) {
7309 previousResourceList->next = resourceList->next;
7311 This->resources = resourceList->next;
7315 LeaveCriticalSection(&resourceStoreCriticalSection);
7321 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
7322 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7325 TRACE("(%p) : resource %p\n", This, resource);
7326 switch(IWineD3DResource_GetType(resource)){
7327 case WINED3DRTYPE_SURFACE:
7328 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
7330 case WINED3DRTYPE_TEXTURE:
7331 case WINED3DRTYPE_CUBETEXTURE:
7332 case WINED3DRTYPE_VOLUMETEXTURE:
7333 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
7334 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7335 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7336 This->stateBlock->textures[counter] = NULL;
7338 if (This->updateStateBlock != This->stateBlock ){
7339 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7340 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7341 This->updateStateBlock->textures[counter] = NULL;
7346 case WINED3DRTYPE_VOLUME:
7347 /* TODO: nothing really? */
7349 case WINED3DRTYPE_VERTEXBUFFER:
7350 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
7353 TRACE("Cleaning up stream pointers\n");
7355 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
7356 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
7357 FINDOUT: should changes.streamSource[StreamNumber] be set ?
7359 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7360 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
7361 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
7362 This->updateStateBlock->streamSource[streamNumber] = 0;
7363 /* Set changed flag? */
7366 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) */
7367 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
7368 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
7369 This->stateBlock->streamSource[streamNumber] = 0;
7372 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
7373 else { /* This shouldn't happen */
7374 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
7381 case WINED3DRTYPE_INDEXBUFFER:
7382 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
7383 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7384 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7385 This->updateStateBlock->pIndexData = NULL;
7388 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
7389 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7390 This->stateBlock->pIndexData = NULL;
7396 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
7401 /* Remove the resoruce from the resourceStore */
7402 IWineD3DDeviceImpl_RemoveResource(iface, resource);
7404 TRACE("Resource released\n");
7408 /**********************************************************
7409 * IWineD3DDevice VTbl follows
7410 **********************************************************/
7412 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
7414 /*** IUnknown methods ***/
7415 IWineD3DDeviceImpl_QueryInterface,
7416 IWineD3DDeviceImpl_AddRef,
7417 IWineD3DDeviceImpl_Release,
7418 /*** IWineD3DDevice methods ***/
7419 IWineD3DDeviceImpl_GetParent,
7420 /*** Creation methods**/
7421 IWineD3DDeviceImpl_CreateVertexBuffer,
7422 IWineD3DDeviceImpl_CreateIndexBuffer,
7423 IWineD3DDeviceImpl_CreateStateBlock,
7424 IWineD3DDeviceImpl_CreateSurface,
7425 IWineD3DDeviceImpl_CreateTexture,
7426 IWineD3DDeviceImpl_CreateVolumeTexture,
7427 IWineD3DDeviceImpl_CreateVolume,
7428 IWineD3DDeviceImpl_CreateCubeTexture,
7429 IWineD3DDeviceImpl_CreateQuery,
7430 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
7431 IWineD3DDeviceImpl_CreateVertexDeclaration,
7432 IWineD3DDeviceImpl_CreateVertexShader,
7433 IWineD3DDeviceImpl_CreatePixelShader,
7434 IWineD3DDeviceImpl_CreatePalette,
7435 /*** Odd functions **/
7436 IWineD3DDeviceImpl_Init3D,
7437 IWineD3DDeviceImpl_Uninit3D,
7438 IWineD3DDeviceImpl_EnumDisplayModes,
7439 IWineD3DDeviceImpl_EvictManagedResources,
7440 IWineD3DDeviceImpl_GetAvailableTextureMem,
7441 IWineD3DDeviceImpl_GetBackBuffer,
7442 IWineD3DDeviceImpl_GetCreationParameters,
7443 IWineD3DDeviceImpl_GetDeviceCaps,
7444 IWineD3DDeviceImpl_GetDirect3D,
7445 IWineD3DDeviceImpl_GetDisplayMode,
7446 IWineD3DDeviceImpl_SetDisplayMode,
7447 IWineD3DDeviceImpl_GetHWND,
7448 IWineD3DDeviceImpl_SetHWND,
7449 IWineD3DDeviceImpl_GetNumberOfSwapChains,
7450 IWineD3DDeviceImpl_GetRasterStatus,
7451 IWineD3DDeviceImpl_GetSwapChain,
7452 IWineD3DDeviceImpl_Reset,
7453 IWineD3DDeviceImpl_SetDialogBoxMode,
7454 IWineD3DDeviceImpl_SetCursorProperties,
7455 IWineD3DDeviceImpl_SetCursorPosition,
7456 IWineD3DDeviceImpl_ShowCursor,
7457 IWineD3DDeviceImpl_TestCooperativeLevel,
7458 IWineD3DDeviceImpl_EnumZBufferFormats,
7459 IWineD3DDeviceImpl_EnumTextureFormats,
7460 /*** Getters and setters **/
7461 IWineD3DDeviceImpl_SetClipPlane,
7462 IWineD3DDeviceImpl_GetClipPlane,
7463 IWineD3DDeviceImpl_SetClipStatus,
7464 IWineD3DDeviceImpl_GetClipStatus,
7465 IWineD3DDeviceImpl_SetCurrentTexturePalette,
7466 IWineD3DDeviceImpl_GetCurrentTexturePalette,
7467 IWineD3DDeviceImpl_SetDepthStencilSurface,
7468 IWineD3DDeviceImpl_GetDepthStencilSurface,
7469 IWineD3DDeviceImpl_SetFVF,
7470 IWineD3DDeviceImpl_GetFVF,
7471 IWineD3DDeviceImpl_SetGammaRamp,
7472 IWineD3DDeviceImpl_GetGammaRamp,
7473 IWineD3DDeviceImpl_SetIndices,
7474 IWineD3DDeviceImpl_GetIndices,
7475 IWineD3DDeviceImpl_SetLight,
7476 IWineD3DDeviceImpl_GetLight,
7477 IWineD3DDeviceImpl_SetLightEnable,
7478 IWineD3DDeviceImpl_GetLightEnable,
7479 IWineD3DDeviceImpl_SetMaterial,
7480 IWineD3DDeviceImpl_GetMaterial,
7481 IWineD3DDeviceImpl_SetNPatchMode,
7482 IWineD3DDeviceImpl_GetNPatchMode,
7483 IWineD3DDeviceImpl_SetPaletteEntries,
7484 IWineD3DDeviceImpl_GetPaletteEntries,
7485 IWineD3DDeviceImpl_SetPixelShader,
7486 IWineD3DDeviceImpl_GetPixelShader,
7487 IWineD3DDeviceImpl_SetPixelShaderConstant,
7488 IWineD3DDeviceImpl_GetPixelShaderConstant,
7489 IWineD3DDeviceImpl_SetPixelShaderConstantB,
7490 IWineD3DDeviceImpl_GetPixelShaderConstantB,
7491 IWineD3DDeviceImpl_SetPixelShaderConstantI,
7492 IWineD3DDeviceImpl_GetPixelShaderConstantI,
7493 IWineD3DDeviceImpl_SetPixelShaderConstantF,
7494 IWineD3DDeviceImpl_GetPixelShaderConstantF,
7495 IWineD3DDeviceImpl_SetPixelShaderConstantN,
7496 IWineD3DDeviceImpl_SetRenderState,
7497 IWineD3DDeviceImpl_GetRenderState,
7498 IWineD3DDeviceImpl_SetRenderTarget,
7499 IWineD3DDeviceImpl_GetRenderTarget,
7500 IWineD3DDeviceImpl_SetFrontBackBuffers,
7501 IWineD3DDeviceImpl_SetSamplerState,
7502 IWineD3DDeviceImpl_GetSamplerState,
7503 IWineD3DDeviceImpl_SetScissorRect,
7504 IWineD3DDeviceImpl_GetScissorRect,
7505 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
7506 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
7507 IWineD3DDeviceImpl_SetStreamSource,
7508 IWineD3DDeviceImpl_GetStreamSource,
7509 IWineD3DDeviceImpl_SetStreamSourceFreq,
7510 IWineD3DDeviceImpl_GetStreamSourceFreq,
7511 IWineD3DDeviceImpl_SetTexture,
7512 IWineD3DDeviceImpl_GetTexture,
7513 IWineD3DDeviceImpl_SetTextureStageState,
7514 IWineD3DDeviceImpl_GetTextureStageState,
7515 IWineD3DDeviceImpl_SetTransform,
7516 IWineD3DDeviceImpl_GetTransform,
7517 IWineD3DDeviceImpl_SetVertexDeclaration,
7518 IWineD3DDeviceImpl_GetVertexDeclaration,
7519 IWineD3DDeviceImpl_SetVertexShader,
7520 IWineD3DDeviceImpl_GetVertexShader,
7521 IWineD3DDeviceImpl_SetVertexShaderConstant,
7522 IWineD3DDeviceImpl_GetVertexShaderConstant,
7523 IWineD3DDeviceImpl_SetVertexShaderConstantB,
7524 IWineD3DDeviceImpl_GetVertexShaderConstantB,
7525 IWineD3DDeviceImpl_SetVertexShaderConstantI,
7526 IWineD3DDeviceImpl_GetVertexShaderConstantI,
7527 IWineD3DDeviceImpl_SetVertexShaderConstantF,
7528 IWineD3DDeviceImpl_GetVertexShaderConstantF,
7529 IWineD3DDeviceImpl_SetVertexShaderConstantN,
7530 IWineD3DDeviceImpl_SetViewport,
7531 IWineD3DDeviceImpl_GetViewport,
7532 IWineD3DDeviceImpl_MultiplyTransform,
7533 IWineD3DDeviceImpl_ValidateDevice,
7534 IWineD3DDeviceImpl_ProcessVertices,
7535 /*** State block ***/
7536 IWineD3DDeviceImpl_BeginStateBlock,
7537 IWineD3DDeviceImpl_EndStateBlock,
7538 /*** Scene management ***/
7539 IWineD3DDeviceImpl_BeginScene,
7540 IWineD3DDeviceImpl_EndScene,
7541 IWineD3DDeviceImpl_Present,
7542 IWineD3DDeviceImpl_Clear,
7544 IWineD3DDeviceImpl_DrawPrimitive,
7545 IWineD3DDeviceImpl_DrawIndexedPrimitive,
7546 IWineD3DDeviceImpl_DrawPrimitiveUP,
7547 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
7548 IWineD3DDeviceImpl_DrawPrimitiveStrided,
7549 IWineD3DDeviceImpl_DrawRectPatch,
7550 IWineD3DDeviceImpl_DrawTriPatch,
7551 IWineD3DDeviceImpl_DeletePatch,
7552 IWineD3DDeviceImpl_ColorFill,
7553 IWineD3DDeviceImpl_UpdateTexture,
7554 IWineD3DDeviceImpl_UpdateSurface,
7555 IWineD3DDeviceImpl_CopyRects,
7556 IWineD3DDeviceImpl_StretchRect,
7557 IWineD3DDeviceImpl_GetRenderTargetData,
7558 IWineD3DDeviceImpl_GetFrontBufferData,
7559 /*** Internal use IWineD3DDevice methods ***/
7560 IWineD3DDeviceImpl_SetupTextureStates,
7561 /*** object tracking ***/
7562 IWineD3DDeviceImpl_ResourceReleased
7566 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
7567 WINED3DRS_ALPHABLENDENABLE ,
7568 WINED3DRS_ALPHAFUNC ,
7569 WINED3DRS_ALPHAREF ,
7570 WINED3DRS_ALPHATESTENABLE ,
7572 WINED3DRS_COLORWRITEENABLE ,
7573 WINED3DRS_DESTBLEND ,
7574 WINED3DRS_DITHERENABLE ,
7575 WINED3DRS_FILLMODE ,
7576 WINED3DRS_FOGDENSITY ,
7578 WINED3DRS_FOGSTART ,
7579 WINED3DRS_LASTPIXEL ,
7580 WINED3DRS_SHADEMODE ,
7581 WINED3DRS_SRCBLEND ,
7582 WINED3DRS_STENCILENABLE ,
7583 WINED3DRS_STENCILFAIL ,
7584 WINED3DRS_STENCILFUNC ,
7585 WINED3DRS_STENCILMASK ,
7586 WINED3DRS_STENCILPASS ,
7587 WINED3DRS_STENCILREF ,
7588 WINED3DRS_STENCILWRITEMASK ,
7589 WINED3DRS_STENCILZFAIL ,
7590 WINED3DRS_TEXTUREFACTOR ,
7601 WINED3DRS_ZWRITEENABLE
7604 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
7605 WINED3DTSS_ADDRESSW ,
7606 WINED3DTSS_ALPHAARG0 ,
7607 WINED3DTSS_ALPHAARG1 ,
7608 WINED3DTSS_ALPHAARG2 ,
7609 WINED3DTSS_ALPHAOP ,
7610 WINED3DTSS_BUMPENVLOFFSET ,
7611 WINED3DTSS_BUMPENVLSCALE ,
7612 WINED3DTSS_BUMPENVMAT00 ,
7613 WINED3DTSS_BUMPENVMAT01 ,
7614 WINED3DTSS_BUMPENVMAT10 ,
7615 WINED3DTSS_BUMPENVMAT11 ,
7616 WINED3DTSS_COLORARG0 ,
7617 WINED3DTSS_COLORARG1 ,
7618 WINED3DTSS_COLORARG2 ,
7619 WINED3DTSS_COLOROP ,
7620 WINED3DTSS_RESULTARG ,
7621 WINED3DTSS_TEXCOORDINDEX ,
7622 WINED3DTSS_TEXTURETRANSFORMFLAGS
7625 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
7626 WINED3DSAMP_ADDRESSU ,
7627 WINED3DSAMP_ADDRESSV ,
7628 WINED3DSAMP_ADDRESSW ,
7629 WINED3DSAMP_BORDERCOLOR ,
7630 WINED3DSAMP_MAGFILTER ,
7631 WINED3DSAMP_MINFILTER ,
7632 WINED3DSAMP_MIPFILTER ,
7633 WINED3DSAMP_MIPMAPLODBIAS ,
7634 WINED3DSAMP_MAXMIPLEVEL ,
7635 WINED3DSAMP_MAXANISOTROPY ,
7636 WINED3DSAMP_SRGBTEXTURE ,
7637 WINED3DSAMP_ELEMENTINDEX
7640 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
7642 WINED3DRS_AMBIENTMATERIALSOURCE ,
7643 WINED3DRS_CLIPPING ,
7644 WINED3DRS_CLIPPLANEENABLE ,
7645 WINED3DRS_COLORVERTEX ,
7646 WINED3DRS_DIFFUSEMATERIALSOURCE ,
7647 WINED3DRS_EMISSIVEMATERIALSOURCE ,
7648 WINED3DRS_FOGDENSITY ,
7650 WINED3DRS_FOGSTART ,
7651 WINED3DRS_FOGTABLEMODE ,
7652 WINED3DRS_FOGVERTEXMODE ,
7653 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
7654 WINED3DRS_LIGHTING ,
7655 WINED3DRS_LOCALVIEWER ,
7656 WINED3DRS_MULTISAMPLEANTIALIAS ,
7657 WINED3DRS_MULTISAMPLEMASK ,
7658 WINED3DRS_NORMALIZENORMALS ,
7659 WINED3DRS_PATCHEDGESTYLE ,
7660 WINED3DRS_POINTSCALE_A ,
7661 WINED3DRS_POINTSCALE_B ,
7662 WINED3DRS_POINTSCALE_C ,
7663 WINED3DRS_POINTSCALEENABLE ,
7664 WINED3DRS_POINTSIZE ,
7665 WINED3DRS_POINTSIZE_MAX ,
7666 WINED3DRS_POINTSIZE_MIN ,
7667 WINED3DRS_POINTSPRITEENABLE ,
7668 WINED3DRS_RANGEFOGENABLE ,
7669 WINED3DRS_SPECULARMATERIALSOURCE ,
7670 WINED3DRS_TWEENFACTOR ,
7671 WINED3DRS_VERTEXBLEND
7674 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
7675 WINED3DTSS_TEXCOORDINDEX ,
7676 WINED3DTSS_TEXTURETRANSFORMFLAGS
7679 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
7680 WINED3DSAMP_DMAPOFFSET