зеркало из https://github.com/mozilla/pjs.git
Backout bug 736716.
This commit is contained in:
Родитель
6561c9d080
Коммит
0802e137f1
|
@ -698,6 +698,39 @@ public:
|
|||
Mutated();
|
||||
}
|
||||
|
||||
/**
|
||||
* CONSTRUCTION PHASE ONLY
|
||||
*
|
||||
* Define a subrect of this layer that will be used as the source
|
||||
* image for tiling this layer's visible region. The coordinates
|
||||
* are in the un-transformed space of this layer (i.e. the visible
|
||||
* region of this this layer is tiled before being transformed).
|
||||
* The visible region is tiled "outwards" from the source rect; that
|
||||
* is, the source rect is drawn "in place", then repeated to cover
|
||||
* the layer's visible region.
|
||||
*
|
||||
* The interpretation of the source rect varies depending on
|
||||
* underlying layer type. For ImageLayers and CanvasLayers, it
|
||||
* doesn't make sense to set a source rect not fully contained by
|
||||
* the bounds of their underlying images. For ThebesLayers, thebes
|
||||
* content may need to be rendered to fill the source rect. For
|
||||
* ColorLayers, a source rect for tiling doesn't make sense at all.
|
||||
*
|
||||
* If aRect is null no tiling will be performed.
|
||||
*
|
||||
* NB: this interface is only implemented for BasicImageLayers, and
|
||||
* then only for source rects the same size as the layers'
|
||||
* underlying images.
|
||||
*/
|
||||
void SetTileSourceRect(const nsIntRect* aRect)
|
||||
{
|
||||
mUseTileSourceRect = aRect != nsnull;
|
||||
if (aRect) {
|
||||
mTileSourceRect = *aRect;
|
||||
}
|
||||
Mutated();
|
||||
}
|
||||
|
||||
void SetIsFixedPosition(bool aFixedPosition) { mIsFixedPosition = aFixedPosition; }
|
||||
|
||||
// These getters can be used anytime.
|
||||
|
@ -711,6 +744,7 @@ public:
|
|||
virtual Layer* GetFirstChild() { return nsnull; }
|
||||
virtual Layer* GetLastChild() { return nsnull; }
|
||||
const gfx3DMatrix& GetTransform() { return mTransform; }
|
||||
const nsIntRect* GetTileSourceRect() { return mUseTileSourceRect ? &mTileSourceRect : nsnull; }
|
||||
bool GetIsFixedPosition() { return mIsFixedPosition; }
|
||||
|
||||
/**
|
||||
|
|
|
@ -880,6 +880,7 @@ public:
|
|||
|
||||
static void PaintContext(gfxPattern* aPattern,
|
||||
const nsIntRegion& aVisible,
|
||||
const nsIntRect* aTileSourceRect,
|
||||
float aOpacity,
|
||||
gfxContext* aContext);
|
||||
|
||||
|
@ -939,11 +940,14 @@ BasicImageLayer::GetAndPaintCurrentImage(gfxContext* aContext,
|
|||
size = mScaleToSize;
|
||||
}
|
||||
|
||||
// The visible region can extend outside the image, so just draw
|
||||
// within the image bounds.
|
||||
// The visible region can extend outside the image. If we're not
|
||||
// tiling, we don't want to draw into that area, so just draw within
|
||||
// the image bounds.
|
||||
const nsIntRect* tileSrcRect = GetTileSourceRect();
|
||||
AutoSetOperator setOperator(aContext, GetOperator());
|
||||
PaintContext(pat,
|
||||
nsIntRegion(nsIntRect(0, 0, size.width, size.height)),
|
||||
tileSrcRect ? GetVisibleRegion() : nsIntRegion(nsIntRect(0, 0, size.width, size.height)),
|
||||
tileSrcRect,
|
||||
aOpacity, aContext);
|
||||
|
||||
GetContainer()->NotifyPaintedImage(image);
|
||||
|
@ -954,6 +958,7 @@ BasicImageLayer::GetAndPaintCurrentImage(gfxContext* aContext,
|
|||
/*static*/ void
|
||||
BasicImageLayer::PaintContext(gfxPattern* aPattern,
|
||||
const nsIntRegion& aVisible,
|
||||
const nsIntRect* aTileSourceRect,
|
||||
float aOpacity,
|
||||
gfxContext* aContext)
|
||||
{
|
||||
|
@ -973,13 +978,31 @@ BasicImageLayer::PaintContext(gfxPattern* aPattern,
|
|||
}
|
||||
}
|
||||
|
||||
aContext->NewPath();
|
||||
// No need to snap here; our transform has already taken care of it.
|
||||
// XXX true for arbitrary regions? Don't care yet though
|
||||
gfxUtils::PathFromRegion(aContext, aVisible);
|
||||
aPattern->SetExtend(extend);
|
||||
aContext->SetPattern(aPattern);
|
||||
aContext->FillWithOpacity(aOpacity);
|
||||
if (!aTileSourceRect) {
|
||||
aContext->NewPath();
|
||||
// No need to snap here; our transform has already taken care of it.
|
||||
// XXX true for arbitrary regions? Don't care yet though
|
||||
gfxUtils::PathFromRegion(aContext, aVisible);
|
||||
aPattern->SetExtend(extend);
|
||||
aContext->SetPattern(aPattern);
|
||||
aContext->FillWithOpacity(aOpacity);
|
||||
} else {
|
||||
nsRefPtr<gfxASurface> source = aPattern->GetSurface();
|
||||
NS_ABORT_IF_FALSE(source, "Expecting a surface pattern");
|
||||
gfxIntSize sourceSize = source->GetSize();
|
||||
nsIntRect sourceRect(0, 0, sourceSize.width, sourceSize.height);
|
||||
NS_ABORT_IF_FALSE(sourceRect == *aTileSourceRect,
|
||||
"Cowardly refusing to create a temporary surface for tiling");
|
||||
|
||||
gfxContextAutoSaveRestore saveRestore(aContext);
|
||||
|
||||
aContext->NewPath();
|
||||
gfxUtils::PathFromRegion(aContext, aVisible);
|
||||
|
||||
aPattern->SetExtend(gfxPattern::EXTEND_REPEAT);
|
||||
aContext->SetPattern(aPattern);
|
||||
aContext->FillWithOpacity(aOpacity);
|
||||
}
|
||||
|
||||
// Reset extend mode for callers that need to reuse the pattern
|
||||
aPattern->SetExtend(extend);
|
||||
|
@ -2606,7 +2629,7 @@ BasicShadowableImageLayer::Paint(gfxContext* aContext)
|
|||
tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
PaintContext(pat,
|
||||
nsIntRegion(nsIntRect(0, 0, mSize.width, mSize.height)),
|
||||
1.0, tmpCtx);
|
||||
nsnull, 1.0, tmpCtx);
|
||||
|
||||
BasicManager()->PaintedImage(BasicManager()->Hold(this),
|
||||
mBackBuffer);
|
||||
|
@ -3052,11 +3075,14 @@ BasicShadowImageLayer::Paint(gfxContext* aContext)
|
|||
nsRefPtr<gfxPattern> pat = new gfxPattern(surface);
|
||||
pat->SetFilter(mFilter);
|
||||
|
||||
// The visible region can extend outside the image, so just draw
|
||||
// within the image bounds.
|
||||
// The visible region can extend outside the image. If we're not
|
||||
// tiling, we don't want to draw into that area, so just draw within
|
||||
// the image bounds.
|
||||
const nsIntRect* tileSrcRect = GetTileSourceRect();
|
||||
AutoSetOperator setOperator(aContext, GetOperator());
|
||||
BasicImageLayer::PaintContext(pat,
|
||||
nsIntRegion(nsIntRect(0, 0, mSize.width, mSize.height)),
|
||||
tileSrcRect ? GetEffectiveVisibleRegion() : nsIntRegion(nsIntRect(0, 0, mSize.width, mSize.height)),
|
||||
tileSrcRect,
|
||||
GetEffectiveOpacity(), aContext);
|
||||
}
|
||||
|
||||
|
|
|
@ -117,6 +117,8 @@ struct CommonLayerAttributes {
|
|||
float opacity;
|
||||
bool useClipRect;
|
||||
nsIntRect clipRect;
|
||||
bool useTileSourceRect;
|
||||
nsIntRect tileSourceRect;
|
||||
bool isFixedPosition;
|
||||
};
|
||||
|
||||
|
|
|
@ -298,6 +298,9 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies)
|
|||
common.clipRect() = (common.useClipRect() ?
|
||||
*mutant->GetClipRect() : nsIntRect());
|
||||
common.isFixedPosition() = mutant->GetIsFixedPosition();
|
||||
common.useTileSourceRect() = !!mutant->GetTileSourceRect();
|
||||
common.tileSourceRect() = (common.useTileSourceRect() ?
|
||||
*mutant->GetTileSourceRect() : nsIntRect());
|
||||
attrs.specific() = null_t();
|
||||
mutant->FillSpecificAttributes(attrs.specific());
|
||||
|
||||
|
|
|
@ -225,6 +225,7 @@ ShadowLayersParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
|
|||
layer->SetOpacity(common.opacity());
|
||||
layer->SetClipRect(common.useClipRect() ? &common.clipRect() : NULL);
|
||||
layer->SetTransform(common.transform());
|
||||
layer->SetTileSourceRect(common.useTileSourceRect() ? &common.tileSourceRect() : NULL);
|
||||
static bool fixedPositionLayersEnabled = getenv("MOZ_ENABLE_FIXED_POSITION_LAYERS") != 0;
|
||||
if (fixedPositionLayersEnabled) {
|
||||
layer->SetIsFixedPosition(common.isFixedPosition());
|
||||
|
|
|
@ -305,6 +305,7 @@ ImageLayerOGL::RenderLayer(int,
|
|||
return;
|
||||
}
|
||||
|
||||
data->SetTiling(mUseTileSourceRect);
|
||||
gl()->MakeCurrent();
|
||||
unsigned int iwidth = cairoImage->mSize.width;
|
||||
unsigned int iheight = cairoImage->mSize.height;
|
||||
|
@ -341,16 +342,68 @@ ImageLayerOGL::RenderLayer(int,
|
|||
|
||||
nsIntRect rect = GetVisibleRegion().GetBounds();
|
||||
|
||||
bool tileIsWholeImage = (mTileSourceRect == nsIntRect(0, 0, iwidth, iheight))
|
||||
|| !mUseTileSourceRect;
|
||||
bool imageIsPowerOfTwo = IsPowerOfTwo(iwidth) &&
|
||||
IsPowerOfTwo(iheight);
|
||||
|
||||
bool canDoNPOT = (
|
||||
gl()->IsExtensionSupported(GLContext::ARB_texture_non_power_of_two) ||
|
||||
gl()->IsExtensionSupported(GLContext::OES_texture_npot));
|
||||
|
||||
GLContext::RectTriangles triangleBuffer;
|
||||
// do GL_REPEAT if we can - should be the fastest option.
|
||||
// draw a single rect for the whole region, a little overdraw
|
||||
// on the gpu should be faster than tesselating
|
||||
// maybe we can write a shader that can also handle texture subrects
|
||||
// and repeat?
|
||||
if (tileIsWholeImage && (imageIsPowerOfTwo || canDoNPOT)) {
|
||||
// we need to anchor the repeating texture appropriately
|
||||
// otherwise it will start from the region border instead
|
||||
// of the layer origin. This is the offset into the texture
|
||||
// that the region border represents
|
||||
float tex_offset_u = (float)(rect.x % iwidth) / iwidth;
|
||||
float tex_offset_v = (float)(rect.y % iheight) / iheight;
|
||||
triangleBuffer.addRect(rect.x, rect.y,
|
||||
rect.x + rect.width, rect.y + rect.height,
|
||||
tex_offset_u, tex_offset_v,
|
||||
tex_offset_u + (float)rect.width / (float)iwidth,
|
||||
tex_offset_v + (float)rect.height / (float)iheight);
|
||||
}
|
||||
// can't do fast path via GL_REPEAT - we have to tessellate individual rects.
|
||||
else {
|
||||
unsigned int twidth = mTileSourceRect.width;
|
||||
unsigned int theight = mTileSourceRect.height;
|
||||
|
||||
float tex_offset_u = float(rect.x % iwidth) / iwidth;
|
||||
float tex_offset_v = float(rect.y % iheight) / iheight;
|
||||
triangleBuffer.addRect(rect.x, rect.y,
|
||||
rect.x + rect.width, rect.y + rect.height,
|
||||
tex_offset_u, tex_offset_v,
|
||||
tex_offset_u + float(rect.width) / float(iwidth),
|
||||
tex_offset_v + float(rect.height) / float(iheight);
|
||||
nsIntRegion region = GetVisibleRegion();
|
||||
// image subrect in texture coordinates
|
||||
float subrect_tl_u = float(mTileSourceRect.x) / float(iwidth);
|
||||
float subrect_tl_v = float(mTileSourceRect.y) / float(iheight);
|
||||
float subrect_br_u = float(mTileSourceRect.width + mTileSourceRect.x) / float(iwidth);
|
||||
float subrect_br_v = float(mTileSourceRect.height + mTileSourceRect.y) / float(iheight);
|
||||
|
||||
// round rect position down to multiples of texture size
|
||||
// this way we start at multiples of rect positions
|
||||
rect.x = (rect.x / iwidth) * iwidth;
|
||||
rect.y = (rect.y / iheight) * iheight;
|
||||
// round up size to accomodate for rounding down above
|
||||
rect.width = (rect.width / iwidth + 2) * iwidth;
|
||||
rect.height = (rect.height / iheight + 2) * iheight;
|
||||
|
||||
// tesselate the visible region with tiles of subrect size
|
||||
for (int y = rect.y; y < rect.y + rect.height; y += theight) {
|
||||
for (int x = rect.x; x < rect.x + rect.width; x += twidth) {
|
||||
// when we already tessellate, we might as well save on overdraw here
|
||||
if (!region.Intersects(nsIntRect(x, y, twidth, theight))) {
|
||||
continue;
|
||||
}
|
||||
triangleBuffer.addRect(x, y,
|
||||
x + twidth, y + theight,
|
||||
subrect_tl_u, subrect_tl_v,
|
||||
subrect_br_u, subrect_br_v);
|
||||
}
|
||||
}
|
||||
}
|
||||
GLuint vertAttribIndex =
|
||||
program->AttribLocation(LayerProgram::VertexAttrib);
|
||||
GLuint texCoordAttribIndex =
|
||||
|
@ -575,6 +628,25 @@ ImageLayerOGL::AllocateTexturesCairo(CairoImage *aImage)
|
|||
aImage->SetBackendData(LayerManager::LAYERS_OPENGL, backendData.forget());
|
||||
}
|
||||
|
||||
void CairoOGLBackendData::SetTiling(bool aTiling)
|
||||
{
|
||||
if (aTiling == mTiling)
|
||||
return;
|
||||
mozilla::gl::GLContext *gl = mTexture.GetGLContext();
|
||||
gl->MakeCurrent();
|
||||
gl->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture.GetTextureID());
|
||||
mTiling = aTiling;
|
||||
|
||||
if (aTiling) {
|
||||
gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_REPEAT);
|
||||
gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_REPEAT);
|
||||
} else {
|
||||
gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
}
|
||||
|
||||
ShadowImageLayerOGL::ShadowImageLayerOGL(LayerManagerOGL* aManager)
|
||||
: ShadowImageLayer(aManager, nsnull)
|
||||
, LayerOGL(aManager)
|
||||
|
|
|
@ -172,9 +172,11 @@ struct THEBES_API PlanarYCbCrOGLBackendData : public ImageBackendData
|
|||
|
||||
struct CairoOGLBackendData : public ImageBackendData
|
||||
{
|
||||
CairoOGLBackendData() : mLayerProgram(gl::RGBALayerProgramType) {}
|
||||
CairoOGLBackendData() : mLayerProgram(gl::RGBALayerProgramType), mTiling(false) {}
|
||||
void SetTiling(bool aTiling);
|
||||
GLTexture mTexture;
|
||||
gl::ShaderProgramType mLayerProgram;
|
||||
bool mTiling;
|
||||
};
|
||||
|
||||
class ShadowImageLayerOGL : public ShadowImageLayer,
|
||||
|
|
Загрузка…
Ссылка в новой задаче