1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "gpu/command_buffer/tests/gl_manager.h" 6 7#include <vector> 8 9#include "base/at_exit.h" 10#include "base/bind.h" 11#include "gpu/command_buffer/client/gles2_implementation.h" 12#include "gpu/command_buffer/client/gles2_lib.h" 13#include "gpu/command_buffer/client/transfer_buffer.h" 14#include "gpu/command_buffer/common/constants.h" 15#include "gpu/command_buffer/common/gles2_cmd_utils.h" 16#include "gpu/command_buffer/service/command_buffer_service.h" 17#include "gpu/command_buffer/service/context_group.h" 18#include "gpu/command_buffer/service/gl_context_virtual.h" 19#include "gpu/command_buffer/service/gles2_cmd_decoder.h" 20#include "gpu/command_buffer/service/gpu_control_service.h" 21#include "gpu/command_buffer/service/gpu_scheduler.h" 22#include "gpu/command_buffer/service/image_manager.h" 23#include "gpu/command_buffer/service/mailbox_manager.h" 24#include "testing/gtest/include/gtest/gtest.h" 25#include "ui/gl/gl_context.h" 26#include "ui/gl/gl_share_group.h" 27#include "ui/gl/gl_surface.h" 28 29namespace gpu { 30 31int GLManager::use_count_; 32scoped_refptr<gfx::GLShareGroup>* GLManager::base_share_group_; 33scoped_refptr<gfx::GLSurface>* GLManager::base_surface_; 34scoped_refptr<gfx::GLContext>* GLManager::base_context_; 35 36GLManager::Options::Options() 37 : size(4, 4), 38 share_group_manager(NULL), 39 share_mailbox_manager(NULL), 40 virtual_manager(NULL), 41 bind_generates_resource(false), 42 context_lost_allowed(false), 43 image_manager(NULL) { 44} 45 46GLManager::GLManager() 47 : context_lost_allowed_(false) { 48 SetupBaseContext(); 49} 50 51GLManager::~GLManager() { 52 --use_count_; 53 if (!use_count_) { 54 if (base_share_group_) { 55 delete base_context_; 56 base_context_ = NULL; 57 } 58 if (base_surface_) { 59 delete base_surface_; 60 base_surface_ = NULL; 61 } 62 if (base_context_) { 63 delete base_context_; 64 base_context_ = NULL; 65 } 66 } 67} 68 69void GLManager::Initialize(const GLManager::Options& options) { 70 const int32 kCommandBufferSize = 1024 * 1024; 71 const size_t kStartTransferBufferSize = 4 * 1024 * 1024; 72 const size_t kMinTransferBufferSize = 1 * 256 * 1024; 73 const size_t kMaxTransferBufferSize = 16 * 1024 * 1024; 74 75 context_lost_allowed_ = options.context_lost_allowed; 76 77 gles2::MailboxManager* mailbox_manager = NULL; 78 if (options.share_mailbox_manager) { 79 mailbox_manager = options.share_mailbox_manager->mailbox_manager(); 80 } else if (options.share_group_manager) { 81 mailbox_manager = options.share_group_manager->mailbox_manager(); 82 } 83 84 gfx::GLShareGroup* share_group = NULL; 85 if (options.share_group_manager) { 86 share_group = options.share_group_manager->share_group(); 87 } else if (options.share_mailbox_manager) { 88 share_group = options.share_mailbox_manager->share_group(); 89 } 90 91 gles2::ContextGroup* context_group = NULL; 92 gles2::ShareGroup* client_share_group = NULL; 93 if (options.share_group_manager) { 94 context_group = options.share_group_manager->decoder_->GetContextGroup(); 95 client_share_group = 96 options.share_group_manager->gles2_implementation()->share_group(); 97 } 98 99 gfx::GLContext* real_gl_context = NULL; 100 if (options.virtual_manager) { 101 real_gl_context = options.virtual_manager->context(); 102 } 103 104 mailbox_manager_ = 105 mailbox_manager ? mailbox_manager : new gles2::MailboxManager; 106 share_group_ = 107 share_group ? share_group : new gfx::GLShareGroup; 108 109 gfx::GpuPreference gpu_preference(gfx::PreferDiscreteGpu); 110 std::vector<int32> attribs; 111 gles2::ContextCreationAttribHelper attrib_helper; 112 attrib_helper.red_size_ = 8; 113 attrib_helper.green_size_ = 8; 114 attrib_helper.blue_size_ = 8; 115 attrib_helper.alpha_size_ = 8; 116 attrib_helper.depth_size_ = 16; 117 attrib_helper.Serialize(&attribs); 118 119 if (!context_group) { 120 context_group = new gles2::ContextGroup(mailbox_manager_.get(), 121 options.image_manager, 122 NULL, 123 NULL, 124 NULL, 125 options.bind_generates_resource); 126 } 127 128 decoder_.reset(::gpu::gles2::GLES2Decoder::Create(context_group)); 129 130 command_buffer_.reset(new CommandBufferService( 131 decoder_->GetContextGroup()->transfer_buffer_manager())); 132 ASSERT_TRUE(command_buffer_->Initialize()) 133 << "could not create command buffer service"; 134 135 gpu_scheduler_.reset(new GpuScheduler(command_buffer_.get(), 136 decoder_.get(), 137 decoder_.get())); 138 139 decoder_->set_engine(gpu_scheduler_.get()); 140 141 surface_ = gfx::GLSurface::CreateOffscreenGLSurface(options.size); 142 ASSERT_TRUE(surface_.get() != NULL) << "could not create offscreen surface"; 143 144 if (real_gl_context) { 145 context_ = scoped_refptr<gfx::GLContext>(new gpu::GLContextVirtual( 146 share_group_.get(), real_gl_context, decoder_->AsWeakPtr())); 147 ASSERT_TRUE(context_->Initialize( 148 surface_.get(), gfx::PreferIntegratedGpu)); 149 } else { 150 if (base_context_) { 151 context_ = scoped_refptr<gfx::GLContext>(new gpu::GLContextVirtual( 152 share_group_.get(), base_context_->get(), decoder_->AsWeakPtr())); 153 ASSERT_TRUE(context_->Initialize( 154 surface_.get(), gfx::PreferIntegratedGpu)); 155 } else { 156 context_ = gfx::GLContext::CreateGLContext(share_group_.get(), 157 surface_.get(), 158 gpu_preference); 159 } 160 } 161 ASSERT_TRUE(context_.get() != NULL) << "could not create GL context"; 162 163 ASSERT_TRUE(context_->MakeCurrent(surface_.get())); 164 165 ASSERT_TRUE(decoder_->Initialize( 166 surface_.get(), 167 context_.get(), 168 true, 169 options.size, 170 ::gpu::gles2::DisallowedFeatures(), 171 attribs)) << "could not initialize decoder"; 172 173 gpu_control_.reset( 174 new GpuControlService(decoder_->GetContextGroup()->image_manager(), 175 options.gpu_memory_buffer_factory, 176 decoder_->GetContextGroup()->mailbox_manager(), 177 decoder_->GetQueryManager(), 178 decoder_->GetCapabilities())); 179 180 command_buffer_->SetPutOffsetChangeCallback( 181 base::Bind(&GLManager::PumpCommands, base::Unretained(this))); 182 command_buffer_->SetGetBufferChangeCallback( 183 base::Bind(&GLManager::GetBufferChanged, base::Unretained(this))); 184 185 // Create the GLES2 helper, which writes the command buffer protocol. 186 gles2_helper_.reset(new gles2::GLES2CmdHelper(command_buffer_.get())); 187 ASSERT_TRUE(gles2_helper_->Initialize(kCommandBufferSize)); 188 189 // Create a transfer buffer. 190 transfer_buffer_.reset(new TransferBuffer(gles2_helper_.get())); 191 192 bool free_everything_when_invisible = false; 193 194 // Create the object exposing the OpenGL API. 195 gles2_implementation_.reset(new gles2::GLES2Implementation( 196 gles2_helper_.get(), 197 client_share_group, 198 transfer_buffer_.get(), 199 options.bind_generates_resource, 200 free_everything_when_invisible , 201 gpu_control_.get())); 202 203 ASSERT_TRUE(gles2_implementation_->Initialize( 204 kStartTransferBufferSize, 205 kMinTransferBufferSize, 206 kMaxTransferBufferSize, 207 gpu::gles2::GLES2Implementation::kNoLimit)) 208 << "Could not init GLES2Implementation"; 209 210 MakeCurrent(); 211} 212 213void GLManager::SetupBaseContext() { 214 if (use_count_) { 215 #if defined(OS_ANDROID) 216 base_share_group_ = new scoped_refptr<gfx::GLShareGroup>( 217 new gfx::GLShareGroup); 218 gfx::Size size(4, 4); 219 base_surface_ = new scoped_refptr<gfx::GLSurface>( 220 gfx::GLSurface::CreateOffscreenGLSurface(size)); 221 gfx::GpuPreference gpu_preference(gfx::PreferDiscreteGpu); 222 base_context_ = new scoped_refptr<gfx::GLContext>( 223 gfx::GLContext::CreateGLContext(base_share_group_->get(), 224 base_surface_->get(), 225 gpu_preference)); 226 #endif 227 } 228 ++use_count_; 229} 230 231void GLManager::MakeCurrent() { 232 ::gles2::SetGLContext(gles2_implementation_.get()); 233} 234 235void GLManager::SetSurface(gfx::GLSurface* surface) { 236 decoder_->SetSurface(surface); 237} 238 239void GLManager::Destroy() { 240 if (gles2_implementation_.get()) { 241 MakeCurrent(); 242 EXPECT_TRUE(glGetError() == GL_NONE); 243 gles2_implementation_->Flush(); 244 gles2_implementation_.reset(); 245 } 246 transfer_buffer_.reset(); 247 gles2_helper_.reset(); 248 command_buffer_.reset(); 249 if (decoder_.get()) { 250 decoder_->MakeCurrent(); 251 decoder_->Destroy(true); 252 decoder_.reset(); 253 } 254} 255 256const gpu::gles2::FeatureInfo::Workarounds& GLManager::workarounds() const { 257 return decoder_->GetContextGroup()->feature_info()->workarounds(); 258} 259 260void GLManager::PumpCommands() { 261 decoder_->MakeCurrent(); 262 gpu_scheduler_->PutChanged(); 263 ::gpu::CommandBuffer::State state = command_buffer_->GetState(); 264 if (!context_lost_allowed_) { 265 ASSERT_EQ(::gpu::error::kNoError, state.error); 266 } 267} 268 269bool GLManager::GetBufferChanged(int32 transfer_buffer_id) { 270 return gpu_scheduler_->SetGetBuffer(transfer_buffer_id); 271} 272 273} // namespace gpu 274