Fix FullScreen crash in Webapp
[platform/framework/web/chromium-efl.git] / media / renderers / paint_canvas_video_renderer_unittest.cc
1 // Copyright 2012 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 <GLES3/gl3.h>
6 #include <stdint.h>
7
8 #include "base/functional/bind.h"
9 #include "base/logging.h"
10 #include "base/memory/aligned_memory.h"
11 #include "base/memory/raw_ptr.h"
12 #include "base/sys_byteorder.h"
13 #include "base/test/task_environment.h"
14 #include "build/build_config.h"
15 #include "cc/paint/paint_flags.h"
16 #include "cc/paint/skia_paint_canvas.h"
17 #include "components/viz/common/gpu/context_provider.h"
18 #include "components/viz/test/test_context_provider.h"
19 #include "components/viz/test/test_gpu_service_holder.h"
20 #include "components/viz/test/test_in_process_context_provider.h"
21 #include "gpu/GLES2/gl2extchromium.h"
22 #include "gpu/command_buffer/client/gles2_interface_stub.h"
23 #include "gpu/command_buffer/common/capabilities.h"
24 #include "gpu/command_buffer/common/shared_image_usage.h"
25 #include "gpu/config/gpu_feature_info.h"
26 #include "media/base/timestamp_constants.h"
27 #include "media/base/video_frame.h"
28 #include "media/base/video_util.h"
29 #include "media/renderers/paint_canvas_video_renderer.h"
30 #include "media/renderers/shared_image_video_frame_test_utils.h"
31 #include "testing/gtest/include/gtest/gtest.h"
32 #include "third_party/libyuv/include/libyuv/convert.h"
33 #include "third_party/libyuv/include/libyuv/scale.h"
34 #include "third_party/skia/include/core/SkColorPriv.h"
35 #include "third_party/skia/include/core/SkImage.h"
36 #include "third_party/skia/include/core/SkRefCnt.h"
37 #include "third_party/skia/include/core/SkSurface.h"
38 #include "third_party/skia/include/gpu/GrDirectContext.h"
39 #include "ui/gfx/color_space.h"
40 #include "ui/gfx/geometry/rect_f.h"
41 #include "ui/gl/gl_implementation.h"
42 #include "ui/gl/test/gl_surface_test_support.h"
43
44 using media::VideoFrame;
45
46 namespace media {
47
48 static const int kWidth = 320;
49 static const int kHeight = 240;
50 static const gfx::RectF kNaturalRect(kWidth, kHeight);
51
52 // Generate frame pixels to provided |external_memory| and wrap it as frame.
53 scoped_refptr<VideoFrame> CreateTestY16Frame(const gfx::Size& coded_size,
54                                              const gfx::Rect& visible_rect,
55                                              void* external_memory,
56                                              base::TimeDelta timestamp) {
57   const int offset_x = visible_rect.x();
58   const int offset_y = visible_rect.y();
59   const int stride = coded_size.width();
60   const size_t byte_size = stride * coded_size.height() * 2;
61
62   // In the visible rect, fill upper byte with [0-255] and lower with [255-0].
63   uint16_t* data = static_cast<uint16_t*>(external_memory);
64   for (int j = 0; j < visible_rect.height(); j++) {
65     for (int i = 0; i < visible_rect.width(); i++) {
66       const int value = i + j * visible_rect.width();
67       data[(stride * (j + offset_y)) + i + offset_x] =
68           ((value & 0xFF) << 8) | (~value & 0xFF);
69     }
70   }
71
72   return media::VideoFrame::WrapExternalData(
73       media::PIXEL_FORMAT_Y16, coded_size, visible_rect, visible_rect.size(),
74       static_cast<uint8_t*>(external_memory), byte_size, timestamp);
75 }
76
77 // Readback the contents of a RGBA texture into an array of RGBA values.
78 static std::unique_ptr<uint8_t[]> ReadbackTexture(
79     gpu::gles2::GLES2Interface* gl,
80     GLuint texture,
81     const gfx::Size& size) {
82   size_t pixel_count = size.width() * size.height();
83   GLuint fbo = 0;
84   gl->GenFramebuffers(1, &fbo);
85   gl->BindFramebuffer(GL_FRAMEBUFFER, fbo);
86   gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
87                            texture, 0);
88   auto pixels = std::make_unique<uint8_t[]>(pixel_count * 4);
89   uint8_t* raw_pixels = pixels.get();
90   gl->ReadPixels(0, 0, size.width(), size.height(), GL_RGBA, GL_UNSIGNED_BYTE,
91                  raw_pixels);
92   gl->DeleteFramebuffers(1, &fbo);
93   return pixels;
94 }
95
96 // Returns a functor that retrieves a SkColor for a given pixel, from raw RGBA
97 // data.
98 static auto ColorGetter(uint8_t* pixels, const gfx::Size& size) {
99   return [pixels, size](size_t x, size_t y) {
100     uint8_t* p = pixels + (size.width() * y + x) * 4;
101     return SkColorSetARGB(p[3], p[0], p[1], p[2]);
102   };
103 }
104
105 class PaintCanvasVideoRendererTest : public testing::Test {
106  public:
107   enum Color {
108     kNone,
109     kRed,
110     kGreen,
111     kBlue,
112   };
113
114   PaintCanvasVideoRendererTest();
115
116   PaintCanvasVideoRendererTest(const PaintCanvasVideoRendererTest&) = delete;
117   PaintCanvasVideoRendererTest& operator=(const PaintCanvasVideoRendererTest&) =
118       delete;
119
120   ~PaintCanvasVideoRendererTest() override;
121
122   // Paints to |canvas| using |renderer_| without any frame data.
123   void PaintWithoutFrame(cc::PaintCanvas* canvas);
124
125   // Paints the |video_frame| to the |canvas| using |renderer_|, setting the
126   // color of |video_frame| to |color| first.
127   void Paint(scoped_refptr<VideoFrame> video_frame,
128              cc::PaintCanvas* canvas,
129              Color color);
130   void PaintRotated(scoped_refptr<VideoFrame> video_frame,
131                     cc::PaintCanvas* canvas,
132                     const gfx::RectF& dest_rect,
133                     Color color,
134                     SkBlendMode mode,
135                     VideoTransformation video_transformation);
136
137   void Copy(scoped_refptr<VideoFrame> video_frame, cc::PaintCanvas* canvas);
138
139   // Getters for various frame sizes.
140   scoped_refptr<VideoFrame> natural_frame() { return natural_frame_; }
141   scoped_refptr<VideoFrame> larger_frame() { return larger_frame_; }
142   scoped_refptr<VideoFrame> smaller_frame() { return smaller_frame_; }
143   scoped_refptr<VideoFrame> cropped_frame() { return cropped_frame_; }
144
145   // Standard canvas.
146   cc::PaintCanvas* target_canvas() { return &target_canvas_; }
147   SkBitmap* bitmap() { return &bitmap_; }
148
149  protected:
150   PaintCanvasVideoRenderer renderer_;
151
152   scoped_refptr<VideoFrame> natural_frame_;
153   scoped_refptr<VideoFrame> larger_frame_;
154   scoped_refptr<VideoFrame> smaller_frame_;
155   scoped_refptr<VideoFrame> cropped_frame_;
156
157   SkBitmap bitmap_;
158   cc::SkiaPaintCanvas target_canvas_;
159   base::test::TaskEnvironment task_environment_;
160 };
161
162 static SkBitmap AllocBitmap(int width, int height) {
163   SkBitmap bitmap;
164   bitmap.allocPixels(SkImageInfo::MakeN32(width, height, kPremul_SkAlphaType));
165   bitmap.eraseColor(0);
166   return bitmap;
167 }
168
169 static scoped_refptr<VideoFrame> CreateCroppedFrame() {
170   scoped_refptr<VideoFrame> cropped_frame = VideoFrame::CreateFrame(
171       PIXEL_FORMAT_I420, gfx::Size(16, 16), gfx::Rect(6, 6, 8, 6),
172       gfx::Size(8, 6), base::Milliseconds(4));
173   // Make sure the cropped video frame's aspect ratio matches the output device.
174   // Update cropped_frame_'s crop dimensions if this is not the case.
175   EXPECT_EQ(cropped_frame->visible_rect().width() * kHeight,
176             cropped_frame->visible_rect().height() * kWidth);
177
178   // Fill in the cropped frame's entire data with colors:
179   //
180   //   Bl Bl Bl Bl Bl Bl Bl Bl R  R  R  R  R  R  R  R
181   //   Bl Bl Bl Bl Bl Bl Bl Bl R  R  R  R  R  R  R  R
182   //   Bl Bl Bl Bl Bl Bl Bl Bl R  R  R  R  R  R  R  R
183   //   Bl Bl Bl Bl Bl Bl Bl Bl R  R  R  R  R  R  R  R
184   //   Bl Bl Bl Bl Bl Bl Bl Bl R  R  R  R  R  R  R  R
185   //   Bl Bl Bl Bl Bl Bl Bl Bl R  R  R  R  R  R  R  R
186   //   Bl Bl Bl Bl Bl Bl Bl Bl R  R  R  R  R  R  R  R
187   //   Bl Bl Bl Bl Bl Bl Bl Bl R  R  R  R  R  R  R  R
188   //   G  G  G  G  G  G  G  G  B  B  B  B  B  B  B  B
189   //   G  G  G  G  G  G  G  G  B  B  B  B  B  B  B  B
190   //   G  G  G  G  G  G  G  G  B  B  B  B  B  B  B  B
191   //   G  G  G  G  G  G  G  G  B  B  B  B  B  B  B  B
192   //   G  G  G  G  G  G  G  G  B  B  B  B  B  B  B  B
193   //   G  G  G  G  G  G  G  G  B  B  B  B  B  B  B  B
194   //   G  G  G  G  G  G  G  G  B  B  B  B  B  B  B  B
195   //   G  G  G  G  G  G  G  G  B  B  B  B  B  B  B  B
196   //
197   // The visible crop of the frame (as set by its visible_rect_) has contents:
198   //
199   //   Bl Bl R  R  R  R  R  R
200   //   Bl Bl R  R  R  R  R  R
201   //   G  G  B  B  B  B  B  B
202   //   G  G  B  B  B  B  B  B
203   //   G  G  B  B  B  B  B  B
204   //   G  G  B  B  B  B  B  B
205   //
206   // Each color region in the cropped frame is on a 2x2 block granularity, to
207   // avoid sharing UV samples between regions.
208
209   static const uint8_t cropped_y_plane[] = {
210       0,   0,   0,   0,   0,   0,   0,   0,   76, 76, 76, 76, 76, 76, 76, 76,
211       0,   0,   0,   0,   0,   0,   0,   0,   76, 76, 76, 76, 76, 76, 76, 76,
212       0,   0,   0,   0,   0,   0,   0,   0,   76, 76, 76, 76, 76, 76, 76, 76,
213       0,   0,   0,   0,   0,   0,   0,   0,   76, 76, 76, 76, 76, 76, 76, 76,
214       0,   0,   0,   0,   0,   0,   0,   0,   76, 76, 76, 76, 76, 76, 76, 76,
215       0,   0,   0,   0,   0,   0,   0,   0,   76, 76, 76, 76, 76, 76, 76, 76,
216       0,   0,   0,   0,   0,   0,   0,   0,   76, 76, 76, 76, 76, 76, 76, 76,
217       0,   0,   0,   0,   0,   0,   0,   0,   76, 76, 76, 76, 76, 76, 76, 76,
218       149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29,
219       149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29,
220       149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29,
221       149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29,
222       149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29,
223       149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29,
224       149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29,
225       149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29,
226   };
227
228   static const uint8_t cropped_u_plane[] = {
229       128, 128, 128, 128, 84,  84,  84,  84,  128, 128, 128, 128, 84,
230       84,  84,  84,  128, 128, 128, 128, 84,  84,  84,  84,  128, 128,
231       128, 128, 84,  84,  84,  84,  43,  43,  43,  43,  255, 255, 255,
232       255, 43,  43,  43,  43,  255, 255, 255, 255, 43,  43,  43,  43,
233       255, 255, 255, 255, 43,  43,  43,  43,  255, 255, 255, 255,
234   };
235   static const uint8_t cropped_v_plane[] = {
236       128, 128, 128, 128, 255, 255, 255, 255, 128, 128, 128, 128, 255,
237       255, 255, 255, 128, 128, 128, 128, 255, 255, 255, 255, 128, 128,
238       128, 128, 255, 255, 255, 255, 21,  21,  21,  21,  107, 107, 107,
239       107, 21,  21,  21,  21,  107, 107, 107, 107, 21,  21,  21,  21,
240       107, 107, 107, 107, 21,  21,  21,  21,  107, 107, 107, 107,
241   };
242
243   libyuv::I420Copy(cropped_y_plane, 16, cropped_u_plane, 8, cropped_v_plane, 8,
244                    cropped_frame->writable_data(VideoFrame::kYPlane),
245                    cropped_frame->stride(VideoFrame::kYPlane),
246                    cropped_frame->writable_data(VideoFrame::kUPlane),
247                    cropped_frame->stride(VideoFrame::kUPlane),
248                    cropped_frame->writable_data(VideoFrame::kVPlane),
249                    cropped_frame->stride(VideoFrame::kVPlane), 16, 16);
250
251   return cropped_frame;
252 }
253
254 PaintCanvasVideoRendererTest::PaintCanvasVideoRendererTest()
255     : natural_frame_(VideoFrame::CreateBlackFrame(gfx::Size(kWidth, kHeight))),
256       larger_frame_(
257           VideoFrame::CreateBlackFrame(gfx::Size(kWidth * 2, kHeight * 2))),
258       smaller_frame_(
259           VideoFrame::CreateBlackFrame(gfx::Size(kWidth / 2, kHeight / 2))),
260       cropped_frame_(CreateCroppedFrame()),
261       bitmap_(AllocBitmap(kWidth, kHeight)),
262       target_canvas_(bitmap_) {
263   // Give each frame a unique timestamp.
264   natural_frame_->set_timestamp(base::Milliseconds(1));
265   larger_frame_->set_timestamp(base::Milliseconds(2));
266   smaller_frame_->set_timestamp(base::Milliseconds(3));
267 }
268
269 PaintCanvasVideoRendererTest::~PaintCanvasVideoRendererTest() = default;
270
271 void PaintCanvasVideoRendererTest::PaintWithoutFrame(cc::PaintCanvas* canvas) {
272   cc::PaintFlags flags;
273   flags.setFilterQuality(cc::PaintFlags::FilterQuality::kLow);
274   renderer_.Paint(nullptr, canvas, kNaturalRect, flags, kNoTransformation,
275                   nullptr);
276 }
277
278 void PaintCanvasVideoRendererTest::Paint(scoped_refptr<VideoFrame> video_frame,
279                                          cc::PaintCanvas* canvas,
280                                          Color color) {
281   PaintRotated(std::move(video_frame), canvas, kNaturalRect, color,
282                SkBlendMode::kSrcOver, kNoTransformation);
283 }
284
285 void PaintCanvasVideoRendererTest::PaintRotated(
286     scoped_refptr<VideoFrame> video_frame,
287     cc::PaintCanvas* canvas,
288     const gfx::RectF& dest_rect,
289     Color color,
290     SkBlendMode mode,
291     VideoTransformation video_transformation) {
292   switch (color) {
293     case kNone:
294       break;
295     case kRed:
296       media::FillYUV(video_frame.get(), 76, 84, 255);
297       break;
298     case kGreen:
299       media::FillYUV(video_frame.get(), 149, 43, 21);
300       break;
301     case kBlue:
302       media::FillYUV(video_frame.get(), 29, 255, 107);
303       break;
304   }
305   cc::PaintFlags flags;
306   flags.setBlendMode(mode);
307   flags.setFilterQuality(cc::PaintFlags::FilterQuality::kLow);
308   renderer_.Paint(std::move(video_frame), canvas, dest_rect, flags,
309                   video_transformation, nullptr);
310 }
311
312 void PaintCanvasVideoRendererTest::Copy(scoped_refptr<VideoFrame> video_frame,
313                                         cc::PaintCanvas* canvas) {
314   renderer_.Copy(std::move(video_frame), canvas, nullptr);
315 }
316
317 TEST_F(PaintCanvasVideoRendererTest, NoFrame) {
318   // Test that black gets painted over canvas.
319   target_canvas()->clear(SkColors::kRed);
320   PaintWithoutFrame(target_canvas());
321   EXPECT_EQ(SK_ColorBLACK, bitmap()->getColor(0, 0));
322 }
323
324 TEST_F(PaintCanvasVideoRendererTest, TransparentFrame) {
325   target_canvas()->clear(SkColors::kRed);
326   PaintRotated(
327       VideoFrame::CreateTransparentFrame(gfx::Size(kWidth, kHeight)).get(),
328       target_canvas(), kNaturalRect, kNone, SkBlendMode::kSrcOver,
329       kNoTransformation);
330   EXPECT_EQ(static_cast<SkColor>(SK_ColorRED), bitmap()->getColor(0, 0));
331 }
332
333 TEST_F(PaintCanvasVideoRendererTest, TransparentFrameSrcMode) {
334   target_canvas()->clear(SkColors::kRed);
335   // SRC mode completely overwrites the buffer.
336   PaintRotated(
337       VideoFrame::CreateTransparentFrame(gfx::Size(kWidth, kHeight)).get(),
338       target_canvas(), kNaturalRect, kNone, SkBlendMode::kSrc,
339       kNoTransformation);
340   EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT),
341             bitmap()->getColor(0, 0));
342 }
343
344 TEST_F(PaintCanvasVideoRendererTest, TransparentFrameSrcMode1x1) {
345   target_canvas()->clear(SkColors::kRed);
346   // SRC mode completely overwrites the buffer.
347   auto frame = VideoFrame::CreateTransparentFrame(gfx::Size(1, 1));
348   PaintRotated(frame.get(), target_canvas(), gfx::RectF(1, 1), kNone,
349                SkBlendMode::kSrc, kNoTransformation);
350   EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT),
351             bitmap()->getColor(0, 0));
352 }
353
354 TEST_F(PaintCanvasVideoRendererTest, CopyTransparentFrame) {
355   target_canvas()->clear(SkColors::kRed);
356   Copy(VideoFrame::CreateTransparentFrame(gfx::Size(kWidth, kHeight)).get(),
357        target_canvas());
358   EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT),
359             bitmap()->getColor(0, 0));
360 }
361
362 TEST_F(PaintCanvasVideoRendererTest, Natural) {
363   Paint(natural_frame(), target_canvas(), kRed);
364   EXPECT_EQ(SK_ColorRED, bitmap()->getColor(0, 0));
365 }
366
367 TEST_F(PaintCanvasVideoRendererTest, Larger) {
368   Paint(natural_frame(), target_canvas(), kRed);
369   EXPECT_EQ(SK_ColorRED, bitmap()->getColor(0, 0));
370
371   Paint(larger_frame(), target_canvas(), kBlue);
372   EXPECT_EQ(SK_ColorBLUE, bitmap()->getColor(0, 0));
373 }
374
375 TEST_F(PaintCanvasVideoRendererTest, Smaller) {
376   Paint(natural_frame(), target_canvas(), kRed);
377   EXPECT_EQ(SK_ColorRED, bitmap()->getColor(0, 0));
378
379   Paint(smaller_frame(), target_canvas(), kBlue);
380   EXPECT_EQ(SK_ColorBLUE, bitmap()->getColor(0, 0));
381 }
382
383 TEST_F(PaintCanvasVideoRendererTest, NoTimestamp) {
384   VideoFrame* video_frame = natural_frame().get();
385   video_frame->set_timestamp(media::kNoTimestamp);
386   Paint(video_frame, target_canvas(), kRed);
387   EXPECT_EQ(SK_ColorRED, bitmap()->getColor(0, 0));
388 }
389
390 TEST_F(PaintCanvasVideoRendererTest, CroppedFrame) {
391   Paint(cropped_frame(), target_canvas(), kNone);
392   // Check the corners.
393   EXPECT_EQ(SK_ColorBLACK, bitmap()->getColor(0, 0));
394   EXPECT_EQ(SK_ColorRED, bitmap()->getColor(kWidth - 1, 0));
395   EXPECT_EQ(SK_ColorGREEN, bitmap()->getColor(0, kHeight - 1));
396   EXPECT_EQ(SK_ColorBLUE, bitmap()->getColor(kWidth - 1, kHeight - 1));
397   // Check the interior along the border between color regions.  Note that we're
398   // bilinearly upscaling, so we'll need to take care to pick sample points that
399   // are just outside the "zone of resampling".
400   EXPECT_EQ(SK_ColorBLACK,
401             bitmap()->getColor(kWidth * 1 / 8 - 1, kHeight * 1 / 6 - 1));
402   EXPECT_EQ(SK_ColorRED,
403             bitmap()->getColor(kWidth * 3 / 8, kHeight * 1 / 6 - 1));
404   EXPECT_EQ(SK_ColorGREEN,
405             bitmap()->getColor(kWidth * 1 / 8 - 1, kHeight * 3 / 6));
406   EXPECT_EQ(SK_ColorBLUE, bitmap()->getColor(kWidth * 3 / 8, kHeight * 3 / 6));
407 }
408
409 uint32_t MaybeConvertABGRToARGB(uint32_t abgr) {
410 #if SK_B32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_R32_SHIFT == 16 && \
411     SK_A32_SHIFT == 24
412   return abgr;
413 #else
414   return (base::ByteSwap(abgr & 0x00FFFFFF) >> 8) | (abgr & 0xFF000000);
415 #endif
416 }
417
418 TEST_F(PaintCanvasVideoRendererTest, CroppedFrameToRGBParallel) {
419   // We need a test frame large enough to trigger parallel conversion. So we use
420   // cropped_frame() as a base and scale it up. Note: Visible rect and natural
421   // size must be even.
422   auto test_frame = VideoFrame::CreateFrame(
423       PIXEL_FORMAT_I420, gfx::Size(3840, 2160), gfx::Rect(1440, 810, 1920, 810),
424       gfx::Size(1920, 810), base::TimeDelta());
425
426   // Fill in the frame with the same data as the cropped frame.
427   libyuv::I420Scale(cropped_frame()->data(0), cropped_frame()->stride(0),
428                     cropped_frame()->data(1), cropped_frame()->stride(1),
429                     cropped_frame()->data(2), cropped_frame()->stride(2),
430                     cropped_frame()->coded_size().width(),
431                     cropped_frame()->coded_size().height(),
432                     test_frame->writable_data(0), test_frame->stride(0),
433                     test_frame->writable_data(1), test_frame->stride(1),
434                     test_frame->writable_data(2), test_frame->stride(2),
435                     test_frame->coded_size().width(),
436                     test_frame->coded_size().height(), libyuv::kFilterNone);
437
438   const gfx::Size visible_size = test_frame->visible_rect().size();
439   const size_t row_bytes = visible_size.width() * sizeof(SkColor);
440   const size_t allocation_size = row_bytes * visible_size.height();
441
442   std::unique_ptr<uint8_t, base::AlignedFreeDeleter> memory(
443       static_cast<uint8_t*>(base::AlignedAlloc(
444           allocation_size, media::VideoFrame::kFrameAddressAlignment)));
445   memset(memory.get(), 0, allocation_size);
446
447   PaintCanvasVideoRenderer::ConvertVideoFrameToRGBPixels(
448       test_frame.get(), memory.get(), row_bytes);
449
450   const uint32_t* rgb_pixels = reinterpret_cast<uint32_t*>(memory.get());
451
452   // Check the corners; this is sufficient to reveal https://crbug.com/1027442.
453   EXPECT_EQ(SK_ColorBLACK, rgb_pixels[0]);
454   EXPECT_EQ(MaybeConvertABGRToARGB(SK_ColorRED),
455             rgb_pixels[visible_size.width() - 1]);
456   EXPECT_EQ(SK_ColorGREEN,
457             rgb_pixels[visible_size.width() * (visible_size.height() - 1)]);
458   EXPECT_EQ(MaybeConvertABGRToARGB(SK_ColorBLUE),
459             rgb_pixels[(visible_size.width() - 1) * visible_size.height()]);
460 }
461
462 TEST_F(PaintCanvasVideoRendererTest, CroppedFrame_NoScaling) {
463   SkBitmap bitmap = AllocBitmap(kWidth, kHeight);
464   cc::SkiaPaintCanvas canvas(bitmap);
465   const gfx::Rect crop_rect = cropped_frame()->visible_rect();
466
467   // Force painting to a non-zero position on the destination bitmap, to check
468   // if the coordinates are calculated properly.
469   const int offset_x = 10;
470   const int offset_y = 15;
471   canvas.translate(offset_x, offset_y);
472
473   // Create a destination canvas with dimensions and scale which would not
474   // cause scaling.
475   canvas.scale(static_cast<SkScalar>(crop_rect.width()) / kWidth,
476                static_cast<SkScalar>(crop_rect.height()) / kHeight);
477
478   Paint(cropped_frame(), &canvas, kNone);
479
480   // Check the corners.
481   EXPECT_EQ(SK_ColorBLACK, bitmap.getColor(offset_x, offset_y));
482   EXPECT_EQ(SK_ColorRED,
483             bitmap.getColor(offset_x + crop_rect.width() - 1, offset_y));
484   EXPECT_EQ(SK_ColorGREEN,
485             bitmap.getColor(offset_x, offset_y + crop_rect.height() - 1));
486   EXPECT_EQ(SK_ColorBLUE, bitmap.getColor(offset_x + crop_rect.width() - 1,
487                                           offset_y + crop_rect.height() - 1));
488 }
489
490 TEST_F(PaintCanvasVideoRendererTest, Video_Rotation_90) {
491   SkBitmap bitmap = AllocBitmap(kWidth, kHeight);
492   cc::SkiaPaintCanvas canvas(bitmap);
493   PaintRotated(cropped_frame(), &canvas, kNaturalRect, kNone,
494                SkBlendMode::kSrcOver, VideoTransformation(VIDEO_ROTATION_90));
495   // Check the corners.
496   EXPECT_EQ(SK_ColorGREEN, bitmap.getColor(0, 0));
497   EXPECT_EQ(SK_ColorBLACK, bitmap.getColor(kWidth - 1, 0));
498   EXPECT_EQ(SK_ColorRED, bitmap.getColor(kWidth - 1, kHeight - 1));
499   EXPECT_EQ(SK_ColorBLUE, bitmap.getColor(0, kHeight - 1));
500 }
501
502 TEST_F(PaintCanvasVideoRendererTest, Video_Rotation_180) {
503   SkBitmap bitmap = AllocBitmap(kWidth, kHeight);
504   cc::SkiaPaintCanvas canvas(bitmap);
505   PaintRotated(cropped_frame(), &canvas, kNaturalRect, kNone,
506                SkBlendMode::kSrcOver, VideoTransformation(VIDEO_ROTATION_180));
507   // Check the corners.
508   EXPECT_EQ(SK_ColorBLUE, bitmap.getColor(0, 0));
509   EXPECT_EQ(SK_ColorGREEN, bitmap.getColor(kWidth - 1, 0));
510   EXPECT_EQ(SK_ColorBLACK, bitmap.getColor(kWidth - 1, kHeight - 1));
511   EXPECT_EQ(SK_ColorRED, bitmap.getColor(0, kHeight - 1));
512 }
513
514 TEST_F(PaintCanvasVideoRendererTest, Video_Rotation_270) {
515   SkBitmap bitmap = AllocBitmap(kWidth, kHeight);
516   cc::SkiaPaintCanvas canvas(bitmap);
517   PaintRotated(cropped_frame(), &canvas, kNaturalRect, kNone,
518                SkBlendMode::kSrcOver, VideoTransformation(VIDEO_ROTATION_270));
519   // Check the corners.
520   EXPECT_EQ(SK_ColorRED, bitmap.getColor(0, 0));
521   EXPECT_EQ(SK_ColorBLUE, bitmap.getColor(kWidth - 1, 0));
522   EXPECT_EQ(SK_ColorGREEN, bitmap.getColor(kWidth - 1, kHeight - 1));
523   EXPECT_EQ(SK_ColorBLACK, bitmap.getColor(0, kHeight - 1));
524 }
525
526 TEST_F(PaintCanvasVideoRendererTest, Video_Translate) {
527   SkBitmap bitmap = AllocBitmap(kWidth, kHeight);
528   cc::SkiaPaintCanvas canvas(bitmap);
529   canvas.clear(SkColors::kMagenta);
530
531   PaintRotated(cropped_frame(), &canvas,
532                gfx::RectF(kWidth / 2, kHeight / 2, kWidth / 2, kHeight / 2),
533                kNone, SkBlendMode::kSrcOver, kNoTransformation);
534   // Check the corners of quadrant 2 and 4.
535   EXPECT_EQ(SK_ColorMAGENTA, bitmap.getColor(0, 0));
536   EXPECT_EQ(SK_ColorMAGENTA, bitmap.getColor((kWidth / 2) - 1, 0));
537   EXPECT_EQ(SK_ColorMAGENTA,
538             bitmap.getColor((kWidth / 2) - 1, (kHeight / 2) - 1));
539   EXPECT_EQ(SK_ColorMAGENTA, bitmap.getColor(0, (kHeight / 2) - 1));
540   EXPECT_EQ(SK_ColorBLACK, bitmap.getColor(kWidth / 2, kHeight / 2));
541   EXPECT_EQ(SK_ColorRED, bitmap.getColor(kWidth - 1, kHeight / 2));
542   EXPECT_EQ(SK_ColorBLUE, bitmap.getColor(kWidth - 1, kHeight - 1));
543   EXPECT_EQ(SK_ColorGREEN, bitmap.getColor(kWidth / 2, kHeight - 1));
544 }
545
546 TEST_F(PaintCanvasVideoRendererTest, Video_Translate_Rotation_90) {
547   SkBitmap bitmap = AllocBitmap(kWidth, kHeight);
548   cc::SkiaPaintCanvas canvas(bitmap);
549   canvas.clear(SkColors::kMagenta);
550
551   PaintRotated(cropped_frame(), &canvas,
552                gfx::RectF(kWidth / 2, kHeight / 2, kWidth / 2, kHeight / 2),
553                kNone, SkBlendMode::kSrcOver,
554                VideoTransformation(VIDEO_ROTATION_90));
555   // Check the corners of quadrant 2 and 4.
556   EXPECT_EQ(SK_ColorMAGENTA, bitmap.getColor(0, 0));
557   EXPECT_EQ(SK_ColorMAGENTA, bitmap.getColor((kWidth / 2) - 1, 0));
558   EXPECT_EQ(SK_ColorMAGENTA,
559             bitmap.getColor((kWidth / 2) - 1, (kHeight / 2) - 1));
560   EXPECT_EQ(SK_ColorMAGENTA, bitmap.getColor(0, (kHeight / 2) - 1));
561   EXPECT_EQ(SK_ColorGREEN, bitmap.getColor(kWidth / 2, kHeight / 2));
562   EXPECT_EQ(SK_ColorBLACK, bitmap.getColor(kWidth - 1, kHeight / 2));
563   EXPECT_EQ(SK_ColorRED, bitmap.getColor(kWidth - 1, kHeight - 1));
564   EXPECT_EQ(SK_ColorBLUE, bitmap.getColor(kWidth / 2, kHeight - 1));
565 }
566
567 TEST_F(PaintCanvasVideoRendererTest, Video_Translate_Rotation_180) {
568   SkBitmap bitmap = AllocBitmap(kWidth, kHeight);
569   cc::SkiaPaintCanvas canvas(bitmap);
570   canvas.clear(SkColors::kMagenta);
571
572   PaintRotated(cropped_frame(), &canvas,
573                gfx::RectF(kWidth / 2, kHeight / 2, kWidth / 2, kHeight / 2),
574                kNone, SkBlendMode::kSrcOver,
575                VideoTransformation(VIDEO_ROTATION_180));
576   // Check the corners of quadrant 2 and 4.
577   EXPECT_EQ(SK_ColorMAGENTA, bitmap.getColor(0, 0));
578   EXPECT_EQ(SK_ColorMAGENTA, bitmap.getColor((kWidth / 2) - 1, 0));
579   EXPECT_EQ(SK_ColorMAGENTA,
580             bitmap.getColor((kWidth / 2) - 1, (kHeight / 2) - 1));
581   EXPECT_EQ(SK_ColorMAGENTA, bitmap.getColor(0, (kHeight / 2) - 1));
582   EXPECT_EQ(SK_ColorBLUE, bitmap.getColor(kWidth / 2, kHeight / 2));
583   EXPECT_EQ(SK_ColorGREEN, bitmap.getColor(kWidth - 1, kHeight / 2));
584   EXPECT_EQ(SK_ColorBLACK, bitmap.getColor(kWidth - 1, kHeight - 1));
585   EXPECT_EQ(SK_ColorRED, bitmap.getColor(kWidth / 2, kHeight - 1));
586 }
587
588 TEST_F(PaintCanvasVideoRendererTest, Video_Translate_Rotation_270) {
589   SkBitmap bitmap = AllocBitmap(kWidth, kHeight);
590   cc::SkiaPaintCanvas canvas(bitmap);
591   canvas.clear(SkColors::kMagenta);
592
593   PaintRotated(cropped_frame(), &canvas,
594                gfx::RectF(kWidth / 2, kHeight / 2, kWidth / 2, kHeight / 2),
595                kNone, SkBlendMode::kSrcOver,
596                VideoTransformation(VIDEO_ROTATION_270));
597   // Check the corners of quadrant 2 and 4.
598   EXPECT_EQ(SK_ColorMAGENTA, bitmap.getColor(0, 0));
599   EXPECT_EQ(SK_ColorMAGENTA, bitmap.getColor((kWidth / 2) - 1, 0));
600   EXPECT_EQ(SK_ColorMAGENTA,
601             bitmap.getColor((kWidth / 2) - 1, (kHeight / 2) - 1));
602   EXPECT_EQ(SK_ColorMAGENTA, bitmap.getColor(0, (kHeight / 2) - 1));
603   EXPECT_EQ(SK_ColorRED, bitmap.getColor(kWidth / 2, kHeight / 2));
604   EXPECT_EQ(SK_ColorBLUE, bitmap.getColor(kWidth - 1, kHeight / 2));
605   EXPECT_EQ(SK_ColorGREEN, bitmap.getColor(kWidth - 1, kHeight - 1));
606   EXPECT_EQ(SK_ColorBLACK, bitmap.getColor(kWidth / 2, kHeight - 1));
607 }
608
609 TEST_F(PaintCanvasVideoRendererTest, HighBitDepth) {
610   struct params {
611     int bit_depth;
612     VideoPixelFormat format;
613   } kBitDepthAndFormats[] = {{9, PIXEL_FORMAT_YUV420P9},
614                              {10, PIXEL_FORMAT_YUV420P10},
615                              {12, PIXEL_FORMAT_YUV420P12}};
616   for (const auto param : kBitDepthAndFormats) {
617     // Copy cropped_frame into a highbit frame.
618     scoped_refptr<VideoFrame> frame(VideoFrame::CreateFrame(
619         param.format, cropped_frame()->coded_size(),
620         cropped_frame()->visible_rect(), cropped_frame()->natural_size(),
621         cropped_frame()->timestamp()));
622     for (int plane = VideoFrame::kYPlane; plane <= VideoFrame::kVPlane;
623          ++plane) {
624       int width = cropped_frame()->row_bytes(plane);
625       uint16_t* dst = reinterpret_cast<uint16_t*>(frame->writable_data(plane));
626       const uint8_t* src = cropped_frame()->data(plane);
627       for (int row = 0; row < cropped_frame()->rows(plane); row++) {
628         for (int col = 0; col < width; col++) {
629           dst[col] = src[col] << (param.bit_depth - 8);
630         }
631         src += cropped_frame()->stride(plane);
632         dst += frame->stride(plane) / 2;
633       }
634     }
635
636     Paint(frame, target_canvas(), kNone);
637     // Check the corners.
638     EXPECT_EQ(SK_ColorBLACK, bitmap()->getColor(0, 0));
639     EXPECT_EQ(SK_ColorRED, bitmap()->getColor(kWidth - 1, 0));
640     EXPECT_EQ(SK_ColorGREEN, bitmap()->getColor(0, kHeight - 1));
641     EXPECT_EQ(SK_ColorBLUE, bitmap()->getColor(kWidth - 1, kHeight - 1));
642     // Check the interior along the border between color regions.  Note that
643     // we're bilinearly upscaling, so we'll need to take care to pick sample
644     // points that are just outside the "zone of resampling".
645     EXPECT_EQ(SK_ColorBLACK,
646               bitmap()->getColor(kWidth * 1 / 8 - 1, kHeight * 1 / 6 - 1));
647     EXPECT_EQ(SK_ColorRED,
648               bitmap()->getColor(kWidth * 3 / 8, kHeight * 1 / 6 - 1));
649     EXPECT_EQ(SK_ColorGREEN,
650               bitmap()->getColor(kWidth * 1 / 8 - 1, kHeight * 3 / 6));
651     EXPECT_EQ(SK_ColorBLUE,
652               bitmap()->getColor(kWidth * 3 / 8, kHeight * 3 / 6));
653   }
654 }
655
656 TEST_F(PaintCanvasVideoRendererTest, Y16) {
657   SkBitmap bitmap;
658   bitmap.allocPixels(SkImageInfo::MakeN32(16, 16, kPremul_SkAlphaType));
659
660   // |offset_x| and |offset_y| define visible rect's offset to coded rect.
661   const int offset_x = 3;
662   const int offset_y = 5;
663   const int stride = bitmap.width() + offset_x;
664   const size_t byte_size = stride * (bitmap.height() + offset_y) * 2;
665   std::unique_ptr<unsigned char, base::AlignedFreeDeleter> memory(
666       static_cast<unsigned char*>(base::AlignedAlloc(
667           byte_size, media::VideoFrame::kFrameAddressAlignment)));
668   const gfx::Rect rect(offset_x, offset_y, bitmap.width(), bitmap.height());
669   auto video_frame =
670       CreateTestY16Frame(gfx::Size(stride, offset_y + bitmap.height()), rect,
671                          memory.get(), cropped_frame()->timestamp());
672
673   cc::SkiaPaintCanvas canvas(bitmap);
674   cc::PaintFlags flags;
675   flags.setFilterQuality(cc::PaintFlags::FilterQuality::kNone);
676   renderer_.Paint(std::move(video_frame), &canvas,
677                   gfx::RectF(bitmap.width(), bitmap.height()), flags,
678                   kNoTransformation, nullptr);
679   for (int j = 0; j < bitmap.height(); j++) {
680     for (int i = 0; i < bitmap.width(); i++) {
681       const int value = i + j * bitmap.width();
682       EXPECT_EQ(SkColorSetRGB(value, value, value), bitmap.getColor(i, j));
683     }
684   }
685 }
686
687 // A reproducer test case for crbug.com/1230409 if run with ASAN enabled.
688 TEST_F(PaintCanvasVideoRendererTest, Yuv420P12OddWidth) {
689   // Allocate the Y, U, V planes for a 3x3 12-bit YUV 4:2:0 image. Note that
690   // there are no padding bytes after each row.
691   constexpr int kImgWidth = 3;
692   constexpr int kImgHeight = 3;
693   constexpr int kUvWidth = (kImgWidth + 1) / 2;
694   constexpr int kUvHeight = (kImgHeight + 1) / 2;
695   std::unique_ptr<uint16_t[]> y_plane =
696       std::make_unique<uint16_t[]>(kImgWidth * kImgHeight);
697   std::unique_ptr<uint16_t[]> u_plane =
698       std::make_unique<uint16_t[]>(kUvWidth * kUvHeight);
699   std::unique_ptr<uint16_t[]> v_plane =
700       std::make_unique<uint16_t[]>(kUvWidth * kUvHeight);
701   // Set all pixels to white.
702   for (int i = 0; i < kImgHeight; ++i) {
703     for (int j = 0; j < kImgWidth; ++j) {
704       y_plane[i * kImgWidth + j] = 4095;
705     }
706   }
707   for (int i = 0; i < kUvHeight; ++i) {
708     for (int j = 0; j < kUvWidth; ++j) {
709       u_plane[i * kUvWidth + j] = 2048;
710       v_plane[i * kUvWidth + j] = 2048;
711     }
712   }
713   const int32_t y_stride = sizeof(uint16_t) * kImgWidth;
714   const int32_t uv_stride = sizeof(uint16_t) * kUvWidth;
715   uint8_t* const y_data = reinterpret_cast<uint8_t*>(y_plane.get());
716   uint8_t* const u_data = reinterpret_cast<uint8_t*>(u_plane.get());
717   uint8_t* const v_data = reinterpret_cast<uint8_t*>(v_plane.get());
718
719   auto size = gfx::Size(kImgWidth, kImgHeight);
720   scoped_refptr<VideoFrame> frame = VideoFrame::WrapExternalYuvData(
721       PIXEL_FORMAT_YUV420P12, size, gfx::Rect(size), size, y_stride, uv_stride,
722       uv_stride, y_data, u_data, v_data, base::TimeDelta());
723
724   std::unique_ptr<uint32_t[]> rgba =
725       std::make_unique<uint32_t[]>(kImgWidth * kImgHeight);
726   PaintCanvasVideoRenderer::ConvertVideoFrameToRGBPixels(
727       frame.get(), rgba.get(), frame->visible_rect().width() * 4,
728       /*premultiply_alpha=*/true);
729   for (int i = 0; i < kImgHeight; ++i) {
730     for (int j = 0; j < kImgWidth; ++j) {
731       EXPECT_EQ(rgba[i * kImgWidth + j], 0xffffffff);
732     }
733   }
734 }
735
736 TEST_F(PaintCanvasVideoRendererTest, I420WithFilters) {
737   // Allocate the Y, U, V planes for a 4x4 8-bit YUV 4:2:0 image. Note that
738   // there are no padding bytes after each row.
739   constexpr int kImgWidth = 4;
740   constexpr int kImgHeight = 4;
741   constexpr int kUvWidth = (kImgWidth + 1) / 2;
742   constexpr int kUvHeight = (kImgHeight + 1) / 2;
743   std::unique_ptr<uint8_t[]> y_plane =
744       std::make_unique<uint8_t[]>(kImgWidth * kImgHeight);
745   std::unique_ptr<uint8_t[]> u_plane =
746       std::make_unique<uint8_t[]>(kUvWidth * kUvHeight);
747   std::unique_ptr<uint8_t[]> v_plane =
748       std::make_unique<uint8_t[]>(kUvWidth * kUvHeight);
749   // In the JPEG color space (K_R = 0.299, K_B = 0.114, full range), red
750   // (R = 255, G = 0, B = 0) is Y = 76, U = 85, V = 255.
751   //
752   // Set Y to 76 for all pixels.
753   memset(y_plane.get(), 76, kImgWidth * kImgHeight);
754   // Set U = 85 and V = 255 for the upperleft pixel. Then vary U and V with a
755   // linear, diagonal slope over the UV planes with a step size of 4 and -4,
756   // respectively.
757   //
758   // The full U plane is
759   //  85  89  93  97
760   //  89  93  97 101
761   //  93  97 101 105
762   //  97 101 105 109
763   // The subsampled U plane is
764   //    89      97
765   //    97     105
766   //
767   // The full V plane is
768   // 255 251 247 243
769   // 251 247 243 239
770   // 247 243 239 235
771   // 243 239 235 231
772   // The subsampled V plane is
773   //   251     243
774   //   243     235
775   for (int i = 0; i < kUvHeight; ++i) {
776     for (int j = 0; j < kUvWidth; ++j) {
777       u_plane[i * kUvWidth + j] = 89 + 8 * i + 8 * j;
778       v_plane[i * kUvWidth + j] = 251 - 8 * i - 8 * j;
779     }
780   }
781
782   auto size = gfx::Size(kImgWidth, kImgHeight);
783   scoped_refptr<VideoFrame> frame = VideoFrame::WrapExternalYuvData(
784       PIXEL_FORMAT_I420, size, gfx::Rect(size), size, kImgWidth, kUvWidth,
785       kUvWidth, y_plane.get(), u_plane.get(), v_plane.get(), base::TimeDelta());
786   frame->set_color_space(gfx::ColorSpace::CreateJpeg());
787
788   std::unique_ptr<uint32_t[]> rgba =
789       std::make_unique<uint32_t[]>(kImgWidth * kImgHeight);
790
791   // First convert with kFilterNone (nearest neighbor).
792   PaintCanvasVideoRenderer::ConvertVideoFrameToRGBPixels(
793       frame.get(), rgba.get(), frame->visible_rect().width() * 4,
794       /*premultiply_alpha=*/true);
795
796   // The pixel at coordinates (1, 1) will have U = 89 and V = 251 if nearest
797   // neighbor is used. (The correct values are U = 93 and V = 247.)
798   int i = 1;
799   int j = 1;
800   uint32_t color = rgba[i * kImgWidth + j];
801   EXPECT_EQ(SkGetPackedA32(color), 255u);
802   EXPECT_EQ(SkGetPackedR32(color), 249u);
803   EXPECT_EQ(SkGetPackedG32(color), 1u);
804   EXPECT_EQ(SkGetPackedB32(color), 7u);
805   // The pixel at coordinates (2, 2) will have U = 105 and V = 235 if nearest
806   // neighbor is used. (The correct values are U = 101 and V = 239.)
807   i = 2;
808   j = 2;
809   color = rgba[i * kImgWidth + j];
810   EXPECT_EQ(SkGetPackedA32(color), 255u);
811   EXPECT_EQ(SkGetPackedR32(color), 226u);
812   EXPECT_EQ(SkGetPackedG32(color), 7u);
813   EXPECT_EQ(SkGetPackedB32(color), 35u);
814
815   // Then convert with kFilterBilinear (bilinear interpolation).
816   PaintCanvasVideoRenderer::ConvertVideoFrameToRGBPixels(
817       frame.get(), rgba.get(), frame->visible_rect().width() * 4,
818       /*premultiply_alpha=*/true, PaintCanvasVideoRenderer::kFilterBilinear);
819
820   // The pixel at coordinates (1, 1) will have the correct values U = 93 and
821   // V = 247 if bilinear interpolation is used.
822   i = 1;
823   j = 1;
824   color = rgba[i * kImgWidth + j];
825   EXPECT_EQ(SkGetPackedA32(color), 255u);
826   EXPECT_EQ(SkGetPackedR32(color), 243u);
827   EXPECT_EQ(SkGetPackedG32(color), 2u);
828   EXPECT_EQ(SkGetPackedB32(color), 14u);
829   // The pixel at coordinates (2, 2) will have the correct values U = 101 and
830   // V = 239 if bilinear interpolation is used.
831   i = 2;
832   j = 2;
833   color = rgba[i * kImgWidth + j];
834   EXPECT_EQ(SkGetPackedA32(color), 255u);
835   EXPECT_EQ(SkGetPackedR32(color), 232u);
836   EXPECT_EQ(SkGetPackedG32(color), 5u);
837   EXPECT_EQ(SkGetPackedB32(color), 28u);
838 }
839
840 namespace {
841 class TestGLES2Interface : public gpu::gles2::GLES2InterfaceStub {
842  public:
843   void GenTextures(GLsizei n, GLuint* textures) override {
844     DCHECK_EQ(1, n);
845     *textures = 1;
846   }
847
848   void TexImage2D(GLenum target,
849                   GLint level,
850                   GLint internalformat,
851                   GLsizei width,
852                   GLsizei height,
853                   GLint border,
854                   GLenum format,
855                   GLenum type,
856                   const void* pixels) override {
857     if (!teximage2d_callback_.is_null()) {
858       teximage2d_callback_.Run(target, level, internalformat, width, height,
859                                border, format, type, pixels);
860     }
861   }
862
863   void TexSubImage2D(GLenum target,
864                      GLint level,
865                      GLint xoffset,
866                      GLint yoffset,
867                      GLsizei width,
868                      GLsizei height,
869                      GLenum format,
870                      GLenum type,
871                      const void* pixels) override {
872     if (!texsubimage2d_callback_.is_null()) {
873       texsubimage2d_callback_.Run(target, level, xoffset, yoffset, width,
874                                   height, format, type, pixels);
875     }
876   }
877
878   base::RepeatingCallback<void(GLenum target,
879                                GLint level,
880                                GLint internalformat,
881                                GLsizei width,
882                                GLsizei height,
883                                GLint border,
884                                GLenum format,
885                                GLenum type,
886                                const void* pixels)>
887       teximage2d_callback_;
888
889   base::RepeatingCallback<void(GLenum target,
890                                GLint level,
891                                GLint xoffset,
892                                GLint yoffset,
893                                GLsizei width,
894                                GLsizei height,
895                                GLenum format,
896                                GLenum type,
897                                const void* pixels)>
898       texsubimage2d_callback_;
899 };
900
901 void MailboxHoldersReleased(const gpu::SyncToken& sync_token) {}
902 }  // namespace
903
904 // Test that PaintCanvasVideoRenderer::Paint doesn't crash when GrContext is
905 // unable to wrap a video frame texture (eg due to being abandoned).
906 TEST_F(PaintCanvasVideoRendererTest, ContextLost) {
907   auto context_provider = viz::TestContextProvider::Create();
908   context_provider->BindToCurrentSequence();
909   context_provider->GrContext()->abandonContext();
910
911   cc::SkiaPaintCanvas canvas(AllocBitmap(kWidth, kHeight));
912
913   gfx::Size size(kWidth, kHeight);
914   gpu::MailboxHolder holders[VideoFrame::kMaxPlanes] = {
915       gpu::MailboxHolder(gpu::Mailbox::GenerateForSharedImage(),
916                          gpu::SyncToken(), GL_TEXTURE_RECTANGLE_ARB)};
917   auto video_frame = VideoFrame::WrapNativeTextures(
918       PIXEL_FORMAT_NV12, holders, base::BindOnce(MailboxHoldersReleased), size,
919       gfx::Rect(size), size, kNoTimestamp);
920
921   cc::PaintFlags flags;
922   flags.setFilterQuality(cc::PaintFlags::FilterQuality::kLow);
923   renderer_.Paint(std::move(video_frame), &canvas, kNaturalRect, flags,
924                   kNoTransformation, context_provider.get());
925 }
926
927 void EmptyCallback(const gpu::SyncToken& sync_token) {}
928
929 TEST_F(PaintCanvasVideoRendererTest, CorrectFrameSizeToVisibleRect) {
930   constexpr int fWidth{16}, fHeight{16};
931   SkImageInfo imInfo =
932       SkImageInfo::MakeN32(fWidth, fHeight, kOpaque_SkAlphaType);
933
934   cc::SkiaPaintCanvas canvas(AllocBitmap(kWidth, kHeight));
935
936   gfx::Size coded_size(fWidth, fHeight);
937   gfx::Size visible_size(fWidth / 2, fHeight / 2);
938
939   uint8_t memory[fWidth * fHeight * 2] = {0};
940
941   auto video_frame = media::VideoFrame::WrapExternalData(
942       media::PIXEL_FORMAT_Y16, coded_size, gfx::Rect(visible_size),
943       visible_size, &memory[0], fWidth * fHeight * 2, base::Milliseconds(4));
944
945   gfx::RectF visible_rect(visible_size.width(), visible_size.height());
946   cc::PaintFlags flags;
947   renderer_.Paint(std::move(video_frame), &canvas, visible_rect, flags,
948                   kNoTransformation, nullptr);
949
950   EXPECT_EQ(fWidth / 2, renderer_.LastImageDimensionsForTesting().width());
951   EXPECT_EQ(fWidth / 2, renderer_.LastImageDimensionsForTesting().height());
952 }
953
954 TEST_F(PaintCanvasVideoRendererTest, TexImage2D_Y16_RGBA32F) {
955   // Create test frame.
956   // |offset_x| and |offset_y| define visible rect's offset to coded rect.
957   const int offset_x = 3;
958   const int offset_y = 5;
959   const int width = 16;
960   const int height = 16;
961   const int stride = width + offset_x;
962   const size_t byte_size = stride * (height + offset_y) * 2;
963   std::unique_ptr<unsigned char, base::AlignedFreeDeleter> memory(
964       static_cast<unsigned char*>(base::AlignedAlloc(
965           byte_size, media::VideoFrame::kFrameAddressAlignment)));
966   const gfx::Rect rect(offset_x, offset_y, width, height);
967   auto video_frame =
968       CreateTestY16Frame(gfx::Size(stride, offset_y + height), rect,
969                          memory.get(), cropped_frame()->timestamp());
970
971   TestGLES2Interface gles2;
972   // Bind the texImage2D callback to verify the uint16 to float32 conversion.
973   gles2.teximage2d_callback_ =
974       base::BindRepeating([](GLenum target, GLint level, GLint internalformat,
975                              GLsizei width, GLsizei height, GLint border,
976                              GLenum format, GLenum type, const void* pixels) {
977         EXPECT_EQ(static_cast<unsigned>(GL_FLOAT), type);
978         EXPECT_EQ(static_cast<unsigned>(GL_RGBA), format);
979         EXPECT_EQ(GL_RGBA, internalformat);
980         EXPECT_EQ(0, border);
981         EXPECT_EQ(16, width);
982         EXPECT_EQ(16, height);
983         EXPECT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
984         const float* data = static_cast<const float*>(pixels);
985         for (int j = 0; j < height; j++) {
986           for (int i = 0; i < width; i++) {
987             const int value = i + (height - j - 1) * width;  // flip_y is true.
988             float expected_value =
989                 (((value & 0xFF) << 8) | (~value & 0xFF)) / 65535.f;
990             EXPECT_EQ(expected_value, data[(i + j * width) * 4]);
991             EXPECT_EQ(expected_value, data[(i + j * width) * 4 + 1]);
992             EXPECT_EQ(expected_value, data[(i + j * width) * 4 + 2]);
993             EXPECT_EQ(1.0f, data[(i + j * width) * 4 + 3]);
994           }
995         }
996       });
997   PaintCanvasVideoRenderer::TexImage2D(
998       GL_TEXTURE_2D, 0, &gles2, gpu::Capabilities(), video_frame.get(), 0,
999       GL_RGBA, GL_RGBA, GL_FLOAT, true /*flip_y*/, true);
1000 }
1001
1002 TEST_F(PaintCanvasVideoRendererTest, TexSubImage2D_Y16_R32F) {
1003   // Create test frame.
1004   // |offset_x| and |offset_y| define visible rect's offset to coded rect.
1005   const int offset_x = 3;
1006   const int offset_y = 5;
1007   const int width = 16;
1008   const int height = 16;
1009   const int stride = width + offset_x;
1010   const size_t byte_size = stride * (height + offset_y) * 2;
1011   std::unique_ptr<unsigned char, base::AlignedFreeDeleter> memory(
1012       static_cast<unsigned char*>(base::AlignedAlloc(
1013           byte_size, media::VideoFrame::kFrameAddressAlignment)));
1014   const gfx::Rect rect(offset_x, offset_y, width, height);
1015   auto video_frame =
1016       CreateTestY16Frame(gfx::Size(stride, offset_y + height), rect,
1017                          memory.get(), cropped_frame()->timestamp());
1018
1019   TestGLES2Interface gles2;
1020   // Bind the texImage2D callback to verify the uint16 to float32 conversion.
1021   gles2.texsubimage2d_callback_ =
1022       base::BindRepeating([](GLenum target, GLint level, GLint xoffset,
1023                              GLint yoffset, GLsizei width, GLsizei height,
1024                              GLenum format, GLenum type, const void* pixels) {
1025         EXPECT_EQ(static_cast<unsigned>(GL_FLOAT), type);
1026         EXPECT_EQ(static_cast<unsigned>(GL_RED), format);
1027         EXPECT_EQ(2, xoffset);
1028         EXPECT_EQ(1, yoffset);
1029         EXPECT_EQ(16, width);
1030         EXPECT_EQ(16, height);
1031         EXPECT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
1032         const float* data = static_cast<const float*>(pixels);
1033         for (int j = 0; j < height; j++) {
1034           for (int i = 0; i < width; i++) {
1035             const int value = i + j * width;  // flip_y is false.
1036             float expected_value =
1037                 (((value & 0xFF) << 8) | (~value & 0xFF)) / 65535.f;
1038             EXPECT_EQ(expected_value, data[(i + j * width)]);
1039           }
1040         }
1041       });
1042   PaintCanvasVideoRenderer::TexSubImage2D(
1043       GL_TEXTURE_2D, &gles2, video_frame.get(), 0, GL_RED, GL_FLOAT,
1044       2 /*xoffset*/, 1 /*yoffset*/, false /*flip_y*/, true);
1045 }
1046
1047 // Fixture for tests that require a GL context.
1048 class PaintCanvasVideoRendererWithGLTest : public testing::Test {
1049  public:
1050   using GetColorCallback = base::RepeatingCallback<SkColor(int, int)>;
1051
1052   void SetUp() override {
1053     display_ = gl::GLSurfaceTestSupport::InitializeOneOff();
1054     enable_pixels_.emplace();
1055     media_context_ = base::MakeRefCounted<viz::TestInProcessContextProvider>(
1056         viz::TestContextType::kGpuRaster, /*support_locking=*/false);
1057     gpu::ContextResult result = media_context_->BindToCurrentSequence();
1058     ASSERT_EQ(result, gpu::ContextResult::kSuccess);
1059
1060     gles2_context_ = base::MakeRefCounted<viz::TestInProcessContextProvider>(
1061         viz::TestContextType::kGLES2, /*support_locking=*/false);
1062     result = gles2_context_->BindToCurrentSequence();
1063     ASSERT_EQ(result, gpu::ContextResult::kSuccess);
1064
1065     destination_context_ =
1066         base::MakeRefCounted<viz::TestInProcessContextProvider>(
1067             viz::TestContextType::kGLES2, /*support_locking=*/false);
1068     result = destination_context_->BindToCurrentSequence();
1069     ASSERT_EQ(result, gpu::ContextResult::kSuccess);
1070     cropped_frame_ = CreateCroppedFrame();
1071   }
1072
1073   void TearDown() override {
1074     renderer_.ResetCache();
1075     destination_context_.reset();
1076     gles2_context_.reset();
1077     media_context_.reset();
1078     enable_pixels_.reset();
1079     viz::TestGpuServiceHolder::ResetInstance();
1080     gl::GLSurfaceTestSupport::ShutdownGL(display_);
1081   }
1082
1083   // Uses CopyVideoFrameTexturesToGLTexture to copy |frame| into a GL texture,
1084   // reads back its contents, and runs |check_pixels| to validate it.
1085   template <class CheckPixels>
1086   void CopyVideoFrameTexturesAndCheckPixels(scoped_refptr<VideoFrame> frame,
1087                                             CheckPixels check_pixels) {
1088     auto* destination_gl = destination_context_->ContextGL();
1089     DCHECK(destination_gl);
1090     GLenum target = GL_TEXTURE_2D;
1091     GLuint texture = 0;
1092     destination_gl->GenTextures(1, &texture);
1093     destination_gl->BindTexture(target, texture);
1094
1095     renderer_.CopyVideoFrameTexturesToGLTexture(
1096         media_context_.get(), destination_gl,
1097         destination_context_->ContextCapabilities(), frame, target, texture,
1098         GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 0, false /* premultiply_alpha */,
1099         false /* flip_y */);
1100
1101     gfx::Size expected_size = frame->visible_rect().size();
1102
1103     std::unique_ptr<uint8_t[]> pixels =
1104         ReadbackTexture(destination_gl, texture, expected_size);
1105     destination_gl->DeleteTextures(1, &texture);
1106
1107     auto get_color = base::BindRepeating(
1108         [](uint8_t* pixels, const gfx::Size& size, int x, int y) {
1109           uint8_t* p = pixels + (size.width() * y + x) * 4;
1110           return SkColorSetARGB(p[3], p[0], p[1], p[2]);
1111         },
1112         pixels.get(), expected_size);
1113     check_pixels(get_color);
1114   }
1115
1116   // Uses Copy to paint |frame| into a bitmap-backed canvas, then
1117   // runs |check_pixels| to validate the contents of the canvas.
1118   template <class CheckPixels>
1119   void PaintVideoFrameAndCheckPixels(scoped_refptr<VideoFrame> frame,
1120                                      CheckPixels check_pixels) {
1121     gfx::Size expected_size = frame->visible_rect().size();
1122     SkBitmap bitmap =
1123         AllocBitmap(expected_size.width(), expected_size.height());
1124     cc::SkiaPaintCanvas canvas(bitmap);
1125     canvas.clear(SkColors::kGray);
1126     renderer_.Copy(frame, &canvas, media_context_.get());
1127
1128     auto get_color = base::BindRepeating(
1129         [](SkBitmap* bitmap, int x, int y) { return bitmap->getColor(x, y); },
1130         &bitmap);
1131     check_pixels(get_color);
1132   }
1133
1134   // Creates a cropped RGBA VideoFrame. |closure| is run once the shared images
1135   // backing the VideoFrame have been destroyed.
1136   scoped_refptr<VideoFrame> CreateTestRGBAFrame(base::OnceClosure closure) {
1137     return CreateSharedImageRGBAFrame(gles2_context_, gfx::Size(16, 8),
1138                                       gfx::Rect(3, 3, 12, 4),
1139                                       std::move(closure));
1140   }
1141
1142   // Checks that the contents of a texture/canvas match the expectations for the
1143   // cropped RGBA frame above. |get_color| is a callback that returns the actual
1144   // color at a given pixel location.
1145   static void CheckRGBAFramePixels(GetColorCallback get_color) {
1146     EXPECT_EQ(SK_ColorBLACK, get_color.Run(0, 0));
1147     EXPECT_EQ(SK_ColorRED, get_color.Run(1, 0));
1148     EXPECT_EQ(SK_ColorRED, get_color.Run(4, 0));
1149     EXPECT_EQ(SK_ColorGREEN, get_color.Run(5, 0));
1150     EXPECT_EQ(SK_ColorYELLOW, get_color.Run(9, 0));
1151     EXPECT_EQ(SK_ColorYELLOW, get_color.Run(11, 0));
1152     EXPECT_EQ(SK_ColorBLUE, get_color.Run(0, 1));
1153     EXPECT_EQ(SK_ColorBLUE, get_color.Run(0, 3));
1154     EXPECT_EQ(SK_ColorMAGENTA, get_color.Run(1, 1));
1155     EXPECT_EQ(SK_ColorMAGENTA, get_color.Run(4, 1));
1156     EXPECT_EQ(SK_ColorMAGENTA, get_color.Run(1, 3));
1157     EXPECT_EQ(SK_ColorMAGENTA, get_color.Run(4, 3));
1158     EXPECT_EQ(SK_ColorCYAN, get_color.Run(5, 1));
1159     EXPECT_EQ(SK_ColorCYAN, get_color.Run(5, 3));
1160     EXPECT_EQ(SK_ColorWHITE, get_color.Run(9, 1));
1161     EXPECT_EQ(SK_ColorWHITE, get_color.Run(11, 1));
1162     EXPECT_EQ(SK_ColorWHITE, get_color.Run(9, 3));
1163     EXPECT_EQ(SK_ColorWHITE, get_color.Run(11, 3));
1164   }
1165
1166   // Creates a cropped I420 VideoFrame. |closure| is run once the shared images
1167   // backing the VideoFrame have been destroyed.
1168   scoped_refptr<VideoFrame> CreateTestI420Frame(base::OnceClosure closure) {
1169     return CreateSharedImageI420Frame(gles2_context_, gfx::Size(16, 8),
1170                                       gfx::Rect(2, 2, 12, 4),
1171                                       std::move(closure));
1172   }
1173   // Creates a cropped I420 VideoFrame. |closure| is run once the shared images
1174   // backing the VideoFrame have been destroyed.
1175   scoped_refptr<VideoFrame> CreateTestI420FrameNotSubset(
1176       base::OnceClosure closure) {
1177     return CreateSharedImageI420Frame(gles2_context_, gfx::Size(16, 8),
1178                                       gfx::Rect(0, 0, 16, 8),
1179                                       std::move(closure));
1180   }
1181
1182   // Checks that the contents of a texture/canvas match the expectations for the
1183   // cropped I420 frame above. |get_color| is a callback that returns the actual
1184   // color at a given pixel location.
1185   static void CheckI420FramePixels(GetColorCallback get_color) {
1186     // Avoid checking around the "seams" where subsamples may be interpolated.
1187     EXPECT_EQ(SK_ColorBLACK, get_color.Run(0, 0));
1188     EXPECT_EQ(SK_ColorRED, get_color.Run(3, 0));
1189     EXPECT_EQ(SK_ColorRED, get_color.Run(4, 0));
1190     EXPECT_EQ(SK_ColorGREEN, get_color.Run(7, 0));
1191     EXPECT_EQ(SK_ColorGREEN, get_color.Run(8, 0));
1192     EXPECT_EQ(SK_ColorYELLOW, get_color.Run(11, 0));
1193     EXPECT_EQ(SK_ColorBLUE, get_color.Run(0, 3));
1194     EXPECT_EQ(SK_ColorMAGENTA, get_color.Run(3, 3));
1195     EXPECT_EQ(SK_ColorCYAN, get_color.Run(7, 3));
1196     EXPECT_EQ(SK_ColorWHITE, get_color.Run(11, 3));
1197   }
1198
1199   // Checks that the contents of a texture/canvas match the expectations for the
1200   // cropped I420 frame above. |get_color| is a callback that returns the actual
1201   // color at a given pixel location.
1202   static void CheckI420FramePixelsNotSubset(GetColorCallback get_color) {
1203     // Avoid checking around the "seams" where subsamples may be interpolated.
1204     EXPECT_EQ(SK_ColorBLACK, get_color.Run(2, 2));
1205     EXPECT_EQ(SK_ColorRED, get_color.Run(5, 2));
1206     EXPECT_EQ(SK_ColorRED, get_color.Run(6, 2));
1207     EXPECT_EQ(SK_ColorGREEN, get_color.Run(9, 2));
1208     EXPECT_EQ(SK_ColorGREEN, get_color.Run(10, 2));
1209     EXPECT_EQ(SK_ColorYELLOW, get_color.Run(13, 2));
1210     EXPECT_EQ(SK_ColorBLUE, get_color.Run(2, 5));
1211     EXPECT_EQ(SK_ColorMAGENTA, get_color.Run(5, 5));
1212     EXPECT_EQ(SK_ColorCYAN, get_color.Run(9, 5));
1213     EXPECT_EQ(SK_ColorWHITE, get_color.Run(13, 5));
1214   }
1215
1216   // Creates a cropped NV12 VideoFrame, or nullptr if the needed extension is
1217   // not available. |closure| is run once the shared images backing the
1218   // VideoFrame have been destroyed.
1219   scoped_refptr<VideoFrame> CreateTestNV12Frame(base::OnceClosure closure) {
1220     return CreateSharedImageNV12Frame(gles2_context_, gfx::Size(16, 8),
1221                                       gfx::Rect(2, 2, 12, 4),
1222                                       std::move(closure));
1223   }
1224
1225   // Checks that the contents of a texture/canvas match the expectations for the
1226   // cropped NV12 frame above. |get_color| is a callback that returns the actual
1227   // color at a given pixel location. Note that the expectations are the same as
1228   // for the I420 frame.
1229   static void CheckNV12FramePixels(GetColorCallback get_color) {
1230     CheckI420FramePixels(std::move(get_color));
1231   }
1232
1233   scoped_refptr<VideoFrame> cropped_frame() { return cropped_frame_; }
1234
1235  protected:
1236   absl::optional<gl::DisableNullDrawGLBindings> enable_pixels_;
1237   scoped_refptr<viz::TestInProcessContextProvider> media_context_;
1238   scoped_refptr<viz::TestInProcessContextProvider> gles2_context_;
1239   scoped_refptr<viz::TestInProcessContextProvider> destination_context_;
1240
1241   PaintCanvasVideoRenderer renderer_;
1242   scoped_refptr<VideoFrame> cropped_frame_;
1243   base::test::TaskEnvironment task_environment_;
1244   raw_ptr<gl::GLDisplay> display_ = nullptr;
1245 };
1246
1247 TEST_F(PaintCanvasVideoRendererWithGLTest, CopyVideoFrameYUVDataToGLTexture) {
1248   auto* destination_gl = destination_context_->ContextGL();
1249   DCHECK(destination_gl);
1250   GLenum target = GL_TEXTURE_2D;
1251   GLuint texture = 0;
1252   destination_gl->GenTextures(1, &texture);
1253   destination_gl->BindTexture(target, texture);
1254
1255   renderer_.CopyVideoFrameYUVDataToGLTexture(
1256       media_context_.get(), destination_gl,
1257       destination_context_->ContextCapabilities(), cropped_frame(), target,
1258       texture, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 0,
1259       false /* premultiply_alpha */, false /* flip_y */);
1260
1261   gfx::Size expected_size = cropped_frame()->visible_rect().size();
1262
1263   std::unique_ptr<uint8_t[]> pixels =
1264       ReadbackTexture(destination_gl, texture, expected_size);
1265   auto get_color = ColorGetter(pixels.get(), expected_size);
1266
1267   // Avoid checking around the seams.
1268   EXPECT_EQ(SK_ColorBLACK, get_color(0, 0));
1269   EXPECT_EQ(SK_ColorRED, get_color(3, 0));
1270   EXPECT_EQ(SK_ColorRED, get_color(7, 0));
1271   EXPECT_EQ(SK_ColorGREEN, get_color(0, 3));
1272   EXPECT_EQ(SK_ColorGREEN, get_color(0, 5));
1273   EXPECT_EQ(SK_ColorBLUE, get_color(3, 3));
1274   EXPECT_EQ(SK_ColorBLUE, get_color(7, 5));
1275
1276   destination_gl->DeleteTextures(1, &texture);
1277 }
1278
1279 TEST_F(PaintCanvasVideoRendererWithGLTest,
1280        CopyVideoFrameYUVDataToGLTexture_FlipY) {
1281   auto* destination_gl = destination_context_->ContextGL();
1282   DCHECK(destination_gl);
1283   GLenum target = GL_TEXTURE_2D;
1284   GLuint texture = 0;
1285   destination_gl->GenTextures(1, &texture);
1286   destination_gl->BindTexture(target, texture);
1287
1288   renderer_.CopyVideoFrameYUVDataToGLTexture(
1289       media_context_.get(), destination_gl,
1290       destination_context_->ContextCapabilities(), cropped_frame(), target,
1291       texture, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 0,
1292       false /* premultiply_alpha */, true /* flip_y */);
1293
1294   gfx::Size expected_size = cropped_frame()->visible_rect().size();
1295
1296   std::unique_ptr<uint8_t[]> pixels =
1297       ReadbackTexture(destination_gl, texture, expected_size);
1298   auto get_color = ColorGetter(pixels.get(), expected_size);
1299
1300   // Avoid checking around the seams.
1301   EXPECT_EQ(SK_ColorBLACK, get_color(0, 5));
1302   EXPECT_EQ(SK_ColorRED, get_color(3, 5));
1303   EXPECT_EQ(SK_ColorRED, get_color(7, 5));
1304   EXPECT_EQ(SK_ColorGREEN, get_color(0, 2));
1305   EXPECT_EQ(SK_ColorGREEN, get_color(0, 0));
1306   EXPECT_EQ(SK_ColorBLUE, get_color(3, 2));
1307   EXPECT_EQ(SK_ColorBLUE, get_color(7, 0));
1308
1309   destination_gl->DeleteTextures(1, &texture);
1310 }
1311
1312 // Checks that we correctly copy a RGBA shared image VideoFrame when using
1313 // CopyVideoFrameYUVDataToGLTexture, including correct cropping.
1314 #if BUILDFLAG(IS_IOS) && BUILDFLAG(SKIA_USE_METAL)
1315 // TODO(crbug.com/1476625): R and B channels are currently inverted with
1316 // SkiaGraphite and metal.
1317 #define MAYBE_CopyVideoFrameTexturesToGLTextureRGBA \
1318   DISABLED_CopyVideoFrameTexturesToGLTextureRGBA
1319 #else
1320 #define MAYBE_CopyVideoFrameTexturesToGLTextureRGBA \
1321   CopyVideoFrameTexturesToGLTextureRGBA
1322 #endif  // BUILDFLAG(IS_IOS) && BUILDFLAG(SKIA_USE_METAL)
1323 TEST_F(PaintCanvasVideoRendererWithGLTest,
1324        MAYBE_CopyVideoFrameTexturesToGLTextureRGBA) {
1325   base::RunLoop run_loop;
1326   scoped_refptr<VideoFrame> frame = CreateTestRGBAFrame(run_loop.QuitClosure());
1327
1328   CopyVideoFrameTexturesAndCheckPixels(frame, &CheckRGBAFramePixels);
1329
1330   frame.reset();
1331   run_loop.Run();
1332 }
1333
1334 // Checks that we correctly copy a RGBA shared image VideoFrame that needs read
1335 // lock fences, when using CopyVideoFrameYUVDataToGLTexture, including correct
1336 // cropping.
1337 #if BUILDFLAG(IS_IOS) && BUILDFLAG(SKIA_USE_METAL)
1338 // TODO(crbug.com/1476625): R and B channels are currently inverted with
1339 // SkiaGraphite and metal.
1340 #define MAYBE_CopyVideoFrameTexturesToGLTextureRGBA_ReadLockFence \
1341   DISABLED_CopyVideoFrameTexturesToGLTextureRGBA_ReadLockFence
1342 #else
1343 #define MAYBE_CopyVideoFrameTexturesToGLTextureRGBA_ReadLockFence \
1344   CopyVideoFrameTexturesToGLTextureRGBA_ReadLockFence
1345 #endif  // BUILDFLAG(IS_IOS) && BUILDFLAG(SKIA_USE_METAL)
1346 TEST_F(PaintCanvasVideoRendererWithGLTest,
1347        MAYBE_CopyVideoFrameTexturesToGLTextureRGBA_ReadLockFence) {
1348   base::RunLoop run_loop;
1349   scoped_refptr<VideoFrame> frame = CreateTestRGBAFrame(run_loop.QuitClosure());
1350   frame->metadata().read_lock_fences_enabled = true;
1351
1352   CopyVideoFrameTexturesAndCheckPixels(frame, &CheckRGBAFramePixels);
1353
1354   frame.reset();
1355   run_loop.Run();
1356 }
1357
1358 // Checks that we correctly paint a RGBA shared image VideoFrame, including
1359 // correct cropping.
1360 TEST_F(PaintCanvasVideoRendererWithGLTest, PaintRGBA) {
1361   base::RunLoop run_loop;
1362   scoped_refptr<VideoFrame> frame = CreateTestRGBAFrame(run_loop.QuitClosure());
1363
1364   PaintVideoFrameAndCheckPixels(frame, &CheckRGBAFramePixels);
1365
1366   frame.reset();
1367   run_loop.Run();
1368 }
1369
1370 // Checks that we correctly copy an I420 shared image VideoFrame when using
1371 // CopyVideoFrameYUVDataToGLTexture, including correct cropping.
1372 TEST_F(PaintCanvasVideoRendererWithGLTest,
1373        CopyVideoFrameTexturesToGLTextureI420) {
1374   base::RunLoop run_loop;
1375   scoped_refptr<VideoFrame> frame = CreateTestI420Frame(run_loop.QuitClosure());
1376
1377   CopyVideoFrameTexturesAndCheckPixels(frame, &CheckI420FramePixels);
1378
1379   frame.reset();
1380   run_loop.Run();
1381 }
1382
1383 // Checks that we correctly paint a I420 shared image VideoFrame, including
1384 // correct cropping.
1385 TEST_F(PaintCanvasVideoRendererWithGLTest, PaintI420) {
1386   base::RunLoop run_loop;
1387   scoped_refptr<VideoFrame> frame = CreateTestI420Frame(run_loop.QuitClosure());
1388
1389   PaintVideoFrameAndCheckPixels(frame, &CheckI420FramePixels);
1390
1391   frame.reset();
1392   run_loop.Run();
1393 }
1394
1395 // Checks that we correctly paint a I420 shared image VideoFrame, including
1396 // correct cropping.
1397 TEST_F(PaintCanvasVideoRendererWithGLTest, PaintI420NotSubset) {
1398   base::RunLoop run_loop;
1399   scoped_refptr<VideoFrame> frame =
1400       CreateTestI420FrameNotSubset(run_loop.QuitClosure());
1401
1402   PaintVideoFrameAndCheckPixels(frame, &CheckI420FramePixelsNotSubset);
1403
1404   frame.reset();
1405   run_loop.Run();
1406 }
1407
1408 // Checks that we correctly copy a NV12 shared image VideoFrame when using
1409 // CopyVideoFrameYUVDataToGLTexture, including correct cropping.
1410 TEST_F(PaintCanvasVideoRendererWithGLTest,
1411        CopyVideoFrameTexturesToGLTextureNV12) {
1412   base::RunLoop run_loop;
1413   scoped_refptr<VideoFrame> frame = CreateTestNV12Frame(run_loop.QuitClosure());
1414   if (!frame) {
1415     LOG(ERROR) << "GL_EXT_texture_rg not supported, skipping NV12 test";
1416     return;
1417   }
1418
1419   CopyVideoFrameTexturesAndCheckPixels(frame, &CheckNV12FramePixels);
1420
1421   frame.reset();
1422   run_loop.Run();
1423 }
1424
1425 // Checks that we correctly paint a NV12 shared image VideoFrame, including
1426 // correct cropping.
1427 TEST_F(PaintCanvasVideoRendererWithGLTest, PaintNV12) {
1428   base::RunLoop run_loop;
1429   scoped_refptr<VideoFrame> frame = CreateTestNV12Frame(run_loop.QuitClosure());
1430   if (!frame) {
1431     LOG(ERROR) << "GL_EXT_texture_rg not supported, skipping NV12 test";
1432     return;
1433   }
1434
1435   PaintVideoFrameAndCheckPixels(frame, &CheckNV12FramePixels);
1436
1437   frame.reset();
1438   run_loop.Run();
1439 }
1440
1441 }  // namespace media