summaryrefslogtreecommitdiffstats
path: root/remoting
diff options
context:
space:
mode:
authorjamiewalch@chromium.org <jamiewalch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-29 20:50:49 +0000
committerjamiewalch@chromium.org <jamiewalch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-29 20:50:49 +0000
commit6f680ab8a9adc9bd6b0f4705288ba7aa78c2cf82 (patch)
treea1644ee6d6257028c119e0e28ab95fa29ee82f03 /remoting
parentcef7a6d8a06baab27a38e5f285b449df22c38dc4 (diff)
downloadchromium_src-6f680ab8a9adc9bd6b0f4705288ba7aa78c2cf82.zip
chromium_src-6f680ab8a9adc9bd6b0f4705288ba7aa78c2cf82.tar.gz
chromium_src-6f680ab8a9adc9bd6b0f4705288ba7aa78c2cf82.tar.bz2
Use pixel buffer objects where supported to improve capturer speed.
BUG=79043 TEST=Manual Review URL: http://codereview.chromium.org/6903079 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@83586 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting')
-rw-r--r--remoting/host/capturer_mac.cc123
1 files changed, 108 insertions, 15 deletions
diff --git a/remoting/host/capturer_mac.cc b/remoting/host/capturer_mac.cc
index f0efc7f..dc831fd 100644
--- a/remoting/host/capturer_mac.cc
+++ b/remoting/host/capturer_mac.cc
@@ -17,6 +17,63 @@
namespace remoting {
namespace {
+
+class scoped_pixel_buffer_object {
+ public:
+ scoped_pixel_buffer_object();
+ ~scoped_pixel_buffer_object();
+
+ bool Init(CGLContextObj cgl_context, int size_in_bytes);
+ void Release();
+
+ GLuint get() const { return pixel_buffer_object_; }
+
+ private:
+ CGLContextObj cgl_context_;
+ GLuint pixel_buffer_object_;
+
+ DISALLOW_COPY_AND_ASSIGN(scoped_pixel_buffer_object);
+};
+
+scoped_pixel_buffer_object::scoped_pixel_buffer_object()
+ : cgl_context_(NULL),
+ pixel_buffer_object_(0) {
+}
+
+scoped_pixel_buffer_object::~scoped_pixel_buffer_object() {
+ Release();
+}
+
+bool scoped_pixel_buffer_object::Init(CGLContextObj cgl_context,
+ int size_in_bytes) {
+ cgl_context_ = cgl_context;
+ CGLContextObj CGL_MACRO_CONTEXT = cgl_context_;
+ glGenBuffersARB(1, &pixel_buffer_object_);
+ if (glGetError() == GL_NO_ERROR) {
+ glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pixel_buffer_object_);
+ glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, size_in_bytes, NULL,
+ GL_STREAM_READ_ARB);
+ glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
+ if (glGetError() != GL_NO_ERROR) {
+ Release();
+ }
+ } else {
+ cgl_context_ = NULL;
+ pixel_buffer_object_ = 0;
+ }
+ return pixel_buffer_object_ != 0;
+}
+
+void scoped_pixel_buffer_object::Release() {
+ if (pixel_buffer_object_) {
+ CGLContextObj CGL_MACRO_CONTEXT = cgl_context_;
+ glDeleteBuffersARB(1, &pixel_buffer_object_);
+ cgl_context_ = NULL;
+ pixel_buffer_object_ = 0;
+ }
+}
+
+
// A class to perform capturing for mac.
class CapturerMac : public Capturer {
public:
@@ -34,6 +91,8 @@ class CapturerMac : public Capturer {
virtual const gfx::Size& size_most_recent() const OVERRIDE;
private:
+ void FastBlit(uint8* buffer);
+ void SlowBlit(uint8* buffer);
void CaptureRects(const InvalidRects& rects,
CaptureCompletedCallback* callback);
@@ -55,6 +114,7 @@ class CapturerMac : public Capturer {
void ReleaseBuffers();
CGLContextObj cgl_context_;
static const int kNumBuffers = 2;
+ scoped_pixel_buffer_object pixel_buffer_object_;
scoped_array<uint8> buffers_[kNumBuffers];
// A thread-safe list of invalid rectangles, and the size of the most
@@ -109,6 +169,7 @@ CapturerMac::~CapturerMac() {
void CapturerMac::ReleaseBuffers() {
if (cgl_context_) {
+ pixel_buffer_object_.Release();
CGLDestroyContext(cgl_context_);
cgl_context_ = NULL;
}
@@ -143,6 +204,8 @@ void CapturerMac::ScreenConfigurationChanged() {
CGLDestroyPixelFormat(pixel_format);
CGLSetFullScreen(cgl_context_);
CGLSetCurrentContext(cgl_context_);
+
+ pixel_buffer_object_.Init(cgl_context_, buffer_size);
}
media::VideoFrame::Format CapturerMac::pixel_format() const {
@@ -168,24 +231,16 @@ void CapturerMac::InvalidateFullScreen() {
void CapturerMac::CaptureInvalidRects(CaptureCompletedCallback* callback) {
InvalidRects rects;
helper_.SwapInvalidRects(rects);
-
- CGLContextObj CGL_MACRO_CONTEXT = cgl_context_;
- glReadBuffer(GL_FRONT);
- glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
-
- glPixelStorei(GL_PACK_ALIGNMENT, 4); // Force 4-byte alignment.
- glPixelStorei(GL_PACK_ROW_LENGTH, 0);
- glPixelStorei(GL_PACK_SKIP_ROWS, 0);
- glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
-
- // Read a block of pixels from the frame buffer.
uint8* current_buffer = buffers_[current_buffer_].get();
- glReadPixels(0, 0, width_, height_, GL_BGRA, GL_UNSIGNED_BYTE,
- current_buffer);
- glPopClientAttrib();
+
+ if (pixel_buffer_object_.get() != 0) {
+ FastBlit(current_buffer);
+ } else {
+ SlowBlit(current_buffer);
+ }
DataPlanes planes;
- planes.data[0] = buffers_[current_buffer_].get() + height_ * bytes_per_row_;
+ planes.data[0] = current_buffer + height_ * bytes_per_row_;
planes.strides[0] = -bytes_per_row_;
scoped_refptr<CaptureData> data(
@@ -199,6 +254,44 @@ void CapturerMac::CaptureInvalidRects(CaptureCompletedCallback* callback) {
delete callback;
}
+void CapturerMac::FastBlit(uint8* buffer) {
+ CGLContextObj CGL_MACRO_CONTEXT = cgl_context_;
+ glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pixel_buffer_object_.get());
+ glReadPixels(0, 0, width_, height_, GL_BGRA, GL_UNSIGNED_BYTE, 0);
+ GLubyte* ptr = static_cast<GLubyte*>(
+ glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB));
+ if (ptr == NULL) {
+ // If the buffer can't be mapped, assume that it's no longer valid, release
+ // it and fall back on SlowBlit for this (and subsequent) captures.
+ pixel_buffer_object_.Release();
+ SlowBlit(buffer);
+ } else {
+ memcpy(buffer, ptr, height_ * bytes_per_row_);
+ }
+ if (!glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB)) {
+ // If glUnmapBuffer returns false, then the contents of the data store are
+ // undefined. This might be because the screen mode has changed, in which
+ // case it will be recreated in ScreenConfigurationChanged, but releasing
+ // the object here is the best option. Capturing will fall back on SlowBlit
+ // until such time as the pixel buffer object is recreated.
+ pixel_buffer_object_.Release();
+ }
+ glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
+}
+
+void CapturerMac::SlowBlit(uint8* buffer) {
+ CGLContextObj CGL_MACRO_CONTEXT = cgl_context_;
+ glReadBuffer(GL_FRONT);
+ glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
+ glPixelStorei(GL_PACK_ALIGNMENT, 4); // Force 4-byte alignment.
+ glPixelStorei(GL_PACK_ROW_LENGTH, 0);
+ glPixelStorei(GL_PACK_SKIP_ROWS, 0);
+ glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
+ // Read a block of pixels from the frame buffer.
+ glReadPixels(0, 0, width_, height_, GL_BGRA, GL_UNSIGNED_BYTE, buffer);
+ glPopClientAttrib();
+}
+
const gfx::Size& CapturerMac::size_most_recent() const {
return helper_.size_most_recent();
}