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_surface.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <OpenGL/CGLRenderers.h> 8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/basictypes.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/mac/mac_util.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_bindings.h" 15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ui/gl/gl_context.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_implementation.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_surface_osmesa.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_surface_stub.h" 19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ui/gl/gpu_switching_manager.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx { 22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace { 23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// A "no-op" surface. It is not required that a CGLContextObj have an 25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// associated drawable (pbuffer or fullscreen context) in order to be 26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// made current. Everywhere this surface type is used, we allocate an 27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// FBO at the user level as the drawable of the associated context. 28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class GL_EXPORT NoOpGLSurface : public GLSurface { 29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public: 30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) explicit NoOpGLSurface(const gfx::Size& size) : size_(size) {} 31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Implement GLSurface. 33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual bool Initialize() OVERRIDE { return true; } 34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual void Destroy() OVERRIDE {} 35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual bool IsOffscreen() OVERRIDE { return true; } 36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual bool SwapBuffers() OVERRIDE { 37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NOTREACHED() << "Cannot call SwapBuffers on a NoOpGLSurface."; 38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual gfx::Size GetSize() OVERRIDE { return size_; } 41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual void* GetHandle() OVERRIDE { return NULL; } 42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual void* GetDisplay() OVERRIDE { return NULL; } 43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) protected: 45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual ~NoOpGLSurface() {} 46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) private: 48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) gfx::Size size_; 49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(NoOpGLSurface); 51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// static 54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool InitializeOneOffForSandbox() { 55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) static bool initialized = false; 56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (initialized) 57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // This is called from the sandbox warmup code on Mac OS X. 60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // GPU-related stuff is very slow without this, probably because 61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // the sandbox prevents loading graphics drivers or some such. 62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<CGLPixelFormatAttribute> attribs; 63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) { 64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Avoid switching to the discrete GPU just for this pixel 65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // format selection. 66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) attribs.push_back(kCGLPFAAllowOfflineRenderers); 67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (GetGLImplementation() == kGLImplementationAppleGL) { 69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) attribs.push_back(kCGLPFARendererID); 70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) attribs.push_back(static_cast<CGLPixelFormatAttribute>( 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) kCGLRendererGenericFloatID)); 72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) attribs.push_back(static_cast<CGLPixelFormatAttribute>(0)); 74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CGLPixelFormatObj format; 76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GLint num_pixel_formats; 77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (CGLChoosePixelFormat(&attribs.front(), 78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &format, 79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &num_pixel_formats) != kCGLNoError) { 80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LOG(ERROR) << "Error choosing pixel format."; 81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!format) { 84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LOG(ERROR) << "format == 0."; 85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CGLReleasePixelFormat(format); 88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK_NE(num_pixel_formats, 0); 89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) initialized = true; 90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} // namespace 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurface::InitializeOneOffInternal() { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (GetGLImplementation()) { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kGLImplementationDesktopGL: 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kGLImplementationAppleGL: 99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!InitializeOneOffForSandbox()) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "GLSurfaceCGL::InitializeOneOff failed."; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface( 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::AcceleratedWidget window) { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRACE_EVENT0("gpu", "GLSurface::CreateViewGLSurface"); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (GetGLImplementation()) { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kGLImplementationDesktopGL: 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kGLImplementationAppleGL: { 116c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch NOTIMPLEMENTED() << "No onscreen support on Mac."; 117c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return NULL; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci case kGLImplementationOSMesaGL: { 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_refptr<GLSurface> surface(new GLSurfaceOSMesaHeadless()); 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!surface->Initialize()) 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return NULL; 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return surface; 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kGLImplementationMockGL: 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new GLSurfaceStub; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface( 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& size) { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRACE_EVENT0("gpu", "GLSurface::CreateOffscreenGLSurface"); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (GetGLImplementation()) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kGLImplementationOSMesaGL: { 13803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_refptr<GLSurface> surface( 13903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) new GLSurfaceOSMesa(OSMesaSurfaceFormatRGBA, size)); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!surface->Initialize()) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return surface; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kGLImplementationDesktopGL: 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kGLImplementationAppleGL: { 147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_refptr<GLSurface> surface(new NoOpGLSurface(size)); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!surface->Initialize()) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return surface; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kGLImplementationMockGL: 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new GLSurfaceStub; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace gfx 162