Home | History | Annotate | Download | only in dri
      1 // Copyright 2014 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 "ui/ozone/platform/dri/gbm_surface.h"
      6 
      7 #include <gbm.h>
      8 
      9 #include "base/logging.h"
     10 #include "third_party/skia/include/core/SkImageInfo.h"
     11 #include "ui/ozone/platform/dri/buffer_data.h"
     12 #include "ui/ozone/platform/dri/dri_buffer.h"
     13 #include "ui/ozone/platform/dri/dri_wrapper.h"
     14 #include "ui/ozone/platform/dri/hardware_display_controller.h"
     15 
     16 namespace ui {
     17 
     18 GbmSurface::GbmSurface(gbm_device* device,
     19                        DriWrapper* dri,
     20                        const gfx::Size& size)
     21     : gbm_device_(device),
     22       dri_(dri),
     23       size_(size),
     24       native_surface_(NULL),
     25       buffers_(),
     26       front_buffer_(0) {
     27   for (size_t i = 0; i < arraysize(buffers_); ++i)
     28     buffers_[i] = NULL;
     29 }
     30 
     31 GbmSurface::~GbmSurface() {
     32   for (size_t i = 0; i < arraysize(buffers_); ++i) {
     33     if (buffers_[i]) {
     34       gbm_surface_release_buffer(native_surface_, buffers_[i]);
     35     }
     36   }
     37 
     38   if (native_surface_)
     39     gbm_surface_destroy(native_surface_);
     40 }
     41 
     42 bool GbmSurface::Initialize() {
     43   // TODO(dnicoara) Check underlying system support for pixel format.
     44   native_surface_ = gbm_surface_create(
     45       gbm_device_,
     46       size_.width(),
     47       size_.height(),
     48       GBM_BO_FORMAT_XRGB8888,
     49       GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
     50 
     51   if (!native_surface_)
     52     return false;
     53 
     54   dumb_buffer_.reset(new DriBuffer(dri_));
     55   if (!dumb_buffer_->Initialize(SkImageInfo::MakeN32Premul(size_.width(),
     56                                                            size_.height())))
     57     return false;
     58 
     59   return true;
     60 }
     61 
     62 uint32_t GbmSurface::GetFramebufferId() const {
     63   if (!buffers_[front_buffer_ ^ 1])
     64     return dumb_buffer_->framebuffer();
     65 
     66   BufferData* data = BufferData::GetData(buffers_[front_buffer_ ^ 1]);
     67   CHECK(data);
     68   return data->framebuffer();
     69 }
     70 
     71 uint32_t GbmSurface::GetHandle() const {
     72   if (!buffers_[front_buffer_ ^ 1])
     73     return dumb_buffer_->handle();
     74 
     75   BufferData* data = BufferData::GetData(buffers_[front_buffer_ ^ 1]);
     76   CHECK(data);
     77   return data->handle();
     78 }
     79 
     80 gfx::Size GbmSurface::Size() const {
     81   return size_;
     82 }
     83 
     84 void GbmSurface::SwapBuffers() {
     85   // If there was a frontbuffer, is no longer active. Release it back to GBM.
     86   if (buffers_[front_buffer_])
     87     gbm_surface_release_buffer(native_surface_, buffers_[front_buffer_]);
     88 
     89   // Update the index to the frontbuffer.
     90   front_buffer_ ^= 1;
     91   // We've just released it. Since GBM doesn't guarantee we'll get the same
     92   // buffer back, we set it to NULL so we don't keep track of objects that may
     93   // have been destroyed.
     94   buffers_[front_buffer_ ^ 1] = NULL;
     95 }
     96 
     97 void GbmSurface::LockCurrentDrawable() {
     98   CHECK(native_surface_);
     99   // Lock the buffer we want to display.
    100   buffers_[front_buffer_ ^ 1] = gbm_surface_lock_front_buffer(native_surface_);
    101 
    102   BufferData* data = BufferData::GetData(buffers_[front_buffer_ ^ 1]);
    103   // If it is a new buffer, it won't have any data associated with it. So we
    104   // create it. On creation it will associate itself with the buffer and
    105   // register the buffer.
    106   if (!data) {
    107     data = BufferData::CreateData(dri_, buffers_[front_buffer_ ^ 1]);
    108     DCHECK(data) << "Failed to associate the buffer with the controller";
    109   }
    110 }
    111 
    112 }  // namespace ui
    113