Bug 924403 - Send non-OMTC GL layers into oblivion. r=nrc

This commit is contained in:
Nicolas Silva 2013-11-27 11:15:17 +13:00
parent 36bdfd62ab
commit fd65e156ab
28 changed files with 8 additions and 4724 deletions

View File

@ -66,7 +66,6 @@ namespace mozilla {
namespace layers {
class ColorTextureLayerProgram;
class LayerManagerOGL;
}
}

View File

@ -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',

View File

@ -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 <OpenGL/OpenGL.h>
#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<LayerOGL*>(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<MacIOSurface> ioSurface = MacIOSurface::IOSurfaceContextGetSurface((CGContextRef)aCGIOSurfaceContext);
ioSurface->CGLTexImageIOSurface2D(static_cast<CGLContextObj>(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<gfxXlibSurface*>(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;
}

View File

@ -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<gfxASurface> mCanvasSurface;
nsRefPtr<GLContext> mGLContext;
ShaderProgramType mLayerProgram;
RefPtr<gfx::DrawTarget> mDrawTarget;
GLuint mTexture;
GLenum mTextureTarget;
bool mDelayedUpdates;
bool mIsGLAlphaPremult;
bool mNeedsYFlip;
bool mForceReadback;
GLuint mUploadTexture;
#if defined(GL_PROVIDER_GLX)
GLXPixmap mPixmap;
#endif
nsRefPtr<gfxImageSurface> mCachedTempSurface;
gfxIntSize mCachedSize;
gfxImageFormat mCachedFormat;
gfxImageSurface* GetTempSurface(const gfxIntSize& aSize,
const gfxImageFormat aFormat);
void DiscardTempSurface() {
mCachedTempSurface = nullptr;
}
};
} /* layers */
} /* mozilla */
#endif /* GFX_IMAGELAYEROGL_H */

View File

@ -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 */

View File

@ -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<LayerOGL*>(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 */

View File

@ -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;

View File

@ -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 <stdint.h> // for uint32_t
#include <algorithm> // 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<LayerOGL*>(layer->
ImplData())
: nullptr;
}
ContainerLayerOGL::ContainerLayerOGL(LayerManagerOGL *mOGLManager)
: ContainerLayer(mOGLManager, nullptr)
, LayerOGL(mOGLManager)
{
mImplData = static_cast<LayerOGL*>(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<LayerOGL*>(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<Layer*, 12> children;
SortChildrenBy3DZOrder(children);
/**
* Render this container's contents.
*/
for (uint32_t i = 0; i < children.Length(); i++) {
LayerOGL* layerToRender = static_cast<LayerOGL*>(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<gfxImageSurface> 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<LayerOGL*>(l->ImplData());
layerToRender->CleanupResources();
}
}
} /* layers */
} /* mozilla */

View File

@ -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 */

View File

@ -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<LayerManagerOGL> 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<LayerManagerOGL*>(aManager));
}
if (aManager->GetBackendType() == LAYERS_NONE) {
if (Compositor::GetBackend() == LAYERS_OPENGL) {

View File

@ -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
{

View File

@ -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 <stdint.h> // 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<GLContext> 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<GLContext> 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<GLContext> context = mContext.forget();
nsCOMPtr<nsIRunnable> 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<ImageOGLBackendData> 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<ImageContainer> 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<PlanarYCbCrImage*>(image);
if (!yuvImage->IsValid()) {
return;
}
PlanarYCbCrOGLBackendData *data =
static_cast<PlanarYCbCrOGLBackendData*>(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<PlanarYCbCrOGLBackendData*>(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<CairoImage*>(image);
if (!cairoImage->mSurface) {
return;
}
NS_ASSERTION(cairoImage->mSurface->GetContentType() != GFX_CONTENT_ALPHA,
"Image layer has alpha image");
CairoOGLBackendData *data =
static_cast<CairoOGLBackendData*>(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<CairoOGLBackendData*>(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<SharedTextureImage*>(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<ImageOGLBackendData*>(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<gfxASurface> 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<LayerOGL*>(this);
}
void
ImageLayerOGL::AllocateTexturesYCbCr(PlanarYCbCrImage *aImage)
{
if (!aImage->IsValid())
return;
nsAutoPtr<PlanarYCbCrOGLBackendData> 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<CairoOGLBackendData> 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<gfxXlibSurface*>(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<CairoImage*>(image);
if (!cairoImage->mSurface) {
return false;
}
CairoOGLBackendData *data = static_cast<CairoOGLBackendData*>(
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 */

View File

@ -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<GLContext> 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<GLTexture> 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<TextureRecycleBin> 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<TextureRecycleBin> mTextureRecycleBin;
};
struct CairoOGLBackendData : public ImageBackendData
{
CairoOGLBackendData() : mLayerProgram(RGBALayerProgramType) {}
GLTexture mTexture;
ShaderProgramType mLayerProgram;
gfxIntSize mTextureSize;
};
} /* layers */
} /* mozilla */
#endif /* GFX_IMAGELAYEROGL_H */

File diff suppressed because it is too large Load Diff

View File

@ -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 <sys/types.h> // 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 <windows.h>
#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<ThebesLayer> CreateThebesLayer();
virtual already_AddRefed<ContainerLayer> CreateContainerLayer();
virtual already_AddRefed<ImageLayer> CreateImageLayer();
virtual already_AddRefed<ColorLayer> CreateColorLayer();
virtual already_AddRefed<CanvasLayer> CreateCanvasLayer();
virtual LayersBackend GetBackendType() { return LAYERS_OPENGL; }
virtual void GetBackendName(nsAString& name) { name.AssignLiteral("OpenGL"); }
virtual already_AddRefed<gfxASurface>
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<mozilla::gfx::DrawTarget>
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<gfxContext> mTarget;
nsRefPtr<GLContext> mGLContext;
/** Our more efficient but less powerful alter ego, if one is available. */
nsRefPtr<Composer2D> mComposer2D;
already_AddRefed<mozilla::gl::GLContext> CreateContext();
/** Backbuffer */
GLuint mBackBufferFBO;
GLuint mBackBufferTexture;
nsIntSize mBackBufferSize;
/** Shader Programs */
struct ShaderProgramVariations {
ShaderProgramOGL* mVariations[NumMaskTypes];
};
nsTArray<ShaderProgramVariations> 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<FPSState> 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 */

View File

@ -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<LayerOGL*>(aMaskLayer->ImplData())
->LoadAsTexture(LOCAL_GL_TEXTURE0 + mProfile.mTextureCount - 1, &size)){
return false;
}
SetUniform(mProfile.LookupUniformLocation("uMaskTexture"),
(GLint)(mProfile.mTextureCount - 1));
gfxMatrix maskTransform;
mozilla::DebugOnly<bool> 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()
{

View File

@ -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

View File

@ -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 <stdint.h> // for uint32_t
#include <sys/types.h> // 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<TextureImage>
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<TextureImage> mTexImage;
nsRefPtr<TextureImage> 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<gfxImageSurface> 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<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) MOZ_OVERRIDE
{
NS_ASSERTION(GFX_CONTENT_ALPHA != aType,"ThebesBuffer has color");
mTexImage = CreateClampOrRepeatTextureImage(gl(), aRect.Size(), aType, aFlags);
nsRefPtr<gfxASurface> 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<gfxContext> 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<TextureImage> destBuffer;
nsRefPtr<TextureImage> 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<DrawTarget> onBlackDT = gfxPlatform::GetPlatform()->CreateDrawTargetForUpdateSurface(onBlack, onBlack->GetSize());
RefPtr<DrawTarget> onWhiteDT = gfxPlatform::GetPlatform()->CreateDrawTargetForUpdateSurface(onWhite, onWhite->GetSize());
RefPtr<DrawTarget> dt = Factory::CreateDualDrawTarget(onBlackDT, onWhiteDT);
result.mContext = new gfxContext(dt);
result.mContext->Translate(onBlack->GetDeviceOffset());
} else {
gfxASurface* surfaces[2] = { onBlack, onWhite };
nsRefPtr<gfxTeeSurface> 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<gfxASurface> surf = mTexImage->BeginUpdate(result.mRegionToDraw);
if (gfxPlatform::GetPlatform()->SupportsAzureContentForType(BACKEND_COREGRAPHICS)) {
RefPtr<DrawTarget> 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<LayerOGL*>(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

View File

@ -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<Buffer> mBuffer;
};
} /* layers */
} /* mozilla */
#endif /* GFX_THEBESLAYEROGL_H */

View File

@ -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

View File

@ -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<mozilla::layers::LayerManagerOGL*>(GetLayerManager(nullptr))->
SetClippingRegion(nsIntRegion(boundsRect));
mWidgetListener->PaintWindow(this, region);
break;
}
default:
NS_ERROR("Invalid layer manager");
}

View File

@ -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<LayerManagerOGL*>(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

View File

@ -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<LayerManagerOGL*>(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<LayerManagerOGL> 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.

View File

@ -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<GLContext> gl = nullptr;
if (mLayerManager->GetBackendType() == mozilla::layers::LAYERS_OPENGL) {
LayerManagerOGL *ogllm = static_cast<LayerManagerOGL*>(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<LayerManagerOGL*>(GetLayerManager());
manager->SetClippingRegion(region);
listener->PaintWindow(this, region);
listener->DidPaintWindow();
return TRUE;

View File

@ -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<gfxASurface> gBufferSurface;
@ -370,17 +368,7 @@ nsWindow::Destroy(void)
/** Need to clean our LayerManager up while still alive */
if (mLayerManager) {
nsRefPtr<GLContext> gl = nullptr;
if (mLayerManager->GetBackendType() == mozilla::layers::LAYERS_OPENGL) {
LayerManagerOGL *ogllm = static_cast<LayerManagerOGL*>(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<mozilla::layers::LayerManagerOGL*>(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<mozilla::layers::LayerManagerOGL*>(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();

View File

@ -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<nsIGfxInfo> 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<LayerManagerOGL> 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.

View File

@ -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<mozilla::layers::LayerManagerOGL*>(GetLayerManager())->
SetClippingRegion(region);
result = listener->PaintWindow(this, region);
break;
#ifdef MOZ_ENABLE_D3D9_LAYER
case LAYERS_D3D9:
{

View File

@ -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<LayerManagerOGL> 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)