Index: gm/gmmain.cpp |
diff --git a/gm/gmmain.cpp b/gm/gmmain.cpp |
index 46b039d1647df1536fdc22ef8ca1b23a8a6f0103..da4184db673d9364688ef91f227d57ac871984cc 100644 |
--- a/gm/gmmain.cpp |
+++ b/gm/gmmain.cpp |
@@ -35,6 +35,7 @@ |
#include "SkImageDecoder.h" |
#include "SkImageEncoder.h" |
#include "SkJSONCPP.h" |
+#include "SkMultiPictureDraw.h" |
#include "SkOSFile.h" |
#include "SkPDFRasterizer.h" |
#include "SkPicture.h" |
@@ -481,7 +482,7 @@ public: |
* (logically a noop for rasters, if wasted time), and thus collapse the |
* GPU special case and also let this be used for SkPicture testing. |
*/ |
- static void setup_bitmap(const ConfigData& gRec, SkISize& size, |
+ static void setup_bitmap(const ConfigData& gRec, const SkISize& size, |
SkBitmap* bitmap) { |
bitmap->allocPixels(SkImageInfo::Make(size.width(), size.height(), |
gRec.fColorType, kPremul_SkAlphaType)); |
@@ -548,7 +549,7 @@ public: |
force_all_opaque(*bitmap); |
} |
- static void installFilter(SkCanvas* canvas); |
+ static void InstallFilter(SkCanvas* canvas); |
static void invokeGM(GM* gm, SkCanvas* canvas, bool isPDF, bool isDeferred) { |
SkAutoCanvasRestore acr(canvas, true); |
@@ -556,7 +557,7 @@ public: |
if (!isPDF) { |
canvas->concat(gm->getInitialTransform()); |
} |
- installFilter(canvas); |
+ InstallFilter(canvas); |
gm->setCanvasIsDeferred(isDeferred); |
gm->draw(canvas); |
canvas->setDrawFilter(NULL); |
@@ -566,46 +567,92 @@ public: |
GrSurface* gpuTarget, |
SkBitmap* bitmap, |
bool deferred) { |
- SkISize size (gm->getISize()); |
- setup_bitmap(gRec, size, bitmap); |
- const SkImageInfo info = bitmap->info(); |
+ const SkISize size (gm->getISize()); |
- SkAutoTUnref<SkSurface> surface; |
+ SkAutoTUnref<SkSurface> surface(CreateSurface(gRec, size, gpuTarget)); |
SkAutoTUnref<SkCanvas> canvas; |
- if (gRec.fBackend == kRaster_Backend) { |
- surface.reset(SkSurface::NewRasterDirect(info, |
- bitmap->getPixels(), |
- bitmap->rowBytes())); |
- if (deferred) { |
- canvas.reset(SkDeferredCanvas::Create(surface)); |
- } else { |
- canvas.reset(SkRef(surface->getCanvas())); |
- } |
- invokeGM(gm, canvas, false, deferred); |
- canvas->flush(); |
+ if (deferred) { |
+ canvas.reset(SkDeferredCanvas::Create(surface)); |
+ } else { |
+ canvas.reset(SkRef(surface->getCanvas())); |
} |
-#if SK_SUPPORT_GPU |
- else { // GPU |
- uint32_t flags = (gRec.fFlags & kDFText_ConfigFlag) ? |
- SkSurfaceProps::kUseDistanceFieldFonts_Flag : 0; |
- SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType); |
- surface.reset(SkSurface::NewRenderTargetDirect(gpuTarget->asRenderTarget(), &props)); |
- if (deferred) { |
- canvas.reset(SkDeferredCanvas::Create(surface)); |
+ invokeGM(gm, canvas, false, deferred); |
+ canvas->flush(); |
+ |
+ setup_bitmap(gRec, size, bitmap); |
+ surface->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), 0, 0); |
+ complete_bitmap(bitmap); |
+ return kEmpty_ErrorCombination; |
+ } |
+ |
+ static void DrawPictureToSurface(SkSurface* surf, |
+ const SkPicture* pict, |
+ SkScalar scale, |
+ bool tile, |
+ bool useMPD) { |
+ SkASSERT(surf->width() == pict->cullRect().width() && |
+ surf->height() == pict->cullRect().height()); |
+ |
+ if (tile) { |
+ SkMultiPictureDraw mpd; |
+ SkTDArray<SkSurface*> surfaces; |
+ |
+ const SkISize tileSize = SkISize::Make(16, 16); |
+ |
+ const SkImageInfo ii = surf->getCanvas()->imageInfo().makeWH(tileSize.width(), |
+ tileSize.height()); |
+ |
+ for (int tileY = 0; tileY < pict->cullRect().height(); tileY += tileSize.height()) { |
+ for (int tileX = 0; tileX < pict->cullRect().width(); tileX += tileSize.width()) { |
+ |
+ *surfaces.append() = surf->getCanvas()->newSurface(ii); |
+ |
+ InstallFilter(surfaces.top()->getCanvas()); |
+ |
+ SkMatrix matrix; |
+ matrix.setTranslate(-pict->cullRect().fLeft, -pict->cullRect().fTop); |
+ matrix.postTranslate(-SkIntToScalar(tileX), -SkIntToScalar(tileY)); |
+ matrix.postScale(scale, scale); |
+ |
+ if (useMPD) { |
+ mpd.add(surfaces.top()->getCanvas(), pict, &matrix, NULL); |
+ } else { |
+ surfaces.top()->getCanvas()->drawPicture(pict, &matrix, NULL); |
+ } |
+ } |
+ } |
+ |
+ mpd.draw(); |
+ |
+ SkPaint gatherPaint; |
+ gatherPaint.setXfermodeMode(SkXfermode::kSrc_Mode); |
+ |
+ int tileIndex = 0; |
+ for (int tileY = 0; tileY < pict->cullRect().height(); tileY += tileSize.height()) { |
+ for (int tileX = 0; tileX < pict->cullRect().width(); tileX += tileSize.width()) { |
+ surf->getCanvas()->drawImage(surfaces[tileIndex]->newImageSnapshot(), |
+ SkIntToScalar(tileX), SkIntToScalar(tileY), |
+ &gatherPaint); |
+ surfaces[tileIndex]->unref(); |
+ tileIndex++; |
+ } |
+ } |
+ } else { |
+ InstallFilter(surf->getCanvas()); |
+ |
+ SkMatrix matrix; |
+ matrix.setTranslate(-pict->cullRect().fLeft, -pict->cullRect().fTop); |
+ matrix.postScale(scale, scale); |
+ |
+ if (useMPD) { |
+ SkMultiPictureDraw mpd; |
+ mpd.add(surf->getCanvas(), pict, &matrix, NULL); |
+ mpd.draw(); |
} else { |
- canvas.reset(SkRef(surface->getCanvas())); |
+ surf->getCanvas()->drawPicture(pict, &matrix, NULL); |
} |
- invokeGM(gm, canvas, false, deferred); |
- // the device is as large as the current rendertarget, so |
- // we explicitly only readback the amount we expect (in |
- // size) overwrite our previous allocation |
- bitmap->setInfo(SkImageInfo::MakeN32Premul(size.fWidth, size.fHeight)); |
- canvas->readPixels(bitmap, 0, 0); |
} |
-#endif |
- complete_bitmap(bitmap); |
- return kEmpty_ErrorCombination; |
} |
static void generate_image_from_picture(GM* gm, const ConfigData& gRec, |
@@ -615,46 +662,12 @@ public: |
SkISize size = gm->getISize(); |
setup_bitmap(gRec, size, bitmap); |
- if (tile) { |
- // Generate the result image by rendering to tiles and accumulating |
- // the results in 'bitmap' |
- |
- // This 16x16 tiling matches the settings applied to 'pict' in |
- // 'generate_new_picture' |
- SkISize tileSize = SkISize::Make(16, 16); |
- |
- SkBitmap tileBM; |
- setup_bitmap(gRec, tileSize, &tileBM); |
- SkCanvas tileCanvas(tileBM); |
- installFilter(&tileCanvas); |
- |
- SkCanvas bmpCanvas(*bitmap); |
- SkPaint bmpPaint; |
- bmpPaint.setXfermodeMode(SkXfermode::kSrc_Mode); |
- |
- for (int yTile = 0; yTile < (size.height()+15)/16; ++yTile) { |
- for (int xTile = 0; xTile < (size.width()+15)/16; ++xTile) { |
- int saveCount = tileCanvas.save(); |
- SkMatrix mat(tileCanvas.getTotalMatrix()); |
- mat.postTranslate(SkIntToScalar(-xTile*tileSize.width()), |
- SkIntToScalar(-yTile*tileSize.height())); |
- tileCanvas.setMatrix(mat); |
- pict->playback(&tileCanvas); |
- tileCanvas.flush(); |
- tileCanvas.restoreToCount(saveCount); |
- bmpCanvas.drawBitmap(tileBM, |
- SkIntToScalar(xTile * tileSize.width()), |
- SkIntToScalar(yTile * tileSize.height()), |
- &bmpPaint); |
- } |
- } |
- } else { |
- SkCanvas canvas(*bitmap); |
- installFilter(&canvas); |
- canvas.scale(scale, scale); |
- canvas.drawPicture(pict); |
- complete_bitmap(bitmap); |
- } |
+ SkAutoTUnref<SkSurface> surf(SkSurface::NewRasterDirect(bitmap->info(), |
+ bitmap->getPixels(), |
+ bitmap->rowBytes())); |
+ |
+ DrawPictureToSurface(surf, pict, scale, tile, false); |
+ complete_bitmap(bitmap); |
} |
static bool generate_pdf(GM* gm, SkDynamicMemoryWStream& pdf) { |
@@ -1169,6 +1182,52 @@ public: |
return kEmpty_ErrorCombination; |
} |
+ static SkSurface* CreateSurface(const ConfigData& config, |
+ const SkISize& size, |
+ GrSurface* gpuTarget) { |
+ if (config.fBackend == kRaster_Backend) { |
+ SkImageInfo ii = SkImageInfo::Make(size.width(), size.height(), |
+ config.fColorType, kPremul_SkAlphaType); |
+ |
+ return SkSurface::NewRaster(ii); |
+ } |
+#if SK_SUPPORT_GPU |
+ else { |
+ uint32_t flags = (config.fFlags & kDFText_ConfigFlag) ? |
+ SkSurfaceProps::kUseDistanceFieldFonts_Flag : 0; |
+ SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType); |
+ return SkSurface::NewRenderTargetDirect(gpuTarget->asRenderTarget(), &props); |
+ } |
+#endif |
+ |
+ return NULL; |
+ } |
+ |
+ ErrorCombination testMPDDrawing(GM* gm, |
+ const ConfigData& config, |
+ GrSurface* gpuTarget, |
+ const SkBitmap& referenceBitmap) { |
+ SkASSERT(kRaster_Backend == config.fBackend || kGPU_Backend == config.fBackend); |
+ |
+ static const uint32_t kMPDFlags = SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag; |
+ |
+ SkAutoTUnref<SkPicture> pict(generate_new_picture(gm, kRTree_BbhType, kMPDFlags)); |
+ |
+ SkAutoTUnref<SkSurface> surf(CreateSurface(config, gm->getISize(), gpuTarget)); |
+ |
+ DrawPictureToSurface(surf, pict, SK_Scalar1, false, true); |
+ |
+ SkBitmap bitmap; |
+ |
+ setup_bitmap(config, gm->getISize(), &bitmap); |
+ |
+ surf->readPixels(bitmap.info(), bitmap.getPixels(), bitmap.rowBytes(), 0, 0); |
+ complete_bitmap(&bitmap); |
+ |
+ return compare_test_results_to_reference_bitmap( |
+ gm->getName(), config.fName, "-mpd", bitmap, &referenceBitmap); |
+ } |
+ |
ErrorCombination test_pipe_playback(GM* gm, const ConfigData& gRec, |
const SkBitmap& referenceBitmap, bool simulateFailure) { |
const SkString shortNamePlusConfig = make_shortname_plus_config(gm->getName(), |
@@ -1189,7 +1248,7 @@ public: |
SkISize size = gm->getISize(); |
setup_bitmap(gRec, size, &bitmap); |
SkCanvas canvas(bitmap); |
- installFilter(&canvas); |
+ InstallFilter(&canvas); |
// Pass a decoding function so the factory GM (which has an SkBitmap |
// with encoded data) will not fail playback. |
PipeController pipeController(&canvas, &SkImageDecoder::DecodeMemory); |
@@ -1232,7 +1291,7 @@ public: |
SkISize size = gm->getISize(); |
setup_bitmap(gRec, size, &bitmap); |
SkCanvas canvas(bitmap); |
- installFilter(&canvas); |
+ InstallFilter(&canvas); |
TiledPipeController pipeController(bitmap, &SkImageDecoder::DecodeMemory); |
SkGPipeWriter writer; |
SkCanvas* pipeCanvas = writer.startRecording(&pipeController, |
@@ -1432,6 +1491,8 @@ DEFINE_string(config, "", configUsage().c_str()); |
DEFINE_bool(cpu, true, "Allows non-GPU configs to be run. Applied after --config."); |
DEFINE_string(pdfRasterizers, "default", pdfRasterizerUsage().c_str()); |
DEFINE_bool(deferred, false, "Exercise the deferred rendering test pass."); |
+DEFINE_bool(mpd, false, "Exercise MultiPictureDraw."); |
+ |
DEFINE_bool(dryRun, false, "Don't actually run the tests, just print what would have been done."); |
DEFINE_string(excludeConfig, "", "Space delimited list of configs to skip."); |
DEFINE_bool(forceBWtext, false, "Disable text anti-aliasing."); |
@@ -1823,6 +1884,19 @@ ErrorCombination run_multiple_configs(GMMain &gmmain, GM *gm, |
gpuTarget)); |
} |
+ if (FLAGS_mpd && (kGPU_Backend == config.fBackend || kRaster_Backend == config.fBackend)) { |
+ |
+ if (gmFlags & GM::kSkipPicture_Flag) { |
+ gmmain.RecordSkippedTest(shortNamePlusConfig, |
+ renderModeDescriptor, |
+ config.fBackend); |
+ errorsForThisConfig.add(kIntentionallySkipped_ErrorType); |
+ } else if (!(gmFlags & GM::kGPUOnly_Flag)) { |
+ errorsForThisConfig.add(gmmain.testMPDDrawing(gm, config, gpuTarget, |
+ comparisonBitmap)); |
+ } |
+ } |
+ |
errorsForAllConfigs.add(errorsForThisConfig); |
} |
return errorsForAllConfigs; |
@@ -2486,7 +2560,7 @@ int tool_main(int argc, char** argv) { |
return (reportError) ? -1 : 0; |
} |
-void GMMain::installFilter(SkCanvas* canvas) { |
+void GMMain::InstallFilter(SkCanvas* canvas) { |
if (FLAGS_forceBWtext) { |
canvas->setDrawFilter(SkNEW(BWTextDrawFilter))->unref(); |
} |