diff options
Diffstat (limited to 'remoting/client/plugin/pepper_view.cc')
-rw-r--r-- | remoting/client/plugin/pepper_view.cc | 234 |
1 files changed, 142 insertions, 92 deletions
diff --git a/remoting/client/plugin/pepper_view.cc b/remoting/client/plugin/pepper_view.cc index d66624b5..a6ebc13 100644 --- a/remoting/client/plugin/pepper_view.cc +++ b/remoting/client/plugin/pepper_view.cc @@ -6,14 +6,17 @@ #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" +#include "third_party/ppapi/cpp/point.h" +#include "third_party/ppapi/cpp/size.h" namespace remoting { -PepperView::PepperView(MessageLoop* message_loop, NPDevice* rendering_device, - NPP plugin_instance) - : message_loop_(message_loop), - rendering_device_(rendering_device), - plugin_instance_(plugin_instance), +PepperView::PepperView(ChromotingPlugin* plugin) + : plugin_(plugin), backing_store_width_(0), backing_store_height_(0), viewport_x_(0), @@ -28,127 +31,174 @@ PepperView::~PepperView() { } void PepperView::Paint() { - message_loop_->PostTask( - FROM_HERE, - NewRunnableMethod(this, &PepperView::DoPaint)); -} - -void PepperView::SetSolidFill(uint32 color) { - message_loop_->PostTask( - FROM_HERE, - NewRunnableMethod(this, &PepperView::DoSetSolidFill, color)); -} - -void PepperView::UnsetSolidFill() { - message_loop_->PostTask( - FROM_HERE, - NewRunnableMethod(this, &PepperView::DoUnsetSolidFill)); -} - -void PepperView::SetViewport(int x, int y, int width, int height) { - message_loop_->PostTask( - FROM_HERE, - NewRunnableMethod(this, &PepperView::DoSetViewport, - x, y, width, height)); -} - -void PepperView::SetBackingStoreSize(int width, int height) { - message_loop_->PostTask( - FROM_HERE, - NewRunnableMethod(this, &PepperView::DoSetBackingStoreSize, - width, height)); -} - -void PepperView::HandleBeginUpdateStream(HostMessage* msg) { - message_loop_->PostTask( - FROM_HERE, - NewRunnableMethod(this, &PepperView::DoHandleBeginUpdateStream, msg)); -} - -void PepperView::HandleUpdateStreamPacket(HostMessage* msg) { - message_loop_->PostTask( - FROM_HERE, - NewRunnableMethod(this, &PepperView::DoHandleUpdateStreamPacket, msg)); -} - -void PepperView::HandleEndUpdateStream(HostMessage* msg) { - message_loop_->PostTask( - FROM_HERE, - NewRunnableMethod(this, &PepperView::DoHandleEndUpdateStream, msg)); -} - -void PepperView::DoPaint() { - DCHECK_EQ(message_loop_, MessageLoop::current()); - - LOG(INFO) << "Starting PepperView::DoPaint"; - - NPDeviceContext2D context; - NPDeviceContext2DConfig config; - rendering_device_->initializeContext(plugin_instance_, &config, &context); + if (!plugin_->CurrentlyOnPluginThread()) { + RunTaskOnPluginThread(NewRunnableMethod(this, &PepperView::Paint)); + return; + } - uint32* output_bitmap = static_cast<uint32*>(context.region); + // TODO(ajwong): We shouldn't assume the image data format. + pp::ImageData image(PP_IMAGEDATAFORMAT_BGRA_PREMUL, + pp::Size(viewport_width_, viewport_height_), + false); + if (image.is_null()) { + LOG(ERROR) << "Unable to allocate image."; + return; + } - // 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_; + if (is_static_fill_) { + for (int y = 0; y < image.size().height(); y++) { + for (int x = 0; x < image.size().width(); x++) { + *image.GetAddr32(pp::Point(x, y)) = static_fill_color_; + } + } + } else if (frame_) { + uint32_t* frame_data = + reinterpret_cast<uint32_t*>(frame_->data(media::VideoFrame::kRGBPlane)); + int max_height = std::min(backing_store_height_, image.size().height()); + int max_width = std::min(backing_store_width_, image.size().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(pp::Point(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; } - - rendering_device_->flushContext(plugin_instance_, &context, NULL, NULL); - LOG(INFO) << "Finishing PepperView::DoPaint"; + device_context_.ReplaceContents(&image); + device_context_.Flush(TaskToCompletionCallback( + NewRunnableMethod(this, &PepperView::OnPaintDone))); } -void PepperView::DoSetSolidFill(uint32 color) { - DCHECK_EQ(message_loop_, MessageLoop::current()); +void PepperView::SetSolidFill(uint32 color) { + if (!plugin_->CurrentlyOnPluginThread()) { + RunTaskOnPluginThread( + NewRunnableMethod(this, &PepperView::SetSolidFill, color)); + return; + } is_static_fill_ = true; static_fill_color_ = color; } -void PepperView::DoUnsetSolidFill() { - DCHECK_EQ(message_loop_, MessageLoop::current()); +void PepperView::UnsetSolidFill() { + if (!plugin_->CurrentlyOnPluginThread()) { + RunTaskOnPluginThread( + NewRunnableMethod(this, &PepperView::UnsetSolidFill)); + return; + } is_static_fill_ = false; } -void PepperView::DoSetViewport(int x, int y, int width, int height) { - DCHECK_EQ(message_loop_, MessageLoop::current()); +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? + + // TODO(ajwong): What does viewport x, y mean to a plugin anyways? viewport_x_ = x; viewport_y_ = y; viewport_width_ = width; viewport_height_ = height; + + device_context_ = + pp::DeviceContext2D(pp::Size(viewport_width_, viewport_height_), false); + if (!plugin_->BindGraphicsDeviceContext(device_context_)) { + LOG(ERROR) << "Couldn't bind the device context."; + return; + } } -void PepperView::DoSetBackingStoreSize(int width, int height) { - DCHECK_EQ(message_loop_, MessageLoop::current()); +void PepperView::SetBackingStoreSize(int width, int height) { + if (!plugin_->CurrentlyOnPluginThread()) { + RunTaskOnPluginThread(NewRunnableMethod(this, + &PepperView::SetBackingStoreSize, + width, height)); + return; + } backing_store_width_ = width; backing_store_height_ = height; } -void PepperView::DoHandleBeginUpdateStream(HostMessage* msg) { - DCHECK_EQ(message_loop_, MessageLoop::current()); +void PepperView::HandleBeginUpdateStream(HostMessage* msg) { + if (!plugin_->CurrentlyOnPluginThread()) { + RunTaskOnPluginThread( + NewRunnableMethod(this, &PepperView::HandleBeginUpdateStream, + msg)); + return; + } + + scoped_ptr<HostMessage> deleter(msg); - NOTIMPLEMENTED(); + // TODO(hclam): Use the information from the message to create the decoder. + // We lazily construct the decoder. + if (!decoder_.get()) { + decoder_.reset(new DecoderVerbatim()); + } + + if (!frame_) { + media::VideoFrame::CreateFrame(media::VideoFrame::RGB32, + backing_store_width_, + backing_store_height_, + base::TimeDelta(), base::TimeDelta(), + &frame_); + } + + // Tell the decoder to do start decoding. + decoder_->BeginDecode(frame_, &update_rects_, + NewRunnableMethod(this, &PepperView::OnPartialDecodeDone), + NewRunnableMethod(this, &PepperView::OnDecodeDone)); +} + +void PepperView::HandleUpdateStreamPacket(HostMessage* msg) { + if (!plugin_->CurrentlyOnPluginThread()) { + RunTaskOnPluginThread( + NewRunnableMethod(this, &PepperView::HandleUpdateStreamPacket, + msg)); + return; + } + + decoder_->PartialDecode(msg); } -void PepperView::DoHandleUpdateStreamPacket(HostMessage* msg) { - DCHECK_EQ(message_loop_, MessageLoop::current()); +void PepperView::HandleEndUpdateStream(HostMessage* msg) { + if (!plugin_->CurrentlyOnPluginThread()) { + RunTaskOnPluginThread( + NewRunnableMethod(this, &PepperView::HandleEndUpdateStream, + msg)); + return; + } + + scoped_ptr<HostMessage> deleter(msg); + decoder_->EndDecode(); +} + +void PepperView::OnPaintDone() { + // TODO(ajwong):Probably should set some variable to allow repaints to + // actually paint. + return; +} - NOTIMPLEMENTED(); +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::DoHandleEndUpdateStream(HostMessage* msg) { - DCHECK_EQ(message_loop_, MessageLoop::current()); - NOTIMPLEMENTED(); +void PepperView::OnDecodeDone() { } } // namespace remoting |