diff --git a/gfx/gl/GLContext.h b/gfx/gl/GLContext.h index bbd31183e9f..4004d3774d9 100644 --- a/gfx/gl/GLContext.h +++ b/gfx/gl/GLContext.h @@ -66,7 +66,6 @@ namespace mozilla { namespace layers { class ColorTextureLayerProgram; - class LayerManagerOGL; } } diff --git a/gfx/layers/moz.build b/gfx/layers/moz.build index 1488956c978..7616c1883b0 100644 --- a/gfx/layers/moz.build +++ b/gfx/layers/moz.build @@ -32,8 +32,6 @@ EXPORTS += [ 'LayerSorter.h', 'LayerTreeInvalidation.h', 'opengl/Composer2D.h', - 'opengl/ImageLayerOGL.h', - 'opengl/LayerManagerOGL.h', 'opengl/LayerManagerOGLProgram.h', 'opengl/LayerManagerOGLShaders.h', 'opengl/TexturePoolOGL.h', @@ -255,18 +253,12 @@ UNIFIED_SOURCES += [ 'LayersLogging.cpp', 'LayerSorter.cpp', 'LayerTreeInvalidation.cpp', - 'opengl/CanvasLayerOGL.cpp', - 'opengl/ColorLayerOGL.cpp', 'opengl/CompositingRenderTargetOGL.cpp', 'opengl/CompositorOGL.cpp', - 'opengl/ContainerLayerOGL.cpp', - 'opengl/ImageLayerOGL.cpp', - 'opengl/LayerManagerOGL.cpp', 'opengl/LayerManagerOGLProgram.cpp', 'opengl/TextureClientOGL.cpp', 'opengl/TextureHostOGL.cpp', 'opengl/TexturePoolOGL.cpp', - 'opengl/ThebesLayerOGL.cpp', 'ReadbackProcessor.cpp', 'RenderTrace.cpp', 'ThebesLayerBuffer.cpp', diff --git a/gfx/layers/opengl/CanvasLayerOGL.cpp b/gfx/layers/opengl/CanvasLayerOGL.cpp deleted file mode 100644 index cab7f6864eb..00000000000 --- a/gfx/layers/opengl/CanvasLayerOGL.cpp +++ /dev/null @@ -1,400 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "CanvasLayerOGL.h" -#include "GLContext.h" // for GLContext -#include "GLScreenBuffer.h" // for GLScreenBuffer -#include "SharedSurface.h" // for SharedSurface -#include "SharedSurfaceGL.h" // for SharedSurface_Basic, etc -#include "SurfaceStream.h" // for SurfaceStream, etc -#include "SurfaceTypes.h" // for SharedSurfaceType, etc -#include "gfx3DMatrix.h" // for gfx3DMatrix -#include "gfxImageSurface.h" // for gfxImageSurface -#include "gfxPlatform.h" // for gfxPlatform -#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc -#include "mozilla/gfx/Types.h" // for SurfaceFormat, etc -#include "nsDebug.h" // for NS_ABORT_IF_FALSE, etc -#include "nsPoint.h" // for nsIntPoint -#include "nsRect.h" // for nsIntRect -#include "nsRegion.h" // for nsIntRegion -#include "nsSize.h" // for nsIntSize -#include "LayerManagerOGL.h" // for LayerOGL::GLContext, etc - -#ifdef XP_MACOSX -#include "mozilla/gfx/MacIOSurface.h" -#include "SharedSurfaceIO.h" -#endif - -#ifdef XP_WIN -#include "gfxWindowsSurface.h" -#include "WGLLibrary.h" -#endif - -#ifdef XP_MACOSX -#include -#endif - -#ifdef GL_PROVIDER_GLX -#include "GLXLibrary.h" // for GLXLibrary, sDefGLXLib -#include "gfxXlibSurface.h" -#endif - -using namespace mozilla; -using namespace mozilla::layers; -using namespace mozilla::gl; -using namespace mozilla::gfx; - -CanvasLayerOGL::CanvasLayerOGL(LayerManagerOGL *aManager) - : CanvasLayer(aManager, nullptr) - , LayerOGL(aManager) - , mLayerProgram(RGBALayerProgramType) - , mTexture(0) - , mTextureTarget(LOCAL_GL_TEXTURE_2D) - , mDelayedUpdates(false) - , mIsGLAlphaPremult(false) - , mUploadTexture(0) -#if defined(GL_PROVIDER_GLX) - , mPixmap(0) -#endif -{ - mImplData = static_cast(this); - mForceReadback = Preferences::GetBool("webgl.force-layers-readback", false); -} - -CanvasLayerOGL::~CanvasLayerOGL() { - Destroy(); -} - -static void -MakeTextureIfNeeded(GLContext* gl, GLuint& aTexture) -{ - if (aTexture != 0) - return; - - gl->fGenTextures(1, &aTexture); - - gl->fActiveTexture(LOCAL_GL_TEXTURE0); - gl->fBindTexture(LOCAL_GL_TEXTURE_2D, aTexture); - - gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR); - gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR); - gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE); - gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE); -} - -#ifdef XP_MACOSX -static GLuint -MakeIOSurfaceTexture(void* aCGIOSurfaceContext, mozilla::gl::GLContext* aGL) -{ - GLuint ioSurfaceTexture; - - aGL->MakeCurrent(); - - aGL->fGenTextures(1, &ioSurfaceTexture); - - aGL->fActiveTexture(LOCAL_GL_TEXTURE0); - aGL->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, ioSurfaceTexture); - - aGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR); - aGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR); - aGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE); - aGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE); - - RefPtr ioSurface = MacIOSurface::IOSurfaceContextGetSurface((CGContextRef)aCGIOSurfaceContext); - - ioSurface->CGLTexImageIOSurface2D(static_cast(aGL->GetNativeData(GLContext::NativeCGLContext))); - - aGL->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, 0); - - return ioSurfaceTexture; -} -#endif - -void -CanvasLayerOGL::Destroy() -{ - if (!mDestroyed) { - CleanupResources(); - mDestroyed = true; - } -} - -void -CanvasLayerOGL::Initialize(const Data& aData) -{ - NS_ASSERTION(mCanvasSurface == nullptr, "BasicCanvasLayer::Initialize called twice!"); - - if (aData.mGLContext != nullptr && - aData.mSurface != nullptr) - { - NS_WARNING("CanvasLayerOGL can't have both surface and WebGLContext"); - return; - } - - mOGLManager->MakeCurrent(); - - if (aData.mDrawTarget && - aData.mDrawTarget->GetNativeSurface(gfx::NATIVE_SURFACE_CGCONTEXT_ACCELERATED)) { - mDrawTarget = aData.mDrawTarget; - mNeedsYFlip = false; - mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height); - return; - } else if (aData.mDrawTarget) { - mDrawTarget = aData.mDrawTarget; - mCanvasSurface = gfxPlatform::GetPlatform()->CreateThebesSurfaceAliasForDrawTarget_hack(mDrawTarget); - mNeedsYFlip = false; - } else if (aData.mSurface) { - mCanvasSurface = aData.mSurface; - mNeedsYFlip = false; -#if defined(GL_PROVIDER_GLX) - if (aData.mSurface->GetType() == gfxSurfaceTypeXlib) { - gfxXlibSurface *xsurf = static_cast(aData.mSurface); - mPixmap = xsurf->GetGLXPixmap(); - if (mPixmap) { - mLayerProgram = ShaderProgramFromContentType(aData.mSurface->GetContentType()); - MakeTextureIfNeeded(gl(), mUploadTexture); - } - } -#endif - } else if (aData.mGLContext) { - mGLContext = aData.mGLContext; - NS_ASSERTION(mGLContext->IsOffscreen(), "Canvas GLContext must be offscreen."); - mIsGLAlphaPremult = aData.mIsGLAlphaPremult; - mNeedsYFlip = true; - - // [OGL Layers, MTC] WebGL layer init. - - GLScreenBuffer* screen = mGLContext->Screen(); - SurfaceStreamType streamType = - SurfaceStream::ChooseGLStreamType(SurfaceStream::MainThread, - screen->PreserveBuffer()); - SurfaceFactory_GL* factory = nullptr; - if (!mForceReadback) { - factory = new SurfaceFactory_GLTexture(mGLContext, gl(), screen->Caps()); - } - - if (factory) { - screen->Morph(factory, streamType); - } - } else { - NS_WARNING("CanvasLayerOGL::Initialize called without surface or GL context!"); - return; - } - - mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height); - - // Check the maximum texture size supported by GL. glTexImage2D supports - // images of up to 2 + GL_MAX_TEXTURE_SIZE - GLint texSize = 0; - gl()->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &texSize); - MOZ_ASSERT(texSize != 0); - if (mBounds.width > (2 + texSize) || mBounds.height > (2 + texSize)) { - mDelayedUpdates = true; - MakeTextureIfNeeded(gl(), mUploadTexture); - // This should only ever occur with 2d canvas, WebGL can't already have a texture - // of this size can it? - NS_ABORT_IF_FALSE(mCanvasSurface || mDrawTarget, - "Invalid texture size when WebGL surface already exists at that size?"); - } -} - -/** - * Following UpdateSurface(), mTexture on context this->gl() should contain the data we want, - * unless mDelayedUpdates is true because of a too-large surface. - */ -void -CanvasLayerOGL::UpdateSurface() -{ - if (!IsDirty()) - return; - Painted(); - - if (mDestroyed || mDelayedUpdates) { - return; - } - -#if defined(GL_PROVIDER_GLX) - if (mPixmap) { - return; - } -#endif - - gfxASurface* updatedSurface = nullptr; - gfxImageSurface* temporarySurface = nullptr; - bool nothingToShow = false; - if (mGLContext) { - SharedSurface* surf = mGLContext->RequestFrame(); - if (surf) { - mLayerProgram = surf->HasAlpha() ? RGBALayerProgramType - : RGBXLayerProgramType; - switch (surf->Type()) { - case SharedSurfaceType::Basic: { - SharedSurface_Basic* readbackSurf = SharedSurface_Basic::Cast(surf); - updatedSurface = readbackSurf->GetData(); - break; - } - case SharedSurfaceType::GLTextureShare: { - SharedSurface_GLTexture* textureSurf = SharedSurface_GLTexture::Cast(surf); - mTexture = textureSurf->Texture(); - break; - } -#ifdef XP_MACOSX - case SharedSurfaceType::IOSurface: { - SharedSurface_IOSurface *ioSurf = SharedSurface_IOSurface::Cast(surf); - mTexture = ioSurf->Texture(); - mTextureTarget = ioSurf->TextureTarget(); - mLayerProgram = ioSurf->HasAlpha() ? RGBARectLayerProgramType : RGBXRectLayerProgramType; - break; - } -#endif - default: - MOZ_CRASH("Unacceptable SharedSurface type."); - } - } else { - nothingToShow = true; - } - } else if (mCanvasSurface) { -#ifdef XP_MACOSX - if (mDrawTarget && mDrawTarget->GetNativeSurface(gfx::NATIVE_SURFACE_CGCONTEXT_ACCELERATED)) { - if (!mTexture) { - mTexture = MakeIOSurfaceTexture((CGContextRef)mDrawTarget->GetNativeSurface( - gfx::NATIVE_SURFACE_CGCONTEXT_ACCELERATED), - gl()); - mTextureTarget = LOCAL_GL_TEXTURE_RECTANGLE_ARB; - mLayerProgram = RGBARectLayerProgramType; - } - mDrawTarget->Flush(); - return; - } -#endif - updatedSurface = mCanvasSurface; - } else { - MOZ_CRASH("Unhandled canvas layer type."); - } - - if (updatedSurface) { - mOGLManager->MakeCurrent(); - gfx::SurfaceFormat format = - gl()->UploadSurfaceToTexture(updatedSurface, - mBounds, - mUploadTexture, - true,//false, - nsIntPoint(0, 0)); - mLayerProgram = ShaderProgramFromSurfaceFormat(format); - mTexture = mUploadTexture; - - if (temporarySurface) - delete temporarySurface; - } - - MOZ_ASSERT(mTexture || nothingToShow); -} - -void -CanvasLayerOGL::RenderLayer(int aPreviousDestination, - const nsIntPoint& aOffset) -{ - FirePreTransactionCallback(); - UpdateSurface(); - if (mOGLManager->CompositingDisabled()) { - return; - } - FireDidTransactionCallback(); - - mOGLManager->MakeCurrent(); - - // XXX We're going to need a different program depending on if - // mGLBufferIsPremultiplied is TRUE or not. The RGBLayerProgram - // assumes that it's true. - - gl()->fActiveTexture(LOCAL_GL_TEXTURE0); - - if (mTexture) { - gl()->fBindTexture(mTextureTarget, mTexture); - } - - ShaderProgramOGL *program = nullptr; - - nsIntRect drawRect = mBounds; - if (mDelayedUpdates) { - NS_ABORT_IF_FALSE(mCanvasSurface || mDrawTarget, "WebGL canvases should always be using full texture upload"); - - drawRect.IntersectRect(drawRect, GetEffectiveVisibleRegion().GetBounds()); - - gfx::SurfaceFormat format = - gl()->UploadSurfaceToTexture(mCanvasSurface, - nsIntRect(0, 0, drawRect.width, drawRect.height), - mUploadTexture, - true, - drawRect.TopLeft()); - mLayerProgram = ShaderProgramFromSurfaceFormat(format); - mTexture = mUploadTexture; - } - - if (!program) { - program = mOGLManager->GetProgram(mLayerProgram, GetMaskLayer()); - } - -#if defined(GL_PROVIDER_GLX) - if (mPixmap && !mDelayedUpdates) { - sDefGLXLib.BindTexImage(mPixmap); - } -#endif - - gl()->ApplyFilterToBoundTexture(mFilter); - - program->Activate(); - if (mLayerProgram == RGBARectLayerProgramType || - mLayerProgram == RGBXRectLayerProgramType) { - // This is used by IOSurface that use 0,0...w,h coordinate rather then 0,0..1,1. - program->SetTexCoordMultiplier(mBounds.width, mBounds.height); - } - program->SetLayerQuadRect(drawRect); - program->SetLayerTransform(GetEffectiveTransform()); - program->SetTextureTransform(gfx3DMatrix()); - program->SetLayerOpacity(GetEffectiveOpacity()); - program->SetRenderOffset(aOffset); - program->SetTextureUnit(0); - program->LoadMask(GetMaskLayer()); - - if (gl()->CanUploadNonPowerOfTwo()) { - mOGLManager->BindAndDrawQuad(program, mNeedsYFlip ? true : false); - } else { - mOGLManager->BindAndDrawQuadWithTextureRect(program, drawRect, drawRect.Size()); - } - -#if defined(GL_PROVIDER_GLX) - if (mPixmap && !mDelayedUpdates) { - sDefGLXLib.ReleaseTexImage(mPixmap); - } -#endif -} - -void -CanvasLayerOGL::CleanupResources() -{ - if (mUploadTexture) { - gl()->MakeCurrent(); - gl()->fDeleteTextures(1, &mUploadTexture); - mUploadTexture = 0; - } -} - -gfxImageSurface* -CanvasLayerOGL::GetTempSurface(const gfxIntSize& aSize, - const gfxImageFormat aFormat) -{ - if (!mCachedTempSurface || - aSize.width != mCachedSize.width || - aSize.height != mCachedSize.height || - aFormat != mCachedFormat) - { - mCachedTempSurface = new gfxImageSurface(aSize, aFormat); - mCachedSize = aSize; - mCachedFormat = aFormat; - } - - return mCachedTempSurface; -} diff --git a/gfx/layers/opengl/CanvasLayerOGL.h b/gfx/layers/opengl/CanvasLayerOGL.h deleted file mode 100644 index c9c41460f60..00000000000 --- a/gfx/layers/opengl/CanvasLayerOGL.h +++ /dev/null @@ -1,85 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef GFX_CANVASLAYEROGL_H -#define GFX_CANVASLAYEROGL_H - -#include "GLContextTypes.h" // for GLContext -#include "GLDefs.h" // for GLuint, LOCAL_GL_TEXTURE_2D -#include "LayerManagerOGL.h" // for LayerOGL::GLContext, etc -#include "Layers.h" // for CanvasLayer, etc -#include "gfxTypes.h" -#include "gfxPoint.h" // for gfxIntSize -#include "mozilla/Preferences.h" // for Preferences -#include "mozilla/RefPtr.h" // for RefPtr -#include "mozilla/gfx/2D.h" // for DrawTarget -#include "mozilla/mozalloc.h" // for operator delete, etc -#include "nsAutoPtr.h" // for nsRefPtr -#include "opengl/LayerManagerOGLProgram.h" // for ShaderProgramType, etc -#if defined(GL_PROVIDER_GLX) -#include "GLXLibrary.h" -#include "mozilla/X11Util.h" -#endif - -struct nsIntPoint; -class gfxASurface; -class gfxImageSurface; - -namespace mozilla { -namespace layers { - -class CanvasLayerOGL : - public CanvasLayer, - public LayerOGL -{ -public: - CanvasLayerOGL(LayerManagerOGL *aManager); - ~CanvasLayerOGL(); - - // CanvasLayer implementation - virtual void Initialize(const Data& aData); - - // LayerOGL implementation - virtual void Destroy(); - virtual Layer* GetLayer() { return this; } - virtual void RenderLayer(int aPreviousFrameBuffer, - const nsIntPoint& aOffset); - virtual void CleanupResources(); - -protected: - void UpdateSurface(); - - nsRefPtr mCanvasSurface; - nsRefPtr mGLContext; - ShaderProgramType mLayerProgram; - RefPtr mDrawTarget; - - GLuint mTexture; - GLenum mTextureTarget; - - bool mDelayedUpdates; - bool mIsGLAlphaPremult; - bool mNeedsYFlip; - bool mForceReadback; - GLuint mUploadTexture; -#if defined(GL_PROVIDER_GLX) - GLXPixmap mPixmap; -#endif - - nsRefPtr mCachedTempSurface; - gfxIntSize mCachedSize; - gfxImageFormat mCachedFormat; - - gfxImageSurface* GetTempSurface(const gfxIntSize& aSize, - const gfxImageFormat aFormat); - - void DiscardTempSurface() { - mCachedTempSurface = nullptr; - } -}; - -} /* layers */ -} /* mozilla */ -#endif /* GFX_IMAGELAYEROGL_H */ diff --git a/gfx/layers/opengl/ColorLayerOGL.cpp b/gfx/layers/opengl/ColorLayerOGL.cpp deleted file mode 100644 index 84ff69bcb49..00000000000 --- a/gfx/layers/opengl/ColorLayerOGL.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "ColorLayerOGL.h" -#include "gfxColor.h" // for gfxRGBA -#include "LayerManagerOGL.h" // for LayerManagerOGL -#include "LayerManagerOGLProgram.h" // for ShaderProgramOGL, etc - -struct nsIntPoint; - -namespace mozilla { -namespace layers { - -static void -RenderColorLayer(ColorLayer* aLayer, LayerManagerOGL *aManager, - const nsIntPoint& aOffset) -{ - if (aManager->CompositingDisabled()) { - return; - } - - aManager->MakeCurrent(); - - // XXX we might be able to improve performance by using glClear - - /* Multiply color by the layer opacity, as the shader - * ignores layer opacity and expects a final color to - * write to the color buffer. This saves a needless - * multiply in the fragment shader. - */ - gfxRGBA color(aLayer->GetColor()); - float opacity = aLayer->GetEffectiveOpacity() * color.a; - color.r *= opacity; - color.g *= opacity; - color.b *= opacity; - color.a = opacity; - - ShaderProgramOGL *program = aManager->GetProgram(ColorLayerProgramType, - aLayer->GetMaskLayer()); - program->Activate(); - program->SetLayerQuadRect(aLayer->GetBounds()); - program->SetLayerTransform(aLayer->GetEffectiveTransform()); - program->SetRenderOffset(aOffset); - program->SetRenderColor(color); - program->LoadMask(aLayer->GetMaskLayer()); - - aManager->BindAndDrawQuad(program); -} - -void -ColorLayerOGL::RenderLayer(int, - const nsIntPoint& aOffset) -{ - RenderColorLayer(this, mOGLManager, aOffset); -} - -} /* layers */ -} /* mozilla */ diff --git a/gfx/layers/opengl/ColorLayerOGL.h b/gfx/layers/opengl/ColorLayerOGL.h deleted file mode 100644 index d1ddd4839f2..00000000000 --- a/gfx/layers/opengl/ColorLayerOGL.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef GFX_COLORLAYEROGL_H -#define GFX_COLORLAYEROGL_H - -#include "LayerManagerOGL.h" // for LayerOGL, LayerManagerOGL -#include "Layers.h" // for ColorLayer, etc - -struct nsIntPoint; - -namespace mozilla { -namespace layers { - -class ColorLayerOGL : public ColorLayer, - public LayerOGL -{ -public: - ColorLayerOGL(LayerManagerOGL *aManager) - : ColorLayer(aManager, nullptr) - , LayerOGL(aManager) - { - mImplData = static_cast(this); - } - ~ColorLayerOGL() { Destroy(); } - - // LayerOGL Implementation - virtual Layer* GetLayer() { return this; } - - virtual void Destroy() { mDestroyed = true; } - - virtual void RenderLayer(int aPreviousFrameBuffer, - const nsIntPoint& aOffset); - virtual void CleanupResources() {}; -}; - -} /* layers */ -} /* mozilla */ -#endif /* GFX_COLORLAYEROGL_H */ diff --git a/gfx/layers/opengl/CompositorOGL.cpp b/gfx/layers/opengl/CompositorOGL.cpp index fa396cd2336..c7af5505624 100644 --- a/gfx/layers/opengl/CompositorOGL.cpp +++ b/gfx/layers/opengl/CompositorOGL.cpp @@ -10,7 +10,6 @@ #include "FPSCounter.h" // for FPSState, FPSCounter #include "GLContextProvider.h" // for GLContextProvider #include "GLContext.h" // for GLContext -#include "LayerManagerOGL.h" // for BUFFER_OFFSET #include "Layers.h" // for WriteSnapshotToDumpFile #include "gfx2DGlue.h" // for ThebesFilter #include "gfx3DMatrix.h" // for gfx3DMatrix @@ -49,6 +48,8 @@ #include "GfxInfo.h" #endif +#define BUFFER_OFFSET(i) ((char *)nullptr + (i)) + namespace mozilla { using namespace gfx; diff --git a/gfx/layers/opengl/ContainerLayerOGL.cpp b/gfx/layers/opengl/ContainerLayerOGL.cpp deleted file mode 100644 index c1bb16dadb2..00000000000 --- a/gfx/layers/opengl/ContainerLayerOGL.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "ContainerLayerOGL.h" -#include // for uint32_t -#include // for min -#include "GLContext.h" -#include "gfx3DMatrix.h" // for gfx3DMatrix -#include "gfxMatrix.h" // for gfxMatrix -#include "gfxPlatform.h" // for gfxPlatform -#include "gfxUtils.h" // for gfxUtils, etc -#include "mozilla/gfx/BaseRect.h" // for BaseRect -#include "mozilla/layers/CompositorTypes.h" // for MaskType, etc -#include "nsAutoPtr.h" // for nsRefPtr -#include "nsDebug.h" // for NS_ASSERTION -#include "nsISupportsUtils.h" // for NS_ADDREF, NS_RELEASE -#include "nsPoint.h" // for nsIntPoint -#include "nsRect.h" // for nsIntRect -#include "nsRegion.h" // for nsIntRegion -#include "nsTArray.h" // for nsAutoTArray -#include "LayerManagerOGL.h" // for LayerManagerOGL, LayerOGL, etc -#include "LayerManagerOGLProgram.h" // for ShaderProgramOGL -class gfxImageSurface; - -namespace mozilla { -namespace layers { - -static inline LayerOGL* -GetNextSibling(LayerOGL* aLayer) -{ - Layer* layer = aLayer->GetLayer()->GetNextSibling(); - return layer ? static_cast(layer-> - ImplData()) - : nullptr; -} - -ContainerLayerOGL::ContainerLayerOGL(LayerManagerOGL *mOGLManager) - : ContainerLayer(mOGLManager, nullptr) - , LayerOGL(mOGLManager) -{ - mImplData = static_cast(this); -} - -ContainerLayerOGL::~ContainerLayerOGL() -{ - Destroy(); -} - -void -ContainerLayerOGL::Destroy() -{ - if (!mDestroyed) { - while (mFirstChild) { - GetFirstChildOGL()->Destroy(); - RemoveChild(mFirstChild); - } - mDestroyed = true; - } -} - -LayerOGL* -ContainerLayerOGL::GetFirstChildOGL() -{ - if (!mFirstChild) { - return nullptr; - } - return static_cast(mFirstChild->ImplData()); -} - -void -ContainerLayerOGL::RenderLayer(int aPreviousFrameBuffer, - const nsIntPoint& aOffset) -{ - /** - * Setup our temporary texture for rendering the contents of this container. - */ - GLuint containerSurface; - GLuint frameBuffer; - - nsIntPoint childOffset(aOffset); - nsIntRect visibleRect = GetEffectiveVisibleRegion().GetBounds(); - - nsIntRect cachedScissor = gl()->ScissorRect(); - gl()->PushScissorRect(); - mSupportsComponentAlphaChildren = false; - - float opacity = GetEffectiveOpacity(); - const gfx3DMatrix& transform = GetEffectiveTransform(); - bool needsFramebuffer = UseIntermediateSurface(); - if (needsFramebuffer) { - nsIntRect framebufferRect = visibleRect; - // we're about to create a framebuffer backed by textures to use as an intermediate - // surface. What to do if its size (as given by framebufferRect) would exceed the - // maximum texture size supported by the GL? The present code chooses the compromise - // of just clamping the framebuffer's size to the max supported size. - // This gives us a lower resolution rendering of the intermediate surface (children layers). - // See bug 827170 for a discussion. - GLint maxTexSize; - gl()->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &maxTexSize); - framebufferRect.width = std::min(framebufferRect.width, maxTexSize); - framebufferRect.height = std::min(framebufferRect.height, maxTexSize); - - LayerManagerOGL::InitMode mode = LayerManagerOGL::InitModeClear; - if (GetEffectiveVisibleRegion().GetNumRects() == 1 && - (GetContentFlags() & Layer::CONTENT_OPAQUE)) - { - // don't need a background, we're going to paint all opaque stuff - mSupportsComponentAlphaChildren = true; - mode = LayerManagerOGL::InitModeNone; - } else { - const gfx3DMatrix& transform3D = GetEffectiveTransform(); - gfxMatrix transform; - // If we have an opaque ancestor layer, then we can be sure that - // all the pixels we draw into are either opaque already or will be - // covered by something opaque. Otherwise copying up the background is - // not safe. - if (HasOpaqueAncestorLayer(this) && - transform3D.Is2D(&transform) && !transform.HasNonIntegerTranslation()) { - mode = gfxPlatform::ComponentAlphaEnabled() ? - LayerManagerOGL::InitModeCopy : - LayerManagerOGL::InitModeClear; - framebufferRect.x += transform.x0; - framebufferRect.y += transform.y0; - mSupportsComponentAlphaChildren = gfxPlatform::ComponentAlphaEnabled(); - } - } - - gl()->PushViewportRect(); - framebufferRect -= childOffset; - if (!mOGLManager->CompositingDisabled()) { - if (!mOGLManager->CreateFBOWithTexture(framebufferRect, - mode, - aPreviousFrameBuffer, - &frameBuffer, - &containerSurface)) { - gl()->PopViewportRect(); - gl()->PopScissorRect(); - gl()->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aPreviousFrameBuffer); - return; - } - } - childOffset.x = visibleRect.x; - childOffset.y = visibleRect.y; - } else { - frameBuffer = aPreviousFrameBuffer; - mSupportsComponentAlphaChildren = (GetContentFlags() & Layer::CONTENT_OPAQUE) || - (GetParent() && GetParent()->SupportsComponentAlphaChildren()); - } - - nsAutoTArray children; - SortChildrenBy3DZOrder(children); - - /** - * Render this container's contents. - */ - for (uint32_t i = 0; i < children.Length(); i++) { - LayerOGL* layerToRender = static_cast(children.ElementAt(i)->ImplData()); - - if (layerToRender->GetLayer()->GetEffectiveVisibleRegion().IsEmpty()) { - continue; - } - - nsIntRect scissorRect = layerToRender->GetLayer()-> - CalculateScissorRect(cachedScissor, &mOGLManager->GetWorldTransform()); - if (scissorRect.IsEmpty()) { - continue; - } - - gl()->fScissor(scissorRect.x, - scissorRect.y, - scissorRect.width, - scissorRect.height); - - layerToRender->RenderLayer(frameBuffer, childOffset); - gl()->MakeCurrent(); - } - - - if (needsFramebuffer) { - // Unbind the current framebuffer and rebind the previous one. -#ifdef MOZ_DUMP_PAINTING - if (gfxUtils::sDumpPainting) { - nsRefPtr surf = - gl()->GetTexImage(containerSurface, true, mOGLManager->GetFBOTextureFormat()); - - WriteSnapshotToDumpFile(this, surf); - } -#endif - - // Restore the viewport - gl()->PopViewportRect(); - nsIntRect viewport = gl()->ViewportRect(); - mOGLManager->SetupPipeline(viewport.width, viewport.height, - LayerManagerOGL::ApplyWorldTransform); - gl()->PopScissorRect(); - - if (!mOGLManager->CompositingDisabled()) { - gl()->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aPreviousFrameBuffer); - gl()->fDeleteFramebuffers(1, &frameBuffer); - - gl()->fActiveTexture(LOCAL_GL_TEXTURE0); - - gl()->fBindTexture(mOGLManager->FBOTextureTarget(), containerSurface); - - MaskType maskType = MaskNone; - if (GetMaskLayer()) { - if (!GetTransform().CanDraw2D()) { - maskType = Mask3d; - } else { - maskType = Mask2d; - } - } - ShaderProgramOGL *rgb = - mOGLManager->GetFBOLayerProgram(maskType); - - rgb->Activate(); - rgb->SetLayerQuadRect(visibleRect); - rgb->SetLayerTransform(transform); - rgb->SetTextureTransform(gfx3DMatrix()); - rgb->SetLayerOpacity(opacity); - rgb->SetRenderOffset(aOffset); - rgb->SetTextureUnit(0); - rgb->LoadMask(GetMaskLayer()); - - if (rgb->GetTexCoordMultiplierUniformLocation() != -1) { - // 2DRect case, get the multiplier right for a sampler2DRect - rgb->SetTexCoordMultiplier(visibleRect.width, visibleRect.height); - } - - // Drawing is always flipped, but when copying between surfaces we want to avoid - // this. Pass true for the flip parameter to introduce a second flip - // that cancels the other one out. - mOGLManager->BindAndDrawQuad(rgb, true); - - // Clean up resources. This also unbinds the texture. - gl()->fDeleteTextures(1, &containerSurface); - } - } else { - gl()->PopScissorRect(); - } -} - -void -ContainerLayerOGL::CleanupResources() -{ - for (Layer* l = GetFirstChild(); l; l = l->GetNextSibling()) { - LayerOGL* layerToRender = static_cast(l->ImplData()); - layerToRender->CleanupResources(); - } -} - -} /* layers */ -} /* mozilla */ diff --git a/gfx/layers/opengl/ContainerLayerOGL.h b/gfx/layers/opengl/ContainerLayerOGL.h deleted file mode 100644 index 1e80d23d58d..00000000000 --- a/gfx/layers/opengl/ContainerLayerOGL.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef GFX_CONTAINERLAYEROGL_H -#define GFX_CONTAINERLAYEROGL_H - -#include "LayerManagerOGL.h" // for LayerOGL -#include "Layers.h" // for Layer (ptr only), etc -class gfx3DMatrix; -struct nsIntPoint; - -namespace mozilla { -namespace layers { - -class ContainerLayerOGL : public ContainerLayer, - public LayerOGL -{ -public: - ContainerLayerOGL(LayerManagerOGL *aManager); - ~ContainerLayerOGL(); - - /** LayerOGL implementation */ - Layer* GetLayer() { return this; } - - void Destroy(); - - LayerOGL* GetFirstChildOGL(); - - virtual void RenderLayer(int aPreviousFrameBuffer, - const nsIntPoint& aOffset); - - virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface) - { - DefaultComputeEffectiveTransforms(aTransformToSurface); - } - - virtual void CleanupResources(); -}; - -} /* layers */ -} /* mozilla */ - -#endif /* GFX_CONTAINERLAYEROGL_H */ diff --git a/gfx/layers/opengl/GLManager.cpp b/gfx/layers/opengl/GLManager.cpp index 056e17b8b44..f6a610c6eb4 100644 --- a/gfx/layers/opengl/GLManager.cpp +++ b/gfx/layers/opengl/GLManager.cpp @@ -6,7 +6,6 @@ #include "GLManager.h" #include "CompositorOGL.h" // for CompositorOGL #include "GLContext.h" // for GLContext -#include "LayerManagerOGL.h" // for LayerManagerOGL #include "Layers.h" // for LayerManager #include "mozilla/Assertions.h" // for MOZ_CRASH #include "mozilla/Attributes.h" // for MOZ_OVERRIDE @@ -23,32 +22,6 @@ using namespace mozilla::gl; namespace mozilla { namespace layers { -class GLManagerLayerManager : public GLManager -{ -public: - GLManagerLayerManager(LayerManagerOGL* aManager) - : mImpl(aManager) - {} - - virtual GLContext* gl() const MOZ_OVERRIDE - { - return mImpl->gl(); - } - - virtual ShaderProgramOGL* GetProgram(ShaderProgramType aType) MOZ_OVERRIDE - { - return mImpl->GetProgram(aType); - } - - virtual void BindAndDrawQuad(ShaderProgramOGL *aProg) MOZ_OVERRIDE - { - mImpl->BindAndDrawQuad(aProg); - } - -private: - nsRefPtr mImpl; -}; - class GLManagerCompositor : public GLManager { public: @@ -80,8 +53,6 @@ GLManager::CreateGLManager(LayerManager* aManager) { if (!aManager) { return nullptr; - } else if (aManager->GetBackendType() == LAYERS_OPENGL) { - return new GLManagerLayerManager(static_cast(aManager)); } if (aManager->GetBackendType() == LAYERS_NONE) { if (Compositor::GetBackend() == LAYERS_OPENGL) { diff --git a/gfx/layers/opengl/GLManager.h b/gfx/layers/opengl/GLManager.h index 5f3a65123c7..307abfdf6b7 100644 --- a/gfx/layers/opengl/GLManager.h +++ b/gfx/layers/opengl/GLManager.h @@ -20,8 +20,8 @@ class LayerManager; /** * Minimal interface to allow widgets to draw using OpenGL. Abstracts - * LayerManagerOGL and CompositorOGL. Call CreateGLManager with either a - * LayerManagerOGL or a LayerManagerComposite backed by a CompositorOGL. + * CompositorOGL. Call CreateGLManager with a LayerManagerComposite + * backed by a CompositorOGL. */ class GLManager { diff --git a/gfx/layers/opengl/ImageLayerOGL.cpp b/gfx/layers/opengl/ImageLayerOGL.cpp deleted file mode 100644 index 9aa09abfc6d..00000000000 --- a/gfx/layers/opengl/ImageLayerOGL.cpp +++ /dev/null @@ -1,609 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "ImageLayerOGL.h" -#include // for uint32_t -#include "mozilla-config.h" // for GL_PROVIDER_GLX -#include "GLContext.h" // for GLContext, etc -#include "ImageContainer.h" // for CairoImage, etc -#include "ImageTypes.h" // for ImageFormat::CAIRO_SURFACE, etc -#include "SharedTextureImage.h" // for SharedTextureImage::Data, etc -#include "gfx3DMatrix.h" // for gfx3DMatrix -#include "gfxASurface.h" // for gfxASurface, etc -#include "gfxImageSurface.h" // for gfxImageSurface -#include "gfxUtils.h" // for NextPowerOfTwo -#include "mozilla/gfx/BaseSize.h" // for BaseSize -#include "mozilla/gfx/Types.h" // for SurfaceFormat -#include "mozilla/layers/LayersTypes.h" -#include "nsAutoRef.h" // for nsCountedRef, nsAutoRefBase -#include "nsCOMPtr.h" // for nsCOMPtr, already_AddRefed -#include "nsDebug.h" // for NS_ASSERTION, NS_ERROR -#include "nsIRunnable.h" // for nsIRunnable -#include "nsPoint.h" // for nsIntPoint -#include "nsRect.h" // for nsIntRect -#include "nsSize.h" // for nsIntSize -#include "nsThreadUtils.h" // for nsRunnable -#include "nscore.h" // for NS_IMETHOD -#include "LayerManagerOGL.h" // for LayerOGL::GLContext, etc -#if defined(GL_PROVIDER_GLX) -# include "GLXLibrary.h" -# include "gfxXlibSurface.h" -#endif - -using namespace mozilla::gfx; -using namespace mozilla::gl; - -namespace mozilla { -namespace layers { - -class Layer; - -/** - * This is an event used to unref a GLContext on the main thread and - * optionally delete a texture associated with that context. - */ -class TextureDeleter : public nsRunnable { -public: - TextureDeleter(already_AddRefed aContext, - GLuint aTexture) - : mContext(aContext), mTexture(aTexture) - { - NS_ASSERTION(aTexture, "TextureDeleter instantiated with nothing to do"); - } - - NS_IMETHOD Run() { - mContext->MakeCurrent(); - mContext->fDeleteTextures(1, &mTexture); - - // Ensure context is released on the main thread - mContext = nullptr; - return NS_OK; - } - - nsRefPtr mContext; - GLuint mTexture; -}; - -GLTexture::GLTexture() - : mTexture(0) -{ -} - -GLTexture::~GLTexture() -{ - Release(); -} - -void -GLTexture::Allocate(GLContext *aContext) -{ - NS_ASSERTION(aContext->IsGlobalSharedContext() || aContext->IsOwningThreadCurrent(), - "Can only allocate texture on context's owning thread or with cx sharing"); - - Release(); - - mContext = aContext; - - mContext->MakeCurrent(); - mContext->fGenTextures(1, &mTexture); -} - -void -GLTexture::TakeFrom(GLTexture *aOther) -{ - Release(); - - mContext = aOther->mContext.forget(); - mTexture = aOther->mTexture; - aOther->mTexture = 0; -} - -void -GLTexture::Release() -{ - if (!mContext) { - NS_ASSERTION(!mTexture, "Can't delete texture without a context"); - return; - } - - if (mContext->IsDestroyed() && !mContext->IsGlobalSharedContext()) { - mContext = mContext->GetSharedContext(); - if (!mContext) { - NS_ASSERTION(!mTexture, - "Context has been destroyed and couldn't find a shared context!"); - return; - } - } - - if (mTexture) { - if (mContext->IsOwningThreadCurrent() || mContext->IsGlobalSharedContext()) { - mContext->MakeCurrent(); - mContext->fDeleteTextures(1, &mTexture); - } else { - already_AddRefed context = mContext.forget(); - nsCOMPtr runnable = new TextureDeleter(context, mTexture); - context.get()->DispatchToOwningThread(runnable); - } - - mTexture = 0; - } - - mContext = nullptr; -} - -TextureRecycleBin::TextureRecycleBin() - : mLock("mozilla.layers.TextureRecycleBin.mLock") -{ -} - -void -TextureRecycleBin::RecycleTexture(GLTexture *aTexture, TextureType aType, - const gfxIntSize& aSize) -{ - MutexAutoLock lock(mLock); - - if (!aTexture->IsAllocated()) - return; - - if (!mRecycledTextures[aType].IsEmpty() && aSize != mRecycledTextureSizes[aType]) { - mRecycledTextures[aType].Clear(); - } - mRecycledTextureSizes[aType] = aSize; - mRecycledTextures[aType].AppendElement()->TakeFrom(aTexture); -} - -void -TextureRecycleBin::GetTexture(TextureType aType, const gfxIntSize& aSize, - GLContext *aContext, GLTexture *aOutTexture) -{ - MutexAutoLock lock(mLock); - - if (mRecycledTextures[aType].IsEmpty() || mRecycledTextureSizes[aType] != aSize) { - aOutTexture->Allocate(aContext); - return; - } - uint32_t last = mRecycledTextures[aType].Length() - 1; - aOutTexture->TakeFrom(&mRecycledTextures[aType].ElementAt(last)); - mRecycledTextures[aType].RemoveElementAt(last); -} - -struct ImageOGLBackendData : public ImageBackendData -{ - GLTexture mTexture; -}; - -void -AllocateTextureSharedTexture(SharedTextureImage *aTexImage, mozilla::gl::GLContext* aGL, GLenum aTarget) -{ - nsAutoPtr backendData( - new ImageOGLBackendData); - - backendData->mTexture.Allocate(aGL); - - aGL->fBindTexture(aTarget, backendData->mTexture.GetTextureID()); - aGL->fTexParameteri(aTarget, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR); - aGL->fTexParameteri(aTarget, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR); - aGL->fTexParameteri(aTarget, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE); - aGL->fTexParameteri(aTarget, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE); - - aTexImage->SetBackendData(LAYERS_OPENGL, backendData.forget()); -} - -Layer* -ImageLayerOGL::GetLayer() -{ - return this; -} - -void -ImageLayerOGL::RenderLayer(int, - const nsIntPoint& aOffset) -{ - nsRefPtr container = GetContainer(); - - if (!container || mOGLManager->CompositingDisabled()) - return; - - mOGLManager->MakeCurrent(); - - AutoLockImage autoLock(container); - - Image *image = autoLock.GetImage(); - if (!image) { - return; - } - - NS_ASSERTION(image->GetFormat() != REMOTE_IMAGE_BITMAP, - "Remote images aren't handled yet in OGL layers!"); - - if (image->GetFormat() == PLANAR_YCBCR) { - PlanarYCbCrImage *yuvImage = - static_cast(image); - - if (!yuvImage->IsValid()) { - return; - } - - PlanarYCbCrOGLBackendData *data = - static_cast(yuvImage->GetBackendData(LAYERS_OPENGL)); - - if (data && data->mTextures->GetGLContext() != gl()) { - // If these textures were allocated by another layer manager, - // clear them out and re-allocate below. - data = nullptr; - yuvImage->SetBackendData(LAYERS_OPENGL, nullptr); - } - - if (!data) { - AllocateTexturesYCbCr(yuvImage); - data = static_cast(yuvImage->GetBackendData(LAYERS_OPENGL)); - } - - if (!data || data->mTextures->GetGLContext() != gl()) { - // XXX - Can this ever happen? If so I need to fix this! - return; - } - - gl()->MakeCurrent(); - gl()->fActiveTexture(LOCAL_GL_TEXTURE2); - gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, data->mTextures[2].GetTextureID()); - gl()->ApplyFilterToBoundTexture(mFilter); - gl()->fActiveTexture(LOCAL_GL_TEXTURE1); - gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, data->mTextures[1].GetTextureID()); - gl()->ApplyFilterToBoundTexture(mFilter); - gl()->fActiveTexture(LOCAL_GL_TEXTURE0); - gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, data->mTextures[0].GetTextureID()); - gl()->ApplyFilterToBoundTexture(mFilter); - - ShaderProgramOGL *program = mOGLManager->GetProgram(YCbCrLayerProgramType, - GetMaskLayer()); - - program->Activate(); - program->SetLayerQuadRect(nsIntRect(0, 0, - yuvImage->GetSize().width, - yuvImage->GetSize().height)); - program->SetLayerTransform(GetEffectiveTransform()); - program->SetTextureTransform(gfx3DMatrix()); - program->SetLayerOpacity(GetEffectiveOpacity()); - program->SetRenderOffset(aOffset); - program->SetYCbCrTextureUnits(0, 1, 2); - program->LoadMask(GetMaskLayer()); - - mOGLManager->BindAndDrawQuadWithTextureRect(program, - yuvImage->GetData()->GetPictureRect(), - nsIntSize(yuvImage->GetData()->mYSize.width, - yuvImage->GetData()->mYSize.height)); - - // We shouldn't need to do this, but do it anyway just in case - // someone else forgets. - gl()->fActiveTexture(LOCAL_GL_TEXTURE0); - } else if (image->GetFormat() == CAIRO_SURFACE) { - CairoImage *cairoImage = - static_cast(image); - - if (!cairoImage->mSurface) { - return; - } - - NS_ASSERTION(cairoImage->mSurface->GetContentType() != GFX_CONTENT_ALPHA, - "Image layer has alpha image"); - - CairoOGLBackendData *data = - static_cast(cairoImage->GetBackendData(LAYERS_OPENGL)); - - if (data && data->mTexture.GetGLContext() != gl()) { - // If this texture was allocated by another layer manager, clear - // it out and re-allocate below. - data = nullptr; - cairoImage->SetBackendData(LAYERS_OPENGL, nullptr); - } - - if (!data) { - AllocateTexturesCairo(cairoImage); - data = static_cast(cairoImage->GetBackendData(LAYERS_OPENGL)); - } - - if (!data || data->mTexture.GetGLContext() != gl()) { - // XXX - Can this ever happen? If so I need to fix this! - return; - } - - gl()->MakeCurrent(); - - gl()->fActiveTexture(LOCAL_GL_TEXTURE0); - gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, data->mTexture.GetTextureID()); - - ShaderProgramOGL *program = mOGLManager->GetProgram(data->mLayerProgram, GetMaskLayer()); - - gl()->ApplyFilterToBoundTexture(mFilter); - - program->Activate(); - program->SetLayerQuadRect(nsIntRect(0, 0, - cairoImage->GetSize().width, - cairoImage->GetSize().height)); - program->SetLayerTransform(GetEffectiveTransform()); - program->SetTextureTransform(gfx3DMatrix()); - program->SetLayerOpacity(GetEffectiveOpacity()); - program->SetRenderOffset(aOffset); - program->SetTextureUnit(0); - program->LoadMask(GetMaskLayer()); - - mOGLManager->BindAndDrawQuad(program); - } else if (image->GetFormat() == SHARED_TEXTURE) { - SharedTextureImage* texImage = - static_cast(image); - const SharedTextureImage::Data* data = texImage->GetData(); - GLContext::SharedHandleDetails handleDetails; - if (!gl()->GetSharedHandleDetails(data->mShareType, data->mHandle, handleDetails)) { - NS_ERROR("Failed to get shared handle details"); - return; - } - - ShaderProgramType programType = - ShaderProgramFromTargetAndFormat(handleDetails.mTarget, - handleDetails.mTextureFormat); - ShaderProgramOGL* program = mOGLManager->GetProgram(programType, GetMaskLayer()); - - program->Activate(); - if (programType == RGBARectLayerProgramType) { - // 2DRect case, get the multiplier right for a sampler2DRect - program->SetTexCoordMultiplier(data->mSize.width, data->mSize.height); - } - program->SetLayerTransform(GetEffectiveTransform()); - program->SetTextureTransform(gfx3DMatrix()); - program->SetLayerOpacity(GetEffectiveOpacity()); - program->SetRenderOffset(aOffset); - program->SetTextureUnit(0); - program->SetTextureTransform(handleDetails.mTextureTransform); - program->LoadMask(GetMaskLayer()); - - if (!texImage->GetBackendData(LAYERS_OPENGL)) { - AllocateTextureSharedTexture(texImage, gl(), handleDetails.mTarget); - } - - ImageOGLBackendData *backendData = - static_cast(texImage->GetBackendData(LAYERS_OPENGL)); - gl()->fActiveTexture(LOCAL_GL_TEXTURE0); - gl()->fBindTexture(handleDetails.mTarget, backendData->mTexture.GetTextureID()); - - if (!gl()->AttachSharedHandle(data->mShareType, data->mHandle)) { - NS_ERROR("Failed to bind shared texture handle"); - return; - } - - gl()->ApplyFilterToBoundTexture(handleDetails.mTarget, mFilter); - program->SetLayerQuadRect(nsIntRect(nsIntPoint(0, 0), data->mSize)); - mOGLManager->BindAndDrawQuad(program, data->mInverted); - gl()->fBindTexture(handleDetails.mTarget, 0); - gl()->DetachSharedHandle(data->mShareType, data->mHandle); - } - GetContainer()->NotifyPaintedImage(image); -} - -static void -SetClamping(GLContext* aGL, GLuint aTexture) -{ - aGL->fBindTexture(LOCAL_GL_TEXTURE_2D, aTexture); - aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE); - aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE); -} - -static void -UploadYUVToTexture(GLContext* gl, const PlanarYCbCrData& aData, - GLTexture* aYTexture, - GLTexture* aUTexture, - GLTexture* aVTexture) -{ - nsIntRect size(0, 0, aData.mYSize.width, aData.mYSize.height); - GLuint texture = aYTexture->GetTextureID(); - nsRefPtr surf = new gfxImageSurface(aData.mYChannel, - aData.mYSize, - aData.mYStride, - gfxImageFormatA8); - gl->UploadSurfaceToTexture(surf, size, texture, true); - - size = nsIntRect(0, 0, aData.mCbCrSize.width, aData.mCbCrSize.height); - texture = aUTexture->GetTextureID(); - surf = new gfxImageSurface(aData.mCbChannel, - aData.mCbCrSize, - aData.mCbCrStride, - gfxImageFormatA8); - gl->UploadSurfaceToTexture(surf, size, texture, true); - - texture = aVTexture->GetTextureID(); - surf = new gfxImageSurface(aData.mCrChannel, - aData.mCbCrSize, - aData.mCbCrStride, - gfxImageFormatA8); - gl->UploadSurfaceToTexture(surf, size, texture, true); -} - -ImageLayerOGL::ImageLayerOGL(LayerManagerOGL *aManager) - : ImageLayer(aManager, nullptr) - , LayerOGL(aManager) - , mTextureRecycleBin(new TextureRecycleBin()) -{ - mImplData = static_cast(this); -} - -void -ImageLayerOGL::AllocateTexturesYCbCr(PlanarYCbCrImage *aImage) -{ - if (!aImage->IsValid()) - return; - - nsAutoPtr backendData( - new PlanarYCbCrOGLBackendData); - - const PlanarYCbCrData *data = aImage->GetData(); - - gl()->MakeCurrent(); - - mTextureRecycleBin->GetTexture(TextureRecycleBin::TEXTURE_Y, data->mYSize, gl(), &backendData->mTextures[0]); - SetClamping(gl(), backendData->mTextures[0].GetTextureID()); - - mTextureRecycleBin->GetTexture(TextureRecycleBin::TEXTURE_C, data->mCbCrSize, gl(), &backendData->mTextures[1]); - SetClamping(gl(), backendData->mTextures[1].GetTextureID()); - - mTextureRecycleBin->GetTexture(TextureRecycleBin::TEXTURE_C, data->mCbCrSize, gl(), &backendData->mTextures[2]); - SetClamping(gl(), backendData->mTextures[2].GetTextureID()); - - UploadYUVToTexture(gl(), *data, - &backendData->mTextures[0], - &backendData->mTextures[1], - &backendData->mTextures[2]); - - backendData->mYSize = data->mYSize; - backendData->mCbCrSize = data->mCbCrSize; - backendData->mTextureRecycleBin = mTextureRecycleBin; - - aImage->SetBackendData(LAYERS_OPENGL, backendData.forget()); -} - -void -ImageLayerOGL::AllocateTexturesCairo(CairoImage *aImage) -{ - nsAutoPtr backendData( - new CairoOGLBackendData); - - GLTexture &texture = backendData->mTexture; - - texture.Allocate(gl()); - - if (!texture.IsAllocated()) { - return; - } - - mozilla::gl::GLContext *gl = texture.GetGLContext(); - gl->MakeCurrent(); - - GLuint tex = texture.GetTextureID(); - gl->fActiveTexture(LOCAL_GL_TEXTURE0); - - SetClamping(gl, tex); - -#if defined(GL_PROVIDER_GLX) - if (aImage->mSurface->GetType() == gfxSurfaceTypeXlib) { - gfxXlibSurface *xsurf = - static_cast(aImage->mSurface.get()); - GLXPixmap pixmap = xsurf->GetGLXPixmap(); - if (pixmap) { - backendData->mLayerProgram = ShaderProgramFromContentType(aImage->mSurface->GetContentType()); - - aImage->SetBackendData(LAYERS_OPENGL, backendData.forget()); - - sDefGLXLib.BindTexImage(pixmap); - - return; - } - } -#endif - gfx::SurfaceFormat format = - gl->UploadSurfaceToTexture(aImage->mSurface, - nsIntRect(0,0, aImage->mSize.width, aImage->mSize.height), - tex, true); - backendData->mLayerProgram = ShaderProgramFromSurfaceFormat(format); - - aImage->SetBackendData(LAYERS_OPENGL, backendData.forget()); -} - -/* - * Returns a size that is larger than and closest to aSize where both - * width and height are powers of two. - * If the OpenGL setup is capable of using non-POT textures, then it - * will just return aSize. - */ -static gfxIntSize -CalculatePOTSize(const gfxIntSize& aSize, GLContext* gl) -{ - if (gl->CanUploadNonPowerOfTwo()) - return aSize; - - return gfxIntSize(NextPowerOfTwo(aSize.width), NextPowerOfTwo(aSize.height)); -} - -bool -ImageLayerOGL::LoadAsTexture(GLuint aTextureUnit, gfxIntSize* aSize) -{ - // this method shares a lot of code with RenderLayer, but it doesn't seem - // to be possible to factor it out into a helper method - - if (!GetContainer()) { - return false; - } - - AutoLockImage autoLock(GetContainer()); - - Image *image = autoLock.GetImage(); - if (!image) { - return false; - } - - if (image->GetFormat() != CAIRO_SURFACE) { - return false; - } - - CairoImage* cairoImage = static_cast(image); - - if (!cairoImage->mSurface) { - return false; - } - - CairoOGLBackendData *data = static_cast( - cairoImage->GetBackendData(LAYERS_OPENGL)); - - if (!data) { - NS_ASSERTION(cairoImage->mSurface->GetContentType() == GFX_CONTENT_ALPHA, - "OpenGL mask layers must be backed by alpha surfaces"); - - // allocate a new texture and save the details in the backend data - data = new CairoOGLBackendData; - data->mTextureSize = CalculatePOTSize(cairoImage->mSize, gl()); - - GLTexture &texture = data->mTexture; - texture.Allocate(mOGLManager->gl()); - - if (!texture.IsAllocated()) { - return false; - } - - mozilla::gl::GLContext *texGL = texture.GetGLContext(); - texGL->MakeCurrent(); - - GLuint texID = texture.GetTextureID(); - - gfx::SurfaceFormat format = - texGL->UploadSurfaceToTexture(cairoImage->mSurface, - nsIntRect(0,0, - data->mTextureSize.width, - data->mTextureSize.height), - texID, true, nsIntPoint(0,0), false, - aTextureUnit); - data->mLayerProgram = ShaderProgramFromSurfaceFormat(format); - - cairoImage->SetBackendData(LAYERS_OPENGL, data); - - gl()->MakeCurrent(); - gl()->fActiveTexture(aTextureUnit); - gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, texID); - gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, - LOCAL_GL_LINEAR); - gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, - LOCAL_GL_LINEAR); - gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, - LOCAL_GL_CLAMP_TO_EDGE); - gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, - LOCAL_GL_CLAMP_TO_EDGE); - } else { - gl()->fActiveTexture(aTextureUnit); - gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, data->mTexture.GetTextureID()); - } - - *aSize = data->mTextureSize; - return true; -} - -} /* layers */ -} /* mozilla */ diff --git a/gfx/layers/opengl/ImageLayerOGL.h b/gfx/layers/opengl/ImageLayerOGL.h deleted file mode 100644 index 9c9ab993124..00000000000 --- a/gfx/layers/opengl/ImageLayerOGL.h +++ /dev/null @@ -1,164 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef GFX_IMAGELAYEROGL_H -#define GFX_IMAGELAYEROGL_H - -#include "GLContextTypes.h" // for GLContext, GLuint -#include "ImageContainer.h" // for ImageBackendData, etc -#include "ImageLayers.h" // for ImageLayer -#include "LayerManagerOGL.h" // for LayerOGL -#include "gfxPoint.h" // for gfxIntSize -#include "mozilla/Assertions.h" // for MOZ_ASSERT_HELPER2 -#include "mozilla/Mutex.h" // for Mutex -#include "mozilla/mozalloc.h" // for operator delete -#include "nsAutoPtr.h" // for nsRefPtr -#include "nsISupportsImpl.h" // for TextureRecycleBin::Release, etc -#include "nsTArray.h" // for nsTArray -#include "opengl/LayerManagerOGLProgram.h" // for ShaderProgramType, etc - -struct nsIntPoint; - -namespace mozilla { -namespace layers { - -class BlobYCbCrSurface; -class Layer; - -/** - * This class wraps a GL texture. It includes a GLContext reference - * so we can use to free the texture when destroyed. The implementation - * makes sure to always free the texture on the main thread, even if the - * destructor runs on another thread. - * - * We ensure that the GLContext reference is only addrefed and released - * on the main thread, although it uses threadsafe recounting so we don't - * really have to. - * - * Initially the texture is not allocated --- it's in a "null" state. - */ -class GLTexture -{ - typedef mozilla::gl::GLContext GLContext; - -public: - GLTexture(); - ~GLTexture(); - - /** - * Allocate the texture. This can only be called on the main thread. - */ - void Allocate(GLContext *aContext); - /** - * Move the state of aOther to this GLTexture. If this GLTexture currently - * has a texture, it is released. This can be called on any thread. - */ - void TakeFrom(GLTexture *aOther); - - bool IsAllocated() { return mTexture != 0; } - GLuint GetTextureID() { return mTexture; } - GLContext *GetGLContext() { return mContext; } - - void Release(); -private: - - nsRefPtr mContext; - GLuint mTexture; -}; - -/** - * A RecycleBin is owned by an ImageLayer. We store textures in it that we - * want to recycle from one image to the next. It's a separate object from - * ImageContainer because images need to store a strong ref to their RecycleBin - * and we must avoid creating a reference loop between an ImageContainer and - * its active image. - */ -class TextureRecycleBin { - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureRecycleBin) - - typedef mozilla::gl::GLContext GLContext; - -public: - TextureRecycleBin(); - - enum TextureType { - TEXTURE_Y, - TEXTURE_C - }; - - void RecycleTexture(GLTexture *aTexture, TextureType aType, - const gfxIntSize& aSize); - void GetTexture(TextureType aType, const gfxIntSize& aSize, - GLContext *aContext, GLTexture *aOutTexture); - -private: - typedef mozilla::Mutex Mutex; - - // This protects mRecycledBuffers, mRecycledBufferSize, mRecycledTextures - // and mRecycledTextureSizes - Mutex mLock; - - nsTArray mRecycledTextures[2]; - gfxIntSize mRecycledTextureSizes[2]; -}; - -class ImageLayerOGL : public ImageLayer, - public LayerOGL -{ -public: - ImageLayerOGL(LayerManagerOGL *aManager); - ~ImageLayerOGL() { Destroy(); } - - // LayerOGL Implementation - virtual void Destroy() { mDestroyed = true; } - virtual Layer* GetLayer(); - virtual bool LoadAsTexture(GLuint aTextureUnit, gfxIntSize* aSize); - - virtual void RenderLayer(int aPreviousFrameBuffer, - const nsIntPoint& aOffset); - virtual void CleanupResources() {} - - - void AllocateTexturesYCbCr(PlanarYCbCrImage *aImage); - void AllocateTexturesCairo(CairoImage *aImage); - -protected: - nsRefPtr mTextureRecycleBin; -}; - -struct PlanarYCbCrOGLBackendData : public ImageBackendData -{ - ~PlanarYCbCrOGLBackendData() - { - if (HasTextures()) { - mTextureRecycleBin->RecycleTexture(&mTextures[0], TextureRecycleBin::TEXTURE_Y, mYSize); - mTextureRecycleBin->RecycleTexture(&mTextures[1], TextureRecycleBin::TEXTURE_C, mCbCrSize); - mTextureRecycleBin->RecycleTexture(&mTextures[2], TextureRecycleBin::TEXTURE_C, mCbCrSize); - } - } - - bool HasTextures() - { - return mTextures[0].IsAllocated() && mTextures[1].IsAllocated() && - mTextures[2].IsAllocated(); - } - - GLTexture mTextures[3]; - gfxIntSize mYSize, mCbCrSize; - nsRefPtr mTextureRecycleBin; -}; - - -struct CairoOGLBackendData : public ImageBackendData -{ - CairoOGLBackendData() : mLayerProgram(RGBALayerProgramType) {} - GLTexture mTexture; - ShaderProgramType mLayerProgram; - gfxIntSize mTextureSize; -}; - -} /* layers */ -} /* mozilla */ -#endif /* GFX_IMAGELAYEROGL_H */ diff --git a/gfx/layers/opengl/LayerManagerOGL.cpp b/gfx/layers/opengl/LayerManagerOGL.cpp deleted file mode 100644 index 94029105ec5..00000000000 --- a/gfx/layers/opengl/LayerManagerOGL.cpp +++ /dev/null @@ -1,1319 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "LayerManagerOGL.h" -#include // for size_t -#include // for uint32_t, uint8_t, etc -#include "CanvasLayerOGL.h" // for CanvasLayerOGL -#include "ColorLayerOGL.h" // for ColorLayerOGL -#include "Composer2D.h" // for Composer2D -#include "ContainerLayerOGL.h" // for ContainerLayerOGL -#include "FPSCounter.h" // for FPSState, FPSCounter -#include "GLContext.h" // for GLContext, etc -#include "GLContextProvider.h" // for GLContextProvider -#include "GeckoProfiler.h" // for PROFILER_LABEL -#include "ImageLayerOGL.h" // for ImageLayerOGL -#include "ImageLayers.h" // for ImageLayer -#include "ThebesLayerOGL.h" // for ThebesLayerOGL -#include "gfx3DMatrix.h" // for gfx3DMatrix -#include "gfxASurface.h" // for gfxASurface, etc -#include "gfxContext.h" // for gfxContext, etc -#include "gfxCrashReporterUtils.h" // for ScopedGfxFeatureReporter -#include "gfxImageSurface.h" // for gfxImageSurface -#include "gfxPlatform.h" // for gfxPlatform -#include "gfxRect.h" // for gfxRect -#include "gfxUtils.h" // for NextPowerOfTwo, gfxUtils, etc -#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc -#include "mozilla/Preferences.h" // for Preferences -#include "mozilla/TimeStamp.h" // for TimeStamp -#include "mozilla/Util.h" // for ArrayLength -#include "mozilla/gfx/2D.h" // for DrawTarget -#include "mozilla/gfx/BasePoint.h" // for BasePoint -#include "mozilla/mozalloc.h" // for operator delete, etc -#include "nsIConsoleService.h" // for nsIConsoleService, etc -#include "nsIWidget.h" // for nsIWidget -#include "nsLiteralString.h" // for NS_LITERAL_STRING -#include "nsPoint.h" // for nsIntPoint -#include "nsServiceManagerUtils.h" // for do_GetService -#include "nsString.h" // for nsAutoCString, nsString, etc -#include "LayerManagerOGLProgram.h" // for ShaderProgramOGL, etc -#ifdef XP_WIN -#include "prenv.h" // for PR_GetEnv -#endif -#ifdef MOZ_WIDGET_ANDROID -#include -#include "TexturePoolOGL.h" -#endif -#ifdef XP_MACOSX -#include "gfxPlatformMac.h" -#endif - -namespace mozilla { -namespace layers { - -using namespace mozilla::gfx; -using namespace mozilla::gl; - -int32_t -LayerManagerOGL::GetMaxTextureSize() const -{ - int32_t maxSize; - mGLContext->MakeCurrent(); - mGLContext->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &maxSize); - return maxSize; -} - -void -LayerManagerOGL::MakeCurrent(bool aForce) -{ - if (mDestroyed) { - NS_WARNING("Call on destroyed layer manager"); - return; - } - mGLContext->MakeCurrent(aForce); -} - -void* -LayerManagerOGL::GetNSOpenGLContext() const -{ - return gl()->GetNativeData(GLContext::NativeGLContext); -} - - -void -LayerManagerOGL::BindQuadVBO() { - mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mQuadVBO); -} - -void -LayerManagerOGL::QuadVBOVerticesAttrib(GLuint aAttribIndex) { - mGLContext->fVertexAttribPointer(aAttribIndex, 2, - LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, - (GLvoid*) QuadVBOVertexOffset()); -} - -void -LayerManagerOGL::QuadVBOTexCoordsAttrib(GLuint aAttribIndex) { - mGLContext->fVertexAttribPointer(aAttribIndex, 2, - LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, - (GLvoid*) QuadVBOTexCoordOffset()); -} - -void -LayerManagerOGL::QuadVBOFlippedTexCoordsAttrib(GLuint aAttribIndex) { - mGLContext->fVertexAttribPointer(aAttribIndex, 2, - LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, - (GLvoid*) QuadVBOFlippedTexCoordOffset()); -} - -// Super common - -void -LayerManagerOGL::BindAndDrawQuad(GLuint aVertAttribIndex, - GLuint aTexCoordAttribIndex, - bool aFlipped) -{ - BindQuadVBO(); - QuadVBOVerticesAttrib(aVertAttribIndex); - - if (aTexCoordAttribIndex != GLuint(-1)) { - if (aFlipped) - QuadVBOFlippedTexCoordsAttrib(aTexCoordAttribIndex); - else - QuadVBOTexCoordsAttrib(aTexCoordAttribIndex); - - mGLContext->fEnableVertexAttribArray(aTexCoordAttribIndex); - } - - mGLContext->fEnableVertexAttribArray(aVertAttribIndex); - - mGLContext->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4); - - mGLContext->fDisableVertexAttribArray(aVertAttribIndex); - - if (aTexCoordAttribIndex != GLuint(-1)) { - mGLContext->fDisableVertexAttribArray(aTexCoordAttribIndex); - } -} - -/** - * LayerManagerOGL - */ -LayerManagerOGL::LayerManagerOGL(nsIWidget *aWidget, int aSurfaceWidth, int aSurfaceHeight, - bool aIsRenderingToEGLSurface) - : mWidget(aWidget) - , mWidgetSize(-1, -1) - , mSurfaceSize(aSurfaceWidth, aSurfaceHeight) - , mBackBufferFBO(0) - , mBackBufferTexture(0) - , mBackBufferSize(-1, -1) - , mHasBGRA(0) - , mIsRenderingToEGLSurface(aIsRenderingToEGLSurface) -#ifdef DEBUG - , mMaybeInvalidTree(false) -#endif -{ -} - -LayerManagerOGL::~LayerManagerOGL() -{ - Destroy(); -} - -void -LayerManagerOGL::Destroy() -{ - if (mDestroyed) - return; - - if (mRoot) { - RootLayer()->Destroy(); - mRoot = nullptr; - } - - mWidget->CleanupWindowEffects(); - - if (!mGLContext) - return; - - nsRefPtr ctx = mGLContext->GetSharedContext(); - if (!ctx) { - ctx = mGLContext; - } - - ctx->MakeCurrent(); - - for (uint32_t i = 0; i < mPrograms.Length(); ++i) { - for (uint32_t type = MaskNone; type < NumMaskTypes; ++type) { - delete mPrograms[i].mVariations[type]; - } - } - mPrograms.Clear(); - - ctx->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0); - - if (mBackBufferFBO) { - ctx->fDeleteFramebuffers(1, &mBackBufferFBO); - mBackBufferFBO = 0; - } - - if (mBackBufferTexture) { - ctx->fDeleteTextures(1, &mBackBufferTexture); - mBackBufferTexture = 0; - } - - if (mQuadVBO) { - ctx->fDeleteBuffers(1, &mQuadVBO); - mQuadVBO = 0; - } - - mGLContext = nullptr; - - mDestroyed = true; -} - -already_AddRefed -LayerManagerOGL::CreateContext() -{ - nsRefPtr context; - -#ifdef XP_WIN - if (PR_GetEnv("MOZ_LAYERS_PREFER_EGL")) { - printf_stderr("Trying GL layers...\n"); - context = gl::GLContextProviderEGL::CreateForWindow(mWidget); - } -#endif - - if (!context) - context = gl::GLContextProvider::CreateForWindow(mWidget); - - if (!context) { - NS_WARNING("Failed to create LayerManagerOGL context"); - } - return context.forget(); -} - -void -LayerManagerOGL::AddPrograms(ShaderProgramType aType) -{ - for (uint32_t maskType = MaskNone; maskType < NumMaskTypes; ++maskType) { - if (ProgramProfileOGL::ProgramExists(aType, static_cast(maskType))) { - mPrograms[aType].mVariations[maskType] = new ShaderProgramOGL(this->gl(), - ProgramProfileOGL::GetProfileFor(aType, static_cast(maskType))); - } else { - mPrograms[aType].mVariations[maskType] = nullptr; - } - } -} - -// Impl of a a helper-runnable's "Run" method, used in Initialize() -NS_IMETHODIMP -LayerManagerOGL::ReadDrawFPSPref::Run() -{ - // NOTE: This must match the code in Initialize()'s NS_IsMainThread check. - Preferences::AddBoolVarCache(&sDrawFPS, "layers.acceleration.draw-fps"); - return NS_OK; -} - -bool -LayerManagerOGL::Initialize(bool force) -{ - ScopedGfxFeatureReporter reporter("GL Layers", force); - - // Do not allow double initialization - NS_ABORT_IF_FALSE(mGLContext == nullptr, "Don't reinitialize layer managers"); - - nsRefPtr ctx = CreateContext(); - -#ifdef MOZ_WIDGET_ANDROID - if (!ctx) { - NS_RUNTIMEABORT("We need a context on Android"); - } -#endif - - if (!ctx) { - return false; - } - - mGLContext = ctx; - mGLContext->SetFlipped(true); - - MakeCurrent(); - - mHasBGRA = - mGLContext->IsExtensionSupported(gl::GLContext::EXT_texture_format_BGRA8888) || - mGLContext->IsExtensionSupported(gl::GLContext::EXT_bgra); - - mGLContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA, - LOCAL_GL_ONE, LOCAL_GL_ONE); - mGLContext->fEnable(LOCAL_GL_BLEND); - - mPrograms.AppendElements(NumProgramTypes); - for (int type = 0; type < NumProgramTypes; ++type) { - AddPrograms(static_cast(type)); - } - - // initialise a common shader to check that we can actually compile a shader - if (!mPrograms[RGBALayerProgramType].mVariations[MaskNone]->Initialize()) { -#ifdef MOZ_WIDGET_ANDROID - NS_RUNTIMEABORT("Shader initialization failed"); -#endif - return false; - } - - - mGLContext->fGenFramebuffers(1, &mBackBufferFBO); - - if (mGLContext->WorkAroundDriverBugs()) { - - /** - * We'll test the ability here to bind NPOT textures to a framebuffer, if - * this fails we'll try ARB_texture_rectangle. - */ - - GLenum textureTargets[] = { - LOCAL_GL_TEXTURE_2D, - LOCAL_GL_NONE - }; - - if (mGLContext->IsGLES2()) { - textureTargets[1] = LOCAL_GL_TEXTURE_RECTANGLE_ARB; - } - - mFBOTextureTarget = LOCAL_GL_NONE; - - for (uint32_t i = 0; i < ArrayLength(textureTargets); i++) { - GLenum target = textureTargets[i]; - if (!target) - continue; - - mGLContext->fGenTextures(1, &mBackBufferTexture); - mGLContext->fBindTexture(target, mBackBufferTexture); - mGLContext->fTexParameteri(target, - LOCAL_GL_TEXTURE_MIN_FILTER, - LOCAL_GL_NEAREST); - mGLContext->fTexParameteri(target, - LOCAL_GL_TEXTURE_MAG_FILTER, - LOCAL_GL_NEAREST); - mGLContext->fTexImage2D(target, - 0, - LOCAL_GL_RGBA, - 5, 3, /* sufficiently NPOT */ - 0, - LOCAL_GL_RGBA, - LOCAL_GL_UNSIGNED_BYTE, - nullptr); - - // unbind this texture, in preparation for binding it to the FBO - mGLContext->fBindTexture(target, 0); - - mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mBackBufferFBO); - mGLContext->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, - LOCAL_GL_COLOR_ATTACHMENT0, - target, - mBackBufferTexture, - 0); - - if (mGLContext->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER) == - LOCAL_GL_FRAMEBUFFER_COMPLETE) - { - mFBOTextureTarget = target; - break; - } - - // We weren't succesful with this texture, so we don't need it - // any more. - mGLContext->fDeleteTextures(1, &mBackBufferTexture); - } - - if (mFBOTextureTarget == LOCAL_GL_NONE) { - /* Unable to find a texture target that works with FBOs and NPOT textures */ -#ifdef MOZ_WIDGET_ANDROID - NS_RUNTIMEABORT("No texture target"); -#endif - return false; - } - } else { - // not trying to work around driver bugs, so TEXTURE_2D should just work - mFBOTextureTarget = LOCAL_GL_TEXTURE_2D; - } - - // back to default framebuffer, to avoid confusion - mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0); - - if (mFBOTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB) { - /* If we're using TEXTURE_RECTANGLE, then we must have the ARB - * extension -- the EXT variant does not provide support for - * texture rectangle access inside GLSL (sampler2DRect, - * texture2DRect). - */ - if (!mGLContext->IsExtensionSupported(gl::GLContext::ARB_texture_rectangle)) -#ifdef MOZ_WIDGET_ANDROID - NS_RUNTIMEABORT("No texture rectangle"); -#endif - return false; - } - - // If we're double-buffered, we don't need this fbo anymore. - if (mGLContext->IsDoubleBuffered()) { - mGLContext->fDeleteFramebuffers(1, &mBackBufferFBO); - mBackBufferFBO = 0; - } - - /* Create a simple quad VBO */ - - mGLContext->fGenBuffers(1, &mQuadVBO); - mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mQuadVBO); - - GLfloat vertices[] = { - /* First quad vertices */ - 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, - /* Then quad texcoords */ - 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, - /* Then flipped quad texcoords */ - 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - }; - mGLContext->fBufferData(LOCAL_GL_ARRAY_BUFFER, sizeof(vertices), vertices, LOCAL_GL_STATIC_DRAW); - mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0); - - nsCOMPtr - console(do_GetService(NS_CONSOLESERVICE_CONTRACTID)); - - if (console) { - nsString msg; - msg += - NS_LITERAL_STRING("OpenGL LayerManager Initialized Succesfully.\nVersion: "); - msg += NS_ConvertUTF8toUTF16( - nsDependentCString((const char*)mGLContext->fGetString(LOCAL_GL_VERSION))); - msg += NS_LITERAL_STRING("\nVendor: "); - msg += NS_ConvertUTF8toUTF16( - nsDependentCString((const char*)mGLContext->fGetString(LOCAL_GL_VENDOR))); - msg += NS_LITERAL_STRING("\nRenderer: "); - msg += NS_ConvertUTF8toUTF16( - nsDependentCString((const char*)mGLContext->fGetString(LOCAL_GL_RENDERER))); - msg += NS_LITERAL_STRING("\nFBO Texture Target: "); - if (mFBOTextureTarget == LOCAL_GL_TEXTURE_2D) - msg += NS_LITERAL_STRING("TEXTURE_2D"); - else - msg += NS_LITERAL_STRING("TEXTURE_RECTANGLE"); - console->LogStringMessage(msg.get()); - } - - if (NS_IsMainThread()) { - // NOTE: This must match the code in ReadDrawFPSPref::Run(). - Preferences::AddBoolVarCache(&sDrawFPS, "layers.acceleration.draw-fps"); - } else { - // We have to dispatch an event to the main thread to read the pref. - NS_DispatchToMainThread(new ReadDrawFPSPref()); - } - - mComposer2D = mWidget->GetComposer2D(); - - reporter.SetSuccessful(); - return true; -} - -void -LayerManagerOGL::SetClippingRegion(const nsIntRegion& aClippingRegion) -{ - mClippingRegion = aClippingRegion; -} - -void -LayerManagerOGL::BeginTransaction() -{ - mInTransaction = true; -#ifdef DEBUG - mMaybeInvalidTree = false; -#endif -} - -void -LayerManagerOGL::BeginTransactionWithTarget(gfxContext *aTarget) -{ - mInTransaction = true; -#ifdef DEBUG - mMaybeInvalidTree = false; -#endif - -#ifdef MOZ_LAYERS_HAVE_LOG - MOZ_LAYERS_LOG(("[----- BeginTransaction")); - Log(); -#endif - - if (mDestroyed) { - NS_WARNING("Call on destroyed layer manager"); - return; - } - - mTarget = aTarget; -} - -bool -LayerManagerOGL::EndEmptyTransaction(EndTransactionFlags aFlags) -{ - // NB: this makes the somewhat bogus assumption that pure - // compositing txns don't call BeginTransaction(), because that's - // the behavior of CompositorParent. - MOZ_ASSERT(!mMaybeInvalidTree); - mInTransaction = false; - - if (!mRoot) - return false; - - EndTransaction(nullptr, nullptr, aFlags); - return true; -} - -void -LayerManagerOGL::EndTransaction(DrawThebesLayerCallback aCallback, - void* aCallbackData, - EndTransactionFlags aFlags) -{ - mInTransaction = false; - -#ifdef MOZ_LAYERS_HAVE_LOG - MOZ_LAYERS_LOG((" ----- (beginning paint)")); - Log(); -#endif - - if (mDestroyed) { - NS_WARNING("Call on destroyed layer manager"); - return; - } - - if (mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) { - if (aFlags & END_NO_COMPOSITE) { - // Apply pending tree updates before recomputing effective - // properties. - mRoot->ApplyPendingUpdatesToSubtree(); - } - - // The results of our drawing always go directly into a pixel buffer, - // so we don't need to pass any global transform here. - mRoot->ComputeEffectiveTransforms(gfx3DMatrix()); - - mThebesLayerCallback = aCallback; - mThebesLayerCallbackData = aCallbackData; - SetCompositingDisabled(aFlags & END_NO_COMPOSITE); - - bool needGLRender = true; - if (mComposer2D && mComposer2D->TryRender(mRoot, mWorldMatrix)) { - needGLRender = false; - - if (sDrawFPS) { - if (!mFPS) { - mFPS = new FPSState(); - } - double fps = mFPS->mCompositionFps.AddFrameAndGetFps(TimeStamp::Now()); - printf_stderr("HWComposer: FPS is %g\n", fps); - } - - // This lets us reftest and screenshot content rendered by the - // 2d composer. - if (mTarget) { - MakeCurrent(); - CopyToTarget(mTarget); - mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0); - } - - MOZ_ASSERT(!needGLRender); - } - if (needGLRender) { - Render(); - } - - mThebesLayerCallback = nullptr; - mThebesLayerCallbackData = nullptr; - } - - mTarget = nullptr; - -#ifdef MOZ_LAYERS_HAVE_LOG - Log(); - MOZ_LAYERS_LOG(("]----- EndTransaction")); -#endif -} - -already_AddRefed -LayerManagerOGL::CreateOptimalMaskSurface(const gfxIntSize &aSize) -{ - return gfxPlatform::GetPlatform()-> - CreateOffscreenImageSurface(aSize, GFX_CONTENT_ALPHA); -} - -already_AddRefed -LayerManagerOGL::CreateThebesLayer() -{ - if (mDestroyed) { - NS_WARNING("Call on destroyed layer manager"); - return nullptr; - } - - nsRefPtr layer = new ThebesLayerOGL(this); - return layer.forget(); -} - -already_AddRefed -LayerManagerOGL::CreateContainerLayer() -{ - if (mDestroyed) { - NS_WARNING("Call on destroyed layer manager"); - return nullptr; - } - - nsRefPtr layer = new ContainerLayerOGL(this); - return layer.forget(); -} - -already_AddRefed -LayerManagerOGL::CreateImageLayer() -{ - if (mDestroyed) { - NS_WARNING("Call on destroyed layer manager"); - return nullptr; - } - - nsRefPtr layer = new ImageLayerOGL(this); - return layer.forget(); -} - -already_AddRefed -LayerManagerOGL::CreateColorLayer() -{ - if (mDestroyed) { - NS_WARNING("Call on destroyed layer manager"); - return nullptr; - } - - nsRefPtr layer = new ColorLayerOGL(this); - return layer.forget(); -} - -already_AddRefed -LayerManagerOGL::CreateCanvasLayer() -{ - if (mDestroyed) { - NS_WARNING("Call on destroyed layer manager"); - return nullptr; - } - - nsRefPtr layer = new CanvasLayerOGL(this); - return layer.forget(); -} - -static LayerOGL* -ToLayerOGL(Layer* aLayer) -{ - return static_cast(aLayer->ImplData()); -} - -static void ClearSubtree(Layer* aLayer) -{ - ToLayerOGL(aLayer)->CleanupResources(); - for (Layer* child = aLayer->GetFirstChild(); child; - child = child->GetNextSibling()) { - ClearSubtree(child); - } -} - -void -LayerManagerOGL::ClearCachedResources(Layer* aSubtree) -{ - MOZ_ASSERT(!aSubtree || aSubtree->Manager() == this); - Layer* subtree = aSubtree ? aSubtree : mRoot.get(); - if (!subtree) { - return; - } - - ClearSubtree(subtree); -#ifdef DEBUG - // If this subtree is reachable from the root layer, then it's - // possibly onscreen, and the resource clear means that composites - // until the next received transaction may draw garbage to the - // framebuffer. - for(; subtree && subtree != mRoot; subtree = subtree->GetParent()); - mMaybeInvalidTree = (subtree == mRoot); -#endif // DEBUG -} - -LayerOGL* -LayerManagerOGL::RootLayer() const -{ - if (mDestroyed) { - NS_WARNING("Call on destroyed layer manager"); - return nullptr; - } - - return ToLayerOGL(mRoot); -} - -bool LayerManagerOGL::sDrawFPS = false; - -// |aTexCoordRect| is the rectangle from the texture that we want to -// draw using the given program. The program already has a necessary -// offset and scale, so the geometry that needs to be drawn is a unit -// square from 0,0 to 1,1. -// -// |aTexSize| is the actual size of the texture, as it can be larger -// than the rectangle given by |aTexCoordRect|. -void -LayerManagerOGL::BindAndDrawQuadWithTextureRect(ShaderProgramOGL *aProg, - const nsIntRect& aTexCoordRect, - const nsIntSize& aTexSize, - GLenum aWrapMode /* = LOCAL_GL_REPEAT */, - bool aFlipped /* = false */) -{ - NS_ASSERTION(aProg->HasInitialized(), "Shader program not correctly initialized"); - GLuint vertAttribIndex = - aProg->AttribLocation(ShaderProgramOGL::VertexCoordAttrib); - GLuint texCoordAttribIndex = - aProg->AttribLocation(ShaderProgramOGL::TexCoordAttrib); - NS_ASSERTION(texCoordAttribIndex != GLuint(-1), "no texture coords?"); - - // clear any bound VBO so that glVertexAttribPointer() goes back to - // "pointer mode" - mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0); - - // Given what we know about these textures and coordinates, we can - // compute fmod(t, 1.0f) to get the same texture coordinate out. If - // the texCoordRect dimension is < 0 or > width/height, then we have - // wraparound that we need to deal with by drawing multiple quads, - // because we can't rely on full non-power-of-two texture support - // (which is required for the REPEAT wrap mode). - - GLContext::RectTriangles rects; - - nsIntSize realTexSize = aTexSize; - if (!mGLContext->CanUploadNonPowerOfTwo()) { - realTexSize = nsIntSize(NextPowerOfTwo(aTexSize.width), - NextPowerOfTwo(aTexSize.height)); - } - - if (aWrapMode == LOCAL_GL_REPEAT) { - rects.addRect(/* dest rectangle */ - 0.0f, 0.0f, 1.0f, 1.0f, - /* tex coords */ - aTexCoordRect.x / GLfloat(realTexSize.width), - aTexCoordRect.y / GLfloat(realTexSize.height), - aTexCoordRect.XMost() / GLfloat(realTexSize.width), - aTexCoordRect.YMost() / GLfloat(realTexSize.height), - aFlipped); - } else { - GLContext::DecomposeIntoNoRepeatTriangles(aTexCoordRect, realTexSize, - rects, aFlipped); - } - - mGLContext->fVertexAttribPointer(vertAttribIndex, 2, - LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, - rects.vertexPointer()); - - mGLContext->fVertexAttribPointer(texCoordAttribIndex, 2, - LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, - rects.texCoordPointer()); - - { - mGLContext->fEnableVertexAttribArray(texCoordAttribIndex); - { - mGLContext->fEnableVertexAttribArray(vertAttribIndex); - - mGLContext->fDrawArrays(LOCAL_GL_TRIANGLES, 0, rects.elements()); - - mGLContext->fDisableVertexAttribArray(vertAttribIndex); - } - mGLContext->fDisableVertexAttribArray(texCoordAttribIndex); - } -} - -void -LayerManagerOGL::Render() -{ - PROFILER_LABEL("LayerManagerOGL", "Render"); - if (mDestroyed) { - NS_WARNING("Call on destroyed layer manager"); - return; - } - - nsIntRect rect; - if (mIsRenderingToEGLSurface) { - rect = nsIntRect(0, 0, mSurfaceSize.width, mSurfaceSize.height); - } else { - rect = mRenderBounds; - // If render bounds is not updated explicitly, try to infer it from widget - if (rect.width == 0 || rect.height == 0) { - // FIXME/bug XXXXXX this races with rotation changes on the main - // thread, and undoes all the care we take with layers txns being - // sent atomically with rotation changes - mWidget->GetClientBounds(rect); - rect.x = rect.y = 0; - } - } - WorldTransformRect(rect); - - GLint width = rect.width; - GLint height = rect.height; - - // We can't draw anything to something with no area - // so just return - if (width == 0 || height == 0) - return; - - // If the widget size changed, we have to force a MakeCurrent - // to make sure that GL sees the updated widget size. - if (mWidgetSize.width != width || - mWidgetSize.height != height) - { - MakeCurrent(true); - - mWidgetSize.width = width; - mWidgetSize.height = height; - } else { - MakeCurrent(); - } - -#if MOZ_WIDGET_ANDROID - TexturePoolOGL::Fill(gl()); -#endif - - SetupBackBuffer(width, height); - SetupPipeline(width, height, ApplyWorldTransform); - - // Default blend function implements "OVER" - mGLContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA, - LOCAL_GL_ONE, LOCAL_GL_ONE); - mGLContext->fEnable(LOCAL_GL_BLEND); - - const nsIntRect *clipRect = mRoot->GetClipRect(); - - if (clipRect) { - nsIntRect r = *clipRect; - WorldTransformRect(r); - mGLContext->fScissor(r.x, r.y, r.width, r.height); - } else { - mGLContext->fScissor(0, 0, width, height); - } - - if (CompositingDisabled()) { - RootLayer()->RenderLayer(mGLContext->IsDoubleBuffered() ? 0 : mBackBufferFBO, - nsIntPoint(0, 0)); - mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0); - return; - } - - mGLContext->fEnable(LOCAL_GL_SCISSOR_TEST); - - // If the Android compositor is being used, this clear will be done in - // DrawWindowUnderlay. Make sure the bits used here match up with those used - // in mobile/android/base/gfx/LayerRenderer.java -#ifndef MOZ_ANDROID_OMTC - mGLContext->fClearColor(0.0, 0.0, 0.0, 0.0); - mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT); -#endif - - // Allow widget to render a custom background. - mWidget->PrepareWindowEffects(); - mWidget->DrawWindowUnderlay(this, rect); - - // Reset some state that might of been clobbered by the underlay. - mGLContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA, - LOCAL_GL_ONE, LOCAL_GL_ONE); - - // Render our layers. - RootLayer()->RenderLayer(mGLContext->IsDoubleBuffered() ? 0 : mBackBufferFBO, - nsIntPoint(0, 0)); - - // Allow widget to render a custom foreground too. - mWidget->DrawWindowOverlay(this, rect); - -#ifdef MOZ_DUMP_PAINTING - if (gfxUtils::sDumpPainting) { - nsIntRect rect; - if (mIsRenderingToEGLSurface) { - rect = nsIntRect(0, 0, mSurfaceSize.width, mSurfaceSize.height); - } else { - mWidget->GetClientBounds(rect); - } - nsRefPtr surf = gfxPlatform::GetPlatform()->CreateOffscreenSurface(rect.Size(), GFX_CONTENT_COLOR_ALPHA); - nsRefPtr ctx = new gfxContext(surf); - CopyToTarget(ctx); - - WriteSnapshotToDumpFile(this, surf); - } -#endif - - if (mTarget) { - CopyToTarget(mTarget); - mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0); - return; - } - - if (sDrawFPS && !mFPS) { - mFPS = new FPSState(); - } else if (!sDrawFPS && mFPS) { - mFPS = nullptr; - } - - if (mFPS) { - mFPS->DrawFPS(TimeStamp::Now(), 0, mGLContext, GetProgram(Copy2DProgramType)); - } - - if (mGLContext->IsDoubleBuffered()) { - mGLContext->SwapBuffers(); - LayerManager::PostPresent(); - mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0); - return; - } - - mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0); - - mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0); - - ShaderProgramOGL *copyprog = GetProgram(Copy2DProgramType); - - if (mFBOTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB) { - copyprog = GetProgram(Copy2DRectProgramType); - } - - mGLContext->fBindTexture(mFBOTextureTarget, mBackBufferTexture); - - copyprog->Activate(); - copyprog->SetTextureUnit(0); - - if (copyprog->GetTexCoordMultiplierUniformLocation() != -1) { - copyprog->SetTexCoordMultiplier(width, height); - } - - // we're going to use client-side vertex arrays for this. - mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0); - - // "COPY" - mGLContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ZERO, - LOCAL_GL_ONE, LOCAL_GL_ZERO); - - // enable our vertex attribs; we'll call glVertexPointer below - // to fill with the correct data. - GLint vcattr = copyprog->AttribLocation(ShaderProgramOGL::VertexCoordAttrib); - GLint tcattr = copyprog->AttribLocation(ShaderProgramOGL::TexCoordAttrib); - - mGLContext->fEnableVertexAttribArray(vcattr); - mGLContext->fEnableVertexAttribArray(tcattr); - - const nsIntRect *r; - nsIntRegionRectIterator iter(mClippingRegion); - - while ((r = iter.Next()) != nullptr) { - nsIntRect cRect = *r; r = &cRect; - WorldTransformRect(cRect); - float left = (GLfloat)r->x / width; - float right = (GLfloat)r->XMost() / width; - float top = (GLfloat)r->y / height; - float bottom = (GLfloat)r->YMost() / height; - - float vertices[] = { left * 2.0f - 1.0f, - -(top * 2.0f - 1.0f), - right * 2.0f - 1.0f, - -(top * 2.0f - 1.0f), - left * 2.0f - 1.0f, - -(bottom * 2.0f - 1.0f), - right * 2.0f - 1.0f, - -(bottom * 2.0f - 1.0f) }; - - // Use inverted texture coordinates since our projection matrix also has a - // flip and we need to cancel that out. - float coords[] = { left, 1 - top, - right, 1 - top, - left, 1 - bottom, - right, 1 - bottom }; - - mGLContext->fVertexAttribPointer(vcattr, - 2, LOCAL_GL_FLOAT, - LOCAL_GL_FALSE, - 0, vertices); - - mGLContext->fVertexAttribPointer(tcattr, - 2, LOCAL_GL_FLOAT, - LOCAL_GL_FALSE, - 0, coords); - - mGLContext->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4); - } - - mGLContext->fDisableVertexAttribArray(vcattr); - mGLContext->fDisableVertexAttribArray(tcattr); - - mGLContext->fFlush(); - mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0); -} - -void -LayerManagerOGL::SetWorldTransform(const gfxMatrix& aMatrix) -{ - NS_ASSERTION(aMatrix.PreservesAxisAlignedRectangles(), - "SetWorldTransform only accepts matrices that satisfy PreservesAxisAlignedRectangles"); - NS_ASSERTION(!aMatrix.HasNonIntegerScale(), - "SetWorldTransform only accepts matrices with integer scale"); - - mWorldMatrix = aMatrix; -} - -gfxMatrix& -LayerManagerOGL::GetWorldTransform(void) -{ - return mWorldMatrix; -} - -void -LayerManagerOGL::WorldTransformRect(nsIntRect& aRect) -{ - gfxRect grect(aRect.x, aRect.y, aRect.width, aRect.height); - grect = mWorldMatrix.TransformBounds(grect); - aRect.SetRect(grect.X(), grect.Y(), grect.Width(), grect.Height()); -} - -void -LayerManagerOGL::UpdateRenderBounds(const nsIntRect& aRect) -{ - mRenderBounds = aRect; -} - -void -LayerManagerOGL::SetSurfaceSize(int width, int height) -{ - mSurfaceSize.width = width; - mSurfaceSize.height = height; -} - -void -LayerManagerOGL::SetupPipeline(int aWidth, int aHeight, WorldTransforPolicy aTransformPolicy) -{ - // Set the viewport correctly. - mGLContext->fViewport(0, 0, aWidth, aHeight); - - // We flip the view matrix around so that everything is right-side up; we're - // drawing directly into the window's back buffer, so this keeps things - // looking correct. - // - // XXX: We keep track of whether the window size changed, so we could skip - // this update if it hadn't changed since the last call. We will need to - // track changes to aTransformPolicy and mWorldMatrix for this to work - // though. - - // Matrix to transform (0, 0, aWidth, aHeight) to viewport space (-1.0, 1.0, - // 2, 2) and flip the contents. - gfxMatrix viewMatrix; - viewMatrix.Translate(-gfxPoint(1.0, -1.0)); - viewMatrix.Scale(2.0f / float(aWidth), 2.0f / float(aHeight)); - viewMatrix.Scale(1.0f, -1.0f); - - if (aTransformPolicy == ApplyWorldTransform) { - viewMatrix = mWorldMatrix * viewMatrix; - } - - gfx3DMatrix matrix3d = gfx3DMatrix::From2D(viewMatrix); - matrix3d._33 = 0.0f; - - SetLayerProgramProjectionMatrix(matrix3d); -} - -void -LayerManagerOGL::SetupBackBuffer(int aWidth, int aHeight) -{ - if (mGLContext->IsDoubleBuffered()) { - mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0); - return; - } - - // Do we have a FBO of the right size already? - if (mBackBufferSize.width == aWidth && - mBackBufferSize.height == aHeight) - { - mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mBackBufferFBO); - return; - } - - // we already have a FBO, but we need to resize its texture. - mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0); - mGLContext->fBindTexture(mFBOTextureTarget, mBackBufferTexture); - mGLContext->fTexImage2D(mFBOTextureTarget, - 0, - LOCAL_GL_RGBA, - aWidth, aHeight, - 0, - LOCAL_GL_RGBA, - LOCAL_GL_UNSIGNED_BYTE, - nullptr); - mGLContext->fBindTexture(mFBOTextureTarget, 0); - - mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mBackBufferFBO); - mGLContext->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, - LOCAL_GL_COLOR_ATTACHMENT0, - mFBOTextureTarget, - mBackBufferTexture, - 0); - - GLenum result = mGLContext->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER); - if (result != LOCAL_GL_FRAMEBUFFER_COMPLETE) { - nsAutoCString msg; - msg.Append("Framebuffer not complete -- error 0x"); - msg.AppendInt(result, 16); - NS_RUNTIMEABORT(msg.get()); - } - - mBackBufferSize.width = aWidth; - mBackBufferSize.height = aHeight; -} - -void -LayerManagerOGL::CopyToTarget(gfxContext *aTarget) -{ - nsIntRect rect; - if (mIsRenderingToEGLSurface) { - rect = nsIntRect(0, 0, mSurfaceSize.width, mSurfaceSize.height); - } else { - rect = nsIntRect(0, 0, mWidgetSize.width, mWidgetSize.height); - } - GLint width = rect.width; - GLint height = rect.height; - - if ((int64_t(width) * int64_t(height) * int64_t(4)) > INT32_MAX) { - NS_ERROR("Widget size too big - integer overflow!"); - return; - } - - nsRefPtr imageSurface = - new gfxImageSurface(gfxIntSize(width, height), - gfxImageFormatARGB32); - - mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, - mGLContext->IsDoubleBuffered() ? 0 : mBackBufferFBO); - - if (!mGLContext->IsGLES2()) { - // GLES2 promises that binding to any custom FBO will attach - // to GL_COLOR_ATTACHMENT0 attachment point. - if (mGLContext->IsDoubleBuffered()) { - mGLContext->fReadBuffer(LOCAL_GL_BACK); - } - else { - mGLContext->fReadBuffer(LOCAL_GL_COLOR_ATTACHMENT0); - } - } - - NS_ASSERTION(imageSurface->Stride() == width * 4, - "Image Surfaces being created with weird stride!"); - - mGLContext->ReadPixelsIntoImageSurface(imageSurface); - - // Map from GL space to Cairo space and reverse the world transform. - gfxMatrix glToCairoTransform = mWorldMatrix; - glToCairoTransform.Invert(); - glToCairoTransform.Scale(1.0, -1.0); - glToCairoTransform.Translate(-gfxPoint(0.0, height)); - - gfxContextAutoSaveRestore restore(aTarget); - aTarget->SetOperator(gfxContext::OPERATOR_SOURCE); - aTarget->SetMatrix(glToCairoTransform); - aTarget->SetSource(imageSurface); - aTarget->Paint(); -} - -void -LayerManagerOGL::SetLayerProgramProjectionMatrix(const gfx3DMatrix& aMatrix) -{ - for (unsigned int i = 0; i < mPrograms.Length(); ++i) { - for (uint32_t mask = MaskNone; mask < NumMaskTypes; ++mask) { - if (mPrograms[i].mVariations[mask]) { - mPrograms[i].mVariations[mask]->CheckAndSetProjectionMatrix(aMatrix); - } - } - } -} - -static GLenum -LayerManagerOGL_GetFrameBufferInternalFormat(GLContext* gl, - GLuint aCurrentFrameBuffer, - nsIWidget* aWidget) -{ - if (aCurrentFrameBuffer == 0) { // default framebuffer - return aWidget->GetGLFrameBufferFormat(); - } - return LOCAL_GL_RGBA; -} - -bool -LayerManagerOGL::CreateFBOWithTexture(const nsIntRect& aRect, InitMode aInit, - GLuint aCurrentFrameBuffer, - GLuint *aFBO, GLuint *aTexture) -{ - GLuint tex, fbo; - - mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0); - mGLContext->fGenTextures(1, &tex); - mGLContext->fBindTexture(mFBOTextureTarget, tex); - - if (aInit == InitModeCopy) { - // We're going to create an RGBA temporary fbo. But to - // CopyTexImage() from the current framebuffer, the framebuffer's - // format has to be compatible with the new texture's. So we - // check the format of the framebuffer here and take a slow path - // if it's incompatible. - GLenum format = - LayerManagerOGL_GetFrameBufferInternalFormat(gl(), aCurrentFrameBuffer, mWidget); - - bool isFormatCompatibleWithRGBA - = gl()->IsGLES2() ? (format == LOCAL_GL_RGBA) - : true; - - if (isFormatCompatibleWithRGBA) { - mGLContext->fCopyTexImage2D(mFBOTextureTarget, - 0, - LOCAL_GL_RGBA, - aRect.x, aRect.y, - aRect.width, aRect.height, - 0); - } else { - // Curses, incompatible formats. Take a slow path. - - // RGBA - size_t bufferSize = aRect.width * aRect.height * 4; - nsAutoArrayPtr buf(new uint8_t[bufferSize]); - - mGLContext->fReadPixels(aRect.x, aRect.y, - aRect.width, aRect.height, - LOCAL_GL_RGBA, - LOCAL_GL_UNSIGNED_BYTE, - buf); - mGLContext->fTexImage2D(mFBOTextureTarget, - 0, - LOCAL_GL_RGBA, - aRect.width, aRect.height, - 0, - LOCAL_GL_RGBA, - LOCAL_GL_UNSIGNED_BYTE, - buf); - } - } else { - mGLContext->fTexImage2D(mFBOTextureTarget, - 0, - LOCAL_GL_RGBA, - aRect.width, aRect.height, - 0, - LOCAL_GL_RGBA, - LOCAL_GL_UNSIGNED_BYTE, - nullptr); - } - mGLContext->fTexParameteri(mFBOTextureTarget, LOCAL_GL_TEXTURE_MIN_FILTER, - LOCAL_GL_LINEAR); - mGLContext->fTexParameteri(mFBOTextureTarget, LOCAL_GL_TEXTURE_MAG_FILTER, - LOCAL_GL_LINEAR); - mGLContext->fTexParameteri(mFBOTextureTarget, LOCAL_GL_TEXTURE_WRAP_S, - LOCAL_GL_CLAMP_TO_EDGE); - mGLContext->fTexParameteri(mFBOTextureTarget, LOCAL_GL_TEXTURE_WRAP_T, - LOCAL_GL_CLAMP_TO_EDGE); - mGLContext->fBindTexture(mFBOTextureTarget, 0); - - mGLContext->fGenFramebuffers(1, &fbo); - mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, fbo); - mGLContext->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, - LOCAL_GL_COLOR_ATTACHMENT0, - mFBOTextureTarget, - tex, - 0); - - // Making this call to fCheckFramebufferStatus prevents a crash on - // PowerVR. See bug 695246. - GLenum result = mGLContext->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER); - if (result != LOCAL_GL_FRAMEBUFFER_COMPLETE) { - nsAutoCString msg; - msg.Append("Framebuffer not complete -- error 0x"); - msg.AppendInt(result, 16); - msg.Append(", mFBOTextureTarget 0x"); - msg.AppendInt(mFBOTextureTarget, 16); - msg.Append(", aRect.width "); - msg.AppendInt(aRect.width); - msg.Append(", aRect.height "); - msg.AppendInt(aRect.height); - NS_WARNING(msg.get()); - - mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0); - mGLContext->fDeleteFramebuffers(1, &fbo); - mGLContext->fDeleteTextures(1, &tex); - return false; - } - - SetupPipeline(aRect.width, aRect.height, DontApplyWorldTransform); - mGLContext->fScissor(0, 0, aRect.width, aRect.height); - - if (aInit == InitModeClear) { - mGLContext->fClearColor(0.0, 0.0, 0.0, 0.0); - mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT); - } - - *aFBO = fbo; - *aTexture = tex; - return true; -} - -TemporaryRef -LayerManagerOGL::CreateDrawTarget(const IntSize &aSize, - SurfaceFormat aFormat) -{ -#ifdef XP_MACOSX - // We don't want to accelerate if the surface is too small which indicates - // that it's likely used for an icon/static image. We also don't want to - // accelerate anything that is above the maximum texture size of weakest gpu. - // Safari uses 5000 area as the minimum for acceleration, we decided 64^2 is more logical. - bool useAcceleration = aSize.width <= 4096 && aSize.height <= 4096 && - aSize.width > 64 && aSize.height > 64 && - gfxPlatformMac::GetPlatform()->UseAcceleratedCanvas(); - if (useAcceleration) { - return Factory::CreateDrawTarget(BACKEND_COREGRAPHICS_ACCELERATED, - aSize, aFormat); - } -#endif - return LayerManager::CreateDrawTarget(aSize, aFormat); -} - -} /* layers */ -} /* mozilla */ diff --git a/gfx/layers/opengl/LayerManagerOGL.h b/gfx/layers/opengl/LayerManagerOGL.h deleted file mode 100644 index edfe63269b6..00000000000 --- a/gfx/layers/opengl/LayerManagerOGL.h +++ /dev/null @@ -1,494 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef GFX_LAYERMANAGEROGL_H -#define GFX_LAYERMANAGEROGL_H - -#include // for int32_t -#include "GLDefs.h" // for GLuint, GLenum, GLintptr, etc -#include "LayerManagerOGLProgram.h" // for ShaderProgramOGL, etc -#include "Layers.h" -#include "gfxMatrix.h" // for gfxMatrix -#include "gfxPoint.h" // for gfxIntSize -#include "mozilla/Attributes.h" // for MOZ_OVERRIDE, MOZ_FINAL -#include "mozilla/RefPtr.h" // for TemporaryRef -#include "mozilla/gfx/BaseSize.h" // for BaseSize -#include "mozilla/gfx/Point.h" // for IntSize -#include "mozilla/gfx/Types.h" // for SurfaceFormat, etc -#include "mozilla/layers/CompositorTypes.h" // for MaskType::MaskNone, etc -#include "mozilla/layers/LayersTypes.h" // for LayersBackend, etc -#include "nsAString.h" -#include "nsAutoPtr.h" // for nsRefPtr, nsAutoPtr -#include "nsCOMPtr.h" // for already_AddRefed -#include "nsDebug.h" // for NS_ASSERTION, NS_WARNING -#include "nsISupportsImpl.h" // for Layer::AddRef, etc -#include "nsRect.h" // for nsIntRect -#include "nsRegion.h" // for nsIntRegion -#include "nsSize.h" // for nsIntSize -#include "nsTArray.h" // for nsTArray, nsTArray_Impl, etc -#include "nsThreadUtils.h" // for nsRunnable -#include "nscore.h" // for NS_IMETHOD, nsAString, etc -#ifdef XP_WIN -#include -#endif - -#define BUFFER_OFFSET(i) ((char *)nullptr + (i)) - -class gfx3DMatrix; -class gfxASurface; -class gfxContext; -class nsIWidget; -struct nsIntPoint; - -namespace mozilla { -namespace gl { -class GLContext; -} -namespace gfx { -class DrawTarget; -} -namespace layers { - -class Composer2D; -class ImageLayer; -class LayerOGL; -class ThebesLayerComposite; -class ContainerLayerComposite; -class ImageLayerComposite; -class CanvasLayerComposite; -class ColorLayerComposite; -struct FPSState; - -/** - * This is the LayerManager used for OpenGL 2.1 and OpenGL ES 2.0. - * This should be used only on the main thread. - */ -class LayerManagerOGL : public LayerManager -{ - typedef mozilla::gl::GLContext GLContext; - -public: - LayerManagerOGL(nsIWidget *aWidget, int aSurfaceWidth = -1, int aSurfaceHeight = -1, - bool aIsRenderingToEGLSurface = false); - virtual ~LayerManagerOGL(); - - void Destroy(); - - /** - * Initializes the layer manager with a given GLContext. If aContext is null - * then the layer manager will try to create one for the associated widget. - * - * \return True is initialization was succesful, false when it was not. - */ - bool Initialize(bool force = false); - - /** - * Sets the clipping region for this layer manager. This is important on - * windows because using OGL we no longer have GDI's native clipping. Therefor - * widget must tell us what part of the screen is being invalidated, - * and we should clip to this. - * - * \param aClippingRegion Region to clip to. Setting an empty region - * will disable clipping. - */ - void SetClippingRegion(const nsIntRegion& aClippingRegion); - - /** - * LayerManager implementation. - */ - void BeginTransaction(); - - void BeginTransactionWithTarget(gfxContext* aTarget); - - void EndConstruction(); - - virtual bool EndEmptyTransaction(EndTransactionFlags aFlags = END_DEFAULT); - virtual void EndTransaction(DrawThebesLayerCallback aCallback, - void* aCallbackData, - EndTransactionFlags aFlags = END_DEFAULT); - - virtual void SetRoot(Layer* aLayer) { mRoot = aLayer; } - - virtual bool CanUseCanvasLayerForSize(const gfxIntSize &aSize) { - if (!mGLContext) - return false; - int32_t maxSize = GetMaxTextureSize(); - return aSize <= gfxIntSize(maxSize, maxSize); - } - - virtual int32_t GetMaxTextureSize() const; - - virtual already_AddRefed CreateThebesLayer(); - - virtual already_AddRefed CreateContainerLayer(); - - virtual already_AddRefed CreateImageLayer(); - - virtual already_AddRefed CreateColorLayer(); - - virtual already_AddRefed CreateCanvasLayer(); - - virtual LayersBackend GetBackendType() { return LAYERS_OPENGL; } - virtual void GetBackendName(nsAString& name) { name.AssignLiteral("OpenGL"); } - - virtual already_AddRefed - CreateOptimalMaskSurface(const gfxIntSize &aSize); - - virtual void ClearCachedResources(Layer* aSubtree = nullptr) MOZ_OVERRIDE; - - /** - * Helper methods. - */ - void MakeCurrent(bool aForce = false); - - ShaderProgramOGL* GetBasicLayerProgram(bool aOpaque, bool aIsRGB, - MaskType aMask = MaskNone) - { - ShaderProgramType format = BGRALayerProgramType; - if (aIsRGB) { - if (aOpaque) { - format = RGBXLayerProgramType; - } else { - format = RGBALayerProgramType; - } - } else { - if (aOpaque) { - format = BGRXLayerProgramType; - } - } - return GetProgram(format, aMask); - } - - ShaderProgramOGL* GetProgram(ShaderProgramType aType, - Layer* aMaskLayer) { - if (aMaskLayer) - return GetProgram(aType, Mask2d); - return GetProgram(aType, MaskNone); - } - - ShaderProgramOGL* GetProgram(ShaderProgramType aType, - MaskType aMask = MaskNone) { - NS_ASSERTION(ProgramProfileOGL::ProgramExists(aType, aMask), - "Invalid program type."); - return mPrograms[aType].mVariations[aMask]; - } - - ShaderProgramOGL* GetFBOLayerProgram(MaskType aMask = MaskNone) { - return GetProgram(GetFBOLayerProgramType(), aMask); - } - - ShaderProgramType GetFBOLayerProgramType() { - if (mFBOTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB) - return RGBARectLayerProgramType; - return RGBALayerProgramType; - } - - gfx::SurfaceFormat GetFBOTextureFormat() { - return gfx::FORMAT_R8G8B8A8; - } - - GLContext* gl() const { return mGLContext; } - - // |NSOpenGLContext*|: - void* GetNSOpenGLContext() const; - - DrawThebesLayerCallback GetThebesLayerCallback() const - { return mThebesLayerCallback; } - - void* GetThebesLayerCallbackData() const - { return mThebesLayerCallbackData; } - - GLenum FBOTextureTarget() { return mFBOTextureTarget; } - - /** - * Controls how to initialize the texture / FBO created by - * CreateFBOWithTexture. - * - InitModeNone: No initialization, contents are undefined. - * - InitModeClear: Clears the FBO. - * - InitModeCopy: Copies the contents of the current glReadBuffer into the - * texture. - */ - enum InitMode { - InitModeNone, - InitModeClear, - InitModeCopy - }; - - /* Create a FBO backed by a texture; will leave the FBO - * bound. Note that the texture target type will be - * of the type returned by FBOTextureTarget; different - * shaders are required to sample from the different - * texture types. - */ - bool CreateFBOWithTexture(const nsIntRect& aRect, InitMode aInit, - GLuint aCurrentFrameBuffer, - GLuint *aFBO, GLuint *aTexture); - - GLuint QuadVBO() { return mQuadVBO; } - GLintptr QuadVBOVertexOffset() { return 0; } - GLintptr QuadVBOTexCoordOffset() { return sizeof(float)*4*2; } - GLintptr QuadVBOFlippedTexCoordOffset() { return sizeof(float)*8*2; } - - void BindQuadVBO(); - void QuadVBOVerticesAttrib(GLuint aAttribIndex); - void QuadVBOTexCoordsAttrib(GLuint aAttribIndex); - void QuadVBOFlippedTexCoordsAttrib(GLuint aAttribIndex); - - // Super common - - void BindAndDrawQuad(GLuint aVertAttribIndex, - GLuint aTexCoordAttribIndex, - bool aFlipped = false); - - void BindAndDrawQuad(ShaderProgramOGL *aProg, - bool aFlipped = false) - { - NS_ASSERTION(aProg->HasInitialized(), "Shader program not correctly initialized"); - BindAndDrawQuad(aProg->AttribLocation(ShaderProgramOGL::VertexCoordAttrib), - aProg->AttribLocation(ShaderProgramOGL::TexCoordAttrib), - aFlipped); - } - - // |aTexCoordRect| is the rectangle from the texture that we want to - // draw using the given program. The program already has a necessary - // offset and scale, so the geometry that needs to be drawn is a unit - // square from 0,0 to 1,1. - // - // |aTexSize| is the actual size of the texture, as it can be larger - // than the rectangle given by |aTexCoordRect|. - void BindAndDrawQuadWithTextureRect(ShaderProgramOGL *aProg, - const nsIntRect& aTexCoordRect, - const nsIntSize& aTexSize, - GLenum aWrapMode = LOCAL_GL_REPEAT, - bool aFlipped = false); - - virtual const char* Name() const { return "OGL"; } - - const nsIntSize& GetWidgetSize() { - return mWidgetSize; - } - - enum WorldTransforPolicy { - ApplyWorldTransform, - DontApplyWorldTransform - }; - - /** - * Setup the viewport and projection matrix for rendering - * to a window of the given dimensions. - */ - void SetupPipeline(int aWidth, int aHeight, WorldTransforPolicy aTransformPolicy); - - /** - * Setup World transform matrix. - * Transform will be ignored if it is not PreservesAxisAlignedRectangles - * or has non integer scale - */ - void SetWorldTransform(const gfxMatrix& aMatrix); - gfxMatrix& GetWorldTransform(void); - void WorldTransformRect(nsIntRect& aRect); - - void UpdateRenderBounds(const nsIntRect& aRect); - - /** - * Set the size of the surface we're rendering to. - */ - void SetSurfaceSize(int width, int height); - - bool CompositingDisabled() { return mCompositingDisabled; } - void SetCompositingDisabled(bool aCompositingDisabled) { mCompositingDisabled = aCompositingDisabled; } - - /** - * Creates a DrawTarget which is optimized for inter-operating with this - * layermanager. - */ - virtual TemporaryRef - CreateDrawTarget(const mozilla::gfx::IntSize &aSize, - mozilla::gfx::SurfaceFormat aFormat); - - /** - * Calculates the 'completeness' of the rendering that intersected with the - * screen on the last render. This is only useful when progressive tile - * drawing is enabled, otherwise this will always return 1.0. - * This function's expense scales with the size of the layer tree and the - * complexity of individual layers' valid regions. - */ - float ComputeRenderIntegrity(); - -private: - /** Widget associated with this layer manager */ - nsIWidget *mWidget; - nsIntSize mWidgetSize; - - /** The size of the surface we are rendering to */ - nsIntSize mSurfaceSize; - - /** - * Context target, nullptr when drawing directly to our swap chain. - */ - nsRefPtr mTarget; - - nsRefPtr mGLContext; - - /** Our more efficient but less powerful alter ego, if one is available. */ - nsRefPtr mComposer2D; - - already_AddRefed CreateContext(); - - /** Backbuffer */ - GLuint mBackBufferFBO; - GLuint mBackBufferTexture; - nsIntSize mBackBufferSize; - - /** Shader Programs */ - struct ShaderProgramVariations { - ShaderProgramOGL* mVariations[NumMaskTypes]; - }; - nsTArray mPrograms; - - /** Texture target to use for FBOs */ - GLenum mFBOTextureTarget; - - /** VBO that has some basics in it for a textured quad, - * including vertex coords and texcoords for both - * flipped and unflipped textures */ - GLuint mQuadVBO; - - /** Region we're clipping our current drawing to. */ - nsIntRegion mClippingRegion; - - /** Misc */ - bool mHasBGRA; - bool mCompositingDisabled; - - /** - * When rendering to an EGL surface (e.g. on Android), we rely on being told - * about size changes (via SetSurfaceSize) rather than pulling this information - * from the widget, since the widget's information can lag behind. - */ - bool mIsRenderingToEGLSurface; - - /** Helper-class used by Initialize **/ - class ReadDrawFPSPref MOZ_FINAL : public nsRunnable { - public: - NS_IMETHOD Run() MOZ_OVERRIDE; - }; - - /** Current root layer. */ - LayerOGL *RootLayer() const; - - /** - * Render the current layer tree to the active target. - */ - void Render(); - - /** - * Setup a backbuffer of the given dimensions. - */ - void SetupBackBuffer(int aWidth, int aHeight); - - /** - * Copies the content of our backbuffer to the set transaction target. - */ - void CopyToTarget(gfxContext *aTarget); - - /** - * Updates all layer programs with a new projection matrix. - */ - void SetLayerProgramProjectionMatrix(const gfx3DMatrix& aMatrix); - - /** - * Helper method for Initialize, creates all valid variations of a program - * and adds them to mPrograms - */ - void AddPrograms(ShaderProgramType aType); - - /** - * Recursive helper method for use by ComputeRenderIntegrity. Subtracts - * any incomplete rendering on aLayer from aScreenRegion. Any low-precision - * rendering is included in aLowPrecisionScreenRegion. aTransform is the - * accumulated transform of intermediate surfaces beneath aLayer. - */ - static void ComputeRenderIntegrityInternal(Layer* aLayer, - nsIntRegion& aScreenRegion, - nsIntRegion& aLowPrecisionScreenRegion, - const gfx3DMatrix& aTransform); - - /* Thebes layer callbacks; valid at the end of a transaciton, - * while rendering */ - DrawThebesLayerCallback mThebesLayerCallback; - void *mThebesLayerCallbackData; - gfxMatrix mWorldMatrix; - nsAutoPtr mFPS; - nsIntRect mRenderBounds; -#ifdef DEBUG - // NB: only interesting when this is a purely compositing layer - // manager. True after possibly onscreen layers have had their - // cached resources cleared outside of a transaction, and before the - // next forwarded transaction that re-validates their buffers. - bool mMaybeInvalidTree; -#endif - - static bool sDrawFPS; -}; - -/** - * General information and tree management for OGL layers. - */ -class LayerOGL -{ -public: - LayerOGL(LayerManagerOGL *aManager) - : mOGLManager(aManager), mDestroyed(false) - { } - - virtual ~LayerOGL() { } - - virtual LayerOGL *GetFirstChildOGL() { - return nullptr; - } - - /* Do NOT call this from the generic LayerOGL destructor. Only from the - * concrete class destructor - */ - virtual void Destroy() = 0; - - virtual Layer* GetLayer() = 0; - - virtual void RenderLayer(int aPreviousFrameBuffer, - const nsIntPoint& aOffset) = 0; - - typedef mozilla::gl::GLContext GLContext; - - LayerManagerOGL* OGLManager() const { return mOGLManager; } - GLContext *gl() const { return mOGLManager->gl(); } - virtual void CleanupResources() = 0; - - /** - * Loads the result of rendering the layer as an OpenGL texture in aTextureUnit. - * Will try to use an existing texture if possible, or a temporary - * one if not. It is the callee's responsibility to release the texture. - * Will return true if a texture could be constructed and loaded, false otherwise. - * The texture will not be transformed, i.e., it will be in the same coord - * space as this. - * Any layer that can be used as a mask layer should override this method. - * aSize will contain the size of the image. - */ - virtual bool LoadAsTexture(GLuint aTextureUnit, gfxIntSize* aSize) - { - NS_WARNING("LoadAsTexture called without being overriden"); - return false; - } - -protected: - LayerManagerOGL *mOGLManager; - bool mDestroyed; -}; - - -} /* layers */ -} /* mozilla */ - -#endif /* GFX_LAYERMANAGEROGL_H */ diff --git a/gfx/layers/opengl/LayerManagerOGLProgram.cpp b/gfx/layers/opengl/LayerManagerOGLProgram.cpp index bbeee162377..8b43a85b777 100644 --- a/gfx/layers/opengl/LayerManagerOGLProgram.cpp +++ b/gfx/layers/opengl/LayerManagerOGLProgram.cpp @@ -12,7 +12,6 @@ #include "nsAutoPtr.h" // for nsRefPtr #include "nsString.h" // for nsAutoCString #include "prenv.h" // for PR_GetEnv -#include "LayerManagerOGL.h" #include "LayerManagerOGLShaders.h" #include "Layers.h" #include "GLContext.h" @@ -439,40 +438,6 @@ ShaderProgramOGL::CreateProgram(const char *aVertexShaderString, return true; } -bool -ShaderProgramOGL::LoadMask(Layer* aMaskLayer) -{ - if (!aMaskLayer) { - return false; - } - - gfxIntSize size; - if (!static_cast(aMaskLayer->ImplData()) - ->LoadAsTexture(LOCAL_GL_TEXTURE0 + mProfile.mTextureCount - 1, &size)){ - return false; - } - - SetUniform(mProfile.LookupUniformLocation("uMaskTexture"), - (GLint)(mProfile.mTextureCount - 1)); - - gfxMatrix maskTransform; - mozilla::DebugOnly isMask2D = - aMaskLayer->GetEffectiveTransform().CanDraw2D(&maskTransform); - NS_ASSERTION(isMask2D, "How did we end up with a 3D transform here?!"); - gfxRect bounds = gfxRect(gfxPoint(), size); - bounds = maskTransform.TransformBounds(bounds); - - gfx3DMatrix m; - m._11 = 1.0f/bounds.width; - m._22 = 1.0f/bounds.height; - m._41 = float(-bounds.x)/bounds.width; - m._42 = float(-bounds.y)/bounds.height; - - SetMatrixUniform(mProfile.LookupUniformLocation("uMaskQuadTransform"), m); - - return true; -} - void ShaderProgramOGL::Activate() { diff --git a/gfx/layers/opengl/LayerManagerOGLProgram.h b/gfx/layers/opengl/LayerManagerOGLProgram.h index eb6ebce6930..83c978baf4e 100644 --- a/gfx/layers/opengl/LayerManagerOGLProgram.h +++ b/gfx/layers/opengl/LayerManagerOGLProgram.h @@ -247,20 +247,6 @@ public: return mTexCoordMultiplierUniformLocation; } - /** - * aLayer is the mask layer to use for rendering, or null, if there is no - * mask layer. - * If aLayer is non-null, then the result of rendering aLayer is stored as - * as a texture to be used by the shader. It is stored in the next available - * texture unit, as determined by the texture unit requirements for the - * shader. - * Any other features of the mask layer required by the shader are also - * loaded to graphics memory. In particular the transform used to move from - * the layer's coordinates to the mask's coordinates is loaded; this must be - * a 2D transform. - */ - bool LoadMask(Layer* aLayer); - /** * The following set of methods set a uniform argument to the shader program. * Not all uniforms may be set for all programs, and such uses will throw diff --git a/gfx/layers/opengl/ThebesLayerOGL.cpp b/gfx/layers/opengl/ThebesLayerOGL.cpp deleted file mode 100644 index c94c0eddacb..00000000000 --- a/gfx/layers/opengl/ThebesLayerOGL.cpp +++ /dev/null @@ -1,955 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "ThebesLayerOGL.h" -#include // for uint32_t -#include // for int32_t -#include "GLContext.h" // for GLContext, etc -#include "GLContextTypes.h" // for GLenum -#include "GLDefs.h" // for LOCAL_GL_ONE, LOCAL_GL_BGRA, etc -#include "GLTextureImage.h" // for TextureImage, etc -#include "ThebesLayerBuffer.h" // for ThebesLayerBuffer, etc -#include "gfx3DMatrix.h" // for gfx3DMatrix -#include "gfxASurface.h" // for gfxASurface, etc -#include "gfxColor.h" // for gfxRGBA -#include "gfxContext.h" // for gfxContext, etc -#include "gfxImageSurface.h" // for gfxImageSurface -#include "gfxPlatform.h" -#include "gfxPoint.h" // for gfxPoint -#include "gfxTeeSurface.h" // for gfxTeeSurface -#include "gfxUtils.h" // for gfxUtils, etc -#include "mozilla/Assertions.h" // for MOZ_ASSERT_HELPER2 -#include "mozilla/Util.h" // for ArrayLength -#include "mozilla/gfx/BasePoint.h" // for BasePoint -#include "mozilla/gfx/BaseRect.h" // for BaseRect -#include "mozilla/gfx/BaseSize.h" // for BaseSize -#include "mozilla/gfx/2D.h" // for DrawTarget, etc -#include "mozilla/mozalloc.h" // for operator new -#include "nsCOMPtr.h" // for already_AddRefed -#include "nsDebug.h" // for NS_ASSERTION, etc -#include "nsPoint.h" // for nsIntPoint -#include "nsRect.h" // for nsIntRect -#include "nsSize.h" // for nsIntSize -#include "LayerManagerOGL.h" // for LayerManagerOGL, etc -#include "LayerManagerOGLProgram.h" // for ShaderProgramOGL, etc -#include "gfx2DGlue.h" - -using namespace mozilla; -using namespace mozilla::gfx; - -namespace mozilla { -namespace layers { - -using gl::GLContext; -using gl::TextureImage; - -static const int ALLOW_REPEAT = ThebesLayerBuffer::ALLOW_REPEAT; - -GLenum -WrapMode(GLContext *aGl, uint32_t aFlags) -{ - if ((aFlags & ALLOW_REPEAT) && - (aGl->IsExtensionSupported(GLContext::ARB_texture_non_power_of_two) || - aGl->IsExtensionSupported(GLContext::OES_texture_npot))) { - return LOCAL_GL_REPEAT; - } - return LOCAL_GL_CLAMP_TO_EDGE; -} - -// BindAndDrawQuadWithTextureRect can work with either GL_REPEAT (preferred) -// or GL_CLAMP_TO_EDGE textures. If ALLOW_REPEAT is set in aFlags, we -// select based on whether REPEAT is valid for non-power-of-two textures -- -// if we have NPOT support we use it, otherwise we stick with CLAMP_TO_EDGE and -// decompose. -// If ALLOW_REPEAT is not set, we always use GL_CLAMP_TO_EDGE. -static already_AddRefed -CreateClampOrRepeatTextureImage(GLContext *aGl, - const nsIntSize& aSize, - TextureImage::ContentType aContentType, - uint32_t aFlags) -{ - - return aGl->CreateTextureImage(aSize, aContentType, WrapMode(aGl, aFlags)); -} - -class ThebesLayerBufferOGL -{ - NS_INLINE_DECL_REFCOUNTING(ThebesLayerBufferOGL) -public: - typedef TextureImage::ContentType ContentType; - typedef ThebesLayerBuffer::PaintState PaintState; - - ThebesLayerBufferOGL(ThebesLayer* aLayer, LayerOGL* aOGLLayer) - : mLayer(aLayer) - , mOGLLayer(aOGLLayer) - , mInitialised(true) - {} - virtual ~ThebesLayerBufferOGL() {} - - enum { PAINT_WILL_RESAMPLE = ThebesLayerBuffer::PAINT_WILL_RESAMPLE }; - virtual PaintState BeginPaint(ContentType aContentType, - uint32_t aFlags) = 0; - - void RenderTo(const nsIntPoint& aOffset, LayerManagerOGL* aManager, - uint32_t aFlags); - - void EndUpdate(); - - nsIntSize GetSize() { - if (mTexImage) - return ThebesIntSize(mTexImage->GetSize()); - return nsIntSize(0, 0); - } - - bool Initialised() { return mInitialised; } - - virtual nsIntPoint GetOriginOffset() = 0; -protected: - - GLContext* gl() const { return mOGLLayer->gl(); } - - ThebesLayer* mLayer; - LayerOGL* mOGLLayer; - nsRefPtr mTexImage; - nsRefPtr mTexImageOnWhite; - bool mInitialised; -}; - -void ThebesLayerBufferOGL::EndUpdate() -{ - if (mTexImage && mTexImage->InUpdate()) { - mTexImage->EndUpdate(); - } - - if (mTexImageOnWhite && mTexImageOnWhite->InUpdate()) { - mTexImageOnWhite->EndUpdate(); - } -} - -void -ThebesLayerBufferOGL::RenderTo(const nsIntPoint& aOffset, - LayerManagerOGL* aManager, - uint32_t aFlags) -{ - NS_ASSERTION(Initialised(), "RenderTo with uninitialised buffer!"); - - if (!mTexImage || !Initialised()) - return; - - EndUpdate(); - -#ifdef MOZ_DUMP_PAINTING - if (gfxUtils::sDumpPainting) { - nsRefPtr surf = - gl()->GetTexImage(mTexImage->GetTextureID(), false, mTexImage->GetTextureFormat()); - - WriteSnapshotToDumpFile(mLayer, surf); - } -#endif - - int32_t passes = mTexImageOnWhite ? 2 : 1; - for (int32_t pass = 1; pass <= passes; ++pass) { - ShaderProgramOGL *program; - - if (passes == 2) { - ShaderProgramOGL* alphaProgram; - if (pass == 1) { - ShaderProgramType type = gl()->GetPreferredARGB32Format() == LOCAL_GL_BGRA ? - ComponentAlphaPass1RGBProgramType : - ComponentAlphaPass1ProgramType; - - alphaProgram = aManager->GetProgram(type, mLayer->GetMaskLayer()); - gl()->fBlendFuncSeparate(LOCAL_GL_ZERO, LOCAL_GL_ONE_MINUS_SRC_COLOR, - LOCAL_GL_ONE, LOCAL_GL_ONE); - } else { - ShaderProgramType type = gl()->GetPreferredARGB32Format() == LOCAL_GL_BGRA ? - ComponentAlphaPass2RGBProgramType : - ComponentAlphaPass2ProgramType; - alphaProgram = aManager->GetProgram(type, mLayer->GetMaskLayer()); - gl()->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE, - LOCAL_GL_ONE, LOCAL_GL_ONE); - } - - alphaProgram->Activate(); - alphaProgram->SetBlackTextureUnit(0); - alphaProgram->SetWhiteTextureUnit(1); - program = alphaProgram; - } else { - // Note BGR: Cairo's image surfaces are always in what - // OpenGL and our shaders consider BGR format. - ShaderProgramOGL* basicProgram = - aManager->GetProgram(ShaderProgramFromSurfaceFormat(mTexImage->GetTextureFormat()), - mLayer->GetMaskLayer()); - - basicProgram->Activate(); - basicProgram->SetTextureUnit(0); - program = basicProgram; - } - - program->SetLayerOpacity(mLayer->GetEffectiveOpacity()); - program->SetLayerTransform(mLayer->GetEffectiveTransform()); - program->SetTextureTransform(gfx3DMatrix()); - program->SetRenderOffset(aOffset); - program->LoadMask(mLayer->GetMaskLayer()); - - const nsIntRegion& visibleRegion = mLayer->GetEffectiveVisibleRegion(); - nsIntRegion tmpRegion; - const nsIntRegion* renderRegion; - if (aFlags & PAINT_WILL_RESAMPLE) { - // If we're resampling, then the texture image will contain exactly the - // entire visible region's bounds, and we should draw it all in one quad - // to avoid unexpected aliasing. - tmpRegion = visibleRegion.GetBounds(); - renderRegion = &tmpRegion; - } else { - renderRegion = &visibleRegion; - } - - nsIntRegion region(*renderRegion); - nsIntPoint origin = GetOriginOffset(); - region.MoveBy(-origin); // translate into TexImage space, buffer origin might not be at texture (0,0) - - // Figure out the intersecting draw region - nsIntSize texSize = ThebesIntSize(mTexImage->GetSize()); - nsIntRect textureRect = nsIntRect(0, 0, texSize.width, texSize.height); - textureRect.MoveBy(region.GetBounds().TopLeft()); - nsIntRegion subregion; - subregion.And(region, textureRect); - if (subregion.IsEmpty()) // Region is empty, nothing to draw - return; - - nsIntRegion screenRects; - nsIntRegion regionRects; - - // Collect texture/screen coordinates for drawing - nsIntRegionRectIterator iter(subregion); - while (const nsIntRect* iterRect = iter.Next()) { - nsIntRect regionRect = *iterRect; - nsIntRect screenRect = regionRect; - screenRect.MoveBy(origin); - - screenRects.Or(screenRects, screenRect); - regionRects.Or(regionRects, regionRect); - } - - mTexImage->BeginTileIteration(); - if (mTexImageOnWhite) { - NS_ASSERTION(mTexImage->GetTileCount() == mTexImageOnWhite->GetTileCount(), - "Tile count mismatch on component alpha texture"); - mTexImageOnWhite->BeginTileIteration(); - } - - bool usingTiles = (mTexImage->GetTileCount() > 1); - do { - if (mTexImageOnWhite) { - NS_ASSERTION(ThebesIntRect(mTexImageOnWhite->GetTileRect()) == ThebesIntRect(mTexImage->GetTileRect()), "component alpha textures should be the same size."); - } - - nsIntRect tileRect = ThebesIntRect(mTexImage->GetTileRect()); - - // Bind textures. - TextureImage::ScopedBindTexture texBind(mTexImage, LOCAL_GL_TEXTURE0); - TextureImage::ScopedBindTexture texOnWhiteBind(mTexImageOnWhite, LOCAL_GL_TEXTURE1); - - // Draw texture. If we're using tiles, we do repeating manually, as texture - // repeat would cause each individual tile to repeat instead of the - // compound texture as a whole. This involves drawing at most 4 sections, - // 2 for each axis that has texture repeat. - for (int y = 0; y < (usingTiles ? 2 : 1); y++) { - for (int x = 0; x < (usingTiles ? 2 : 1); x++) { - nsIntRect currentTileRect(tileRect); - currentTileRect.MoveBy(x * texSize.width, y * texSize.height); - - nsIntRegionRectIterator screenIter(screenRects); - nsIntRegionRectIterator regionIter(regionRects); - - const nsIntRect* screenRect; - const nsIntRect* regionRect; - while ((screenRect = screenIter.Next()) && - (regionRect = regionIter.Next())) { - nsIntRect tileScreenRect(*screenRect); - nsIntRect tileRegionRect(*regionRect); - - // When we're using tiles, find the intersection between the tile - // rect and this region rect. Tiling is then handled by the - // outer for-loops and modifying the tile rect. - if (usingTiles) { - tileScreenRect.MoveBy(-origin); - tileScreenRect = tileScreenRect.Intersect(currentTileRect); - tileScreenRect.MoveBy(origin); - - if (tileScreenRect.IsEmpty()) - continue; - - tileRegionRect = regionRect->Intersect(currentTileRect); - tileRegionRect.MoveBy(-currentTileRect.TopLeft()); - } - -#ifdef ANDROID - // Bug 691354 - // Using the LINEAR filter we get unexplained artifacts. - // Use NEAREST when no scaling is required. - gfxMatrix matrix; - bool is2D = mLayer->GetEffectiveTransform().Is2D(&matrix); - if (is2D && !matrix.HasNonTranslationOrFlip()) { - gl()->ApplyFilterToBoundTexture(GraphicsFilter::FILTER_NEAREST); - } else { - mTexImage->ApplyFilter(); - } -#endif - program->SetLayerQuadRect(tileScreenRect); - aManager->BindAndDrawQuadWithTextureRect(program, tileRegionRect, - tileRect.Size(), - mTexImage->GetWrapMode()); - } - } - } - - if (mTexImageOnWhite) - mTexImageOnWhite->NextTile(); - } while (mTexImage->NextTile()); - } - - if (mTexImageOnWhite) { - // Restore defaults - gl()->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA, - LOCAL_GL_ONE, LOCAL_GL_ONE); - } -} - -// This implementation is the fast-path for when our TextureImage is -// permanently backed with a server-side ASurface. We can simply -// reuse the ThebesLayerBuffer logic in its entirety and profit. -class SurfaceBufferOGL : public ThebesLayerBufferOGL, private ThebesLayerBuffer -{ -public: - typedef ThebesLayerBufferOGL::ContentType ContentType; - typedef ThebesLayerBufferOGL::PaintState PaintState; - - SurfaceBufferOGL(ThebesLayerOGL* aLayer) - : ThebesLayerBufferOGL(aLayer, aLayer) - , ThebesLayerBuffer(SizedToVisibleBounds) - { - } - virtual ~SurfaceBufferOGL() {} - - // ThebesLayerBufferOGL interface - virtual PaintState BeginPaint(ContentType aContentType, - uint32_t aFlags) - { - // Let ThebesLayerBuffer do all the hard work for us! :D - return ThebesLayerBuffer::BeginPaint(mLayer, - aContentType, - aFlags); - } - - // ThebesLayerBuffer interface - void - CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags, - gfxASurface** aBlackSurface, gfxASurface** aWhiteSurface, - RefPtr* aBlackDT, RefPtr* aWhiteDT) MOZ_OVERRIDE - { - NS_ASSERTION(GFX_CONTENT_ALPHA != aType,"ThebesBuffer has color"); - - mTexImage = CreateClampOrRepeatTextureImage(gl(), aRect.Size(), aType, aFlags); - nsRefPtr ret = mTexImage ? mTexImage->GetBackingSurface() : nullptr; - *aBlackSurface = ret.forget().get(); - } - - virtual nsIntPoint GetOriginOffset() { - return BufferRect().TopLeft() - BufferRotation(); - } -}; - - -// This implementation is (currently) the slow-path for when we can't -// implement pixel retaining using thebes. This implementation and -// the above could be unified by abstracting buffer-copy operations -// and implementing them here using GL hacketry. -class BasicBufferOGL : public ThebesLayerBufferOGL -{ -public: - BasicBufferOGL(ThebesLayerOGL* aLayer) - : ThebesLayerBufferOGL(aLayer, aLayer) - , mBufferRect(0,0,0,0) - , mBufferRotation(0,0) - {} - virtual ~BasicBufferOGL() {} - - virtual PaintState BeginPaint(ContentType aContentType, - uint32_t aFlags); - virtual nsIntPoint GetOriginOffset() { - return mBufferRect.TopLeft() - mBufferRotation; - } - - -protected: - enum XSide { - LEFT, RIGHT - }; - enum YSide { - TOP, BOTTOM - }; - nsIntRect GetQuadrantRectangle(XSide aXSide, YSide aYSide); - -private: - nsIntRect mBufferRect; - nsIntPoint mBufferRotation; -}; - -static void -WrapRotationAxis(int32_t* aRotationPoint, int32_t aSize) -{ - if (*aRotationPoint < 0) { - *aRotationPoint += aSize; - } else if (*aRotationPoint >= aSize) { - *aRotationPoint -= aSize; - } -} - -nsIntRect -BasicBufferOGL::GetQuadrantRectangle(XSide aXSide, YSide aYSide) -{ - // quadrantTranslation is the amount we translate the top-left - // of the quadrant by to get coordinates relative to the layer - nsIntPoint quadrantTranslation = -mBufferRotation; - quadrantTranslation.x += aXSide == LEFT ? mBufferRect.width : 0; - quadrantTranslation.y += aYSide == TOP ? mBufferRect.height : 0; - return mBufferRect + quadrantTranslation; -} - -static void -FillSurface(gfxASurface* aSurface, const nsIntRegion& aRegion, - const nsIntPoint& aOffset, const gfxRGBA& aColor) -{ - nsRefPtr ctx = new gfxContext(aSurface); - ctx->Translate(-gfxPoint(aOffset.x, aOffset.y)); - gfxUtils::ClipToRegion(ctx, aRegion); - ctx->SetColor(aColor); - ctx->Paint(); -} - -BasicBufferOGL::PaintState -BasicBufferOGL::BeginPaint(ContentType aContentType, - uint32_t aFlags) -{ - PaintState result; - // We need to disable rotation if we're going to be resampled when - // drawing, because we might sample across the rotation boundary. - bool canHaveRotation = !(aFlags & PAINT_WILL_RESAMPLE); - - nsIntRegion validRegion = mLayer->GetValidRegion(); - - Layer::SurfaceMode mode; - ContentType contentType; - nsIntRegion neededRegion; - bool canReuseBuffer; - nsIntRect destBufferRect; - - while (true) { - mode = mLayer->GetSurfaceMode(); - contentType = aContentType; - neededRegion = mLayer->GetVisibleRegion(); - // If we're going to resample, we need a buffer that's in clamp mode. - canReuseBuffer = neededRegion.GetBounds().Size() <= mBufferRect.Size() && - mTexImage && - (!(aFlags & PAINT_WILL_RESAMPLE) || - mTexImage->GetWrapMode() == LOCAL_GL_CLAMP_TO_EDGE); - - if (canReuseBuffer) { - if (mBufferRect.Contains(neededRegion.GetBounds())) { - // We don't need to adjust mBufferRect. - destBufferRect = mBufferRect; - } else { - // The buffer's big enough but doesn't contain everything that's - // going to be visible. We'll move it. - destBufferRect = nsIntRect(neededRegion.GetBounds().TopLeft(), mBufferRect.Size()); - } - } else { - destBufferRect = neededRegion.GetBounds(); - } - - if (mode == Layer::SURFACE_COMPONENT_ALPHA) { - if (!gfxPlatform::ComponentAlphaEnabled() || - !mLayer->GetParent() || - !mLayer->GetParent()->SupportsComponentAlphaChildren()) { - mode = Layer::SURFACE_SINGLE_CHANNEL_ALPHA; - } else { - contentType = GFX_CONTENT_COLOR; - } - } - - if ((aFlags & PAINT_WILL_RESAMPLE) && - (!neededRegion.GetBounds().IsEqualInterior(destBufferRect) || - neededRegion.GetNumRects() > 1)) { - // The area we add to neededRegion might not be painted opaquely - if (mode == Layer::SURFACE_OPAQUE) { - contentType = GFX_CONTENT_COLOR_ALPHA; - mode = Layer::SURFACE_SINGLE_CHANNEL_ALPHA; - } - // For component alpha layers, we leave contentType as GFX_CONTENT_COLOR. - - // We need to validate the entire buffer, to make sure that only valid - // pixels are sampled - neededRegion = destBufferRect; - } - - if (mTexImage && - (mTexImage->GetContentType() != contentType || - (mode == Layer::SURFACE_COMPONENT_ALPHA) != (mTexImageOnWhite != nullptr))) { - // We're effectively clearing the valid region, so we need to draw - // the entire needed region now. - result.mRegionToInvalidate = mLayer->GetValidRegion(); - validRegion.SetEmpty(); - mTexImage = nullptr; - mTexImageOnWhite = nullptr; - mBufferRect.SetRect(0, 0, 0, 0); - mBufferRotation.MoveTo(0, 0); - // Restart decision process with the cleared buffer. We can only go - // around the loop one more iteration, since mTexImage is null now. - continue; - } - - break; - } - - result.mRegionToDraw.Sub(neededRegion, validRegion); - if (result.mRegionToDraw.IsEmpty()) - return result; - - if (destBufferRect.width > gl()->GetMaxTextureImageSize() || - destBufferRect.height > gl()->GetMaxTextureImageSize()) { - return result; - } - - nsIntRect drawBounds = result.mRegionToDraw.GetBounds(); - nsRefPtr destBuffer; - nsRefPtr destBufferOnWhite; - - uint32_t bufferFlags = canHaveRotation ? ALLOW_REPEAT : 0; - if (canReuseBuffer) { - nsIntRect keepArea; - if (keepArea.IntersectRect(destBufferRect, mBufferRect)) { - // Set mBufferRotation so that the pixels currently in mBuffer - // will still be rendered in the right place when mBufferRect - // changes to destBufferRect. - nsIntPoint newRotation = mBufferRotation + - (destBufferRect.TopLeft() - mBufferRect.TopLeft()); - WrapRotationAxis(&newRotation.x, mBufferRect.width); - WrapRotationAxis(&newRotation.y, mBufferRect.height); - NS_ASSERTION(nsIntRect(nsIntPoint(0,0), mBufferRect.Size()).Contains(newRotation), - "newRotation out of bounds"); - int32_t xBoundary = destBufferRect.XMost() - newRotation.x; - int32_t yBoundary = destBufferRect.YMost() - newRotation.y; - if ((drawBounds.x < xBoundary && xBoundary < drawBounds.XMost()) || - (drawBounds.y < yBoundary && yBoundary < drawBounds.YMost()) || - (newRotation != nsIntPoint(0,0) && !canHaveRotation)) { - // The stuff we need to redraw will wrap around an edge of the - // buffer, so we will need to do a self-copy - // If mBufferRotation == nsIntPoint(0,0) we could do a real - // self-copy but we're not going to do that in GL yet. - // We can't do a real self-copy because the buffer is rotated. - // So allocate a new buffer for the destination. - destBufferRect = neededRegion.GetBounds(); - destBuffer = CreateClampOrRepeatTextureImage(gl(), destBufferRect.Size(), contentType, bufferFlags); - if (!destBuffer) - return result; - if (mode == Layer::SURFACE_COMPONENT_ALPHA) { - destBufferOnWhite = - CreateClampOrRepeatTextureImage(gl(), destBufferRect.Size(), contentType, bufferFlags); - if (!destBufferOnWhite) - return result; - } - } else { - mBufferRect = destBufferRect; - mBufferRotation = newRotation; - } - } else { - // No pixels are going to be kept. The whole visible region - // will be redrawn, so we don't need to copy anything, so we don't - // set destBuffer. - mBufferRect = destBufferRect; - mBufferRotation = nsIntPoint(0,0); - } - } else { - // The buffer's not big enough, so allocate a new one - destBuffer = CreateClampOrRepeatTextureImage(gl(), destBufferRect.Size(), contentType, bufferFlags); - if (!destBuffer) - return result; - - if (mode == Layer::SURFACE_COMPONENT_ALPHA) { - destBufferOnWhite = - CreateClampOrRepeatTextureImage(gl(), destBufferRect.Size(), contentType, bufferFlags); - if (!destBufferOnWhite) - return result; - } - } - NS_ASSERTION(!(aFlags & PAINT_WILL_RESAMPLE) || destBufferRect == neededRegion.GetBounds(), - "If we're resampling, we need to validate the entire buffer"); - - if (!destBuffer && !mTexImage) { - return result; - } - - if (destBuffer) { - if (mTexImage && (mode != Layer::SURFACE_COMPONENT_ALPHA || mTexImageOnWhite)) { - // BlitTextureImage depends on the FBO texture target being - // TEXTURE_2D. This isn't the case on some older X1600-era Radeons. - if (mOGLLayer->OGLManager()->FBOTextureTarget() == LOCAL_GL_TEXTURE_2D) { - nsIntRect overlap; - - // The buffer looks like: - // ______ - // |1 |2 | Where the center point is offset by mBufferRotation from the top-left corner. - // |___|__| - // |3 |4 | - // |___|__| - // - // This is drawn to the screen as: - // ______ - // |4 |3 | Where the center point is { width - mBufferRotation.x, height - mBufferRotation.y } from - // |___|__| from the top left corner - rotationPoint. - // |2 |1 | - // |___|__| - // - - // The basic idea below is to take all quadrant rectangles from the src and transform them into rectangles - // in the destination. Unfortunately, it seems it is overly complex and could perhaps be simplified. - - nsIntRect srcBufferSpaceBottomRight(mBufferRotation.x, mBufferRotation.y, mBufferRect.width - mBufferRotation.x, mBufferRect.height - mBufferRotation.y); - nsIntRect srcBufferSpaceTopRight(mBufferRotation.x, 0, mBufferRect.width - mBufferRotation.x, mBufferRotation.y); - nsIntRect srcBufferSpaceTopLeft(0, 0, mBufferRotation.x, mBufferRotation.y); - nsIntRect srcBufferSpaceBottomLeft(0, mBufferRotation.y, mBufferRotation.x, mBufferRect.height - mBufferRotation.y); - - overlap.IntersectRect(mBufferRect, destBufferRect); - - nsIntRect srcRect(overlap), dstRect(overlap); - srcRect.MoveBy(- mBufferRect.TopLeft() + mBufferRotation); - - nsIntRect srcRectDrawTopRight(srcRect); - nsIntRect srcRectDrawTopLeft(srcRect); - nsIntRect srcRectDrawBottomLeft(srcRect); - // transform into the different quadrants - srcRectDrawTopRight .MoveBy(-nsIntPoint(0, mBufferRect.height)); - srcRectDrawTopLeft .MoveBy(-nsIntPoint(mBufferRect.width, mBufferRect.height)); - srcRectDrawBottomLeft.MoveBy(-nsIntPoint(mBufferRect.width, 0)); - - // Intersect with the quadrant - srcRect = srcRect .Intersect(srcBufferSpaceBottomRight); - srcRectDrawTopRight = srcRectDrawTopRight .Intersect(srcBufferSpaceTopRight); - srcRectDrawTopLeft = srcRectDrawTopLeft .Intersect(srcBufferSpaceTopLeft); - srcRectDrawBottomLeft = srcRectDrawBottomLeft.Intersect(srcBufferSpaceBottomLeft); - - dstRect = srcRect; - nsIntRect dstRectDrawTopRight(srcRectDrawTopRight); - nsIntRect dstRectDrawTopLeft(srcRectDrawTopLeft); - nsIntRect dstRectDrawBottomLeft(srcRectDrawBottomLeft); - - // transform back to src buffer space - dstRect .MoveBy(-mBufferRotation); - dstRectDrawTopRight .MoveBy(-mBufferRotation + nsIntPoint(0, mBufferRect.height)); - dstRectDrawTopLeft .MoveBy(-mBufferRotation + nsIntPoint(mBufferRect.width, mBufferRect.height)); - dstRectDrawBottomLeft.MoveBy(-mBufferRotation + nsIntPoint(mBufferRect.width, 0)); - - // transform back to draw coordinates - dstRect .MoveBy(mBufferRect.TopLeft()); - dstRectDrawTopRight .MoveBy(mBufferRect.TopLeft()); - dstRectDrawTopLeft .MoveBy(mBufferRect.TopLeft()); - dstRectDrawBottomLeft.MoveBy(mBufferRect.TopLeft()); - - // transform to destBuffer space - dstRect .MoveBy(-destBufferRect.TopLeft()); - dstRectDrawTopRight .MoveBy(-destBufferRect.TopLeft()); - dstRectDrawTopLeft .MoveBy(-destBufferRect.TopLeft()); - dstRectDrawBottomLeft.MoveBy(-destBufferRect.TopLeft()); - - destBuffer->Resize(destBufferRect.Size()); - - gl()->BlitTextureImage(mTexImage, srcRect, - destBuffer, dstRect); - if (mBufferRotation != nsIntPoint(0, 0)) { - // Draw the remaining quadrants. We call BlitTextureImage 3 extra - // times instead of doing a single draw call because supporting that - // with a tiled source is quite tricky. - - if (!srcRectDrawTopRight.IsEmpty()) - gl()->BlitTextureImage(mTexImage, srcRectDrawTopRight, - destBuffer, dstRectDrawTopRight); - if (!srcRectDrawTopLeft.IsEmpty()) - gl()->BlitTextureImage(mTexImage, srcRectDrawTopLeft, - destBuffer, dstRectDrawTopLeft); - if (!srcRectDrawBottomLeft.IsEmpty()) - gl()->BlitTextureImage(mTexImage, srcRectDrawBottomLeft, - destBuffer, dstRectDrawBottomLeft); - } - destBuffer->MarkValid(); - - if (mode == Layer::SURFACE_COMPONENT_ALPHA) { - destBufferOnWhite->Resize(destBufferRect.Size()); - gl()->BlitTextureImage(mTexImageOnWhite, srcRect, - destBufferOnWhite, dstRect); - if (mBufferRotation != nsIntPoint(0, 0)) { - // draw the remaining quadrants - if (!srcRectDrawTopRight.IsEmpty()) - gl()->BlitTextureImage(mTexImageOnWhite, srcRectDrawTopRight, - destBufferOnWhite, dstRectDrawTopRight); - if (!srcRectDrawTopLeft.IsEmpty()) - gl()->BlitTextureImage(mTexImageOnWhite, srcRectDrawTopLeft, - destBufferOnWhite, dstRectDrawTopLeft); - if (!srcRectDrawBottomLeft.IsEmpty()) - gl()->BlitTextureImage(mTexImageOnWhite, srcRectDrawBottomLeft, - destBufferOnWhite, dstRectDrawBottomLeft); - } - destBufferOnWhite->MarkValid(); - } - } else { - // can't blit, just draw everything - destBuffer = CreateClampOrRepeatTextureImage(gl(), destBufferRect.Size(), contentType, bufferFlags); - if (mode == Layer::SURFACE_COMPONENT_ALPHA) { - destBufferOnWhite = - CreateClampOrRepeatTextureImage(gl(), destBufferRect.Size(), contentType, bufferFlags); - } - } - } - - mTexImage = destBuffer.forget(); - if (mode == Layer::SURFACE_COMPONENT_ALPHA) { - mTexImageOnWhite = destBufferOnWhite.forget(); - } - mBufferRect = destBufferRect; - mBufferRotation = nsIntPoint(0,0); - } - NS_ASSERTION(canHaveRotation || mBufferRotation == nsIntPoint(0,0), - "Rotation disabled, but we have nonzero rotation?"); - - nsIntRegion invalidate; - invalidate.Sub(mLayer->GetValidRegion(), destBufferRect); - result.mRegionToInvalidate.Or(result.mRegionToInvalidate, invalidate); - - // Figure out which quadrant to draw in - int32_t xBoundary = mBufferRect.XMost() - mBufferRotation.x; - int32_t yBoundary = mBufferRect.YMost() - mBufferRotation.y; - XSide sideX = drawBounds.XMost() <= xBoundary ? RIGHT : LEFT; - YSide sideY = drawBounds.YMost() <= yBoundary ? BOTTOM : TOP; - nsIntRect quadrantRect = GetQuadrantRectangle(sideX, sideY); - NS_ASSERTION(quadrantRect.Contains(drawBounds), "Messed up quadrants"); - - nsIntPoint offset = -nsIntPoint(quadrantRect.x, quadrantRect.y); - - // Make the region to draw relative to the buffer, before - // passing to BeginUpdate. - result.mRegionToDraw.MoveBy(offset); - // BeginUpdate is allowed to modify the given region, - // if it wants more to be repainted than we request. - if (mode == Layer::SURFACE_COMPONENT_ALPHA) { - nsIntRegion drawRegionCopy = result.mRegionToDraw; - gfxASurface *onBlack = mTexImage->BeginUpdate(drawRegionCopy); - gfxASurface *onWhite = mTexImageOnWhite->BeginUpdate(result.mRegionToDraw); - if (onBlack && onWhite) { - NS_ASSERTION(result.mRegionToDraw == drawRegionCopy, - "BeginUpdate should always modify the draw region in the same way!"); - FillSurface(onBlack, result.mRegionToDraw, nsIntPoint(0,0), gfxRGBA(0.0, 0.0, 0.0, 1.0)); - FillSurface(onWhite, result.mRegionToDraw, nsIntPoint(0,0), gfxRGBA(1.0, 1.0, 1.0, 1.0)); - if (gfxPlatform::GetPlatform()->SupportsAzureContentForType(BACKEND_COREGRAPHICS)) { - RefPtr onBlackDT = gfxPlatform::GetPlatform()->CreateDrawTargetForUpdateSurface(onBlack, onBlack->GetSize()); - RefPtr onWhiteDT = gfxPlatform::GetPlatform()->CreateDrawTargetForUpdateSurface(onWhite, onWhite->GetSize()); - RefPtr dt = Factory::CreateDualDrawTarget(onBlackDT, onWhiteDT); - result.mContext = new gfxContext(dt); - result.mContext->Translate(onBlack->GetDeviceOffset()); - } else { - gfxASurface* surfaces[2] = { onBlack, onWhite }; - nsRefPtr surf = new gfxTeeSurface(surfaces, ArrayLength(surfaces)); - - // XXX If the device offset is set on the individual surfaces instead of on - // the tee surface, we render in the wrong place. Why? - gfxPoint deviceOffset = onBlack->GetDeviceOffset(); - onBlack->SetDeviceOffset(gfxPoint(0, 0)); - onWhite->SetDeviceOffset(gfxPoint(0, 0)); - surf->SetDeviceOffset(deviceOffset); - - // Using this surface as a source will likely go horribly wrong, since - // only the onBlack surface will really be used, so alpha information will - // be incorrect. - surf->SetAllowUseAsSource(false); - result.mContext = new gfxContext(surf); - } - } else { - result.mContext = nullptr; - } - } else { - nsRefPtr surf = mTexImage->BeginUpdate(result.mRegionToDraw); - if (gfxPlatform::GetPlatform()->SupportsAzureContentForType(BACKEND_COREGRAPHICS)) { - RefPtr dt = gfxPlatform::GetPlatform()->CreateDrawTargetForUpdateSurface(surf, surf->GetSize()); - result.mContext = new gfxContext(dt); - result.mContext->Translate(surf->GetDeviceOffset()); - } else { - result.mContext = new gfxContext(surf); - } - } - if (!result.mContext) { - NS_WARNING("unable to get context for update"); - return result; - } - result.mContext->Translate(-gfxPoint(quadrantRect.x, quadrantRect.y)); - // Move rgnToPaint back into position so that the thebes callback - // gets the right coordintes. - result.mRegionToDraw.MoveBy(-offset); - - // If we do partial updates, we have to clip drawing to the regionToDraw. - // If we don't clip, background images will be fillrect'd to the region correctly, - // while text or lines will paint outside of the regionToDraw. This becomes apparent - // with concave regions. Right now the scrollbars invalidate a narrow strip of the bar - // although they never cover it. This leads to two draw rects, the narow strip and the actually - // newly exposed area. It would be wise to fix this glitch in any way to have simpler - // clip and draw regions. - result.mClip = CLIP_DRAW; - - if (mTexImage->GetContentType() == GFX_CONTENT_COLOR_ALPHA) { - result.mContext->Save(); - gfxUtils::ClipToRegion(result.mContext, result.mRegionToDraw); - result.mContext->SetOperator(gfxContext::OPERATOR_CLEAR); - result.mContext->Paint(); - result.mContext->Restore(); - } - - return result; -} - -ThebesLayerOGL::ThebesLayerOGL(LayerManagerOGL* aManager) - : ThebesLayer(aManager, nullptr) - , LayerOGL(aManager) - , mBuffer(nullptr) -{ - mImplData = static_cast(this); -} - -ThebesLayerOGL::~ThebesLayerOGL() -{ - Destroy(); -} - -void -ThebesLayerOGL::Destroy() -{ - if (!mDestroyed) { - mBuffer = nullptr; - mDestroyed = true; - } -} - -bool -ThebesLayerOGL::CreateSurface() -{ - NS_ASSERTION(!mBuffer, "buffer already created?"); - - if (mVisibleRegion.IsEmpty()) { - return false; - } - - if (gl()->TextureImageSupportsGetBackingSurface()) { - // use the ThebesLayerBuffer fast-path - mBuffer = new SurfaceBufferOGL(this); - } else { - mBuffer = new BasicBufferOGL(this); - } - return true; -} - -void -ThebesLayerOGL::SetVisibleRegion(const nsIntRegion &aRegion) -{ - if (aRegion.IsEqual(mVisibleRegion)) - return; - ThebesLayer::SetVisibleRegion(aRegion); -} - -void -ThebesLayerOGL::InvalidateRegion(const nsIntRegion &aRegion) -{ - mInvalidRegion.Or(mInvalidRegion, aRegion); - mInvalidRegion.SimplifyOutward(10); - mValidRegion.Sub(mValidRegion, mInvalidRegion); -} - -void -ThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer, - const nsIntPoint& aOffset) -{ - if (!mBuffer && !CreateSurface()) { - return; - } - NS_ABORT_IF_FALSE(mBuffer, "should have a buffer here"); - - mOGLManager->MakeCurrent(); - gl()->fActiveTexture(LOCAL_GL_TEXTURE0); - - TextureImage::ContentType contentType = - CanUseOpaqueSurface() ? GFX_CONTENT_COLOR : - GFX_CONTENT_COLOR_ALPHA; - - uint32_t flags = 0; -#ifndef MOZ_GFX_OPTIMIZE_MOBILE - if (MayResample()) { - flags |= ThebesLayerBufferOGL::PAINT_WILL_RESAMPLE; - } -#endif - - Buffer::PaintState state = mBuffer->BeginPaint(contentType, flags); - mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate); - - if (state.mContext) { - state.mRegionToInvalidate.And(state.mRegionToInvalidate, mVisibleRegion); - - LayerManager::DrawThebesLayerCallback callback = - mOGLManager->GetThebesLayerCallback(); - if (!callback) { - NS_ERROR("GL should never need to update ThebesLayers in an empty transaction"); - } else { - void* callbackData = mOGLManager->GetThebesLayerCallbackData(); - SetAntialiasingFlags(this, state.mContext); - callback(this, state.mContext, state.mRegionToDraw, state.mClip, - state.mRegionToInvalidate, callbackData); - // Everything that's visible has been validated. Do this instead of just - // OR-ing with aRegionToDraw, since that can lead to a very complex region - // here (OR doesn't automatically simplify to the simplest possible - // representation of a region.) - nsIntRegion tmp; - tmp.Or(mVisibleRegion, state.mRegionToDraw); - mValidRegion.Or(mValidRegion, tmp); - } - } - - if (mOGLManager->CompositingDisabled()) { - mBuffer->EndUpdate(); - return; - } - - // Drawing thebes layers can change the current context, reset it. - gl()->MakeCurrent(); - - gl()->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aPreviousFrameBuffer); - mBuffer->RenderTo(aOffset, mOGLManager, flags); -} - -Layer* -ThebesLayerOGL::GetLayer() -{ - return this; -} - -bool -ThebesLayerOGL::IsEmpty() -{ - return !mBuffer; -} - -void -ThebesLayerOGL::CleanupResources() -{ - mBuffer = nullptr; -} - -} // layers -} // mozilla diff --git a/gfx/layers/opengl/ThebesLayerOGL.h b/gfx/layers/opengl/ThebesLayerOGL.h deleted file mode 100644 index 4656ccf1e04..00000000000 --- a/gfx/layers/opengl/ThebesLayerOGL.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef GFX_THEBESLAYEROGL_H -#define GFX_THEBESLAYEROGL_H - -#include "LayerManagerOGL.h" // for LayerOGL -#include "Layers.h" // for Layer (ptr only), etc -#include "nsAutoPtr.h" // for nsRefPtr -#include "nsISupportsImpl.h" -#include "nsRegion.h" // for nsIntRegion - -namespace mozilla { -namespace layers { - -class ThebesLayerBufferOGL; -class BasicBufferOGL; - -class ThebesLayerOGL : public ThebesLayer, - public LayerOGL -{ - typedef ThebesLayerBufferOGL Buffer; - -public: - ThebesLayerOGL(LayerManagerOGL *aManager); - virtual ~ThebesLayerOGL(); - - /** Layer implementation */ - void SetVisibleRegion(const nsIntRegion& aRegion); - - /** ThebesLayer implementation */ - void InvalidateRegion(const nsIntRegion& aRegion); - - /** LayerOGL implementation */ - void Destroy(); - Layer* GetLayer(); - virtual bool IsEmpty(); - virtual void RenderLayer(int aPreviousFrameBuffer, - const nsIntPoint& aOffset); - virtual void CleanupResources(); - -private: - friend class BasicBufferOGL; - - bool CreateSurface(); - - nsRefPtr mBuffer; -}; - - -} /* layers */ -} /* mozilla */ -#endif /* GFX_THEBESLAYEROGL_H */ diff --git a/layout/ipc/RenderFrameParent.cpp b/layout/ipc/RenderFrameParent.cpp index d96348ad5fd..c1c9d6dbb3e 100644 --- a/layout/ipc/RenderFrameParent.cpp +++ b/layout/ipc/RenderFrameParent.cpp @@ -9,7 +9,6 @@ #include "BasicLayers.h" #include "gfx3DMatrix.h" -#include "LayerManagerOGL.h" #ifdef MOZ_ENABLE_D3D9_LAYER # include "LayerManagerD3D9.h" #endif //MOZ_ENABLE_D3D9_LAYER diff --git a/widget/android/nsWindow.cpp b/widget/android/nsWindow.cpp index a078bf1dd66..ae33928593f 100644 --- a/widget/android/nsWindow.cpp +++ b/widget/android/nsWindow.cpp @@ -42,7 +42,6 @@ using mozilla::unused; #include "gfxContext.h" #include "Layers.h" -#include "LayerManagerOGL.h" #include "mozilla/layers/LayerManagerComposite.h" #include "mozilla/layers/AsyncCompositionManager.h" #include "mozilla/layers/APZCTreeManager.h" @@ -1002,15 +1001,6 @@ nsWindow::DrawTo(gfxASurface *targetSurface, const nsIntRect &invalidRect) break; } - case mozilla::layers::LAYERS_OPENGL: { - - static_cast(GetLayerManager(nullptr))-> - SetClippingRegion(nsIntRegion(boundsRect)); - - mWidgetListener->PaintWindow(this, region); - break; - } - default: NS_ERROR("Invalid layer manager"); } diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm index e0d2eefa1df..e83dad38170 100644 --- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -56,7 +56,6 @@ #include "gfxUtils.h" #include "nsRegion.h" #include "Layers.h" -#include "LayerManagerOGL.h" #include "ClientLayerManager.h" #include "mozilla/layers/LayerManagerComposite.h" #include "GLTextureImage.h" @@ -3521,17 +3520,6 @@ NSEvent* gLastDragMouseDownEvent = nil; mGeckoChild->GetBounds(geckoBounds); nsIntRegion region(geckoBounds); - if ([self isUsingMainThreadOpenGL]) { - LayerManagerOGL *manager = static_cast(mGeckoChild->GetLayerManager(nullptr)); - manager->SetClippingRegion(region); - NSOpenGLContext *glContext = (NSOpenGLContext *)manager->GetNSOpenGLContext(); - - if (!mGLContext) { - [self setGLContext:glContext]; - [self updateGLContext]; - } - } - mGeckoChild->PaintWindow(region); // Force OpenGL to refresh the very first time we draw. This works around a diff --git a/widget/gonk/nsWindow.cpp b/widget/gonk/nsWindow.cpp index 3720d06f6f9..90daf123f3e 100644 --- a/widget/gonk/nsWindow.cpp +++ b/widget/gonk/nsWindow.cpp @@ -30,7 +30,6 @@ #include "gfxUtils.h" #include "GLContextProvider.h" #include "GLContext.h" -#include "LayerManagerOGL.h" #include "nsAutoPtr.h" #include "nsAppShell.h" #include "nsIdleService.h" @@ -46,7 +45,7 @@ #include "mozilla/BasicEvents.h" #include "mozilla/layers/CompositorParent.h" #include "ParentProcessController.h" - +#include "nsThreadUtils.h" #include "HwcComposer2D.h" #define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args) @@ -213,16 +212,7 @@ nsWindow::DoDraw(void) } LayerManager* lm = gWindowToRedraw->GetLayerManager(); - if (mozilla::layers::LAYERS_OPENGL == lm->GetBackendType()) { - LayerManagerOGL* oglm = static_cast(lm); - oglm->SetClippingRegion(region); - oglm->SetWorldTransform(sRotationMatrix); - - listener = gWindowToRedraw->GetWidgetListener(); - if (listener) { - listener->PaintWindow(gWindowToRedraw, region); - } - } else if (mozilla::layers::LAYERS_CLIENT == lm->GetBackendType()) { + if (mozilla::layers::LAYERS_CLIENT == lm->GetBackendType()) { // No need to do anything, the compositor will handle drawing } else if (mozilla::layers::LAYERS_BASIC == lm->GetBackendType()) { MOZ_ASSERT(sFramebufferOpen || sUsingOMTC); @@ -606,18 +596,6 @@ nsWindow::GetLayerManager(PLayerTransactionChild* aShadowManager, } MOZ_ASSERT(fbBounds.value == gScreenBounds); - if (sGLContext) { - nsRefPtr layerManager = new LayerManagerOGL(this); - - if (layerManager->Initialize(sGLContext)) { - mLayerManager = layerManager; - return mLayerManager; - } else { - LOGW("Could not create OGL LayerManager"); - } - } else { - LOGW("GL context was not created"); - } } // Fall back to software rendering. diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp index 57c0f512125..040a248fb47 100644 --- a/widget/gtk/nsWindow.cpp +++ b/widget/gtk/nsWindow.cpp @@ -106,7 +106,6 @@ extern "C" { #include "gfxImageSurface.h" #include "gfxUtils.h" #include "Layers.h" -#include "LayerManagerOGL.h" #include "GLContextProvider.h" #include "mozilla/gfx/2D.h" #include "mozilla/layers/CompositorParent.h" @@ -127,7 +126,6 @@ using namespace mozilla::gfx; using namespace mozilla::widget; using namespace mozilla::layers; using mozilla::gl::GLContext; -using mozilla::layers::LayerManagerOGL; // Don't put more than this many rects in the dirty region, just fluff // out to the bounding-box if there are more @@ -602,17 +600,7 @@ nsWindow::Destroy(void) /** Need to clean our LayerManager up while still alive */ if (mLayerManager) { - nsRefPtr gl = nullptr; - if (mLayerManager->GetBackendType() == mozilla::layers::LAYERS_OPENGL) { - LayerManagerOGL *ogllm = static_cast(mLayerManager.get()); - gl = ogllm->gl(); - } - mLayerManager->Destroy(); - - if (gl) { - gl->MarkDestroyed(); - } } mLayerManager = nullptr; @@ -2143,13 +2131,6 @@ nsWindow::OnExposeEvent(cairo_t *cr) // If this widget uses OMTC... if (GetLayerManager()->GetBackendType() == LAYERS_CLIENT) { - listener->PaintWindow(this, region); - listener->DidPaintWindow(); - return TRUE; - } else if (GetLayerManager()->GetBackendType() == mozilla::layers::LAYERS_OPENGL) { - LayerManagerOGL *manager = static_cast(GetLayerManager()); - manager->SetClippingRegion(region); - listener->PaintWindow(this, region); listener->DidPaintWindow(); return TRUE; diff --git a/widget/qt/nsWindow.cpp b/widget/qt/nsWindow.cpp index 12585eaf0ab..655de8a5523 100644 --- a/widget/qt/nsWindow.cpp +++ b/widget/qt/nsWindow.cpp @@ -99,7 +99,6 @@ using namespace QtMobility; #include "gfxUtils.h" #include "Layers.h" #include "GLContextProvider.h" -#include "LayerManagerOGL.h" #include "nsFastStartupQt.h" // If embedding clients want to create widget without real parent window @@ -115,7 +114,6 @@ extern "C" { using namespace mozilla; using namespace mozilla::widget; using mozilla::gl::GLContext; -using mozilla::layers::LayerManagerOGL; // Cached offscreen surface static nsRefPtr gBufferSurface; @@ -370,17 +368,7 @@ nsWindow::Destroy(void) /** Need to clean our LayerManager up while still alive */ if (mLayerManager) { - nsRefPtr gl = nullptr; - if (mLayerManager->GetBackendType() == mozilla::layers::LAYERS_OPENGL) { - LayerManagerOGL *ogllm = static_cast(mLayerManager.get()); - gl = ogllm->gl(); - } - mLayerManager->Destroy(); - - if (gl) { - gl->MarkDestroyed(); - } } mLayerManager = nullptr; @@ -1041,30 +1029,6 @@ nsWindow::DoPaint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption, Q startup->RemoveFakeLayout(); } - if (GetLayerManager(nullptr)->GetBackendType() == mozilla::layers::LAYERS_OPENGL) { - aPainter->beginNativePainting(); - nsIntRegion region(rect); - static_cast(GetLayerManager(nullptr))-> - SetClippingRegion(region); - - gfxMatrix matr; - matr.Translate(gfxPoint(aPainter->transform().dx(), aPainter->transform().dy())); -#ifdef MOZ_ENABLE_QTMOBILITY - // This is needed for rotate transformation on MeeGo - // This will work very slow if pixman does not handle rotation very well - matr.Rotate((M_PI/180) * gOrientationFilter.GetWindowRotationAngle()); - static_cast(GetLayerManager(nullptr))-> - SetWorldTransform(matr); -#endif //MOZ_ENABLE_QTMOBILITY - - if (mWidgetListener) - painted = mWidgetListener->PaintWindow(this, region); - aPainter->endNativePainting(); - if (mWidgetListener) - mWidgetListener->DidPaintWindow(); - return painted; - } - gfxQtPlatform::RenderMode renderMode = gfxQtPlatform::GetPlatform()->GetRenderMode(); int depth = aPainter->device()->depth(); diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp index 80717ff2be3..6247e5cdfff 100644 --- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -135,7 +135,6 @@ #include "LayerManagerD3D10.h" #endif -#include "LayerManagerOGL.h" #include "nsIGfxInfo.h" #include "nsUXThemeConstants.h" #include "KeyboardLayout.h" @@ -3314,25 +3313,6 @@ nsWindow::GetLayerManager(PLayerTransactionChild* aShadowManager, } } #endif - if (!mLayerManager && prefs.mPreferOpenGL) { - nsCOMPtr gfxInfo = do_GetService("@mozilla.org/gfx/info;1"); - int32_t status = nsIGfxInfo::FEATURE_NO_INFO; - - if (gfxInfo && !prefs.mForceAcceleration) { - gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_OPENGL_LAYERS, &status); - } - - if (status == nsIGfxInfo::FEATURE_NO_INFO) { - nsRefPtr layerManager = - new LayerManagerOGL(this); - if (layerManager->Initialize()) { - mLayerManager = layerManager; - } - - } else { - NS_WARNING("OpenGL accelerated layers are not supported on this system."); - } - } } // Fall back to software if we couldn't use any hardware backends. diff --git a/widget/windows/nsWindowGfx.cpp b/widget/windows/nsWindowGfx.cpp index c1fe476dbb8..bec8f6d5b1b 100644 --- a/widget/windows/nsWindowGfx.cpp +++ b/widget/windows/nsWindowGfx.cpp @@ -37,7 +37,6 @@ using mozilla::plugins::PluginInstanceParent; #include "nsIWidgetListener.h" #include "mozilla/unused.h" -#include "LayerManagerOGL.h" #ifdef MOZ_ENABLE_D3D9_LAYER #include "LayerManagerD3D9.h" #endif @@ -551,11 +550,6 @@ bool nsWindow::OnPaint(HDC aDC, uint32_t aNestingLevel) } } break; - case LAYERS_OPENGL: - static_cast(GetLayerManager())-> - SetClippingRegion(region); - result = listener->PaintWindow(this, region); - break; #ifdef MOZ_ENABLE_D3D9_LAYER case LAYERS_D3D9: { diff --git a/widget/xpwidgets/nsBaseWidget.cpp b/widget/xpwidgets/nsBaseWidget.cpp index 2431113ce70..5dcdd09a061 100644 --- a/widget/xpwidgets/nsBaseWidget.cpp +++ b/widget/xpwidgets/nsBaseWidget.cpp @@ -23,7 +23,6 @@ #include "mozilla/Preferences.h" #include "BasicLayers.h" #include "ClientLayerManager.h" -#include "LayerManagerOGL.h" #include "mozilla/layers/Compositor.h" #include "nsIXULRuntime.h" #include "nsIXULWindow.h" @@ -41,6 +40,7 @@ #include "gfxPlatform.h" #include "mozilla/gfx/2D.h" #include "mozilla/MouseEvents.h" +#include "GLConsts.h" #ifdef ACCESSIBILITY #include "nsAccessibilityService.h" @@ -1014,22 +1014,6 @@ LayerManager* nsBaseWidget::GetLayerManager(PLayerTransactionChild* aShadowManag CreateCompositor(); } - if (mUseLayersAcceleration) { - if (!mLayerManager) { - nsRefPtr layerManager = new LayerManagerOGL(this); - /** - * XXX - On several OSes initialization is expected to fail for now. - * If we'd get a non-basic layer manager they'd crash. This is ok though - * since on those platforms it will fail. Anyone implementing new - * platforms on LayerManagerOGL should ensure their widget is able to - * deal with it though! - */ - - if (layerManager->Initialize(mForceLayersAcceleration)) { - mLayerManager = layerManager; - } - } - } if (!mLayerManager) { mLayerManager = CreateBasicLayerManager(); } @@ -1415,13 +1399,7 @@ nsBaseWidget::BeginMoveDrag(WidgetMouseEvent* aEvent) uint32_t nsBaseWidget::GetGLFrameBufferFormat() { - if (mLayerManager && - mLayerManager->GetBackendType() == LAYERS_OPENGL) { - // Assume that the default framebuffer has RGBA format. Specific - // backends that know differently will override this method. - return LOCAL_GL_RGBA; - } - return LOCAL_GL_NONE; + return LOCAL_GL_RGBA; } void nsBaseWidget::SetSizeConstraints(const SizeConstraints& aConstraints)