skia2/experimental/Debugger/DebuggerContentView.cpp
junov@chromium.org fb10389403 Adding a silent playback option to SkGPipeRead
Testing state consistency after silent playback in CanvasTest indirectly
through SkDeferredCanvas.

BUG=http://code.google.com/p/chromium/issues/detail?id=146178
TEST=CanvasTest unit test, and bench with --mode deferredSilent
Review URL: https://codereview.appspot.com/6542047

git-svn-id: http://skia.googlecode.com/svn/trunk@5619 2bbb7eff-a529-9590-31e7-b0007b416f81
2012-09-20 19:35:43 +00:00

274 lines
9.7 KiB
C++

#include "SampleCode.h"
#include "SkOSMenu.h"
#include "DebuggerViews.h"
static const char gIsDebuggerQuery[] = "is-debugger";
class DebuggerView : public SampleView {
public:
DebuggerView(const char* data, size_t size) {
fData.append(size, data);
fCommandsVisible = true;
fCommandsResizing = false;
fStateVisible = true;
fStateResizing = false;
fCommands = new DebuggerCommandsView;
fCommands->setVisibleP(fCommandsVisible);
this->attachChildToFront(fCommands)->unref();
fState = new DebuggerStateView;
fState->setVisibleP(fStateVisible);
this->attachChildToFront(fState)->unref();
fAtomsToRead = 0;
fDisplayClip = false;
fDumper = new SkDebugDumper(this->getSinkID(), fCommands->getSinkID(),
fState->getSinkID());
fDumper->unload();
fAtomBounds.reset();
fFrameBounds.reset();
SkDumpCanvas* dumpCanvas = new SkDumpCanvas(fDumper);
SkGPipeReader* dumpReader = new SkGPipeReader(dumpCanvas);
if (size > 0) {
int offset = 0;
int frameBound = 0;
size_t bytesRead;
while (static_cast<unsigned>(offset) < size) {
SkGPipeReader::Status s =
dumpReader->playback(data + offset, size - offset,
SkGPipeReader::kReadAtom_PlaybackFlag, &bytesRead);
SkASSERT(SkGPipeReader::kError_Status != s);
offset += bytesRead;
if (SkGPipeReader::kDone_Status == s) {
fDumper->dump(dumpCanvas, SkDumpCanvas::kNULL_Verb,
"End of Frame", NULL);
delete dumpReader;
delete dumpCanvas;
dumpCanvas = new SkDumpCanvas(fDumper);
dumpReader = new SkGPipeReader(dumpCanvas);
frameBound = offset;
}
fAtomBounds.append(1, &offset);
fFrameBounds.append(1, &frameBound);
}
}
delete dumpReader;
delete dumpCanvas;
fDumper->load();
}
~DebuggerView() {
fAtomBounds.reset();
fFrameBounds.reset();
delete fDumper;
}
virtual void requestMenu(SkOSMenu* menu) {
menu->setTitle("Debugger");
menu->appendSwitch("Show Commands", "Commands", this->getSinkID(), fCommandsVisible);
menu->appendSwitch("Show State", "State", this->getSinkID(), fStateVisible);
menu->appendSwitch("Display Clip", "Clip", this->getSinkID(), fDisplayClip);
}
void goToAtom(int atom) {
if (atom != fAtomsToRead) {
fAtomsToRead = atom;
this->inval(NULL);
}
}
protected:
virtual bool onQuery(SkEvent* evt) {
if (SampleCode::TitleQ(*evt)) {
SampleCode::TitleR(evt, "Debugger");
return true;
}
if (evt->isType(gIsDebuggerQuery)) {
return true;
}
return this->INHERITED::onQuery(evt);
}
virtual bool onEvent(const SkEvent& evt) {
if (SkOSMenu::FindSwitchState(evt, "Commands", &fCommandsVisible) ||
SkOSMenu::FindSwitchState(evt, "State", &fStateVisible)) {
fCommands->setVisibleP(fCommandsVisible);
fState->setVisibleP(fStateVisible);
fStateOffset = (fCommandsVisible) ? fCommands->width() : 0;
fState->setSize(this->width() - fStateOffset, fState->height());
fState->setLoc(fStateOffset, this->height() - fState->height());
this->inval(NULL);
return true;
}
if (SkOSMenu::FindSwitchState(evt, "Clip", &fDisplayClip)) {
this->inval(NULL);
return true;
}
return this->INHERITED::onEvent(evt);
}
virtual void onDrawContent(SkCanvas* canvas) {
if (fData.count() <= 0)
return;
SkAutoCanvasRestore acr(canvas, true);
canvas->translate(fStateOffset, 0);
int lastFrameBound = fFrameBounds[fAtomsToRead];
int toBeRead = fAtomBounds[fAtomsToRead] - lastFrameBound;
int firstChunk = (fAtomsToRead > 0) ? fAtomBounds[fAtomsToRead - 1] - lastFrameBound: 0;
if (toBeRead > 0) {
SkDumpCanvas* dumpCanvas = new SkDumpCanvas(fDumper);
SkGPipeReader* dumpReader = new SkGPipeReader(dumpCanvas);
SkGPipeReader* reader = new SkGPipeReader(canvas);
fDumper->disable();
int offset = 0;
size_t bytesRead;
SkGPipeReader::Status s;
//Read the first chunk
if (offset < firstChunk && firstChunk < toBeRead) {
s = dumpReader->playback(fData.begin() + offset, firstChunk - offset);
SkASSERT(SkGPipeReader::kError_Status != s);
s = reader->playback(fData.begin() + offset, firstChunk - offset, 0, &bytesRead);
SkASSERT(SkGPipeReader::kError_Status != s);
if (SkGPipeReader::kDone_Status == s){
delete dumpReader;
delete dumpCanvas;
dumpCanvas = new SkDumpCanvas(fDumper);
dumpReader = new SkGPipeReader(dumpCanvas);
delete reader;
reader = new SkGPipeReader(canvas);
}
offset += bytesRead;
}
SkASSERT(offset == firstChunk);
//Then read the current atom
fDumper->enable();
s = dumpReader->playback(fData.begin() + offset, toBeRead - offset,
SkGPipeReader::kReadAtom_PlaybackFlag);
SkASSERT(SkGPipeReader::kError_Status != s);
s = reader->playback(fData.begin() + offset, toBeRead - offset,
SkGPipeReader::kReadAtom_PlaybackFlag, &bytesRead);
SkASSERT(SkGPipeReader::kError_Status != s);
delete reader;
delete dumpReader;
delete dumpCanvas;
if (fDisplayClip) {
SkPaint p;
p.setColor(0x440000AA);
SkPath path;
canvas->getTotalClip().getBoundaryPath(&path);
canvas->drawPath(path, p);
}
}
}
virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
return new Click(this);
}
virtual bool onClick(SkView::Click* click) {
SkPoint prev = click->fPrev;
SkPoint curr = click->fCurr;
bool handled = true;
switch (click->fState) {
case SkView::Click::kDown_State:
if (SkScalarAbs(curr.fX - fCommands->width()) <= SKDEBUGGER_RESIZEBARSIZE) {
fCommandsResizing = true;
}
else if (SkScalarAbs(curr.fY - (this->height() - fState->height())) <= SKDEBUGGER_RESIZEBARSIZE &&
curr.fX > fCommands->width()) {
fStateResizing = true;
}
else if (curr.fX < fCommands->width()) {
fAtomsToRead = fCommands->selectHighlight(
SkScalarFloorToInt(curr.fY));
}
else
handled = false;
break;
case SkView::Click::kMoved_State:
if (fCommandsResizing)
fCommands->setSize(curr.fX, this->height());
else if (fStateResizing)
fState->setSize(this->width(), this->height() - curr.fY);
else if (curr.fX < fCommands->width()) {
if (curr.fY - prev.fY < 0) {
fCommands->scrollDown();
}
if (curr.fY - prev.fY > 0) {
fCommands->scrollUp();
}
}
else
handled = false;
break;
case SkView::Click::kUp_State:
fStateResizing = fCommandsResizing = false;
break;
default:
break;
}
fStateOffset = fCommands->width();
fState->setSize(this->width() - fStateOffset, fState->height());
fState->setLoc(fStateOffset, this->height() - fState->height());
if (handled)
this->inval(NULL);
return handled;
}
virtual void onSizeChange() {
this->INHERITED::onSizeChange();
fCommands->setSize(CMD_WIDTH, this->height());
fCommands->setLoc(0, 0);
fState->setSize(this->width() - CMD_WIDTH, SkFloatToScalar(INFO_HEIGHT));
fState->setLoc(CMD_WIDTH, this->height() - SkFloatToScalar(INFO_HEIGHT));
}
private:
DebuggerCommandsView* fCommands;
DebuggerStateView* fState;
bool fCommandsResizing;
bool fCommandsVisible;
bool fStateResizing;
bool fStateVisible;
float fStateOffset;
bool fDisplayClip;
int fAtomsToRead;
SkTDArray<int> fAtomBounds;
SkTDArray<int> fFrameBounds;
SkTDArray<char> fData;
SkDebugDumper* fDumper;
typedef SampleView INHERITED;
};
///////////////////////////////////////////////////////////////////////////////
SkView* create_debugger(const char* data, size_t size);
SkView* create_debugger(const char* data, size_t size) {
return SkNEW_ARGS(DebuggerView, (data, size));
};
bool is_debugger(SkView* view);
bool is_debugger(SkView* view) {
SkEvent isDebugger(gIsDebuggerQuery);
return view->doQuery(&isDebugger);
}