Bug 1280744 - Set swap interval to 0 when running in ASAP mode on GLX. r=jgilbert
MozReview-Commit-ID: FYKDeBVUhnd
--- a/gfx/gl/GLContextProviderGLX.cpp
+++ b/gfx/gl/GLContextProviderGLX.cpp
@@ -170,16 +170,21 @@ GLXLibrary::EnsureInitialized()
};
GLLibraryLoader::SymLoadStruct symbols_videosync[] = {
{ (PRFuncPtr*) &xGetVideoSyncInternal, { "glXGetVideoSyncSGI", nullptr } },
{ (PRFuncPtr*) &xWaitVideoSyncInternal, { "glXWaitVideoSyncSGI", nullptr } },
{ nullptr, { nullptr } }
};
+ GLLibraryLoader::SymLoadStruct symbols_swapcontrol[] = {
+ { (PRFuncPtr*) &xSwapIntervalInternal, { "glXSwapIntervalEXT", nullptr } },
+ { nullptr, { nullptr } }
+ };
+
if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, &symbols[0])) {
NS_WARNING("Couldn't find required entry point in OpenGL shared library");
return false;
}
Display* display = DefaultXDisplay();
int screen = DefaultScreen(display);
@@ -254,16 +259,22 @@ GLXLibrary::EnsureInitialized()
if (HasExtension(extensionsStr, "GLX_SGI_video_sync") &&
GLLibraryLoader::LoadSymbols(mOGLLibrary, symbols_videosync,
(GLLibraryLoader::PlatformLookupFunction)&xGetProcAddress))
{
mHasVideoSync = true;
}
+ if (!(HasExtension(extensionsStr, "GLX_EXT_swap_control") &&
+ GLLibraryLoader::LoadSymbols(mOGLLibrary, symbols_swapcontrol)))
+ {
+ NS_WARNING("GLX_swap_control unsupported, ASAP mode may still block on buffer swaps.");
+ }
+
mIsATI = serverVendor && DoesStringMatch(serverVendor, "ATI");
mIsNVIDIA = serverVendor && DoesStringMatch(serverVendor, "NVIDIA Corporation");
mClientIsMesa = clientVendor && DoesStringMatch(clientVendor, "Mesa");
mInitialized = true;
return true;
}
@@ -773,16 +784,24 @@ int
GLXLibrary::xWaitVideoSync(int divisor, int remainder, unsigned int* count)
{
BEFORE_GLX_CALL;
int result = xWaitVideoSyncInternal(divisor, remainder, count);
AFTER_GLX_CALL;
return result;
}
+void
+GLXLibrary::xSwapInterval(Display* display, GLXDrawable drawable, int interval)
+{
+ BEFORE_GLX_CALL;
+ xSwapIntervalInternal(display, drawable, interval);
+ AFTER_GLX_CALL;
+}
+
already_AddRefed<GLContextGLX>
GLContextGLX::CreateGLContext(CreateContextFlags flags, const SurfaceCaps& caps,
GLContextGLX* shareContext, bool isOffscreen,
Display* display, GLXDrawable drawable, GLXFBConfig cfg,
bool deleteDrawable, gfxXlibSurface* pixmap,
ContextProfile profile)
{
GLXLibrary& glx = sGLXLibrary;
@@ -918,16 +937,24 @@ GLContextGLX::MakeCurrentImpl(bool aForc
// (This is not the case with other drivers such as NVIDIA).
// So avoid calling it more than necessary. Since GLX documentation says that:
// "glXGetCurrentContext returns client-side information.
// It does not make a round trip to the server."
// I assume that it's not worth using our own TLS slot here.
if (aForce || mGLX->xGetCurrentContext() != mContext) {
succeeded = mGLX->xMakeCurrent(mDisplay, mDrawable, mContext);
NS_ASSERTION(succeeded, "Failed to make GL context current!");
+
+ if (!IsOffscreen() && mGLX->SupportsSwapControl()) {
+ // Many GLX implementations default to blocking until the next
+ // VBlank when calling glXSwapBuffers. We want to run unthrottled
+ // in ASAP mode. See bug 1280744.
+ int interval = gfxPlatform::IsInLayoutAsapMode() ? 0 : 1;
+ mGLX->xSwapInterval(mDisplay, mDrawable, interval);
+ }
}
return succeeded;
}
bool
GLContextGLX::IsCurrent() {
return mGLX->xGetCurrentContext() == mContext;
--- a/gfx/gl/GLXLibrary.h
+++ b/gfx/gl/GLXLibrary.h
@@ -51,16 +51,17 @@ public:
, xQueryVersionInternal(nullptr)
, xBindTexImageInternal(nullptr)
, xReleaseTexImageInternal(nullptr)
, xWaitGLInternal(nullptr)
, xWaitXInternal(nullptr)
, xCreateContextAttribsInternal(nullptr)
, xGetVideoSyncInternal(nullptr)
, xWaitVideoSyncInternal(nullptr)
+ , xSwapIntervalInternal(nullptr)
, mInitialized(false), mTriedInitializing(false)
, mUseTextureFromPixmap(false), mDebug(false)
, mHasRobustness(false), mHasCreateContextAttribs(false)
, mHasVideoSync(false)
, mIsATI(false), mIsNVIDIA(false)
, mClientIsMesa(false), mGLXMajorVersion(0)
, mGLXMinorVersion(0)
, mOGLLibrary(nullptr)
@@ -120,30 +121,32 @@ public:
GLXContext xCreateContextAttribs(Display* display,
GLXFBConfig config,
GLXContext share_list,
Bool direct,
const int* attrib_list);
int xGetVideoSync(unsigned int* count);
int xWaitVideoSync(int divisor, int remainder, unsigned int* count);
+ void xSwapInterval(Display* dpy, GLXDrawable drawable, int interval);
bool EnsureInitialized();
GLXPixmap CreatePixmap(gfxASurface* aSurface);
void DestroyPixmap(Display* aDisplay, GLXPixmap aPixmap);
void BindTexImage(Display* aDisplay, GLXPixmap aPixmap);
void ReleaseTexImage(Display* aDisplay, GLXPixmap aPixmap);
void UpdateTexImage(Display* aDisplay, GLXPixmap aPixmap);
bool UseTextureFromPixmap() { return mUseTextureFromPixmap; }
bool HasRobustness() { return mHasRobustness; }
bool HasCreateContextAttribs() { return mHasCreateContextAttribs; }
bool SupportsTextureFromPixmap(gfxASurface* aSurface);
bool SupportsVideoSync();
+ bool SupportsSwapControl() const { return bool(xSwapIntervalInternal); }
bool IsATI() { return mIsATI; }
bool GLXVersionCheck(int aMajor, int aMinor);
private:
typedef void (GLAPIENTRY * PFNGLXDESTROYCONTEXTPROC) (Display*,
GLXContext);
PFNGLXDESTROYCONTEXTPROC xDestroyContextInternal;
@@ -233,16 +236,19 @@ private:
PFNGLXCREATECONTEXTATTRIBS xCreateContextAttribsInternal;
typedef int (GLAPIENTRY * PFNGLXGETVIDEOSYNCSGI) (unsigned int* count);
PFNGLXGETVIDEOSYNCSGI xGetVideoSyncInternal;
typedef int (GLAPIENTRY * PFNGLXWAITVIDEOSYNCSGI) (int divisor, int remainder, unsigned int* count);
PFNGLXWAITVIDEOSYNCSGI xWaitVideoSyncInternal;
+ typedef void (GLAPIENTRY * PFNGLXSWAPINTERVALEXT) (Display* dpy, GLXDrawable drawable, int interval);
+ PFNGLXSWAPINTERVALEXT xSwapIntervalInternal;
+
#ifdef DEBUG
void BeforeGLXCall();
void AfterGLXCall();
#endif
bool mInitialized;
bool mTriedInitializing;
bool mUseTextureFromPixmap;