blob: 4e8984df21d2a204b7df1170ad140b40e444d3c1 [file] [log] [blame]
// Copyright (c) 2009 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 "base/callback.h"
#include "base/compiler_specific.h"
#include "base/message_loop.h"
#include "app/gfx/gl/gl_context.h"
#include "gpu/command_buffer/service/gpu_processor.h"
using ::base::SharedMemory;
namespace gpu {
GPUProcessor::GPUProcessor(CommandBuffer* command_buffer)
: command_buffer_(command_buffer),
commands_per_update_(100),
method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
DCHECK(command_buffer);
decoder_.reset(gles2::GLES2Decoder::Create(&group_));
decoder_->set_engine(this);
}
GPUProcessor::GPUProcessor(CommandBuffer* command_buffer,
gles2::GLES2Decoder* decoder,
CommandParser* parser,
int commands_per_update)
: command_buffer_(command_buffer),
commands_per_update_(commands_per_update),
method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
DCHECK(command_buffer);
decoder_.reset(decoder);
parser_.reset(parser);
}
GPUProcessor::~GPUProcessor() {
Destroy();
}
bool GPUProcessor::InitializeCommon(gfx::GLContext* context,
const gfx::Size& size,
const std::vector<int32>& attribs,
gles2::GLES2Decoder* parent_decoder,
uint32 parent_texture_id) {
DCHECK(context);
// Map the ring buffer and create the parser.
Buffer ring_buffer = command_buffer_->GetRingBuffer();
if (ring_buffer.ptr) {
parser_.reset(new CommandParser(ring_buffer.ptr,
ring_buffer.size,
0,
ring_buffer.size,
0,
decoder_.get()));
} else {
parser_.reset(new CommandParser(NULL, 0, 0, 0, 0,
decoder_.get()));
}
if (!group_.Initialize(NULL)) {
LOG(ERROR) << "GPUProcessor::InitializeCommon failed because group "
<< "failed to initialize.";
Destroy();
}
// Initialize the decoder with either the view or pbuffer GLContext.
if (!decoder_->Initialize(context,
size,
attribs,
parent_decoder,
parent_texture_id)) {
LOG(ERROR) << "GPUProcessor::InitializeCommon failed because decoder "
<< "failed to initialize.";
Destroy();
return false;
}
return true;
}
void GPUProcessor::DestroyCommon() {
bool have_context = false;
if (decoder_.get()) {
have_context = decoder_->MakeCurrent();
decoder_->Destroy();
decoder_.reset();
}
group_.Destroy(have_context);
parser_.reset();
}
void GPUProcessor::ProcessCommands() {
CommandBuffer::State state = command_buffer_->GetState();
if (state.error != error::kNoError)
return;
if (decoder_.get()) {
if (!decoder_->MakeCurrent()) {
LOG(ERROR) << "Context lost because MakeCurrent failed.";
command_buffer_->SetParseError(error::kLostContext);
return;
}
}
parser_->set_put(state.put_offset);
int commands_processed = 0;
while (commands_processed < commands_per_update_ && !parser_->IsEmpty()) {
error::Error error = parser_->ProcessCommand();
if (error != error::kNoError) {
command_buffer_->SetParseError(error);
return;
}
++commands_processed;
}
command_buffer_->SetGetOffset(static_cast<int32>(parser_->get()));
if (!parser_->IsEmpty()) {
MessageLoop::current()->PostTask(
FROM_HERE,
method_factory_.NewRunnableMethod(&GPUProcessor::ProcessCommands));
}
}
Buffer GPUProcessor::GetSharedMemoryBuffer(int32 shm_id) {
return command_buffer_->GetTransferBuffer(shm_id);
}
void GPUProcessor::set_token(int32 token) {
command_buffer_->SetToken(token);
}
bool GPUProcessor::SetGetOffset(int32 offset) {
if (parser_->set_get(offset)) {
command_buffer_->SetGetOffset(static_cast<int32>(parser_->get()));
return true;
}
return false;
}
int32 GPUProcessor::GetGetOffset() {
return parser_->get();
}
void GPUProcessor::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
decoder_->ResizeOffscreenFrameBuffer(size);
}
void GPUProcessor::SetSwapBuffersCallback(
Callback0::Type* callback) {
wrapped_swap_buffers_callback_.reset(callback);
decoder_->SetSwapBuffersCallback(
NewCallback(this,
&GPUProcessor::WillSwapBuffers));
}
} // namespace gpu