Bug 739679 - Part 4: TiledLayerBufferOGL. r=mwoodrow,roc

This commit is contained in:
Benoit Girard 2012-04-16 19:04:24 -04:00
parent 9a37018a8c
commit 98ad37d209
9 changed files with 376 additions and 10 deletions

View File

@ -61,6 +61,8 @@ endif
EXPORTS = \
BasicLayers.h \
BasicTiledThebesLayer.h \
BasicImplData.h \
ImageLayers.h \
Layers.h \
LayerManagerOGL.h \
@ -83,6 +85,7 @@ CPPSRCS = \
ImageLayerOGL.cpp \
LayerManagerOGL.cpp \
ThebesLayerOGL.cpp \
TiledThebesLayerOGL.cpp \
LayerSorter.cpp \
ImageLayers.cpp \
$(NULL)

View File

@ -54,6 +54,16 @@ static void DrawDebugOverlay(gfxImageSurface* imgSurf, int x, int y)
namespace mozilla {
namespace layers {
gfxASurface::gfxImageFormat
BasicTiledLayerBuffer::GetFormat() const
{
if (mThebesLayer->CanUseOpaqueSurface()) {
return gfxASurface::ImageFormatRGB16_565;
} else {
return gfxASurface::ImageFormatARGB32;
}
}
void
BasicTiledLayerBuffer::PaintThebes(BasicTiledThebesLayer* aLayer,
const nsIntRegion& aNewValidRegion,
@ -71,7 +81,7 @@ BasicTiledLayerBuffer::PaintThebes(BasicTiledThebesLayer* aLayer,
if (UseSinglePaintBuffer()) {
SAMPLE_LABEL("BasicTiledLayerBuffer", "PaintThebesSingleBuffer");
const nsIntRect bounds = aPaintRegion.GetBounds();
mSinglePaintBuffer = new gfxImageSurface(gfxIntSize(bounds.width, bounds.height), gfxASurface::ImageFormatRGB16_565);
mSinglePaintBuffer = new gfxImageSurface(gfxIntSize(bounds.width, bounds.height), GetFormat());
mSinglePaintBufferOffset = nsIntPoint(bounds.x, bounds.y);
nsRefPtr<gfxContext> ctxt = new gfxContext(mSinglePaintBuffer);
ctxt->NewPath();
@ -122,7 +132,8 @@ BasicTiledLayerBuffer::ValidateTileInternal(BasicTiledLayerTile aTile,
const nsIntRect& aDirtyRect)
{
if (aTile == GetPlaceholderTile()) {
gfxImageSurface* tmpTile = new gfxImageSurface(gfxIntSize(GetTileLength(), GetTileLength()), gfxASurface::ImageFormatRGB16_565);
gfxImageSurface* tmpTile = new gfxImageSurface(gfxIntSize(GetTileLength(), GetTileLength()),
GetFormat());
aTile = BasicTiledLayerTile(tmpTile);
}
@ -137,11 +148,13 @@ BasicTiledLayerBuffer::ValidateTileInternal(BasicTiledLayerTile aTile,
// Bug 742100, this gfxContext really should live on the stack.
nsRefPtr<gfxContext> ctxt = new gfxContext(writableSurface);
ctxt->NewPath();
ctxt->SetOperator(gfxContext::OPERATOR_CLEAR);
ctxt->Rectangle(drawRect, true);
ctxt->Fill();
ctxt->SetOperator(gfxContext::OPERATOR_OVER);
if (!mThebesLayer->CanUseOpaqueSurface()) {
ctxt->NewPath();
ctxt->SetOperator(gfxContext::OPERATOR_CLEAR);
ctxt->Rectangle(drawRect, true);
ctxt->Fill();
ctxt->SetOperator(gfxContext::OPERATOR_OVER);
}
if (mSinglePaintBuffer) {
ctxt->NewPath();
ctxt->SetSource(mSinglePaintBuffer.get(),

View File

@ -121,6 +121,7 @@ protected:
}
private:
gfxASurface::gfxImageFormat GetFormat() const;
BasicTiledThebesLayer* mThebesLayer;
LayerManager::DrawThebesLayerCallback mCallback;
void* mCallbackData;

View File

@ -48,6 +48,7 @@
#include "ImageLayerOGL.h"
#include "ColorLayerOGL.h"
#include "CanvasLayerOGL.h"
#include "TiledThebesLayerOGL.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/Preferences.h"
@ -1264,7 +1265,11 @@ LayerManagerOGL::CreateShadowThebesLayer()
NS_WARNING("Call on destroyed layer manager");
return nsnull;
}
#ifdef FORCE_BASICTILEDTHEBESLAYER
return nsRefPtr<ShadowThebesLayer>(new TiledThebesLayerOGL(this)).forget();
#else
return nsRefPtr<ShadowThebesLayerOGL>(new ShadowThebesLayerOGL(this)).forget();
#endif
}
already_AddRefed<ShadowContainerLayer>

View File

@ -37,6 +37,7 @@
* ***** END LICENSE BLOCK ***** */
#include "mozilla/layers/PLayers.h"
#include "TiledLayerBuffer.h"
/* This must occur *after* layers/PLayers.h to avoid typedefs conflicts. */
#include "mozilla/Util.h"
@ -986,6 +987,9 @@ ShadowThebesLayerOGL::ShadowThebesLayerOGL(LayerManagerOGL *aManager)
, LayerOGL(aManager)
, mUploadTask(nsnull)
{
#ifdef FORCE_BASICTILEDTHEBESLAYER
NS_ABORT();
#endif
mImplData = static_cast<LayerOGL*>(this);
}

View File

@ -0,0 +1,197 @@
/* 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 "mozilla/layers/PLayersChild.h"
#include "TiledThebesLayerOGL.h"
#include "BasicTiledThebesLayer.h"
#include "gfxImageSurface.h"
namespace mozilla {
namespace layers {
using mozilla::gl::GLContext;
TiledLayerBufferOGL::~TiledLayerBufferOGL()
{
if (mRetainedTiles.Length() == 0)
return;
mContext->MakeCurrent();
for (size_t i = 0; i < mRetainedTiles.Length(); i++) {
if (mRetainedTiles[i] == GetPlaceholderTile())
continue;
mContext->fDeleteTextures(1, &mRetainedTiles[i].mTextureHandle);
}
}
void
TiledLayerBufferOGL::ReleaseTile(TiledTexture aTile)
{
// We've made current prior to calling TiledLayerBufferOGL::Update
if (aTile == GetPlaceholderTile())
return;
mContext->fDeleteTextures(1, &aTile.mTextureHandle);
}
void
TiledLayerBufferOGL::Upload(const BasicTiledLayerBuffer* aMainMemoryTiledBuffer,
const nsIntRegion& aNewValidRegion,
const nsIntRegion& aInvalidateRegion)
{
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
printf_stderr("Upload %i, %i, %i, %i\n", aInvalidateRegion.GetBounds().x, aInvalidateRegion.GetBounds().y, aInvalidateRegion.GetBounds().width, aInvalidateRegion.GetBounds().height);
long start = PR_IntervalNow();
#endif
mMainMemoryTiledBuffer = aMainMemoryTiledBuffer;
mContext->MakeCurrent();
Update(aNewValidRegion, aInvalidateRegion);
mMainMemoryTiledBuffer = nsnull;
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
if (PR_IntervalNow() - start > 10) {
printf_stderr("Time to upload %i\n", PR_IntervalNow() - start);
}
#endif
}
void
TiledLayerBufferOGL::GetFormatAndTileForImageFormat(gfxASurface::gfxImageFormat aFormat,
GLenum& aOutFormat,
GLenum& aOutType)
{
if (aFormat == gfxASurface::ImageFormatRGB16_565) {
aOutFormat = LOCAL_GL_RGB;
aOutType = LOCAL_GL_UNSIGNED_SHORT_5_6_5;
} else {
aOutFormat = LOCAL_GL_RGBA;
aOutType = LOCAL_GL_UNSIGNED_BYTE;
}
}
TiledTexture
TiledLayerBufferOGL::ValidateTile(TiledTexture aTile,
const nsIntPoint& aTileOrigin,
const nsIntRegion& aDirtyRect)
{
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
printf_stderr("Upload tile %i, %i\n", aTileOrigin.x, aTileOrigin.y);
long start = PR_IntervalNow();
#endif
if (aTile == GetPlaceholderTile()) {
mContext->fGenTextures(1, &aTile.mTextureHandle);
mContext->fBindTexture(LOCAL_GL_TEXTURE_2D, aTile.mTextureHandle);
mContext->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
mContext->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
mContext->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
mContext->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
} else {
mContext->fBindTexture(LOCAL_GL_TEXTURE_2D, aTile.mTextureHandle);
}
nsRefPtr<gfxReusableSurfaceWrapper> reusableSurface = mMainMemoryTiledBuffer->GetTile(aTileOrigin).mSurface.get();
GLenum format, type;
GetFormatAndTileForImageFormat(reusableSurface->Format(), format, type);
const unsigned char* buf = reusableSurface->GetReadOnlyData();
mContext->fTexImage2D(LOCAL_GL_TEXTURE_2D, 0, format,
GetTileLength(), GetTileLength(), 0,
format, type, buf);
aTile.mFormat = format;
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
if (PR_IntervalNow() - start > 1) {
printf_stderr("Tile Time to upload %i\n", PR_IntervalNow() - start);
}
#endif
return aTile;
}
TiledThebesLayerOGL::TiledThebesLayerOGL(LayerManagerOGL *aManager)
: ShadowThebesLayer(aManager, nsnull)
, LayerOGL(aManager)
, mVideoMemoryTiledBuffer(aManager->gl())
{
mImplData = static_cast<LayerOGL*>(this);
}
void
TiledThebesLayerOGL::PaintedTiledLayerBuffer(const BasicTiledLayerBuffer* mTiledBuffer)
{
mMainMemoryTiledBuffer = *mTiledBuffer;
mRegionToUpload.Or(mRegionToUpload, mMainMemoryTiledBuffer.GetLastPaintRegion());
gl()->MakeCurrent();
ProcessUploadQueue(); // TODO: Remove me; this should be unnecessary.
}
void
TiledThebesLayerOGL::ProcessUploadQueue()
{
if (mRegionToUpload.IsEmpty())
return;
mVideoMemoryTiledBuffer.Upload(&mMainMemoryTiledBuffer, mMainMemoryTiledBuffer.GetValidRegion(), mRegionToUpload);
mValidRegion = mVideoMemoryTiledBuffer.GetValidRegion();
mMainMemoryTiledBuffer.ReadUnlock();
mRegionToUpload = nsIntRegion();
}
void
TiledThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer, const nsIntPoint& aOffset)
{
gl()->MakeCurrent();
ProcessUploadQueue();
const nsIntRegion& visibleRegion = GetEffectiveVisibleRegion();
const nsIntRect visibleRect = visibleRegion.GetBounds();
unsigned int rowCount = 0;
int tileX = 0;
for (size_t x = visibleRect.x; x < visibleRect.x + visibleRect.width;) {
rowCount++;
uint16_t tileStartX = x % mVideoMemoryTiledBuffer.GetTileLength();
uint16_t w = mVideoMemoryTiledBuffer.GetTileLength() - tileStartX;
if (x + w > visibleRect.x + visibleRect.width)
w = visibleRect.x + visibleRect.width - x;
int tileY = 0;
for( size_t y = visibleRect.y; y < visibleRect.y + visibleRect.height;) {
uint16_t tileStartY = y % mVideoMemoryTiledBuffer.GetTileLength();
uint16_t h = mVideoMemoryTiledBuffer.GetTileLength() - tileStartY;
if (y + h > visibleRect.y + visibleRect.height)
h = visibleRect.y + visibleRect.height - y;
TiledTexture tileTexture = mVideoMemoryTiledBuffer.
GetTile(nsIntPoint(mVideoMemoryTiledBuffer.RoundDownToTileEdge(x),
mVideoMemoryTiledBuffer.RoundDownToTileEdge(y)));
if (tileTexture != mVideoMemoryTiledBuffer.GetPlaceholderTile()) {
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, tileTexture.mTextureHandle);
ColorTextureLayerProgram *program;
if (tileTexture.mFormat == LOCAL_GL_RGB) {
program = mOGLManager->GetRGBXLayerProgram();
} else {
program = mOGLManager->GetBGRALayerProgram();
}
program->Activate();
program->SetTextureUnit(0);
program->SetLayerOpacity(GetEffectiveOpacity());
program->SetLayerTransform(GetEffectiveTransform());
program->SetRenderOffset(aOffset);
program->SetLayerQuadRect(nsIntRect(x,y,w,h)); // screen
mOGLManager->BindAndDrawQuadWithTextureRect(program, nsIntRect(tileStartX, tileStartY, w, h), nsIntSize(mVideoMemoryTiledBuffer.GetTileLength(), mVideoMemoryTiledBuffer.GetTileLength())); // texture bounds
}
tileY++;
y += h;
}
tileX++;
x += w;
}
}
} // mozilla
} // layers

View File

@ -0,0 +1,138 @@
/* 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_TILEDTHEBESLAYEROGL_H
#define GFX_TILEDTHEBESLAYEROGL_H
#include "mozilla/layers/ShadowLayers.h"
#include "TiledLayerBuffer.h"
#include "Layers.h"
#include "LayerManagerOGL.h"
#include "BasicTiledThebesLayer.h"
#include <algorithm>
namespace mozilla {
namespace gl {
class GLContext;
}
namespace layers {
class TiledTexture {
public:
// Constructs a placeholder TiledTexture. See the comments above
// TiledLayerBuffer for more information on what this is used for;
// essentially, this is a sentinel used to represent an invalid or blank
// tile.
//
// Note that we assume that zero is not a valid GL texture handle here.
TiledTexture()
: mTextureHandle(0)
, mFormat(0)
{}
// Constructs a TiledTexture from a GL texture handle and an image format.
TiledTexture(GLuint aTextureHandle, GLenum aFormat)
: mTextureHandle(aTextureHandle)
, mFormat(aFormat)
{}
TiledTexture(const TiledTexture& o) {
mTextureHandle = o.mTextureHandle;
mFormat = o.mFormat;
}
TiledTexture& operator=(const TiledTexture& o) {
if (this == &o) return *this;
mTextureHandle = o.mTextureHandle;
mFormat = o.mFormat;
return *this;
}
bool operator== (const TiledTexture& o) const {
return mTextureHandle == o.mTextureHandle;
}
bool operator!= (const TiledTexture& o) const {
return mTextureHandle != o.mTextureHandle;
}
GLuint mTextureHandle;
GLenum mFormat;
};
class TiledLayerBufferOGL : public TiledLayerBuffer<TiledLayerBufferOGL, TiledTexture>
{
friend class TiledLayerBuffer<TiledLayerBufferOGL, TiledTexture>;
public:
TiledLayerBufferOGL(gl::GLContext* aContext)
: mContext(aContext)
{}
~TiledLayerBufferOGL();
void Upload(const BasicTiledLayerBuffer* aMainMemoryTiledBuffer,
const nsIntRegion& aNewValidRegion,
const nsIntRegion& aInvalidateRegion);
TiledTexture GetPlaceholderTile() const { return TiledTexture(); }
protected:
TiledTexture ValidateTile(TiledTexture aTile,
const nsIntPoint& aTileRect,
const nsIntRegion& dirtyRect);
void ReleaseTile(TiledTexture aTile);
void SwapTiles(TiledTexture& aTileA, TiledTexture& aTileB) {
std::swap(aTileA, aTileB);
}
private:
nsRefPtr<gl::GLContext> mContext;
const BasicTiledLayerBuffer* mMainMemoryTiledBuffer;
void GetFormatAndTileForImageFormat(gfxASurface::gfxImageFormat aFormat,
GLenum& aOutFormat,
GLenum& aOutType);
};
class TiledThebesLayerOGL : public ShadowThebesLayer,
public LayerOGL,
public TiledLayerComposer
{
public:
TiledThebesLayerOGL(LayerManagerOGL *aManager);
virtual ~TiledThebesLayerOGL()
{
mMainMemoryTiledBuffer.ReadUnlock();
}
// LayerOGL impl
void Destroy() {}
Layer* GetLayer() { return this; }
virtual void RenderLayer(int aPreviousFrameBuffer,
const nsIntPoint& aOffset);
virtual void CleanupResources() { }
// Shadow
virtual TiledLayerComposer* AsTiledLayerComposer() { return this; }
virtual void DestroyFrontBuffer() {}
void Swap(const ThebesBuffer& aNewFront, const nsIntRegion& aUpdatedRegion,
OptionalThebesBuffer* aNewBack, nsIntRegion* aNewBackValidRegion,
OptionalThebesBuffer* aReadOnlyFront, nsIntRegion* aFrontUpdatedRegion)
{
NS_ABORT_IF_FALSE(false, "Not supported");
}
void PaintedTiledLayerBuffer(const BasicTiledLayerBuffer* mTiledBuffer);
void ProcessUploadQueue();
private:
nsIntRegion mRegionToUpload;
BasicTiledLayerBuffer mMainMemoryTiledBuffer;
TiledLayerBufferOGL mVideoMemoryTiledBuffer;
};
} // layers
} // mozilla
#endif

View File

@ -9,6 +9,7 @@
gfxReusableSurfaceWrapper::gfxReusableSurfaceWrapper(gfxImageSurface* aSurface)
: mSurface(aSurface)
, mSurfaceData(aSurface->Data())
, mFormat(aSurface->Format())
, mReadCount(0)
{
MOZ_COUNT_CTOR(gfxReusableSurfaceWrapper);

View File

@ -5,6 +5,7 @@
#ifndef GFXCOWSURFACEWRAPPER
#define GFXCOWSURFACEWRAPPER
#include "gfxASurface.h"
#include "nsISupportsImpl.h"
#include "nsAutoPtr.h"
@ -43,6 +44,8 @@ public:
return mSurfaceData;
}
const gfxASurface::gfxImageFormat& Format() { return mFormat; }
/**
* Get a writable copy of the image.
* If necessary this will copy the wrapper. If there are no contention
@ -60,9 +63,10 @@ public:
private:
NS_DECL_OWNINGTHREAD
nsRefPtr<gfxImageSurface> mSurface;
const unsigned char* mSurfaceData;
PRInt32 mReadCount;
nsRefPtr<gfxImageSurface> mSurface;
const gfxASurface::gfxImageFormat mFormat;
const unsigned char* mSurfaceData;
PRInt32 mReadCount;
};
#endif // GFXCOWSURFACEWRAPPER