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 "ui/ozone/platform/dri/dri_buffer.h"
     11 #include "ui/ozone/platform/dri/dri_window_delegate.h"
     12 #include "ui/ozone/platform/dri/dri_wrapper.h"
     13 #include "ui/ozone/platform/dri/gbm_buffer_base.h"
     14 #include "ui/ozone/platform/dri/hardware_display_controller.h"
     15 #include "ui/ozone/platform/dri/scanout_buffer.h"
     16 
     17 namespace ui {
     18 
     19 namespace {
     20 
     21 class GbmSurfaceBuffer : public GbmBufferBase {
     22  public:
     23   static scoped_refptr<GbmSurfaceBuffer> CreateBuffer(DriWrapper* dri,
     24                                                       gbm_bo* buffer);
     25   static scoped_refptr<GbmSurfaceBuffer> GetBuffer(gbm_bo* buffer);
     26 
     27  private:
     28   GbmSurfaceBuffer(DriWrapper* dri, gbm_bo* bo);
     29   virtual ~GbmSurfaceBuffer();
     30 
     31   static void Destroy(gbm_bo* buffer, void* data);
     32 
     33   // This buffer is special and is released by GBM at any point in time (as
     34   // long as it isn't being used). Since GBM should be the only one to
     35   // release this buffer, keep a self-reference in order to keep this alive.
     36   // When GBM calls Destroy(..) the self-reference will dissapear and this will
     37   // be destroyed.
     38   scoped_refptr<GbmSurfaceBuffer> self_;
     39 
     40   DISALLOW_COPY_AND_ASSIGN(GbmSurfaceBuffer);
     41 };
     42 
     43 GbmSurfaceBuffer::GbmSurfaceBuffer(DriWrapper* dri, gbm_bo* bo)
     44   : GbmBufferBase(dri, bo, true) {
     45   if (GetFramebufferId()) {
     46     self_ = this;
     47     gbm_bo_set_user_data(bo, this, GbmSurfaceBuffer::Destroy);
     48   }
     49 }
     50 
     51 GbmSurfaceBuffer::~GbmSurfaceBuffer() {}
     52 
     53 // static
     54 scoped_refptr<GbmSurfaceBuffer> GbmSurfaceBuffer::CreateBuffer(
     55     DriWrapper* dri, gbm_bo* buffer) {
     56   scoped_refptr<GbmSurfaceBuffer> scoped_buffer(new GbmSurfaceBuffer(dri,
     57                                                                      buffer));
     58   if (!scoped_buffer->GetFramebufferId())
     59     return NULL;
     60 
     61   return scoped_buffer;
     62 }
     63 
     64 // static
     65 scoped_refptr<GbmSurfaceBuffer> GbmSurfaceBuffer::GetBuffer(gbm_bo* buffer) {
     66   return scoped_refptr<GbmSurfaceBuffer>(
     67       static_cast<GbmSurfaceBuffer*>(gbm_bo_get_user_data(buffer)));
     68 }
     69 
     70 // static
     71 void GbmSurfaceBuffer::Destroy(gbm_bo* buffer, void* data) {
     72   GbmSurfaceBuffer* scoped_buffer = static_cast<GbmSurfaceBuffer*>(data);
     73   scoped_buffer->self_ = NULL;
     74 }
     75 
     76 }  // namespace
     77 
     78 GbmSurface::GbmSurface(DriWindowDelegate* window_delegate,
     79                        gbm_device* device,
     80                        DriWrapper* dri)
     81     : GbmSurfaceless(window_delegate),
     82       gbm_device_(device),
     83       dri_(dri),
     84       native_surface_(NULL),
     85       current_buffer_(NULL) {
     86 }
     87 
     88 GbmSurface::~GbmSurface() {
     89   if (current_buffer_)
     90     gbm_surface_release_buffer(native_surface_, current_buffer_);
     91 
     92   if (native_surface_)
     93     gbm_surface_destroy(native_surface_);
     94 }
     95 
     96 bool GbmSurface::Initialize() {
     97   // If we're initializing the surface without a controller (possible on startup
     98   // where the surface creation can happen before the native window delegate
     99   // IPCs arrive), initialize the size to a valid value such that surface
    100   // creation doesn't fail.
    101   gfx::Size size(1, 1);
    102   if (window_delegate_->GetController()) {
    103     size = window_delegate_->GetController()->GetModeSize();
    104   }
    105   // TODO(dnicoara) Check underlying system support for pixel format.
    106   native_surface_ =
    107       gbm_surface_create(gbm_device_,
    108                          size.width(),
    109                          size.height(),
    110                          GBM_BO_FORMAT_XRGB8888,
    111                          GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
    112 
    113   if (!native_surface_)
    114     return false;
    115 
    116   size_ = size;
    117   return true;
    118 }
    119 
    120 intptr_t GbmSurface::GetNativeWindow() {
    121   DCHECK(native_surface_);
    122   return reinterpret_cast<intptr_t>(native_surface_);
    123 }
    124 
    125 bool GbmSurface::ResizeNativeWindow(const gfx::Size& viewport_size) {
    126   if (size_ == viewport_size)
    127     return true;
    128 
    129   return false;
    130 }
    131 
    132 bool GbmSurface::OnSwapBuffers() {
    133   DCHECK(native_surface_);
    134 
    135   gbm_bo* pending_buffer = gbm_surface_lock_front_buffer(native_surface_);
    136   scoped_refptr<GbmSurfaceBuffer> primary =
    137       GbmSurfaceBuffer::GetBuffer(pending_buffer);
    138   if (!primary.get()) {
    139     primary = GbmSurfaceBuffer::CreateBuffer(dri_, pending_buffer);
    140     if (!primary.get()) {
    141       LOG(ERROR) << "Failed to associate the buffer with the controller";
    142       return false;
    143     }
    144   }
    145 
    146   // The primary buffer is a special case.
    147   if (window_delegate_->GetController())
    148     window_delegate_->GetController()->QueueOverlayPlane(OverlayPlane(primary));
    149 
    150   if (!GbmSurfaceless::OnSwapBuffers())
    151     return false;
    152 
    153   // If there was a frontbuffer, it is no longer active. Release it back to GBM.
    154   if (current_buffer_)
    155     gbm_surface_release_buffer(native_surface_, current_buffer_);
    156 
    157   current_buffer_ = pending_buffer;
    158   return true;
    159 }
    160 
    161 }  // namespace ui
    162