2012-04-16 16:04:24 -07:00
|
|
|
/* 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"
|
2012-04-24 19:48:33 -07:00
|
|
|
#include "ReusableTileStoreOGL.h"
|
2012-04-16 16:04:24 -07:00
|
|
|
#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,
|
2012-04-24 19:48:33 -07:00
|
|
|
const nsIntRegion& aInvalidateRegion,
|
|
|
|
const gfxSize& aResolution)
|
2012-04-16 16:04:24 -07:00
|
|
|
{
|
|
|
|
#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
|
2012-04-24 19:48:33 -07:00
|
|
|
|
|
|
|
mResolution = aResolution;
|
2012-04-16 16:04:24 -07:00
|
|
|
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);
|
2012-04-24 19:48:33 -07:00
|
|
|
// XXX Add a pref for reusable tile store size
|
|
|
|
mReusableTileStore = new ReusableTileStoreOGL(aManager->gl(), 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
TiledThebesLayerOGL::~TiledThebesLayerOGL()
|
|
|
|
{
|
|
|
|
mMainMemoryTiledBuffer.ReadUnlock();
|
|
|
|
if (mReusableTileStore)
|
|
|
|
delete mReusableTileStore;
|
2012-04-16 16:04:24 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
TiledThebesLayerOGL::PaintedTiledLayerBuffer(const BasicTiledLayerBuffer* mTiledBuffer)
|
|
|
|
{
|
2012-05-12 13:56:55 -07:00
|
|
|
mMainMemoryTiledBuffer.ReadUnlock();
|
2012-04-16 16:04:24 -07:00
|
|
|
mMainMemoryTiledBuffer = *mTiledBuffer;
|
2012-05-01 12:59:41 -07:00
|
|
|
// TODO: Remove me once Bug 747811 lands.
|
|
|
|
delete mTiledBuffer;
|
2012-04-16 16:04:24 -07:00
|
|
|
mRegionToUpload.Or(mRegionToUpload, mMainMemoryTiledBuffer.GetLastPaintRegion());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
TiledThebesLayerOGL::ProcessUploadQueue()
|
|
|
|
{
|
|
|
|
if (mRegionToUpload.IsEmpty())
|
|
|
|
return;
|
|
|
|
|
2012-04-24 19:48:33 -07:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2012-05-03 17:55:08 -07:00
|
|
|
mReusableTileStore->HarvestTiles(this,
|
|
|
|
&mVideoMemoryTiledBuffer,
|
2012-04-24 19:48:33 -07:00
|
|
|
mVideoMemoryTiledBuffer.GetValidRegion(),
|
|
|
|
mMainMemoryTiledBuffer.GetValidRegion(),
|
|
|
|
mVideoMemoryTiledBuffer.GetResolution(),
|
|
|
|
resolution);
|
|
|
|
}
|
|
|
|
|
2012-05-18 18:19:43 -07:00
|
|
|
// If we coalesce uploads while the layers' valid region is changing we will
|
|
|
|
// end up trying to upload area outside of the valid region. (bug 756555)
|
|
|
|
mRegionToUpload.And(mRegionToUpload, mMainMemoryTiledBuffer.GetValidRegion());
|
|
|
|
|
2012-04-24 19:48:33 -07:00
|
|
|
mVideoMemoryTiledBuffer.Upload(&mMainMemoryTiledBuffer,
|
|
|
|
mMainMemoryTiledBuffer.GetValidRegion(),
|
|
|
|
mRegionToUpload, resolution);
|
2012-04-16 16:04:24 -07:00
|
|
|
mValidRegion = mVideoMemoryTiledBuffer.GetValidRegion();
|
|
|
|
|
|
|
|
mMainMemoryTiledBuffer.ReadUnlock();
|
2012-04-23 17:08:18 -07:00
|
|
|
// Release all the tiles by replacing the tile buffer with an empty
|
|
|
|
// tiled buffer. This will prevent us from doing a double unlock when
|
|
|
|
// calling ~TiledThebesLayerOGL.
|
|
|
|
// FIXME: This wont be needed when we do progressive upload and lock
|
|
|
|
// tile by tile.
|
|
|
|
mMainMemoryTiledBuffer = BasicTiledLayerBuffer();
|
2012-04-16 16:04:24 -07:00
|
|
|
mRegionToUpload = nsIntRegion();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2012-04-24 19:48:33 -07:00
|
|
|
void
|
|
|
|
TiledThebesLayerOGL::RenderTile(TiledTexture aTile,
|
|
|
|
const gfx3DMatrix& aTransform,
|
|
|
|
const nsIntPoint& aOffset,
|
2012-04-30 07:19:17 -07:00
|
|
|
nsIntRegion aScreenRegion,
|
|
|
|
nsIntPoint aTextureOffset,
|
2012-03-18 16:02:38 -07:00
|
|
|
nsIntSize aTextureBounds,
|
|
|
|
Layer* aMaskLayer)
|
2012-04-24 19:48:33 -07:00
|
|
|
{
|
|
|
|
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, aTile.mTextureHandle);
|
2012-03-18 13:07:25 -07:00
|
|
|
ShaderProgramOGL *program;
|
2012-04-24 19:48:33 -07:00
|
|
|
if (aTile.mFormat == LOCAL_GL_RGB) {
|
2012-03-18 16:02:38 -07:00
|
|
|
program = mOGLManager->GetProgram(gl::RGBXLayerProgramType, aMaskLayer);
|
2012-04-24 19:48:33 -07:00
|
|
|
} else {
|
2012-03-18 16:02:38 -07:00
|
|
|
program = mOGLManager->GetProgram(gl::BGRALayerProgramType, aMaskLayer);
|
2012-04-24 19:48:33 -07:00
|
|
|
}
|
|
|
|
program->Activate();
|
|
|
|
program->SetTextureUnit(0);
|
|
|
|
program->SetLayerOpacity(GetEffectiveOpacity());
|
|
|
|
program->SetLayerTransform(aTransform);
|
|
|
|
program->SetRenderOffset(aOffset);
|
2012-03-18 16:02:38 -07:00
|
|
|
program->LoadMask(GetMaskLayer());
|
2012-04-24 19:48:33 -07:00
|
|
|
|
2012-04-30 07:19:17 -07:00
|
|
|
nsIntRegionRectIterator it(aScreenRegion);
|
|
|
|
for (const nsIntRect* rect = it.Next(); rect != nsnull; rect = it.Next()) {
|
|
|
|
nsIntRect textureRect(rect->x - aTextureOffset.x, rect->y - aTextureOffset.y,
|
|
|
|
rect->width, rect->height);
|
|
|
|
program->SetLayerQuadRect(*rect);
|
|
|
|
mOGLManager->BindAndDrawQuadWithTextureRect(program,
|
|
|
|
textureRect,
|
|
|
|
aTextureBounds);
|
|
|
|
}
|
2012-04-24 19:48:33 -07:00
|
|
|
}
|
|
|
|
|
2012-04-16 16:04:24 -07:00
|
|
|
void
|
|
|
|
TiledThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer, const nsIntPoint& aOffset)
|
|
|
|
{
|
|
|
|
gl()->MakeCurrent();
|
2012-04-30 11:51:05 -07:00
|
|
|
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
2012-04-16 16:04:24 -07:00
|
|
|
ProcessUploadQueue();
|
|
|
|
|
2012-03-18 16:02:38 -07:00
|
|
|
Layer* maskLayer = GetMaskLayer();
|
|
|
|
|
2012-04-24 19:48:33 -07:00
|
|
|
// Render old tiles to fill in gaps we haven't had the time to render yet.
|
2012-04-26 09:53:14 -07:00
|
|
|
if (mReusableTileStore) {
|
2012-05-03 17:55:08 -07:00
|
|
|
mReusableTileStore->DrawTiles(this,
|
2012-04-26 09:53:14 -07:00
|
|
|
mVideoMemoryTiledBuffer.GetValidRegion(),
|
2012-04-24 19:48:33 -07:00
|
|
|
mVideoMemoryTiledBuffer.GetResolution(),
|
2012-03-18 16:02:38 -07:00
|
|
|
GetEffectiveTransform(), aOffset, maskLayer);
|
2012-04-26 09:53:14 -07:00
|
|
|
}
|
2012-04-24 19:48:33 -07:00
|
|
|
|
|
|
|
// Render valid tiles.
|
2012-04-16 16:04:24 -07:00
|
|
|
const nsIntRegion& visibleRegion = GetEffectiveVisibleRegion();
|
|
|
|
const nsIntRect visibleRect = visibleRegion.GetBounds();
|
2012-03-18 16:02:38 -07:00
|
|
|
|
2012-05-17 12:47:53 -07:00
|
|
|
uint32_t rowCount = 0;
|
|
|
|
uint32_t tileX = 0;
|
|
|
|
for (int32_t x = visibleRect.x; x < visibleRect.x + visibleRect.width;) {
|
2012-04-16 16:04:24 -07:00
|
|
|
rowCount++;
|
2012-05-17 12:47:53 -07:00
|
|
|
int32_t tileStartX = mVideoMemoryTiledBuffer.GetTileStart(x);
|
|
|
|
int16_t w = mVideoMemoryTiledBuffer.GetTileLength() - tileStartX;
|
2012-04-16 16:04:24 -07:00
|
|
|
if (x + w > visibleRect.x + visibleRect.width)
|
|
|
|
w = visibleRect.x + visibleRect.width - x;
|
|
|
|
int tileY = 0;
|
2012-05-17 12:47:53 -07:00
|
|
|
for (int32_t y = visibleRect.y; y < visibleRect.y + visibleRect.height;) {
|
|
|
|
int32_t tileStartY = mVideoMemoryTiledBuffer.GetTileStart(y);
|
|
|
|
int16_t h = mVideoMemoryTiledBuffer.GetTileLength() - tileStartY;
|
2012-04-16 16:04:24 -07:00
|
|
|
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()) {
|
2012-04-30 07:19:17 -07:00
|
|
|
nsIntRegion tileDrawRegion = nsIntRegion(nsIntRect(x, y, w, h));
|
|
|
|
tileDrawRegion.And(tileDrawRegion, mValidRegion);
|
|
|
|
|
|
|
|
nsIntPoint tileOffset(x - tileStartX, y - tileStartY);
|
2012-04-24 19:48:33 -07:00
|
|
|
uint16_t tileSize = mVideoMemoryTiledBuffer.GetTileLength();
|
2012-04-30 07:19:17 -07:00
|
|
|
RenderTile(tileTexture, GetEffectiveTransform(), aOffset, tileDrawRegion,
|
2012-03-18 16:02:38 -07:00
|
|
|
tileOffset, nsIntSize(tileSize, tileSize), maskLayer);
|
2012-04-16 16:04:24 -07:00
|
|
|
}
|
|
|
|
tileY++;
|
|
|
|
y += h;
|
|
|
|
}
|
|
|
|
tileX++;
|
|
|
|
x += w;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} // mozilla
|
|
|
|
} // layers
|