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