itss: Make the virtual table functions static where possible.
[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(d3d_fps);
55
56
57 /* IDirect3DSwapChain IUnknown parts follow: */
58 ULONG WINAPI IWineD3DSwapChainImpl_AddRef(IWineD3DSwapChain *iface) {
59     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
60     DWORD refCount = InterlockedIncrement(&This->ref);
61     TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
62     return refCount;
63 }
64
65 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 ULONG WINAPI IWineD3DSwapChainImpl_Release(IWineD3DSwapChain *iface) {
86     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
87     DWORD refCount;
88     refCount = InterlockedDecrement(&This->ref);
89     TRACE("(%p) : ReleaseRef to %ld\n", This, refCount);
90     if (refCount == 0) {
91         IUnknown* bufferParent;
92
93         /* release the ref to the front and back buffer parents */
94         if(This->frontBuffer) {
95             IWineD3DSurface_SetContainer(This->frontBuffer, 0);
96             IWineD3DSurface_GetParent(This->frontBuffer, &bufferParent);
97             IUnknown_Release(bufferParent); /* once for the get parent */
98             if(IUnknown_Release(bufferParent) > 0){
99                 FIXME("(%p) Something's still holding the front buffer\n",This);
100             }
101         }
102
103         if(This->backBuffer) {
104             IWineD3DSurface_SetContainer(This->backBuffer, 0);
105             IWineD3DSurface_GetParent(This->backBuffer, &bufferParent);
106             IUnknown_Release(bufferParent); /* once for the get parent */
107             if(IUnknown_Release(bufferParent) > 0){
108                 FIXME("(%p) Something's still holding the back buffer\n",This);
109             }
110         }
111
112         /* Clean up the context */
113         /* check that we are the current context first */
114         if(glXGetCurrentContext() == This->glCtx){
115             glXMakeCurrent(This->display, None, NULL);
116         }
117         glXDestroyContext(This->display, This->glCtx);
118         /* IUnknown_Release(This->parent); This should only apply to the primary swapchain,
119          all others are crated by the caller, so releasing the parent should cause
120          the child to be released, not the other way around!
121          */
122         HeapFree(GetProcessHeap(), 0, This);
123     }
124     return refCount;
125 }
126
127 HRESULT WINAPI IWineD3DSwapChainImpl_GetParent(IWineD3DSwapChain *iface, IUnknown ** ppParent){
128     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
129     *ppParent = This->parent;
130     IUnknown_AddRef(*ppParent);
131     TRACE("(%p) returning %p\n", This , *ppParent);
132     return WINED3D_OK;
133 }
134
135 /*IWineD3DSwapChain parts follow: */
136 HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CONST RECT *pSourceRect, CONST RECT *pDestRect, HWND hDestWindowOverride, CONST RGNDATA *pDirtyRegion, DWORD dwFlags) {
137     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
138
139     ENTER_GL();
140
141     if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect);
142     /* TODO: If only source rect or dest rect are supplied then clip the window to match */
143     TRACE("preseting display %p, drawable %ld\n", This->display, This->drawable);
144
145     /* Don't call checkGLcall, as glGetError is not applicable here */
146     if (hDestWindowOverride && This->win_handle != hDestWindowOverride) {
147         /* Set this swapchain up to point to the new destination.. */
148 #ifdef USE_CONTEXT_MANAGER
149             /* TODO: use a context mamager */
150 #endif
151
152             /* FIXME: Never access */
153             IWineD3DSwapChainImpl *swapChainImpl;
154             IWineD3DDevice_GetSwapChain((IWineD3DDevice *)This->wineD3DDevice, 0 , (IWineD3DSwapChain **)&swapChainImpl);
155             FIXME("Unable to render to a destination window %p\n", hDestWindowOverride );
156             if(This == swapChainImpl){
157                 /* FIXME: this will be fixed by moving to a context management system */
158                 FIXME("Cannot change the target of the implicit swapchain\n");
159             }else{
160                 HDC               hDc;
161                 XVisualInfo       template;
162                 int               num;
163                 Display          *oldDisplay = This->display;
164                 GLXContext        oldContext = This->glCtx;
165                 IUnknown*         tmp;
166                 GLXContext        currentContext;
167                 Drawable          currentDrawable;
168                 hDc                          = GetDC(hDestWindowOverride);
169                 This->win_handle             = hDestWindowOverride;
170                 This->win                    = (Window)GetPropA( hDestWindowOverride, "__wine_x11_whole_window" );
171
172                 TRACE("Creating a new context for the window %p\n", hDestWindowOverride);
173                 ENTER_GL();
174                 TRACE("Desctroying context %p %p\n", This->display, This->render_ctx);
175
176
177
178                 LEAVE_GL();
179                 ENTER_GL();
180
181                 This->display    = get_display(hDc);
182                 TRACE("Got display%p  for  %p %p\n",  This->display, hDc, hDestWindowOverride);
183                 ReleaseDC(hDestWindowOverride, hDc);
184                 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
185                 This->visInfo   = XGetVisualInfo(This->display, VisualIDMask, &template, &num);
186                 if (NULL == This->visInfo) {
187                     ERR("cannot really get XVisual\n");
188                     LEAVE_GL();
189                     return WINED3DERR_NOTAVAILABLE;
190                 }
191                 /* Now we have problems? well not really we just need to know what the implicit context is */
192                 /* now destroy the old context and create a new one (we should really copy the buffers over, and do the whole make current thing! */
193                 /* destroy the active context?*/
194                 TRACE("Creating new context for %p %p %p\n",This->display, This->visInfo, swapChainImpl->glCtx);
195                 This->glCtx = glXCreateContext(This->display, This->visInfo, swapChainImpl->glCtx, GL_TRUE);
196
197                 if (NULL == This->glCtx) {
198                     ERR("cannot create glxContext\n");
199                 }
200                 This->drawable     = This->win;
201                 This->render_ctx   = This->glCtx;
202                 /* Setup some default states TODO: apply the stateblock to the new context */
203                 /** save current context and drawable **/
204                 currentContext  =   glXGetCurrentContext();
205                 currentDrawable =   glXGetCurrentDrawable();
206
207                 if (glXMakeCurrent(This->display, This->win, This->glCtx) == False) {
208                     ERR("Error in setting current context (display %p context %p drawable %ld)!\n", This->display, This->glCtx, This->win);
209                 }
210
211                 checkGLcall("glXMakeCurrent");
212
213                 /* Clear the screen */
214                 glClearColor(0.0, 0.0, 0.0, 0.0);
215                 checkGLcall("glClearColor");
216                 glClearIndex(0);
217                 glClearDepth(1);
218                 glClearStencil(0);
219
220                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
221                 checkGLcall("glClear");
222
223                 glColor3f(1.0, 1.0, 1.0);
224                 checkGLcall("glColor3f");
225
226                 glEnable(GL_LIGHTING);
227                 checkGLcall("glEnable");
228
229                 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
230                 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
231
232                 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
233                 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
234
235                 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
236                 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
237
238                 /* If this swapchain is currently the active context then make this swapchain active */
239                 if(IWineD3DSurface_GetContainer(This->wineD3DDevice->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmp) == WINED3D_OK){
240                     if(tmp != (IUnknown *)This){
241                         glXMakeCurrent(This->display, currentDrawable, currentContext);
242                         checkGLcall("glXMakeCurrent");
243                     }
244                     IUnknown_Release(tmp);
245                 }else{
246                     /* reset the context */
247                     glXMakeCurrent(This->display, currentDrawable, currentContext);
248                     checkGLcall("glXMakeCurrent");
249                 }
250                 /* delete the old contxt*/
251                 glXDestroyContext(oldDisplay, oldContext); /* Should this happen on an active context? seems a bad idea */
252                 LEAVE_GL();
253             }
254             IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapChainImpl);
255
256         }
257
258
259         /* 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. */
260
261     glXSwapBuffers(This->display, This->drawable); /* TODO: cycle through the swapchain buffers */
262
263     TRACE("glXSwapBuffers called, Starting new frame\n");
264     /* FPS support */
265     if (TRACE_ON(d3d_fps))
266     {
267         static long prev_time, frames;
268
269         DWORD time = GetTickCount();
270         frames++;
271         /* every 1.5 seconds */
272         if (time - prev_time > 1500) {
273             TRACE_(d3d_fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
274             prev_time = time;
275             frames = 0;
276         }
277     }
278
279 #if defined(FRAME_DEBUGGING)
280 {
281     if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
282         if (!isOn) {
283             isOn = TRUE;
284             FIXME("Enabling D3D Trace\n");
285             __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
286 #if defined(SHOW_FRAME_MAKEUP)
287             FIXME("Singe Frame snapshots Starting\n");
288             isDumpingFrames = TRUE;
289             glClear(GL_COLOR_BUFFER_BIT);
290 #endif
291
292 #if defined(SINGLE_FRAME_DEBUGGING)
293         } else {
294 #if defined(SHOW_FRAME_MAKEUP)
295             FIXME("Singe Frame snapshots Finishing\n");
296             isDumpingFrames = FALSE;
297 #endif
298             FIXME("Singe Frame trace complete\n");
299             DeleteFileA("C:\\D3DTRACE");
300             __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
301 #endif
302         }
303     } else {
304         if (isOn) {
305             isOn = FALSE;
306 #if defined(SHOW_FRAME_MAKEUP)
307             FIXME("Single Frame snapshots Finishing\n");
308             isDumpingFrames = FALSE;
309 #endif
310             FIXME("Disabling D3D Trace\n");
311             __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
312         }
313     }
314 }
315 #endif
316
317     LEAVE_GL();
318     /* Although this is not strictly required, a simple demo showed this does occur
319        on (at least non-debug) d3d                                                  */
320     if (This->presentParms.SwapEffect == WINED3DSWAPEFFECT_DISCARD) {
321
322         TRACE("Clearing\n");
323
324         IWineD3DDevice_Clear((IWineD3DDevice*)This->wineD3DDevice, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
325
326     } else {
327         TRACE("Clearing z/stencil buffer\n");
328
329         IWineD3DDevice_Clear((IWineD3DDevice*)This->wineD3DDevice, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER, 0x00, 1.0, 0);
330     }
331
332     ((IWineD3DSurfaceImpl *) This->frontBuffer)->Flags |= SFLAG_GLDIRTY;
333     ((IWineD3DSurfaceImpl *) This->backBuffer)->Flags |= SFLAG_GLDIRTY;
334
335     TRACE("returning\n");
336     return WINED3D_OK;
337 }
338
339 HRESULT WINAPI IWineD3DSwapChainImpl_GetFrontBufferData(IWineD3DSwapChain *iface, IWineD3DSurface *pDestSurface) {
340     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
341     WINED3DFORMAT d3dformat;
342     UINT width;
343     UINT height;
344     WINED3DSURFACE_DESC desc;
345     glDescriptor *glDescription;
346
347     TRACE("(%p) : iface(%p) pDestSurface(%p)\n", This, iface, pDestSurface);
348     ENTER_GL();
349     memset(&desc, 0, sizeof(desc));
350     desc.Width =  &width;
351     desc.Height = &height;
352     desc.Format = &d3dformat;
353 #if 0 /* TODO: make sure that this swapchains context is active */
354     IWineD3DDevice_ActivateSwapChainContext(This->wineD3DDevice, iface);
355 #endif
356     IWineD3DSurface_GetDesc(pDestSurface, &desc);
357     /* make sure that the front buffer is the active read buffer */
358     glReadBuffer(GL_FRONT);
359     /* Read the pixels from the buffer into the surfaces memory */
360     IWineD3DSurface_GetGlDesc(pDestSurface, &glDescription);
361     glReadPixels(glDescription->target,
362                 glDescription->level,
363                 width,
364                 height,
365                 glDescription->glFormat,
366                 glDescription->glType,
367                 (void *)IWineD3DSurface_GetData(pDestSurface));
368     LEAVE_GL();
369     return WINED3D_OK;
370 }
371
372 HRESULT WINAPI IWineD3DSwapChainImpl_GetBackBuffer(IWineD3DSwapChain *iface, UINT iBackBuffer, WINED3DBACKBUFFER_TYPE Type, IWineD3DSurface **ppBackBuffer) {
373
374     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
375
376     *ppBackBuffer = This->backBuffer;
377     TRACE("(%p) : BackBuf %d Type %d  returning %p\n", This, iBackBuffer, Type, *ppBackBuffer);
378
379     if (iBackBuffer > This->presentParms.BackBufferCount - 1) {
380         TRACE("Back buffer count out of range\n");
381         /* Native d3d9 doesn't set NULL here, just as wine's d3d9. But set it here
382          * in wined3d to avoid problems in other libs
383          */
384         *ppBackBuffer = NULL;
385         return WINED3DERR_INVALIDCALL;
386     }
387
388     /* Note inc ref on returned surface */
389     if(*ppBackBuffer) IWineD3DSurface_AddRef(*ppBackBuffer);
390     return WINED3D_OK;
391
392 }
393
394 HRESULT WINAPI IWineD3DSwapChainImpl_GetRasterStatus(IWineD3DSwapChain *iface, WINED3DRASTER_STATUS *pRasterStatus) {
395     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
396     static BOOL showFixmes = TRUE;
397     pRasterStatus->InVBlank = TRUE;
398     pRasterStatus->ScanLine = 0;
399     /* No openGL equivalent */
400     if(showFixmes) {
401         FIXME("(%p) : stub (once)\n", This);
402         showFixmes = FALSE;
403     }
404     return WINED3D_OK;
405 }
406
407 HRESULT WINAPI IWineD3DSwapChainImpl_GetDisplayMode(IWineD3DSwapChain *iface, WINED3DDISPLAYMODE*pMode) {
408     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
409     HDC                 hdc;
410     int                 bpp = 0;
411
412     pMode->Width        = GetSystemMetrics(SM_CXSCREEN);
413     pMode->Height       = GetSystemMetrics(SM_CYSCREEN);
414     pMode->RefreshRate  = 85; /* FIXME: How to identify? */
415
416     hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
417     bpp = GetDeviceCaps(hdc, BITSPIXEL);
418     DeleteDC(hdc);
419
420     switch (bpp) {
421     case  8: pMode->Format       = D3DFMT_R8G8B8; break;
422     case 16: pMode->Format       = D3DFMT_R5G6B5; break;
423     case 24: /*pMode->Format       = D3DFMT_R8G8B8; break; */ /* 32bpp and 24bpp can be aliased for X */
424     case 32: pMode->Format       = D3DFMT_A8R8G8B8; break;
425     default:
426        FIXME("Unrecognized display mode format\n");
427        pMode->Format       = D3DFMT_UNKNOWN;
428     }
429
430     TRACE("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate,
431     pMode->Format, debug_d3dformat(pMode->Format));
432     return WINED3D_OK;
433 }
434
435 HRESULT WINAPI IWineD3DSwapChainImpl_GetDevice(IWineD3DSwapChain *iface, IWineD3DDevice**ppDevice) {
436     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
437
438     *ppDevice = (IWineD3DDevice *) This->wineD3DDevice;
439
440     /* Note  Calling this method will increase the internal reference count
441        on the IDirect3DDevice9 interface. */
442     IWineD3DDevice_AddRef(*ppDevice);
443     TRACE("(%p) : returning %p\n", This, *ppDevice);
444     return WINED3D_OK;
445 }
446
447 HRESULT WINAPI IWineD3DSwapChainImpl_GetPresentParameters(IWineD3DSwapChain *iface, WINED3DPRESENT_PARAMETERS *pPresentationParameters) {
448     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
449     TRACE("(%p)\n", This);
450     *pPresentationParameters->BackBufferWidth = This->presentParms.BackBufferWidth;
451     *pPresentationParameters->BackBufferHeight = This->presentParms.BackBufferHeight;
452     *pPresentationParameters->BackBufferFormat = This->presentParms.BackBufferFormat;
453     *pPresentationParameters->BackBufferCount = This->presentParms.BackBufferCount;
454     *pPresentationParameters->MultiSampleType = This->presentParms.MultiSampleType;
455     *pPresentationParameters->MultiSampleQuality = This->presentParms.MultiSampleQuality;
456     *pPresentationParameters->SwapEffect = This->presentParms.SwapEffect;
457     *pPresentationParameters->hDeviceWindow = This->presentParms.hDeviceWindow;
458     *pPresentationParameters->Windowed = This->presentParms.Windowed;
459     *pPresentationParameters->EnableAutoDepthStencil = This->presentParms.EnableAutoDepthStencil;
460     *pPresentationParameters->Flags = This->presentParms.Flags;
461     *pPresentationParameters->FullScreen_RefreshRateInHz = This->presentParms.FullScreen_RefreshRateInHz;
462     *pPresentationParameters->PresentationInterval = This->presentParms.PresentationInterval;
463     return WINED3D_OK;
464 }
465
466 HRESULT WINAPI IWineD3DSwapChainImpl_SetGammaRamp(IWineD3DSwapChain *iface, DWORD Flags, CONST WINED3DGAMMARAMP *pRamp){
467
468     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
469     HDC hDC;
470     TRACE("(%p) : pRamp@%p flags(%ld)\n", This, pRamp, Flags);
471     hDC = GetDC(This->win_handle);
472     SetDeviceGammaRamp(hDC, (LPVOID)pRamp);
473     ReleaseDC(This->win_handle, hDC);
474     return WINED3D_OK;
475
476 }
477
478 HRESULT WINAPI IWineD3DSwapChainImpl_GetGammaRamp(IWineD3DSwapChain *iface, WINED3DGAMMARAMP *pRamp){
479
480     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
481     HDC hDC;
482     TRACE("(%p) : pRamp@%p\n", This, pRamp);
483     hDC = GetDC(This->win_handle);
484     GetDeviceGammaRamp(hDC, pRamp);
485     ReleaseDC(This->win_handle, hDC);
486     return WINED3D_OK;
487
488 }
489
490
491 IWineD3DSwapChainVtbl IWineD3DSwapChain_Vtbl =
492 {
493     /* IUnknown */
494     IWineD3DSwapChainImpl_QueryInterface,
495     IWineD3DSwapChainImpl_AddRef,
496     IWineD3DSwapChainImpl_Release,
497     /* IWineD3DSwapChain */
498     IWineD3DSwapChainImpl_GetParent,
499     IWineD3DSwapChainImpl_GetDevice,
500     IWineD3DSwapChainImpl_Present,
501     IWineD3DSwapChainImpl_GetFrontBufferData,
502     IWineD3DSwapChainImpl_GetBackBuffer,
503     IWineD3DSwapChainImpl_GetRasterStatus,
504     IWineD3DSwapChainImpl_GetDisplayMode,
505     IWineD3DSwapChainImpl_GetPresentParameters,
506     IWineD3DSwapChainImpl_SetGammaRamp,
507     IWineD3DSwapChainImpl_GetGammaRamp
508 };