Skip to content

Commit

Permalink
Bug 1484812 - Use SwapBuffersWithDamage on EGL platforms (Wayland/And…
Browse files Browse the repository at this point in the history
…roid) 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
  • Loading branch information
valpackett committed Jan 30, 2020
1 parent 628d88a commit 95ccb8d
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 2 deletions.
11 changes: 11 additions & 0 deletions gfx/gl/GLContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
*/
Expand Down
4 changes: 4 additions & 0 deletions gfx/gl/GLContextEGL.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down
20 changes: 20 additions & 0 deletions gfx/gl/GLContextProviderEGL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
30 changes: 29 additions & 1 deletion gfx/gl/GLLibraryEGL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
13 changes: 12 additions & 1 deletion gfx/gl/GLLibraryEGL.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
};

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down
9 changes: 9 additions & 0 deletions gfx/layers/opengl/CompositorOGL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -2033,6 +2039,7 @@ void CompositorOGL::EndFrame() {

InsertFrameDoneSync();

mGLContext->SetDamage(mCurrentFrameInvalidRegion);
mGLContext->SwapBuffers();
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);

Expand All @@ -2045,6 +2052,8 @@ void CompositorOGL::EndFrame() {
}
}

mCurrentFrameInvalidRegion.SetEmpty();

Compositor::EndFrame();
}

Expand Down
2 changes: 2 additions & 0 deletions gfx/layers/opengl/CompositorOGL.h
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,8 @@ class CompositorOGL final : public Compositor {
*/
gfx::IntSize mViewportSize;

gfx::IntRegion mCurrentFrameInvalidRegion;

ShaderProgramOGL* mCurrentProgram;
};

Expand Down

0 comments on commit 95ccb8d

Please sign in to comment.