diff options
author | ajwong@chromium.org <ajwong@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-08 20:19:44 +0000 |
---|---|---|
committer | ajwong@chromium.org <ajwong@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-08 20:19:44 +0000 |
commit | f51ffcf1fa06f12c96cc3bcb6c0659c65371fe81 (patch) | |
tree | 73cf0fc1db209096852914e7ea719d217cf0ad08 | |
parent | 482a2662398a751f1a231b1ef84f19de91ee3764 (diff) | |
download | chromium_src-f51ffcf1fa06f12c96cc3bcb6c0659c65371fe81.zip chromium_src-f51ffcf1fa06f12c96cc3bcb6c0659c65371fe81.tar.gz chromium_src-f51ffcf1fa06f12c96cc3bcb6c0659c65371fe81.tar.bz2 |
Revert r51857 "Integrating back into using the external ppapi/cpp wrappers."
For some reason, this looks like it breaks all PPAPI ui tests on linux.
TBR: tonyg
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@51885 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | remoting/client/chromoting_client.cc | 10 | ||||
-rw-r--r-- | remoting/client/chromoting_client.h | 4 | ||||
-rw-r--r-- | remoting/client/plugin/chromoting_plugin.cc | 82 | ||||
-rw-r--r-- | remoting/client/plugin/chromoting_plugin.h | 38 | ||||
-rw-r--r-- | remoting/client/plugin/pepper_entrypoints.cc | 235 | ||||
-rw-r--r-- | remoting/client/plugin/pepper_util.cc | 31 | ||||
-rw-r--r-- | remoting/client/plugin/pepper_util.h | 32 | ||||
-rw-r--r-- | remoting/client/plugin/pepper_view.cc | 231 | ||||
-rw-r--r-- | remoting/client/plugin/pepper_view.h | 51 | ||||
-rw-r--r-- | remoting/remoting.gyp | 5 |
10 files changed, 390 insertions, 329 deletions
diff --git a/remoting/client/chromoting_client.cc b/remoting/client/chromoting_client.cc index 39f18b4..cad1993 100644 --- a/remoting/client/chromoting_client.cc +++ b/remoting/client/chromoting_client.cc @@ -8,9 +8,9 @@ #include "remoting/client/chromoting_view.h" #include "remoting/client/host_connection.h" -static const uint32 kCreatedColor = 0xffccccff; -static const uint32 kDisconnectedColor = 0xff00ccff; -static const uint32 kFailedColor = 0xffcc00ff; +static const uint32 kCreatedColor = 0xff0000ff; +static const uint32 kDisconnectedColor = 0xff00ff00; +static const uint32 kFailedColor = 0xffff0000; namespace remoting { @@ -162,9 +162,9 @@ void ChromotingClient::DoHandleUpdate(HostMessage* msg) { void ChromotingClient::DoEndUpdate(HostMessage* msg) { DCHECK_EQ(message_loop(), MessageLoop::current()); - DCHECK(msg->has_end_update_stream()); + DCHECK(msg->has_update_stream_packet()); - view_->HandleEndUpdateStream(msg); + view_->HandleUpdateStreamPacket(msg); } } // namespace remoting diff --git a/remoting/client/chromoting_client.h b/remoting/client/chromoting_client.h index 50cc0dc..587f1fb 100644 --- a/remoting/client/chromoting_client.h +++ b/remoting/client/chromoting_client.h @@ -28,10 +28,6 @@ class ChromotingClient : public HostConnection::HostEventCallback { // Sets the viewport to do display. The viewport may be larger and/or // smaller than the actual image background being displayed. - // - // TODO(ajwong): This doesn't make sense to have here. We're going to have - // threading isseus since pepper view needs to be called from the main pepper - // thread synchronously really. virtual void SetViewport(int x, int y, int width, int height); // HostConnection::HostEventCallback implementation. diff --git a/remoting/client/plugin/chromoting_plugin.cc b/remoting/client/plugin/chromoting_plugin.cc index 84dfe32..c5b5b03 100644 --- a/remoting/client/plugin/chromoting_plugin.cc +++ b/remoting/client/plugin/chromoting_plugin.cc @@ -7,7 +7,6 @@ #include <string> #include <vector> -#include "base/message_loop.h" #include "base/string_util.h" #include "base/thread.h" #include "remoting/client/chromoting_client.h" @@ -18,6 +17,7 @@ #include "third_party/ppapi/c/pp_event.h" #include "third_party/ppapi/c/pp_rect.h" #include "third_party/ppapi/cpp/completion_callback.h" +#include "third_party/ppapi/cpp/image_data.h" using std::string; using std::vector; @@ -26,9 +26,13 @@ namespace remoting { const char* ChromotingPlugin::kMimeType = "pepper-application/x-chromoting"; -ChromotingPlugin::ChromotingPlugin(PP_Instance pp_instance) - : pp::Instance(pp_instance), - pepper_main_loop_dont_post_to_me_(NULL) { +ChromotingPlugin::ChromotingPlugin(PP_Instance pp_instance, + const PPB_Instance* ppb_instance_funcs) + : width_(0), + height_(0), + drawing_context_(NULL), + pp_instance_(pp_instance), + ppb_instance_funcs_(ppb_instance_funcs) { } ChromotingPlugin::~ChromotingPlugin() { @@ -49,19 +53,6 @@ ChromotingPlugin::~ChromotingPlugin() { bool ChromotingPlugin::Init(uint32_t argc, const char* argn[], const char* argv[]) { - CHECK(pepper_main_loop_dont_post_to_me_ == NULL); - - // Record the current thread. This function should only be invoked by the - // plugin thread, so we capture the current message loop and assume it is - // indeed the plugin thread. - // - // We're abusing the pepper API slightly here. We know we're running as an - // internal plugin, and thus we are on the pepper main thread that uses a - // message loop. - // - // TODO(ajwong): See if there is a method for querying what thread we're on - // from inside the pepper API. - pepper_main_loop_dont_post_to_me_ = MessageLoop::current(); LOG(INFO) << "Started ChromotingPlugin::Init"; // Extract the URL from the arguments. @@ -96,23 +87,21 @@ bool ChromotingPlugin::Init(uint32_t argc, // Create the chromting objects. host_connection_.reset(new JingleHostConnection(network_thread_.get())); - view_.reset(new PepperView(this)); - client_.reset(new ChromotingClient(main_thread_->message_loop(), - host_connection_.get(), view_.get())); - - // Default to a medium grey. - view_->SetSolidFill(0xFFCDCDCD); + /* + view_.reset(new PepperView(main_thread_->message_loop(), device_, + instance())); + */ + //client_.reset(new ChromotingClient(main_thread_->message_loop(), + // host_connection_.get(), view_.get())); // Kick off the connection. - host_connection_->Connect(user_id, auth_token, host_jid, client_.get()); + //host_connection_->Connect(user_id, auth_token, host_jid, client_.get()); return true; } void ChromotingPlugin::ViewChanged(const PP_Rect& position, const PP_Rect& clip) { - DCHECK(CurrentlyOnPluginThread()); - // TODO(ajwong): This is going to be a race condition when the view changes // and we're in the middle of a Paint(). LOG(INFO) << "ViewChanged " @@ -121,18 +110,43 @@ void ChromotingPlugin::ViewChanged(const PP_Rect& position, << position.size.width << "," << position.size.height; - view_->SetViewport(position.point.x, position.point.y, - position.size.width, position.size.height); - view_->Paint(); -} + // TODO(ajwong): Do we care about the position? Probably not... + if (position.size.width == width_ || position.size.height == height_) + return; + + width_ = position.size.width; + height_ = position.size.height; + + /* + * TODO(ajwong): Reenable this code once we fingure out how we want to + * abstract away the C-api for DeviceContext2D. + device_context_ = pp::DeviceContext2D(width_, height_, false); + if (!ppb_instance_funcs_->BindGraphicsDeviceContext( + pp_instance_, + device_context_.pp_resource())) { + LOG(ERROR) << "Couldn't bind the device context."; + return; + } -bool ChromotingPlugin::CurrentlyOnPluginThread() const { - return pepper_main_loop_dont_post_to_me_ == MessageLoop::current(); + pp::ImageData image(PP_IMAGEDATAFORMAT_BGRA_PREMUL, width_, height_, false); + if (!image.is_null()) { + for (int y = 0; y < image.height(); y++) { + for (int x = 0; x < image.width(); x++) { + *image.GetAddr32(x, y) = 0xccff00cc; + } + } + device_context_.ReplaceContents(&image); + device_context_.Flush(pp::CompletionCallback(NULL, this)); + } else { + LOG(ERROR) << "Unable to allocate image."; + } + */ + + //client_->SetViewport(0, 0, width_, height_); + //client_->Repaint(); } bool ChromotingPlugin::HandleEvent(const PP_Event& event) { - DCHECK(CurrentlyOnPluginThread()); - switch (event.type) { case PP_Event_Type_MouseDown: case PP_Event_Type_MouseUp: diff --git a/remoting/client/plugin/chromoting_plugin.h b/remoting/client/plugin/chromoting_plugin.h index 0aac051..757e038 100644 --- a/remoting/client/plugin/chromoting_plugin.h +++ b/remoting/client/plugin/chromoting_plugin.h @@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// TODO(ajwong): We need to come up with a better description of the -// responsibilities for each thread. - #ifndef REMOTING_CLIENT_PLUGIN_CHROMOTING_PLUGIN_H_ #define REMOTING_CLIENT_PLUGIN_CHROMOTING_PLUGIN_H_ @@ -18,19 +15,12 @@ #include "third_party/ppapi/c/pp_instance.h" #include "third_party/ppapi/c/pp_rect.h" #include "third_party/ppapi/c/pp_resource.h" -#include "third_party/ppapi/cpp/instance.h" -#include "third_party/ppapi/cpp/device_context_2d.h" - -class MessageLoop; +#include "third_party/ppapi/c/ppb_instance.h" namespace base { class Thread; } // namespace base -namespace pp { -class Module; -} // namespace pp - namespace remoting { class ChromotingClient; @@ -38,20 +28,23 @@ class HostConnection; class JingleThread; class PepperView; -class ChromotingPlugin : public pp::Instance { +class ChromotingClient; + +class ChromotingPlugin { public: // The mimetype for which this plugin is registered. + // + // TODO(ajwong): Mimetype doesn't really make sense for us as the trigger + // point. I think we should handle a special protocol (eg., chromotocol://) static const char *kMimeType; - ChromotingPlugin(PP_Instance instance); + ChromotingPlugin(PP_Instance instance, const PPB_Instance* instance_funcs); virtual ~ChromotingPlugin(); virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]); virtual bool HandleEvent(const PP_Event& event); virtual void ViewChanged(const PP_Rect& position, const PP_Rect& clip); - virtual bool CurrentlyOnPluginThread() const; - private: FRIEND_TEST(ChromotingPluginTest, ParseUrl); FRIEND_TEST(ChromotingPluginTest, TestCaseSetup); @@ -61,13 +54,14 @@ class ChromotingPlugin : public pp::Instance { std::string* auth_token, std::string* host_jid); - // Since we're an internal plugin, we can just grab the message loop during - // init to figure out which thread we're on. This should only be used to - // sanity check which thread we're executing on. Do not post task here! - // Instead, use PPB_Core:CallOnMainThread() in the pepper api. - // - // TODO(ajwong): Think if there is a better way to safeguard this. - MessageLoop* pepper_main_loop_dont_post_to_me_; + // Size of the plugin window. + int width_; + int height_; + + PP_Resource drawing_context_; + + PP_Instance pp_instance_; + const PPB_Instance* ppb_instance_funcs_; scoped_ptr<base::Thread> main_thread_; scoped_ptr<JingleThread> network_thread_; diff --git a/remoting/client/plugin/pepper_entrypoints.cc b/remoting/client/plugin/pepper_entrypoints.cc index bd69863..c8a0895 100644 --- a/remoting/client/plugin/pepper_entrypoints.cc +++ b/remoting/client/plugin/pepper_entrypoints.cc @@ -4,59 +4,236 @@ #include "remoting/client/plugin/pepper_entrypoints.h" -#include "base/message_loop.h" #include "remoting/client/plugin/chromoting_plugin.h" -#include "third_party/ppapi/c/pp_errors.h" #include "third_party/ppapi/c/pp_instance.h" #include "third_party/ppapi/c/pp_module.h" -#include "third_party/ppapi/c/ppb_instance.h" +#include "third_party/ppapi/c/ppp_instance.h" #include "third_party/ppapi/cpp/instance.h" #include "third_party/ppapi/cpp/module.h" -static pp::Module* g_module_singleton = NULL; +static const int kModuleInitSuccess = 0; +static const int kModuleInitFailure = 1; -namespace pp { +namespace remoting { -Module* Module::Get() { - return g_module_singleton; -} +// Fork of ppapi::Module +// +// TODO(ajwong): Generalize this into something that other internal plugins can +// use. Either that, or attempt to refactor the external ppapi C++ wrapper to +// make it friendly for multiple Modules in one process. I think we can do this +// by: +// 1) Moving the singleton Module instance + C-bindings into another class +// (eg., ModuleExporter) under a different gyp targe. +// 2) Extracting the idea of a "Browser" out of the module that returns +// PPB_Core, etc. This can be a singleton per process regardless of +// module. +// 3) Migrate all PPB related objects to get data out of Browser interface +// instead of Module::Get(). +class ChromotingModule { + public: + ChromotingModule() {} -} // namespace pp + // This function will be automatically called after the object is created. + // This is where you can put functions that rely on other parts of the API, + // now that the module has been created. + virtual bool Init() { return true; } -namespace remoting { + PP_Module pp_module() const { return pp_module_; } + const PPB_Core& core() const { return *core_; } + + // Implements GetInterface for the browser to get plugin interfaces. Override + // if you need to implement your own interface types that this wrapper + // doesn't support. + virtual const void* GetInstanceInterface(const char* interface_name) { + if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) + return &instance_interface_; + + return NULL; + } + + // Returns an interface in the browser. + const void* GetBrowserInterface(const char* interface_name) { + return get_browser_interface_(interface_name); + } + + // Returns the object associated with this PP_Instance, or NULL if one is + // not found. + ChromotingPlugin* InstanceForPPInstance(PP_Instance instance) { + InstanceMap::iterator found = current_instances_.find(instance); + if (found == current_instances_.end()) + return NULL; + return found->second; + } + + // Sets the browser interface and calls the regular init function that + // can be overridden by the base classes. + // + // TODO(brettw) make this private when I can figure out how to make the + // initialize function a friend. + bool InternalInit(PP_Module mod, + PPB_GetInterface get_browser_interface) { + pp_module_ = mod; + get_browser_interface_ = get_browser_interface; + core_ = reinterpret_cast<const PPB_Core*>(GetBrowserInterface( + PPB_CORE_INTERFACE)); + if (!core_) + return false; // Can't run without the core interface. + + return Init(); + } + + // Implementation of Global PPP functions --------------------------------- + static int PPP_InitializeModule(PP_Module module_id, + PPB_GetInterface get_browser_interface) { + ChromotingModule* module = new ChromotingModule(); + if (!module) + return kModuleInitFailure; + + if (!module->InternalInit(module_id, get_browser_interface)) { + delete module; + return kModuleInitFailure; + } + + module_singleton_ = module; + return kModuleInitSuccess; + } + + static void PPP_ShutdownModule() { + delete module_singleton_; + module_singleton_ = NULL; + } + + static const void* PPP_GetInterface(const char* interface_name) { + if (!module_singleton_) + return NULL; + return module_singleton_->GetInstanceInterface(interface_name); + } -class ChromotingModule : public pp::Module { protected: virtual ChromotingPlugin* CreateInstance(PP_Instance instance) { - return new ChromotingPlugin(instance); + const PPB_Instance* ppb_instance_funcs = + reinterpret_cast<const PPB_Instance *>( + module_singleton_->GetBrowserInterface(PPB_INSTANCE_INTERFACE)); + return new ChromotingPlugin(instance, ppb_instance_funcs); } -}; -// Implementation of Global PPP functions --------------------------------- -int32_t PPP_InitializeModule(PP_Module module_id, - PPB_GetInterface get_browser_interface) { - ChromotingModule* module = new ChromotingModule(); - if (!module) - return PP_Error_Failed; + private: + static bool Instance_New(PP_Instance instance) { + if (!module_singleton_) + return false; + ChromotingPlugin* obj = module_singleton_->CreateInstance(instance); + if (obj) { + module_singleton_->current_instances_[instance] = obj; + return true; + } + return false; + } + + static void Instance_Delete(PP_Instance instance) { + if (!module_singleton_) + return; + ChromotingModule::InstanceMap::iterator found = + module_singleton_->current_instances_.find(instance); + if (found == module_singleton_->current_instances_.end()) + return; + + // Remove it from the map before deleting to try to catch reentrancy. + ChromotingPlugin* obj = found->second; + module_singleton_->current_instances_.erase(found); + delete obj; + } + + static bool Instance_Initialize(PP_Instance pp_instance, + uint32_t argc, + const char* argn[], + const char* argv[]) { + if (!module_singleton_) + return false; + ChromotingPlugin* instance = + module_singleton_->InstanceForPPInstance(pp_instance); + if (!instance) + return false; + return instance->Init(argc, argn, argv); + } + + static bool Instance_HandleDocumentLoad(PP_Instance pp_instance, + PP_Resource url_loader) { + return false; + } - if (!module->InternalInit(module_id, get_browser_interface)) { - delete module; - return PP_Error_Failed; + static bool Instance_HandleEvent(PP_Instance pp_instance, + const PP_Event* event) { + if (!module_singleton_) + return false; + ChromotingPlugin* instance = + module_singleton_->InstanceForPPInstance(pp_instance); + if (!instance) + return false; + return instance->HandleEvent(*event); } - g_module_singleton = module; - return PP_OK; + static PP_Var Instance_GetInstanceObject(PP_Instance pp_instance) { + PP_Var var; + var.type = PP_VarType_Void; + return var; + } + + static void Instance_ViewChanged(PP_Instance pp_instance, + const PP_Rect* position, + const PP_Rect* clip) { + if (!module_singleton_) + return; + ChromotingPlugin* instance = + module_singleton_->InstanceForPPInstance(pp_instance); + if (!instance) + return; + instance->ViewChanged(*position, *clip); + } + + // Bindings and identifiers to and from the browser. + PP_Module pp_module_; + PPB_GetInterface get_browser_interface_; + PPB_Core const* core_; + + // Instance tracking. + typedef std::map<PP_Instance, ChromotingPlugin*> InstanceMap; + InstanceMap current_instances_; + + // Static members for the ppapi C-bridge. + static PPP_Instance instance_interface_; + static ChromotingModule* module_singleton_; + + DISALLOW_COPY_AND_ASSIGN(ChromotingModule); +}; + +ChromotingModule* ChromotingModule::module_singleton_ = NULL; + +PPP_Instance ChromotingModule::instance_interface_ = { + &ChromotingModule::Instance_New, + &ChromotingModule::Instance_Delete, + &ChromotingModule::Instance_Initialize, + &ChromotingModule::Instance_HandleDocumentLoad, + &ChromotingModule::Instance_HandleEvent, + &ChromotingModule::Instance_GetInstanceObject, + &ChromotingModule::Instance_ViewChanged, +}; + +// Implementation of Global PPP functions --------------------------------- +// +// TODO(ajwong): This is to get around friending issues. Fix it after we decide +// whether or not ChromotingModule should be generalized. +int PPP_InitializeModule(PP_Module module_id, + PPB_GetInterface get_browser_interface) { + return ChromotingModule::PPP_InitializeModule(module_id, + get_browser_interface); } void PPP_ShutdownModule() { - delete pp::Module::Get(); - g_module_singleton = NULL; + return ChromotingModule::PPP_ShutdownModule(); } const void* PPP_GetInterface(const char* interface_name) { - if (!pp::Module::Get()) - return NULL; - return pp::Module::Get()->GetInstanceInterface(interface_name); + return ChromotingModule::PPP_GetInterface(interface_name); } } // namespace remoting diff --git a/remoting/client/plugin/pepper_util.cc b/remoting/client/plugin/pepper_util.cc deleted file mode 100644 index 7c91233..0000000 --- a/remoting/client/plugin/pepper_util.cc +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "remoting/client/plugin/pepper_util.h" - -#include "base/task.h" -#include "third_party/ppapi/c/pp_completion_callback.h" -#include "third_party/ppapi/cpp/module.h" - -namespace remoting { - -void CompletionCallbackTaskAdapter(void* user_data, int32_t not_used) { - Task* task = reinterpret_cast<Task*>(user_data); - task->Run(); - delete task; -} - -pp::CompletionCallback TaskToCompletionCallback(Task* task) { - return pp::CompletionCallback(&CompletionCallbackTaskAdapter, task); -} - -void RunTaskOnPluginThread(Task* task) { - pp::Module::Get()->core()->CallOnMainThread( - 0 /* run immediately */, - TaskToCompletionCallback(task), - 0 /* unused value */ - ); -} - -} // namespace remoting diff --git a/remoting/client/plugin/pepper_util.h b/remoting/client/plugin/pepper_util.h deleted file mode 100644 index 6c6cfb0..0000000 --- a/remoting/client/plugin/pepper_util.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef REMOTING_CLIENT_PLUGIN_PLUGIN_UTIL_H_ -#define REMOTING_CLIENT_PLUGIN_PLUGIN_UTIL_H_ - -#include "base/basictypes.h" - -#include "third_party/ppapi/cpp/completion_callback.h" - -class Task; - -namespace remoting { - -// Function for adapting a Chromium style Task into a -// PP_CompletionCallback friendly function. The Task object should be passed -// as |user_data|. This function will invoke Task::Run() on |user_data| when -// called, and then delete |user_data|. -void CompletionCallbackTaskAdapter(void* user_data, int32_t not_used); - -// Converts a Task* to a pp::CompletionCallback suitable for use with ppapi C++ -// APIs that require a pp::CompletionCallback. Takes ownership of |task|. -pp::CompletionCallback TaskToCompletionCallback(Task* task); - -// Posts the current task to the plugin's main thread. Takes ownership of -// |task|. -void RunTaskOnPluginThread(Task* task); - -} // namespace remoting - -#endif // REMOTING_CLIENT_PLUGIN_PLUGIN_UTIL_H_ diff --git a/remoting/client/plugin/pepper_view.cc b/remoting/client/plugin/pepper_view.cc index f638df0..d66624b5 100644 --- a/remoting/client/plugin/pepper_view.cc +++ b/remoting/client/plugin/pepper_view.cc @@ -6,15 +6,14 @@ #include "base/message_loop.h" #include "remoting/client/decoder_verbatim.h" -#include "remoting/client/plugin/chromoting_plugin.h" -#include "remoting/client/plugin/pepper_util.h" -#include "third_party/ppapi/cpp/device_context_2d.h" -#include "third_party/ppapi/cpp/image_data.h" namespace remoting { -PepperView::PepperView(ChromotingPlugin* plugin) - : plugin_(plugin), +PepperView::PepperView(MessageLoop* message_loop, NPDevice* rendering_device, + NPP plugin_instance) + : message_loop_(message_loop), + rendering_device_(rendering_device), + plugin_instance_(plugin_instance), backing_store_width_(0), backing_store_height_(0), viewport_x_(0), @@ -29,173 +28,127 @@ PepperView::~PepperView() { } void PepperView::Paint() { - if (!plugin_->CurrentlyOnPluginThread()) { - RunTaskOnPluginThread(NewRunnableMethod(this, &PepperView::Paint)); - return; - } - - // TODO(ajwong): We shouldn't assume the image data format. - pp::ImageData image(PP_IMAGEDATAFORMAT_BGRA_PREMUL, viewport_width_, - viewport_height_, false); - if (image.is_null()) { - LOG(ERROR) << "Unable to allocate image."; - return; - } - - if (is_static_fill_) { - for (int y = 0; y < image.height(); y++) { - for (int x = 0; x < image.width(); x++) { - *image.GetAddr32(x, y) = static_fill_color_; - } - } - } else if (frame_) { - int32_t* frame_data = - reinterpret_cast<int32_t*>(frame_->data(media::VideoFrame::kRGBPlane)); - int max_height = std::min(backing_store_height_, image.height()); - int max_width = std::min(backing_store_width_, image.width()); - for (int y = 0; y < max_height; y++) { - for (int x = 0; x < max_width; x++) { - // Force alpha to be set to 255. - *image.GetAddr32(x, y) = - frame_data[y*backing_store_width_ + x] | 0xFF000000; - } - } - } else { - // Nothing to paint. escape! - // - // TODO(ajwong): This is an ugly control flow. fix. - return; - } - device_context_.ReplaceContents(&image); - device_context_.Flush(TaskToCompletionCallback( - NewRunnableMethod(this, &PepperView::OnPaintDone))); + message_loop_->PostTask( + FROM_HERE, + NewRunnableMethod(this, &PepperView::DoPaint)); } void PepperView::SetSolidFill(uint32 color) { - if (!plugin_->CurrentlyOnPluginThread()) { - RunTaskOnPluginThread( - NewRunnableMethod(this, &PepperView::SetSolidFill, color)); - return; - } - - is_static_fill_ = true; - static_fill_color_ = color; + message_loop_->PostTask( + FROM_HERE, + NewRunnableMethod(this, &PepperView::DoSetSolidFill, color)); } void PepperView::UnsetSolidFill() { - if (!plugin_->CurrentlyOnPluginThread()) { - RunTaskOnPluginThread( - NewRunnableMethod(this, &PepperView::UnsetSolidFill)); - return; - } - - is_static_fill_ = false; + message_loop_->PostTask( + FROM_HERE, + NewRunnableMethod(this, &PepperView::DoUnsetSolidFill)); } void PepperView::SetViewport(int x, int y, int width, int height) { - if (!plugin_->CurrentlyOnPluginThread()) { - RunTaskOnPluginThread(NewRunnableMethod(this, &PepperView::SetViewport, - x, y, width, height)); - return; - } - - // TODO(ajwong): Should we ignore x & y updates? What do those even mean? + message_loop_->PostTask( + FROM_HERE, + NewRunnableMethod(this, &PepperView::DoSetViewport, + x, y, width, height)); +} - // TODO(ajwong): What does viewport x, y mean to a plugin anyways? - viewport_x_ = x; - viewport_y_ = y; - viewport_width_ = width; - viewport_height_ = height; +void PepperView::SetBackingStoreSize(int width, int height) { + message_loop_->PostTask( + FROM_HERE, + NewRunnableMethod(this, &PepperView::DoSetBackingStoreSize, + width, height)); +} - device_context_ = - pp::DeviceContext2D(viewport_width_, viewport_height_, false); - if (!plugin_->BindGraphicsDeviceContext(device_context_)) { - LOG(ERROR) << "Couldn't bind the device context."; - return; - } +void PepperView::HandleBeginUpdateStream(HostMessage* msg) { + message_loop_->PostTask( + FROM_HERE, + NewRunnableMethod(this, &PepperView::DoHandleBeginUpdateStream, msg)); } -void PepperView::SetBackingStoreSize(int width, int height) { - if (!plugin_->CurrentlyOnPluginThread()) { - RunTaskOnPluginThread(NewRunnableMethod(this, - &PepperView::SetBackingStoreSize, - width, height)); - return; - } +void PepperView::HandleUpdateStreamPacket(HostMessage* msg) { + message_loop_->PostTask( + FROM_HERE, + NewRunnableMethod(this, &PepperView::DoHandleUpdateStreamPacket, msg)); +} - backing_store_width_ = width; - backing_store_height_ = height; +void PepperView::HandleEndUpdateStream(HostMessage* msg) { + message_loop_->PostTask( + FROM_HERE, + NewRunnableMethod(this, &PepperView::DoHandleEndUpdateStream, msg)); } -void PepperView::HandleBeginUpdateStream(HostMessage* msg) { - if (!plugin_->CurrentlyOnPluginThread()) { - RunTaskOnPluginThread( - NewRunnableMethod(this, &PepperView::HandleBeginUpdateStream, - msg)); - return; - } +void PepperView::DoPaint() { + DCHECK_EQ(message_loop_, MessageLoop::current()); - scoped_ptr<HostMessage> deleter(msg); + LOG(INFO) << "Starting PepperView::DoPaint"; - // TODO(hclam): Use the information from the message to create the decoder. - // We lazily construct the decoder. - if (!decoder_.get()) { - decoder_.reset(new DecoderVerbatim()); - } + NPDeviceContext2D context; + NPDeviceContext2DConfig config; + rendering_device_->initializeContext(plugin_instance_, &config, &context); - if (!frame_) { - media::VideoFrame::CreateFrame(media::VideoFrame::RGB32, - backing_store_width_, - backing_store_height_, - base::TimeDelta(), base::TimeDelta(), - &frame_); + uint32* output_bitmap = static_cast<uint32*>(context.region); + + // TODO(ajwong): Remove debugging code and actually hook up real painting + // logic from the decoder. + LOG(INFO) << "Painting top: " << context.dirty.top + << " bottom: " << context.dirty.bottom + << " left: " << context.dirty.left + << " right: " << context.dirty.right; + for (int i = context.dirty.top; i < context.dirty.bottom; ++i) { + for (int j = context.dirty.left; j < context.dirty.right; ++j) { + *output_bitmap++ = static_fill_color_; + } } - // Tell the decoder to do start decoding. - decoder_->BeginDecode(frame_, &update_rects_, - NewRunnableMethod(this, &PepperView::OnPartialDecodeDone), - NewRunnableMethod(this, &PepperView::OnDecodeDone)); + rendering_device_->flushContext(plugin_instance_, &context, NULL, NULL); + LOG(INFO) << "Finishing PepperView::DoPaint"; } -void PepperView::HandleUpdateStreamPacket(HostMessage* msg) { - if (!plugin_->CurrentlyOnPluginThread()) { - RunTaskOnPluginThread( - NewRunnableMethod(this, &PepperView::HandleUpdateStreamPacket, - msg)); - return; - } +void PepperView::DoSetSolidFill(uint32 color) { + DCHECK_EQ(message_loop_, MessageLoop::current()); - decoder_->PartialDecode(msg); + is_static_fill_ = true; + static_fill_color_ = color; } -void PepperView::HandleEndUpdateStream(HostMessage* msg) { - if (!plugin_->CurrentlyOnPluginThread()) { - RunTaskOnPluginThread( - NewRunnableMethod(this, &PepperView::HandleEndUpdateStream, - msg)); - return; - } +void PepperView::DoUnsetSolidFill() { + DCHECK_EQ(message_loop_, MessageLoop::current()); - scoped_ptr<HostMessage> deleter(msg); - decoder_->EndDecode(); + is_static_fill_ = false; } -void PepperView::OnPaintDone() { - // TODO(ajwong):Probably should set some variable to allow repaints to - // actually paint. - return; +void PepperView::DoSetViewport(int x, int y, int width, int height) { + DCHECK_EQ(message_loop_, MessageLoop::current()); + + viewport_x_ = x; + viewport_y_ = y; + viewport_width_ = width; + viewport_height_ = height; +} + +void PepperView::DoSetBackingStoreSize(int width, int height) { + DCHECK_EQ(message_loop_, MessageLoop::current()); + + backing_store_width_ = width; + backing_store_height_ = height; } -void PepperView::OnPartialDecodeDone() { - all_update_rects_.insert(all_update_rects_.begin() + - all_update_rects_.size(), - update_rects_.begin(), update_rects_.end()); - Paint(); - // TODO(ajwong): Need to block here to be synchronous. +void PepperView::DoHandleBeginUpdateStream(HostMessage* msg) { + DCHECK_EQ(message_loop_, MessageLoop::current()); + + NOTIMPLEMENTED(); +} + +void PepperView::DoHandleUpdateStreamPacket(HostMessage* msg) { + DCHECK_EQ(message_loop_, MessageLoop::current()); + + NOTIMPLEMENTED(); } +void PepperView::DoHandleEndUpdateStream(HostMessage* msg) { + DCHECK_EQ(message_loop_, MessageLoop::current()); -void PepperView::OnDecodeDone() { + NOTIMPLEMENTED(); } } // namespace remoting diff --git a/remoting/client/plugin/pepper_view.h b/remoting/client/plugin/pepper_view.h index 655b9ae..9dc8a56 100644 --- a/remoting/client/plugin/pepper_view.h +++ b/remoting/client/plugin/pepper_view.h @@ -2,38 +2,30 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// This class is an implementation of the ChromotingView using Pepper devices -// as the backing stores. The public APIs to this class are thread-safe. -// Calls will dispatch any interaction with the pepper API onto the pepper -// main thread. -// -// TODO(ajwong): We need to better understand the threading semantics of this -// class. Currently, we're just going to always run everything on the pepper -// main thread. Is this smart? - #ifndef REMOTING_CLIENT_PLUGIN_PEPPER_VIEW_H_ #define REMOTING_CLIENT_PLUGIN_PEPPER_VIEW_H_ #include "base/scoped_ptr.h" #include "base/task.h" -#include "media/base/video_frame.h" #include "remoting/client/chromoting_view.h" -#include "remoting/client/decoder.h" -#include "third_party/ppapi/cpp/device_context_2d.h" +#include "third_party/npapi/bindings/npapi.h" +#include "third_party/npapi/bindings/npapi_extensions.h" + +class MessageLoop; namespace remoting { -class ChromotingPlugin; class Decoder; class PepperView : public ChromotingView { public: - // Constructs a PepperView that draws to the |rendering_device|. The + // Constructs a PepperView that draw to the |rendering_device|. The // |rendering_device| instance must outlive this class. // // TODO(ajwong): This probably needs to synchronize with the pepper thread // to be safe. - explicit PepperView(ChromotingPlugin* plugin); + PepperView(MessageLoop* message_loop, NPDevice* rendering_device, + NPP plugin_instance); virtual ~PepperView(); // ChromotingView implementation. @@ -47,16 +39,21 @@ class PepperView : public ChromotingView { virtual void HandleEndUpdateStream(HostMessage* msg); private: - void OnPaintDone(); - void OnPartialDecodeDone(); - void OnDecodeDone(); - - // Reference to the creating plugin instance. Needed for interacting with - // pepper. Marking explciitly as const since it must be initialized at - // object creation, and never change. - ChromotingPlugin* const plugin_; - - pp::DeviceContext2D device_context_; + void DoPaint(); + void DoSetSolidFill(uint32 color); + void DoUnsetSolidFill(); + void DoSetViewport(int x, int y, int width, int height); + void DoSetBackingStoreSize(int width, int height); + void DoHandleBeginUpdateStream(HostMessage* msg); + void DoHandleUpdateStreamPacket(HostMessage* msg); + void DoHandleEndUpdateStream(HostMessage* msg); + + // Synchronization and thread handling objects. + MessageLoop* message_loop_; + + // Handles to Pepper objects needed for drawing to the screen. + NPDevice* rendering_device_; + NPP plugin_instance_; int backing_store_width_; int backing_store_height_; @@ -69,10 +66,6 @@ class PepperView : public ChromotingView { bool is_static_fill_; uint32 static_fill_color_; - scoped_refptr<media::VideoFrame> frame_; - UpdatedRects update_rects_; - UpdatedRects all_update_rects_; - scoped_ptr<Decoder> decoder_; DISALLOW_COPY_AND_ASSIGN(PepperView); diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp index c1450c1..82df802 100644 --- a/remoting/remoting.gyp +++ b/remoting/remoting.gyp @@ -71,8 +71,7 @@ 'chromoting_base', 'chromoting_client', 'chromoting_jingle_glue', - '../third_party/ppapi/ppapi.gyp:ppapi_cpp_objects', - '../third_party/zlib/zlib.gyp:zlib', + '../third_party/ppapi/ppapi.gyp:ppapi_c', ], 'sources': [ 'client/plugin/chromoting_plugin.cc', @@ -81,8 +80,6 @@ 'client/plugin/pepper_entrypoints.h', 'client/plugin/pepper_view.cc', 'client/plugin/pepper_view.h', - 'client/plugin/pepper_util.cc', - 'client/plugin/pepper_util.h', '../media/base/yuv_convert.cc', '../media/base/yuv_convert.h', '../media/base/yuv_row.h', |