mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 924403 - Send non-OMTC GL layers into oblivion. r=nrc
This commit is contained in:
parent
e7402a3186
commit
532313927f
@ -66,7 +66,6 @@ namespace mozilla {
|
||||
|
||||
namespace layers {
|
||||
class ColorTextureLayerProgram;
|
||||
class LayerManagerOGL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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',
|
||||
|
@ -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;
|
||||
}
|
@ -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 */
|
@ -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 */
|
@ -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 */
|
@ -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;
|
||||
|
@ -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 */
|
@ -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 */
|
@ -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) {
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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 */
|
@ -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
@ -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 */
|
@ -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()
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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 */
|
@ -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
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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:
|
||||
{
|
||||
|
@ -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,14 +1399,8 @@ 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;
|
||||
}
|
||||
|
||||
void nsBaseWidget::SetSizeConstraints(const SizeConstraints& aConstraints)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user