Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(255)

Side by Side Diff: remoting/host/video_frame_capturer_mac.mm

Issue 10917119: Dynamically link to deprecated APIs when running on OS 10.6 devices. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address review comments. Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "remoting/host/video_frame_capturer.h" 5 #include "remoting/host/video_frame_capturer.h"
6 6
7 #include <ApplicationServices/ApplicationServices.h> 7 #include <ApplicationServices/ApplicationServices.h>
8 #include <Cocoa/Cocoa.h> 8 #include <Cocoa/Cocoa.h>
9 #include <dlfcn.h> 9 #include <dlfcn.h>
10 #include <IOKit/pwr_mgt/IOPMLib.h> 10 #include <IOKit/pwr_mgt/IOPMLib.h>
11 #include <OpenGL/CGLMacro.h> 11 #include <OpenGL/CGLMacro.h>
12 #include <OpenGL/OpenGL.h> 12 #include <OpenGL/OpenGL.h>
13 #include <stddef.h> 13 #include <stddef.h>
14 14
15 #include "base/logging.h" 15 #include "base/logging.h"
16 #include "base/file_path.h"
16 #include "base/mac/mac_util.h" 17 #include "base/mac/mac_util.h"
17 #include "base/mac/scoped_cftyperef.h" 18 #include "base/mac/scoped_cftyperef.h"
18 #include "base/memory/scoped_ptr.h" 19 #include "base/memory/scoped_ptr.h"
20 #include "base/scoped_native_library.h"
19 #include "base/synchronization/waitable_event.h" 21 #include "base/synchronization/waitable_event.h"
20 #include "base/time.h" 22 #include "base/time.h"
21 #include "remoting/base/capture_data.h" 23 #include "remoting/base/capture_data.h"
22 #include "remoting/base/util.h" 24 #include "remoting/base/util.h"
23 #include "remoting/host/mac/scoped_pixel_buffer_object.h" 25 #include "remoting/host/mac/scoped_pixel_buffer_object.h"
24 #include "remoting/host/video_frame_capturer_helper.h" 26 #include "remoting/host/video_frame_capturer_helper.h"
25 #include "remoting/proto/control.pb.h" 27 #include "remoting/proto/control.pb.h"
26 28
27 namespace remoting { 29 namespace remoting {
28 30
29 namespace { 31 namespace {
30 32
33 // Definitions used to dynamic-link to deprecated OS 10.6 functions.
34 const char* kApplicationServicesLibraryName =
35 "/System/Library/Frameworks/ApplicationServices.framework/"
36 "ApplicationServices";
37 typedef void* (*CGDisplayBaseAddressFunc)(CGDirectDisplayID);
38 typedef size_t (*CGDisplayBytesPerRowFunc)(CGDirectDisplayID);
39 typedef size_t (*CGDisplayBitsPerPixelFunc)(CGDirectDisplayID);
40 const char* kOpenGlLibraryName =
41 "/System/Library/Frameworks/OpenGL.framework/OpenGL";
42 typedef CGLError (*CGLSetFullScreenFunc)(CGLContextObj);
43
31 // skia/ext/skia_utils_mac.h only defines CGRectToSkRect(). 44 // skia/ext/skia_utils_mac.h only defines CGRectToSkRect().
32 SkIRect CGRectToSkIRect(const CGRect& rect) { 45 SkIRect CGRectToSkIRect(const CGRect& rect) {
33 SkIRect sk_rect = { 46 SkIRect sk_rect = {
34 SkScalarRound(rect.origin.x), 47 SkScalarRound(rect.origin.x),
35 SkScalarRound(rect.origin.y), 48 SkScalarRound(rect.origin.y),
36 SkScalarRound(rect.origin.x + rect.size.width), 49 SkScalarRound(rect.origin.x + rect.size.width),
37 SkScalarRound(rect.origin.y + rect.size.height) 50 SkScalarRound(rect.origin.y + rect.size.height)
38 }; 51 };
39 return sk_rect; 52 return sk_rect;
40 } 53 }
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 // Acts as a critical section around our display configuration data 188 // Acts as a critical section around our display configuration data
176 // structures. Specifically cgl_context_ and pixel_buffer_object_. 189 // structures. Specifically cgl_context_ and pixel_buffer_object_.
177 base::WaitableEvent display_configuration_capture_event_; 190 base::WaitableEvent display_configuration_capture_event_;
178 191
179 // Power management assertion to prevent the screen from sleeping. 192 // Power management assertion to prevent the screen from sleeping.
180 IOPMAssertionID power_assertion_id_display_; 193 IOPMAssertionID power_assertion_id_display_;
181 194
182 // Power management assertion to indicate that the user is active. 195 // Power management assertion to indicate that the user is active.
183 IOPMAssertionID power_assertion_id_user_; 196 IOPMAssertionID power_assertion_id_user_;
184 197
198 // Dynamically link to deprecated APIs for Mac OS X 10.6 support.
199 base::ScopedNativeLibrary app_services_library_;
200 CGDisplayBaseAddressFunc cg_display_base_address_;
201 CGDisplayBytesPerRowFunc cg_display_bytes_per_row_;
202 CGDisplayBitsPerPixelFunc cg_display_bits_per_pixel_;
203 base::ScopedNativeLibrary opengl_library_;
204 CGLSetFullScreenFunc cgl_set_full_screen_;
205
185 DISALLOW_COPY_AND_ASSIGN(VideoFrameCapturerMac); 206 DISALLOW_COPY_AND_ASSIGN(VideoFrameCapturerMac);
186 }; 207 };
187 208
188 VideoFrameCapturerMac::VideoFrameCapturerMac() 209 VideoFrameCapturerMac::VideoFrameCapturerMac()
189 : cgl_context_(NULL), 210 : cgl_context_(NULL),
190 current_buffer_(0), 211 current_buffer_(0),
191 last_buffer_(NULL), 212 last_buffer_(NULL),
192 pixel_format_(media::VideoFrame::RGB32), 213 pixel_format_(media::VideoFrame::RGB32),
193 display_configuration_capture_event_(false, true), 214 display_configuration_capture_event_(false, true),
194 power_assertion_id_display_(kIOPMNullAssertionID), 215 power_assertion_id_display_(kIOPMNullAssertionID),
195 power_assertion_id_user_(kIOPMNullAssertionID) { 216 power_assertion_id_user_(kIOPMNullAssertionID),
217 cg_display_base_address_(NULL),
218 cg_display_bytes_per_row_(NULL),
219 cg_display_bits_per_pixel_(NULL),
220 cgl_set_full_screen_(NULL)
221 {
196 } 222 }
197 223
198 VideoFrameCapturerMac::~VideoFrameCapturerMac() { 224 VideoFrameCapturerMac::~VideoFrameCapturerMac() {
199 ReleaseBuffers(); 225 ReleaseBuffers();
200 CGUnregisterScreenRefreshCallback( 226 CGUnregisterScreenRefreshCallback(
201 VideoFrameCapturerMac::ScreenRefreshCallback, this); 227 VideoFrameCapturerMac::ScreenRefreshCallback, this);
202 CGScreenUnregisterMoveCallback( 228 CGScreenUnregisterMoveCallback(
203 VideoFrameCapturerMac::ScreenUpdateMoveCallback, this); 229 VideoFrameCapturerMac::ScreenUpdateMoveCallback, this);
204 CGError err = CGDisplayRemoveReconfigurationCallback( 230 CGError err = CGDisplayRemoveReconfigurationCallback(
205 VideoFrameCapturerMac::DisplaysReconfiguredCallback, this); 231 VideoFrameCapturerMac::DisplaysReconfiguredCallback, this);
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
512 const int buffer_height = buffer.size().height(); 538 const int buffer_height = buffer.size().height();
513 539
514 // Copy the entire contents of the previous capture buffer, to capture over. 540 // Copy the entire contents of the previous capture buffer, to capture over.
515 // TODO(wez): Get rid of this as per crbug.com/145064, or implement 541 // TODO(wez): Get rid of this as per crbug.com/145064, or implement
516 // crbug.com/92354. 542 // crbug.com/92354.
517 if (last_buffer_) 543 if (last_buffer_)
518 memcpy(buffer.ptr(), last_buffer_, buffer.bytes_per_row() * buffer_height); 544 memcpy(buffer.ptr(), last_buffer_, buffer.bytes_per_row() * buffer_height);
519 last_buffer_ = buffer.ptr(); 545 last_buffer_ = buffer.ptr();
520 546
521 for (unsigned int d = 0; d < display_ids_.size(); ++d) { 547 for (unsigned int d = 0; d < display_ids_.size(); ++d) {
522 #pragma clang diagnostic push 548 // Use deprecated APIs to determine the display buffer layout.
523 #pragma clang diagnostic ignored "-Wdeprecated-declarations" 549 DCHECK(cg_display_base_address_ && cg_display_bytes_per_row_ &&
550 cg_display_bits_per_pixel_);
524 uint8* display_base_address = 551 uint8* display_base_address =
525 reinterpret_cast<uint8*>(CGDisplayBaseAddress(display_ids_[d])); 552 reinterpret_cast<uint8*>((*cg_display_base_address_)(display_ids_[d]));
526 CHECK(display_base_address); 553 CHECK(display_base_address);
527 int src_bytes_per_row = CGDisplayBytesPerRow(display_ids_[d]); 554 int src_bytes_per_row = (*cg_display_bytes_per_row_)(display_ids_[d]);
528 int src_bytes_per_pixel = CGDisplayBitsPerPixel(display_ids_[d]) / 8; 555 int src_bytes_per_pixel =
529 #pragma clang diagnostic pop 556 (*cg_display_bits_per_pixel_)(display_ids_[d]) / 8;
557
530 // Determine the position of the display in the buffer. 558 // Determine the position of the display in the buffer.
531 SkIRect display_bounds = CGRectToSkIRect(CGDisplayBounds(display_ids_[d])); 559 SkIRect display_bounds = CGRectToSkIRect(CGDisplayBounds(display_ids_[d]));
532 display_bounds.offset(-desktop_bounds_.left(), -desktop_bounds_.top()); 560 display_bounds.offset(-desktop_bounds_.left(), -desktop_bounds_.top());
533 561
534 // Determine which parts of the blit region, if any, lay within the monitor. 562 // Determine which parts of the blit region, if any, lay within the monitor.
535 SkRegion copy_region; 563 SkRegion copy_region;
536 if (!copy_region.op(region, display_bounds, SkRegion::kIntersect_Op)) 564 if (!copy_region.op(region, display_bounds, SkRegion::kIntersect_Op))
537 continue; 565 continue;
538 566
539 // Translate the region to be copied into display-relative coordinates. 567 // Translate the region to be copied into display-relative coordinates.
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
640 desktop_bounds_ = SkIRect::MakeEmpty(); 668 desktop_bounds_ = SkIRect::MakeEmpty();
641 for (unsigned int d = 0; d < display_count; ++d) { 669 for (unsigned int d = 0; d < display_count; ++d) {
642 CGRect display_bounds = CGDisplayBounds(display_ids_[d]); 670 CGRect display_bounds = CGDisplayBounds(display_ids_[d]);
643 desktop_bounds_.join(CGRectToSkIRect(display_bounds)); 671 desktop_bounds_.join(CGRectToSkIRect(display_bounds));
644 } 672 }
645 673
646 // Re-mark the entire desktop as dirty. 674 // Re-mark the entire desktop as dirty.
647 helper_.InvalidateScreen(SkISize::Make(desktop_bounds_.width(), 675 helper_.InvalidateScreen(SkISize::Make(desktop_bounds_.width(),
648 desktop_bounds_.height())); 676 desktop_bounds_.height()));
649 677
678 // CgBlitPostLion uses CGDisplayCreateImage() to snapshot each display's
679 // contents. Although the API exists in OS 10.6, it crashes the caller if
680 // the machine has no monitor connected, so we fall back to depcreated APIs
681 // when running on 10.6.
650 if (base::mac::IsOSLionOrLater()) { 682 if (base::mac::IsOSLionOrLater()) {
651 LOG(INFO) << "Using CgBlitPostLion."; 683 LOG(INFO) << "Using CgBlitPostLion.";
652 // No need for any OpenGL support on Lion 684 // No need for any OpenGL support on Lion
653 return; 685 return;
654 } 686 }
655 687
688 // Dynamically link to the deprecated pre-Lion capture APIs.
689 std::string app_services_library_error;
690 FilePath app_services_path(kApplicationServicesLibraryName);
691 app_services_library_.Reset(
692 base::LoadNativeLibrary(app_services_path, &app_services_library_error));
693 CHECK(app_services_library_.is_valid()) << app_services_library_error;
694
695 std::string opengl_library_error;
696 FilePath opengl_path(kOpenGlLibraryName);
697 opengl_library_.Reset(
698 base::LoadNativeLibrary(opengl_path, &opengl_library_error));
699 CHECK(opengl_library_.is_valid()) << opengl_library_error;
700
701 cg_display_base_address_ = reinterpret_cast<CGDisplayBaseAddressFunc>(
702 app_services_library_.GetFunctionPointer("CGDisplayBaseAddress"));
703 cg_display_bytes_per_row_ = reinterpret_cast<CGDisplayBytesPerRowFunc>(
704 app_services_library_.GetFunctionPointer("CGDisplayBytesPerRow"));
705 cg_display_bits_per_pixel_ = reinterpret_cast<CGDisplayBitsPerPixelFunc>(
706 app_services_library_.GetFunctionPointer("CGDisplayBitsPerPixel"));
707 cgl_set_full_screen_ = reinterpret_cast<CGLSetFullScreenFunc>(
708 opengl_library_.GetFunctionPointer("CGLSetFullScreen"));
709 CHECK(cg_display_base_address_ && cg_display_bytes_per_row_ &&
710 cg_display_bits_per_pixel_ && cgl_set_full_screen_);
711
656 if (display_ids_.size() > 1) { 712 if (display_ids_.size() > 1) {
657 LOG(INFO) << "Using CgBlitPreLion (Multi-monitor)."; 713 LOG(INFO) << "Using CgBlitPreLion (Multi-monitor).";
658 return; 714 return;
659 } 715 }
660 716
661 CGDirectDisplayID mainDevice = CGMainDisplayID(); 717 CGDirectDisplayID mainDevice = CGMainDisplayID();
662 if (!CGDisplayUsesOpenGLAcceleration(mainDevice)) { 718 if (!CGDisplayUsesOpenGLAcceleration(mainDevice)) {
663 LOG(INFO) << "Using CgBlitPreLion (OpenGL unavailable)."; 719 LOG(INFO) << "Using CgBlitPreLion (OpenGL unavailable).";
664 return; 720 return;
665 } 721 }
666 722
667 LOG(INFO) << "Using GlBlit"; 723 LOG(INFO) << "Using GlBlit";
668 724
669 CGLPixelFormatAttribute attributes[] = { 725 CGLPixelFormatAttribute attributes[] = {
670 kCGLPFAFullScreen, 726 kCGLPFAFullScreen,
671 kCGLPFADisplayMask, 727 kCGLPFADisplayMask,
672 (CGLPixelFormatAttribute)CGDisplayIDToOpenGLDisplayMask(mainDevice), 728 (CGLPixelFormatAttribute)CGDisplayIDToOpenGLDisplayMask(mainDevice),
673 (CGLPixelFormatAttribute)0 729 (CGLPixelFormatAttribute)0
674 }; 730 };
675 CGLPixelFormatObj pixel_format = NULL; 731 CGLPixelFormatObj pixel_format = NULL;
676 GLint matching_pixel_format_count = 0; 732 GLint matching_pixel_format_count = 0;
677 CGLError err = CGLChoosePixelFormat(attributes, 733 CGLError err = CGLChoosePixelFormat(attributes,
678 &pixel_format, 734 &pixel_format,
679 &matching_pixel_format_count); 735 &matching_pixel_format_count);
680 DCHECK_EQ(err, kCGLNoError); 736 DCHECK_EQ(err, kCGLNoError);
681 err = CGLCreateContext(pixel_format, NULL, &cgl_context_); 737 err = CGLCreateContext(pixel_format, NULL, &cgl_context_);
682 DCHECK_EQ(err, kCGLNoError); 738 DCHECK_EQ(err, kCGLNoError);
683 CGLDestroyPixelFormat(pixel_format); 739 CGLDestroyPixelFormat(pixel_format);
684 #pragma clang diagnostic push 740 (*cgl_set_full_screen_)(cgl_context_);
685 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
686 // TODO(jamiewalch): The non-deprecated equivalent code is shown below, but
687 // it causes 10.6 Macs' displays to go black. Find out why.
688 //
689 // CGLSetFullScreenOnDisplay(cgl_context_,
690 // CGDisplayIDToOpenGLDisplayMask(mainDevice));
691 CGLSetFullScreen(cgl_context_);
692 #pragma clang diagnostic pop
693 CGLSetCurrentContext(cgl_context_); 741 CGLSetCurrentContext(cgl_context_);
694 742
695 size_t buffer_size = desktop_bounds_.width() * desktop_bounds_.height() * 743 size_t buffer_size = desktop_bounds_.width() * desktop_bounds_.height() *
696 sizeof(uint32_t); 744 sizeof(uint32_t);
697 pixel_buffer_object_.Init(cgl_context_, buffer_size); 745 pixel_buffer_object_.Init(cgl_context_, buffer_size);
698 } 746 }
699 747
700 void VideoFrameCapturerMac::ScreenRefresh(CGRectCount count, 748 void VideoFrameCapturerMac::ScreenRefresh(CGRectCount count,
701 const CGRect* rect_array) { 749 const CGRect* rect_array) {
702 SkIRect skirect_array[count]; 750 SkIRect skirect_array[count];
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
776 VideoFrameCapturer* VideoFrameCapturer::Create() { 824 VideoFrameCapturer* VideoFrameCapturer::Create() {
777 VideoFrameCapturerMac* capturer = new VideoFrameCapturerMac(); 825 VideoFrameCapturerMac* capturer = new VideoFrameCapturerMac();
778 if (!capturer->Init()) { 826 if (!capturer->Init()) {
779 delete capturer; 827 delete capturer;
780 capturer = NULL; 828 capturer = NULL;
781 } 829 }
782 return capturer; 830 return capturer;
783 } 831 }
784 832
785 } // namespace remoting 833 } // namespace remoting
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698