Bug 1677165 - Add support for partial present to GLX. r=kvark,jgilbert

This adds support for GLX_EXT_buffer_age if available to minimize how
much must be redrawn when using GLX.

Differential Revision: https://phabricator.services.mozilla.com/D93098
This commit is contained in:
Andrew Osmond 2020-11-13 18:41:41 +00:00
Родитель e2b0a11bac
Коммит ca9f3b661d
9 изменённых файлов: 66 добавлений и 8 удалений

Просмотреть файл

@ -3381,6 +3381,12 @@ class GLContext : public GenericAtomicRefCounted, public SupportsWeakPtr {
*/
virtual void SetDamage(const nsIntRegion& aDamageRegion) {}
/**
* Get the buffer age. If it returns 0, that indicates the buffer state is
* unknown and the entire frame should be redrawn.
*/
virtual GLint GetBufferAge() const { return 0; }
/**
* Defines a two-dimensional texture image for context target surface
*/

Просмотреть файл

@ -90,6 +90,8 @@ class GLContextEGL final : public GLContext {
virtual void SetDamage(const nsIntRegion& aDamageRegion) override;
GLint GetBufferAge() const override;
virtual void GetWSIInfo(nsCString* const out) const override;
// hold a reference to the given surface
@ -100,7 +102,6 @@ class GLContextEGL final : public GLContext {
bool HasExtBufferAge() const;
bool HasKhrPartialUpdate() const;
EGLint GetBufferAge() const;
bool BindTex2DOffscreen(GLContext* aOffscreen);
void UnbindTex2DOffscreen(GLContext* aOffscreen);

Просмотреть файл

@ -53,6 +53,8 @@ class GLContextGLX : public GLContext {
bool SwapBuffers() override;
GLint GetBufferAge() const override;
void GetWSIInfo(nsCString* const out) const override;
// Overrides the current GLXDrawable backing the context and makes the

Просмотреть файл

@ -606,7 +606,7 @@ bool GLContextEGL::HasKhrPartialUpdate() const {
return mEgl->IsExtensionSupported(EGLExtension::KHR_partial_update);
}
EGLint GLContextEGL::GetBufferAge() const {
GLint GLContextEGL::GetBufferAge() const {
EGLSurface surface =
mSurfaceOverride != EGL_NO_SURFACE ? mSurfaceOverride : mSurface;

Просмотреть файл

@ -171,6 +171,9 @@ bool GLXLibrary::EnsureInitialized() {
const SymLoadStruct symbols_swapcontrol[] = {SYMBOL(SwapIntervalEXT),
END_OF_SYMBOLS};
const SymLoadStruct symbols_querydrawable[] = {SYMBOL(QueryDrawable),
END_OF_SYMBOLS};
const auto fnLoadSymbols = [&](const SymLoadStruct* symbols) {
if (pfnLoader.LoadSymbols(symbols)) return true;
@ -217,6 +220,11 @@ bool GLXLibrary::EnsureInitialized() {
"swaps.");
}
if (HasExtension(extensionsStr, "GLX_EXT_buffer_age") &&
fnLoadSymbols(symbols_querydrawable)) {
mHasBufferAge = true;
}
mIsATI = serverVendor && DoesStringMatch(serverVendor, "ATI");
mIsNVIDIA =
serverVendor && DoesStringMatch(serverVendor, "NVIDIA Corporation");
@ -619,6 +627,21 @@ bool GLContextGLX::SwapBuffers() {
return true;
}
GLint GLContextGLX::GetBufferAge() const {
if (!sGLXLibrary.SupportsBufferAge()) {
return 0;
}
GLuint result = 0;
mGLX->fQueryDrawable(mDisplay, mDrawable, LOCAL_GLX_BACK_BUFFER_AGE_EXT,
&result);
if (result > INT32_MAX) {
// If the result can't fit, just assume the buffer cannot be reused.
return 0;
}
return result;
}
void GLContextGLX::GetWSIInfo(nsCString* const out) const {
Display* display = DefaultXDisplay();
int screen = DefaultScreen(display);

Просмотреть файл

@ -154,6 +154,10 @@ class GLXLibrary final {
int interval) const
VOID_WRAP(fSwapIntervalEXT(dpy, drawable, interval))
int fQueryDrawable(Display* dpy, GLXDrawable drawable, int attribute,
unsigned int* value) const
WRAP(fQueryDrawable(dpy, drawable, attribute, value))
#undef WRAP
#undef VOID_WRAP
#undef BEFORE_CALL
@ -176,6 +180,10 @@ class GLXLibrary final {
bool SupportsTextureFromPixmap(gfxASurface* aSurface);
bool SupportsVideoSync();
bool SupportsSwapControl() const { return bool(mSymbols.fSwapIntervalEXT); }
bool SupportsBufferAge() const {
MOZ_ASSERT(mInitialized);
return mHasBufferAge;
}
bool IsATI() { return mIsATI; }
bool IsMesa() { return mClientIsMesa; }
@ -214,6 +222,7 @@ class GLXLibrary final {
int(GLAPIENTRY* fGetVideoSyncSGI)(unsigned int*);
int(GLAPIENTRY* fWaitVideoSyncSGI)(int, int, unsigned int*);
void(GLAPIENTRY* fSwapIntervalEXT)(Display*, GLXDrawable, int);
int(GLAPIENTRY* fQueryDrawable)(Display*, GLXDrawable, int, unsigned int*);
} mSymbols = {};
#ifdef DEBUG
@ -229,6 +238,7 @@ class GLXLibrary final {
bool mHasVideoMemoryPurge = false;
bool mHasCreateContextAttribs = false;
bool mHasVideoSync = false;
bool mHasBufferAge = false;
bool mIsATI = false;
bool mIsNVIDIA = false;
bool mClientIsMesa = false;

Просмотреть файл

@ -10,6 +10,7 @@
#include "GLContextEGL.h"
#include "GLContextProvider.h"
#include "GLLibraryEGL.h"
#include "mozilla/StaticPrefs_gfx.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/layers/BuildConstants.h"
#include "mozilla/webrender/RenderThread.h"
@ -244,7 +245,11 @@ bool RenderCompositorEGL::ShouldDrawPreviousPartialPresentRegions() {
}
size_t RenderCompositorEGL::GetBufferAge() const {
return gl::GLContextEGL::Cast(gl())->GetBufferAge();
if (!StaticPrefs::
gfx_webrender_allow_partial_present_buffer_age_AtStartup()) {
return 0;
}
return gl()->GetBufferAge();
}
void RenderCompositorEGL::SetBufferDamageRegion(const wr::DeviceIntRect* aRects,

Просмотреть файл

@ -104,13 +104,13 @@ CompositorCapabilities RenderCompositorOGL::GetCompositorCapabilities() {
}
uint32_t RenderCompositorOGL::GetMaxPartialPresentRects() {
return mIsEGL ? gfx::gfxVars::WebRenderMaxPartialPresentRects() : 0;
return gfx::gfxVars::WebRenderMaxPartialPresentRects();
}
bool RenderCompositorOGL::RequestFullRender() { return false; }
bool RenderCompositorOGL::UsePartialPresent() {
return mIsEGL && gfx::gfxVars::WebRenderMaxPartialPresentRects() > 0;
return gfx::gfxVars::WebRenderMaxPartialPresentRects() > 0;
}
bool RenderCompositorOGL::ShouldDrawPreviousPartialPresentRegions() {
@ -118,10 +118,11 @@ bool RenderCompositorOGL::ShouldDrawPreviousPartialPresentRegions() {
}
size_t RenderCompositorOGL::GetBufferAge() const {
if (mIsEGL) {
return gl::GLContextEGL::Cast(gl())->GetBufferAge();
if (!StaticPrefs::
gfx_webrender_allow_partial_present_buffer_age_AtStartup()) {
return 0;
}
return 0;
return gl()->GetBufferAge();
}
} // namespace wr

Просмотреть файл

@ -4569,6 +4569,8 @@
value: 25
mirror: once
# Number of damage rects we can give to the compositor for a new frame with
# partial present. This controls whether partial present is used or not.
- name: gfx.webrender.max-partial-present-rects
type: uint32_t
#if defined(XP_WIN) || defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GTK)
@ -4578,6 +4580,14 @@
#endif
mirror: once
# Whether or not we can reuse the buffer contents using the GL buffer age
# extension, if supported by the platform. This requires partial present
# to be used.
- name: gfx.webrender.allow-partial-present-buffer-age
type: bool
value: true
mirror: once
- name: gfx.webrender.enable-gpu-markers
type: bool
#ifdef DEBUG