Home | History | Annotate | Download | only in tests
      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