wined3d: Move the projection matrix into its own state.
[wine] / dlls / wined3d / swapchain.c
1 /*
2  *IDirect3DSwapChain9 implementation
3  *
4  *Copyright 2002-2003 Jason Edmeades
5  *Copyright 2002-2003 Raphael Junqueira
6  *Copyright 2005 Oliver Stieber
7  *
8  *This library is free software; you can redistribute it and/or
9  *modify it under the terms of the GNU Lesser General Public
10  *License as published by the Free Software Foundation; either
11  *version 2.1 of the License, or (at your option) any later version.
12  *
13  *This library is distributed in the hope that it will be useful,
14  *but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  *Lesser General Public License for more details.
17  *
18  *You should have received a copy of the GNU Lesser General Public
19  *License along with this library; if not, write to the Free Software
20  *Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include "config.h"
24 #include "wined3d_private.h"
25
26
27 /* TODO: move to shared header (or context manager )*/
28 /* x11drv GDI escapes */
29 #define X11DRV_ESCAPE 6789
30 enum x11drv_escape_codes
31 {
32     X11DRV_GET_DISPLAY,   /* get X11 display for a DC */
33     X11DRV_GET_DRAWABLE,  /* get current drawable for a DC */
34     X11DRV_GET_FONT,      /* get current X font for a DC */
35 };
36
37 /* retrieve the X display to use on a given DC */
38 inline static Display *get_display( HDC hdc )
39 {
40     Display *display;
41     enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
42
43     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
44                     sizeof(display), (LPSTR)&display )) display = NULL;
45     return display;
46 }
47
48 /*TODO: some of the additional parameters may be required to
49     set the gamma ramp (for some weird reason microsoft have left swap gammaramp in device
50     but it operates on a swapchain, it may be a good idea to move it to IWineD3DSwapChain for IWineD3D)*/
51
52
53 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
54 WINE_DECLARE_DEBUG_CHANNEL(fps);
55
56
57 /* IDirect3DSwapChain IUnknown parts follow: */
58 static ULONG WINAPI IWineD3DSwapChainImpl_AddRef(IWineD3DSwapChain *iface) {
59     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
60     DWORD refCount = InterlockedIncrement(&This->ref);
61     TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
62     return refCount;
63 }
64
65 static HRESULT WINAPI IWineD3DSwapChainImpl_QueryInterface(IWineD3DSwapChain *iface, REFIID riid, LPVOID *ppobj)
66 {
67     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
68     TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppobj);
69     if (IsEqualGUID(riid, &IID_IUnknown)
70         || IsEqualGUID(riid, &IID_IWineD3DBase)
71         || IsEqualGUID(riid, &IID_IWineD3DSwapChain)){
72         IWineD3DSwapChainImpl_AddRef(iface);
73         if(ppobj == NULL){
74             ERR("Query interface called but now data allocated\n");
75             return E_NOINTERFACE;
76         }
77         *ppobj = This;
78         return WINED3D_OK;
79     }
80     *ppobj = NULL;
81     return E_NOINTERFACE;
82 }
83
84
85 static ULONG WINAPI IWineD3DSwapChainImpl_Release(IWineD3DSwapChain *iface) {
86     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
87     DWORD refCount;
88     refCount = InterlockedDecrement(&This->ref);
89     TRACE("(%p) : ReleaseRef to %d\n", This, refCount);
90     if (refCount == 0) {
91         IWineD3DSwapChain_Destroy(iface, D3DCB_DefaultDestroySurface);
92     }
93     return refCount;
94 }
95
96 static HRESULT WINAPI IWineD3DSwapChainImpl_GetParent(IWineD3DSwapChain *iface, IUnknown ** ppParent){
97     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
98     *ppParent = This->parent;
99     IUnknown_AddRef(*ppParent);
100     TRACE("(%p) returning %p\n", This , *ppParent);
101     return WINED3D_OK;
102 }
103
104 /*IWineD3DSwapChain parts follow: */
105 static void WINAPI IWineD3DSwapChainImpl_Destroy(IWineD3DSwapChain *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroyRenderTarget) {
106     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
107
108     /* release the ref to the front and back buffer parents */
109     if(This->frontBuffer) {
110         IWineD3DSurface_SetContainer(This->frontBuffer, 0);
111         if(D3DCB_DestroyRenderTarget(This->frontBuffer) > 0) {
112             FIXME("(%p) Something's still holding the front buffer\n",This);
113         }
114     }
115
116     if(This->backBuffer) {
117         int i;
118         for(i = 0; i < This->presentParms.BackBufferCount; i++) {
119             IWineD3DSurface_SetContainer(This->backBuffer[i], 0);
120             if(D3DCB_DestroyRenderTarget(This->backBuffer[i]) > 0) {
121                 FIXME("(%p) Something's still holding the back buffer\n",This);
122             }
123         }
124     }
125
126     /* Clean up the context */
127     /* check that we are the current context first */
128     if(glXGetCurrentContext() == This->glCtx){
129         glXMakeCurrent(This->display, None, NULL);
130     }
131     glXDestroyContext(This->display, This->glCtx);
132     /* IUnknown_Release(This->parent); This should only apply to the primary swapchain,
133         all others are created by the caller, so releasing the parent should cause
134         the child to be released, not the other way around!
135         */
136     HeapFree(GetProcessHeap(), 0, This);
137 }
138
139 static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CONST RECT *pSourceRect, CONST RECT *pDestRect, HWND hDestWindowOverride, CONST RGNDATA *pDirtyRegion, DWORD dwFlags) {
140     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
141
142     ENTER_GL();
143
144     /* Render the cursor onto the back buffer, using our nifty directdraw blitting code :-) */
145     if(This->wineD3DDevice->bCursorVisible && This->wineD3DDevice->cursorTexture) {
146         IWineD3DSurfaceImpl cursor;
147         RECT destRect = {This->wineD3DDevice->xScreenSpace - This->wineD3DDevice->xHotSpot,
148                          This->wineD3DDevice->yScreenSpace - This->wineD3DDevice->yHotSpot,
149                          This->wineD3DDevice->xScreenSpace + This->wineD3DDevice->cursorWidth - This->wineD3DDevice->xHotSpot,
150                          This->wineD3DDevice->yScreenSpace + This->wineD3DDevice->cursorHeight - This->wineD3DDevice->yHotSpot};
151         TRACE("Rendering the cursor. Creating fake surface at %p\n", &cursor);
152         /* Build a fake surface to call the Blitting code. It is not possible to use the interface passed by
153          * the application because we are only supposed to copy the information out. Using a fake surface
154          * allows to use the Blitting engine and avoid copying the whole texture -> render target blitting code.
155          */
156         memset(&cursor, 0, sizeof(cursor));
157         cursor.lpVtbl = &IWineD3DSurface_Vtbl;
158         cursor.resource.ref = 1;
159         cursor.resource.wineD3DDevice = This->wineD3DDevice;
160         cursor.resource.pool = WINED3DPOOL_SCRATCH;
161         cursor.resource.format = WINED3DFMT_A8R8G8B8;
162         cursor.resource.resourceType = WINED3DRTYPE_SURFACE;
163         cursor.glDescription.textureName = This->wineD3DDevice->cursorTexture;
164         cursor.glDescription.target = GL_TEXTURE_2D;
165         cursor.glDescription.level = 0;
166         cursor.currentDesc.Width = This->wineD3DDevice->cursorWidth;
167         cursor.currentDesc.Height = This->wineD3DDevice->cursorHeight;
168         cursor.glRect.left = 0;
169         cursor.glRect.top = 0;
170         cursor.glRect.right = cursor.currentDesc.Width;
171         cursor.glRect.bottom = cursor.currentDesc.Height;
172         /* The cursor must have pow2 sizes */
173         cursor.pow2Width = cursor.currentDesc.Width;
174         cursor.pow2Height = cursor.currentDesc.Height;
175         /* DDBLT_KEYSRC will cause BltOverride to enable the alpha test with GL_NOTEQUAL, 0.0,
176          * which is exactly what we want :-)
177          */
178         if (This->presentParms.Windowed) {
179             MapWindowPoints(NULL, This->win_handle, (LPPOINT)&destRect, 2);
180         }
181         IWineD3DSurface_Blt(This->backBuffer[0], &destRect, (IWineD3DSurface *) &cursor, NULL, DDBLT_KEYSRC, NULL);
182     }
183
184     if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect);
185     /* TODO: If only source rect or dest rect are supplied then clip the window to match */
186     TRACE("preseting display %p, drawable %ld\n", This->display, This->drawable);
187
188     /* Don't call checkGLcall, as glGetError is not applicable here */
189     if (hDestWindowOverride && This->win_handle != hDestWindowOverride) {
190         /* Set this swapchain up to point to the new destination.. */
191 #ifdef USE_CONTEXT_MANAGER
192             /* TODO: use a context mamager */
193 #endif
194
195             /* FIXME: Never access */
196             IWineD3DSwapChainImpl *swapChainImpl;
197             IWineD3DDevice_GetSwapChain((IWineD3DDevice *)This->wineD3DDevice, 0 , (IWineD3DSwapChain **)&swapChainImpl);
198             FIXME("Unable to render to a destination window %p\n", hDestWindowOverride );
199             if(This == swapChainImpl){
200                 /* FIXME: this will be fixed by moving to a context management system */
201                 FIXME("Cannot change the target of the implicit swapchain\n");
202             }else{
203                 HDC               hDc;
204                 XVisualInfo       template;
205                 int               num;
206                 Display          *oldDisplay = This->display;
207                 GLXContext        oldContext = This->glCtx;
208                 IUnknown*         tmp;
209                 GLXContext        currentContext;
210                 Drawable          currentDrawable;
211                 hDc                          = GetDC(hDestWindowOverride);
212                 This->win_handle             = hDestWindowOverride;
213                 This->win                    = (Window)GetPropA( hDestWindowOverride, "__wine_x11_whole_window" );
214
215                 TRACE("Creating a new context for the window %p\n", hDestWindowOverride);
216                 ENTER_GL();
217                 TRACE("Desctroying context %p %p\n", This->display, This->render_ctx);
218
219
220
221                 LEAVE_GL();
222                 ENTER_GL();
223
224                 This->display    = get_display(hDc);
225                 TRACE("Got display%p  for  %p %p\n",  This->display, hDc, hDestWindowOverride);
226                 ReleaseDC(hDestWindowOverride, hDc);
227                 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
228                 This->visInfo   = XGetVisualInfo(This->display, VisualIDMask, &template, &num);
229                 if (NULL == This->visInfo) {
230                     ERR("cannot really get XVisual\n");
231                     LEAVE_GL();
232                     return WINED3DERR_NOTAVAILABLE;
233                 }
234                 /* Now we have problems? well not really we just need to know what the implicit context is */
235                 /* now destroy the old context and create a new one (we should really copy the buffers over, and do the whole make current thing! */
236                 /* destroy the active context?*/
237                 TRACE("Creating new context for %p %p %p\n",This->display, This->visInfo, swapChainImpl->glCtx);
238                 This->glCtx = glXCreateContext(This->display, This->visInfo, swapChainImpl->glCtx, GL_TRUE);
239
240                 if (NULL == This->glCtx) {
241                     ERR("cannot create glxContext\n");
242                 }
243                 This->drawable     = This->win;
244                 This->render_ctx   = This->glCtx;
245                 /* Setup some default states TODO: apply the stateblock to the new context */
246                 /** save current context and drawable **/
247                 currentContext  =   glXGetCurrentContext();
248                 currentDrawable =   glXGetCurrentDrawable();
249
250                 if (glXMakeCurrent(This->display, This->win, This->glCtx) == False) {
251                     ERR("Error in setting current context (display %p context %p drawable %ld)!\n", This->display, This->glCtx, This->win);
252                 }
253
254                 checkGLcall("glXMakeCurrent");
255
256                 /* Clear the screen */
257                 glClearColor(0.0, 0.0, 0.0, 0.0);
258                 checkGLcall("glClearColor");
259                 glClearIndex(0);
260                 glClearDepth(1);
261                 glClearStencil(0);
262
263                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
264                 checkGLcall("glClear");
265
266                 glColor3f(1.0, 1.0, 1.0);
267                 checkGLcall("glColor3f");
268
269                 glEnable(GL_LIGHTING);
270                 checkGLcall("glEnable");
271
272                 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
273                 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
274
275                 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
276                 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
277
278                 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
279                 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
280
281                 /* If this swapchain is currently the active context then make this swapchain active */
282                 if(IWineD3DSurface_GetContainer(This->wineD3DDevice->render_targets[0], &IID_IWineD3DSwapChain, (void **)&tmp) == WINED3D_OK){
283                     if(tmp != (IUnknown *)This){
284                         glXMakeCurrent(This->display, currentDrawable, currentContext);
285                         checkGLcall("glXMakeCurrent");
286                     }
287                     IUnknown_Release(tmp);
288                 }else{
289                     /* reset the context */
290                     glXMakeCurrent(This->display, currentDrawable, currentContext);
291                     checkGLcall("glXMakeCurrent");
292                 }
293                 /* delete the old contxt*/
294                 glXDestroyContext(oldDisplay, oldContext); /* Should this happen on an active context? seems a bad idea */
295                 LEAVE_GL();
296             }
297             IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapChainImpl);
298
299         }
300
301
302         /* TODO: The slow way, save the data to memory, create a new context for the destination window, transfer the data cleanup, it may be a good idea to the move this swapchain over to the using the target winows context so that it runs faster in feature. */
303
304     glXSwapBuffers(This->display, This->drawable); /* TODO: cycle through the swapchain buffers */
305
306     TRACE("glXSwapBuffers called, Starting new frame\n");
307     /* FPS support */
308     if (TRACE_ON(fps))
309     {
310         static long prev_time, frames;
311
312         DWORD time = GetTickCount();
313         frames++;
314         /* every 1.5 seconds */
315         if (time - prev_time > 1500) {
316             TRACE_(fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
317             prev_time = time;
318             frames = 0;
319         }
320     }
321
322 #if defined(FRAME_DEBUGGING)
323 {
324     if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
325         if (!isOn) {
326             isOn = TRUE;
327             FIXME("Enabling D3D Trace\n");
328             __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
329 #if defined(SHOW_FRAME_MAKEUP)
330             FIXME("Singe Frame snapshots Starting\n");
331             isDumpingFrames = TRUE;
332             glClear(GL_COLOR_BUFFER_BIT);
333 #endif
334
335 #if defined(SINGLE_FRAME_DEBUGGING)
336         } else {
337 #if defined(SHOW_FRAME_MAKEUP)
338             FIXME("Singe Frame snapshots Finishing\n");
339             isDumpingFrames = FALSE;
340 #endif
341             FIXME("Singe Frame trace complete\n");
342             DeleteFileA("C:\\D3DTRACE");
343             __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
344 #endif
345         }
346     } else {
347         if (isOn) {
348             isOn = FALSE;
349 #if defined(SHOW_FRAME_MAKEUP)
350             FIXME("Single Frame snapshots Finishing\n");
351             isDumpingFrames = FALSE;
352 #endif
353             FIXME("Disabling D3D Trace\n");
354             __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
355         }
356     }
357 }
358 #endif
359
360     LEAVE_GL();
361     /* Although this is not strictly required, a simple demo showed this does occur
362        on (at least non-debug) d3d                                                  */
363     if (This->presentParms.SwapEffect == WINED3DSWAPEFFECT_DISCARD) {
364
365         TRACE("Clearing\n");
366
367         IWineD3DDevice_Clear((IWineD3DDevice*)This->wineD3DDevice, 0, NULL, WINED3DCLEAR_STENCIL|WINED3DCLEAR_ZBUFFER|WINED3DCLEAR_TARGET, 0x00, 1.0, 0);
368
369     } else {
370         TRACE("Clearing z/stencil buffer\n");
371
372         IWineD3DDevice_Clear((IWineD3DDevice*)This->wineD3DDevice, 0, NULL, WINED3DCLEAR_STENCIL|WINED3DCLEAR_ZBUFFER, 0x00, 1.0, 0);
373     }
374
375     if(!(((IWineD3DSurfaceImpl *) This->frontBuffer)->Flags   & SFLAG_GLDIRTY) ||
376        !(((IWineD3DSurfaceImpl *) This->backBuffer[0])->Flags & SFLAG_GLDIRTY) ) {
377         /* Both memory copies of the surfaces are ok, flip them around too instead of dirtifying */
378         IWineD3DSurfaceImpl *front = (IWineD3DSurfaceImpl *) This->frontBuffer;
379         IWineD3DSurfaceImpl *back = (IWineD3DSurfaceImpl *) This->backBuffer[0];
380         BOOL frontdirty = front->Flags & SFLAG_GLDIRTY;
381         BOOL backdirty = back->Flags & SFLAG_GLDIRTY;
382
383         /* Flip the DC */
384         {
385             HDC tmp;
386             tmp = front->hDC;
387             front->hDC = back->hDC;
388             back->hDC = tmp;
389         }
390
391         /* Flip the DIBsection */
392         {
393             HBITMAP tmp;
394             tmp = front->dib.DIBsection;
395             front->dib.DIBsection = back->dib.DIBsection;
396             back->dib.DIBsection = tmp;
397         }
398
399         /* Flip the surface data */
400         {
401             void* tmp;
402
403             tmp = front->dib.bitmap_data;
404             front->dib.bitmap_data = back->dib.bitmap_data;
405             back->dib.bitmap_data = tmp;
406
407             tmp = front->resource.allocatedMemory;
408             front->resource.allocatedMemory = back->resource.allocatedMemory;
409             back->resource.allocatedMemory = tmp;
410         }
411
412         /* client_memory should not be different, but just in case */
413         {
414             BOOL tmp;
415             tmp = front->dib.client_memory;
416             front->dib.client_memory = back->dib.client_memory;
417             back->dib.client_memory = tmp;
418         }
419         if(frontdirty) back->Flags |= SFLAG_GLDIRTY;
420         else back->Flags &= ~SFLAG_GLDIRTY;
421         if(backdirty) front->Flags |= SFLAG_GLDIRTY;
422         else front->Flags &= ~SFLAG_GLDIRTY;
423     }
424
425     TRACE("returning\n");
426     return WINED3D_OK;
427 }
428
429 static HRESULT WINAPI IWineD3DSwapChainImpl_GetFrontBufferData(IWineD3DSwapChain *iface, IWineD3DSurface *pDestSurface) {
430     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
431     POINT start;
432
433     TRACE("(%p) : iface(%p) pDestSurface(%p)\n", This, iface, pDestSurface);
434     
435     start.x = 0;
436     start.y = 0;
437     
438     if (This->presentParms.Windowed) {
439         MapWindowPoints(This->win_handle, NULL, &start, 1);
440     }
441 #if 0 /* TODO: make sure that this swapchains context is active */
442     IWineD3DDevice_ActivateSwapChainContext(This->wineD3DDevice, iface);
443 #endif
444     IWineD3DSurface_BltFast(pDestSurface, start.x, start.y, This->frontBuffer, NULL, 0);
445     return WINED3D_OK;
446 }
447
448 static HRESULT WINAPI IWineD3DSwapChainImpl_GetBackBuffer(IWineD3DSwapChain *iface, UINT iBackBuffer, WINED3DBACKBUFFER_TYPE Type, IWineD3DSurface **ppBackBuffer) {
449
450     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
451
452     if (iBackBuffer > This->presentParms.BackBufferCount - 1) {
453         TRACE("Back buffer count out of range\n");
454         /* Native d3d9 doesn't set NULL here, just as wine's d3d9. But set it here
455          * in wined3d to avoid problems in other libs
456          */
457         *ppBackBuffer = NULL;
458         return WINED3DERR_INVALIDCALL;
459     }
460
461     *ppBackBuffer = This->backBuffer[iBackBuffer];
462     TRACE("(%p) : BackBuf %d Type %d  returning %p\n", This, iBackBuffer, Type, *ppBackBuffer);
463
464     /* Note inc ref on returned surface */
465     if(*ppBackBuffer) IWineD3DSurface_AddRef(*ppBackBuffer);
466     return WINED3D_OK;
467
468 }
469
470 static HRESULT WINAPI IWineD3DSwapChainImpl_GetRasterStatus(IWineD3DSwapChain *iface, WINED3DRASTER_STATUS *pRasterStatus) {
471     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
472     static BOOL showFixmes = TRUE;
473     pRasterStatus->InVBlank = TRUE;
474     pRasterStatus->ScanLine = 0;
475     /* No openGL equivalent */
476     if(showFixmes) {
477         FIXME("(%p) : stub (once)\n", This);
478         showFixmes = FALSE;
479     }
480     return WINED3D_OK;
481 }
482
483 static HRESULT WINAPI IWineD3DSwapChainImpl_GetDisplayMode(IWineD3DSwapChain *iface, WINED3DDISPLAYMODE*pMode) {
484     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
485     HDC                 hdc;
486     int                 bpp = 0;
487
488     pMode->Width        = GetSystemMetrics(SM_CXSCREEN);
489     pMode->Height       = GetSystemMetrics(SM_CYSCREEN);
490     pMode->RefreshRate  = 85; /* FIXME: How to identify? */
491
492     hdc = GetDC(0);
493     bpp = GetDeviceCaps(hdc, BITSPIXEL);
494     ReleaseDC(0, hdc);
495
496     switch (bpp) {
497     case  8: pMode->Format       = WINED3DFMT_R8G8B8; break;
498     case 16: pMode->Format       = WINED3DFMT_R5G6B5; break;
499     case 24: /*pMode->Format       = WINED3DFMT_R8G8B8; break; */ /* 32bpp and 24bpp can be aliased for X */
500     case 32: pMode->Format       = WINED3DFMT_A8R8G8B8; break;
501     default:
502        FIXME("Unrecognized display mode format\n");
503        pMode->Format       = WINED3DFMT_UNKNOWN;
504     }
505
506     TRACE("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate,
507     pMode->Format, debug_d3dformat(pMode->Format));
508     return WINED3D_OK;
509 }
510
511 static HRESULT WINAPI IWineD3DSwapChainImpl_GetDevice(IWineD3DSwapChain *iface, IWineD3DDevice**ppDevice) {
512     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
513
514     *ppDevice = (IWineD3DDevice *) This->wineD3DDevice;
515
516     /* Note  Calling this method will increase the internal reference count
517        on the IDirect3DDevice9 interface. */
518     IWineD3DDevice_AddRef(*ppDevice);
519     TRACE("(%p) : returning %p\n", This, *ppDevice);
520     return WINED3D_OK;
521 }
522
523 static HRESULT WINAPI IWineD3DSwapChainImpl_GetPresentParameters(IWineD3DSwapChain *iface, WINED3DPRESENT_PARAMETERS *pPresentationParameters) {
524     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
525     TRACE("(%p)\n", This);
526     *pPresentationParameters->BackBufferWidth = This->presentParms.BackBufferWidth;
527     *pPresentationParameters->BackBufferHeight = This->presentParms.BackBufferHeight;
528     *pPresentationParameters->BackBufferFormat = This->presentParms.BackBufferFormat;
529     *pPresentationParameters->BackBufferCount = This->presentParms.BackBufferCount;
530     *pPresentationParameters->MultiSampleType = This->presentParms.MultiSampleType;
531     *pPresentationParameters->MultiSampleQuality = This->presentParms.MultiSampleQuality;
532     *pPresentationParameters->SwapEffect = This->presentParms.SwapEffect;
533     *pPresentationParameters->hDeviceWindow = This->presentParms.hDeviceWindow;
534     *pPresentationParameters->Windowed = This->presentParms.Windowed;
535     *pPresentationParameters->EnableAutoDepthStencil = This->presentParms.EnableAutoDepthStencil;
536     *pPresentationParameters->Flags = This->presentParms.Flags;
537     *pPresentationParameters->FullScreen_RefreshRateInHz = This->presentParms.FullScreen_RefreshRateInHz;
538     *pPresentationParameters->PresentationInterval = This->presentParms.PresentationInterval;
539     return WINED3D_OK;
540 }
541
542 static HRESULT WINAPI IWineD3DSwapChainImpl_SetGammaRamp(IWineD3DSwapChain *iface, DWORD Flags, CONST WINED3DGAMMARAMP *pRamp){
543
544     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
545     HDC hDC;
546     TRACE("(%p) : pRamp@%p flags(%d)\n", This, pRamp, Flags);
547     hDC = GetDC(This->win_handle);
548     SetDeviceGammaRamp(hDC, (LPVOID)pRamp);
549     ReleaseDC(This->win_handle, hDC);
550     return WINED3D_OK;
551
552 }
553
554 static HRESULT WINAPI IWineD3DSwapChainImpl_GetGammaRamp(IWineD3DSwapChain *iface, WINED3DGAMMARAMP *pRamp){
555
556     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
557     HDC hDC;
558     TRACE("(%p) : pRamp@%p\n", This, pRamp);
559     hDC = GetDC(This->win_handle);
560     GetDeviceGammaRamp(hDC, pRamp);
561     ReleaseDC(This->win_handle, hDC);
562     return WINED3D_OK;
563
564 }
565
566
567 const IWineD3DSwapChainVtbl IWineD3DSwapChain_Vtbl =
568 {
569     /* IUnknown */
570     IWineD3DSwapChainImpl_QueryInterface,
571     IWineD3DSwapChainImpl_AddRef,
572     IWineD3DSwapChainImpl_Release,
573     /* IWineD3DSwapChain */
574     IWineD3DSwapChainImpl_GetParent,
575     IWineD3DSwapChainImpl_Destroy,
576     IWineD3DSwapChainImpl_GetDevice,
577     IWineD3DSwapChainImpl_Present,
578     IWineD3DSwapChainImpl_GetFrontBufferData,
579     IWineD3DSwapChainImpl_GetBackBuffer,
580     IWineD3DSwapChainImpl_GetRasterStatus,
581     IWineD3DSwapChainImpl_GetDisplayMode,
582     IWineD3DSwapChainImpl_GetPresentParameters,
583     IWineD3DSwapChainImpl_SetGammaRamp,
584     IWineD3DSwapChainImpl_GetGammaRamp
585 };