// Copyright (c) 2010 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 "app/gfx/gl/gl_context.h" #include "gpu/command_buffer/service/gpu_processor.h" using ::base::SharedMemory; namespace gpu { bool GPUProcessor::Initialize(gfx::PluginWindowHandle window, const gfx::Size& size, const char* allowed_extensions, const std::vector& attribs, GPUProcessor* parent, uint32 parent_texture_id) { // Get the parent decoder and the GLContext to share IDs with, if any. gles2::GLES2Decoder* parent_decoder = NULL; gfx::GLContext* parent_context = NULL; if (parent) { parent_decoder = parent->decoder_.get(); DCHECK(parent_decoder); parent_context = parent_decoder->GetGLContext(); DCHECK(parent_context); } scoped_ptr context( gfx::GLContext::CreateOffscreenGLContext(parent_context)); if (!context.get()) return false; // On Mac OS X since we can not render on-screen we don't even // attempt to create a view based GLContext. The only difference // between "on-screen" and "off-screen" rendering on this platform // is whether we allocate an AcceleratedSurface, which transmits the // rendering results back to the browser. if (window) { surface_.reset(new AcceleratedSurface()); // Note that although the GLContext is passed to Initialize and the // GLContext will later be owned by the decoder, AcceleratedSurface does // not hold on to the reference. It simply extracts the underlying GL // context in order to share the namespace with another context. if (!surface_->Initialize(context.get(), false)) { LOG(ERROR) << "GPUProcessor::Initialize failed to " << "initialize AcceleratedSurface."; Destroy(); return false; } } return InitializeCommon(context.release(), size, allowed_extensions, attribs, parent_decoder, parent_texture_id); } void GPUProcessor::Destroy() { if (surface_.get()) { surface_->Destroy(); surface_.reset(); } DestroyCommon(); } uint64 GPUProcessor::SetWindowSizeForIOSurface(const gfx::Size& size) { // This is called from an IPC handler, so it's undefined which context is // current. Make sure the right one is. decoder_->GetGLContext()->MakeCurrent(); ResizeOffscreenFrameBuffer(size); decoder_->UpdateOffscreenFrameBufferSize(); // Note: The following line changes the current context again. return surface_->SetSurfaceSize(size); } TransportDIB::Handle GPUProcessor::SetWindowSizeForTransportDIB( const gfx::Size& size) { ResizeOffscreenFrameBuffer(size); decoder_->UpdateOffscreenFrameBufferSize(); return surface_->SetTransportDIBSize(size); } void GPUProcessor::SetTransportDIBAllocAndFree( Callback2::Type* allocator, Callback1::Type* deallocator) { surface_->SetTransportDIBAllocAndFree(allocator, deallocator); } uint64 GPUProcessor::GetSurfaceId() { if (!surface_.get()) return 0; return surface_->GetSurfaceId(); } uint64 GPUProcessor::swap_buffers_count() const { return swap_buffers_count_; } void GPUProcessor::set_acknowledged_swap_buffers_count( uint64 acknowledged_swap_buffers_count) { acknowledged_swap_buffers_count_ = acknowledged_swap_buffers_count; } void GPUProcessor::DidDestroySurface() { // When a browser window with a GPUProcessor is closed, the render process // will attempt to finish all GL commands, it will busy-wait on the GPU // process until the command queue is empty. If a paint is pending, the GPU // process won't process any GL commands until the browser sends a paint ack, // but since the browser window is already closed, it will never arrive. // To break this infinite loop, the browser tells the GPU process that the // surface became invalid, which causes the GPU process to not wait for paint // acks. surface_.reset(); } void GPUProcessor::WillSwapBuffers() { DCHECK(decoder_.get()); DCHECK(decoder_->GetGLContext()); DCHECK(decoder_->GetGLContext()->IsCurrent()); ++swap_buffers_count_; if (surface_.get()) { surface_->SwapBuffers(); } if (wrapped_swap_buffers_callback_.get()) { wrapped_swap_buffers_callback_->Run(); } } } // namespace gpu