Bug 782785 - Use temp surfaces to ReadPixels with correct stride - r=bjacob

This commit is contained in:
Jeff Gilbert
2012-08-21 16:13:26 -07:00
parent 85467e5480
commit e1f66565ad
5 changed files with 76 additions and 63 deletions

View File

@@ -77,6 +77,7 @@ protected:
mCachedFormat = aFormat;
}
MOZ_ASSERT(mCachedTempSurface->Stride() == mCachedTempSurface->Width() * 4);
return mCachedTempSurface;
}
@@ -155,41 +156,67 @@ BasicCanvasLayer::UpdateSurface(gfxASurface* aDestSurface, Layer* aMaskLayer)
return;
}
#endif
nsRefPtr<gfxImageSurface> isurf;
gfxIntSize readSize(mBounds.width, mBounds.height);
gfxImageFormat format = (GetContentFlags() & CONTENT_OPAQUE)
? gfxASurface::ImageFormatRGB24
: gfxASurface::ImageFormatARGB32;
nsRefPtr<gfxImageSurface> readSurf;
nsRefPtr<gfxImageSurface> resultSurf;
bool usingTempSurface = false;
if (aDestSurface) {
DiscardTempSurface();
isurf = static_cast<gfxImageSurface*>(aDestSurface);
resultSurf = static_cast<gfxImageSurface*>(aDestSurface);
if (resultSurf->GetSize() != readSize ||
resultSurf->Stride() != resultSurf->Width() * 4)
{
readSurf = GetTempSurface(readSize, format);
usingTempSurface = true;
}
} else {
nsIntSize size(mBounds.width, mBounds.height);
gfxImageFormat format = (GetContentFlags() & CONTENT_OPAQUE)
? gfxASurface::ImageFormatRGB24
: gfxASurface::ImageFormatARGB32;
isurf = GetTempSurface(size, format);
resultSurf = GetTempSurface(readSize, format);
usingTempSurface = true;
}
if (!usingTempSurface)
DiscardTempSurface();
if (!isurf || isurf->CairoStatus() != 0) {
if (!readSurf)
readSurf = resultSurf;
if (!resultSurf || resultSurf->CairoStatus() != 0)
return;
}
NS_ASSERTION(isurf->Stride() == mBounds.width * 4, "gfxImageSurface stride isn't what we expect!");
MOZ_ASSERT(readSurf);
MOZ_ASSERT(readSurf->Stride() == mBounds.width * 4, "gfxImageSurface stride isn't what we expect!");
// We need to Flush() the surface before modifying it outside of cairo.
isurf->Flush();
mGLContext->ReadScreenIntoImageSurface(isurf);
isurf->MarkDirty();
readSurf->Flush();
mGLContext->ReadScreenIntoImageSurface(readSurf);
readSurf->MarkDirty();
// If the underlying GLContext doesn't have a framebuffer into which
// premultiplied values were written, we have to do this ourselves here.
// Note that this is a WebGL attribute; GL itself has no knowledge of
// premultiplied or unpremultiplied alpha.
if (!mGLBufferIsPremultiplied)
gfxUtils::PremultiplyImageSurface(isurf);
gfxUtils::PremultiplyImageSurface(readSurf);
if (readSurf != resultSurf) {
MOZ_ASSERT(resultSurf->Width() >= readSurf->Width());
MOZ_ASSERT(resultSurf->Height() >= readSurf->Height());
resultSurf->Flush();
resultSurf->CopyFrom(readSurf);
resultSurf->MarkDirty();
}
// stick our surface into mSurface, so that the Paint() path is the same
if (!aDestSurface) {
mSurface = isurf;
mSurface = resultSurf;
}
}
}