mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
eda62c08cb
Changes to FrameMetrics and progressive tiling caused ReusableTileStoreOGL to basically not work anymore. Refactor to provide the same function as it did previously taking into account the platform changes.
300 lines
11 KiB
C++
300 lines
11 KiB
C++
/* 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 "ReusableTileStoreOGL.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,
|
|
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);
|
|
mMainMemoryTiledBuffer = nullptr;
|
|
#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, nullptr)
|
|
, LayerOGL(aManager)
|
|
, mVideoMemoryTiledBuffer(aManager->gl())
|
|
, mReusableTileStore(nullptr)
|
|
{
|
|
mImplData = static_cast<LayerOGL*>(this);
|
|
}
|
|
|
|
TiledThebesLayerOGL::~TiledThebesLayerOGL()
|
|
{
|
|
mMainMemoryTiledBuffer.ReadUnlock();
|
|
if (mReusableTileStore)
|
|
delete mReusableTileStore;
|
|
}
|
|
|
|
void
|
|
TiledThebesLayerOGL::MemoryPressure()
|
|
{
|
|
if (mReusableTileStore) {
|
|
delete mReusableTileStore;
|
|
mReusableTileStore = new ReusableTileStoreOGL(gl(), 1);
|
|
}
|
|
}
|
|
|
|
void
|
|
TiledThebesLayerOGL::PaintedTiledLayerBuffer(const BasicTiledLayerBuffer* mTiledBuffer)
|
|
{
|
|
mMainMemoryTiledBuffer.ReadUnlock();
|
|
mMainMemoryTiledBuffer = *mTiledBuffer;
|
|
// TODO: Remove me once Bug 747811 lands.
|
|
delete mTiledBuffer;
|
|
mRegionToUpload.Or(mRegionToUpload, mMainMemoryTiledBuffer.GetPaintedRegion());
|
|
mMainMemoryTiledBuffer.ClearPaintedRegion();
|
|
}
|
|
|
|
void
|
|
TiledThebesLayerOGL::ProcessUploadQueue()
|
|
{
|
|
if (mRegionToUpload.IsEmpty())
|
|
return;
|
|
|
|
// We should only be retaining old tiles if we're not fixed position.
|
|
// Fixed position layers don't/shouldn't move on the screen, so retaining
|
|
// tiles is not useful and often results in rendering artifacts.
|
|
if (mReusableTileStore && mIsFixedPosition) {
|
|
delete mReusableTileStore;
|
|
mReusableTileStore = nullptr;
|
|
} else if (!mReusableTileStore && !mIsFixedPosition) {
|
|
// XXX Add a pref for reusable tile store size
|
|
mReusableTileStore = new ReusableTileStoreOGL(gl(), 2);
|
|
}
|
|
|
|
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(this,
|
|
&mVideoMemoryTiledBuffer,
|
|
mVideoMemoryTiledBuffer.GetValidRegion(),
|
|
mMainMemoryTiledBuffer.GetValidRegion(),
|
|
mVideoMemoryTiledBuffer.GetResolution(),
|
|
resolution);
|
|
}
|
|
|
|
// 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());
|
|
|
|
mVideoMemoryTiledBuffer.Upload(&mMainMemoryTiledBuffer,
|
|
mMainMemoryTiledBuffer.GetValidRegion(),
|
|
mRegionToUpload, resolution);
|
|
mValidRegion = mVideoMemoryTiledBuffer.GetValidRegion();
|
|
|
|
mMainMemoryTiledBuffer.ReadUnlock();
|
|
// 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();
|
|
mRegionToUpload = nsIntRegion();
|
|
|
|
}
|
|
|
|
void
|
|
TiledThebesLayerOGL::RenderTile(const TiledTexture& aTile,
|
|
const gfx3DMatrix& aTransform,
|
|
const nsIntPoint& aOffset,
|
|
const nsIntRegion& aScreenRegion,
|
|
const nsIntPoint& aTextureOffset,
|
|
const nsIntSize& aTextureBounds,
|
|
Layer* aMaskLayer)
|
|
{
|
|
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, aTile.mTextureHandle);
|
|
ShaderProgramOGL *program;
|
|
if (aTile.mFormat == LOCAL_GL_RGB) {
|
|
program = mOGLManager->GetProgram(gl::RGBXLayerProgramType, aMaskLayer);
|
|
} else {
|
|
program = mOGLManager->GetProgram(gl::BGRALayerProgramType, aMaskLayer);
|
|
}
|
|
program->Activate();
|
|
program->SetTextureUnit(0);
|
|
program->SetLayerOpacity(GetEffectiveOpacity());
|
|
program->SetLayerTransform(aTransform);
|
|
program->SetRenderOffset(aOffset);
|
|
program->LoadMask(aMaskLayer);
|
|
|
|
nsIntRegionRectIterator it(aScreenRegion);
|
|
for (const nsIntRect* rect = it.Next(); rect != nullptr; 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);
|
|
}
|
|
}
|
|
|
|
void
|
|
TiledThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer, const nsIntPoint& aOffset)
|
|
{
|
|
gl()->MakeCurrent();
|
|
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
|
ProcessUploadQueue();
|
|
|
|
Layer* maskLayer = GetMaskLayer();
|
|
|
|
// 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, maskLayer);
|
|
}
|
|
|
|
// Render valid tiles.
|
|
const nsIntRegion& visibleRegion = GetEffectiveVisibleRegion();
|
|
const nsIntRect visibleRect = visibleRegion.GetBounds();
|
|
|
|
uint32_t rowCount = 0;
|
|
uint32_t tileX = 0;
|
|
for (int32_t x = visibleRect.x; x < visibleRect.x + visibleRect.width;) {
|
|
rowCount++;
|
|
int32_t tileStartX = mVideoMemoryTiledBuffer.GetTileStart(x);
|
|
int16_t w = mVideoMemoryTiledBuffer.GetTileLength() - tileStartX;
|
|
if (x + w > visibleRect.x + visibleRect.width)
|
|
w = visibleRect.x + visibleRect.width - x;
|
|
int tileY = 0;
|
|
for (int32_t y = visibleRect.y; y < visibleRect.y + visibleRect.height;) {
|
|
int32_t tileStartY = mVideoMemoryTiledBuffer.GetTileStart(y);
|
|
int16_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()) {
|
|
nsIntRegion tileDrawRegion = nsIntRegion(nsIntRect(x, y, w, h));
|
|
tileDrawRegion.And(tileDrawRegion, mValidRegion);
|
|
|
|
nsIntPoint tileOffset(x - tileStartX, y - tileStartY);
|
|
uint16_t tileSize = mVideoMemoryTiledBuffer.GetTileLength();
|
|
RenderTile(tileTexture, GetEffectiveTransform(), aOffset, tileDrawRegion,
|
|
tileOffset, nsIntSize(tileSize, tileSize), maskLayer);
|
|
}
|
|
tileY++;
|
|
y += h;
|
|
}
|
|
tileX++;
|
|
x += w;
|
|
}
|
|
}
|
|
|
|
} // mozilla
|
|
} // layers
|