Bug 1187322 - Don't require accelerated OpenGL contexts for BasicCompositor on OS X. r?jrmuizel
--- a/gfx/gl/GLContextProviderCGL.mm
+++ b/gfx/gl/GLContextProviderCGL.mm
@@ -12,16 +12,20 @@
#include "gfxFailure.h"
#include "gfxPrefs.h"
#include "prenv.h"
#include "GeckoProfiler.h"
#include "mozilla/gfx/MacIOSurface.h"
#include <OpenGL/OpenGL.h>
+// When running inside a VM, creating an accelerated OpenGL context usually
+// fails. Uncomment this line to emulate that behavior.
+// #define EMULATE_VM
+
namespace mozilla {
namespace gl {
using namespace mozilla::gfx;
class CGLLibrary
{
public:
@@ -169,22 +173,33 @@ GLContextCGL::SwapBuffers()
already_AddRefed<GLContext>
GLContextProviderCGL::CreateWrappingExisting(void*, void*)
{
return nullptr;
}
static const NSOpenGLPixelFormatAttribute kAttribs_singleBuffered[] = {
+ NSOpenGLPFAAllowOfflineRenderers,
+ 0
+};
+
+static const NSOpenGLPixelFormatAttribute kAttribs_singleBuffered_accel[] = {
NSOpenGLPFAAccelerated,
NSOpenGLPFAAllowOfflineRenderers,
0
};
static const NSOpenGLPixelFormatAttribute kAttribs_doubleBuffered[] = {
+ NSOpenGLPFAAllowOfflineRenderers,
+ NSOpenGLPFADoubleBuffer,
+ 0
+};
+
+static const NSOpenGLPixelFormatAttribute kAttribs_doubleBuffered_accel[] = {
NSOpenGLPFAAccelerated,
NSOpenGLPFAAllowOfflineRenderers,
NSOpenGLPFADoubleBuffer,
0
};
static const NSOpenGLPixelFormatAttribute kAttribs_offscreen[] = {
0
@@ -220,27 +235,33 @@ CreateWithFormat(const NSOpenGLPixelForm
shareContext:nullptr];
[format release];
return context;
}
already_AddRefed<GLContext>
-GLContextProviderCGL::CreateForWindow(nsIWidget *aWidget)
+GLContextProviderCGL::CreateForWindow(nsIWidget *aWidget, bool aForceAccelerated)
{
if (!sCGLLibrary.EnsureInitialized()) {
return nullptr;
}
+#ifdef EMULATE_VM
+ if (aForceAccelerated) {
+ return nullptr;
+ }
+#endif
+
const NSOpenGLPixelFormatAttribute* attribs;
if (sCGLLibrary.UseDoubleBufferedWindows()) {
- attribs = kAttribs_doubleBuffered;
+ attribs = aForceAccelerated ? kAttribs_doubleBuffered_accel : kAttribs_doubleBuffered;
} else {
- attribs = kAttribs_singleBuffered;
+ attribs = aForceAccelerated ? kAttribs_singleBuffered_accel : kAttribs_singleBuffered;
}
NSOpenGLContext* context = CreateWithFormat(attribs);
if (!context) {
return nullptr;
}
// make the context transparent
GLint opaque = 0;
--- a/gfx/gl/GLContextProviderEAGL.mm
+++ b/gfx/gl/GLContextProviderEAGL.mm
@@ -206,17 +206,17 @@ CreateEAGLContext(bool aOffscreen, GLCon
glContext = nullptr;
return nullptr;
}
return glContext.forget();
}
already_AddRefed<GLContext>
-GLContextProviderEAGL::CreateForWindow(nsIWidget* aWidget)
+GLContextProviderEAGL::CreateForWindow(nsIWidget* aWidget, bool aForceAccelerated)
{
RefPtr<GLContext> glContext = CreateEAGLContext(false, GetGlobalContextEAGL());
if (!glContext) {
return nullptr;
}
if (!GLContextEAGL::Cast(glContext)->AttachToWindow(aWidget)) {
return nullptr;
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -758,17 +758,17 @@ GLContextProviderEGL::CreateWrappingExis
return glContext.forget();
}
return nullptr;
}
already_AddRefed<GLContext>
-GLContextProviderEGL::CreateForWindow(nsIWidget *aWidget)
+GLContextProviderEGL::CreateForWindow(nsIWidget *aWidget, bool aForceAccelerated)
{
if (!sEGLLibrary.EnsureInitialized()) {
MOZ_CRASH("GFX: Failed to load EGL library 3!\n");
return nullptr;
}
bool doubleBuffered = true;
--- a/gfx/gl/GLContextProviderGLX.cpp
+++ b/gfx/gl/GLContextProviderGLX.cpp
@@ -1047,17 +1047,17 @@ GLContextProviderGLX::CreateWrappingExis
return glContext.forget();
}
return nullptr;
}
already_AddRefed<GLContext>
-GLContextProviderGLX::CreateForWindow(nsIWidget *aWidget)
+GLContextProviderGLX::CreateForWindow(nsIWidget *aWidget, bool aForceAccelerated)
{
if (!sGLXLibrary.EnsureInitialized()) {
return nullptr;
}
// Currently, we take whatever Visual the window already has, and
// try to create an fbconfig for that visual. This isn't
// necessarily what we want in the long run; an fbconfig may not
--- a/gfx/gl/GLContextProviderImpl.h
+++ b/gfx/gl/GLContextProviderImpl.h
@@ -30,21 +30,22 @@ public:
* The GetSharedContext() method will return non-null if sharing
* was successful.
*
* Note: a context created for a widget /must not/ hold a strong
* reference to the widget; otherwise a cycle can be created through
* a GL layer manager.
*
* @param aWidget Widget whose surface to create a context for
+ * @param aForceAccelerated true if only accelerated contexts are allowed
*
* @return Context to use for the window
*/
static already_AddRefed<GLContext>
- CreateForWindow(nsIWidget* widget);
+ CreateForWindow(nsIWidget* widget, bool aForceAccelerated);
/**
* Create a context for offscreen rendering. The target of this
* context should be treated as opaque -- it might be a FBO, or a
* pbuffer, or some other construct. Users of this GLContext
* should bind framebuffer 0 directly to use this offscreen buffer.
*
* The offscreen context returned by this method will always have
--- a/gfx/gl/GLContextProviderNull.cpp
+++ b/gfx/gl/GLContextProviderNull.cpp
@@ -4,17 +4,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GLContextProvider.h"
namespace mozilla {
namespace gl {
already_AddRefed<GLContext>
-GLContextProviderNull::CreateForWindow(nsIWidget*)
+GLContextProviderNull::CreateForWindow(nsIWidget*, bool aForceAccelerated)
{
return nullptr;
}
already_AddRefed<GLContext>
GLContextProviderNull::CreateWrappingExisting(void*, void*)
{
return nullptr;
--- a/gfx/gl/GLContextProviderWGL.cpp
+++ b/gfx/gl/GLContextProviderWGL.cpp
@@ -433,17 +433,17 @@ GetGlobalContextWGL()
already_AddRefed<GLContext>
GLContextProviderWGL::CreateWrappingExisting(void*, void*)
{
return nullptr;
}
already_AddRefed<GLContext>
-GLContextProviderWGL::CreateForWindow(nsIWidget *aWidget)
+GLContextProviderWGL::CreateForWindow(nsIWidget *aWidget, bool aForceAccelerated)
{
if (!sWGLLib.EnsureInitialized()) {
return nullptr;
}
/**
* We need to make sure we call SetPixelFormat -after- calling
* EnsureInitialized, otherwise it can load/unload the dll and
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -102,32 +102,33 @@ CompositorOGL::CreateContext()
if (widgetOpenGLContext) {
GLContext* alreadyRefed = reinterpret_cast<GLContext*>(widgetOpenGLContext);
return already_AddRefed<GLContext>(alreadyRefed);
}
#ifdef XP_WIN
if (gfxEnv::LayersPreferEGL()) {
printf_stderr("Trying GL layers...\n");
- context = gl::GLContextProviderEGL::CreateForWindow(mWidget);
+ context = gl::GLContextProviderEGL::CreateForWindow(mWidget, false);
}
#endif
// Allow to create offscreen GL context for main Layer Manager
if (!context && gfxEnv::LayersPreferOffscreen()) {
SurfaceCaps caps = SurfaceCaps::ForRGB();
caps.preserve = false;
caps.bpp16 = gfxPlatform::GetPlatform()->GetOffscreenFormat() == gfxImageFormat::RGB16_565;
context = GLContextProvider::CreateOffscreen(mSurfaceSize,
caps, CreateContextFlags::REQUIRE_COMPAT_PROFILE);
}
if (!context) {
- context = gl::GLContextProvider::CreateForWindow(mWidget);
+ context = gl::GLContextProvider::CreateForWindow(mWidget,
+ gfxPlatform::GetPlatform()->RequiresAcceleratedGLContextForCompositorOGL());
}
if (!context) {
NS_WARNING("Failed to create CompositorOGL context");
}
#ifdef MOZ_WIDGET_GONK
mWidget->SetNativeData(NS_NATIVE_OPENGL_CONTEXT,
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -2241,19 +2241,17 @@ gfxPlatform::GetAcceleratedCompositorBac
}
void
gfxPlatform::GetCompositorBackends(bool useAcceleration, nsTArray<mozilla::layers::LayersBackend>& aBackends)
{
if (useAcceleration) {
GetAcceleratedCompositorBackends(aBackends);
}
- if (SupportsBasicCompositor()) {
- aBackends.AppendElement(LayersBackend::LAYERS_BASIC);
- }
+ aBackends.AppendElement(LayersBackend::LAYERS_BASIC);
}
void
gfxPlatform::NotifyCompositorCreated(LayersBackend aBackend)
{
if (mCompositorBackend == aBackend) {
return;
}
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -639,36 +639,37 @@ public:
// devices. Currently this is only used on Windows.
virtual void GetDeviceInitData(mozilla::gfx::DeviceInitData* aOut);
// Plugin async drawing support.
virtual bool SupportsPluginDirectBitmapDrawing() {
return false;
}
+ // Some platforms don't support CompositorOGL in an unaccelerated OpenGL
+ // context. These platforms should return true here.
+ virtual bool RequiresAcceleratedGLContextForCompositorOGL() const {
+ return false;
+ }
+
protected:
gfxPlatform();
virtual ~gfxPlatform();
/**
* Initialized hardware vsync based on each platform.
*/
virtual already_AddRefed<mozilla::gfx::VsyncSource> CreateHardwareVsyncSource();
// Returns whether or not layers should be accelerated by default on this platform.
virtual bool AccelerateLayersByDefault();
// Returns a prioritized list of available compositor backends for acceleration.
virtual void GetAcceleratedCompositorBackends(nsTArray<mozilla::layers::LayersBackend>& aBackends);
- // Returns whether or not the basic compositor is supported.
- virtual bool SupportsBasicCompositor() const {
- return true;
- }
-
/**
* Initialise the preferred and fallback canvas backends
* aBackendBitmask specifies the backends which are acceptable to the caller.
* The backend used is determined by aBackendBitmask and the order specified
* by the gfx.canvas.azure.backends pref.
*/
void InitBackendPrefs(uint32_t aCanvasBitmask, mozilla::gfx::BackendType aCanvasDefault,
uint32_t aContentBitmask, mozilla::gfx::BackendType aContentDefault);
--- a/gfx/thebes/gfxPlatformMac.h
+++ b/gfx/thebes/gfxPlatformMac.h
@@ -78,19 +78,21 @@ public:
virtual bool CanRenderContentToDataSurface() const override {
return true;
}
virtual bool SupportsApzWheelInput() const override {
return true;
}
- bool SupportsBasicCompositor() const override {
- // At the moment, BasicCompositor is broken on mac.
- return false;
+ bool RequiresAcceleratedGLContextForCompositorOGL() const override {
+ // On OS X in a VM, unaccelerated CompositorOGL shows black flashes, so we
+ // require accelerated GL for CompositorOGL but allow unaccelerated GL for
+ // BasicCompositor.
+ return true;
}
bool UseAcceleratedCanvas();
virtual bool UseProgressivePaint() override;
virtual already_AddRefed<mozilla::gfx::VsyncSource> CreateHardwareVsyncSource() override;
// lower threshold on font anti-aliasing
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -4326,19 +4326,16 @@ pref("layers.tiled-drawtarget.enabled",
pref("layers.tiled-drawtarget.enabled", true);
pref("layers.tiles.edge-padding", true);
#endif
// same effect as layers.offmainthreadcomposition.enabled, but specifically for
// use with tests.
pref("layers.offmainthreadcomposition.testing.enabled", false);
-// whether to allow use of the basic compositor
-pref("layers.offmainthreadcomposition.force-basic", false);
-
// Whether to animate simple opacity and transforms on the compositor
pref("layers.offmainthreadcomposition.async-animations", true);
// Whether to log information about off main thread animations to stderr
pref("layers.offmainthreadcomposition.log-animations", false);
pref("layers.bufferrotation.enabled", true);
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -331,17 +331,19 @@ protected:
// We need to use OpenGL for this because there seems to be no other robust
// way of drawing from a secondary thread without locking, which would cause
// deadlocks in our setup. See bug 882523.
class GLPresenter : public GLManager
{
public:
static GLPresenter* CreateForWindow(nsIWidget* aWindow)
{
- RefPtr<GLContext> context = gl::GLContextProvider::CreateForWindow(aWindow);
+ // Contrary to CompositorOGL, we allow unaccelerated OpenGL contexts to be
+ // used. BasicCompositor only requires very basic GL functionality.
+ RefPtr<GLContext> context = gl::GLContextProvider::CreateForWindow(aWindow, false);
return context ? new GLPresenter(context) : nullptr;
}
explicit GLPresenter(GLContext* aContext);
virtual ~GLPresenter();
virtual GLContext* gl() const override { return mGLContext; }
virtual ShaderProgramOGL* GetProgram(GLenum aTarget, gfx::SurfaceFormat aFormat) override