14a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com/* 24a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com * Copyright 2012 Google Inc. 34a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com * 44a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com * Use of this source code is governed by a BSD-style license that can be 54a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com * found in the LICENSE file. 64a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com */ 74a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com 84a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com#include "picture_utils.h" 94a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com#include "CopyTilesRenderer.h" 104a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com#include "SkCanvas.h" 114a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com#include "SkDevice.h" 124a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com#include "SkImageEncoder.h" 1378c71272fb26852bf3d2ca31785e61d4a598af82robertphillips#include "SkMultiPictureDraw.h" 144a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com#include "SkPicture.h" 154a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com#include "SkPixelRef.h" 164a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com#include "SkRect.h" 174a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com#include "SkString.h" 184a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com 194a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.comnamespace sk_tools { 20b1aded8edd1d809cded20ff546c6e9218b43cda4krajcevski#if SK_SUPPORT_GPU 21b1aded8edd1d809cded20ff546c6e9218b43cda4krajcevski CopyTilesRenderer::CopyTilesRenderer(const GrContext::Options& opts, int x, int y) 22b1aded8edd1d809cded20ff546c6e9218b43cda4krajcevski : INHERITED(opts) 23b1aded8edd1d809cded20ff546c6e9218b43cda4krajcevski , fXTilesPerLargeTile(x) 24b1aded8edd1d809cded20ff546c6e9218b43cda4krajcevski , fYTilesPerLargeTile(y) { } 25b1aded8edd1d809cded20ff546c6e9218b43cda4krajcevski#else 264a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com CopyTilesRenderer::CopyTilesRenderer(int x, int y) 274a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com : fXTilesPerLargeTile(x) 28b1aded8edd1d809cded20ff546c6e9218b43cda4krajcevski , fYTilesPerLargeTile(y) { } 29b1aded8edd1d809cded20ff546c6e9218b43cda4krajcevski#endif 30ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips void CopyTilesRenderer::init(const SkPicture* pict, const SkString* writePath, 313f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org const SkString* mismatchPath, const SkString* inputFilename, 3278c71272fb26852bf3d2ca31785e61d4a598af82robertphillips bool useChecksumBasedFilenames, bool useMultiPictureDraw) { 33f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org // Do not call INHERITED::init(), which would create a (potentially large) canvas which is 34f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org // not used by bench_pictures. 354a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com SkASSERT(pict != NULL); 364a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com // Only work with absolute widths (as opposed to percentages). 374a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com SkASSERT(this->getTileWidth() != 0 && this->getTileHeight() != 0); 3884b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com fPicture.reset(pict)->ref(); 393f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org this->CopyString(&fWritePath, writePath); 403f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org this->CopyString(&fMismatchPath, mismatchPath); 41f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org this->CopyString(&fInputFilename, inputFilename); 42f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org fUseChecksumBasedFilenames = useChecksumBasedFilenames; 4378c71272fb26852bf3d2ca31785e61d4a598af82robertphillips fUseMultiPictureDraw = useMultiPictureDraw; 444a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com this->buildBBoxHierarchy(); 454a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com // In order to avoid allocating a large canvas (particularly important for GPU), create one 464a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com // canvas that is a multiple of the tile size, and draw portions of the picture. 474a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com fLargeTileWidth = fXTilesPerLargeTile * this->getTileWidth(); 484a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com fLargeTileHeight = fYTilesPerLargeTile * this->getTileHeight(); 494a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com fCanvas.reset(this->INHERITED::setupCanvas(fLargeTileWidth, fLargeTileHeight)); 504a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com } 514a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com 52f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org bool CopyTilesRenderer::render(SkBitmap** out) { 534a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com int i = 0; 544a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com bool success = true; 554a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com SkBitmap dst; 56c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com for (int x = 0; x < this->getViewWidth(); x += fLargeTileWidth) { 57c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com for (int y = 0; y < this->getViewHeight(); y += fLargeTileHeight) { 584a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com SkAutoCanvasRestore autoRestore(fCanvas, true); 5982ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com // Translate so that we draw the correct portion of the picture. 6082ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com // Perform a postTranslate so that the scaleFactor does not interfere with the 6182ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com // positioning. 6282ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com SkMatrix mat(fCanvas->getTotalMatrix()); 6382ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com mat.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y)); 6482ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com fCanvas->setMatrix(mat); 654a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com // Draw the picture 6678c71272fb26852bf3d2ca31785e61d4a598af82robertphillips if (fUseMultiPictureDraw) { 6778c71272fb26852bf3d2ca31785e61d4a598af82robertphillips SkMultiPictureDraw mpd; 6878c71272fb26852bf3d2ca31785e61d4a598af82robertphillips 6978c71272fb26852bf3d2ca31785e61d4a598af82robertphillips mpd.add(fCanvas, fPicture); 7078c71272fb26852bf3d2ca31785e61d4a598af82robertphillips 7178c71272fb26852bf3d2ca31785e61d4a598af82robertphillips mpd.draw(); 7278c71272fb26852bf3d2ca31785e61d4a598af82robertphillips } else { 7378c71272fb26852bf3d2ca31785e61d4a598af82robertphillips fCanvas->drawPicture(fPicture); 7478c71272fb26852bf3d2ca31785e61d4a598af82robertphillips } 754a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com // Now extract the picture into tiles 7652d9ac6c92ddf33b3b05eb77ba9509a7aa441657reed SkBitmap baseBitmap; 7752d9ac6c92ddf33b3b05eb77ba9509a7aa441657reed fCanvas->readPixels(SkIRect::MakeSize(fCanvas->getBaseLayerSize()), &baseBitmap); 784a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com SkIRect subset; 794a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com for (int tileY = 0; tileY < fLargeTileHeight; tileY += this->getTileHeight()) { 804a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com for (int tileX = 0; tileX < fLargeTileWidth; tileX += this->getTileWidth()) { 814a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com subset.set(tileX, tileY, tileX + this->getTileWidth(), 824a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com tileY + this->getTileHeight()); 834a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com SkDEBUGCODE(bool extracted =) 844a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com baseBitmap.extractSubset(&dst, subset); 854a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com SkASSERT(extracted); 863f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org if (!fWritePath.isEmpty()) { 87f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org // Similar to write() in PictureRenderer.cpp, but just encodes 884a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com // a bitmap directly. 89f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org // TODO: Share more common code with write() to do this, to properly 90f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org // write out the JSON summary, etc. 91a8e2e1504b9af6ba791637f228debaa23953064atfarina SkString pathWithNumber = SkOSPath::Join(fWritePath.c_str(), 92a8e2e1504b9af6ba791637f228debaa23953064atfarina fInputFilename.c_str()); 93f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org pathWithNumber.remove(pathWithNumber.size() - 4, 4); 944a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com pathWithNumber.appendf("%i.png", i++); 954a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com SkBitmap copy; 964a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com#if SK_SUPPORT_GPU 974a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com if (isUsingGpuDevice()) { 984a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com dst.pixelRef()->readPixels(©, &subset); 994a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com } else { 1004a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com#endif 1018a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org dst.copyTo(©); 1024a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com#if SK_SUPPORT_GPU 1034a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com } 1044a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com#endif 1054a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com success &= SkImageEncoder::EncodeFile(pathWithNumber.c_str(), copy, 1064a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com SkImageEncoder::kPNG_Type, 100); 1074a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com } 1084a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com } 1094a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com } 1104a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com } 1114a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com } 1124a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com return success; 1134a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com } 1144a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com 1154a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com SkString CopyTilesRenderer::getConfigNameInternal() { 1164a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com return SkString("copy_tiles"); 1174a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com } 1184a26d9d62a6d762a518c0ca08d43189916b75cf2scroggo@google.com} 119