1 // Copyright 2018 The Chromium Authors. All rights reserved.
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 "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h"
6 
7 #include "components/viz/common/resources/single_release_callback.h"
8 #include "components/viz/test/test_context_provider.h"
9 #include "components/viz/test/test_gles2_interface.h"
10 #include "components/viz/test/test_gpu_memory_buffer_manager.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "third_party/blink/renderer/platform/graphics/canvas_color_params.h"
14 #include "third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h"
15 #include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
16 #include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
17 #include "third_party/blink/renderer/platform/graphics/test/fake_gles2_interface.h"
18 #include "third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h"
19 #include "third_party/blink/renderer/platform/graphics/test/gpu_memory_buffer_test_platform.h"
20 #include "third_party/blink/renderer/platform/graphics/test/gpu_test_utils.h"
21 #include "third_party/blink/renderer/platform/wtf/functional.h"
22 #include "third_party/skia/include/core/SkFilterQuality.h"
23 #include "ui/gfx/buffer_types.h"
24 
25 using testing::_;
26 using testing::InSequence;
27 using testing::Return;
28 using testing::Test;
29 
30 namespace blink {
31 
32 namespace {
33 
34 constexpr int kMaxTextureSize = 1024;
35 
36 class MockCanvasResourceDispatcherClient
37     : public CanvasResourceDispatcherClient {
38  public:
39   MockCanvasResourceDispatcherClient() = default;
40 
41   MOCK_METHOD0(BeginFrame, bool());
42   MOCK_METHOD1(SetFilterQualityInResource, void(SkFilterQuality));
43 };
44 
45 }  // anonymous namespace
46 
47 class CanvasResourceProviderTest : public Test {
48  public:
SetUp()49   void SetUp() override {
50     test_context_provider_ = viz::TestContextProvider::Create();
51     auto* test_gl = test_context_provider_->UnboundTestContextGL();
52     test_gl->set_max_texture_size(kMaxTextureSize);
53     test_gl->set_support_texture_storage_image(true);
54     test_gl->set_supports_shared_image_swap_chain(true);
55     test_gl->set_supports_gpu_memory_buffer_format(gfx::BufferFormat::RGBA_8888,
56                                                    true);
57     test_gl->set_supports_gpu_memory_buffer_format(gfx::BufferFormat::BGRA_8888,
58                                                    true);
59     test_gl->set_supports_gpu_memory_buffer_format(gfx::BufferFormat::RGBA_F16,
60                                                    true);
61     InitializeSharedGpuContext(test_context_provider_.get(),
62                                &image_decode_cache_);
63     context_provider_wrapper_ = SharedGpuContext::ContextProviderWrapper();
64   }
65 
TearDown()66   void TearDown() override { SharedGpuContext::ResetForTesting(); }
67 
68  protected:
69   cc::StubDecodeCache image_decode_cache_;
70   scoped_refptr<viz::TestContextProvider> test_context_provider_;
71   base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper_;
72   ScopedTestingPlatformSupport<GpuMemoryBufferTestPlatform> platform_;
73 };
74 
TEST_F(CanvasResourceProviderTest,CanvasResourceProviderAcceleratedOverlay)75 TEST_F(CanvasResourceProviderTest, CanvasResourceProviderAcceleratedOverlay) {
76   const IntSize kSize(10, 10);
77   const CanvasColorParams kColorParams(
78       CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
79       kNonOpaque);
80 
81   auto provider = CanvasResourceProvider::Create(
82       kSize,
83       CanvasResourceProvider::ResourceUsage::kAcceleratedDirect2DResourceUsage,
84       context_provider_wrapper_, 0 /* msaa_sample_count */,
85       kMedium_SkFilterQuality, kColorParams,
86       CanvasResourceProvider::kAllowImageChromiumPresentationMode,
87       nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
88 
89   EXPECT_EQ(provider->Size(), kSize);
90   EXPECT_TRUE(provider->IsValid());
91   EXPECT_TRUE(provider->IsAccelerated());
92   EXPECT_TRUE(provider->SupportsDirectCompositing());
93   EXPECT_TRUE(provider->SupportsSingleBuffering());
94   EXPECT_EQ(provider->ColorParams().ColorSpace(), kColorParams.ColorSpace());
95   // As it is an CanvasResourceProviderSharedImage and an accelerated canvas, it
96   // will internally force it to kRGBA8
97   EXPECT_EQ(provider->ColorParams().PixelFormat(), CanvasPixelFormat::kRGBA8);
98   EXPECT_EQ(provider->ColorParams().GetOpacityMode(),
99             kColorParams.GetOpacityMode());
100 
101   EXPECT_FALSE(provider->IsSingleBuffered());
102   provider->TryEnableSingleBuffering();
103   EXPECT_TRUE(provider->IsSingleBuffered());
104 }
105 
TEST_F(CanvasResourceProviderTest,CanvasResourceProviderTexture)106 TEST_F(CanvasResourceProviderTest, CanvasResourceProviderTexture) {
107   const IntSize kSize(10, 10);
108   const CanvasColorParams kColorParams(
109       CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
110       kNonOpaque);
111 
112   auto provider = CanvasResourceProvider::CreateSharedImageProvider(
113       kSize, context_provider_wrapper_, kLow_SkFilterQuality, kColorParams,
114       true /*is_origin_top_left*/, CanvasResourceProvider::RasterMode::kGPU,
115       0u /*shared_image_usage_flags*/);
116 
117   EXPECT_EQ(provider->Size(), kSize);
118   EXPECT_TRUE(provider->IsValid());
119   EXPECT_TRUE(provider->IsAccelerated());
120   EXPECT_TRUE(provider->SupportsDirectCompositing());
121   EXPECT_FALSE(provider->SupportsSingleBuffering());
122   EXPECT_EQ(provider->ColorParams().ColorSpace(), kColorParams.ColorSpace());
123   // As it is an CanvasResourceProviderSharedImage and an accelerated canvas, it
124   // will internally force it to kRGBA8
125   EXPECT_EQ(provider->ColorParams().PixelFormat(), CanvasPixelFormat::kRGBA8);
126   EXPECT_EQ(provider->ColorParams().GetOpacityMode(),
127             kColorParams.GetOpacityMode());
128 
129   EXPECT_FALSE(provider->IsSingleBuffered());
130 }
131 
TEST_F(CanvasResourceProviderTest,CanvasResourceProviderUnacceleratedOverlay)132 TEST_F(CanvasResourceProviderTest, CanvasResourceProviderUnacceleratedOverlay) {
133   const IntSize kSize(10, 10);
134   const CanvasColorParams kColorParams(
135       CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
136       kNonOpaque);
137 
138   auto provider = CanvasResourceProvider::Create(
139       kSize,
140       CanvasResourceProvider::ResourceUsage::kSoftwareCompositedResourceUsage,
141       context_provider_wrapper_, 0 /* msaa_sample_count */,
142       kLow_SkFilterQuality, kColorParams,
143       CanvasResourceProvider::kAllowImageChromiumPresentationMode,
144       nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
145 
146   EXPECT_EQ(provider->Size(), kSize);
147   EXPECT_TRUE(provider->IsValid());
148   EXPECT_FALSE(provider->IsAccelerated());
149   EXPECT_TRUE(provider->SupportsDirectCompositing());
150 
151   // We do not support single buffering for unaccelerated low latency canvas.
152   EXPECT_FALSE(provider->SupportsSingleBuffering());
153 
154   EXPECT_EQ(provider->ColorParams().ColorSpace(), kColorParams.ColorSpace());
155   EXPECT_EQ(provider->ColorParams().PixelFormat(), kColorParams.PixelFormat());
156   EXPECT_EQ(provider->ColorParams().GetOpacityMode(),
157             kColorParams.GetOpacityMode());
158 
159   EXPECT_FALSE(provider->IsSingleBuffered());
160 }
161 
TEST_F(CanvasResourceProviderTest,CanvasResourceProviderSharedImageResourceRecycling)162 TEST_F(CanvasResourceProviderTest,
163        CanvasResourceProviderSharedImageResourceRecycling) {
164   const IntSize kSize(10, 10);
165   const CanvasColorParams kColorParams(
166       CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
167       kNonOpaque);
168 
169   auto provider = CanvasResourceProvider::Create(
170       kSize,
171       CanvasResourceProvider::ResourceUsage::
172           kAcceleratedCompositedResourceUsage,
173       context_provider_wrapper_, 0 /* msaa_sample_count */,
174       kMedium_SkFilterQuality, kColorParams,
175       CanvasResourceProvider::kAllowImageChromiumPresentationMode,
176       nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
177 
178   EXPECT_EQ(provider->Size(), kSize);
179   EXPECT_TRUE(provider->IsValid());
180   EXPECT_TRUE(provider->IsAccelerated());
181   EXPECT_FALSE(provider->IsSingleBuffered());
182   EXPECT_FALSE(provider->SupportsSingleBuffering());
183   EXPECT_EQ(provider->ColorParams().ColorSpace(), kColorParams.ColorSpace());
184   // As it is an CanvasResourceProviderSharedImage and an accelerated canvas, it
185   // will internally force it to kRGBA8
186   EXPECT_EQ(provider->ColorParams().PixelFormat(), CanvasPixelFormat::kRGBA8);
187   EXPECT_EQ(provider->ColorParams().GetOpacityMode(),
188             kColorParams.GetOpacityMode());
189 
190   // Same resource and sync token if we query again without updating.
191   auto resource = provider->ProduceCanvasResource();
192   auto sync_token = resource->GetSyncToken();
193   ASSERT_TRUE(resource);
194   EXPECT_EQ(resource, provider->ProduceCanvasResource());
195   EXPECT_EQ(sync_token, resource->GetSyncToken());
196 
197   // Resource updated after draw.
198   provider->Canvas()->clear(SK_ColorWHITE);
199   auto new_resource = provider->ProduceCanvasResource();
200   EXPECT_NE(resource, new_resource);
201   EXPECT_NE(sync_token, new_resource->GetSyncToken());
202 
203   // Resource recycled.
204   viz::TransferableResource transferable_resource;
205   std::unique_ptr<viz::SingleReleaseCallback> release_callback;
206   ASSERT_TRUE(resource->PrepareTransferableResource(
207       &transferable_resource, &release_callback, kUnverifiedSyncToken));
208   auto* resource_ptr = resource.get();
209   resource = nullptr;
210   release_callback->Run(sync_token, false);
211 
212   provider->Canvas()->clear(SK_ColorBLACK);
213   auto resource_again = provider->ProduceCanvasResource();
214   EXPECT_EQ(resource_ptr, resource_again);
215   EXPECT_NE(sync_token, resource_again->GetSyncToken());
216 }
217 
TEST_F(CanvasResourceProviderTest,CanvasResourceProviderSharedImageStaticBitmapImage)218 TEST_F(CanvasResourceProviderTest,
219        CanvasResourceProviderSharedImageStaticBitmapImage) {
220   const IntSize kSize(10, 10);
221   const CanvasColorParams kColorParams(
222       CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
223       kNonOpaque);
224 
225   auto provider = CanvasResourceProvider::Create(
226       kSize,
227       CanvasResourceProvider::ResourceUsage::
228           kAcceleratedCompositedResourceUsage,
229       context_provider_wrapper_, 0 /* msaa_sample_count */,
230       kMedium_SkFilterQuality, kColorParams,
231       CanvasResourceProvider::kAllowImageChromiumPresentationMode,
232       nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
233   ASSERT_TRUE(provider->IsValid());
234 
235   // Same resource returned until the canvas is updated.
236   auto image = provider->Snapshot();
237   ASSERT_TRUE(image);
238   auto new_image = provider->Snapshot();
239   EXPECT_EQ(image->GetMailboxHolder().mailbox,
240             new_image->GetMailboxHolder().mailbox);
241   EXPECT_EQ(provider->ProduceCanvasResource()->GetOrCreateGpuMailbox(
242                 kOrderingBarrier),
243             image->GetMailboxHolder().mailbox);
244 
245   // Resource updated after draw.
246   provider->Canvas()->clear(SK_ColorWHITE);
247   provider->FlushCanvas();
248   new_image = provider->Snapshot();
249   EXPECT_NE(new_image->GetMailboxHolder().mailbox,
250             image->GetMailboxHolder().mailbox);
251 
252   // Resource recycled.
253   auto original_mailbox = image->GetMailboxHolder().mailbox;
254   image.reset();
255   provider->Canvas()->clear(SK_ColorBLACK);
256   provider->FlushCanvas();
257   EXPECT_EQ(original_mailbox, provider->Snapshot()->GetMailboxHolder().mailbox);
258 }
259 
TEST_F(CanvasResourceProviderTest,CanvasResourceProviderSharedImageCopyOnWriteDisabled)260 TEST_F(CanvasResourceProviderTest,
261        CanvasResourceProviderSharedImageCopyOnWriteDisabled) {
262   auto* fake_context = static_cast<FakeWebGraphicsContext3DProvider*>(
263       context_provider_wrapper_->ContextProvider());
264   auto caps = fake_context->GetCapabilities();
265   caps.disable_2d_canvas_copy_on_write = true;
266   fake_context->SetCapabilities(caps);
267 
268   const IntSize kSize(10, 10);
269   const CanvasColorParams kColorParams(
270       CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
271       kNonOpaque);
272 
273   auto provider = CanvasResourceProvider::Create(
274       kSize,
275       CanvasResourceProvider::ResourceUsage::
276           kAcceleratedCompositedResourceUsage,
277       context_provider_wrapper_, 0 /* msaa_sample_count */,
278       kMedium_SkFilterQuality, kColorParams,
279       CanvasResourceProvider::kAllowImageChromiumPresentationMode,
280       nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
281   ASSERT_TRUE(provider->IsValid());
282 
283   // Disabling copy-on-write forces a copy each time the resource is queried.
284   auto resource = provider->ProduceCanvasResource();
285   EXPECT_NE(resource->GetOrCreateGpuMailbox(kOrderingBarrier),
286             provider->ProduceCanvasResource()->GetOrCreateGpuMailbox(
287                 kOrderingBarrier));
288 }
289 
TEST_F(CanvasResourceProviderTest,CanvasResourceProviderBitmap)290 TEST_F(CanvasResourceProviderTest, CanvasResourceProviderBitmap) {
291   const IntSize kSize(10, 10);
292   const CanvasColorParams kColorParams(
293       CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
294       kNonOpaque);
295 
296   auto provider = CanvasResourceProvider::CreateBitmapProvider(
297       kSize, kLow_SkFilterQuality, kColorParams);
298 
299   EXPECT_EQ(provider->Size(), kSize);
300   EXPECT_TRUE(provider->IsValid());
301   EXPECT_FALSE(provider->IsAccelerated());
302   EXPECT_FALSE(provider->SupportsDirectCompositing());
303   EXPECT_FALSE(provider->SupportsSingleBuffering());
304   EXPECT_EQ(provider->ColorParams().ColorSpace(), kColorParams.ColorSpace());
305   EXPECT_EQ(provider->ColorParams().PixelFormat(), kColorParams.PixelFormat());
306   EXPECT_EQ(provider->ColorParams().GetOpacityMode(),
307             kColorParams.GetOpacityMode());
308 
309   EXPECT_FALSE(provider->IsSingleBuffered());
310 }
311 
TEST_F(CanvasResourceProviderTest,CanvasResourceProviderSharedBitmap)312 TEST_F(CanvasResourceProviderTest, CanvasResourceProviderSharedBitmap) {
313   const IntSize kSize(10, 10);
314   const CanvasColorParams kColorParams(
315       CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
316       kNonOpaque);
317 
318   MockCanvasResourceDispatcherClient client;
319   CanvasResourceDispatcher resource_dispatcher(
320       &client, 1 /* client_id */, 1 /* sink_id */,
321       1 /* placeholder_canvas_id */, kSize);
322 
323   auto provider = CanvasResourceProvider::Create(
324       kSize,
325       CanvasResourceProvider::ResourceUsage::kSoftwareCompositedResourceUsage,
326       context_provider_wrapper_, 0 /* msaa_sample_count */,
327       kLow_SkFilterQuality, kColorParams,
328       CanvasResourceProvider::kDefaultPresentationMode,
329       resource_dispatcher.GetWeakPtr(), true /* is_origin_top_left */);
330 
331   EXPECT_EQ(provider->Size(), kSize);
332   EXPECT_TRUE(provider->IsValid());
333   EXPECT_FALSE(provider->IsAccelerated());
334   EXPECT_TRUE(provider->SupportsDirectCompositing());
335   EXPECT_FALSE(provider->SupportsSingleBuffering());
336   EXPECT_EQ(provider->ColorParams().ColorSpace(), kColorParams.ColorSpace());
337   EXPECT_EQ(provider->ColorParams().PixelFormat(), kColorParams.PixelFormat());
338   EXPECT_EQ(provider->ColorParams().GetOpacityMode(),
339             kColorParams.GetOpacityMode());
340 
341   EXPECT_FALSE(provider->IsSingleBuffered());
342   provider->TryEnableSingleBuffering();
343   EXPECT_FALSE(provider->IsSingleBuffered());
344 }
345 
TEST_F(CanvasResourceProviderTest,CanvasResourceProviderDirect2DGpuMemoryBuffer)346 TEST_F(CanvasResourceProviderTest,
347        CanvasResourceProviderDirect2DGpuMemoryBuffer) {
348   const IntSize kSize(10, 10);
349   const CanvasColorParams kColorParams(
350       CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
351       kNonOpaque);
352 
353   auto provider = CanvasResourceProvider::Create(
354       kSize,
355       CanvasResourceProvider::ResourceUsage::kAcceleratedDirect2DResourceUsage,
356       context_provider_wrapper_, 0 /* msaa_sample_count */,
357       kLow_SkFilterQuality, kColorParams,
358       CanvasResourceProvider::kAllowImageChromiumPresentationMode,
359       nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
360 
361   EXPECT_EQ(provider->Size(), kSize);
362   EXPECT_TRUE(provider->IsValid());
363   EXPECT_TRUE(provider->IsAccelerated());
364   EXPECT_TRUE(provider->SupportsDirectCompositing());
365   EXPECT_TRUE(provider->SupportsSingleBuffering());
366   EXPECT_EQ(provider->ColorParams().ColorSpace(), kColorParams.ColorSpace());
367   // As it is an CanvasResourceProviderSharedImage and an accelerated canvas, it
368   // will internally force it to kRGBA8
369   EXPECT_EQ(provider->ColorParams().PixelFormat(), CanvasPixelFormat::kRGBA8);
370   EXPECT_EQ(provider->ColorParams().GetOpacityMode(),
371             kColorParams.GetOpacityMode());
372 
373   EXPECT_FALSE(provider->IsSingleBuffered());
374   provider->TryEnableSingleBuffering();
375   EXPECT_TRUE(provider->IsSingleBuffered());
376 }
377 
TEST_F(CanvasResourceProviderTest,CanvasResourceProviderDirect3DGpuMemoryBuffer)378 TEST_F(CanvasResourceProviderTest,
379        CanvasResourceProviderDirect3DGpuMemoryBuffer) {
380   const IntSize kSize(10, 10);
381   const CanvasColorParams kColorParams(
382       CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
383       kNonOpaque);
384 
385   auto provider = CanvasResourceProvider::Create(
386       kSize,
387       CanvasResourceProvider::ResourceUsage::kAcceleratedDirect3DResourceUsage,
388       context_provider_wrapper_, 0 /* msaa_sample_count */,
389       kLow_SkFilterQuality, kColorParams,
390       CanvasResourceProvider::kAllowImageChromiumPresentationMode,
391       nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
392 
393   EXPECT_EQ(provider->Size(), kSize);
394   EXPECT_TRUE(provider->IsValid());
395   EXPECT_TRUE(provider->IsAccelerated());
396   EXPECT_TRUE(provider->SupportsDirectCompositing());
397   EXPECT_TRUE(provider->SupportsSingleBuffering());
398   EXPECT_EQ(provider->ColorParams().ColorSpace(), kColorParams.ColorSpace());
399   EXPECT_EQ(provider->ColorParams().PixelFormat(), kColorParams.PixelFormat());
400   EXPECT_EQ(provider->ColorParams().GetOpacityMode(),
401             kColorParams.GetOpacityMode());
402 
403   EXPECT_FALSE(provider->IsSingleBuffered());
404   provider->TryEnableSingleBuffering();
405   EXPECT_TRUE(provider->IsSingleBuffered());
406 
407   gpu::Mailbox mailbox = gpu::Mailbox::Generate();
408   scoped_refptr<ExternalCanvasResource> resource =
409       ExternalCanvasResource::Create(
410           mailbox, kSize, GL_TEXTURE_2D, kColorParams,
411           SharedGpuContext::ContextProviderWrapper(), provider->CreateWeakPtr(),
412           kMedium_SkFilterQuality, true /*is_origin_top_left*/);
413 
414   // NewOrRecycledResource() would return nullptr before an ImportResource().
415   EXPECT_TRUE(provider->ImportResource(resource));
416   EXPECT_EQ(provider->NewOrRecycledResource(), resource);
417   // NewOrRecycledResource() will always return the same |resource|.
418   EXPECT_EQ(provider->NewOrRecycledResource(), resource);
419 }
420 
421 // Verifies that Accelerated Direct 3D resources are backed by SharedImages.
422 // https://crbug.com/985366
TEST_F(CanvasResourceProviderTest,CanvasResourceProviderDirect3DTexture)423 TEST_F(CanvasResourceProviderTest, CanvasResourceProviderDirect3DTexture) {
424   const IntSize kSize(10, 10);
425   const CanvasColorParams kColorParams(
426       CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
427       kNonOpaque);
428 
429   auto provider = CanvasResourceProvider::Create(
430       kSize,
431       CanvasResourceProvider::ResourceUsage::kAcceleratedDirect3DResourceUsage,
432       context_provider_wrapper_, 0 /* msaa_sample_count */,
433       kLow_SkFilterQuality, kColorParams,
434       CanvasResourceProvider::kDefaultPresentationMode,
435       nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
436 
437   EXPECT_EQ(provider->Size(), kSize);
438   EXPECT_TRUE(provider->IsValid());
439   EXPECT_TRUE(provider->IsAccelerated());
440   EXPECT_TRUE(provider->SupportsDirectCompositing());
441   EXPECT_FALSE(provider->SupportsSingleBuffering());
442   EXPECT_EQ(provider->ColorParams().ColorSpace(), kColorParams.ColorSpace());
443   // As it is an CanvasResourceProviderSharedImage and an accelerated canvas, it
444   // will internally force it to kRGBA8
445   EXPECT_EQ(provider->ColorParams().PixelFormat(), CanvasPixelFormat::kRGBA8);
446   EXPECT_EQ(provider->ColorParams().GetOpacityMode(),
447             kColorParams.GetOpacityMode());
448 
449   EXPECT_FALSE(provider->IsSingleBuffered());
450   provider->TryEnableSingleBuffering();
451   EXPECT_FALSE(provider->IsSingleBuffered());
452 
453   auto resource = provider->ProduceCanvasResource();
454   viz::TransferableResource transferable_resource;
455   std::unique_ptr<viz::SingleReleaseCallback> callback;
456   resource->PrepareTransferableResource(&transferable_resource, &callback,
457                                         kOrderingBarrier);
458   EXPECT_TRUE(transferable_resource.mailbox_holder.mailbox.IsSharedImage());
459   EXPECT_FALSE(transferable_resource.is_overlay_candidate);
460   callback->Run(gpu::SyncToken(), true /* is_lost */);
461 }
462 
TEST_F(CanvasResourceProviderTest,DimensionsExceedMaxTextureSize_Bitmap)463 TEST_F(CanvasResourceProviderTest, DimensionsExceedMaxTextureSize_Bitmap) {
464   const CanvasColorParams kColorParams(
465       CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
466       kNonOpaque);
467 
468   auto provider = CanvasResourceProvider::CreateBitmapProvider(
469       IntSize(kMaxTextureSize - 1, kMaxTextureSize), kLow_SkFilterQuality,
470       kColorParams);
471   EXPECT_FALSE(provider->SupportsDirectCompositing());
472   provider = CanvasResourceProvider::CreateBitmapProvider(
473       IntSize(kMaxTextureSize, kMaxTextureSize), kLow_SkFilterQuality,
474       kColorParams);
475   EXPECT_FALSE(provider->SupportsDirectCompositing());
476   provider = CanvasResourceProvider::CreateBitmapProvider(
477       IntSize(kMaxTextureSize + 1, kMaxTextureSize), kLow_SkFilterQuality,
478       kColorParams);
479   EXPECT_FALSE(provider->SupportsDirectCompositing());
480 }
481 
TEST_F(CanvasResourceProviderTest,DimensionsExceedMaxTextureSize_SharedImage)482 TEST_F(CanvasResourceProviderTest, DimensionsExceedMaxTextureSize_SharedImage) {
483   const CanvasColorParams kColorParams(
484       CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
485       kNonOpaque);
486 
487   auto provider = CanvasResourceProvider::CreateSharedImageProvider(
488       IntSize(kMaxTextureSize - 1, kMaxTextureSize), context_provider_wrapper_,
489       kLow_SkFilterQuality, kColorParams, true /*is_origin_top_left*/,
490       CanvasResourceProvider::RasterMode::kGPU,
491       0u /*shared_image_usage_flags*/);
492   EXPECT_TRUE(provider->SupportsDirectCompositing());
493   provider = CanvasResourceProvider::CreateSharedImageProvider(
494       IntSize(kMaxTextureSize, kMaxTextureSize), context_provider_wrapper_,
495       kLow_SkFilterQuality, kColorParams, true /*is_origin_top_left*/,
496       CanvasResourceProvider::RasterMode::kGPU,
497       0u /*shared_image_usage_flags*/);
498   EXPECT_TRUE(provider->SupportsDirectCompositing());
499   provider = CanvasResourceProvider::CreateSharedImageProvider(
500       IntSize(kMaxTextureSize + 1, kMaxTextureSize), context_provider_wrapper_,
501       kLow_SkFilterQuality, kColorParams, true /*is_origin_top_left*/,
502       CanvasResourceProvider::RasterMode::kGPU,
503       0u /*shared_image_usage_flags*/);
504   // The CanvasResourceProvider for SharedImage should not be created or valid
505   // if the texture size is greater than the maximum value
506   EXPECT_TRUE(!provider || !provider->IsValid());
507 }
508 
TEST_F(CanvasResourceProviderTest,DimensionsExceedMaxTextureSize)509 TEST_F(CanvasResourceProviderTest, DimensionsExceedMaxTextureSize) {
510   const CanvasColorParams kColorParams(
511       CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
512       kNonOpaque);
513 
514   for (int i = 0;
515        i < static_cast<int>(CanvasResourceProvider::ResourceUsage::kMaxValue);
516        ++i) {
517     SCOPED_TRACE(i);
518     auto usage = static_cast<CanvasResourceProvider::ResourceUsage>(i);
519     bool should_support_compositing = false;
520     std::unique_ptr<CanvasResourceProvider> provider;
521     switch (usage) {
522       // Skipping ResourceUsages that will be removed after this refactor
523       // bug(1035589)
524       case CanvasResourceProvider::ResourceUsage::kSoftwareResourceUsage:
525         continue;
526       case CanvasResourceProvider::ResourceUsage::kAcceleratedResourceUsage:
527         continue;
528       case CanvasResourceProvider::ResourceUsage::
529           kSoftwareCompositedResourceUsage:
530         FALLTHROUGH;
531       case CanvasResourceProvider::ResourceUsage::
532           kSoftwareCompositedDirect2DResourceUsage:
533         FALLTHROUGH;
534       case CanvasResourceProvider::ResourceUsage::
535           kAcceleratedCompositedResourceUsage:
536         FALLTHROUGH;
537       case CanvasResourceProvider::ResourceUsage::
538           kAcceleratedDirect2DResourceUsage:
539         FALLTHROUGH;
540       case CanvasResourceProvider::ResourceUsage::
541           kAcceleratedDirect3DResourceUsage:
542         should_support_compositing = true;
543         break;
544     }
545 
546       provider = CanvasResourceProvider::Create(
547           IntSize(kMaxTextureSize - 1, kMaxTextureSize), usage,
548           context_provider_wrapper_, 0 /* msaa_sample_count */,
549           kLow_SkFilterQuality, kColorParams,
550           CanvasResourceProvider::kAllowImageChromiumPresentationMode,
551           nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
552 
553     EXPECT_EQ(provider->SupportsDirectCompositing(),
554               should_support_compositing);
555 
556       provider = CanvasResourceProvider::Create(
557           IntSize(kMaxTextureSize, kMaxTextureSize), usage,
558           context_provider_wrapper_, 0 /* msaa_sample_count */,
559           kLow_SkFilterQuality, kColorParams,
560           CanvasResourceProvider::kAllowImageChromiumPresentationMode,
561           nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
562 
563     EXPECT_EQ(provider->SupportsDirectCompositing(),
564               should_support_compositing);
565 
566       provider = CanvasResourceProvider::Create(
567           IntSize(kMaxTextureSize + 1, kMaxTextureSize), usage,
568           context_provider_wrapper_, 0 /* msaa_sample_count */,
569           kLow_SkFilterQuality, kColorParams,
570           CanvasResourceProvider::kAllowImageChromiumPresentationMode,
571           nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
572 
573     EXPECT_FALSE(provider->SupportsDirectCompositing());
574   }
575 }
576 
TEST_F(CanvasResourceProviderTest,CanvasResourceProviderDirect2DSwapChain)577 TEST_F(CanvasResourceProviderTest, CanvasResourceProviderDirect2DSwapChain) {
578   const IntSize kSize(10, 10);
579   const CanvasColorParams kColorParams(
580       CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(),
581       kNonOpaque);
582 
583   auto provider = CanvasResourceProvider::Create(
584       kSize,
585       CanvasResourceProvider::ResourceUsage::kAcceleratedDirect2DResourceUsage,
586       context_provider_wrapper_, 0 /* msaa_sample_count */,
587       kLow_SkFilterQuality, kColorParams,
588       CanvasResourceProvider::kAllowSwapChainPresentationMode,
589       nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
590 
591   EXPECT_EQ(provider->Size(), kSize);
592   EXPECT_TRUE(provider->IsValid());
593   EXPECT_TRUE(provider->IsAccelerated());
594   EXPECT_TRUE(provider->SupportsDirectCompositing());
595   EXPECT_TRUE(provider->SupportsSingleBuffering());
596   EXPECT_EQ(provider->ColorParams().ColorSpace(), kColorParams.ColorSpace());
597   EXPECT_EQ(provider->ColorParams().PixelFormat(), kColorParams.PixelFormat());
598   EXPECT_EQ(provider->ColorParams().GetOpacityMode(),
599             kColorParams.GetOpacityMode());
600 
601   EXPECT_FALSE(provider->IsSingleBuffered());
602   provider->TryEnableSingleBuffering();
603   EXPECT_TRUE(provider->IsSingleBuffered());
604 }
605 
606 }  // namespace blink
607