Commit 94bc2ccf authored by wez@chromium.org's avatar wez@chromium.org

Make Chromoting client plugin always render at device DPI.

This addresses image quality issues when to a high-resolution device from a high-DPI but lower resolution client.  In this case Chromoting would down-scale to the plugin's DIP dimensions, only for Chrome to up-scale to device dimensions.

Follow-up CLs will add DPI information to the FrameConsumer interface, and try to optimize the plugin's up-scaling mode.

BUG=133349,135089


Review URL: https://chromiumcodereview.appspot.com/10785041

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@148012 0039d316-1c4b-4281-b951-d872f2087c98
parent ca5dfb21
...@@ -341,18 +341,13 @@ void ChromotingInstance::HandleMessage(const pp::Var& message) { ...@@ -341,18 +341,13 @@ void ChromotingInstance::HandleMessage(const pp::Var& message) {
} }
} }
void ChromotingInstance::DidChangeView(const pp::Rect& position, void ChromotingInstance::DidChangeView(const pp::View& view) {
const pp::Rect& clip) {
DCHECK(plugin_message_loop_->BelongsToCurrentThread()); DCHECK(plugin_message_loop_->BelongsToCurrentThread());
SkISize new_size = SkISize::Make(position.width(), position.height()); view_->SetView(view);
SkIRect new_clip =
SkIRect::MakeXYWH(clip.x(), clip.y(), clip.width(), clip.height());
view_->SetView(new_size, new_clip);
if (mouse_input_filter_.get()) { if (mouse_input_filter_.get()) {
mouse_input_filter_->set_input_size(view_->get_view_size()); mouse_input_filter_->set_input_size(view_->get_view_size_dips());
} }
} }
...@@ -484,7 +479,7 @@ void ChromotingInstance::Connect(const ClientConfig& config) { ...@@ -484,7 +479,7 @@ void ChromotingInstance::Connect(const ClientConfig& config) {
// Construct the input pipeline // Construct the input pipeline
mouse_input_filter_.reset( mouse_input_filter_.reset(
new protocol::MouseInputFilter(host_connection_->input_stub())); new protocol::MouseInputFilter(host_connection_->input_stub()));
mouse_input_filter_->set_input_size(view_->get_view_size()); mouse_input_filter_->set_input_size(view_->get_view_size_dips());
input_tracker_.reset( input_tracker_.reset(
new protocol::InputEventTracker(mouse_input_filter_.get())); new protocol::InputEventTracker(mouse_input_filter_.get()));
......
...@@ -98,8 +98,7 @@ class ChromotingInstance : ...@@ -98,8 +98,7 @@ class ChromotingInstance :
virtual ~ChromotingInstance(); virtual ~ChromotingInstance();
// pp::Instance interface. // pp::Instance interface.
virtual void DidChangeView(const pp::Rect& position, virtual void DidChangeView(const pp::View& view) OVERRIDE;
const pp::Rect& clip) OVERRIDE;
virtual bool Init(uint32_t argc, const char* argn[], virtual bool Init(uint32_t argc, const char* argn[],
const char* argv[]) OVERRIDE; const char* argv[]) OVERRIDE;
virtual void HandleMessage(const pp::Var& message) OVERRIDE; virtual void HandleMessage(const pp::Var& message) OVERRIDE;
......
...@@ -11,7 +11,8 @@ ...@@ -11,7 +11,8 @@
#include "base/time.h" #include "base/time.h"
#include "base/synchronization/waitable_event.h" #include "base/synchronization/waitable_event.h"
#include "ppapi/cpp/completion_callback.h" #include "ppapi/cpp/completion_callback.h"
#include "ppapi/cpp/graphics_2d.h" #include "ppapi/cpp/dev/graphics_2d_dev.h"
#include "ppapi/cpp/dev/view_dev.h"
#include "ppapi/cpp/image_data.h" #include "ppapi/cpp/image_data.h"
#include "ppapi/cpp/point.h" #include "ppapi/cpp/point.h"
#include "ppapi/cpp/rect.h" #include "ppapi/cpp/rect.h"
...@@ -46,6 +47,8 @@ PepperView::PepperView(ChromotingInstance* instance, ...@@ -46,6 +47,8 @@ PepperView::PepperView(ChromotingInstance* instance,
clip_area_(SkIRect::MakeEmpty()), clip_area_(SkIRect::MakeEmpty()),
source_size_(SkISize::Make(0, 0)), source_size_(SkISize::Make(0, 0)),
source_dpi_(SkIPoint::Make(0, 0)), source_dpi_(SkIPoint::Make(0, 0)),
view_size_dips_(SkISize::Make(0, 0)),
view_scale_(1.0f),
flush_pending_(false), flush_pending_(false),
frame_received_(false) { frame_received_(false) {
InitiateDrawing(); InitiateDrawing();
...@@ -66,27 +69,46 @@ PepperView::~PepperView() { ...@@ -66,27 +69,46 @@ PepperView::~PepperView() {
} }
} }
void PepperView::SetView(const SkISize& view_size, const SkIRect& clip_area) { void PepperView::SetView(const pp::View& view) {
bool view_changed = false; bool view_changed = false;
if (view_size_ != view_size) { pp::Rect pp_size = view.GetRect();
SkISize new_size_dips = SkISize::Make(pp_size.width(), pp_size.height());
pp::ViewDev view_dev(view);
float new_scale = view_dev.GetDeviceScale();
if (view_size_dips_ != new_size_dips || view_scale_ != new_scale) {
view_changed = true; view_changed = true;
view_size_ = view_size; view_scale_ = new_scale;
view_size_dips_ = new_size_dips;
view_size_ = SkISize::Make(ceilf(view_size_dips_.width() * view_scale_),
ceilf(view_size_dips_.height() * view_scale_));
pp::Size pp_size = pp::Size(view_size_.width(), view_size_.height()); pp::Size pp_size = pp::Size(view_size_.width(), view_size_.height());
graphics2d_ = pp::Graphics2D(instance_, pp_size, true); graphics2d_ = pp::Graphics2D(instance_, pp_size, true);
// Ideally we would always let Graphics2D scale us, but the output quality
// is lousy, so we don't.
pp::Graphics2DDev graphics2d_dev(graphics2d_);
graphics2d_dev.SetScale(1.0f / view_scale_);
bool result = instance_->BindGraphics(graphics2d_); bool result = instance_->BindGraphics(graphics2d_);
// There is no good way to handle this error currently. // There is no good way to handle this error currently.
DCHECK(result) << "Couldn't bind the device context."; DCHECK(result) << "Couldn't bind the device context.";
} }
if (clip_area_ != clip_area) { pp::Rect pp_clip = view.GetClipRect();
SkIRect new_clip = SkIRect::MakeLTRB(floorf(pp_clip.x() * view_scale_),
floorf(pp_clip.y() * view_scale_),
ceilf(pp_clip.right() * view_scale_),
ceilf(pp_clip.bottom() * view_scale_));
if (clip_area_ != new_clip) {
view_changed = true; view_changed = true;
// YUV to RGB conversion may require even X and Y coordinates for // YUV to RGB conversion may require even X and Y coordinates for
// the top left corner of the clipping area. // the top left corner of the clipping area.
clip_area_ = AlignRect(clip_area); clip_area_ = AlignRect(new_clip);
clip_area_.intersect(SkIRect::MakeSize(view_size_)); clip_area_.intersect(SkIRect::MakeSize(view_size_));
} }
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "ppapi/cpp/graphics_2d.h" #include "ppapi/cpp/graphics_2d.h"
#include "ppapi/cpp/view.h"
#include "ppapi/cpp/point.h" #include "ppapi/cpp/point.h"
#include "remoting/client/frame_consumer.h" #include "remoting/client/frame_consumer.h"
...@@ -44,10 +45,10 @@ class PepperView : public FrameConsumer, ...@@ -44,10 +45,10 @@ class PepperView : public FrameConsumer,
virtual void SetSourceSize(const SkISize& source_size, virtual void SetSourceSize(const SkISize& source_size,
const SkIPoint& dpi) OVERRIDE; const SkIPoint& dpi) OVERRIDE;
// Sets the display size and clipping area of this view. // Updates the PepperView's size, clipping area and scale factor.
void SetView(const SkISize& view_size, const SkIRect& clip_area); void SetView(const pp::View& view);
// Return the client view and original host dimensions. // Return the dimensions of the view and source in device pixels.
const SkISize& get_view_size() const { const SkISize& get_view_size() const {
return view_size_; return view_size_;
} }
...@@ -55,6 +56,12 @@ class PepperView : public FrameConsumer, ...@@ -55,6 +56,12 @@ class PepperView : public FrameConsumer,
return source_size_; return source_size_;
} }
// Return the dimensions of the view in Density Independent Pixels (DIPs).
// On high-DPI devices this will be smaller than the size in device pixels.
const SkISize& get_view_size_dips() const {
return view_size_dips_;
}
private: private:
// This routine allocates an image buffer. // This routine allocates an image buffer.
pp::ImageData* AllocateBuffer(); pp::ImageData* AllocateBuffer();
...@@ -91,22 +98,25 @@ class PepperView : public FrameConsumer, ...@@ -91,22 +98,25 @@ class PepperView : public FrameConsumer,
// List of allocated image buffers. // List of allocated image buffers.
std::list<pp::ImageData*> buffers_; std::list<pp::ImageData*> buffers_;
// Queued buffer to paint, with clip area and dirty region in device pixels.
pp::ImageData* merge_buffer_; pp::ImageData* merge_buffer_;
SkIRect merge_clip_area_; SkIRect merge_clip_area_;
SkRegion merge_region_; SkRegion merge_region_;
// The size of the plugin element. // View size, clip area and host dimensions, in device pixels.
SkISize view_size_; SkISize view_size_;
// The current clip area rectangle.
SkIRect clip_area_; SkIRect clip_area_;
// The size of the host screen.
SkISize source_size_; SkISize source_size_;
// The DPI of the host screen. // The DPI of the host screen.
SkIPoint source_dpi_; SkIPoint source_dpi_;
// View size in Density-Independent pixels.
SkISize view_size_dips_;
// DIP-to-device pixel scale factor.
float view_scale_;
// True if there is already a Flush() pending on the Graphics2D context. // True if there is already a Flush() pending on the Graphics2D context.
bool flush_pending_; bool flush_pending_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment