| // Copyright 2022 The Chromium Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "gpu/command_buffer/service/shared_image/gl_repack_utils.h" | |
| #include <vector> | |
| #include "base/bits.h" | |
| #include "base/check_op.h" | |
| #include "base/containers/span.h" | |
| #include "gpu/command_buffer/service/shared_image/copy_image_plane.h" | |
| #include "third_party/skia/include/core/SkPixmap.h" | |
| #include "ui/gfx/skia_span_util.h" | |
| namespace gpu { | |
| std::vector<uint8_t> RepackPixelDataAsRgb(const gfx::Size& size, | |
| const SkPixmap& src_pixmap, | |
| bool src_is_bgrx) { | |
| DCHECK_EQ(src_pixmap.info().bytesPerPixel(), 4); | |
| constexpr size_t kSrcBytesPerPixel = 4; | |
| constexpr size_t kDstBytesPerPixel = 3; | |
| base::span<const uint8_t> src_data = gfx::SkPixmapToSpan(src_pixmap); | |
| size_t src_stride = src_pixmap.rowBytes(); | |
| // 3 bytes per pixel with 4 byte row alignment. | |
| size_t dst_stride = | |
| base::bits::AlignUp<size_t>(size.width() * kDstBytesPerPixel, 4); | |
| std::vector<uint8_t> dst_data(dst_stride * size.height()); | |
| base::span<uint8_t> dst_span(dst_data); | |
| const size_t src_payload_bytes = size.width() * kSrcBytesPerPixel; | |
| const size_t dst_payload_bytes = size.width() * kDstBytesPerPixel; | |
| for (int y = 0; y < size.height(); ++y) { | |
| base::span<const uint8_t> src_row = | |
| src_data.subspan(y * src_stride, src_payload_bytes); | |
| base::span<uint8_t> dst_row = | |
| dst_span.subspan(y * dst_stride, dst_payload_bytes); | |
| for (int x = 0; x < size.width(); ++x) { | |
| base::span<const uint8_t, kSrcBytesPerPixel> src = | |
| src_row.take_first<kSrcBytesPerPixel>(); | |
| base::span<uint8_t, kDstBytesPerPixel> dst = | |
| dst_row.take_first<kDstBytesPerPixel>(); | |
| if (src_is_bgrx) { | |
| dst[0] = src[2]; | |
| dst[1] = src[1]; | |
| dst[2] = src[0]; | |
| } else { | |
| dst[0] = src[0]; | |
| dst[1] = src[1]; | |
| dst[2] = src[2]; | |
| } | |
| } | |
| } | |
| return dst_data; | |
| } | |
| std::vector<uint8_t> RepackPixelDataWithStride(const gfx::Size& size, | |
| const SkPixmap& src_pixmap, | |
| size_t dst_stride) { | |
| size_t src_stride = src_pixmap.rowBytes(); | |
| DCHECK_LT(dst_stride, src_stride); | |
| std::vector<uint8_t> dst_data(dst_stride * size.height()); | |
| CopyImagePlane(gfx::SkPixmapToSpan(src_pixmap), src_stride, dst_data, | |
| dst_stride, src_pixmap.info().minRowBytes(), size.height()); | |
| return dst_data; | |
| } | |
| void UnpackPixelDataWithStride(const gfx::Size& size, | |
| const std::vector<uint8_t>& src_data, | |
| size_t src_stride, | |
| const SkPixmap& dst_pixmap) { | |
| size_t dst_stride = dst_pixmap.rowBytes(); | |
| DCHECK_GT(dst_stride, src_stride); | |
| CopyImagePlane(src_data, src_stride, gfx::SkPixmapToWritableSpan(dst_pixmap), | |
| dst_stride, dst_pixmap.info().minRowBytes(), size.height()); | |
| } | |
| void SwizzleRedAndBlue(const SkPixmap& pixmap) { | |
| DCHECK_EQ(pixmap.info().bytesPerPixel(), 4); | |
| base::span<uint8_t> data = gfx::SkPixmapToWritableSpan(pixmap); | |
| size_t stride = pixmap.rowBytes(); | |
| for (int y = 0; y < pixmap.height(); ++y) { | |
| size_t row_offset = y * stride; | |
| for (int x = 0; x < pixmap.width(); ++x) { | |
| size_t pixel_offset = row_offset + x * 4; | |
| std::swap(data[pixel_offset], data[pixel_offset + 2]); | |
| } | |
| } | |
| } | |
| } // namespace gpu |