15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_context_cgl.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <OpenGL/CGLRenderers.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <OpenGL/CGLTypes.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/memory/scoped_ptr.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_bindings.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_implementation.h" 16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ui/gl/gl_surface.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gpu_switching_manager.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace { 2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool g_support_renderer_switching; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)struct CGLRendererInfoObjDeleter { 2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void operator()(CGLRendererInfoObj* x) { 2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (x) 2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CGLDestroyRendererInfo(*x); 2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}; 3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace 3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static CGLPixelFormatObj GetPixelFormat() { 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static CGLPixelFormatObj format; 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (format) 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return format; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<CGLPixelFormatAttribute> attribs; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the system supports dual gpus then allow offline renderers for every 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // context, so that they can all be in the same share group. 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attribs.push_back(kCGLPFAAllowOfflineRenderers); 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) g_support_renderer_switching = true; 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetGLImplementation() == kGLImplementationAppleGL) { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attribs.push_back(kCGLPFARendererID); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attribs.push_back((CGLPixelFormatAttribute) kCGLRendererGenericFloatID); 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) g_support_renderer_switching = false; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attribs.push_back((CGLPixelFormatAttribute) 0); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GLint num_virtual_screens; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CGLChoosePixelFormat(&attribs.front(), 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &format, 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &num_virtual_screens) != kCGLNoError) { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Error choosing pixel format."; 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!format) { 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "format == 0."; 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_NE(num_virtual_screens, 0); 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return format; 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)GLContextCGL::GLContextCGL(GLShareGroup* share_group) 68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) : GLContextReal(share_group), 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) context_(NULL), 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gpu_preference_(PreferIntegratedGpu), 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) discrete_pixelformat_(NULL), 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) screen_(-1), 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) renderer_id_(-1), 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) safe_to_force_gpu_switch_(false) { 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GLContextCGL::Initialize(GLSurface* compatible_surface, 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GpuPreference gpu_preference) { 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(compatible_surface); 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gpu_preference = ui::GpuSwitchingManager::GetInstance()->AdjustGpuPreference( 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gpu_preference); 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GLContextCGL* share_context = share_group() ? 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<GLContextCGL*>(share_group()->GetContext()) : NULL; 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CGLPixelFormatObj format = GetPixelFormat(); 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!format) 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If using the discrete gpu, create a pixel format requiring it before we 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // create the context. 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus() || 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gpu_preference == PreferDiscreteGpu) { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<CGLPixelFormatAttribute> discrete_attribs; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) discrete_attribs.push_back((CGLPixelFormatAttribute) 0); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLint num_pixel_formats; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CGLChoosePixelFormat(&discrete_attribs.front(), 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &discrete_pixelformat_, 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &num_pixel_formats) != kCGLNoError) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Error choosing pixel format."; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The renderer might be switched after this, so ignore the saved ID. 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) share_group()->SetRendererID(-1); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CGLError res = CGLCreateContext( 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) format, 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) share_context ? 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<CGLContextObj>(share_context->GetHandle()) : NULL, 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<CGLContextObj*>(&context_)); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (res != kCGLNoError) { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Error creating context."; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Destroy(); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gpu_preference_ = gpu_preference; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GLContextCGL::Destroy() { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (discrete_pixelformat_) { 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Delay releasing the pixel format for 10 seconds to reduce the number of 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // unnecessary GPU switches. 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FROM_HERE, 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&CGLReleasePixelFormat, discrete_pixelformat_), 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::TimeDelta::FromSeconds(10)); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) discrete_pixelformat_ = NULL; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (context_) { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CGLDestroyContext(static_cast<CGLContextObj>(context_)); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_ = NULL; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLContextCGL::MakeCurrent(GLSurface* surface) { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(context_); 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // The call to CGLSetVirtualScreen can hang on some AMD drivers 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // http://crbug.com/227228 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (safe_to_force_gpu_switch_) { 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int renderer_id = share_group()->GetRendererID(); 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int screen; 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CGLGetVirtualScreen(static_cast<CGLContextObj>(context_), &screen); 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (g_support_renderer_switching && 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !discrete_pixelformat_ && renderer_id != -1 && 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (screen != screen_ || renderer_id != renderer_id_)) { 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Attempt to find a virtual screen that's using the requested renderer, 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // and switch the context to use that screen. Don't attempt to switch if 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // the context requires the discrete GPU. 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CGLPixelFormatObj format = GetPixelFormat(); 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int virtual_screen_count; 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (CGLDescribePixelFormat(format, 0, kCGLPFAVirtualScreenCount, 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &virtual_screen_count) != kCGLNoError) 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (int i = 0; i < virtual_screen_count; ++i) { 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int screen_renderer_id; 163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (CGLDescribePixelFormat(format, i, kCGLPFARendererID, 164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &screen_renderer_id) != kCGLNoError) 165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) screen_renderer_id &= kCGLRendererIDMatchingMask; 168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (screen_renderer_id == renderer_id) { 169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CGLSetVirtualScreen(static_cast<CGLContextObj>(context_), i); 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) screen_ = i; 171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) renderer_id_ = renderer_id; 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsCurrent(surface)) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 181e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch ScopedReleaseCurrent release_current; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRACE_EVENT0("gpu", "GLContextCGL::MakeCurrent"); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CGLSetCurrentContext( 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<CGLContextObj>(context_)) != kCGLNoError) { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Unable to make gl context current."; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Set this as soon as the context is current, since we might call into GL. 1917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) SetRealGLApi(); 1927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SetCurrent(surface); 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!InitializeDynamicBindings()) { 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!surface->OnMakeCurrent(this)) { 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Unable to make gl context current."; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 203e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch release_current.Cancel(); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GLContextCGL::ReleaseCurrent(GLSurface* surface) { 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsCurrent(surface)) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SetCurrent(NULL); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CGLSetCurrentContext(NULL); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLContextCGL::IsCurrent(GLSurface* surface) { 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool native_context_is_current = CGLGetCurrentContext() == context_; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If our context is current then our notion of which GLContext is 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // current must be correct. On the other hand, third-party code 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // using OpenGL might change the current context. 221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(!native_context_is_current || (GetRealCurrent() == this)); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!native_context_is_current) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* GLContextCGL::GetHandle() { 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return context_; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GLContextCGL::SetSwapInterval(int interval) { 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(IsCurrent(NULL)); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "GLContex: GLContextCGL::SetSwapInterval is ignored."; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLContextCGL::GetTotalGpuMemory(size_t* bytes) { 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(bytes); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *bytes = 0; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CGLContextObj context = reinterpret_cast<CGLContextObj>(context_); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!context) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Retrieve the current renderer ID 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLint current_renderer_id = 0; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CGLGetParameter(context, 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kCGLCPCurrentRendererID, 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ¤t_renderer_id) != kCGLNoError) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Iterate through the list of all renderers 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLuint display_mask = static_cast<GLuint>(-1); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CGLRendererInfoObj renderer_info = NULL; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLint num_renderers = 0; 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CGLQueryRendererInfo(display_mask, 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &renderer_info, 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &num_renderers) != kCGLNoError) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<CGLRendererInfoObj, 26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CGLRendererInfoObjDeleter> scoper(&renderer_info); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (GLint renderer_index = 0; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) renderer_index < num_renderers; 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++renderer_index) { 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Skip this if this renderer is not the current renderer. 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLint renderer_id = 0; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CGLDescribeRenderer(renderer_info, 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) renderer_index, 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kCGLRPRendererID, 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &renderer_id) != kCGLNoError) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (renderer_id != current_renderer_id) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Retrieve the video memory for the renderer. 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLint video_memory = 0; 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CGLDescribeRenderer(renderer_info, 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) renderer_index, 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kCGLRPVideoMemory, 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &video_memory) != kCGLNoError) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *bytes = video_memory; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void GLContextCGL::SetSafeToForceGpuSwitch() { 293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) safe_to_force_gpu_switch_ = true; 294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLContextCGL::~GLContextCGL() { 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Destroy(); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuPreference GLContextCGL::GetGpuPreference() { 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return gpu_preference_; 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace gfx 306