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
This commit is contained in:
chudy@google.com 2012-08-01 15:57:52 +00:00
parent 6385314686
commit 830b8793bb
7 changed files with 94 additions and 80 deletions

View File

@ -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);
}

View File

@ -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);

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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