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