Bug 1484812 - Use SwapBuffersWithDamage on EGL platforms (Wayland/Android) r=jnicol,mstange,jgilbert

EGL_KHR_swap_buffers_with_damage (or EGL_EXT_swap_buffers_with_damage)
is an EGL extension that allows the application to inform the display
server (system compositor) which areas of the window have changed.

This commit implements support for that extension in the layers compositor.
The layers compositor always renders the whole frame, so we're only getting
the benefit of not redrawing unchanged areas *in the system compositor*,
not actually doing partial invalidation/compositing,
but that makes the implementation simpler (no need to track buffer age).

Differential Revision: https://phabricator.services.mozilla.com/D51517

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Greg V 2020-01-30 10:46:54 +00:00
Родитель f62b4f716b
Коммит 2befd54d63
7 изменённых файлов: 87 добавлений и 2 удалений

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

@ -36,6 +36,7 @@
#include "GLDefs.h"
#include "GLLibraryLoader.h"
#include "nsISupportsImpl.h"
#include "nsRegionFwd.h"
#include "plstr.h"
#include "GLContextTypes.h"
#include "SurfaceTypes.h"
@ -3351,6 +3352,16 @@ class GLContext : public GenericAtomicRefCounted,
*/
virtual bool SwapBuffers() { return false; }
/**
* Stores a damage region (in origin bottom left coordinates), which
* makes the next SwapBuffers call do eglSwapBuffersWithDamage if supported.
*
* Note that even if only part of the context is damaged, the entire buffer
* needs to be filled with up-to-date contents. This region is only a hint
* telling the system compositor which parts of the buffer were updated.
*/
virtual void SetDamage(const nsIntRegion& aDamageRegion) {}
/**
* Defines a two-dimensional texture image for context target surface
*/

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

@ -70,6 +70,8 @@ class GLContextEGL : public GLContext {
virtual bool SwapBuffers() override;
virtual void SetDamage(const nsIntRegion& aDamageRegion) override;
virtual void GetWSIInfo(nsCString* const out) const override;
// hold a reference to the given surface
@ -117,6 +119,8 @@ class GLContextEGL : public GLContext {
bool mShareWithEGLImage = false;
bool mOwnsContext = true;
nsIntRegion mDamageRegion;
static EGLSurface CreatePBufferSurfaceTryingPowerOfTwo(
GLLibraryEGL*, EGLConfig config, EGLenum bindToTextureFormat,
gfx::IntSize& pbsize);

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

@ -506,12 +506,32 @@ bool GLContextEGL::SwapBuffers() {
EGLSurface surface =
mSurfaceOverride != EGL_NO_SURFACE ? mSurfaceOverride : mSurface;
if (surface) {
if ((mEgl->IsExtensionSupported(
GLLibraryEGL::EXT_swap_buffers_with_damage) ||
mEgl->IsExtensionSupported(
GLLibraryEGL::KHR_swap_buffers_with_damage))) {
std::vector<EGLint> rects;
for (auto iter = mDamageRegion.RectIter(); !iter.Done(); iter.Next()) {
const IntRect& r = iter.Get();
rects.push_back(r.X());
rects.push_back(r.Y());
rects.push_back(r.Width());
rects.push_back(r.Height());
}
mDamageRegion.SetEmpty();
return mEgl->fSwapBuffersWithDamage(mEgl->Display(), surface,
rects.data(), rects.size() / 4);
}
return mEgl->fSwapBuffers(mEgl->Display(), surface);
} else {
return false;
}
}
void GLContextEGL::SetDamage(const nsIntRegion& aDamageRegion) {
mDamageRegion = aDamageRegion;
}
void GLContextEGL::GetWSIInfo(nsCString* const out) const {
out->AppendLiteral("EGL_VENDOR: ");
out->Append(

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

@ -72,7 +72,9 @@ static const char* sEGLExtensionNames[] = {
"EGL_ANGLE_device_creation_d3d11",
"EGL_KHR_surfaceless_context",
"EGL_KHR_create_context_no_error",
"EGL_MOZ_create_context_provoking_vertex_dont_care"};
"EGL_MOZ_create_context_provoking_vertex_dont_care",
"EGL_EXT_swap_buffers_with_damage",
"EGL_KHR_swap_buffers_with_damage"};
PRLibrary* LoadApitraceLibrary() {
const char* path = nullptr;
@ -703,6 +705,32 @@ bool GLLibraryEGL::DoEnsureInitialized(bool forceAccel,
}
}
if (IsExtensionSupported(EXT_swap_buffers_with_damage)) {
const SymLoadStruct symbols[] = {
{(PRFuncPtr*)&mSymbols.fSwapBuffersWithDamage,
{{"eglSwapBuffersWithDamageEXT"}}},
END_OF_SYMBOLS};
if (!fnLoadSymbols(symbols)) {
NS_ERROR(
"EGL supports EXT_swap_buffers_with_damage without exposing its "
"functions!");
MarkExtensionUnsupported(EXT_swap_buffers_with_damage);
}
}
if (IsExtensionSupported(KHR_swap_buffers_with_damage)) {
const SymLoadStruct symbols[] = {
{(PRFuncPtr*)&mSymbols.fSwapBuffersWithDamage,
{{"eglSwapBuffersWithDamageKHR"}}},
END_OF_SYMBOLS};
if (!fnLoadSymbols(symbols)) {
NS_ERROR(
"EGL supports KHR_swap_buffers_with_damage without exposing its "
"functions!");
MarkExtensionUnsupported(KHR_swap_buffers_with_damage);
}
}
mInitialized = true;
reporter.SetSuccessful();
return true;

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

@ -85,6 +85,8 @@ class GLLibraryEGL final {
KHR_surfaceless_context,
KHR_create_context_no_error,
MOZ_create_context_provoking_vertex_dont_care,
EXT_swap_buffers_with_damage,
KHR_swap_buffers_with_damage,
Extensions_Max
};
@ -349,6 +351,11 @@ class GLLibraryEGL final {
EGLBoolean fReleaseDeviceANGLE(EGLDeviceEXT device)
WRAP(fReleaseDeviceANGLE(device))
// EGL_EXT_swap_buffers_with_damage / EGL_KHR_swap_buffers_with_damage
EGLBoolean fSwapBuffersWithDamage(EGLDisplay dpy, EGLSurface surface,
const EGLint* rects, EGLint n_rects)
WRAP(fSwapBuffersWithDamage(dpy, surface, rects, n_rects))
#undef WRAP
#undef VOID_WRAP
#undef PROFILE_CALL
@ -520,7 +527,11 @@ class GLLibraryEGL final {
void* native_device,
const EGLAttrib* attrib_list);
EGLBoolean(GLAPIENTRY* fReleaseDeviceANGLE)(EGLDeviceEXT device);
// EGL_EXT_swap_buffers_with_damage / EGL_KHR_swap_buffers_with_damage
EGLBoolean(GLAPIENTRY* fSwapBuffersWithDamage)(EGLDisplay dpy,
EGLSurface surface,
const EGLint* rects,
EGLint n_rects);
} mSymbols = {};
private:

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

@ -1045,6 +1045,12 @@ Maybe<IntRect> CompositorOGL::BeginFrame(const nsIntRegion& aInvalidRegion,
#endif // defined(MOZ_WIDGET_ANDROID)
mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);
for (auto iter = aInvalidRegion.RectIter(); !iter.Done(); iter.Next()) {
const IntRect& r = iter.Get();
mCurrentFrameInvalidRegion.OrWith(
IntRect(r.X(), FlipY(r.YMost()), r.Width(), r.Height()));
}
return Some(rect);
}
@ -2033,6 +2039,7 @@ void CompositorOGL::EndFrame() {
InsertFrameDoneSync();
mGLContext->SetDamage(mCurrentFrameInvalidRegion);
mGLContext->SwapBuffers();
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
@ -2045,6 +2052,8 @@ void CompositorOGL::EndFrame() {
}
}
mCurrentFrameInvalidRegion.SetEmpty();
Compositor::EndFrame();
}

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

@ -523,6 +523,8 @@ class CompositorOGL final : public Compositor {
*/
gfx::IntSize mViewportSize;
gfx::IntRegion mCurrentFrameInvalidRegion;
ShaderProgramOGL* mCurrentProgram;
};