wined3d: Pass the correct mask to shader_glsl_add_src_param() in shader_glsl_loop().
[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         DWORD time = GetTickCount();
311         This->frames++;
312         /* every 1.5 seconds */
313         if (time - This->prev_time > 1500) {
314             TRACE_(fps)("%p @ approx %.2ffps\n", This, 1000.0*This->frames/(time - This->prev_time));
315             This->prev_time = time;
316             This->frames = 0;
317         }
318     }
319
320 #if defined(FRAME_DEBUGGING)
321 {
322     if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
323         if (!isOn) {
324             isOn = TRUE;
325             FIXME("Enabling D3D Trace\n");
326             __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
327 #if defined(SHOW_FRAME_MAKEUP)
328             FIXME("Singe Frame snapshots Starting\n");
329             isDumpingFrames = TRUE;
330             glClear(GL_COLOR_BUFFER_BIT);
331 #endif
332
333 #if defined(SINGLE_FRAME_DEBUGGING)
334         } else {
335 #if defined(SHOW_FRAME_MAKEUP)
336             FIXME("Singe Frame snapshots Finishing\n");
337             isDumpingFrames = FALSE;
338 #endif
339             FIXME("Singe Frame trace complete\n");
340             DeleteFileA("C:\\D3DTRACE");
341             __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
342 #endif
343         }
344     } else {
345         if (isOn) {
346             isOn = FALSE;
347 #if defined(SHOW_FRAME_MAKEUP)
348             FIXME("Single Frame snapshots Finishing\n");
349             isDumpingFrames = FALSE;
350 #endif
351             FIXME("Disabling D3D Trace\n");
352             __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
353         }
354     }
355 }
356 #endif
357
358     LEAVE_GL();
359     /* Although this is not strictly required, a simple demo showed this does occur
360        on (at least non-debug) d3d                                                  */
361     if (This->presentParms.SwapEffect == WINED3DSWAPEFFECT_DISCARD) {
362
363         TRACE("Clearing\n");
364
365         IWineD3DDevice_Clear((IWineD3DDevice*)This->wineD3DDevice, 0, NULL, WINED3DCLEAR_STENCIL|WINED3DCLEAR_ZBUFFER|WINED3DCLEAR_TARGET, 0x00, 1.0, 0);
366
367     } else {
368         TRACE("Clearing z/stencil buffer\n");
369
370         IWineD3DDevice_Clear((IWineD3DDevice*)This->wineD3DDevice, 0, NULL, WINED3DCLEAR_STENCIL|WINED3DCLEAR_ZBUFFER, 0x00, 1.0, 0);
371     }
372
373     if(!(((IWineD3DSurfaceImpl *) This->frontBuffer)->Flags   & SFLAG_GLDIRTY) ||
374        !(((IWineD3DSurfaceImpl *) This->backBuffer[0])->Flags & SFLAG_GLDIRTY) ) {
375         /* Both memory copies of the surfaces are ok, flip them around too instead of dirtifying */
376         IWineD3DSurfaceImpl *front = (IWineD3DSurfaceImpl *) This->frontBuffer;
377         IWineD3DSurfaceImpl *back = (IWineD3DSurfaceImpl *) This->backBuffer[0];
378         BOOL frontdirty = front->Flags & SFLAG_GLDIRTY;
379         BOOL backdirty = back->Flags & SFLAG_GLDIRTY;
380
381         /* Flip the DC */
382         {
383             HDC tmp;
384             tmp = front->hDC;
385             front->hDC = back->hDC;
386             back->hDC = tmp;
387         }
388
389         /* Flip the DIBsection */
390         {
391             HBITMAP tmp;
392             tmp = front->dib.DIBsection;
393             front->dib.DIBsection = back->dib.DIBsection;
394             back->dib.DIBsection = tmp;
395         }
396
397         /* Flip the surface data */
398         {
399             void* tmp;
400
401             tmp = front->dib.bitmap_data;
402             front->dib.bitmap_data = back->dib.bitmap_data;
403             back->dib.bitmap_data = tmp;
404
405             tmp = front->resource.allocatedMemory;
406             front->resource.allocatedMemory = back->resource.allocatedMemory;
407             back->resource.allocatedMemory = tmp;
408         }
409
410         /* client_memory should not be different, but just in case */
411         {
412             BOOL tmp;
413             tmp = front->dib.client_memory;
414             front->dib.client_memory = back->dib.client_memory;
415             back->dib.client_memory = tmp;
416         }
417         if(frontdirty) back->Flags |= SFLAG_GLDIRTY;
418         else back->Flags &= ~SFLAG_GLDIRTY;
419         if(backdirty) front->Flags |= SFLAG_GLDIRTY;
420         else front->Flags &= ~SFLAG_GLDIRTY;
421     }
422
423     TRACE("returning\n");
424     return WINED3D_OK;
425 }
426
427 static HRESULT WINAPI IWineD3DSwapChainImpl_GetFrontBufferData(IWineD3DSwapChain *iface, IWineD3DSurface *pDestSurface) {
428     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
429     POINT start;
430
431     TRACE("(%p) : iface(%p) pDestSurface(%p)\n", This, iface, pDestSurface);
432     
433     start.x = 0;
434     start.y = 0;
435     
436     if (This->presentParms.Windowed) {
437         MapWindowPoints(This->win_handle, NULL, &start, 1);
438     }
439 #if 0 /* TODO: make sure that this swapchains context is active */
440     IWineD3DDevice_ActivateSwapChainContext(This->wineD3DDevice, iface);
441 #endif
442     IWineD3DSurface_BltFast(pDestSurface, start.x, start.y, This->frontBuffer, NULL, 0);
443     return WINED3D_OK;
444 }
445
446 static HRESULT WINAPI IWineD3DSwapChainImpl_GetBackBuffer(IWineD3DSwapChain *iface, UINT iBackBuffer, WINED3DBACKBUFFER_TYPE Type, IWineD3DSurface **ppBackBuffer) {
447
448     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
449
450     if (iBackBuffer > This->presentParms.BackBufferCount - 1) {
451         TRACE("Back buffer count out of range\n");
452         /* Native d3d9 doesn't set NULL here, just as wine's d3d9. But set it here
453          * in wined3d to avoid problems in other libs
454          */
455         *ppBackBuffer = NULL;
456         return WINED3DERR_INVALIDCALL;
457     }
458
459     *ppBackBuffer = This->backBuffer[iBackBuffer];
460     TRACE("(%p) : BackBuf %d Type %d  returning %p\n", This, iBackBuffer, Type, *ppBackBuffer);
461
462     /* Note inc ref on returned surface */
463     if(*ppBackBuffer) IWineD3DSurface_AddRef(*ppBackBuffer);
464     return WINED3D_OK;
465
466 }
467
468 static HRESULT WINAPI IWineD3DSwapChainImpl_GetRasterStatus(IWineD3DSwapChain *iface, WINED3DRASTER_STATUS *pRasterStatus) {
469     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
470     static BOOL showFixmes = TRUE;
471     pRasterStatus->InVBlank = TRUE;
472     pRasterStatus->ScanLine = 0;
473     /* No openGL equivalent */
474     if(showFixmes) {
475         FIXME("(%p) : stub (once)\n", This);
476         showFixmes = FALSE;
477     }
478     return WINED3D_OK;
479 }
480
481 static HRESULT WINAPI IWineD3DSwapChainImpl_GetDisplayMode(IWineD3DSwapChain *iface, WINED3DDISPLAYMODE*pMode) {
482     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
483     HDC                 hdc;
484     int                 bpp = 0;
485
486     pMode->Width        = GetSystemMetrics(SM_CXSCREEN);
487     pMode->Height       = GetSystemMetrics(SM_CYSCREEN);
488     pMode->RefreshRate  = 85; /* FIXME: How to identify? */
489
490     hdc = GetDC(0);
491     bpp = GetDeviceCaps(hdc, BITSPIXEL);
492     ReleaseDC(0, hdc);
493
494     switch (bpp) {
495     case  8: pMode->Format       = WINED3DFMT_R8G8B8; break;
496     case 16: pMode->Format       = WINED3DFMT_R5G6B5; break;
497     case 24: /*pMode->Format       = WINED3DFMT_R8G8B8; break; */ /* 32bpp and 24bpp can be aliased for X */
498     case 32: pMode->Format       = WINED3DFMT_A8R8G8B8; break;
499     default:
500        FIXME("Unrecognized display mode format\n");
501        pMode->Format       = WINED3DFMT_UNKNOWN;
502     }
503
504     TRACE("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate,
505     pMode->Format, debug_d3dformat(pMode->Format));
506     return WINED3D_OK;
507 }
508
509 static HRESULT WINAPI IWineD3DSwapChainImpl_GetDevice(IWineD3DSwapChain *iface, IWineD3DDevice**ppDevice) {
510     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
511
512     *ppDevice = (IWineD3DDevice *) This->wineD3DDevice;
513
514     /* Note  Calling this method will increase the internal reference count
515        on the IDirect3DDevice9 interface. */
516     IWineD3DDevice_AddRef(*ppDevice);
517     TRACE("(%p) : returning %p\n", This, *ppDevice);
518     return WINED3D_OK;
519 }
520
521 static HRESULT WINAPI IWineD3DSwapChainImpl_GetPresentParameters(IWineD3DSwapChain *iface, WINED3DPRESENT_PARAMETERS *pPresentationParameters) {
522     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
523     TRACE("(%p)\n", This);
524     *pPresentationParameters->BackBufferWidth = This->presentParms.BackBufferWidth;
525     *pPresentationParameters->BackBufferHeight = This->presentParms.BackBufferHeight;
526     *pPresentationParameters->BackBufferFormat = This->presentParms.BackBufferFormat;
527     *pPresentationParameters->BackBufferCount = This->presentParms.BackBufferCount;
528     *pPresentationParameters->MultiSampleType = This->presentParms.MultiSampleType;
529     *pPresentationParameters->MultiSampleQuality = This->presentParms.MultiSampleQuality;
530     *pPresentationParameters->SwapEffect = This->presentParms.SwapEffect;
531     *pPresentationParameters->hDeviceWindow = This->presentParms.hDeviceWindow;
532     *pPresentationParameters->Windowed = This->presentParms.Windowed;
533     *pPresentationParameters->EnableAutoDepthStencil = This->presentParms.EnableAutoDepthStencil;
534     *pPresentationParameters->Flags = This->presentParms.Flags;
535     *pPresentationParameters->FullScreen_RefreshRateInHz = This->presentParms.FullScreen_RefreshRateInHz;
536     *pPresentationParameters->PresentationInterval = This->presentParms.PresentationInterval;
537     return WINED3D_OK;
538 }
539
540 static HRESULT WINAPI IWineD3DSwapChainImpl_SetGammaRamp(IWineD3DSwapChain *iface, DWORD Flags, CONST WINED3DGAMMARAMP *pRamp){
541
542     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
543     HDC hDC;
544     TRACE("(%p) : pRamp@%p flags(%d)\n", This, pRamp, Flags);
545     hDC = GetDC(This->win_handle);
546     SetDeviceGammaRamp(hDC, (LPVOID)pRamp);
547     ReleaseDC(This->win_handle, hDC);
548     return WINED3D_OK;
549
550 }
551
552 static HRESULT WINAPI IWineD3DSwapChainImpl_GetGammaRamp(IWineD3DSwapChain *iface, WINED3DGAMMARAMP *pRamp){
553
554     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
555     HDC hDC;
556     TRACE("(%p) : pRamp@%p\n", This, pRamp);
557     hDC = GetDC(This->win_handle);
558     GetDeviceGammaRamp(hDC, pRamp);
559     ReleaseDC(This->win_handle, hDC);
560     return WINED3D_OK;
561
562 }
563
564
565 const IWineD3DSwapChainVtbl IWineD3DSwapChain_Vtbl =
566 {
567     /* IUnknown */
568     IWineD3DSwapChainImpl_QueryInterface,
569     IWineD3DSwapChainImpl_AddRef,
570     IWineD3DSwapChainImpl_Release,
571     /* IWineD3DSwapChain */
572     IWineD3DSwapChainImpl_GetParent,
573     IWineD3DSwapChainImpl_Destroy,
574     IWineD3DSwapChainImpl_GetDevice,
575     IWineD3DSwapChainImpl_Present,
576     IWineD3DSwapChainImpl_GetFrontBufferData,
577     IWineD3DSwapChainImpl_GetBackBuffer,
578     IWineD3DSwapChainImpl_GetRasterStatus,
579     IWineD3DSwapChainImpl_GetDisplayMode,
580     IWineD3DSwapChainImpl_GetPresentParameters,
581     IWineD3DSwapChainImpl_SetGammaRamp,
582     IWineD3DSwapChainImpl_GetGammaRamp
583 };