зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
fdc9625e88
Коммит
a459a00ba8
|
@ -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) \
|
||||
|
|
|
@ -86,6 +86,7 @@ CPPSRCS = \
|
|||
LayerManagerOGL.cpp \
|
||||
ThebesLayerOGL.cpp \
|
||||
TiledThebesLayerOGL.cpp \
|
||||
ReusableTileStoreOGL.cpp \
|
||||
LayerSorter.cpp \
|
||||
ImageLayers.cpp \
|
||||
$(NULL)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче