Commit c9b8a79e authored by Stefan Dösinger's avatar Stefan Dösinger Committed by Alexandre Julliard

wined3d: Implement vertical refresh sync.

parent 43fda1f4
......@@ -1064,6 +1064,10 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info, Display* display) {
}
memcpy(ThisExtn, Start, (GLX_Extensions - Start));
TRACE_(d3d_caps)("- %s\n", ThisExtn);
if (strstr(ThisExtn, "GLX_SGI_video_sync")) {
gl_info->supported[SGI_VIDEO_SYNC] = TRUE;
}
if (*GLX_Extensions == ' ') GLX_Extensions++;
}
}
......
......@@ -2355,7 +2355,8 @@ HRESULT WINAPI IWineD3DSurfaceImpl_SetMem(IWineD3DSurface *iface, void *Mem) {
static HRESULT WINAPI IWineD3DSurfaceImpl_Flip(IWineD3DSurface *iface, IWineD3DSurface *override, DWORD Flags) {
IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
IWineD3DDevice *D3D = (IWineD3DDevice *) This->resource.wineD3DDevice;
IWineD3DSwapChainImpl *swapchain = NULL;
HRESULT hr;
TRACE("(%p)->(%p,%x)\n", This, override, Flags);
/* Flipping is only supported on RenderTargets */
......@@ -2369,8 +2370,32 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_Flip(IWineD3DSurface *iface, IWineD3DS
*/
}
IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **) &swapchain);
if(!swapchain) {
ERR("Flipped surface is not on a swapchain\n");
return WINEDDERR_NOTFLIPPABLE;
}
/* Just overwrite the swapchain presentation interval. This is ok because only ddraw apps can call Flip,
* and only d3d8 and d3d9 apps specify the presentation interval
*/
if((Flags & (WINEDDFLIP_NOVSYNC | WINEDDFLIP_INTERVAL2 | WINEDDFLIP_INTERVAL3 | WINEDDFLIP_INTERVAL4)) == 0) {
/* Most common case first to avoid wasting time on all the other cases */
swapchain->presentParms.PresentationInterval = WINED3DPRESENT_INTERVAL_ONE;
} else if(Flags & WINEDDFLIP_NOVSYNC) {
swapchain->presentParms.PresentationInterval = WINED3DPRESENT_INTERVAL_IMMEDIATE;
} else if(Flags & WINEDDFLIP_INTERVAL2) {
swapchain->presentParms.PresentationInterval = WINED3DPRESENT_INTERVAL_TWO;
} else if(Flags & WINEDDFLIP_INTERVAL3) {
swapchain->presentParms.PresentationInterval = WINED3DPRESENT_INTERVAL_THREE;
} else {
swapchain->presentParms.PresentationInterval = WINED3DPRESENT_INTERVAL_FOUR;
}
/* Flipping a OpenGL surface -> Use WineD3DDevice::Present */
return IWineD3DDevice_Present(D3D, NULL, NULL, 0, NULL);
hr = IWineD3DSwapChain_Present((IWineD3DSwapChain *) swapchain, NULL, NULL, 0, NULL, 0);
IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
return hr;
}
/* Does a direct frame buffer -> texture copy. Stretching is done
......@@ -2773,10 +2798,10 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT *
*/
dstSwapchain->presentParms.SwapEffect = WINED3DSWAPEFFECT_COPY;
dstSwapchain->presentParms.PresentationInterval = WINED3DPRESENT_INTERVAL_IMMEDIATE;
TRACE("Full screen back buffer -> front buffer blt, performing a flip instead\n");
IWineD3DDevice_Present((IWineD3DDevice *) This->resource.wineD3DDevice,
NULL, NULL, 0, NULL);
IWineD3DSwapChain_Present((IWineD3DSwapChain *) dstSwapchain, NULL, NULL, 0, NULL, 0);
dstSwapchain->presentParms.SwapEffect = orig_swap;
......
......@@ -53,6 +53,7 @@ static inline Display *get_display( HDC hdc )
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
WINE_DECLARE_DEBUG_CHANNEL(fps);
#define GLINFO_LOCATION This->wineD3DDevice->adapter->gl_info
/* IDirect3DSwapChain IUnknown parts follow: */
static ULONG WINAPI IWineD3DSwapChainImpl_AddRef(IWineD3DSwapChain *iface) {
......@@ -148,6 +149,8 @@ static void WINAPI IWineD3DSwapChainImpl_Destroy(IWineD3DSwapChain *iface, D3DCB
static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CONST RECT *pSourceRect, CONST RECT *pDestRect, HWND hDestWindowOverride, CONST RGNDATA *pDirtyRegion, DWORD dwFlags) {
IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
DWORD clear_flags = 0;
unsigned int sync;
int retval;
ENTER_GL();
......@@ -374,6 +377,47 @@ static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CO
}
}
if(This->presentParms.PresentationInterval != WINED3DPRESENT_INTERVAL_IMMEDIATE && GL_SUPPORT(SGI_VIDEO_SYNC)) {
retval = GL_EXTCALL(glXGetVideoSyncSGI(&sync));
if(retval != 0) {
ERR("glXGetVideoSyncSGI failed(retval = %d\n", retval);
}
switch(This->presentParms.PresentationInterval) {
case WINED3DPRESENT_INTERVAL_DEFAULT:
case WINED3DPRESENT_INTERVAL_ONE:
if(sync <= This->vSyncCounter) {
retval = GL_EXTCALL(glXWaitVideoSyncSGI(1, 0, &This->vSyncCounter));
} else {
This->vSyncCounter = sync;
}
break;
case WINED3DPRESENT_INTERVAL_TWO:
if(sync <= This->vSyncCounter + 1) {
retval = GL_EXTCALL(glXWaitVideoSyncSGI(2, This->vSyncCounter & 0x1, &This->vSyncCounter));
} else {
This->vSyncCounter = sync;
}
break;
case WINED3DPRESENT_INTERVAL_THREE:
if(sync <= This->vSyncCounter + 2) {
retval = GL_EXTCALL(glXWaitVideoSyncSGI(3, This->vSyncCounter % 0x3, &This->vSyncCounter));
} else {
This->vSyncCounter = sync;
}
break;
case WINED3DPRESENT_INTERVAL_FOUR:
if(sync <= This->vSyncCounter + 3) {
retval = GL_EXTCALL(glXWaitVideoSyncSGI(4, This->vSyncCounter & 0x3, &This->vSyncCounter));
} else {
This->vSyncCounter = sync;
}
break;
default:
FIXME("Unknown presentation interval %08x\n", This->presentParms.PresentationInterval);
}
}
TRACE("returning\n");
return WINED3D_OK;
}
......
......@@ -1404,6 +1404,7 @@ typedef struct IWineD3DSwapChainImpl
WINED3DFORMAT orig_fmt;
long prev_time, frames; /* Performance tracking */
unsigned int vSyncCounter;
WineD3DContext **context; /* Later a array for multithreading */
unsigned int num_contexts;
......
......@@ -241,6 +241,10 @@ typedef struct IDirectDrawGammaControl *LPDIRECTDRAWGAMMACONTROL;
#define DDFLIP_NOVSYNC 0x00000008
#define DDFLIP_STEREO 0x00000010
#define DDFLIP_DONOTWAIT 0x00000020
#define DDFLIP_INTERVAL2 0x02000000
#define DDFLIP_INTERVAL3 0x03000000
#define DDFLIP_INTERVAL4 0x04000000
/* dwFlags for GetBltStatus */
#define DDGBS_CANBLT 0x00000001
......
......@@ -1225,6 +1225,10 @@ typedef void (APIENTRY * PGLFNTEXBUMPPARAMETERFVATIPROC) (GLenum, GLfloat *);
typedef void (APIENTRY * PGLFNGETTEXBUMPPARAMETERIVATIPROC) (GLenum, GLint *);
typedef void (APIENTRY * PGLFNGETTEXBUMPPARAMETERFVATIPROC) (GLenum, GLfloat *);
/* GLX_SGI_video_sync */
typedef int (APIENTRY * PGLXFNGETVIDEOSYNCSGIPROC) (unsigned int *);
typedef int (APIENTRY * PGLXFNWAITVIDEOSYNCSGIPROC) (int, int, unsigned int *);
/* GL_VERSION_2_0 */
#ifndef GL_VERSION_2_0
#define GL_VERSION_2_0 1
......@@ -1593,6 +1597,8 @@ typedef enum _GL_SupportedExt {
/* APPLE */
APPLE_FENCE,
APPLE_CLIENT_STORAGE,
/* SGI */
SGI_VIDEO_SYNC,
OPENGL_SUPPORTED_EXT_END
} GL_SupportedExt;
......@@ -1817,6 +1823,9 @@ typedef enum _GL_SupportedExt {
USE_GL_FUNC(PGLFNTEXBUMPPARAMETERFVATIPROC, glTexBumpParameterfvATI); \
USE_GL_FUNC(PGLFNGETTEXBUMPPARAMETERIVATIPROC, glGetTexBumpParameterivATI); \
USE_GL_FUNC(PGLFNGETTEXBUMPPARAMETERFVATIPROC, glGetTexBumpParameterfvATI); \
/* GLX_SGI_video_sync */ \
USE_GL_FUNC(PGLXFNGETVIDEOSYNCSGIPROC, glXGetVideoSyncSGI); \
USE_GL_FUNC(PGLXFNWAITVIDEOSYNCSGIPROC, glXWaitVideoSyncSGI); \
/* OpenGL 2.0 functions */
#define GL2_FUNCS_GEN \
......
......@@ -1759,4 +1759,15 @@ typedef struct _WINEDDOVERLAYFX
#define WINEDDGFS_CANFLIP 1L
#define WINEDDGFS_ISFLIPDONE 2L
/* dwFlags for Flip */
#define WINEDDFLIP_WAIT 0x00000001
#define WINEDDFLIP_EVEN 0x00000002 /* only valid for overlay */
#define WINEDDFLIP_ODD 0x00000004 /* only valid for overlay */
#define WINEDDFLIP_NOVSYNC 0x00000008
#define WINEDDFLIP_STEREO 0x00000010
#define WINEDDFLIP_DONOTWAIT 0x00000020
#define WINEDDFLIP_INTERVAL2 0x02000000
#define WINEDDFLIP_INTERVAL3 0x03000000
#define WINEDDFLIP_INTERVAL4 0x04000000
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment