2 *IDirect3DSwapChain9 implementation
4 *Copyright 2002-2003 Jason Edmeades
5 *Copyright 2002-2003 Raphael Junqueira
6 *Copyright 2005 Oliver Stieber
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.
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.
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
24 #include "wined3d_private.h"
27 /* TODO: move to shared header (or context manager )*/
28 /* x11drv GDI escapes */
29 #define X11DRV_ESCAPE 6789
30 enum x11drv_escape_codes
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 */
37 /* retrieve the X display to use on a given DC */
38 inline static Display *get_display( HDC hdc )
41 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
43 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
44 sizeof(display), (LPSTR)&display )) display = NULL;
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)*/
53 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
54 WINE_DECLARE_DEBUG_CHANNEL(fps);
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);
65 static HRESULT WINAPI IWineD3DSwapChainImpl_QueryInterface(IWineD3DSwapChain *iface, REFIID riid, LPVOID *ppobj)
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);
74 ERR("Query interface called but now data allocated\n");
85 static ULONG WINAPI IWineD3DSwapChainImpl_Release(IWineD3DSwapChain *iface) {
86 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
88 refCount = InterlockedDecrement(&This->ref);
89 TRACE("(%p) : ReleaseRef to %d\n", This, refCount);
91 IWineD3DSwapChain_Destroy(iface, D3DCB_DefaultDestroySurface);
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);
104 /*IWineD3DSwapChain parts follow: */
105 static void WINAPI IWineD3DSwapChainImpl_Destroy(IWineD3DSwapChain *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroyRenderTarget) {
106 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
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);
116 if(This->backBuffer) {
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);
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);
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!
136 HeapFree(GetProcessHeap(), 0, This);
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;
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.
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 :-)
178 if (This->presentParms.Windowed) {
179 MapWindowPoints(NULL, This->win_handle, (LPPOINT)&destRect, 2);
181 IWineD3DSurface_Blt(This->backBuffer[0], &destRect, (IWineD3DSurface *) &cursor, NULL, DDBLT_KEYSRC, NULL);
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);
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 */
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");
204 XVisualInfo template;
206 Display *oldDisplay = This->display;
207 GLXContext oldContext = This->glCtx;
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" );
215 TRACE("Creating a new context for the window %p\n", hDestWindowOverride);
217 TRACE("Desctroying context %p %p\n", This->display, This->render_ctx);
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");
232 return WINED3DERR_NOTAVAILABLE;
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);
240 if (NULL == This->glCtx) {
241 ERR("cannot create glxContext\n");
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();
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);
254 checkGLcall("glXMakeCurrent");
256 /* Clear the screen */
257 glClearColor(0.0, 0.0, 0.0, 0.0);
258 checkGLcall("glClearColor");
263 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
264 checkGLcall("glClear");
266 glColor3f(1.0, 1.0, 1.0);
267 checkGLcall("glColor3f");
269 glEnable(GL_LIGHTING);
270 checkGLcall("glEnable");
272 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
273 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
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);");
278 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
279 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
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");
287 IUnknown_Release(tmp);
289 /* reset the context */
290 glXMakeCurrent(This->display, currentDrawable, currentContext);
291 checkGLcall("glXMakeCurrent");
293 /* delete the old contxt*/
294 glXDestroyContext(oldDisplay, oldContext); /* Should this happen on an active context? seems a bad idea */
297 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapChainImpl);
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. */
304 glXSwapBuffers(This->display, This->drawable); /* TODO: cycle through the swapchain buffers */
306 TRACE("glXSwapBuffers called, Starting new frame\n");
310 DWORD time = GetTickCount();
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;
320 #if defined(FRAME_DEBUGGING)
322 if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
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);
333 #if defined(SINGLE_FRAME_DEBUGGING)
335 #if defined(SHOW_FRAME_MAKEUP)
336 FIXME("Singe Frame snapshots Finishing\n");
337 isDumpingFrames = FALSE;
339 FIXME("Singe Frame trace complete\n");
340 DeleteFileA("C:\\D3DTRACE");
341 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
347 #if defined(SHOW_FRAME_MAKEUP)
348 FIXME("Single Frame snapshots Finishing\n");
349 isDumpingFrames = FALSE;
351 FIXME("Disabling D3D Trace\n");
352 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
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) {
365 IWineD3DDevice_Clear((IWineD3DDevice*)This->wineD3DDevice, 0, NULL, WINED3DCLEAR_STENCIL|WINED3DCLEAR_ZBUFFER|WINED3DCLEAR_TARGET, 0x00, 1.0, 0);
368 TRACE("Clearing z/stencil buffer\n");
370 IWineD3DDevice_Clear((IWineD3DDevice*)This->wineD3DDevice, 0, NULL, WINED3DCLEAR_STENCIL|WINED3DCLEAR_ZBUFFER, 0x00, 1.0, 0);
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;
385 front->hDC = back->hDC;
389 /* Flip the DIBsection */
392 tmp = front->dib.DIBsection;
393 front->dib.DIBsection = back->dib.DIBsection;
394 back->dib.DIBsection = tmp;
397 /* Flip the surface data */
401 tmp = front->dib.bitmap_data;
402 front->dib.bitmap_data = back->dib.bitmap_data;
403 back->dib.bitmap_data = tmp;
405 tmp = front->resource.allocatedMemory;
406 front->resource.allocatedMemory = back->resource.allocatedMemory;
407 back->resource.allocatedMemory = tmp;
410 /* client_memory should not be different, but just in case */
413 tmp = front->dib.client_memory;
414 front->dib.client_memory = back->dib.client_memory;
415 back->dib.client_memory = tmp;
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;
423 TRACE("returning\n");
427 static HRESULT WINAPI IWineD3DSwapChainImpl_GetFrontBufferData(IWineD3DSwapChain *iface, IWineD3DSurface *pDestSurface) {
428 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
431 TRACE("(%p) : iface(%p) pDestSurface(%p)\n", This, iface, pDestSurface);
436 if (This->presentParms.Windowed) {
437 MapWindowPoints(This->win_handle, NULL, &start, 1);
439 #if 0 /* TODO: make sure that this swapchains context is active */
440 IWineD3DDevice_ActivateSwapChainContext(This->wineD3DDevice, iface);
442 IWineD3DSurface_BltFast(pDestSurface, start.x, start.y, This->frontBuffer, NULL, 0);
446 static HRESULT WINAPI IWineD3DSwapChainImpl_GetBackBuffer(IWineD3DSwapChain *iface, UINT iBackBuffer, WINED3DBACKBUFFER_TYPE Type, IWineD3DSurface **ppBackBuffer) {
448 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
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
455 *ppBackBuffer = NULL;
456 return WINED3DERR_INVALIDCALL;
459 *ppBackBuffer = This->backBuffer[iBackBuffer];
460 TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, iBackBuffer, Type, *ppBackBuffer);
462 /* Note inc ref on returned surface */
463 if(*ppBackBuffer) IWineD3DSurface_AddRef(*ppBackBuffer);
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 */
475 FIXME("(%p) : stub (once)\n", This);
481 static HRESULT WINAPI IWineD3DSwapChainImpl_GetDisplayMode(IWineD3DSwapChain *iface, WINED3DDISPLAYMODE*pMode) {
482 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
486 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
487 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
488 pMode->RefreshRate = 85; /* FIXME: How to identify? */
491 bpp = GetDeviceCaps(hdc, BITSPIXEL);
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;
500 FIXME("Unrecognized display mode format\n");
501 pMode->Format = WINED3DFMT_UNKNOWN;
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));
509 static HRESULT WINAPI IWineD3DSwapChainImpl_GetDevice(IWineD3DSwapChain *iface, IWineD3DDevice**ppDevice) {
510 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
512 *ppDevice = (IWineD3DDevice *) This->wineD3DDevice;
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);
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;
540 static HRESULT WINAPI IWineD3DSwapChainImpl_SetGammaRamp(IWineD3DSwapChain *iface, DWORD Flags, CONST WINED3DGAMMARAMP *pRamp){
542 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
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);
552 static HRESULT WINAPI IWineD3DSwapChainImpl_GetGammaRamp(IWineD3DSwapChain *iface, WINED3DGAMMARAMP *pRamp){
554 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
556 TRACE("(%p) : pRamp@%p\n", This, pRamp);
557 hDC = GetDC(This->win_handle);
558 GetDeviceGammaRamp(hDC, pRamp);
559 ReleaseDC(This->win_handle, hDC);
565 const IWineD3DSwapChainVtbl IWineD3DSwapChain_Vtbl =
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