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 <GLES2/gl2.h> 8#include <GLES2/gl2ext.h> 9 10#include <vector> 11 12#include "base/at_exit.h" 13#include "base/bind.h" 14#include "base/memory/ref_counted_memory.h" 15#include "gpu/command_buffer/client/gles2_implementation.h" 16#include "gpu/command_buffer/client/gles2_lib.h" 17#include "gpu/command_buffer/client/transfer_buffer.h" 18#include "gpu/command_buffer/common/constants.h" 19#include "gpu/command_buffer/common/gles2_cmd_utils.h" 20#include "gpu/command_buffer/service/command_buffer_service.h" 21#include "gpu/command_buffer/service/context_group.h" 22#include "gpu/command_buffer/service/gl_context_virtual.h" 23#include "gpu/command_buffer/service/gles2_cmd_decoder.h" 24#include "gpu/command_buffer/service/gpu_scheduler.h" 25#include "gpu/command_buffer/service/image_manager.h" 26#include "gpu/command_buffer/service/mailbox_manager.h" 27#include "gpu/command_buffer/service/memory_tracking.h" 28#include "testing/gtest/include/gtest/gtest.h" 29#include "ui/gfx/gpu_memory_buffer.h" 30#include "ui/gl/gl_context.h" 31#include "ui/gl/gl_image_ref_counted_memory.h" 32#include "ui/gl/gl_share_group.h" 33#include "ui/gl/gl_surface.h" 34 35namespace gpu { 36namespace { 37 38int BytesPerPixel(unsigned internalformat) { 39 switch (internalformat) { 40 case GL_RGBA8_OES: 41 return 4; 42 default: 43 NOTREACHED(); 44 return 0; 45 } 46} 47 48class GpuMemoryBufferImpl : public gfx::GpuMemoryBuffer { 49 public: 50 GpuMemoryBufferImpl(base::RefCountedBytes* bytes, 51 const gfx::Size& size, 52 unsigned internalformat) 53 : bytes_(bytes), 54 size_(size), 55 internalformat_(internalformat), 56 mapped_(false) {} 57 58 // Overridden from gfx::GpuMemoryBuffer: 59 virtual void* Map() OVERRIDE { 60 mapped_ = true; 61 return &bytes_->data().front(); 62 } 63 virtual void Unmap() OVERRIDE { mapped_ = false; } 64 virtual bool IsMapped() const OVERRIDE { return mapped_; } 65 virtual uint32 GetStride() const OVERRIDE { 66 return size_.width() * BytesPerPixel(internalformat_); 67 } 68 virtual gfx::GpuMemoryBufferHandle GetHandle() const OVERRIDE { 69 NOTREACHED(); 70 return gfx::GpuMemoryBufferHandle(); 71 } 72 73 private: 74 scoped_refptr<base::RefCountedBytes> bytes_; 75 const gfx::Size size_; 76 unsigned internalformat_; 77 bool mapped_; 78}; 79 80} // namespace 81 82int GLManager::use_count_; 83scoped_refptr<gfx::GLShareGroup>* GLManager::base_share_group_; 84scoped_refptr<gfx::GLSurface>* GLManager::base_surface_; 85scoped_refptr<gfx::GLContext>* GLManager::base_context_; 86 87GLManager::Options::Options() 88 : size(4, 4), 89 share_group_manager(NULL), 90 share_mailbox_manager(NULL), 91 virtual_manager(NULL), 92 bind_generates_resource(false), 93 lose_context_when_out_of_memory(false), 94 context_lost_allowed(false) { 95} 96 97GLManager::GLManager() : context_lost_allowed_(false) { 98 SetupBaseContext(); 99} 100 101GLManager::~GLManager() { 102 --use_count_; 103 if (!use_count_) { 104 if (base_share_group_) { 105 delete base_context_; 106 base_context_ = NULL; 107 } 108 if (base_surface_) { 109 delete base_surface_; 110 base_surface_ = NULL; 111 } 112 if (base_context_) { 113 delete base_context_; 114 base_context_ = NULL; 115 } 116 } 117} 118 119void GLManager::Initialize(const GLManager::Options& options) { 120 const int32 kCommandBufferSize = 1024 * 1024; 121 const size_t kStartTransferBufferSize = 4 * 1024 * 1024; 122 const size_t kMinTransferBufferSize = 1 * 256 * 1024; 123 const size_t kMaxTransferBufferSize = 16 * 1024 * 1024; 124 125 context_lost_allowed_ = options.context_lost_allowed; 126 127 gles2::MailboxManager* mailbox_manager = NULL; 128 if (options.share_mailbox_manager) { 129 mailbox_manager = options.share_mailbox_manager->mailbox_manager(); 130 } else if (options.share_group_manager) { 131 mailbox_manager = options.share_group_manager->mailbox_manager(); 132 } 133 134 gfx::GLShareGroup* share_group = NULL; 135 if (options.share_group_manager) { 136 share_group = options.share_group_manager->share_group(); 137 } else if (options.share_mailbox_manager) { 138 share_group = options.share_mailbox_manager->share_group(); 139 } 140 141 gles2::ContextGroup* context_group = NULL; 142 gles2::ShareGroup* client_share_group = NULL; 143 if (options.share_group_manager) { 144 context_group = options.share_group_manager->decoder_->GetContextGroup(); 145 client_share_group = 146 options.share_group_manager->gles2_implementation()->share_group(); 147 } 148 149 gfx::GLContext* real_gl_context = NULL; 150 if (options.virtual_manager) { 151 real_gl_context = options.virtual_manager->context(); 152 } 153 154 mailbox_manager_ = 155 mailbox_manager ? mailbox_manager : new gles2::MailboxManager; 156 share_group_ = 157 share_group ? share_group : new gfx::GLShareGroup; 158 159 gfx::GpuPreference gpu_preference(gfx::PreferDiscreteGpu); 160 std::vector<int32> attribs; 161 gles2::ContextCreationAttribHelper attrib_helper; 162 attrib_helper.red_size = 8; 163 attrib_helper.green_size = 8; 164 attrib_helper.blue_size = 8; 165 attrib_helper.alpha_size = 8; 166 attrib_helper.depth_size = 16; 167 attrib_helper.Serialize(&attribs); 168 169 if (!context_group) { 170 context_group = 171 new gles2::ContextGroup(mailbox_manager_.get(), 172 NULL, 173 new gpu::gles2::ShaderTranslatorCache, 174 NULL, 175 options.bind_generates_resource); 176 } 177 178 decoder_.reset(::gpu::gles2::GLES2Decoder::Create(context_group)); 179 180 command_buffer_.reset(new CommandBufferService( 181 decoder_->GetContextGroup()->transfer_buffer_manager())); 182 ASSERT_TRUE(command_buffer_->Initialize()) 183 << "could not create command buffer service"; 184 185 gpu_scheduler_.reset(new GpuScheduler(command_buffer_.get(), 186 decoder_.get(), 187 decoder_.get())); 188 189 decoder_->set_engine(gpu_scheduler_.get()); 190 191 surface_ = gfx::GLSurface::CreateOffscreenGLSurface(options.size); 192 ASSERT_TRUE(surface_.get() != NULL) << "could not create offscreen surface"; 193 194 if (base_context_) { 195 context_ = scoped_refptr<gfx::GLContext>(new gpu::GLContextVirtual( 196 share_group_.get(), base_context_->get(), decoder_->AsWeakPtr())); 197 ASSERT_TRUE(context_->Initialize( 198 surface_.get(), gfx::PreferIntegratedGpu)); 199 } else { 200 if (real_gl_context) { 201 context_ = scoped_refptr<gfx::GLContext>(new gpu::GLContextVirtual( 202 share_group_.get(), real_gl_context, decoder_->AsWeakPtr())); 203 ASSERT_TRUE(context_->Initialize( 204 surface_.get(), gfx::PreferIntegratedGpu)); 205 } else { 206 context_ = gfx::GLContext::CreateGLContext(share_group_.get(), 207 surface_.get(), 208 gpu_preference); 209 } 210 } 211 ASSERT_TRUE(context_.get() != NULL) << "could not create GL context"; 212 213 ASSERT_TRUE(context_->MakeCurrent(surface_.get())); 214 215 ASSERT_TRUE(decoder_->Initialize( 216 surface_.get(), 217 context_.get(), 218 true, 219 options.size, 220 ::gpu::gles2::DisallowedFeatures(), 221 attribs)) << "could not initialize decoder"; 222 223 command_buffer_->SetPutOffsetChangeCallback( 224 base::Bind(&GLManager::PumpCommands, base::Unretained(this))); 225 command_buffer_->SetGetBufferChangeCallback( 226 base::Bind(&GLManager::GetBufferChanged, base::Unretained(this))); 227 228 // Create the GLES2 helper, which writes the command buffer protocol. 229 gles2_helper_.reset(new gles2::GLES2CmdHelper(command_buffer_.get())); 230 ASSERT_TRUE(gles2_helper_->Initialize(kCommandBufferSize)); 231 232 // Create a transfer buffer. 233 transfer_buffer_.reset(new TransferBuffer(gles2_helper_.get())); 234 235 // Create the object exposing the OpenGL API. 236 gles2_implementation_.reset( 237 new gles2::GLES2Implementation(gles2_helper_.get(), 238 client_share_group, 239 transfer_buffer_.get(), 240 options.bind_generates_resource, 241 options.lose_context_when_out_of_memory, 242 this)); 243 244 ASSERT_TRUE(gles2_implementation_->Initialize( 245 kStartTransferBufferSize, 246 kMinTransferBufferSize, 247 kMaxTransferBufferSize, 248 gpu::gles2::GLES2Implementation::kNoLimit)) 249 << "Could not init GLES2Implementation"; 250 251 MakeCurrent(); 252} 253 254void GLManager::SetupBaseContext() { 255 if (use_count_) { 256 #if defined(OS_ANDROID) 257 base_share_group_ = new scoped_refptr<gfx::GLShareGroup>( 258 new gfx::GLShareGroup); 259 gfx::Size size(4, 4); 260 base_surface_ = new scoped_refptr<gfx::GLSurface>( 261 gfx::GLSurface::CreateOffscreenGLSurface(size)); 262 gfx::GpuPreference gpu_preference(gfx::PreferDiscreteGpu); 263 base_context_ = new scoped_refptr<gfx::GLContext>( 264 gfx::GLContext::CreateGLContext(base_share_group_->get(), 265 base_surface_->get(), 266 gpu_preference)); 267 #endif 268 } 269 ++use_count_; 270} 271 272void GLManager::MakeCurrent() { 273 ::gles2::SetGLContext(gles2_implementation_.get()); 274} 275 276void GLManager::SetSurface(gfx::GLSurface* surface) { 277 decoder_->SetSurface(surface); 278} 279 280void GLManager::Destroy() { 281 if (gles2_implementation_.get()) { 282 MakeCurrent(); 283 EXPECT_TRUE(glGetError() == GL_NONE); 284 gles2_implementation_->Flush(); 285 gles2_implementation_.reset(); 286 } 287 transfer_buffer_.reset(); 288 gles2_helper_.reset(); 289 command_buffer_.reset(); 290 if (decoder_.get()) { 291 decoder_->MakeCurrent(); 292 decoder_->Destroy(true); 293 decoder_.reset(); 294 } 295} 296 297const gpu::gles2::FeatureInfo::Workarounds& GLManager::workarounds() const { 298 return decoder_->GetContextGroup()->feature_info()->workarounds(); 299} 300 301void GLManager::PumpCommands() { 302 decoder_->MakeCurrent(); 303 gpu_scheduler_->PutChanged(); 304 ::gpu::CommandBuffer::State state = command_buffer_->GetLastState(); 305 if (!context_lost_allowed_) { 306 ASSERT_EQ(::gpu::error::kNoError, state.error); 307 } 308} 309 310bool GLManager::GetBufferChanged(int32 transfer_buffer_id) { 311 return gpu_scheduler_->SetGetBuffer(transfer_buffer_id); 312} 313 314Capabilities GLManager::GetCapabilities() { 315 return decoder_->GetCapabilities(); 316} 317 318gfx::GpuMemoryBuffer* GLManager::CreateGpuMemoryBuffer( 319 size_t width, 320 size_t height, 321 unsigned internalformat, 322 unsigned usage, 323 int32* id) { 324 gfx::Size size(width, height); 325 326 *id = -1; 327 328 std::vector<unsigned char> data( 329 size.GetArea() * BytesPerPixel(internalformat), 0); 330 scoped_refptr<base::RefCountedBytes> bytes(new base::RefCountedBytes(data)); 331 scoped_ptr<gfx::GpuMemoryBuffer> buffer( 332 new GpuMemoryBufferImpl(bytes.get(), size, internalformat)); 333 334 static int32 next_id = 1; 335 int32 new_id = next_id++; 336 337 scoped_refptr<gfx::GLImageRefCountedMemory> image( 338 new gfx::GLImageRefCountedMemory(size, internalformat)); 339 if (!image->Initialize(bytes.get())) 340 return NULL; 341 342 gpu::gles2::ImageManager* image_manager = decoder_->GetImageManager(); 343 DCHECK(image_manager); 344 image_manager->AddImage(image.get(), new_id); 345 346 *id = new_id; 347 DCHECK(gpu_memory_buffers_.find(new_id) == gpu_memory_buffers_.end()); 348 return gpu_memory_buffers_.add(new_id, buffer.Pass()).first->second; 349} 350 351void GLManager::DestroyGpuMemoryBuffer(int32 id) { 352 gpu::gles2::ImageManager* image_manager = decoder_->GetImageManager(); 353 DCHECK(image_manager); 354 image_manager->RemoveImage(id); 355 356 gpu_memory_buffers_.erase(id); 357} 358 359uint32 GLManager::InsertSyncPoint() { 360 NOTIMPLEMENTED(); 361 return 0u; 362} 363 364uint32 GLManager::InsertFutureSyncPoint() { 365 NOTIMPLEMENTED(); 366 return 0u; 367} 368 369void GLManager::RetireSyncPoint(uint32 sync_point) { 370 NOTIMPLEMENTED(); 371} 372 373void GLManager::SignalSyncPoint(uint32 sync_point, 374 const base::Closure& callback) { 375 NOTIMPLEMENTED(); 376} 377 378void GLManager::SignalQuery(uint32 query, const base::Closure& callback) { 379 NOTIMPLEMENTED(); 380} 381 382void GLManager::SetSurfaceVisible(bool visible) { 383 NOTIMPLEMENTED(); 384} 385 386void GLManager::Echo(const base::Closure& callback) { 387 NOTIMPLEMENTED(); 388} 389 390uint32 GLManager::CreateStreamTexture(uint32 texture_id) { 391 NOTIMPLEMENTED(); 392 return 0; 393} 394 395} // namespace gpu 396