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 21 namespace gfx { 22 namespace { 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. 28 class 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 54 bool 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 95 bool 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 110 scoped_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 133 scoped_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