// Copyright (c) 2012 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 "gpu/command_buffer/service/gl_context_virtual.h" #include "gpu/command_buffer/service/gl_state_restorer_impl.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" #include "ui/gl/gl_surface.h" namespace gpu { GLContextVirtual::GLContextVirtual( gfx::GLShareGroup* share_group, gfx::GLContext* shared_context, base::WeakPtr decoder) : GLContext(share_group), shared_context_(shared_context), display_(NULL), decoder_(decoder) { } gfx::Display* GLContextVirtual::display() { return display_; } bool GLContextVirtual::Initialize( gfx::GLSurface* compatible_surface, gfx::GpuPreference gpu_preference) { SetGLStateRestorer(new GLStateRestorerImpl(decoder_)); display_ = static_cast(compatible_surface->GetDisplay()); // Virtual contexts obviously can't make a context that is compatible // with the surface (the context already exists), but we do need to // make a context current for SetupForVirtualization() below. if (!IsCurrent(compatible_surface)) { if (!shared_context_->MakeCurrent(compatible_surface)) { // This is likely an error. The real context should be made as // compatible with all required surfaces when it was created. LOG(ERROR) << "Failed MakeCurrent(compatible_surface)"; return false; } } shared_context_->SetupForVirtualization(); shared_context_->MakeVirtuallyCurrent(this, compatible_surface); return true; } void GLContextVirtual::Destroy() { shared_context_->OnReleaseVirtuallyCurrent(this); shared_context_ = NULL; display_ = NULL; } bool GLContextVirtual::MakeCurrent(gfx::GLSurface* surface) { if (decoder_.get()) return shared_context_->MakeVirtuallyCurrent(this, surface); LOG(ERROR) << "Trying to make virtual context current without decoder."; return false; } void GLContextVirtual::ReleaseCurrent(gfx::GLSurface* surface) { if (IsCurrent(surface)) { shared_context_->OnReleaseVirtuallyCurrent(this); shared_context_->ReleaseCurrent(surface); } } bool GLContextVirtual::IsCurrent(gfx::GLSurface* surface) { // If it's a real surface it needs to be current. if (surface && !surface->IsOffscreen()) return shared_context_->IsCurrent(surface); // Otherwise, only insure the context itself is current. return shared_context_->IsCurrent(NULL); } void* GLContextVirtual::GetHandle() { return shared_context_->GetHandle(); } void GLContextVirtual::SetSwapInterval(int interval) { shared_context_->SetSwapInterval(interval); } std::string GLContextVirtual::GetExtensions() { return shared_context_->GetExtensions(); } bool GLContextVirtual::GetTotalGpuMemory(size_t* bytes) { return shared_context_->GetTotalGpuMemory(bytes); } void GLContextVirtual::SetSafeToForceGpuSwitch() { // TODO(ccameron): This will not work if two contexts that disagree // about whether or not forced gpu switching may be done both share // the same underlying shared_context_. return shared_context_->SetSafeToForceGpuSwitch(); } bool GLContextVirtual::WasAllocatedUsingRobustnessExtension() { return shared_context_->WasAllocatedUsingRobustnessExtension(); } void GLContextVirtual::SetUnbindFboOnMakeCurrent() { shared_context_->SetUnbindFboOnMakeCurrent(); } GLContextVirtual::~GLContextVirtual() { Destroy(); } } // namespace gpu