46616af01b
Feature-wise, this removes: 1) BBH support; 2) peephole optimizations; 3) record-time text op specializations; 4) the guarantee that SkPaints are flattened. This deletes the optimizations GM, which only exists to test the peepholes of the old backend. SkRecord optimizations are unit tested, and if that ever fails we can think about adding another GM like this, but they're different enough we'd want to start from scratch anyway. We need to keep the code that plays back the specialized text ops around for a while for compatibility with existing .SKPs that have those ops recorded. BUG=skia: CQ_EXTRA_TRYBOTS=tryserver.skia:Canary-Chrome-Ubuntu13.10-Ninja-x86_64-ToT-Trybot R=robertphillips@google.com, reed@google.com, mtklein@google.com Author: mtklein@chromium.org Review URL: https://codereview.chromium.org/617953002
176 lines
5.8 KiB
C++
176 lines
5.8 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/SkCanvas.h"
|
|
#include "../include/core/SkPicture.h"
|
|
#include "../include/core/SkStream.h"
|
|
#include "../include/core/SkString.h"
|
|
#include "../include/record/SkRecording.h"
|
|
#include "../include/core/SkPictureRecorder.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, SkXfermode::Mode mode) const {
|
|
SkPaint greenPaint;
|
|
greenPaint.setColor(0xff008000);
|
|
SkPaint blackPaint;
|
|
blackPaint.setColor(0xff000000);
|
|
SkPaint whitePaint;
|
|
whitePaint.setColor(0xffffffff);
|
|
SkPaint layerPaint;
|
|
layerPaint.setColor(0xff000000);
|
|
layerPaint.setXfermodeMode(mode);
|
|
SkRect canvasRect(SkRect::MakeWH(SkIntToScalar(fImageInfo.width()),
|
|
SkIntToScalar(fImageInfo.height())));
|
|
|
|
canvas->clipRect(clipRect);
|
|
canvas->clear(0xff000000);
|
|
|
|
canvas->saveLayer(NULL, &blackPaint);
|
|
canvas->drawRect(canvasRect, greenPaint);
|
|
canvas->saveLayer(NULL, &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,
|
|
SkXfermode::Mode) = 0;
|
|
};
|
|
|
|
class BitmapBackedCanvasStrategy : public RecordingStrategy {
|
|
// This version just draws into a bitmap-backed canvas.
|
|
public:
|
|
BitmapBackedCanvasStrategy(const SkImageInfo& imageInfo) {
|
|
fBitmap.allocPixels(imageInfo);
|
|
}
|
|
|
|
virtual const SkBitmap& recordAndReplay(const Drawer& drawer,
|
|
const SkRect& intoClip,
|
|
SkXfermode::Mode mode) {
|
|
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();
|
|
}
|
|
|
|
virtual const SkBitmap& recordAndReplay(const Drawer& drawer,
|
|
const SkRect& intoClip,
|
|
SkXfermode::Mode mode) {
|
|
SkTileGridFactory::TileGridInfo tileGridInfo = { {100,100}, {0,0}, {0,0} };
|
|
SkTileGridFactory factory(tileGridInfo);
|
|
SkPictureRecorder recorder;
|
|
SkRect canvasRect(SkRect::MakeWH(SkIntToScalar(fWidth),SkIntToScalar(fHeight)));
|
|
SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(fWidth),
|
|
SkIntToScalar(fHeight),
|
|
&factory);
|
|
drawer.draw(canvas, canvasRect, mode);
|
|
SkAutoTDelete<SkPicture> picture(recorder.endRecording());
|
|
|
|
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(SkXfermode::kLastMode); iMode++) {
|
|
const SkRect& clip = SkRect::MakeXYWH(100, 0, 100, 100);
|
|
SkXfermode::Mode mode = SkXfermode::Mode(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, SkXfermode::ModeName(mode));
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#if !FINEGRAIN
|
|
REPORTER_ASSERT_MESSAGE(reporter, 0 == numErrors, errors.c_str());
|
|
#endif
|
|
}
|