• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GbmSurfaceBuffer(DriWrapper * dri,gbm_bo * bo)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 
~GbmSurfaceBuffer()51 GbmSurfaceBuffer::~GbmSurfaceBuffer() {}
52 
53 // static
CreateBuffer(DriWrapper * dri,gbm_bo * buffer)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
GetBuffer(gbm_bo * buffer)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
Destroy(gbm_bo * buffer,void * data)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 
GbmSurface(DriWindowDelegate * window_delegate,gbm_device * device,DriWrapper * dri)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 
~GbmSurface()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 
Initialize()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 
GetNativeWindow()120 intptr_t GbmSurface::GetNativeWindow() {
121   DCHECK(native_surface_);
122   return reinterpret_cast<intptr_t>(native_surface_);
123 }
124 
ResizeNativeWindow(const gfx::Size & viewport_size)125 bool GbmSurface::ResizeNativeWindow(const gfx::Size& viewport_size) {
126   if (size_ == viewport_size)
127     return true;
128 
129   return false;
130 }
131 
OnSwapBuffers()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