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/service/command_buffer_service.h" 16 #include "gpu/command_buffer/service/context_group.h" 17 #include "gpu/command_buffer/service/gl_context_virtual.h" 18 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" 19 #include "gpu/command_buffer/service/gpu_scheduler.h" 20 #include "gpu/command_buffer/service/image_manager.h" 21 #include "gpu/command_buffer/service/mailbox_manager.h" 22 #include "testing/gtest/include/gtest/gtest.h" 23 #include "ui/gl/gl_context.h" 24 #include "ui/gl/gl_share_group.h" 25 #include "ui/gl/gl_surface.h" 26 27 namespace gpu { 28 29 int GLManager::use_count_; 30 scoped_refptr<gfx::GLShareGroup>* GLManager::base_share_group_; 31 scoped_refptr<gfx::GLSurface>* GLManager::base_surface_; 32 scoped_refptr<gfx::GLContext>* GLManager::base_context_; 33 34 GLManager::Options::Options() 35 : size(4, 4), 36 share_group_manager(NULL), 37 share_mailbox_manager(NULL), 38 virtual_manager(NULL), 39 bind_generates_resource(false), 40 context_lost_allowed(false), 41 image_manager(NULL), 42 image_factory(NULL) { 43 } 44 45 GLManager::GLManager() 46 : context_lost_allowed_(false) { 47 SetupBaseContext(); 48 } 49 50 GLManager::~GLManager() { 51 --use_count_; 52 if (!use_count_) { 53 if (base_share_group_) { 54 delete base_context_; 55 base_context_ = NULL; 56 } 57 if (base_surface_) { 58 delete base_surface_; 59 base_surface_ = NULL; 60 } 61 if (base_context_) { 62 delete base_context_; 63 base_context_ = NULL; 64 } 65 } 66 } 67 68 void GLManager::Initialize(const GLManager::Options& options) { 69 const int32 kCommandBufferSize = 1024 * 1024; 70 const size_t kStartTransferBufferSize = 4 * 1024 * 1024; 71 const size_t kMinTransferBufferSize = 1 * 256 * 1024; 72 const size_t kMaxTransferBufferSize = 16 * 1024 * 1024; 73 74 context_lost_allowed_ = options.context_lost_allowed; 75 76 gles2::MailboxManager* mailbox_manager = NULL; 77 if (options.share_mailbox_manager) { 78 mailbox_manager = options.share_mailbox_manager->mailbox_manager(); 79 } else if (options.share_group_manager) { 80 mailbox_manager = options.share_group_manager->mailbox_manager(); 81 } 82 83 gfx::GLShareGroup* share_group = NULL; 84 if (options.share_group_manager) { 85 share_group = options.share_group_manager->share_group(); 86 } else if (options.share_mailbox_manager) { 87 share_group = options.share_mailbox_manager->share_group(); 88 } 89 90 gles2::ContextGroup* context_group = NULL; 91 gles2::ShareGroup* client_share_group = NULL; 92 if (options.share_group_manager) { 93 context_group = options.share_group_manager->decoder_->GetContextGroup(); 94 client_share_group = 95 options.share_group_manager->gles2_implementation()->share_group(); 96 } 97 98 gfx::GLContext* real_gl_context = NULL; 99 if (options.virtual_manager) { 100 real_gl_context = options.virtual_manager->context(); 101 } 102 103 // From <EGL/egl.h>. 104 const int32 EGL_ALPHA_SIZE = 0x3021; 105 const int32 EGL_BLUE_SIZE = 0x3022; 106 const int32 EGL_GREEN_SIZE = 0x3023; 107 const int32 EGL_RED_SIZE = 0x3024; 108 const int32 EGL_DEPTH_SIZE = 0x3025; 109 const int32 EGL_NONE = 0x3038; 110 111 mailbox_manager_ = 112 mailbox_manager ? mailbox_manager : new gles2::MailboxManager; 113 share_group_ = 114 share_group ? share_group : new gfx::GLShareGroup; 115 116 gfx::GpuPreference gpu_preference(gfx::PreferDiscreteGpu); 117 const char* allowed_extensions = "*"; 118 std::vector<int32> attribs; 119 attribs.push_back(EGL_RED_SIZE); 120 attribs.push_back(8); 121 attribs.push_back(EGL_GREEN_SIZE); 122 attribs.push_back(8); 123 attribs.push_back(EGL_BLUE_SIZE); 124 attribs.push_back(8); 125 attribs.push_back(EGL_ALPHA_SIZE); 126 attribs.push_back(8); 127 attribs.push_back(EGL_DEPTH_SIZE); 128 attribs.push_back(16); 129 attribs.push_back(EGL_NONE); 130 131 if (!context_group) { 132 context_group = new gles2::ContextGroup(mailbox_manager_.get(), 133 options.image_manager, 134 NULL, 135 NULL, 136 options.bind_generates_resource); 137 } 138 139 decoder_.reset(::gpu::gles2::GLES2Decoder::Create(context_group)); 140 141 command_buffer_.reset(new CommandBufferService( 142 decoder_->GetContextGroup()->transfer_buffer_manager())); 143 ASSERT_TRUE(command_buffer_->Initialize()) 144 << "could not create command buffer service"; 145 146 gpu_scheduler_.reset(new GpuScheduler(command_buffer_.get(), 147 decoder_.get(), 148 decoder_.get())); 149 150 decoder_->set_engine(gpu_scheduler_.get()); 151 152 surface_ = gfx::GLSurface::CreateOffscreenGLSurface(options.size); 153 ASSERT_TRUE(surface_.get() != NULL) << "could not create offscreen surface"; 154 155 if (real_gl_context) { 156 context_ = scoped_refptr<gfx::GLContext>(new gpu::GLContextVirtual( 157 share_group_.get(), real_gl_context, decoder_->AsWeakPtr())); 158 ASSERT_TRUE(context_->Initialize( 159 surface_.get(), gfx::PreferIntegratedGpu)); 160 } else { 161 if (base_context_) { 162 context_ = scoped_refptr<gfx::GLContext>(new gpu::GLContextVirtual( 163 share_group_.get(), base_context_->get(), decoder_->AsWeakPtr())); 164 ASSERT_TRUE(context_->Initialize( 165 surface_.get(), gfx::PreferIntegratedGpu)); 166 } else { 167 context_ = gfx::GLContext::CreateGLContext(share_group_.get(), 168 surface_.get(), 169 gpu_preference); 170 } 171 } 172 ASSERT_TRUE(context_.get() != NULL) << "could not create GL context"; 173 174 ASSERT_TRUE(context_->MakeCurrent(surface_.get())); 175 176 ASSERT_TRUE(decoder_->Initialize( 177 surface_.get(), 178 context_.get(), 179 true, 180 options.size, 181 ::gpu::gles2::DisallowedFeatures(), 182 allowed_extensions, 183 attribs)) << "could not initialize decoder"; 184 185 command_buffer_->SetPutOffsetChangeCallback( 186 base::Bind(&GLManager::PumpCommands, base::Unretained(this))); 187 command_buffer_->SetGetBufferChangeCallback( 188 base::Bind(&GLManager::GetBufferChanged, base::Unretained(this))); 189 190 // Create the GLES2 helper, which writes the command buffer protocol. 191 gles2_helper_.reset(new gles2::GLES2CmdHelper(command_buffer_.get())); 192 ASSERT_TRUE(gles2_helper_->Initialize(kCommandBufferSize)); 193 194 // Create a transfer buffer. 195 transfer_buffer_.reset(new TransferBuffer(gles2_helper_.get())); 196 197 // Create the object exposing the OpenGL API. 198 gles2_implementation_.reset(new gles2::GLES2Implementation( 199 gles2_helper_.get(), 200 client_share_group, 201 transfer_buffer_.get(), 202 options.bind_generates_resource, 203 options.image_factory)); 204 205 ASSERT_TRUE(gles2_implementation_->Initialize( 206 kStartTransferBufferSize, 207 kMinTransferBufferSize, 208 kMaxTransferBufferSize)) << "Could not init GLES2Implementation"; 209 210 MakeCurrent(); 211 } 212 213 void 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 231 void GLManager::MakeCurrent() { 232 ::gles2::SetGLContext(gles2_implementation_.get()); 233 } 234 235 void GLManager::SetSurface(gfx::GLSurface* surface) { 236 decoder_->SetSurface(surface); 237 } 238 239 void 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 256 const gpu::gles2::FeatureInfo::Workarounds& GLManager::workarounds() const { 257 return decoder_->GetContextGroup()->feature_info()->workarounds(); 258 } 259 260 void 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 269 bool GLManager::GetBufferChanged(int32 transfer_buffer_id) { 270 return gpu_scheduler_->SetGetBuffer(transfer_buffer_id); 271 } 272 273 } // namespace gpu 274