+void SharedRendererState::DrawGL(AwDrawGLInfo* draw_info) {
+ if (draw_info->mode == AwDrawGLInfo::kModeSync) {
+ if (hardware_renderer_)
+ hardware_renderer_->CommitFrame();
+ return;
+ }
+
+ {
+ GLViewRendererManager* manager = GLViewRendererManager::GetInstance();
+ base::AutoLock lock(lock_);
+ if (renderer_manager_key_ != manager->NullKey()) {
+ manager->DidDrawGL(renderer_manager_key_);
+ }
+ }
+
+ ScopedAppGLStateRestore state_restore(
+ draw_info->mode == AwDrawGLInfo::kModeDraw
+ ? ScopedAppGLStateRestore::MODE_DRAW
+ : ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT);
+ ScopedAllowGL allow_gl;
+
+ if (draw_info->mode == AwDrawGLInfo::kModeProcessNoContext) {
+ LOG(ERROR) << "Received unexpected kModeProcessNoContext";
+ }
+
+ // kModeProcessNoContext should never happen because we tear down hardware
+ // in onTrimMemory. However that guarantee is maintained outside of chromium
+ // code. Not notifying shared state in kModeProcessNoContext can lead to
+ // immediate deadlock, which is slightly more catastrophic than leaks or
+ // corruption.
+ if (draw_info->mode == AwDrawGLInfo::kModeProcess ||
+ draw_info->mode == AwDrawGLInfo::kModeProcessNoContext) {
+ DidDrawGLProcess();
+ }
+
+ if (IsInsideHardwareRelease()) {
+ hardware_renderer_.reset();
+ // Flush the idle queue in tear down.
+ DeferredGpuCommandService::GetInstance()->PerformAllIdleWork();
+ return;
+ }
+
+ if (draw_info->mode != AwDrawGLInfo::kModeDraw) {
+ if (draw_info->mode == AwDrawGLInfo::kModeProcess) {
+ DeferredGpuCommandService::GetInstance()->PerformIdleWork(true);
+ }
+ return;
+ }
+
+ if (!hardware_renderer_) {
+ hardware_renderer_.reset(new HardwareRenderer(this));
+ hardware_renderer_->CommitFrame();
+ }
+
+ hardware_renderer_->DrawGL(state_restore.stencil_enabled(),
+ state_restore.framebuffer_binding_ext(),
+ draw_info);
+ DeferredGpuCommandService::GetInstance()->PerformIdleWork(false);
+}
+
+void SharedRendererState::ReleaseHardwareDrawIfNeededOnUI() {
+ DCHECK(ui_loop_->BelongsToCurrentThread());
+ InsideHardwareReleaseReset auto_inside_hardware_release_reset(this);
+
+ browser_view_renderer_->InvalidateOnFunctorDestroy();
+ bool hardware_initialized = browser_view_renderer_->hardware_enabled();
+ if (hardware_initialized) {
+ bool draw_functor_succeeded = browser_view_renderer_->RequestDrawGL(true);
+ if (!draw_functor_succeeded) {
+ LOG(ERROR) << "Unable to free GL resources. Has the Window leaked?";
+ // Calling release on wrong thread intentionally.
+ AwDrawGLInfo info;
+ info.mode = AwDrawGLInfo::kModeProcess;
+ DrawGL(&info);
+ }
+
+ browser_view_renderer_->ReleaseHardware();
+ }
+
+ GLViewRendererManager* manager = GLViewRendererManager::GetInstance();
+
+ {
+ base::AutoLock lock(lock_);
+ if (renderer_manager_key_ != manager->NullKey()) {
+ manager->Remove(renderer_manager_key_);
+ renderer_manager_key_ = manager->NullKey();
+ }
+ }
+
+ if (hardware_initialized) {
+ // Flush any invoke functors that's caused by ReleaseHardware.
+ browser_view_renderer_->RequestDrawGL(true);
+ }
+}
+
+void SharedRendererState::InitializeHardwareDrawIfNeededOnUI() {
+ DCHECK(ui_loop_->BelongsToCurrentThread());
+ GLViewRendererManager* manager = GLViewRendererManager::GetInstance();
+
+ base::AutoLock lock(lock_);
+ if (renderer_manager_key_ == manager->NullKey()) {
+ renderer_manager_key_ = manager->PushBack(this);
+ DeferredGpuCommandService::SetInstance();
+ }
+}
+
+SharedRendererState::InsideHardwareReleaseReset::InsideHardwareReleaseReset(