Reland "Reland "Reland "Reland "Implemented screen enumeration and selection for desktop capture under X11 using the X Resize and Rotate extension version 1.5.""""
This is a reland of 703a5d76d9ba8e7984509cc7bf70fb4ed84ef6be Original change's description: > Reland "Reland "Reland "Implemented screen enumeration and selection for desktop capture under X11 using the X Resize and Rotate extension version 1.5.""" > > This is a reland of af51be7869994a299451e22e6382ae641767b26d > > Original change's description: > > Reland "Reland "Implemented screen enumeration and selection for desktop capture under X11 using the X Resize and Rotate extension version 1.5."" > > > > This is a reland of a0adf3d4409036d095480e9bfa0fc06990362f84 > > > > Original change's description: > > > Reland "Implemented screen enumeration and selection for desktop capture under X11 using the X Resize and Rotate extension version 1.5." > > > > > > This is a reland of e7153012682ccd3d1eacc18f802cab7820e3bad3 > > > > > > Original change's description: > > > > Implemented screen enumeration and selection for desktop capture under X11 using the X Resize and Rotate entension version 1.5. > > > > > > > > Bug: chromium:396091 > > > > Change-Id: Ia1b36c771632c536bb8d15322461b479fabc409e > > > > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/148768 > > > > Commit-Queue: Sergey Ulanov <sergeyu@chromium.org> > > > > Reviewed-by: Sergey Ulanov <sergeyu@chromium.org> > > > > Cr-Commit-Position: refs/heads/master@{#29083} > > > > > > Bug: chromium:396091 > > > Change-Id: I0d9171ae5f340e0489e4b45ce5d97bc52b0a4904 > > > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/156067 > > > Commit-Queue: Tommi <tommi@webrtc.org> > > > Reviewed-by: Tommi <tommi@webrtc.org> > > > Cr-Commit-Position: refs/heads/master@{#29655} > > > > Bug: chromium:396091 > > Change-Id: I47525911095fabc6cee613d03b0d83134b95b084 > > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/158900 > > Reviewed-by: Tomas Gunnarsson <tommi@chromium.org> > > Reviewed-by: Tommi <tommi@webrtc.org> > > Commit-Queue: Tommi <tommi@webrtc.org> > > Cr-Commit-Position: refs/heads/master@{#30032} > > Bug: chromium:396091 > Change-Id: I03702c8ea935bb5fe1797defda1ba6b279b95217 > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/165724 > Reviewed-by: Jamie Walch <jamiewalch@chromium.org> > Commit-Queue: Jamie Walch <jamiewalch@chromium.org> > Cr-Commit-Position: refs/heads/master@{#30461} TBR=jamiewalch@chromium.org,tommi@webrtc.org Bug: chromium:396091 Change-Id: If9bd5e7b35240acc4dd528397926ba663fe2affc Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/168760 Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org> Commit-Queue: Mirko Bonadei <mbonadei@webrtc.org> Cr-Commit-Position: refs/heads/master@{#30548}
This commit is contained in:
1
AUTHORS
1
AUTHORS
@ -61,6 +61,7 @@ Silviu Caragea <silviu.cpp@gmail.com>
|
|||||||
Stefan Gula <steweg@gmail.com>
|
Stefan Gula <steweg@gmail.com>
|
||||||
Steve Reid <sreid@sea-to-sky.net>
|
Steve Reid <sreid@sea-to-sky.net>
|
||||||
Tarun Chawla <trnkumarchawla@gmail.com>
|
Tarun Chawla <trnkumarchawla@gmail.com>
|
||||||
|
Trevor Hayes <trevor.axiom@gmail.com>
|
||||||
Uladzislau Susha <landby@gmail.com>
|
Uladzislau Susha <landby@gmail.com>
|
||||||
Vladimir Beloborodov <VladimirTechMan@gmail.com>
|
Vladimir Beloborodov <VladimirTechMan@gmail.com>
|
||||||
Vicken Simonian <vsimon@gmail.com>
|
Vicken Simonian <vsimon@gmail.com>
|
||||||
|
@ -397,6 +397,7 @@ rtc_library("desktop_capture_generic") {
|
|||||||
"Xext",
|
"Xext",
|
||||||
"Xfixes",
|
"Xfixes",
|
||||||
"Xrender",
|
"Xrender",
|
||||||
|
"Xrandr",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -483,6 +484,10 @@ rtc_library("desktop_capture_generic") {
|
|||||||
"//third_party/abseil-cpp/absl/strings",
|
"//third_party/abseil-cpp/absl/strings",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if (rtc_use_x11_extensions) {
|
||||||
|
deps += [ "../../rtc_base:sanitizer" ]
|
||||||
|
}
|
||||||
|
|
||||||
if (build_with_mozilla) {
|
if (build_with_mozilla) {
|
||||||
deps += [ "../../rtc_base:rtc_base_approved" ]
|
deps += [ "../../rtc_base:rtc_base_approved" ]
|
||||||
} else {
|
} else {
|
||||||
|
@ -43,6 +43,8 @@ class DesktopVector {
|
|||||||
return DesktopVector(x() - other.x(), y() - other.y());
|
return DesktopVector(x() - other.x(), y() - other.y());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DesktopVector operator-() const { return DesktopVector(-x_, -y_); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int32_t x_;
|
int32_t x_;
|
||||||
int32_t y_;
|
int32_t y_;
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include <X11/extensions/Xdamage.h>
|
#include <X11/extensions/Xdamage.h>
|
||||||
#include <X11/extensions/Xfixes.h>
|
#include <X11/extensions/Xfixes.h>
|
||||||
#include <X11/extensions/damagewire.h>
|
#include <X11/extensions/damagewire.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@ -30,6 +31,7 @@
|
|||||||
#include "modules/desktop_capture/shared_desktop_frame.h"
|
#include "modules/desktop_capture/shared_desktop_frame.h"
|
||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
#include "rtc_base/logging.h"
|
#include "rtc_base/logging.h"
|
||||||
|
#include "rtc_base/sanitizer.h"
|
||||||
#include "rtc_base/time_utils.h"
|
#include "rtc_base/time_utils.h"
|
||||||
#include "rtc_base/trace_event.h"
|
#include "rtc_base/trace_event.h"
|
||||||
|
|
||||||
@ -45,6 +47,10 @@ ScreenCapturerX11::~ScreenCapturerX11() {
|
|||||||
options_.x_display()->RemoveEventHandler(damage_event_base_ + XDamageNotify,
|
options_.x_display()->RemoveEventHandler(damage_event_base_ + XDamageNotify,
|
||||||
this);
|
this);
|
||||||
}
|
}
|
||||||
|
if (use_randr_) {
|
||||||
|
options_.x_display()->RemoveEventHandler(
|
||||||
|
randr_event_base_ + RRScreenChangeNotify, this);
|
||||||
|
}
|
||||||
DeinitXlib();
|
DeinitXlib();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,6 +98,8 @@ bool ScreenCapturerX11::Init(const DesktopCaptureOptions& options) {
|
|||||||
InitXDamage();
|
InitXDamage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InitXrandr();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,6 +144,75 @@ void ScreenCapturerX11::InitXDamage() {
|
|||||||
RTC_LOG(LS_INFO) << "Using XDamage extension.";
|
RTC_LOG(LS_INFO) << "Using XDamage extension.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RTC_NO_SANITIZE("cfi-icall")
|
||||||
|
void ScreenCapturerX11::InitXrandr() {
|
||||||
|
int major_version = 0;
|
||||||
|
int minor_version = 0;
|
||||||
|
int error_base_ignored = 0;
|
||||||
|
if (XRRQueryExtension(display(), &randr_event_base_, &error_base_ignored) &&
|
||||||
|
XRRQueryVersion(display(), &major_version, &minor_version)) {
|
||||||
|
if (major_version > 1 || (major_version == 1 && minor_version >= 5)) {
|
||||||
|
// Dynamically link XRRGetMonitors and XRRFreeMonitors as a workaround
|
||||||
|
// to avoid a dependency issue with Debian 8.
|
||||||
|
get_monitors_ = reinterpret_cast<get_monitors_func>(
|
||||||
|
dlsym(RTLD_DEFAULT, "XRRGetMonitors"));
|
||||||
|
free_monitors_ = reinterpret_cast<free_monitors_func>(
|
||||||
|
dlsym(RTLD_DEFAULT, "XRRFreeMonitors"));
|
||||||
|
if (get_monitors_ && free_monitors_) {
|
||||||
|
use_randr_ = true;
|
||||||
|
RTC_LOG(LS_INFO) << "Using XRandR extension v" << major_version << '.'
|
||||||
|
<< minor_version << '.';
|
||||||
|
monitors_ =
|
||||||
|
get_monitors_(display(), root_window_, true, &num_monitors_);
|
||||||
|
|
||||||
|
// Register for screen change notifications
|
||||||
|
XRRSelectInput(display(), root_window_, RRScreenChangeNotifyMask);
|
||||||
|
options_.x_display()->AddEventHandler(
|
||||||
|
randr_event_base_ + RRScreenChangeNotify, this);
|
||||||
|
} else {
|
||||||
|
RTC_LOG(LS_ERROR) << "Unable to link XRandR monitor functions.";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
RTC_LOG(LS_ERROR) << "XRandR entension is older than v1.5.";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
RTC_LOG(LS_ERROR) << "X server does not support XRandR.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RTC_NO_SANITIZE("cfi-icall")
|
||||||
|
void ScreenCapturerX11::UpdateMonitors() {
|
||||||
|
if (monitors_) {
|
||||||
|
free_monitors_(monitors_);
|
||||||
|
monitors_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
monitors_ = get_monitors_(display(), root_window_, true, &num_monitors_);
|
||||||
|
|
||||||
|
if (selected_monitor_name_) {
|
||||||
|
if (selected_monitor_name_ == static_cast<Atom>(kFullDesktopScreenId)) {
|
||||||
|
selected_monitor_rect_ =
|
||||||
|
DesktopRect::MakeSize(x_server_pixel_buffer_.window_size());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < num_monitors_; ++i) {
|
||||||
|
XRRMonitorInfo& m = monitors_[i];
|
||||||
|
if (selected_monitor_name_ == m.name) {
|
||||||
|
RTC_LOG(LS_INFO) << "XRandR monitor " << m.name << " rect updated.";
|
||||||
|
selected_monitor_rect_ =
|
||||||
|
DesktopRect::MakeXYWH(m.x, m.y, m.width, m.height);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The selected monitor is not connected anymore
|
||||||
|
RTC_LOG(LS_INFO) << "XRandR selected monitor " << selected_monitor_name_
|
||||||
|
<< " lost.";
|
||||||
|
selected_monitor_rect_ = DesktopRect::MakeWH(0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ScreenCapturerX11::Start(Callback* callback) {
|
void ScreenCapturerX11::Start(Callback* callback) {
|
||||||
RTC_DCHECK(!callback_);
|
RTC_DCHECK(!callback_);
|
||||||
RTC_DCHECK(callback);
|
RTC_DCHECK(callback);
|
||||||
@ -167,9 +244,13 @@ void ScreenCapturerX11::CaptureFrame() {
|
|||||||
// Note that we can't reallocate other buffers at this point, since the caller
|
// Note that we can't reallocate other buffers at this point, since the caller
|
||||||
// may still be reading from them.
|
// may still be reading from them.
|
||||||
if (!queue_.current_frame()) {
|
if (!queue_.current_frame()) {
|
||||||
queue_.ReplaceCurrentFrame(
|
std::unique_ptr<DesktopFrame> frame(
|
||||||
SharedDesktopFrame::Wrap(std::unique_ptr<DesktopFrame>(
|
new BasicDesktopFrame(selected_monitor_rect_.size()));
|
||||||
new BasicDesktopFrame(x_server_pixel_buffer_.window_size()))));
|
|
||||||
|
// We set the top-left of the frame so the mouse cursor will be composited
|
||||||
|
// properly, and our frame buffer will not be overrun while blitting.
|
||||||
|
frame->set_top_left(selected_monitor_rect_.top_left());
|
||||||
|
queue_.ReplaceCurrentFrame(SharedDesktopFrame::Wrap(std::move(frame)));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<DesktopFrame> result = CaptureScreen();
|
std::unique_ptr<DesktopFrame> result = CaptureScreen();
|
||||||
@ -187,14 +268,46 @@ void ScreenCapturerX11::CaptureFrame() {
|
|||||||
|
|
||||||
bool ScreenCapturerX11::GetSourceList(SourceList* sources) {
|
bool ScreenCapturerX11::GetSourceList(SourceList* sources) {
|
||||||
RTC_DCHECK(sources->size() == 0);
|
RTC_DCHECK(sources->size() == 0);
|
||||||
// TODO(jiayl): implement screen enumeration.
|
if (!use_randr_) {
|
||||||
sources->push_back({0});
|
sources->push_back({});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that |monitors_| is updated with changes that may have happened
|
||||||
|
// between calls to GetSourceList().
|
||||||
|
options_.x_display()->ProcessPendingXEvents();
|
||||||
|
|
||||||
|
for (int i = 0; i < num_monitors_; ++i) {
|
||||||
|
XRRMonitorInfo& m = monitors_[i];
|
||||||
|
char* monitor_title = XGetAtomName(display(), m.name);
|
||||||
|
|
||||||
|
// Note name is an X11 Atom used to id the monitor.
|
||||||
|
sources->push_back({static_cast<SourceId>(m.name), monitor_title});
|
||||||
|
XFree(monitor_title);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScreenCapturerX11::SelectSource(SourceId id) {
|
bool ScreenCapturerX11::SelectSource(SourceId id) {
|
||||||
// TODO(jiayl): implement screen selection.
|
if (!use_randr_ || id == kFullDesktopScreenId) {
|
||||||
return true;
|
selected_monitor_name_ = kFullDesktopScreenId;
|
||||||
|
selected_monitor_rect_ =
|
||||||
|
DesktopRect::MakeSize(x_server_pixel_buffer_.window_size());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < num_monitors_; ++i) {
|
||||||
|
if (id == static_cast<SourceId>(monitors_[i].name)) {
|
||||||
|
RTC_LOG(LS_INFO) << "XRandR selected source: " << id;
|
||||||
|
XRRMonitorInfo& m = monitors_[i];
|
||||||
|
selected_monitor_name_ = m.name;
|
||||||
|
selected_monitor_rect_ =
|
||||||
|
DesktopRect::MakeXYWH(m.x, m.y, m.width, m.height);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScreenCapturerX11::HandleXEvent(const XEvent& event) {
|
bool ScreenCapturerX11::HandleXEvent(const XEvent& event) {
|
||||||
@ -205,6 +318,12 @@ bool ScreenCapturerX11::HandleXEvent(const XEvent& event) {
|
|||||||
return false;
|
return false;
|
||||||
RTC_DCHECK(damage_event->level == XDamageReportNonEmpty);
|
RTC_DCHECK(damage_event->level == XDamageReportNonEmpty);
|
||||||
return true;
|
return true;
|
||||||
|
} else if (use_randr_ &&
|
||||||
|
event.type == randr_event_base_ + RRScreenChangeNotify) {
|
||||||
|
XRRUpdateConfiguration(const_cast<XEvent*>(&event));
|
||||||
|
UpdateMonitors();
|
||||||
|
RTC_LOG(LS_INFO) << "XRandR screen change event received.";
|
||||||
|
return true;
|
||||||
} else if (event.type == ConfigureNotify) {
|
} else if (event.type == ConfigureNotify) {
|
||||||
ScreenConfigurationChanged();
|
ScreenConfigurationChanged();
|
||||||
return true;
|
return true;
|
||||||
@ -214,11 +333,11 @@ bool ScreenCapturerX11::HandleXEvent(const XEvent& event) {
|
|||||||
|
|
||||||
std::unique_ptr<DesktopFrame> ScreenCapturerX11::CaptureScreen() {
|
std::unique_ptr<DesktopFrame> ScreenCapturerX11::CaptureScreen() {
|
||||||
std::unique_ptr<SharedDesktopFrame> frame = queue_.current_frame()->Share();
|
std::unique_ptr<SharedDesktopFrame> frame = queue_.current_frame()->Share();
|
||||||
RTC_DCHECK(x_server_pixel_buffer_.window_size().equals(frame->size()));
|
RTC_DCHECK(selected_monitor_rect_.size().equals(frame->size()));
|
||||||
|
|
||||||
// Pass the screen size to the helper, so it can clip the invalid region if it
|
// Pass the screen size to the helper, so it can clip the invalid region if it
|
||||||
// expands that region to a grid.
|
// expands that region to a grid.
|
||||||
helper_.set_size_most_recent(frame->size());
|
helper_.set_size_most_recent(x_server_pixel_buffer_.window_size());
|
||||||
|
|
||||||
// In the DAMAGE case, ensure the frame is up-to-date with the previous frame
|
// In the DAMAGE case, ensure the frame is up-to-date with the previous frame
|
||||||
// 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
|
||||||
@ -246,12 +365,7 @@ std::unique_ptr<DesktopFrame> ScreenCapturerX11::CaptureScreen() {
|
|||||||
|
|
||||||
// Capture the damaged portions of the desktop.
|
// Capture the damaged portions of the desktop.
|
||||||
helper_.TakeInvalidRegion(updated_region);
|
helper_.TakeInvalidRegion(updated_region);
|
||||||
|
updated_region->IntersectWith(selected_monitor_rect_);
|
||||||
// Clip the damaged portions to the current screen size, just in case some
|
|
||||||
// spurious XDamage notifications were received for a previous (larger)
|
|
||||||
// screen size.
|
|
||||||
updated_region->IntersectWith(
|
|
||||||
DesktopRect::MakeSize(x_server_pixel_buffer_.window_size()));
|
|
||||||
|
|
||||||
for (DesktopRegion::Iterator it(*updated_region); !it.IsAtEnd();
|
for (DesktopRegion::Iterator it(*updated_region); !it.IsAtEnd();
|
||||||
it.Advance()) {
|
it.Advance()) {
|
||||||
@ -261,10 +375,11 @@ std::unique_ptr<DesktopFrame> ScreenCapturerX11::CaptureScreen() {
|
|||||||
} else {
|
} else {
|
||||||
// Doing full-screen polling, or this is the first capture after a
|
// Doing full-screen polling, or this is the first capture after a
|
||||||
// screen-resolution change. In either case, need a full-screen capture.
|
// screen-resolution change. In either case, need a full-screen capture.
|
||||||
DesktopRect screen_rect = DesktopRect::MakeSize(frame->size());
|
if (!x_server_pixel_buffer_.CaptureRect(selected_monitor_rect_,
|
||||||
if (!x_server_pixel_buffer_.CaptureRect(screen_rect, frame.get()))
|
frame.get())) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
updated_region->SetRect(screen_rect);
|
}
|
||||||
|
updated_region->SetRect(selected_monitor_rect_);
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::move(frame);
|
return std::move(frame);
|
||||||
@ -281,6 +396,11 @@ void ScreenCapturerX11::ScreenConfigurationChanged() {
|
|||||||
RTC_LOG(LS_ERROR) << "Failed to initialize pixel buffer after screen "
|
RTC_LOG(LS_ERROR) << "Failed to initialize pixel buffer after screen "
|
||||||
"configuration change.";
|
"configuration change.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!use_randr_) {
|
||||||
|
selected_monitor_rect_ =
|
||||||
|
DesktopRect::MakeSize(x_server_pixel_buffer_.window_size());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenCapturerX11::SynchronizeFrame() {
|
void ScreenCapturerX11::SynchronizeFrame() {
|
||||||
@ -299,11 +419,21 @@ void ScreenCapturerX11::SynchronizeFrame() {
|
|||||||
RTC_DCHECK(current != last);
|
RTC_DCHECK(current != last);
|
||||||
for (DesktopRegion::Iterator it(last_invalid_region_); !it.IsAtEnd();
|
for (DesktopRegion::Iterator it(last_invalid_region_); !it.IsAtEnd();
|
||||||
it.Advance()) {
|
it.Advance()) {
|
||||||
current->CopyPixelsFrom(*last, it.rect().top_left(), it.rect());
|
if (selected_monitor_rect_.ContainsRect(it.rect())) {
|
||||||
|
DesktopRect r = it.rect();
|
||||||
|
r.Translate(-selected_monitor_rect_.top_left());
|
||||||
|
current->CopyPixelsFrom(*last, r.top_left(), r);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RTC_NO_SANITIZE("cfi-icall")
|
||||||
void ScreenCapturerX11::DeinitXlib() {
|
void ScreenCapturerX11::DeinitXlib() {
|
||||||
|
if (monitors_) {
|
||||||
|
free_monitors_(monitors_);
|
||||||
|
monitors_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (gc_) {
|
if (gc_) {
|
||||||
XFreeGC(display(), gc_);
|
XFreeGC(display(), gc_);
|
||||||
gc_ = nullptr;
|
gc_ = nullptr;
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/extensions/Xdamage.h>
|
#include <X11/extensions/Xdamage.h>
|
||||||
#include <X11/extensions/Xfixes.h>
|
#include <X11/extensions/Xfixes.h>
|
||||||
|
#include <X11/extensions/Xrandr.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@ -64,6 +65,8 @@ class ScreenCapturerX11 : public DesktopCapturer,
|
|||||||
bool HandleXEvent(const XEvent& event) override;
|
bool HandleXEvent(const XEvent& event) override;
|
||||||
|
|
||||||
void InitXDamage();
|
void InitXDamage();
|
||||||
|
void InitXrandr();
|
||||||
|
void UpdateMonitors();
|
||||||
|
|
||||||
// Capture screen pixels to the current buffer in the queue. In the DAMAGE
|
// Capture screen pixels to the current buffer in the queue. In the DAMAGE
|
||||||
// case, the ScreenCapturerHelper already holds the list of invalid rectangles
|
// case, the ScreenCapturerHelper already holds the list of invalid rectangles
|
||||||
@ -92,6 +95,18 @@ class ScreenCapturerX11 : public DesktopCapturer,
|
|||||||
GC gc_ = nullptr;
|
GC gc_ = nullptr;
|
||||||
Window root_window_ = BadValue;
|
Window root_window_ = BadValue;
|
||||||
|
|
||||||
|
// XRandR 1.5 monitors.
|
||||||
|
bool use_randr_ = false;
|
||||||
|
int randr_event_base_ = 0;
|
||||||
|
XRRMonitorInfo* monitors_ = nullptr;
|
||||||
|
int num_monitors_ = 0;
|
||||||
|
DesktopRect selected_monitor_rect_;
|
||||||
|
Atom selected_monitor_name_ = 0;
|
||||||
|
typedef XRRMonitorInfo* (*get_monitors_func)(Display*, Window, Bool, int*);
|
||||||
|
typedef void (*free_monitors_func)(XRRMonitorInfo*);
|
||||||
|
get_monitors_func get_monitors_ = nullptr;
|
||||||
|
free_monitors_func free_monitors_ = nullptr;
|
||||||
|
|
||||||
// XFixes.
|
// XFixes.
|
||||||
bool has_xfixes_ = false;
|
bool has_xfixes_ = false;
|
||||||
int xfixes_event_base_ = -1;
|
int xfixes_event_base_ = -1;
|
||||||
|
@ -66,8 +66,12 @@ void FastBlit(XImage* x_image,
|
|||||||
uint8_t* src_pos,
|
uint8_t* src_pos,
|
||||||
const DesktopRect& rect,
|
const DesktopRect& rect,
|
||||||
DesktopFrame* frame) {
|
DesktopFrame* frame) {
|
||||||
|
RTC_DCHECK_LE(frame->top_left().x(), rect.left());
|
||||||
|
RTC_DCHECK_LE(frame->top_left().y(), rect.top());
|
||||||
|
|
||||||
int src_stride = x_image->bytes_per_line;
|
int src_stride = x_image->bytes_per_line;
|
||||||
int dst_x = rect.left(), dst_y = rect.top();
|
int dst_x = rect.left() - frame->top_left().x();
|
||||||
|
int dst_y = rect.top() - frame->top_left().y();
|
||||||
|
|
||||||
uint8_t* dst_pos = frame->data() + frame->stride() * dst_y;
|
uint8_t* dst_pos = frame->data() + frame->stride() * dst_y;
|
||||||
dst_pos += dst_x * DesktopFrame::kBytesPerPixel;
|
dst_pos += dst_x * DesktopFrame::kBytesPerPixel;
|
||||||
@ -85,8 +89,12 @@ void SlowBlit(XImage* x_image,
|
|||||||
uint8_t* src_pos,
|
uint8_t* src_pos,
|
||||||
const DesktopRect& rect,
|
const DesktopRect& rect,
|
||||||
DesktopFrame* frame) {
|
DesktopFrame* frame) {
|
||||||
|
RTC_DCHECK_LE(frame->top_left().x(), rect.left());
|
||||||
|
RTC_DCHECK_LE(frame->top_left().y(), rect.top());
|
||||||
|
|
||||||
int src_stride = x_image->bytes_per_line;
|
int src_stride = x_image->bytes_per_line;
|
||||||
int dst_x = rect.left(), dst_y = rect.top();
|
int dst_x = rect.left() - frame->top_left().x();
|
||||||
|
int dst_y = rect.top() - frame->top_left().y();
|
||||||
int width = rect.width(), height = rect.height();
|
int width = rect.width(), height = rect.height();
|
||||||
|
|
||||||
uint32_t red_mask = x_image->red_mask;
|
uint32_t red_mask = x_image->red_mask;
|
||||||
|
Reference in New Issue
Block a user