Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / ui / accelerated_widget_mac / io_surface_context.mm
blob21d854ceba307466fef9b4b5e55a3d358899b483
1 // Copyright (c) 2013 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.
5 #include "ui/accelerated_widget_mac/io_surface_context.h"
7 #include <OpenGL/gl.h>
8 #include <OpenGL/OpenGL.h>
9 #include <vector>
11 #include "base/command_line.h"
12 #include "base/logging.h"
13 #include "base/trace_event/trace_event.h"
14 #include "ui/gl/gl_switches.h"
15 #include "ui/gl/gpu_switching_manager.h"
17 namespace ui {
19 // static
20 scoped_refptr<IOSurfaceContext>
21 IOSurfaceContext::Get(Type type) {
22   TRACE_EVENT0("browser", "IOSurfaceContext::Get");
24   // Return the context for this type, if it exists.
25   TypeMap::iterator found = type_map()->find(type);
26   if (found != type_map()->end()) {
27     DCHECK(!found->second->poisoned_);
28     return found->second;
29   }
31   base::ScopedTypeRef<CGLContextObj> cgl_context;
32   CGLError error = kCGLNoError;
34   // Create the pixel format object for the context.
35   std::vector<CGLPixelFormatAttribute> attribs;
36   attribs.push_back(kCGLPFADepthSize);
37   attribs.push_back(static_cast<CGLPixelFormatAttribute>(0));
38   if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus())
39     attribs.push_back(kCGLPFAAllowOfflineRenderers);
40   attribs.push_back(static_cast<CGLPixelFormatAttribute>(0));
41   GLint number_virtual_screens = 0;
42   base::ScopedTypeRef<CGLPixelFormatObj> pixel_format;
43   error = CGLChoosePixelFormat(&attribs.front(),
44                                pixel_format.InitializeInto(),
45                                &number_virtual_screens);
46   if (error != kCGLNoError) {
47     LOG(ERROR) << "Failed to create pixel format object.";
48     return NULL;
49   }
51   // Create all contexts in the same share group so that the textures don't
52   // need to be recreated when transitioning contexts.
53   CGLContextObj share_context = NULL;
54   if (!type_map()->empty())
55     share_context = type_map()->begin()->second->cgl_context();
56   error = CGLCreateContext(
57       pixel_format, share_context, cgl_context.InitializeInto());
58   if (error != kCGLNoError) {
59     LOG(ERROR) << "Failed to create context object.";
60     return NULL;
61   }
63   return new IOSurfaceContext(type, cgl_context);
66 void IOSurfaceContext::PoisonContextAndSharegroup() {
67   if (poisoned_)
68     return;
70   for (TypeMap::iterator it = type_map()->begin();
71        it != type_map()->end();
72        ++it) {
73     it->second->poisoned_ = true;
74   }
75   type_map()->clear();
78 IOSurfaceContext::IOSurfaceContext(
79     Type type, base::ScopedTypeRef<CGLContextObj> cgl_context)
80     : type_(type), cgl_context_(cgl_context), poisoned_(false) {
81   DCHECK(type_map()->find(type_) == type_map()->end());
82   type_map()->insert(std::make_pair(type_, this));
84   ui::GpuSwitchingManager::GetInstance()->AddObserver(this);
87 IOSurfaceContext::~IOSurfaceContext() {
88   ui::GpuSwitchingManager::GetInstance()->RemoveObserver(this);
90   if (!poisoned_) {
91     DCHECK(type_map()->find(type_) != type_map()->end());
92     DCHECK(type_map()->find(type_)->second == this);
93     type_map()->erase(type_);
94   } else {
95     TypeMap::const_iterator found = type_map()->find(type_);
96     if (found != type_map()->end())
97       DCHECK(found->second != this);
98   }
101 void IOSurfaceContext::OnGpuSwitched() {
102   // Recreate all browser-side GL contexts whenever the GPU switches. If this
103   // is not done, performance will suffer.
104   // http://crbug.com/361493
105   PoisonContextAndSharegroup();
108 // static
109 IOSurfaceContext::TypeMap*
110     IOSurfaceContext::type_map() {
111   return type_map_.Pointer();
114 // static
115 base::LazyInstance<IOSurfaceContext::TypeMap>
116     IOSurfaceContext::type_map_;
118 }  // namespace ui