wined3d: Do not return WINED3DERR_INVALIDCALL for Phong shading.
[wine/multimedia.git] / dlls / wined3d / swapchain.c
blobe4b385de89fc6d747083c5641aeef1daa2ed1350
1 /*
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
23 #include "config.h"
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 )
40 Display *display;
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;
45 return display;
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);
62 return refCount;
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);
73 if(ppobj == NULL){
74 ERR("Query interface called but now data allocated\n");
75 return E_NOINTERFACE;
77 *ppobj = This;
78 return WINED3D_OK;
80 *ppobj = NULL;
81 return E_NOINTERFACE;
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 %ld\n", This, refCount);
90 if (refCount == 0) {
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) {
104 int i;
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);
127 return refCount;
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);
135 return WINED3D_OK;
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;
142 ENTER_GL();
144 if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect);
145 /* TODO: If only source rect or dest rect are supplied then clip the window to match */
146 TRACE("preseting display %p, drawable %ld\n", This->display, This->drawable);
148 /* Don't call checkGLcall, as glGetError is not applicable here */
149 if (hDestWindowOverride && This->win_handle != hDestWindowOverride) {
150 /* Set this swapchain up to point to the new destination.. */
151 #ifdef USE_CONTEXT_MANAGER
152 /* TODO: use a context mamager */
153 #endif
155 /* FIXME: Never access */
156 IWineD3DSwapChainImpl *swapChainImpl;
157 IWineD3DDevice_GetSwapChain((IWineD3DDevice *)This->wineD3DDevice, 0 , (IWineD3DSwapChain **)&swapChainImpl);
158 FIXME("Unable to render to a destination window %p\n", hDestWindowOverride );
159 if(This == swapChainImpl){
160 /* FIXME: this will be fixed by moving to a context management system */
161 FIXME("Cannot change the target of the implicit swapchain\n");
162 }else{
163 HDC hDc;
164 XVisualInfo template;
165 int num;
166 Display *oldDisplay = This->display;
167 GLXContext oldContext = This->glCtx;
168 IUnknown* tmp;
169 GLXContext currentContext;
170 Drawable currentDrawable;
171 hDc = GetDC(hDestWindowOverride);
172 This->win_handle = hDestWindowOverride;
173 This->win = (Window)GetPropA( hDestWindowOverride, "__wine_x11_whole_window" );
175 TRACE("Creating a new context for the window %p\n", hDestWindowOverride);
176 ENTER_GL();
177 TRACE("Desctroying context %p %p\n", This->display, This->render_ctx);
181 LEAVE_GL();
182 ENTER_GL();
184 This->display = get_display(hDc);
185 TRACE("Got display%p for %p %p\n", This->display, hDc, hDestWindowOverride);
186 ReleaseDC(hDestWindowOverride, hDc);
187 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
188 This->visInfo = XGetVisualInfo(This->display, VisualIDMask, &template, &num);
189 if (NULL == This->visInfo) {
190 ERR("cannot really get XVisual\n");
191 LEAVE_GL();
192 return WINED3DERR_NOTAVAILABLE;
194 /* Now we have problems? well not really we just need to know what the implicit context is */
195 /* now destroy the old context and create a new one (we should really copy the buffers over, and do the whole make current thing! */
196 /* destroy the active context?*/
197 TRACE("Creating new context for %p %p %p\n",This->display, This->visInfo, swapChainImpl->glCtx);
198 This->glCtx = glXCreateContext(This->display, This->visInfo, swapChainImpl->glCtx, GL_TRUE);
200 if (NULL == This->glCtx) {
201 ERR("cannot create glxContext\n");
203 This->drawable = This->win;
204 This->render_ctx = This->glCtx;
205 /* Setup some default states TODO: apply the stateblock to the new context */
206 /** save current context and drawable **/
207 currentContext = glXGetCurrentContext();
208 currentDrawable = glXGetCurrentDrawable();
210 if (glXMakeCurrent(This->display, This->win, This->glCtx) == False) {
211 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", This->display, This->glCtx, This->win);
214 checkGLcall("glXMakeCurrent");
216 /* Clear the screen */
217 glClearColor(0.0, 0.0, 0.0, 0.0);
218 checkGLcall("glClearColor");
219 glClearIndex(0);
220 glClearDepth(1);
221 glClearStencil(0);
223 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
224 checkGLcall("glClear");
226 glColor3f(1.0, 1.0, 1.0);
227 checkGLcall("glColor3f");
229 glEnable(GL_LIGHTING);
230 checkGLcall("glEnable");
232 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
233 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
235 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
236 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
238 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
239 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
241 /* If this swapchain is currently the active context then make this swapchain active */
242 if(IWineD3DSurface_GetContainer(This->wineD3DDevice->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmp) == WINED3D_OK){
243 if(tmp != (IUnknown *)This){
244 glXMakeCurrent(This->display, currentDrawable, currentContext);
245 checkGLcall("glXMakeCurrent");
247 IUnknown_Release(tmp);
248 }else{
249 /* reset the context */
250 glXMakeCurrent(This->display, currentDrawable, currentContext);
251 checkGLcall("glXMakeCurrent");
253 /* delete the old contxt*/
254 glXDestroyContext(oldDisplay, oldContext); /* Should this happen on an active context? seems a bad idea */
255 LEAVE_GL();
257 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapChainImpl);
262 /* 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. */
264 glXSwapBuffers(This->display, This->drawable); /* TODO: cycle through the swapchain buffers */
266 TRACE("glXSwapBuffers called, Starting new frame\n");
267 /* FPS support */
268 if (TRACE_ON(fps))
270 static long prev_time, frames;
272 DWORD time = GetTickCount();
273 frames++;
274 /* every 1.5 seconds */
275 if (time - prev_time > 1500) {
276 TRACE_(fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
277 prev_time = time;
278 frames = 0;
282 #if defined(FRAME_DEBUGGING)
284 if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
285 if (!isOn) {
286 isOn = TRUE;
287 FIXME("Enabling D3D Trace\n");
288 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
289 #if defined(SHOW_FRAME_MAKEUP)
290 FIXME("Singe Frame snapshots Starting\n");
291 isDumpingFrames = TRUE;
292 glClear(GL_COLOR_BUFFER_BIT);
293 #endif
295 #if defined(SINGLE_FRAME_DEBUGGING)
296 } else {
297 #if defined(SHOW_FRAME_MAKEUP)
298 FIXME("Singe Frame snapshots Finishing\n");
299 isDumpingFrames = FALSE;
300 #endif
301 FIXME("Singe Frame trace complete\n");
302 DeleteFileA("C:\\D3DTRACE");
303 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
304 #endif
306 } else {
307 if (isOn) {
308 isOn = FALSE;
309 #if defined(SHOW_FRAME_MAKEUP)
310 FIXME("Single Frame snapshots Finishing\n");
311 isDumpingFrames = FALSE;
312 #endif
313 FIXME("Disabling D3D Trace\n");
314 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
318 #endif
320 LEAVE_GL();
321 /* Although this is not strictly required, a simple demo showed this does occur
322 on (at least non-debug) d3d */
323 if (This->presentParms.SwapEffect == WINED3DSWAPEFFECT_DISCARD) {
325 TRACE("Clearing\n");
327 IWineD3DDevice_Clear((IWineD3DDevice*)This->wineD3DDevice, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
329 } else {
330 TRACE("Clearing z/stencil buffer\n");
332 IWineD3DDevice_Clear((IWineD3DDevice*)This->wineD3DDevice, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER, 0x00, 1.0, 0);
335 if(!(((IWineD3DSurfaceImpl *) This->frontBuffer)->Flags & SFLAG_GLDIRTY) ||
336 !(((IWineD3DSurfaceImpl *) This->backBuffer[0])->Flags & SFLAG_GLDIRTY) ) {
337 /* Both memory copies of the surfaces are ok, flip them around too instead of dirtifying */
338 IWineD3DSurfaceImpl *front = (IWineD3DSurfaceImpl *) This->frontBuffer;
339 IWineD3DSurfaceImpl *back = (IWineD3DSurfaceImpl *) This->backBuffer[0];
340 BOOL frontdirty = front->Flags & SFLAG_GLDIRTY;
341 BOOL backdirty = back->Flags & SFLAG_GLDIRTY;
343 /* Flip the DC */
345 HDC tmp;
346 tmp = front->hDC;
347 front->hDC = back->hDC;
348 back->hDC = tmp;
351 /* Flip the DIBsection */
353 HBITMAP tmp;
354 tmp = front->dib.DIBsection;
355 front->dib.DIBsection = back->dib.DIBsection;
356 back->dib.DIBsection = tmp;
359 /* Flip the surface data */
361 void* tmp;
363 tmp = front->dib.bitmap_data;
364 front->dib.bitmap_data = back->dib.bitmap_data;
365 back->dib.bitmap_data = tmp;
367 tmp = front->resource.allocatedMemory;
368 front->resource.allocatedMemory = back->resource.allocatedMemory;
369 back->resource.allocatedMemory = tmp;
372 /* client_memory should not be different, but just in case */
374 BOOL tmp;
375 tmp = front->dib.client_memory;
376 front->dib.client_memory = back->dib.client_memory;
377 back->dib.client_memory = tmp;
379 if(frontdirty) back->Flags |= SFLAG_GLDIRTY;
380 else back->Flags &= ~SFLAG_GLDIRTY;
381 if(backdirty) front->Flags |= SFLAG_GLDIRTY;
382 else front->Flags &= ~SFLAG_GLDIRTY;
385 TRACE("returning\n");
386 return WINED3D_OK;
389 static HRESULT WINAPI IWineD3DSwapChainImpl_GetFrontBufferData(IWineD3DSwapChain *iface, IWineD3DSurface *pDestSurface) {
390 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
391 WINED3DFORMAT d3dformat;
392 UINT width;
393 UINT height;
394 WINED3DSURFACE_DESC desc;
395 glDescriptor *glDescription;
397 TRACE("(%p) : iface(%p) pDestSurface(%p)\n", This, iface, pDestSurface);
398 ENTER_GL();
399 memset(&desc, 0, sizeof(desc));
400 desc.Width = &width;
401 desc.Height = &height;
402 desc.Format = &d3dformat;
403 #if 0 /* TODO: make sure that this swapchains context is active */
404 IWineD3DDevice_ActivateSwapChainContext(This->wineD3DDevice, iface);
405 #endif
406 IWineD3DSurface_GetDesc(pDestSurface, &desc);
407 /* make sure that the front buffer is the active read buffer */
408 glReadBuffer(GL_FRONT);
409 /* Read the pixels from the buffer into the surfaces memory */
410 IWineD3DSurface_GetGlDesc(pDestSurface, &glDescription);
411 glReadPixels(glDescription->target,
412 glDescription->level,
413 width,
414 height,
415 glDescription->glFormat,
416 glDescription->glType,
417 (void *)IWineD3DSurface_GetData(pDestSurface));
418 LEAVE_GL();
419 return WINED3D_OK;
422 static HRESULT WINAPI IWineD3DSwapChainImpl_GetBackBuffer(IWineD3DSwapChain *iface, UINT iBackBuffer, WINED3DBACKBUFFER_TYPE Type, IWineD3DSurface **ppBackBuffer) {
424 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
426 if (iBackBuffer > This->presentParms.BackBufferCount - 1) {
427 TRACE("Back buffer count out of range\n");
428 /* Native d3d9 doesn't set NULL here, just as wine's d3d9. But set it here
429 * in wined3d to avoid problems in other libs
431 *ppBackBuffer = NULL;
432 return WINED3DERR_INVALIDCALL;
435 *ppBackBuffer = This->backBuffer[iBackBuffer];
436 TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, iBackBuffer, Type, *ppBackBuffer);
438 /* Note inc ref on returned surface */
439 if(*ppBackBuffer) IWineD3DSurface_AddRef(*ppBackBuffer);
440 return WINED3D_OK;
444 static HRESULT WINAPI IWineD3DSwapChainImpl_GetRasterStatus(IWineD3DSwapChain *iface, WINED3DRASTER_STATUS *pRasterStatus) {
445 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
446 static BOOL showFixmes = TRUE;
447 pRasterStatus->InVBlank = TRUE;
448 pRasterStatus->ScanLine = 0;
449 /* No openGL equivalent */
450 if(showFixmes) {
451 FIXME("(%p) : stub (once)\n", This);
452 showFixmes = FALSE;
454 return WINED3D_OK;
457 static HRESULT WINAPI IWineD3DSwapChainImpl_GetDisplayMode(IWineD3DSwapChain *iface, WINED3DDISPLAYMODE*pMode) {
458 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
459 HDC hdc;
460 int bpp = 0;
462 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
463 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
464 pMode->RefreshRate = 85; /* FIXME: How to identify? */
466 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
467 bpp = GetDeviceCaps(hdc, BITSPIXEL);
468 DeleteDC(hdc);
470 switch (bpp) {
471 case 8: pMode->Format = D3DFMT_R8G8B8; break;
472 case 16: pMode->Format = D3DFMT_R5G6B5; break;
473 case 24: /*pMode->Format = D3DFMT_R8G8B8; break; */ /* 32bpp and 24bpp can be aliased for X */
474 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
475 default:
476 FIXME("Unrecognized display mode format\n");
477 pMode->Format = D3DFMT_UNKNOWN;
480 TRACE("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate,
481 pMode->Format, debug_d3dformat(pMode->Format));
482 return WINED3D_OK;
485 static HRESULT WINAPI IWineD3DSwapChainImpl_GetDevice(IWineD3DSwapChain *iface, IWineD3DDevice**ppDevice) {
486 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
488 *ppDevice = (IWineD3DDevice *) This->wineD3DDevice;
490 /* Note Calling this method will increase the internal reference count
491 on the IDirect3DDevice9 interface. */
492 IWineD3DDevice_AddRef(*ppDevice);
493 TRACE("(%p) : returning %p\n", This, *ppDevice);
494 return WINED3D_OK;
497 static HRESULT WINAPI IWineD3DSwapChainImpl_GetPresentParameters(IWineD3DSwapChain *iface, WINED3DPRESENT_PARAMETERS *pPresentationParameters) {
498 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
499 TRACE("(%p)\n", This);
500 *pPresentationParameters->BackBufferWidth = This->presentParms.BackBufferWidth;
501 *pPresentationParameters->BackBufferHeight = This->presentParms.BackBufferHeight;
502 *pPresentationParameters->BackBufferFormat = This->presentParms.BackBufferFormat;
503 *pPresentationParameters->BackBufferCount = This->presentParms.BackBufferCount;
504 *pPresentationParameters->MultiSampleType = This->presentParms.MultiSampleType;
505 *pPresentationParameters->MultiSampleQuality = This->presentParms.MultiSampleQuality;
506 *pPresentationParameters->SwapEffect = This->presentParms.SwapEffect;
507 *pPresentationParameters->hDeviceWindow = This->presentParms.hDeviceWindow;
508 *pPresentationParameters->Windowed = This->presentParms.Windowed;
509 *pPresentationParameters->EnableAutoDepthStencil = This->presentParms.EnableAutoDepthStencil;
510 *pPresentationParameters->Flags = This->presentParms.Flags;
511 *pPresentationParameters->FullScreen_RefreshRateInHz = This->presentParms.FullScreen_RefreshRateInHz;
512 *pPresentationParameters->PresentationInterval = This->presentParms.PresentationInterval;
513 return WINED3D_OK;
516 static HRESULT WINAPI IWineD3DSwapChainImpl_SetGammaRamp(IWineD3DSwapChain *iface, DWORD Flags, CONST WINED3DGAMMARAMP *pRamp){
518 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
519 HDC hDC;
520 TRACE("(%p) : pRamp@%p flags(%ld)\n", This, pRamp, Flags);
521 hDC = GetDC(This->win_handle);
522 SetDeviceGammaRamp(hDC, (LPVOID)pRamp);
523 ReleaseDC(This->win_handle, hDC);
524 return WINED3D_OK;
528 static HRESULT WINAPI IWineD3DSwapChainImpl_GetGammaRamp(IWineD3DSwapChain *iface, WINED3DGAMMARAMP *pRamp){
530 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
531 HDC hDC;
532 TRACE("(%p) : pRamp@%p\n", This, pRamp);
533 hDC = GetDC(This->win_handle);
534 GetDeviceGammaRamp(hDC, pRamp);
535 ReleaseDC(This->win_handle, hDC);
536 return WINED3D_OK;
541 IWineD3DSwapChainVtbl IWineD3DSwapChain_Vtbl =
543 /* IUnknown */
544 IWineD3DSwapChainImpl_QueryInterface,
545 IWineD3DSwapChainImpl_AddRef,
546 IWineD3DSwapChainImpl_Release,
547 /* IWineD3DSwapChain */
548 IWineD3DSwapChainImpl_GetParent,
549 IWineD3DSwapChainImpl_GetDevice,
550 IWineD3DSwapChainImpl_Present,
551 IWineD3DSwapChainImpl_GetFrontBufferData,
552 IWineD3DSwapChainImpl_GetBackBuffer,
553 IWineD3DSwapChainImpl_GetRasterStatus,
554 IWineD3DSwapChainImpl_GetDisplayMode,
555 IWineD3DSwapChainImpl_GetPresentParameters,
556 IWineD3DSwapChainImpl_SetGammaRamp,
557 IWineD3DSwapChainImpl_GetGammaRamp