Bug 745177 - Retain and re-use uploaded GL tiles. r=ajuma

Rather than discarding uploaded tiles once they fall outside of the valid
region, shuffle them off into a separate tile-store with all the metadata they
need to render them, and render them in the areas that our current valid
region doesn't cover in TiledThebesLayerOGL::RenderLayer.
This commit is contained in:
Chris Lord 2012-04-24 22:48:33 -04:00
parent 0e8cc7021e
commit 8000a2a211
10 changed files with 458 additions and 31 deletions

View File

@ -110,6 +110,7 @@ public:
, mViewportScrollOffset(0, 0)
, mScrollId(NULL_SCROLL_ID)
, mCSSContentSize(0, 0)
, mResolution(1, 1)
{}
// Default copy ctor and operator= are fine
@ -151,6 +152,10 @@ public:
// Consumers often want to know the size before scaling to pixels
// so we record this size as well.
gfx::Size mCSSContentSize;
// This represents the resolution at which the associated layer
// will been rendered.
gfxSize mResolution;
};
#define MOZ_LAYER_DECL_NAME(n, e) \

View File

@ -86,6 +86,7 @@ CPPSRCS = \
LayerManagerOGL.cpp \
ThebesLayerOGL.cpp \
TiledThebesLayerOGL.cpp \
ReusableTileStoreOGL.cpp \
LayerSorter.cpp \
ImageLayers.cpp \
$(NULL)

View File

@ -87,8 +87,20 @@ public:
// (x*GetTileLength(), y*GetTileLength(), GetTileLength(), GetTileLength())
Tile GetTile(int x, int y) const;
// This operates the same as GetTile(aTileOrigin), but will also replace the
// specified tile with the placeholder tile. This does not call ReleaseTile
// on the removed tile.
bool RemoveTile(const nsIntPoint& aTileOrigin, Tile& aRemovedTile);
// This operates the same as GetTile(x, y), but will also replace the
// specified tile with the placeholder tile. This does not call ReleaseTile
// on the removed tile.
bool RemoveTile(int x, int y, Tile& aRemovedTile);
uint16_t GetTileLength() const { return TILEDLAYERBUFFER_TILE_SIZE; }
unsigned int GetTileCount() const { return mRetainedTiles.Length(); }
const nsIntRegion& GetValidRegion() const { return mValidRegion; }
const nsIntRegion& GetLastPaintRegion() const { return mLastPaintRegion; }
void SetLastPaintRegion(const nsIntRegion& aLastPaintRegion) {
@ -161,6 +173,30 @@ TiledLayerBuffer<Derived, Tile>::GetTile(int x, int y) const
return mRetainedTiles.SafeElementAt(index, AsDerived().GetPlaceholderTile());
}
template<typename Derived, typename Tile> bool
TiledLayerBuffer<Derived, Tile>::RemoveTile(const nsIntPoint& aTileOrigin,
Tile& aRemovedTile)
{
int firstTileX = mValidRegion.GetBounds().x / GetTileLength();
int firstTileY = mValidRegion.GetBounds().y / GetTileLength();
return RemoveTile(aTileOrigin.x / GetTileLength() - firstTileX,
aTileOrigin.y / GetTileLength() - firstTileY,
aRemovedTile);
}
template<typename Derived, typename Tile> bool
TiledLayerBuffer<Derived, Tile>::RemoveTile(int x, int y, Tile& aRemovedTile)
{
int index = x * mRetainedHeight + y;
const Tile& tileToRemove = mRetainedTiles.SafeElementAt(index, AsDerived().GetPlaceholderTile());
if (!IsPlaceholder(tileToRemove)) {
aRemovedTile = tileToRemove;
mRetainedTiles[index] = AsDerived().GetPlaceholderTile();
return true;
}
return false;
}
template<typename Derived, typename Tile> void
TiledLayerBuffer<Derived, Tile>::Update(const nsIntRegion& aNewValidRegion,
const nsIntRegion& aPaintRegion)
@ -209,14 +245,16 @@ TiledLayerBuffer<Derived, Tile>::Update(const nsIntRegion& aNewValidRegion,
int tileY = (y - oldBufferOrigin.y) / GetTileLength();
int index = tileX * oldRetainedHeight + tileY;
NS_ABORT_IF_FALSE(!IsPlaceholder(oldRetainedTiles.
SafeElementAt(index, AsDerived().GetPlaceholderTile())),
"Expected tile");
// The tile may have been removed, skip over it in this case.
if (IsPlaceholder(oldRetainedTiles.
SafeElementAt(index, AsDerived().GetPlaceholderTile()))) {
newRetainedTiles.AppendElement(AsDerived().GetPlaceholderTile());
} else {
Tile tileWithPartialValidContent = oldRetainedTiles[index];
newRetainedTiles.AppendElement(tileWithPartialValidContent);
oldRetainedTiles[index] = AsDerived().GetPlaceholderTile();
}
Tile tileWithPartialValidContent = oldRetainedTiles[index];
newRetainedTiles.AppendElement(tileWithPartialValidContent);
oldRetainedTiles[index] = AsDerived().GetPlaceholderTile();
} else {
// This tile is either:
// 1) Outside the new valid region and will simply be an empty

View File

@ -73,6 +73,7 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
WriteParam(aMsg, aParam.mViewportScrollOffset);
WriteParam(aMsg, aParam.mDisplayPort);
WriteParam(aMsg, aParam.mScrollId);
WriteParam(aMsg, aParam.mResolution);
}
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
@ -82,7 +83,8 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
ReadParam(aMsg, aIter, &aResult->mContentSize) &&
ReadParam(aMsg, aIter, &aResult->mViewportScrollOffset) &&
ReadParam(aMsg, aIter, &aResult->mDisplayPort) &&
ReadParam(aMsg, aIter, &aResult->mScrollId));
ReadParam(aMsg, aIter, &aResult->mScrollId) &&
ReadParam(aMsg, aIter, &aResult->mResolution));
}
};

View File

@ -0,0 +1,188 @@
/* 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 "ReusableTileStoreOGL.h"
namespace mozilla {
namespace layers {
ReusableTileStoreOGL::~ReusableTileStoreOGL()
{
if (mTiles.Length() == 0)
return;
mContext->MakeCurrent();
for (int i = 0; i < mTiles.Length(); i++)
mContext->fDeleteTextures(1, &mTiles[i]->mTexture.mTextureHandle);
mTiles.Clear();
}
void
ReusableTileStoreOGL::HarvestTiles(TiledLayerBufferOGL* aVideoMemoryTiledBuffer,
const nsIntRegion& aOldValidRegion,
const nsIntRegion& aNewValidRegion,
const gfxSize& aOldResolution,
const gfxSize& aNewResolution)
{
gfxSize scaleFactor = gfxSize(aNewResolution.width / aOldResolution.width,
aNewResolution.height / aOldResolution.height);
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
printf_stderr("Seeing if there are any tiles we can reuse\n");
#endif
// Iterate over existing harvested tiles and release any that are contained
// within the new valid region.
mContext->MakeCurrent();
for (int i = 0; i < mTiles.Length();) {
ReusableTiledTextureOGL* tile = mTiles[i];
bool release = false;
if (tile->mResolution == aNewResolution) {
if (aNewValidRegion.Contains(tile->mTileRegion))
release = true;
} else {
nsIntRegion transformedTileRegion(tile->mTileRegion);
transformedTileRegion.ScaleRoundOut(tile->mResolution.width / aNewResolution.width,
tile->mResolution.height / aNewResolution.height);
if (aNewValidRegion.Contains(transformedTileRegion))
release = true;
}
if (release) {
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
nsIntRect tileBounds = tile->mTileRegion.GetBounds();
printf_stderr("Releasing obsolete reused tile at %d,%d, x%f\n",
tileBounds.x, tileBounds.y, tile->mResolution.width);
#endif
mContext->fDeleteTextures(1, &tile->mTexture.mTextureHandle);
mTiles.RemoveElementAt(i);
continue;
}
i++;
}
// Iterate over the tiles and decide which ones we're going to harvest.
// We harvest any tile that is entirely outside of the new valid region, or
// any tile that is partially outside of the valid region and whose
// resolution has changed.
// XXX Tile iteration needs to be abstracted, or have some utility functions
// to make it simpler.
uint16_t tileSize = aVideoMemoryTiledBuffer->GetTileLength();
nsIntRect validBounds = aOldValidRegion.GetBounds();
for (int x = validBounds.x; x < validBounds.XMost();) {
int w = tileSize - x % tileSize;
if (x + w > validBounds.x + validBounds.width)
w = validBounds.x + validBounds.width - x;
for (int y = validBounds.y; y < validBounds.YMost();) {
int h = tileSize - y % tileSize;
if (y + h > validBounds.y + validBounds.height)
h = validBounds.y + validBounds.height - y;
// If the new valid region doesn't contain this tile region,
// harvest the tile.
nsIntRegion tileRegion;
tileRegion.And(aOldValidRegion, nsIntRect(x, y, w, h));
nsIntRegion intersectingRegion;
bool retainTile = false;
if (aNewResolution != aOldResolution) {
// Reconcile resolution changes.
// If the resolution changes, we know the backing layer will have been
// invalidated, so retain tiles that are partially encompassed by the
// new valid area, instead of just tiles that don't intersect at all.
nsIntRegion transformedTileRegion(tileRegion);
transformedTileRegion.ScaleRoundOut(scaleFactor.width, scaleFactor.height);
if (!aNewValidRegion.Contains(transformedTileRegion))
retainTile = true;
} else if (intersectingRegion.And(tileRegion, aNewValidRegion).IsEmpty()) {
retainTile = true;
}
if (retainTile) {
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
printf_stderr("Retaining tile at %d,%d, x%f for reuse\n", x, y, aOldResolution.width);
#endif
TiledTexture removedTile;
if (aVideoMemoryTiledBuffer->RemoveTile(nsIntPoint(x, y), removedTile)) {
ReusableTiledTextureOGL* reusedTile =
new ReusableTiledTextureOGL(removedTile, tileRegion, tileSize,
aOldResolution);
mTiles.AppendElement(reusedTile);
}
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
else
printf_stderr("Failed to retain tile for reuse\n");
#endif
}
y += h;
}
x += w;
}
// Now prune our reused tile store of its oldest tiles if it gets too large.
while (mTiles.Length() > aVideoMemoryTiledBuffer->GetTileCount() * mSizeLimit) {
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
nsIntRect tileBounds = mTiles[0]->mTileRegion.GetBounds();
printf_stderr("Releasing old reused tile at %d,%d, x%f\n",
tileBounds.x, tileBounds.y, mTiles[0]->mResolution.width);
#endif
mContext->fDeleteTextures(1, &mTiles[0]->mTexture.mTextureHandle);
mTiles.RemoveElementAt(0);
}
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
printf_stderr("Retained %d tiles\n", mTiles.Length());
#endif
}
void
ReusableTileStoreOGL::DrawTiles(TiledThebesLayerOGL* aLayer,
const nsIntRegion& aValidRegion,
const gfxSize& aResolution,
const gfx3DMatrix& aTransform,
const nsIntPoint& aRenderOffset)
{
// Render old tiles to fill in gaps we haven't had the time to render yet.
for (size_t i = 0; i < mTiles.Length(); i++) {
ReusableTiledTextureOGL* tile = mTiles[i];
// Work out the scaling factor in case of resolution differences.
gfxSize scaleFactor = gfxSize(aResolution.width / tile->mResolution.width,
aResolution.height / tile->mResolution.height);
// Get the valid tile region, in the given coordinate space.
nsIntRegion transformedTileRegion(tile->mTileRegion);
if (aResolution != tile->mResolution)
transformedTileRegion.ScaleRoundOut(scaleFactor.width, scaleFactor.height);
// Skip drawing tiles that will be completely drawn over.
if (aValidRegion.Contains(transformedTileRegion))
continue;
// Reconcile the resolution difference by adjusting the transform.
gfx3DMatrix transform = aTransform;
if (aResolution != tile->mResolution)
transform.Scale(scaleFactor.width, scaleFactor.height, 1);
// XXX We should clip here to make sure we don't overlap with the valid
// region, otherwise we may end up with rendering artifacts on
// semi-transparent layers.
// Similarly, if we have multiple tiles covering the same area, we will
// end up with rendering artifacts if the aLayer isn't opaque.
nsIntRect tileRect = tile->mTileRegion.GetBounds();
uint16_t tileStartX = tileRect.x % tile->mTileSize;
uint16_t tileStartY = tileRect.y % tile->mTileSize;
nsIntRect textureRect(tileStartX, tileStartY, tileRect.width, tileRect.height);
nsIntSize textureSize(tile->mTileSize, tile->mTileSize);
aLayer->RenderTile(tile->mTexture, transform, aRenderOffset, tileRect, textureRect, textureSize);
}
}
} // mozilla
} // layers

View File

@ -0,0 +1,96 @@
/* 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_REUSABLETILESTOREOGL_H
#define GFX_REUSABLETILESTOREOGL_H
#include "TiledThebesLayerOGL.h"
#include "nsTArray.h"
#include "nsAutoPtr.h"
namespace mozilla {
namespace gl {
class GLContext;
}
namespace layers {
// A storage class for the information required to render a single tile from
// a TiledLayerBufferOGL.
class ReusableTiledTextureOGL
{
public:
ReusableTiledTextureOGL(TiledTexture aTexture,
const nsIntRegion& aTileRegion,
uint16_t aTileSize,
gfxSize aResolution)
: mTexture(aTexture)
, mTileRegion(aTileRegion)
, mTileSize(aTileSize)
, mResolution(aResolution)
{}
~ReusableTiledTextureOGL() {}
TiledTexture mTexture;
const nsIntRegion mTileRegion;
uint16_t mTileSize;
gfxSize mResolution;
};
// This class will operate on a TiledLayerBufferOGL to harvest tiles that have
// rendered content that is about to become invalid. We do this so that in the
// situation that we need to render an area of a TiledThebesLayerOGL that hasn't
// been updated quickly enough, we can still display something (and hopefully
// it'll be the same as the valid rendered content). While this may end up
// showing invalid data, it should only be momentarily.
class ReusableTileStoreOGL
{
public:
ReusableTileStoreOGL(gl::GLContext* aContext, float aSizeLimit)
: mContext(aContext)
, mSizeLimit(aSizeLimit)
{}
~ReusableTileStoreOGL();
// Harvests tiles from a TiledLayerBufferOGL that are about to become
// invalid. aOldValidRegion and aOldResolution should be the valid region
// and resolution of the data currently in aVideoMemoryTiledBuffer, and
// aNewValidRegion and aNewResolution should be the valid region and
// resolution of the data that is about to update aVideoMemoryTiledBuffer.
void HarvestTiles(TiledLayerBufferOGL* aVideoMemoryTiledBuffer,
const nsIntRegion& aOldValidRegion,
const nsIntRegion& aNewValidRegion,
const gfxSize& aOldResolution,
const gfxSize& aNewResolution);
// Draws all harvested tiles that don't intersect with the given valid region.
// Differences in resolution will be reconciled via altering the given
// transformation.
void DrawTiles(TiledThebesLayerOGL* aLayer,
const nsIntRegion& aValidRegion,
const gfxSize& aResolution,
const gfx3DMatrix& aTransform,
const nsIntPoint& aRenderOffset);
private:
// This GLContext should correspond to the one used in any TiledLayerBufferOGL
// that is passed into HarvestTiles and DrawTiles.
nsRefPtr<gl::GLContext> mContext;
// This determines the maximum number of tiles stored in this tile store,
// as a fraction of the amount of tiles stored in the TiledLayerBufferOGL
// given to HarvestTiles.
float mSizeLimit;
// This stores harvested tiles, in the order in which they were harvested.
nsTArray<nsAutoPtr<ReusableTiledTextureOGL>> mTiles;
};
} // layers
} // mozilla
#endif // GFX_REUSABLETILESTOREOGL_H

View File

@ -4,6 +4,7 @@
#include "mozilla/layers/PLayersChild.h"
#include "TiledThebesLayerOGL.h"
#include "ReusableTileStoreOGL.h"
#include "BasicTiledThebesLayer.h"
#include "gfxImageSurface.h"
@ -37,12 +38,15 @@ TiledLayerBufferOGL::ReleaseTile(TiledTexture aTile)
void
TiledLayerBufferOGL::Upload(const BasicTiledLayerBuffer* aMainMemoryTiledBuffer,
const nsIntRegion& aNewValidRegion,
const nsIntRegion& aInvalidateRegion)
const nsIntRegion& aInvalidateRegion,
const gfxSize& aResolution)
{
#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
mResolution = aResolution;
mMainMemoryTiledBuffer = aMainMemoryTiledBuffer;
mContext->MakeCurrent();
Update(aNewValidRegion, aInvalidateRegion);
@ -113,6 +117,15 @@ TiledThebesLayerOGL::TiledThebesLayerOGL(LayerManagerOGL *aManager)
, mVideoMemoryTiledBuffer(aManager->gl())
{
mImplData = static_cast<LayerOGL*>(this);
// XXX Add a pref for reusable tile store size
mReusableTileStore = new ReusableTileStoreOGL(aManager->gl(), 1);
}
TiledThebesLayerOGL::~TiledThebesLayerOGL()
{
mMainMemoryTiledBuffer.ReadUnlock();
if (mReusableTileStore)
delete mReusableTileStore;
}
void
@ -132,7 +145,29 @@ TiledThebesLayerOGL::ProcessUploadQueue()
if (mRegionToUpload.IsEmpty())
return;
mVideoMemoryTiledBuffer.Upload(&mMainMemoryTiledBuffer, mMainMemoryTiledBuffer.GetValidRegion(), mRegionToUpload);
gfxSize resolution(1, 1);
if (mReusableTileStore) {
// Work out render resolution by multiplying the resolution of our ancestors.
// Only container layers can have frame metrics, so we start off with a
// resolution of 1, 1.
// XXX For large layer trees, it would be faster to do this once from the
// root node upwards and store the value on each layer.
for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
const FrameMetrics& metrics = parent->GetFrameMetrics();
resolution.width *= metrics.mResolution.width;
resolution.height *= metrics.mResolution.height;
}
mReusableTileStore->HarvestTiles(&mVideoMemoryTiledBuffer,
mVideoMemoryTiledBuffer.GetValidRegion(),
mMainMemoryTiledBuffer.GetValidRegion(),
mVideoMemoryTiledBuffer.GetResolution(),
resolution);
}
mVideoMemoryTiledBuffer.Upload(&mMainMemoryTiledBuffer,
mMainMemoryTiledBuffer.GetValidRegion(),
mRegionToUpload, resolution);
mValidRegion = mVideoMemoryTiledBuffer.GetValidRegion();
mMainMemoryTiledBuffer.ReadUnlock();
@ -146,12 +181,46 @@ TiledThebesLayerOGL::ProcessUploadQueue()
}
void
TiledThebesLayerOGL::RenderTile(TiledTexture aTile,
const gfx3DMatrix& aTransform,
const nsIntPoint& aOffset,
nsIntRect aScreenRect,
nsIntRect aTextureRect,
nsIntSize aTextureBounds)
{
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, aTile.mTextureHandle);
ColorTextureLayerProgram *program;
if (aTile.mFormat == LOCAL_GL_RGB) {
program = mOGLManager->GetRGBXLayerProgram();
} else {
program = mOGLManager->GetBGRALayerProgram();
}
program->Activate();
program->SetTextureUnit(0);
program->SetLayerOpacity(GetEffectiveOpacity());
program->SetLayerTransform(aTransform);
program->SetRenderOffset(aOffset);
program->SetLayerQuadRect(aScreenRect);
mOGLManager->BindAndDrawQuadWithTextureRect(program,
aTextureRect,
aTextureBounds);
}
void
TiledThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer, const nsIntPoint& aOffset)
{
gl()->MakeCurrent();
ProcessUploadQueue();
// Render old tiles to fill in gaps we haven't had the time to render yet.
if (mReusableTileStore)
mReusableTileStore->DrawTiles(this, mVideoMemoryTiledBuffer.GetValidRegion(),
mVideoMemoryTiledBuffer.GetResolution(),
GetEffectiveTransform(), aOffset);
// Render valid tiles.
const nsIntRegion& visibleRegion = GetEffectiveVisibleRegion();
const nsIntRect visibleRect = visibleRegion.GetBounds();
unsigned int rowCount = 0;
@ -173,22 +242,9 @@ TiledThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer, const nsIntPoint& aOf
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
uint16_t tileSize = mVideoMemoryTiledBuffer.GetTileLength();
RenderTile(tileTexture, GetEffectiveTransform(), aOffset, nsIntRect(x,y,w,h),
nsIntRect(tileStartX, tileStartY, w, h), nsIntSize(tileSize, tileSize));
}
tileY++;
y += h;

View File

@ -20,6 +20,8 @@ class GLContext;
namespace layers {
class ReusableTileStoreOGL;
class TiledTexture {
public:
// Constructs a placeholder TiledTexture. See the comments above
@ -73,10 +75,13 @@ public:
void Upload(const BasicTiledLayerBuffer* aMainMemoryTiledBuffer,
const nsIntRegion& aNewValidRegion,
const nsIntRegion& aInvalidateRegion);
const nsIntRegion& aInvalidateRegion,
const gfxSize& aResolution);
TiledTexture GetPlaceholderTile() const { return TiledTexture(); }
const gfxSize& GetResolution() { return mResolution; }
protected:
TiledTexture ValidateTile(TiledTexture aTile,
const nsIntPoint& aTileRect,
@ -91,6 +96,7 @@ protected:
private:
nsRefPtr<gl::GLContext> mContext;
const BasicTiledLayerBuffer* mMainMemoryTiledBuffer;
gfxSize mResolution;
void GetFormatAndTileForImageFormat(gfxASurface::gfxImageFormat aFormat,
GLenum& aOutFormat,
@ -103,10 +109,7 @@ class TiledThebesLayerOGL : public ShadowThebesLayer,
{
public:
TiledThebesLayerOGL(LayerManagerOGL *aManager);
virtual ~TiledThebesLayerOGL()
{
mMainMemoryTiledBuffer.ReadUnlock();
}
virtual ~TiledThebesLayerOGL();
// LayerOGL impl
void Destroy() {}
@ -126,10 +129,22 @@ public:
}
void PaintedTiledLayerBuffer(const BasicTiledLayerBuffer* mTiledBuffer);
void ProcessUploadQueue();
// Renders a single given tile.
// XXX This currently takes an nsIntRect, but should actually take an
// nsIntRegion and iterate over each rectangle in the region.
void RenderTile(TiledTexture aTile,
const gfx3DMatrix& aTransform,
const nsIntPoint& aOffset,
nsIntRect aScreenRect,
nsIntRect aTextureRect,
nsIntSize aTextureBounds);
private:
nsIntRegion mRegionToUpload;
BasicTiledLayerBuffer mMainMemoryTiledBuffer;
TiledLayerBufferOGL mVideoMemoryTiledBuffer;
ReusableTileStoreOGL* mReusableTileStore;
};
} // layers

View File

@ -53,6 +53,7 @@
#include "gfxColor.h"
#include "gfxMatrix.h"
#include "gfxPattern.h"
#include "gfxPoint.h"
#include "nsRect.h"
#include "nsRegion.h"
#include "gfxASurface.h"
@ -458,6 +459,27 @@ struct ParamTraits<gfxMatrix>
}
};
template<>
struct ParamTraits<gfxSize>
{
typedef gfxSize paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
WriteParam(aMsg, aParam.width);
WriteParam(aMsg, aParam.height);
}
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
{
if (ReadParam(aMsg, aIter, &aResult->width) &&
ReadParam(aMsg, aIter, &aResult->height))
return true;
return false;
}
};
template<>
struct ParamTraits<gfx3DMatrix>
{

View File

@ -250,6 +250,10 @@ static void RecordFrameMetrics(nsIFrame* aForFrame,
}
metrics.mScrollId = aScrollId;
nsIPresShell* presShell = presContext->GetPresShell();
metrics.mResolution = gfxSize(presShell->GetXResolution(), presShell->GetYResolution());
aRoot->SetFrameMetrics(metrics);
}