summaryrefslogtreecommitdiffstats
path: root/ppapi/proxy/ppb_graphics_2d_proxy.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ppapi/proxy/ppb_graphics_2d_proxy.cc')
-rw-r--r--ppapi/proxy/ppb_graphics_2d_proxy.cc90
1 files changed, 72 insertions, 18 deletions
diff --git a/ppapi/proxy/ppb_graphics_2d_proxy.cc b/ppapi/proxy/ppb_graphics_2d_proxy.cc
index 0567369..74f8b91 100644
--- a/ppapi/proxy/ppb_graphics_2d_proxy.cc
+++ b/ppapi/proxy/ppb_graphics_2d_proxy.cc
@@ -4,8 +4,9 @@
#include "ppapi/proxy/ppb_graphics_2d_proxy.h"
-#include <string.h> // For memset
+#include <string.h> // For memset.
+#include "base/compiler_specific.h"
#include "base/logging.h"
#include "ppapi/c/pp_completion_callback.h"
#include "ppapi/c/pp_errors.h"
@@ -21,7 +22,9 @@ namespace proxy {
class Graphics2D : public PluginResource {
public:
Graphics2D(const PP_Size& size, PP_Bool is_always_opaque)
- : size_(size), is_always_opaque_(is_always_opaque) {
+ : size_(size),
+ is_always_opaque_(is_always_opaque),
+ current_flush_callback_(PP_BlockUntilComplete()) {
}
// Resource overrides.
@@ -30,10 +33,23 @@ class Graphics2D : public PluginResource {
const PP_Size& size() const { return size_; }
PP_Bool is_always_opaque() const { return is_always_opaque_; }
+ bool is_flush_pending() const { return !!current_flush_callback_.func; }
+
+ PP_CompletionCallback current_flush_callback() const {
+ return current_flush_callback_;
+ }
+ void set_current_flush_callback(PP_CompletionCallback cb) {
+ current_flush_callback_ = cb;
+ }
+
private:
PP_Size size_;
PP_Bool is_always_opaque_;
+ // In the plugin, this is the current callback set for Flushes. When the
+ // callback function pointer is non-NULL, we're waiting for a flush ACK.
+ PP_CompletionCallback current_flush_callback_;
+
DISALLOW_COPY_AND_ASSIGN(Graphics2D);
};
@@ -103,13 +119,22 @@ void ReplaceContents(PP_Resource graphics_2d, PP_Resource image_data) {
int32_t Flush(PP_Resource graphics_2d,
PP_CompletionCallback callback) {
- PluginDispatcher* dispatcher = PluginDispatcher::Get();
- int32_t result = PP_ERROR_FAILED;
- dispatcher->Send(new PpapiHostMsg_PPBGraphics2D_Flush(
- INTERFACE_ID_PPB_GRAPHICS_2D, graphics_2d,
- dispatcher->callback_tracker().SendCallback(callback),
- &result));
- return result;
+ Graphics2D* object = PluginResource::GetAs<Graphics2D>(graphics_2d);
+ if (!object)
+ return PP_ERROR_BADRESOURCE;
+
+ // For now, disallow blocking calls. We'll need to add support for other
+ // threads to this later.
+ if (!callback.func)
+ return PP_ERROR_BADARGUMENT;
+
+ if (object->is_flush_pending())
+ return PP_ERROR_INPROGRESS; // Can't have >1 flush pending.
+ object->set_current_flush_callback(callback);
+
+ PluginDispatcher::Get()->Send(new PpapiHostMsg_PPBGraphics2D_Flush(
+ INTERFACE_ID_PPB_GRAPHICS_2D, graphics_2d));
+ return PP_ERROR_WOULDBLOCK;
}
const PPB_Graphics2D ppb_graphics_2d = {
@@ -126,7 +151,8 @@ const PPB_Graphics2D ppb_graphics_2d = {
PPB_Graphics2D_Proxy::PPB_Graphics2D_Proxy(Dispatcher* dispatcher,
const void* target_interface)
- : InterfaceProxy(dispatcher, target_interface) {
+ : InterfaceProxy(dispatcher, target_interface),
+ callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
}
PPB_Graphics2D_Proxy::~PPB_Graphics2D_Proxy() {
@@ -152,6 +178,9 @@ void PPB_Graphics2D_Proxy::OnMessageReceived(const IPC::Message& msg) {
OnMsgReplaceContents)
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics2D_Flush,
OnMsgFlush)
+
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBGraphics2D_FlushACK,
+ OnMsgFlushACK)
IPC_END_MESSAGE_MAP()
// FIXME(brettw) handle bad messages!
}
@@ -188,14 +217,39 @@ void PPB_Graphics2D_Proxy::OnMsgReplaceContents(PP_Resource graphics_2d,
ppb_graphics_2d_target()->ReplaceContents(graphics_2d, image_data);
}
-void PPB_Graphics2D_Proxy::OnMsgFlush(PP_Resource graphics_2d,
- uint32_t serialized_callback,
- int32_t* result) {
- // TODO(brettw) this should be a non-sync function. Ideally it would call
- // the callback with a failure code from here if you weren't allowed to
- // call Flush there.
- *result = ppb_graphics_2d_target()->Flush(
- graphics_2d, ReceiveCallback(serialized_callback));
+void PPB_Graphics2D_Proxy::OnMsgFlush(PP_Resource graphics_2d) {
+ CompletionCallback callback = callback_factory_.NewCallback(
+ &PPB_Graphics2D_Proxy::SendFlushACKToPlugin, graphics_2d);
+ int32_t result = ppb_graphics_2d_target()->Flush(
+ graphics_2d, callback.pp_completion_callback());
+ if (result != PP_ERROR_WOULDBLOCK) {
+ // There was some error, so we won't get a flush callback. We need to now
+ // issue the ACK to the plugin hears about the error. This will also clean
+ // up the data associated with the callback.
+ callback.Run(result);
+ }
+}
+
+void PPB_Graphics2D_Proxy::OnMsgFlushACK(PP_Resource resource,
+ int32_t pp_error) {
+ Graphics2D* object = PluginResource::GetAs<Graphics2D>(resource);
+ if (!object) {
+ // The plugin has released the graphics 2D object so don't issue the
+ // callback.
+ return;
+ }
+
+ // Be careful to make the callback NULL again before issuing the callback
+ // since the plugin might want to flush from within the callback.
+ PP_CompletionCallback callback = object->current_flush_callback();
+ object->set_current_flush_callback(PP_BlockUntilComplete());
+ PP_RunCompletionCallback(&callback, pp_error);
+}
+
+void PPB_Graphics2D_Proxy::SendFlushACKToPlugin(int32_t result,
+ PP_Resource graphics_2d) {
+ dispatcher()->Send(new PpapiMsg_PPBGraphics2D_FlushACK(
+ INTERFACE_ID_PPB_GRAPHICS_2D, graphics_2d, result));
}
} // namespace proxy