Home | History | Annotate | Download | only in egl
      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/gles2_conform_support/egl/display.h"
      6 
      7 #include <vector>
      8 #include "base/bind.h"
      9 #include "base/bind_helpers.h"
     10 #include "gpu/command_buffer/client/gles2_implementation.h"
     11 #include "gpu/command_buffer/client/gles2_lib.h"
     12 #include "gpu/command_buffer/client/transfer_buffer.h"
     13 #include "gpu/command_buffer/service/context_group.h"
     14 #include "gpu/command_buffer/service/mailbox_manager.h"
     15 #include "gpu/command_buffer/service/memory_tracking.h"
     16 #include "gpu/command_buffer/service/transfer_buffer_manager.h"
     17 #include "gpu/gles2_conform_support/egl/config.h"
     18 #include "gpu/gles2_conform_support/egl/surface.h"
     19 
     20 namespace {
     21 const int32 kCommandBufferSize = 1024 * 1024;
     22 const int32 kTransferBufferSize = 512 * 1024;
     23 }
     24 
     25 namespace egl {
     26 
     27 Display::Display(EGLNativeDisplayType display_id)
     28     : display_id_(display_id),
     29       is_initialized_(false),
     30       create_offscreen_(false),
     31       create_offscreen_width_(0),
     32       create_offscreen_height_(0) {
     33 }
     34 
     35 Display::~Display() {
     36   gles2::Terminate();
     37 }
     38 
     39 bool Display::Initialize() {
     40   gles2::Initialize();
     41   is_initialized_ = true;
     42   return true;
     43 }
     44 
     45 bool Display::IsValidConfig(EGLConfig config) {
     46   return (config != NULL) && (config == config_.get());
     47 }
     48 
     49 bool Display::ChooseConfigs(EGLConfig* configs,
     50                             EGLint config_size,
     51                             EGLint* num_config) {
     52   // TODO(alokp): Find out a way to find all configs. CommandBuffer currently
     53   // does not support finding or choosing configs.
     54   *num_config = 1;
     55   if (configs != NULL) {
     56     if (config_ == NULL) {
     57       config_.reset(new Config);
     58     }
     59     configs[0] = config_.get();
     60   }
     61   return true;
     62 }
     63 
     64 bool Display::GetConfigs(EGLConfig* configs,
     65                          EGLint config_size,
     66                          EGLint* num_config) {
     67   // TODO(alokp): Find out a way to find all configs. CommandBuffer currently
     68   // does not support finding or choosing configs.
     69   *num_config = 1;
     70   if (configs != NULL) {
     71     if (config_ == NULL) {
     72       config_.reset(new Config);
     73     }
     74     configs[0] = config_.get();
     75   }
     76   return true;
     77 }
     78 
     79 bool Display::GetConfigAttrib(EGLConfig config,
     80                               EGLint attribute,
     81                               EGLint* value) {
     82   const egl::Config* cfg = static_cast<egl::Config*>(config);
     83   return cfg->GetAttrib(attribute, value);
     84 }
     85 
     86 bool Display::IsValidNativeWindow(EGLNativeWindowType win) {
     87 #if defined OS_WIN
     88   return ::IsWindow(win) != FALSE;
     89 #else
     90   // TODO(alokp): Validate window handle.
     91   return true;
     92 #endif  // OS_WIN
     93 }
     94 
     95 bool Display::IsValidSurface(EGLSurface surface) {
     96   return (surface != NULL) && (surface == surface_.get());
     97 }
     98 
     99 EGLSurface Display::CreateWindowSurface(EGLConfig config,
    100                                         EGLNativeWindowType win,
    101                                         const EGLint* attrib_list) {
    102   if (surface_ != NULL) {
    103     // We do not support more than one window surface.
    104     return EGL_NO_SURFACE;
    105   }
    106 
    107   {
    108     gpu::TransferBufferManager* manager = new gpu::TransferBufferManager();
    109     transfer_buffer_manager_.reset(manager);
    110     manager->Initialize();
    111   }
    112   scoped_ptr<gpu::CommandBufferService> command_buffer(
    113       new gpu::CommandBufferService(transfer_buffer_manager_.get()));
    114   if (!command_buffer->Initialize())
    115     return NULL;
    116 
    117   scoped_refptr<gpu::gles2::ContextGroup> group(new gpu::gles2::ContextGroup(
    118       NULL, NULL, new gpu::gles2::ShaderTranslatorCache, NULL, true));
    119 
    120   decoder_.reset(gpu::gles2::GLES2Decoder::Create(group.get()));
    121   if (!decoder_.get())
    122     return EGL_NO_SURFACE;
    123 
    124   gpu_scheduler_.reset(new gpu::GpuScheduler(command_buffer.get(),
    125                                              decoder_.get(),
    126                                              NULL));
    127 
    128   decoder_->set_engine(gpu_scheduler_.get());
    129   gfx::Size size(create_offscreen_width_, create_offscreen_height_);
    130   if (create_offscreen_) {
    131     gl_surface_ = gfx::GLSurface::CreateOffscreenGLSurface(size);
    132     create_offscreen_ = false;
    133     create_offscreen_width_ = 0;
    134     create_offscreen_height_ = 0;
    135   } else {
    136     gl_surface_ = gfx::GLSurface::CreateViewGLSurface(win);
    137   }
    138   if (!gl_surface_.get())
    139     return EGL_NO_SURFACE;
    140 
    141   gl_context_ = gfx::GLContext::CreateGLContext(NULL,
    142                                                 gl_surface_.get(),
    143                                                 gfx::PreferDiscreteGpu);
    144   if (!gl_context_.get())
    145     return EGL_NO_SURFACE;
    146 
    147   gl_context_->MakeCurrent(gl_surface_.get());
    148 
    149   EGLint depth_size = 0;
    150   EGLint alpha_size = 0;
    151   EGLint stencil_size = 0;
    152   GetConfigAttrib(config, EGL_DEPTH_SIZE, &depth_size);
    153   GetConfigAttrib(config, EGL_ALPHA_SIZE, &alpha_size);
    154   GetConfigAttrib(config, EGL_STENCIL_SIZE, &stencil_size);
    155   std::vector<int32> attribs;
    156   attribs.push_back(EGL_DEPTH_SIZE);
    157   attribs.push_back(depth_size);
    158   attribs.push_back(EGL_ALPHA_SIZE);
    159   attribs.push_back(alpha_size);
    160   attribs.push_back(EGL_STENCIL_SIZE);
    161   attribs.push_back(stencil_size);
    162   // TODO(gman): Insert attrib_list. Although ES 1.1 says it must be null
    163   attribs.push_back(EGL_NONE);
    164 
    165   if (!decoder_->Initialize(gl_surface_.get(),
    166                             gl_context_.get(),
    167                             gl_surface_->IsOffscreen(),
    168                             size,
    169                             gpu::gles2::DisallowedFeatures(),
    170                             attribs)) {
    171     return EGL_NO_SURFACE;
    172   }
    173 
    174   command_buffer->SetPutOffsetChangeCallback(
    175       base::Bind(&gpu::GpuScheduler::PutChanged,
    176                  base::Unretained(gpu_scheduler_.get())));
    177   command_buffer->SetGetBufferChangeCallback(
    178       base::Bind(&gpu::GpuScheduler::SetGetBuffer,
    179                  base::Unretained(gpu_scheduler_.get())));
    180 
    181   scoped_ptr<gpu::gles2::GLES2CmdHelper> cmd_helper(
    182       new gpu::gles2::GLES2CmdHelper(command_buffer.get()));
    183   if (!cmd_helper->Initialize(kCommandBufferSize))
    184     return NULL;
    185 
    186   scoped_ptr<gpu::TransferBuffer> transfer_buffer(new gpu::TransferBuffer(
    187       cmd_helper.get()));
    188 
    189   command_buffer_.reset(command_buffer.release());
    190   transfer_buffer_.reset(transfer_buffer.release());
    191   gles2_cmd_helper_.reset(cmd_helper.release());
    192   surface_.reset(new Surface(win));
    193 
    194   return surface_.get();
    195 }
    196 
    197 void Display::DestroySurface(EGLSurface surface) {
    198   DCHECK(IsValidSurface(surface));
    199   gpu_scheduler_.reset();
    200   if (decoder_.get()) {
    201     decoder_->Destroy(true);
    202   }
    203   decoder_.reset();
    204   gl_surface_ = NULL;
    205   gl_context_ = NULL;
    206   surface_.reset();
    207 }
    208 
    209 void Display::SwapBuffers(EGLSurface surface) {
    210   DCHECK(IsValidSurface(surface));
    211   context_->SwapBuffers();
    212 }
    213 
    214 bool Display::IsValidContext(EGLContext ctx) {
    215   return (ctx != NULL) && (ctx == context_.get());
    216 }
    217 
    218 EGLContext Display::CreateContext(EGLConfig config,
    219                                   EGLContext share_ctx,
    220                                   const EGLint* attrib_list) {
    221   DCHECK(IsValidConfig(config));
    222   // TODO(alokp): Add support for shared contexts.
    223   if (share_ctx != NULL)
    224     return EGL_NO_CONTEXT;
    225 
    226   DCHECK(command_buffer_ != NULL);
    227   DCHECK(transfer_buffer_.get());
    228 
    229   bool bind_generates_resources = true;
    230   bool lose_context_when_out_of_memory = false;
    231 
    232   context_.reset(
    233       new gpu::gles2::GLES2Implementation(gles2_cmd_helper_.get(),
    234                                           NULL,
    235                                           transfer_buffer_.get(),
    236                                           bind_generates_resources,
    237                                           lose_context_when_out_of_memory,
    238                                           this));
    239 
    240   if (!context_->Initialize(
    241       kTransferBufferSize,
    242       kTransferBufferSize / 2,
    243       kTransferBufferSize * 2,
    244       gpu::gles2::GLES2Implementation::kNoLimit)) {
    245     return EGL_NO_CONTEXT;
    246   }
    247 
    248   context_->EnableFeatureCHROMIUM("pepper3d_allow_buffers_on_multiple_targets");
    249   context_->EnableFeatureCHROMIUM("pepper3d_support_fixed_attribs");
    250 
    251   return context_.get();
    252 }
    253 
    254 void Display::DestroyContext(EGLContext ctx) {
    255   DCHECK(IsValidContext(ctx));
    256   context_.reset();
    257   transfer_buffer_.reset();
    258 }
    259 
    260 bool Display::MakeCurrent(EGLSurface draw, EGLSurface read, EGLContext ctx) {
    261   if (ctx == EGL_NO_CONTEXT) {
    262     gles2::SetGLContext(NULL);
    263   } else {
    264     DCHECK(IsValidSurface(draw));
    265     DCHECK(IsValidSurface(read));
    266     DCHECK(IsValidContext(ctx));
    267     gles2::SetGLContext(context_.get());
    268   }
    269   return true;
    270 }
    271 
    272 gpu::Capabilities Display::GetCapabilities() {
    273   return decoder_->GetCapabilities();
    274 }
    275 
    276 gfx::GpuMemoryBuffer* Display::CreateGpuMemoryBuffer(
    277     size_t width,
    278     size_t height,
    279     unsigned internalformat,
    280     unsigned usage,
    281     int32* id) {
    282   NOTIMPLEMENTED();
    283   return NULL;
    284 }
    285 
    286 void Display::DestroyGpuMemoryBuffer(int32 id) {
    287   NOTIMPLEMENTED();
    288 }
    289 
    290 uint32 Display::InsertSyncPoint() {
    291   NOTIMPLEMENTED();
    292   return 0u;
    293 }
    294 
    295 uint32 Display::InsertFutureSyncPoint() {
    296   NOTIMPLEMENTED();
    297   return 0u;
    298 }
    299 
    300 void Display::RetireSyncPoint(uint32 sync_point) {
    301   NOTIMPLEMENTED();
    302 }
    303 
    304 void Display::SignalSyncPoint(uint32 sync_point,
    305                               const base::Closure& callback) {
    306   NOTIMPLEMENTED();
    307 }
    308 
    309 void Display::SignalQuery(uint32 query, const base::Closure& callback) {
    310   NOTIMPLEMENTED();
    311 }
    312 
    313 void Display::SetSurfaceVisible(bool visible) {
    314   NOTIMPLEMENTED();
    315 }
    316 
    317 void Display::Echo(const base::Closure& callback) {
    318   NOTIMPLEMENTED();
    319 }
    320 
    321 uint32 Display::CreateStreamTexture(uint32 texture_id) {
    322   NOTIMPLEMENTED();
    323   return 0;
    324 }
    325 
    326 }  // namespace egl
    327