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 object was created via a callback
303 ** ***************************/
305 IUnknown* swapChainParent;
307 /* Release all of the swapchains, except the implicit 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 its 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 implicit 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 kludging 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) {
553 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
554 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
555 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
556 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d) \n",
557 This, Width, Height);
558 return D3DERR_NOTAVAILABLE;
562 /** TODO: Check against the maximum texture sizes supported by the video card **/
564 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,D3DRTYPE_SURFACE)
565 object->container = (IUnknown*) This;
567 object->currentDesc.Width = Width;
568 object->currentDesc.Height = Height;
569 object->currentDesc.MultiSampleType = MultiSample;
570 object->currentDesc.MultiSampleQuality = MultisampleQuality;
572 /* Setup some glformat defaults */
573 object->glDescription.glFormat = D3DFmt2GLFmt(This, object->resource.format);
574 object->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This, object->resource.format);
575 object->glDescription.glType = D3DFmt2GLType(This, object->resource.format);
576 object->glDescription.textureName = 0;
577 object->glDescription.level = Level;
578 object->glDescription.target = GL_TEXTURE_2D;
581 object->pow2Width = pow2Width;
582 object->pow2Height = pow2Height;
583 object->nonpow2 = (pow2Width != Width || pow2Height != Height) ? TRUE : FALSE;
584 object->discard = Discard;
585 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
586 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
588 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
590 /* Precalculated scaling for 'faked' non power of two texture coords */
591 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
592 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
593 TRACE(" xf(%f) yf(%f) \n", object->pow2scalingFactorX, object->pow2scalingFactorY);
595 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
596 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
598 *********************************/
599 if (Format == WINED3DFMT_DXT1) {
600 /* DXT1 is half byte per pixel */
601 object->resource.size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4)) / 2;
603 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
604 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
605 object->resource.size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4));
607 object->resource.size = (Width * object->bytesPerPixel) * Height;
610 TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
613 /* TODO: Check that we have enough video ram left */
614 if(Pool == D3DPOOL_DEFAULT && IWineD3DDevice_GetAvailableTextureMem(iface) <= object->currentDesc.Size){
615 TRACE("Out of 'bogus' video memory\n");
616 HeapFree(GetProcessHeap(),0,object);
618 return D3DERR_OUTOFVIDEOMEMORY;
622 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
623 * this function is too deap to need to care about things like this.
624 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
625 * ****************************************/
627 case D3DPOOL_SCRATCH:
628 if(Lockable == FALSE)
629 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
630 which are mutually exclusive, setting lockable to true\n");
633 case D3DPOOL_SYSTEMMEM:
634 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
635 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
636 case D3DPOOL_MANAGED:
637 if(Usage == D3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
638 Usage of DYNAMIC which are mutually exclusive, not doing \
639 anything just telling you.\n");
641 case D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
642 if(!(Usage & D3DUSAGE_DYNAMIC) && !(Usage & D3DUSAGE_RENDERTARGET)
643 && !(Usage && D3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
644 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
647 FIXME("(%p) Unknown pool %d\n", This, Pool);
651 if (Usage & D3DUSAGE_RENDERTARGET && Pool != D3DPOOL_DEFAULT){
652 FIXME("Trying to create a render target that isn't in the default pool\n");
656 object->locked = FALSE;
657 object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
658 /* TODO: memory management */
659 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
660 if(object->resource.allocatedMemory == NULL ) {
661 FIXME("Out of memory!\n");
662 HeapFree(GetProcessHeap(),0,object);
664 return D3DERR_OUTOFVIDEOMEMORY;
667 /* mark the texture as dirty so that it get's loaded first time around*/
668 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
669 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
670 This, Width, Height, Format, debug_d3dformat(Format),
671 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
676 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
677 DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool,
678 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
679 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
681 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
682 IWineD3DTextureImpl *object;
688 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) .... \n", This, Width, Height, Levels, Usage);
690 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_TEXTURE);
691 D3DINITILIZEBASETEXTURE(object->baseTexture);
692 object->width = Width;
693 object->height = Height;
695 /* Calculate levels for mip mapping */
697 TRACE("calculating levels %d\n", object->baseTexture.levels);
698 object->baseTexture.levels++;
701 while (tmpW > 1 && tmpH > 1) {
702 tmpW = max(1, tmpW >> 1);
703 tmpH = max(1, tmpH >> 1);
704 object->baseTexture.levels++;
706 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
709 /* Generate all the surfaces */
712 for (i = 0; i < object->baseTexture.levels; i++)
714 /* use the callback to create the texture surface */
715 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
718 FIXME("Failed to create surface %p \n",object);
721 IWineD3DSurface_Release(object->surfaces[j]);
723 /* heap free object */
724 HeapFree(GetProcessHeap(),0,object);
730 IWineD3DSurface_SetContainer(object->surfaces[i], (IUnknown *)object);
731 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
732 /* calculate the next mipmap level */
733 tmpW = max(1, tmpW >> 1);
734 tmpH = max(1, tmpH >> 1);
737 TRACE("(%p) : Created texture %p\n", This, object);
741 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
742 UINT Width, UINT Height, UINT Depth,
743 UINT Levels, DWORD Usage,
744 WINED3DFORMAT Format, D3DPOOL Pool,
745 IWineD3DVolumeTexture** ppVolumeTexture,
746 HANDLE* pSharedHandle, IUnknown *parent,
747 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
749 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
750 IWineD3DVolumeTextureImpl *object;
756 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_VOLUMETEXTURE);
757 D3DINITILIZEBASETEXTURE(object->baseTexture);
759 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
760 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
762 object->width = Width;
763 object->height = Height;
764 object->depth = Depth;
766 /* Calculate levels for mip mapping */
768 object->baseTexture.levels++;
772 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
773 tmpW = max(1, tmpW >> 1);
774 tmpH = max(1, tmpH >> 1);
775 tmpD = max(1, tmpD >> 1);
776 object->baseTexture.levels++;
778 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
781 /* Generate all the surfaces */
786 for (i = 0; i < object->baseTexture.levels; i++)
788 /* Create the volume */
789 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
790 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
791 IWineD3DVolume_SetContainer(object->volumes[i], (IUnknown *)object);
793 tmpW = max(1, tmpW >> 1);
794 tmpH = max(1, tmpH >> 1);
795 tmpD = max(1, tmpD >> 1);
798 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
799 TRACE("(%p) : Created volume texture %p\n", This, object);
803 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
804 UINT Width, UINT Height, UINT Depth,
806 WINED3DFORMAT Format, D3DPOOL Pool,
807 IWineD3DVolume** ppVolume,
808 HANDLE* pSharedHandle, IUnknown *parent) {
810 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
811 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
813 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, D3DRTYPE_VOLUME)
815 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
816 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
818 object->currentDesc.Width = Width;
819 object->currentDesc.Height = Height;
820 object->currentDesc.Depth = Depth;
821 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
823 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
824 object->resource.size = (Width * object->bytesPerPixel) * Height * Depth;
825 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
826 object->lockable = TRUE;
827 object->locked = FALSE;
828 memset(&object->lockedBox, 0, sizeof(D3DBOX));
829 object->dirty = FALSE;
830 return IWineD3DVolume_CleanDirtyBox((IWineD3DVolume *) object);
833 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
834 UINT Levels, DWORD Usage,
835 WINED3DFORMAT Format, D3DPOOL Pool,
836 IWineD3DCubeTexture** ppCubeTexture,
837 HANDLE* pSharedHandle, IUnknown *parent,
838 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
840 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
841 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
846 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE);
847 D3DINITILIZEBASETEXTURE(object->baseTexture);
849 TRACE("(%p) Create Cube Texture \n", This);
851 object->edgeLength = EdgeLength;
853 /* Calculate levels for mip mapping */
855 object->baseTexture.levels++;
858 tmpW = max(1, tmpW / 2);
859 object->baseTexture.levels++;
861 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
864 /* Generate all the surfaces */
866 for (i = 0; i < object->baseTexture.levels; i++) {
868 /* Create the 6 faces */
869 for (j = 0; j < 6; j++) {
871 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
872 i /* Level */, &object->surfaces[j][i],pSharedHandle);
879 IWineD3DSurface_Release(object->surfaces[j][i]);
883 IWineD3DSurface_Release(object->surfaces[l][j]);
887 FIXME("(%p) Failed to create surface\n",object);
888 HeapFree(GetProcessHeap(),0,object);
889 *ppCubeTexture = NULL;
892 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IUnknown *)object);
893 TRACE("Created surface level %d @ %p, \n", i, object->surfaces[j][i]);
895 tmpW = max(1, tmpW >> 1);
898 TRACE("(%p) : Created Cube Texture %p\n", This, object);
899 *ppCubeTexture = (IWineD3DCubeTexture *) object;
903 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent){
904 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
905 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
908 /* Just a check to see if we support this type of query */
909 HRESULT hr = D3DERR_NOTAVAILABLE;
910 /* Lie and say everything is good (we can return ok fake data from a stub) */
912 case WINED3DQUERYTYPE_VCACHE:
913 case WINED3DQUERYTYPE_RESOURCEMANAGER:
914 case WINED3DQUERYTYPE_VERTEXSTATS:
915 case WINED3DQUERYTYPE_EVENT:
916 case WINED3DQUERYTYPE_OCCLUSION:
917 case WINED3DQUERYTYPE_TIMESTAMP:
918 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
919 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
920 case WINED3DQUERYTYPE_PIPELINETIMINGS:
921 case WINED3DQUERYTYPE_INTERFACETIMINGS:
922 case WINED3DQUERYTYPE_VERTEXTIMINGS:
923 case WINED3DQUERYTYPE_PIXELTIMINGS:
924 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
925 case WINED3DQUERYTYPE_CACHEUTILIZATION:
929 FIXME("(%p) Unhandled query type %d\n",This , Type);
931 FIXME("(%p) : Stub request for query type %d returned %ld\n", This, Type, hr);
935 D3DCREATEOBJECTINSTANCE(object, Query)
937 object->extendedData = 0;
938 TRACE("(%p) : Created Query %p\n", This, object);
942 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
943 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
945 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
946 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil){
947 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
950 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
952 XVisualInfo template;
953 GLXContext oldContext;
954 Drawable oldDrawable;
957 TRACE("(%p) : Created Aditional Swap Chain\n", This);
959 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
960 * does a device hold a reference to a swap chain giving them a lifetime of the device
961 * or does the swap chain notify the device of it'd destruction.
962 *******************************/
964 D3DCREATEOBJECTINSTANCE(object, SwapChain)
966 /* Initialize other useful values */
967 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
969 /*********************
970 * Lookup the window Handle and the relating X window handle
971 ********************/
973 /* Setup hwnd we are using, plus which display this equates to */
974 object->win_handle = *(pPresentationParameters->hDeviceWindow);
975 if (!object->win_handle) {
976 object->win_handle = This->createParms.hFocusWindow;
979 object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window" );
980 hDc = GetDC(object->win_handle);
981 object->display = get_display(hDc);
982 ReleaseDC(object->win_handle, hDc);
983 TRACE("Using a display of %p %p \n", object->display, hDc);
985 if (NULL == object->display || NULL == hDc) {
986 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
987 return D3DERR_NOTAVAILABLE;
990 if (object->win == 0) {
991 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
992 return D3DERR_NOTAVAILABLE;
995 * Create an opengl context for the display visual
996 * NOTE: the visual is chosen as the window is created and the glcontext cannot
997 * use different properties after that point in time. FIXME: How to handle when requested format
998 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
999 * it chooses is identical to the one already being used!
1000 **********************************/
1002 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1005 /* Create a new context for this swapchain */
1006 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1007 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1008 (or the best possible if none is requested) */
1009 TRACE("Found x visual ID : %ld\n", template.visualid);
1011 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1012 if (NULL == object->visInfo) {
1013 ERR("cannot really get XVisual\n");
1015 return D3DERR_NOTAVAILABLE;
1018 /* Write out some debug info about the visual/s */
1019 TRACE("Using x visual ID : %ld\n", template.visualid);
1020 TRACE(" visual info: %p\n", object->visInfo);
1021 TRACE(" num items : %d\n", num);
1022 for(n = 0;n < num; n++){
1023 TRACE("=====item=====: %d\n", n + 1);
1024 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1025 TRACE(" screen : %d\n", object->visInfo[n].screen);
1026 TRACE(" depth : %u\n", object->visInfo[n].depth);
1027 TRACE(" class : %d\n", object->visInfo[n].class);
1028 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1029 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1030 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1031 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1032 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1033 /* log some extra glx info */
1034 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1035 TRACE(" gl_aux_buffers : %d\n", value);
1036 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1037 TRACE(" gl_buffer_size : %d\n", value);
1038 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1039 TRACE(" gl_red_size : %d\n", value);
1040 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1041 TRACE(" gl_green_size : %d\n", value);
1042 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1043 TRACE(" gl_blue_size : %d\n", value);
1044 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1045 TRACE(" gl_alpha_size : %d\n", value);
1046 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1047 TRACE(" gl_depth_size : %d\n", value);
1048 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1049 TRACE(" gl_stencil_size : %d\n", value);
1051 /* Now choose a simila visual ID*/
1053 #ifdef USE_CONTEXT_MANAGER
1055 /** TODO: use a context mamager **/
1059 IWineD3DSwapChain *implSwapChain;
1060 if (D3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1061 /* The first time around we create the context that is shared with all other swapchains and render targets */
1062 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1063 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1066 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1067 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1068 /* and create a new context with the implicit swapchains context as the shared context */
1069 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1070 IWineD3DSwapChain_Release(implSwapChain);
1075 XFree(object->visInfo);
1076 object->visInfo = NULL;
1078 if (NULL == object->glCtx) {
1079 ERR("cannot create glxContext\n");
1081 return D3DERR_NOTAVAILABLE;
1085 if (object->glCtx == NULL) {
1086 ERR("Error in context creation !\n");
1087 return D3DERR_INVALIDCALL;
1089 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1090 object->win_handle, object->glCtx, object->win, object->visInfo);
1093 /*********************
1094 * Windowed / Fullscreen
1095 *******************/
1098 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1099 * so we should really check to see if their is a fullscreen swapchain already
1100 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1101 **************************************/
1103 if (!*(pPresentationParameters->Windowed)) {
1109 /* Get info on the current display setup */
1110 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1111 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1114 /* Change the display settings */
1115 memset(&devmode, 0, sizeof(DEVMODEW));
1116 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1117 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1118 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1119 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1120 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1121 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1123 /* Make popup window */
1124 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1125 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1126 *(pPresentationParameters->BackBufferWidth),
1127 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1133 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1134 * then the corresponding dimension of the client area of the hDeviceWindow
1135 * (or the focus window, if hDeviceWindow is NULL) is taken.
1136 **********************/
1138 if (*(pPresentationParameters->Windowed) &&
1139 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1140 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1143 GetClientRect(object->win_handle, &Rect);
1145 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1146 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1147 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1149 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1150 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1151 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1155 /*********************
1156 * finish off parameter initialization
1157 *******************/
1159 /* Put the correct figures in the presentation parameters */
1160 TRACE("Coppying accross presentaion paraneters\n");
1161 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1162 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1163 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1164 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1165 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1166 object->presentParms.MultiSampleQuality = *(pPresentationParameters->MultiSampleQuality);
1167 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1168 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1169 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1170 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1171 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1172 object->presentParms.Flags = *(pPresentationParameters->Flags);
1173 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1174 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1177 /* FIXME: check for any failures */
1178 /*********************
1179 * Create the back, front and stencil buffers
1180 *******************/
1181 TRACE("calling rendertarget CB\n");
1182 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1183 object->presentParms.BackBufferWidth,
1184 object->presentParms.BackBufferHeight,
1185 object->presentParms.BackBufferFormat,
1186 object->presentParms.MultiSampleType,
1187 object->presentParms.MultiSampleQuality,
1188 TRUE /* Lockable */,
1189 &object->frontBuffer,
1190 NULL /* pShared (always null)*/);
1191 if (object->frontBuffer != NULL)
1192 IWineD3DSurface_SetContainer(object->frontBuffer, (IUnknown *)object);
1193 TRACE("calling rendertarget CB\n");
1194 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1195 object->presentParms.BackBufferWidth,
1196 object->presentParms.BackBufferHeight,
1197 object->presentParms.BackBufferFormat,
1198 object->presentParms.MultiSampleType,
1199 object->presentParms.MultiSampleQuality,
1200 TRUE /* Lockable */,
1201 &object->backBuffer,
1202 NULL /* pShared (always null)*/);
1203 if (object->backBuffer != NULL)
1204 IWineD3DSurface_SetContainer(object->backBuffer, (IUnknown *)object);
1206 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1207 if (pPresentationParameters->EnableAutoDepthStencil) {
1208 TRACE("Creating depth stencil buffer\n");
1209 if (This->depthStencilBuffer == NULL ) {
1210 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1211 object->presentParms.BackBufferWidth,
1212 object->presentParms.BackBufferHeight,
1213 object->presentParms.AutoDepthStencilFormat,
1214 object->presentParms.MultiSampleType,
1215 object->presentParms.MultiSampleQuality,
1216 FALSE /* FIXME: Discard */,
1217 &This->depthStencilBuffer,
1218 NULL /* pShared (always null)*/ );
1219 if (This->depthStencilBuffer != NULL)
1220 IWineD3DSurface_SetContainer(This->depthStencilBuffer, (IUnknown *)iface);
1223 /** TODO: A check on width, height and multisample types
1224 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1225 ****************************/
1226 object->wantsDepthStencilBuffer = TRUE;
1228 object->wantsDepthStencilBuffer = FALSE;
1231 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1234 /*********************
1235 * init the default renderTarget management
1236 *******************/
1237 object->drawable = object->win;
1238 object->render_ctx = object->glCtx;
1241 /*********************
1242 * Setup some defaults and clear down the buffers
1243 *******************/
1245 /** save current context and drawable **/
1246 oldContext = glXGetCurrentContext();
1247 oldDrawable = glXGetCurrentDrawable();
1249 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1250 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1251 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1253 checkGLcall("glXMakeCurrent");
1255 TRACE("Setting up the screen\n");
1256 /* Clear the screen */
1257 glClearColor(0.0, 0.0, 0.0, 0.0);
1258 checkGLcall("glClearColor");
1261 glClearStencil(0xffff);
1263 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1264 checkGLcall("glClear");
1266 glColor3f(1.0, 1.0, 1.0);
1267 checkGLcall("glColor3f");
1269 glEnable(GL_LIGHTING);
1270 checkGLcall("glEnable");
1272 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1273 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1275 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1276 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1278 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1279 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1281 /* switch back to the original context (unless it was zero)*/
1282 if (This->numberOfSwapChains != 0) {
1283 /** TODO: restore the context and drawable **/
1284 glXMakeCurrent(object->display, oldDrawable, oldContext);
1289 /* TODO: move this off into a linked list implementation! (add swapchain, remove swapchain or something along those lines) */
1291 IListOperator *listOperator;
1292 IListStore_CreateListOperator(This->swapchainStore, &listOperator);
1293 IListOperator_Append(listOperator, (void *)object);
1294 IListOperator_Release(listOperator);
1297 This->swapchains[This->numberOfSwapChains++] = (IWineD3DSwapChain *)object;
1298 TRACE("Set swapchain to %p\n", object);
1299 } else { /* something went wrong so clean up */
1300 IUnknown* bufferParent;
1301 if (object->frontBuffer) {
1302 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1303 IUnknown_Release(bufferParent); /* once for the get parent */
1304 if(IUnknown_Release(bufferParent) > 0){
1305 FIXME("(%p) Something's still holding the front buffer\n",This);
1308 if (object->backBuffer) {
1309 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1310 IUnknown_Release(bufferParent); /* once for the get parent */
1311 if(IUnknown_Release(bufferParent) > 0){
1312 FIXME("(%p) Something's still holding the back buffer\n",This);
1315 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1316 /* Clean up the context */
1317 /* check that we are the current context first (we shouldn't be though!) */
1318 if (object->glCtx != 0) {
1319 if(glXGetCurrentContext() == object->glCtx){
1320 glXMakeCurrent(object->display, None, NULL);
1322 glXDestroyContext(object->display, object->glCtx);
1324 HeapFree(GetProcessHeap(), 0, object);
1330 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1331 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1332 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1334 /* TODO: move over to using a linked list. */
1335 TRACE("(%p) returning %d\n", This, This->numberOfSwapChains);
1336 return This->numberOfSwapChains;
1339 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1340 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1341 TRACE("(%p) : swapchain %d \n", This, iSwapChain);
1343 if(iSwapChain >= IWineD3DDeviceImpl_GetNumberOfSwapChains(iface) || iSwapChain < 0){
1345 return D3DERR_INVALIDCALL;
1347 /** TODO: move off to a linked list implementation **/
1348 *pSwapChain = This->swapchains[iSwapChain];
1351 /* TODO: move over to using stores and linked lists. */
1353 IWineD3DSwapChain_AddRef(*pSwapChain);
1354 TRACE("(%p) returning %p\n", This, *pSwapChain);
1358 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters){
1359 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1361 FIXME("(%p) : Stub\n",This);
1367 * Vertex Declaration
1369 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1370 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1371 IWineD3DVertexDeclarationImpl *object = NULL;
1372 HRESULT hr = D3D_OK;
1373 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1374 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1377 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1382 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1383 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DVertexShader** ppVertexShader, IUnknown *parent){
1384 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1385 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1386 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1387 object->function = pFunction;
1388 FIXME("(%p) : STUB: Created Vertex shader %p\n", This, ppVertexShader);
1393 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DPixelShader** ppPixelShader, IUnknown *parent){
1394 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1395 FIXME("(%p) : Stub\n", This);
1399 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice* iface, IWineD3D** ppD3D){
1400 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1401 *ppD3D= This->wineD3D;
1402 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1403 IWineD3D_AddRef(*ppD3D);
1408 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1409 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1410 FIXME("Stub :(%p) returning 64Mib\n", This);
1411 return 64*1024*1024;
1418 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1419 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1421 /* Update the current state block */
1422 This->updateStateBlock->fvf = fvf;
1423 This->updateStateBlock->changed.fvf = TRUE;
1424 This->updateStateBlock->set.fvf = TRUE;
1426 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1427 /* clear down the vertex declaration
1428 NOTE: Axis and Allies doesn't work properly otherwise
1429 (may be a stateblock problem though!)
1431 /* No difference if recording or not */
1432 return IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1437 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1438 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1439 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1440 *pfvf = This->stateBlock->fvf;
1445 * Get / Set Stream Source
1447 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1448 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1449 IWineD3DVertexBuffer *oldSrc;
1451 oldSrc = This->stateBlock->streamSource[StreamNumber];
1452 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1454 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1455 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1456 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1457 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1458 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1460 /* Handle recording of state blocks */
1461 if (This->isRecordingState) {
1462 TRACE("Recording... not performing anything\n");
1466 /* Not recording... */
1467 if (oldSrc != NULL) IWineD3DVertexBuffer_Release(oldSrc);
1468 if (pStreamData != NULL) IWineD3DVertexBuffer_AddRef(pStreamData);
1473 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1474 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1476 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1477 *pStream = This->stateBlock->streamSource[StreamNumber];
1478 *pStride = This->stateBlock->streamStride[StreamNumber];
1479 *pOffset = This->stateBlock->streamOffset[StreamNumber];
1480 if (*pStream != NULL) IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1484 /*Should be quite easy, just an extension of vertexdata
1486 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1488 The divider is a bit odd though
1490 VertexOffset = StartVertex / Divider * StreamStride +
1491 VertexIndex / Divider * StreamStride + StreamOffset
1494 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider){
1495 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1497 FIXME("(%p) : stub\n", This);
1501 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider){
1502 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1504 FIXME("(%p) : stub\n", This);
1510 * Get / Set & Multiply Transform
1512 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1513 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1515 /* Most of this routine, comments included copied from ddraw tree initially: */
1516 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1518 /* Handle recording of state blocks */
1519 if (This->isRecordingState) {
1520 TRACE("Recording... not performing anything\n");
1521 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1522 This->updateStateBlock->set.transform[d3dts] = TRUE;
1523 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1528 * If the new matrix is the same as the current one,
1529 * we cut off any further processing. this seems to be a reasonable
1530 * optimization because as was noticed, some apps (warcraft3 for example)
1531 * tend towards setting the same matrix repeatedly for some reason.
1533 * From here on we assume that the new matrix is different, wherever it matters.
1535 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1536 TRACE("The app is setting the same matrix over again\n");
1539 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1543 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1544 where ViewMat = Camera space, WorldMat = world space.
1546 In OpenGL, camera and world space is combined into GL_MODELVIEW
1547 matrix. The Projection matrix stay projection matrix.
1550 /* Capture the times we can just ignore the change for now */
1551 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1552 This->modelview_valid = FALSE;
1555 } else if (d3dts == D3DTS_PROJECTION) {
1556 This->proj_valid = FALSE;
1559 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1560 /* Indexed Vertex Blending Matrices 256 -> 511 */
1561 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1562 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1566 /* Now we really are going to have to change a matrix */
1569 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1570 if (d3dts < GL_LIMITS(textures)) {
1571 int tex = d3dts - D3DTS_TEXTURE0;
1572 GLACTIVETEXTURE(tex);
1573 set_texture_matrix((float *)lpmatrix,
1574 This->updateStateBlock->textureState[tex][WINED3DTSS_TEXTURETRANSFORMFLAGS]);
1577 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1580 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1581 * NOTE: We have to reset the positions even if the light/plane is not currently
1582 * enabled, since the call to enable it will not reset the position.
1583 * NOTE2: Apparently texture transforms do NOT need reapplying
1586 PLIGHTINFOEL *lightChain = NULL;
1587 This->modelview_valid = FALSE;
1588 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1590 glMatrixMode(GL_MODELVIEW);
1591 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1593 glLoadMatrixf((float *)lpmatrix);
1594 checkGLcall("glLoadMatrixf(...)");
1597 lightChain = This->stateBlock->lights;
1598 while (lightChain && lightChain->glIndex != -1) {
1599 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1600 checkGLcall("glLightfv posn");
1601 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1602 checkGLcall("glLightfv dirn");
1603 lightChain = lightChain->next;
1606 /* Reset Clipping Planes if clipping is enabled */
1607 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1608 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1609 checkGLcall("glClipPlane");
1613 } else { /* What was requested!?? */
1614 WARN("invalid matrix specified: %i\n", d3dts);
1617 /* Release lock, all done */
1622 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1623 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1624 TRACE("(%p) : for Transform State %d\n", This, State);
1625 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1629 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1630 D3DMATRIX *mat = NULL;
1633 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1634 * below means it will be recorded in a state block change, but it
1635 * works regardless where it is recorded.
1636 * If this is found to be wrong, change to StateBlock.
1638 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1639 TRACE("(%p) : For state %u\n", This, State);
1641 if (State < HIGHEST_TRANSFORMSTATE)
1643 mat = &This->updateStateBlock->transforms[State];
1645 FIXME("Unhandled transform state!!\n");
1648 /* Copied from ddraw code: */
1649 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);
1650 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);
1651 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);
1652 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);
1654 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);
1655 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);
1656 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);
1657 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);
1659 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);
1660 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);
1661 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);
1662 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);
1664 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);
1665 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);
1666 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);
1667 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);
1669 /* Apply change via set transform - will reapply to eg. lights this way */
1670 IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
1676 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
1678 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1679 you can reference any indexes you want as long as that number max are enabled at any
1680 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1681 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1682 but when recording, just build a chain pretty much of commands to be replayed. */
1684 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
1686 PLIGHTINFOEL *object, *temp;
1688 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1689 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1691 /* If recording state block, just add to end of lights chain */
1692 if (This->isRecordingState) {
1693 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1694 if (NULL == object) {
1695 return D3DERR_OUTOFVIDEOMEMORY;
1697 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1698 object->OriginalIndex = Index;
1699 object->glIndex = -1;
1700 object->changed = TRUE;
1702 /* Add to the END of the chain of lights changes to be replayed */
1703 if (This->updateStateBlock->lights == NULL) {
1704 This->updateStateBlock->lights = object;
1706 temp = This->updateStateBlock->lights;
1707 while (temp->next != NULL) temp=temp->next;
1708 temp->next = object;
1710 TRACE("Recording... not performing anything more\n");
1714 /* Ok, not recording any longer so do real work */
1715 object = This->stateBlock->lights;
1716 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1718 /* If we didn't find it in the list of lights, time to add it */
1719 if (object == NULL) {
1720 PLIGHTINFOEL *insertAt,*prevPos;
1722 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1723 if (NULL == object) {
1724 return D3DERR_OUTOFVIDEOMEMORY;
1726 object->OriginalIndex = Index;
1727 object->glIndex = -1;
1729 /* Add it to the front of list with the idea that lights will be changed as needed
1730 BUT after any lights currently assigned GL indexes */
1731 insertAt = This->stateBlock->lights;
1733 while (insertAt != NULL && insertAt->glIndex != -1) {
1735 insertAt = insertAt->next;
1738 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1739 This->stateBlock->lights = object;
1740 } else if (insertAt == NULL) { /* End of list */
1741 prevPos->next = object;
1742 object->prev = prevPos;
1743 } else { /* Middle of chain */
1744 if (prevPos == NULL) {
1745 This->stateBlock->lights = object;
1747 prevPos->next = object;
1749 object->prev = prevPos;
1750 object->next = insertAt;
1751 insertAt->prev = object;
1755 /* Initialze the object */
1756 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,
1757 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1758 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1759 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1760 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1761 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1762 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1764 /* Save away the information */
1765 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1767 switch (pLight->Type) {
1768 case D3DLIGHT_POINT:
1770 object->lightPosn[0] = pLight->Position.x;
1771 object->lightPosn[1] = pLight->Position.y;
1772 object->lightPosn[2] = pLight->Position.z;
1773 object->lightPosn[3] = 1.0f;
1774 object->cutoff = 180.0f;
1778 case D3DLIGHT_DIRECTIONAL:
1780 object->lightPosn[0] = -pLight->Direction.x;
1781 object->lightPosn[1] = -pLight->Direction.y;
1782 object->lightPosn[2] = -pLight->Direction.z;
1783 object->lightPosn[3] = 0.0;
1784 object->exponent = 0.0f;
1785 object->cutoff = 180.0f;
1790 object->lightPosn[0] = pLight->Position.x;
1791 object->lightPosn[1] = pLight->Position.y;
1792 object->lightPosn[2] = pLight->Position.z;
1793 object->lightPosn[3] = 1.0;
1796 object->lightDirn[0] = pLight->Direction.x;
1797 object->lightDirn[1] = pLight->Direction.y;
1798 object->lightDirn[2] = pLight->Direction.z;
1799 object->lightDirn[3] = 1.0;
1802 * opengl-ish and d3d-ish spot lights use too different models for the
1803 * light "intensity" as a function of the angle towards the main light direction,
1804 * so we only can approximate very roughly.
1805 * however spot lights are rather rarely used in games (if ever used at all).
1806 * furthermore if still used, probably nobody pays attention to such details.
1808 if (pLight->Falloff == 0) {
1811 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1813 if (rho < 0.0001) rho = 0.0001f;
1814 object->exponent = -0.3/log(cos(rho/2));
1815 object->cutoff = pLight->Phi*90/M_PI;
1821 FIXME("Unrecognized light type %d\n", pLight->Type);
1824 /* Update the live definitions if the light is currently assigned a glIndex */
1825 if (object->glIndex != -1) {
1826 setup_light(iface, object->glIndex, object);
1831 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
1832 PLIGHTINFOEL *lightInfo = NULL;
1833 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1834 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1836 /* Locate the light in the live lights */
1837 lightInfo = This->stateBlock->lights;
1838 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1840 if (lightInfo == NULL) {
1841 TRACE("Light information requested but light not defined\n");
1842 return D3DERR_INVALIDCALL;
1845 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
1850 * Get / Set Light Enable
1851 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
1853 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
1854 PLIGHTINFOEL *lightInfo = NULL;
1855 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1856 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1858 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1859 if (This->isRecordingState) {
1860 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1861 if (NULL == lightInfo) {
1862 return D3DERR_OUTOFVIDEOMEMORY;
1864 lightInfo->OriginalIndex = Index;
1865 lightInfo->glIndex = -1;
1866 lightInfo->enabledChanged = TRUE;
1868 /* Add to the END of the chain of lights changes to be replayed */
1869 if (This->updateStateBlock->lights == NULL) {
1870 This->updateStateBlock->lights = lightInfo;
1872 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
1873 while (temp->next != NULL) temp=temp->next;
1874 temp->next = lightInfo;
1876 TRACE("Recording... not performing anything more\n");
1880 /* Not recording... So, locate the light in the live lights */
1881 lightInfo = This->stateBlock->lights;
1882 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1884 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1885 if (lightInfo == NULL) {
1886 D3DLIGHT9 lightParms;
1887 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1888 wait until someone confirms it seems to work! */
1889 TRACE("Light enabled requested but light not defined, so defining one!\n");
1890 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1891 lightParms.Diffuse.r = 1.0;
1892 lightParms.Diffuse.g = 1.0;
1893 lightParms.Diffuse.b = 1.0;
1894 lightParms.Diffuse.a = 0.0;
1895 lightParms.Specular.r = 0.0;
1896 lightParms.Specular.g = 0.0;
1897 lightParms.Specular.b = 0.0;
1898 lightParms.Specular.a = 0.0;
1899 lightParms.Ambient.r = 0.0;
1900 lightParms.Ambient.g = 0.0;
1901 lightParms.Ambient.b = 0.0;
1902 lightParms.Ambient.a = 0.0;
1903 lightParms.Position.x = 0.0;
1904 lightParms.Position.y = 0.0;
1905 lightParms.Position.z = 0.0;
1906 lightParms.Direction.x = 0.0;
1907 lightParms.Direction.y = 0.0;
1908 lightParms.Direction.z = 1.0;
1909 lightParms.Range = 0.0;
1910 lightParms.Falloff = 0.0;
1911 lightParms.Attenuation0 = 0.0;
1912 lightParms.Attenuation1 = 0.0;
1913 lightParms.Attenuation2 = 0.0;
1914 lightParms.Theta = 0.0;
1915 lightParms.Phi = 0.0;
1916 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
1918 /* Search for it again! Should be fairly quick as near head of list */
1919 lightInfo = This->stateBlock->lights;
1920 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1921 if (lightInfo == NULL) {
1922 FIXME("Adding default lights has failed dismally\n");
1923 return D3DERR_INVALIDCALL;
1927 /* OK, we now have a light... */
1928 if (Enable == FALSE) {
1930 /* If we are disabling it, check it was enabled, and
1931 still only do something if it has assigned a glIndex (which it should have!) */
1932 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
1933 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1935 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1936 checkGLcall("glDisable GL_LIGHT0+Index");
1939 TRACE("Nothing to do as light was not enabled\n");
1941 lightInfo->lightEnabled = FALSE;
1944 /* We are enabling it. If it is enabled, it's really simple */
1945 if (lightInfo->lightEnabled) {
1947 TRACE("Nothing to do as light was enabled\n");
1949 /* If it already has a glIndex, it's still simple */
1950 } else if (lightInfo->glIndex != -1) {
1951 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1952 lightInfo->lightEnabled = TRUE;
1954 glEnable(GL_LIGHT0 + lightInfo->glIndex);
1955 checkGLcall("glEnable GL_LIGHT0+Index already setup");
1958 /* Otherwise got to find space - lights are ordered gl indexes first */
1960 PLIGHTINFOEL *bsf = NULL;
1961 PLIGHTINFOEL *pos = This->stateBlock->lights;
1962 PLIGHTINFOEL *prev = NULL;
1966 /* Try to minimize changes as much as possible */
1967 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
1969 /* Try to remember which index can be replaced if necessary */
1970 if (bsf==NULL && pos->lightEnabled == FALSE) {
1971 /* Found a light we can replace, save as best replacement */
1975 /* Step to next space */
1981 /* If we have too many active lights, fail the call */
1982 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
1983 FIXME("Program requests too many concurrent lights\n");
1984 return D3DERR_INVALIDCALL;
1986 /* If we have allocated all lights, but not all are enabled,
1987 reuse one which is not enabled */
1988 } else if (Index == This->maxConcurrentLights) {
1989 /* use bsf - Simply swap the new light and the BSF one */
1990 PLIGHTINFOEL *bsfNext = bsf->next;
1991 PLIGHTINFOEL *bsfPrev = bsf->prev;
1994 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
1995 if (bsf->prev != NULL) {
1996 bsf->prev->next = lightInfo;
1998 This->stateBlock->lights = lightInfo;
2001 /* If not side by side, lots of chains to update */
2002 if (bsf->next != lightInfo) {
2003 lightInfo->prev->next = bsf;
2004 bsf->next->prev = lightInfo;
2005 bsf->next = lightInfo->next;
2006 bsf->prev = lightInfo->prev;
2007 lightInfo->next = bsfNext;
2008 lightInfo->prev = bsfPrev;
2012 bsf->prev = lightInfo;
2013 bsf->next = lightInfo->next;
2014 lightInfo->next = bsf;
2015 lightInfo->prev = bsfPrev;
2020 glIndex = bsf->glIndex;
2022 lightInfo->glIndex = glIndex;
2023 lightInfo->lightEnabled = TRUE;
2025 /* Finally set up the light in gl itself */
2026 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2028 setup_light(iface, glIndex, lightInfo);
2029 glEnable(GL_LIGHT0 + glIndex);
2030 checkGLcall("glEnable GL_LIGHT0 new setup");
2033 /* If we reached the end of the allocated lights, with space in the
2034 gl lights, setup a new light */
2035 } else if (pos->glIndex == -1) {
2037 /* We reached the end of the allocated gl lights, so already
2038 know the index of the next one! */
2040 lightInfo->glIndex = glIndex;
2041 lightInfo->lightEnabled = TRUE;
2043 /* In an ideal world, it's already in the right place */
2044 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2045 /* No need to move it */
2047 /* Remove this light from the list */
2048 lightInfo->prev->next = lightInfo->next;
2049 if (lightInfo->next != NULL) {
2050 lightInfo->next->prev = lightInfo->prev;
2053 /* Add in at appropriate place (inbetween prev and pos) */
2054 lightInfo->prev = prev;
2055 lightInfo->next = pos;
2057 This->stateBlock->lights = lightInfo;
2059 prev->next = lightInfo;
2062 pos->prev = lightInfo;
2066 /* Finally set up the light in gl itself */
2067 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2069 setup_light(iface, glIndex, lightInfo);
2070 glEnable(GL_LIGHT0 + glIndex);
2071 checkGLcall("glEnable GL_LIGHT0 new setup");
2080 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2082 PLIGHTINFOEL *lightInfo = NULL;
2083 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2084 TRACE("(%p) : for idx(%ld)\n", This, Index);
2086 /* Locate the light in the live lights */
2087 lightInfo = This->stateBlock->lights;
2088 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2090 if (lightInfo == NULL) {
2091 TRACE("Light enabled state requested but light not defined\n");
2092 return D3DERR_INVALIDCALL;
2094 *pEnable = lightInfo->lightEnabled;
2099 * Get / Set Clip Planes
2101 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2102 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2103 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2105 /* Validate Index */
2106 if (Index >= GL_LIMITS(clipplanes)) {
2107 TRACE("Application has requested clipplane this device doesn't support\n");
2108 return D3DERR_INVALIDCALL;
2111 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2112 This->updateStateBlock->set.clipplane[Index] = TRUE;
2113 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2114 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2115 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2116 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2118 /* Handle recording of state blocks */
2119 if (This->isRecordingState) {
2120 TRACE("Recording... not performing anything\n");
2128 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2129 glMatrixMode(GL_MODELVIEW);
2131 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2133 TRACE("Clipplane [%f,%f,%f,%f]\n",
2134 This->updateStateBlock->clipplane[Index][0],
2135 This->updateStateBlock->clipplane[Index][1],
2136 This->updateStateBlock->clipplane[Index][2],
2137 This->updateStateBlock->clipplane[Index][3]);
2138 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2139 checkGLcall("glClipPlane");
2147 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2148 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2149 TRACE("(%p) : for idx %ld\n", This, Index);
2151 /* Validate Index */
2152 if (Index >= GL_LIMITS(clipplanes)) {
2153 TRACE("Application has requested clipplane this device doesn't support\n");
2154 return D3DERR_INVALIDCALL;
2157 pPlane[0] = This->stateBlock->clipplane[Index][0];
2158 pPlane[1] = This->stateBlock->clipplane[Index][1];
2159 pPlane[2] = This->stateBlock->clipplane[Index][2];
2160 pPlane[3] = This->stateBlock->clipplane[Index][3];
2165 * Get / Set Clip Plane Status
2166 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2168 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2169 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2170 FIXME("(%p) : stub\n", This);
2171 if (NULL == pClipStatus) {
2172 return D3DERR_INVALIDCALL;
2174 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2175 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2179 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2180 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2181 FIXME("(%p) : stub\n", This);
2182 if (NULL == pClipStatus) {
2183 return D3DERR_INVALIDCALL;
2185 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2186 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2191 * Get / Set Material
2192 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2194 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2195 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2197 This->updateStateBlock->changed.material = TRUE;
2198 This->updateStateBlock->set.material = TRUE;
2199 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2201 /* Handle recording of state blocks */
2202 if (This->isRecordingState) {
2203 TRACE("Recording... not performing anything\n");
2208 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2209 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2210 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2211 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2212 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2214 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2215 checkGLcall("glMaterialfv");
2216 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2217 checkGLcall("glMaterialfv");
2219 /* Only change material color if specular is enabled, otherwise it is set to black */
2220 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2221 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2222 checkGLcall("glMaterialfv");
2224 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2225 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2226 checkGLcall("glMaterialfv");
2228 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2229 checkGLcall("glMaterialfv");
2230 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2231 checkGLcall("glMaterialf");
2237 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2238 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2239 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2240 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2241 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2242 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2243 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2244 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2251 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2252 UINT BaseVertexIndex) {
2253 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2254 IWineD3DIndexBuffer *oldIdxs;
2256 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2257 oldIdxs = This->updateStateBlock->pIndexData;
2259 This->updateStateBlock->changed.indices = TRUE;
2260 This->updateStateBlock->set.indices = TRUE;
2261 This->updateStateBlock->pIndexData = pIndexData;
2262 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2264 /* Handle recording of state blocks */
2265 if (This->isRecordingState) {
2266 TRACE("Recording... not performing anything\n");
2270 if (oldIdxs) IWineD3DIndexBuffer_Release(oldIdxs);
2271 if (pIndexData) IWineD3DIndexBuffer_AddRef(This->stateBlock->pIndexData);
2275 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2276 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2278 *ppIndexData = This->stateBlock->pIndexData;
2280 /* up ref count on ppindexdata */
2281 if (*ppIndexData) IWineD3DIndexBuffer_AddRef(*ppIndexData);
2282 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2288 * Get / Set Viewports
2290 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2291 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2293 TRACE("(%p)\n", This);
2294 This->updateStateBlock->changed.viewport = TRUE;
2295 This->updateStateBlock->set.viewport = TRUE;
2296 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2298 /* Handle recording of state blocks */
2299 if (This->isRecordingState) {
2300 TRACE("Recording... not performing anything\n");
2306 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2307 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2309 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2310 checkGLcall("glDepthRange");
2311 /* Note: GL requires lower left, DirectX supplies upper left */
2312 /* TODO: replace usage of renderTarget with context management */
2313 glViewport(pViewport->X, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2314 pViewport->Width, pViewport->Height);
2315 checkGLcall("glViewport");
2323 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2324 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2325 TRACE("(%p)\n", This);
2326 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2331 * Get / Set Render States
2332 * TODO: Verify against dx9 definitions
2334 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2336 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2337 DWORD OldValue = This->stateBlock->renderState[State];
2339 /* Simple way of referring to either a DWORD or a 4 byte float */
2345 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2346 This->updateStateBlock->changed.renderState[State] = TRUE;
2347 This->updateStateBlock->set.renderState[State] = TRUE;
2348 This->updateStateBlock->renderState[State] = Value;
2350 /* Handle recording of state blocks */
2351 if (This->isRecordingState) {
2352 TRACE("Recording... not performing anything\n");
2359 case WINED3DRS_FILLMODE :
2360 switch ((D3DFILLMODE) Value) {
2361 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2362 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2363 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2365 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2367 checkGLcall("glPolygonMode (fillmode)");
2370 case WINED3DRS_LIGHTING :
2372 glEnable(GL_LIGHTING);
2373 checkGLcall("glEnable GL_LIGHTING");
2375 glDisable(GL_LIGHTING);
2376 checkGLcall("glDisable GL_LIGHTING");
2380 case WINED3DRS_ZENABLE :
2381 switch ((D3DZBUFFERTYPE) Value) {
2383 glDisable(GL_DEPTH_TEST);
2384 checkGLcall("glDisable GL_DEPTH_TEST");
2387 glEnable(GL_DEPTH_TEST);
2388 checkGLcall("glEnable GL_DEPTH_TEST");
2391 glEnable(GL_DEPTH_TEST);
2392 checkGLcall("glEnable GL_DEPTH_TEST");
2393 FIXME("W buffer is not well handled\n");
2396 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2400 case WINED3DRS_CULLMODE :
2402 /* If we are culling "back faces with clockwise vertices" then
2403 set front faces to be counter clockwise and enable culling
2405 switch ((D3DCULL) Value) {
2407 glDisable(GL_CULL_FACE);
2408 checkGLcall("glDisable GL_CULL_FACE");
2411 glEnable(GL_CULL_FACE);
2412 checkGLcall("glEnable GL_CULL_FACE");
2413 if (This->renderUpsideDown) {
2415 checkGLcall("glFrontFace GL_CW");
2417 glFrontFace(GL_CCW);
2418 checkGLcall("glFrontFace GL_CCW");
2420 glCullFace(GL_BACK);
2423 glEnable(GL_CULL_FACE);
2424 checkGLcall("glEnable GL_CULL_FACE");
2425 if (This->renderUpsideDown) {
2426 glFrontFace(GL_CCW);
2427 checkGLcall("glFrontFace GL_CCW");
2430 checkGLcall("glFrontFace GL_CW");
2432 glCullFace(GL_BACK);
2435 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2439 case WINED3DRS_SHADEMODE :
2440 switch ((D3DSHADEMODE) Value) {
2442 glShadeModel(GL_FLAT);
2443 checkGLcall("glShadeModel");
2445 case D3DSHADE_GOURAUD:
2446 glShadeModel(GL_SMOOTH);
2447 checkGLcall("glShadeModel");
2449 case D3DSHADE_PHONG:
2450 FIXME("D3DSHADE_PHONG isn't supported?\n");
2453 return D3DERR_INVALIDCALL;
2455 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2459 case WINED3DRS_DITHERENABLE :
2461 glEnable(GL_DITHER);
2462 checkGLcall("glEnable GL_DITHER");
2464 glDisable(GL_DITHER);
2465 checkGLcall("glDisable GL_DITHER");
2469 case WINED3DRS_ZWRITEENABLE :
2472 checkGLcall("glDepthMask");
2475 checkGLcall("glDepthMask");
2479 case WINED3DRS_ZFUNC :
2481 int glParm = GL_LESS;
2483 switch ((D3DCMPFUNC) Value) {
2484 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2485 case D3DCMP_LESS: glParm=GL_LESS; break;
2486 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2487 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2488 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2489 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2490 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2491 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2493 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2495 glDepthFunc(glParm);
2496 checkGLcall("glDepthFunc");
2500 case WINED3DRS_AMBIENT :
2503 D3DCOLORTOGLFLOAT4(Value, col);
2504 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2505 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2506 checkGLcall("glLightModel for MODEL_AMBIENT");
2511 case WINED3DRS_ALPHABLENDENABLE :
2514 checkGLcall("glEnable GL_BLEND");
2516 glDisable(GL_BLEND);
2517 checkGLcall("glDisable GL_BLEND");
2521 case WINED3DRS_SRCBLEND :
2522 case WINED3DRS_DESTBLEND :
2524 int newVal = GL_ZERO;
2526 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2527 case D3DBLEND_ONE : newVal = GL_ONE; break;
2528 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2529 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2530 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2531 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2532 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2533 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2534 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2535 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2536 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2538 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2539 This->srcBlend = newVal;
2540 This->dstBlend = newVal;
2543 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2544 This->srcBlend = newVal;
2545 This->dstBlend = newVal;
2548 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2551 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2552 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2553 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2554 glBlendFunc(This->srcBlend, This->dstBlend);
2556 checkGLcall("glBlendFunc");
2560 case WINED3DRS_ALPHATESTENABLE :
2562 glEnable(GL_ALPHA_TEST);
2563 checkGLcall("glEnable GL_ALPHA_TEST");
2565 glDisable(GL_ALPHA_TEST);
2566 checkGLcall("glDisable GL_ALPHA_TEST");
2570 case WINED3DRS_ALPHAFUNC :
2572 int glParm = GL_LESS;
2573 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2575 switch ((D3DCMPFUNC) Value) {
2576 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2577 case D3DCMP_LESS: glParm = GL_LESS; break;
2578 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2579 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2580 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2581 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2582 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2583 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2585 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2587 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2588 glAlphaFunc(glParm, ref);
2589 This->alphafunc = glParm;
2590 checkGLcall("glAlphaFunc");
2594 case WINED3DRS_ALPHAREF :
2596 int glParm = This->alphafunc;
2599 ref = ((float) Value) / 255.0f;
2600 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2601 glAlphaFunc(glParm, ref);
2602 checkGLcall("glAlphaFunc");
2606 case WINED3DRS_CLIPPLANEENABLE :
2607 case WINED3DRS_CLIPPING :
2609 /* Ensure we only do the changed clip planes */
2610 DWORD enable = 0xFFFFFFFF;
2611 DWORD disable = 0x00000000;
2613 /* If enabling / disabling all */
2614 if (State == WINED3DRS_CLIPPING) {
2616 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2619 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2623 enable = Value & ~OldValue;
2624 disable = ~Value & OldValue;
2627 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2628 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2629 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2630 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2631 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2632 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2634 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2635 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2636 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2637 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2638 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2639 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2641 /** update clipping status */
2643 This->stateBlock->clip_status.ClipUnion = 0;
2644 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2646 This->stateBlock->clip_status.ClipUnion = 0;
2647 This->stateBlock->clip_status.ClipIntersection = 0;
2652 case WINED3DRS_BLENDOP :
2654 int glParm = GL_FUNC_ADD;
2656 switch ((D3DBLENDOP) Value) {
2657 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2658 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2659 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2660 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2661 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2663 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2665 TRACE("glBlendEquation(%x)\n", glParm);
2666 glBlendEquation(glParm);
2667 checkGLcall("glBlendEquation");
2671 case WINED3DRS_TEXTUREFACTOR :
2675 /* Note the texture color applies to all textures whereas
2676 GL_TEXTURE_ENV_COLOR applies to active only */
2678 D3DCOLORTOGLFLOAT4(Value, col);
2679 /* Set the default alpha blend color */
2680 glBlendColor(col[0], col[1], col[2], col[3]);
2681 checkGLcall("glBlendColor");
2683 /* And now the default texture color as well */
2684 for (i = 0; i < GL_LIMITS(textures); i++) {
2686 /* Note the D3DRS value applies to all textures, but GL has one
2687 per texture, so apply it now ready to be used! */
2688 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2691 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2694 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2695 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2700 case WINED3DRS_SPECULARENABLE :
2702 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2703 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2704 specular color. This is wrong:
2705 Separate specular color means the specular colour is maintained separately, whereas
2706 single color means it is merged in. However in both cases they are being used to
2708 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2709 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2713 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2714 checkGLcall("glMaterialfv");
2715 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2716 glEnable(GL_COLOR_SUM_EXT);
2718 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2720 checkGLcall("glEnable(GL_COLOR_SUM)");
2722 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2724 /* for the case of enabled lighting: */
2725 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2726 checkGLcall("glMaterialfv");
2728 /* for the case of disabled lighting: */
2729 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2730 glDisable(GL_COLOR_SUM_EXT);
2732 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2734 checkGLcall("glDisable(GL_COLOR_SUM)");
2739 case WINED3DRS_STENCILENABLE :
2741 glEnable(GL_STENCIL_TEST);
2742 checkGLcall("glEnable GL_STENCIL_TEST");
2744 glDisable(GL_STENCIL_TEST);
2745 checkGLcall("glDisable GL_STENCIL_TEST");
2749 case WINED3DRS_STENCILFUNC :
2751 int glParm = GL_ALWAYS;
2752 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2753 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2755 switch ((D3DCMPFUNC) Value) {
2756 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2757 case D3DCMP_LESS: glParm=GL_LESS; break;
2758 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2759 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2760 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2761 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2762 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2763 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2765 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2767 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2768 This->stencilfunc = glParm;
2769 glStencilFunc(glParm, ref, mask);
2770 checkGLcall("glStencilFunc");
2774 case WINED3DRS_STENCILREF :
2776 int glParm = This->stencilfunc;
2778 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2781 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2782 glStencilFunc(glParm, ref, mask);
2783 checkGLcall("glStencilFunc");
2787 case WINED3DRS_STENCILMASK :
2789 int glParm = This->stencilfunc;
2790 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2791 GLuint mask = Value;
2793 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2794 glStencilFunc(glParm, ref, mask);
2795 checkGLcall("glStencilFunc");
2799 case WINED3DRS_STENCILFAIL :
2805 fail = StencilOp(Value);
2806 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2807 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2808 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2809 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2811 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2812 glStencilOp(fail, zfail, zpass);
2813 checkGLcall("glStencilOp(fail, zfail, zpass);");
2816 case WINED3DRS_STENCILZFAIL :
2822 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2823 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2824 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2825 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2826 zfail = StencilOp(Value);
2828 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2829 glStencilOp(fail, zfail, zpass);
2830 checkGLcall("glStencilOp(fail, zfail, zpass);");
2833 case WINED3DRS_STENCILPASS :
2839 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2840 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2841 zpass = StencilOp(Value);
2842 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2843 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2845 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2846 glStencilOp(fail, zfail, zpass);
2847 checkGLcall("glStencilOp(fail, zfail, zpass);");
2851 case WINED3DRS_STENCILWRITEMASK :
2853 glStencilMask(Value);
2854 TRACE("glStencilMask(%lu)\n", Value);
2855 checkGLcall("glStencilMask");
2859 case WINED3DRS_FOGENABLE :
2861 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2863 checkGLcall("glEnable GL_FOG");
2866 checkGLcall("glDisable GL_FOG");
2871 case WINED3DRS_RANGEFOGENABLE :
2874 TRACE("Enabled RANGEFOG");
2876 TRACE("Disabled RANGEFOG");
2881 case WINED3DRS_FOGCOLOR :
2884 D3DCOLORTOGLFLOAT4(Value, col);
2885 /* Set the default alpha blend color */
2886 glFogfv(GL_FOG_COLOR, &col[0]);
2887 checkGLcall("glFog GL_FOG_COLOR");
2891 case WINED3DRS_FOGTABLEMODE :
2893 glHint(GL_FOG_HINT, GL_NICEST);
2895 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2896 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2897 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2898 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2900 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2902 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2903 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2908 case WINED3DRS_FOGVERTEXMODE :
2910 glHint(GL_FOG_HINT, GL_FASTEST);
2912 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2913 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2914 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2915 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2917 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2919 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2920 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
2925 case WINED3DRS_FOGSTART :
2928 glFogfv(GL_FOG_START, &tmpvalue.f);
2929 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2930 TRACE("Fog Start == %f\n", tmpvalue.f);
2934 case WINED3DRS_FOGEND :
2937 glFogfv(GL_FOG_END, &tmpvalue.f);
2938 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2939 TRACE("Fog End == %f\n", tmpvalue.f);
2943 case WINED3DRS_FOGDENSITY :
2946 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
2947 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2951 case WINED3DRS_VERTEXBLEND :
2953 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2954 TRACE("Vertex Blending state to %ld\n", Value);
2958 case WINED3DRS_TWEENFACTOR :
2961 This->updateStateBlock->tween_factor = tmpvalue.f;
2962 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
2966 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
2968 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2972 case WINED3DRS_COLORVERTEX :
2973 case WINED3DRS_DIFFUSEMATERIALSOURCE :
2974 case WINED3DRS_SPECULARMATERIALSOURCE :
2975 case WINED3DRS_AMBIENTMATERIALSOURCE :
2976 case WINED3DRS_EMISSIVEMATERIALSOURCE :
2978 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2980 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
2981 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2982 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
2983 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
2984 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
2985 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
2987 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2988 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2989 Parm = GL_AMBIENT_AND_DIFFUSE;
2993 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2995 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2997 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3004 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3006 This->tracking_color = NEEDS_TRACKING;
3007 This->tracking_parm = Parm;
3011 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3016 case WINED3DRS_LINEPATTERN :
3022 tmppattern.d = Value;
3024 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3026 if (tmppattern.lp.wRepeatFactor) {
3027 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3028 checkGLcall("glLineStipple(repeat, linepattern)");
3029 glEnable(GL_LINE_STIPPLE);
3030 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3032 glDisable(GL_LINE_STIPPLE);
3033 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3038 case WINED3DRS_ZBIAS :
3042 TRACE("ZBias value %f\n", tmpvalue.f);
3043 glPolygonOffset(0, -tmpvalue.f);
3044 checkGLcall("glPolygonOffset(0, -Value)");
3045 glEnable(GL_POLYGON_OFFSET_FILL);
3046 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3047 glEnable(GL_POLYGON_OFFSET_LINE);
3048 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3049 glEnable(GL_POLYGON_OFFSET_POINT);
3050 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3052 glDisable(GL_POLYGON_OFFSET_FILL);
3053 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3054 glDisable(GL_POLYGON_OFFSET_LINE);
3055 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3056 glDisable(GL_POLYGON_OFFSET_POINT);
3057 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3062 case WINED3DRS_NORMALIZENORMALS :
3064 glEnable(GL_NORMALIZE);
3065 checkGLcall("glEnable(GL_NORMALIZE);");
3067 glDisable(GL_NORMALIZE);
3068 checkGLcall("glDisable(GL_NORMALIZE);");
3072 case WINED3DRS_POINTSIZE :
3074 TRACE("Set point size to %f\n", tmpvalue.f);
3075 glPointSize(tmpvalue.f);
3076 checkGLcall("glPointSize(...);");
3079 case WINED3DRS_POINTSIZE_MIN :
3080 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3082 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3083 checkGLcall("glPointParameterfEXT(...);");
3085 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3089 case WINED3DRS_POINTSIZE_MAX :
3090 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3092 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3093 checkGLcall("glPointParameterfEXT(...);");
3095 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3099 case WINED3DRS_POINTSCALE_A :
3100 case WINED3DRS_POINTSCALE_B :
3101 case WINED3DRS_POINTSCALE_C :
3102 case WINED3DRS_POINTSCALEENABLE :
3104 /* If enabled, supply the parameters, otherwise fall back to defaults */
3105 if (This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3106 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3107 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]);
3108 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]);
3109 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]);
3111 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3112 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3113 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3115 TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
3118 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3119 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3120 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3121 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3123 TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
3129 case WINED3DRS_COLORWRITEENABLE :
3131 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3132 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3133 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3134 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3135 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3136 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3137 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3138 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3139 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3140 checkGLcall("glColorMask(...)");
3144 case WINED3DRS_LOCALVIEWER :
3146 GLint state = (Value) ? 1 : 0;
3147 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3148 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3152 case WINED3DRS_LASTPIXEL :
3155 TRACE("Last Pixel Drawing Enabled\n");
3157 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3162 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3165 TRACE("Software Processing Enabled\n");
3167 TRACE("Software Processing Disabled\n");
3172 /** not supported */
3173 case WINED3DRS_ZVISIBLE :
3176 return D3DERR_INVALIDCALL;
3179 /* Unhandled yet...! */
3180 case WINED3DRS_EDGEANTIALIAS :
3181 case WINED3DRS_WRAP0 :
3182 case WINED3DRS_WRAP1 :
3183 case WINED3DRS_WRAP2 :
3184 case WINED3DRS_WRAP3 :
3185 case WINED3DRS_WRAP4 :
3186 case WINED3DRS_WRAP5 :
3187 case WINED3DRS_WRAP6 :
3188 case WINED3DRS_WRAP7 :
3189 case WINED3DRS_POINTSPRITEENABLE :
3190 case WINED3DRS_MULTISAMPLEANTIALIAS :
3191 case WINED3DRS_MULTISAMPLEMASK :
3192 case WINED3DRS_PATCHEDGESTYLE :
3193 case WINED3DRS_PATCHSEGMENTS :
3194 case WINED3DRS_DEBUGMONITORTOKEN :
3195 case WINED3DRS_POSITIONORDER :
3196 case WINED3DRS_NORMALORDER :
3197 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3198 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3201 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3209 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3210 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3211 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3212 *pValue = This->stateBlock->renderState[State];
3216 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value){
3217 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3219 * SetSampler is designed to allow for more than the standard up to 8 textures
3220 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3221 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3223 * http://developer.nvidia.com/object/General_FAQ.html#t6
3225 * There are two new settings for GForce
3227 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3228 * and the texture one:
3229 * GL_MAX_TEXTURE_COORDS_ARB.
3230 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3237 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3239 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > HIGHEST_SAMPLER_STATE || Type < 0){
3240 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), HIGHEST_SAMPLER_STATE, Sampler, Type);
3241 return D3DERR_INVALIDCALL;
3244 This->updateStateBlock->changed.samplerState[Sampler][Type] = TRUE;
3245 This->updateStateBlock->set.samplerState[Sampler][Type] = TRUE;
3246 TRACE("Setting sampler %ld %d to %ld \n", Sampler, Type, Value);
3247 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3249 /* Handle recording of state blocks */
3250 if (This->isRecordingState) {
3251 TRACE("Recording... not performing anything\n");
3255 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
3256 clamping, MIPLOD, etc. This will work for up to 16 samplers.
3257 is this just GL_TEXTURE_2D or is it GL_TEXTURE_1D and GL_TEXTURE_3D as well?
3260 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
3261 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3262 GLACTIVETEXTURE(Sampler);
3263 } else if (Sampler > 0) {
3264 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3270 case WINED3DSAMP_ADDRESSU : /* 1 */
3271 case WINED3DSAMP_ADDRESSV : /* 2 */
3272 case WINED3DSAMP_ADDRESSW : /* 3 */
3274 GLint wrapParm = GL_REPEAT;
3276 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3277 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3278 case D3DTADDRESS_BORDER:
3280 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3281 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3283 /* FIXME: Not right, but better */
3284 TRACE("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3285 wrapParm = GL_REPEAT;
3289 case D3DTADDRESS_MIRROR:
3291 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3292 wrapParm = GL_MIRRORED_REPEAT_ARB;
3294 /* Unsupported in OpenGL pre-1.4 */
3295 TRACE("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3296 wrapParm = GL_REPEAT;
3300 case D3DTADDRESS_MIRRORONCE:
3302 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3303 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3305 TRACE("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3306 wrapParm = GL_REPEAT;
3312 /* This is for the whole context, not just the sampler,
3313 so we should warn if two states are baing set for any given scene */
3315 TRACE("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3316 wrapParm = GL_REPEAT;
3319 case WINED3DSAMP_ADDRESSU:
3320 TRACE("Setting WRAP_S for %ld to %d \n", Sampler, wrapParm);
3321 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_S, wrapParm);
3322 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3324 case WINED3DSAMP_ADDRESSV:
3325 TRACE("Setting WRAP_T for %ld to %d\n", Sampler, wrapParm);
3326 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_T, wrapParm);
3327 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3330 case WINED3DSAMP_ADDRESSW:
3331 TRACE("Setting WRAP_R for %ld to %d\n", Sampler, wrapParm);
3332 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_R, wrapParm);
3333 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3336 break; /** stupic compilator */
3341 case WINED3DSAMP_BORDERCOLOR : /* 4 */
3344 D3DCOLORTOGLFLOAT4(Value, col);
3345 TRACE("Setting border color for %ld to %lx\n", Sampler, Value);
3346 glTexParameterfv(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_BORDER_COLOR, &col[0]);
3347 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3351 case WINED3DSAMP_MAGFILTER : /* 5 */
3353 DWORD ValueMAG = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAGFILTER];
3354 GLint realVal = GL_NEAREST;
3356 if (ValueMAG == D3DTEXF_POINT) {
3357 realVal = GL_NEAREST;
3358 } else if (ValueMAG == D3DTEXF_LINEAR) {
3359 realVal = GL_LINEAR;
3360 } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
3361 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3362 realVal = GL_LINEAR;
3364 FIXME("Trying to use ANISOTROPIC_FILTERING for WINED3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
3365 realVal = GL_NEAREST;
3368 FIXME("Unhandled WINED3DTSS_MAGFILTER value of %ld\n", ValueMAG);
3369 realVal = GL_NEAREST;
3371 TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
3372 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MAG_FILTER, realVal);
3373 checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
3375 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3377 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
3378 glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3379 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3380 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3381 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3386 case WINED3DSAMP_MINFILTER: /* 6 */
3387 case WINED3DSAMP_MIPFILTER: /* 7 */
3389 DWORD ValueMIN = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MINFILTER];
3390 DWORD ValueMIP = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPFILTER];
3391 GLint realVal = GL_LINEAR;
3393 if (ValueMIN == D3DTEXF_NONE) {
3394 /* Doesn't really make sense - Windows just seems to disable
3395 mipmapping when this occurs */
3396 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3397 realVal = GL_LINEAR;
3398 } else if (ValueMIN == D3DTEXF_POINT) {
3400 if (ValueMIP == D3DTEXF_NONE) {
3401 realVal = GL_NEAREST;
3402 } else if (ValueMIP == D3DTEXF_POINT) {
3403 realVal = GL_NEAREST_MIPMAP_NEAREST;
3404 } else if (ValueMIP == D3DTEXF_LINEAR) {
3405 realVal = GL_NEAREST_MIPMAP_LINEAR;
3407 FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3408 realVal = GL_NEAREST;
3410 } else if (ValueMIN == D3DTEXF_LINEAR) {
3412 if (ValueMIP == D3DTEXF_NONE) {
3413 realVal = GL_LINEAR;
3414 } else if (ValueMIP == D3DTEXF_POINT) {
3415 realVal = GL_LINEAR_MIPMAP_NEAREST;
3416 } else if (ValueMIP == D3DTEXF_LINEAR) {
3417 realVal = GL_LINEAR_MIPMAP_LINEAR;
3419 FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3420 realVal = GL_LINEAR;
3422 } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
3423 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3424 if (ValueMIP == D3DTEXF_NONE) {
3425 realVal = GL_LINEAR_MIPMAP_LINEAR;
3426 } else if (ValueMIP == D3DTEXF_POINT) {
3427 realVal = GL_LINEAR_MIPMAP_NEAREST;
3428 } else if (ValueMIP == D3DTEXF_LINEAR) {
3429 realVal = GL_LINEAR_MIPMAP_LINEAR;
3431 FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3432 realVal = GL_LINEAR;
3435 WARN("Trying to use ANISOTROPIC_FILTERING for WINED3DTSS_MINFILTER. But not supported by OpenGL driver\n");
3436 realVal = GL_LINEAR;
3439 FIXME("Unhandled WINED3DTSS_MINFILTER value of %ld\n", ValueMIN);
3440 realVal = GL_LINEAR_MIPMAP_LINEAR;
3443 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3444 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MIN_FILTER, realVal);
3445 checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
3447 * if we just choose to use ANISOTROPIC filtering, refresh openGL state
3449 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
3450 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MAX_ANISOTROPY_EXT,
3451 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3452 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3457 case WINED3DSAMP_MIPMAPLODBIAS : /* 8 */
3459 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3461 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3462 GL_TEXTURE_LOD_BIAS_EXT,
3464 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
3469 case WINED3DSAMP_MAXMIPLEVEL : /* 9 */
3472 * Not really the same, but the more apprioprate than nothing
3474 glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3475 GL_TEXTURE_BASE_LEVEL,
3476 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXMIPLEVEL]);
3477 checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
3481 case WINED3DSAMP_MAXANISOTROPY : /* 10 */
3483 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3484 glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3485 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3486 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3487 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3491 case WINED3DSAMP_SRGBTEXTURE : /* 11 */
3492 /* Per texture gamma correction, default 0 */
3493 case WINED3DSAMP_ELEMENTINDEX : /* 12 */
3494 /* When a multi-element textures is used this indicates the element, (what's a multielement texture?) */
3495 case WINED3DSAMP_DMAPOFFSET : /* 13 */
3496 /* Value of a precompiled displacement map used by the tesselator, default 0 */
3497 TRACE("Unsupported sampler setting, Sampler=%ld, Type=%d, Value =%ld\n", Sampler, Type, Value);
3501 TRACE("invalid sampler setting, Sampler=%ld, Type=%d, Value =%ld\n", Sampler, Type, Value);
3507 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value){
3508 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3509 /** TODO: check that sampler is in range **/
3510 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3511 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3516 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect){
3517 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3520 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3521 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3522 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3527 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect){
3528 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3529 GLint scissorBox[4];
3532 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3533 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3534 pRect->left = scissorBox[1];
3535 pRect->top = scissorBox[2];
3536 pRect->right = scissorBox[1] + scissorBox[3];
3537 pRect->bottom = scissorBox[2] + scissorBox[4];
3538 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3543 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3544 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3546 TRACE("(%p) : pDecl=%p\n", This, pDecl);
3548 /* TODO: what about recording stateblocks? */
3549 if (NULL != pDecl) {
3550 IWineD3DVertexDeclaration_AddRef(pDecl);
3552 if (NULL != This->updateStateBlock->vertexDecl) {
3553 IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
3555 This->updateStateBlock->vertexDecl = pDecl;
3556 This->updateStateBlock->changed.vertexDecl = TRUE;
3557 This->updateStateBlock->set.vertexDecl = TRUE;
3561 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3562 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3564 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3566 *ppDecl = This->updateStateBlock->vertexDecl;
3567 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3571 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader){
3572 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3574 static BOOL showFixmes = TRUE;
3576 This->updateStateBlock->vertexShader = pShader;
3577 This->updateStateBlock->changed.vertexShader = TRUE;
3578 This->updateStateBlock->set.vertexShader = TRUE;
3580 if(pShader == NULL){
3581 /* clear down the shader */
3582 TRACE("Clear down the shader\n");
3585 FIXME("(%p) : stub pShader(%p)\n", This, pShader);
3592 /** FIXME: refernece counting? **/
3593 if (pShader == NULL) { /* only valid with non FVF shaders */
3594 TRACE_(d3d_shader)("(%p) : FVF Shader, pShader=%p\n", This, pShader);
3595 This->updateStateBlock->vertexShader = NULL;
3597 TRACE_(d3d_shader)("(%p) : Created shader, pShader=%p\n", This, pShader);
3598 This->updateStateBlock->vertexShader = pShader;
3601 This->updateStateBlock->changed.vertexShader = TRUE;
3602 This->updateStateBlock->set.vertexShader = TRUE;
3604 /* Handle recording of state blocks */
3605 if (This->isRecordingState) {
3606 TRACE("Recording... not performing anything\n");
3610 * TODO: merge HAL shaders context switching from prototype
3616 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader){
3617 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3618 *ppShader = This->stateBlock->vertexShader;
3619 if(*ppShader != NULL)
3620 IWineD3DVertexShader_AddRef(*ppShader);
3621 TRACE("(%p) : returning %p\n", This, *ppShader);
3625 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
3626 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3628 TRACE("(%p) : stub\n", This);
3632 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3633 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3634 TRACE("(%p) : stub\n", This);
3638 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3639 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3640 TRACE("(%p) : stub\n", This);
3644 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
3645 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3646 TRACE("(%p) : stub\n", This);
3650 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3651 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3652 TRACE("(%p) : stub\n", This);
3656 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
3657 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3658 TRACE("(%p) : stub\n", This);
3662 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader){
3663 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3664 TRACE("(%p) : stub\n", This);
3668 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader){
3669 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3670 TRACE("(%p) : stub\n", This);
3675 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
3676 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3677 TRACE("(%p) : stub\n", This);
3681 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3682 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3683 TRACE("(%p) : stub\n", This);
3687 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3688 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3689 TRACE("(%p) : stub\n", This);
3693 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
3694 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3695 TRACE("(%p) : stub\n", This);
3699 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3700 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3701 TRACE("(%p) : stub\n", This);
3705 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
3706 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3707 TRACE("(%p) : stub\n", This);
3711 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags){
3712 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3713 FIXME("(%p) : stub\n", This);
3718 * Get / Set Texture Stage States
3719 * TODO: Verify against dx9 definitions
3721 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3722 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3724 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3726 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3728 /* Reject invalid texture units */
3729 if (Stage >= GL_LIMITS(textures)) {
3730 TRACE("Attempt to access invalid texture rejected\n");
3731 return D3DERR_INVALIDCALL;
3734 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
3735 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
3736 This->updateStateBlock->textureState[Stage][Type] = Value;
3738 /* Handle recording of state blocks */
3739 if (This->isRecordingState) {
3740 TRACE("Recording... not performing anything\n");
3746 /* Make appropriate texture active */
3747 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3748 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3749 GLACTIVETEXTURE(Stage);
3750 } else if (Stage > 0) {
3751 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3755 case WINED3DTSS_ALPHAOP :
3756 case WINED3DTSS_COLOROP :
3759 if ((Value == D3DTOP_DISABLE) && (Type == WINED3DTSS_COLOROP)) {
3760 /* TODO: Disable by making this and all later levels disabled */
3761 glDisable(GL_TEXTURE_1D);
3762 checkGLcall("Disable GL_TEXTURE_1D");
3763 glDisable(GL_TEXTURE_2D);
3764 checkGLcall("Disable GL_TEXTURE_2D");
3765 glDisable(GL_TEXTURE_3D);
3766 checkGLcall("Disable GL_TEXTURE_3D");
3767 break; /* Don't bother setting the texture operations */
3769 /* Enable only the appropriate texture dimension */
3770 if (Type == WINED3DTSS_COLOROP) {
3771 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3772 glEnable(GL_TEXTURE_1D);
3773 checkGLcall("Enable GL_TEXTURE_1D");
3775 glDisable(GL_TEXTURE_1D);
3776 checkGLcall("Disable GL_TEXTURE_1D");
3778 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3779 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3780 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3781 checkGLcall("Enable GL_TEXTURE_2D");
3783 glEnable(GL_TEXTURE_2D);
3784 checkGLcall("Enable GL_TEXTURE_2D");
3787 glDisable(GL_TEXTURE_2D);
3788 checkGLcall("Disable GL_TEXTURE_2D");
3790 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3791 glEnable(GL_TEXTURE_3D);
3792 checkGLcall("Enable GL_TEXTURE_3D");
3794 glDisable(GL_TEXTURE_3D);
3795 checkGLcall("Disable GL_TEXTURE_3D");
3797 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3798 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3799 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3801 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3802 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3806 /* Drop through... (Except disable case) */
3807 case WINED3DTSS_COLORARG0 :
3808 case WINED3DTSS_COLORARG1 :
3809 case WINED3DTSS_COLORARG2 :
3810 case WINED3DTSS_ALPHAARG0 :
3811 case WINED3DTSS_ALPHAARG1 :
3812 case WINED3DTSS_ALPHAARG2 :
3814 BOOL isAlphaArg = (Type == WINED3DTSS_ALPHAOP || Type == WINED3DTSS_ALPHAARG1 ||
3815 Type == WINED3DTSS_ALPHAARG2 || Type == WINED3DTSS_ALPHAARG0);
3817 set_tex_op(iface, TRUE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAOP],
3818 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG1],
3819 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG2],
3820 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG0]);
3822 set_tex_op(iface, FALSE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP],
3823 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG1],
3824 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG2],
3825 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG0]);
3831 case WINED3DTSS_ADDRESSW :
3833 GLint wrapParm = GL_REPEAT;
3836 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3837 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3838 case D3DTADDRESS_BORDER:
3840 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3841 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3843 /* FIXME: Not right, but better */
3844 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3845 wrapParm = GL_REPEAT;
3849 case D3DTADDRESS_MIRROR:
3851 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3852 wrapParm = GL_MIRRORED_REPEAT_ARB;
3854 /* Unsupported in OpenGL pre-1.4 */
3855 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3856 wrapParm = GL_REPEAT;
3860 case D3DTADDRESS_MIRRORONCE:
3862 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3863 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3865 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3866 wrapParm = GL_REPEAT;
3872 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3873 wrapParm = GL_REPEAT;
3876 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3877 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3878 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3882 case WINED3DTSS_TEXCOORDINDEX :
3884 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3886 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
3887 one flag, you can still specify an index value, which the system uses to
3888 determine the texture wrapping mode.
3889 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3890 means use the vertex position (camera-space) as the input texture coordinates
3891 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3892 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3893 to the TEXCOORDINDEX value */
3896 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3898 switch (Value & 0xFFFF0000) {
3899 case D3DTSS_TCI_PASSTHRU:
3900 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3901 glDisable(GL_TEXTURE_GEN_S);
3902 glDisable(GL_TEXTURE_GEN_T);
3903 glDisable(GL_TEXTURE_GEN_R);
3904 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3907 case D3DTSS_TCI_CAMERASPACEPOSITION:
3908 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3909 as the input texture coordinates for this stage's texture transformation. This
3910 equates roughly to EYE_LINEAR */
3912 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3913 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3914 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3915 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3916 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3918 glMatrixMode(GL_MODELVIEW);
3921 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3922 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3923 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3924 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3927 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3928 glEnable(GL_TEXTURE_GEN_S);
3929 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3930 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3931 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3932 glEnable(GL_TEXTURE_GEN_T);
3933 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3934 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3935 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3936 glEnable(GL_TEXTURE_GEN_R);
3937 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3938 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3939 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3943 case D3DTSS_TCI_CAMERASPACENORMAL:
3945 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3946 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3947 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3948 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3949 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3950 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3952 glMatrixMode(GL_MODELVIEW);
3955 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3956 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3957 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3958 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3961 glEnable(GL_TEXTURE_GEN_S);
3962 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3963 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3964 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3965 glEnable(GL_TEXTURE_GEN_T);
3966 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3967 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3968 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3969 glEnable(GL_TEXTURE_GEN_R);
3970 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3971 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3972 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3977 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3979 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3980 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3981 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3982 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3983 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3984 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3986 glMatrixMode(GL_MODELVIEW);
3989 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3990 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3991 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3992 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3995 glEnable(GL_TEXTURE_GEN_S);
3996 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3997 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3998 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3999 glEnable(GL_TEXTURE_GEN_T);
4000 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4001 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4002 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4003 glEnable(GL_TEXTURE_GEN_R);
4004 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4005 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4006 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4011 /* Unhandled types: */
4014 /* ? disable GL_TEXTURE_GEN_n ? */
4015 glDisable(GL_TEXTURE_GEN_S);
4016 glDisable(GL_TEXTURE_GEN_T);
4017 glDisable(GL_TEXTURE_GEN_R);
4018 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
4025 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4026 set_texture_matrix((float *)&This->stateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
4029 case WINED3DTSS_BUMPENVMAT00 :
4030 case WINED3DTSS_BUMPENVMAT01 :
4031 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4033 case WINED3DTSS_BUMPENVMAT10 :
4034 case WINED3DTSS_BUMPENVMAT11 :
4035 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4038 case WINED3DTSS_BUMPENVLSCALE :
4039 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4042 case WINED3DTSS_BUMPENVLOFFSET :
4043 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4046 case WINED3DTSS_RESULTARG :
4047 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4051 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4052 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4060 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4061 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4062 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4063 *pValue = This->updateStateBlock->textureState[Stage][Type];
4070 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4072 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4073 IWineD3DBaseTexture *oldTexture;
4074 BOOL reapplyStates = TRUE;
4075 DWORD reapplyFlags = 0;
4076 INT oldTextureDimensions = -1;
4077 D3DRESOURCETYPE textureType;
4079 oldTexture = This->updateStateBlock->textures[Stage];
4080 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4082 /* Reject invalid texture units */
4083 if (Stage >= GL_LIMITS(textures)) {
4084 TRACE("Attempt to access invalid texture rejected\n");
4085 return D3DERR_INVALIDCALL;
4088 This->updateStateBlock->set.textures[Stage] = TRUE;
4089 This->updateStateBlock->changed.textures[Stage] = TRUE;
4090 This->updateStateBlock->textures[Stage] = pTexture;
4092 /* Handle recording of state blocks */
4093 if (This->isRecordingState) {
4094 TRACE("Recording... not performing anything\n");
4098 oldTextureDimensions = This->updateStateBlock->textureDimensions[Stage];
4102 /* Make appropriate texture active */
4103 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
4104 GLACTIVETEXTURE(Stage);
4106 } else if (Stage>0) {
4107 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
4110 /** NOTE: MSDN says that setTexture increases the reference count,
4111 * and the the application nust set the texture back to null (or have a leaky application),
4112 * This means we should pass the refcount upto the parent
4113 *******************************/
4114 if (NULL != oldTexture) {
4116 IUnknown *textureParent;
4117 IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
4118 IUnknown_Release(textureParent);
4119 IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
4124 if (NULL != pTexture) {
4125 IUnknown *textureParent;
4126 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
4127 /** NOTE: GetParent will increase the ref count for me, I won't clean up untill the texture is set to NULL **/
4129 /* Now setup the texture appropraitly */
4130 textureType = IWineD3DBaseTexture_GetType(pTexture);
4132 if (textureType == D3DRTYPE_TEXTURE) {
4134 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4135 TRACE("Skipping setting texture as old == new\n");
4136 reapplyStates = FALSE;
4140 /* Standard 2D texture */
4141 TRACE("Standard 2d texture\n");
4142 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
4144 /* Load up the texture now */
4145 IWineD3DTexture_PreLoad((IWineD3DTexture *) pTexture);
4148 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
4150 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4151 TRACE("Skipping setting texture as old == new\n");
4152 reapplyStates = FALSE;
4156 /* Standard 3D (volume) texture */
4157 TRACE("Standard 3d texture\n");
4158 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
4160 /* Load up the texture now */
4161 IWineD3DVolumeTexture_PreLoad((IWineD3DVolumeTexture *) pTexture);
4164 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
4166 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4167 TRACE("Skipping setting texture as old == new\n");
4168 reapplyStates = FALSE;
4172 /* Standard Cube texture */
4173 TRACE("Standard Cube texture\n");
4174 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
4176 /* Load up the texture now */
4177 IWineD3DCubeTexture_PreLoad((IWineD3DCubeTexture *) pTexture);
4181 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dresourcetype(textureType));
4186 TRACE("Setting to no texture (ie default texture)\n");
4187 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
4188 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
4189 checkGLcall("glBindTexture");
4190 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
4193 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
4194 if (oldTextureDimensions != This->updateStateBlock->textureDimensions[Stage]) {
4196 glDisable(oldTextureDimensions);
4197 checkGLcall("Disable oldTextureDimensions");
4199 if (This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP] != D3DTOP_DISABLE) {
4200 glEnable(This->updateStateBlock->textureDimensions[Stage]);
4201 checkGLcall("glEnable new texture dimensions");
4204 /* If Alpha arg1 is texture then handle the special case when there changes between a
4205 texture and no texture - See comments in set_tex_op */
4206 if ((This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
4207 (((oldTexture == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTexture != NULL))))
4209 reapplyFlags |= REAPPLY_ALPHAOP;
4214 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
4215 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
4216 if (reapplyStates) {
4217 IWineD3DDeviceImpl_SetupTextureStates(iface, Stage, reapplyFlags);
4221 TRACE("Texture now fully setup\n");
4226 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4227 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4228 TRACE("(%p) : returning %p for stage %ld\n", This, This->updateStateBlock->textures[Stage], Stage);
4229 *ppTexture = (IWineD3DBaseTexture *) This->updateStateBlock->textures[Stage];
4231 IWineD3DBaseTexture_AddRef(*ppTexture);
4238 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4239 IWineD3DSurface** ppBackBuffer) {
4240 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4241 IWineD3DSwapChain *swapChain;
4244 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4246 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4248 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4249 IWineD3DSwapChain_Release(swapChain);
4251 *ppBackBuffer = NULL;
4256 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4257 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4258 WARN("(%p) : stub, calling idirect3d for now\n", This);
4259 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4262 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4263 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4264 IWineD3DSwapChain *swapChain;
4267 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4269 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4270 IWineD3DSwapChain_Release(swapChain);
4272 FIXME("(%p) Error getting display mode\n", This);
4277 * Stateblock related functions
4280 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4281 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4282 IWineD3DStateBlockImpl *object;
4283 TRACE("(%p)", This);
4284 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4285 if(NULL == object ){
4286 FIXME("(%p)Error allocating memory for stateblock\n", This);
4287 return E_OUTOFMEMORY;
4289 TRACE("(%p) creted object %p\n", This, object);
4290 object->wineD3DDevice= This;
4291 /** FIXME: object->parent = parent; **/
4292 object->parent = NULL;
4293 object->blockType = D3DSBT_ALL;
4295 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4297 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4298 This->updateStateBlock = object;
4299 This->isRecordingState = TRUE;
4301 TRACE("(%p) recording stateblock %p\n",This , object);
4305 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4306 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4308 if (!This->isRecordingState) {
4309 FIXME("(%p) not recording! returning error\n", This);
4310 *ppStateBlock = NULL;
4311 return D3DERR_INVALIDCALL;
4314 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4315 This->isRecordingState = FALSE;
4316 This->updateStateBlock = This->stateBlock;
4317 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4318 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4319 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4324 * Scene related functions
4326 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4327 /* At the moment we have no need for any functionality at the beginning
4329 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4330 TRACE("(%p) : stub\n", This);
4334 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4335 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4336 TRACE("(%p)\n", This);
4338 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4340 checkGLcall("glFlush");
4342 TRACE("End Scene\n");
4343 if(This->renderTarget != NULL){
4345 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4346 IUnknown *targetContainer = NULL;
4347 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)) {
4348 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4349 /** always dirtify for now. we must find a better way to see that surface have been modified
4350 (Modifications should will only occur via draw-primitive, but we do need better locking
4351 switching to render-to-texture should remove the overhead though.
4353 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4354 IWineD3DBaseTexture_SetDirty((IWineD3DBaseTexture *)targetContainer, TRUE);
4355 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *)targetContainer);
4356 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4357 IUnknown_Release(targetContainer);
4359 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)){
4360 /* The surface is stand-alone, so doesn't currently have a context of it's own */
4361 TRACE("(%p) : standalone rendertarget %p\n", This, This->renderTarget);
4362 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4363 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4364 IWineD3DSurface_PreLoad(This->renderTarget);
4365 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4366 IUnknown_Release(targetContainer);
4375 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4376 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4377 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4378 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4379 IWineD3DSwapChain *swapChain = NULL;
4381 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4383 TRACE("(%p) Presenting the frame\n", This);
4385 for(i = 0 ; i < swapchains ; i ++){
4387 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4388 TRACE("presentinng chain %d, %p\n", i, swapChain);
4389 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4390 IWineD3DSwapChain_Release(swapChain);
4396 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4397 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4398 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4400 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4401 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4402 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4403 GLbitfield glMask = 0;
4404 GLboolean old_ztest;
4405 GLfloat old_z_clear_value;
4406 GLint old_stencil_clear_value;
4407 GLfloat old_color_clear_value[4];
4409 CONST D3DRECT* curRect;
4411 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4412 Count, pRects, Flags, Z, Stencil);
4416 glEnable(GL_SCISSOR_TEST);
4417 checkGLcall("glEnable GL_SCISSOR_TEST");
4419 if (Count > 0 && pRects) {
4425 /* Only set the values up once, as they are not changing */
4426 if (Flags & D3DCLEAR_STENCIL) {
4427 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4428 glClearStencil(Stencil);
4429 checkGLcall("glClearStencil");
4430 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4431 glStencilMask(0xFFFFFFFF);
4434 if (Flags & D3DCLEAR_ZBUFFER) {
4435 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4436 glDepthMask(GL_TRUE);
4437 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4439 checkGLcall("glClearDepth");
4440 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4443 if (Flags & D3DCLEAR_TARGET) {
4444 TRACE("Clearing screen with glClear to color %lx\n", Color);
4445 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4446 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
4447 ((Color >> 8) & 0xFF) / 255.0f,
4448 ((Color >> 0) & 0xFF) / 255.0f,
4449 ((Color >> 24) & 0xFF) / 255.0f);
4450 checkGLcall("glClearColor");
4452 /* Clear ALL colors! */
4453 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4454 glMask = glMask | GL_COLOR_BUFFER_BIT;
4457 /* Now process each rect in turn */
4458 for (i = 0; i < Count || i == 0; i++) {
4461 /* Note gl uses lower left, width/height */
4462 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4463 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4464 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4465 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4466 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4467 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4468 checkGLcall("glScissor");
4470 glScissor(This->stateBlock->viewport.X,
4471 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4472 This->stateBlock->viewport.Width,
4473 This->stateBlock->viewport.Height);
4474 checkGLcall("glScissor");
4477 /* Clear the selected rectangle (or full screen) */
4479 checkGLcall("glClear");
4481 /* Step to the next rectangle */
4482 if (curRect) curRect = curRect + sizeof(D3DRECT);
4485 /* Restore the old values (why..?) */
4486 if (Flags & D3DCLEAR_STENCIL) {
4487 glClearStencil(old_stencil_clear_value);
4488 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4490 if (Flags & D3DCLEAR_ZBUFFER) {
4491 glDepthMask(old_ztest);
4492 glClearDepth(old_z_clear_value);
4494 if (Flags & D3DCLEAR_TARGET) {
4495 glClearColor(old_color_clear_value[0],
4496 old_color_clear_value[1],
4497 old_color_clear_value[2],
4498 old_color_clear_value[3]);
4499 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4500 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4501 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4502 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4505 glDisable(GL_SCISSOR_TEST);
4506 checkGLcall("glDisable");
4515 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4516 UINT PrimitiveCount) {
4518 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4519 This->stateBlock->streamIsUP = FALSE;
4521 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4522 debug_d3dprimitivetype(PrimitiveType),
4523 StartVertex, PrimitiveCount);
4524 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
4529 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4530 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4531 D3DPRIMITIVETYPE PrimitiveType,
4532 INT baseVIndex, UINT minIndex,
4533 UINT NumVertices,UINT startIndex,UINT primCount) {
4535 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4537 IWineD3DIndexBuffer *pIB;
4538 D3DINDEXBUFFER_DESC IdxBufDsc;
4540 pIB = This->stateBlock->pIndexData;
4541 This->stateBlock->streamIsUP = FALSE;
4543 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This,
4544 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4545 minIndex, NumVertices, startIndex, baseVIndex, primCount);
4547 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4548 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4554 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex,
4555 startIndex, idxStride,
4556 ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory,
4562 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4563 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4564 UINT VertexStreamZeroStride) {
4565 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4567 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4568 debug_d3dprimitivetype(PrimitiveType),
4569 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4571 if (This->stateBlock->streamSource[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
4573 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4574 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4575 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4576 This->stateBlock->streamIsUP = TRUE;
4577 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
4578 This->stateBlock->streamStride[0] = 0;
4579 This->stateBlock->streamSource[0] = NULL;
4581 /*stream zero settings set to null at end, as per the msdn */
4585 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4586 UINT MinVertexIndex,
4587 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
4588 WINED3DFORMAT IndexDataFormat, CONST void* pVertexStreamZeroData,
4589 UINT VertexStreamZeroStride) {
4591 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4593 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4594 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4595 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,
4596 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4598 if (This->stateBlock->streamSource[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
4600 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4606 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4607 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4608 This->stateBlock->streamIsUP = TRUE;
4609 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4611 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, idxStride, pIndexData, MinVertexIndex);
4613 /* stream zero settings set to null at end as per the msdn */
4614 This->stateBlock->streamSource[0] = NULL;
4615 This->stateBlock->streamStride[0] = 0;
4616 IWineD3DDevice_SetIndices(iface, NULL, 0);
4621 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4622 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4624 TRACE("(%p) : stub\n", This);
4628 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4629 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4630 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4631 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4633 TRACE("(%p) : stub\n", This);
4636 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface){
4637 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4639 TRACE("(%p) : stub\n", This);
4643 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface){
4644 IWineD3DSwapChain *swapChain;
4646 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4648 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4649 IWineD3DSwapChain_Release(swapChain);
4654 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4655 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4656 /* return a sensible default */
4658 FIXME("(%p) : stub\n", This);
4662 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4663 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4664 FIXME("(%p) : stub\n", This);
4668 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4669 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4670 FIXME("(%p) : stub\n", This);
4674 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4675 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4676 FIXME("(%p) : stub\n", This);
4680 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4681 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4682 FIXME("(%p) : stub\n", This);
4686 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4687 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4688 FIXME("(%p) : stub\n", This);
4693 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4694 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4695 FIXME("(%p) : stub\n", This);
4700 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
4701 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4703 pRasterStatus->InVBlank = TRUE;
4704 pRasterStatus->ScanLine = 0;
4705 FIXME("(%p) : stub\n", This);
4710 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4711 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4712 static BOOL showfixmes = TRUE;
4713 if(nSegments != 0.0f){
4715 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4722 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4723 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4724 static BOOL showfixmes = TRUE;
4726 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4733 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4734 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4735 FIXME("(%p) : stub\n", This);
4740 /* Implementation details at http://developer.nvidia.com/attach/6494
4742 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
4743 hmm.. no longer supported use
4744 OpenGL evaluators or tessellate surfaces within your application.
4747 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
4748 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo){
4749 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4750 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p) \n", This, Handle, pNumSegs, pRectPatchInfo);
4751 FIXME("(%p) : Stub\n", This);
4756 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
4757 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo){
4758 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4759 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p) \n", This, Handle, pNumSegs, pTriPatchInfo);
4760 FIXME("(%p) : Stub\n", This);
4764 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle){
4765 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4766 TRACE("(%p) Handle(%d)\n", This, Handle);
4767 FIXME("(%p) : Stub\n", This);
4771 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color){
4772 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4774 FIXME("(%p) : stub\n", This);
4778 /* rendertarget and deptth stencil functions */
4779 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget){
4780 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4782 /* FIXME: Implelent RenderTargetIndex >0 */
4783 if(RenderTargetIndex > 0)
4784 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
4786 *ppRenderTarget = (IWineD3DSurface *)This->renderTarget;
4787 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
4788 /* Note inc ref on returned surface */
4789 if(*ppRenderTarget != NULL)
4790 IWineD3DSurface_AddRef(*ppRenderTarget);
4794 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface){
4795 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4796 *ppZStencilSurface = (IWineD3DSurface *)This->depthStencilBuffer;
4797 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
4799 if(*ppZStencilSurface != NULL){
4800 /* Note inc ref on returned surface */
4801 IWineD3DSurface_AddRef(*ppZStencilSurface);
4806 /* internal static helper functions */
4807 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
4808 IWineD3DSurface *RenderSurface);
4810 HRESULT WINAPI static IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain);
4812 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget){
4813 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4814 HRESULT hr = D3D_OK;
4815 WINED3DVIEWPORT viewport;
4817 TRACE("(%p) Swapping rendertarget\n",This);
4818 if (RenderTargetIndex>0) {
4819 FIXME("(%p) Render targets other than the first are not supported\n",This);
4820 RenderTargetIndex=0;
4823 /* MSDN says that null disables the render target
4824 but a device must always be associated with a render target
4825 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
4827 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
4830 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
4831 FIXME("Trying to set render target 0 to NULL\n");
4832 return D3DERR_INVALIDCALL;
4834 /* TODO: raplce Impl* usage with interface usage */
4835 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & D3DUSAGE_RENDERTARGET) {
4836 FIXME("(%p)Trying to set the render target to a surface(%p) that wasn't created with a usage of D3DUSAGE_RENDERTARGET\n",This ,pRenderTarget);
4837 return D3DERR_INVALIDCALL;
4839 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
4840 * builds, but I think wine counts as a 'debug' build for now.
4841 ******************************/
4842 /* If we are trying to set what we already have, don't bother */
4843 if (pRenderTarget == This->renderTarget) {
4844 TRACE("Trying to do a NOP SetRenderTarget operation\n");
4846 /* Otherwise, set the render target up */
4847 TRACE("clearing renderer\n");
4848 /* IWineD3DDeviceImpl_CleanRender(iface); */
4849 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
4850 depending on the renter target implementation being used.
4851 A shared context implementation will share all buffers between all rendertargets (including swapchains),
4852 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
4853 stencil buffer and incure an extra memory overhead */
4854 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
4857 if (SUCCEEDED(hr)) {
4858 /* Finally, reset the viewport as the MSDN states. */
4859 /* TODO: Replace impl usage */
4860 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
4861 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
4864 viewport.MaxZ = 1.0f;
4865 viewport.MinZ = 0.0f;
4866 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
4868 FIXME("Unknown error setting the render target\n");
4873 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil){
4874 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4875 HRESULT hr = D3D_OK;
4876 WINED3DVIEWPORT viewport;
4877 IWineD3DSurface *tmp;
4879 TRACE("(%p) Swapping z-buffer\n",This);
4881 if (pNewZStencil == This->stencilBufferTarget){
4882 TRACE("Trying to do a NOP SetRenderTarget operation\n");
4884 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
4885 * depending on the renter target implementation being used.
4886 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
4887 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
4888 * stencil buffer and incure an extra memory overhead
4889 ******************************************************/
4892 tmp = This->stencilBufferTarget;
4893 This->stencilBufferTarget = pNewZStencil;
4894 /* should we be calling the parent or the wined3d surface? */
4895 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
4896 if (NULL != tmp) IWineD3DSurface_Release(tmp);
4898 /** TODO: glEnable/glDisable on depth/stencil depending on
4899 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
4900 **********************************************************/
4903 if (SUCCEEDED(hr)) {
4904 /* Finally, reset the viewport as the MSDN states.*/
4905 /* TODO: get ridd of Impl usage */
4906 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
4907 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
4910 viewport.MaxZ = 1.0f;
4911 viewport.MinZ = 0.0f;
4912 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
4919 /* Internal functions not in DirectX */
4920 /** TODO: move this off to the opengl context manager
4921 *(the swapchain doesn't need to know anything about offscreen rendering!)
4922 ****************************************************/
4924 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
4926 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4927 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
4929 TRACE("(%p), %p\n", This, swapchain);
4931 if (swapchain->win != swapchain->drawable) {
4933 if (swapchain->glCtx != swapchain->render_ctx) {
4934 FIXME("Destroying context %p \n", swapchain->render_ctx);
4935 glXDestroyContext(swapchain->display, swapchain->render_ctx);
4938 FIXME("glXDestroyPbuffer %ld \n", swapchain->drawable);
4939 glXDestroyPbuffer(swapchain->display, swapchain->drawable);
4942 /* Set everything back the way it ws */
4943 swapchain->render_ctx = swapchain->glCtx;
4944 swapchain->drawable = swapchain->win;
4949 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
4950 * the functionality needs splitting up so that we don't do more than we should do.
4951 * this only seems to impact performance a little.
4952 ******************************/
4953 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
4954 IWineD3DSurface *RenderSurface) {
4955 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4956 #ifndef USE_RENDER_MANAGER
4958 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
4959 HRESULT ret = D3DERR_INVALIDCALL;
4961 * Currently only active for GLX >= 1.3
4962 * for others versions we'll have to use GLXPixmaps
4964 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
4965 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
4966 * so only check OpenGL version
4967 * ..........................
4968 * I don't believe that it is a problem with NVidia headers,
4969 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
4970 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
4972 * Your application will report GLX version 1.2 on glXQueryVersion.
4973 * However, it is safe to call the GLX 1.3 functions as described below.
4975 #if defined(GL_VERSION_1_3)
4977 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
4978 GLXFBConfig* cfgs = NULL;
4982 IWineD3DSwapChain *currentSwapchain;
4983 IWineD3DSwapChainImpl *swapchain;
4984 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
4985 * but switch them off if the StencilSurface is set to NULL
4986 ** *********************************************************/
4987 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
4988 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
4990 UINT Width = ((IWineD3DSurfaceImpl *) RenderSurface)->currentDesc.Width;
4991 UINT Height = ((IWineD3DSurfaceImpl *) RenderSurface)->currentDesc.Height;
4993 IWineD3DSurface *tmp;
4996 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
4997 it StencilSurface != NULL && zBufferTarget == NULL switch it on
5000 #define PUSH1(att) attribs[nAttribs++] = (att);
5001 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
5003 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
5005 /** TODO: remove the reff to Impl (context manager should fix this!) **/
5006 IWineD3DSwapChainImpl *impSwapChain;
5007 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
5008 if (NULL == impSwapChain){ /* NOTE: This should NEVER fail */
5009 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
5014 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
5015 PUSH2(GLX_X_RENDERABLE, TRUE);
5016 PUSH2(GLX_DOUBLEBUFFER, TRUE);
5017 TRACE("calling makeglcfg\n");
5018 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
5023 TRACE("calling chooseFGConfig\n");
5024 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5027 if (!cfgs){ /* OK we didn't find the exact config, so use any reasonable match */
5028 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
5029 why we failed and only show this message once! */
5030 MESSAGE("Failed to find exact match, finding alternative but you may suffer performance issues, try changing xfree's depth to match the requested depth\n"); /**/
5032 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
5033 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
5034 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
5035 PUSH2(GLX_DOUBLEBUFFER, FALSE);
5036 TRACE("calling makeglcfg\n");
5037 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
5039 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5046 for (i = 0; i < nCfgs; ++i) {
5047 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
5048 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
5049 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
5053 if (NULL != This->renderTarget) {
5056 vcheckGLcall("glFlush");
5057 /** This is only useful if the old render target was a swapchain,
5058 * we need to supercede this with a function that displays
5059 * the current buffer on the screen. This is easy to do in glx1.3 but
5060 * we need to do copy-write pixels in glx 1.2.
5061 ************************************************/
5062 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
5064 printf("Hit Enter to get next frame ...\n");
5069 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain) != D3D_OK){
5070 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
5071 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
5075 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
5076 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
5077 **********************************************************************/
5078 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == D3D_OK){
5079 /* We also need to make sure that the lights &co are also in the context of the swapchains */
5080 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
5081 TRACE("making swapchain active\n");
5082 if (RenderSurface != This->renderTarget){
5083 if (RenderSurface == swapchain->backBuffer){
5085 /* This could be flagged so that some operations work directly with the front buffer */
5086 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
5088 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
5090 TRACE("Error in setting current context: context %p drawable %ld !\n",
5091 impSwapChain->glCtx, impSwapChain->win);
5095 #if 0 /* TODO: apply the state block to the 'possibly' new context. */
5097 IWineD3DStateBlockImpl *oldUpdateStateBlock;
5098 oldUpdateStateBlock = This->updateStateBlock;
5099 oldRecording= This->isRecordingState;
5100 This->isRecordingState = FALSE;
5101 This->updateStateBlock = This->stateBlock;
5102 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
5104 This->isRecordingState = oldRecording;
5105 This->updateStateBlock = oldUpdateStateBlock;
5108 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5110 checkGLcall("glXMakeContextCurrent");
5112 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5117 (((IWineD3DSwapChainImpl *)currentSwapchain)->drawable == ((IWineD3DSwapChainImpl *)currentSwapchain)->win
5118 || BackBufferFormat != ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Format
5119 || (Width > ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width
5120 || Height > ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height))) {
5122 /** ********************************************************************
5123 * This code is far too leaky to be useful. IWineD3DDeviceImpl_CleanRender
5124 * doesn't seem to work properly and creating a new context every time is 'extremely' overkill.
5125 * The code does however work, and should be moved to a context manager to
5126 * manage caching of pbuffers or render to texture are appropriate.
5128 * There are some real speed vs compatibility issues here:
5129 * we should really use a new context for every texture, but that eats ram.
5130 * we should also be restoring the texture to the pbuffer but that eats CPU
5131 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
5132 * but if this means reusing the display backbuffer then we need to make sure that
5133 * states are correctly preserved.
5134 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
5135 * and gain a good performance increase at the cost of compatibility.
5136 * I would suggest that, when this is the case, a user configurable flag be made
5137 * available, allowing the user to choose the best emulated experience for them.
5138 *********************************************************************/
5141 * TODO: support for faces of cube textures, possibly volumes
5142 * (this should be easy for ATI as I have examples)
5145 GLXContext newContext;
5146 Drawable newDrawable;
5147 XVisualInfo *visinfo;
5149 TRACE("making new buffer\n");
5151 PUSH2(GLX_PBUFFER_WIDTH, Width);
5152 PUSH2(GLX_PBUFFER_HEIGHT, Height);
5154 #if 0 /* ATI render to texture support */
5155 PUSH2(GLX_LARGEST_PBUFFER, True);/* This is ignored by ATI */
5156 PUSH2(GLX_TEXTURE_FORMAT_ATI, GLX_TEXTURE_RGBA_ATI);
5157 PUSH2(GLX_TEXTURE_TARGET_ATI, cubemap? GLX_TEXTURE_CUBE_MAP_ATI : GLX_TEXTURE_2D_ATI);
5158 PUSH2(GLX_MIPMAP_TEXTURE_ATI, mipmapped? True : False);
5162 /* TODO: discardable Pbuffer */
5163 PUSH2(GLX_PRESERVED_CONTENTS, FALSE);
5167 newDrawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
5169 /** ****************************************
5170 *GLX1.3 isn't supported by XFree 'yet' untill that point ATI emulates pBuffers
5172 * In future releases, we may provide the calls glXCreateNewContext,
5173 * glXQueryDrawable and glXMakeContextCurrent.
5174 * so until then we have to use glXGetVisualFromFBConfig &co..
5175 ********************************************/
5178 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
5180 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
5182 newContext = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
5185 /* Make sure that the sorface exists as a glTexture */
5186 IWineD3DSurface_PreLoad(RenderSurface);
5188 newContext = glXCreateNewContext(impSwapChain->display, cfgs[0], GLX_RGBA_TYPE, impSwapChain->glCtx, TRUE);
5190 if (NULL == newContext) {
5191 ERR("cannot create glxContext\n");
5193 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
5194 FIXME("Created context %p drawable %ld \n", newContext, newDrawable);
5196 if (glXMakeCurrent(impSwapChain->display, newDrawable, newContext) == False) {
5198 TRACE("Error in setting current context: context %p drawable %ld\n", newContext, newDrawable);
5201 /* TODO: find out what of the current context needs to be coppied accross */
5203 checkGLcall("glXMakeContextCurrent");
5205 /* clean renderer should become part of the context manager so I'm not goint to put in in SwapChain just to remove it */
5206 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5207 /** TODO: We may need to copy the bits into the buffer,
5208 * this should !!ONLY!! be done if an operation is performed on the target
5209 * without it being cleared and the buffer is not discardable.
5210 * (basically only bother preserving the contents if there's a possibility that it will be reused)
5211 ** *********************************************************************/
5212 impSwapChain->drawable = newDrawable;
5213 impSwapChain->render_ctx = newContext;
5219 /* clean up the current rendertargets swapchain (if it belonged to one) */
5220 if (currentSwapchain != NULL){
5221 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
5224 /* Were done with the opengl context management, setup the rendertargets */
5226 tmp = This->renderTarget;
5227 This->renderTarget = RenderSurface;
5228 IWineD3DSurface_AddRef(This->renderTarget);
5229 IWineD3DSurface_Release(tmp);
5235 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
5236 /* Check that the container is not a swapchain member */
5238 IWineD3DSwapChain *tmpSwapChain;
5239 if (D3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)){
5240 This->renderUpsideDown = TRUE;
5242 This->renderUpsideDown = FALSE;
5243 IWineD3DSwapChain_Release(tmpSwapChain);
5245 /* Force updating the cull mode */
5246 TRACE("setting render state\n");
5247 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
5248 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
5250 /* Force updating projection matrix */
5251 This->last_was_rhw = FALSE;
5252 This->proj_valid = FALSE;
5260 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
5261 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
5266 if ( NULL != impSwapChain) {
5267 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
5274 IWineD3DSurface *tmp;
5275 /* This should be handled outside of this function */
5276 tmp = This->renderTarget;
5277 This->renderTarget = RenderSurface;
5278 IWineD3DSurface_AddRef(This->renderTarget);
5279 IWineD3DSurface_Release( tmp);
5280 tmp = This->stencilBufferTarget;
5281 This->stencilBufferTarget = StencilSurface;
5288 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5289 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5290 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5291 /* TODO: the use of Impl is deprecated. */
5292 /* some basic validation checks */
5293 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5295 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5297 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
5298 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
5299 return D3DERR_INVALIDCALL;
5301 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
5302 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
5303 return D3DERR_INVALIDCALL;
5305 /* TODO: make the cursor 'real' */
5307 This->xHotSpot = XHotSpot;
5308 This->yHotSpot = YHotSpot;
5313 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5314 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5315 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5317 This->xScreenSpace = XScreenSpace;
5318 This->yScreenSpace = YScreenSpace;
5324 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5325 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5326 TRACE("(%p) : visible(%d)\n", This, bShow);
5328 This->bCursorVisible = bShow;
5333 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
5334 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5335 FIXME("(%p) : stub\n", This); /* No way of notifying yet! */
5340 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
5341 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5342 /** FIXME: Resource tracking needs to be done,
5343 * The closes we can do to this is set the priorities of all managed textures low
5344 * and then reset them.
5345 ***********************************************************/
5346 FIXME("(%p) : stub\n", This);
5350 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
5351 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5352 /** FIXME: Resource trascking needs to be done.
5353 * in effect this pulls all non only default
5354 * textures out of video memory and deletes all glTextures (glDeleteTextures)
5355 * and should clear down the context and set it up according to pPresentationParameters
5356 ***********************************************************/
5357 FIXME("(%p) : stub\n", This);
5361 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs){
5362 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5363 /** FIXME: always true at the moment **/
5364 if(bEnableDialogs == FALSE){
5365 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
5371 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
5372 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5374 FIXME("(%p) : stub\n", This);
5375 /* Setup some reasonable defaults */
5376 pParameters->AdapterOrdinal = 0; /* always for now */
5377 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
5378 pParameters->hFocusWindow = 0;
5379 pParameters->BehaviorFlags =0;
5383 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
5384 IWineD3DSwapChain *swapchain;
5385 HRESULT hrc = D3D_OK;
5387 TRACE("Relaying to swapchain\n");
5389 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK){
5390 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
5391 IWineD3DSwapChain_Release(swapchain);
5396 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
5397 IWineD3DSwapChain *swapchain;
5398 HRESULT hrc = D3D_OK;
5400 TRACE("Relaying to swapchain\n");
5402 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK){
5403 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
5404 IWineD3DSwapChain_Release(swapchain);
5409 /**********************************************************
5410 * IWineD3DDevice VTbl follows
5411 **********************************************************/
5413 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
5415 /*** IUnknown methods ***/
5416 IWineD3DDeviceImpl_QueryInterface,
5417 IWineD3DDeviceImpl_AddRef,
5418 IWineD3DDeviceImpl_Release,
5419 /*** IWineD3DDevice methods ***/
5420 IWineD3DDeviceImpl_GetParent,
5421 /*** Creation methods**/
5422 IWineD3DDeviceImpl_CreateVertexBuffer,
5423 IWineD3DDeviceImpl_CreateIndexBuffer,
5424 IWineD3DDeviceImpl_CreateStateBlock,
5425 IWineD3DDeviceImpl_CreateSurface,
5426 IWineD3DDeviceImpl_CreateTexture,
5427 IWineD3DDeviceImpl_CreateVolumeTexture,
5428 IWineD3DDeviceImpl_CreateVolume,
5429 IWineD3DDeviceImpl_CreateCubeTexture,
5430 IWineD3DDeviceImpl_CreateQuery,
5431 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
5432 IWineD3DDeviceImpl_CreateVertexDeclaration,
5433 IWineD3DDeviceImpl_CreateVertexShader,
5434 IWineD3DDeviceImpl_CreatePixelShader,
5436 /*** Odd functions **/
5437 IWineD3DDeviceImpl_EvictManagedResources,
5438 IWineD3DDeviceImpl_GetAvailableTextureMem,
5439 IWineD3DDeviceImpl_GetBackBuffer,
5440 IWineD3DDeviceImpl_GetCreationParameters,
5441 IWineD3DDeviceImpl_GetDeviceCaps,
5442 IWineD3DDeviceImpl_GetDirect3D,
5443 IWineD3DDeviceImpl_GetDisplayMode,
5444 IWineD3DDeviceImpl_GetNumberOfSwapChains,
5445 IWineD3DDeviceImpl_GetRasterStatus,
5446 IWineD3DDeviceImpl_GetSwapChain,
5447 IWineD3DDeviceImpl_Reset,
5448 IWineD3DDeviceImpl_SetDialogBoxMode,
5449 IWineD3DDeviceImpl_SetCursorProperties,
5450 IWineD3DDeviceImpl_SetCursorPosition,
5451 IWineD3DDeviceImpl_ShowCursor,
5452 IWineD3DDeviceImpl_TestCooperativeLevel,
5453 /*** Getters and setters **/
5454 IWineD3DDeviceImpl_SetClipPlane,
5455 IWineD3DDeviceImpl_GetClipPlane,
5456 IWineD3DDeviceImpl_SetClipStatus,
5457 IWineD3DDeviceImpl_GetClipStatus,
5458 IWineD3DDeviceImpl_SetCurrentTexturePalette,
5459 IWineD3DDeviceImpl_GetCurrentTexturePalette,
5460 IWineD3DDeviceImpl_SetDepthStencilSurface,
5461 IWineD3DDeviceImpl_GetDepthStencilSurface,
5462 IWineD3DDeviceImpl_SetFVF,
5463 IWineD3DDeviceImpl_GetFVF,
5464 IWineD3DDeviceImpl_SetGammaRamp,
5465 IWineD3DDeviceImpl_GetGammaRamp,
5466 IWineD3DDeviceImpl_SetIndices,
5467 IWineD3DDeviceImpl_GetIndices,
5468 IWineD3DDeviceImpl_SetLight,
5469 IWineD3DDeviceImpl_GetLight,
5470 IWineD3DDeviceImpl_SetLightEnable,
5471 IWineD3DDeviceImpl_GetLightEnable,
5472 IWineD3DDeviceImpl_SetMaterial,
5473 IWineD3DDeviceImpl_GetMaterial,
5474 IWineD3DDeviceImpl_SetNPatchMode,
5475 IWineD3DDeviceImpl_GetNPatchMode,
5476 IWineD3DDeviceImpl_SetPaletteEntries,
5477 IWineD3DDeviceImpl_GetPaletteEntries,
5478 IWineD3DDeviceImpl_SetPixelShader,
5479 IWineD3DDeviceImpl_GetPixelShader,
5480 IWineD3DDeviceImpl_SetPixelShaderConstantB,
5481 IWineD3DDeviceImpl_GetPixelShaderConstantB,
5482 IWineD3DDeviceImpl_SetPixelShaderConstantI,
5483 IWineD3DDeviceImpl_GetPixelShaderConstantI,
5484 IWineD3DDeviceImpl_SetPixelShaderConstantF,
5485 IWineD3DDeviceImpl_GetPixelShaderConstantF,
5486 IWineD3DDeviceImpl_SetRenderState,
5487 IWineD3DDeviceImpl_GetRenderState,
5488 IWineD3DDeviceImpl_SetRenderTarget,
5489 IWineD3DDeviceImpl_GetRenderTarget,
5490 IWineD3DDeviceImpl_SetSamplerState,
5491 IWineD3DDeviceImpl_GetSamplerState,
5492 IWineD3DDeviceImpl_SetScissorRect,
5493 IWineD3DDeviceImpl_GetScissorRect,
5494 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
5495 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
5496 IWineD3DDeviceImpl_SetStreamSource,
5497 IWineD3DDeviceImpl_GetStreamSource,
5498 IWineD3DDeviceImpl_SetStreamSourceFreq,
5499 IWineD3DDeviceImpl_GetStreamSourceFreq,
5500 IWineD3DDeviceImpl_SetTexture,
5501 IWineD3DDeviceImpl_GetTexture,
5502 IWineD3DDeviceImpl_SetTextureStageState,
5503 IWineD3DDeviceImpl_GetTextureStageState,
5504 IWineD3DDeviceImpl_SetTransform,
5505 IWineD3DDeviceImpl_GetTransform,
5506 IWineD3DDeviceImpl_SetVertexDeclaration,
5507 IWineD3DDeviceImpl_GetVertexDeclaration,
5508 IWineD3DDeviceImpl_SetVertexShader,
5509 IWineD3DDeviceImpl_GetVertexShader,
5510 IWineD3DDeviceImpl_SetVertexShaderConstantB,
5511 IWineD3DDeviceImpl_GetVertexShaderConstantB,
5512 IWineD3DDeviceImpl_SetVertexShaderConstantI,
5513 IWineD3DDeviceImpl_GetVertexShaderConstantI,
5514 IWineD3DDeviceImpl_SetVertexShaderConstantF,
5515 IWineD3DDeviceImpl_GetVertexShaderConstantF,
5516 IWineD3DDeviceImpl_SetViewport,
5517 IWineD3DDeviceImpl_GetViewport,
5518 IWineD3DDeviceImpl_MultiplyTransform,
5519 IWineD3DDeviceImpl_ValidateDevice,
5520 IWineD3DDeviceImpl_ProcessVertices,
5521 /*** State block ***/
5522 IWineD3DDeviceImpl_BeginStateBlock,
5523 IWineD3DDeviceImpl_EndStateBlock,
5524 /*** Scene management ***/
5525 IWineD3DDeviceImpl_BeginScene,
5526 IWineD3DDeviceImpl_EndScene,
5527 IWineD3DDeviceImpl_Present,
5528 IWineD3DDeviceImpl_Clear,
5530 IWineD3DDeviceImpl_DrawPrimitive,
5531 IWineD3DDeviceImpl_DrawIndexedPrimitive,
5532 IWineD3DDeviceImpl_DrawPrimitiveUP,
5533 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
5534 IWineD3DDeviceImpl_DrawRectPatch,
5535 IWineD3DDeviceImpl_DrawTriPatch,
5536 IWineD3DDeviceImpl_DeletePatch,
5537 IWineD3DDeviceImpl_ColorFill,
5538 IWineD3DDeviceImpl_UpdateTexture,
5539 IWineD3DDeviceImpl_UpdateSurface,
5540 IWineD3DDeviceImpl_StretchRect,
5541 IWineD3DDeviceImpl_GetRenderTargetData,
5542 IWineD3DDeviceImpl_GetFrontBufferData,
5543 /*** Internal use IWineD3DDevice methods ***/
5544 IWineD3DDeviceImpl_SetupTextureStates
5548 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
5549 WINED3DRS_ALPHABLENDENABLE ,
5550 WINED3DRS_ALPHAFUNC ,
5551 WINED3DRS_ALPHAREF ,
5552 WINED3DRS_ALPHATESTENABLE ,
5554 WINED3DRS_COLORWRITEENABLE ,
5555 WINED3DRS_DESTBLEND ,
5556 WINED3DRS_DITHERENABLE ,
5557 WINED3DRS_FILLMODE ,
5558 WINED3DRS_FOGDENSITY ,
5560 WINED3DRS_FOGSTART ,
5561 WINED3DRS_LASTPIXEL ,
5562 WINED3DRS_SHADEMODE ,
5563 WINED3DRS_SRCBLEND ,
5564 WINED3DRS_STENCILENABLE ,
5565 WINED3DRS_STENCILFAIL ,
5566 WINED3DRS_STENCILFUNC ,
5567 WINED3DRS_STENCILMASK ,
5568 WINED3DRS_STENCILPASS ,
5569 WINED3DRS_STENCILREF ,
5570 WINED3DRS_STENCILWRITEMASK ,
5571 WINED3DRS_STENCILZFAIL ,
5572 WINED3DRS_TEXTUREFACTOR ,
5583 WINED3DRS_ZWRITEENABLE
5586 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
5587 WINED3DTSS_ADDRESSW ,
5588 WINED3DTSS_ALPHAARG0 ,
5589 WINED3DTSS_ALPHAARG1 ,
5590 WINED3DTSS_ALPHAARG2 ,
5591 WINED3DTSS_ALPHAOP ,
5592 WINED3DTSS_BUMPENVLOFFSET ,
5593 WINED3DTSS_BUMPENVLSCALE ,
5594 WINED3DTSS_BUMPENVMAT00 ,
5595 WINED3DTSS_BUMPENVMAT01 ,
5596 WINED3DTSS_BUMPENVMAT10 ,
5597 WINED3DTSS_BUMPENVMAT11 ,
5598 WINED3DTSS_COLORARG0 ,
5599 WINED3DTSS_COLORARG1 ,
5600 WINED3DTSS_COLORARG2 ,
5601 WINED3DTSS_COLOROP ,
5602 WINED3DTSS_RESULTARG ,
5603 WINED3DTSS_TEXCOORDINDEX ,
5604 WINED3DTSS_TEXTURETRANSFORMFLAGS
5607 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
5608 WINED3DSAMP_ADDRESSU ,
5609 WINED3DSAMP_ADDRESSV ,
5610 WINED3DSAMP_ADDRESSW ,
5611 WINED3DSAMP_BORDERCOLOR ,
5612 WINED3DSAMP_MAGFILTER ,
5613 WINED3DSAMP_MINFILTER ,
5614 WINED3DSAMP_MIPFILTER ,
5615 WINED3DSAMP_MIPMAPLODBIAS ,
5616 WINED3DSAMP_MAXMIPLEVEL ,
5617 WINED3DSAMP_MAXANISOTROPY ,
5618 WINED3DSAMP_SRGBTEXTURE ,
5619 WINED3DSAMP_ELEMENTINDEX
5622 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
5624 WINED3DRS_AMBIENTMATERIALSOURCE ,
5625 WINED3DRS_CLIPPING ,
5626 WINED3DRS_CLIPPLANEENABLE ,
5627 WINED3DRS_COLORVERTEX ,
5628 WINED3DRS_DIFFUSEMATERIALSOURCE ,
5629 WINED3DRS_EMISSIVEMATERIALSOURCE ,
5630 WINED3DRS_FOGDENSITY ,
5632 WINED3DRS_FOGSTART ,
5633 WINED3DRS_FOGTABLEMODE ,
5634 WINED3DRS_FOGVERTEXMODE ,
5635 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
5636 WINED3DRS_LIGHTING ,
5637 WINED3DRS_LOCALVIEWER ,
5638 WINED3DRS_MULTISAMPLEANTIALIAS ,
5639 WINED3DRS_MULTISAMPLEMASK ,
5640 WINED3DRS_NORMALIZENORMALS ,
5641 WINED3DRS_PATCHEDGESTYLE ,
5642 WINED3DRS_POINTSCALE_A ,
5643 WINED3DRS_POINTSCALE_B ,
5644 WINED3DRS_POINTSCALE_C ,
5645 WINED3DRS_POINTSCALEENABLE ,
5646 WINED3DRS_POINTSIZE ,
5647 WINED3DRS_POINTSIZE_MAX ,
5648 WINED3DRS_POINTSIZE_MIN ,
5649 WINED3DRS_POINTSPRITEENABLE ,
5650 WINED3DRS_RANGEFOGENABLE ,
5651 WINED3DRS_SPECULARMATERIALSOURCE ,
5652 WINED3DRS_TWEENFACTOR ,
5653 WINED3DRS_VERTEXBLEND
5656 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
5657 WINED3DTSS_TEXCOORDINDEX ,
5658 WINED3DTSS_TEXTURETRANSFORMFLAGS
5661 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
5662 WINED3DSAMP_DMAPOFFSET