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 static long prev_time, frames;
312 DWORD time = GetTickCount();
314 /* every 1.5 seconds */
315 if (time - prev_time > 1500) {
316 TRACE_(fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
322 #if defined(FRAME_DEBUGGING)
324 if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
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);
335 #if defined(SINGLE_FRAME_DEBUGGING)
337 #if defined(SHOW_FRAME_MAKEUP)
338 FIXME("Singe Frame snapshots Finishing\n");
339 isDumpingFrames = FALSE;
341 FIXME("Singe Frame trace complete\n");
342 DeleteFileA("C:\\D3DTRACE");
343 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
349 #if defined(SHOW_FRAME_MAKEUP)
350 FIXME("Single Frame snapshots Finishing\n");
351 isDumpingFrames = FALSE;
353 FIXME("Disabling D3D Trace\n");
354 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
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) {
367 IWineD3DDevice_Clear((IWineD3DDevice*)This->wineD3DDevice, 0, NULL, WINED3DCLEAR_STENCIL|WINED3DCLEAR_ZBUFFER|WINED3DCLEAR_TARGET, 0x00, 1.0, 0);
370 TRACE("Clearing z/stencil buffer\n");
372 IWineD3DDevice_Clear((IWineD3DDevice*)This->wineD3DDevice, 0, NULL, WINED3DCLEAR_STENCIL|WINED3DCLEAR_ZBUFFER, 0x00, 1.0, 0);
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;
387 front->hDC = back->hDC;
391 /* Flip the DIBsection */
394 tmp = front->dib.DIBsection;
395 front->dib.DIBsection = back->dib.DIBsection;
396 back->dib.DIBsection = tmp;
399 /* Flip the surface data */
403 tmp = front->dib.bitmap_data;
404 front->dib.bitmap_data = back->dib.bitmap_data;
405 back->dib.bitmap_data = tmp;
407 tmp = front->resource.allocatedMemory;
408 front->resource.allocatedMemory = back->resource.allocatedMemory;
409 back->resource.allocatedMemory = tmp;
412 /* client_memory should not be different, but just in case */
415 tmp = front->dib.client_memory;
416 front->dib.client_memory = back->dib.client_memory;
417 back->dib.client_memory = tmp;
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;
425 TRACE("returning\n");
429 static HRESULT WINAPI IWineD3DSwapChainImpl_GetFrontBufferData(IWineD3DSwapChain *iface, IWineD3DSurface *pDestSurface) {
430 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
433 TRACE("(%p) : iface(%p) pDestSurface(%p)\n", This, iface, pDestSurface);
438 if (This->presentParms.Windowed) {
439 MapWindowPoints(This->win_handle, NULL, &start, 1);
441 #if 0 /* TODO: make sure that this swapchains context is active */
442 IWineD3DDevice_ActivateSwapChainContext(This->wineD3DDevice, iface);
444 IWineD3DSurface_BltFast(pDestSurface, start.x, start.y, This->frontBuffer, NULL, 0);
448 static HRESULT WINAPI IWineD3DSwapChainImpl_GetBackBuffer(IWineD3DSwapChain *iface, UINT iBackBuffer, WINED3DBACKBUFFER_TYPE Type, IWineD3DSurface **ppBackBuffer) {
450 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
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
457 *ppBackBuffer = NULL;
458 return WINED3DERR_INVALIDCALL;
461 *ppBackBuffer = This->backBuffer[iBackBuffer];
462 TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, iBackBuffer, Type, *ppBackBuffer);
464 /* Note inc ref on returned surface */
465 if(*ppBackBuffer) IWineD3DSurface_AddRef(*ppBackBuffer);
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 */
477 FIXME("(%p) : stub (once)\n", This);
483 static HRESULT WINAPI IWineD3DSwapChainImpl_GetDisplayMode(IWineD3DSwapChain *iface, WINED3DDISPLAYMODE*pMode) {
484 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
488 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
489 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
490 pMode->RefreshRate = 85; /* FIXME: How to identify? */
493 bpp = GetDeviceCaps(hdc, BITSPIXEL);
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;
502 FIXME("Unrecognized display mode format\n");
503 pMode->Format = WINED3DFMT_UNKNOWN;
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));
511 static HRESULT WINAPI IWineD3DSwapChainImpl_GetDevice(IWineD3DSwapChain *iface, IWineD3DDevice**ppDevice) {
512 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
514 *ppDevice = (IWineD3DDevice *) This->wineD3DDevice;
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);
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;
542 static HRESULT WINAPI IWineD3DSwapChainImpl_SetGammaRamp(IWineD3DSwapChain *iface, DWORD Flags, CONST WINED3DGAMMARAMP *pRamp){
544 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
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);
554 static HRESULT WINAPI IWineD3DSwapChainImpl_GetGammaRamp(IWineD3DSwapChain *iface, WINED3DGAMMARAMP *pRamp){
556 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
558 TRACE("(%p) : pRamp@%p\n", This, pRamp);
559 hDC = GetDC(This->win_handle);
560 GetDeviceGammaRamp(hDC, pRamp);
561 ReleaseDC(This->win_handle, hDC);
567 const IWineD3DSwapChainVtbl IWineD3DSwapChain_Vtbl =
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