2 * IWineD3DDevice implementation
4 * Copyright 2002-2005 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "wined3d_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
28 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
29 WINE_DECLARE_DEBUG_CHANNEL(d3d_fps);
30 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
31 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
33 /* x11drv GDI escapes */
34 #define X11DRV_ESCAPE 6789
35 enum x11drv_escape_codes
37 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
38 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
39 X11DRV_GET_FONT, /* get current X font for a DC */
42 /* retrieve the X display to use on a given DC */
43 inline static Display *get_display( HDC hdc )
46 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
48 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
49 sizeof(display), (LPSTR)&display )) display = NULL;
54 #define D3DMEMCHECK(object, ppResult) if(NULL == object){ *ppResult = NULL; WARN("Out of memory\n"); return D3DERR_OUTOFVIDEOMEMORY;}
56 #define D3DCREATEOBJECTINSTANCE(object, type){ \
57 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
58 D3DMEMCHECK(object, pp##type); \
59 object->lpVtbl = &IWineD3D##type##_Vtbl; \
60 object->wineD3DDevice = This; \
61 object->parent = parent; \
63 *pp##type = (IWineD3D##type *) object; \
66 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype){ \
67 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
68 D3DMEMCHECK(object, pp##type); \
69 object->lpVtbl = &IWineD3D##type##_Vtbl; \
70 object->resource.wineD3DDevice = This; \
71 object->resource.parent = parent; \
72 object->resource.resourceType = d3dtype; \
73 object->resource.ref = 1; \
74 object->resource.pool = Pool; \
75 object->resource.format = Format; \
76 object->resource.usage = Usage; \
77 object->resource.size = 0; \
78 object->resource.allocatedMemory = 0; \
79 *pp##type = (IWineD3D##type *) object; \
82 #define D3DINITILIZEBASETEXTURE(_basetexture) { \
83 _basetexture.levels = Levels; \
84 _basetexture.filterType = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? D3DTEXF_LINEAR : D3DTEXF_NONE; \
85 _basetexture.LOD = 0; \
86 _basetexture.dirty = TRUE; \
89 /**********************************************************
90 * Global variable / Constants follow
91 **********************************************************/
92 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
94 /**********************************************************
95 * Utility functions follow
96 **********************************************************/
97 /* Convert the D3DLIGHT properties into equivalent gl lights */
98 void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
101 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
102 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
104 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
105 glMatrixMode(GL_MODELVIEW);
107 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
110 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
111 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
112 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
113 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
114 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
115 checkGLcall("glLightfv");
118 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
119 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
120 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
121 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
122 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
123 checkGLcall("glLightfv");
126 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
127 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
128 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
129 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
130 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
131 checkGLcall("glLightfv");
133 /* Attenuation - Are these right? guessing... */
134 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
135 checkGLcall("glLightf");
136 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
137 checkGLcall("glLightf");
139 quad_att = 1.4/(lightInfo->OriginalParms.Range*lightInfo->OriginalParms.Range);
140 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
141 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
142 checkGLcall("glLightf");
144 switch (lightInfo->OriginalParms.Type) {
147 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
148 checkGLcall("glLightfv");
149 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
150 checkGLcall("glLightf");
156 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
157 checkGLcall("glLightfv");
159 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
160 checkGLcall("glLightfv");
161 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
162 checkGLcall("glLightf");
163 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
164 checkGLcall("glLightf");
168 case D3DLIGHT_DIRECTIONAL:
170 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
171 checkGLcall("glLightfv");
172 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
173 checkGLcall("glLightf");
174 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
175 checkGLcall("glLightf");
179 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
182 /* Restore the modelview matrix */
186 /* Apply the current values to the specified texture stage */
187 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Stage, DWORD Flags) {
188 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
191 BOOL changeTexture = TRUE;
193 TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
194 for (i = 1; i < HIGHEST_TEXTURE_STATE; i++) {
199 /* Performance: For texture states where multiples effect the outcome, only bother
200 applying the last one as it will pick up all the other values */
201 case WINED3DTSS_COLORARG0: /* Will be picked up when setting color op */
202 case WINED3DTSS_COLORARG1: /* Will be picked up when setting color op */
203 case WINED3DTSS_COLORARG2: /* Will be picked up when setting color op */
204 case WINED3DTSS_ALPHAARG0: /* Will be picked up when setting alpha op */
205 case WINED3DTSS_ALPHAARG1: /* Will be picked up when setting alpha op */
206 case WINED3DTSS_ALPHAARG2: /* Will be picked up when setting alpha op */
210 /* Performance: If the texture states only impact settings for the texture unit
211 (compared to the texture object) then there is no need to reapply them. The
212 only time they need applying is the first time, since we cheat and put the
213 values into the stateblock without applying.
214 Per-texture unit: texture function (eg. combine), ops and args
216 texture generation settings
217 Note: Due to some special conditions there may be a need to do particular ones
218 of these, which is what the Flags allows */
219 case WINED3DTSS_COLOROP:
220 case WINED3DTSS_TEXCOORDINDEX:
221 if (!(Flags == REAPPLY_ALL)) skip=TRUE;
224 case WINED3DTSS_ALPHAOP:
225 if (!(Flags & REAPPLY_ALPHAOP)) skip=TRUE;
233 /* Performance: Only change to this texture if we have to */
235 /* Make appropriate texture active */
236 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
237 GLACTIVETEXTURE(Stage);
238 } else if (Stage > 0) {
239 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
241 changeTexture = FALSE;
244 /* Now apply the change */
245 IWineD3DDevice_SetTextureStageState(iface, Stage, i, This->stateBlock->textureState[Stage][i]);
249 /* apply the sampler states to the texture */
250 for (i = 1; i <= HIGHEST_SAMPLER_STATE;i++) {
251 IWineD3DDevice_SetSamplerState(iface, Stage, i, This->stateBlock->samplerState[Stage][i]);
254 /* Note the D3DRS value applies to all textures, but GL has one
255 * per texture, so apply it now ready to be used!
257 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
258 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
259 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
261 TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
264 /**********************************************************
265 * IUnknown parts follows
266 **********************************************************/
268 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
270 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
271 /* FIXME: This needs to extend an IWineD3DBaseObject */
273 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
274 if (IsEqualGUID(riid, &IID_IUnknown)
275 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
276 IUnknown_AddRef(iface);
281 return E_NOINTERFACE;
284 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
285 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
286 ULONG refCount = InterlockedIncrement(&This->ref);
288 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
292 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
293 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
294 ULONG refCount = InterlockedDecrement(&This->ref);
296 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
299 /* TODO: Clean up all the surfaces and textures! */
300 /* FIXME: Create targets and state blocks in d3d8 */
301 if (((IWineD3DImpl *)This->wineD3D)->dxVersion > 8) { /*We don't create a state block in d3d8 yet*/
302 /* NOTE: You must release the parent if the objects was created via a callback
303 ** ***************************/
305 IUnknown* swapChainParent;
307 /* Release all of the swapchains, except the implicite swapchain (#0) */
308 for(i = 1; i < This->numberOfSwapChains; i++){
309 /* TODO: don't access swapchains[x] directly! */
310 IWineD3DSwapChain_Release(This->swapchains[i]);
313 if (This->stateBlock != NULL) {
314 IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
317 if (This->swapchains[0] != NULL) {
318 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release it's parent now */
319 /* TODO: don't access swapchains[x] directly!, check that there are no-more swapchains left for this device! */
320 IWineD3DSwapChain_GetParent(This->swapchains[0], &swapChainParent);
321 IUnknown_Release(swapChainParent); /* once for the get parent */
322 if (IUnknown_Release(swapChainParent) > 0){ /* the second time for when it was created */
323 FIXME("(%p) Something's still holding the implicite swapchain\n",This);
328 IWineD3D_Release(This->wineD3D);
329 HeapFree(GetProcessHeap(), 0, This);
334 /**********************************************************
335 * IWineD3DDevice implementation follows
336 **********************************************************/
337 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
338 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
339 *pParent = This->parent;
340 IUnknown_AddRef(This->parent);
344 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
345 DWORD FVF, D3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
347 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
348 IWineD3DVertexBufferImpl *object;
349 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
350 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, D3DRTYPE_VERTEXBUFFER)
352 object->resource.size = Size;
353 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
356 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
357 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
362 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
363 WINED3DFORMAT Format, D3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
364 HANDLE *sharedHandle, IUnknown *parent) {
365 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
366 IWineD3DIndexBufferImpl *object;
367 TRACE("(%p) Creating index buffer\n", This);
369 /* Allocate the storage for the device */
370 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,D3DRTYPE_INDEXBUFFER)
372 object->resource.size = Length;
373 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
375 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
376 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
377 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
382 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, D3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
384 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
385 IWineD3DStateBlockImpl *object;
388 D3DCREATEOBJECTINSTANCE(object, StateBlock)
389 object->blockType = Type;
391 /* Special case - Used during initialization to produce a placeholder stateblock
392 so other functions called can update a state block */
393 if (Type == (D3DSTATEBLOCKTYPE) 0) {
394 /* Don't bother increasing the reference count otherwise a device will never
395 be freed due to circular dependencies */
399 /* Otherwise, might as well set the whole state block to the appropriate values */
400 IWineD3DDevice_AddRef(iface);
401 /* Otherwise, might as well set the whole state block to the appropriate values */
402 if ( This->stateBlock != NULL){
403 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
405 memset(object->streamFreq, 1, sizeof(object->streamFreq));
408 /* Reset the ref and type after kluging it */
409 object->wineD3DDevice = This;
411 object->blockType = Type;
413 TRACE("Updating changed flags appropriate for type %d\n", Type);
415 if (Type == D3DSBT_ALL) {
416 TRACE("ALL => Pretend everything has changed\n");
417 memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
418 } else if (Type == D3DSBT_PIXELSTATE) {
420 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
421 /* TODO: Pixel Shader Constants */
422 object->changed.pixelShader = TRUE;
423 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
424 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
426 for (j = 0; j < GL_LIMITS(textures); i++) {
427 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
428 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
431 /* Setting sampler block changes states */
432 for (j = 0 ; j < GL_LIMITS(samplers); j++){
433 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++){
435 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
438 } else if (Type == D3DSBT_VERTEXSTATE) {
440 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
442 /* TODO: Vertex Shader Constants */
443 object->changed.vertexShader = TRUE;
444 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
445 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
447 for (j = 0; j < GL_LIMITS(textures); i++) {
448 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
449 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
452 /* Setting sampler block changes states */
453 for (j = 0 ; j < GL_LIMITS(samplers); j++){
454 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++){
455 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
459 /* Duplicate light chain */
461 PLIGHTINFOEL *src = NULL;
462 PLIGHTINFOEL *dst = NULL;
463 PLIGHTINFOEL *newEl = NULL;
464 src = This->stateBlock->lights;
465 object->lights = NULL;
469 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
470 if (newEl == NULL) return D3DERR_OUTOFVIDEOMEMORY;
471 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
473 newEl->changed = TRUE;
474 newEl->enabledChanged = TRUE;
476 object->lights = newEl;
487 FIXME("Unrecognized state block type %d\n", Type);
490 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
495 /* ************************************
497 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
500 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
502 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.
504 ******************************** */
506 HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,D3DRESOURCETYPE Type, DWORD Usage, D3DPOOL Pool, D3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, IUnknown *parent) {
507 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
508 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
509 unsigned int pow2Width, pow2Height;
511 TRACE("(%p) Create surface\n",This);
513 /** FIXME: Check ranges on the inputs are valid
516 * [in] Quality level. The valid range is between zero and one less than the level
517 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
518 * Passing a larger value returns the error D3DERR_INVALIDCALL. The MultisampleQuality
519 * values of paired render targets, depth stencil surfaces, and the MultiSample type
521 *******************************/
526 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
528 * If this flag is set, the contents of the depth stencil buffer will be
529 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
530 * with a different depth surface.
532 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
533 ***************************/
535 if(MultisampleQuality < 0) {
536 FIXME("Invalid multisample level %ld \n", MultisampleQuality);
537 return D3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
540 if(MultisampleQuality > 0){
541 FIXME("MultisampleQuality set to %ld, substituting 0 \n" , MultisampleQuality);
542 MultisampleQuality=0;
545 /* Non-power2 support */
547 /* Find the nearest pow2 match */
548 pow2Width = pow2Height = 1;
549 while (pow2Width < Width) pow2Width <<= 1;
550 while (pow2Height < Height) pow2Height <<= 1;
552 if((pow2Width > Width || pow2Height > Height) && !Usage & D3DUSAGE_RENDERTARGET) {
553 /** TODO: add support for non power two textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
554 FIXME("non-power-two textures unsupported\n");
555 return D3DERR_NOTAVAILABLE;
558 /** TODO: Check against the maximum texture sizes supported by the video card **/
560 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,D3DRTYPE_SURFACE)
561 object->container = (IUnknown*) This;
563 object->currentDesc.Width = Width;
564 object->currentDesc.Height = Height;
565 object->currentDesc.Level = Level;
566 object->currentDesc.MultiSampleType = MultiSample;
567 object->currentDesc.MultiSampleQuality = MultisampleQuality;
568 object->discard = Discard;
569 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
571 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
572 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
574 *********************************/
575 if (Format == WINED3DFMT_DXT1) {
576 /* DXT1 is half byte per pixel */
577 object->resource.size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4)) / 2;
579 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
580 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
581 object->resource.size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4));
583 object->resource.size = (Width * object->bytesPerPixel) * Height;
586 TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
589 /* TODO: Check that we have enough video ram left */
590 if(Pool == D3DPOOL_DEFAULT && IWineD3DDevice_GetAvailableTextureMem(iface) <= object->currentDesc.Size){
591 TRACE("Out of 'bogus' video memory\n");
592 HeapFree(GetProcessHeap(),0,object);
594 return D3DERR_OUTOFVIDEOMEMORY;
598 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
599 * this function is too deap to need to care about things like this.
600 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
601 * ****************************************/
603 case D3DPOOL_SCRATCH:
604 if(Lockable == FALSE)
605 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
606 which are mutually exclusive, setting lockable to true\n");
609 case D3DPOOL_SYSTEMMEM:
610 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
611 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
612 case D3DPOOL_MANAGED:
613 if(Usage == D3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
614 Usage of DYNAMIC which are mutually exclusive, not doing \
615 anything just telling you.\n");
617 case D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
618 if(!(Usage & D3DUSAGE_DYNAMIC) && !(Usage & D3DUSAGE_RENDERTARGET)
619 && !(Usage && D3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
620 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
623 FIXME("(%p) Unknown pool %d\n", This, Pool);
627 if (Usage & D3DUSAGE_RENDERTARGET && Pool != D3DPOOL_DEFAULT){
628 FIXME("Trying to create a render target that isn't in the default pool\n");
632 object->locked = FALSE;
633 object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
634 /* TODO: memory management */
635 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
636 if(object->resource.allocatedMemory == NULL ) {
637 FIXME("Out of memory!\n");
638 HeapFree(GetProcessHeap(),0,object);
640 return D3DERR_OUTOFVIDEOMEMORY;
644 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
645 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
646 This, Width, Height, Format, debug_d3dformat(Format),
647 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
652 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
653 DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool,
654 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
655 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
657 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
658 IWineD3DTextureImpl *object;
664 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) .... \n", This, Width, Height, Levels, Usage);
666 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_TEXTURE);
667 D3DINITILIZEBASETEXTURE(object->baseTexture);
668 object->width = Width;
669 object->height = Height;
671 /* Calculate levels for mip mapping */
673 TRACE("calculating levels %d\n", object->baseTexture.levels);
674 object->baseTexture.levels++;
677 while (tmpW > 1 && tmpH > 1) {
678 tmpW = max(1, tmpW >> 1);
679 tmpH = max(1, tmpH >> 1);
680 object->baseTexture.levels++;
682 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
685 /* Generate all the surfaces */
688 for (i = 0; i < object->baseTexture.levels; i++)
690 /* use the callback to create the texture surface */
691 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
694 FIXME("Failed to create surface %p \n",object);
697 IWineD3DSurface_Release(object->surfaces[j]);
699 /* heap free object */
700 HeapFree(GetProcessHeap(),0,object);
706 IWineD3DSurface_SetContainer(object->surfaces[i], (IUnknown *)object);
707 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
708 /* calculate the next mipmap level */
709 tmpW = max(1, tmpW >> 1);
710 tmpH = max(1, tmpH >> 1);
713 TRACE("(%p) : Created texture %p\n", This, object);
717 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
718 UINT Width, UINT Height, UINT Depth,
719 UINT Levels, DWORD Usage,
720 WINED3DFORMAT Format, D3DPOOL Pool,
721 IWineD3DVolumeTexture** ppVolumeTexture,
722 HANDLE* pSharedHandle, IUnknown *parent,
723 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
725 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
726 IWineD3DVolumeTextureImpl *object;
732 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_VOLUMETEXTURE);
733 D3DINITILIZEBASETEXTURE(object->baseTexture);
735 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
736 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
738 object->width = Width;
739 object->height = Height;
740 object->depth = Depth;
742 /* Calculate levels for mip mapping */
744 object->baseTexture.levels++;
748 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
749 tmpW = max(1, tmpW >> 1);
750 tmpH = max(1, tmpH >> 1);
751 tmpD = max(1, tmpD >> 1);
752 object->baseTexture.levels++;
754 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
757 /* Generate all the surfaces */
762 for (i = 0; i < object->baseTexture.levels; i++)
764 /* Create the volume */
765 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
766 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
767 IWineD3DVolume_SetContainer(object->volumes[i], (IUnknown *)object);
769 tmpW = max(1, tmpW >> 1);
770 tmpH = max(1, tmpH >> 1);
771 tmpD = max(1, tmpD >> 1);
774 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
775 TRACE("(%p) : Created volume texture %p\n", This, object);
779 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
780 UINT Width, UINT Height, UINT Depth,
782 WINED3DFORMAT Format, D3DPOOL Pool,
783 IWineD3DVolume** ppVolume,
784 HANDLE* pSharedHandle, IUnknown *parent) {
786 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
787 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
789 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, D3DRTYPE_VOLUME)
791 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
792 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
794 object->currentDesc.Width = Width;
795 object->currentDesc.Height = Height;
796 object->currentDesc.Depth = Depth;
797 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
799 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
800 object->resource.size = (Width * object->bytesPerPixel) * Height * Depth;
801 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
802 object->lockable = TRUE;
803 object->locked = FALSE;
804 memset(&object->lockedBox, 0, sizeof(D3DBOX));
805 object->dirty = FALSE;
806 return IWineD3DVolume_CleanDirtyBox((IWineD3DVolume *) object);
809 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
810 UINT Levels, DWORD Usage,
811 WINED3DFORMAT Format, D3DPOOL Pool,
812 IWineD3DCubeTexture** ppCubeTexture,
813 HANDLE* pSharedHandle, IUnknown *parent,
814 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
816 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
817 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
822 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE);
823 D3DINITILIZEBASETEXTURE(object->baseTexture);
825 TRACE("(%p) Create Cube Texture \n", This);
827 object->edgeLength = EdgeLength;
829 /* Calculate levels for mip mapping */
831 object->baseTexture.levels++;
834 tmpW = max(1, tmpW / 2);
835 object->baseTexture.levels++;
837 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
840 /* Generate all the surfaces */
842 for (i = 0; i < object->baseTexture.levels; i++) {
844 /* Create the 6 faces */
845 for (j = 0; j < 6; j++) {
847 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
848 i /* Level */, &object->surfaces[j][i],pSharedHandle);
855 IWineD3DSurface_Release(object->surfaces[j][i]);
859 IWineD3DSurface_Release(object->surfaces[l][j]);
863 FIXME("(%p) Failed to create surface\n",object);
864 HeapFree(GetProcessHeap(),0,object);
865 *ppCubeTexture = NULL;
868 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IUnknown *)object);
869 TRACE("Created surface level %d @ %p, \n", i, object->surfaces[j][i]);
871 tmpW = max(1, tmpW >> 1);
874 TRACE("(%p) : Created Cube Texture %p\n", This, object);
875 *ppCubeTexture = (IWineD3DCubeTexture *) object;
879 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent){
880 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
881 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
884 /* Just a check to see if we support this type of query */
885 HRESULT hr = D3DERR_NOTAVAILABLE;
886 /* Lie and say everything is good (we can return ok fake data from a stub) */
888 case WINED3DQUERYTYPE_VCACHE:
889 case WINED3DQUERYTYPE_RESOURCEMANAGER:
890 case WINED3DQUERYTYPE_VERTEXSTATS:
891 case WINED3DQUERYTYPE_EVENT:
892 case WINED3DQUERYTYPE_OCCLUSION:
893 case WINED3DQUERYTYPE_TIMESTAMP:
894 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
895 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
896 case WINED3DQUERYTYPE_PIPELINETIMINGS:
897 case WINED3DQUERYTYPE_INTERFACETIMINGS:
898 case WINED3DQUERYTYPE_VERTEXTIMINGS:
899 case WINED3DQUERYTYPE_PIXELTIMINGS:
900 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
901 case WINED3DQUERYTYPE_CACHEUTILIZATION:
905 FIXME("(%p) Unhandled query type %d\n",This , Type);
907 FIXME("(%p) : Stub request for query type %d returned %ld\n", This, Type, hr);
911 D3DCREATEOBJECTINSTANCE(object, Query)
913 object->extendedData = 0;
914 TRACE("(%p) : Created Query %p\n", This, object);
918 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
919 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
921 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
922 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil){
923 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
926 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
928 XVisualInfo template;
929 GLXContext oldContext;
930 Drawable oldDrawable;
933 TRACE("(%p) : Created Aditional Swap Chain\n", This);
935 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
936 * does a device hold a reference to a swap chain giving them a lifetime of the device
937 * or does the swap chain notify the device of it'd destruction.
938 *******************************/
940 D3DCREATEOBJECTINSTANCE(object, SwapChain)
942 /* Initialize other useful values */
943 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
945 /*********************
946 * Lookup the window Handle and the relating X window handle
947 ********************/
949 /* Setup hwnd we are using, plus which display this equates to */
950 object->win_handle = *(pPresentationParameters->hDeviceWindow);
951 if (!object->win_handle) {
952 object->win_handle = This->createParms.hFocusWindow;
955 object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window" );
956 hDc = GetDC(object->win_handle);
957 object->display = get_display(hDc);
958 ReleaseDC(object->win_handle, hDc);
959 TRACE("Using a display of %p %p \n", object->display, hDc);
961 if (NULL == object->display || NULL == hDc) {
962 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
963 return D3DERR_NOTAVAILABLE;
966 if (object->win == 0) {
967 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
968 return D3DERR_NOTAVAILABLE;
971 * Create an opengl context for the display visual
972 * NOTE: the visual is chosen as the window is created and the glcontext cannot
973 * use different properties after that point in time. FIXME: How to handle when requested format
974 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
975 * it chooses is identical to the one already being used!
976 **********************************/
978 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
981 /* Create a new context for this swapchain */
982 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
983 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
984 (or the best possible if none is requested) */
985 TRACE("Found x visual ID : %ld\n", template.visualid);
987 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
988 if (NULL == object->visInfo) {
989 ERR("cannot really get XVisual\n");
991 return D3DERR_NOTAVAILABLE;
994 /* Write out some debug info about the visual/s */
995 TRACE("Using x visual ID : %ld\n", template.visualid);
996 TRACE(" visual info: %p\n", object->visInfo);
997 TRACE(" num items : %d\n", num);
998 for(n = 0;n < num; n++){
999 TRACE("=====item=====: %d\n", n + 1);
1000 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1001 TRACE(" screen : %d\n", object->visInfo[n].screen);
1002 TRACE(" depth : %u\n", object->visInfo[n].depth);
1003 TRACE(" class : %d\n", object->visInfo[n].class);
1004 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1005 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1006 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1007 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1008 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1009 /* log some extra glx info */
1010 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1011 TRACE(" gl_aux_buffers : %d\n", value);
1012 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1013 TRACE(" gl_buffer_size : %d\n", value);
1014 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1015 TRACE(" gl_red_size : %d\n", value);
1016 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1017 TRACE(" gl_green_size : %d\n", value);
1018 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1019 TRACE(" gl_blue_size : %d\n", value);
1020 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1021 TRACE(" gl_alpha_size : %d\n", value);
1022 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1023 TRACE(" gl_depth_size : %d\n", value);
1024 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1025 TRACE(" gl_stencil_size : %d\n", value);
1027 /* Now choose a simila visual ID*/
1029 #ifdef USE_CONTEXT_MANAGER
1031 /** TODO: use a context mamager **/
1035 IWineD3DSwapChain *implSwapChain;
1036 if (D3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1037 /* The first time around we create the context that is shared with all other swapchians and render targets */
1038 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1039 TRACE("Creating implicite context for vis %p, hwnd %p\n", object->display, object->visInfo);
1042 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1043 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1044 /* and create a new context with the implicit swapchains context as the shared context */
1045 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1046 IWineD3DSwapChain_Release(implSwapChain);
1051 XFree(object->visInfo);
1052 object->visInfo = NULL;
1054 if (NULL == object->glCtx) {
1055 ERR("cannot create glxContext\n");
1057 return D3DERR_NOTAVAILABLE;
1061 if (object->glCtx == NULL) {
1062 ERR("Error in context creation !\n");
1063 return D3DERR_INVALIDCALL;
1065 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1066 object->win_handle, object->glCtx, object->win, object->visInfo);
1069 /*********************
1070 * Windowed / Fullscreen
1071 *******************/
1074 * TODO: MSDNsays that we are only allowed one fullscreen swapchain per device,
1075 * so we should really check to see if their is a fullscreen swapchain already
1076 * I think Windows and X have differnt ideas about fullscreen, does a single head count as full screen?
1077 **************************************/
1079 if (!*(pPresentationParameters->Windowed)) {
1085 /* Get info on the current display setup */
1086 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1087 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1090 /* Change the display settings */
1091 memset(&devmode, 0, sizeof(DEVMODEW));
1092 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1093 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1094 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1095 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1096 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1097 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1099 /* Make popup window */
1100 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1101 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1102 *(pPresentationParameters->BackBufferWidth),
1103 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1109 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1110 * then the corresponding dimension of the client area of the hDeviceWindow
1111 * (or the focus window, if hDeviceWindow is NULL) is taken.
1112 **********************/
1114 if (*(pPresentationParameters->Windowed) &&
1115 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1116 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1119 GetClientRect(object->win_handle, &Rect);
1121 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1122 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1123 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1125 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1126 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1127 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1131 /*********************
1132 * finish off parameter initialization
1133 *******************/
1135 /* Put the correct figures in the presentation parameters */
1136 TRACE("Coppying accross presentaion paraneters\n");
1137 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1138 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1139 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1140 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1141 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1142 object->presentParms.MultiSampleQuality = *(pPresentationParameters->MultiSampleQuality);
1143 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1144 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1145 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1146 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1147 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1148 object->presentParms.Flags = *(pPresentationParameters->Flags);
1149 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1150 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1153 /* FIXME: check for any failures */
1154 /*********************
1155 * Create the back, front and stencil buffers
1156 *******************/
1157 TRACE("calling rendertarget CB\n");
1158 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1159 object->presentParms.BackBufferWidth,
1160 object->presentParms.BackBufferHeight,
1161 object->presentParms.BackBufferFormat,
1162 object->presentParms.MultiSampleType,
1163 object->presentParms.MultiSampleQuality,
1164 TRUE /* Lockable */,
1165 &object->frontBuffer,
1166 NULL /* pShared (always null)*/);
1167 if (object->frontBuffer != NULL)
1168 IWineD3DSurface_SetContainer(object->frontBuffer, (IUnknown *)object);
1169 TRACE("calling rendertarget CB\n");
1170 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1171 object->presentParms.BackBufferWidth,
1172 object->presentParms.BackBufferHeight,
1173 object->presentParms.BackBufferFormat,
1174 object->presentParms.MultiSampleType,
1175 object->presentParms.MultiSampleQuality,
1176 TRUE /* Lockable */,
1177 &object->backBuffer,
1178 NULL /* pShared (always null)*/);
1179 if (object->backBuffer != NULL)
1180 IWineD3DSurface_SetContainer(object->backBuffer, (IUnknown *)object);
1182 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1183 if (pPresentationParameters->EnableAutoDepthStencil) {
1184 TRACE("Creating depth stencil buffer\n");
1185 if (This->depthStencilBuffer == NULL ) {
1186 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1187 object->presentParms.BackBufferWidth,
1188 object->presentParms.BackBufferHeight,
1189 object->presentParms.AutoDepthStencilFormat,
1190 object->presentParms.MultiSampleType,
1191 object->presentParms.MultiSampleQuality,
1192 FALSE /* FIXME: Discard */,
1193 &This->depthStencilBuffer,
1194 NULL /* pShared (always null)*/ );
1195 if (This->depthStencilBuffer != NULL)
1196 IWineD3DSurface_SetContainer(This->depthStencilBuffer, (IUnknown *)iface);
1199 /** TODO: A check on width, height and multisample types
1200 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1201 ****************************/
1202 object->wantsDepthStencilBuffer = TRUE;
1204 object->wantsDepthStencilBuffer = FALSE;
1207 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1210 /*********************
1211 * init the default renderTarget management
1212 *******************/
1213 object->drawable = object->win;
1214 object->render_ctx = object->glCtx;
1217 /*********************
1218 * Setup some defaults and clear down the buffers
1219 *******************/
1221 /** save current context and drawable **/
1222 oldContext = glXGetCurrentContext();
1223 oldDrawable = glXGetCurrentDrawable();
1225 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1226 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1227 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1229 checkGLcall("glXMakeCurrent");
1231 TRACE("Setting up the screen\n");
1232 /* Clear the screen */
1233 glClearColor(0.0, 0.0, 0.0, 0.0);
1234 checkGLcall("glClearColor");
1237 glClearStencil(0xffff);
1239 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1240 checkGLcall("glClear");
1242 glColor3f(1.0, 1.0, 1.0);
1243 checkGLcall("glColor3f");
1245 glEnable(GL_LIGHTING);
1246 checkGLcall("glEnable");
1248 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1249 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1251 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1252 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1254 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1255 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1257 /* switch back to the original context (unless it was zero)*/
1258 if (This->numberOfSwapChains != 0) {
1259 /** TODO: restore the context and drawable **/
1260 glXMakeCurrent(object->display, oldDrawable, oldContext);
1265 /* TODO: move this off into a linked list implementation! (add swapchain, remove swapchain or something along those lines) */
1267 IListOperator *listOperator;
1268 IListStore_CreateListOperator(This->swapchainStore, &listOperator);
1269 IListOperator_Append(listOperator, (void *)object);
1270 IListOperator_Release(listOperator);
1273 This->swapchains[This->numberOfSwapChains++] = (IWineD3DSwapChain *)object;
1274 TRACE("Set swapchain to %p\n", object);
1275 } else { /* something went wrong so clean up */
1276 IUnknown* bufferParent;
1277 if (object->frontBuffer) {
1278 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1279 IUnknown_Release(bufferParent); /* once for the get parent */
1280 if(IUnknown_Release(bufferParent) > 0){
1281 FIXME("(%p) Something's still holding the front buffer\n",This);
1284 if (object->backBuffer) {
1285 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1286 IUnknown_Release(bufferParent); /* once for the get parent */
1287 if(IUnknown_Release(bufferParent) > 0){
1288 FIXME("(%p) Something's still holding the back buffer\n",This);
1291 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1292 /* Clean up the context */
1293 /* check that we are the current context first (we shouldn't be though!) */
1294 if (object->glCtx != 0) {
1295 if(glXGetCurrentContext() == object->glCtx){
1296 glXMakeCurrent(object->display, None, NULL);
1298 glXDestroyContext(object->display, object->glCtx);
1300 HeapFree(GetProcessHeap(), 0, object);
1306 /** NOTE: These are ahead of the other getters and setters to save using a forward declartion **/
1307 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1308 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1310 /* TODO: move over to using a linked list. */
1311 TRACE("(%p) returning %d\n", This, This->numberOfSwapChains);
1312 return This->numberOfSwapChains;
1315 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1316 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1317 TRACE("(%p) : swapchain %d \n", This, iSwapChain);
1319 if(iSwapChain >= IWineD3DDeviceImpl_GetNumberOfSwapChains(iface) || iSwapChain < 0){
1321 return D3DERR_INVALIDCALL;
1323 /** TODO: move off to a linked list implementation **/
1324 *pSwapChain = This->swapchains[iSwapChain];
1327 /* TODO: move over to using stores and linked lists. */
1329 IWineD3DSwapChain_AddRef(*pSwapChain);
1330 TRACE("(%p) returning %p\n", This, *pSwapChain);
1334 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters){
1335 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1337 FIXME("(%p) : Stub\n",This);
1343 * Vertex Declaration
1345 /* TODO: Get ridd of thease and put the functions in the IWineD3DVertexDeclaration interface */
1347 extern HRESULT IWineD3DVertexDeclarationImpl_ParseDeclaration8(IWineD3DDeviceImpl * This, const DWORD* pDecl, IWineD3DVertexDeclarationImpl * object);
1348 extern HRESULT IWineD3DVertexDeclarationImpl_ParseDeclaration9(IWineD3DDeviceImpl * This, const D3DVERTEXELEMENT9* pDecl, IWineD3DVertexDeclarationImpl * object);
1351 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1352 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1353 IWineD3DVertexDeclarationImpl *object = NULL;
1354 HRESULT hr = D3D_OK;
1356 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1357 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1360 if (8 == ((IWineD3DImpl *)This->wineD3D)->dxVersion) {
1362 hr = IWineD3DVertexDeclarationImpl_ParseDeclaration8(This, (const DWORD*) pDeclaration, object);
1364 hr = IWineD3DVertexDeclarationImpl_ParseDeclaration9(This, (const D3DVERTEXELEMENT9*) pDeclaration, object);
1372 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration8(IWineD3DDevice* iface, const DWORD* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent){
1373 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1374 IWineD3DVertexDeclarationImpl *object = NULL; /* NOTE: impl allowed, this is a create */
1375 HRESULT hr = D3D_OK;
1376 /* TODO: replace impl usage with a call to Version*/
1377 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1378 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1380 /* TODO: get ridd of the impl usage, we should only be using interfaces */
1381 hr = IWineD3DVertexDeclarationImpl_ParseDeclaration8(This, pDeclaration, object);
1386 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration9(IWineD3DDevice* iface, const D3DVERTEXELEMENT9* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent){
1387 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1388 IWineD3DVertexDeclarationImpl *object = NULL; /* NOTE: impl allowed, this is a create */
1389 HRESULT hr = D3D_OK;
1390 /* TODO: replace impl usage with a call to Version*/
1391 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1392 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1394 /* TODO: get ridd of the impl usage, we should only be using interfaces */
1395 hr = IWineD3DVertexDeclarationImpl_ParseDeclaration9(This, pDeclaration, object);
1401 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1402 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DVertexShader** ppVertexShader, IUnknown *parent){
1403 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1404 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1405 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1406 object->function = pFunction;
1407 FIXME("(%p) : STUB: Created Vertex shader %p\n", This, ppVertexShader);
1412 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DPixelShader** ppPixelShader, IUnknown *parent){
1413 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1414 FIXME("(%p) : Stub\n", This);
1418 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice* iface, IWineD3D** ppD3D){
1419 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1420 *ppD3D= This->wineD3D;
1421 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1422 IWineD3D_AddRef(*ppD3D);
1427 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1428 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1429 FIXME("Stub :(%p) returning 64Mib\n", This);
1430 return 64*1024*1024;
1437 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1438 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1440 /* Update the current state block */
1441 This->updateStateBlock->fvf = fvf;
1442 This->updateStateBlock->changed.fvf = TRUE;
1443 This->updateStateBlock->set.fvf = TRUE;
1445 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1447 /* No difference if recording or not */
1450 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1451 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1452 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1453 *pfvf = This->stateBlock->fvf;
1458 * Get / Set Stream Source
1460 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1461 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1462 IWineD3DVertexBuffer *oldSrc;
1464 oldSrc = This->stateBlock->streamSource[StreamNumber];
1465 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1467 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1468 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1469 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1470 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1471 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1473 /* Handle recording of state blocks */
1474 if (This->isRecordingState) {
1475 TRACE("Recording... not performing anything\n");
1479 /* Not recording... */
1480 if (oldSrc != NULL) IWineD3DVertexBuffer_Release(oldSrc);
1481 if (pStreamData != NULL) IWineD3DVertexBuffer_AddRef(pStreamData);
1486 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1487 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1489 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1490 *pStream = This->stateBlock->streamSource[StreamNumber];
1491 *pStride = This->stateBlock->streamStride[StreamNumber];
1492 *pOffset = This->stateBlock->streamOffset[StreamNumber];
1493 if (*pStream != NULL) IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1497 /*Should be quite easy, just an extension of vertexdata
1499 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1501 The divider is a bit odd though
1503 VertexOffset = StartVertex / Divider * StreamStride +
1504 VertexIndex / Divider * StreamStride + StreamOffset
1507 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider){
1508 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1510 FIXME("(%p) : stub\n", This);
1514 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider){
1515 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1517 FIXME("(%p) : stub\n", This);
1523 * Get / Set & Multipy Transform
1525 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1526 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1528 /* Most of this routine, comments included copied from ddraw tree initially: */
1529 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1531 /* Handle recording of state blocks */
1532 if (This->isRecordingState) {
1533 TRACE("Recording... not performing anything\n");
1534 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1535 This->updateStateBlock->set.transform[d3dts] = TRUE;
1536 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1541 * If the new matrix is the same as the current one,
1542 * we cut off any further processing. this seems to be a reasonable
1543 * optimization because as was noticed, some apps (warcraft3 for example)
1544 * tend towards setting the same matrix repeatedly for some reason.
1546 * From here on we assume that the new matrix is different, wherever it matters.
1548 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1549 TRACE("The app is setting the same matrix over again\n");
1552 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1556 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1557 where ViewMat = Camera space, WorldMat = world space.
1559 In OpenGL, camera and world space is combined into GL_MODELVIEW
1560 matrix. The Projection matrix stay projection matrix.
1563 /* Capture the times we can just ignore the change for now */
1564 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1565 This->modelview_valid = FALSE;
1568 } else if (d3dts == D3DTS_PROJECTION) {
1569 This->proj_valid = FALSE;
1572 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1573 /* Indexed Vertex Blending Matrices 256 -> 511 */
1574 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1575 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1579 /* Now we really are going to have to change a matrix */
1582 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1583 if (d3dts < GL_LIMITS(textures)) {
1584 int tex = d3dts - D3DTS_TEXTURE0;
1585 GLACTIVETEXTURE(tex);
1586 set_texture_matrix((float *)lpmatrix,
1587 This->updateStateBlock->textureState[tex][WINED3DTSS_TEXTURETRANSFORMFLAGS]);
1590 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1593 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1594 * NOTE: We have to reset the positions even if the light/plane is not currently
1595 * enabled, since the call to enable it will not reset the position.
1596 * NOTE2: Apparently texture transforms do NOT need reapplying
1599 PLIGHTINFOEL *lightChain = NULL;
1600 This->modelview_valid = FALSE;
1601 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1603 glMatrixMode(GL_MODELVIEW);
1604 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1606 glLoadMatrixf((float *)lpmatrix);
1607 checkGLcall("glLoadMatrixf(...)");
1610 lightChain = This->stateBlock->lights;
1611 while (lightChain && lightChain->glIndex != -1) {
1612 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1613 checkGLcall("glLightfv posn");
1614 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1615 checkGLcall("glLightfv dirn");
1616 lightChain = lightChain->next;
1619 /* Reset Clipping Planes if clipping is enabled */
1620 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1621 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1622 checkGLcall("glClipPlane");
1626 } else { /* What was requested!?? */
1627 WARN("invalid matrix specified: %i\n", d3dts);
1630 /* Release lock, all done */
1635 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1636 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1637 TRACE("(%p) : for Transform State %d\n", This, State);
1638 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1642 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1643 D3DMATRIX *mat = NULL;
1646 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1647 * below means it will be recorded in a state block change, but it
1648 * works regardless where it is recorded.
1649 * If this is found to be wrong, change to StateBlock.
1651 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1652 TRACE("(%p) : For state %u\n", This, State);
1654 if (State < HIGHEST_TRANSFORMSTATE)
1656 mat = &This->updateStateBlock->transforms[State];
1658 FIXME("Unhandled transform state!!\n");
1661 /* Copied from ddraw code: */
1662 temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) + (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
1663 temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) + (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
1664 temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) + (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
1665 temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) + (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
1667 temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) + (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
1668 temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) + (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
1669 temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) + (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
1670 temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) + (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
1672 temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) + (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
1673 temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) + (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
1674 temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) + (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
1675 temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) + (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
1677 temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) + (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
1678 temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) + (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
1679 temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) + (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
1680 temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) + (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
1682 /* Apply change via set transform - will reapply to eg. lights this way */
1683 IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
1689 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
1691 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1692 you can reference any indexes you want as long as that number max are enabled at any
1693 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1694 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1695 but when recording, just build a chain pretty much of commands to be replayed. */
1697 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
1699 PLIGHTINFOEL *object, *temp;
1701 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1702 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1704 /* If recording state block, just add to end of lights chain */
1705 if (This->isRecordingState) {
1706 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1707 if (NULL == object) {
1708 return D3DERR_OUTOFVIDEOMEMORY;
1710 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1711 object->OriginalIndex = Index;
1712 object->glIndex = -1;
1713 object->changed = TRUE;
1715 /* Add to the END of the chain of lights changes to be replayed */
1716 if (This->updateStateBlock->lights == NULL) {
1717 This->updateStateBlock->lights = object;
1719 temp = This->updateStateBlock->lights;
1720 while (temp->next != NULL) temp=temp->next;
1721 temp->next = object;
1723 TRACE("Recording... not performing anything more\n");
1727 /* Ok, not recording any longer so do real work */
1728 object = This->stateBlock->lights;
1729 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1731 /* If we didn't find it in the list of lights, time to add it */
1732 if (object == NULL) {
1733 PLIGHTINFOEL *insertAt,*prevPos;
1735 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1736 if (NULL == object) {
1737 return D3DERR_OUTOFVIDEOMEMORY;
1739 object->OriginalIndex = Index;
1740 object->glIndex = -1;
1742 /* Add it to the front of list with the idea that lights will be changed as needed
1743 BUT after any lights currently assigned GL indexes */
1744 insertAt = This->stateBlock->lights;
1746 while (insertAt != NULL && insertAt->glIndex != -1) {
1748 insertAt = insertAt->next;
1751 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1752 This->stateBlock->lights = object;
1753 } else if (insertAt == NULL) { /* End of list */
1754 prevPos->next = object;
1755 object->prev = prevPos;
1756 } else { /* Middle of chain */
1757 if (prevPos == NULL) {
1758 This->stateBlock->lights = object;
1760 prevPos->next = object;
1762 object->prev = prevPos;
1763 object->next = insertAt;
1764 insertAt->prev = object;
1768 /* Initialze the object */
1769 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,
1770 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1771 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1772 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1773 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1774 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1775 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1777 /* Save away the information */
1778 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1780 switch (pLight->Type) {
1781 case D3DLIGHT_POINT:
1783 object->lightPosn[0] = pLight->Position.x;
1784 object->lightPosn[1] = pLight->Position.y;
1785 object->lightPosn[2] = pLight->Position.z;
1786 object->lightPosn[3] = 1.0f;
1787 object->cutoff = 180.0f;
1791 case D3DLIGHT_DIRECTIONAL:
1793 object->lightPosn[0] = -pLight->Direction.x;
1794 object->lightPosn[1] = -pLight->Direction.y;
1795 object->lightPosn[2] = -pLight->Direction.z;
1796 object->lightPosn[3] = 0.0;
1797 object->exponent = 0.0f;
1798 object->cutoff = 180.0f;
1803 object->lightPosn[0] = pLight->Position.x;
1804 object->lightPosn[1] = pLight->Position.y;
1805 object->lightPosn[2] = pLight->Position.z;
1806 object->lightPosn[3] = 1.0;
1809 object->lightDirn[0] = pLight->Direction.x;
1810 object->lightDirn[1] = pLight->Direction.y;
1811 object->lightDirn[2] = pLight->Direction.z;
1812 object->lightDirn[3] = 1.0;
1815 * opengl-ish and d3d-ish spot lights use too different models for the
1816 * light "intensity" as a function of the angle towards the main light direction,
1817 * so we only can approximate very roughly.
1818 * however spot lights are rather rarely used in games (if ever used at all).
1819 * furthermore if still used, probably nobody pays attention to such details.
1821 if (pLight->Falloff == 0) {
1824 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1826 if (rho < 0.0001) rho = 0.0001f;
1827 object->exponent = -0.3/log(cos(rho/2));
1828 object->cutoff = pLight->Phi*90/M_PI;
1834 FIXME("Unrecognized light type %d\n", pLight->Type);
1837 /* Update the live definitions if the light is currently assigned a glIndex */
1838 if (object->glIndex != -1) {
1839 setup_light(iface, object->glIndex, object);
1844 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
1845 PLIGHTINFOEL *lightInfo = NULL;
1846 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1847 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1849 /* Locate the light in the live lights */
1850 lightInfo = This->stateBlock->lights;
1851 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1853 if (lightInfo == NULL) {
1854 TRACE("Light information requested but light not defined\n");
1855 return D3DERR_INVALIDCALL;
1858 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
1863 * Get / Set Light Enable
1864 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
1866 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
1867 PLIGHTINFOEL *lightInfo = NULL;
1868 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1869 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1871 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1872 if (This->isRecordingState) {
1873 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1874 if (NULL == lightInfo) {
1875 return D3DERR_OUTOFVIDEOMEMORY;
1877 lightInfo->OriginalIndex = Index;
1878 lightInfo->glIndex = -1;
1879 lightInfo->enabledChanged = TRUE;
1881 /* Add to the END of the chain of lights changes to be replayed */
1882 if (This->updateStateBlock->lights == NULL) {
1883 This->updateStateBlock->lights = lightInfo;
1885 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
1886 while (temp->next != NULL) temp=temp->next;
1887 temp->next = lightInfo;
1889 TRACE("Recording... not performing anything more\n");
1893 /* Not recording... So, locate the light in the live lights */
1894 lightInfo = This->stateBlock->lights;
1895 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1897 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1898 if (lightInfo == NULL) {
1899 D3DLIGHT9 lightParms;
1900 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1901 wait until someone confirms it seems to work! */
1902 TRACE("Light enabled requested but light not defined, so defining one!\n");
1903 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1904 lightParms.Diffuse.r = 1.0;
1905 lightParms.Diffuse.g = 1.0;
1906 lightParms.Diffuse.b = 1.0;
1907 lightParms.Diffuse.a = 0.0;
1908 lightParms.Specular.r = 0.0;
1909 lightParms.Specular.g = 0.0;
1910 lightParms.Specular.b = 0.0;
1911 lightParms.Specular.a = 0.0;
1912 lightParms.Ambient.r = 0.0;
1913 lightParms.Ambient.g = 0.0;
1914 lightParms.Ambient.b = 0.0;
1915 lightParms.Ambient.a = 0.0;
1916 lightParms.Position.x = 0.0;
1917 lightParms.Position.y = 0.0;
1918 lightParms.Position.z = 0.0;
1919 lightParms.Direction.x = 0.0;
1920 lightParms.Direction.y = 0.0;
1921 lightParms.Direction.z = 1.0;
1922 lightParms.Range = 0.0;
1923 lightParms.Falloff = 0.0;
1924 lightParms.Attenuation0 = 0.0;
1925 lightParms.Attenuation1 = 0.0;
1926 lightParms.Attenuation2 = 0.0;
1927 lightParms.Theta = 0.0;
1928 lightParms.Phi = 0.0;
1929 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
1931 /* Search for it again! Should be fairly quick as near head of list */
1932 lightInfo = This->stateBlock->lights;
1933 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1934 if (lightInfo == NULL) {
1935 FIXME("Adding default lights has failed dismally\n");
1936 return D3DERR_INVALIDCALL;
1940 /* OK, we now have a light... */
1941 if (Enable == FALSE) {
1943 /* If we are disabling it, check it was enabled, and
1944 still only do something if it has assigned a glIndex (which it should have!) */
1945 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
1946 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1948 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1949 checkGLcall("glDisable GL_LIGHT0+Index");
1952 TRACE("Nothing to do as light was not enabled\n");
1954 lightInfo->lightEnabled = FALSE;
1957 /* We are enabling it. If it is enabled, it's really simple */
1958 if (lightInfo->lightEnabled) {
1960 TRACE("Nothing to do as light was enabled\n");
1962 /* If it already has a glIndex, it's still simple */
1963 } else if (lightInfo->glIndex != -1) {
1964 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1965 lightInfo->lightEnabled = TRUE;
1967 glEnable(GL_LIGHT0 + lightInfo->glIndex);
1968 checkGLcall("glEnable GL_LIGHT0+Index already setup");
1971 /* Otherwise got to find space - lights are ordered gl indexes first */
1973 PLIGHTINFOEL *bsf = NULL;
1974 PLIGHTINFOEL *pos = This->stateBlock->lights;
1975 PLIGHTINFOEL *prev = NULL;
1979 /* Try to minimize changes as much as possible */
1980 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
1982 /* Try to remember which index can be replaced if necessary */
1983 if (bsf==NULL && pos->lightEnabled == FALSE) {
1984 /* Found a light we can replace, save as best replacement */
1988 /* Step to next space */
1994 /* If we have too many active lights, fail the call */
1995 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
1996 FIXME("Program requests too many concurrent lights\n");
1997 return D3DERR_INVALIDCALL;
1999 /* If we have allocated all lights, but not all are enabled,
2000 reuse one which is not enabled */
2001 } else if (Index == This->maxConcurrentLights) {
2002 /* use bsf - Simply swap the new light and the BSF one */
2003 PLIGHTINFOEL *bsfNext = bsf->next;
2004 PLIGHTINFOEL *bsfPrev = bsf->prev;
2007 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2008 if (bsf->prev != NULL) {
2009 bsf->prev->next = lightInfo;
2011 This->stateBlock->lights = lightInfo;
2014 /* If not side by side, lots of chains to update */
2015 if (bsf->next != lightInfo) {
2016 lightInfo->prev->next = bsf;
2017 bsf->next->prev = lightInfo;
2018 bsf->next = lightInfo->next;
2019 bsf->prev = lightInfo->prev;
2020 lightInfo->next = bsfNext;
2021 lightInfo->prev = bsfPrev;
2025 bsf->prev = lightInfo;
2026 bsf->next = lightInfo->next;
2027 lightInfo->next = bsf;
2028 lightInfo->prev = bsfPrev;
2033 glIndex = bsf->glIndex;
2035 lightInfo->glIndex = glIndex;
2036 lightInfo->lightEnabled = TRUE;
2038 /* Finally set up the light in gl itself */
2039 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2041 setup_light(iface, glIndex, lightInfo);
2042 glEnable(GL_LIGHT0 + glIndex);
2043 checkGLcall("glEnable GL_LIGHT0 new setup");
2046 /* If we reached the end of the allocated lights, with space in the
2047 gl lights, setup a new light */
2048 } else if (pos->glIndex == -1) {
2050 /* We reached the end of the allocated gl lights, so already
2051 know the index of the next one! */
2053 lightInfo->glIndex = glIndex;
2054 lightInfo->lightEnabled = TRUE;
2056 /* In an ideal world, it's already in the right place */
2057 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2058 /* No need to move it */
2060 /* Remove this light from the list */
2061 lightInfo->prev->next = lightInfo->next;
2062 if (lightInfo->next != NULL) {
2063 lightInfo->next->prev = lightInfo->prev;
2066 /* Add in at appropriate place (inbetween prev and pos) */
2067 lightInfo->prev = prev;
2068 lightInfo->next = pos;
2070 This->stateBlock->lights = lightInfo;
2072 prev->next = lightInfo;
2075 pos->prev = lightInfo;
2079 /* Finally set up the light in gl itself */
2080 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2082 setup_light(iface, glIndex, lightInfo);
2083 glEnable(GL_LIGHT0 + glIndex);
2084 checkGLcall("glEnable GL_LIGHT0 new setup");
2093 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2095 PLIGHTINFOEL *lightInfo = NULL;
2096 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2097 TRACE("(%p) : for idx(%ld)\n", This, Index);
2099 /* Locate the light in the live lights */
2100 lightInfo = This->stateBlock->lights;
2101 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2103 if (lightInfo == NULL) {
2104 TRACE("Light enabled state requested but light not defined\n");
2105 return D3DERR_INVALIDCALL;
2107 *pEnable = lightInfo->lightEnabled;
2112 * Get / Set Clip Planes
2114 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2115 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2116 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2118 /* Validate Index */
2119 if (Index >= GL_LIMITS(clipplanes)) {
2120 TRACE("Application has requested clipplane this device doesn't support\n");
2121 return D3DERR_INVALIDCALL;
2124 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2125 This->updateStateBlock->set.clipplane[Index] = TRUE;
2126 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2127 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2128 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2129 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2131 /* Handle recording of state blocks */
2132 if (This->isRecordingState) {
2133 TRACE("Recording... not performing anything\n");
2141 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2142 glMatrixMode(GL_MODELVIEW);
2144 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2146 TRACE("Clipplane [%f,%f,%f,%f]\n",
2147 This->updateStateBlock->clipplane[Index][0],
2148 This->updateStateBlock->clipplane[Index][1],
2149 This->updateStateBlock->clipplane[Index][2],
2150 This->updateStateBlock->clipplane[Index][3]);
2151 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2152 checkGLcall("glClipPlane");
2160 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2161 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2162 TRACE("(%p) : for idx %ld\n", This, Index);
2164 /* Validate Index */
2165 if (Index >= GL_LIMITS(clipplanes)) {
2166 TRACE("Application has requested clipplane this device doesn't support\n");
2167 return D3DERR_INVALIDCALL;
2170 pPlane[0] = This->stateBlock->clipplane[Index][0];
2171 pPlane[1] = This->stateBlock->clipplane[Index][1];
2172 pPlane[2] = This->stateBlock->clipplane[Index][2];
2173 pPlane[3] = This->stateBlock->clipplane[Index][3];
2178 * Get / Set Clip Plane Status
2179 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2181 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2182 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2183 FIXME("(%p) : stub\n", This);
2184 if (NULL == pClipStatus) {
2185 return D3DERR_INVALIDCALL;
2187 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2188 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2192 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2193 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2194 FIXME("(%p) : stub\n", This);
2195 if (NULL == pClipStatus) {
2196 return D3DERR_INVALIDCALL;
2198 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2199 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2204 * Get / Set Material
2205 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2207 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2208 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2210 This->updateStateBlock->changed.material = TRUE;
2211 This->updateStateBlock->set.material = TRUE;
2212 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2214 /* Handle recording of state blocks */
2215 if (This->isRecordingState) {
2216 TRACE("Recording... not performing anything\n");
2221 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2222 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2223 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2224 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2225 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2227 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2228 checkGLcall("glMaterialfv");
2229 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2230 checkGLcall("glMaterialfv");
2232 /* Only change material color if specular is enabled, otherwise it is set to black */
2233 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2234 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2235 checkGLcall("glMaterialfv");
2237 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2238 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2239 checkGLcall("glMaterialfv");
2241 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2242 checkGLcall("glMaterialfv");
2243 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2244 checkGLcall("glMaterialf");
2250 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2251 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2252 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2253 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2254 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2255 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2256 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2257 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2264 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2265 UINT BaseVertexIndex) {
2266 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2267 IWineD3DIndexBuffer *oldIdxs;
2269 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2270 oldIdxs = This->updateStateBlock->pIndexData;
2272 This->updateStateBlock->changed.indices = TRUE;
2273 This->updateStateBlock->set.indices = TRUE;
2274 This->updateStateBlock->pIndexData = pIndexData;
2275 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2277 /* Handle recording of state blocks */
2278 if (This->isRecordingState) {
2279 TRACE("Recording... not performing anything\n");
2283 if (oldIdxs) IWineD3DIndexBuffer_Release(oldIdxs);
2284 if (pIndexData) IWineD3DIndexBuffer_AddRef(This->stateBlock->pIndexData);
2288 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2289 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2291 *ppIndexData = This->stateBlock->pIndexData;
2293 /* up ref count on ppindexdata */
2294 if (*ppIndexData) IWineD3DIndexBuffer_AddRef(*ppIndexData);
2295 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2301 * Get / Set Viewports
2303 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2304 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2306 TRACE("(%p)\n", This);
2307 This->updateStateBlock->changed.viewport = TRUE;
2308 This->updateStateBlock->set.viewport = TRUE;
2309 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2311 /* Handle recording of state blocks */
2312 if (This->isRecordingState) {
2313 TRACE("Recording... not performing anything\n");
2319 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2320 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2322 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2323 checkGLcall("glDepthRange");
2324 /* Note: GL requires lower left, DirectX supplies upper left */
2325 /* TODO: replace usage of renderTarget with context management */
2326 glViewport(pViewport->X, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2327 pViewport->Width, pViewport->Height);
2328 checkGLcall("glViewport");
2336 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2337 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2338 TRACE("(%p)\n", This);
2339 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2344 * Get / Set Render States
2345 * TODO: Verify against dx9 definitions
2347 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2349 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2350 DWORD OldValue = This->stateBlock->renderState[State];
2352 /* Simple way of referring to either a DWORD or a 4 byte float */
2358 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2359 This->updateStateBlock->changed.renderState[State] = TRUE;
2360 This->updateStateBlock->set.renderState[State] = TRUE;
2361 This->updateStateBlock->renderState[State] = Value;
2363 /* Handle recording of state blocks */
2364 if (This->isRecordingState) {
2365 TRACE("Recording... not performing anything\n");
2372 case WINED3DRS_FILLMODE :
2373 switch ((D3DFILLMODE) Value) {
2374 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2375 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2376 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2378 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2380 checkGLcall("glPolygonMode (fillmode)");
2383 case WINED3DRS_LIGHTING :
2385 glEnable(GL_LIGHTING);
2386 checkGLcall("glEnable GL_LIGHTING");
2388 glDisable(GL_LIGHTING);
2389 checkGLcall("glDisable GL_LIGHTING");
2393 case WINED3DRS_ZENABLE :
2394 switch ((D3DZBUFFERTYPE) Value) {
2396 glDisable(GL_DEPTH_TEST);
2397 checkGLcall("glDisable GL_DEPTH_TEST");
2400 glEnable(GL_DEPTH_TEST);
2401 checkGLcall("glEnable GL_DEPTH_TEST");
2404 glEnable(GL_DEPTH_TEST);
2405 checkGLcall("glEnable GL_DEPTH_TEST");
2406 FIXME("W buffer is not well handled\n");
2409 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2413 case WINED3DRS_CULLMODE :
2415 /* If we are culling "back faces with clockwise vertices" then
2416 set front faces to be counter clockwise and enable culling
2418 switch ((D3DCULL) Value) {
2420 glDisable(GL_CULL_FACE);
2421 checkGLcall("glDisable GL_CULL_FACE");
2424 glEnable(GL_CULL_FACE);
2425 checkGLcall("glEnable GL_CULL_FACE");
2426 if (This->renderUpsideDown) {
2428 checkGLcall("glFrontFace GL_CW");
2430 glFrontFace(GL_CCW);
2431 checkGLcall("glFrontFace GL_CCW");
2433 glCullFace(GL_BACK);
2436 glEnable(GL_CULL_FACE);
2437 checkGLcall("glEnable GL_CULL_FACE");
2438 if (This->renderUpsideDown) {
2439 glFrontFace(GL_CCW);
2440 checkGLcall("glFrontFace GL_CCW");
2443 checkGLcall("glFrontFace GL_CW");
2445 glCullFace(GL_BACK);
2448 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2452 case WINED3DRS_SHADEMODE :
2453 switch ((D3DSHADEMODE) Value) {
2455 glShadeModel(GL_FLAT);
2456 checkGLcall("glShadeModel");
2458 case D3DSHADE_GOURAUD:
2459 glShadeModel(GL_SMOOTH);
2460 checkGLcall("glShadeModel");
2462 case D3DSHADE_PHONG:
2463 FIXME("D3DSHADE_PHONG isn't supported?\n");
2466 return D3DERR_INVALIDCALL;
2468 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2472 case WINED3DRS_DITHERENABLE :
2474 glEnable(GL_DITHER);
2475 checkGLcall("glEnable GL_DITHER");
2477 glDisable(GL_DITHER);
2478 checkGLcall("glDisable GL_DITHER");
2482 case WINED3DRS_ZWRITEENABLE :
2485 checkGLcall("glDepthMask");
2488 checkGLcall("glDepthMask");
2492 case WINED3DRS_ZFUNC :
2494 int glParm = GL_LESS;
2496 switch ((D3DCMPFUNC) Value) {
2497 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2498 case D3DCMP_LESS: glParm=GL_LESS; break;
2499 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2500 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2501 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2502 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2503 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2504 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2506 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2508 glDepthFunc(glParm);
2509 checkGLcall("glDepthFunc");
2513 case WINED3DRS_AMBIENT :
2516 D3DCOLORTOGLFLOAT4(Value, col);
2517 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2518 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2519 checkGLcall("glLightModel for MODEL_AMBIENT");
2524 case WINED3DRS_ALPHABLENDENABLE :
2527 checkGLcall("glEnable GL_BLEND");
2529 glDisable(GL_BLEND);
2530 checkGLcall("glDisable GL_BLEND");
2534 case WINED3DRS_SRCBLEND :
2535 case WINED3DRS_DESTBLEND :
2537 int newVal = GL_ZERO;
2539 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2540 case D3DBLEND_ONE : newVal = GL_ONE; break;
2541 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2542 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2543 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2544 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2545 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2546 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2547 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2548 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2549 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2551 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2552 This->srcBlend = newVal;
2553 This->dstBlend = newVal;
2556 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2557 This->srcBlend = newVal;
2558 This->dstBlend = newVal;
2561 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2564 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2565 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2566 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2567 glBlendFunc(This->srcBlend, This->dstBlend);
2569 checkGLcall("glBlendFunc");
2573 case WINED3DRS_ALPHATESTENABLE :
2575 glEnable(GL_ALPHA_TEST);
2576 checkGLcall("glEnable GL_ALPHA_TEST");
2578 glDisable(GL_ALPHA_TEST);
2579 checkGLcall("glDisable GL_ALPHA_TEST");
2583 case WINED3DRS_ALPHAFUNC :
2585 int glParm = GL_LESS;
2586 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2588 switch ((D3DCMPFUNC) Value) {
2589 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2590 case D3DCMP_LESS: glParm = GL_LESS; break;
2591 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2592 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2593 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2594 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2595 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2596 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2598 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2600 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2601 glAlphaFunc(glParm, ref);
2602 This->alphafunc = glParm;
2603 checkGLcall("glAlphaFunc");
2607 case WINED3DRS_ALPHAREF :
2609 int glParm = This->alphafunc;
2612 ref = ((float) Value) / 255.0f;
2613 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2614 glAlphaFunc(glParm, ref);
2615 checkGLcall("glAlphaFunc");
2619 case WINED3DRS_CLIPPLANEENABLE :
2620 case WINED3DRS_CLIPPING :
2622 /* Ensure we only do the changed clip planes */
2623 DWORD enable = 0xFFFFFFFF;
2624 DWORD disable = 0x00000000;
2626 /* If enabling / disabling all */
2627 if (State == WINED3DRS_CLIPPING) {
2629 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2632 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2636 enable = Value & ~OldValue;
2637 disable = ~Value & OldValue;
2640 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2641 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2642 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2643 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2644 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2645 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2647 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2648 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2649 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2650 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2651 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2652 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2654 /** update clipping status */
2656 This->stateBlock->clip_status.ClipUnion = 0;
2657 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2659 This->stateBlock->clip_status.ClipUnion = 0;
2660 This->stateBlock->clip_status.ClipIntersection = 0;
2665 case WINED3DRS_BLENDOP :
2667 int glParm = GL_FUNC_ADD;
2669 switch ((D3DBLENDOP) Value) {
2670 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2671 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2672 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2673 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2674 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2676 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2678 TRACE("glBlendEquation(%x)\n", glParm);
2679 glBlendEquation(glParm);
2680 checkGLcall("glBlendEquation");
2684 case WINED3DRS_TEXTUREFACTOR :
2688 /* Note the texture color applies to all textures whereas
2689 GL_TEXTURE_ENV_COLOR applies to active only */
2691 D3DCOLORTOGLFLOAT4(Value, col);
2692 /* Set the default alpha blend color */
2693 glBlendColor(col[0], col[1], col[2], col[3]);
2694 checkGLcall("glBlendColor");
2696 /* And now the default texture color as well */
2697 for (i = 0; i < GL_LIMITS(textures); i++) {
2699 /* Note the D3DRS value applies to all textures, but GL has one
2700 per texture, so apply it now ready to be used! */
2701 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2704 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2707 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2708 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2713 case WINED3DRS_SPECULARENABLE :
2715 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2716 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2717 specular color. This is wrong:
2718 Separate specular color means the specular colour is maintained separately, whereas
2719 single color means it is merged in. However in both cases they are being used to
2721 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2722 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2726 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2727 checkGLcall("glMaterialfv");
2728 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2729 glEnable(GL_COLOR_SUM_EXT);
2731 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2733 checkGLcall("glEnable(GL_COLOR_SUM)");
2735 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2737 /* for the case of enabled lighting: */
2738 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2739 checkGLcall("glMaterialfv");
2741 /* for the case of disabled lighting: */
2742 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2743 glDisable(GL_COLOR_SUM_EXT);
2745 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2747 checkGLcall("glDisable(GL_COLOR_SUM)");
2752 case WINED3DRS_STENCILENABLE :
2754 glEnable(GL_STENCIL_TEST);
2755 checkGLcall("glEnable GL_STENCIL_TEST");
2757 glDisable(GL_STENCIL_TEST);
2758 checkGLcall("glDisable GL_STENCIL_TEST");
2762 case WINED3DRS_STENCILFUNC :
2764 int glParm = GL_ALWAYS;
2765 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2766 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2768 switch ((D3DCMPFUNC) Value) {
2769 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2770 case D3DCMP_LESS: glParm=GL_LESS; break;
2771 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2772 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2773 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2774 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2775 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2776 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2778 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2780 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2781 This->stencilfunc = glParm;
2782 glStencilFunc(glParm, ref, mask);
2783 checkGLcall("glStencilFunc");
2787 case WINED3DRS_STENCILREF :
2789 int glParm = This->stencilfunc;
2791 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2794 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2795 glStencilFunc(glParm, ref, mask);
2796 checkGLcall("glStencilFunc");
2800 case WINED3DRS_STENCILMASK :
2802 int glParm = This->stencilfunc;
2803 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2804 GLuint mask = Value;
2806 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2807 glStencilFunc(glParm, ref, mask);
2808 checkGLcall("glStencilFunc");
2812 case WINED3DRS_STENCILFAIL :
2818 fail = StencilOp(Value);
2819 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2820 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2821 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2822 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2824 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2825 glStencilOp(fail, zfail, zpass);
2826 checkGLcall("glStencilOp(fail, zfail, zpass);");
2829 case WINED3DRS_STENCILZFAIL :
2835 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2836 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2837 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2838 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2839 zfail = StencilOp(Value);
2841 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2842 glStencilOp(fail, zfail, zpass);
2843 checkGLcall("glStencilOp(fail, zfail, zpass);");
2846 case WINED3DRS_STENCILPASS :
2852 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2853 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2854 zpass = StencilOp(Value);
2855 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2856 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2858 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2859 glStencilOp(fail, zfail, zpass);
2860 checkGLcall("glStencilOp(fail, zfail, zpass);");
2864 case WINED3DRS_STENCILWRITEMASK :
2866 glStencilMask(Value);
2867 TRACE("glStencilMask(%lu)\n", Value);
2868 checkGLcall("glStencilMask");
2872 case WINED3DRS_FOGENABLE :
2874 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2876 checkGLcall("glEnable GL_FOG");
2879 checkGLcall("glDisable GL_FOG");
2884 case WINED3DRS_RANGEFOGENABLE :
2887 TRACE("Enabled RANGEFOG");
2889 TRACE("Disabled RANGEFOG");
2894 case WINED3DRS_FOGCOLOR :
2897 D3DCOLORTOGLFLOAT4(Value, col);
2898 /* Set the default alpha blend color */
2899 glFogfv(GL_FOG_COLOR, &col[0]);
2900 checkGLcall("glFog GL_FOG_COLOR");
2904 case WINED3DRS_FOGTABLEMODE :
2906 glHint(GL_FOG_HINT, GL_NICEST);
2908 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2909 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2910 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2911 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2913 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2915 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2916 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2921 case WINED3DRS_FOGVERTEXMODE :
2923 glHint(GL_FOG_HINT, GL_FASTEST);
2925 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2926 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2927 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2928 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2930 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2932 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2933 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
2938 case WINED3DRS_FOGSTART :
2941 glFogfv(GL_FOG_START, &tmpvalue.f);
2942 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2943 TRACE("Fog Start == %f\n", tmpvalue.f);
2947 case WINED3DRS_FOGEND :
2950 glFogfv(GL_FOG_END, &tmpvalue.f);
2951 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2952 TRACE("Fog End == %f\n", tmpvalue.f);
2956 case WINED3DRS_FOGDENSITY :
2959 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
2960 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2964 case WINED3DRS_VERTEXBLEND :
2966 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2967 TRACE("Vertex Blending state to %ld\n", Value);
2971 case WINED3DRS_TWEENFACTOR :
2974 This->updateStateBlock->tween_factor = tmpvalue.f;
2975 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
2979 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
2981 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2985 case WINED3DRS_COLORVERTEX :
2986 case WINED3DRS_DIFFUSEMATERIALSOURCE :
2987 case WINED3DRS_SPECULARMATERIALSOURCE :
2988 case WINED3DRS_AMBIENTMATERIALSOURCE :
2989 case WINED3DRS_EMISSIVEMATERIALSOURCE :
2991 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2993 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
2994 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2995 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
2996 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
2997 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
2998 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3000 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3001 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3002 Parm = GL_AMBIENT_AND_DIFFUSE;
3006 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3008 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3010 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3017 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3019 This->tracking_color = NEEDS_TRACKING;
3020 This->tracking_parm = Parm;
3024 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3029 case WINED3DRS_LINEPATTERN :
3035 tmppattern.d = Value;
3037 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3039 if (tmppattern.lp.wRepeatFactor) {
3040 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3041 checkGLcall("glLineStipple(repeat, linepattern)");
3042 glEnable(GL_LINE_STIPPLE);
3043 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3045 glDisable(GL_LINE_STIPPLE);
3046 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3051 case WINED3DRS_ZBIAS :
3055 TRACE("ZBias value %f\n", tmpvalue.f);
3056 glPolygonOffset(0, -tmpvalue.f);
3057 checkGLcall("glPolygonOffset(0, -Value)");
3058 glEnable(GL_POLYGON_OFFSET_FILL);
3059 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3060 glEnable(GL_POLYGON_OFFSET_LINE);
3061 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3062 glEnable(GL_POLYGON_OFFSET_POINT);
3063 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3065 glDisable(GL_POLYGON_OFFSET_FILL);
3066 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3067 glDisable(GL_POLYGON_OFFSET_LINE);
3068 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3069 glDisable(GL_POLYGON_OFFSET_POINT);
3070 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3075 case WINED3DRS_NORMALIZENORMALS :
3077 glEnable(GL_NORMALIZE);
3078 checkGLcall("glEnable(GL_NORMALIZE);");
3080 glDisable(GL_NORMALIZE);
3081 checkGLcall("glDisable(GL_NORMALIZE);");
3085 case WINED3DRS_POINTSIZE :
3087 TRACE("Set point size to %f\n", tmpvalue.f);
3088 glPointSize(tmpvalue.f);
3089 checkGLcall("glPointSize(...);");
3092 case WINED3DRS_POINTSIZE_MIN :
3093 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3095 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3096 checkGLcall("glPointParameterfEXT(...);");
3098 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3102 case WINED3DRS_POINTSIZE_MAX :
3103 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3105 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3106 checkGLcall("glPointParameterfEXT(...);");
3108 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3112 case WINED3DRS_POINTSCALE_A :
3113 case WINED3DRS_POINTSCALE_B :
3114 case WINED3DRS_POINTSCALE_C :
3115 case WINED3DRS_POINTSCALEENABLE :
3117 /* If enabled, supply the parameters, otherwise fall back to defaults */
3118 if (This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3119 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3120 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]);
3121 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]);
3122 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]);
3124 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3125 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3126 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3128 TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
3131 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3132 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3133 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3134 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3136 TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
3142 case WINED3DRS_COLORWRITEENABLE :
3144 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3145 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3146 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3147 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3148 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3149 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3150 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3151 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3152 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3153 checkGLcall("glColorMask(...)");
3157 case WINED3DRS_LOCALVIEWER :
3159 GLint state = (Value) ? 1 : 0;
3160 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3161 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3165 case WINED3DRS_LASTPIXEL :
3168 TRACE("Last Pixel Drawing Enabled\n");
3170 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3175 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3178 TRACE("Software Processing Enabled\n");
3180 TRACE("Software Processing Disabled\n");
3185 /** not supported */
3186 case WINED3DRS_ZVISIBLE :
3189 return D3DERR_INVALIDCALL;
3192 /* Unhandled yet...! */
3193 case WINED3DRS_EDGEANTIALIAS :
3194 case WINED3DRS_WRAP0 :
3195 case WINED3DRS_WRAP1 :
3196 case WINED3DRS_WRAP2 :
3197 case WINED3DRS_WRAP3 :
3198 case WINED3DRS_WRAP4 :
3199 case WINED3DRS_WRAP5 :
3200 case WINED3DRS_WRAP6 :
3201 case WINED3DRS_WRAP7 :
3202 case WINED3DRS_POINTSPRITEENABLE :
3203 case WINED3DRS_MULTISAMPLEANTIALIAS :
3204 case WINED3DRS_MULTISAMPLEMASK :
3205 case WINED3DRS_PATCHEDGESTYLE :
3206 case WINED3DRS_PATCHSEGMENTS :
3207 case WINED3DRS_DEBUGMONITORTOKEN :
3208 case WINED3DRS_POSITIONORDER :
3209 case WINED3DRS_NORMALORDER :
3210 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3211 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3214 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3222 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3223 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3224 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3225 *pValue = This->stateBlock->renderState[State];
3229 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value){
3230 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3232 * SetSampler is designed to allow for more than the standard up to 8 textures
3233 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3234 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3236 * http://developer.nvidia.com/object/General_FAQ.html#t6
3238 * There are two new settings for GForce
3240 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3241 * and the texture one:
3242 * GL_MAX_TEXTURE_COORDS_ARB.
3243 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3250 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3252 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > HIGHEST_SAMPLER_STATE || Type < 0){
3253 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), HIGHEST_SAMPLER_STATE, Sampler, Type);
3254 return D3DERR_INVALIDCALL;
3257 This->updateStateBlock->changed.samplerState[Sampler][Type] = TRUE;
3258 This->updateStateBlock->set.samplerState[Sampler][Type] = TRUE;
3259 TRACE("Setting sampler %ld %d to %ld \n", Sampler, Type, Value);
3260 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3262 /* Handle recording of state blocks */
3263 if (This->isRecordingState) {
3264 TRACE("Recording... not performing anything\n");
3268 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
3269 clamping, MIPLOD, etc. This will work for up to 16 samplers.
3270 is this just GL_TEXTURE_2D or is it GL_TEXTURE_1D and GL_TEXTURE_3D as well?
3273 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
3274 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3275 GLACTIVETEXTURE(Sampler);
3276 } else if (Sampler > 0) {
3277 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3283 case WINED3DSAMP_ADDRESSU : /* 1 */
3284 case WINED3DSAMP_ADDRESSV : /* 2 */
3285 case WINED3DSAMP_ADDRESSW : /* 3 */
3287 GLint wrapParm = GL_REPEAT;
3289 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3290 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3291 case D3DTADDRESS_BORDER:
3293 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3294 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3296 /* FIXME: Not right, but better */
3297 TRACE("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3298 wrapParm = GL_REPEAT;
3302 case D3DTADDRESS_MIRROR:
3304 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3305 wrapParm = GL_MIRRORED_REPEAT_ARB;
3307 /* Unsupported in OpenGL pre-1.4 */
3308 TRACE("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3309 wrapParm = GL_REPEAT;
3313 case D3DTADDRESS_MIRRORONCE:
3315 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3316 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3318 TRACE("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3319 wrapParm = GL_REPEAT;
3325 /* This is for the whole context, not just the sampler,
3326 so we should warn if two states are baing set for any given scene */
3328 TRACE("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3329 wrapParm = GL_REPEAT;
3332 case WINED3DSAMP_ADDRESSU:
3333 TRACE("Setting WRAP_S for %ld to %d \n", Sampler, wrapParm);
3334 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_S, wrapParm);
3335 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3337 case WINED3DSAMP_ADDRESSV:
3338 TRACE("Setting WRAP_T for %ld to %d\n", Sampler, wrapParm);
3339 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_T, wrapParm);
3340 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3343 case WINED3DSAMP_ADDRESSW:
3344 TRACE("Setting WRAP_R for %ld to %d\n", Sampler, wrapParm);
3345 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_R, wrapParm);
3346 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3349 break; /** stupic compilator */
3354 case WINED3DSAMP_BORDERCOLOR : /* 4 */
3357 D3DCOLORTOGLFLOAT4(Value, col);
3358 TRACE("Setting border color for %ld to %lx\n", Sampler, Value);
3359 glTexParameterfv(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_BORDER_COLOR, &col[0]);
3360 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3364 case WINED3DSAMP_MAGFILTER : /* 5 */
3366 DWORD ValueMAG = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAGFILTER];
3367 GLint realVal = GL_NEAREST;
3369 if (ValueMAG == D3DTEXF_POINT) {
3370 realVal = GL_NEAREST;
3371 } else if (ValueMAG == D3DTEXF_LINEAR) {
3372 realVal = GL_LINEAR;
3373 } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
3374 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3375 realVal = GL_LINEAR;
3377 FIXME("Trying to use ANISOTROPIC_FILTERING for WINED3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
3378 realVal = GL_NEAREST;
3381 FIXME("Unhandled WINED3DTSS_MAGFILTER value of %ld\n", ValueMAG);
3382 realVal = GL_NEAREST;
3384 TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
3385 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MAG_FILTER, realVal);
3386 checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
3388 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3390 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
3391 glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3392 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3393 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3394 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3399 case WINED3DSAMP_MINFILTER: /* 6 */
3400 case WINED3DSAMP_MIPFILTER: /* 7 */
3402 DWORD ValueMIN = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MINFILTER];
3403 DWORD ValueMIP = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPFILTER];
3404 GLint realVal = GL_LINEAR;
3406 if (ValueMIN == D3DTEXF_NONE) {
3407 /* Doesn't really make sense - Windows just seems to disable
3408 mipmapping when this occurs */
3409 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3410 realVal = GL_LINEAR;
3411 } else if (ValueMIN == D3DTEXF_POINT) {
3413 if (ValueMIP == D3DTEXF_NONE) {
3414 realVal = GL_NEAREST;
3415 } else if (ValueMIP == D3DTEXF_POINT) {
3416 realVal = GL_NEAREST_MIPMAP_NEAREST;
3417 } else if (ValueMIP == D3DTEXF_LINEAR) {
3418 realVal = GL_NEAREST_MIPMAP_LINEAR;
3420 FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3421 realVal = GL_NEAREST;
3423 } else if (ValueMIN == D3DTEXF_LINEAR) {
3425 if (ValueMIP == D3DTEXF_NONE) {
3426 realVal = GL_LINEAR;
3427 } else if (ValueMIP == D3DTEXF_POINT) {
3428 realVal = GL_LINEAR_MIPMAP_NEAREST;
3429 } else if (ValueMIP == D3DTEXF_LINEAR) {
3430 realVal = GL_LINEAR_MIPMAP_LINEAR;
3432 FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3433 realVal = GL_LINEAR;
3435 } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
3436 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3437 if (ValueMIP == D3DTEXF_NONE) {
3438 realVal = GL_LINEAR_MIPMAP_LINEAR;
3439 } else if (ValueMIP == D3DTEXF_POINT) {
3440 realVal = GL_LINEAR_MIPMAP_NEAREST;
3441 } else if (ValueMIP == D3DTEXF_LINEAR) {
3442 realVal = GL_LINEAR_MIPMAP_LINEAR;
3444 FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3445 realVal = GL_LINEAR;
3448 WARN("Trying to use ANISOTROPIC_FILTERING for WINED3DTSS_MINFILTER. But not supported by OpenGL driver\n");
3449 realVal = GL_LINEAR;
3452 FIXME("Unhandled WINED3DTSS_MINFILTER value of %ld\n", ValueMIN);
3453 realVal = GL_LINEAR_MIPMAP_LINEAR;
3456 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3457 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MIN_FILTER, realVal);
3458 checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
3460 * if we just choose to use ANISOTROPIC filtering, refresh openGL state
3462 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
3463 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MAX_ANISOTROPY_EXT,
3464 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3465 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3470 case WINED3DSAMP_MIPMAPLODBIAS : /* 8 */
3472 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3474 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3475 GL_TEXTURE_LOD_BIAS_EXT,
3477 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
3482 case WINED3DSAMP_MAXMIPLEVEL : /* 9 */
3485 * Not really the same, but the more apprioprate than nothing
3487 glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3488 GL_TEXTURE_BASE_LEVEL,
3489 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXMIPLEVEL]);
3490 checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
3494 case WINED3DSAMP_MAXANISOTROPY : /* 10 */
3496 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3497 glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3498 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3499 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3500 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3504 case WINED3DSAMP_SRGBTEXTURE : /* 11 */
3505 /* Per texture gamma correction, default 0 */
3506 case WINED3DSAMP_ELEMENTINDEX : /* 12 */
3507 /* When a multi-element textures is used this indicates the element, (what's a multielement texture?) */
3508 case WINED3DSAMP_DMAPOFFSET : /* 13 */
3509 /* Value of a precompiled displacement map used by the tesselator, default 0 */
3510 TRACE("Unsupported sampler setting, Sampler=%ld, Type=%d, Value =%ld\n", Sampler, Type, Value);
3514 TRACE("invalid sampler setting, Sampler=%ld, Type=%d, Value =%ld\n", Sampler, Type, Value);
3520 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value){
3521 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3522 /** TODO: check that sampler is in range **/
3523 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3524 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3529 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect){
3530 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3533 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3534 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3535 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3540 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect){
3541 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3542 GLint scissorBox[4];
3545 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3546 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3547 pRect->left = scissorBox[1];
3548 pRect->top = scissorBox[2];
3549 pRect->right = scissorBox[1] + scissorBox[3];
3550 pRect->bottom = scissorBox[2] + scissorBox[4];
3551 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3556 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3557 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3559 TRACE("(%p) : pDecl=%p\n", This, pDecl);
3561 IWineD3DVertexDeclaration_AddRef(pDecl);
3562 if (NULL != This->updateStateBlock->vertexDecl) {
3563 IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
3565 This->updateStateBlock->vertexDecl = pDecl;
3566 This->updateStateBlock->changed.vertexDecl = TRUE;
3567 This->updateStateBlock->set.vertexDecl = TRUE;
3571 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3572 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3574 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3576 *ppDecl = This->updateStateBlock->vertexDecl;
3577 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3581 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader){
3582 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3584 static BOOL showFixmes = TRUE;
3586 This->updateStateBlock->vertexShader = pShader;
3587 This->updateStateBlock->changed.vertexShader = TRUE;
3588 This->updateStateBlock->set.vertexShader = TRUE;
3590 if(pShader == NULL){
3591 /* clear down the shader */
3592 TRACE("Clear down the shader\n");
3595 FIXME("(%p) : stub pShader(%p)\n", This, pShader);
3602 /** FIXME: refernece counting? **/
3603 if (pShader == NULL) { /* only valid with non FVF shaders */
3604 TRACE_(d3d_shader)("(%p) : FVF Shader, pShader=%p\n", This, pShader);
3605 This->updateStateBlock->vertexShader = NULL;
3607 TRACE_(d3d_shader)("(%p) : Created shader, pShader=%p\n", This, pShader);
3608 This->updateStateBlock->vertexShader = pShader;
3611 This->updateStateBlock->changed.vertexShader = TRUE;
3612 This->updateStateBlock->set.vertexShader = TRUE;
3614 /* Handle recording of state blocks */
3615 if (This->isRecordingState) {
3616 TRACE("Recording... not performing anything\n");
3620 * TODO: merge HAL shaders context switching from prototype
3626 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader){
3627 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3628 *ppShader = This->stateBlock->vertexShader;
3629 if(*ppShader != NULL)
3630 IWineD3DVertexShader_AddRef(*ppShader);
3631 TRACE("(%p) : returning %p\n", This, *ppShader);
3635 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
3636 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3638 TRACE("(%p) : stub\n", This);
3642 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3643 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3644 TRACE("(%p) : stub\n", This);
3648 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3649 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3650 TRACE("(%p) : stub\n", This);
3654 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
3655 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3656 TRACE("(%p) : stub\n", This);
3660 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3661 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3662 TRACE("(%p) : stub\n", This);
3666 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
3667 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3668 TRACE("(%p) : stub\n", This);
3672 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader){
3673 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3674 TRACE("(%p) : stub\n", This);
3678 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader){
3679 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3680 TRACE("(%p) : stub\n", This);
3685 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
3686 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3687 TRACE("(%p) : stub\n", This);
3691 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3692 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3693 TRACE("(%p) : stub\n", This);
3697 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3698 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3699 TRACE("(%p) : stub\n", This);
3703 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
3704 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3705 TRACE("(%p) : stub\n", This);
3709 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3710 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3711 TRACE("(%p) : stub\n", This);
3715 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
3716 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3717 TRACE("(%p) : stub\n", This);
3721 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags){
3722 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3723 FIXME("(%p) : stub\n", This);
3728 * Get / Set Texture Stage States
3729 * TODO: Verify against dx9 definitions
3731 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3732 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3734 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3736 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3738 /* Reject invalid texture units */
3739 if (Stage >= GL_LIMITS(textures)) {
3740 TRACE("Attempt to access invalid texture rejected\n");
3741 return D3DERR_INVALIDCALL;
3744 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
3745 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
3746 This->updateStateBlock->textureState[Stage][Type] = Value;
3748 /* Handle recording of state blocks */
3749 if (This->isRecordingState) {
3750 TRACE("Recording... not performing anything\n");
3756 /* Make appropriate texture active */
3757 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3758 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3759 GLACTIVETEXTURE(Stage);
3760 } else if (Stage > 0) {
3761 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3765 case WINED3DTSS_ALPHAOP :
3766 case WINED3DTSS_COLOROP :
3769 if ((Value == D3DTOP_DISABLE) && (Type == WINED3DTSS_COLOROP)) {
3770 /* TODO: Disable by making this and all later levels disabled */
3771 glDisable(GL_TEXTURE_1D);
3772 checkGLcall("Disable GL_TEXTURE_1D");
3773 glDisable(GL_TEXTURE_2D);
3774 checkGLcall("Disable GL_TEXTURE_2D");
3775 glDisable(GL_TEXTURE_3D);
3776 checkGLcall("Disable GL_TEXTURE_3D");
3777 break; /* Don't bother setting the texture operations */
3779 /* Enable only the appropriate texture dimension */
3780 if (Type == WINED3DTSS_COLOROP) {
3781 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3782 glEnable(GL_TEXTURE_1D);
3783 checkGLcall("Enable GL_TEXTURE_1D");
3785 glDisable(GL_TEXTURE_1D);
3786 checkGLcall("Disable GL_TEXTURE_1D");
3788 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3789 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3790 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3791 checkGLcall("Enable GL_TEXTURE_2D");
3793 glEnable(GL_TEXTURE_2D);
3794 checkGLcall("Enable GL_TEXTURE_2D");
3797 glDisable(GL_TEXTURE_2D);
3798 checkGLcall("Disable GL_TEXTURE_2D");
3800 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3801 glEnable(GL_TEXTURE_3D);
3802 checkGLcall("Enable GL_TEXTURE_3D");
3804 glDisable(GL_TEXTURE_3D);
3805 checkGLcall("Disable GL_TEXTURE_3D");
3807 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3808 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3809 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3811 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3812 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3816 /* Drop through... (Except disable case) */
3817 case WINED3DTSS_COLORARG0 :
3818 case WINED3DTSS_COLORARG1 :
3819 case WINED3DTSS_COLORARG2 :
3820 case WINED3DTSS_ALPHAARG0 :
3821 case WINED3DTSS_ALPHAARG1 :
3822 case WINED3DTSS_ALPHAARG2 :
3824 BOOL isAlphaArg = (Type == WINED3DTSS_ALPHAOP || Type == WINED3DTSS_ALPHAARG1 ||
3825 Type == WINED3DTSS_ALPHAARG2 || Type == WINED3DTSS_ALPHAARG0);
3827 set_tex_op(iface, TRUE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAOP],
3828 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG1],
3829 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG2],
3830 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG0]);
3832 set_tex_op(iface, FALSE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP],
3833 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG1],
3834 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG2],
3835 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG0]);
3841 case WINED3DTSS_ADDRESSW :
3843 GLint wrapParm = GL_REPEAT;
3846 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3847 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3848 case D3DTADDRESS_BORDER:
3850 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3851 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3853 /* FIXME: Not right, but better */
3854 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3855 wrapParm = GL_REPEAT;
3859 case D3DTADDRESS_MIRROR:
3861 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3862 wrapParm = GL_MIRRORED_REPEAT_ARB;
3864 /* Unsupported in OpenGL pre-1.4 */
3865 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3866 wrapParm = GL_REPEAT;
3870 case D3DTADDRESS_MIRRORONCE:
3872 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3873 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3875 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3876 wrapParm = GL_REPEAT;
3882 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3883 wrapParm = GL_REPEAT;
3886 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3887 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3888 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3892 case WINED3DTSS_TEXCOORDINDEX :
3894 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3896 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
3897 one flag, you can still specify an index value, which the system uses to
3898 determine the texture wrapping mode.
3899 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3900 means use the vertex position (camera-space) as the input texture coordinates
3901 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3902 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3903 to the TEXCOORDINDEX value */
3906 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3908 switch (Value & 0xFFFF0000) {
3909 case D3DTSS_TCI_PASSTHRU:
3910 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3911 glDisable(GL_TEXTURE_GEN_S);
3912 glDisable(GL_TEXTURE_GEN_T);
3913 glDisable(GL_TEXTURE_GEN_R);
3914 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3917 case D3DTSS_TCI_CAMERASPACEPOSITION:
3918 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3919 as the input texture coordinates for this stage's texture transformation. This
3920 equates roughly to EYE_LINEAR */
3922 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3923 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3924 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3925 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3926 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3928 glMatrixMode(GL_MODELVIEW);
3931 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3932 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3933 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3934 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3937 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3938 glEnable(GL_TEXTURE_GEN_S);
3939 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3940 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3941 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3942 glEnable(GL_TEXTURE_GEN_T);
3943 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3944 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3945 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3946 glEnable(GL_TEXTURE_GEN_R);
3947 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3948 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3949 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3953 case D3DTSS_TCI_CAMERASPACENORMAL:
3955 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3956 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3957 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3958 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3959 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3960 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3962 glMatrixMode(GL_MODELVIEW);
3965 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3966 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3967 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3968 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3971 glEnable(GL_TEXTURE_GEN_S);
3972 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3973 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3974 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3975 glEnable(GL_TEXTURE_GEN_T);
3976 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3977 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3978 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3979 glEnable(GL_TEXTURE_GEN_R);
3980 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3981 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3982 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3987 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3989 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3990 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3991 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3992 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3993 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3994 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3996 glMatrixMode(GL_MODELVIEW);
3999 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4000 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4001 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4002 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4005 glEnable(GL_TEXTURE_GEN_S);
4006 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4007 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4008 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4009 glEnable(GL_TEXTURE_GEN_T);
4010 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4011 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4012 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4013 glEnable(GL_TEXTURE_GEN_R);
4014 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4015 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4016 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4021 /* Unhandled types: */
4024 /* ? disable GL_TEXTURE_GEN_n ? */
4025 glDisable(GL_TEXTURE_GEN_S);
4026 glDisable(GL_TEXTURE_GEN_T);
4027 glDisable(GL_TEXTURE_GEN_R);
4028 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
4035 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4036 set_texture_matrix((float *)&This->stateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
4039 case WINED3DTSS_BUMPENVMAT00 :
4040 case WINED3DTSS_BUMPENVMAT01 :
4041 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4043 case WINED3DTSS_BUMPENVMAT10 :
4044 case WINED3DTSS_BUMPENVMAT11 :
4045 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4048 case WINED3DTSS_BUMPENVLSCALE :
4049 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4052 case WINED3DTSS_BUMPENVLOFFSET :
4053 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4056 case WINED3DTSS_RESULTARG :
4057 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4061 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4062 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4070 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4071 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4072 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4073 *pValue = This->updateStateBlock->textureState[Stage][Type];
4080 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4082 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4083 IWineD3DBaseTexture *oldTexture;
4084 BOOL reapplyStates = TRUE;
4085 DWORD reapplyFlags = 0;
4086 INT oldTextureDimensions = -1;
4087 D3DRESOURCETYPE textureType;
4089 oldTexture = This->updateStateBlock->textures[Stage];
4090 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4092 /* Reject invalid texture units */
4093 if (Stage >= GL_LIMITS(textures)) {
4094 TRACE("Attempt to access invalid texture rejected\n");
4095 return D3DERR_INVALIDCALL;
4098 This->updateStateBlock->set.textures[Stage] = TRUE;
4099 This->updateStateBlock->changed.textures[Stage] = TRUE;
4100 This->updateStateBlock->textures[Stage] = pTexture;
4102 /* Handle recording of state blocks */
4103 if (This->isRecordingState) {
4104 TRACE("Recording... not performing anything\n");
4108 oldTextureDimensions = This->updateStateBlock->textureDimensions[Stage];
4112 /* Make appropriate texture active */
4113 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
4114 GLACTIVETEXTURE(Stage);
4116 } else if (Stage>0) {
4117 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
4120 /** NOTE: MSDN says that setTexture increases the reference count,
4121 * and the the application nust set the texture back to null (or have a leaky application),
4122 * This means we should pass the refcount upto the parent
4123 *******************************/
4124 if (NULL != oldTexture) {
4126 IUnknown *textureParent;
4127 IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
4128 IUnknown_Release(textureParent);
4129 IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
4134 if (NULL != pTexture) {
4135 IUnknown *textureParent;
4136 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
4137 /** NOTE: GetParent will increase the ref count for me, I won't clean up untill the texture is set to NULL **/
4139 /* Now setup the texture appropraitly */
4140 textureType = IWineD3DBaseTexture_GetType(pTexture);
4142 if (textureType == D3DRTYPE_TEXTURE) {
4144 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4145 TRACE("Skipping setting texture as old == new\n");
4146 reapplyStates = FALSE;
4150 /* Standard 2D texture */
4151 TRACE("Standard 2d texture\n");
4152 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
4154 /* Load up the texture now */
4155 IWineD3DTexture_PreLoad((IWineD3DTexture *) pTexture);
4158 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
4160 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4161 TRACE("Skipping setting texture as old == new\n");
4162 reapplyStates = FALSE;
4166 /* Standard 3D (volume) texture */
4167 TRACE("Standard 3d texture\n");
4168 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
4170 /* Load up the texture now */
4171 IWineD3DVolumeTexture_PreLoad((IWineD3DVolumeTexture *) pTexture);
4174 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
4176 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4177 TRACE("Skipping setting texture as old == new\n");
4178 reapplyStates = FALSE;
4182 /* Standard Cube texture */
4183 TRACE("Standard Cube texture\n");
4184 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
4186 /* Load up the texture now */
4187 IWineD3DCubeTexture_PreLoad((IWineD3DCubeTexture *) pTexture);
4191 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dresourcetype(textureType));
4196 TRACE("Setting to no texture (ie default texture)\n");
4197 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
4198 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
4199 checkGLcall("glBindTexture");
4200 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
4203 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
4204 if (oldTextureDimensions != This->updateStateBlock->textureDimensions[Stage]) {
4206 glDisable(oldTextureDimensions);
4207 checkGLcall("Disable oldTextureDimensions");
4209 if (This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP] != D3DTOP_DISABLE) {
4210 glEnable(This->updateStateBlock->textureDimensions[Stage]);
4211 checkGLcall("glEnable new texture dimensions");
4214 /* If Alpha arg1 is texture then handle the special case when there changes between a
4215 texture and no texture - See comments in set_tex_op */
4216 if ((This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
4217 (((oldTexture == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTexture != NULL))))
4219 reapplyFlags |= REAPPLY_ALPHAOP;
4224 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
4225 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
4226 if (reapplyStates) {
4227 IWineD3DDeviceImpl_SetupTextureStates(iface, Stage, reapplyFlags);
4231 TRACE("Texture now fully setup\n");
4236 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4237 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4238 TRACE("(%p) : returning %p for stage %ld\n", This, This->updateStateBlock->textures[Stage], Stage);
4239 *ppTexture = (IWineD3DBaseTexture *) This->updateStateBlock->textures[Stage];
4241 IWineD3DBaseTexture_AddRef(*ppTexture);
4248 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4249 IWineD3DSurface** ppBackBuffer) {
4250 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4251 IWineD3DSwapChain *swapChain;
4254 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4256 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4258 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4259 IWineD3DSwapChain_Release(swapChain);
4261 *ppBackBuffer = NULL;
4266 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4267 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4268 WARN("(%p) : stub, calling idirect3d for now\n", This);
4269 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4272 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4273 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4274 IWineD3DSwapChain *swapChain;
4277 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4279 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4280 IWineD3DSwapChain_Release(swapChain);
4282 FIXME("(%p) Error getting display mode\n", This);
4287 * Stateblock related functions
4290 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4291 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4292 IWineD3DStateBlockImpl *object;
4293 TRACE("(%p)", This);
4294 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4295 if(NULL == object ){
4296 FIXME("(%p)Error allocating memory for stateblock\n", This);
4297 return E_OUTOFMEMORY;
4299 TRACE("(%p) creted object %p\n", This, object);
4300 object->wineD3DDevice= This;
4301 /** FIXME: object->parent = parent; **/
4302 object->parent = NULL;
4303 object->blockType = D3DSBT_ALL;
4305 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4307 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4308 This->updateStateBlock = object;
4309 This->isRecordingState = TRUE;
4311 TRACE("(%p) recording stateblock %p\n",This , object);
4315 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4316 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4318 if (!This->isRecordingState) {
4319 FIXME("(%p) not recording! returning error\n", This);
4320 *ppStateBlock = NULL;
4321 return D3DERR_INVALIDCALL;
4324 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4325 This->isRecordingState = FALSE;
4326 This->updateStateBlock = This->stateBlock;
4327 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4328 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4329 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4334 * Scene related functions
4336 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4337 /* At the moment we have no need for any functionality at the beginning
4339 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4340 TRACE("(%p) : stub\n", This);
4344 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4345 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4346 TRACE("(%p)\n", This);
4348 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4350 checkGLcall("glFlush");
4352 TRACE("End Scene\n");
4353 if(This->renderTarget != NULL){
4355 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4356 IUnknown *targetContainer = NULL;
4357 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)) {
4358 TRACE("RenderTarget is either standalone of a texture.\n");
4359 /** always dirtify for now. we must find a better way to see that surface have been modified
4360 (Modifications should will only occur via draw-primitive, but we do need better locking
4361 switching to render-to-texture should remove the overhead though.
4363 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4364 IWineD3DBaseTexture_SetDirty((IWineD3DBaseTexture *)targetContainer, TRUE);
4365 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *)targetContainer);
4366 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4367 IUnknown_Release(targetContainer);
4376 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4377 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4378 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4379 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4380 IWineD3DSwapChain *swapChain = NULL;
4382 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4384 TRACE("(%p) Presenting the frame\n", This);
4386 for(i = 0 ; i < swapchains ; i ++){
4388 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4389 TRACE("presentinng chain %d, %p\n", i, swapChain);
4390 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4391 IWineD3DSwapChain_Release(swapChain);
4397 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4398 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4399 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4401 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4402 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4403 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4404 GLbitfield glMask = 0;
4405 GLboolean old_ztest;
4406 GLfloat old_z_clear_value;
4407 GLint old_stencil_clear_value;
4408 GLfloat old_color_clear_value[4];
4410 CONST D3DRECT* curRect;
4412 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4413 Count, pRects, Flags, Z, Stencil);
4417 glEnable(GL_SCISSOR_TEST);
4418 checkGLcall("glEnable GL_SCISSOR_TEST");
4420 if (Count > 0 && pRects) {
4426 /* Only set the values up once, as they are not changing */
4427 if (Flags & D3DCLEAR_STENCIL) {
4428 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4429 glClearStencil(Stencil);
4430 checkGLcall("glClearStencil");
4431 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4432 glStencilMask(0xFFFFFFFF);
4435 if (Flags & D3DCLEAR_ZBUFFER) {
4436 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4437 glDepthMask(GL_TRUE);
4438 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4440 checkGLcall("glClearDepth");
4441 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4444 if (Flags & D3DCLEAR_TARGET) {
4445 TRACE("Clearing screen with glClear to color %lx\n", Color);
4446 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4447 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
4448 ((Color >> 8) & 0xFF) / 255.0f,
4449 ((Color >> 0) & 0xFF) / 255.0f,
4450 ((Color >> 24) & 0xFF) / 255.0f);
4451 checkGLcall("glClearColor");
4453 /* Clear ALL colors! */
4454 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4455 glMask = glMask | GL_COLOR_BUFFER_BIT;
4458 /* Now process each rect in turn */
4459 for (i = 0; i < Count || i == 0; i++) {
4462 /* Note gl uses lower left, width/height */
4463 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4464 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4465 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4466 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4467 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4468 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4469 checkGLcall("glScissor");
4471 glScissor(This->stateBlock->viewport.X,
4472 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4473 This->stateBlock->viewport.Width,
4474 This->stateBlock->viewport.Height);
4475 checkGLcall("glScissor");
4478 /* Clear the selected rectangle (or full screen) */
4480 checkGLcall("glClear");
4482 /* Step to the next rectangle */
4483 if (curRect) curRect = curRect + sizeof(D3DRECT);
4486 /* Restore the old values (why..?) */
4487 if (Flags & D3DCLEAR_STENCIL) {
4488 glClearStencil(old_stencil_clear_value);
4489 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4491 if (Flags & D3DCLEAR_ZBUFFER) {
4492 glDepthMask(old_ztest);
4493 glClearDepth(old_z_clear_value);
4495 if (Flags & D3DCLEAR_TARGET) {
4496 glClearColor(old_color_clear_value[0],
4497 old_color_clear_value[1],
4498 old_color_clear_value[2],
4499 old_color_clear_value[3]);
4500 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4501 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4502 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4503 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4506 glDisable(GL_SCISSOR_TEST);
4507 checkGLcall("glDisable");
4516 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4517 UINT PrimitiveCount) {
4519 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4520 This->stateBlock->streamIsUP = FALSE;
4522 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4523 debug_d3dprimitivetype(PrimitiveType),
4524 StartVertex, PrimitiveCount);
4525 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
4530 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4531 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4532 D3DPRIMITIVETYPE PrimitiveType,
4533 INT baseVIndex, UINT minIndex,
4534 UINT NumVertices,UINT startIndex,UINT primCount) {
4536 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4538 IWineD3DIndexBuffer *pIB;
4539 D3DINDEXBUFFER_DESC IdxBufDsc;
4541 pIB = This->stateBlock->pIndexData;
4542 This->stateBlock->streamIsUP = FALSE;
4544 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This,
4545 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4546 minIndex, NumVertices, startIndex, baseVIndex, primCount);
4548 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4549 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4555 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex,
4556 startIndex, idxStride,
4557 ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory,
4563 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4564 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4565 UINT VertexStreamZeroStride) {
4566 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4568 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4569 debug_d3dprimitivetype(PrimitiveType),
4570 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4572 if (This->stateBlock->streamSource[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
4574 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4575 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4576 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4577 This->stateBlock->streamIsUP = TRUE;
4578 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
4579 This->stateBlock->streamStride[0] = 0;
4580 This->stateBlock->streamSource[0] = NULL;
4582 /*stream zero settings set to null at end, as per the msdn */
4586 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4587 UINT MinVertexIndex,
4588 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
4589 WINED3DFORMAT IndexDataFormat, CONST void* pVertexStreamZeroData,
4590 UINT VertexStreamZeroStride) {
4592 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4594 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4595 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4596 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,
4597 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4599 if (This->stateBlock->streamSource[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
4601 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4607 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4608 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4609 This->stateBlock->streamIsUP = TRUE;
4610 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4612 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, idxStride, pIndexData, MinVertexIndex);
4614 /* stream zero settings set to null at end as per the msdn */
4615 This->stateBlock->streamSource[0] = NULL;
4616 This->stateBlock->streamStride[0] = 0;
4617 IWineD3DDevice_SetIndices(iface, NULL, 0);
4622 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4623 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4625 TRACE("(%p) : stub\n", This);
4629 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4630 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4631 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4632 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4634 TRACE("(%p) : stub\n", This);
4637 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface){
4638 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4640 TRACE("(%p) : stub\n", This);
4644 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface){
4645 IWineD3DSwapChain *swapChain;
4647 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4649 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4650 IWineD3DSwapChain_Release(swapChain);
4655 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4656 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4657 /* return a sensible default */
4659 FIXME("(%p) : stub\n", This);
4663 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4664 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4665 FIXME("(%p) : stub\n", This);
4669 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4670 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4671 FIXME("(%p) : stub\n", This);
4675 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4676 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4677 FIXME("(%p) : stub\n", This);
4681 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4682 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4683 FIXME("(%p) : stub\n", This);
4687 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4688 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4689 FIXME("(%p) : stub\n", This);
4694 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4695 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4696 FIXME("(%p) : stub\n", This);
4701 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
4702 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4704 pRasterStatus->InVBlank = TRUE;
4705 pRasterStatus->ScanLine = 0;
4706 FIXME("(%p) : stub\n", This);
4711 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4712 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4713 static BOOL showfixmes = TRUE;
4714 if(nSegments != 0.0f){
4716 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4723 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4724 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4725 static BOOL showfixmes = TRUE;
4727 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4734 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4735 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4736 FIXME("(%p) : stub\n", This);
4741 /* Implementation details at http://developer.nvidia.com/attach/6494
4743 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
4744 hmm.. no longer supported use
4745 OpenGL evaluators or tessellate surfaces within your application.
4748 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
4749 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo){
4750 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4751 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p) \n", This, Handle, pNumSegs, pRectPatchInfo);
4752 FIXME("(%p) : Stub\n", This);
4757 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
4758 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo){
4759 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4760 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p) \n", This, Handle, pNumSegs, pTriPatchInfo);
4761 FIXME("(%p) : Stub\n", This);
4765 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle){
4766 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4767 TRACE("(%p) Handle(%d)\n", This, Handle);
4768 FIXME("(%p) : Stub\n", This);
4772 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color){
4773 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4775 FIXME("(%p) : stub\n", This);
4779 /* rendertarget and deptth stencil functions */
4780 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget){
4781 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4783 /* FIXME: Implelent RenderTargetIndex >0 */
4784 if(RenderTargetIndex > 0)
4785 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
4787 *ppRenderTarget = (IWineD3DSurface *)This->renderTarget;
4788 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
4789 /* Note inc ref on returned surface */
4790 if(*ppRenderTarget != NULL)
4791 IWineD3DSurface_AddRef(*ppRenderTarget);
4795 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface){
4796 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4797 *ppZStencilSurface = (IWineD3DSurface *)This->depthStencilBuffer;
4798 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
4800 if(*ppZStencilSurface != NULL){
4801 /* Note inc ref on returned surface */
4802 IWineD3DSurface_AddRef(*ppZStencilSurface);
4807 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget){
4808 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4810 FIXME("(%p) : stub\n", This);
4814 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil){
4815 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4817 FIXME("(%p) : stub\n", This);
4821 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
4822 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
4823 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4824 /* TODO: the use of Impl is deprecated. */
4825 /* some basic validation checks */
4826 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
4828 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
4830 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
4831 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
4832 return D3DERR_INVALIDCALL;
4834 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
4835 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
4836 return D3DERR_INVALIDCALL;
4838 /* TODO: make the cursor 'real' */
4840 This->xHotSpot = XHotSpot;
4841 This->yHotSpot = YHotSpot;
4846 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
4847 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4848 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
4850 This->xScreenSpace = XScreenSpace;
4851 This->yScreenSpace = YScreenSpace;
4857 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
4858 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4859 TRACE("(%p) : visible(%d)\n", This, bShow);
4861 This->bCursorVisible = bShow;
4866 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
4867 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4868 FIXME("(%p) : stub\n", This); /* No way of notifying yet! */
4873 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
4874 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4875 /** FIXME: Resource tracking needs to be done,
4876 * The closes we can do to this is set the priorities of all managed textures low
4877 * and then reset them.
4878 ***********************************************************/
4879 FIXME("(%p) : stub\n", This);
4883 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
4884 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4885 /** FIXME: Resource trascking needs to be done.
4886 * in effect this pulls all non only default
4887 * textures out of video memory and deletes all glTextures (glDeleteTextures)
4888 * and should clear down the context and set it up according to pPresentationParameters
4889 ***********************************************************/
4890 FIXME("(%p) : stub\n", This);
4894 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs){
4895 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4896 /** FIXME: always true at the moment **/
4897 if(bEnableDialogs == FALSE){
4898 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
4904 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
4905 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4907 FIXME("(%p) : stub\n", This);
4908 /* Setup some reasonable defaults */
4909 pParameters->AdapterOrdinal = 0; /* always for now */
4910 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
4911 pParameters->hFocusWindow = 0;
4912 pParameters->BehaviorFlags =0;
4916 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
4917 IWineD3DSwapChain *swapchain;
4918 HRESULT hrc = D3D_OK;
4920 TRACE("Relaying to swapchain\n");
4922 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK){
4923 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
4924 IWineD3DSwapChain_Release(swapchain);
4929 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
4930 IWineD3DSwapChain *swapchain;
4931 HRESULT hrc = D3D_OK;
4933 TRACE("Relaying to swapchain\n");
4935 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK){
4936 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
4937 IWineD3DSwapChain_Release(swapchain);
4942 /**********************************************************
4943 * IWineD3DDevice VTbl follows
4944 **********************************************************/
4946 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
4948 /*** IUnknown methods ***/
4949 IWineD3DDeviceImpl_QueryInterface,
4950 IWineD3DDeviceImpl_AddRef,
4951 IWineD3DDeviceImpl_Release,
4952 /*** IWineD3DDevice methods ***/
4953 IWineD3DDeviceImpl_GetParent,
4954 /*** Creation methods**/
4955 IWineD3DDeviceImpl_CreateVertexBuffer,
4956 IWineD3DDeviceImpl_CreateIndexBuffer,
4957 IWineD3DDeviceImpl_CreateStateBlock,
4958 IWineD3DDeviceImpl_CreateSurface,
4959 IWineD3DDeviceImpl_CreateTexture,
4960 IWineD3DDeviceImpl_CreateVolumeTexture,
4961 IWineD3DDeviceImpl_CreateVolume,
4962 IWineD3DDeviceImpl_CreateCubeTexture,
4963 IWineD3DDeviceImpl_CreateQuery,
4964 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
4965 IWineD3DDeviceImpl_CreateVertexDeclaration,
4966 IWineD3DDeviceImpl_CreateVertexShader,
4967 IWineD3DDeviceImpl_CreatePixelShader,
4969 /*** Odd functions **/
4970 IWineD3DDeviceImpl_EvictManagedResources,
4971 IWineD3DDeviceImpl_GetAvailableTextureMem,
4972 IWineD3DDeviceImpl_GetBackBuffer,
4973 IWineD3DDeviceImpl_GetCreationParameters,
4974 IWineD3DDeviceImpl_GetDeviceCaps,
4975 IWineD3DDeviceImpl_GetDirect3D,
4976 IWineD3DDeviceImpl_GetDisplayMode,
4977 IWineD3DDeviceImpl_GetNumberOfSwapChains,
4978 IWineD3DDeviceImpl_GetRasterStatus,
4979 IWineD3DDeviceImpl_GetSwapChain,
4980 IWineD3DDeviceImpl_Reset,
4981 IWineD3DDeviceImpl_SetDialogBoxMode,
4982 IWineD3DDeviceImpl_SetCursorProperties,
4983 IWineD3DDeviceImpl_SetCursorPosition,
4984 IWineD3DDeviceImpl_ShowCursor,
4985 IWineD3DDeviceImpl_TestCooperativeLevel,
4986 /*** Getters and setters **/
4987 IWineD3DDeviceImpl_SetClipPlane,
4988 IWineD3DDeviceImpl_GetClipPlane,
4989 IWineD3DDeviceImpl_SetClipStatus,
4990 IWineD3DDeviceImpl_GetClipStatus,
4991 IWineD3DDeviceImpl_SetCurrentTexturePalette,
4992 IWineD3DDeviceImpl_GetCurrentTexturePalette,
4993 IWineD3DDeviceImpl_SetDepthStencilSurface,
4994 IWineD3DDeviceImpl_GetDepthStencilSurface,
4995 IWineD3DDeviceImpl_SetFVF,
4996 IWineD3DDeviceImpl_GetFVF,
4997 IWineD3DDeviceImpl_SetGammaRamp,
4998 IWineD3DDeviceImpl_GetGammaRamp,
4999 IWineD3DDeviceImpl_SetIndices,
5000 IWineD3DDeviceImpl_GetIndices,
5001 IWineD3DDeviceImpl_SetLight,
5002 IWineD3DDeviceImpl_GetLight,
5003 IWineD3DDeviceImpl_SetLightEnable,
5004 IWineD3DDeviceImpl_GetLightEnable,
5005 IWineD3DDeviceImpl_SetMaterial,
5006 IWineD3DDeviceImpl_GetMaterial,
5007 IWineD3DDeviceImpl_SetNPatchMode,
5008 IWineD3DDeviceImpl_GetNPatchMode,
5009 IWineD3DDeviceImpl_SetPaletteEntries,
5010 IWineD3DDeviceImpl_GetPaletteEntries,
5011 IWineD3DDeviceImpl_SetPixelShader,
5012 IWineD3DDeviceImpl_GetPixelShader,
5013 IWineD3DDeviceImpl_SetPixelShaderConstantB,
5014 IWineD3DDeviceImpl_GetPixelShaderConstantB,
5015 IWineD3DDeviceImpl_SetPixelShaderConstantI,
5016 IWineD3DDeviceImpl_GetPixelShaderConstantI,
5017 IWineD3DDeviceImpl_SetPixelShaderConstantF,
5018 IWineD3DDeviceImpl_GetPixelShaderConstantF,
5019 IWineD3DDeviceImpl_SetRenderState,
5020 IWineD3DDeviceImpl_GetRenderState,
5021 IWineD3DDeviceImpl_SetRenderTarget,
5022 IWineD3DDeviceImpl_GetRenderTarget,
5023 IWineD3DDeviceImpl_SetSamplerState,
5024 IWineD3DDeviceImpl_GetSamplerState,
5025 IWineD3DDeviceImpl_SetScissorRect,
5026 IWineD3DDeviceImpl_GetScissorRect,
5027 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
5028 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
5029 IWineD3DDeviceImpl_SetStreamSource,
5030 IWineD3DDeviceImpl_GetStreamSource,
5031 IWineD3DDeviceImpl_SetStreamSourceFreq,
5032 IWineD3DDeviceImpl_GetStreamSourceFreq,
5033 IWineD3DDeviceImpl_SetTexture,
5034 IWineD3DDeviceImpl_GetTexture,
5035 IWineD3DDeviceImpl_SetTextureStageState,
5036 IWineD3DDeviceImpl_GetTextureStageState,
5037 IWineD3DDeviceImpl_SetTransform,
5038 IWineD3DDeviceImpl_GetTransform,
5039 IWineD3DDeviceImpl_SetVertexDeclaration,
5040 IWineD3DDeviceImpl_GetVertexDeclaration,
5041 IWineD3DDeviceImpl_SetVertexShader,
5042 IWineD3DDeviceImpl_GetVertexShader,
5043 IWineD3DDeviceImpl_SetVertexShaderConstantB,
5044 IWineD3DDeviceImpl_GetVertexShaderConstantB,
5045 IWineD3DDeviceImpl_SetVertexShaderConstantI,
5046 IWineD3DDeviceImpl_GetVertexShaderConstantI,
5047 IWineD3DDeviceImpl_SetVertexShaderConstantF,
5048 IWineD3DDeviceImpl_GetVertexShaderConstantF,
5049 IWineD3DDeviceImpl_SetViewport,
5050 IWineD3DDeviceImpl_GetViewport,
5051 IWineD3DDeviceImpl_MultiplyTransform,
5052 IWineD3DDeviceImpl_ValidateDevice,
5053 IWineD3DDeviceImpl_ProcessVertices,
5054 /*** State block ***/
5055 IWineD3DDeviceImpl_BeginStateBlock,
5056 IWineD3DDeviceImpl_EndStateBlock,
5057 /*** Scene management ***/
5058 IWineD3DDeviceImpl_BeginScene,
5059 IWineD3DDeviceImpl_EndScene,
5060 IWineD3DDeviceImpl_Present,
5061 IWineD3DDeviceImpl_Clear,
5063 IWineD3DDeviceImpl_DrawPrimitive,
5064 IWineD3DDeviceImpl_DrawIndexedPrimitive,
5065 IWineD3DDeviceImpl_DrawPrimitiveUP,
5066 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
5067 IWineD3DDeviceImpl_DrawRectPatch,
5068 IWineD3DDeviceImpl_DrawTriPatch,
5069 IWineD3DDeviceImpl_DeletePatch,
5070 IWineD3DDeviceImpl_ColorFill,
5071 IWineD3DDeviceImpl_UpdateTexture,
5072 IWineD3DDeviceImpl_UpdateSurface,
5073 IWineD3DDeviceImpl_StretchRect,
5074 IWineD3DDeviceImpl_GetRenderTargetData,
5075 IWineD3DDeviceImpl_GetFrontBufferData,
5076 /*** Internal use IWineD3DDevice methods ***/
5077 IWineD3DDeviceImpl_SetupTextureStates
5081 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
5082 WINED3DRS_ALPHABLENDENABLE ,
5083 WINED3DRS_ALPHAFUNC ,
5084 WINED3DRS_ALPHAREF ,
5085 WINED3DRS_ALPHATESTENABLE ,
5087 WINED3DRS_COLORWRITEENABLE ,
5088 WINED3DRS_DESTBLEND ,
5089 WINED3DRS_DITHERENABLE ,
5090 WINED3DRS_FILLMODE ,
5091 WINED3DRS_FOGDENSITY ,
5093 WINED3DRS_FOGSTART ,
5094 WINED3DRS_LASTPIXEL ,
5095 WINED3DRS_SHADEMODE ,
5096 WINED3DRS_SRCBLEND ,
5097 WINED3DRS_STENCILENABLE ,
5098 WINED3DRS_STENCILFAIL ,
5099 WINED3DRS_STENCILFUNC ,
5100 WINED3DRS_STENCILMASK ,
5101 WINED3DRS_STENCILPASS ,
5102 WINED3DRS_STENCILREF ,
5103 WINED3DRS_STENCILWRITEMASK ,
5104 WINED3DRS_STENCILZFAIL ,
5105 WINED3DRS_TEXTUREFACTOR ,
5116 WINED3DRS_ZWRITEENABLE
5119 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
5120 WINED3DTSS_ADDRESSW ,
5121 WINED3DTSS_ALPHAARG0 ,
5122 WINED3DTSS_ALPHAARG1 ,
5123 WINED3DTSS_ALPHAARG2 ,
5124 WINED3DTSS_ALPHAOP ,
5125 WINED3DTSS_BUMPENVLOFFSET ,
5126 WINED3DTSS_BUMPENVLSCALE ,
5127 WINED3DTSS_BUMPENVMAT00 ,
5128 WINED3DTSS_BUMPENVMAT01 ,
5129 WINED3DTSS_BUMPENVMAT10 ,
5130 WINED3DTSS_BUMPENVMAT11 ,
5131 WINED3DTSS_COLORARG0 ,
5132 WINED3DTSS_COLORARG1 ,
5133 WINED3DTSS_COLORARG2 ,
5134 WINED3DTSS_COLOROP ,
5135 WINED3DTSS_RESULTARG ,
5136 WINED3DTSS_TEXCOORDINDEX ,
5137 WINED3DTSS_TEXTURETRANSFORMFLAGS
5140 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
5141 WINED3DSAMP_ADDRESSU ,
5142 WINED3DSAMP_ADDRESSV ,
5143 WINED3DSAMP_ADDRESSW ,
5144 WINED3DSAMP_BORDERCOLOR ,
5145 WINED3DSAMP_MAGFILTER ,
5146 WINED3DSAMP_MINFILTER ,
5147 WINED3DSAMP_MIPFILTER ,
5148 WINED3DSAMP_MIPMAPLODBIAS ,
5149 WINED3DSAMP_MAXMIPLEVEL ,
5150 WINED3DSAMP_MAXANISOTROPY ,
5151 WINED3DSAMP_SRGBTEXTURE ,
5152 WINED3DSAMP_ELEMENTINDEX
5155 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
5157 WINED3DRS_AMBIENTMATERIALSOURCE ,
5158 WINED3DRS_CLIPPING ,
5159 WINED3DRS_CLIPPLANEENABLE ,
5160 WINED3DRS_COLORVERTEX ,
5161 WINED3DRS_DIFFUSEMATERIALSOURCE ,
5162 WINED3DRS_EMISSIVEMATERIALSOURCE ,
5163 WINED3DRS_FOGDENSITY ,
5165 WINED3DRS_FOGSTART ,
5166 WINED3DRS_FOGTABLEMODE ,
5167 WINED3DRS_FOGVERTEXMODE ,
5168 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
5169 WINED3DRS_LIGHTING ,
5170 WINED3DRS_LOCALVIEWER ,
5171 WINED3DRS_MULTISAMPLEANTIALIAS ,
5172 WINED3DRS_MULTISAMPLEMASK ,
5173 WINED3DRS_NORMALIZENORMALS ,
5174 WINED3DRS_PATCHEDGESTYLE ,
5175 WINED3DRS_POINTSCALE_A ,
5176 WINED3DRS_POINTSCALE_B ,
5177 WINED3DRS_POINTSCALE_C ,
5178 WINED3DRS_POINTSCALEENABLE ,
5179 WINED3DRS_POINTSIZE ,
5180 WINED3DRS_POINTSIZE_MAX ,
5181 WINED3DRS_POINTSIZE_MIN ,
5182 WINED3DRS_POINTSPRITEENABLE ,
5183 WINED3DRS_RANGEFOGENABLE ,
5184 WINED3DRS_SPECULARMATERIALSOURCE ,
5185 WINED3DRS_TWEENFACTOR ,
5186 WINED3DRS_VERTEXBLEND
5189 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
5190 WINED3DTSS_TEXCOORDINDEX ,
5191 WINED3DTSS_TEXTURETRANSFORMFLAGS
5194 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
5195 WINED3DSAMP_DMAPOFFSET