From 830b8793bb1646bb76817bdc228dd8e2a92bef7d Mon Sep 17 00:00:00 2001 From: "chudy@google.com" Date: Wed, 1 Aug 2012 15:57:52 +0000 Subject: [PATCH] Optimization: SkDebugCanvas is capable of pausing and drawing incrementally instead of redrawing all commands. Review URL: https://codereview.appspot.com/6458056 git-svn-id: http://skia.googlecode.com/svn/trunk@4891 2bbb7eff-a529-9590-31e7-b0007b416f81 --- debugger/QT/SkCanvasWidget.cpp | 53 +++++++++++++++--------------------------- debugger/QT/SkCanvasWidget.h | 11 ++------- debugger/QT/SkGLWidget.cpp | 17 +++++++------- debugger/QT/SkRasterWidget.cpp | 28 ++++++++++------------ debugger/QT/SkRasterWidget.h | 3 ++- debugger/SkDebugCanvas.cpp | 42 ++++++++++++++++++++++++++------- debugger/SkDebugCanvas.h | 20 ++++++++++++++-- 7 files changed, 94 insertions(+), 80 deletions(-) diff --git a/debugger/QT/SkCanvasWidget.cpp b/debugger/QT/SkCanvasWidget.cpp index 1056bbb..2ff21b0 100644 --- a/debugger/QT/SkCanvasWidget.cpp +++ b/debugger/QT/SkCanvasWidget.cpp @@ -25,8 +25,8 @@ SkCanvasWidget::SkCanvasWidget() : QWidget() fIndex = 0; fPreviousPoint.set(0,0); - fTransform.set(0,0); - fScaleFactor = 1.0; + fUserOffset.set(0,0); + fUserScaleFactor = 1.0; setWidgetVisibility(kGPU_WidgetType, true); this->setDisabled(true); @@ -58,42 +58,37 @@ void SkCanvasWidget::loadPicture(QString filename) { fDebugCanvas = new SkDebugCanvas(picture->width(), picture->height()); picture->draw(fDebugCanvas); - fIndex = fDebugCanvas->getSize(); + fIndex = fDebugCanvas->getSize() - 1; fRasterWidget.setDebugCanvas(fDebugCanvas); fGLWidget.setDebugCanvas(fDebugCanvas); - - // TODO(chudy): Remove bounds from debug canvas storage. fDebugCanvas->setBounds(this->width(), this->height()); } void SkCanvasWidget::mouseMoveEvent(QMouseEvent* event) { SkIPoint eventPoint = SkIPoint::Make(event->globalX(), event->globalY()); - fTransform += eventPoint - fPreviousPoint; + fUserOffset += eventPoint - fPreviousPoint; fPreviousPoint = eventPoint; - updateWidgetTransform(kTranslate); + fDebugCanvas->setUserOffset(fUserOffset); drawTo(fIndex); } void SkCanvasWidget::mousePressEvent(QMouseEvent* event) { fPreviousPoint.set(event->globalX(), event->globalY()); emit hitChanged(fDebugCanvas->getCommandAtPoint(event->x(), event->y(), - fIndex, fTransform, fScaleFactor)); + fIndex)); } void SkCanvasWidget::mouseDoubleClickEvent(QMouseEvent* event) { - fTransform.set(0,0); - fScaleFactor = 1.0; - emit scaleFactorChanged(fScaleFactor); - // TODO(chudy): Change to signal / slot mechanism. resetWidgetTransform(); - drawTo(fIndex); } void SkCanvasWidget::resetWidgetTransform() { - fTransform.set(0,0); - fScaleFactor = 1.0; - updateWidgetTransform(kTranslate); - updateWidgetTransform(kScale); + fUserOffset.set(0,0); + fUserScaleFactor = 1.0; + fDebugCanvas->setUserOffset(fUserOffset); + fDebugCanvas->setUserScale(fUserScaleFactor); + emit scaleFactorChanged(fUserScaleFactor); + drawTo(fIndex); } void SkCanvasWidget::setWidgetVisibility(WidgetType type, bool isHidden) { @@ -104,27 +99,17 @@ void SkCanvasWidget::setWidgetVisibility(WidgetType type, bool isHidden) { } } -void SkCanvasWidget::updateWidgetTransform(TransformType type) { - if (type == kTranslate) { - fRasterWidget.setTranslate(fTransform); - fGLWidget.setTranslate(fTransform); - } else if (type == kScale) { - fRasterWidget.setScale(fScaleFactor); - fGLWidget.setScale(fScaleFactor); - } -} - void SkCanvasWidget::zoom(float zoomIncrement) { - fScaleFactor += zoomIncrement; + fUserScaleFactor += zoomIncrement; - /* The range of the fScaleFactor crosses over the range -1,0,1 frequently. + /* The range of the fUserScaleFactor crosses over the range -1,0,1 frequently. * Based on the code below, -1 and 1 both scale the image to it's original * size we do the following to never have a registered wheel scroll - * not effect the fScaleFactor. */ - if (fScaleFactor == 0) { - fScaleFactor = 2 * zoomIncrement; + * not effect the fUserScaleFactor. */ + if (fUserScaleFactor == 0) { + fUserScaleFactor = 2 * zoomIncrement; } - emit scaleFactorChanged(fScaleFactor); - updateWidgetTransform(kScale); + emit scaleFactorChanged(fUserScaleFactor); + fDebugCanvas->setUserScale(fUserScaleFactor); drawTo(fIndex); } diff --git a/debugger/QT/SkCanvasWidget.h b/debugger/QT/SkCanvasWidget.h index 317a007..2c34240 100644 --- a/debugger/QT/SkCanvasWidget.h +++ b/debugger/QT/SkCanvasWidget.h @@ -118,19 +118,12 @@ private: SkGLWidget fGLWidget; SkDebugCanvas* fDebugCanvas; SkIPoint fPreviousPoint; - SkIPoint fTransform; - float fScaleFactor; + SkIPoint fUserOffset; + float fUserScaleFactor; int fIndex; - enum TransformType { - kTranslate = 1 << 0, - kScale = 1 << 1, - }; - void resetWidgetTransform(); - void updateWidgetTransform(TransformType type); - void mouseMoveEvent(QMouseEvent* event); void mousePressEvent(QMouseEvent* event); diff --git a/debugger/QT/SkGLWidget.cpp b/debugger/QT/SkGLWidget.cpp index e3c4161..ff903ad 100644 --- a/debugger/QT/SkGLWidget.cpp +++ b/debugger/QT/SkGLWidget.cpp @@ -18,12 +18,14 @@ SkGLWidget::SkGLWidget() : QGLWidget() { fCurIntf = NULL; fCurContext = NULL; fGpuDevice = NULL; + fCanvas = NULL; } SkGLWidget::~SkGLWidget() { SkSafeUnref(fCurIntf); SkSafeUnref(fCurContext); SkSafeUnref(fGpuDevice); + SkSafeUnref(fCanvas); } void SkGLWidget::initializeGL() { @@ -31,6 +33,7 @@ void SkGLWidget::initializeGL() { fCurContext = GrContext::Create(kOpenGL_Shaders_GrEngine, (GrPlatform3DContext) fCurIntf); GrRenderTarget* curRenderTarget = fCurContext->createPlatformRenderTarget(getDesc(this->width(), this->height())); fGpuDevice = new SkGpuDevice(fCurContext, curRenderTarget); + fCanvas = new SkCanvas(fGpuDevice); curRenderTarget->unref(); glClearColor(1, 1, 1, 0); @@ -41,21 +44,17 @@ void SkGLWidget::initializeGL() { void SkGLWidget::resizeGL(int w, int h) { GrRenderTarget* curRenderTarget = fCurContext->createPlatformRenderTarget(getDesc(w,h)); SkSafeUnref(fGpuDevice); + SkSafeUnref(fCanvas); fGpuDevice = new SkGpuDevice(fCurContext, curRenderTarget); + fCanvas = new SkCanvas(fGpuDevice); drawTo(fIndex); } void SkGLWidget::paintGL() { glClearColor(1, 1, 1, 0); - SkCanvas canvas(fGpuDevice); - canvas.translate(fTransform.fX, fTransform.fY); - if(fScaleFactor < 0) { - canvas.scale((1.0 / -fScaleFactor),(1.0 / -fScaleFactor)); - } else if (fScaleFactor > 0) { - canvas.scale(fScaleFactor, fScaleFactor); - } - fDebugCanvas->drawTo(&canvas, fIndex); - canvas.flush(); + fDebugCanvas->drawTo(fCanvas, fIndex); + // TODO(chudy): Implement an optional flush button in Gui. + fCanvas->flush(); } GrPlatformRenderTargetDesc SkGLWidget::getDesc(int w, int h) { diff --git a/debugger/QT/SkRasterWidget.cpp b/debugger/QT/SkRasterWidget.cpp index 2cf1f34..33728d0 100644 --- a/debugger/QT/SkRasterWidget.cpp +++ b/debugger/QT/SkRasterWidget.cpp @@ -9,44 +9,40 @@ #include "SkRasterWidget.h" -SkRasterWidget::SkRasterWidget(QWidget* parent) : QWidget(parent) { +SkRasterWidget::SkRasterWidget() : QWidget() { fBitmap.setConfig(SkBitmap::kARGB_8888_Config, 800, 800); fBitmap.allocPixels(); fBitmap.eraseColor(0); fTransform.set(0,0); fScaleFactor = 1.0; fIndex = 0; - fDevice = NULL; + fDevice = new SkDevice(fBitmap); fDebugCanvas = NULL; + fCanvas = new SkCanvas(fDevice); this->setStyleSheet("QWidget {background-color: white; border: 1px solid #cccccc;}"); } SkRasterWidget::~SkRasterWidget() { - delete fDevice; + SkSafeUnref(fCanvas); + SkSafeUnref(fDevice); } void SkRasterWidget::resizeEvent(QResizeEvent* event) { fBitmap.setConfig(SkBitmap::kARGB_8888_Config, event->size().width(), event->size().height()); fBitmap.allocPixels(); - delete fDevice; + SkSafeUnref(fCanvas); + SkSafeUnref(fDevice); fDevice = new SkDevice(fBitmap); + fCanvas = new SkCanvas(fDevice); this->update(); } void SkRasterWidget::paintEvent(QPaintEvent* event) { if (fDebugCanvas) { - fBitmap.eraseColor(0); - SkCanvas canvas(fDevice); - canvas.translate(fTransform.fX, fTransform.fY); - if (fScaleFactor < 0) { - canvas.scale((1.0 / -fScaleFactor), (1.0 / -fScaleFactor)); - } else if (fScaleFactor > 0) { - canvas.scale(fScaleFactor, fScaleFactor); - } - - fMatrix = canvas.getTotalMatrix(); - fClip = canvas.getTotalClip().getBounds(); - fDebugCanvas->drawTo(&canvas, fIndex); + fDebugCanvas->drawTo(fCanvas, fIndex); + // TODO(chudy): Refactor into SkDebugCanvas. + fMatrix = fCanvas->getTotalMatrix(); + fClip = fCanvas->getTotalClip().getBounds(); QPainter painter(this); QStyleOption opt; diff --git a/debugger/QT/SkRasterWidget.h b/debugger/QT/SkRasterWidget.h index 1692800..3fca4f3 100644 --- a/debugger/QT/SkRasterWidget.h +++ b/debugger/QT/SkRasterWidget.h @@ -20,7 +20,7 @@ class SkRasterWidget : public QWidget { public: - SkRasterWidget(QWidget* parent = NULL); + SkRasterWidget(); ~SkRasterWidget(); @@ -67,6 +67,7 @@ protected: private: SkBitmap fBitmap; SkDebugCanvas* fDebugCanvas; + SkCanvas* fCanvas; SkDevice* fDevice; SkMatrix fMatrix; diff --git a/debugger/SkDebugCanvas.cpp b/debugger/SkDebugCanvas.cpp index 5fe1503..6070867 100644 --- a/debugger/SkDebugCanvas.cpp +++ b/debugger/SkDebugCanvas.cpp @@ -18,6 +18,9 @@ SkDebugCanvas::SkDebugCanvas(int width, int height) { fBm.setConfig(SkBitmap::kNo_Config, fWidth, fHeight); this->setBitmapDevice(fBm); fFilter = false; + fIndex = 0; + fUserOffset.set(0,0); + fUserScale = 1.0; } SkDebugCanvas::~SkDebugCanvas() {} @@ -34,21 +37,26 @@ void SkDebugCanvas::draw(SkCanvas* canvas) { } } } + fIndex = commandVector.size() - 1; } -int SkDebugCanvas::getCommandAtPoint(int x, int y, int index, - SkIPoint transform, float scale) { +void SkDebugCanvas::applyUserTransform(SkCanvas* canvas) { + canvas->translate(fUserOffset.fX, fUserOffset.fY); + if (fUserScale < 0) { + canvas->scale((1.0 / -fUserScale), (1.0 / -fUserScale)); + } else if (fUserScale > 0) { + canvas->scale(fUserScale, fUserScale); + } +} + +int SkDebugCanvas::getCommandAtPoint(int x, int y, int index) { SkBitmap bitmap; bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1); bitmap.allocPixels(); SkCanvas canvas(bitmap); - canvas.translate(transform.fX - x, transform.fY - y); - if (scale < 0) { - canvas.scale((1.0 / -scale), (1.0 / -scale)); - } else if (scale > 0) { - canvas.scale(scale, scale); - } + canvas.translate(-x, -y); + applyUserTransform(&canvas); int layer = 0; SkColor prev = bitmap.getColor(0,0); @@ -68,7 +76,21 @@ void SkDebugCanvas::drawTo(SkCanvas* canvas, int index) { int counter = 0; SkASSERT(!commandVector.empty()); SkASSERT(index < (int)commandVector.size()); - for (int i = 0; i <= index; i++) { + int i; + + // This only works assuming the canvas and device are the same ones that + // were previously drawn into because they need to preserve all saves + // and restores. + if (fIndex < index) { + i = fIndex + 1; + } else { + i = 0; + canvas->clear(0); + canvas->resetMatrix(); + applyUserTransform(canvas); + } + + for (; i <= index; i++) { if (i == index && fFilter) { SkPaint p; p.setColor(0xAAFFFFFF); @@ -87,6 +109,8 @@ void SkDebugCanvas::drawTo(SkCanvas* canvas, int index) { commandVector[i]->execute(canvas); } } + + fIndex = index; } SkDrawCommand* SkDebugCanvas::getDrawCommandAt(int index) { diff --git a/debugger/SkDebugCanvas.h b/debugger/SkDebugCanvas.h index c13ea10..c51e40f 100644 --- a/debugger/SkDebugCanvas.h +++ b/debugger/SkDebugCanvas.h @@ -47,8 +47,7 @@ public: /** Returns the index of the last draw command to write to the pixel at (x,y) */ - int getCommandAtPoint(int x, int y, int index, - SkIPoint transform, float scale); + int getCommandAtPoint(int x, int y, int index); /** Returns the draw command at the given index. @@ -96,6 +95,14 @@ public: fHeight = height; } + void setUserOffset(SkIPoint offset) { + fUserOffset = offset; + } + + void setUserScale(float scale) { + fUserScale = scale; + } + //////////////////////////////////////////////////////////////////////////////// // Inherited from SkCanvas //////////////////////////////////////////////////////////////////////////////// @@ -181,12 +188,21 @@ private: int fWidth; SkBitmap fBm; bool fFilter; + int fIndex; + SkIPoint fUserOffset; + float fUserScale; /** Adds the command to the classes vector of commands. @param command The draw command for execution */ void addDrawCommand(SkDrawCommand* command); + + /** + Applies any panning and zooming the user has specified before + drawing anything else into the canvas. + */ + void applyUserTransform(SkCanvas* canvas); }; #endif -- 2.7.4