Index: nacl/src/nacl_debugger.cpp |
=================================================================== |
--- nacl/src/nacl_debugger.cpp (revision 7896) |
+++ nacl/src/nacl_debugger.cpp (working copy) |
@@ -6,75 +6,45 @@ |
#include "ppapi/cpp/image_data.h" |
#include "ppapi/cpp/instance.h" |
#include "ppapi/cpp/module.h" |
+#include "ppapi/cpp/point.h" |
+#include "ppapi/cpp/rect.h" |
#include "ppapi/cpp/var.h" |
+#include "SkBase64.h" |
+#include "SkBitmap.h" |
#include "SkCanvas.h" |
-#include "SkBitmap.h" |
+#include "SkColor.h" |
+#include "SkDebugger.h" |
+#include "SkGraphics.h" |
+#include "SkStream.h" |
#include "SkString.h" |
-#include "SkThreadUtils.h" |
class SkiaInstance; |
// Used by SkDebugf |
SkiaInstance* gPluginInstance; |
-// Main entry point for the app we're linked into |
-extern int tool_main(int, char**); |
+void FlushCallback(void* data, int32_t result); |
-// Tokenize a command line and store it in argc and argv. |
-void SkStringToProgramArgs(const SkString commandLine, int* argc, char*** argv) { |
- int numBreaks = 0; |
- const char* commandChars = commandLine.c_str(); |
- for (int i = 0; i < strlen(commandChars); i++) { |
- if (isspace(commandChars[i])) { |
- numBreaks++; |
- } |
- } |
- int numArgs; |
- if (strlen(commandChars) > 0) { |
- numArgs = numBreaks + 1; |
- } else { |
- numArgs = 0; |
- } |
- *argc = numArgs; |
- *argv = new char*[numArgs + 1]; |
- (*argv)[numArgs] = NULL; |
- char* start = (char*) commandChars; |
- int length = 0; |
- int argIndex = 0; |
- for (int i = 0; i < strlen(commandChars) + 1; i++) { |
- if (isspace(commandChars[i]) || '\0' == commandChars[i]) { |
- if (length > 0) { |
- char* argument = new char[length + 1]; |
- memcpy(argument, start, length); |
- argument[length] = '\0'; |
- (*argv)[argIndex++] = argument; |
- } |
- start = (char*) commandChars + i + 1; |
- length = 0; |
- } else { |
- length++; |
- } |
- } |
-} |
- |
-// Run the program with the given command line. |
-void RunProgram(const SkString& commandLine) { |
- int argc; |
- char** argv; |
- SkStringToProgramArgs(commandLine, &argc, &argv); |
- tool_main(argc, argv); |
-} |
- |
- |
// Skia's subclass of pp::Instance, our interface with the browser. |
class SkiaInstance : public pp::Instance { |
public: |
- explicit SkiaInstance(PP_Instance instance) : pp::Instance(instance) { |
+ explicit SkiaInstance(PP_Instance instance) |
+ : pp::Instance(instance) |
+ , fBitmap() |
+ , fCanvas(NULL) |
+ , fDebugger() |
+ , fImage() |
+ , fFlushLoopRunning(false) |
+ , fFlushPending(false) |
+ , fPicture(NULL) |
+ { |
gPluginInstance = this; |
+ SkGraphics::Init(); |
} |
virtual ~SkiaInstance() { |
+ SkGraphics::Term(); |
gPluginInstance = NULL; |
} |
@@ -83,12 +53,143 @@ |
if (var_message.is_string()) { |
SkString msg(var_message.AsString().c_str()); |
if (msg.startsWith("init")) { |
- RunProgram(msg); |
+ } else if (msg.startsWith("LoadSKP")) { |
+ size_t startIndex = strlen("LoadSKP"); |
+ size_t dataSize = msg.size()/sizeof(char) - startIndex; |
+ SkBase64 decodedData; |
+ decodedData.decode(msg.c_str() + startIndex, dataSize); |
+ size_t decodedSize = 3 * (dataSize / 4); |
+ SkDebugf("Got size: %d\n", decodedSize); |
+ if (!decodedData.getData()) { |
+ SkDebugf("Failed to decode SKP\n"); |
+ return; |
+ } |
+ SkMemoryStream pictureStream(decodedData.getData(), decodedSize); |
+ fPicture = new SkPicture(&pictureStream); |
+ if (fPicture->width() == 0 || fPicture->height() == 0) { |
+ SkDebugf("Failed to create SKP.\n"); |
+ return; |
+ } |
+ fDebugger.loadPicture(fPicture); |
+ SkTArray<SkString>* commands = fDebugger.getDrawCommandsAsStrings(); |
+ PostMessage("ClearCommands"); |
+ for (int i = 0; i < commands->count(); ++i) { |
+ SkString message("AddCommand:"); |
+ message.append((*commands)[i]); |
+ PostMessage(message.c_str()); |
+ } |
+ if (!fFlushLoopRunning) { |
+ Paint(); |
+ } |
+ } else if (msg.startsWith("CommandSelected:")) { |
+ size_t startIndex = strlen("CommandSelected:"); |
+ int index = atoi(msg.c_str() + startIndex); |
+ fDebugger.setIndex(index); |
+ if (!fFlushLoopRunning) { |
+ Paint(); |
+ } |
+ } else if (msg.startsWith("Rewind")) { |
+ fCanvas->clear(SK_ColorWHITE); |
+ fDebugger.setIndex(0); |
+ if (!fFlushLoopRunning) { |
+ Paint(); |
+ } |
+ } else if (msg.startsWith("StepBack")) { |
+ fCanvas->clear(SK_ColorWHITE); |
+ int currentIndex = fDebugger.index(); |
+ if (currentIndex > 1) { |
+ fDebugger.setIndex(currentIndex - 1); |
+ if (!fFlushLoopRunning) { |
+ Paint(); |
+ } |
+ } |
+ } else if (msg.startsWith("Pause")) { |
+ // TODO(borenet) |
+ } else if (msg.startsWith("StepForward")) { |
+ int currentIndex = fDebugger.index(); |
+ if (currentIndex < fDebugger.getSize() -1) { |
+ fDebugger.setIndex(currentIndex + 1); |
+ if (!fFlushLoopRunning) { |
+ Paint(); |
+ } |
+ } |
+ } else if (msg.startsWith("Play")) { |
+ fDebugger.setIndex(fDebugger.getSize() - 1); |
+ if (!fFlushLoopRunning) { |
+ Paint(); |
+ } |
} |
} |
} |
+ |
+ void Paint() { |
+ if (!fImage.is_null()) { |
+ fDebugger.draw(fCanvas); |
+ fDeviceContext.PaintImageData(fImage, pp::Point(0, 0)); |
+ if (!fFlushPending) { |
+ fFlushPending = true; |
+ fDeviceContext.Flush(pp::CompletionCallback(&FlushCallback, this)); |
+ } else { |
+ SkDebugf("A flush is pending... Skipping flush.\n"); |
+ } |
+ } else { |
+ SkDebugf("No pixels to write to!\n"); |
+ } |
+ } |
+ |
+ virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip) { |
+ if (position.size().width() == fWidth && |
+ position.size().height() == fHeight) { |
+ return; // We don't care about the position, only the size. |
+ } |
+ fWidth = position.size().width(); |
+ fHeight = position.size().height(); |
+ |
+ fDeviceContext = pp::Graphics2D(this, pp::Size(fWidth, fHeight), false); |
+ if (!BindGraphics(fDeviceContext)) { |
+ SkDebugf("Couldn't bind the device context\n"); |
+ return; |
+ } |
+ fImage = pp::ImageData(this, |
+ PP_IMAGEDATAFORMAT_BGRA_PREMUL, |
+ pp::Size(fWidth, fHeight), false); |
+ fBitmap.setConfig(SkBitmap::kARGB_8888_Config, fWidth, fHeight); |
+ fBitmap.setPixels(fImage.data()); |
+ if (fCanvas) { |
+ delete fCanvas; |
+ } |
+ fCanvas = new SkCanvas(fBitmap); |
+ fCanvas->clear(SK_ColorWHITE); |
+ if (!fFlushLoopRunning) { |
+ Paint(); |
+ } |
+ } |
+ |
+ void OnFlush() { |
+ fFlushLoopRunning = true; |
+ fFlushPending = false; |
+ Paint(); |
+ } |
+ |
+private: |
+ pp::Graphics2D fDeviceContext; |
+ pp::ImageData fImage; |
+ int fWidth; |
+ int fHeight; |
+ |
+ SkBitmap fBitmap; |
+ SkCanvas* fCanvas; |
+ SkDebugger fDebugger; |
+ SkPicture* fPicture; |
+ |
+ bool fFlushLoopRunning; |
+ bool fFlushPending; |
}; |
+void FlushCallback(void* data, int32_t result) { |
+ static_cast<SkiaInstance*>(data)->OnFlush(); |
+} |
+ |
class SkiaModule : public pp::Module { |
public: |
SkiaModule() : pp::Module() {} |
@@ -104,11 +205,3 @@ |
return new SkiaModule(); |
} |
} // namespace pp |
- |
-/////////////////////////////////////////// |
-////////////// SkThread impl ////////////// |
-/////////////////////////////////////////// |
- |
-bool SkThread::setProcessorAffinity(unsigned int processor) { |
- return false; |
-} |