1902ebe5eb41a350b766238b3b103c22fe9fc0fb5chudy@google.com
2902ebe5eb41a350b766238b3b103c22fe9fc0fb5chudy@google.com/*
3902ebe5eb41a350b766238b3b103c22fe9fc0fb5chudy@google.com * Copyright 2012 Google Inc.
4902ebe5eb41a350b766238b3b103c22fe9fc0fb5chudy@google.com *
5902ebe5eb41a350b766238b3b103c22fe9fc0fb5chudy@google.com * Use of this source code is governed by a BSD-style license that can be
6902ebe5eb41a350b766238b3b103c22fe9fc0fb5chudy@google.com * found in the LICENSE file.
7902ebe5eb41a350b766238b3b103c22fe9fc0fb5chudy@google.com */
8902ebe5eb41a350b766238b3b103c22fe9fc0fb5chudy@google.com
9607357fde8a9c4c70549d4223e0bd1181b012e0echudy@google.com#include "SkDebugger.h"
10770963f23f4fc313db0fa3bac18b1b8aafb55f17robertphillips@google.com#include "SkPictureRecorder.h"
112d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com#include "SkString.h"
122d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com
13902ebe5eb41a350b766238b3b103c22fe9fc0fb5chudy@google.com
14607357fde8a9c4c70549d4223e0bd1181b012e0echudy@google.comSkDebugger::SkDebugger() {
15607357fde8a9c4c70549d4223e0bd1181b012e0echudy@google.com    // Create this some other dynamic way?
16607357fde8a9c4c70549d4223e0bd1181b012e0echudy@google.com    fDebugCanvas = new SkDebugCanvas(100, 100);
17607357fde8a9c4c70549d4223e0bd1181b012e0echudy@google.com    fPicture = NULL;
18607357fde8a9c4c70549d4223e0bd1181b012e0echudy@google.com    fPictureWidth = 0;
19607357fde8a9c4c70549d4223e0bd1181b012e0echudy@google.com    fPictureHeight = 0;
20607357fde8a9c4c70549d4223e0bd1181b012e0echudy@google.com    fIndex = 0;
21607357fde8a9c4c70549d4223e0bd1181b012e0echudy@google.com}
22607357fde8a9c4c70549d4223e0bd1181b012e0echudy@google.com
23607357fde8a9c4c70549d4223e0bd1181b012e0echudy@google.comSkDebugger::~SkDebugger() {
24607357fde8a9c4c70549d4223e0bd1181b012e0echudy@google.com    // Need to inherit from SkRef object in order for following to work
25607357fde8a9c4c70549d4223e0bd1181b012e0echudy@google.com    SkSafeUnref(fDebugCanvas);
26607357fde8a9c4c70549d4223e0bd1181b012e0echudy@google.com    SkSafeUnref(fPicture);
27607357fde8a9c4c70549d4223e0bd1181b012e0echudy@google.com}
28607357fde8a9c4c70549d4223e0bd1181b012e0echudy@google.com
29607357fde8a9c4c70549d4223e0bd1181b012e0echudy@google.comvoid SkDebugger::loadPicture(SkPicture* picture) {
30607357fde8a9c4c70549d4223e0bd1181b012e0echudy@google.com    fPictureWidth = picture->width();
31607357fde8a9c4c70549d4223e0bd1181b012e0echudy@google.com    fPictureHeight = picture->height();
32607357fde8a9c4c70549d4223e0bd1181b012e0echudy@google.com    delete fDebugCanvas;
33607357fde8a9c4c70549d4223e0bd1181b012e0echudy@google.com    fDebugCanvas = new SkDebugCanvas(fPictureWidth, fPictureHeight);
34607357fde8a9c4c70549d4223e0bd1181b012e0echudy@google.com    fDebugCanvas->setBounds(fPictureWidth, fPictureHeight);
3557f74e0aa931e7784d47cba3ecc83020aa8e72b2commit-bot@chromium.org    fDebugCanvas->setPicture(picture);
36607357fde8a9c4c70549d4223e0bd1181b012e0echudy@google.com    picture->draw(fDebugCanvas);
3757f74e0aa931e7784d47cba3ecc83020aa8e72b2commit-bot@chromium.org    fDebugCanvas->setPicture(NULL);
38607357fde8a9c4c70549d4223e0bd1181b012e0echudy@google.com    fIndex = fDebugCanvas->getSize() - 1;
39607357fde8a9c4c70549d4223e0bd1181b012e0echudy@google.com    SkRefCnt_SafeAssign(fPicture, picture);
40607357fde8a9c4c70549d4223e0bd1181b012e0echudy@google.com}
41607357fde8a9c4c70549d4223e0bd1181b012e0echudy@google.com
4225bc2f86c2b94ee1f0921d90e6629d8cb22f69b7robertphillips@google.comSkPicture* SkDebugger::copyPicture() {
4325bc2f86c2b94ee1f0921d90e6629d8cb22f69b7robertphillips@google.com    // We can't just call clone here since we want to removed the "deleted"
4425bc2f86c2b94ee1f0921d90e6629d8cb22f69b7robertphillips@google.com    // commands. Playing back will strip those out.
4584b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com    SkPictureRecorder recorder;
465fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org    SkCanvas* canvas = recorder.beginRecording(fPictureWidth, fPictureHeight, NULL, 0);
4757f74e0aa931e7784d47cba3ecc83020aa8e72b2commit-bot@chromium.org
4857f74e0aa931e7784d47cba3ecc83020aa8e72b2commit-bot@chromium.org    bool vizMode = fDebugCanvas->getMegaVizMode();
4957f74e0aa931e7784d47cba3ecc83020aa8e72b2commit-bot@chromium.org    fDebugCanvas->setMegaVizMode(false);
5057f74e0aa931e7784d47cba3ecc83020aa8e72b2commit-bot@chromium.org    bool overDraw = fDebugCanvas->getOverdrawViz();
5157f74e0aa931e7784d47cba3ecc83020aa8e72b2commit-bot@chromium.org    fDebugCanvas->setOverdrawViz(false);
522a67e123a3e559774a16a58cbe5106bc0fb86740commit-bot@chromium.org    bool pathOps = fDebugCanvas->getAllowSimplifyClip();
532a67e123a3e559774a16a58cbe5106bc0fb86740commit-bot@chromium.org    fDebugCanvas->setAllowSimplifyClip(false);
5457f74e0aa931e7784d47cba3ecc83020aa8e72b2commit-bot@chromium.org    int saveCount = fDebugCanvas->getOutstandingSaveCount();
5557f74e0aa931e7784d47cba3ecc83020aa8e72b2commit-bot@chromium.org    fDebugCanvas->setOutstandingSaveCount(0);
5657f74e0aa931e7784d47cba3ecc83020aa8e72b2commit-bot@chromium.org
57607357fde8a9c4c70549d4223e0bd1181b012e0echudy@google.com    fDebugCanvas->draw(canvas);
5857f74e0aa931e7784d47cba3ecc83020aa8e72b2commit-bot@chromium.org
5957f74e0aa931e7784d47cba3ecc83020aa8e72b2commit-bot@chromium.org    int temp = fDebugCanvas->getOutstandingSaveCount();
6057f74e0aa931e7784d47cba3ecc83020aa8e72b2commit-bot@chromium.org    for (int i = 0; i < temp; ++i) {
6157f74e0aa931e7784d47cba3ecc83020aa8e72b2commit-bot@chromium.org        canvas->restore();
6257f74e0aa931e7784d47cba3ecc83020aa8e72b2commit-bot@chromium.org    }
6357f74e0aa931e7784d47cba3ecc83020aa8e72b2commit-bot@chromium.org
6457f74e0aa931e7784d47cba3ecc83020aa8e72b2commit-bot@chromium.org    fDebugCanvas->setMegaVizMode(vizMode);
6557f74e0aa931e7784d47cba3ecc83020aa8e72b2commit-bot@chromium.org    fDebugCanvas->setOverdrawViz(overDraw);
6657f74e0aa931e7784d47cba3ecc83020aa8e72b2commit-bot@chromium.org    fDebugCanvas->setOutstandingSaveCount(saveCount);
672a67e123a3e559774a16a58cbe5106bc0fb86740commit-bot@chromium.org    fDebugCanvas->setAllowSimplifyClip(pathOps);
6857f74e0aa931e7784d47cba3ecc83020aa8e72b2commit-bot@chromium.org
6984b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com    return recorder.endRecording();
70902ebe5eb41a350b766238b3b103c22fe9fc0fb5chudy@google.com}
712d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com
722d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.comvoid SkDebugger::getOverviewText(const SkTDArray<double>* typeTimes,
732d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com                                 double totTime,
74e428f9b1132c12299c204a333192495d7e748511robertphillips@google.com                                 SkString* overview,
75e428f9b1132c12299c204a333192495d7e748511robertphillips@google.com                                 int numRuns) {
762d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com    const SkTDArray<SkDrawCommand*>& commands = this->getDrawCommands();
772d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com
782d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com    SkTDArray<int> counts;
792d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com    counts.setCount(LAST_DRAWTYPE_ENUM+1);
802d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com    for (int i = 0; i < LAST_DRAWTYPE_ENUM+1; ++i) {
812d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com        counts[i] = 0;
822d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com    }
832d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com
842d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com    for (int i = 0; i < commands.count(); i++) {
852d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com        counts[commands[i]->getType()]++;
862d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com    }
872d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com
882d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com    overview->reset();
892d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com    int total = 0;
902d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com#ifdef SK_DEBUG
912d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com    double totPercent = 0, tempSum = 0;
922d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com#endif
932d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com    for (int i = 0; i < LAST_DRAWTYPE_ENUM+1; ++i) {
942d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com        if (0 == counts[i]) {
952d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com            // if there were no commands of this type then they should've consumed no time
962d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com            SkASSERT(NULL == typeTimes || 0.0 == (*typeTimes)[i]);
972d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com            continue;
982d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com        }
992d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com
1002d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com        overview->append(SkDrawCommand::GetCommandString((DrawType) i));
1012d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com        overview->append(": ");
102e428f9b1132c12299c204a333192495d7e748511robertphillips@google.com        overview->appendS32(counts[i]);
1036d9c92b2f6e5be64dd5dd98e44d672877e4c9fbcrobertphillips@google.com        if (NULL != typeTimes && totTime >= 0.0) {
1042d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com            overview->append(" - ");
105e428f9b1132c12299c204a333192495d7e748511robertphillips@google.com            overview->appendf("%.2f", (*typeTimes)[i]/(float)numRuns);
1062d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com            overview->append("ms");
1072d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com            overview->append(" - ");
1082d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com            double percent = 100.0*(*typeTimes)[i]/totTime;
109e428f9b1132c12299c204a333192495d7e748511robertphillips@google.com            overview->appendf("%.2f", percent);
1102d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com            overview->append("%");
1112d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com#ifdef SK_DEBUG
1122d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com            totPercent += percent;
1132d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com            tempSum += (*typeTimes)[i];
1142d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com#endif
1152d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com        }
1162d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com        overview->append("<br/>");
1172d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com        total += counts[i];
1182d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com    }
1192d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com#ifdef SK_DEBUG
1202d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com    if (NULL != typeTimes) {
12191274b99722d9be62e077ab979c630c23cdd04b1skia.committer@gmail.com        SkASSERT(SkScalarNearlyEqual(SkDoubleToScalar(totPercent),
122e428f9b1132c12299c204a333192495d7e748511robertphillips@google.com                                     SkDoubleToScalar(100.0)));
12391274b99722d9be62e077ab979c630c23cdd04b1skia.committer@gmail.com        SkASSERT(SkScalarNearlyEqual(SkDoubleToScalar(tempSum),
124e428f9b1132c12299c204a333192495d7e748511robertphillips@google.com                                     SkDoubleToScalar(totTime)));
1252d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com    }
1262d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com#endif
1272d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com
1282d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com    if (totTime > 0.0) {
1292d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com        overview->append("Total Time: ");
130e428f9b1132c12299c204a333192495d7e748511robertphillips@google.com        overview->appendf("%.2f", totTime/(float)numRuns);
1312d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com        overview->append("ms");
1322d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com#ifdef SK_DEBUG
1332d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com        overview->append(" ");
134e428f9b1132c12299c204a333192495d7e748511robertphillips@google.com        overview->appendScalar(SkDoubleToScalar(totPercent));
1352d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com        overview->append("% ");
1362d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com#endif
1372d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com        overview->append("<br/>");
1382d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com    }
1392d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com
1402d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com    SkString totalStr;
1412d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com    totalStr.append("Total Draw Commands: ");
142e428f9b1132c12299c204a333192495d7e748511robertphillips@google.com    totalStr.appendScalar(SkDoubleToScalar(total));
1432d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com    totalStr.append("<br/>");
1442d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com    overview->insert(0, totalStr);
1452d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com
1462d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com    overview->append("<br/>");
1472d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com    overview->append("SkPicture Width: ");
148e428f9b1132c12299c204a333192495d7e748511robertphillips@google.com    overview->appendS32(pictureWidth());
1492d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com    overview->append("px<br/>");
1502d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com    overview->append("SkPicture Height: ");
151e428f9b1132c12299c204a333192495d7e748511robertphillips@google.com    overview->appendS32(pictureHeight());
1522d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com    overview->append("px");
1532d9dbd4f78314b4b36f67d6ebbf3e0f2d9a163e3borenet@google.com}
1542a67e123a3e559774a16a58cbe5106bc0fb86740commit-bot@chromium.org
1552a67e123a3e559774a16a58cbe5106bc0fb86740commit-bot@chromium.orgvoid SkDebugger::getClipStackText(SkString* clipStack) {
1562a67e123a3e559774a16a58cbe5106bc0fb86740commit-bot@chromium.org    clipStack->set(fDebugCanvas->clipStackData());
1572a67e123a3e559774a16a58cbe5106bc0fb86740commit-bot@chromium.org}
158