Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(525)

Unified Diff: ui/gl/gl_context_cgl.cc

Issue 1238983002: Initial ui/gl updates for Mac Sky shell target (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/gl/gl_context_cgl.h ('k') | ui/gl/gl_context_mac.mm » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/gl/gl_context_cgl.cc
diff --git a/ui/gl/gl_context_cgl.cc b/ui/gl/gl_context_cgl.cc
new file mode 100644
index 0000000000000000000000000000000000000000..4a82d33d2a30a242ab948189b1c0e77a5635999f
--- /dev/null
+++ b/ui/gl/gl_context_cgl.cc
@@ -0,0 +1,304 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_context_cgl.h"
+
+#include <OpenGL/CGLRenderers.h>
+#include <OpenGL/CGLTypes.h>
+#include <OpenGL/CGLCurrent.h>
+
+#include <vector>
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/trace_event/trace_event.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_surface.h"
+#include "ui/gl/gpu_switching_manager.h"
+
+extern "C" {
+extern CGLError CGLChoosePixelFormat(const CGLPixelFormatAttribute *attribs,
+ CGLPixelFormatObj *pix, GLint *npix);
+extern CGLError CGLDescribePixelFormat(CGLPixelFormatObj pix, GLint pix_num,
+ CGLPixelFormatAttribute attrib,
+ GLint *value);
+extern void CGLReleasePixelFormat(CGLPixelFormatObj pix);
+
+extern CGLError CGLCreateContext(CGLPixelFormatObj pix, CGLContextObj share,
+ CGLContextObj *ctx);
+extern CGLError CGLDestroyContext(CGLContextObj ctx);
+
+extern CGLError CGLGetParameter(CGLContextObj ctx, CGLContextParameter pname,
+ GLint *params);
+
+extern CGLError CGLGetVirtualScreen(CGLContextObj ctx, GLint *screen);
+extern CGLError CGLSetVirtualScreen(CGLContextObj ctx, GLint screen);
+
+extern CGLError CGLQueryRendererInfo(GLuint display_mask,
+ CGLRendererInfoObj *rend, GLint *nrend);
+extern CGLError CGLDescribeRenderer(CGLRendererInfoObj rend, GLint rend_num,
+ CGLRendererProperty prop, GLint *value);
+extern CGLError CGLDestroyRendererInfo(CGLRendererInfoObj rend);
+} // extern "C"
+
+namespace gfx {
+
+namespace {
+
+bool g_support_renderer_switching;
+
+struct CGLRendererInfoObjDeleter {
+ void operator()(CGLRendererInfoObj* x) {
+ if (x)
+ CGLDestroyRendererInfo(*x);
+ }
+};
+
+} // namespace
+
+static CGLPixelFormatObj GetPixelFormat() {
+ static CGLPixelFormatObj format;
+ if (format)
+ return format;
+ std::vector<CGLPixelFormatAttribute> attribs;
+ // If the system supports dual gpus then allow offline renderers for every
+ // context, so that they can all be in the same share group.
+ if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) {
+ attribs.push_back(kCGLPFAAllowOfflineRenderers);
+ g_support_renderer_switching = true;
+ }
+ if (GetGLImplementation() == kGLImplementationAppleGL) {
+ attribs.push_back(kCGLPFARendererID);
+ attribs.push_back((CGLPixelFormatAttribute) kCGLRendererGenericFloatID);
+ g_support_renderer_switching = false;
+ }
+
+ attribs.push_back((CGLPixelFormatAttribute) 0);
+
+ GLint num_virtual_screens;
+ if (CGLChoosePixelFormat(&attribs.front(),
+ &format,
+ &num_virtual_screens) != kCGLNoError) {
+ LOG(ERROR) << "Error choosing pixel format.";
+ return nullptr;
+ }
+ if (!format) {
+ LOG(ERROR) << "format == 0.";
+ return nullptr;
+ }
+ DCHECK_NE(num_virtual_screens, 0);
+ return format;
+}
+
+GLContextCGL::GLContextCGL(GLShareGroup* share_group)
+ : GLContextReal(share_group),
+ context_(nullptr),
+ gpu_preference_(PreferIntegratedGpu),
+ discrete_pixelformat_(nullptr),
+ screen_(-1),
+ renderer_id_(-1),
+ safe_to_force_gpu_switch_(false) {
+}
+
+bool GLContextCGL::Initialize(GLSurface* compatible_surface,
+ GpuPreference gpu_preference) {
+ DCHECK(compatible_surface);
+
+ gpu_preference = ui::GpuSwitchingManager::GetInstance()->AdjustGpuPreference(
+ gpu_preference);
+
+ GLContextCGL* share_context = share_group() ?
+ static_cast<GLContextCGL*>(share_group()->GetContext()) : nullptr;
+
+ CGLPixelFormatObj format = GetPixelFormat();
+ if (!format)
+ return false;
+
+ // If using the discrete gpu, create a pixel format requiring it before we
+ // create the context.
+ if (!ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus() ||
+ gpu_preference == PreferDiscreteGpu) {
+ std::vector<CGLPixelFormatAttribute> discrete_attribs;
+ discrete_attribs.push_back((CGLPixelFormatAttribute) 0);
+ GLint num_pixel_formats;
+ if (CGLChoosePixelFormat(&discrete_attribs.front(),
+ &discrete_pixelformat_,
+ &num_pixel_formats) != kCGLNoError) {
+ LOG(ERROR) << "Error choosing pixel format.";
+ return false;
+ }
+ }
+
+ CGLError res = CGLCreateContext(
+ format,
+ share_context ?
+ static_cast<CGLContextObj>(share_context->GetHandle()) : nullptr,
+ reinterpret_cast<CGLContextObj*>(&context_));
+ if (res != kCGLNoError) {
+ LOG(ERROR) << "Error creating context.";
+ Destroy();
+ return false;
+ }
+
+ gpu_preference_ = gpu_preference;
+ return true;
+}
+
+void GLContextCGL::Destroy() {
+ if (discrete_pixelformat_) {
+ if (base::MessageLoop::current() != nullptr) {
+ // Delay releasing the pixel format for 10 seconds to reduce the number of
+ // unnecessary GPU switches.
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE, base::Bind(&CGLReleasePixelFormat, discrete_pixelformat_),
+ base::TimeDelta::FromSeconds(10));
+ } else {
+ CGLReleasePixelFormat(discrete_pixelformat_);
+ }
+ discrete_pixelformat_ = nullptr;
+ }
+ if (context_) {
+ CGLDestroyContext(static_cast<CGLContextObj>(context_));
+ context_ = nullptr;
+ }
+}
+
+bool GLContextCGL::ForceGpuSwitchIfNeeded() {
+ DCHECK(context_);
+ return true;
+}
+
+bool GLContextCGL::MakeCurrent(GLSurface* surface) {
+ DCHECK(context_);
+
+ if (!ForceGpuSwitchIfNeeded())
+ return false;
+
+ if (IsCurrent(surface))
+ return true;
+
+ ScopedReleaseCurrent release_current;
+ TRACE_EVENT0("gpu", "GLContextCGL::MakeCurrent");
+
+ if (CGLSetCurrentContext(
+ static_cast<CGLContextObj>(context_)) != kCGLNoError) {
+ LOG(ERROR) << "Unable to make gl context current.";
+ return false;
+ }
+
+ // Set this as soon as the context is current, since we might call into GL.
+ SetRealGLApi();
+
+ SetCurrent(surface);
+ if (!InitializeDynamicBindings()) {
+ return false;
+ }
+
+ if (!surface->OnMakeCurrent(this)) {
+ LOG(ERROR) << "Unable to make gl context current.";
+ return false;
+ }
+
+ release_current.Cancel();
+ return true;
+}
+
+void GLContextCGL::ReleaseCurrent(GLSurface* surface) {
+ if (!IsCurrent(surface))
+ return;
+
+ SetCurrent(nullptr);
+ CGLSetCurrentContext(nullptr);
+}
+
+bool GLContextCGL::IsCurrent(GLSurface* surface) {
+ bool native_context_is_current = CGLGetCurrentContext() == context_;
+
+ // If our context is current then our notion of which GLContext is
+ // current must be correct. On the other hand, third-party code
+ // using OpenGL might change the current context.
+ DCHECK(!native_context_is_current || (GetRealCurrent() == this));
+
+ if (!native_context_is_current)
+ return false;
+
+ return true;
+}
+
+void* GLContextCGL::GetHandle() {
+ return context_;
+}
+
+void GLContextCGL::OnSetSwapInterval(int interval) {
+ DCHECK(IsCurrent(nullptr));
+}
+
+bool GLContextCGL::GetTotalGpuMemory(size_t* bytes) {
+ DCHECK(bytes);
+ *bytes = 0;
+
+ CGLContextObj context = reinterpret_cast<CGLContextObj>(context_);
+ if (!context)
+ return false;
+
+ // Retrieve the current renderer ID
+ GLint current_renderer_id = 0;
+ if (CGLGetParameter(context,
+ kCGLCPCurrentRendererID,
+ &current_renderer_id) != kCGLNoError)
+ return false;
+
+ // Iterate through the list of all renderers
+ GLuint display_mask = static_cast<GLuint>(-1);
+ CGLRendererInfoObj renderer_info = nullptr;
+ GLint num_renderers = 0;
+ if (CGLQueryRendererInfo(display_mask,
+ &renderer_info,
+ &num_renderers) != kCGLNoError)
+ return false;
+
+ scoped_ptr<CGLRendererInfoObj,
+ CGLRendererInfoObjDeleter> scoper(&renderer_info);
+
+ for (GLint renderer_index = 0;
+ renderer_index < num_renderers;
+ ++renderer_index) {
+ // Skip this if this renderer is not the current renderer.
+ GLint renderer_id = 0;
+ if (CGLDescribeRenderer(renderer_info,
+ renderer_index,
+ kCGLRPRendererID,
+ &renderer_id) != kCGLNoError)
+ continue;
+ if (renderer_id != current_renderer_id)
+ continue;
+ // Retrieve the video memory for the renderer.
+ GLint video_memory = 0;
+ if (CGLDescribeRenderer(renderer_info,
+ renderer_index,
+ kCGLRPVideoMemory,
+ &video_memory) != kCGLNoError)
+ continue;
+ *bytes = video_memory;
+ return true;
+ }
+
+ return false;
+}
+
+void GLContextCGL::SetSafeToForceGpuSwitch() {
+ safe_to_force_gpu_switch_ = true;
+}
+
+
+GLContextCGL::~GLContextCGL() {
+ Destroy();
+}
+
+GpuPreference GLContextCGL::GetGpuPreference() {
+ return gpu_preference_;
+}
+
+} // namespace gfx
« no previous file with comments | « ui/gl/gl_context_cgl.h ('k') | ui/gl/gl_context_mac.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698