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