Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(30)

Side by Side Diff: ui/ozone/platform/drm/gpu/gbm_buffer.cc

Issue 2533163002: ozone: Create GbmBuffers from fourcc formats and gbm flags. (Closed)
Patch Set: Make ozone_unittests compile. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/drm/gpu/gbm_buffer.h" 5 #include "ui/ozone/platform/drm/gpu/gbm_buffer.h"
6 6
7 #include <drm.h> 7 #include <drm.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #include <gbm.h> 9 #include <gbm.h>
10 #include <xf86drm.h> 10 #include <xf86drm.h>
(...skipping 10 matching lines...) Expand all
21 #include "ui/ozone/platform/drm/gpu/gbm_device.h" 21 #include "ui/ozone/platform/drm/gpu/gbm_device.h"
22 #include "ui/ozone/platform/drm/gpu/gbm_surface_factory.h" 22 #include "ui/ozone/platform/drm/gpu/gbm_surface_factory.h"
23 #include "ui/ozone/platform/drm/gpu/gbm_surfaceless.h" 23 #include "ui/ozone/platform/drm/gpu/gbm_surfaceless.h"
24 #include "ui/ozone/public/ozone_platform.h" 24 #include "ui/ozone/public/ozone_platform.h"
25 #include "ui/ozone/public/surface_factory_ozone.h" 25 #include "ui/ozone/public/surface_factory_ozone.h"
26 26
27 namespace ui { 27 namespace ui {
28 28
29 GbmBuffer::GbmBuffer(const scoped_refptr<GbmDevice>& gbm, 29 GbmBuffer::GbmBuffer(const scoped_refptr<GbmDevice>& gbm,
30 gbm_bo* bo, 30 gbm_bo* bo,
31 gfx::BufferFormat format, 31 uint32_t format,
32 gfx::BufferUsage usage, 32 uint32_t flags,
33 std::vector<base::ScopedFD>&& fds, 33 std::vector<base::ScopedFD>&& fds,
34 const gfx::Size& size, 34 const gfx::Size& size,
35 const std::vector<gfx::NativePixmapPlane>&& planes) 35 const std::vector<gfx::NativePixmapPlane>&& planes)
36 : GbmBufferBase(gbm, bo, format, usage), 36 : GbmBufferBase(gbm, bo, format, flags),
37 format_(format), 37 format_(format),
38 usage_(usage), 38 flags_(flags),
39 fds_(std::move(fds)), 39 fds_(std::move(fds)),
40 size_(size), 40 size_(size),
41 planes_(std::move(planes)) {} 41 planes_(std::move(planes)) {}
42 42
43 GbmBuffer::~GbmBuffer() { 43 GbmBuffer::~GbmBuffer() {
44 if (bo()) 44 if (bo())
45 gbm_bo_destroy(bo()); 45 gbm_bo_destroy(bo());
46 } 46 }
47 47
48 bool GbmBuffer::AreFdsValid() const { 48 bool GbmBuffer::AreFdsValid() const {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 87
88 // TODO(reveman): This should not be needed once crbug.com/597932 is fixed, 88 // TODO(reveman): This should not be needed once crbug.com/597932 is fixed,
89 // as the size would be queried directly from the underlying bo. 89 // as the size would be queried directly from the underlying bo.
90 gfx::Size GbmBuffer::GetSize() const { 90 gfx::Size GbmBuffer::GetSize() const {
91 return size_; 91 return size_;
92 } 92 }
93 93
94 // static 94 // static
95 scoped_refptr<GbmBuffer> GbmBuffer::CreateBuffer( 95 scoped_refptr<GbmBuffer> GbmBuffer::CreateBuffer(
96 const scoped_refptr<GbmDevice>& gbm, 96 const scoped_refptr<GbmDevice>& gbm,
97 gfx::BufferFormat format, 97 uint32_t format,
98 const gfx::Size& size, 98 const gfx::Size& size,
99 gfx::BufferUsage usage) { 99 uint32_t flags) {
100 TRACE_EVENT2("drm", "GbmBuffer::CreateBuffer", "device", 100 TRACE_EVENT2("drm", "GbmBuffer::CreateBuffer", "device",
101 gbm->device_path().value(), "size", size.ToString()); 101 gbm->device_path().value(), "size", size.ToString());
102 102
103 unsigned flags = 0; 103 gbm_bo* bo =
104 switch (usage) { 104 gbm_bo_create(gbm->device(), size.width(), size.height(), format, flags);
105 case gfx::BufferUsage::GPU_READ:
106 break;
107 case gfx::BufferUsage::SCANOUT:
108 flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
109 break;
110 case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE:
111 case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE_PERSISTENT:
112 flags = GBM_BO_USE_LINEAR;
113 break;
114 }
115
116 gbm_bo* bo = gbm_bo_create(gbm->device(), size.width(), size.height(),
117 GetFourCCFormatFromBufferFormat(format), flags);
118 if (!bo) 105 if (!bo)
119 return nullptr; 106 return nullptr;
120 107
121 std::vector<base::ScopedFD> fds; 108 std::vector<base::ScopedFD> fds;
122 std::vector<gfx::NativePixmapPlane> planes; 109 std::vector<gfx::NativePixmapPlane> planes;
123 110
124 DCHECK_EQ(gbm_bo_get_num_planes(bo), 111 for (size_t i = 0; i < gbm_bo_get_num_planes(bo); ++i) {
125 gfx::NumberOfPlanesForBufferFormat(format));
126 for (size_t i = 0; i < gfx::NumberOfPlanesForBufferFormat(format); ++i) {
127 // The fd returned by gbm_bo_get_fd is not ref-counted and need to be 112 // The fd returned by gbm_bo_get_fd is not ref-counted and need to be
128 // kept open for the lifetime of the buffer. 113 // kept open for the lifetime of the buffer.
129 base::ScopedFD fd(gbm_bo_get_plane_fd(bo, i)); 114 base::ScopedFD fd(gbm_bo_get_plane_fd(bo, i));
130 115
131 // TODO(dcastagna): support multiple fds. 116 // TODO(dcastagna): support multiple fds.
132 // crbug.com/642410 117 // crbug.com/642410
133 if (!i) { 118 if (!i) {
134 if (!fd.is_valid()) { 119 if (!fd.is_valid()) {
135 PLOG(ERROR) << "Failed to export buffer to dma_buf"; 120 PLOG(ERROR) << "Failed to export buffer to dma_buf";
136 gbm_bo_destroy(bo); 121 gbm_bo_destroy(bo);
137 return nullptr; 122 return nullptr;
138 } 123 }
139 fds.emplace_back(std::move(fd)); 124 fds.emplace_back(std::move(fd));
140 } 125 }
141 126
142 planes.emplace_back( 127 planes.emplace_back(
143 gbm_bo_get_plane_stride(bo, i), gbm_bo_get_plane_offset(bo, i), 128 gbm_bo_get_plane_stride(bo, i), gbm_bo_get_plane_offset(bo, i),
144 gbm_bo_get_plane_size(bo, i), gbm_bo_get_plane_format_modifier(bo, i)); 129 gbm_bo_get_plane_size(bo, i), gbm_bo_get_plane_format_modifier(bo, i));
145 } 130 }
146 scoped_refptr<GbmBuffer> buffer(new GbmBuffer( 131 scoped_refptr<GbmBuffer> buffer(new GbmBuffer(
147 gbm, bo, format, usage, std::move(fds), size, std::move(planes))); 132 gbm, bo, format, flags, std::move(fds), size, std::move(planes)));
148 if (usage == gfx::BufferUsage::SCANOUT && !buffer->GetFramebufferId()) 133 if (flags & GBM_BO_USE_SCANOUT && !buffer->GetFramebufferId())
149 return nullptr; 134 return nullptr;
150 135
151 return buffer; 136 return buffer;
152 } 137 }
153 138
154 // static 139 // static
155 scoped_refptr<GbmBuffer> GbmBuffer::CreateBufferFromFds( 140 scoped_refptr<GbmBuffer> GbmBuffer::CreateBufferFromFds(
156 const scoped_refptr<GbmDevice>& gbm, 141 const scoped_refptr<GbmDevice>& gbm,
157 gfx::BufferFormat format, 142 uint32_t format,
158 const gfx::Size& size, 143 const gfx::Size& size,
159 std::vector<base::ScopedFD>&& fds, 144 std::vector<base::ScopedFD>&& fds,
160 const std::vector<gfx::NativePixmapPlane>& planes) { 145 const std::vector<gfx::NativePixmapPlane>& planes) {
161 TRACE_EVENT2("drm", "GbmBuffer::CreateBufferFromFD", "device", 146 TRACE_EVENT2("drm", "GbmBuffer::CreateBufferFromFD", "device",
162 gbm->device_path().value(), "size", size.ToString()); 147 gbm->device_path().value(), "size", size.ToString());
163 DCHECK_LE(fds.size(), planes.size()); 148 DCHECK_LE(fds.size(), planes.size());
164 DCHECK_EQ(planes[0].offset, 0); 149 DCHECK_EQ(planes[0].offset, 0);
165 150
166 uint32_t fourcc_format = GetFourCCFormatFromBufferFormat(format);
167
168 // Use scanout if supported. 151 // Use scanout if supported.
169 bool use_scanout = gbm_device_is_format_supported( 152 bool use_scanout =
170 gbm->device(), fourcc_format, 153 gbm_device_is_format_supported(
171 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING) && 154 gbm->device(), format, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING) &&
172 (planes.size() == 1); 155 (planes.size() == 1);
173 156
174 gbm_bo* bo = nullptr; 157 gbm_bo* bo = nullptr;
175 if (use_scanout) { 158 if (use_scanout) {
176 struct gbm_import_fd_data fd_data; 159 struct gbm_import_fd_data fd_data;
177 fd_data.fd = fds[0].get(); 160 fd_data.fd = fds[0].get();
178 fd_data.width = size.width(); 161 fd_data.width = size.width();
179 fd_data.height = size.height(); 162 fd_data.height = size.height();
180 fd_data.stride = planes[0].stride; 163 fd_data.stride = planes[0].stride;
181 fd_data.format = fourcc_format; 164 fd_data.format = format;
182 165
183 // The fd passed to gbm_bo_import is not ref-counted and need to be 166 // The fd passed to gbm_bo_import is not ref-counted and need to be
184 // kept open for the lifetime of the buffer. 167 // kept open for the lifetime of the buffer.
185 bo = gbm_bo_import(gbm->device(), GBM_BO_IMPORT_FD, &fd_data, 168 bo = gbm_bo_import(gbm->device(), GBM_BO_IMPORT_FD, &fd_data,
186 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); 169 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
187 if (!bo) { 170 if (!bo) {
188 LOG(ERROR) << "nullptr returned from gbm_bo_import"; 171 LOG(ERROR) << "nullptr returned from gbm_bo_import";
189 return nullptr; 172 return nullptr;
190 } 173 }
191 } 174 }
192 175
176 uint32_t flags = GBM_BO_USE_RENDERING;
177 if (use_scanout)
178 flags |= GBM_BO_USE_SCANOUT;
193 scoped_refptr<GbmBuffer> buffer(new GbmBuffer( 179 scoped_refptr<GbmBuffer> buffer(new GbmBuffer(
194 gbm, bo, format, 180 gbm, bo, format, flags, std::move(fds), size, std::move(planes)));
195 use_scanout ? gfx::BufferUsage::SCANOUT : gfx::BufferUsage::GPU_READ,
196 std::move(fds), size, std::move(planes)));
197 // If scanout support for buffer is expected then make sure we managed to 181 // If scanout support for buffer is expected then make sure we managed to
198 // create a framebuffer for it as otherwise using it for scanout will fail. 182 // create a framebuffer for it as otherwise using it for scanout will fail.
199 if (use_scanout && !buffer->GetFramebufferId()) 183 if (use_scanout && !buffer->GetFramebufferId())
200 return nullptr; 184 return nullptr;
201 185
202 return buffer; 186 return buffer;
203 } 187 }
204 188
205 GbmPixmap::GbmPixmap(GbmSurfaceFactory* surface_manager, 189 GbmPixmap::GbmPixmap(GbmSurfaceFactory* surface_manager,
206 const scoped_refptr<GbmBuffer>& buffer) 190 const scoped_refptr<GbmBuffer>& buffer)
207 : surface_manager_(surface_manager), buffer_(buffer) {} 191 : surface_manager_(surface_manager), buffer_(buffer) {}
208 192
209 void GbmPixmap::SetProcessingCallback( 193 void GbmPixmap::SetProcessingCallback(
210 const ProcessingCallback& processing_callback) { 194 const ProcessingCallback& processing_callback) {
211 DCHECK(processing_callback_.is_null()); 195 DCHECK(processing_callback_.is_null());
212 processing_callback_ = processing_callback; 196 processing_callback_ = processing_callback;
213 } 197 }
214 198
215 gfx::NativePixmapHandle GbmPixmap::ExportHandle() { 199 gfx::NativePixmapHandle GbmPixmap::ExportHandle() {
216 gfx::NativePixmapHandle handle; 200 gfx::NativePixmapHandle handle;
217 for (size_t i = 0; 201 gfx::BufferFormat format =
218 i < gfx::NumberOfPlanesForBufferFormat(buffer_->GetFormat()); ++i) { 202 ui::GetBufferFormatFromFourCCFormat(buffer_->GetFormat());
203 // TODO(dcastagna): Use gbm_bo_get_num_planes.
204 for (size_t i = 0; i < gfx::NumberOfPlanesForBufferFormat(format); ++i) {
dnicoara 2016/11/30 15:12:01 Wondering why gbm_bo_get_num_planes() can't be use
Daniele Castagna 2016/11/30 18:41:38 We don't always have a gbm bo pointer. There are s
dnicoara 2016/11/30 18:44:15 Ahh, thank you for clarifying.
219 // Some formats (e.g: YVU_420) might have less than one fd per plane. 205 // Some formats (e.g: YVU_420) might have less than one fd per plane.
220 if (i < buffer_->GetFdCount()) { 206 if (i < buffer_->GetFdCount()) {
221 base::ScopedFD scoped_fd(HANDLE_EINTR(dup(buffer_->GetFd(i)))); 207 base::ScopedFD scoped_fd(HANDLE_EINTR(dup(buffer_->GetFd(i))));
222 if (!scoped_fd.is_valid()) { 208 if (!scoped_fd.is_valid()) {
223 PLOG(ERROR) << "dup"; 209 PLOG(ERROR) << "dup";
224 return gfx::NativePixmapHandle(); 210 return gfx::NativePixmapHandle();
225 } 211 }
226 handle.fds.emplace_back( 212 handle.fds.emplace_back(
227 base::FileDescriptor(scoped_fd.release(), true /* auto_close */)); 213 base::FileDescriptor(scoped_fd.release(), true /* auto_close */));
228 } 214 }
(...skipping 29 matching lines...) Expand all
258 244
259 int GbmPixmap::GetDmaBufOffset(size_t plane) const { 245 int GbmPixmap::GetDmaBufOffset(size_t plane) const {
260 return buffer_->GetOffset(plane); 246 return buffer_->GetOffset(plane);
261 } 247 }
262 248
263 uint64_t GbmPixmap::GetDmaBufModifier(size_t plane) const { 249 uint64_t GbmPixmap::GetDmaBufModifier(size_t plane) const {
264 return buffer_->GetFormatModifier(plane); 250 return buffer_->GetFormatModifier(plane);
265 } 251 }
266 252
267 gfx::BufferFormat GbmPixmap::GetBufferFormat() const { 253 gfx::BufferFormat GbmPixmap::GetBufferFormat() const {
268 return buffer_->GetFormat(); 254 return ui::GetBufferFormatFromFourCCFormat(buffer_->GetFormat());
269 } 255 }
270 256
271 gfx::Size GbmPixmap::GetBufferSize() const { 257 gfx::Size GbmPixmap::GetBufferSize() const {
272 return buffer_->GetSize(); 258 return buffer_->GetSize();
273 } 259 }
274 260
275 bool GbmPixmap::ScheduleOverlayPlane(gfx::AcceleratedWidget widget, 261 bool GbmPixmap::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
276 int plane_z_order, 262 int plane_z_order,
277 gfx::OverlayTransform plane_transform, 263 gfx::OverlayTransform plane_transform,
278 const gfx::Rect& display_bounds, 264 const gfx::Rect& display_bounds,
279 const gfx::RectF& crop_rect) { 265 const gfx::RectF& crop_rect) {
280 DCHECK(buffer_->GetUsage() == gfx::BufferUsage::SCANOUT); 266 DCHECK(buffer_->GetFlags() & GBM_BO_USE_SCANOUT);
281 OverlayPlane::ProcessBufferCallback processing_callback; 267 OverlayPlane::ProcessBufferCallback processing_callback;
282 if (!processing_callback_.is_null()) 268 if (!processing_callback_.is_null())
283 processing_callback = base::Bind(&GbmPixmap::ProcessBuffer, this); 269 processing_callback = base::Bind(&GbmPixmap::ProcessBuffer, this);
284 270
285 surface_manager_->GetSurface(widget)->QueueOverlayPlane( 271 surface_manager_->GetSurface(widget)->QueueOverlayPlane(
286 OverlayPlane(buffer_, plane_z_order, plane_transform, display_bounds, 272 OverlayPlane(buffer_, plane_z_order, plane_transform, display_bounds,
287 crop_rect, processing_callback)); 273 crop_rect, processing_callback));
288 274
289 return true; 275 return true;
290 } 276 }
291 277
292 scoped_refptr<ScanoutBuffer> GbmPixmap::ProcessBuffer(const gfx::Size& size, 278 scoped_refptr<ScanoutBuffer> GbmPixmap::ProcessBuffer(const gfx::Size& size,
293 uint32_t format) { 279 uint32_t format) {
294 DCHECK(GetBufferSize() != size || 280 DCHECK(GetBufferSize() != size ||
295 buffer_->GetFramebufferPixelFormat() != format); 281 buffer_->GetFramebufferPixelFormat() != format);
296 282
297 if (!processed_pixmap_ || size != processed_pixmap_->GetBufferSize() || 283 if (!processed_pixmap_ || size != processed_pixmap_->GetBufferSize() ||
298 format != processed_pixmap_->buffer()->GetFramebufferPixelFormat()) { 284 format != processed_pixmap_->buffer()->GetFramebufferPixelFormat()) {
299 // Release any old processed pixmap. 285 // Release any old processed pixmap.
300 processed_pixmap_ = nullptr; 286 processed_pixmap_ = nullptr;
301 gfx::BufferFormat buffer_format = GetBufferFormatFromFourCCFormat(format);
302
303 scoped_refptr<GbmBuffer> buffer = GbmBuffer::CreateBuffer( 287 scoped_refptr<GbmBuffer> buffer = GbmBuffer::CreateBuffer(
304 buffer_->drm().get(), buffer_format, size, buffer_->GetUsage()); 288 buffer_->drm().get(), format, size, buffer_->GetFlags());
305 if (!buffer) 289 if (!buffer)
306 return nullptr; 290 return nullptr;
307 291
308 // ProcessBuffer is called on DrmThread. We could have used 292 // ProcessBuffer is called on DrmThread. We could have used
309 // CreateNativePixmap to initialize the pixmap, however it posts a 293 // CreateNativePixmap to initialize the pixmap, however it posts a
310 // synchronous task to DrmThread resulting in a deadlock. 294 // synchronous task to DrmThread resulting in a deadlock.
311 processed_pixmap_ = new GbmPixmap(surface_manager_, buffer); 295 processed_pixmap_ = new GbmPixmap(surface_manager_, buffer);
312 } 296 }
313 297
314 DCHECK(!processing_callback_.is_null()); 298 DCHECK(!processing_callback_.is_null());
315 if (!processing_callback_.Run(this, processed_pixmap_)) { 299 if (!processing_callback_.Run(this, processed_pixmap_)) {
316 LOG(ERROR) << "Failed processing NativePixmap"; 300 LOG(ERROR) << "Failed processing NativePixmap";
317 return nullptr; 301 return nullptr;
318 } 302 }
319 303
320 return processed_pixmap_->buffer(); 304 return processed_pixmap_->buffer();
321 } 305 }
322 306
323 } // namespace ui 307 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698