Index: ui/gl/gl_surface_mac.cc |
diff --git a/ui/gl/gl_surface_mac.cc b/ui/gl/gl_surface_mac.cc |
index cd93cb00a3bcaba7771ea1fbe7fedd786db65262..dd5fa0ed8e4bba6e2e92410abaa937983caa188f 100644 |
--- a/ui/gl/gl_surface_mac.cc |
+++ b/ui/gl/gl_surface_mac.cc |
@@ -4,23 +4,100 @@ |
#include "ui/gl/gl_surface.h" |
+#include <OpenGL/CGLRenderers.h> |
+ |
+#include "base/basictypes.h" |
#include "base/debug/trace_event.h" |
#include "base/logging.h" |
+#include "base/mac/mac_util.h" |
#include "base/memory/scoped_ptr.h" |
#include "third_party/mesa/src/include/GL/osmesa.h" |
#include "ui/gl/gl_bindings.h" |
+#include "ui/gl/gl_context.h" |
#include "ui/gl/gl_implementation.h" |
-#include "ui/gl/gl_surface_cgl.h" |
#include "ui/gl/gl_surface_osmesa.h" |
#include "ui/gl/gl_surface_stub.h" |
+#include "ui/gl/gpu_switching_manager.h" |
namespace gfx { |
+namespace { |
+ |
+// A "no-op" surface. It is not required that a CGLContextObj have an |
+// associated drawable (pbuffer or fullscreen context) in order to be |
+// made current. Everywhere this surface type is used, we allocate an |
+// FBO at the user level as the drawable of the associated context. |
+class GL_EXPORT NoOpGLSurface : public GLSurface { |
+ public: |
+ explicit NoOpGLSurface(const gfx::Size& size) : size_(size) {} |
+ |
+ // Implement GLSurface. |
+ virtual bool Initialize() OVERRIDE { return true; } |
+ virtual void Destroy() OVERRIDE {} |
+ virtual bool IsOffscreen() OVERRIDE { return true; } |
+ virtual bool SwapBuffers() OVERRIDE { |
+ NOTREACHED() << "Cannot call SwapBuffers on a NoOpGLSurface."; |
+ return false; |
+ } |
+ virtual gfx::Size GetSize() OVERRIDE { return size_; } |
+ virtual void* GetHandle() OVERRIDE { return NULL; } |
+ virtual void* GetDisplay() OVERRIDE { return NULL; } |
+ |
+ protected: |
+ virtual ~NoOpGLSurface() {} |
+ |
+ private: |
+ gfx::Size size_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(NoOpGLSurface); |
+}; |
+ |
+// static |
+bool InitializeOneOffForSandbox() { |
+ static bool initialized = false; |
+ if (initialized) |
+ return true; |
+ |
+ // This is called from the sandbox warmup code on Mac OS X. |
+ // GPU-related stuff is very slow without this, probably because |
+ // the sandbox prevents loading graphics drivers or some such. |
+ std::vector<CGLPixelFormatAttribute> attribs; |
+ if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) { |
+ // Avoid switching to the discrete GPU just for this pixel |
+ // format selection. |
+ attribs.push_back(kCGLPFAAllowOfflineRenderers); |
+ } |
+ if (GetGLImplementation() == kGLImplementationAppleGL) { |
+ attribs.push_back(kCGLPFARendererID); |
+ attribs.push_back(static_cast<CGLPixelFormatAttribute>( |
+ kCGLRendererGenericFloatID)); |
+ } |
+ attribs.push_back(static_cast<CGLPixelFormatAttribute>(0)); |
+ |
+ CGLPixelFormatObj format; |
+ GLint num_pixel_formats; |
+ if (CGLChoosePixelFormat(&attribs.front(), |
+ &format, |
+ &num_pixel_formats) != kCGLNoError) { |
+ LOG(ERROR) << "Error choosing pixel format."; |
+ return false; |
+ } |
+ if (!format) { |
+ LOG(ERROR) << "format == 0."; |
+ return false; |
+ } |
+ CGLReleasePixelFormat(format); |
+ DCHECK_NE(num_pixel_formats, 0); |
+ initialized = true; |
+ return true; |
+} |
+ |
+} // namespace |
bool GLSurface::InitializeOneOffInternal() { |
switch (GetGLImplementation()) { |
case kGLImplementationDesktopGL: |
case kGLImplementationAppleGL: |
- if (!GLSurfaceCGL::InitializeOneOff()) { |
+ if (!InitializeOneOffForSandbox()) { |
LOG(ERROR) << "GLSurfaceCGL::InitializeOneOff failed."; |
return false; |
} |
@@ -62,7 +139,7 @@ scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface( |
} |
case kGLImplementationDesktopGL: |
case kGLImplementationAppleGL: { |
- scoped_refptr<GLSurface> surface(new NoOpGLSurfaceCGL(size)); |
+ scoped_refptr<GLSurface> surface(new NoOpGLSurface(size)); |
if (!surface->Initialize()) |
return NULL; |