| Index: remoting/client/plugin/pepper_view.cc
|
| diff --git a/remoting/client/plugin/pepper_view.cc b/remoting/client/plugin/pepper_view.cc
|
| index d66624b58bbc8f31f3d98db6d09b939569b2a1e8..f638df0d1d4821c240033ce616937a8b15de8637 100644
|
| --- a/remoting/client/plugin/pepper_view.cc
|
| +++ b/remoting/client/plugin/pepper_view.cc
|
| @@ -6,14 +6,15 @@
|
|
|
| #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(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 +29,173 @@ 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, 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.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;
|
| }
|
| -
|
| - 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(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
|
|
|