gl_surface_mac.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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 3// found in the LICENSE file. 4 5#include "ui/gl/gl_surface.h" 6 7#include <OpenGL/CGLRenderers.h> 8 9#include "base/basictypes.h" 10#include "base/debug/trace_event.h" 11#include "base/logging.h" 12#include "base/mac/mac_util.h" 13#include "base/memory/scoped_ptr.h" 14#include "ui/gl/gl_bindings.h" 15#include "ui/gl/gl_context.h" 16#include "ui/gl/gl_implementation.h" 17#include "ui/gl/gl_surface_osmesa.h" 18#include "ui/gl/gl_surface_stub.h" 19#include "ui/gl/gpu_switching_manager.h" 20 21namespace gfx { 22namespace { 23 24// A "no-op" surface. It is not required that a CGLContextObj have an 25// associated drawable (pbuffer or fullscreen context) in order to be 26// made current. Everywhere this surface type is used, we allocate an 27// FBO at the user level as the drawable of the associated context. 28class GL_EXPORT NoOpGLSurface : public GLSurface { 29 public: 30 explicit NoOpGLSurface(const gfx::Size& size) : size_(size) {} 31 32 // Implement GLSurface. 33 virtual bool Initialize() OVERRIDE { return true; } 34 virtual void Destroy() OVERRIDE {} 35 virtual bool IsOffscreen() OVERRIDE { return true; } 36 virtual bool SwapBuffers() OVERRIDE { 37 NOTREACHED() << "Cannot call SwapBuffers on a NoOpGLSurface."; 38 return false; 39 } 40 virtual gfx::Size GetSize() OVERRIDE { return size_; } 41 virtual void* GetHandle() OVERRIDE { return NULL; } 42 virtual void* GetDisplay() OVERRIDE { return NULL; } 43 44 protected: 45 virtual ~NoOpGLSurface() {} 46 47 private: 48 gfx::Size size_; 49 50 DISALLOW_COPY_AND_ASSIGN(NoOpGLSurface); 51}; 52 53// static 54bool InitializeOneOffForSandbox() { 55 static bool initialized = false; 56 if (initialized) 57 return true; 58 59 // This is called from the sandbox warmup code on Mac OS X. 60 // GPU-related stuff is very slow without this, probably because 61 // the sandbox prevents loading graphics drivers or some such. 62 std::vector<CGLPixelFormatAttribute> attribs; 63 if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) { 64 // Avoid switching to the discrete GPU just for this pixel 65 // format selection. 66 attribs.push_back(kCGLPFAAllowOfflineRenderers); 67 } 68 if (GetGLImplementation() == kGLImplementationAppleGL) { 69 attribs.push_back(kCGLPFARendererID); 70 attribs.push_back(static_cast<CGLPixelFormatAttribute>( 71 kCGLRendererGenericFloatID)); 72 } 73 attribs.push_back(static_cast<CGLPixelFormatAttribute>(0)); 74 75 CGLPixelFormatObj format; 76 GLint num_pixel_formats; 77 if (CGLChoosePixelFormat(&attribs.front(), 78 &format, 79 &num_pixel_formats) != kCGLNoError) { 80 LOG(ERROR) << "Error choosing pixel format."; 81 return false; 82 } 83 if (!format) { 84 LOG(ERROR) << "format == 0."; 85 return false; 86 } 87 CGLReleasePixelFormat(format); 88 DCHECK_NE(num_pixel_formats, 0); 89 initialized = true; 90 return true; 91} 92 93} // namespace 94 95bool GLSurface::InitializeOneOffInternal() { 96 switch (GetGLImplementation()) { 97 case kGLImplementationDesktopGL: 98 case kGLImplementationAppleGL: 99 if (!InitializeOneOffForSandbox()) { 100 LOG(ERROR) << "GLSurfaceCGL::InitializeOneOff failed."; 101 return false; 102 } 103 break; 104 default: 105 break; 106 } 107 return true; 108} 109 110scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface( 111 gfx::AcceleratedWidget window) { 112 TRACE_EVENT0("gpu", "GLSurface::CreateViewGLSurface"); 113 switch (GetGLImplementation()) { 114 case kGLImplementationDesktopGL: 115 case kGLImplementationAppleGL: { 116 NOTIMPLEMENTED() << "No onscreen support on Mac."; 117 return NULL; 118 } 119 case kGLImplementationOSMesaGL: { 120 scoped_refptr<GLSurface> surface(new GLSurfaceOSMesaHeadless()); 121 if (!surface->Initialize()) 122 return NULL; 123 return surface; 124 } 125 case kGLImplementationMockGL: 126 return new GLSurfaceStub; 127 default: 128 NOTREACHED(); 129 return NULL; 130 } 131} 132 133scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface( 134 const gfx::Size& size) { 135 TRACE_EVENT0("gpu", "GLSurface::CreateOffscreenGLSurface"); 136 switch (GetGLImplementation()) { 137 case kGLImplementationOSMesaGL: { 138 scoped_refptr<GLSurface> surface( 139 new GLSurfaceOSMesa(OSMesaSurfaceFormatRGBA, size)); 140 if (!surface->Initialize()) 141 return NULL; 142 143 return surface; 144 } 145 case kGLImplementationDesktopGL: 146 case kGLImplementationAppleGL: { 147 scoped_refptr<GLSurface> surface(new NoOpGLSurface(size)); 148 if (!surface->Initialize()) 149 return NULL; 150 151 return surface; 152 } 153 case kGLImplementationMockGL: 154 return new GLSurfaceStub; 155 default: 156 NOTREACHED(); 157 return NULL; 158 } 159} 160 161} // namespace gfx 162