OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/ozone/platform/dri/gbm_surface.h" | 5 #include "ui/ozone/platform/dri/gbm_surface.h" |
6 | 6 |
7 #include <gbm.h> | 7 #include <gbm.h> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "third_party/skia/include/core/SkImageInfo.h" | 10 #include "third_party/skia/include/core/SkImageInfo.h" |
11 #include "ui/ozone/platform/dri/buffer_data.h" | 11 #include "ui/ozone/platform/dri/buffer_data.h" |
12 #include "ui/ozone/platform/dri/dri_buffer.h" | 12 #include "ui/ozone/platform/dri/dri_buffer.h" |
13 #include "ui/ozone/platform/dri/dri_wrapper.h" | 13 #include "ui/ozone/platform/dri/dri_wrapper.h" |
14 #include "ui/ozone/platform/dri/hardware_display_controller.h" | 14 #include "ui/ozone/platform/dri/hardware_display_controller.h" |
15 #include "ui/ozone/platform/dri/scanout_buffer.h" | |
15 | 16 |
16 namespace ui { | 17 namespace ui { |
17 | 18 |
19 namespace { | |
20 | |
21 // Pixel configuration for the current buffer format. | |
22 // TODO(dnicoara) These will need to change once we query the hardware for | |
23 // supported configurations. | |
24 const uint8_t kColorDepth = 24; | |
25 const uint8_t kPixelDepth = 32; | |
26 | |
27 } // namespace | |
28 | |
29 class GbmSurface::GbmSurfaceBuffer : public ScanoutBuffer { | |
dnicoara
2014/07/18 19:30:20
This is pretty much BufferData with a few addition
alexst (slow to review)
2014/07/18 19:49:07
This looks a lot like https://code.google.com/p/ch
dnicoara
2014/07/18 20:04:19
I initially wanted to do that, but the semantics o
alexst (slow to review)
2014/07/18 21:11:31
I've been looking at the details and I see what yo
dnicoara
2014/07/18 21:48:27
Done.
| |
30 public: | |
31 static scoped_refptr<GbmSurfaceBuffer> CreateBuffer(DriWrapper* dri, | |
32 gbm_bo* buffer); | |
33 static scoped_refptr<GbmSurfaceBuffer> GetBuffer(gbm_bo* buffer); | |
34 | |
35 gbm_bo* bo() const { return bo_; } | |
36 | |
37 // ScanoutBuffer: | |
38 virtual uint32_t GetFramebufferId() const OVERRIDE; | |
39 virtual uint32_t GetHandle() const OVERRIDE; | |
40 virtual gfx::Size GetSize() const OVERRIDE; | |
41 | |
42 private: | |
43 GbmSurfaceBuffer(DriWrapper* dri, gbm_bo* bo); | |
44 virtual ~GbmSurfaceBuffer(); | |
45 | |
46 static void Destroy(gbm_bo* buffer, void* data); | |
47 | |
48 // This buffer is special and is released by GBM at any point in time (as | |
49 // long as it isn't being used). Since GBM should be the only one to | |
50 // release this buffer, keep a self-reference in order to keep this alive. | |
51 // When GBM calls Destroy(..) the self-reference will dissapear and this will | |
52 // be destroyed. | |
53 scoped_refptr<GbmSurfaceBuffer> self_; | |
54 | |
55 DriWrapper* dri_; | |
56 gbm_bo* bo_; | |
57 uint32_t framebuffer_; | |
58 | |
59 DISALLOW_COPY_AND_ASSIGN(GbmSurfaceBuffer); | |
60 }; | |
61 | |
62 GbmSurface::GbmSurfaceBuffer::GbmSurfaceBuffer(DriWrapper* dri, gbm_bo* bo) | |
63 : dri_(dri), bo_(bo), framebuffer_(0) { | |
64 if (!dri_->AddFramebuffer(gbm_bo_get_width(bo), | |
65 gbm_bo_get_height(bo), | |
66 kColorDepth, | |
67 kPixelDepth, | |
68 gbm_bo_get_stride(bo), | |
69 gbm_bo_get_handle(bo).u32, | |
70 &framebuffer_)) { | |
71 LOG(ERROR) << "Failed to register buffer"; | |
72 return; | |
73 } | |
74 | |
75 self_ = this; | |
76 gbm_bo_set_user_data(bo, this, GbmSurfaceBuffer::Destroy); | |
77 } | |
78 | |
79 GbmSurface::GbmSurfaceBuffer::~GbmSurfaceBuffer() { | |
80 if (framebuffer_) | |
81 dri_->RemoveFramebuffer(framebuffer_); | |
82 } | |
83 | |
84 // static | |
85 scoped_refptr<GbmSurface::GbmSurfaceBuffer> | |
86 GbmSurface::GbmSurfaceBuffer::CreateBuffer(DriWrapper* dri, gbm_bo* buffer) { | |
87 scoped_refptr<GbmSurfaceBuffer> scoped_buffer(new GbmSurfaceBuffer(dri, | |
88 buffer)); | |
89 if (!scoped_buffer->GetFramebufferId()) | |
90 return NULL; | |
91 | |
92 return scoped_buffer; | |
93 } | |
94 | |
95 // static | |
96 scoped_refptr<GbmSurface::GbmSurfaceBuffer> | |
97 GbmSurface::GbmSurfaceBuffer::GetBuffer(gbm_bo* buffer) { | |
98 return scoped_refptr<GbmSurfaceBuffer>( | |
99 static_cast<GbmSurfaceBuffer*>(gbm_bo_get_user_data(buffer))); | |
100 } | |
101 | |
102 // static | |
103 void GbmSurface::GbmSurfaceBuffer::Destroy(gbm_bo* buffer, void* data) { | |
104 GbmSurfaceBuffer* scoped_buffer = static_cast<GbmSurfaceBuffer*>(data); | |
105 scoped_buffer->self_ = NULL; | |
106 } | |
107 | |
108 uint32_t GbmSurface::GbmSurfaceBuffer::GetFramebufferId() const { | |
109 return framebuffer_; | |
110 } | |
111 | |
112 uint32_t GbmSurface::GbmSurfaceBuffer::GetHandle() const { | |
113 return gbm_bo_get_handle(bo_).u32; | |
114 } | |
115 | |
116 gfx::Size GbmSurface::GbmSurfaceBuffer::GetSize() const { | |
117 return gfx::Size(gbm_bo_get_width(bo_), gbm_bo_get_height(bo_)); | |
118 } | |
119 | |
18 GbmSurface::GbmSurface(gbm_device* device, | 120 GbmSurface::GbmSurface(gbm_device* device, |
19 DriWrapper* dri, | 121 DriWrapper* dri, |
20 const gfx::Size& size) | 122 const gfx::Size& size) |
21 : gbm_device_(device), | 123 : gbm_device_(device), |
22 dri_(dri), | 124 dri_(dri), |
23 size_(size), | 125 size_(size), |
24 native_surface_(NULL), | 126 native_surface_(NULL), |
25 buffers_(), | 127 buffers_(), |
26 front_buffer_(0) { | 128 front_buffer_(0) { |
27 for (size_t i = 0; i < arraysize(buffers_); ++i) | 129 for (size_t i = 0; i < arraysize(buffers_); ++i) |
28 buffers_[i] = NULL; | 130 buffers_[i] = NULL; |
29 } | 131 } |
30 | 132 |
31 GbmSurface::~GbmSurface() { | 133 GbmSurface::~GbmSurface() { |
32 for (size_t i = 0; i < arraysize(buffers_); ++i) { | 134 for (size_t i = 0; i < arraysize(buffers_); ++i) { |
33 if (buffers_[i]) { | 135 if (buffers_[i]) { |
34 gbm_surface_release_buffer(native_surface_, buffers_[i]); | 136 gbm_surface_release_buffer(native_surface_, buffers_[i]->bo()); |
35 } | 137 } |
36 } | 138 } |
37 | 139 |
38 if (native_surface_) | 140 if (native_surface_) |
39 gbm_surface_destroy(native_surface_); | 141 gbm_surface_destroy(native_surface_); |
40 } | 142 } |
41 | 143 |
42 bool GbmSurface::Initialize() { | 144 bool GbmSurface::Initialize() { |
43 // TODO(dnicoara) Check underlying system support for pixel format. | 145 // TODO(dnicoara) Check underlying system support for pixel format. |
44 native_surface_ = gbm_surface_create( | 146 native_surface_ = gbm_surface_create( |
(...skipping 11 matching lines...) Expand all Loading... | |
56 size_.height()))) | 158 size_.height()))) |
57 return false; | 159 return false; |
58 | 160 |
59 return true; | 161 return true; |
60 } | 162 } |
61 | 163 |
62 uint32_t GbmSurface::GetFramebufferId() const { | 164 uint32_t GbmSurface::GetFramebufferId() const { |
63 if (!buffers_[front_buffer_ ^ 1]) | 165 if (!buffers_[front_buffer_ ^ 1]) |
64 return dumb_buffer_->GetFramebufferId(); | 166 return dumb_buffer_->GetFramebufferId(); |
65 | 167 |
66 BufferData* data = BufferData::GetData(buffers_[front_buffer_ ^ 1]); | 168 return buffers_[front_buffer_ ^ 1]->GetFramebufferId(); |
67 CHECK(data); | |
68 return data->framebuffer(); | |
69 } | 169 } |
70 | 170 |
71 uint32_t GbmSurface::GetHandle() const { | 171 uint32_t GbmSurface::GetHandle() const { |
72 if (!buffers_[front_buffer_ ^ 1]) | 172 if (!buffers_[front_buffer_ ^ 1]) |
73 return dumb_buffer_->GetHandle(); | 173 return dumb_buffer_->GetHandle(); |
74 | 174 |
75 BufferData* data = BufferData::GetData(buffers_[front_buffer_ ^ 1]); | 175 return buffers_[front_buffer_ ^ 1]->GetHandle(); |
76 CHECK(data); | |
77 return data->handle(); | |
78 } | 176 } |
79 | 177 |
80 gfx::Size GbmSurface::Size() const { | 178 gfx::Size GbmSurface::Size() const { |
81 return size_; | 179 return size_; |
82 } | 180 } |
83 | 181 |
84 // Before scheduling the backbuffer to be scanned out we need to "lock" it. | 182 // Before scheduling the backbuffer to be scanned out we need to "lock" it. |
85 // When we lock it, GBM will give a pointer to a buffer representing the | 183 // When we lock it, GBM will give a pointer to a buffer representing the |
86 // backbuffer. It will also update its information on which buffers can not be | 184 // backbuffer. It will also update its information on which buffers can not be |
87 // used for drawing. The buffer will be released when the page flip event | 185 // used for drawing. The buffer will be released when the page flip event |
88 // occurs (see SwapBuffers). This is called from HardwareDisplayController | 186 // occurs (see SwapBuffers). This is called from HardwareDisplayController |
89 // before scheduling a page flip. | 187 // before scheduling a page flip. |
90 void GbmSurface::PreSwapBuffers() { | 188 void GbmSurface::PreSwapBuffers() { |
91 CHECK(native_surface_); | 189 CHECK(native_surface_); |
92 // Lock the buffer we want to display. | 190 // Lock the buffer we want to display. |
93 buffers_[front_buffer_ ^ 1] = gbm_surface_lock_front_buffer(native_surface_); | 191 gbm_bo* bo = gbm_surface_lock_front_buffer(native_surface_); |
94 | 192 |
95 BufferData* data = BufferData::GetData(buffers_[front_buffer_ ^ 1]); | 193 buffers_[front_buffer_ ^ 1] = GbmSurfaceBuffer::GetBuffer(bo); |
96 // If it is a new buffer, it won't have any data associated with it. So we | 194 // If it is a new buffer, it won't have any data associated with it. So we |
97 // create it. On creation it will associate itself with the buffer and | 195 // create it. On creation it will associate itself with the buffer and |
98 // register the buffer. | 196 // register the buffer. |
99 if (!data) { | 197 if (!buffers_[front_buffer_ ^ 1]) { |
100 data = BufferData::CreateData(dri_, buffers_[front_buffer_ ^ 1]); | 198 buffers_[front_buffer_ ^ 1] = GbmSurfaceBuffer::CreateBuffer(dri_, bo); |
101 DCHECK(data) << "Failed to associate the buffer with the controller"; | 199 DCHECK(buffers_[front_buffer_ ^ 1]) |
200 << "Failed to associate the buffer with the controller"; | |
102 } | 201 } |
103 } | 202 } |
104 | 203 |
105 void GbmSurface::SwapBuffers() { | 204 void GbmSurface::SwapBuffers() { |
106 // If there was a frontbuffer, is no longer active. Release it back to GBM. | 205 // If there was a frontbuffer, is no longer active. Release it back to GBM. |
107 if (buffers_[front_buffer_]) | 206 if (buffers_[front_buffer_]) |
108 gbm_surface_release_buffer(native_surface_, buffers_[front_buffer_]); | 207 gbm_surface_release_buffer(native_surface_, buffers_[front_buffer_]->bo()); |
109 | 208 |
110 // Update the index to the frontbuffer. | 209 // Update the index to the frontbuffer. |
111 front_buffer_ ^= 1; | 210 front_buffer_ ^= 1; |
112 // We've just released it. Since GBM doesn't guarantee we'll get the same | 211 // We've just released it. Since GBM doesn't guarantee we'll get the same |
113 // buffer back, we set it to NULL so we don't keep track of objects that may | 212 // buffer back, we set it to NULL so we don't keep track of objects that may |
114 // have been destroyed. | 213 // have been destroyed. |
115 buffers_[front_buffer_ ^ 1] = NULL; | 214 buffers_[front_buffer_ ^ 1] = NULL; |
116 } | 215 } |
117 | 216 |
118 } // namespace ui | 217 } // namespace ui |
OLD | NEW |