mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-15 06:15:43 +00:00
Bug 586683 - Part 2b - Add resolution handling to ThebesLayerOGL. r=joe a=blocking2.0
This commit is contained in:
parent
76d5166e16
commit
a159a42fa7
@ -156,7 +156,9 @@ public:
|
|||||||
{}
|
{}
|
||||||
virtual ~ThebesLayerBufferOGL() {}
|
virtual ~ThebesLayerBufferOGL() {}
|
||||||
|
|
||||||
virtual PaintState BeginPaint(ContentType aContentType) = 0;
|
virtual PaintState BeginPaint(ContentType aContentType,
|
||||||
|
float aXResolution,
|
||||||
|
float aYResolution) = 0;
|
||||||
|
|
||||||
void RenderTo(const nsIntPoint& aOffset, LayerManagerOGL* aManager);
|
void RenderTo(const nsIntPoint& aOffset, LayerManagerOGL* aManager);
|
||||||
|
|
||||||
@ -256,12 +258,9 @@ ThebesLayerBufferOGL::RenderTo(const nsIntPoint& aOffset,
|
|||||||
// non-1.0 resolution, only the texture size is scaled by the
|
// non-1.0 resolution, only the texture size is scaled by the
|
||||||
// resolution. So map the quadrent rect into the space scaled to
|
// resolution. So map the quadrent rect into the space scaled to
|
||||||
// the texture size and let GL do the rest.
|
// the texture size and let GL do the rest.
|
||||||
gfxRect sqr(quadRect.x, quadRect.y, quadRect.width, quadRect.height);
|
quadRect.ScaleRoundOut(xres, yres);
|
||||||
sqr.Scale(xres, yres);
|
|
||||||
sqr.Round();
|
|
||||||
nsIntRect scaledQuadRect(sqr.pos.x, sqr.pos.y, sqr.size.width, sqr.size.height);
|
|
||||||
|
|
||||||
BindAndDrawQuadWithTextureRect(gl(), program, scaledQuadRect,
|
BindAndDrawQuadWithTextureRect(gl(), program, quadRect,
|
||||||
mTexImage->GetSize(),
|
mTexImage->GetSize(),
|
||||||
mTexImage->GetWrapMode());
|
mTexImage->GetWrapMode());
|
||||||
DEBUG_GL_ERROR_CHECK(gl());
|
DEBUG_GL_ERROR_CHECK(gl());
|
||||||
@ -293,10 +292,15 @@ public:
|
|||||||
virtual ~SurfaceBufferOGL() {}
|
virtual ~SurfaceBufferOGL() {}
|
||||||
|
|
||||||
// ThebesLayerBufferOGL interface
|
// ThebesLayerBufferOGL interface
|
||||||
virtual PaintState BeginPaint(ContentType aContentType)
|
virtual PaintState BeginPaint(ContentType aContentType,
|
||||||
|
float aXResolution,
|
||||||
|
float aYResolution)
|
||||||
{
|
{
|
||||||
// Let ThebesLayerBuffer do all the hard work for us! :D
|
// Let ThebesLayerBuffer do all the hard work for us! :D
|
||||||
return ThebesLayerBuffer::BeginPaint(mLayer, aContentType, 1.0, 1.0);
|
return ThebesLayerBuffer::BeginPaint(mLayer,
|
||||||
|
aContentType,
|
||||||
|
aXResolution,
|
||||||
|
aYResolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ThebesLayerBuffer interface
|
// ThebesLayerBuffer interface
|
||||||
@ -330,7 +334,9 @@ public:
|
|||||||
{}
|
{}
|
||||||
virtual ~BasicBufferOGL() {}
|
virtual ~BasicBufferOGL() {}
|
||||||
|
|
||||||
virtual PaintState BeginPaint(ContentType aContentType);
|
virtual PaintState BeginPaint(ContentType aContentType,
|
||||||
|
float aXResolution,
|
||||||
|
float aYResolution);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
enum XSide {
|
enum XSide {
|
||||||
@ -373,22 +379,40 @@ BasicBufferOGL::GetQuadrantRectangle(XSide aXSide, YSide aYSide)
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
FillSurface(gfxASurface* aSurface, const nsIntRegion& aRegion,
|
FillSurface(gfxASurface* aSurface, const nsIntRegion& aRegion,
|
||||||
const nsIntPoint& aOffset, const gfxRGBA& aColor)
|
const nsIntPoint& aOffset, const gfxRGBA& aColor,
|
||||||
|
float aXRes, float aYRes)
|
||||||
{
|
{
|
||||||
nsRefPtr<gfxContext> ctx = new gfxContext(aSurface);
|
nsRefPtr<gfxContext> ctx = new gfxContext(aSurface);
|
||||||
|
ctx->Scale(aXRes, aYRes);
|
||||||
ctx->Translate(-gfxPoint(aOffset.x, aOffset.y));
|
ctx->Translate(-gfxPoint(aOffset.x, aOffset.y));
|
||||||
gfxUtils::ClipToRegion(ctx, aRegion);
|
gfxUtils::ClipToRegion(ctx, aRegion);
|
||||||
ctx->SetColor(aColor);
|
ctx->SetColor(aColor);
|
||||||
ctx->Paint();
|
ctx->Paint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static nsIntSize
|
||||||
|
ScaledSize(const nsIntSize& aSize, float aXScale, float aYScale)
|
||||||
|
{
|
||||||
|
if (aXScale == 1.0 && aYScale == 1.0) {
|
||||||
|
return aSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIntRect rect(0, 0, aSize.width, aSize.height);
|
||||||
|
rect.ScaleRoundOut(aXScale, aYScale);
|
||||||
|
return rect.Size();
|
||||||
|
}
|
||||||
|
|
||||||
BasicBufferOGL::PaintState
|
BasicBufferOGL::PaintState
|
||||||
BasicBufferOGL::BeginPaint(ContentType aContentType)
|
BasicBufferOGL::BeginPaint(ContentType aContentType,
|
||||||
|
float aXResolution,
|
||||||
|
float aYResolution)
|
||||||
{
|
{
|
||||||
PaintState result;
|
PaintState result;
|
||||||
|
|
||||||
result.mRegionToDraw.Sub(mLayer->GetVisibleRegion(), mLayer->GetValidRegion());
|
result.mRegionToDraw.Sub(mLayer->GetVisibleRegion(), mLayer->GetValidRegion());
|
||||||
|
|
||||||
|
float curXRes = mLayer->GetXResolution();
|
||||||
|
float curYRes = mLayer->GetYResolution();
|
||||||
Layer::SurfaceMode mode = mLayer->GetSurfaceMode();
|
Layer::SurfaceMode mode = mLayer->GetSurfaceMode();
|
||||||
|
|
||||||
if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
|
if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
|
||||||
@ -404,6 +428,7 @@ BasicBufferOGL::BeginPaint(ContentType aContentType)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!mTexImage || mTexImage->GetContentType() != aContentType ||
|
if (!mTexImage || mTexImage->GetContentType() != aContentType ||
|
||||||
|
aXResolution != curXRes || aYResolution != curYRes ||
|
||||||
(mode == Layer::SURFACE_COMPONENT_ALPHA) != (mTexImageOnWhite != nsnull)) {
|
(mode == Layer::SURFACE_COMPONENT_ALPHA) != (mTexImageOnWhite != nsnull)) {
|
||||||
// We're effectively clearing the valid region, so we need to draw
|
// We're effectively clearing the valid region, so we need to draw
|
||||||
// the entire visible region now.
|
// the entire visible region now.
|
||||||
@ -432,11 +457,15 @@ BasicBufferOGL::BeginPaint(ContentType aContentType)
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsIntRect drawBounds = result.mRegionToDraw.GetBounds();
|
nsIntRect drawBounds = result.mRegionToDraw.GetBounds();
|
||||||
|
nsIntSize destBufferDims = ScaledSize(visibleBounds.Size(),
|
||||||
|
aXResolution, aYResolution);
|
||||||
nsRefPtr<TextureImage> destBuffer;
|
nsRefPtr<TextureImage> destBuffer;
|
||||||
nsRefPtr<TextureImage> destBufferOnWhite;
|
nsRefPtr<TextureImage> destBufferOnWhite;
|
||||||
nsIntRect destBufferRect;
|
nsIntRect destBufferRect;
|
||||||
|
|
||||||
if (visibleBounds.Size() <= mBufferRect.Size()) {
|
if (visibleBounds.Size() <= mBufferRect.Size()) {
|
||||||
|
NS_ASSERTION(curXRes == aXResolution && curYRes == aYResolution,
|
||||||
|
"resolution changes must clear the buffer!");
|
||||||
// The current buffer is big enough to hold the visible area.
|
// The current buffer is big enough to hold the visible area.
|
||||||
if (mBufferRect.Contains(visibleBounds)) {
|
if (mBufferRect.Contains(visibleBounds)) {
|
||||||
// We don't need to adjust mBufferRect.
|
// We don't need to adjust mBufferRect.
|
||||||
@ -468,13 +497,13 @@ BasicBufferOGL::BeginPaint(ContentType aContentType)
|
|||||||
// We can't do a real self-copy because the buffer is rotated.
|
// We can't do a real self-copy because the buffer is rotated.
|
||||||
// So allocate a new buffer for the destination.
|
// So allocate a new buffer for the destination.
|
||||||
destBufferRect = visibleBounds;
|
destBufferRect = visibleBounds;
|
||||||
destBuffer = CreateClampOrRepeatTextureImage(gl(), visibleBounds.Size(), aContentType);
|
destBuffer = CreateClampOrRepeatTextureImage(gl(), destBufferDims, aContentType);
|
||||||
DEBUG_GL_ERROR_CHECK(gl());
|
DEBUG_GL_ERROR_CHECK(gl());
|
||||||
if (!destBuffer)
|
if (!destBuffer)
|
||||||
return result;
|
return result;
|
||||||
if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
|
if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
|
||||||
destBufferOnWhite =
|
destBufferOnWhite =
|
||||||
CreateClampOrRepeatTextureImage(gl(), visibleBounds.Size(), aContentType);
|
CreateClampOrRepeatTextureImage(gl(), destBufferDims, aContentType);
|
||||||
DEBUG_GL_ERROR_CHECK(gl());
|
DEBUG_GL_ERROR_CHECK(gl());
|
||||||
if (!destBufferOnWhite)
|
if (!destBufferOnWhite)
|
||||||
return result;
|
return result;
|
||||||
@ -493,14 +522,14 @@ BasicBufferOGL::BeginPaint(ContentType aContentType)
|
|||||||
} else {
|
} else {
|
||||||
// The buffer's not big enough, so allocate a new one
|
// The buffer's not big enough, so allocate a new one
|
||||||
destBufferRect = visibleBounds;
|
destBufferRect = visibleBounds;
|
||||||
destBuffer = CreateClampOrRepeatTextureImage(gl(), visibleBounds.Size(), aContentType);
|
destBuffer = CreateClampOrRepeatTextureImage(gl(), destBufferDims, aContentType);
|
||||||
DEBUG_GL_ERROR_CHECK(gl());
|
DEBUG_GL_ERROR_CHECK(gl());
|
||||||
if (!destBuffer)
|
if (!destBuffer)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
|
if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
|
||||||
destBufferOnWhite =
|
destBufferOnWhite =
|
||||||
CreateClampOrRepeatTextureImage(gl(), visibleBounds.Size(), aContentType);
|
CreateClampOrRepeatTextureImage(gl(), destBufferDims, aContentType);
|
||||||
DEBUG_GL_ERROR_CHECK(gl());
|
DEBUG_GL_ERROR_CHECK(gl());
|
||||||
if (!destBufferOnWhite)
|
if (!destBufferOnWhite)
|
||||||
return result;
|
return result;
|
||||||
@ -523,22 +552,25 @@ BasicBufferOGL::BeginPaint(ContentType aContentType)
|
|||||||
srcRect.MoveBy(- mBufferRect.TopLeft() + mBufferRotation);
|
srcRect.MoveBy(- mBufferRect.TopLeft() + mBufferRotation);
|
||||||
dstRect.MoveBy(- destBufferRect.TopLeft());
|
dstRect.MoveBy(- destBufferRect.TopLeft());
|
||||||
|
|
||||||
destBuffer->Resize(destBufferRect.Size());
|
nsIntSize size = ScaledSize(destBufferRect.Size(), aXResolution, aYResolution);
|
||||||
|
destBuffer->Resize(size);
|
||||||
|
srcRect.ScaleRoundOut(aXResolution, aYResolution);
|
||||||
|
dstRect.ScaleRoundOut(aXResolution, aYResolution);
|
||||||
|
|
||||||
gl()->BlitTextureImage(mTexImage, srcRect,
|
gl()->BlitTextureImage(mTexImage, srcRect,
|
||||||
destBuffer, dstRect);
|
destBuffer, dstRect);
|
||||||
if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
|
if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
|
||||||
destBufferOnWhite->Resize(destBufferRect.Size());
|
destBufferOnWhite->Resize(size);
|
||||||
gl()->BlitTextureImage(mTexImageOnWhite, srcRect,
|
gl()->BlitTextureImage(mTexImageOnWhite, srcRect,
|
||||||
destBufferOnWhite, dstRect);
|
destBufferOnWhite, dstRect);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// can't blit, just draw everything
|
// can't blit, just draw everything
|
||||||
destBufferRect = visibleBounds;
|
destBufferRect = visibleBounds;
|
||||||
destBuffer = CreateClampOrRepeatTextureImage(gl(), visibleBounds.Size(), aContentType);
|
destBuffer = CreateClampOrRepeatTextureImage(gl(), destBufferDims, aContentType);
|
||||||
if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
|
if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
|
||||||
destBufferOnWhite =
|
destBufferOnWhite =
|
||||||
CreateClampOrRepeatTextureImage(gl(), visibleBounds.Size(), aContentType);
|
CreateClampOrRepeatTextureImage(gl(), destBufferDims, aContentType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -564,10 +596,11 @@ BasicBufferOGL::BeginPaint(ContentType aContentType)
|
|||||||
NS_ASSERTION(quadrantRect.Contains(drawBounds), "Messed up quadrants");
|
NS_ASSERTION(quadrantRect.Contains(drawBounds), "Messed up quadrants");
|
||||||
|
|
||||||
nsIntPoint offset = -nsIntPoint(quadrantRect.x, quadrantRect.y);
|
nsIntPoint offset = -nsIntPoint(quadrantRect.x, quadrantRect.y);
|
||||||
|
|
||||||
// Make the region to draw relative to the buffer, before
|
// Make the region to draw relative to the buffer, before
|
||||||
// passing to BeginUpdate.
|
// passing to BeginUpdate.
|
||||||
result.mRegionToDraw.MoveBy(offset);
|
result.mRegionToDraw.MoveBy(offset);
|
||||||
|
result.mRegionToDraw.ScaleRoundOut(aXResolution, aYResolution);
|
||||||
// BeginUpdate is allowed to modify the given region,
|
// BeginUpdate is allowed to modify the given region,
|
||||||
// if it wants more to be repainted than we request.
|
// if it wants more to be repainted than we request.
|
||||||
if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
|
if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
|
||||||
@ -576,8 +609,8 @@ BasicBufferOGL::BeginPaint(ContentType aContentType)
|
|||||||
gfxASurface *onWhite = mTexImageOnWhite->BeginUpdate(result.mRegionToDraw);
|
gfxASurface *onWhite = mTexImageOnWhite->BeginUpdate(result.mRegionToDraw);
|
||||||
NS_ASSERTION(result.mRegionToDraw == drawRegionCopy,
|
NS_ASSERTION(result.mRegionToDraw == drawRegionCopy,
|
||||||
"BeginUpdate should always modify the draw region in the same way!");
|
"BeginUpdate should always modify the draw region in the same way!");
|
||||||
FillSurface(onBlack, result.mRegionToDraw, nsIntPoint(0,0), gfxRGBA(0.0, 0.0, 0.0, 1.0));
|
FillSurface(onBlack, result.mRegionToDraw, nsIntPoint(0,0), gfxRGBA(0.0, 0.0, 0.0, 1.0), aXResolution, aYResolution);
|
||||||
FillSurface(onWhite, result.mRegionToDraw, nsIntPoint(0,0), gfxRGBA(1.0, 1.0, 1.0, 1.0));
|
FillSurface(onWhite, result.mRegionToDraw, nsIntPoint(0,0), gfxRGBA(1.0, 1.0, 1.0, 1.0), aXResolution, aYResolution);
|
||||||
gfxASurface* surfaces[2] = { onBlack, onWhite };
|
gfxASurface* surfaces[2] = { onBlack, onWhite };
|
||||||
nsRefPtr<gfxTeeSurface> surf = new gfxTeeSurface(surfaces, NS_ARRAY_LENGTH(surfaces));
|
nsRefPtr<gfxTeeSurface> surf = new gfxTeeSurface(surfaces, NS_ARRAY_LENGTH(surfaces));
|
||||||
|
|
||||||
@ -606,10 +639,15 @@ BasicBufferOGL::BeginPaint(ContentType aContentType)
|
|||||||
NS_WARNING("unable to get context for update");
|
NS_WARNING("unable to get context for update");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
result.mContext->Scale(aXResolution, aYResolution);
|
||||||
result.mContext->Translate(-gfxPoint(quadrantRect.x, quadrantRect.y));
|
result.mContext->Translate(-gfxPoint(quadrantRect.x, quadrantRect.y));
|
||||||
// Move rgnToPaint back into position so that the thebes callback
|
// Move rgnToPaint back into position so that the thebes callback
|
||||||
// gets the right coordintes.
|
// gets the right coordintes.
|
||||||
|
result.mRegionToDraw.ScaleRoundOut(1/aXResolution, 1/aYResolution);
|
||||||
result.mRegionToDraw.MoveBy(-offset);
|
result.mRegionToDraw.MoveBy(-offset);
|
||||||
|
// Round our region out to values that will scale cleanly by the given
|
||||||
|
// resolution.
|
||||||
|
result.mRegionToDraw.ExtendForScaling(aXResolution, aYResolution);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -685,11 +723,23 @@ ThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer,
|
|||||||
TextureImage::ContentType contentType =
|
TextureImage::ContentType contentType =
|
||||||
CanUseOpaqueSurface() ? gfxASurface::CONTENT_COLOR :
|
CanUseOpaqueSurface() ? gfxASurface::CONTENT_COLOR :
|
||||||
gfxASurface::CONTENT_COLOR_ALPHA;
|
gfxASurface::CONTENT_COLOR_ALPHA;
|
||||||
Buffer::PaintState state = mBuffer->BeginPaint(contentType);
|
|
||||||
|
const gfx3DMatrix& transform = GetEffectiveTransform();
|
||||||
|
gfxMatrix transform2d;
|
||||||
|
gfxSize scale(1.0, 1.0);
|
||||||
|
if (transform.Is2D(&transform2d)) {
|
||||||
|
scale = transform2d.ScaleFactors(PR_TRUE);
|
||||||
|
}
|
||||||
|
float paintXRes = gfxUtils::ClampToScaleFactor(scale.width);
|
||||||
|
float paintYRes = gfxUtils::ClampToScaleFactor(scale.height);
|
||||||
|
|
||||||
|
Buffer::PaintState state = mBuffer->BeginPaint(contentType, paintXRes, paintYRes);
|
||||||
mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);
|
mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);
|
||||||
|
|
||||||
if (state.mContext) {
|
if (state.mContext) {
|
||||||
state.mRegionToInvalidate.And(state.mRegionToInvalidate, mVisibleRegion);
|
state.mRegionToInvalidate.And(state.mRegionToInvalidate, mVisibleRegion);
|
||||||
|
mXResolution = paintXRes;
|
||||||
|
mYResolution = paintYRes;
|
||||||
|
|
||||||
LayerManager::DrawThebesLayerCallback callback =
|
LayerManager::DrawThebesLayerCallback callback =
|
||||||
mOGLManager->GetThebesLayerCallback();
|
mOGLManager->GetThebesLayerCallback();
|
||||||
@ -736,7 +786,7 @@ public:
|
|||||||
: ThebesLayerBufferOGL(aLayer, aLayer)
|
: ThebesLayerBufferOGL(aLayer, aLayer)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual PaintState BeginPaint(ContentType aContentType) {
|
virtual PaintState BeginPaint(ContentType aContentType, float, float) {
|
||||||
NS_RUNTIMEABORT("can't BeginPaint for a shadow layer");
|
NS_RUNTIMEABORT("can't BeginPaint for a shadow layer");
|
||||||
return PaintState();
|
return PaintState();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user