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/gpu_memory_buffer_factory.h" 14#include "gpu/command_buffer/client/transfer_buffer.h" 15#include "gpu/command_buffer/common/constants.h" 16#include "gpu/command_buffer/common/gles2_cmd_utils.h" 17#include "gpu/command_buffer/service/command_buffer_service.h" 18#include "gpu/command_buffer/service/context_group.h" 19#include "gpu/command_buffer/service/gl_context_virtual.h" 20#include "gpu/command_buffer/service/gles2_cmd_decoder.h" 21#include "gpu/command_buffer/service/gpu_control_service.h" 22#include "gpu/command_buffer/service/gpu_scheduler.h" 23#include "gpu/command_buffer/service/image_manager.h" 24#include "gpu/command_buffer/service/mailbox_manager.h" 25#include "testing/gtest/include/gtest/gtest.h" 26#include "ui/gl/gl_context.h" 27#include "ui/gl/gl_share_group.h" 28#include "ui/gl/gl_surface.h" 29 30namespace gpu { 31 32int GLManager::use_count_; 33scoped_refptr<gfx::GLShareGroup>* GLManager::base_share_group_; 34scoped_refptr<gfx::GLSurface>* GLManager::base_surface_; 35scoped_refptr<gfx::GLContext>* GLManager::base_context_; 36 37GLManager::Options::Options() 38 : size(4, 4), 39 share_group_manager(NULL), 40 share_mailbox_manager(NULL), 41 virtual_manager(NULL), 42 bind_generates_resource(false), 43 lose_context_when_out_of_memory(false), 44 context_lost_allowed(false), 45 image_manager(NULL) {} 46 47GLManager::GLManager() 48 : context_lost_allowed_(false), gpu_memory_buffer_factory_(NULL) { 49 SetupBaseContext(); 50} 51 52GLManager::~GLManager() { 53 --use_count_; 54 if (!use_count_) { 55 if (base_share_group_) { 56 delete base_context_; 57 base_context_ = NULL; 58 } 59 if (base_surface_) { 60 delete base_surface_; 61 base_surface_ = NULL; 62 } 63 if (base_context_) { 64 delete base_context_; 65 base_context_ = NULL; 66 } 67 } 68} 69 70void GLManager::Initialize(const GLManager::Options& options) { 71 const int32 kCommandBufferSize = 1024 * 1024; 72 const size_t kStartTransferBufferSize = 4 * 1024 * 1024; 73 const size_t kMinTransferBufferSize = 1 * 256 * 1024; 74 const size_t kMaxTransferBufferSize = 16 * 1024 * 1024; 75 76 context_lost_allowed_ = options.context_lost_allowed; 77 78 gles2::MailboxManager* mailbox_manager = NULL; 79 if (options.share_mailbox_manager) { 80 mailbox_manager = options.share_mailbox_manager->mailbox_manager(); 81 } else if (options.share_group_manager) { 82 mailbox_manager = options.share_group_manager->mailbox_manager(); 83 } 84 85 gfx::GLShareGroup* share_group = NULL; 86 if (options.share_group_manager) { 87 share_group = options.share_group_manager->share_group(); 88 } else if (options.share_mailbox_manager) { 89 share_group = options.share_mailbox_manager->share_group(); 90 } 91 92 gles2::ContextGroup* context_group = NULL; 93 gles2::ShareGroup* client_share_group = NULL; 94 if (options.share_group_manager) { 95 context_group = options.share_group_manager->decoder_->GetContextGroup(); 96 client_share_group = 97 options.share_group_manager->gles2_implementation()->share_group(); 98 } 99 100 gfx::GLContext* real_gl_context = NULL; 101 if (options.virtual_manager) { 102 real_gl_context = options.virtual_manager->context(); 103 } 104 105 mailbox_manager_ = 106 mailbox_manager ? mailbox_manager : new gles2::MailboxManager; 107 share_group_ = 108 share_group ? share_group : new gfx::GLShareGroup; 109 110 gfx::GpuPreference gpu_preference(gfx::PreferDiscreteGpu); 111 std::vector<int32> attribs; 112 gles2::ContextCreationAttribHelper attrib_helper; 113 attrib_helper.red_size_ = 8; 114 attrib_helper.green_size_ = 8; 115 attrib_helper.blue_size_ = 8; 116 attrib_helper.alpha_size_ = 8; 117 attrib_helper.depth_size_ = 16; 118 attrib_helper.Serialize(&attribs); 119 120 if (!context_group) { 121 context_group = 122 new gles2::ContextGroup(mailbox_manager_.get(), 123 options.image_manager, 124 NULL, 125 new gpu::gles2::ShaderTranslatorCache, 126 NULL, 127 options.bind_generates_resource); 128 } 129 130 decoder_.reset(::gpu::gles2::GLES2Decoder::Create(context_group)); 131 132 command_buffer_.reset(new CommandBufferService( 133 decoder_->GetContextGroup()->transfer_buffer_manager())); 134 ASSERT_TRUE(command_buffer_->Initialize()) 135 << "could not create command buffer service"; 136 137 gpu_scheduler_.reset(new GpuScheduler(command_buffer_.get(), 138 decoder_.get(), 139 decoder_.get())); 140 141 decoder_->set_engine(gpu_scheduler_.get()); 142 143 surface_ = gfx::GLSurface::CreateOffscreenGLSurface(options.size); 144 ASSERT_TRUE(surface_.get() != NULL) << "could not create offscreen surface"; 145 146 if (base_context_) { 147 context_ = scoped_refptr<gfx::GLContext>(new gpu::GLContextVirtual( 148 share_group_.get(), base_context_->get(), decoder_->AsWeakPtr())); 149 ASSERT_TRUE(context_->Initialize( 150 surface_.get(), gfx::PreferIntegratedGpu)); 151 } else { 152 if (real_gl_context) { 153 context_ = scoped_refptr<gfx::GLContext>(new gpu::GLContextVirtual( 154 share_group_.get(), real_gl_context, decoder_->AsWeakPtr())); 155 ASSERT_TRUE(context_->Initialize( 156 surface_.get(), gfx::PreferIntegratedGpu)); 157 } else { 158 context_ = gfx::GLContext::CreateGLContext(share_group_.get(), 159 surface_.get(), 160 gpu_preference); 161 } 162 } 163 ASSERT_TRUE(context_.get() != NULL) << "could not create GL context"; 164 165 ASSERT_TRUE(context_->MakeCurrent(surface_.get())); 166 167 ASSERT_TRUE(decoder_->Initialize( 168 surface_.get(), 169 context_.get(), 170 true, 171 options.size, 172 ::gpu::gles2::DisallowedFeatures(), 173 attribs)) << "could not initialize decoder"; 174 175 gpu_control_service_.reset( 176 new GpuControlService(decoder_->GetContextGroup()->image_manager(), 177 decoder_->GetQueryManager())); 178 gpu_memory_buffer_factory_ = options.gpu_memory_buffer_factory; 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 // Create the object exposing the OpenGL API. 193 gles2_implementation_.reset( 194 new gles2::GLES2Implementation(gles2_helper_.get(), 195 client_share_group, 196 transfer_buffer_.get(), 197 options.bind_generates_resource, 198 options.lose_context_when_out_of_memory, 199 this)); 200 201 ASSERT_TRUE(gles2_implementation_->Initialize( 202 kStartTransferBufferSize, 203 kMinTransferBufferSize, 204 kMaxTransferBufferSize, 205 gpu::gles2::GLES2Implementation::kNoLimit)) 206 << "Could not init GLES2Implementation"; 207 208 MakeCurrent(); 209} 210 211void GLManager::SetupBaseContext() { 212 if (use_count_) { 213 #if defined(OS_ANDROID) 214 base_share_group_ = new scoped_refptr<gfx::GLShareGroup>( 215 new gfx::GLShareGroup); 216 gfx::Size size(4, 4); 217 base_surface_ = new scoped_refptr<gfx::GLSurface>( 218 gfx::GLSurface::CreateOffscreenGLSurface(size)); 219 gfx::GpuPreference gpu_preference(gfx::PreferDiscreteGpu); 220 base_context_ = new scoped_refptr<gfx::GLContext>( 221 gfx::GLContext::CreateGLContext(base_share_group_->get(), 222 base_surface_->get(), 223 gpu_preference)); 224 #endif 225 } 226 ++use_count_; 227} 228 229void GLManager::MakeCurrent() { 230 ::gles2::SetGLContext(gles2_implementation_.get()); 231} 232 233void GLManager::SetSurface(gfx::GLSurface* surface) { 234 decoder_->SetSurface(surface); 235} 236 237void GLManager::Destroy() { 238 if (gles2_implementation_.get()) { 239 MakeCurrent(); 240 EXPECT_TRUE(glGetError() == GL_NONE); 241 gles2_implementation_->Flush(); 242 gles2_implementation_.reset(); 243 } 244 transfer_buffer_.reset(); 245 gles2_helper_.reset(); 246 command_buffer_.reset(); 247 if (decoder_.get()) { 248 decoder_->MakeCurrent(); 249 decoder_->Destroy(true); 250 decoder_.reset(); 251 } 252} 253 254const gpu::gles2::FeatureInfo::Workarounds& GLManager::workarounds() const { 255 return decoder_->GetContextGroup()->feature_info()->workarounds(); 256} 257 258void GLManager::PumpCommands() { 259 decoder_->MakeCurrent(); 260 gpu_scheduler_->PutChanged(); 261 ::gpu::CommandBuffer::State state = command_buffer_->GetLastState(); 262 if (!context_lost_allowed_) { 263 ASSERT_EQ(::gpu::error::kNoError, state.error); 264 } 265} 266 267bool GLManager::GetBufferChanged(int32 transfer_buffer_id) { 268 return gpu_scheduler_->SetGetBuffer(transfer_buffer_id); 269} 270 271Capabilities GLManager::GetCapabilities() { 272 return decoder_->GetCapabilities(); 273} 274 275gfx::GpuMemoryBuffer* GLManager::CreateGpuMemoryBuffer( 276 size_t width, 277 size_t height, 278 unsigned internalformat, 279 unsigned usage, 280 int32* id) { 281 *id = -1; 282 scoped_ptr<gfx::GpuMemoryBuffer> buffer( 283 gpu_memory_buffer_factory_->CreateGpuMemoryBuffer( 284 width, height, internalformat, usage)); 285 if (!buffer.get()) 286 return NULL; 287 288 static int32 next_id = 1; 289 *id = next_id++; 290 gpu_control_service_->RegisterGpuMemoryBuffer( 291 *id, buffer->GetHandle(), width, height, internalformat); 292 gfx::GpuMemoryBuffer* raw_buffer = buffer.get(); 293 memory_buffers_.add(*id, buffer.Pass()); 294 return raw_buffer; 295} 296 297void GLManager::DestroyGpuMemoryBuffer(int32 id) { 298 memory_buffers_.erase(id); 299 gpu_control_service_->UnregisterGpuMemoryBuffer(id); 300} 301 302uint32 GLManager::InsertSyncPoint() { 303 NOTIMPLEMENTED(); 304 return 0u; 305} 306 307void GLManager::SignalSyncPoint(uint32 sync_point, 308 const base::Closure& callback) { 309 NOTIMPLEMENTED(); 310} 311 312void GLManager::SignalQuery(uint32 query, const base::Closure& callback) { 313 NOTIMPLEMENTED(); 314} 315 316void GLManager::SetSurfaceVisible(bool visible) { 317 NOTIMPLEMENTED(); 318} 319 320void GLManager::Echo(const base::Closure& callback) { 321 NOTIMPLEMENTED(); 322} 323 324uint32 GLManager::CreateStreamTexture(uint32 texture_id) { 325 NOTIMPLEMENTED(); 326 return 0; 327} 328 329} // namespace gpu 330