1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
gpu / command_buffer / service / shared_image / shared_image_format_service_utils_mac.mm [blame]
// 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/shared_image_format_service_utils.h"
#include <CoreVideo/CoreVideo.h>
#include <Metal/Metal.h>
#include "base/check_op.h"
#include "base/logging.h"
#include "base/notreached.h"
#include "components/viz/common/resources/shared_image_format.h"
#if BUILDFLAG(SKIA_USE_METAL)
#include "third_party/skia/include/gpu/graphite/mtl/MtlGraphiteTypes.h"
#endif
namespace gpu {
uint32_t SharedImageFormatToIOSurfacePixelFormat(viz::SharedImageFormat format,
bool override_rgba_to_bgra) {
if (format.is_single_plane()) {
if (format == viz::SinglePlaneFormat::kR_8) {
return kCVPixelFormatType_OneComponent8;
} else if (format == viz::SinglePlaneFormat::kRG_88) {
return kCVPixelFormatType_TwoComponent8;
} else if (format == viz::SinglePlaneFormat::kR_16) {
return kCVPixelFormatType_OneComponent16;
} else if (format == viz::SinglePlaneFormat::kRG_1616) {
return kCVPixelFormatType_TwoComponent16;
} else if (format == viz::SinglePlaneFormat::kBGRA_1010102) {
return kCVPixelFormatType_ARGB2101010LEPacked;
} else if (format == viz::SinglePlaneFormat::kBGRA_8888 ||
format == viz::SinglePlaneFormat::kBGRX_8888) {
return kCVPixelFormatType_32BGRA;
} else if (format == viz::SinglePlaneFormat::kRGBA_8888 ||
format == viz::SinglePlaneFormat::kRGBX_8888) {
return override_rgba_to_bgra ? kCVPixelFormatType_32BGRA
: kCVPixelFormatType_32RGBA;
} else if (format == viz::SinglePlaneFormat::kRGBA_F16) {
return kCVPixelFormatType_64RGBAHalf;
} else if (format == viz::SinglePlaneFormat::kBGR_565 ||
format == viz::SinglePlaneFormat::kRGBA_4444 ||
format == viz::SinglePlaneFormat::kRGBA_1010102) {
// Technically RGBA_1010102 should be accepted as 'R10k', but
// then it won't be supported by CGLTexImageIOSurface2D(), so
// it's best to reject it here.
return 0;
}
} else if (format.is_multi_plane()) {
if (format == viz::MultiPlaneFormat::kNV12) {
return kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
} else if (format == viz::MultiPlaneFormat::kNV16) {
return kCVPixelFormatType_422YpCbCr8BiPlanarVideoRange;
} else if (format == viz::MultiPlaneFormat::kNV24) {
return kCVPixelFormatType_444YpCbCr8BiPlanarVideoRange;
} else if (format == viz::MultiPlaneFormat::kNV12A) {
return kCVPixelFormatType_420YpCbCr8VideoRange_8A_TriPlanar;
} else if (format == viz::MultiPlaneFormat::kP010) {
return kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange;
} else if (format == viz::MultiPlaneFormat::kP210) {
return kCVPixelFormatType_422YpCbCr10BiPlanarVideoRange;
} else if (format == viz::MultiPlaneFormat::kP410) {
return kCVPixelFormatType_444YpCbCr10BiPlanarVideoRange;
} else if (format == viz::MultiPlaneFormat::kI420) {
return kCVPixelFormatType_420YpCbCr8Planar;
} else if (format == viz::MultiPlaneFormat::kYV12) {
return 0;
}
}
NOTREACHED();
}
unsigned int ToMTLPixelFormat(viz::SharedImageFormat format, int plane_index) {
MTLPixelFormat mtl_pixel_format = MTLPixelFormatInvalid;
if (format.is_single_plane()) {
if (format == viz::SinglePlaneFormat::kR_8 ||
format == viz::SinglePlaneFormat::kALPHA_8 ||
format == viz::SinglePlaneFormat::kLUMINANCE_8) {
mtl_pixel_format = MTLPixelFormatR8Unorm;
} else if (format == viz::SinglePlaneFormat::kRG_88) {
mtl_pixel_format = MTLPixelFormatRG8Unorm;
} else if (format == viz::SinglePlaneFormat::kRGBA_8888) {
mtl_pixel_format = MTLPixelFormatRGBA8Unorm;
} else if (format == viz::SinglePlaneFormat::kBGRA_8888) {
mtl_pixel_format = MTLPixelFormatBGRA8Unorm;
} else {
DLOG(ERROR) << "Invalid Metal pixel format:" << format.ToString();
}
return static_cast<unsigned int>(mtl_pixel_format);
}
// Does not support external sampler.
if (format.PrefersExternalSampler()) {
return static_cast<unsigned int>(MTLPixelFormatInvalid);
}
// For multiplanar formats without external sampler, Metal formats are per
// plane.
// For 1 channel 8-bit planes Y, U, V, A return MTLPixelFormatR8Unorm.
// For 2 channel 8-bit plane UV return MTLPixelFormatRG8Unorm.
// For 1 channel 10/16-bit planes Y, U, V, A return MTLPixelFormatR16Unorm.
// For 2 channel 10/16-bit plane UV return MTLPixelFormatRG16Unorm.
// For 1 channel 16-bit float planes Y, U, V, A return MTLPixelFormatR16Float.
// For 2 channel 16-bit float plane UV return MTLPixelFormatRG16Float.
int num_channels = format.NumChannelsInPlane(plane_index);
DCHECK_LE(num_channels, 2);
switch (format.channel_format()) {
case viz::SharedImageFormat::ChannelFormat::k8:
mtl_pixel_format =
num_channels == 2 ? MTLPixelFormatRG8Unorm : MTLPixelFormatR8Unorm;
break;
case viz::SharedImageFormat::ChannelFormat::k10:
case viz::SharedImageFormat::ChannelFormat::k16:
mtl_pixel_format =
num_channels == 2 ? MTLPixelFormatRG16Unorm : MTLPixelFormatR16Unorm;
break;
case viz::SharedImageFormat::ChannelFormat::k16F:
mtl_pixel_format =
num_channels == 2 ? MTLPixelFormatRG16Float : MTLPixelFormatR16Float;
break;
}
return static_cast<unsigned int>(mtl_pixel_format);
}
#if BUILDFLAG(SKIA_USE_METAL)
skgpu::graphite::TextureInfo GraphiteMetalTextureInfo(
viz::SharedImageFormat format,
int plane_index,
bool is_yuv_plane,
bool mipmapped) {
MTLPixelFormat mtl_pixel_format =
static_cast<MTLPixelFormat>(ToMTLPixelFormat(format, plane_index));
CHECK_NE(mtl_pixel_format, MTLPixelFormatInvalid);
// Must match CreateMetalTexture in iosurface_image_backing.mm.
// TODO(sunnyps): Move constants to a common utility header.
skgpu::graphite::MtlTextureInfo mtl_texture_info;
mtl_texture_info.fSampleCount = 1;
mtl_texture_info.fFormat = mtl_pixel_format;
mtl_texture_info.fUsage = MTLTextureUsageShaderRead;
if (format.is_single_plane() && !is_yuv_plane) {
mtl_texture_info.fUsage |= MTLTextureUsageRenderTarget;
}
#if BUILDFLAG(IS_IOS)
mtl_texture_info.fStorageMode = MTLStorageModeShared;
#else
mtl_texture_info.fStorageMode = MTLStorageModeManaged;
#endif
mtl_texture_info.fMipmapped =
mipmapped ? skgpu::Mipmapped::kYes : skgpu::Mipmapped::kNo;
return skgpu::graphite::TextureInfos::MakeMetal(mtl_texture_info);
}
#endif
} // namespace gpu