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 %ld\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 %ld\n", This, refCount);
91 IUnknown* bufferParent;
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);
103 if(This->backBuffer) {
105 for(i = 0; i < This->presentParms.BackBufferCount; i++) {
106 IWineD3DSurface_SetContainer(This->backBuffer[i], 0);
107 IWineD3DSurface_GetParent(This->backBuffer[i], &bufferParent);
108 IUnknown_Release(bufferParent); /* once for the get parent */
109 if(IUnknown_Release(bufferParent) > 0){
110 FIXME("(%p) Something's still holding the back buffer\n",This);
115 /* Clean up the context */
116 /* check that we are the current context first */
117 if(glXGetCurrentContext() == This->glCtx){
118 glXMakeCurrent(This->display, None, NULL);
120 glXDestroyContext(This->display, This->glCtx);
121 /* IUnknown_Release(This->parent); This should only apply to the primary swapchain,
122 all others are crated by the caller, so releasing the parent should cause
123 the child to be released, not the other way around!
125 HeapFree(GetProcessHeap(), 0, This);
130 static HRESULT WINAPI IWineD3DSwapChainImpl_GetParent(IWineD3DSwapChain *iface, IUnknown ** ppParent){
131 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
132 *ppParent = This->parent;
133 IUnknown_AddRef(*ppParent);
134 TRACE("(%p) returning %p\n", This , *ppParent);
138 /*IWineD3DSwapChain parts follow: */
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 IWineD3DSurface_Blt(This->backBuffer[0], &destRect, (IWineD3DSurface *) &cursor, NULL, DDBLT_KEYSRC, NULL);
181 if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect);
182 /* TODO: If only source rect or dest rect are supplied then clip the window to match */
183 TRACE("preseting display %p, drawable %ld\n", This->display, This->drawable);
185 /* Don't call checkGLcall, as glGetError is not applicable here */
186 if (hDestWindowOverride && This->win_handle != hDestWindowOverride) {
187 /* Set this swapchain up to point to the new destination.. */
188 #ifdef USE_CONTEXT_MANAGER
189 /* TODO: use a context mamager */
192 /* FIXME: Never access */
193 IWineD3DSwapChainImpl *swapChainImpl;
194 IWineD3DDevice_GetSwapChain((IWineD3DDevice *)This->wineD3DDevice, 0 , (IWineD3DSwapChain **)&swapChainImpl);
195 FIXME("Unable to render to a destination window %p\n", hDestWindowOverride );
196 if(This == swapChainImpl){
197 /* FIXME: this will be fixed by moving to a context management system */
198 FIXME("Cannot change the target of the implicit swapchain\n");
201 XVisualInfo template;
203 Display *oldDisplay = This->display;
204 GLXContext oldContext = This->glCtx;
206 GLXContext currentContext;
207 Drawable currentDrawable;
208 hDc = GetDC(hDestWindowOverride);
209 This->win_handle = hDestWindowOverride;
210 This->win = (Window)GetPropA( hDestWindowOverride, "__wine_x11_whole_window" );
212 TRACE("Creating a new context for the window %p\n", hDestWindowOverride);
214 TRACE("Desctroying context %p %p\n", This->display, This->render_ctx);
221 This->display = get_display(hDc);
222 TRACE("Got display%p for %p %p\n", This->display, hDc, hDestWindowOverride);
223 ReleaseDC(hDestWindowOverride, hDc);
224 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
225 This->visInfo = XGetVisualInfo(This->display, VisualIDMask, &template, &num);
226 if (NULL == This->visInfo) {
227 ERR("cannot really get XVisual\n");
229 return WINED3DERR_NOTAVAILABLE;
231 /* Now we have problems? well not really we just need to know what the implicit context is */
232 /* now destroy the old context and create a new one (we should really copy the buffers over, and do the whole make current thing! */
233 /* destroy the active context?*/
234 TRACE("Creating new context for %p %p %p\n",This->display, This->visInfo, swapChainImpl->glCtx);
235 This->glCtx = glXCreateContext(This->display, This->visInfo, swapChainImpl->glCtx, GL_TRUE);
237 if (NULL == This->glCtx) {
238 ERR("cannot create glxContext\n");
240 This->drawable = This->win;
241 This->render_ctx = This->glCtx;
242 /* Setup some default states TODO: apply the stateblock to the new context */
243 /** save current context and drawable **/
244 currentContext = glXGetCurrentContext();
245 currentDrawable = glXGetCurrentDrawable();
247 if (glXMakeCurrent(This->display, This->win, This->glCtx) == False) {
248 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", This->display, This->glCtx, This->win);
251 checkGLcall("glXMakeCurrent");
253 /* Clear the screen */
254 glClearColor(0.0, 0.0, 0.0, 0.0);
255 checkGLcall("glClearColor");
260 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
261 checkGLcall("glClear");
263 glColor3f(1.0, 1.0, 1.0);
264 checkGLcall("glColor3f");
266 glEnable(GL_LIGHTING);
267 checkGLcall("glEnable");
269 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
270 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
272 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
273 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
275 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
276 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
278 /* If this swapchain is currently the active context then make this swapchain active */
279 if(IWineD3DSurface_GetContainer(This->wineD3DDevice->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmp) == WINED3D_OK){
280 if(tmp != (IUnknown *)This){
281 glXMakeCurrent(This->display, currentDrawable, currentContext);
282 checkGLcall("glXMakeCurrent");
284 IUnknown_Release(tmp);
286 /* reset the context */
287 glXMakeCurrent(This->display, currentDrawable, currentContext);
288 checkGLcall("glXMakeCurrent");
290 /* delete the old contxt*/
291 glXDestroyContext(oldDisplay, oldContext); /* Should this happen on an active context? seems a bad idea */
294 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapChainImpl);
299 /* 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. */
301 glXSwapBuffers(This->display, This->drawable); /* TODO: cycle through the swapchain buffers */
303 TRACE("glXSwapBuffers called, Starting new frame\n");
307 static long prev_time, frames;
309 DWORD time = GetTickCount();
311 /* every 1.5 seconds */
312 if (time - prev_time > 1500) {
313 TRACE_(fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
319 #if defined(FRAME_DEBUGGING)
321 if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
324 FIXME("Enabling D3D Trace\n");
325 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
326 #if defined(SHOW_FRAME_MAKEUP)
327 FIXME("Singe Frame snapshots Starting\n");
328 isDumpingFrames = TRUE;
329 glClear(GL_COLOR_BUFFER_BIT);
332 #if defined(SINGLE_FRAME_DEBUGGING)
334 #if defined(SHOW_FRAME_MAKEUP)
335 FIXME("Singe Frame snapshots Finishing\n");
336 isDumpingFrames = FALSE;
338 FIXME("Singe Frame trace complete\n");
339 DeleteFileA("C:\\D3DTRACE");
340 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
346 #if defined(SHOW_FRAME_MAKEUP)
347 FIXME("Single Frame snapshots Finishing\n");
348 isDumpingFrames = FALSE;
350 FIXME("Disabling D3D Trace\n");
351 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
358 /* Although this is not strictly required, a simple demo showed this does occur
359 on (at least non-debug) d3d */
360 if (This->presentParms.SwapEffect == WINED3DSWAPEFFECT_DISCARD) {
364 IWineD3DDevice_Clear((IWineD3DDevice*)This->wineD3DDevice, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
367 TRACE("Clearing z/stencil buffer\n");
369 IWineD3DDevice_Clear((IWineD3DDevice*)This->wineD3DDevice, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER, 0x00, 1.0, 0);
372 if(!(((IWineD3DSurfaceImpl *) This->frontBuffer)->Flags & SFLAG_GLDIRTY) ||
373 !(((IWineD3DSurfaceImpl *) This->backBuffer[0])->Flags & SFLAG_GLDIRTY) ) {
374 /* Both memory copies of the surfaces are ok, flip them around too instead of dirtifying */
375 IWineD3DSurfaceImpl *front = (IWineD3DSurfaceImpl *) This->frontBuffer;
376 IWineD3DSurfaceImpl *back = (IWineD3DSurfaceImpl *) This->backBuffer[0];
377 BOOL frontdirty = front->Flags & SFLAG_GLDIRTY;
378 BOOL backdirty = back->Flags & SFLAG_GLDIRTY;
384 front->hDC = back->hDC;
388 /* Flip the DIBsection */
391 tmp = front->dib.DIBsection;
392 front->dib.DIBsection = back->dib.DIBsection;
393 back->dib.DIBsection = tmp;
396 /* Flip the surface data */
400 tmp = front->dib.bitmap_data;
401 front->dib.bitmap_data = back->dib.bitmap_data;
402 back->dib.bitmap_data = tmp;
404 tmp = front->resource.allocatedMemory;
405 front->resource.allocatedMemory = back->resource.allocatedMemory;
406 back->resource.allocatedMemory = tmp;
409 /* client_memory should not be different, but just in case */
412 tmp = front->dib.client_memory;
413 front->dib.client_memory = back->dib.client_memory;
414 back->dib.client_memory = tmp;
416 if(frontdirty) back->Flags |= SFLAG_GLDIRTY;
417 else back->Flags &= ~SFLAG_GLDIRTY;
418 if(backdirty) front->Flags |= SFLAG_GLDIRTY;
419 else front->Flags &= ~SFLAG_GLDIRTY;
422 TRACE("returning\n");
426 static HRESULT WINAPI IWineD3DSwapChainImpl_GetFrontBufferData(IWineD3DSwapChain *iface, IWineD3DSurface *pDestSurface) {
427 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
428 WINED3DFORMAT d3dformat;
431 WINED3DSURFACE_DESC desc;
432 glDescriptor *glDescription;
434 TRACE("(%p) : iface(%p) pDestSurface(%p)\n", This, iface, pDestSurface);
436 memset(&desc, 0, sizeof(desc));
438 desc.Height = &height;
439 desc.Format = &d3dformat;
440 #if 0 /* TODO: make sure that this swapchains context is active */
441 IWineD3DDevice_ActivateSwapChainContext(This->wineD3DDevice, iface);
443 IWineD3DSurface_GetDesc(pDestSurface, &desc);
444 /* make sure that the front buffer is the active read buffer */
445 glReadBuffer(GL_FRONT);
446 /* Read the pixels from the buffer into the surfaces memory */
447 IWineD3DSurface_GetGlDesc(pDestSurface, &glDescription);
448 glReadPixels(glDescription->target,
449 glDescription->level,
452 glDescription->glFormat,
453 glDescription->glType,
454 (void *)IWineD3DSurface_GetData(pDestSurface));
459 static HRESULT WINAPI IWineD3DSwapChainImpl_GetBackBuffer(IWineD3DSwapChain *iface, UINT iBackBuffer, WINED3DBACKBUFFER_TYPE Type, IWineD3DSurface **ppBackBuffer) {
461 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
463 if (iBackBuffer > This->presentParms.BackBufferCount - 1) {
464 TRACE("Back buffer count out of range\n");
465 /* Native d3d9 doesn't set NULL here, just as wine's d3d9. But set it here
466 * in wined3d to avoid problems in other libs
468 *ppBackBuffer = NULL;
469 return WINED3DERR_INVALIDCALL;
472 *ppBackBuffer = This->backBuffer[iBackBuffer];
473 TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, iBackBuffer, Type, *ppBackBuffer);
475 /* Note inc ref on returned surface */
476 if(*ppBackBuffer) IWineD3DSurface_AddRef(*ppBackBuffer);
481 static HRESULT WINAPI IWineD3DSwapChainImpl_GetRasterStatus(IWineD3DSwapChain *iface, WINED3DRASTER_STATUS *pRasterStatus) {
482 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
483 static BOOL showFixmes = TRUE;
484 pRasterStatus->InVBlank = TRUE;
485 pRasterStatus->ScanLine = 0;
486 /* No openGL equivalent */
488 FIXME("(%p) : stub (once)\n", This);
494 static HRESULT WINAPI IWineD3DSwapChainImpl_GetDisplayMode(IWineD3DSwapChain *iface, WINED3DDISPLAYMODE*pMode) {
495 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
499 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
500 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
501 pMode->RefreshRate = 85; /* FIXME: How to identify? */
503 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
504 bpp = GetDeviceCaps(hdc, BITSPIXEL);
508 case 8: pMode->Format = D3DFMT_R8G8B8; break;
509 case 16: pMode->Format = D3DFMT_R5G6B5; break;
510 case 24: /*pMode->Format = D3DFMT_R8G8B8; break; */ /* 32bpp and 24bpp can be aliased for X */
511 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
513 FIXME("Unrecognized display mode format\n");
514 pMode->Format = D3DFMT_UNKNOWN;
517 TRACE("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate,
518 pMode->Format, debug_d3dformat(pMode->Format));
522 static HRESULT WINAPI IWineD3DSwapChainImpl_GetDevice(IWineD3DSwapChain *iface, IWineD3DDevice**ppDevice) {
523 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
525 *ppDevice = (IWineD3DDevice *) This->wineD3DDevice;
527 /* Note Calling this method will increase the internal reference count
528 on the IDirect3DDevice9 interface. */
529 IWineD3DDevice_AddRef(*ppDevice);
530 TRACE("(%p) : returning %p\n", This, *ppDevice);
534 static HRESULT WINAPI IWineD3DSwapChainImpl_GetPresentParameters(IWineD3DSwapChain *iface, WINED3DPRESENT_PARAMETERS *pPresentationParameters) {
535 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
536 TRACE("(%p)\n", This);
537 *pPresentationParameters->BackBufferWidth = This->presentParms.BackBufferWidth;
538 *pPresentationParameters->BackBufferHeight = This->presentParms.BackBufferHeight;
539 *pPresentationParameters->BackBufferFormat = This->presentParms.BackBufferFormat;
540 *pPresentationParameters->BackBufferCount = This->presentParms.BackBufferCount;
541 *pPresentationParameters->MultiSampleType = This->presentParms.MultiSampleType;
542 *pPresentationParameters->MultiSampleQuality = This->presentParms.MultiSampleQuality;
543 *pPresentationParameters->SwapEffect = This->presentParms.SwapEffect;
544 *pPresentationParameters->hDeviceWindow = This->presentParms.hDeviceWindow;
545 *pPresentationParameters->Windowed = This->presentParms.Windowed;
546 *pPresentationParameters->EnableAutoDepthStencil = This->presentParms.EnableAutoDepthStencil;
547 *pPresentationParameters->Flags = This->presentParms.Flags;
548 *pPresentationParameters->FullScreen_RefreshRateInHz = This->presentParms.FullScreen_RefreshRateInHz;
549 *pPresentationParameters->PresentationInterval = This->presentParms.PresentationInterval;
553 static HRESULT WINAPI IWineD3DSwapChainImpl_SetGammaRamp(IWineD3DSwapChain *iface, DWORD Flags, CONST WINED3DGAMMARAMP *pRamp){
555 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
557 TRACE("(%p) : pRamp@%p flags(%ld)\n", This, pRamp, Flags);
558 hDC = GetDC(This->win_handle);
559 SetDeviceGammaRamp(hDC, (LPVOID)pRamp);
560 ReleaseDC(This->win_handle, hDC);
565 static HRESULT WINAPI IWineD3DSwapChainImpl_GetGammaRamp(IWineD3DSwapChain *iface, WINED3DGAMMARAMP *pRamp){
567 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
569 TRACE("(%p) : pRamp@%p\n", This, pRamp);
570 hDC = GetDC(This->win_handle);
571 GetDeviceGammaRamp(hDC, pRamp);
572 ReleaseDC(This->win_handle, hDC);
578 IWineD3DSwapChainVtbl IWineD3DSwapChain_Vtbl =
581 IWineD3DSwapChainImpl_QueryInterface,
582 IWineD3DSwapChainImpl_AddRef,
583 IWineD3DSwapChainImpl_Release,
584 /* IWineD3DSwapChain */
585 IWineD3DSwapChainImpl_GetParent,
586 IWineD3DSwapChainImpl_GetDevice,
587 IWineD3DSwapChainImpl_Present,
588 IWineD3DSwapChainImpl_GetFrontBufferData,
589 IWineD3DSwapChainImpl_GetBackBuffer,
590 IWineD3DSwapChainImpl_GetRasterStatus,
591 IWineD3DSwapChainImpl_GetDisplayMode,
592 IWineD3DSwapChainImpl_GetPresentParameters,
593 IWineD3DSwapChainImpl_SetGammaRamp,
594 IWineD3DSwapChainImpl_GetGammaRamp