Commit 0377fc31 authored by wez@chromium.org's avatar wez@chromium.org

Compare the sizes of current & previous frames before each capture.

This ensures that the capturer will never try to preserve pixels from a
preceding frame of a different size, in the case where the display has been
resized but we have not yet received the resize notification.

BUG=156201


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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@162484 0039d316-1c4b-4281-b951-d872f2087c98
parent b10abe6b
...@@ -63,6 +63,7 @@ class VideoFrameBuffer { ...@@ -63,6 +63,7 @@ class VideoFrameBuffer {
uint8* ptr() const { return ptr_.get(); } uint8* ptr() const { return ptr_.get(); }
void set_needs_update() { needs_update_ = true; } void set_needs_update() { needs_update_ = true; }
bool needs_update() const { return needs_update_; }
private: private:
SkISize size_; SkISize size_;
...@@ -174,7 +175,7 @@ class VideoFrameCapturerLinux : public VideoFrameCapturer { ...@@ -174,7 +175,7 @@ class VideoFrameCapturerLinux : public VideoFrameCapturer {
SkRegion last_invalid_region_; SkRegion last_invalid_region_;
// Last capture buffer used. // Last capture buffer used.
uint8* last_buffer_; int last_buffer_;
// |Differ| for use when polling for changes. // |Differ| for use when polling for changes.
scoped_ptr<Differ> differ_; scoped_ptr<Differ> differ_;
...@@ -196,7 +197,7 @@ VideoFrameCapturerLinux::VideoFrameCapturerLinux() ...@@ -196,7 +197,7 @@ VideoFrameCapturerLinux::VideoFrameCapturerLinux()
damage_region_(0), damage_region_(0),
current_buffer_(0), current_buffer_(0),
pixel_format_(media::VideoFrame::RGB32), pixel_format_(media::VideoFrame::RGB32),
last_buffer_(NULL) { last_buffer_(kNumBuffers - 1) {
helper_.SetLogGridSize(4); helper_.SetLogGridSize(4);
} }
...@@ -317,14 +318,23 @@ void VideoFrameCapturerLinux::CaptureInvalidRegion( ...@@ -317,14 +318,23 @@ void VideoFrameCapturerLinux::CaptureInvalidRegion(
// screen-resolution. // screen-resolution.
VideoFrameBuffer &current = buffers_[current_buffer_]; VideoFrameBuffer &current = buffers_[current_buffer_];
current.Update(display_, root_window_); current.Update(display_, root_window_);
// Also refresh the Differ helper used by CaptureFrame(), if needed.
if (!use_damage_ && !last_buffer_) { // Mark the previous frame for update if its dimensions no longer match.
differ_.reset(new Differ(current.size().width(), current.size().height(), if (buffers_[last_buffer_].size() != current.size()) {
kBytesPerPixel, current.bytes_per_row())); buffers_[last_buffer_].set_needs_update();
// Also refresh the Differ helper used by CaptureFrame(), if needed.
if (!use_damage_) {
differ_.reset(new Differ(current.size().width(), current.size().height(),
kBytesPerPixel, current.bytes_per_row()));
}
} }
scoped_refptr<CaptureData> capture_data(CaptureFrame()); scoped_refptr<CaptureData> capture_data(CaptureFrame());
// Swap the current & previous buffers ready for the next capture.
last_invalid_region_ = capture_data->dirty_region();
last_buffer_ = current_buffer_;
current_buffer_ = (current_buffer_ + 1) % kNumBuffers; current_buffer_ = (current_buffer_ + 1) % kNumBuffers;
callback.Run(capture_data); callback.Run(capture_data);
...@@ -410,13 +420,13 @@ CaptureData* VideoFrameCapturerLinux::CaptureFrame() { ...@@ -410,13 +420,13 @@ CaptureData* VideoFrameCapturerLinux::CaptureFrame() {
// if any. If there isn't a previous frame, that means a screen-resolution // if any. If there isn't a previous frame, that means a screen-resolution
// change occurred, and |invalid_rects| will be updated to include the whole // change occurred, and |invalid_rects| will be updated to include the whole
// screen. // screen.
if (use_damage_ && last_buffer_) if (use_damage_ && !buffers_[last_buffer_].needs_update())
SynchronizeFrame(); SynchronizeFrame();
SkRegion invalid_region; SkRegion invalid_region;
x_server_pixel_buffer_.Synchronize(); x_server_pixel_buffer_.Synchronize();
if (use_damage_ && last_buffer_) { if (use_damage_ && !buffers_[last_buffer_].needs_update()) {
// Atomically fetch and clear the damage region. // Atomically fetch and clear the damage region.
XDamageSubtract(display_, damage_handle_, None, damage_region_); XDamageSubtract(display_, damage_handle_, None, damage_region_);
int nRects = 0; int nRects = 0;
...@@ -443,11 +453,13 @@ CaptureData* VideoFrameCapturerLinux::CaptureFrame() { ...@@ -443,11 +453,13 @@ CaptureData* VideoFrameCapturerLinux::CaptureFrame() {
buffer.size().height()); buffer.size().height());
CaptureRect(screen_rect, capture_data); CaptureRect(screen_rect, capture_data);
if (last_buffer_) { if (!buffers_[last_buffer_].needs_update()) {
// Full-screen polling, so calculate the invalid rects here, based on the // Full-screen polling, so calculate the invalid rects here, based on the
// changed pixels between current and previous buffers. // changed pixels between current and previous buffers.
DCHECK(differ_ != NULL); DCHECK(differ_ != NULL);
differ_->CalcDirtyRegion(last_buffer_, buffer.ptr(), &invalid_region); VideoFrameBuffer& last_buffer = buffers_[last_buffer_];
differ_->CalcDirtyRegion(
last_buffer.ptr(), buffer.ptr(), &invalid_region);
} else { } else {
// No previous buffer, so always invalidate the whole screen, whether // No previous buffer, so always invalidate the whole screen, whether
// or not DAMAGE is being used. DAMAGE doesn't necessarily send a // or not DAMAGE is being used. DAMAGE doesn't necessarily send a
...@@ -458,13 +470,10 @@ CaptureData* VideoFrameCapturerLinux::CaptureFrame() { ...@@ -458,13 +470,10 @@ CaptureData* VideoFrameCapturerLinux::CaptureFrame() {
} }
capture_data->mutable_dirty_region() = invalid_region; capture_data->mutable_dirty_region() = invalid_region;
last_invalid_region_ = invalid_region;
last_buffer_ = buffer.ptr();
return capture_data; return capture_data;
} }
void VideoFrameCapturerLinux::ScreenConfigurationChanged() { void VideoFrameCapturerLinux::ScreenConfigurationChanged() {
last_buffer_ = NULL;
for (int i = 0; i < kNumBuffers; ++i) { for (int i = 0; i < kNumBuffers; ++i) {
buffers_[i].set_needs_update(); buffers_[i].set_needs_update();
} }
...@@ -481,13 +490,15 @@ void VideoFrameCapturerLinux::SynchronizeFrame() { ...@@ -481,13 +490,15 @@ void VideoFrameCapturerLinux::SynchronizeFrame() {
// TODO(hclam): We can reduce the amount of copying here by subtracting // TODO(hclam): We can reduce the amount of copying here by subtracting
// |capturer_helper_|s region from |last_invalid_region_|. // |capturer_helper_|s region from |last_invalid_region_|.
// http://crbug.com/92354 // http://crbug.com/92354
DCHECK(last_buffer_); DCHECK(!buffers_[last_buffer_].needs_update());
DCHECK_NE(last_buffer_, current_buffer_);
VideoFrameBuffer& buffer = buffers_[current_buffer_]; VideoFrameBuffer& buffer = buffers_[current_buffer_];
VideoFrameBuffer& last_buffer = buffers_[last_buffer_];
for (SkRegion::Iterator it(last_invalid_region_); !it.done(); it.next()) { for (SkRegion::Iterator it(last_invalid_region_); !it.done(); it.next()) {
const SkIRect& r = it.rect(); const SkIRect& r = it.rect();
int offset = r.fTop * buffer.bytes_per_row() + r.fLeft * kBytesPerPixel; int offset = r.fTop * buffer.bytes_per_row() + r.fLeft * kBytesPerPixel;
for (int i = 0; i < r.height(); ++i) { for (int i = 0; i < r.height(); ++i) {
memcpy(buffer.ptr() + offset, last_buffer_ + offset, memcpy(buffer.ptr() + offset, last_buffer.ptr() + offset,
r.width() * kBytesPerPixel); r.width() * kBytesPerPixel);
offset += buffer.size().width() * kBytesPerPixel; offset += buffer.size().width() * kBytesPerPixel;
} }
......
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