| 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/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 14 matching lines...) Expand all Loading... |
| 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 gfx::BufferFormat format, |
| 32 gfx::BufferUsage usage, | 32 gfx::BufferUsage usage, |
| 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<int>& strides, | 35 const std::vector<gfx::NativePixmapPlane>&& planes) |
| 36 const std::vector<int>& offsets) | |
| 37 : GbmBufferBase(gbm, bo, format, usage), | 36 : GbmBufferBase(gbm, bo, format, usage), |
| 38 format_(format), | 37 format_(format), |
| 39 usage_(usage), | 38 usage_(usage), |
| 40 fds_(std::move(fds)), | 39 fds_(std::move(fds)), |
| 41 size_(size), | 40 size_(size), |
| 42 strides_(strides), | 41 planes_(std::move(planes)) {} |
| 43 offsets_(offsets) {} | |
| 44 | 42 |
| 45 GbmBuffer::~GbmBuffer() { | 43 GbmBuffer::~GbmBuffer() { |
| 46 if (bo()) | 44 if (bo()) |
| 47 gbm_bo_destroy(bo()); | 45 gbm_bo_destroy(bo()); |
| 48 } | 46 } |
| 49 | 47 |
| 50 bool GbmBuffer::AreFdsValid() const { | 48 bool GbmBuffer::AreFdsValid() const { |
| 51 if (fds_.empty()) | 49 if (fds_.empty()) |
| 52 return false; | 50 return false; |
| 53 | 51 |
| 54 for (const auto& fd : fds_) { | 52 for (const auto& fd : fds_) { |
| 55 if (fd.get() == -1) | 53 if (fd.get() == -1) |
| 56 return false; | 54 return false; |
| 57 } | 55 } |
| 58 return true; | 56 return true; |
| 59 } | 57 } |
| 60 | 58 |
| 61 size_t GbmBuffer::GetFdCount() const { | 59 size_t GbmBuffer::GetFdCount() const { |
| 62 return fds_.size(); | 60 return fds_.size(); |
| 63 } | 61 } |
| 64 | 62 |
| 65 int GbmBuffer::GetFd(size_t plane) const { | 63 int GbmBuffer::GetFd(size_t index) const { |
| 66 DCHECK_LT(plane, fds_.size()); | 64 DCHECK_LT(index, fds_.size()); |
| 67 return fds_[plane].get(); | 65 return fds_[index].get(); |
| 68 } | 66 } |
| 69 | 67 |
| 70 int GbmBuffer::GetStride(size_t plane) const { | 68 int GbmBuffer::GetStride(size_t index) const { |
| 71 DCHECK_LT(plane, strides_.size()); | 69 DCHECK_LT(index, planes_.size()); |
| 72 return strides_[plane]; | 70 return planes_[index].stride; |
| 73 } | 71 } |
| 74 | 72 |
| 75 int GbmBuffer::GetOffset(size_t plane) const { | 73 int GbmBuffer::GetOffset(size_t index) const { |
| 76 DCHECK_LT(plane, offsets_.size()); | 74 DCHECK_LT(index, planes_.size()); |
| 77 return offsets_[plane]; | 75 return planes_[index].offset; |
| 76 } |
| 77 |
| 78 uint64_t GbmBuffer::GetFormatModifier(size_t index) const { |
| 79 DCHECK_LT(index, planes_.size()); |
| 80 return planes_[index].modifier; |
| 78 } | 81 } |
| 79 | 82 |
| 80 // TODO(reveman): This should not be needed once crbug.com/597932 is fixed, | 83 // TODO(reveman): This should not be needed once crbug.com/597932 is fixed, |
| 81 // as the size would be queried directly from the underlying bo. | 84 // as the size would be queried directly from the underlying bo. |
| 82 gfx::Size GbmBuffer::GetSize() const { | 85 gfx::Size GbmBuffer::GetSize() const { |
| 83 return size_; | 86 return size_; |
| 84 } | 87 } |
| 85 | 88 |
| 86 // static | 89 // static |
| 87 scoped_refptr<GbmBuffer> GbmBuffer::CreateBuffer( | 90 scoped_refptr<GbmBuffer> GbmBuffer::CreateBuffer( |
| (...skipping 25 matching lines...) Expand all Loading... |
| 113 // The fd returned by gbm_bo_get_fd is not ref-counted and need to be | 116 // The fd returned by gbm_bo_get_fd is not ref-counted and need to be |
| 114 // kept open for the lifetime of the buffer. | 117 // kept open for the lifetime of the buffer. |
| 115 base::ScopedFD fd(gbm_bo_get_fd(bo)); | 118 base::ScopedFD fd(gbm_bo_get_fd(bo)); |
| 116 if (!fd.is_valid()) { | 119 if (!fd.is_valid()) { |
| 117 PLOG(ERROR) << "Failed to export buffer to dma_buf"; | 120 PLOG(ERROR) << "Failed to export buffer to dma_buf"; |
| 118 gbm_bo_destroy(bo); | 121 gbm_bo_destroy(bo); |
| 119 return nullptr; | 122 return nullptr; |
| 120 } | 123 } |
| 121 std::vector<base::ScopedFD> fds; | 124 std::vector<base::ScopedFD> fds; |
| 122 fds.emplace_back(std::move(fd)); | 125 fds.emplace_back(std::move(fd)); |
| 123 std::vector<int> strides; | 126 std::vector<gfx::NativePixmapPlane> planes; |
| 124 strides.push_back(gbm_bo_get_stride(bo)); | 127 planes.emplace_back(gbm_bo_get_stride(bo), gbm_bo_get_plane_offset(bo, 0), |
| 125 std::vector<int> offsets; | 128 gbm_bo_get_format_modifier(bo)); |
| 126 offsets.push_back(gbm_bo_get_plane_offset(bo, 0)); | |
| 127 scoped_refptr<GbmBuffer> buffer(new GbmBuffer( | 129 scoped_refptr<GbmBuffer> buffer(new GbmBuffer( |
| 128 gbm, bo, format, usage, std::move(fds), size, strides, offsets)); | 130 gbm, bo, format, usage, std::move(fds), size, std::move(planes))); |
| 129 if (usage == gfx::BufferUsage::SCANOUT && !buffer->GetFramebufferId()) | 131 if (usage == gfx::BufferUsage::SCANOUT && !buffer->GetFramebufferId()) |
| 130 return nullptr; | 132 return nullptr; |
| 131 | 133 |
| 132 return buffer; | 134 return buffer; |
| 133 } | 135 } |
| 134 | 136 |
| 135 // static | 137 // static |
| 136 scoped_refptr<GbmBuffer> GbmBuffer::CreateBufferFromFds( | 138 scoped_refptr<GbmBuffer> GbmBuffer::CreateBufferFromFds( |
| 137 const scoped_refptr<GbmDevice>& gbm, | 139 const scoped_refptr<GbmDevice>& gbm, |
| 138 gfx::BufferFormat format, | 140 gfx::BufferFormat format, |
| 139 const gfx::Size& size, | 141 const gfx::Size& size, |
| 140 std::vector<base::ScopedFD>&& fds, | 142 std::vector<base::ScopedFD>&& fds, |
| 141 const std::vector<int>& strides, | 143 const std::vector<gfx::NativePixmapPlane>& planes) { |
| 142 const std::vector<int>& offsets) { | |
| 143 TRACE_EVENT2("drm", "GbmBuffer::CreateBufferFromFD", "device", | 144 TRACE_EVENT2("drm", "GbmBuffer::CreateBufferFromFD", "device", |
| 144 gbm->device_path().value(), "size", size.ToString()); | 145 gbm->device_path().value(), "size", size.ToString()); |
| 145 DCHECK_LE(fds.size(), strides.size()); | 146 DCHECK_LE(fds.size(), planes.size()); |
| 146 DCHECK_EQ(strides.size(), offsets.size()); | 147 DCHECK_EQ(planes[0].offset, 0); |
| 147 DCHECK_EQ(offsets[0], 0); | |
| 148 | 148 |
| 149 uint32_t fourcc_format = GetFourCCFormatFromBufferFormat(format); | 149 uint32_t fourcc_format = GetFourCCFormatFromBufferFormat(format); |
| 150 | 150 |
| 151 // Use scanout if supported. | 151 // Use scanout if supported. |
| 152 bool use_scanout = gbm_device_is_format_supported( | 152 bool use_scanout = gbm_device_is_format_supported( |
| 153 gbm->device(), fourcc_format, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); | 153 gbm->device(), fourcc_format, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); |
| 154 | 154 |
| 155 gbm_bo* bo = nullptr; | 155 gbm_bo* bo = nullptr; |
| 156 if (use_scanout) { | 156 if (use_scanout) { |
| 157 struct gbm_import_fd_data fd_data; | 157 struct gbm_import_fd_data fd_data; |
| 158 fd_data.fd = fds[0].get(); | 158 fd_data.fd = fds[0].get(); |
| 159 fd_data.width = size.width(); | 159 fd_data.width = size.width(); |
| 160 fd_data.height = size.height(); | 160 fd_data.height = size.height(); |
| 161 fd_data.stride = strides[0]; | 161 fd_data.stride = planes[0].stride; |
| 162 fd_data.format = fourcc_format; | 162 fd_data.format = fourcc_format; |
| 163 | 163 |
| 164 // The fd passed to gbm_bo_import is not ref-counted and need to be | 164 // The fd passed to gbm_bo_import is not ref-counted and need to be |
| 165 // kept open for the lifetime of the buffer. | 165 // kept open for the lifetime of the buffer. |
| 166 bo = gbm_bo_import(gbm->device(), GBM_BO_IMPORT_FD, &fd_data, | 166 bo = gbm_bo_import(gbm->device(), GBM_BO_IMPORT_FD, &fd_data, |
| 167 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); | 167 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); |
| 168 if (!bo) { | 168 if (!bo) { |
| 169 LOG(ERROR) << "nullptr returned from gbm_bo_import"; | 169 LOG(ERROR) << "nullptr returned from gbm_bo_import"; |
| 170 return nullptr; | 170 return nullptr; |
| 171 } | 171 } |
| 172 } | 172 } |
| 173 | 173 |
| 174 scoped_refptr<GbmBuffer> buffer(new GbmBuffer( | 174 scoped_refptr<GbmBuffer> buffer(new GbmBuffer( |
| 175 gbm, bo, format, | 175 gbm, bo, format, |
| 176 use_scanout ? gfx::BufferUsage::SCANOUT : gfx::BufferUsage::GPU_READ, | 176 use_scanout ? gfx::BufferUsage::SCANOUT : gfx::BufferUsage::GPU_READ, |
| 177 std::move(fds), size, strides, offsets)); | 177 std::move(fds), size, std::move(planes))); |
| 178 // If scanout support for buffer is expected then make sure we managed to | 178 // If scanout support for buffer is expected then make sure we managed to |
| 179 // create a framebuffer for it as otherwise using it for scanout will fail. | 179 // create a framebuffer for it as otherwise using it for scanout will fail. |
| 180 if (use_scanout && !buffer->GetFramebufferId()) | 180 if (use_scanout && !buffer->GetFramebufferId()) |
| 181 return nullptr; | 181 return nullptr; |
| 182 | 182 |
| 183 return buffer; | 183 return buffer; |
| 184 } | 184 } |
| 185 | 185 |
| 186 GbmPixmap::GbmPixmap(GbmSurfaceFactory* surface_manager, | 186 GbmPixmap::GbmPixmap(GbmSurfaceFactory* surface_manager, |
| 187 const scoped_refptr<GbmBuffer>& buffer) | 187 const scoped_refptr<GbmBuffer>& buffer) |
| (...skipping 12 matching lines...) Expand all Loading... |
| 200 // Some formats (e.g: YVU_420) might have less than one fd per plane. | 200 // Some formats (e.g: YVU_420) might have less than one fd per plane. |
| 201 if (i < buffer_->GetFdCount()) { | 201 if (i < buffer_->GetFdCount()) { |
| 202 base::ScopedFD scoped_fd(HANDLE_EINTR(dup(buffer_->GetFd(i)))); | 202 base::ScopedFD scoped_fd(HANDLE_EINTR(dup(buffer_->GetFd(i)))); |
| 203 if (!scoped_fd.is_valid()) { | 203 if (!scoped_fd.is_valid()) { |
| 204 PLOG(ERROR) << "dup"; | 204 PLOG(ERROR) << "dup"; |
| 205 return gfx::NativePixmapHandle(); | 205 return gfx::NativePixmapHandle(); |
| 206 } | 206 } |
| 207 handle.fds.emplace_back( | 207 handle.fds.emplace_back( |
| 208 base::FileDescriptor(scoped_fd.release(), true /* auto_close */)); | 208 base::FileDescriptor(scoped_fd.release(), true /* auto_close */)); |
| 209 } | 209 } |
| 210 handle.strides_and_offsets.emplace_back(buffer_->GetStride(i), | 210 handle.planes.emplace_back(buffer_->GetStride(i), buffer_->GetOffset(i), |
| 211 buffer_->GetOffset(i)); | 211 buffer_->GetFormatModifier(i)); |
| 212 } | 212 } |
| 213 return handle; | 213 return handle; |
| 214 } | 214 } |
| 215 | 215 |
| 216 GbmPixmap::~GbmPixmap() { | 216 GbmPixmap::~GbmPixmap() { |
| 217 } | 217 } |
| 218 | 218 |
| 219 void* GbmPixmap::GetEGLClientBuffer() const { | 219 void* GbmPixmap::GetEGLClientBuffer() const { |
| 220 return nullptr; | 220 return nullptr; |
| 221 } | 221 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 233 } | 233 } |
| 234 | 234 |
| 235 int GbmPixmap::GetDmaBufPitch(size_t plane) const { | 235 int GbmPixmap::GetDmaBufPitch(size_t plane) const { |
| 236 return buffer_->GetStride(plane); | 236 return buffer_->GetStride(plane); |
| 237 } | 237 } |
| 238 | 238 |
| 239 int GbmPixmap::GetDmaBufOffset(size_t plane) const { | 239 int GbmPixmap::GetDmaBufOffset(size_t plane) const { |
| 240 return buffer_->GetOffset(plane); | 240 return buffer_->GetOffset(plane); |
| 241 } | 241 } |
| 242 | 242 |
| 243 uint64_t GbmPixmap::GetDmaBufModifier(size_t plane) const { |
| 244 return buffer_->GetFormatModifier(plane); |
| 245 } |
| 246 |
| 243 gfx::BufferFormat GbmPixmap::GetBufferFormat() const { | 247 gfx::BufferFormat GbmPixmap::GetBufferFormat() const { |
| 244 return buffer_->GetFormat(); | 248 return buffer_->GetFormat(); |
| 245 } | 249 } |
| 246 | 250 |
| 247 gfx::Size GbmPixmap::GetBufferSize() const { | 251 gfx::Size GbmPixmap::GetBufferSize() const { |
| 248 return buffer_->GetSize(); | 252 return buffer_->GetSize(); |
| 249 } | 253 } |
| 250 | 254 |
| 251 bool GbmPixmap::ScheduleOverlayPlane(gfx::AcceleratedWidget widget, | 255 bool GbmPixmap::ScheduleOverlayPlane(gfx::AcceleratedWidget widget, |
| 252 int plane_z_order, | 256 int plane_z_order, |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 290 DCHECK(!processing_callback_.is_null()); | 294 DCHECK(!processing_callback_.is_null()); |
| 291 if (!processing_callback_.Run(this, processed_pixmap_)) { | 295 if (!processing_callback_.Run(this, processed_pixmap_)) { |
| 292 LOG(ERROR) << "Failed processing NativePixmap"; | 296 LOG(ERROR) << "Failed processing NativePixmap"; |
| 293 return nullptr; | 297 return nullptr; |
| 294 } | 298 } |
| 295 | 299 |
| 296 return processed_pixmap_->buffer(); | 300 return processed_pixmap_->buffer(); |
| 297 } | 301 } |
| 298 | 302 |
| 299 } // namespace ui | 303 } // namespace ui |
| OLD | NEW |