mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 15:52:07 +00:00
Bug 649525 - WebGL layer compositing through the BasicCanvasLayer is very slow (desktop version). r=jmuizelaar
This commit is contained in:
parent
5572ff62cb
commit
4e4c1347d5
@ -330,6 +330,7 @@ XCOMPOSITE_LIBS = @XCOMPOSITE_LIBS@
|
||||
XSS_LIBS = @XSS_LIBS@
|
||||
|
||||
MOZ_THUMB2 = @MOZ_THUMB2@
|
||||
MOZ_EGL_XRENDER_COMPOSITE = @MOZ_EGL_XRENDER_COMPOSITE@
|
||||
|
||||
WIN_TOP_SRC = @WIN_TOP_SRC@
|
||||
AR = @AR@
|
||||
|
14
configure.in
14
configure.in
@ -7178,6 +7178,20 @@ fi # CPU_ARCH = arm
|
||||
AC_SUBST(HAVE_ARM_SIMD)
|
||||
AC_SUBST(HAVE_ARM_NEON)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = XRender Composite
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(egl-xrender-composite,
|
||||
[ --enable-egl-xrender-composite
|
||||
Enable EGL xrender composite optimizations],
|
||||
MOZ_EGL_XRENDER_COMPOSITE=1)
|
||||
|
||||
if test -n "$MOZ_EGL_XRENDER_COMPOSITE"; then
|
||||
AC_DEFINE(MOZ_EGL_XRENDER_COMPOSITE)
|
||||
fi
|
||||
|
||||
AC_SUBST(MOZ_EGL_XRENDER_COMPOSITE)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = faststripe theme
|
||||
dnl ========================================================
|
||||
|
@ -422,9 +422,11 @@ _cairo_xlib_device_create (Display *dpy)
|
||||
if (VendorRelease (dpy) < 10400000)
|
||||
display->buggy_repeat = TRUE;
|
||||
|
||||
#ifndef MOZ_EGL_XRENDER_COMPOSITE
|
||||
/* Too many bugs in the early drivers */
|
||||
if (VendorRelease (dpy) < 10699000)
|
||||
display->buggy_pad_reflect = TRUE;
|
||||
#endif
|
||||
}
|
||||
} else if (strstr (ServerVendor (dpy), "XFree86") != NULL) {
|
||||
if (VendorRelease (dpy) <= 40500000)
|
||||
|
@ -1082,6 +1082,22 @@ BasicCanvasLayer::UpdateSurface(gfxASurface* aDestSurface)
|
||||
return;
|
||||
}
|
||||
|
||||
// We need to read from the GLContext
|
||||
mGLContext->MakeCurrent();
|
||||
|
||||
#if defined (MOZ_X11) && defined (MOZ_EGL_XRENDER_COMPOSITE)
|
||||
mGLContext->fFinish();
|
||||
gfxASurface* offscreenSurface = mGLContext->GetOffscreenPixmapSurface();
|
||||
|
||||
// XRender can only blend premuliplied alpha, so only allow xrender
|
||||
// path if we have premultiplied alpha or opaque content.
|
||||
if (offscreenSurface && (mGLBufferIsPremultiplied || (GetContentFlags() & CONTENT_OPAQUE))) {
|
||||
mSurface = offscreenSurface;
|
||||
mNeedsYFlip = false;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
nsRefPtr<gfxImageSurface> isurf = aDestSurface ?
|
||||
static_cast<gfxImageSurface*>(aDestSurface) :
|
||||
new gfxImageSurface(gfxIntSize(mBounds.width, mBounds.height),
|
||||
@ -1095,9 +1111,6 @@ BasicCanvasLayer::UpdateSurface(gfxASurface* aDestSurface)
|
||||
|
||||
NS_ASSERTION(isurf->Stride() == mBounds.width * 4, "gfxImageSurface stride isn't what we expect!");
|
||||
|
||||
// We need to read from the GLContext
|
||||
mGLContext->MakeCurrent();
|
||||
|
||||
// We have to flush to ensure that any buffered GL operations are
|
||||
// in the framebuffer before we read.
|
||||
mGLContext->fFlush();
|
||||
@ -1132,6 +1145,7 @@ BasicCanvasLayer::UpdateSurface(gfxASurface* aDestSurface)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BasicCanvasLayer::Paint(gfxContext* aContext)
|
||||
@ -1162,6 +1176,15 @@ BasicCanvasLayer::PaintWithOpacity(gfxContext* aContext,
|
||||
aContext->Scale(1.0, -1.0);
|
||||
}
|
||||
|
||||
// If content opaque, then save off current operator and set to source.
|
||||
// This ensures that alpha is not applied even if the source surface
|
||||
// has an alpha channel
|
||||
gfxContext::GraphicsOperator savedOp;
|
||||
if (GetContentFlags() & CONTENT_OPAQUE) {
|
||||
savedOp = aContext->CurrentOperator();
|
||||
aContext->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
}
|
||||
|
||||
AutoSetOperator setOperator(aContext, GetOperator());
|
||||
aContext->NewPath();
|
||||
// No need to snap here; our transform is already set up to snap our rect
|
||||
@ -1169,6 +1192,19 @@ BasicCanvasLayer::PaintWithOpacity(gfxContext* aContext,
|
||||
aContext->SetPattern(pat);
|
||||
aContext->FillWithOpacity(aOpacity);
|
||||
|
||||
#if defined (MOZ_X11) && defined (MOZ_EGL_XRENDER_COMPOSITE)
|
||||
if (mGLContext) {
|
||||
// Wait for X to complete all operations before continuing
|
||||
// Otherwise gl context could get cleared before X is done.
|
||||
mGLContext->WaitNative();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Restore surface operator
|
||||
if (GetContentFlags() & CONTENT_OPAQUE) {
|
||||
aContext->SetOperator(savedOp);
|
||||
}
|
||||
|
||||
if (mNeedsYFlip) {
|
||||
aContext->SetMatrix(m);
|
||||
}
|
||||
|
@ -66,7 +66,7 @@
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#if defined(MOZ_PLATFORM_MAEMO) || defined(ANDROID)
|
||||
#if defined(MOZ_PLATFORM_MAEMO) || defined(ANDROID) || defined(MOZ_EGL_XRENDER_COMPOSITE)
|
||||
#define USE_GLES2 1
|
||||
#endif
|
||||
|
||||
@ -737,6 +737,15 @@ public:
|
||||
return mOffscreenTexture;
|
||||
}
|
||||
|
||||
#if defined(MOZ_X11) && defined(MOZ_EGL_XRENDER_COMPOSITE)
|
||||
virtual gfxASurface* GetOffscreenPixmapSurface()
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
|
||||
virtual PRBool WaitNative() { return PR_FALSE; }
|
||||
#endif
|
||||
|
||||
virtual PRBool TextureImageSupportsGetBackingSurface() {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
@ -84,6 +84,14 @@ namespace gl {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// X11, with XRender optimizations and no GL layer support
|
||||
#if defined(MOZ_X11) && defined(MOZ_EGL_XRENDER_COMPOSITE) && !defined(GL_CONTEXT_PROVIDER_DEFAULT)
|
||||
#define GL_CONTEXT_PROVIDER_NAME GLContextProviderEGL
|
||||
#include "GLContextProviderImpl.h"
|
||||
#undef GL_CONTEXT_PROVIDER_NAME
|
||||
#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderEGL
|
||||
#endif
|
||||
|
||||
// X11, but only if we didn't use EGL above
|
||||
#if defined(MOZ_X11) && !defined(GL_CONTEXT_PROVIDER_DEFAULT)
|
||||
#define GL_CONTEXT_PROVIDER_NAME GLContextProviderGLX
|
||||
|
@ -192,6 +192,12 @@ CreateSurfaceForWindow(nsIWidget *aWidget, EGLConfig config);
|
||||
EGLConfig
|
||||
CreateConfig();
|
||||
#ifdef MOZ_X11
|
||||
|
||||
#ifdef MOZ_EGL_XRENDER_COMPOSITE
|
||||
static EGLSurface
|
||||
CreateBasicEGLSurfaceForXSurface(gfxASurface* aSurface, EGLConfig* aConfig);
|
||||
#endif
|
||||
|
||||
static EGLConfig
|
||||
CreateEGLSurfaceForXSurface(gfxASurface* aSurface, EGLConfig* aConfig = nsnull, EGLenum aDepth = 0);
|
||||
#endif
|
||||
@ -391,7 +397,11 @@ public:
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
#if defined(MOZ_X11) && defined(MOZ_EGL_XRENDER_COMPOSITE)
|
||||
mEGLDisplay = fGetDisplay((EGLNativeDisplayType) gdk_x11_get_default_xdisplay());
|
||||
#else
|
||||
mEGLDisplay = fGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
#endif
|
||||
if (!fInitialize(mEGLDisplay, NULL, NULL))
|
||||
return PR_FALSE;
|
||||
|
||||
@ -720,6 +730,17 @@ public:
|
||||
mIsDoubleBuffered = aIsDB;
|
||||
}
|
||||
|
||||
#if defined(MOZ_X11) && defined(MOZ_EGL_XRENDER_COMPOSITE)
|
||||
gfxASurface* GetOffscreenPixmapSurface()
|
||||
{
|
||||
return mThebesSurface;
|
||||
}
|
||||
|
||||
virtual PRBool WaitNative() {
|
||||
return sEGLLibrary.fWaitNative(LOCAL_EGL_CORE_NATIVE_ENGINE);
|
||||
}
|
||||
#endif
|
||||
|
||||
PRBool BindTexImage()
|
||||
{
|
||||
if (!mSurface)
|
||||
@ -857,6 +878,14 @@ public:
|
||||
const ContextFormat& aFormat,
|
||||
PRBool aShare);
|
||||
|
||||
#if defined(MOZ_X11) && defined(MOZ_EGL_XRENDER_COMPOSITE)
|
||||
static already_AddRefed<GLContextEGL>
|
||||
CreateBasicEGLPixmapOffscreenContext(const gfxIntSize& aSize,
|
||||
const ContextFormat& aFormat);
|
||||
|
||||
PRBool ResizeOffscreenPixmapSurface(const gfxIntSize& aNewSize);
|
||||
#endif
|
||||
|
||||
static already_AddRefed<GLContextEGL>
|
||||
CreateEGLPBufferOffscreenContext(const gfxIntSize& aSize,
|
||||
const ContextFormat& aFormat);
|
||||
@ -1060,6 +1089,10 @@ GLContextEGL::ResizeOffscreen(const gfxIntSize& aNewSize)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_X11) && defined(MOZ_EGL_XRENDER_COMPOSITE)
|
||||
return ResizeOffscreenPixmapSurface(aNewSize);
|
||||
#endif
|
||||
|
||||
return ResizeOffscreenFBO(aNewSize);
|
||||
}
|
||||
|
||||
@ -2139,6 +2172,8 @@ GLContextProviderEGL::CreateOffscreen(const gfxIntSize& aSize,
|
||||
|
||||
#if defined(ANDROID) || defined(XP_WIN)
|
||||
return GLContextEGL::CreateEGLPBufferOffscreenContext(aSize, aFormat);
|
||||
#elif defined(MOZ_X11) && defined(MOZ_EGL_XRENDER_COMPOSITE)
|
||||
return GLContextEGL::CreateBasicEGLPixmapOffscreenContext(aSize, aFormat);
|
||||
#elif defined(MOZ_X11)
|
||||
nsRefPtr<GLContextEGL> glContext =
|
||||
GLContextEGL::CreateEGLPixmapOffscreenContext(aSize, aFormat, PR_TRUE);
|
||||
@ -2241,6 +2276,181 @@ GLContextProviderEGL::Shutdown()
|
||||
gGlobalContext = nsnull;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// The following methods exist to support an accelerated WebGL XRender composite
|
||||
// path for BasicLayers. This is a potentially temporary change that can be
|
||||
// removed when performance of GL layers is superior on mobile linux platforms.
|
||||
//------------------------------------------------------------------------------
|
||||
#if defined(MOZ_X11) && defined(MOZ_EGL_XRENDER_COMPOSITE)
|
||||
|
||||
EGLSurface
|
||||
CreateBasicEGLSurfaceForXSurface(gfxASurface* aSurface, EGLConfig* aConfig)
|
||||
{
|
||||
gfxXlibSurface* xsurface = static_cast<gfxXlibSurface*>(aSurface);
|
||||
|
||||
PRBool opaque =
|
||||
aSurface->GetContentType() == gfxASurface::CONTENT_COLOR;
|
||||
|
||||
EGLSurface surface = nsnull;
|
||||
if (aConfig && *aConfig) {
|
||||
surface = sEGLLibrary.fCreatePixmapSurface(EGL_DISPLAY(), *aConfig,
|
||||
xsurface->XDrawable(),
|
||||
0);
|
||||
|
||||
if (surface != EGL_NO_SURFACE)
|
||||
return surface;
|
||||
}
|
||||
|
||||
EGLConfig configs[32];
|
||||
int numConfigs = 32;
|
||||
|
||||
static EGLint pixmap_config[] = {
|
||||
LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_PIXMAP_BIT,
|
||||
LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT,
|
||||
0x30E2, 0x30E3,
|
||||
LOCAL_EGL_DEPTH_SIZE, 16,
|
||||
LOCAL_EGL_NONE
|
||||
};
|
||||
|
||||
if (!sEGLLibrary.fChooseConfig(EGL_DISPLAY(),
|
||||
pixmap_config,
|
||||
configs, numConfigs, &numConfigs))
|
||||
return nsnull;
|
||||
|
||||
if (numConfigs == 0)
|
||||
return nsnull;
|
||||
|
||||
int i = 0;
|
||||
for (i = 0; i < numConfigs; ++i) {
|
||||
surface = sEGLLibrary.fCreatePixmapSurface(EGL_DISPLAY(), configs[i],
|
||||
xsurface->XDrawable(),
|
||||
0);
|
||||
|
||||
if (surface != EGL_NO_SURFACE)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!surface) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (aConfig)
|
||||
{
|
||||
*aConfig = configs[i];
|
||||
}
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
already_AddRefed<GLContextEGL>
|
||||
GLContextEGL::CreateBasicEGLPixmapOffscreenContext(const gfxIntSize& aSize,
|
||||
const ContextFormat& aFormat)
|
||||
{
|
||||
gfxASurface *thebesSurface = nsnull;
|
||||
EGLNativePixmapType pixmap = 0;
|
||||
|
||||
XRenderPictFormat* format = gfxXlibSurface::FindRenderFormat(DefaultXDisplay(), gfxASurface::ImageFormatARGB32);
|
||||
|
||||
nsRefPtr<gfxXlibSurface> xsurface =
|
||||
gfxXlibSurface::Create(DefaultScreenOfDisplay(DefaultXDisplay()), format, aSize);
|
||||
|
||||
// XSync required after gfxXlibSurface::Create, otherwise EGL will fail with BadDrawable error
|
||||
XSync(DefaultXDisplay(), False);
|
||||
if (xsurface->CairoStatus() != 0)
|
||||
{
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
thebesSurface = xsurface;
|
||||
|
||||
pixmap = xsurface->XDrawable();
|
||||
|
||||
if (!pixmap) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
EGLSurface surface = 0;
|
||||
EGLConfig config = 0;
|
||||
|
||||
surface = CreateBasicEGLSurfaceForXSurface(xsurface, &config);
|
||||
|
||||
if (!config) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
EGLint cxattribs[] = {
|
||||
LOCAL_EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
LOCAL_EGL_NONE
|
||||
};
|
||||
|
||||
EGLContext context = sEGLLibrary.fCreateContext(EGL_DISPLAY(),
|
||||
config,
|
||||
EGL_NO_CONTEXT,
|
||||
cxattribs);
|
||||
if (!context) {
|
||||
sEGLLibrary.fDestroySurface(EGL_DISPLAY(), surface);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<GLContextEGL> glContext = new GLContextEGL(aFormat, nsnull,
|
||||
config, surface, context,
|
||||
PR_TRUE);
|
||||
|
||||
if (!glContext->Init())
|
||||
{
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
glContext->HoldSurface(thebesSurface);
|
||||
|
||||
return glContext.forget();
|
||||
}
|
||||
|
||||
PRBool GLContextEGL::ResizeOffscreenPixmapSurface(const gfxIntSize& aNewSize)
|
||||
{
|
||||
gfxASurface *thebesSurface = nsnull;
|
||||
EGLNativePixmapType pixmap = 0;
|
||||
|
||||
XRenderPictFormat* format = gfxXlibSurface::FindRenderFormat(DefaultXDisplay(), gfxASurface::ImageFormatARGB32);
|
||||
|
||||
nsRefPtr<gfxXlibSurface> xsurface =
|
||||
gfxXlibSurface::Create(DefaultScreenOfDisplay(DefaultXDisplay()),
|
||||
format,
|
||||
aNewSize);
|
||||
|
||||
// XSync required after gfxXlibSurface::Create, otherwise EGL will fail with BadDrawable error
|
||||
XSync(DefaultXDisplay(), False);
|
||||
if (xsurface->CairoStatus() != 0)
|
||||
return nsnull;
|
||||
|
||||
thebesSurface = xsurface;
|
||||
|
||||
pixmap = xsurface->XDrawable();
|
||||
|
||||
if (!pixmap) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
EGLSurface surface = 0;
|
||||
EGLConfig config = 0;
|
||||
surface = CreateBasicEGLSurfaceForXSurface(xsurface, &config);
|
||||
if (!surface) {
|
||||
NS_WARNING("Failed to resize pbuffer");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
sEGLLibrary.fDestroySurface(EGL_DISPLAY(), mSurface);
|
||||
|
||||
mSurface = surface;
|
||||
HoldSurface(thebesSurface);
|
||||
SetOffscreenSize(aNewSize, aNewSize);
|
||||
MakeCurrent(PR_TRUE);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} /* namespace gl */
|
||||
} /* namespace mozilla */
|
||||
|
||||
|
@ -3197,5 +3197,6 @@ typedef ptrdiff_t GLintptr;
|
||||
#define LOCAL_EGL_READ_SURFACE_BIT_KHR 0x0001
|
||||
#define LOCAL_EGL_WRITE_SURFACE_BIT_KHR 0x0002
|
||||
#define LOCAL_EGL_LOCK_SURFACE_BIT_KHR 0x0080
|
||||
#define LOCAL_EGL_CORE_NATIVE_ENGINE 0x305B
|
||||
|
||||
#endif
|
||||
|
@ -338,9 +338,13 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
|
||||
ifdef MOZ_PLATFORM_MAEMO
|
||||
GL_PROVIDER = EGL
|
||||
else
|
||||
ifdef MOZ_EGL_XRENDER_COMPOSITE
|
||||
GL_PROVIDER = EGL
|
||||
else
|
||||
GL_PROVIDER = GLX
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),qt)
|
||||
ifdef MOZ_PLATFORM_MAEMO
|
||||
|
Loading…
Reference in New Issue
Block a user