skia2/tests/RecordingXfermodeTest.cpp
Greg Daniel f46633f8af Revert "guard old apis for querying byte-size of a bitmap/imageinfo/pixmap"
This reverts commit 98a6216b18.

Reason for revert: breaking the chrome roll. Looks like they may be writing data to create an image across all the row bytes and thus writing to unalloced data on the last row. Link to example failing bot:
 https://build.chromium.org/p/tryserver.chromium.win/builders/win_chromium_rel_ng/builds/539960

Original change's description:
> guard old apis for querying byte-size of a bitmap/imageinfo/pixmap
> 
> Previously we had size_t and uint64_t variations.
> 
> The new (simpler) API always..
> - returns size_t, or 0 if the calculation overflowed
> - returns the trimmed size (does not include rowBytes padding for the last row)
> 
> Bug: skia:
> Change-Id: I05173e877918327c7b207d2f7f1ab0db36892e2e
> Reviewed-on: https://skia-review.googlesource.com/50980
> Commit-Queue: Mike Reed <reed@google.com>
> Reviewed-by: Florin Malita <fmalita@chromium.org>
> Reviewed-by: Leon Scroggins <scroggo@google.com>

TBR=mtklein@google.com,herb@google.com,scroggo@google.com,fmalita@chromium.org,reed@google.com

Change-Id: I726f6ab1b36b14979ba6f37105e0a469b3f0dbc0
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:
Reviewed-on: https://skia-review.googlesource.com/51262
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
2017-09-26 20:08:07 +00:00

174 lines
5.6 KiB
C++

/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "Test.h"
#include "../include/core/SkBitmap.h"
#include "../include/core/SkCanvas.h"
#include "../include/core/SkPicture.h"
#include "../include/core/SkStream.h"
#include "../include/core/SkString.h"
#include "../include/core/SkPictureRecorder.h"
#include "../src/core/SkBlendModePriv.h"
#include <cstring>
// Verify that replay of a recording into a clipped canvas
// produces the correct bitmap.
// This arose from http://crbug.com/401593 which has
// https://code.google.com/p/skia/issues/detail?id=1291 as its root cause.
namespace {
class Drawer {
public:
explicit Drawer() : fImageInfo(SkImageInfo::MakeN32Premul(200, 100)) {
fCircleBM.allocPixels(SkImageInfo::MakeN32Premul(100, 100));
SkCanvas canvas(fCircleBM);
canvas.clear(0xffffffff);
SkPaint circlePaint;
circlePaint.setColor(0xff000000);
canvas.drawCircle(50, 50, 50, circlePaint);
}
const SkImageInfo& imageInfo() const { return fImageInfo; }
void draw(SkCanvas* canvas, const SkRect& clipRect, SkBlendMode mode) const {
SkPaint greenPaint;
greenPaint.setColor(0xff008000);
SkPaint blackPaint;
blackPaint.setColor(0xff000000);
SkPaint whitePaint;
whitePaint.setColor(0xffffffff);
SkPaint layerPaint;
layerPaint.setColor(0xff000000);
layerPaint.setBlendMode(mode);
SkRect canvasRect(SkRect::MakeWH(SkIntToScalar(fImageInfo.width()),
SkIntToScalar(fImageInfo.height())));
canvas->clipRect(clipRect);
canvas->clear(0xff000000);
canvas->saveLayer(nullptr, &blackPaint);
canvas->drawRect(canvasRect, greenPaint);
canvas->saveLayer(nullptr, &layerPaint);
canvas->drawBitmapRect(fCircleBM, SkRect::MakeXYWH(20,20,60,60), &blackPaint);
canvas->restore();
canvas->restore();
}
private:
const SkImageInfo fImageInfo;
SkBitmap fCircleBM;
};
class RecordingStrategy {
public:
virtual ~RecordingStrategy() {}
virtual const SkBitmap& recordAndReplay(const Drawer& drawer,
const SkRect& intoClip,
SkBlendMode) = 0;
};
class BitmapBackedCanvasStrategy : public RecordingStrategy {
// This version just draws into a bitmap-backed canvas.
public:
BitmapBackedCanvasStrategy(const SkImageInfo& imageInfo) {
fBitmap.allocPixels(imageInfo);
}
const SkBitmap& recordAndReplay(const Drawer& drawer, const SkRect& intoClip,
SkBlendMode mode) override {
SkCanvas canvas(fBitmap);
canvas.clear(0xffffffff);
// Note that the scene is drawn just into the clipped region!
canvas.clipRect(intoClip);
drawer.draw(&canvas, intoClip, mode); // Shouild be canvas-wide...
return fBitmap;
}
private:
SkBitmap fBitmap;
};
class PictureStrategy : public RecordingStrategy {
// This version draws the entire scene into an SkPictureRecorder.
// Then it then replays the scene through a clip rectangle.
// This backend proved to be buggy.
public:
PictureStrategy(const SkImageInfo& imageInfo) {
fBitmap.allocPixels(imageInfo);
fWidth = imageInfo.width();
fHeight = imageInfo.height();
}
const SkBitmap& recordAndReplay(const Drawer& drawer, const SkRect& intoClip,
SkBlendMode mode) override {
SkRTreeFactory factory;
SkPictureRecorder recorder;
SkRect canvasRect(SkRect::MakeWH(SkIntToScalar(fWidth),SkIntToScalar(fHeight)));
SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(fWidth),
SkIntToScalar(fHeight),
&factory);
drawer.draw(canvas, canvasRect, mode);
sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
SkCanvas replayCanvas(fBitmap);
replayCanvas.clear(0xffffffff);
replayCanvas.clipRect(intoClip);
picture->playback(&replayCanvas);
return fBitmap;
}
private:
SkBitmap fBitmap;
int fWidth;
int fHeight;
};
} // namespace
DEF_TEST(SkRecordingAccuracyXfermode, reporter) {
#define FINEGRAIN 0
const Drawer drawer;
BitmapBackedCanvasStrategy golden(drawer.imageInfo());
PictureStrategy picture(drawer.imageInfo());
#if !FINEGRAIN
unsigned numErrors = 0;
SkString errors;
#endif
for (int iMode = 0; iMode < int(SkBlendMode::kLastMode); iMode++) {
const SkRect& clip = SkRect::MakeXYWH(100, 0, 100, 100);
SkBlendMode mode = SkBlendMode(iMode);
const SkBitmap& goldenBM = golden.recordAndReplay(drawer, clip, mode);
const SkBitmap& pictureBM = picture.recordAndReplay(drawer, clip, mode);
size_t pixelsSize = goldenBM.getSize();
REPORTER_ASSERT(reporter, pixelsSize == pictureBM.getSize());
// The pixel arrays should match.
#if FINEGRAIN
REPORTER_ASSERT(reporter,
0 == memcmp(goldenBM.getPixels(), pictureBM.getPixels(), pixelsSize));
#else
if (memcmp(goldenBM.getPixels(), pictureBM.getPixels(), pixelsSize)) {
numErrors++;
errors.appendf("For SkXfermode %d %s: SkPictureRecorder bitmap is wrong\n",
iMode, SkBlendMode_Name(mode));
}
#endif
}
#if !FINEGRAIN
REPORTER_ASSERT_MESSAGE(reporter, 0 == numErrors, errors.c_str());
#endif
}