blob: 45589b62c8f4bc535ba293e491f53f12a00de162 [file]
// 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/tests/gl_manager.h"
#include <vector>
#include "base/at_exit.h"
#include "base/bind.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "gpu/command_buffer/client/gles2_lib.h"
#include "gpu/command_buffer/client/transfer_buffer.h"
#include "gpu/command_buffer/common/constants.h"
#include "gpu/command_buffer/service/command_buffer_service.h"
#include "gpu/command_buffer/service/context_group.h"
#include "gpu/command_buffer/service/gpu_scheduler.h"
#include "gpu/command_buffer/service/mailbox_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_share_group.h"
#include "ui/gl/gl_surface.h"
namespace gpu {
GLManager::GLManager() {
}
GLManager::~GLManager() {
}
void GLManager::Initialize(const gfx::Size& size) {
Setup(size, NULL, NULL, NULL, NULL);
}
void GLManager::InitializeShared(
const gfx::Size& size, GLManager* gl_manager) {
DCHECK(gl_manager);
Setup(
size,
gl_manager->mailbox_manager(),
gl_manager->share_group(),
gl_manager->decoder_->GetContextGroup(),
gl_manager->gles2_implementation()->share_group());
}
void GLManager::InitializeSharedMailbox(
const gfx::Size& size, GLManager* gl_manager) {
DCHECK(gl_manager);
Setup(
size,
gl_manager->mailbox_manager(),
gl_manager->share_group(),
NULL,
NULL);
}
void GLManager::Setup(
const gfx::Size& size,
gles2::MailboxManager* mailbox_manager,
gfx::GLShareGroup* share_group,
gles2::ContextGroup* context_group,
gles2::ShareGroup* client_share_group) {
const int32 kCommandBufferSize = 1024 * 1024;
const size_t kStartTransferBufferSize = 4 * 1024 * 1024;
const size_t kMinTransferBufferSize = 1 * 256 * 1024;
const size_t kMaxTransferBufferSize = 16 * 1024 * 1024;
const bool kBindGeneratesResource = false;
const bool kShareResources = true;
// From <EGL/egl.h>.
const int32 EGL_ALPHA_SIZE = 0x3021;
const int32 EGL_BLUE_SIZE = 0x3022;
const int32 EGL_GREEN_SIZE = 0x3023;
const int32 EGL_RED_SIZE = 0x3024;
const int32 EGL_DEPTH_SIZE = 0x3025;
const int32 EGL_NONE = 0x3038;
mailbox_manager_ =
mailbox_manager ? mailbox_manager : new gles2::MailboxManager;
share_group_ =
share_group ? share_group : new gfx::GLShareGroup;
gfx::GpuPreference gpu_preference(gfx::PreferDiscreteGpu);
const char* allowed_extensions = "*";
std::vector<int32> attribs;
attribs.push_back(EGL_RED_SIZE);
attribs.push_back(8);
attribs.push_back(EGL_GREEN_SIZE);
attribs.push_back(8);
attribs.push_back(EGL_BLUE_SIZE);
attribs.push_back(8);
attribs.push_back(EGL_ALPHA_SIZE);
attribs.push_back(8);
attribs.push_back(EGL_DEPTH_SIZE);
attribs.push_back(16);
attribs.push_back(EGL_NONE);
if (!context_group) {
context_group = new gles2::ContextGroup(mailbox_manager_.get(),
NULL,
kBindGeneratesResource);
}
decoder_.reset(::gpu::gles2::GLES2Decoder::Create(context_group));
command_buffer_.reset(new CommandBufferService(
decoder_->GetContextGroup()->transfer_buffer_manager()));
ASSERT_TRUE(command_buffer_->Initialize())
<< "could not create command buffer service";
gpu_scheduler_.reset(new GpuScheduler(command_buffer_.get(),
decoder_.get(),
decoder_.get()));
decoder_->set_engine(gpu_scheduler_.get());
surface_ = gfx::GLSurface::CreateOffscreenGLSurface(false, size);
ASSERT_TRUE(surface_.get() != NULL) << "could not create offscreen surface";
context_ = gfx::GLContext::CreateGLContext(share_group_.get(),
surface_.get(),
gpu_preference);
ASSERT_TRUE(context_.get() != NULL) << "could not create GL context";
ASSERT_TRUE(context_->MakeCurrent(surface_.get()));
ASSERT_TRUE(decoder_->Initialize(
surface_.get(),
context_.get(),
true,
size,
::gpu::gles2::DisallowedFeatures(),
allowed_extensions,
attribs)) << "could not initialize decoder";
command_buffer_->SetPutOffsetChangeCallback(
base::Bind(&GLManager::PumpCommands, base::Unretained(this)));
command_buffer_->SetGetBufferChangeCallback(
base::Bind(&GLManager::GetBufferChanged, base::Unretained(this)));
// Create the GLES2 helper, which writes the command buffer protocol.
gles2_helper_.reset(new gles2::GLES2CmdHelper(command_buffer_.get()));
ASSERT_TRUE(gles2_helper_->Initialize(kCommandBufferSize));
// Create a transfer buffer.
transfer_buffer_.reset(new TransferBuffer(gles2_helper_.get()));
// Create the object exposing the OpenGL API.
gles2_implementation_.reset(new gles2::GLES2Implementation(
gles2_helper_.get(),
client_share_group,
transfer_buffer_.get(),
kShareResources,
kBindGeneratesResource));
ASSERT_TRUE(gles2_implementation_->Initialize(
kStartTransferBufferSize,
kMinTransferBufferSize,
kMaxTransferBufferSize)) << "Could not init GLES2Implementation";
MakeCurrent();
}
void GLManager::MakeCurrent() {
::gles2::SetGLContext(gles2_implementation_.get());
}
void GLManager::Destroy() {
if (gles2_implementation_.get()) {
MakeCurrent();
EXPECT_TRUE(glGetError() == GL_NONE);
gles2_implementation_->Flush();
gles2_implementation_.reset();
}
transfer_buffer_.reset();
gles2_helper_.reset();
command_buffer_.reset();
if (decoder_.get()) {
decoder_->MakeCurrent();
decoder_->Destroy(true);
}
}
void GLManager::PumpCommands() {
decoder_->MakeCurrent();
gpu_scheduler_->PutChanged();
::gpu::CommandBuffer::State state = command_buffer_->GetState();
ASSERT_EQ(::gpu::error::kNoError, state.error);
}
bool GLManager::GetBufferChanged(int32 transfer_buffer_id) {
return gpu_scheduler_->SetGetBuffer(transfer_buffer_id);
}
} // namespace gpu