diff options
Diffstat (limited to 'chromium/content/browser/renderer_host/compositing_iosurface_context_mac.mm')
-rw-r--r-- | chromium/content/browser/renderer_host/compositing_iosurface_context_mac.mm | 138 |
1 files changed, 70 insertions, 68 deletions
diff --git a/chromium/content/browser/renderer_host/compositing_iosurface_context_mac.mm b/chromium/content/browser/renderer_host/compositing_iosurface_context_mac.mm index 4c6cbf1c12a..a66bf5022d3 100644 --- a/chromium/content/browser/renderer_host/compositing_iosurface_context_mac.mm +++ b/chromium/content/browser/renderer_host/compositing_iosurface_context_mac.mm @@ -12,6 +12,8 @@ #include "base/debug/trace_event.h" #include "base/logging.h" #include "content/browser/renderer_host/compositing_iosurface_shader_programs_mac.h" +#include "content/browser/gpu/gpu_data_manager_impl.h" +#include "ui/base/ui_base_switches.h" #include "ui/gl/gl_switches.h" #include "ui/gl/gpu_switching_manager.h" @@ -25,65 +27,68 @@ CompositingIOSurfaceContext::Get(int window_number) { // Return the context for this window_number, if it exists. WindowMap::iterator found = window_map()->find(window_number); if (found != window_map()->end()) { - DCHECK(found->second->can_be_shared_); + DCHECK(!found->second->poisoned_); return found->second; } - std::vector<NSOpenGLPixelFormatAttribute> attributes; - attributes.push_back(NSOpenGLPFADoubleBuffer); - // We don't need a depth buffer - try setting its size to 0... - attributes.push_back(NSOpenGLPFADepthSize); attributes.push_back(0); - if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) - attributes.push_back(NSOpenGLPFAAllowOfflineRenderers); - attributes.push_back(0); - - base::scoped_nsobject<NSOpenGLPixelFormat> glPixelFormat( - [[NSOpenGLPixelFormat alloc] initWithAttributes:&attributes.front()]); - if (!glPixelFormat) { - LOG(ERROR) << "NSOpenGLPixelFormat initWithAttributes failed"; + static bool is_vsync_disabled = + CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync); + + base::ScopedTypeRef<CGLContextObj> cgl_context_strong; + CGLContextObj cgl_context = NULL; + CGLError error = kCGLNoError; + + // Create the pixel format object for the context. + std::vector<CGLPixelFormatAttribute> attribs; + attribs.push_back(kCGLPFADepthSize); + attribs.push_back(static_cast<CGLPixelFormatAttribute>(0)); + if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) { + attribs.push_back(kCGLPFAAllowOfflineRenderers); + attribs.push_back(static_cast<CGLPixelFormatAttribute>(1)); + } + attribs.push_back(static_cast<CGLPixelFormatAttribute>(0)); + GLint number_virtual_screens = 0; + base::ScopedTypeRef<CGLPixelFormatObj> pixel_format; + error = CGLChoosePixelFormat(&attribs.front(), + pixel_format.InitializeInto(), + &number_virtual_screens); + if (error != kCGLNoError) { + LOG(ERROR) << "Failed to create pixel format object."; return NULL; } // Create all contexts in the same share group so that the textures don't // need to be recreated when transitioning contexts. - NSOpenGLContext* share_context = nil; + CGLContextObj share_context = NULL; if (!window_map()->empty()) - share_context = window_map()->begin()->second->nsgl_context(); - base::scoped_nsobject<NSOpenGLContext> nsgl_context( - [[NSOpenGLContext alloc] initWithFormat:glPixelFormat - shareContext:share_context]); - if (!nsgl_context) { - LOG(ERROR) << "NSOpenGLContext initWithFormat failed"; + share_context = window_map()->begin()->second->cgl_context(); + error = CGLCreateContext( + pixel_format, share_context, cgl_context_strong.InitializeInto()); + if (error != kCGLNoError) { + LOG(ERROR) << "Failed to create context object."; return NULL; } + cgl_context = cgl_context_strong; - CGLContextObj cgl_context = (CGLContextObj)[nsgl_context CGLContextObj]; - if (!cgl_context) { - LOG(ERROR) << "CGLContextObj failed"; - return NULL; - } - - // Draw at beam vsync. - bool is_vsync_disabled = - CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync); - GLint swapInterval = is_vsync_disabled ? 0 : 1; - [nsgl_context setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval]; + // Note that VSync is ignored because CoreAnimation will automatically + // rate limit draws. // Prepare the shader program cache. Precompile the shader programs // needed to draw the IO Surface for non-offscreen contexts. - CGLSetCurrentContext(cgl_context); - scoped_ptr<CompositingIOSurfaceShaderPrograms> shader_program_cache( - new CompositingIOSurfaceShaderPrograms()); bool prepared = false; - if (window_number == kOffscreenContextWindowNumber) { - prepared = true; - } else { - prepared = ( - shader_program_cache->UseBlitProgram() && - shader_program_cache->UseSolidWhiteProgram()); + scoped_ptr<CompositingIOSurfaceShaderPrograms> shader_program_cache; + { + gfx::ScopedCGLSetCurrentContext scoped_set_current_context(cgl_context); + shader_program_cache.reset(new CompositingIOSurfaceShaderPrograms()); + if (window_number == kOffscreenContextWindowNumber) { + prepared = true; + } else { + prepared = ( + shader_program_cache->UseBlitProgram() && + shader_program_cache->UseSolidWhiteProgram()); + } + glUseProgram(0u); } - glUseProgram(0u); - CGLSetCurrentContext(0); if (!prepared) { LOG(ERROR) << "IOSurface failed to compile/link required shader programs."; return NULL; @@ -91,46 +96,50 @@ CompositingIOSurfaceContext::Get(int window_number) { return new CompositingIOSurfaceContext( window_number, - nsgl_context.release(), + cgl_context_strong, cgl_context, is_vsync_disabled, shader_program_cache.Pass()); } -// static -void CompositingIOSurfaceContext::MarkExistingContextsAsNotShareable() { +void CompositingIOSurfaceContext::PoisonContextAndSharegroup() { + if (poisoned_) + return; + for (WindowMap::iterator it = window_map()->begin(); it != window_map()->end(); ++it) { - it->second->can_be_shared_ = false; + it->second->poisoned_ = true; } window_map()->clear(); } CompositingIOSurfaceContext::CompositingIOSurfaceContext( int window_number, - NSOpenGLContext* nsgl_context, + base::ScopedTypeRef<CGLContextObj> cgl_context_strong, CGLContextObj cgl_context, bool is_vsync_disabled, scoped_ptr<CompositingIOSurfaceShaderPrograms> shader_program_cache) : window_number_(window_number), - nsgl_context_(nsgl_context), + cgl_context_strong_(cgl_context_strong), cgl_context_(cgl_context), is_vsync_disabled_(is_vsync_disabled), shader_program_cache_(shader_program_cache.Pass()), - can_be_shared_(true), - initialized_is_intel_(false), - is_intel_(false), - screen_(0) { + poisoned_(false) { DCHECK(window_map()->find(window_number_) == window_map()->end()); window_map()->insert(std::make_pair(window_number_, this)); + + GpuDataManager::GetInstance()->AddObserver(this); } CompositingIOSurfaceContext::~CompositingIOSurfaceContext() { - CGLSetCurrentContext(cgl_context_); - shader_program_cache_->Reset(); - CGLSetCurrentContext(0); - if (can_be_shared_) { + GpuDataManager::GetInstance()->RemoveObserver(this); + + { + gfx::ScopedCGLSetCurrentContext scoped_set_current_context(cgl_context_); + shader_program_cache_->Reset(); + } + if (!poisoned_) { DCHECK(window_map()->find(window_number_) != window_map()->end()); DCHECK(window_map()->find(window_number_)->second == this); window_map()->erase(window_number_); @@ -141,18 +150,11 @@ CompositingIOSurfaceContext::~CompositingIOSurfaceContext() { } } -bool CompositingIOSurfaceContext::IsVendorIntel() { - GLint screen; - CGLGetVirtualScreen(cgl_context(), &screen); - if (screen != screen_) - initialized_is_intel_ = false; - screen_ = screen; - if (!initialized_is_intel_) { - is_intel_ = strstr(reinterpret_cast<const char*>(glGetString(GL_VENDOR)), - "Intel") != NULL; - initialized_is_intel_ = true; - } - return is_intel_; +void CompositingIOSurfaceContext::OnGpuSwitching() { + // Recreate all browser-side GL contexts whenever the GPU switches. If this + // is not done, performance will suffer. + // http://crbug.com/361493 + PoisonContextAndSharegroup(); } // static |