diff options
author | dmaclach@chromium.org <dmaclach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-11 05:08:49 +0000 |
---|---|---|
committer | dmaclach@chromium.org <dmaclach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-11 05:08:49 +0000 |
commit | 274e372af7a6d457e4773fdce215e3e6d70efcea (patch) | |
tree | 407836ad1a4f7a34fa14c8ff045e833d90b9b1d5 | |
parent | 418b75e0f077a184e6f1ae81f7e41e98454706dd (diff) | |
download | chromium_src-274e372af7a6d457e4773fdce215e3e6d70efcea.zip chromium_src-274e372af7a6d457e4773fdce215e3e6d70efcea.tar.gz chromium_src-274e372af7a6d457e4773fdce215e3e6d70efcea.tar.bz2 |
Switch over to using SkRegions to calculate dirty areas.
BUG=91619
TEST=Set up a remoting sesssion and make sure it works.
Review URL: http://codereview.chromium.org/7491070
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@96327 0039d316-1c4b-4281-b951-d872f2087c98
32 files changed, 498 insertions, 452 deletions
diff --git a/remoting/DEPS b/remoting/DEPS index 324f7a5..89f92b7 100644 --- a/remoting/DEPS +++ b/remoting/DEPS @@ -5,6 +5,9 @@ include_rules = [ "-remoting", "+remoting/base", "+remoting/proto", + "+skia/config", + "+skia/ext", "+third_party/GTM", "+third_party/GTM/AppKit", + "+third_party/skia/include/core", ] diff --git a/remoting/base/capture_data.cc b/remoting/base/capture_data.cc index 1740447..b66b239 100644 --- a/remoting/base/capture_data.cc +++ b/remoting/base/capture_data.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -17,7 +17,6 @@ CaptureData::CaptureData(const DataPlanes &data_planes, const gfx::Size& size, media::VideoFrame::Format format) : data_planes_(data_planes), - dirty_rects_(), size_(size), pixel_format_(format), capture_time_ms_(0), diff --git a/remoting/base/capture_data.h b/remoting/base/capture_data.h index b8592fa..ae5b89e 100644 --- a/remoting/base/capture_data.h +++ b/remoting/base/capture_data.h @@ -10,7 +10,8 @@ #include "base/basictypes.h" #include "base/memory/ref_counted.h" #include "media/base/video_frame.h" -#include "remoting/base/types.h" +#include "third_party/skia/include/core/SkRegion.h" +#include "ui/gfx/size.h" namespace remoting { @@ -30,12 +31,11 @@ class CaptureData : public base::RefCountedThreadSafe<CaptureData> { const gfx::Size& size, media::VideoFrame::Format format); - // Get the data_planes data of the last capture. + // Get the data_planes data of the previous capture. const DataPlanes& data_planes() const { return data_planes_; } - // Get the list of updated rectangles in the last capture. The result is - // written into |rects|. - const InvalidRects& dirty_rects() const { return dirty_rects_; } + // Get the dirty region from the previous capture. + const SkRegion& dirty_region() const { return dirty_region_; } // Return the size of the image captured. gfx::Size size() const { return size_; } @@ -44,7 +44,7 @@ class CaptureData : public base::RefCountedThreadSafe<CaptureData> { media::VideoFrame::Format pixel_format() const { return pixel_format_; } // Mutating methods. - InvalidRects& mutable_dirty_rects() { return dirty_rects_; } + SkRegion& mutable_dirty_region() { return dirty_region_; } // Return the time spent on capturing. int capture_time_ms() const { return capture_time_ms_; } @@ -62,7 +62,7 @@ class CaptureData : public base::RefCountedThreadSafe<CaptureData> { private: const DataPlanes data_planes_; - InvalidRects dirty_rects_; + SkRegion dirty_region_; gfx::Size size_; media::VideoFrame::Format pixel_format_; diff --git a/remoting/base/codec_test.cc b/remoting/base/codec_test.cc index d1b4978..0b62a63 100644 --- a/remoting/base/codec_test.cc +++ b/remoting/base/codec_test.cc @@ -1,10 +1,11 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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 <deque> #include <stdlib.h> +#include "base/memory/scoped_ptr.h" #include "media/base/video_frame.h" #include "remoting/base/base_mock_objects.h" #include "remoting/base/codec_test.h" @@ -12,19 +13,18 @@ #include "remoting/base/encoder.h" #include "remoting/base/util.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/gfx/rect.h" static const int kWidth = 320; static const int kHeight = 240; static const int kBytesPerPixel = 4; // Some sample rects for testing. -static const gfx::Rect kTestRects[] = { - gfx::Rect(0, 0, kWidth, kHeight), - gfx::Rect(0, 0, kWidth / 2, kHeight / 2), - gfx::Rect(kWidth / 2, kHeight / 2, kWidth / 2, kHeight / 2), - gfx::Rect(16, 16, 16, 16), - gfx::Rect(128, 64, 32, 32), +static const SkIRect kTestRects[] = { + SkIRect::MakeXYWH(0, 0, kWidth, kHeight), + SkIRect::MakeXYWH(0, 0, kWidth / 2, kHeight / 2), + SkIRect::MakeXYWH(kWidth / 2, kHeight / 2, kWidth / 2, kHeight / 2), + SkIRect::MakeXYWH(16, 16, 16, 16), + SkIRect::MakeXYWH(128, 64, 32, 32), }; namespace remoting { @@ -58,10 +58,10 @@ class EncoderMessageTester { ++begin_rect_; if (strict_) { - gfx::Rect rect = rects_.front(); + SkIRect rect = rects_.front(); rects_.pop_front(); - EXPECT_EQ(rect.x(), packet->format().x()); - EXPECT_EQ(rect.y(), packet->format().y()); + EXPECT_EQ(rect.fLeft, packet->format().x()); + EXPECT_EQ(rect.fTop, packet->format().y()); EXPECT_EQ(rect.width(), packet->format().width()); EXPECT_EQ(rect.height(), packet->format().height()); } @@ -93,7 +93,7 @@ class EncoderMessageTester { strict_ = strict; } - void AddRects(const gfx::Rect* rects, int count) { + void AddRects(const SkIRect* rects, int count) { rects_.insert(rects_.begin() + rects_.size(), rects, rects + count); added_rects_ += count; } @@ -111,7 +111,7 @@ class EncoderMessageTester { State state_; bool strict_; - std::deque<gfx::Rect> rects_; + std::deque<SkIRect> rects_; DISALLOW_COPY_AND_ASSIGN(EncoderMessageTester); }; @@ -152,7 +152,7 @@ class DecoderTester { capture_data_ = data; } - void AddRects(const gfx::Rect* rects, int count) { + void AddRects(const SkIRect* rects, int count) { rects_.insert(rects_.begin() + rects_.size(), rects, rects + count); } @@ -165,7 +165,8 @@ class DecoderTester { // Test the content of the update rect. ASSERT_EQ(rects_.size(), update_rects_.size()); for (size_t i = 0; i < update_rects_.size(); ++i) { - gfx::Rect rect = rects_[i]; + SkIRect &r = rects_[i]; + gfx::Rect rect(r.fLeft, r.fTop, r.width(), r.height()); EXPECT_EQ(rect, update_rects_[i]); EXPECT_EQ(frame_->stride(0), capture_data_->data_planes().strides[0]); @@ -186,7 +187,7 @@ class DecoderTester { private: bool strict_; - std::deque<gfx::Rect> rects_; + std::deque<SkIRect> rects_; UpdatedRects update_rects_; Decoder* decoder_; scoped_refptr<media::VideoFrame> frame_; @@ -221,7 +222,7 @@ class EncoderTester { delete packet; } - void AddRects(const gfx::Rect* rects, int count) { + void AddRects(const SkIRect* rects, int count) { message_tester_->AddRects(rects, count); } @@ -263,10 +264,10 @@ scoped_refptr<CaptureData> PrepareEncodeData(media::VideoFrame::Format format, static void TestEncodingRects(Encoder* encoder, EncoderTester* tester, scoped_refptr<CaptureData> data, - const gfx::Rect* rects, int count) { - data->mutable_dirty_rects().clear(); + const SkIRect* rects, int count) { + data->mutable_dirty_region().setEmpty(); for (int i = 0; i < count; ++i) { - data->mutable_dirty_rects().insert(rects[i]); + data->mutable_dirty_region().op(rects[i], SkRegion::kUnion_Op); } tester->AddRects(rects, count); @@ -283,22 +284,22 @@ void TestEncoder(Encoder* encoder, bool strict) { uint8* memory; scoped_refptr<CaptureData> data = PrepareEncodeData(media::VideoFrame::RGB32, &memory); + scoped_array<uint8> memory_wrapper(memory); TestEncodingRects(encoder, &tester, data, kTestRects, 1); TestEncodingRects(encoder, &tester, data, kTestRects + 1, 1); TestEncodingRects(encoder, &tester, data, kTestRects + 2, 1); TestEncodingRects(encoder, &tester, data, kTestRects + 3, 2); - delete [] memory; } static void TestEncodingRects(Encoder* encoder, EncoderTester* encoder_tester, DecoderTester* decoder_tester, scoped_refptr<CaptureData> data, - const gfx::Rect* rects, int count) { - data->mutable_dirty_rects().clear(); + const SkIRect* rects, int count) { + data->mutable_dirty_region().setEmpty(); for (int i = 0; i < count; ++i) { - data->mutable_dirty_rects().insert(rects[i]); + data->mutable_dirty_region().op(rects[i], SkRegion::kUnion_Op); } encoder_tester->AddRects(rects, count); decoder_tester->AddRects(rects, count); @@ -306,12 +307,12 @@ static void TestEncodingRects(Encoder* encoder, // Generate random data for the updated rects. srand(0); for (int i = 0; i < count; ++i) { - const gfx::Rect rect = rects[i]; + const SkIRect& rect = rects[i]; const int bytes_per_pixel = GetBytesPerPixel(data->pixel_format()); const int row_size = bytes_per_pixel * rect.width(); uint8* memory = data->data_planes().data[0] + - data->data_planes().strides[0] * rect.y() + - bytes_per_pixel * rect.x(); + data->data_planes().strides[0] * rect.fTop + + bytes_per_pixel * rect.fLeft; for (int y = 0; y < rect.height(); ++y) { for (int x = 0; x < row_size; ++x) memory[x] = rand() % 256; @@ -334,6 +335,8 @@ void TestEncoderDecoder(Encoder* encoder, Decoder* decoder, bool strict) { uint8* memory; scoped_refptr<CaptureData> data = PrepareEncodeData(media::VideoFrame::RGB32, &memory); + scoped_array<uint8> memory_wrapper(memory); + DecoderTester decoder_tester(decoder); decoder_tester.set_strict(strict); decoder_tester.set_capture_data(data); @@ -347,7 +350,6 @@ void TestEncoderDecoder(Encoder* encoder, Decoder* decoder, bool strict) { kTestRects + 2, 1); TestEncodingRects(encoder, &encoder_tester, &decoder_tester, data, kTestRects + 3, 2); - delete [] memory; } } // namespace remoting diff --git a/remoting/base/decoder.h b/remoting/base/decoder.h index a0a9244..b13483f 100644 --- a/remoting/base/decoder.h +++ b/remoting/base/decoder.h @@ -46,6 +46,8 @@ class Decoder { // Returns rects that were updated in the last frame. Can be called only // after DecodePacket returned DECODE_DONE. Caller keeps ownership of // |rects|. |rects| is kept empty if whole screen needs to be updated. + // TODO(dmaclach): Move this over to using SkRegion. + // http://crbug.com/92085 virtual void GetUpdatedRects(UpdatedRects* rects) = 0; // Reset the decoder to an uninitialized state. Release all references to diff --git a/remoting/base/encoder_row_based.cc b/remoting/base/encoder_row_based.cc index 8039869..75af34a 100644 --- a/remoting/base/encoder_row_based.cc +++ b/remoting/base/encoder_row_based.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -66,16 +66,19 @@ void EncoderRowBased::Encode(scoped_refptr<CaptureData> capture_data, capture_data_ = capture_data; callback_.reset(data_available_callback); - const InvalidRects& rects = capture_data->dirty_rects(); - for (InvalidRects::const_iterator r = rects.begin(); r != rects.end(); ++r) { - EncodeRect(*r, r == --rects.end()); + const SkRegion& region = capture_data->dirty_region(); + SkRegion::Iterator iter(region); + while (!iter.done()) { + SkIRect rect = iter.rect(); + iter.next(); + EncodeRect(rect, iter.done()); } capture_data_ = NULL; callback_.reset(); } -void EncoderRowBased::EncodeRect(const gfx::Rect& rect, bool last) { +void EncoderRowBased::EncodeRect(const SkIRect& rect, bool last) { CHECK(capture_data_->data_planes().data[0]); const int strides = capture_data_->data_planes().strides[0]; const int bytes_per_pixel = GetBytesPerPixel(capture_data_->pixel_format()); @@ -86,7 +89,7 @@ void EncoderRowBased::EncodeRect(const gfx::Rect& rect, bool last) { VideoPacket* packet = new VideoPacket(); PrepareUpdateStart(rect, packet); const uint8* in = capture_data_->data_planes().data[0] + - rect.y() * strides + rect.x() * bytes_per_pixel; + rect.fTop * strides + rect.fLeft * bytes_per_pixel; // TODO(hclam): Fill in the sequence number. uint8* out = GetOutputBuffer(packet, packet_size_); int filled = 0; @@ -142,13 +145,13 @@ void EncoderRowBased::EncodeRect(const gfx::Rect& rect, bool last) { } } -void EncoderRowBased::PrepareUpdateStart(const gfx::Rect& rect, +void EncoderRowBased::PrepareUpdateStart(const SkIRect& rect, VideoPacket* packet) { packet->set_flags(packet->flags() | VideoPacket::FIRST_PACKET); VideoPacketFormat* format = packet->mutable_format(); - format->set_x(rect.x()); - format->set_y(rect.y()); + format->set_x(rect.fLeft); + format->set_y(rect.fTop); format->set_width(rect.width()); format->set_height(rect.height()); format->set_encoding(encoding_); diff --git a/remoting/base/encoder_row_based.h b/remoting/base/encoder_row_based.h index d453ffb..6da2cd5 100644 --- a/remoting/base/encoder_row_based.h +++ b/remoting/base/encoder_row_based.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -7,8 +7,8 @@ #include "remoting/base/encoder.h" #include "remoting/proto/video.pb.h" - -#include "ui/gfx/rect.h" +#include "third_party/skia/include/core/SkRect.h" +#include "ui/gfx/size.h" namespace remoting { @@ -41,10 +41,10 @@ class EncoderRowBased : public Encoder { int packet_size); // Encode a single dirty rect using compressor. - void EncodeRect(const gfx::Rect& rect, bool last); + void EncodeRect(const SkIRect& rect, bool last); // Marks a packet as the first in a series of rectangle updates. - void PrepareUpdateStart(const gfx::Rect& rect, VideoPacket* packet); + void PrepareUpdateStart(const SkIRect& rect, VideoPacket* packet); // Retrieves a pointer to the output buffer in |update| used for storing the // encoded rectangle data. Will resize the buffer to |size|. diff --git a/remoting/base/encoder_vp8.cc b/remoting/base/encoder_vp8.cc index 447e5d5..5616bba 100644 --- a/remoting/base/encoder_vp8.cc +++ b/remoting/base/encoder_vp8.cc @@ -10,6 +10,7 @@ #include "remoting/base/capture_data.h" #include "remoting/base/util.h" #include "remoting/proto/video.pb.h" +#include "third_party/skia/include/core/SkRegion.h" extern "C" { #define VPX_CODEC_DISABLE_COMPAT 1 @@ -148,7 +149,7 @@ bool EncoderVp8::PrepareImage(scoped_refptr<CaptureData> capture_data, return false; } - const InvalidRects& rects = capture_data->dirty_rects(); + const SkRegion& region = capture_data->dirty_region(); const uint8* in = capture_data->data_planes().data[0]; const int in_stride = capture_data->data_planes().strides[0]; const int plane_size = @@ -160,9 +161,11 @@ bool EncoderVp8::PrepareImage(scoped_refptr<CaptureData> capture_data, const int uv_stride = image_->stride[1]; DCHECK(updated_rects->empty()); - for (InvalidRects::const_iterator r = rects.begin(); r != rects.end(); ++r) { + for (SkRegion::Iterator r(region); !r.done(); r.next()) { // Align the rectangle, report it as updated. - gfx::Rect rect = AlignAndClipRect(*r, image_->w, image_->h); + SkIRect skRect = r.rect(); + gfx::Rect rect(skRect.fLeft, skRect.fTop, skRect.width(), skRect.height()); + rect = AlignAndClipRect(rect, image_->w, image_->h); if (!rect.IsEmpty()) updated_rects->push_back(rect); diff --git a/remoting/base/types.h b/remoting/base/types.h deleted file mode 100644 index 1c93f6f..0000000 --- a/remoting/base/types.h +++ /dev/null @@ -1,21 +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_BASE_TYPES_H_ -#define REMOTING_BASE_TYPES_H_ - -#include <set> - -#include "ui/gfx/rect.h" - -namespace remoting { - -// The collection of 'invalid' screen rectangles. -// This is used to keep track of regions of the screen that require -// updating. -typedef std::set<gfx::Rect> InvalidRects; - -} // namespace remoting - -#endif // REMOTING_BASE_TYPES_H_ diff --git a/remoting/base/util.cc b/remoting/base/util.cc index 8671eeb..483d97f 100644 --- a/remoting/base/util.cc +++ b/remoting/base/util.cc @@ -161,11 +161,11 @@ void CopyRect(const uint8* src_plane, uint8* dest_plane, int dest_plane_stride, int bytes_per_pixel, - const gfx::Rect& rect) { + const SkIRect& rect) { // Get the address of the starting point. - const int src_y_offset = src_plane_stride * rect.y(); - const int dest_y_offset = dest_plane_stride * rect.y(); - const int x_offset = bytes_per_pixel * rect.x(); + const int src_y_offset = src_plane_stride * rect.fTop; + const int dest_y_offset = dest_plane_stride * rect.fTop; + const int x_offset = bytes_per_pixel * rect.fLeft; src_plane += src_y_offset + x_offset; dest_plane += dest_y_offset + x_offset; diff --git a/remoting/base/util.h b/remoting/base/util.h index d0e0b0d..262b551 100644 --- a/remoting/base/util.h +++ b/remoting/base/util.h @@ -6,6 +6,7 @@ #define REMOTING_BASE_UTIL_H_ #include "media/base/video_frame.h" +#include "third_party/skia/include/core/SkRect.h" #include "ui/gfx/rect.h" namespace remoting { @@ -64,7 +65,7 @@ void CopyRect(const uint8* src_plane, uint8* dest_plane, int dest_plane_stride, int bytes_per_pixel, - const gfx::Rect& rect); + const SkIRect& rect); } // namespace remoting diff --git a/remoting/host/capturer.h b/remoting/host/capturer.h index 5b95294..7d74c17 100644 --- a/remoting/host/capturer.h +++ b/remoting/host/capturer.h @@ -8,7 +8,7 @@ #include "base/basictypes.h" #include "base/callback_old.h" #include "remoting/base/capture_data.h" -#include "remoting/base/types.h" +#include "third_party/skia/include/core/SkRegion.h" namespace remoting { @@ -51,11 +51,11 @@ class Capturer { // Return the pixel format of the screen. virtual media::VideoFrame::Format pixel_format() const = 0; - // Clear out the list of invalid rects. - virtual void ClearInvalidRects() = 0; + // Clear out the invalid region. + virtual void ClearInvalidRegion() = 0; - // Invalidate the specified screen rects. - virtual void InvalidateRects(const InvalidRects& inval_rects) = 0; + // Invalidate the specified region. + virtual void InvalidateRegion(const SkRegion& invalid_region) = 0; // Invalidate the entire screen, of a given size. virtual void InvalidateScreen(const gfx::Size& size) = 0; @@ -65,19 +65,15 @@ class Capturer { virtual void InvalidateFullScreen() = 0; // Capture the screen data associated with each of the accumulated - // rects in |inval_rects|. - // This routine will first call CalculateInvalidRects to update the - // list of |inval_rects|. - // When the capture is complete, |callback| is called. - // - // If |inval_rects_| is empty, then this does nothing except - // call the |callback| routine. + // dirty region. + // When the capture is complete, |callback| is called even if the dirty region + // is empty. // // It is OK to call this method while another thread is reading - // data of the last capture. + // data of the previous capture. // There can be at most one concurrent read going on when this // method is called. - virtual void CaptureInvalidRects(CaptureCompletedCallback* callback) = 0; + virtual void CaptureInvalidRegion(CaptureCompletedCallback* callback) = 0; // Get the size of the most recently captured screen. virtual const gfx::Size& size_most_recent() const = 0; diff --git a/remoting/host/capturer_fake.cc b/remoting/host/capturer_fake.cc index 8f81b5b..717e0ad 100644 --- a/remoting/host/capturer_fake.cc +++ b/remoting/host/capturer_fake.cc @@ -54,12 +54,12 @@ media::VideoFrame::Format CapturerFake::pixel_format() const { return pixel_format_; } -void CapturerFake::ClearInvalidRects() { - helper.ClearInvalidRects(); +void CapturerFake::ClearInvalidRegion() { + helper.ClearInvalidRegion(); } -void CapturerFake::InvalidateRects(const InvalidRects& inval_rects) { - helper.InvalidateRects(inval_rects); +void CapturerFake::InvalidateRegion(const SkRegion& invalid_region) { + helper.InvalidateRegion(invalid_region); } void CapturerFake::InvalidateScreen(const gfx::Size& size) { @@ -70,14 +70,14 @@ void CapturerFake::InvalidateFullScreen() { helper.InvalidateFullScreen(); } -void CapturerFake::CaptureInvalidRects(CaptureCompletedCallback* callback) { +void CapturerFake::CaptureInvalidRegion(CaptureCompletedCallback* callback) { scoped_ptr<CaptureCompletedCallback> callback_deleter(callback); GenerateImage(); InvalidateScreen(size_); - InvalidRects inval_rects; - helper.SwapInvalidRects(inval_rects); + SkRegion invalid_region; + helper.SwapInvalidRegion(&invalid_region); DataPlanes planes; planes.data[0] = buffers_[current_buffer_].get(); @@ -87,7 +87,7 @@ void CapturerFake::CaptureInvalidRects(CaptureCompletedCallback* callback) { scoped_refptr<CaptureData> capture_data(new CaptureData(planes, size_, pixel_format_)); - capture_data->mutable_dirty_rects() = inval_rects; + capture_data->mutable_dirty_region() = invalid_region; helper.set_size_most_recent(capture_data->size()); diff --git a/remoting/host/capturer_fake.h b/remoting/host/capturer_fake.h index 879ee03..61f41283 100644 --- a/remoting/host/capturer_fake.h +++ b/remoting/host/capturer_fake.h @@ -21,14 +21,15 @@ class CapturerFake : public Capturer { virtual ~CapturerFake(); // Capturer interface. - virtual void ScreenConfigurationChanged(); - virtual media::VideoFrame::Format pixel_format() const; - virtual void ClearInvalidRects(); - virtual void InvalidateRects(const InvalidRects& inval_rects); - virtual void InvalidateScreen(const gfx::Size& size); - virtual void InvalidateFullScreen(); - virtual void CaptureInvalidRects(CaptureCompletedCallback* callback); - virtual const gfx::Size& size_most_recent() const; + virtual void ScreenConfigurationChanged() OVERRIDE; + virtual media::VideoFrame::Format pixel_format() const OVERRIDE; + virtual void ClearInvalidRegion() OVERRIDE; + virtual void InvalidateRegion(const SkRegion& invalid_region) OVERRIDE; + virtual void InvalidateScreen(const gfx::Size& size) OVERRIDE; + virtual void InvalidateFullScreen() OVERRIDE; + virtual void CaptureInvalidRegion(CaptureCompletedCallback* callback) + OVERRIDE; + virtual const gfx::Size& size_most_recent() const OVERRIDE; private: // Generates an image in the front buffer. diff --git a/remoting/host/capturer_fake_ascii.cc b/remoting/host/capturer_fake_ascii.cc index 40f4509..e24bebd 100644 --- a/remoting/host/capturer_fake_ascii.cc +++ b/remoting/host/capturer_fake_ascii.cc @@ -37,23 +37,23 @@ media::VideoFrame::Format CapturerFakeAscii::pixel_format() const { return pixel_format_; } -void CapturerFakeAscii::ClearInvalidRects() { - helper.ClearInvalidRects(); +void CapturerFakeAscii::ClearInvalidRegion() { + helper_.ClearInvalidRegion(); } -void CapturerFakeAscii::InvalidateRects(const InvalidRects& inval_rects) { - helper.InvalidateRects(inval_rects); +void CapturerFakeAscii::InvalidateRegion(const SkRegion& invalid_region) { + helper_.InvalidateRegion(invalid_region); } void CapturerFakeAscii::InvalidateScreen(const gfx::Size& size) { - helper.InvalidateScreen(size); + helper_.InvalidateScreen(size); } void CapturerFakeAscii::InvalidateFullScreen() { - helper.InvalidateFullScreen(); + helper_.InvalidateFullScreen(); } -void CapturerFakeAscii::CaptureInvalidRects( +void CapturerFakeAscii::CaptureInvalidRegion( CaptureCompletedCallback* callback) { scoped_ptr<CaptureCompletedCallback> callback_deleter(callback); @@ -65,13 +65,13 @@ void CapturerFakeAscii::CaptureInvalidRects( scoped_refptr<CaptureData> capture_data(new CaptureData( planes, gfx::Size(width_, height_), pixel_format_)); - helper.set_size_most_recent(capture_data->size()); + helper_.set_size_most_recent(capture_data->size()); callback->Run(capture_data); } const gfx::Size& CapturerFakeAscii::size_most_recent() const { - return helper.size_most_recent(); + return helper_.size_most_recent(); } void CapturerFakeAscii::GenerateImage() { diff --git a/remoting/host/capturer_fake_ascii.h b/remoting/host/capturer_fake_ascii.h index 2f348ad..a7c0d3c 100644 --- a/remoting/host/capturer_fake_ascii.h +++ b/remoting/host/capturer_fake_ascii.h @@ -22,13 +22,14 @@ class CapturerFakeAscii : public Capturer { virtual ~CapturerFakeAscii(); // Capturer interface. - virtual void ScreenConfigurationChanged(); - virtual media::VideoFrame::Format pixel_format() const; - virtual void ClearInvalidRects(); - virtual void InvalidateRects(const InvalidRects& inval_rects); - virtual void InvalidateScreen(const gfx::Size& size); - virtual void InvalidateFullScreen(); - virtual void CaptureInvalidRects(CaptureCompletedCallback* callback); + virtual void ScreenConfigurationChanged() OVERRIDE; + virtual media::VideoFrame::Format pixel_format() const OVERRIDE; + virtual void ClearInvalidRegion() OVERRIDE; + virtual void InvalidateRegion(const SkRegion& invalid_region) OVERRIDE; + virtual void InvalidateScreen(const gfx::Size& size) OVERRIDE; + virtual void InvalidateFullScreen() OVERRIDE; + virtual void CaptureInvalidRegion(CaptureCompletedCallback* callback) + OVERRIDE; virtual const gfx::Size& size_most_recent() const; private: @@ -40,7 +41,7 @@ class CapturerFakeAscii : public Capturer { int height_; int bytes_per_row_; - CapturerHelper helper; + CapturerHelper helper_; // We have two buffers for the screen images as required by Capturer. static const int kNumBuffers = 2; diff --git a/remoting/host/capturer_helper.cc b/remoting/host/capturer_helper.cc index eba7c12..8cb0295 100644 --- a/remoting/host/capturer_helper.cc +++ b/remoting/host/capturer_helper.cc @@ -4,9 +4,6 @@ #include "remoting/host/capturer_helper.h" -#include <algorithm> -#include <iterator> - namespace remoting { CapturerHelper::CapturerHelper() : size_most_recent_(0, 0) { @@ -15,24 +12,20 @@ CapturerHelper::CapturerHelper() : size_most_recent_(0, 0) { CapturerHelper::~CapturerHelper() { } -void CapturerHelper::ClearInvalidRects() { - base::AutoLock auto_inval_rects_lock(inval_rects_lock_); - inval_rects_.clear(); +void CapturerHelper::ClearInvalidRegion() { + base::AutoLock auto_invalid_region_lock(invalid_region_lock_); + invalid_region_.setEmpty(); } -void CapturerHelper::InvalidateRects(const InvalidRects& inval_rects) { - base::AutoLock auto_inval_rects_lock(inval_rects_lock_); - InvalidRects temp_rects; - std::set_union(inval_rects_.begin(), inval_rects_.end(), - inval_rects.begin(), inval_rects.end(), - std::inserter(temp_rects, temp_rects.begin())); - inval_rects_.swap(temp_rects); +void CapturerHelper::InvalidateRegion(const SkRegion& invalid_region) { + base::AutoLock auto_invalid_region_lock(invalid_region_lock_); + invalid_region_.op(invalid_region, SkRegion::kUnion_Op); } void CapturerHelper::InvalidateScreen(const gfx::Size& size) { - base::AutoLock auto_inval_rects_lock(inval_rects_lock_); - inval_rects_.clear(); - inval_rects_.insert(gfx::Rect(0, 0, size.width(), size.height())); + base::AutoLock auto_invalid_region_lock(invalid_region_lock_); + invalid_region_.op(SkIRect::MakeWH(size.width(), size.height()), + SkRegion::kUnion_Op); } void CapturerHelper::InvalidateFullScreen() { @@ -40,17 +33,17 @@ void CapturerHelper::InvalidateFullScreen() { InvalidateScreen(size_most_recent_); } +// TODO: Is this actually required? +// http://crbug.com/92346 bool CapturerHelper::IsCaptureFullScreen(const gfx::Size& size) { - base::AutoLock auto_inval_rects_lock(inval_rects_lock_); - return inval_rects_.size() == 1u && - inval_rects_.begin()->x() == 0 && inval_rects_.begin()->y() == 0 && - inval_rects_.begin()->width() == size.width() && - inval_rects_.begin()->height() == size.height(); + base::AutoLock auto_invalid_region_lock(invalid_region_lock_); + SkRegion fullScreenRegion(SkIRect::MakeWH(size.width(), size.height())); + return fullScreenRegion == invalid_region_; } -void CapturerHelper::SwapInvalidRects(InvalidRects& inval_rects) { - base::AutoLock auto_inval_rects_lock(inval_rects_lock_); - inval_rects.swap(inval_rects_); +void CapturerHelper::SwapInvalidRegion(SkRegion* invalid_region) { + base::AutoLock auto_invalid_region_lock(invalid_region_lock_); + invalid_region->swap(invalid_region_); } const gfx::Size& CapturerHelper::size_most_recent() const { diff --git a/remoting/host/capturer_helper.h b/remoting/host/capturer_helper.h index b7650c0..36968a1 100644 --- a/remoting/host/capturer_helper.h +++ b/remoting/host/capturer_helper.h @@ -6,24 +6,24 @@ #define REMOTING_HOST_CAPTURER_HELPER_H_ #include "base/synchronization/lock.h" -#include "remoting/base/types.h" +#include "third_party/skia/include/core/SkRegion.h" +#include "ui/gfx/size.h" namespace remoting { // CapturerHelper is intended to be used by an implementation of the Capturer -// interface. It maintains a thread-safe list of invalid rectangles, and the -// size of the most recently captured screen, on behalf of the Capturer that -// owns it. +// interface. It maintains a thread-safe invalid region, and the size of the +// most recently captured screen, on behalf of the Capturer that owns it. class CapturerHelper { public: CapturerHelper(); ~CapturerHelper(); - // Clear out the list of invalid rects. - void ClearInvalidRects(); + // Clear out the invalid region. + void ClearInvalidRegion(); - // Invalidate the specified screen rects. - void InvalidateRects(const InvalidRects& inval_rects); + // Invalidate the specified region. + void InvalidateRegion(const SkRegion& invalid_region); // Invalidate the entire screen, of a given size. void InvalidateScreen(const gfx::Size& size); @@ -35,29 +35,21 @@ class CapturerHelper { // Whether the invalid region is a full screen of a given size. bool IsCaptureFullScreen(const gfx::Size& size); - // Swap the given set of rects with the stored invalid rects. - // This should be used like this: - // - // InvalidRects inval_rects; - // common.SwapInvalidRects(inval_rects); - // - // This passes the invalid rects to the caller, and removes them from this - // object. The caller should then pass the raster data in those rects to the - // client. - void SwapInvalidRects(InvalidRects& inval_rects); + // Swap the given region with the stored invalid region. + void SwapInvalidRegion(SkRegion* invalid_region); // Access the size of the most recently captured screen. const gfx::Size& size_most_recent() const; void set_size_most_recent(const gfx::Size& size); private: - // Rects that have been manually invalidated (through InvalidateRect). - // These will be returned as dirty_rects in the capture data during the next + // A region that has been manually invalidated (through InvalidateRegion). + // These will be returned as dirty_region in the capture data during the next // capture. - InvalidRects inval_rects_; + SkRegion invalid_region_; - // A lock protecting |inval_rects_| across threads. - base::Lock inval_rects_lock_; + // A lock protecting |invalid_region_| across threads. + base::Lock invalid_region_lock_; // The size of the most recently captured screen. gfx::Size size_most_recent_; diff --git a/remoting/host/capturer_linux.cc b/remoting/host/capturer_linux.cc index 0c79715..dc68cf6 100644 --- a/remoting/host/capturer_linux.cc +++ b/remoting/host/capturer_linux.cc @@ -13,7 +13,6 @@ #include "base/basictypes.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" -#include "remoting/base/types.h" #include "remoting/host/capturer_helper.h" #include "remoting/host/differ.h" #include "remoting/host/x_server_pixel_buffer.h" @@ -75,11 +74,12 @@ class CapturerLinux : public Capturer { // Capturer interface. virtual void ScreenConfigurationChanged() OVERRIDE; virtual media::VideoFrame::Format pixel_format() const OVERRIDE; - virtual void ClearInvalidRects() OVERRIDE; - virtual void InvalidateRects(const InvalidRects& inval_rects) OVERRIDE; + virtual void ClearInvalidRegion() OVERRIDE; + virtual void InvalidateRegion(const SkRegion& invalid_region) OVERRIDE; virtual void InvalidateScreen(const gfx::Size& size) OVERRIDE; virtual void InvalidateFullScreen() OVERRIDE; - virtual void CaptureInvalidRects(CaptureCompletedCallback* callback) OVERRIDE; + virtual void CaptureInvalidRegion(CaptureCompletedCallback* callback) + OVERRIDE; virtual const gfx::Size& size_most_recent() const OVERRIDE; private: @@ -114,12 +114,12 @@ class CapturerLinux : public Capturer { // Capture a rectangle from |x_server_pixel_buffer_|, and copy the data into // |capture_data|. - void CaptureRect(const gfx::Rect& rect, CaptureData* capture_data); + void CaptureRect(const SkIRect& rect, CaptureData* capture_data); // We expose two forms of blitting to handle variations in the pixel format. // In FastBlit, the operation is effectively a memcpy. - void FastBlit(uint8* image, const gfx::Rect& rect, CaptureData* capture_data); - void SlowBlit(uint8* image, const gfx::Rect& rect, CaptureData* capture_data); + void FastBlit(uint8* image, const SkIRect& rect, CaptureData* capture_data); + void SlowBlit(uint8* image, const SkIRect& rect, CaptureData* capture_data); // X11 graphics context. Display* display_; @@ -147,9 +147,9 @@ class CapturerLinux : public Capturer { // Format of pixels returned in buffer. media::VideoFrame::Format pixel_format_; - // Invalid rects in the last capture. This is used to synchronize current with - // the previous buffer used. - InvalidRects last_invalid_rects_; + // Invalid region from the previous capture. This is used to synchronize the + // current with the last buffer used. + SkRegion last_invalid_region_; // Last capture buffer used. uint8* last_buffer_; @@ -240,8 +240,7 @@ void CapturerLinux::ScreenConfigurationChanged() { for (int i = 0; i < kNumBuffers; ++i) { buffers_[i].set_needs_update(); } - InvalidRects rects; - helper_.SwapInvalidRects(rects); + helper_.ClearInvalidRegion(); x_server_pixel_buffer_.Init(display_); } @@ -249,12 +248,12 @@ media::VideoFrame::Format CapturerLinux::pixel_format() const { return pixel_format_; } -void CapturerLinux::ClearInvalidRects() { - helper_.ClearInvalidRects(); +void CapturerLinux::ClearInvalidRegion() { + helper_.ClearInvalidRegion(); } -void CapturerLinux::InvalidateRects(const InvalidRects& inval_rects) { - helper_.InvalidateRects(inval_rects); +void CapturerLinux::InvalidateRegion(const SkRegion& invalid_region) { + helper_.InvalidateRegion(invalid_region); } void CapturerLinux::InvalidateScreen(const gfx::Size& size) { @@ -266,7 +265,7 @@ void CapturerLinux::InvalidateFullScreen() { last_buffer_ = NULL; } -void CapturerLinux::CaptureInvalidRects( +void CapturerLinux::CaptureInvalidRegion( CaptureCompletedCallback* callback) { scoped_ptr<CaptureCompletedCallback> callback_deleter(callback); @@ -297,7 +296,7 @@ void CapturerLinux::ProcessPendingXEvents() { // on XPending because we want to guarantee this terminates. int events_to_process = XPending(display_); XEvent e; - InvalidRects invalid_rects; + SkRegion invalid_region; for (int i = 0; i < events_to_process; i++) { XNextEvent(display_, &e); @@ -308,21 +307,23 @@ void CapturerLinux::ProcessPendingXEvents() { if (event->area.width <= 0 || event->area.height <= 0) continue; - gfx::Rect damage_rect(event->area.x, event->area.y, event->area.width, - event->area.height); - invalid_rects.insert(damage_rect); - VLOG(3) << "Damage received for rect at (" - << damage_rect.x() << "," << damage_rect.y() << ") size (" - << damage_rect.width() << "," << damage_rect.height() << ")"; + SkIRect damage_rect = SkIRect::MakeXYWH(event->area.x, + event->area.y, + event->area.width, + event->area.height); + invalid_region.op(damage_rect, SkRegion::kUnion_Op); + DVLOG(3) << "Damage received for rect at (" + << damage_rect.fLeft << "," << damage_rect.fTop << ") size (" + << damage_rect.width() << "," << damage_rect.height() << ")"; } else if (e.type == ConfigureNotify) { ScreenConfigurationChanged(); - invalid_rects.clear(); + invalid_region.setEmpty(); } else { LOG(WARNING) << "Got unknown event type: " << e.type; } } - helper_.InvalidateRects(invalid_rects); + helper_.InvalidateRegion(invalid_region); } CaptureData* CapturerLinux::CaptureFrame() { @@ -341,60 +342,60 @@ CaptureData* CapturerLinux::CaptureFrame() { if (use_damage_ && last_buffer_) SynchronizeFrame(); - InvalidRects invalid_rects; + SkRegion invalid_region; x_server_pixel_buffer_.Synchronize(); if (use_damage_ && last_buffer_) { - helper_.SwapInvalidRects(invalid_rects); - for (InvalidRects::const_iterator it = invalid_rects.begin(); - it != invalid_rects.end(); - ++it) { - CaptureRect(*it, capture_data); + helper_.SwapInvalidRegion(&invalid_region); + for (SkRegion::Iterator it(invalid_region); !it.done(); it.next()) { + CaptureRect(it.rect(), capture_data); } // TODO(ajwong): We should only repair the rects that were copied! XDamageSubtract(display_, damage_handle_, None, None); } else { // Doing full-screen polling, or this is the first capture after a // screen-resolution change. In either case, need a full-screen capture. - gfx::Rect screen_rect(buffer.size()); + SkIRect screen_rect = SkIRect::MakeWH(buffer.size().width(), + buffer.size().height()); CaptureRect(screen_rect, capture_data); if (last_buffer_) { // Full-screen polling, so calculate the invalid rects here, based on the // changed pixels between current and previous buffers. DCHECK(differ_ != NULL); - differ_->CalcDirtyRects(last_buffer_, buffer.ptr(), &invalid_rects); + differ_->CalcDirtyRegion(last_buffer_, buffer.ptr(), &invalid_region); } else { // No previous buffer, so always invalidate the whole screen, whether // or not DAMAGE is being used. DAMAGE doesn't necessarily send a // full-screen notification after a screen-resolution change, so // this is done here. - invalid_rects.insert(screen_rect); + invalid_region.op(screen_rect, SkRegion::kUnion_Op); } } - capture_data->mutable_dirty_rects() = invalid_rects; - last_invalid_rects_ = invalid_rects; + capture_data->mutable_dirty_region() = invalid_region; + last_invalid_region_ = invalid_region; last_buffer_ = buffer.ptr(); return capture_data; } void CapturerLinux::SynchronizeFrame() { - // Synchronize the current buffer with the last one since we do not capture - // the entire desktop. Note that encoder may be reading from the previous - // buffer at this time so thread access complaints are false positives. + // Synchronize the current buffer with the previous one since we do not + // capture the entire desktop. Note that encoder may be reading from the + // previous buffer at this time so thread access complaints are false + // positives. // TODO(hclam): We can reduce the amount of copying here by subtracting - // |rects| from |last_invalid_rects_|. + // |capturer_helper_|s region from |last_invalid_region_|. + // http://crbug.com/92354 DCHECK(last_buffer_); VideoFrameBuffer& buffer = buffers_[current_buffer_]; - for (InvalidRects::const_iterator it = last_invalid_rects_.begin(); - it != last_invalid_rects_.end(); - ++it) { - int offset = it->y() * buffer.bytes_per_row() + it->x() * kBytesPerPixel; - for (int i = 0; i < it->height(); ++i) { + for (SkRegion::Iterator it(last_invalid_region_); !it.done(); it.next()) { + const SkIRect& r = it.rect(); + int offset = r.fTop * buffer.bytes_per_row() + r.fLeft * kBytesPerPixel; + for (int i = 0; i < r.height(); ++i) { memcpy(buffer.ptr() + offset, last_buffer_ + offset, - it->width() * kBytesPerPixel); + r.width() * kBytesPerPixel); offset += buffer.size().width() * kBytesPerPixel; } } @@ -412,26 +413,26 @@ void CapturerLinux::DeinitXlib() { } } -void CapturerLinux::CaptureRect(const gfx::Rect& rect, +void CapturerLinux::CaptureRect(const SkIRect& rect, CaptureData* capture_data) { uint8* image = x_server_pixel_buffer_.CaptureRect(rect); int depth = x_server_pixel_buffer_.GetDepth(); int bpp = x_server_pixel_buffer_.GetBitsPerPixel(); bool is_rgb = x_server_pixel_buffer_.IsRgb(); if ((depth == 24 || depth == 32) && bpp == 32 && is_rgb) { - VLOG(3) << "Fast blitting"; + DVLOG(3) << "Fast blitting"; FastBlit(image, rect, capture_data); } else { - VLOG(3) << "Slow blitting"; + DVLOG(3) << "Slow blitting"; SlowBlit(image, rect, capture_data); } } -void CapturerLinux::FastBlit(uint8* image, const gfx::Rect& rect, +void CapturerLinux::FastBlit(uint8* image, const SkIRect& rect, CaptureData* capture_data) { uint8* src_pos = image; int src_stride = x_server_pixel_buffer_.GetStride(); - int dst_x = rect.x(), dst_y = rect.y(); + int dst_x = rect.fLeft, dst_y = rect.fTop; DataPlanes planes = capture_data->data_planes(); uint8* dst_buffer = planes.data[0]; @@ -449,13 +450,13 @@ void CapturerLinux::FastBlit(uint8* image, const gfx::Rect& rect, } } -void CapturerLinux::SlowBlit(uint8* image, const gfx::Rect& rect, +void CapturerLinux::SlowBlit(uint8* image, const SkIRect& rect, CaptureData* capture_data) { DataPlanes planes = capture_data->data_planes(); uint8* dst_buffer = planes.data[0]; const int dst_stride = planes.strides[0]; int src_stride = x_server_pixel_buffer_.GetStride(); - int dst_x = rect.x(), dst_y = rect.y(); + int dst_x = rect.fLeft, dst_y = rect.fTop; int width = rect.width(), height = rect.height(); unsigned int red_mask = x_server_pixel_buffer_.GetRedMask(); diff --git a/remoting/host/capturer_mac.cc b/remoting/host/capturer_mac.cc index bb9f8591..5bdd176 100644 --- a/remoting/host/capturer_mac.cc +++ b/remoting/host/capturer_mac.cc @@ -15,6 +15,7 @@ #include "base/memory/scoped_ptr.h" #include "remoting/base/util.h" #include "remoting/host/capturer_helper.h" +#include "skia/ext/skia_utils_mac.h" namespace remoting { @@ -134,19 +135,20 @@ class CapturerMac : public Capturer { // Capturer interface. virtual void ScreenConfigurationChanged() OVERRIDE; virtual media::VideoFrame::Format pixel_format() const OVERRIDE; - virtual void ClearInvalidRects() OVERRIDE; - virtual void InvalidateRects(const InvalidRects& inval_rects) OVERRIDE; + virtual void ClearInvalidRegion() OVERRIDE; + virtual void InvalidateRegion(const SkRegion& invalid_region) OVERRIDE; virtual void InvalidateScreen(const gfx::Size& size) OVERRIDE; virtual void InvalidateFullScreen() OVERRIDE; - virtual void CaptureInvalidRects(CaptureCompletedCallback* callback) OVERRIDE; + virtual void CaptureInvalidRegion(CaptureCompletedCallback* callback) + OVERRIDE; virtual const gfx::Size& size_most_recent() const OVERRIDE; private: - void GlBlitFast(const VideoFrameBuffer& buffer, const InvalidRects& rects); + void GlBlitFast(const VideoFrameBuffer& buffer, const SkRegion& region); void GlBlitSlow(const VideoFrameBuffer& buffer); - void CgBlit(const VideoFrameBuffer& buffer, const InvalidRects& rects); - void CaptureRects(const InvalidRects& rects, - CaptureCompletedCallback* callback); + void CgBlit(const VideoFrameBuffer& buffer, const SkRegion& region); + void CaptureRegion(const SkRegion& region, + CaptureCompletedCallback* callback); void ScreenRefresh(CGRectCount count, const CGRect *rect_array); void ScreenUpdateMove(CGScreenUpdateMoveDelta delta, @@ -176,12 +178,12 @@ class CapturerMac : public Capturer { // The current buffer with valid data for reading. int current_buffer_; - // The last buffer into which we captured, or NULL for the first capture for - // a particular screen resolution. + // The previous buffer into which we captured, or NULL for the first capture + // for a particular screen resolution. uint8* last_buffer_; - // Contains a list of invalid rectangles in the last capture. - InvalidRects last_invalid_rects_; + // Contains an invalid region from the previous capture. + SkRegion last_invalid_region_; // Format of pixels returned in buffer. media::VideoFrame::Format pixel_format_; @@ -240,8 +242,7 @@ void CapturerMac::ReleaseBuffers() { void CapturerMac::ScreenConfigurationChanged() { ReleaseBuffers(); - InvalidRects rects; - helper_.SwapInvalidRects(rects); + helper_.ClearInvalidRegion(); last_buffer_ = NULL; CGDirectDisplayID mainDevice = CGMainDisplayID(); @@ -280,12 +281,12 @@ media::VideoFrame::Format CapturerMac::pixel_format() const { return pixel_format_; } -void CapturerMac::ClearInvalidRects() { - helper_.ClearInvalidRects(); +void CapturerMac::ClearInvalidRegion() { + helper_.ClearInvalidRegion(); } -void CapturerMac::InvalidateRects(const InvalidRects& inval_rects) { - helper_.InvalidateRects(inval_rects); +void CapturerMac::InvalidateRegion(const SkRegion& invalid_region) { + helper_.InvalidateRegion(invalid_region); } void CapturerMac::InvalidateScreen(const gfx::Size& size) { @@ -296,25 +297,25 @@ void CapturerMac::InvalidateFullScreen() { helper_.InvalidateFullScreen(); } -void CapturerMac::CaptureInvalidRects(CaptureCompletedCallback* callback) { +void CapturerMac::CaptureInvalidRegion(CaptureCompletedCallback* callback) { scoped_refptr<CaptureData> data; if (capturing_) { - InvalidRects rects; - helper_.SwapInvalidRects(rects); + SkRegion region; + helper_.SwapInvalidRegion(®ion); VideoFrameBuffer& current_buffer = buffers_[current_buffer_]; current_buffer.Update(); bool flip = true; // GL capturers need flipping. if (cgl_context_) { if (pixel_buffer_object_.get() != 0) { - GlBlitFast(current_buffer, rects); + GlBlitFast(current_buffer, region); } else { // See comment in scoped_pixel_buffer_object::Init about why the slow // path is always used on 10.5. GlBlitSlow(current_buffer); } } else { - CgBlit(current_buffer, rects); + CgBlit(current_buffer, region); flip = false; } @@ -329,7 +330,7 @@ void CapturerMac::CaptureInvalidRects(CaptureCompletedCallback* callback) { data = new CaptureData(planes, gfx::Size(current_buffer.size()), pixel_format()); - data->mutable_dirty_rects() = rects; + data->mutable_dirty_region() = region; current_buffer_ = (current_buffer_ + 1) % kNumBuffers; helper_.set_size_most_recent(data->size()); @@ -340,31 +341,28 @@ void CapturerMac::CaptureInvalidRects(CaptureCompletedCallback* callback) { } void CapturerMac::GlBlitFast(const VideoFrameBuffer& buffer, - const InvalidRects& rects) { + const SkRegion& region) { if (last_buffer_) { // We are doing double buffer for the capture data so we just need to copy - // invalid rects in the last capture in the current buffer. - // TODO(hclam): |last_invalid_rects_| and |rects| can overlap and this - // causes extra copies on the overlapped region. Subtract |rects| from - // |last_invalid_rects_| to do a minimal amount of copy when we have proper - // region algorithms implemented. + // the invalid region from the previous capture in the current buffer. + // TODO(hclam): We can reduce the amount of copying here by subtracting + // |capturer_helper_|s region from |last_invalid_region_|. + // http://crbug.com/92354 // Since the image obtained from OpenGL is upside-down, need to do some // magic here to copy the correct rectangle. const int y_offset = (buffer.size().height() - 1) * buffer.bytes_per_row(); - for (InvalidRects::iterator i = last_invalid_rects_.begin(); - i != last_invalid_rects_.end(); - ++i) { + for(SkRegion::Iterator i(last_invalid_region_); !i.done(); i.next()) { CopyRect(last_buffer_ + y_offset, -buffer.bytes_per_row(), buffer.ptr() + y_offset, -buffer.bytes_per_row(), 4, // Bytes for pixel for RGBA. - *i); + i.rect()); } } last_buffer_ = buffer.ptr(); - last_invalid_rects_ = rects; + last_invalid_region_ = region; CGLContextObj CGL_MACRO_CONTEXT = cgl_context_; glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pixel_buffer_object_.get()); @@ -380,13 +378,13 @@ void CapturerMac::GlBlitFast(const VideoFrameBuffer& buffer, // Copy only from the dirty rects. Since the image obtained from OpenGL is // upside-down we need to do some magic here to copy the correct rectangle. const int y_offset = (buffer.size().height() - 1) * buffer.bytes_per_row(); - for (InvalidRects::iterator i = rects.begin(); i != rects.end(); ++i) { + for(SkRegion::Iterator i(region); !i.done(); i.next()) { CopyRect(ptr + y_offset, -buffer.bytes_per_row(), buffer.ptr() + y_offset, -buffer.bytes_per_row(), 4, // Bytes for pixel for RGBA. - *i); + i.rect()); } } if (!glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB)) { @@ -415,7 +413,7 @@ void CapturerMac::GlBlitSlow(const VideoFrameBuffer& buffer) { } void CapturerMac::CgBlit(const VideoFrameBuffer& buffer, - const InvalidRects& rects) { + const SkRegion& region) { if (last_buffer_) memcpy(buffer.ptr(), last_buffer_, buffer.bytes_per_row() * buffer.size().height()); @@ -425,13 +423,16 @@ void CapturerMac::CgBlit(const VideoFrameBuffer& buffer, reinterpret_cast<uint8*>(CGDisplayBaseAddress(main_display)); int src_bytes_per_row = CGDisplayBytesPerRow(main_display); int src_bytes_per_pixel = CGDisplayBitsPerPixel(main_display) / 8; - for (InvalidRects::iterator i = rects.begin(); i != rects.end(); ++i) { + // TODO(hclam): We can reduce the amount of copying here by subtracting + // |capturer_helper_|s region from |last_invalid_region_|. + // http://crbug.com/92354 + for(SkRegion::Iterator i(region); !i.done(); i.next()) { CopyRect(display_base_address, src_bytes_per_row, buffer.ptr(), buffer.bytes_per_row(), src_bytes_per_pixel, - *i); + i.rect()); } } @@ -440,24 +441,27 @@ const gfx::Size& CapturerMac::size_most_recent() const { } void CapturerMac::ScreenRefresh(CGRectCount count, const CGRect *rect_array) { - InvalidRects rects; + SkIRect skirect_array[count]; for (CGRectCount i = 0; i < count; ++i) { - rects.insert(gfx::Rect(rect_array[i])); + skirect_array[i] = gfx::CGRectToSkIRect(rect_array[i]); } - InvalidateRects(rects); + SkRegion region; + region.setRects(skirect_array, count); + InvalidateRegion(region); } void CapturerMac::ScreenUpdateMove(CGScreenUpdateMoveDelta delta, size_t count, const CGRect *rect_array) { - InvalidRects rects; + SkIRect skirect_new_array[count]; for (CGRectCount i = 0; i < count; ++i) { CGRect rect = rect_array[i]; - rects.insert(gfx::Rect(rect)); rect = CGRectOffset(rect, delta.dX, delta.dY); - rects.insert(gfx::Rect(rect)); + skirect_new_array[i] = gfx::CGRectToSkIRect(rect); } - InvalidateRects(rects); + SkRegion region; + region.setRects(skirect_new_array, count); + InvalidateRegion(region); } void CapturerMac::ScreenRefreshCallback(CGRectCount count, diff --git a/remoting/host/capturer_mac_unittest.cc b/remoting/host/capturer_mac_unittest.cc index e28b841..681282b 100644 --- a/remoting/host/capturer_mac_unittest.cc +++ b/remoting/host/capturer_mac_unittest.cc @@ -10,7 +10,6 @@ #include "base/callback.h" #include "base/memory/scoped_ptr.h" -#include "remoting/base/types.h" #include "testing/gtest/include/gtest/gtest.h" namespace remoting { @@ -22,11 +21,12 @@ class CapturerMacTest : public testing::Test { } void AddDirtyRect() { - rects_.insert(gfx::Rect(0, 0, 10, 10)); + SkIRect rect = SkIRect::MakeXYWH(0, 0, 10, 10); + region_.op(rect, SkRegion::kUnion_Op); } scoped_ptr<Capturer> capturer_; - InvalidRects rects_; + SkRegion region_; }; // CapturerCallback1 verifies that the whole screen is initially dirty. @@ -44,21 +44,20 @@ void CapturerCallback1::CaptureDoneCallback( CGDirectDisplayID mainDevice = CGMainDisplayID(); int width = CGDisplayPixelsWide(mainDevice); int height = CGDisplayPixelsHigh(mainDevice); - InvalidRects initial_rect; - initial_rect.insert(gfx::Rect(0, 0, width, height)); - EXPECT_EQ(initial_rect, capture_data->dirty_rects()); + SkRegion initial_region(SkIRect::MakeXYWH(0, 0, width, height)); + EXPECT_EQ(initial_region, capture_data->dirty_region()); } // CapturerCallback2 verifies that a rectangle explicitly marked as dirty is // propagated correctly. class CapturerCallback2 { public: - explicit CapturerCallback2(const InvalidRects& expected_dirty_rects) - : expected_dirty_rects_(expected_dirty_rects) { } + explicit CapturerCallback2(const SkRegion& expected_dirty_region) + : expected_dirty_region_(expected_dirty_region) { } void CaptureDoneCallback(scoped_refptr<CaptureData> capture_data); protected: - InvalidRects expected_dirty_rects_; + SkRegion expected_dirty_region_; private: DISALLOW_COPY_AND_ASSIGN(CapturerCallback2); @@ -70,7 +69,7 @@ void CapturerCallback2::CaptureDoneCallback( int width = CGDisplayPixelsWide(mainDevice); int height = CGDisplayPixelsHigh(mainDevice); - EXPECT_EQ(expected_dirty_rects_, capture_data->dirty_rects()); + EXPECT_EQ(expected_dirty_region_, capture_data->dirty_region()); EXPECT_EQ(width, capture_data->size().width()); EXPECT_EQ(height, capture_data->size().height()); const DataPlanes &planes = capture_data->data_planes(); @@ -89,13 +88,13 @@ TEST_F(CapturerMacTest, Capture) { SCOPED_TRACE(""); // Check that we get an initial full-screen updated. CapturerCallback1 callback1; - capturer_->CaptureInvalidRects( + capturer_->CaptureInvalidRegion( NewCallback(&callback1, &CapturerCallback1::CaptureDoneCallback)); // Check that subsequent dirty rects are propagated correctly. AddDirtyRect(); - CapturerCallback2 callback2(rects_); - capturer_->InvalidateRects(rects_); - capturer_->CaptureInvalidRects( + CapturerCallback2 callback2(region_); + capturer_->InvalidateRegion(region_); + capturer_->CaptureInvalidRegion( NewCallback(&callback2, &CapturerCallback2::CaptureDoneCallback)); } @@ -103,13 +102,14 @@ TEST_F(CapturerMacTest, Capture) { namespace gfx { -std::ostream& operator<<(std::ostream& out, - const remoting::InvalidRects& rects) { - for (remoting::InvalidRects::const_iterator i = rects.begin(); - i != rects.end(); - ++i) { - out << *i << std::endl; +std::ostream& operator<<(std::ostream& out, const SkRegion& region) { + out << "SkRegion("; + for (SkRegion::Iterator i(region); !i.done(); i.next()) { + const SkIRect& r = i.rect(); + out << "(" << r.fLeft << "," << r.fTop << "," + << r.fRight << "," << r.fBottom << ")"; } + out << ")"; return out; } diff --git a/remoting/host/capturer_win.cc b/remoting/host/capturer_win.cc index b5fe81e..1fb8b8a 100644 --- a/remoting/host/capturer_win.cc +++ b/remoting/host/capturer_win.cc @@ -9,7 +9,6 @@ #include "base/memory/scoped_ptr.h" #include "remoting/host/capturer_helper.h" #include "remoting/host/differ.h" -#include "ui/gfx/rect.h" namespace remoting { @@ -27,11 +26,12 @@ class CapturerGdi : public Capturer { // Capturer interface. virtual void ScreenConfigurationChanged() OVERRIDE; virtual media::VideoFrame::Format pixel_format() const OVERRIDE; - virtual void ClearInvalidRects() OVERRIDE; - virtual void InvalidateRects(const InvalidRects& inval_rects) OVERRIDE; + virtual void ClearInvalidRegion() OVERRIDE; + virtual void InvalidateRegion(const SkRegion& invalid_region) OVERRIDE; virtual void InvalidateScreen(const gfx::Size& size) OVERRIDE; virtual void InvalidateFullScreen() OVERRIDE; - virtual void CaptureInvalidRects(CaptureCompletedCallback* callback) OVERRIDE; + virtual void CaptureInvalidRegion(CaptureCompletedCallback* callback) + OVERRIDE; virtual const gfx::Size& size_most_recent() const OVERRIDE; private: @@ -60,9 +60,9 @@ class CapturerGdi : public Capturer { // allocated for that buffer. void ReallocateBuffer(int buffer_index, const gfx::Size& size); - void CalculateInvalidRects(); - void CaptureRects(const InvalidRects& rects, - CaptureCompletedCallback* callback); + void CalculateInvalidRegion(); + void CaptureRegion(const SkRegion& region, + CaptureCompletedCallback* callback); void ReleaseBuffers(); // Generates an image in the current buffer. @@ -77,7 +77,7 @@ class CapturerGdi : public Capturer { // A thread-safe list of invalid rectangles, and the size of the most // recently captured screen. - CapturerHelper helper; + CapturerHelper helper_; // There are two buffers for the screen images, as required by Capturer. static const int kNumBuffers = 2; @@ -132,31 +132,31 @@ media::VideoFrame::Format CapturerGdi::pixel_format() const { return pixel_format_; } -void CapturerGdi::ClearInvalidRects() { - helper.ClearInvalidRects(); +void CapturerGdi::ClearInvalidRegion() { + helper_.ClearInvalidRegion(); } -void CapturerGdi::InvalidateRects(const InvalidRects& inval_rects) { - helper.InvalidateRects(inval_rects); +void CapturerGdi::InvalidateRegion(const SkRegion& invalid_region) { + helper_.InvalidateRegion(invalid_region); } void CapturerGdi::InvalidateScreen(const gfx::Size& size) { - helper.InvalidateScreen(size); + helper_.InvalidateScreen(size); } void CapturerGdi::InvalidateFullScreen() { - helper.InvalidateFullScreen(); + helper_.InvalidateFullScreen(); } -void CapturerGdi::CaptureInvalidRects(CaptureCompletedCallback* callback) { - CalculateInvalidRects(); - InvalidRects inval_rects; - helper.SwapInvalidRects(inval_rects); - CaptureRects(inval_rects, callback); +void CapturerGdi::CaptureInvalidRegion(CaptureCompletedCallback* callback) { + CalculateInvalidRegion(); + SkRegion invalid_region; + helper_.SwapInvalidRegion(&invalid_region); + CaptureRegion(invalid_region, callback); } const gfx::Size& CapturerGdi::size_most_recent() const { - return helper.size_most_recent(); + return helper_.size_most_recent(); } void CapturerGdi::ReleaseBuffers() { @@ -243,11 +243,11 @@ void CapturerGdi::ReallocateBuffer(int buffer_index, const gfx::Size& size) { bmi.bmiHeader.biSizeImage / std::abs(bmi.bmiHeader.biHeight); } -void CapturerGdi::CalculateInvalidRects() { +void CapturerGdi::CalculateInvalidRegion() { CaptureImage(); const VideoFrameBuffer& current = buffers_[current_buffer_]; - if (helper.IsCaptureFullScreen(current.size)) + if (helper_.IsCaptureFullScreen(current.size)) capture_fullscreen_ = true; if (capture_fullscreen_) { @@ -282,14 +282,14 @@ void CapturerGdi::CalculateInvalidRects() { current.bytes_per_pixel, current.bytes_per_row)); } - InvalidRects rects; - differ_->CalcDirtyRects(prev.data, current.data, &rects); + SkRegion region; + differ_->CalcDirtyRegion(prev.data, current.data, ®ion); - InvalidateRects(rects); + InvalidateRegion(region); } -void CapturerGdi::CaptureRects(const InvalidRects& rects, - CaptureCompletedCallback* callback) { +void CapturerGdi::CaptureRegion(const SkRegion& region, + CaptureCompletedCallback* callback) { scoped_ptr<CaptureCompletedCallback> callback_deleter(callback); const VideoFrameBuffer& buffer = buffers_[current_buffer_]; @@ -302,9 +302,9 @@ void CapturerGdi::CaptureRects(const InvalidRects& rects, scoped_refptr<CaptureData> data(new CaptureData(planes, buffer.size, pixel_format_)); - data->mutable_dirty_rects() = rects; + data->mutable_dirty_region() = region; - helper.set_size_most_recent(data->size()); + helper_.set_size_most_recent(data->size()); callback->Run(data); } diff --git a/remoting/host/differ.cc b/remoting/host/differ.cc index d5e618a..582521c 100644 --- a/remoting/host/differ.cc +++ b/remoting/host/differ.cc @@ -26,12 +26,12 @@ Differ::Differ(int width, int height, int bpp, int stride) { Differ::~Differ() {} -void Differ::CalcDirtyRects(const void* prev_buffer, const void* curr_buffer, - InvalidRects* rects) { - if (!rects) { +void Differ::CalcDirtyRegion(const void* prev_buffer, const void* curr_buffer, + SkRegion* region) { + if (!region) { return; } - rects->clear(); + region->setEmpty(); if (!prev_buffer || !curr_buffer) { return; @@ -42,7 +42,7 @@ void Differ::CalcDirtyRects(const void* prev_buffer, const void* curr_buffer, // Now that we've identified the blocks that have changed, merge adjacent // blocks to minimize the number of rects that we return. - MergeBlocks(rects); + MergeBlocks(region); } void Differ::MarkDirtyBlocks(const void* prev_buffer, const void* curr_buffer) { @@ -131,9 +131,9 @@ DiffInfo Differ::DiffPartialBlock(const uint8* prev_buffer, return 0; } -void Differ::MergeBlocks(InvalidRects* rects) { - DCHECK(rects); - rects->clear(); +void Differ::MergeBlocks(SkRegion* region) { + DCHECK(region); + region->setEmpty(); uint8* diff_info_row_start = static_cast<uint8*>(diff_info_.get()); int diff_info_stride = diff_info_width_ * sizeof(DiffInfo); @@ -195,7 +195,8 @@ void Differ::MergeBlocks(InvalidRects* rects) { if (top + height > height_) { height = height_ - top; } - rects->insert(gfx::Rect(left, top, width, height)); + region->op(SkIRect::MakeXYWH(left, top, width, height), + SkRegion::kUnion_Op); } // Increment to next block in this row. diff --git a/remoting/host/differ.h b/remoting/host/differ.h index 9903680..c46f57a 100644 --- a/remoting/host/differ.h +++ b/remoting/host/differ.h @@ -9,13 +9,16 @@ #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" -#include "remoting/base/types.h" -#include "ui/gfx/rect.h" +#include "third_party/skia/include/core/SkRegion.h" namespace remoting { typedef uint8 DiffInfo; +// TODO: Simplify differ now that we are working with SkRegions. +// diff_info_ should no longer be needed, as we can put our data directly into +// the region that we are calculating. +// http://crbug.com/92379 class Differ { public: // Create a differ that operates on bitmaps with the specified width, height @@ -28,24 +31,22 @@ class Differ { int bytes_per_pixel() { return bytes_per_pixel_; } int bytes_per_row() { return bytes_per_row_; } - // Given the previous and current screen buffer, calculate the set of - // rectangles that enclose all the changed pixels in the new screen. - void CalcDirtyRects(const void* prev_buffer, const void* curr_buffer, - InvalidRects* rects); + // Given the previous and current screen buffer, calculate the dirty region + // that encloses all of the changed pixels in the new screen. + void CalcDirtyRegion(const void* prev_buffer, const void* curr_buffer, + SkRegion* region); + + private: + // Allow tests to access our private parts. + friend class DifferTest; // Identify all of the blocks that contain changed pixels. void MarkDirtyBlocks(const void* prev_buffer, const void* curr_buffer); // After the dirty blocks have been identified, this routine merges adjacent - // blocks into larger rectangular units. - // The goal is to minimize the number of rects that cover the dirty blocks, - // although it is not required to calc the absolute minimum of rects. - void MergeBlocks(InvalidRects* rects); - - // Allow tests to access our private parts. - friend class DifferTest; - - private: + // blocks into a region. + // The goal is to minimize the region that covers the dirty blocks. + void MergeBlocks(SkRegion* region); // Check for diffs in upper-left portion of the block. The size of the portion // to check is specified by the |width| and |height| values. diff --git a/remoting/host/differ_unittest.cc b/remoting/host/differ_unittest.cc index 23702a8..6ddd722 100644 --- a/remoting/host/differ_unittest.cc +++ b/remoting/host/differ_unittest.cc @@ -44,6 +44,24 @@ class DifferTest : public testing::Test { memset(buffer, 0, buffer_size_); } + // Here in DifferTest so that tests can access private methods of Differ. + void MarkDirtyBlocks(const void* prev_buffer, const void* curr_buffer) { + differ_->MarkDirtyBlocks(prev_buffer, curr_buffer); + } + + void MergeBlocks(SkRegion* dirty) { + differ_->MergeBlocks(dirty); + } + + // Convenience method to count rectangles in a region. + int RegionRectCount(const SkRegion& region) { + int count = 0; + for(SkRegion::Iterator iter(region); !iter.done(); iter.next()) { + ++count; + } + return count; + } + // Convenience wrapper for Differ's DiffBlock that calculates the appropriate // offset to the start of the desired block. DiffInfo DiffBlock(int block_x, int block_y) { @@ -123,29 +141,37 @@ class DifferTest : public testing::Test { } } - // Verify that the given dirty rect matches the expected |x|, |y|, |width| - // and |height|. + // Verify that |region| contains a rectangle defined by |x|, |y|, |width| and + // |height|. // |x|, |y|, |width| and |height| are specified in block (not pixel) units. - void CheckDirtyRect(const InvalidRects& rects, int x, int y, - int width, int height) { - gfx::Rect r(x * kBlockSize, y * kBlockSize, - width * kBlockSize, height * kBlockSize); - EXPECT_TRUE(rects.find(r) != rects.end()); + bool CheckDirtyRegionContainsRect(const SkRegion& region, int x, int y, + int width, int height) { + SkIRect r = SkIRect::MakeXYWH(x * kBlockSize, y * kBlockSize, + width * kBlockSize, height * kBlockSize); + bool found = false; + for (SkRegion::Iterator i(region); !found && !i.done(); i.next()) { + found = (i.rect() == r); + } + return found; } // Mark the range of blocks specified and then verify that they are // merged correctly. // Only one rectangular region of blocks can be checked with this routine. - void MarkBlocksAndCheckMerge(int x_origin, int y_origin, + bool MarkBlocksAndCheckMerge(int x_origin, int y_origin, int width, int height) { ClearDiffInfo(); MarkBlocks(x_origin, y_origin, width, height); - scoped_ptr<InvalidRects> dirty(new InvalidRects()); - differ_->MergeBlocks(dirty.get()); + SkRegion dirty; + MergeBlocks(&dirty); - ASSERT_EQ(1UL, dirty->size()); - CheckDirtyRect(*dirty.get(), x_origin, y_origin, width, height); + bool is_good = dirty.isRect(); + if (is_good) { + is_good = CheckDirtyRegionContainsRect(dirty, x_origin, y_origin, + width, height); + } + return is_good; } // The differ class we're testing. @@ -196,7 +222,7 @@ TEST_F(DifferTest, MarkDirtyBlocks_All) { } } - differ_->MarkDirtyBlocks(prev_.get(), curr_.get()); + MarkDirtyBlocks(prev_.get(), curr_.get()); // Make sure each block is marked as dirty. for (int y = 0; y < GetDiffInfoHeight() - 1; y++) { @@ -216,7 +242,7 @@ TEST_F(DifferTest, MarkDirtyBlocks_Sampling) { WriteBlockPixel(curr_.get(), 2, 1, 10, 10, 0xff00ff); WriteBlockPixel(curr_.get(), 0, 2, 10, 10, 0xff00ff); - differ_->MarkDirtyBlocks(prev_.get(), curr_.get()); + MarkDirtyBlocks(prev_.get(), curr_.get()); // Make sure corresponding blocks are updated. EXPECT_EQ(0, GetDiffInfo(0, 0)); @@ -284,7 +310,7 @@ TEST_F(DifferTest, Partial_FirstPixel) { } } - differ_->MarkDirtyBlocks(prev_.get(), curr_.get()); + MarkDirtyBlocks(prev_.get(), curr_.get()); // Make sure each block is marked as dirty. for (int y = 0; y < GetDiffInfoHeight() - 1; y++) { @@ -307,7 +333,7 @@ TEST_F(DifferTest, Partial_BorderPixel) { WritePixel(curr_.get(), x, height_ - 1, 0xff00ff); } - differ_->MarkDirtyBlocks(prev_.get(), curr_.get()); + MarkDirtyBlocks(prev_.get(), curr_.get()); // Make sure last (partial) block in each row/column is marked as dirty. int x_last = GetDiffInfoWidth() - 2; @@ -343,10 +369,10 @@ TEST_F(DifferTest, MergeBlocks_Empty) { // +---+---+---+---+ ClearDiffInfo(); - scoped_ptr<InvalidRects> dirty(new InvalidRects()); - differ_->MergeBlocks(dirty.get()); + SkRegion dirty; + MergeBlocks(&dirty); - EXPECT_EQ(0UL, dirty->size()); + EXPECT_TRUE(dirty.isEmpty()); } TEST_F(DifferTest, MergeBlocks_SingleBlock) { @@ -355,7 +381,8 @@ TEST_F(DifferTest, MergeBlocks_SingleBlock) { // rect with the correct bounds. for (int y = 0; y < GetDiffInfoHeight() - 1; y++) { for (int x = 0; x < GetDiffInfoWidth() - 1; x++) { - MarkBlocksAndCheckMerge(x, y, 1, 1); + ASSERT_TRUE(MarkBlocksAndCheckMerge(x, y, 1, 1)) << "x: " << x + << "y: " << y; } } } @@ -372,7 +399,7 @@ TEST_F(DifferTest, MergeBlocks_BlockRow) { // +---+---+---+---+ // | _ | _ | _ | _ | // +---+---+---+---+ - MarkBlocksAndCheckMerge(0, 0, 2, 1); + ASSERT_TRUE(MarkBlocksAndCheckMerge(0, 0, 2, 1)); // +---+---+---+---+ // | | | | _ | @@ -383,7 +410,7 @@ TEST_F(DifferTest, MergeBlocks_BlockRow) { // +---+---+---+---+ // | _ | _ | _ | _ | // +---+---+---+---+ - MarkBlocksAndCheckMerge(0, 1, 3, 1); + ASSERT_TRUE(MarkBlocksAndCheckMerge(0, 1, 3, 1)); // +---+---+---+---+ // | | | | _ | @@ -394,7 +421,7 @@ TEST_F(DifferTest, MergeBlocks_BlockRow) { // +---+---+---+---+ // | _ | _ | _ | _ | // +---+---+---+---+ - MarkBlocksAndCheckMerge(1, 2, 2, 1); + ASSERT_TRUE(MarkBlocksAndCheckMerge(1, 2, 2, 1)); } TEST_F(DifferTest, MergeBlocks_BlockColumn) { @@ -409,7 +436,7 @@ TEST_F(DifferTest, MergeBlocks_BlockColumn) { // +---+---+---+---+ // | _ | _ | _ | _ | // +---+---+---+---+ - MarkBlocksAndCheckMerge(0, 0, 1, 2); + ASSERT_TRUE(MarkBlocksAndCheckMerge(0, 0, 1, 2)); // +---+---+---+---+ // | | | | _ | @@ -420,7 +447,7 @@ TEST_F(DifferTest, MergeBlocks_BlockColumn) { // +---+---+---+---+ // | _ | _ | _ | _ | // +---+---+---+---+ - MarkBlocksAndCheckMerge(1, 1, 1, 2); + ASSERT_TRUE(MarkBlocksAndCheckMerge(1, 1, 1, 2)); // +---+---+---+---+ // | | | X | _ | @@ -431,7 +458,7 @@ TEST_F(DifferTest, MergeBlocks_BlockColumn) { // +---+---+---+---+ // | _ | _ | _ | _ | // +---+---+---+---+ - MarkBlocksAndCheckMerge(2, 0, 1, 3); + ASSERT_TRUE(MarkBlocksAndCheckMerge(2, 0, 1, 3)); } TEST_F(DifferTest, MergeBlocks_BlockRect) { @@ -446,7 +473,7 @@ TEST_F(DifferTest, MergeBlocks_BlockRect) { // +---+---+---+---+ // | _ | _ | _ | _ | // +---+---+---+---+ - MarkBlocksAndCheckMerge(0, 0, 2, 2); + ASSERT_TRUE(MarkBlocksAndCheckMerge(0, 0, 2, 2)); // +---+---+---+---+ // | | | | _ | @@ -457,7 +484,7 @@ TEST_F(DifferTest, MergeBlocks_BlockRect) { // +---+---+---+---+ // | _ | _ | _ | _ | // +---+---+---+---+ - MarkBlocksAndCheckMerge(1, 1, 2, 2); + ASSERT_TRUE(MarkBlocksAndCheckMerge(1, 1, 2, 2)); // +---+---+---+---+ // | | X | X | _ | @@ -468,7 +495,7 @@ TEST_F(DifferTest, MergeBlocks_BlockRect) { // +---+---+---+---+ // | _ | _ | _ | _ | // +---+---+---+---+ - MarkBlocksAndCheckMerge(1, 0, 2, 3); + ASSERT_TRUE(MarkBlocksAndCheckMerge(1, 0, 2, 3)); // +---+---+---+---+ // | | | | _ | @@ -479,7 +506,7 @@ TEST_F(DifferTest, MergeBlocks_BlockRect) { // +---+---+---+---+ // | _ | _ | _ | _ | // +---+---+---+---+ - MarkBlocksAndCheckMerge(0, 1, 3, 2); + ASSERT_TRUE(MarkBlocksAndCheckMerge(0, 1, 3, 2)); // +---+---+---+---+ // | X | X | X | _ | @@ -490,7 +517,7 @@ TEST_F(DifferTest, MergeBlocks_BlockRect) { // +---+---+---+---+ // | _ | _ | _ | _ | // +---+---+---+---+ - MarkBlocksAndCheckMerge(0, 0, 3, 3); + ASSERT_TRUE(MarkBlocksAndCheckMerge(0, 0, 3, 3)); } // This tests marked regions that require more than 1 single dirty rect. @@ -498,7 +525,7 @@ TEST_F(DifferTest, MergeBlocks_BlockRect) { // may need to be updated if we modify how we merge blocks. TEST_F(DifferTest, MergeBlocks_MultiRect) { InitDiffer(kScreenWidth, kScreenHeight); - scoped_ptr<InvalidRects> dirty; + SkRegion dirty; // +---+---+---+---+ +---+---+---+ // | | X | | _ | | | 0 | | @@ -514,40 +541,40 @@ TEST_F(DifferTest, MergeBlocks_MultiRect) { MarkBlocks(0, 1, 1, 1); MarkBlocks(2, 2, 1, 1); - dirty.reset(new InvalidRects()); - differ_->MergeBlocks(dirty.get()); + dirty.setEmpty(); + MergeBlocks(&dirty); - ASSERT_EQ(3UL, dirty->size()); - CheckDirtyRect(*dirty.get(), 1, 0, 1, 1); - CheckDirtyRect(*dirty.get(), 0, 1, 1, 1); - CheckDirtyRect(*dirty.get(), 2, 2, 1, 1); + ASSERT_EQ(3, RegionRectCount(dirty)); + ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 1, 0, 1, 1)); + ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 1, 1, 1)); + ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 2, 2, 1, 1)); // +---+---+---+---+ +---+---+---+ // | | | X | _ | | | | 0 | - // +---+---+---+---+ +---+---+ + - // | X | X | X | _ | | 1 1 | 0 | - // +---+---+---+---+ => + + + - // | X | X | X | _ | | 1 1 | 0 | + // +---+---+---+---+ +---+---+---+ + // | X | X | X | _ | | 1 1 1 | + // +---+---+---+---+ => + + + // | X | X | X | _ | | 1 1 1 | // +---+---+---+---+ +---+---+---+ // | _ | _ | _ | _ | // +---+---+---+---+ ClearDiffInfo(); - MarkBlocks(2, 0, 1, 3); - MarkBlocks(0, 1, 2, 2); + MarkBlocks(2, 0, 1, 1); + MarkBlocks(0, 1, 3, 2); - dirty.reset(new InvalidRects()); - differ_->MergeBlocks(dirty.get()); + dirty.setEmpty(); + MergeBlocks(&dirty); - ASSERT_EQ(2UL, dirty->size()); - CheckDirtyRect(*dirty.get(), 2, 0, 1, 3); - CheckDirtyRect(*dirty.get(), 0, 1, 2, 2); + ASSERT_EQ(2, RegionRectCount(dirty)); + ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 2, 0, 1, 1)); + ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 1, 3, 2)); // +---+---+---+---+ +---+---+---+ // | | | | _ | | | | | // +---+---+---+---+ +---+---+---+ // | X | | X | _ | | 0 | | 1 | // +---+---+---+---+ => + +---+ + - // | X | X | X | _ | | 0 | 2 | 1 | + // | X | X | X | _ | | 2 | 2 | 2 | // +---+---+---+---+ +---+---+---+ // | _ | _ | _ | _ | // +---+---+---+---+ @@ -556,20 +583,20 @@ TEST_F(DifferTest, MergeBlocks_MultiRect) { MarkBlocks(2, 1, 1, 1); MarkBlocks(0, 2, 3, 1); - dirty.reset(new InvalidRects()); - differ_->MergeBlocks(dirty.get()); + dirty.setEmpty(); + MergeBlocks(&dirty); - ASSERT_EQ(3UL, dirty->size()); - CheckDirtyRect(*dirty.get(), 0, 1, 1, 2); - CheckDirtyRect(*dirty.get(), 2, 1, 1, 2); - CheckDirtyRect(*dirty.get(), 1, 2, 1, 1); + ASSERT_EQ(3, RegionRectCount(dirty)); + ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 1, 1, 1)); + ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 2, 1, 1, 1)); + ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 2, 3, 1)); // +---+---+---+---+ +---+---+---+ // | X | X | X | _ | | 0 0 0 | // +---+---+---+---+ +---+---+---+ // | X | | X | _ | | 1 | | 2 | // +---+---+---+---+ => + +---+ + - // | X | X | X | _ | | 1 | 3 | 2 | + // | X | X | X | _ | | 3 | 3 | 3 | // +---+---+---+---+ +---+---+---+ // | _ | _ | _ | _ | // +---+---+---+---+ @@ -579,14 +606,14 @@ TEST_F(DifferTest, MergeBlocks_MultiRect) { MarkBlocks(2, 1, 1, 1); MarkBlocks(0, 2, 3, 1); - dirty.reset(new InvalidRects()); - differ_->MergeBlocks(dirty.get()); + dirty.setEmpty(); + MergeBlocks(&dirty); - ASSERT_EQ(4UL, dirty->size()); - CheckDirtyRect(*dirty.get(), 0, 0, 3, 1); - CheckDirtyRect(*dirty.get(), 0, 1, 1, 2); - CheckDirtyRect(*dirty.get(), 2, 1, 1, 2); - CheckDirtyRect(*dirty.get(), 1, 2, 1, 1); + ASSERT_EQ(4, RegionRectCount(dirty)); + ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 0, 3, 1)); + ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 1, 1, 1)); + ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 2, 1, 1, 1)); + ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 2, 3, 1)); // +---+---+---+---+ +---+---+---+ // | X | X | | _ | | 0 0 | | @@ -601,12 +628,12 @@ TEST_F(DifferTest, MergeBlocks_MultiRect) { MarkBlocks(0, 0, 2, 2); MarkBlocks(1, 2, 1, 1); - dirty.reset(new InvalidRects()); - differ_->MergeBlocks(dirty.get()); + dirty.setEmpty(); + MergeBlocks(&dirty); - ASSERT_EQ(2UL, dirty->size()); - CheckDirtyRect(*dirty.get(), 0, 0, 2, 2); - CheckDirtyRect(*dirty.get(), 1, 2, 1, 1); + ASSERT_EQ(2, RegionRectCount(dirty)); + ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 0, 2, 2)); + ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 1, 2, 1, 1)); } } // namespace remoting diff --git a/remoting/host/host_mock_objects.h b/remoting/host/host_mock_objects.h index 0ab8636f..ec486c1 100644 --- a/remoting/host/host_mock_objects.h +++ b/remoting/host/host_mock_objects.h @@ -26,11 +26,11 @@ class MockCapturer : public Capturer { MOCK_METHOD0(ScreenConfigurationChanged, void()); MOCK_CONST_METHOD0(pixel_format, media::VideoFrame::Format()); - MOCK_METHOD0(ClearInvalidRects, void()); - MOCK_METHOD1(InvalidateRects, void(const InvalidRects& inval_rects)); + MOCK_METHOD0(ClearInvalidRegion, void()); + MOCK_METHOD1(InvalidateRegion, void(const SkRegion& invalid_region)); MOCK_METHOD1(InvalidateScreen, void(const gfx::Size&)); MOCK_METHOD0(InvalidateFullScreen, void()); - MOCK_METHOD1(CaptureInvalidRects, void(CaptureCompletedCallback* callback)); + MOCK_METHOD1(CaptureInvalidRegion, void(CaptureCompletedCallback* callback)); MOCK_CONST_METHOD0(size_most_recent, const gfx::Size&()); private: diff --git a/remoting/host/screen_recorder.cc b/remoting/host/screen_recorder.cc index 1a05797..ce982e6 100644 --- a/remoting/host/screen_recorder.cc +++ b/remoting/host/screen_recorder.cc @@ -218,7 +218,7 @@ void ScreenRecorder::DoCapture() { // And finally perform one capture. capture_start_time_ = base::Time::Now(); - capturer()->CaptureInvalidRects( + capturer()->CaptureInvalidRegion( NewCallback(this, &ScreenRecorder::CaptureDoneCallback)); } @@ -365,7 +365,7 @@ void ScreenRecorder::DoEncode( TraceContext::tracer()->PrintString("DoEncode called"); // Early out if there's nothing to encode. - if (!capture_data || !capture_data->dirty_rects().size()) { + if (!capture_data || capture_data->dirty_region().isEmpty()) { // Send an empty video packet to keep network active. VideoPacket* packet = new VideoPacket(); packet->set_flags(VideoPacket::LAST_PARTITION); diff --git a/remoting/host/screen_recorder_unittest.cc b/remoting/host/screen_recorder_unittest.cc index 69650ee..a1c4f13 100644 --- a/remoting/host/screen_recorder_unittest.cc +++ b/remoting/host/screen_recorder_unittest.cc @@ -31,13 +31,9 @@ namespace remoting { namespace { -ACTION_P2(RunCallback, rects, data) { - InvalidRects& dirty_rects = data->mutable_dirty_rects(); - InvalidRects temp_rects; - std::set_union(dirty_rects.begin(), dirty_rects.end(), - rects.begin(), rects.end(), - std::inserter(temp_rects, temp_rects.begin())); - dirty_rects.swap(temp_rects); +ACTION_P2(RunCallback, region, data) { + SkRegion& dirty_region = data->mutable_dirty_region(); + dirty_region.op(region, SkRegion::kUnion_Op); arg0->Run(data); delete arg0; } @@ -107,8 +103,7 @@ class ScreenRecorderTest : public testing::Test { // This test mocks capturer, encoder and network layer to operate one recording // cycle. TEST_F(ScreenRecorderTest, OneRecordCycle) { - InvalidRects update_rects; - update_rects.insert(gfx::Rect(0, 0, 10, 10)); + SkRegion update_region(SkIRect::MakeXYWH(0, 0, 10, 10)); DataPlanes planes; for (int i = 0; i < DataPlanes::kPlaneCount; ++i) { planes.data[i] = reinterpret_cast<uint8*>(i); @@ -119,8 +114,8 @@ TEST_F(ScreenRecorderTest, OneRecordCycle) { EXPECT_CALL(capturer_, InvalidateFullScreen()); // First the capturer is called. - EXPECT_CALL(capturer_, CaptureInvalidRects(NotNull())) - .WillOnce(RunCallback(update_rects, data)); + EXPECT_CALL(capturer_, CaptureInvalidRegion(NotNull())) + .WillOnce(RunCallback(update_region, data)); // Expect the encoder be called. EXPECT_CALL(*encoder_, Encode(data, false, NotNull())) @@ -156,8 +151,7 @@ TEST_F(ScreenRecorderTest, OneRecordCycle) { // ScreenRecorder is instructed to come to a complete stop. We expect the stop // sequence to be executed successfully. TEST_F(ScreenRecorderTest, StartAndStop) { - InvalidRects update_rects; - update_rects.insert(gfx::Rect(0, 0, 10, 10)); + SkRegion update_region(SkIRect::MakeXYWH(0, 0, 10, 10)); DataPlanes planes; for (int i = 0; i < DataPlanes::kPlaneCount; ++i) { planes.data[i] = reinterpret_cast<uint8*>(i); @@ -169,8 +163,8 @@ TEST_F(ScreenRecorderTest, StartAndStop) { EXPECT_CALL(capturer_, InvalidateFullScreen()); // First the capturer is called. - EXPECT_CALL(capturer_, CaptureInvalidRects(NotNull())) - .WillRepeatedly(RunCallback(update_rects, data)); + EXPECT_CALL(capturer_, CaptureInvalidRegion(NotNull())) + .WillRepeatedly(RunCallback(update_region, data)); // Expect the encoder be called. EXPECT_CALL(*encoder_, Encode(data, false, NotNull())) diff --git a/remoting/host/x_server_pixel_buffer.cc b/remoting/host/x_server_pixel_buffer.cc index 8bfd004..a830920 100644 --- a/remoting/host/x_server_pixel_buffer.cc +++ b/remoting/host/x_server_pixel_buffer.cc @@ -148,21 +148,21 @@ void XServerPixelBuffer::Synchronize() { } } -uint8* XServerPixelBuffer::CaptureRect(const gfx::Rect& rect) { +uint8* XServerPixelBuffer::CaptureRect(const SkIRect& rect) { if (shm_segment_info_) { if (shm_pixmap_) { XCopyArea(display_, root_window_, shm_pixmap_, shm_gc_, - rect.x(), rect.y(), rect.width(), rect.height(), - rect.x(), rect.y()); + rect.fLeft, rect.fTop, rect.width(), rect.height(), + rect.fLeft, rect.fTop); XSync(display_, False); } return reinterpret_cast<uint8*>(x_image_->data) + - rect.y() * x_image_->bytes_per_line + - rect.x() * x_image_->bits_per_pixel / 8; + rect.fTop * x_image_->bytes_per_line + + rect.fLeft * x_image_->bits_per_pixel / 8; } else { if (x_image_) XDestroyImage(x_image_); - x_image_ = XGetImage(display_, root_window_, rect.x(), rect.y(), + x_image_ = XGetImage(display_, root_window_, rect.fLeft, rect.fTop, rect.width(), rect.height(), AllPlanes, ZPixmap); return reinterpret_cast<uint8*>(x_image_->data); } diff --git a/remoting/host/x_server_pixel_buffer.h b/remoting/host/x_server_pixel_buffer.h index 49012f1..161beab 100644 --- a/remoting/host/x_server_pixel_buffer.h +++ b/remoting/host/x_server_pixel_buffer.h @@ -9,7 +9,7 @@ #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" -#include "ui/gfx/rect.h" +#include "third_party/skia/include/core/SkRect.h" #include <X11/Xutil.h> #include <X11/extensions/XShm.h> @@ -38,7 +38,7 @@ class XServerPixelBuffer { // call to CaptureRect. // In the case where the full-screen data is captured by Synchronize(), this // simply returns the pointer without doing any more work. - uint8* CaptureRect(const gfx::Rect& rect); + uint8* CaptureRect(const SkIRect& rect); // Return information about the most recent capture. This is only guaranteed // to be valid between CaptureRect calls. diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp index 325313b..51b2973 100644 --- a/remoting/remoting.gyp +++ b/remoting/remoting.gyp @@ -167,6 +167,9 @@ 'remoting_jingle_glue', '../third_party/npapi/npapi.gyp:npapi', ], + 'include_dirs': [ + '../skia/config', + ], 'sources': [ 'host/plugin/host_plugin.cc', 'host/plugin/host_plugin.def', @@ -178,6 +181,11 @@ 'host/plugin/host_script_object.h', ], 'conditions': [ + ['OS=="win"', { + 'include_dirs': [ + '../third_party/skia/include/config', + ], + }], ['OS=="mac"', { 'mac_bundle': 1, 'xcode_settings': { @@ -292,6 +300,9 @@ # TODO(hclam): Enable VP8 in the build. #'third_party/on2/on2.gyp:vp8', ], + 'include_dirs': [ + '../skia/config', + ], 'export_dependent_settings': [ '../base/base.gyp:base', '../net/net.gyp:net', @@ -338,7 +349,6 @@ 'base/task_thread_proxy.h', 'base/tracer.cc', 'base/tracer.h', - 'base/types.h', 'base/util.cc', 'base/util.h', ], @@ -351,6 +361,11 @@ 'base/encoder_vp8.h', ], }], + ['OS=="win"', { + 'include_dirs': [ + '../third_party/skia/include/config', + ], + }], ], }, # end of target 'remoting_base' @@ -364,6 +379,9 @@ 'differ_block', '../crypto/crypto.gyp:crypto', ], + 'include_dirs': [ + '../skia/config', + ], 'sources': [ 'host/access_verifier.h', 'host/capturer.h', @@ -450,6 +468,11 @@ ], }, }], + ['OS=="win"', { + 'include_dirs': [ + '../third_party/skia/include/config', + ], + }], ['OS=="mac"', { 'sources': [ '../third_party/GTM/AppKit/GTMCarbonEvent.h', @@ -482,6 +505,9 @@ 'remoting_jingle_glue', 'remoting_protocol', ], + 'include_dirs': [ + '../skia/config', + ], 'sources': [ 'client/chromoting_client.cc', 'client/chromoting_client.h', @@ -501,6 +527,13 @@ 'client/rectangle_update_decoder.cc', 'client/rectangle_update_decoder.h', ], + 'conditions': [ + ['OS=="win"', { + 'include_dirs': [ + '../third_party/skia/include/config', + ], + }], + ], }, # end of target 'remoting_client' { @@ -514,6 +547,9 @@ '../base/base.gyp:base_i18n', '../media/media.gyp:media', ], + 'include_dirs': [ + '../skia/config', + ], 'sources': [ 'host/capturer_fake_ascii.cc', 'host/capturer_fake_ascii.h', @@ -530,6 +566,13 @@ '../base/test/mock_chrome_application_mac.mm', '../base/test/mock_chrome_application_mac.h', ], + 'conditions': [ + ['OS=="win"', { + 'include_dirs': [ + '../third_party/skia/include/config', + ], + }], + ], }, # end of target 'remoting_simple_host' { @@ -683,9 +726,6 @@ { 'target_name': 'differ_block', 'type': 'static_library', - 'include_dirs': [ - '..', - ], 'dependencies': [ '../media/media.gyp:cpu_features', ], @@ -705,9 +745,6 @@ { 'target_name': 'differ_block_sse2', 'type': 'static_library', - 'include_dirs': [ - '..', - ], 'conditions': [ [ 'os_posix == 1 and OS != "mac"', { 'cflags': [ @@ -754,6 +791,7 @@ ], 'include_dirs': [ '../testing/gmock/include', + '../skia/config', ], 'sources': [ 'base/auth_token_util_unittest.cc', @@ -830,6 +868,11 @@ 'base/encoder_vp8_unittest.cc', ], }], + ['OS=="win"', { + 'include_dirs': [ + '../third_party/skia/include/config', + ], + }], ], # end of 'conditions' }, # end of target 'remoting_unittests' ], # end of targets diff --git a/skia/ext/skia_utils_mac.h b/skia/ext/skia_utils_mac.h index 70cf9ea..bdf6c1f 100644 --- a/skia/ext/skia_utils_mac.h +++ b/skia/ext/skia_utils_mac.h @@ -6,7 +6,7 @@ #define SKIA_EXT_SKIA_UTILS_MAC_H_ #pragma once -#include <CoreGraphics/CGColor.h> +#include <ApplicationServices/ApplicationServices.h> #include <vector> #include "third_party/skia/include/core/SkColor.h" |