Assorted spelling fixes.
[wine/dibdrv.git] / dlls / wined3d / swapchain.c
blobe70880d99252276ba0cfc7245f686db6edf710f5
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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(d3d_fps);
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;
65 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_IWineD3DSwapChain)){
71 IWineD3DSwapChainImpl_AddRef(iface);
72 if(ppobj == NULL){
73 ERR("Query interface called but now data allocated\n");
74 return E_NOINTERFACE;
76 *ppobj = This;
77 return D3D_OK;
79 return E_NOINTERFACE;
83 ULONG WINAPI IWineD3DSwapChainImpl_Release(IWineD3DSwapChain *iface) {
84 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
85 DWORD refCount;
86 refCount = InterlockedDecrement(&This->ref);
87 TRACE("(%p) : ReleaseRef to %ld\n", This, refCount);
88 if (refCount == 0) {
89 IUnknown* bufferParent;
90 IWineD3DSurface_GetParent(This->frontBuffer, &bufferParent);
91 IUnknown_Release(bufferParent); /* once for the get parent */
92 if(IUnknown_Release(bufferParent) > 0){
93 FIXME("(%p) Something's still holding the front buffer\n",This);
96 IWineD3DSurface_GetParent(This->backBuffer, &bufferParent);
97 IUnknown_Release(bufferParent); /* once for the get parent */
98 if(IUnknown_Release(bufferParent) > 0){
99 FIXME("(%p) Something's still holding the back buffer\n",This);
101 /* Clean up the context */
102 /* check that we are the current context first */
103 if(glXGetCurrentContext() == This->glCtx){
104 glXMakeCurrent(This->display, None, NULL);
106 glXDestroyContext(This->display, This->glCtx);
107 /* IUnknown_Release(This->parent); This should only apply to the primary swapchain,
108 all others are crated by the caller, so releasing the parent should cause
109 the child to be released, not the other way around!
111 /* TODO: notify the device that this swapchain doesn't exist any more */
112 HeapFree(GetProcessHeap(), 0, This);
114 return refCount;
117 HRESULT WINAPI IWineD3DSwapChainImpl_GetParent(IWineD3DSwapChain *iface, IUnknown ** ppParent){
118 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
119 *ppParent = This->parent;
120 IUnknown_AddRef(*ppParent);
121 TRACE("(%p) returning %p\n", This , *ppParent);
122 return D3D_OK;
125 /*IWineD3DSwapChain parts follow: */
126 HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CONST RECT *pSourceRect, CONST RECT *pDestRect, HWND hDestWindowOverride, CONST RGNDATA *pDirtyRegion, DWORD dwFlags) {
127 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
129 ENTER_GL();
131 if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect);
132 /* TODO: If only source rect or dest rect are supplied then clip the window to match */
133 TRACE("preseting display %p, drawable %ld\n", This->display, This->drawable);
135 /* Don't call checkGLcall, as glGetError is not applicable here */
136 if (hDestWindowOverride && This->win_handle != hDestWindowOverride) {
137 /* Set this swapchain up to point to the new destination.. */
138 #ifdef USE_CONTEXT_MANAGER
139 /* TODO: use a context mamager */
140 #endif
142 /* FIXME: Never access */
143 IWineD3DSwapChainImpl *swapChainImpl;
144 IWineD3DDevice_GetSwapChain((IWineD3DDevice *)This->wineD3DDevice, 0 , (IWineD3DSwapChain **)&swapChainImpl);
145 FIXME("Unable to render to a destination window %d\n", (int)hDestWindowOverride );
146 if(This == swapChainImpl){
147 /* FIXME: this will be fixed by moving to a context management system */
148 FIXME("Cannot change the target of the implicit swapchain\n");
149 }else{
150 HDC hDc;
151 XVisualInfo template;
152 int num;
153 Display *oldDisplay = This->display;
154 GLXContext oldContext = This->glCtx;
155 IUnknown* tmp;
156 GLXContext currentContext;
157 Drawable currentDrawable;
158 hDc = GetDC(hDestWindowOverride);
159 This->win_handle = hDestWindowOverride;
160 This->win = (Window)GetPropA( hDestWindowOverride, "__wine_x11_whole_window" );
162 TRACE("Creating a new context for the window %p \n", hDestWindowOverride);
163 ENTER_GL();
164 TRACE("Desctroying context %p %p\n", This->display, This->render_ctx);
168 LEAVE_GL();
169 ENTER_GL();
171 This->display = get_display(hDc);
172 TRACE("Got display%p for %p %p\n", This->display, hDc, hDestWindowOverride);
173 ReleaseDC(hDestWindowOverride, hDc);
174 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
175 This->visInfo = XGetVisualInfo(This->display, VisualIDMask, &template, &num);
176 if (NULL == This->visInfo) {
177 ERR("cannot really get XVisual\n");
178 LEAVE_GL();
179 return D3DERR_NOTAVAILABLE;
181 /* Now we have problems? well not really we just need to know what the implicit context is */
182 /* now destroy the old context and create a new one (we should really copy the buffers over, and do the whole make current thing! */
183 /* destroy the active context?*/
184 TRACE("Creating new context for %p %p %p\n",This->display, This->visInfo, swapChainImpl->glCtx);
185 This->glCtx = glXCreateContext(This->display, This->visInfo, swapChainImpl->glCtx, GL_TRUE);
187 if (NULL == This->glCtx) {
188 ERR("cannot create glxContext\n");
190 This->drawable = This->win;
191 This->render_ctx = This->glCtx;
192 /* Setup some default states TODO: apply the stateblock to the new context */
193 /** save current context and drawable **/
194 currentContext = glXGetCurrentContext();
195 currentDrawable = glXGetCurrentDrawable();
197 if (glXMakeCurrent(This->display, This->win, This->glCtx) == False) {
198 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", This->display, This->glCtx, This->win);
201 checkGLcall("glXMakeCurrent");
203 /* Clear the screen */
204 glClearColor(0.0, 0.0, 0.0, 0.0);
205 checkGLcall("glClearColor");
206 glClearIndex(0);
207 glClearDepth(1);
208 glClearStencil(0);
210 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
211 checkGLcall("glClear");
213 glColor3f(1.0, 1.0, 1.0);
214 checkGLcall("glColor3f");
216 glEnable(GL_LIGHTING);
217 checkGLcall("glEnable");
219 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
220 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
222 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
223 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
225 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
226 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
228 /* If this swapchain is currently the active context then make this swapchain active */
229 if(IWineD3DSurface_GetContainer((IWineD3DSurface *)This->wineD3DDevice->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmp) == D3D_OK){
230 if(tmp != (IUnknown *)This){
231 glXMakeCurrent(This->display, currentDrawable, currentContext);
232 checkGLcall("glXMakeCurrent");
234 IUnknown_Release(tmp);
235 }else{
236 /* reset the context */
237 glXMakeCurrent(This->display, currentDrawable, currentContext);
238 checkGLcall("glXMakeCurrent");
240 /* delete the old contxt*/
241 glXDestroyContext(oldDisplay, oldContext); /* Should this happen on an active context? seems a bad idea */
242 LEAVE_GL();
244 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapChainImpl);
249 /* 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. */
251 glXSwapBuffers(This->display, This->drawable); /* TODO: cycle through the swapchain buffers */
253 TRACE("glXSwapBuffers called, Starting new frame\n");
254 /* FPS support */
255 if (TRACE_ON(d3d_fps))
257 static long prev_time, frames;
259 DWORD time = GetTickCount();
260 frames++;
261 /* every 1.5 seconds */
262 if (time - prev_time > 1500) {
263 TRACE_(d3d_fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
264 prev_time = time;
265 frames = 0;
269 #if defined(FRAME_DEBUGGING)
271 if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
272 if (!isOn) {
273 isOn = TRUE;
274 FIXME("Enabling D3D Trace\n");
275 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
276 #if defined(SHOW_FRAME_MAKEUP)
277 FIXME("Singe Frame snapshots Starting\n");
278 isDumpingFrames = TRUE;
279 glClear(GL_COLOR_BUFFER_BIT);
280 #endif
282 #if defined(SINGLE_FRAME_DEBUGGING)
283 } else {
284 #if defined(SHOW_FRAME_MAKEUP)
285 FIXME("Singe Frame snapshots Finishing\n");
286 isDumpingFrames = FALSE;
287 #endif
288 FIXME("Singe Frame trace complete\n");
289 DeleteFileA("C:\\D3DTRACE");
290 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
291 #endif
293 } else {
294 if (isOn) {
295 isOn = FALSE;
296 #if defined(SHOW_FRAME_MAKEUP)
297 FIXME("Single Frame snapshots Finishing\n");
298 isDumpingFrames = FALSE;
299 #endif
300 FIXME("Disabling D3D Trace\n");
301 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
305 #endif
307 LEAVE_GL();
308 /* Although this is not strictly required, a simple demo showed this does occur
309 on (at least non-debug) d3d */
310 if (This->presentParms.SwapEffect & D3DSWAPEFFECT_DISCARD) {
312 TRACE("Clearing\n");
314 IWineD3DDevice_Clear((IWineD3DDevice*)This->wineD3DDevice, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
317 TRACE("returning\n");
318 return D3D_OK;
321 HRESULT WINAPI IWineD3DSwapChainImpl_GetFrontBufferData(IWineD3DSwapChain *iface, IWineD3DSurface *pDestSurface) {
322 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
323 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pDestSurface;
324 GLenum format;
325 GLenum type;
327 TRACE("(%p) : iface(%p) pDestSurface(%p) \n", This, iface, pDestSurface);
328 ENTER_GL();
330 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date) */
331 format = D3DFmt2GLFmt(This->wineD3DDevice, surface->resource.format);
332 type = D3DFmt2GLType(This->wineD3DDevice, surface->resource.format);
333 glReadBuffer(GL_FRONT);
334 glReadPixels(0,
336 surface->currentDesc.Width,
337 surface->currentDesc.Height,
338 format,
339 type,
340 surface->resource.allocatedMemory);
341 LEAVE_GL();
342 return D3D_OK;
345 HRESULT WINAPI IWineD3DSwapChainImpl_GetBackBuffer(IWineD3DSwapChain *iface, UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IWineD3DSurface **ppBackBuffer) {
347 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
349 *ppBackBuffer = (IWineD3DSurface *) This->backBuffer;
350 TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, iBackBuffer, Type, *ppBackBuffer);
352 if (iBackBuffer > This->presentParms.BackBufferCount - 1) {
353 FIXME("Only one backBuffer currently supported\n");
354 return D3DERR_INVALIDCALL;
357 /* Note inc ref on returned surface */
358 IWineD3DSurface_AddRef(*ppBackBuffer);
359 return D3D_OK;
363 HRESULT WINAPI IWineD3DSwapChainImpl_GetRasterStatus(IWineD3DSwapChain *iface, D3DRASTER_STATUS*pRasterStatus) {
364 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
365 pRasterStatus->InVBlank = TRUE;
366 pRasterStatus->ScanLine = 0;
367 FIXME("(%p) : stub\n", This);
368 return D3D_OK;
371 HRESULT WINAPI IWineD3DSwapChainImpl_GetDisplayMode(IWineD3DSwapChain *iface, D3DDISPLAYMODE*pMode) {
372 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
373 HDC hdc;
374 int bpp = 0;
376 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
377 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
378 pMode->RefreshRate = 85; /* FIXME: How to identify? */
380 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
381 bpp = GetDeviceCaps(hdc, BITSPIXEL);
382 DeleteDC(hdc);
384 switch (bpp) {
385 case 8: pMode->Format = D3DFMT_R8G8B8; break;
386 case 16: pMode->Format = D3DFMT_R5G6B5; break;
387 case 24: /*pMode->Format = D3DFMT_R8G8B8; break; */ /* 32bpp and 24bpp can be aliased for X */
388 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
389 default:
390 FIXME("Unrecognized display mode format\n");
391 pMode->Format = D3DFMT_UNKNOWN;
394 TRACE("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate,
395 pMode->Format, debug_d3dformat(pMode->Format));
396 return D3D_OK;
399 HRESULT WINAPI IWineD3DSwapChainImpl_GetDevice(IWineD3DSwapChain *iface, IWineD3DDevice**ppDevice) {
400 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
402 *ppDevice = (IWineD3DDevice *) This->wineD3DDevice;
404 /* Note Calling this method will increase the internal reference count
405 on the IDirect3DDevice9 interface. */
406 IWineD3DDevice_AddRef(*ppDevice);
407 TRACE("(%p) : returning %p\n", This, *ppDevice);
408 return D3D_OK;
411 HRESULT WINAPI IWineD3DSwapChainImpl_GetPresentParameters(IWineD3DSwapChain *iface, D3DPRESENT_PARAMETERS *pPresentationParameters) {
412 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
413 FIXME("(%p) : copy\n", This);
414 memcpy(pPresentationParameters, &This->presentParms, sizeof(D3DPRESENT_PARAMETERS));
415 return D3D_OK;
418 HRESULT WINAPI IWineD3DSwapChainImpl_SetGammaRamp(IWineD3DSwapChain *iface, DWORD Flags, CONST D3DGAMMARAMP *pRamp){
420 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
421 HDC hDC;
422 TRACE("(%p) : pRamp@%p flags(%ld) \n", This, pRamp, Flags);
423 hDC = GetDC(This->win_handle);
424 SetDeviceGammaRamp(hDC, (LPVOID)pRamp);
425 ReleaseDC(This->win_handle, hDC);
426 return D3D_OK;
430 HRESULT WINAPI IWineD3DSwapChainImpl_GetGammaRamp(IWineD3DSwapChain *iface, D3DGAMMARAMP *pRamp){
432 IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
433 HDC hDC;
434 TRACE("(%p) : pRamp@%p\n", This, pRamp);
435 hDC = GetDC(This->win_handle);
436 GetDeviceGammaRamp(hDC, pRamp);
437 ReleaseDC(This->win_handle, hDC);
438 return D3D_OK;
443 IWineD3DSwapChainVtbl IWineD3DSwapChain_Vtbl =
445 IWineD3DSwapChainImpl_QueryInterface,
446 IWineD3DSwapChainImpl_AddRef,
447 IWineD3DSwapChainImpl_Release,
448 IWineD3DSwapChainImpl_GetParent,
449 IWineD3DSwapChainImpl_GetDevice,
450 IWineD3DSwapChainImpl_Present,
451 IWineD3DSwapChainImpl_GetFrontBufferData,
452 IWineD3DSwapChainImpl_GetBackBuffer,
453 IWineD3DSwapChainImpl_GetRasterStatus,
454 IWineD3DSwapChainImpl_GetDisplayMode,
455 IWineD3DSwapChainImpl_GetPresentParameters,
456 IWineD3DSwapChainImpl_SetGammaRamp,
457 IWineD3DSwapChainImpl_GetGammaRamp