Bug 1290293 - Part 1. Make assert ensuring RBGX surfaces set alpha to 0xFF only check sampled bytes. r=mchang

This commit is contained in:
Andrew Osmond 2016-08-18 09:55:45 -04:00
Родитель 8607eb6848
Коммит 8407184bc0
1 изменённых файлов: 52 добавлений и 21 удалений

Просмотреть файл

@ -139,6 +139,29 @@ WriteRGBXFormat(uint8_t* aData, const IntSize &aSize,
}
#ifdef DEBUG
static IntRect
CalculateSurfaceBounds(const IntSize &aSize, const Rect* aBounds, const Matrix* aMatrix)
{
IntRect surfaceBounds(IntPoint(0, 0), aSize);
if (!aBounds) {
return surfaceBounds;
}
MOZ_ASSERT(aMatrix);
Matrix inverse(*aMatrix);
if (!inverse.Invert()) {
return surfaceBounds;
}
IntRect bounds;
Rect sampledBounds = inverse.TransformBounds(*aBounds);
if (!sampledBounds.ToIntRect(&bounds)) {
return surfaceBounds;
}
return surfaceBounds.Intersect(bounds);
}
static bool
VerifyRGBXFormat(uint8_t* aData, const IntSize &aSize, const int32_t aStride, SurfaceFormat aFormat)
{
@ -170,27 +193,32 @@ VerifyRGBXFormat(uint8_t* aData, const IntSize &aSize, const int32_t aStride, Su
// Since checking every pixel is expensive, this only checks the four corners and center
// of a surface that their alpha value is 0xFF.
static bool
VerifyRGBXCorners(uint8_t* aData, const IntSize &aSize, const int32_t aStride, SurfaceFormat aFormat)
VerifyRGBXCorners(uint8_t* aData, const IntSize &aSize, const int32_t aStride, SurfaceFormat aFormat, const Rect* aBounds = nullptr, const Matrix* aMatrix = nullptr)
{
if (aFormat != SurfaceFormat::B8G8R8X8 || aSize.IsEmpty()) {
return true;
}
int height = aSize.height;
int width = aSize.width;
const int pixelSize = 4;
const int strideDiff = aStride - (width * pixelSize);
MOZ_ASSERT(width * pixelSize <= aStride);
IntRect bounds = CalculateSurfaceBounds(aSize, aBounds, aMatrix);
if (bounds.IsEmpty()) {
return true;
}
const int topLeft = 0;
const int topRight = width * pixelSize - pixelSize;
const int bottomRight = aStride * height - strideDiff - pixelSize;
const int bottomLeft = aStride * height - aStride;
const int height = bounds.height;
const int width = bounds.width;
const int pixelSize = 4;
MOZ_ASSERT(aSize.width * pixelSize <= aStride);
const int translation = bounds.y * aStride + bounds.x * pixelSize;
const int topLeft = translation;
const int topRight = topLeft + (width - 1) * pixelSize;
const int bottomLeft = translation + (height - 1) * aStride;
const int bottomRight = bottomLeft + (width - 1) * pixelSize;
// Lastly the center pixel
int middleRowHeight = height / 2;
int middleRowWidth = (width / 2) * pixelSize;
const int middle = aStride * middleRowHeight + middleRowWidth;
const int middleRowHeight = height / 2;
const int middleRowWidth = (width / 2) * pixelSize;
const int middle = translation + aStride * middleRowHeight + middleRowWidth;
const int offsets[] = { topLeft, topRight, bottomRight, bottomLeft, middle };
for (int offset : offsets) {
@ -198,7 +226,9 @@ VerifyRGBXCorners(uint8_t* aData, const IntSize &aSize, const int32_t aStride, S
int row = offset / aStride;
int column = (offset % aStride) / pixelSize;
gfxCriticalError() << "RGBX corner pixel at (" << column << "," << row << ") in "
<< width << "x" << height << " surface is not opaque: "
<< aSize.width << "x" << aSize.height << " surface, bounded by "
<< "(" << bounds.x << "," << bounds.y << "," << width << ","
<< height << ") is not opaque: "
<< int(aData[offset]) << ","
<< int(aData[offset+1]) << ","
<< int(aData[offset+2]) << ","
@ -211,7 +241,7 @@ VerifyRGBXCorners(uint8_t* aData, const IntSize &aSize, const int32_t aStride, S
#endif
static sk_sp<SkImage>
GetSkImageForSurface(SourceSurface* aSurface)
GetSkImageForSurface(SourceSurface* aSurface, const Rect* aBounds = nullptr, const Matrix* aMatrix = nullptr)
{
if (!aSurface) {
gfxDebug() << "Creating null Skia image from null SourceSurface";
@ -238,7 +268,8 @@ GetSkImageForSurface(SourceSurface* aSurface)
// Skia doesn't support RGBX surfaces so ensure that the alpha value is opaque white.
MOZ_ASSERT(VerifyRGBXCorners(surf->GetData(), surf->GetSize(),
surf->Stride(), surf->GetFormat()));
surf->Stride(), surf->GetFormat(),
aBounds, aMatrix));
return image;
}
@ -410,7 +441,7 @@ ExtractAlphaForSurface(SourceSurface* aSurface)
}
static void
SetPaintPattern(SkPaint& aPaint, const Pattern& aPattern, Float aAlpha = 1.0, Point aOffset = Point(0, 0))
SetPaintPattern(SkPaint& aPaint, const Pattern& aPattern, Float aAlpha = 1.0, Point aOffset = Point(0, 0), const Rect* aBounds = nullptr)
{
switch (aPattern.GetType()) {
case PatternType::COLOR: {
@ -472,7 +503,7 @@ SetPaintPattern(SkPaint& aPaint, const Pattern& aPattern, Float aAlpha = 1.0, Po
}
case PatternType::SURFACE: {
const SurfacePattern& pat = static_cast<const SurfacePattern&>(aPattern);
sk_sp<SkImage> image = GetSkImageForSurface(pat.mSurface);
sk_sp<SkImage> image = GetSkImageForSurface(pat.mSurface, aBounds, &pat.mMatrix);
if (!image) {
aPaint.setColor(SK_ColorTRANSPARENT);
break;
@ -520,11 +551,11 @@ GetClipBounds(SkCanvas *aCanvas)
}
struct AutoPaintSetup {
AutoPaintSetup(SkCanvas *aCanvas, const DrawOptions& aOptions, const Pattern& aPattern, const Rect* aMaskBounds = nullptr, Point aOffset = Point(0, 0))
AutoPaintSetup(SkCanvas *aCanvas, const DrawOptions& aOptions, const Pattern& aPattern, const Rect* aMaskBounds = nullptr, Point aOffset = Point(0, 0), const Rect* aSourceBounds = nullptr)
: mNeedsRestore(false), mAlpha(1.0)
{
Init(aCanvas, aOptions, aMaskBounds, false);
SetPaintPattern(mPaint, aPattern, mAlpha, aOffset);
SetPaintPattern(mPaint, aPattern, mAlpha, aOffset, aSourceBounds);
}
AutoPaintSetup(SkCanvas *aCanvas, const DrawOptions& aOptions, const Rect* aMaskBounds = nullptr, bool aForceGroup = false)
@ -753,7 +784,7 @@ DrawTargetSkia::FillRect(const Rect &aRect,
MarkChanged();
SkRect rect = RectToSkRect(aRect);
AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern, &aRect);
AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern, &aRect, Point(0, 0), &aRect);
mCanvas->drawRect(rect, paint.mPaint);
}