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