text: // Copyright (c) 2019 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/dual_gpu_state_mac.h"
  
  #include <OpenGL/CGLRenderers.h>
  #include <OpenGL/CGLTypes.h>
  
  #include "base/bind.h"
  #include "base/cancelable_callback.h"
  #include "base/location.h"
  #include "base/no_destructor.h"
  #include "base/synchronization/lock.h"
  #include "base/task/single_thread_task_runner.h"
  #include "base/threading/thread_task_runner_handle.h"
  #include "base/time/time.h"
  #include "base/trace_event/trace_event.h"
  #include "build/build_config.h"
  #include "ui/gl/gl_bindings.h"
  
  namespace gl {
  
  namespace {
  
  const unsigned int kDelayLengthSeconds = 10;
  
  }  // namespace
  
  // static
  DualGPUStateMac* DualGPUStateMac::GetInstance() {
    static base::NoDestructor<DualGPUStateMac> instance;
    return instance.get();
  }
  
  DualGPUStateMac::DualGPUStateMac() {}
  
  DualGPUStateMac::~DualGPUStateMac() {}
  
  void DualGPUStateMac::SwitchToHighPerformanceGPUIfNeeded() {
    AllocateDiscretePixelFormatObjectIfNeeded();
  }
  
  // This function is called by a delayed task posted in
  // DualGPUStateMac::AttemptSwitchToLowPowerGPUWithDelay.
  void DualGPUStateMac::SwitchToLowPowerGPU() {
    ReleaseDiscretePixelFormatObjectIfNeeded();
  }
  
  void DualGPUStateMac::AttemptSwitchToLowPowerGPUWithDelay() {
    if (base::ThreadTaskRunnerHandle::IsSet()) {
      cancelable_delay_callback_.Reset(base::BindOnce(
          []() { DualGPUStateMac::GetInstance()->SwitchToLowPowerGPU(); }));
  
      base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
          FROM_HERE, cancelable_delay_callback_.callback(),
          base::Seconds(kDelayLengthSeconds));
    } else {
      SwitchToLowPowerGPU();
    }
  }
  
  void DualGPUStateMac::CancelDelayedSwitchToLowPowerGPU() {
    cancelable_delay_callback_.Cancel();
  }
  
  void DualGPUStateMac::AllocateDiscretePixelFormatObjectIfNeeded() {
    if (discrete_pixelformat_)
      return;
    CGLPixelFormatAttribute attribs[1];
    attribs[0] = static_cast<CGLPixelFormatAttribute>(0);
    GLint num_pixel_formats = 0;
    CGLChoosePixelFormat(attribs, &discrete_pixelformat_, &num_pixel_formats);
  }
  
  void DualGPUStateMac::ReleaseDiscretePixelFormatObjectIfNeeded() {
    if (!discrete_pixelformat_)
      return;
    CGLReleasePixelFormat(discrete_pixelformat_);
    discrete_pixelformat_ = nullptr;
  }
  
  }  // namespace gl
  