io_surface_context.mm 3.7 KB

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