Upload upstream chromium 120.0.6099.5
[platform/framework/web/chromium-efl.git] / media / renderers / shared_image_video_frame_test_utils.cc
1 // Copyright 2021 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/renderers/shared_image_video_frame_test_utils.h"
6
7 #include "base/logging.h"
8 #include "components/viz/common/gpu/context_provider.h"
9 #include "components/viz/common/resources/shared_image_format.h"
10 #include "gpu/GLES2/gl2extchromium.h"
11 #include "gpu/command_buffer/client/client_shared_image.h"
12 #include "gpu/command_buffer/client/gles2_interface_stub.h"
13 #include "gpu/command_buffer/client/shared_image_interface.h"
14 #include "gpu/command_buffer/common/capabilities.h"
15 #include "gpu/command_buffer/common/shared_image_usage.h"
16
17 namespace media {
18
19 namespace {
20
21 static constexpr const uint8_t kYuvColors[8][3] = {
22     {0x00, 0x80, 0x80},  // Black
23     {0x4c, 0x54, 0xff},  // Red
24     {0x95, 0x2b, 0x15},  // Green
25     {0xe1, 0x00, 0x94},  // Yellow
26     {0x1d, 0xff, 0x6b},  // Blue
27     {0x69, 0xd3, 0xec},  // Magenta
28     {0xb3, 0xaa, 0x00},  // Cyan
29     {0xff, 0x80, 0x80},  // White
30 };
31
32 // Destroys a list of shared images after a sync token is passed. Also runs
33 // |callback|.
34 void DestroySharedImages(scoped_refptr<viz::ContextProvider> context_provider,
35                          std::vector<gpu::Mailbox> mailboxes,
36                          base::OnceClosure callback,
37                          const gpu::SyncToken& sync_token) {
38   auto* sii = context_provider->SharedImageInterface();
39   for (const auto& mailbox : mailboxes)
40     sii->DestroySharedImage(sync_token, mailbox);
41   std::move(callback).Run();
42 }
43
44 }  // namespace
45
46 scoped_refptr<VideoFrame> CreateSharedImageFrame(
47     scoped_refptr<viz::ContextProvider> context_provider,
48     VideoPixelFormat format,
49     std::vector<gpu::Mailbox> mailboxes,
50     const gpu::SyncToken& sync_token,
51     GLenum texture_target,
52     const gfx::Size& coded_size,
53     const gfx::Rect& visible_rect,
54     const gfx::Size& natural_size,
55     base::TimeDelta timestamp,
56     base::OnceClosure destroyed_callback) {
57   gpu::MailboxHolder mailboxes_for_frame[VideoFrame::kMaxPlanes] = {};
58   size_t i = 0;
59   for (const auto& mailbox : mailboxes) {
60     mailboxes_for_frame[i++] =
61         gpu::MailboxHolder(mailbox, sync_token, texture_target);
62   }
63   auto callback =
64       base::BindOnce(&DestroySharedImages, std::move(context_provider),
65                      std::move(mailboxes), std::move(destroyed_callback));
66   return VideoFrame::WrapNativeTextures(format, mailboxes_for_frame,
67                                         std::move(callback), coded_size,
68                                         visible_rect, natural_size, timestamp);
69 }
70
71 scoped_refptr<VideoFrame> CreateSharedImageRGBAFrame(
72     scoped_refptr<viz::ContextProvider> context_provider,
73     const gfx::Size& coded_size,
74     const gfx::Rect& visible_rect,
75     base::OnceClosure destroyed_callback) {
76   DCHECK_EQ(coded_size.width() % 4, 0);
77   DCHECK_EQ(coded_size.height() % 2, 0);
78   size_t pixels_size = coded_size.GetArea() * 4;
79   std::vector<uint8_t> pixels(pixels_size);
80   size_t i = 0;
81   for (size_t block_y = 0; block_y < 2u; ++block_y) {
82     for (int y = 0; y < coded_size.height() / 2; ++y) {
83       for (size_t block_x = 0; block_x < 4u; ++block_x) {
84         for (int x = 0; x < coded_size.width() / 4; ++x) {
85           pixels[i++] = 0xffu * (block_x % 2);  // R
86           pixels[i++] = 0xffu * (block_x / 2);  // G
87           pixels[i++] = 0xffu * block_y;        // B
88           pixels[i++] = 0xffu;                  // A
89         }
90       }
91     }
92   }
93   DCHECK_EQ(i, pixels_size);
94
95   auto* sii = context_provider->SharedImageInterface();
96   gpu::Mailbox mailbox =
97       sii->CreateSharedImage(viz::SinglePlaneFormat::kRGBA_8888, coded_size,
98                              gfx::ColorSpace(), kTopLeft_GrSurfaceOrigin,
99                              kPremul_SkAlphaType, gpu::SHARED_IMAGE_USAGE_GLES2,
100                              "RGBAVideoFrame", pixels)
101           ->mailbox();
102
103   return CreateSharedImageFrame(
104       std::move(context_provider), VideoPixelFormat::PIXEL_FORMAT_ABGR,
105       {mailbox}, {}, GL_TEXTURE_2D, coded_size, visible_rect,
106       visible_rect.size(), base::Seconds(1), std::move(destroyed_callback));
107 }
108
109 scoped_refptr<VideoFrame> CreateSharedImageI420Frame(
110     scoped_refptr<viz::ContextProvider> context_provider,
111     const gfx::Size& coded_size,
112     const gfx::Rect& visible_rect,
113     base::OnceClosure destroyed_callback) {
114   DCHECK_EQ(coded_size.width() % 8, 0);
115   DCHECK_EQ(coded_size.height() % 4, 0);
116   gfx::Size uv_size(coded_size.width() / 2, coded_size.height() / 2);
117   size_t y_pixels_size = coded_size.GetArea();
118   size_t uv_pixels_size = uv_size.GetArea();
119   std::vector<uint8_t> y_pixels(y_pixels_size);
120   std::vector<uint8_t> u_pixels(uv_pixels_size);
121   std::vector<uint8_t> v_pixels(uv_pixels_size);
122   size_t y_i = 0;
123   size_t uv_i = 0;
124   for (size_t block_y = 0; block_y < 2u; ++block_y) {
125     for (int y = 0; y < coded_size.height() / 2; ++y) {
126       for (size_t block_x = 0; block_x < 4u; ++block_x) {
127         size_t color_index = block_x + block_y * 4;
128         const uint8_t* yuv = kYuvColors[color_index];
129         for (int x = 0; x < coded_size.width() / 4; ++x) {
130           y_pixels[y_i++] = yuv[0];
131           if ((x % 2) && (y % 2)) {
132             u_pixels[uv_i] = yuv[1];
133             v_pixels[uv_i++] = yuv[2];
134           }
135         }
136       }
137     }
138   }
139   DCHECK_EQ(y_i, y_pixels_size);
140   DCHECK_EQ(uv_i, uv_pixels_size);
141
142   auto plane_format = context_provider->ContextCapabilities().texture_rg
143                           ? viz::SinglePlaneFormat::kR_8
144                           : viz::SinglePlaneFormat::kLUMINANCE_8;
145   auto* sii = context_provider->SharedImageInterface();
146   gpu::Mailbox y_mailbox =
147       sii->CreateSharedImage(plane_format, coded_size, gfx::ColorSpace(),
148                              kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType,
149                              gpu::SHARED_IMAGE_USAGE_GLES2, "I420Frame_Y",
150                              y_pixels)
151           ->mailbox();
152   gpu::Mailbox u_mailbox =
153       sii->CreateSharedImage(plane_format, uv_size, gfx::ColorSpace(),
154                              kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType,
155                              gpu::SHARED_IMAGE_USAGE_GLES2, "I420Frame_U",
156                              u_pixels)
157           ->mailbox();
158   gpu::Mailbox v_mailbox =
159       sii->CreateSharedImage(plane_format, uv_size, gfx::ColorSpace(),
160                              kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType,
161                              gpu::SHARED_IMAGE_USAGE_GLES2, "I420Frame_V",
162                              v_pixels)
163           ->mailbox();
164
165   return CreateSharedImageFrame(
166       std::move(context_provider), VideoPixelFormat::PIXEL_FORMAT_I420,
167       {y_mailbox, u_mailbox, v_mailbox}, {}, GL_TEXTURE_2D, coded_size,
168       visible_rect, visible_rect.size(), base::Seconds(1),
169       std::move(destroyed_callback));
170 }
171
172 scoped_refptr<VideoFrame> CreateSharedImageNV12Frame(
173     scoped_refptr<viz::ContextProvider> context_provider,
174     const gfx::Size& coded_size,
175     const gfx::Rect& visible_rect,
176     base::OnceClosure destroyed_callback) {
177   DCHECK_EQ(coded_size.width() % 8, 0);
178   DCHECK_EQ(coded_size.height() % 4, 0);
179   if (!context_provider->ContextCapabilities().texture_rg) {
180     LOG(ERROR) << "GL_EXT_texture_rg not supported";
181     return {};
182   }
183   gfx::Size uv_size(coded_size.width() / 2, coded_size.height() / 2);
184   size_t y_pixels_size = coded_size.GetArea();
185   size_t uv_pixels_size = uv_size.GetArea() * 2;
186   std::vector<uint8_t> y_pixels(y_pixels_size);
187   std::vector<uint8_t> uv_pixels(uv_pixels_size);
188   size_t y_i = 0;
189   size_t uv_i = 0;
190   for (size_t block_y = 0; block_y < 2u; ++block_y) {
191     for (int y = 0; y < coded_size.height() / 2; ++y) {
192       for (size_t block_x = 0; block_x < 4u; ++block_x) {
193         size_t color_index = block_x + block_y * 4;
194         const uint8_t* yuv = kYuvColors[color_index];
195         for (int x = 0; x < coded_size.width() / 4; ++x) {
196           y_pixels[y_i++] = yuv[0];
197           if ((x % 2) && (y % 2)) {
198             uv_pixels[uv_i++] = yuv[1];
199             uv_pixels[uv_i++] = yuv[2];
200           }
201         }
202       }
203     }
204   }
205   DCHECK_EQ(y_i, y_pixels_size);
206   DCHECK_EQ(uv_i, uv_pixels_size);
207
208   auto* sii = context_provider->SharedImageInterface();
209   gpu::Mailbox y_mailbox =
210       sii->CreateSharedImage(viz::SinglePlaneFormat::kR_8, coded_size,
211                              gfx::ColorSpace(), kTopLeft_GrSurfaceOrigin,
212                              kPremul_SkAlphaType, gpu::SHARED_IMAGE_USAGE_GLES2,
213                              "NV12Frame_Y", y_pixels)
214           ->mailbox();
215   gpu::Mailbox uv_mailbox =
216       sii->CreateSharedImage(viz::SinglePlaneFormat::kRG_88, uv_size,
217                              gfx::ColorSpace(), kTopLeft_GrSurfaceOrigin,
218                              kPremul_SkAlphaType, gpu::SHARED_IMAGE_USAGE_GLES2,
219                              "NV12Frame_UV", uv_pixels)
220           ->mailbox();
221   return CreateSharedImageFrame(
222       std::move(context_provider), VideoPixelFormat::PIXEL_FORMAT_NV12,
223       {y_mailbox, uv_mailbox}, {}, GL_TEXTURE_2D, coded_size, visible_rect,
224       visible_rect.size(), base::Seconds(1), std::move(destroyed_callback));
225 }
226
227 }  // namespace media