1 // Copyright 2012 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 "components/viz/service/display/gl_renderer.h"
6 
7 #include <stdint.h>
8 
9 #include <memory>
10 #include <set>
11 #include <tuple>
12 #include <utility>
13 #include <vector>
14 
15 #include "base/bind.h"
16 #include "base/bind_helpers.h"
17 #include "base/location.h"
18 #include "base/single_thread_task_runner.h"
19 #include "base/test/scoped_feature_list.h"
20 #include "base/threading/thread_task_runner_handle.h"
21 #include "build/build_config.h"
22 #include "cc/base/math_util.h"
23 #include "cc/test/fake_impl_task_runner_provider.h"
24 #include "cc/test/fake_layer_tree_host_impl.h"
25 #include "cc/test/fake_output_surface_client.h"
26 #include "cc/test/pixel_test.h"
27 #include "cc/test/render_pass_test_utils.h"
28 #include "cc/test/resource_provider_test_utils.h"
29 #include "components/viz/client/client_resource_provider.h"
30 #include "components/viz/common/display/renderer_settings.h"
31 #include "components/viz/common/frame_sinks/copy_output_request.h"
32 #include "components/viz/common/frame_sinks/copy_output_result.h"
33 #include "components/viz/common/quads/texture_draw_quad.h"
34 #include "components/viz/common/resources/platform_color.h"
35 #include "components/viz/common/resources/transferable_resource.h"
36 #include "components/viz/service/display/display_resource_provider.h"
37 #include "components/viz/test/fake_output_surface.h"
38 #include "components/viz/test/test_gles2_interface.h"
39 #include "components/viz/test/test_shared_bitmap_manager.h"
40 #include "gpu/GLES2/gl2extchromium.h"
41 #include "gpu/command_buffer/client/context_support.h"
42 #include "gpu/config/gpu_finch_features.h"
43 #include "testing/gmock/include/gmock/gmock.h"
44 #include "testing/gtest/include/gtest/gtest.h"
45 #include "third_party/skia/include/core/SkMatrix.h"
46 #include "third_party/skia/include/effects/SkColorMatrixFilter.h"
47 #include "ui/gfx/color_transform.h"
48 #include "ui/gfx/transform.h"
49 #include "ui/latency/latency_info.h"
50 
51 #if defined(OS_WIN)
52 #include "components/viz/service/display/overlay_processor_win.h"
53 #elif defined(OS_MACOSX)
54 #include "components/viz/service/display/overlay_processor_mac.h"
55 #elif defined(OS_ANDROID) || defined(USE_OZONE)
56 #include "components/viz/service/display/overlay_processor_using_strategy.h"
57 #include "components/viz/service/display/overlay_strategy_single_on_top.h"
58 #include "components/viz/service/display/overlay_strategy_underlay.h"
59 #else  // Default
60 #include "components/viz/service/display/overlay_processor_stub.h"
61 #endif
62 
63 using testing::_;
64 using testing::AnyNumber;
65 using testing::Args;
66 using testing::AtLeast;
67 using testing::Contains;
68 using testing::ElementsAre;
69 using testing::Expectation;
70 using testing::InSequence;
71 using testing::Invoke;
72 using testing::Mock;
73 using testing::Not;
74 using testing::Pointee;
75 using testing::Return;
76 using testing::StrictMock;
77 
78 namespace viz {
79 
80 MATCHER_P(MatchesSyncToken, sync_token, "") {
81   gpu::SyncToken other;
82   memcpy(&other, arg, sizeof(other));
83   return other == sync_token;
84 }
85 
86 class GLRendererTest : public testing::Test {
87  protected:
root_render_pass()88   RenderPass* root_render_pass() {
89     return render_passes_in_draw_order_.back().get();
90   }
DrawFrame(GLRenderer * renderer,const gfx::Size & viewport_size)91   void DrawFrame(GLRenderer* renderer, const gfx::Size& viewport_size) {
92     renderer->DrawFrame(&render_passes_in_draw_order_, 1.f, viewport_size,
93                         gfx::DisplayColorSpaces());
94   }
95 
current_program(GLRenderer * renderer)96   static const Program* current_program(GLRenderer* renderer) {
97     return renderer->current_program_;
98   }
99 
get_cached_tex_coord_precision(GLRenderer * renderer)100   static TexCoordPrecision get_cached_tex_coord_precision(
101       GLRenderer* renderer) {
102     return renderer->draw_cache_.program_key.tex_coord_precision();
103   }
104 
105   RenderPassList render_passes_in_draw_order_;
106 };
107 
108 #define EXPECT_PROGRAM_VALID(program_binding)      \
109   do {                                             \
110     ASSERT_TRUE(program_binding);                  \
111     EXPECT_TRUE((program_binding)->program());     \
112     EXPECT_TRUE((program_binding)->initialized()); \
113   } while (false)
114 
BlendModeToSkXfermode(BlendMode blend_mode)115 static inline SkBlendMode BlendModeToSkXfermode(BlendMode blend_mode) {
116   switch (blend_mode) {
117     case BLEND_MODE_NONE:
118     case BLEND_MODE_NORMAL:
119       return SkBlendMode::kSrcOver;
120     case BLEND_MODE_DESTINATION_IN:
121       return SkBlendMode::kDstIn;
122     case BLEND_MODE_SCREEN:
123       return SkBlendMode::kScreen;
124     case BLEND_MODE_OVERLAY:
125       return SkBlendMode::kOverlay;
126     case BLEND_MODE_DARKEN:
127       return SkBlendMode::kDarken;
128     case BLEND_MODE_LIGHTEN:
129       return SkBlendMode::kLighten;
130     case BLEND_MODE_COLOR_DODGE:
131       return SkBlendMode::kColorDodge;
132     case BLEND_MODE_COLOR_BURN:
133       return SkBlendMode::kColorBurn;
134     case BLEND_MODE_HARD_LIGHT:
135       return SkBlendMode::kHardLight;
136     case BLEND_MODE_SOFT_LIGHT:
137       return SkBlendMode::kSoftLight;
138     case BLEND_MODE_DIFFERENCE:
139       return SkBlendMode::kDifference;
140     case BLEND_MODE_EXCLUSION:
141       return SkBlendMode::kExclusion;
142     case BLEND_MODE_MULTIPLY:
143       return SkBlendMode::kMultiply;
144     case BLEND_MODE_HUE:
145       return SkBlendMode::kHue;
146     case BLEND_MODE_SATURATION:
147       return SkBlendMode::kSaturation;
148     case BLEND_MODE_COLOR:
149       return SkBlendMode::kColor;
150     case BLEND_MODE_LUMINOSITY:
151       return SkBlendMode::kLuminosity;
152   }
153   return SkBlendMode::kSrcOver;
154 }
155 
156 // Explicitly named to be a friend in GLRenderer for shader access.
157 class GLRendererShaderPixelTest : public cc::GLRendererPixelTest {
158  public:
SetUp()159   void SetUp() override {
160     cc::GLRendererPixelTest::SetUp();
161     ASSERT_FALSE(renderer()->IsContextLost());
162   }
163 
TearDown()164   void TearDown() override {
165     cc::GLRendererPixelTest::TearDown();
166     ASSERT_FALSE(renderer());
167   }
168 
TestShaderWithDrawingFrame(const ProgramKey & program_key,const DirectRenderer::DrawingFrame & drawing_frame,bool validate_output_color_matrix)169   void TestShaderWithDrawingFrame(
170       const ProgramKey& program_key,
171       const DirectRenderer::DrawingFrame& drawing_frame,
172       bool validate_output_color_matrix) {
173     renderer()->SetCurrentFrameForTesting(drawing_frame);
174     const size_t kNumSrcColorSpaces = 7;
175     gfx::ColorSpace src_color_spaces[kNumSrcColorSpaces] = {
176         gfx::ColorSpace::CreateSRGB(),
177         gfx::ColorSpace(gfx::ColorSpace::PrimaryID::ADOBE_RGB,
178                         gfx::ColorSpace::TransferID::GAMMA28),
179         gfx::ColorSpace::CreateREC709(),
180         gfx::ColorSpace::CreateExtendedSRGB(),
181         gfx::ColorSpace::CreateSCRGBLinear(),
182         // This will be adjusted to the display's SDR white level, because no
183         // level was specified.
184         gfx::ColorSpace::CreateHDR10(),
185         // This won't be, because it has a set SDR white level.
186         gfx::ColorSpace::CreateHDR10(123.f),
187     };
188     const size_t kNumDstColorSpaces = 4;
189     gfx::ColorSpace dst_color_spaces[kNumDstColorSpaces] = {
190         gfx::ColorSpace::CreateSRGB(),
191         gfx::ColorSpace(gfx::ColorSpace::PrimaryID::ADOBE_RGB,
192                         gfx::ColorSpace::TransferID::GAMMA18),
193         gfx::ColorSpace::CreateExtendedSRGB(),
194         gfx::ColorSpace::CreateSCRGBLinear(),
195     };
196     for (size_t i = 0; i < kNumDstColorSpaces; ++i) {
197       for (size_t j = 0; j < kNumSrcColorSpaces; ++j) {
198         const auto& src_color_space = src_color_spaces[j];
199         const auto& dst_color_space = dst_color_spaces[i];
200 
201         renderer()->SetUseProgram(program_key, src_color_space,
202                                   dst_color_space);
203         EXPECT_TRUE(renderer()->current_program_->initialized());
204 
205         if (src_color_space != dst_color_space) {
206           auto adjusted_color_space = src_color_space;
207           // Only in the iteration where we use CreateHDR10 without specifying
208           // an SDR white level should the white level be set by the renderer.
209           if (j == 5) {
210             adjusted_color_space = src_color_space.GetWithPQSDRWhiteLevel(
211                 drawing_frame.display_color_spaces.GetSDRWhiteLevel());
212             EXPECT_NE(adjusted_color_space, src_color_space);
213           }
214           auto color_transform = gfx::ColorTransform::NewColorTransform(
215               adjusted_color_space, dst_color_space,
216               gfx::ColorTransform::Intent::INTENT_PERCEPTUAL);
217           EXPECT_EQ(color_transform->GetShaderSource(),
218                     renderer()
219                         ->current_program_->color_transform_for_testing()
220                         ->GetShaderSource());
221         }
222 
223         if (validate_output_color_matrix) {
224           EXPECT_NE(
225               -1, renderer()->current_program_->output_color_matrix_location());
226         }
227       }
228     }
229   }
230 
TestShader(const ProgramKey & program_key)231   void TestShader(const ProgramKey& program_key) {
232     TestShaderWithDrawingFrame(program_key, GLRenderer::DrawingFrame(), false);
233   }
234 
TestShadersWithOutputColorMatrix(const ProgramKey & program_key)235   void TestShadersWithOutputColorMatrix(const ProgramKey& program_key) {
236     GLRenderer::DrawingFrame frame;
237 
238     RenderPassList render_passes_in_draw_order;
239     gfx::Size viewport_size(100, 100);
240     RenderPassId root_pass_id = 1;
241     RenderPass* root_pass = cc::AddRenderPass(
242         &render_passes_in_draw_order, root_pass_id, gfx::Rect(viewport_size),
243         gfx::Transform(), cc::FilterOperations());
244     root_pass->damage_rect = gfx::Rect(0, 0, 25, 25);
245 
246     frame.root_render_pass = root_pass;
247     frame.current_render_pass = root_pass;
248     frame.render_passes_in_draw_order = &render_passes_in_draw_order;
249 
250     // Set a non-identity color matrix on the output surface.
251     SkMatrix44 color_matrix(SkMatrix44::kIdentity_Constructor);
252     color_matrix.set(0, 0, 0.7f);
253     color_matrix.set(1, 1, 0.4f);
254     color_matrix.set(2, 2, 0.5f);
255     renderer()->output_surface_->set_color_matrix(color_matrix);
256 
257     TestShaderWithDrawingFrame(program_key, frame, true);
258   }
259 
TestShadersWithSDRWhiteLevel(const ProgramKey & program_key,float sdr_white_level)260   void TestShadersWithSDRWhiteLevel(const ProgramKey& program_key,
261                                     float sdr_white_level) {
262     GLRenderer::DrawingFrame frame;
263     frame.display_color_spaces.SetSDRWhiteLevel(sdr_white_level);
264     TestShaderWithDrawingFrame(program_key, frame, false);
265   }
266 
TestBasicShaders()267   void TestBasicShaders() {
268     TestShader(ProgramKey::DebugBorder());
269     TestShader(ProgramKey::SolidColor(NO_AA, false, false));
270     TestShader(ProgramKey::SolidColor(USE_AA, false, false));
271     TestShader(ProgramKey::SolidColor(NO_AA, true, false));
272 
273     TestShadersWithOutputColorMatrix(ProgramKey::DebugBorder());
274     TestShadersWithOutputColorMatrix(
275         ProgramKey::SolidColor(NO_AA, false, false));
276     TestShadersWithOutputColorMatrix(
277         ProgramKey::SolidColor(USE_AA, false, false));
278     TestShadersWithOutputColorMatrix(
279         ProgramKey::SolidColor(NO_AA, true, false));
280 
281     TestShadersWithSDRWhiteLevel(ProgramKey::DebugBorder(), 200.f);
282     TestShadersWithSDRWhiteLevel(ProgramKey::SolidColor(NO_AA, false, false),
283                                  200.f);
284     TestShadersWithSDRWhiteLevel(ProgramKey::SolidColor(USE_AA, false, false),
285                                  200.f);
286     TestShadersWithSDRWhiteLevel(ProgramKey::SolidColor(NO_AA, true, false),
287                                  200.f);
288   }
289 
TestColorShaders()290   void TestColorShaders() {
291     const size_t kNumTransferFns = 7;
292     skcms_TransferFunction transfer_fns[kNumTransferFns] = {
293         // The identity.
294         {1.f, 1.f, 0.f, 1.f, 0.f, 0.f, 0.f},
295         // The identity, with an if statement.
296         {1.f, 1.f, 0.f, 1.f, 0.5f, 0.f, 0.f},
297         // Just the power function.
298         {1.1f, 1.f, 0.f, 1.f, 0.f, 0.f, 0.f},
299         // Everything but the power function, nonlinear only.
300         {1.f, 0.9f, 0.1f, 0.9f, 0.f, 0.1f, 0.1f},
301         // Everything, nonlinear only.
302         {1.1f, 0.9f, 0.1f, 0.9f, 0.f, 0.1f, 0.1f},
303         // Everything but the power function.
304         {1.f, 0.9f, 0.1f, 0.9f, 0.5f, 0.1f, 0.1f},
305         // Everything.
306         {1.1f, 0.9f, 0.1f, 0.9f, 0.5f, 0.1f, 0.1f},
307     };
308 
309     for (size_t i = 0; i < kNumTransferFns; ++i) {
310       skcms_Matrix3x3 primaries;
311       gfx::ColorSpace::CreateSRGB().GetPrimaryMatrix(&primaries);
312       gfx::ColorSpace src =
313           gfx::ColorSpace::CreateCustom(primaries, transfer_fns[i]);
314 
315       renderer()->SetCurrentFrameForTesting(GLRenderer::DrawingFrame());
316       renderer()->SetUseProgram(ProgramKey::SolidColor(NO_AA, false, false),
317                                 src, gfx::ColorSpace::CreateXYZD50());
318       EXPECT_TRUE(renderer()->current_program_->initialized());
319     }
320   }
321 
TestShadersWithPrecision(TexCoordPrecision precision)322   void TestShadersWithPrecision(TexCoordPrecision precision) {
323     // This program uses external textures and sampler, so it won't compile
324     // everywhere.
325     if (context_provider()->ContextCapabilities().egl_image_external) {
326       TestShader(ProgramKey::VideoStream(precision, false));
327     }
328   }
329 
TestShadersWithPrecisionAndBlend(TexCoordPrecision precision,BlendMode blend_mode)330   void TestShadersWithPrecisionAndBlend(TexCoordPrecision precision,
331                                         BlendMode blend_mode) {
332     TestShader(ProgramKey::RenderPass(precision, SAMPLER_TYPE_2D, blend_mode,
333                                       NO_AA, NO_MASK, false, false, false,
334                                       false));
335     TestShader(ProgramKey::RenderPass(precision, SAMPLER_TYPE_2D, blend_mode,
336                                       USE_AA, NO_MASK, false, false, false,
337                                       false));
338   }
339 
TestShadersWithPrecisionAndSampler(TexCoordPrecision precision,SamplerType sampler)340   void TestShadersWithPrecisionAndSampler(TexCoordPrecision precision,
341                                           SamplerType sampler) {
342     TestShader(ProgramKey::Texture(precision, sampler, PREMULTIPLIED_ALPHA,
343                                    false, true, false, false));
344     TestShader(ProgramKey::Texture(precision, sampler, PREMULTIPLIED_ALPHA,
345                                    false, false, false, false));
346     TestShader(ProgramKey::Texture(precision, sampler, PREMULTIPLIED_ALPHA,
347                                    true, true, false, false));
348     TestShader(ProgramKey::Texture(precision, sampler, PREMULTIPLIED_ALPHA,
349                                    true, false, false, false));
350     TestShader(ProgramKey::Texture(precision, sampler, NON_PREMULTIPLIED_ALPHA,
351                                    false, true, false, false));
352     TestShader(ProgramKey::Texture(precision, sampler, NON_PREMULTIPLIED_ALPHA,
353                                    false, false, false, false));
354     TestShader(ProgramKey::Texture(precision, sampler, NON_PREMULTIPLIED_ALPHA,
355                                    true, true, false, false));
356     TestShader(ProgramKey::Texture(precision, sampler, NON_PREMULTIPLIED_ALPHA,
357                                    true, false, false, false));
358 
359     TestShader(ProgramKey::Tile(precision, sampler, USE_AA, PREMULTIPLIED_ALPHA,
360                                 false, false, false, false));
361     TestShader(ProgramKey::Tile(precision, sampler, NO_AA, PREMULTIPLIED_ALPHA,
362                                 false, false, false, false));
363     TestShader(ProgramKey::Tile(precision, sampler, NO_AA, PREMULTIPLIED_ALPHA,
364                                 true, false, false, false));
365     TestShader(ProgramKey::Tile(precision, sampler, NO_AA, PREMULTIPLIED_ALPHA,
366                                 false, true, false, false));
367     TestShader(ProgramKey::Tile(precision, sampler, NO_AA, PREMULTIPLIED_ALPHA,
368                                 true, true, false, false));
369     TestShader(ProgramKey::Tile(precision, sampler, USE_AA,
370                                 NON_PREMULTIPLIED_ALPHA, false, false, false,
371                                 false));
372     TestShader(ProgramKey::Tile(precision, sampler, NO_AA,
373                                 NON_PREMULTIPLIED_ALPHA, false, false, false,
374                                 false));
375     TestShader(ProgramKey::Tile(precision, sampler, NO_AA,
376                                 NON_PREMULTIPLIED_ALPHA, true, false, false,
377                                 false));
378     TestShader(ProgramKey::Tile(precision, sampler, NO_AA,
379                                 NON_PREMULTIPLIED_ALPHA, false, true, false,
380                                 false));
381     TestShader(ProgramKey::Tile(precision, sampler, NO_AA,
382                                 NON_PREMULTIPLIED_ALPHA, true, true, false,
383                                 false));
384 
385     // Iterate over alpha plane and nv12 parameters.
386     UVTextureMode uv_modes[2] = {UV_TEXTURE_MODE_UV, UV_TEXTURE_MODE_U_V};
387     YUVAlphaTextureMode a_modes[2] = {YUV_NO_ALPHA_TEXTURE,
388                                       YUV_HAS_ALPHA_TEXTURE};
389     for (int j = 0; j < 2; j++) {
390       for (int k = 0; k < 2; k++) {
391         TestShader(ProgramKey::YUVVideo(precision, sampler, a_modes[j],
392                                         uv_modes[k], false, false));
393       }
394     }
395   }
396 
TestShadersWithMasks(TexCoordPrecision precision,SamplerType sampler,BlendMode blend_mode,bool mask_for_background)397   void TestShadersWithMasks(TexCoordPrecision precision,
398                             SamplerType sampler,
399                             BlendMode blend_mode,
400                             bool mask_for_background) {
401     TestShader(ProgramKey::RenderPass(precision, sampler, blend_mode, NO_AA,
402                                       HAS_MASK, mask_for_background, false,
403                                       false, false));
404     TestShader(ProgramKey::RenderPass(precision, sampler, blend_mode, NO_AA,
405                                       HAS_MASK, mask_for_background, true,
406                                       false, false));
407     TestShader(ProgramKey::RenderPass(precision, sampler, blend_mode, USE_AA,
408                                       HAS_MASK, mask_for_background, false,
409                                       false, false));
410     TestShader(ProgramKey::RenderPass(precision, sampler, blend_mode, USE_AA,
411                                       HAS_MASK, mask_for_background, true,
412                                       false, false));
413   }
414 };
415 
416 namespace {
417 
418 #if !defined(OS_ANDROID)
419 static const TexCoordPrecision kPrecisionList[] = {TEX_COORD_PRECISION_MEDIUM,
420                                                    TEX_COORD_PRECISION_HIGH};
421 
422 static const BlendMode kBlendModeList[LAST_BLEND_MODE + 1] = {
423     BLEND_MODE_NONE,       BLEND_MODE_NORMAL,      BLEND_MODE_DESTINATION_IN,
424     BLEND_MODE_SCREEN,     BLEND_MODE_OVERLAY,     BLEND_MODE_DARKEN,
425     BLEND_MODE_LIGHTEN,    BLEND_MODE_COLOR_DODGE, BLEND_MODE_COLOR_BURN,
426     BLEND_MODE_HARD_LIGHT, BLEND_MODE_SOFT_LIGHT,  BLEND_MODE_DIFFERENCE,
427     BLEND_MODE_EXCLUSION,  BLEND_MODE_MULTIPLY,    BLEND_MODE_HUE,
428     BLEND_MODE_SATURATION, BLEND_MODE_COLOR,       BLEND_MODE_LUMINOSITY,
429 };
430 
431 static const SamplerType kSamplerList[] = {
432     SAMPLER_TYPE_2D, SAMPLER_TYPE_2D_RECT, SAMPLER_TYPE_EXTERNAL_OES,
433 };
434 
TEST_F(GLRendererShaderPixelTest,BasicShadersCompile)435 TEST_F(GLRendererShaderPixelTest, BasicShadersCompile) {
436   TestBasicShaders();
437 }
438 
TEST_F(GLRendererShaderPixelTest,TestColorShadersCompile)439 TEST_F(GLRendererShaderPixelTest, TestColorShadersCompile) {
440   TestColorShaders();
441 }
442 
443 class PrecisionShaderPixelTest
444     : public GLRendererShaderPixelTest,
445       public ::testing::WithParamInterface<TexCoordPrecision> {};
446 
TEST_P(PrecisionShaderPixelTest,ShadersCompile)447 TEST_P(PrecisionShaderPixelTest, ShadersCompile) {
448   TestShadersWithPrecision(GetParam());
449 }
450 
451 INSTANTIATE_TEST_SUITE_P(PrecisionShadersCompile,
452                          PrecisionShaderPixelTest,
453                          ::testing::ValuesIn(kPrecisionList));
454 
455 class PrecisionBlendShaderPixelTest
456     : public GLRendererShaderPixelTest,
457       public ::testing::WithParamInterface<
458           std::tuple<TexCoordPrecision, BlendMode>> {};
459 
TEST_P(PrecisionBlendShaderPixelTest,ShadersCompile)460 TEST_P(PrecisionBlendShaderPixelTest, ShadersCompile) {
461   TestShadersWithPrecisionAndBlend(std::get<0>(GetParam()),
462                                    std::get<1>(GetParam()));
463 }
464 
465 INSTANTIATE_TEST_SUITE_P(
466     PrecisionBlendShadersCompile,
467     PrecisionBlendShaderPixelTest,
468     ::testing::Combine(::testing::ValuesIn(kPrecisionList),
469                        ::testing::ValuesIn(kBlendModeList)));
470 
471 class PrecisionSamplerShaderPixelTest
472     : public GLRendererShaderPixelTest,
473       public ::testing::WithParamInterface<
474           std::tuple<TexCoordPrecision, SamplerType>> {};
475 
TEST_P(PrecisionSamplerShaderPixelTest,ShadersCompile)476 TEST_P(PrecisionSamplerShaderPixelTest, ShadersCompile) {
477   TestShadersWithPrecisionAndSampler(std::get<0>(GetParam()),
478                                      std::get<1>(GetParam()));
479 }
480 
481 INSTANTIATE_TEST_SUITE_P(PrecisionSamplerShadersCompile,
482                          PrecisionSamplerShaderPixelTest,
483                          ::testing::Combine(::testing::ValuesIn(kPrecisionList),
484                                             ::testing::ValuesIn(kSamplerList)));
485 
486 class MaskShaderPixelTest
487     : public GLRendererShaderPixelTest,
488       public ::testing::WithParamInterface<
489           std::tuple<TexCoordPrecision, SamplerType, BlendMode, bool>> {};
490 
TEST_P(MaskShaderPixelTest,ShadersCompile)491 TEST_P(MaskShaderPixelTest, ShadersCompile) {
492   TestShadersWithMasks(std::get<0>(GetParam()), std::get<1>(GetParam()),
493                        std::get<2>(GetParam()), std::get<3>(GetParam()));
494 }
495 
496 INSTANTIATE_TEST_SUITE_P(MaskShadersCompile,
497                          MaskShaderPixelTest,
498                          ::testing::Combine(::testing::ValuesIn(kPrecisionList),
499                                             ::testing::ValuesIn(kSamplerList),
500                                             ::testing::ValuesIn(kBlendModeList),
501                                             ::testing::Bool()));
502 
503 #endif
504 
505 class FakeRendererGL : public GLRenderer {
506  public:
FakeRendererGL(const RendererSettings * settings,OutputSurface * output_surface,DisplayResourceProvider * resource_provider)507   FakeRendererGL(const RendererSettings* settings,
508                  OutputSurface* output_surface,
509                  DisplayResourceProvider* resource_provider)
510       : GLRenderer(settings,
511                    output_surface,
512                    resource_provider,
513                    nullptr,
514                    nullptr) {}
515 
FakeRendererGL(const RendererSettings * settings,OutputSurface * output_surface,DisplayResourceProvider * resource_provider,OverlayProcessorInterface * overlay_processor)516   FakeRendererGL(const RendererSettings* settings,
517                  OutputSurface* output_surface,
518                  DisplayResourceProvider* resource_provider,
519                  OverlayProcessorInterface* overlay_processor)
520       : GLRenderer(settings,
521                    output_surface,
522                    resource_provider,
523                    overlay_processor,
524                    nullptr) {}
525 
FakeRendererGL(const RendererSettings * settings,OutputSurface * output_surface,DisplayResourceProvider * resource_provider,OverlayProcessorInterface * overlay_processor,scoped_refptr<base::SingleThreadTaskRunner> current_task_runner)526   FakeRendererGL(
527       const RendererSettings* settings,
528       OutputSurface* output_surface,
529       DisplayResourceProvider* resource_provider,
530       OverlayProcessorInterface* overlay_processor,
531       scoped_refptr<base::SingleThreadTaskRunner> current_task_runner)
532       : GLRenderer(settings,
533                    output_surface,
534                    resource_provider,
535                    overlay_processor,
536                    std::move(current_task_runner)) {}
537 
538   // GLRenderer methods.
539 
540   // Changing visibility to public.
541   using GLRenderer::stencil_enabled;
542 };
543 
544 class GLRendererWithDefaultHarnessTest : public GLRendererTest {
545  protected:
GLRendererWithDefaultHarnessTest()546   GLRendererWithDefaultHarnessTest() {
547     output_surface_ = FakeOutputSurface::Create3d();
548     output_surface_->BindToClient(&output_surface_client_);
549 
550     shared_bitmap_manager_ = std::make_unique<TestSharedBitmapManager>();
551     resource_provider_ = std::make_unique<DisplayResourceProvider>(
552         DisplayResourceProvider::kGpu, output_surface_->context_provider(),
553         shared_bitmap_manager_.get());
554     renderer_ = std::make_unique<FakeRendererGL>(
555         &settings_, output_surface_.get(), resource_provider_.get());
556     renderer_->Initialize();
557     renderer_->SetVisible(true);
558   }
559 
SwapBuffers()560   void SwapBuffers() { renderer_->SwapBuffers({}); }
561 
562   RendererSettings settings_;
563   cc::FakeOutputSurfaceClient output_surface_client_;
564   std::unique_ptr<FakeOutputSurface> output_surface_;
565   std::unique_ptr<SharedBitmapManager> shared_bitmap_manager_;
566   std::unique_ptr<DisplayResourceProvider> resource_provider_;
567   std::unique_ptr<FakeRendererGL> renderer_;
568 };
569 
570 // Closing the namespace here so that GLRendererShaderTest can take advantage
571 // of the friend relationship with GLRenderer and all of the mock classes
572 // declared above it.
573 }  // namespace
574 
575 class GLRendererShaderTest : public GLRendererTest {
576  protected:
GLRendererShaderTest()577   GLRendererShaderTest() {
578     output_surface_ = FakeOutputSurface::Create3d();
579     output_surface_->BindToClient(&output_surface_client_);
580 
581     shared_bitmap_manager_ = std::make_unique<TestSharedBitmapManager>();
582     resource_provider_ = std::make_unique<DisplayResourceProvider>(
583         DisplayResourceProvider::kGpu, output_surface_->context_provider(),
584         shared_bitmap_manager_.get());
585     renderer_.reset(new FakeRendererGL(&settings_, output_surface_.get(),
586                                        resource_provider_.get(), nullptr));
587     renderer_->Initialize();
588     renderer_->SetVisible(true);
589 
590     child_context_provider_ = TestContextProvider::Create();
591     child_context_provider_->BindToCurrentThread();
592     child_resource_provider_ = std::make_unique<ClientResourceProvider>();
593   }
594 
~GLRendererShaderTest()595   ~GLRendererShaderTest() override {
596     child_resource_provider_->ShutdownAndReleaseAllResources();
597   }
598 
TestRenderPassProgram(TexCoordPrecision precision,BlendMode blend_mode)599   void TestRenderPassProgram(TexCoordPrecision precision,
600                              BlendMode blend_mode) {
601     const Program* program = renderer_->GetProgramIfInitialized(
602         ProgramKey::RenderPass(precision, SAMPLER_TYPE_2D, blend_mode, NO_AA,
603                                NO_MASK, false, false, false, false));
604     EXPECT_PROGRAM_VALID(program);
605     EXPECT_EQ(program, renderer_->current_program_);
606   }
607 
TestRenderPassColorMatrixProgram(TexCoordPrecision precision,BlendMode blend_mode)608   void TestRenderPassColorMatrixProgram(TexCoordPrecision precision,
609                                         BlendMode blend_mode) {
610     const Program* program = renderer_->GetProgramIfInitialized(
611         ProgramKey::RenderPass(precision, SAMPLER_TYPE_2D, blend_mode, NO_AA,
612                                NO_MASK, false, true, false, false));
613     EXPECT_PROGRAM_VALID(program);
614     EXPECT_EQ(program, renderer_->current_program_);
615   }
616 
TestRenderPassMaskProgram(TexCoordPrecision precision,SamplerType sampler,BlendMode blend_mode)617   void TestRenderPassMaskProgram(TexCoordPrecision precision,
618                                  SamplerType sampler,
619                                  BlendMode blend_mode) {
620     const Program* program = renderer_->GetProgramIfInitialized(
621         ProgramKey::RenderPass(precision, sampler, blend_mode, NO_AA, HAS_MASK,
622                                false, false, false, false));
623     EXPECT_PROGRAM_VALID(program);
624     EXPECT_EQ(program, renderer_->current_program_);
625   }
626 
TestRenderPassMaskColorMatrixProgram(TexCoordPrecision precision,SamplerType sampler,BlendMode blend_mode)627   void TestRenderPassMaskColorMatrixProgram(TexCoordPrecision precision,
628                                             SamplerType sampler,
629                                             BlendMode blend_mode) {
630     const Program* program = renderer_->GetProgramIfInitialized(
631         ProgramKey::RenderPass(precision, sampler, blend_mode, NO_AA, HAS_MASK,
632                                false, true, false, false));
633     EXPECT_PROGRAM_VALID(program);
634     EXPECT_EQ(program, renderer_->current_program_);
635   }
636 
TestRenderPassProgramAA(TexCoordPrecision precision,BlendMode blend_mode)637   void TestRenderPassProgramAA(TexCoordPrecision precision,
638                                BlendMode blend_mode) {
639     const Program* program = renderer_->GetProgramIfInitialized(
640         ProgramKey::RenderPass(precision, SAMPLER_TYPE_2D, blend_mode, USE_AA,
641                                NO_MASK, false, false, false, false));
642     EXPECT_PROGRAM_VALID(program);
643     EXPECT_EQ(program, renderer_->current_program_);
644   }
645 
TestRenderPassColorMatrixProgramAA(TexCoordPrecision precision,BlendMode blend_mode)646   void TestRenderPassColorMatrixProgramAA(TexCoordPrecision precision,
647                                           BlendMode blend_mode) {
648     const Program* program = renderer_->GetProgramIfInitialized(
649         ProgramKey::RenderPass(precision, SAMPLER_TYPE_2D, blend_mode, USE_AA,
650                                NO_MASK, false, true, false, false));
651     EXPECT_PROGRAM_VALID(program);
652     EXPECT_EQ(program, renderer_->current_program_);
653   }
654 
TestRenderPassMaskProgramAA(TexCoordPrecision precision,SamplerType sampler,BlendMode blend_mode)655   void TestRenderPassMaskProgramAA(TexCoordPrecision precision,
656                                    SamplerType sampler,
657                                    BlendMode blend_mode) {
658     const Program* program = renderer_->GetProgramIfInitialized(
659         ProgramKey::RenderPass(precision, sampler, blend_mode, USE_AA, HAS_MASK,
660                                false, false, false, false));
661     EXPECT_PROGRAM_VALID(program);
662     EXPECT_EQ(program, renderer_->current_program_);
663   }
664 
TestRenderPassMaskColorMatrixProgramAA(TexCoordPrecision precision,SamplerType sampler,BlendMode blend_mode)665   void TestRenderPassMaskColorMatrixProgramAA(TexCoordPrecision precision,
666                                               SamplerType sampler,
667                                               BlendMode blend_mode) {
668     const Program* program = renderer_->GetProgramIfInitialized(
669         ProgramKey::RenderPass(precision, sampler, blend_mode, USE_AA, HAS_MASK,
670                                false, true, false, false));
671     EXPECT_PROGRAM_VALID(program);
672     EXPECT_EQ(program, renderer_->current_program_);
673   }
674 
TestSolidColorProgramAA()675   void TestSolidColorProgramAA() {
676     const Program* program = renderer_->GetProgramIfInitialized(
677         ProgramKey::SolidColor(USE_AA, false, false));
678     EXPECT_PROGRAM_VALID(program);
679     EXPECT_EQ(program, renderer_->current_program_);
680   }
681 
682   RendererSettings settings_;
683   cc::FakeOutputSurfaceClient output_surface_client_;
684   std::unique_ptr<FakeOutputSurface> output_surface_;
685   std::unique_ptr<SharedBitmapManager> shared_bitmap_manager_;
686   std::unique_ptr<DisplayResourceProvider> resource_provider_;
687   scoped_refptr<TestContextProvider> child_context_provider_;
688   std::unique_ptr<ClientResourceProvider> child_resource_provider_;
689   std::unique_ptr<FakeRendererGL> renderer_;
690 };
691 
692 namespace {
693 
TEST_F(GLRendererWithDefaultHarnessTest,ExternalStencil)694 TEST_F(GLRendererWithDefaultHarnessTest, ExternalStencil) {
695   gfx::Size viewport_size(1, 1);
696   EXPECT_FALSE(renderer_->stencil_enabled());
697 
698   output_surface_->set_has_external_stencil_test(true);
699 
700   RenderPass* root_pass = cc::AddRenderPass(
701       &render_passes_in_draw_order_, 1, gfx::Rect(viewport_size),
702       gfx::Transform(), cc::FilterOperations());
703   root_pass->has_transparent_background = false;
704 
705   DrawFrame(renderer_.get(), viewport_size);
706   EXPECT_TRUE(renderer_->stencil_enabled());
707 }
708 
TEST_F(GLRendererWithDefaultHarnessTest,TextureDrawQuadShaderPrecisionHigh)709 TEST_F(GLRendererWithDefaultHarnessTest, TextureDrawQuadShaderPrecisionHigh) {
710   // TestContextProvider, used inside FakeOuputSurfaceClient, redefines
711   // GetShaderPrecisionFormat() and sets the resolution of mediump with
712   // 10-bits (1024). So any value higher than 1024 should use highp.
713   // The goal is to make sure the fragment shaders used in DoDrawQuad() use
714   // the correct precision qualifier.
715 
716   const gfx::Size viewport_size(1, 1);
717   RenderPass* root_pass = cc::AddRenderPass(
718       &render_passes_in_draw_order_, 1, gfx::Rect(viewport_size),
719       gfx::Transform(), cc::FilterOperations());
720 
721   const bool needs_blending = false;
722   const bool premultiplied_alpha = false;
723   const bool flipped = false;
724   const bool nearest_neighbor = false;
725   const float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
726   const gfx::PointF uv_top_left(0, 0);
727   const gfx::PointF uv_bottom_right(1, 1);
728 
729   auto child_context_provider = TestContextProvider::Create();
730   child_context_provider->BindToCurrentThread();
731 
732   auto child_resource_provider = std::make_unique<ClientResourceProvider>();
733 
734   // Here is where the texture is created. Any value bigger than 1024 should use
735   // a highp.
736   auto transfer_resource = TransferableResource::MakeGL(
737       gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken(),
738       gfx::Size(1025, 1025), true);
739   ResourceId client_resource_id = child_resource_provider->ImportResource(
740       transfer_resource, SingleReleaseCallback::Create(base::DoNothing()));
741 
742   std::unordered_map<ResourceId, ResourceId> resource_map =
743       cc::SendResourceAndGetChildToParentMap(
744           {client_resource_id}, resource_provider_.get(),
745           child_resource_provider.get(), child_context_provider.get());
746   unsigned resource_id = resource_map[client_resource_id];
747 
748   // The values defined here should not alter the size of the already created
749   // texture.
750   TextureDrawQuad* overlay_quad =
751       root_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
752   SharedQuadState* shared_state = root_pass->CreateAndAppendSharedQuadState();
753   shared_state->SetAll(gfx::Transform(), gfx::Rect(viewport_size),
754                        gfx::Rect(1023, 1023), gfx::RRectF(),
755                        gfx::Rect(1023, 1023), false, false, 1,
756                        SkBlendMode::kSrcOver, 0);
757   overlay_quad->SetNew(shared_state, gfx::Rect(1023, 1023),
758                        gfx::Rect(1023, 1023), needs_blending, resource_id,
759                        premultiplied_alpha, uv_top_left, uv_bottom_right,
760                        SK_ColorTRANSPARENT, vertex_opacity, flipped,
761                        nearest_neighbor, /*secure_output_only=*/false,
762                        gfx::ProtectedVideoType::kClear);
763 
764   DrawFrame(renderer_.get(), viewport_size);
765 
766   TexCoordPrecision precision = get_cached_tex_coord_precision(renderer_.get());
767   EXPECT_EQ(precision, TEX_COORD_PRECISION_HIGH);
768 
769   child_resource_provider->ShutdownAndReleaseAllResources();
770 }
771 
TEST_F(GLRendererWithDefaultHarnessTest,TextureDrawQuadShaderPrecisionMedium)772 TEST_F(GLRendererWithDefaultHarnessTest, TextureDrawQuadShaderPrecisionMedium) {
773   // TestContextProvider, used inside FakeOuputSurfaceClient, redefines
774   // GetShaderPrecisionFormat() and sets the resolution of mediump with
775   // 10-bits (1024). So any value higher than 1024 should use highp.
776   // The goal is to make sure the fragment shaders used in DoDrawQuad() use
777   // the correct precision qualifier.
778 
779   const gfx::Size viewport_size(1, 1);
780   RenderPass* root_pass = cc::AddRenderPass(
781       &render_passes_in_draw_order_, 1, gfx::Rect(viewport_size),
782       gfx::Transform(), cc::FilterOperations());
783 
784   const bool needs_blending = false;
785   const bool premultiplied_alpha = false;
786   const bool flipped = false;
787   const bool nearest_neighbor = false;
788   const float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
789   const gfx::PointF uv_top_left(0, 0);
790   const gfx::PointF uv_bottom_right(1, 1);
791 
792   auto child_context_provider = TestContextProvider::Create();
793   child_context_provider->BindToCurrentThread();
794 
795   auto child_resource_provider = std::make_unique<ClientResourceProvider>();
796 
797   // Here is where the texture is created. Any value smaller than 1024 should
798   // use a mediump.
799   auto transfer_resource = TransferableResource::MakeGL(
800       gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken(),
801       gfx::Size(1023, 1023), true);
802   ResourceId client_resource_id = child_resource_provider->ImportResource(
803       transfer_resource, SingleReleaseCallback::Create(base::DoNothing()));
804 
805   std::unordered_map<ResourceId, ResourceId> resource_map =
806       cc::SendResourceAndGetChildToParentMap(
807           {client_resource_id}, resource_provider_.get(),
808           child_resource_provider.get(), child_context_provider.get());
809   unsigned resource_id = resource_map[client_resource_id];
810 
811   // The values defined here should not alter the size of the already created
812   // texture.
813   TextureDrawQuad* overlay_quad =
814       root_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
815   SharedQuadState* shared_state = root_pass->CreateAndAppendSharedQuadState();
816   shared_state->SetAll(gfx::Transform(), gfx::Rect(viewport_size),
817                        gfx::Rect(1025, 1025), gfx::RRectF(),
818                        gfx::Rect(1025, 1025), false, false, 1,
819                        SkBlendMode::kSrcOver, 0);
820   overlay_quad->SetNew(shared_state, gfx::Rect(1025, 1025),
821                        gfx::Rect(1025, 1025), needs_blending, resource_id,
822                        premultiplied_alpha, uv_top_left, uv_bottom_right,
823                        SK_ColorTRANSPARENT, vertex_opacity, flipped,
824                        nearest_neighbor, /*secure_output_only=*/false,
825                        gfx::ProtectedVideoType::kClear);
826 
827   DrawFrame(renderer_.get(), viewport_size);
828 
829   TexCoordPrecision precision = get_cached_tex_coord_precision(renderer_.get());
830   EXPECT_EQ(precision, TEX_COORD_PRECISION_MEDIUM);
831 
832   child_resource_provider->ShutdownAndReleaseAllResources();
833 }
834 
835 class ForbidSynchronousCallGLES2Interface : public TestGLES2Interface {
836  public:
837   ForbidSynchronousCallGLES2Interface() = default;
838 
GetAttachedShaders(GLuint program,GLsizei max_count,GLsizei * count,GLuint * shaders)839   void GetAttachedShaders(GLuint program,
840                           GLsizei max_count,
841                           GLsizei* count,
842                           GLuint* shaders) override {
843     ADD_FAILURE();
844   }
845 
GetAttribLocation(GLuint program,const GLchar * name)846   GLint GetAttribLocation(GLuint program, const GLchar* name) override {
847     ADD_FAILURE();
848     return 0;
849   }
850 
GetBooleanv(GLenum pname,GLboolean * value)851   void GetBooleanv(GLenum pname, GLboolean* value) override { ADD_FAILURE(); }
852 
GetBufferParameteriv(GLenum target,GLenum pname,GLint * value)853   void GetBufferParameteriv(GLenum target,
854                             GLenum pname,
855                             GLint* value) override {
856     ADD_FAILURE();
857   }
858 
GetError()859   GLenum GetError() override {
860     ADD_FAILURE();
861     return GL_NO_ERROR;
862   }
863 
GetFloatv(GLenum pname,GLfloat * value)864   void GetFloatv(GLenum pname, GLfloat* value) override { ADD_FAILURE(); }
865 
GetFramebufferAttachmentParameteriv(GLenum target,GLenum attachment,GLenum pname,GLint * value)866   void GetFramebufferAttachmentParameteriv(GLenum target,
867                                            GLenum attachment,
868                                            GLenum pname,
869                                            GLint* value) override {
870     ADD_FAILURE();
871   }
872 
GetIntegerv(GLenum pname,GLint * value)873   void GetIntegerv(GLenum pname, GLint* value) override {
874     if (pname == GL_MAX_TEXTURE_SIZE) {
875       // MAX_TEXTURE_SIZE is cached client side, so it's OK to query.
876       *value = 1024;
877     } else {
878       ADD_FAILURE();
879     }
880   }
881 
882   // We allow querying the shader compilation and program link status in debug
883   // mode, but not release.
GetProgramiv(GLuint program,GLenum pname,GLint * value)884   void GetProgramiv(GLuint program, GLenum pname, GLint* value) override {
885     ADD_FAILURE();
886   }
887 
GetShaderiv(GLuint shader,GLenum pname,GLint * value)888   void GetShaderiv(GLuint shader, GLenum pname, GLint* value) override {
889     ADD_FAILURE();
890   }
891 
GetRenderbufferParameteriv(GLenum target,GLenum pname,GLint * value)892   void GetRenderbufferParameteriv(GLenum target,
893                                   GLenum pname,
894                                   GLint* value) override {
895     ADD_FAILURE();
896   }
897 
GetShaderPrecisionFormat(GLenum shadertype,GLenum precisiontype,GLint * range,GLint * precision)898   void GetShaderPrecisionFormat(GLenum shadertype,
899                                 GLenum precisiontype,
900                                 GLint* range,
901                                 GLint* precision) override {
902     ADD_FAILURE();
903   }
904 
GetTexParameterfv(GLenum target,GLenum pname,GLfloat * value)905   void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* value) override {
906     ADD_FAILURE();
907   }
908 
GetTexParameteriv(GLenum target,GLenum pname,GLint * value)909   void GetTexParameteriv(GLenum target, GLenum pname, GLint* value) override {
910     ADD_FAILURE();
911   }
912 
GetUniformfv(GLuint program,GLint location,GLfloat * value)913   void GetUniformfv(GLuint program, GLint location, GLfloat* value) override {
914     ADD_FAILURE();
915   }
916 
GetUniformiv(GLuint program,GLint location,GLint * value)917   void GetUniformiv(GLuint program, GLint location, GLint* value) override {
918     ADD_FAILURE();
919   }
920 
GetUniformLocation(GLuint program,const GLchar * name)921   GLint GetUniformLocation(GLuint program, const GLchar* name) override {
922     ADD_FAILURE();
923     return 0;
924   }
925 
GetVertexAttribfv(GLuint index,GLenum pname,GLfloat * value)926   void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* value) override {
927     ADD_FAILURE();
928   }
929 
GetVertexAttribiv(GLuint index,GLenum pname,GLint * value)930   void GetVertexAttribiv(GLuint index, GLenum pname, GLint* value) override {
931     ADD_FAILURE();
932   }
933 
GetVertexAttribPointerv(GLuint index,GLenum pname,void ** pointer)934   void GetVertexAttribPointerv(GLuint index,
935                                GLenum pname,
936                                void** pointer) override {
937     ADD_FAILURE();
938   }
939 };
940 
TEST_F(GLRendererTest,InitializationDoesNotMakeSynchronousCalls)941 TEST_F(GLRendererTest, InitializationDoesNotMakeSynchronousCalls) {
942   auto gl_owned = std::make_unique<ForbidSynchronousCallGLES2Interface>();
943   auto provider = TestContextProvider::Create(std::move(gl_owned));
944   provider->BindToCurrentThread();
945 
946   cc::FakeOutputSurfaceClient output_surface_client;
947   std::unique_ptr<OutputSurface> output_surface(
948       FakeOutputSurface::Create3d(std::move(provider)));
949   output_surface->BindToClient(&output_surface_client);
950 
951   std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
952       std::make_unique<TestSharedBitmapManager>();
953   std::unique_ptr<DisplayResourceProvider> resource_provider =
954       std::make_unique<DisplayResourceProvider>(
955           DisplayResourceProvider::kGpu, output_surface->context_provider(),
956           shared_bitmap_manager.get());
957 
958   RendererSettings settings;
959   FakeRendererGL renderer(&settings, output_surface.get(),
960                           resource_provider.get());
961 }
962 
963 class LoseContextOnFirstGetGLES2Interface : public TestGLES2Interface {
964  public:
LoseContextOnFirstGetGLES2Interface()965   LoseContextOnFirstGetGLES2Interface() {}
966 
GetProgramiv(GLuint program,GLenum pname,GLint * value)967   void GetProgramiv(GLuint program, GLenum pname, GLint* value) override {
968     LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
969                         GL_INNOCENT_CONTEXT_RESET_ARB);
970     *value = 0;
971   }
972 
GetShaderiv(GLuint shader,GLenum pname,GLint * value)973   void GetShaderiv(GLuint shader, GLenum pname, GLint* value) override {
974     LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
975                         GL_INNOCENT_CONTEXT_RESET_ARB);
976     *value = 0;
977   }
978 };
979 
TEST_F(GLRendererTest,InitializationWithQuicklyLostContextDoesNotAssert)980 TEST_F(GLRendererTest, InitializationWithQuicklyLostContextDoesNotAssert) {
981   auto gl_owned = std::make_unique<LoseContextOnFirstGetGLES2Interface>();
982   auto provider = TestContextProvider::Create(std::move(gl_owned));
983   provider->BindToCurrentThread();
984 
985   cc::FakeOutputSurfaceClient output_surface_client;
986   std::unique_ptr<OutputSurface> output_surface(
987       FakeOutputSurface::Create3d(std::move(provider)));
988   output_surface->BindToClient(&output_surface_client);
989 
990   std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
991       std::make_unique<TestSharedBitmapManager>();
992   std::unique_ptr<DisplayResourceProvider> resource_provider =
993       std::make_unique<DisplayResourceProvider>(
994           DisplayResourceProvider::kGpu, output_surface->context_provider(),
995           shared_bitmap_manager.get());
996 
997   RendererSettings settings;
998   FakeRendererGL renderer(&settings, output_surface.get(),
999                           resource_provider.get());
1000 }
1001 
1002 class ClearCountingGLES2Interface : public TestGLES2Interface {
1003  public:
1004   ClearCountingGLES2Interface() = default;
1005 
1006   MOCK_METHOD3(DiscardFramebufferEXT,
1007                void(GLenum target,
1008                     GLsizei numAttachments,
1009                     const GLenum* attachments));
1010   MOCK_METHOD1(Clear, void(GLbitfield mask));
1011 };
1012 
TEST_F(GLRendererTest,OpaqueBackground)1013 TEST_F(GLRendererTest, OpaqueBackground) {
1014   auto gl_owned = std::make_unique<ClearCountingGLES2Interface>();
1015   gl_owned->set_have_discard_framebuffer(true);
1016 
1017   auto* gl = gl_owned.get();
1018 
1019   auto provider = TestContextProvider::Create(std::move(gl_owned));
1020   provider->BindToCurrentThread();
1021 
1022   cc::FakeOutputSurfaceClient output_surface_client;
1023   std::unique_ptr<OutputSurface> output_surface(
1024       FakeOutputSurface::Create3d(std::move(provider)));
1025   output_surface->BindToClient(&output_surface_client);
1026 
1027   std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
1028       std::make_unique<TestSharedBitmapManager>();
1029   std::unique_ptr<DisplayResourceProvider> resource_provider =
1030       std::make_unique<DisplayResourceProvider>(
1031           DisplayResourceProvider::kGpu, output_surface->context_provider(),
1032           shared_bitmap_manager.get());
1033 
1034   RendererSettings settings;
1035   FakeRendererGL renderer(&settings, output_surface.get(),
1036                           resource_provider.get());
1037   renderer.Initialize();
1038   renderer.SetVisible(true);
1039 
1040   gfx::Size viewport_size(1, 1);
1041   RenderPass* root_pass = cc::AddRenderPass(
1042       &render_passes_in_draw_order_, 1, gfx::Rect(viewport_size),
1043       gfx::Transform(), cc::FilterOperations());
1044   root_pass->has_transparent_background = false;
1045 
1046   // On DEBUG builds, render passes with opaque background clear to blue to
1047   // easily see regions that were not drawn on the screen.
1048   EXPECT_CALL(*gl, DiscardFramebufferEXT(GL_FRAMEBUFFER, _, _))
1049       .With(Args<2, 1>(ElementsAre(GL_COLOR_EXT)))
1050       .Times(1);
1051 #ifdef NDEBUG
1052   EXPECT_CALL(*gl, Clear(_)).Times(0);
1053 #else
1054   EXPECT_CALL(*gl, Clear(_)).Times(1);
1055 #endif
1056   DrawFrame(&renderer, viewport_size);
1057   Mock::VerifyAndClearExpectations(gl);
1058 }
1059 
TEST_F(GLRendererTest,TransparentBackground)1060 TEST_F(GLRendererTest, TransparentBackground) {
1061   auto gl_owned = std::make_unique<ClearCountingGLES2Interface>();
1062   auto* gl = gl_owned.get();
1063   gl_owned->set_have_discard_framebuffer(true);
1064 
1065   auto provider = TestContextProvider::Create(std::move(gl_owned));
1066   provider->BindToCurrentThread();
1067 
1068   cc::FakeOutputSurfaceClient output_surface_client;
1069   std::unique_ptr<OutputSurface> output_surface(
1070       FakeOutputSurface::Create3d(std::move(provider)));
1071   output_surface->BindToClient(&output_surface_client);
1072 
1073   std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
1074       std::make_unique<TestSharedBitmapManager>();
1075   std::unique_ptr<DisplayResourceProvider> resource_provider =
1076       std::make_unique<DisplayResourceProvider>(
1077           DisplayResourceProvider::kGpu, output_surface->context_provider(),
1078           shared_bitmap_manager.get());
1079 
1080   RendererSettings settings;
1081   FakeRendererGL renderer(&settings, output_surface.get(),
1082                           resource_provider.get());
1083   renderer.Initialize();
1084   renderer.SetVisible(true);
1085 
1086   gfx::Size viewport_size(1, 1);
1087   RenderPass* root_pass = cc::AddRenderPass(
1088       &render_passes_in_draw_order_, 1, gfx::Rect(viewport_size),
1089       gfx::Transform(), cc::FilterOperations());
1090   root_pass->has_transparent_background = true;
1091 
1092   EXPECT_CALL(*gl, DiscardFramebufferEXT(GL_FRAMEBUFFER, 1, _)).Times(1);
1093   EXPECT_CALL(*gl, Clear(_)).Times(1);
1094   DrawFrame(&renderer, viewport_size);
1095 
1096   Mock::VerifyAndClearExpectations(gl);
1097 }
1098 
TEST_F(GLRendererTest,OffscreenOutputSurface)1099 TEST_F(GLRendererTest, OffscreenOutputSurface) {
1100   auto gl_owned = std::make_unique<ClearCountingGLES2Interface>();
1101   auto* gl = gl_owned.get();
1102   gl_owned->set_have_discard_framebuffer(true);
1103 
1104   auto provider = TestContextProvider::Create(std::move(gl_owned));
1105   provider->BindToCurrentThread();
1106 
1107   cc::FakeOutputSurfaceClient output_surface_client;
1108   std::unique_ptr<OutputSurface> output_surface(
1109       FakeOutputSurface::CreateOffscreen(std::move(provider)));
1110   output_surface->BindToClient(&output_surface_client);
1111 
1112   std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
1113       std::make_unique<TestSharedBitmapManager>();
1114   std::unique_ptr<DisplayResourceProvider> resource_provider =
1115       std::make_unique<DisplayResourceProvider>(
1116           DisplayResourceProvider::kGpu, output_surface->context_provider(),
1117           shared_bitmap_manager.get());
1118 
1119   RendererSettings settings;
1120   FakeRendererGL renderer(&settings, output_surface.get(),
1121                           resource_provider.get());
1122   renderer.Initialize();
1123   renderer.SetVisible(true);
1124 
1125   gfx::Size viewport_size(1, 1);
1126   cc::AddRenderPass(&render_passes_in_draw_order_, 1, gfx::Rect(viewport_size),
1127                     gfx::Transform(), cc::FilterOperations());
1128 
1129   EXPECT_CALL(*gl, DiscardFramebufferEXT(GL_FRAMEBUFFER, _, _))
1130       .With(Args<2, 1>(ElementsAre(GL_COLOR_ATTACHMENT0)))
1131       .Times(1);
1132   EXPECT_CALL(*gl, Clear(_)).Times(AnyNumber());
1133   DrawFrame(&renderer, viewport_size);
1134   Mock::VerifyAndClearExpectations(gl);
1135 }
1136 
1137 class TextureStateTrackingGLES2Interface : public TestGLES2Interface {
1138  public:
TextureStateTrackingGLES2Interface()1139   TextureStateTrackingGLES2Interface() : active_texture_(GL_INVALID_ENUM) {}
1140 
1141   MOCK_METHOD1(WaitSyncTokenCHROMIUM, void(const GLbyte* sync_token));
1142   MOCK_METHOD3(TexParameteri, void(GLenum target, GLenum pname, GLint param));
1143   MOCK_METHOD4(
1144       DrawElements,
1145       void(GLenum mode, GLsizei count, GLenum type, const void* indices));
1146 
ActiveTexture(GLenum texture)1147   void ActiveTexture(GLenum texture) override {
1148     EXPECT_NE(texture, active_texture_);
1149     active_texture_ = texture;
1150   }
1151 
active_texture() const1152   GLenum active_texture() const { return active_texture_; }
1153 
1154  private:
1155   GLenum active_texture_;
1156 };
1157 
1158 #define EXPECT_FILTER_CALL(filter)                                          \
1159   EXPECT_CALL(*gl,                                                          \
1160               TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter)); \
1161   EXPECT_CALL(*gl, TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter));
1162 
TEST_F(GLRendererTest,ActiveTextureState)1163 TEST_F(GLRendererTest, ActiveTextureState) {
1164   auto child_gl_owned = std::make_unique<TextureStateTrackingGLES2Interface>();
1165   auto child_context_provider =
1166       TestContextProvider::Create(std::move(child_gl_owned));
1167   child_context_provider->BindToCurrentThread();
1168   auto child_resource_provider = std::make_unique<ClientResourceProvider>();
1169 
1170   auto gl_owned = std::make_unique<TextureStateTrackingGLES2Interface>();
1171   gl_owned->set_have_extension_egl_image(true);
1172   auto* gl = gl_owned.get();
1173 
1174   auto provider = TestContextProvider::Create(std::move(gl_owned));
1175   provider->BindToCurrentThread();
1176 
1177   cc::FakeOutputSurfaceClient output_surface_client;
1178   std::unique_ptr<OutputSurface> output_surface(
1179       FakeOutputSurface::Create3d(std::move(provider)));
1180   output_surface->BindToClient(&output_surface_client);
1181 
1182   std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
1183       std::make_unique<TestSharedBitmapManager>();
1184   std::unique_ptr<DisplayResourceProvider> resource_provider =
1185       std::make_unique<DisplayResourceProvider>(
1186           DisplayResourceProvider::kGpu, output_surface->context_provider(),
1187           shared_bitmap_manager.get());
1188 
1189   RendererSettings settings;
1190   FakeRendererGL renderer(&settings, output_surface.get(),
1191                           resource_provider.get());
1192   renderer.Initialize();
1193   renderer.SetVisible(true);
1194 
1195   // During initialization we are allowed to set any texture parameters.
1196   EXPECT_CALL(*gl, TexParameteri(_, _, _)).Times(AnyNumber());
1197 
1198   RenderPass* root_pass =
1199       cc::AddRenderPass(&render_passes_in_draw_order_, 1, gfx::Rect(100, 100),
1200                         gfx::Transform(), cc::FilterOperations());
1201   gpu::SyncToken mailbox_sync_token;
1202   cc::AddOneOfEveryQuadTypeInDisplayResourceProvider(
1203       root_pass, resource_provider.get(), child_resource_provider.get(),
1204       child_context_provider.get(), 0, &mailbox_sync_token);
1205 
1206   EXPECT_EQ(12u, resource_provider->num_resources());
1207   renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1208 
1209   // Set up expected texture filter state transitions that match the quads
1210   // created in AppendOneOfEveryQuadType().
1211   Mock::VerifyAndClearExpectations(gl);
1212   {
1213     InSequence sequence;
1214     // The verified flush flag will be set by
1215     // ClientResourceProvider::PrepareSendToParent. Before checking if
1216     // the gpu::SyncToken matches, set this flag first.
1217     mailbox_sync_token.SetVerifyFlush();
1218     // In AddOneOfEveryQuadTypeInDisplayResourceProvider, resources are added
1219     // into RenderPass with the below order: resource6, resource1, resource8
1220     // (with mailbox), resource2, resource3, resource4, resource9, resource10,
1221     // resource11, resource12. resource8 has its own mailbox mailbox_sync_token.
1222     // The rest resources share a common default sync token.
1223     EXPECT_CALL(*gl, WaitSyncTokenCHROMIUM(_)).Times(2);
1224     EXPECT_CALL(*gl,
1225                 WaitSyncTokenCHROMIUM(MatchesSyncToken(mailbox_sync_token)))
1226         .Times(1);
1227     EXPECT_CALL(*gl, WaitSyncTokenCHROMIUM(_)).Times(7);
1228 
1229     // yuv_quad is drawn with the default linear filter.
1230     for (int i = 0; i < 4; ++i) {
1231       EXPECT_FILTER_CALL(GL_LINEAR);
1232     }
1233     EXPECT_CALL(*gl, DrawElements(_, _, _, _));
1234 
1235     // tile_quad is drawn with GL_NEAREST because it is not transformed or
1236     // scaled.
1237     EXPECT_FILTER_CALL(GL_NEAREST);
1238     EXPECT_CALL(*gl, DrawElements(_, _, _, _));
1239 
1240     // transformed tile_quad
1241     EXPECT_FILTER_CALL(GL_LINEAR);
1242     EXPECT_CALL(*gl, DrawElements(_, _, _, _));
1243 
1244     // scaled tile_quad
1245     EXPECT_FILTER_CALL(GL_LINEAR);
1246     EXPECT_CALL(*gl, DrawElements(_, _, _, _));
1247 
1248     // texture_quad without nearest neighbor
1249     EXPECT_FILTER_CALL(GL_LINEAR);
1250     EXPECT_CALL(*gl, DrawElements(_, _, _, _));
1251 
1252     // texture_quad without nearest neighbor
1253     EXPECT_FILTER_CALL(GL_LINEAR);
1254     EXPECT_CALL(*gl, DrawElements(_, _, _, _));
1255 
1256     // stream video, solid color and debug draw quads
1257     EXPECT_CALL(*gl, DrawElements(_, _, _, _)).Times(3);
1258   }
1259 
1260   gfx::Size viewport_size(100, 100);
1261   DrawFrame(&renderer, viewport_size);
1262   Mock::VerifyAndClearExpectations(gl);
1263 
1264   child_resource_provider->ShutdownAndReleaseAllResources();
1265 }
1266 
1267 class BufferSubDataTrackingGLES2Interface : public TestGLES2Interface {
1268  public:
1269   BufferSubDataTrackingGLES2Interface() = default;
1270   ~BufferSubDataTrackingGLES2Interface() override = default;
1271 
BufferSubData(GLenum target,GLintptr offset,GLsizeiptr size,const void * data)1272   void BufferSubData(GLenum target,
1273                      GLintptr offset,
1274                      GLsizeiptr size,
1275                      const void* data) override {
1276     if (target != GL_ARRAY_BUFFER)
1277       return;
1278     DCHECK_EQ(0, offset);
1279     last_array_data.resize(size);
1280     memcpy(last_array_data.data(), data, size);
1281   }
1282 
1283   std::vector<uint8_t> last_array_data;
1284 };
1285 
TEST_F(GLRendererTest,DrawYUVVideoDrawQuadWithVisibleRect)1286 TEST_F(GLRendererTest, DrawYUVVideoDrawQuadWithVisibleRect) {
1287   gfx::Size viewport_size(100, 100);
1288 
1289   auto mock_gl_owned = std::make_unique<BufferSubDataTrackingGLES2Interface>();
1290   BufferSubDataTrackingGLES2Interface* mock_gl = mock_gl_owned.get();
1291   auto provider = TestContextProvider::Create(std::move(mock_gl_owned));
1292   provider->BindToCurrentThread();
1293 
1294   cc::FakeOutputSurfaceClient output_surface_client;
1295   std::unique_ptr<OutputSurface> output_surface(
1296       FakeOutputSurface::Create3d(std::move(provider)));
1297   output_surface->BindToClient(&output_surface_client);
1298 
1299   std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
1300       std::make_unique<TestSharedBitmapManager>();
1301   std::unique_ptr<DisplayResourceProvider> resource_provider =
1302       std::make_unique<DisplayResourceProvider>(
1303           DisplayResourceProvider::kGpu, output_surface->context_provider(),
1304           shared_bitmap_manager.get());
1305 
1306   RendererSettings settings;
1307   FakeRendererGL renderer(&settings, output_surface.get(),
1308                           resource_provider.get());
1309   renderer.Initialize();
1310   renderer.SetVisible(true);
1311 
1312   RenderPass* root_pass = cc::AddRenderPass(
1313       &render_passes_in_draw_order_, 1, gfx::Rect(viewport_size),
1314       gfx::Transform(), cc::FilterOperations());
1315   root_pass->has_transparent_background = false;
1316 
1317   gfx::Rect rect(viewport_size);
1318   gfx::Rect visible_rect(rect);
1319   gfx::RectF tex_coord_rect(0, 0, 1, 1);
1320   visible_rect.Inset(10, 20, 30, 40);
1321 
1322   SharedQuadState* shared_state = root_pass->CreateAndAppendSharedQuadState();
1323   shared_state->SetAll(gfx::Transform(), gfx::Rect(), rect, gfx::RRectF(), rect,
1324                        false, false, 1, SkBlendMode::kSrcOver, 0);
1325 
1326   YUVVideoDrawQuad* quad =
1327       root_pass->CreateAndAppendDrawQuad<YUVVideoDrawQuad>();
1328   quad->SetNew(shared_state, rect, visible_rect, /*needs_blending=*/false,
1329                tex_coord_rect, tex_coord_rect, rect.size(), rect.size(), 1, 1,
1330                1, 1, gfx::ColorSpace(), 0, 1.0, 8);
1331 
1332   DrawFrame(&renderer, viewport_size);
1333 
1334   ASSERT_EQ(96u, mock_gl->last_array_data.size());
1335   float* geometry_binding_vertexes =
1336       reinterpret_cast<float*>(mock_gl->last_array_data.data());
1337 
1338   const double kEpsilon = 1e-6;
1339   EXPECT_NEAR(-0.4f, geometry_binding_vertexes[0], kEpsilon);
1340   EXPECT_NEAR(-0.3f, geometry_binding_vertexes[1], kEpsilon);
1341   EXPECT_NEAR(0.1f, geometry_binding_vertexes[3], kEpsilon);
1342   EXPECT_NEAR(0.2f, geometry_binding_vertexes[4], kEpsilon);
1343 
1344   EXPECT_NEAR(0.2f, geometry_binding_vertexes[12], kEpsilon);
1345   EXPECT_NEAR(0.1f, geometry_binding_vertexes[13], kEpsilon);
1346   EXPECT_NEAR(0.7f, geometry_binding_vertexes[15], kEpsilon);
1347   EXPECT_NEAR(0.6f, geometry_binding_vertexes[16], kEpsilon);
1348 }
1349 
1350 class NoClearRootRenderPassMockGLES2Interface : public TestGLES2Interface {
1351  public:
1352   MOCK_METHOD1(Clear, void(GLbitfield mask));
1353   MOCK_METHOD4(
1354       DrawElements,
1355       void(GLenum mode, GLsizei count, GLenum type, const void* indices));
1356 };
1357 
TEST_F(GLRendererTest,ShouldClearRootRenderPass)1358 TEST_F(GLRendererTest, ShouldClearRootRenderPass) {
1359   auto mock_gl_owned =
1360       std::make_unique<NoClearRootRenderPassMockGLES2Interface>();
1361   NoClearRootRenderPassMockGLES2Interface* mock_gl = mock_gl_owned.get();
1362 
1363   auto provider = TestContextProvider::Create(std::move(mock_gl_owned));
1364   provider->BindToCurrentThread();
1365 
1366   cc::FakeOutputSurfaceClient output_surface_client;
1367   std::unique_ptr<OutputSurface> output_surface(
1368       FakeOutputSurface::Create3d(std::move(provider)));
1369   output_surface->BindToClient(&output_surface_client);
1370 
1371   std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
1372       std::make_unique<TestSharedBitmapManager>();
1373   std::unique_ptr<DisplayResourceProvider> resource_provider =
1374       std::make_unique<DisplayResourceProvider>(
1375           DisplayResourceProvider::kGpu, output_surface->context_provider(),
1376           shared_bitmap_manager.get());
1377 
1378   RendererSettings settings;
1379   settings.should_clear_root_render_pass = false;
1380 
1381   FakeRendererGL renderer(&settings, output_surface.get(),
1382                           resource_provider.get());
1383   renderer.Initialize();
1384   renderer.SetVisible(true);
1385 
1386   gfx::Size viewport_size(10, 10);
1387 
1388   int child_pass_id = 2;
1389   RenderPass* child_pass = cc::AddRenderPass(
1390       &render_passes_in_draw_order_, child_pass_id, gfx::Rect(viewport_size),
1391       gfx::Transform(), cc::FilterOperations());
1392   cc::AddQuad(child_pass, gfx::Rect(viewport_size), SK_ColorBLUE);
1393 
1394   int root_pass_id = 1;
1395   RenderPass* root_pass = cc::AddRenderPass(
1396       &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
1397       gfx::Transform(), cc::FilterOperations());
1398   cc::AddQuad(root_pass, gfx::Rect(viewport_size), SK_ColorGREEN);
1399 
1400   cc::AddRenderPassQuad(root_pass, child_pass);
1401 
1402 #ifdef NDEBUG
1403   GLint clear_bits = GL_COLOR_BUFFER_BIT;
1404 #else
1405   GLint clear_bits = GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
1406 #endif
1407 
1408   // First render pass is not the root one, clearing should happen.
1409   EXPECT_CALL(*mock_gl, Clear(clear_bits)).Times(AtLeast(1));
1410 
1411   Expectation first_render_pass =
1412       EXPECT_CALL(*mock_gl, DrawElements(_, _, _, _)).Times(1);
1413 
1414   // The second render pass is the root one, clearing should be prevented.
1415   EXPECT_CALL(*mock_gl, Clear(clear_bits)).Times(0).After(first_render_pass);
1416 
1417   EXPECT_CALL(*mock_gl, DrawElements(_, _, _, _))
1418       .Times(AnyNumber())
1419       .After(first_render_pass);
1420 
1421   renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1422   DrawFrame(&renderer, viewport_size);
1423 
1424   // In multiple render passes all but the root pass should clear the
1425   // framebuffer.
1426   Mock::VerifyAndClearExpectations(&mock_gl);
1427 }
1428 
1429 class ScissorTestOnClearCheckingGLES2Interface : public TestGLES2Interface {
1430  public:
1431   ScissorTestOnClearCheckingGLES2Interface() = default;
1432 
Clear(GLbitfield)1433   void Clear(GLbitfield) override { EXPECT_FALSE(scissor_enabled_); }
1434 
Enable(GLenum cap)1435   void Enable(GLenum cap) override {
1436     if (cap == GL_SCISSOR_TEST)
1437       scissor_enabled_ = true;
1438   }
1439 
Disable(GLenum cap)1440   void Disable(GLenum cap) override {
1441     if (cap == GL_SCISSOR_TEST)
1442       scissor_enabled_ = false;
1443   }
1444 
1445  private:
1446   bool scissor_enabled_ = false;
1447 };
1448 
TEST_F(GLRendererTest,ScissorTestWhenClearing)1449 TEST_F(GLRendererTest, ScissorTestWhenClearing) {
1450   auto gl_owned = std::make_unique<ScissorTestOnClearCheckingGLES2Interface>();
1451 
1452   auto provider = TestContextProvider::Create(std::move(gl_owned));
1453   provider->BindToCurrentThread();
1454 
1455   cc::FakeOutputSurfaceClient output_surface_client;
1456   std::unique_ptr<OutputSurface> output_surface(
1457       FakeOutputSurface::Create3d(std::move(provider)));
1458   output_surface->BindToClient(&output_surface_client);
1459 
1460   std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
1461       std::make_unique<TestSharedBitmapManager>();
1462   std::unique_ptr<DisplayResourceProvider> resource_provider =
1463       std::make_unique<DisplayResourceProvider>(
1464           DisplayResourceProvider::kGpu, output_surface->context_provider(),
1465           shared_bitmap_manager.get());
1466 
1467   RendererSettings settings;
1468   FakeRendererGL renderer(&settings, output_surface.get(),
1469                           resource_provider.get());
1470   renderer.Initialize();
1471   EXPECT_FALSE(renderer.use_partial_swap());
1472   renderer.SetVisible(true);
1473 
1474   gfx::Size viewport_size(100, 100);
1475 
1476   gfx::Rect grand_child_rect(25, 25);
1477   int grand_child_pass_id = 3;
1478   RenderPass* grand_child_pass = cc::AddRenderPass(
1479       &render_passes_in_draw_order_, grand_child_pass_id, grand_child_rect,
1480       gfx::Transform(), cc::FilterOperations());
1481   cc::AddClippedQuad(grand_child_pass, grand_child_rect, SK_ColorYELLOW);
1482 
1483   gfx::Rect child_rect(50, 50);
1484   int child_pass_id = 2;
1485   RenderPass* child_pass =
1486       cc::AddRenderPass(&render_passes_in_draw_order_, child_pass_id,
1487                         child_rect, gfx::Transform(), cc::FilterOperations());
1488   cc::AddQuad(child_pass, child_rect, SK_ColorBLUE);
1489 
1490   int root_pass_id = 1;
1491   RenderPass* root_pass = cc::AddRenderPass(
1492       &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
1493       gfx::Transform(), cc::FilterOperations());
1494   cc::AddQuad(root_pass, gfx::Rect(viewport_size), SK_ColorGREEN);
1495 
1496   cc::AddRenderPassQuad(root_pass, child_pass);
1497   cc::AddRenderPassQuad(child_pass, grand_child_pass);
1498 
1499   renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1500   DrawFrame(&renderer, viewport_size);
1501 }
1502 
1503 class DiscardCheckingGLES2Interface : public TestGLES2Interface {
1504  public:
1505   DiscardCheckingGLES2Interface() = default;
1506 
DiscardFramebufferEXT(GLenum target,GLsizei numAttachments,const GLenum * attachments)1507   void DiscardFramebufferEXT(GLenum target,
1508                              GLsizei numAttachments,
1509                              const GLenum* attachments) override {
1510     ++discarded_;
1511   }
1512 
discarded() const1513   int discarded() const { return discarded_; }
reset_discarded()1514   void reset_discarded() { discarded_ = 0; }
1515 
1516  private:
1517   int discarded_ = 0;
1518 };
1519 
TEST_F(GLRendererTest,NoDiscardOnPartialUpdates)1520 TEST_F(GLRendererTest, NoDiscardOnPartialUpdates) {
1521   auto gl_owned = std::make_unique<DiscardCheckingGLES2Interface>();
1522   gl_owned->set_have_post_sub_buffer(true);
1523   gl_owned->set_have_discard_framebuffer(true);
1524 
1525   auto* gl = gl_owned.get();
1526 
1527   auto provider = TestContextProvider::Create(std::move(gl_owned));
1528   provider->BindToCurrentThread();
1529 
1530   cc::FakeOutputSurfaceClient output_surface_client;
1531   auto output_surface = FakeOutputSurface::Create3d(std::move(provider));
1532   output_surface->BindToClient(&output_surface_client);
1533 
1534   std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
1535       std::make_unique<TestSharedBitmapManager>();
1536   std::unique_ptr<DisplayResourceProvider> resource_provider =
1537       std::make_unique<DisplayResourceProvider>(
1538           DisplayResourceProvider::kGpu, output_surface->context_provider(),
1539           shared_bitmap_manager.get());
1540 
1541   RendererSettings settings;
1542   settings.partial_swap_enabled = true;
1543   FakeRendererGL renderer(&settings, output_surface.get(),
1544                           resource_provider.get());
1545   renderer.Initialize();
1546   EXPECT_TRUE(renderer.use_partial_swap());
1547   renderer.SetVisible(true);
1548 
1549   gfx::Size viewport_size(100, 100);
1550   {
1551     // Draw one black frame to make sure the output surface is reshaped before
1552     // testes.
1553     int root_pass_id = 1;
1554     RenderPass* root_pass = cc::AddRenderPass(
1555         &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
1556         gfx::Transform(), cc::FilterOperations());
1557     cc::AddQuad(root_pass, gfx::Rect(viewport_size), SK_ColorBLACK);
1558     root_pass->damage_rect = gfx::Rect(viewport_size);
1559 
1560     renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1561     DrawFrame(&renderer, viewport_size);
1562     gl->reset_discarded();
1563   }
1564   {
1565     // Partial frame, should not discard.
1566     int root_pass_id = 1;
1567     RenderPass* root_pass = cc::AddRenderPass(
1568         &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
1569         gfx::Transform(), cc::FilterOperations());
1570     cc::AddQuad(root_pass, gfx::Rect(viewport_size), SK_ColorGREEN);
1571     root_pass->damage_rect = gfx::Rect(2, 2, 3, 3);
1572 
1573     renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1574     DrawFrame(&renderer, viewport_size);
1575     EXPECT_EQ(0, gl->discarded());
1576     gl->reset_discarded();
1577   }
1578   {
1579     // Full frame, should discard.
1580     int root_pass_id = 1;
1581     RenderPass* root_pass = cc::AddRenderPass(
1582         &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
1583         gfx::Transform(), cc::FilterOperations());
1584     cc::AddQuad(root_pass, gfx::Rect(viewport_size), SK_ColorGREEN);
1585     root_pass->damage_rect = root_pass->output_rect;
1586 
1587     renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1588     DrawFrame(&renderer, viewport_size);
1589     EXPECT_EQ(1, gl->discarded());
1590     gl->reset_discarded();
1591   }
1592   {
1593     // Full frame, external scissor is set, should not discard.
1594     output_surface->set_has_external_stencil_test(true);
1595     int root_pass_id = 1;
1596     RenderPass* root_pass = cc::AddRenderPass(
1597         &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
1598         gfx::Transform(), cc::FilterOperations());
1599     cc::AddQuad(root_pass, gfx::Rect(viewport_size), SK_ColorGREEN);
1600     root_pass->damage_rect = root_pass->output_rect;
1601     root_pass->has_transparent_background = false;
1602 
1603     renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1604     DrawFrame(&renderer, viewport_size);
1605     EXPECT_EQ(0, gl->discarded());
1606     gl->reset_discarded();
1607     output_surface->set_has_external_stencil_test(false);
1608   }
1609 }
1610 
1611 class ResourceTrackingGLES2Interface : public TestGLES2Interface {
1612  public:
1613   ResourceTrackingGLES2Interface() = default;
~ResourceTrackingGLES2Interface()1614   ~ResourceTrackingGLES2Interface() override { CheckNoResources(); }
1615 
CheckNoResources()1616   void CheckNoResources() {
1617     EXPECT_TRUE(textures_.empty());
1618     EXPECT_TRUE(buffers_.empty());
1619     EXPECT_TRUE(framebuffers_.empty());
1620     EXPECT_TRUE(renderbuffers_.empty());
1621     EXPECT_TRUE(queries_.empty());
1622     EXPECT_TRUE(shaders_.empty());
1623     EXPECT_TRUE(programs_.empty());
1624   }
1625 
GenTextures(GLsizei n,GLuint * textures)1626   void GenTextures(GLsizei n, GLuint* textures) override {
1627     GenIds(&textures_, n, textures);
1628   }
1629 
GenBuffers(GLsizei n,GLuint * buffers)1630   void GenBuffers(GLsizei n, GLuint* buffers) override {
1631     GenIds(&buffers_, n, buffers);
1632   }
1633 
GenFramebuffers(GLsizei n,GLuint * framebuffers)1634   void GenFramebuffers(GLsizei n, GLuint* framebuffers) override {
1635     GenIds(&framebuffers_, n, framebuffers);
1636   }
1637 
GenRenderbuffers(GLsizei n,GLuint * renderbuffers)1638   void GenRenderbuffers(GLsizei n, GLuint* renderbuffers) override {
1639     GenIds(&renderbuffers_, n, renderbuffers);
1640   }
1641 
GenQueriesEXT(GLsizei n,GLuint * queries)1642   void GenQueriesEXT(GLsizei n, GLuint* queries) override {
1643     GenIds(&queries_, n, queries);
1644   }
1645 
CreateProgram()1646   GLuint CreateProgram() override { return GenId(&programs_); }
1647 
CreateShader(GLenum type)1648   GLuint CreateShader(GLenum type) override { return GenId(&shaders_); }
1649 
BindTexture(GLenum target,GLuint texture)1650   void BindTexture(GLenum target, GLuint texture) override {
1651     CheckId(&textures_, texture);
1652   }
1653 
BindBuffer(GLenum target,GLuint buffer)1654   void BindBuffer(GLenum target, GLuint buffer) override {
1655     CheckId(&buffers_, buffer);
1656   }
1657 
BindRenderbuffer(GLenum target,GLuint renderbuffer)1658   void BindRenderbuffer(GLenum target, GLuint renderbuffer) override {
1659     CheckId(&renderbuffers_, renderbuffer);
1660   }
1661 
BindFramebuffer(GLenum target,GLuint framebuffer)1662   void BindFramebuffer(GLenum target, GLuint framebuffer) override {
1663     CheckId(&framebuffers_, framebuffer);
1664   }
1665 
UseProgram(GLuint program)1666   void UseProgram(GLuint program) override { CheckId(&programs_, program); }
1667 
DeleteTextures(GLsizei n,const GLuint * textures)1668   void DeleteTextures(GLsizei n, const GLuint* textures) override {
1669     DeleteIds(&textures_, n, textures);
1670   }
1671 
DeleteBuffers(GLsizei n,const GLuint * buffers)1672   void DeleteBuffers(GLsizei n, const GLuint* buffers) override {
1673     DeleteIds(&buffers_, n, buffers);
1674   }
1675 
DeleteFramebuffers(GLsizei n,const GLuint * framebuffers)1676   void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers) override {
1677     DeleteIds(&framebuffers_, n, framebuffers);
1678   }
1679 
DeleteRenderbuffers(GLsizei n,const GLuint * renderbuffers)1680   void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) override {
1681     DeleteIds(&renderbuffers_, n, renderbuffers);
1682   }
1683 
DeleteQueriesEXT(GLsizei n,const GLuint * queries)1684   void DeleteQueriesEXT(GLsizei n, const GLuint* queries) override {
1685     DeleteIds(&queries_, n, queries);
1686   }
1687 
DeleteProgram(GLuint program)1688   void DeleteProgram(GLuint program) override { DeleteId(&programs_, program); }
1689 
DeleteShader(GLuint shader)1690   void DeleteShader(GLuint shader) override { DeleteId(&shaders_, shader); }
1691 
BufferData(GLenum target,GLsizeiptr size,const void * data,GLenum usage)1692   void BufferData(GLenum target,
1693                   GLsizeiptr size,
1694                   const void* data,
1695                   GLenum usage) override {}
1696 
1697  private:
GenId(std::set<GLuint> * resource_set)1698   GLuint GenId(std::set<GLuint>* resource_set) {
1699     GLuint id = next_id_++;
1700     resource_set->insert(id);
1701     return id;
1702   }
1703 
GenIds(std::set<GLuint> * resource_set,GLsizei n,GLuint * ids)1704   void GenIds(std::set<GLuint>* resource_set, GLsizei n, GLuint* ids) {
1705     for (GLsizei i = 0; i < n; ++i)
1706       ids[i] = GenId(resource_set);
1707   }
1708 
CheckId(std::set<GLuint> * resource_set,GLuint id)1709   void CheckId(std::set<GLuint>* resource_set, GLuint id) {
1710     if (id == 0)
1711       return;
1712     EXPECT_TRUE(resource_set->find(id) != resource_set->end());
1713   }
1714 
DeleteId(std::set<GLuint> * resource_set,GLuint id)1715   void DeleteId(std::set<GLuint>* resource_set, GLuint id) {
1716     if (id == 0)
1717       return;
1718     size_t num_erased = resource_set->erase(id);
1719     EXPECT_EQ(1u, num_erased);
1720   }
1721 
DeleteIds(std::set<GLuint> * resource_set,GLsizei n,const GLuint * ids)1722   void DeleteIds(std::set<GLuint>* resource_set, GLsizei n, const GLuint* ids) {
1723     for (GLsizei i = 0; i < n; ++i)
1724       DeleteId(resource_set, ids[i]);
1725   }
1726 
1727   GLuint next_id_ = 1;
1728   std::set<GLuint> textures_;
1729   std::set<GLuint> buffers_;
1730   std::set<GLuint> framebuffers_;
1731   std::set<GLuint> renderbuffers_;
1732   std::set<GLuint> queries_;
1733   std::set<GLuint> shaders_;
1734   std::set<GLuint> programs_;
1735 };
1736 
TEST_F(GLRendererTest,NoResourceLeak)1737 TEST_F(GLRendererTest, NoResourceLeak) {
1738   auto gl_owned = std::make_unique<ResourceTrackingGLES2Interface>();
1739   auto* gl = gl_owned.get();
1740 
1741   auto provider = TestContextProvider::Create(std::move(gl_owned));
1742   provider->BindToCurrentThread();
1743 
1744   cc::FakeOutputSurfaceClient output_surface_client;
1745   auto output_surface = FakeOutputSurface::Create3d(std::move(provider));
1746   output_surface->BindToClient(&output_surface_client);
1747 
1748   std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
1749       std::make_unique<TestSharedBitmapManager>();
1750   std::unique_ptr<DisplayResourceProvider> resource_provider =
1751       std::make_unique<DisplayResourceProvider>(
1752           DisplayResourceProvider::kGpu, output_surface->context_provider(),
1753           shared_bitmap_manager.get());
1754 
1755   {
1756     RendererSettings settings;
1757     FakeRendererGL renderer(&settings, output_surface.get(),
1758                             resource_provider.get());
1759     renderer.Initialize();
1760     renderer.SetVisible(true);
1761 
1762     gfx::Size viewport_size(100, 100);
1763 
1764     int root_pass_id = 1;
1765     RenderPass* root_pass = cc::AddRenderPass(
1766         &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
1767         gfx::Transform(), cc::FilterOperations());
1768     cc::AddQuad(root_pass, gfx::Rect(viewport_size), SK_ColorGREEN);
1769     root_pass->damage_rect = gfx::Rect(2, 2, 3, 3);
1770 
1771     renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1772     DrawFrame(&renderer, viewport_size);
1773   }
1774   gl->CheckNoResources();
1775 }
1776 
1777 class DrawElementsGLES2Interface : public TestGLES2Interface {
1778  public:
1779   MOCK_METHOD4(
1780       DrawElements,
1781       void(GLenum mode, GLsizei count, GLenum type, const void* indices));
1782 };
1783 
1784 class GLRendererSkipTest : public GLRendererTest {
1785  protected:
GLRendererSkipTest()1786   GLRendererSkipTest() {
1787     auto gl_owned = std::make_unique<StrictMock<DrawElementsGLES2Interface>>();
1788     gl_owned->set_have_post_sub_buffer(true);
1789     gl_ = gl_owned.get();
1790 
1791     auto provider = TestContextProvider::Create(std::move(gl_owned));
1792     provider->BindToCurrentThread();
1793 
1794     output_surface_ = FakeOutputSurface::Create3d(std::move(provider));
1795     output_surface_->BindToClient(&output_surface_client_);
1796 
1797     shared_bitmap_manager_ = std::make_unique<TestSharedBitmapManager>();
1798     resource_provider_ = std::make_unique<DisplayResourceProvider>(
1799         DisplayResourceProvider::kGpu, output_surface_->context_provider(),
1800         shared_bitmap_manager_.get());
1801     settings_.partial_swap_enabled = true;
1802     renderer_ = std::make_unique<FakeRendererGL>(
1803         &settings_, output_surface_.get(), resource_provider_.get());
1804     renderer_->Initialize();
1805     renderer_->SetVisible(true);
1806   }
1807 
DrawBlackFrame(const gfx::Size & viewport_size)1808   void DrawBlackFrame(const gfx::Size& viewport_size) {
1809     EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(1);
1810 
1811     int root_pass_id = 1;
1812     RenderPass* root_pass = cc::AddRenderPass(
1813         &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
1814         gfx::Transform(), cc::FilterOperations());
1815     root_pass->damage_rect = gfx::Rect(viewport_size);
1816     cc::AddQuad(root_pass, gfx::Rect(viewport_size), SK_ColorBLACK);
1817     renderer_->DecideRenderPassAllocationsForFrame(
1818         render_passes_in_draw_order_);
1819     DrawFrame(renderer_.get(), viewport_size);
1820     Mock::VerifyAndClearExpectations(gl_);
1821   }
1822 
1823   StrictMock<DrawElementsGLES2Interface>* gl_;
1824   RendererSettings settings_;
1825   cc::FakeOutputSurfaceClient output_surface_client_;
1826   std::unique_ptr<FakeOutputSurface> output_surface_;
1827   std::unique_ptr<SharedBitmapManager> shared_bitmap_manager_;
1828   std::unique_ptr<DisplayResourceProvider> resource_provider_;
1829   std::unique_ptr<FakeRendererGL> renderer_;
1830 };
1831 
TEST_F(GLRendererSkipTest,DrawQuad)1832 TEST_F(GLRendererSkipTest, DrawQuad) {
1833   gfx::Size viewport_size(100, 100);
1834   gfx::Rect quad_rect = gfx::Rect(20, 20, 20, 20);
1835 
1836   // Draw the a black frame to make sure output surface is reshaped before
1837   // tests.
1838   DrawBlackFrame(viewport_size);
1839 
1840   EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(1);
1841   int root_pass_id = 1;
1842   RenderPass* root_pass = cc::AddRenderPass(
1843       &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
1844       gfx::Transform(), cc::FilterOperations());
1845   root_pass->damage_rect = gfx::Rect(0, 0, 25, 25);
1846   cc::AddQuad(root_pass, quad_rect, SK_ColorGREEN);
1847 
1848   renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1849   DrawFrame(renderer_.get(), viewport_size);
1850 }
1851 
TEST_F(GLRendererSkipTest,SkipVisibleRect)1852 TEST_F(GLRendererSkipTest, SkipVisibleRect) {
1853   gfx::Size viewport_size(100, 100);
1854   gfx::Rect quad_rect = gfx::Rect(0, 0, 40, 40);
1855 
1856   // Draw the a black frame to make sure output surface is reshaped before
1857   // tests.
1858   DrawBlackFrame(viewport_size);
1859 
1860   int root_pass_id = 1;
1861   RenderPass* root_pass = cc::AddRenderPass(
1862       &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
1863       gfx::Transform(), cc::FilterOperations());
1864   root_pass->damage_rect = gfx::Rect(0, 0, 10, 10);
1865   cc::AddQuad(root_pass, quad_rect, SK_ColorGREEN);
1866   root_pass->shared_quad_state_list.front()->is_clipped = true;
1867   root_pass->shared_quad_state_list.front()->clip_rect =
1868       gfx::Rect(0, 0, 40, 40);
1869   root_pass->quad_list.front()->visible_rect = gfx::Rect(20, 20, 20, 20);
1870 
1871   renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1872   DrawFrame(renderer_.get(), viewport_size);
1873   // DrawElements should not be called because the visible rect is outside the
1874   // scissor, even though the clip rect and quad rect intersect the scissor.
1875 }
1876 
TEST_F(GLRendererSkipTest,SkipClippedQuads)1877 TEST_F(GLRendererSkipTest, SkipClippedQuads) {
1878   gfx::Size viewport_size(100, 100);
1879   gfx::Rect quad_rect = gfx::Rect(25, 25, 90, 90);
1880 
1881   // Draw the a black frame to make sure output surface is reshaped before
1882   // tests.
1883   DrawBlackFrame(viewport_size);
1884 
1885   int root_pass_id = 1;
1886 
1887   auto* root_pass = cc::AddRenderPass(&render_passes_in_draw_order_,
1888                                       root_pass_id, gfx::Rect(viewport_size),
1889                                       gfx::Transform(), cc::FilterOperations());
1890   root_pass->damage_rect = gfx::Rect(0, 0, 25, 25);
1891   cc::AddClippedQuad(root_pass, quad_rect, SK_ColorGREEN);
1892   root_pass->quad_list.front()->rect = gfx::Rect(20, 20, 20, 20);
1893 
1894   renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1895   DrawFrame(renderer_.get(), viewport_size);
1896   // DrawElements should not be called because the clip rect is outside the
1897   // scissor.
1898 }
1899 
TEST_F(GLRendererTest,DrawFramePreservesFramebuffer)1900 TEST_F(GLRendererTest, DrawFramePreservesFramebuffer) {
1901   // When using render-to-FBO to display the surface, all rendering is done
1902   // to a non-zero FBO. Make sure that the framebuffer is always restored to
1903   // the correct framebuffer during rendering, if changed.
1904   // Note: there is one path that will set it to 0, but that is after the render
1905   // has finished.
1906   cc::FakeOutputSurfaceClient output_surface_client;
1907   std::unique_ptr<FakeOutputSurface> output_surface(
1908       FakeOutputSurface::Create3d());
1909   output_surface->BindToClient(&output_surface_client);
1910 
1911   std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
1912       std::make_unique<TestSharedBitmapManager>();
1913   std::unique_ptr<DisplayResourceProvider> resource_provider =
1914       std::make_unique<DisplayResourceProvider>(
1915           DisplayResourceProvider::kGpu, output_surface->context_provider(),
1916           shared_bitmap_manager.get());
1917 
1918   RendererSettings settings;
1919   FakeRendererGL renderer(&settings, output_surface.get(),
1920                           resource_provider.get());
1921   renderer.Initialize();
1922   EXPECT_FALSE(renderer.use_partial_swap());
1923   renderer.SetVisible(true);
1924 
1925   gfx::Size viewport_size(100, 100);
1926   gfx::Rect quad_rect = gfx::Rect(20, 20, 20, 20);
1927 
1928   int root_pass_id = 1;
1929   RenderPass* root_pass = cc::AddRenderPass(
1930       &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
1931       gfx::Transform(), cc::FilterOperations());
1932   cc::AddClippedQuad(root_pass, quad_rect, SK_ColorGREEN);
1933 
1934   unsigned fbo;
1935   gpu::gles2::GLES2Interface* gl =
1936       output_surface->context_provider()->ContextGL();
1937   gl->GenFramebuffers(1, &fbo);
1938   output_surface->set_framebuffer(fbo, GL_RGB);
1939 
1940   renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1941   DrawFrame(&renderer, viewport_size);
1942 
1943   int bound_fbo;
1944   gl->GetIntegerv(GL_FRAMEBUFFER_BINDING, &bound_fbo);
1945   EXPECT_EQ(static_cast<int>(fbo), bound_fbo);
1946 }
1947 
TEST_F(GLRendererShaderTest,DrawRenderPassQuadShaderPermutations)1948 TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) {
1949   gfx::Size viewport_size(60, 75);
1950 
1951   gfx::Rect child_rect(50, 50);
1952   int child_pass_id = 2;
1953   RenderPass* child_pass;
1954 
1955   int root_pass_id = 1;
1956   RenderPass* root_pass;
1957 
1958   auto transfer_resource = TransferableResource::MakeGL(
1959       gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken(),
1960       child_rect.size(), false /* is_overlay_candidate */);
1961   ResourceId mask = child_resource_provider_->ImportResource(
1962       transfer_resource, SingleReleaseCallback::Create(base::DoNothing()));
1963 
1964   // Return the mapped resource id.
1965   std::unordered_map<ResourceId, ResourceId> resource_map =
1966       cc::SendResourceAndGetChildToParentMap({mask}, resource_provider_.get(),
1967                                              child_resource_provider_.get(),
1968                                              child_context_provider_.get());
1969   ResourceId mapped_mask = resource_map[mask];
1970 
1971   float matrix[20];
1972   float amount = 0.5f;
1973   matrix[0] = 0.213f + 0.787f * amount;
1974   matrix[1] = 0.715f - 0.715f * amount;
1975   matrix[2] = 1.f - (matrix[0] + matrix[1]);
1976   matrix[3] = matrix[4] = 0;
1977   matrix[5] = 0.213f - 0.213f * amount;
1978   matrix[6] = 0.715f + 0.285f * amount;
1979   matrix[7] = 1.f - (matrix[5] + matrix[6]);
1980   matrix[8] = matrix[9] = 0;
1981   matrix[10] = 0.213f - 0.213f * amount;
1982   matrix[11] = 0.715f - 0.715f * amount;
1983   matrix[12] = 1.f - (matrix[10] + matrix[11]);
1984   matrix[13] = matrix[14] = 0;
1985   matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0;
1986   matrix[18] = 1;
1987   cc::FilterOperations filters;
1988   filters.Append(cc::FilterOperation::CreateReferenceFilter(
1989       sk_make_sp<cc::ColorFilterPaintFilter>(SkColorFilters::Matrix(matrix),
1990                                              nullptr)));
1991 
1992   gfx::Transform transform_causing_aa;
1993   transform_causing_aa.Rotate(20.0);
1994 
1995   for (int i = 0; i <= LAST_BLEND_MODE; ++i) {
1996     BlendMode blend_mode = static_cast<BlendMode>(i);
1997     SkBlendMode xfer_mode = BlendModeToSkXfermode(blend_mode);
1998     settings_.force_blending_with_shaders = (blend_mode != BLEND_MODE_NONE);
1999     // RenderPassProgram
2000     render_passes_in_draw_order_.clear();
2001     child_pass =
2002         cc::AddRenderPass(&render_passes_in_draw_order_, child_pass_id,
2003                           child_rect, gfx::Transform(), cc::FilterOperations());
2004 
2005     root_pass = cc::AddRenderPass(&render_passes_in_draw_order_, root_pass_id,
2006                                   gfx::Rect(viewport_size), gfx::Transform(),
2007                                   cc::FilterOperations());
2008 
2009     cc::AddRenderPassQuad(root_pass, child_pass, 0, gfx::Transform(),
2010                           xfer_mode);
2011 
2012     renderer_->DecideRenderPassAllocationsForFrame(
2013         render_passes_in_draw_order_);
2014     DrawFrame(renderer_.get(), viewport_size);
2015     TestRenderPassProgram(TEX_COORD_PRECISION_MEDIUM, blend_mode);
2016 
2017     // RenderPassColorMatrixProgram
2018     render_passes_in_draw_order_.clear();
2019 
2020     child_pass = cc::AddRenderPass(&render_passes_in_draw_order_, child_pass_id,
2021                                    child_rect, transform_causing_aa, filters);
2022 
2023     root_pass = cc::AddRenderPass(&render_passes_in_draw_order_, root_pass_id,
2024                                   gfx::Rect(viewport_size), gfx::Transform(),
2025                                   cc::FilterOperations());
2026 
2027     cc::AddRenderPassQuad(root_pass, child_pass, 0, gfx::Transform(),
2028                           xfer_mode);
2029 
2030     renderer_->DecideRenderPassAllocationsForFrame(
2031         render_passes_in_draw_order_);
2032     DrawFrame(renderer_.get(), viewport_size);
2033     TestRenderPassColorMatrixProgram(TEX_COORD_PRECISION_MEDIUM, blend_mode);
2034 
2035     // RenderPassMaskProgram
2036     render_passes_in_draw_order_.clear();
2037 
2038     child_pass =
2039         cc::AddRenderPass(&render_passes_in_draw_order_, child_pass_id,
2040                           child_rect, gfx::Transform(), cc::FilterOperations());
2041 
2042     root_pass = cc::AddRenderPass(&render_passes_in_draw_order_, root_pass_id,
2043                                   gfx::Rect(viewport_size), gfx::Transform(),
2044                                   cc::FilterOperations());
2045 
2046     cc::AddRenderPassQuad(root_pass, child_pass, mapped_mask, gfx::Transform(),
2047                           xfer_mode);
2048 
2049     renderer_->DecideRenderPassAllocationsForFrame(
2050         render_passes_in_draw_order_);
2051     DrawFrame(renderer_.get(), viewport_size);
2052     TestRenderPassMaskProgram(TEX_COORD_PRECISION_MEDIUM, SAMPLER_TYPE_2D,
2053                               blend_mode);
2054 
2055     // RenderPassMaskColorMatrixProgram
2056     render_passes_in_draw_order_.clear();
2057 
2058     child_pass = cc::AddRenderPass(&render_passes_in_draw_order_, child_pass_id,
2059                                    child_rect, gfx::Transform(), filters);
2060 
2061     root_pass = cc::AddRenderPass(&render_passes_in_draw_order_, root_pass_id,
2062                                   gfx::Rect(viewport_size), gfx::Transform(),
2063                                   cc::FilterOperations());
2064 
2065     cc::AddRenderPassQuad(root_pass, child_pass, mapped_mask, gfx::Transform(),
2066                           xfer_mode);
2067 
2068     renderer_->DecideRenderPassAllocationsForFrame(
2069         render_passes_in_draw_order_);
2070     DrawFrame(renderer_.get(), viewport_size);
2071     TestRenderPassMaskColorMatrixProgram(TEX_COORD_PRECISION_MEDIUM,
2072                                          SAMPLER_TYPE_2D, blend_mode);
2073 
2074     // RenderPassProgramAA
2075     render_passes_in_draw_order_.clear();
2076 
2077     child_pass = cc::AddRenderPass(&render_passes_in_draw_order_, child_pass_id,
2078                                    child_rect, transform_causing_aa,
2079                                    cc::FilterOperations());
2080 
2081     root_pass = cc::AddRenderPass(&render_passes_in_draw_order_, root_pass_id,
2082                                   gfx::Rect(viewport_size), gfx::Transform(),
2083                                   cc::FilterOperations());
2084 
2085     cc::AddRenderPassQuad(root_pass, child_pass, 0, transform_causing_aa,
2086                           xfer_mode);
2087 
2088     renderer_->DecideRenderPassAllocationsForFrame(
2089         render_passes_in_draw_order_);
2090     DrawFrame(renderer_.get(), viewport_size);
2091     TestRenderPassProgramAA(TEX_COORD_PRECISION_MEDIUM, blend_mode);
2092 
2093     // RenderPassColorMatrixProgramAA
2094     render_passes_in_draw_order_.clear();
2095 
2096     child_pass = cc::AddRenderPass(&render_passes_in_draw_order_, child_pass_id,
2097                                    child_rect, transform_causing_aa, filters);
2098 
2099     root_pass = cc::AddRenderPass(&render_passes_in_draw_order_, root_pass_id,
2100                                   gfx::Rect(viewport_size), gfx::Transform(),
2101                                   cc::FilterOperations());
2102 
2103     cc::AddRenderPassQuad(root_pass, child_pass, 0, transform_causing_aa,
2104                           xfer_mode);
2105 
2106     renderer_->DecideRenderPassAllocationsForFrame(
2107         render_passes_in_draw_order_);
2108     DrawFrame(renderer_.get(), viewport_size);
2109     TestRenderPassColorMatrixProgramAA(TEX_COORD_PRECISION_MEDIUM, blend_mode);
2110 
2111     // RenderPassMaskProgramAA
2112     render_passes_in_draw_order_.clear();
2113 
2114     child_pass = cc::AddRenderPass(&render_passes_in_draw_order_, child_pass_id,
2115                                    child_rect, transform_causing_aa,
2116                                    cc::FilterOperations());
2117 
2118     root_pass = cc::AddRenderPass(&render_passes_in_draw_order_, root_pass_id,
2119                                   gfx::Rect(viewport_size), gfx::Transform(),
2120                                   cc::FilterOperations());
2121 
2122     cc::AddRenderPassQuad(root_pass, child_pass, mapped_mask,
2123                           transform_causing_aa, xfer_mode);
2124 
2125     renderer_->DecideRenderPassAllocationsForFrame(
2126         render_passes_in_draw_order_);
2127     DrawFrame(renderer_.get(), viewport_size);
2128     TestRenderPassMaskProgramAA(TEX_COORD_PRECISION_MEDIUM, SAMPLER_TYPE_2D,
2129                                 blend_mode);
2130 
2131     // RenderPassMaskColorMatrixProgramAA
2132     render_passes_in_draw_order_.clear();
2133 
2134     child_pass = cc::AddRenderPass(&render_passes_in_draw_order_, child_pass_id,
2135                                    child_rect, transform_causing_aa, filters);
2136 
2137     root_pass = cc::AddRenderPass(&render_passes_in_draw_order_, root_pass_id,
2138                                   gfx::Rect(viewport_size),
2139                                   transform_causing_aa, cc::FilterOperations());
2140 
2141     cc::AddRenderPassQuad(root_pass, child_pass, mapped_mask,
2142                           transform_causing_aa, xfer_mode);
2143 
2144     renderer_->DecideRenderPassAllocationsForFrame(
2145         render_passes_in_draw_order_);
2146     DrawFrame(renderer_.get(), viewport_size);
2147     TestRenderPassMaskColorMatrixProgramAA(TEX_COORD_PRECISION_MEDIUM,
2148                                            SAMPLER_TYPE_2D, blend_mode);
2149   }
2150 }
2151 
2152 // At this time, the AA code path cannot be taken if the surface's rect would
2153 // project incorrectly by the given transform, because of w<0 clipping.
TEST_F(GLRendererShaderTest,DrawRenderPassQuadSkipsAAForClippingTransform)2154 TEST_F(GLRendererShaderTest, DrawRenderPassQuadSkipsAAForClippingTransform) {
2155   gfx::Rect child_rect(50, 50);
2156   int child_pass_id = 2;
2157   RenderPass* child_pass;
2158 
2159   gfx::Size viewport_size(100, 100);
2160   int root_pass_id = 1;
2161   RenderPass* root_pass;
2162 
2163   gfx::Transform transform_preventing_aa;
2164   transform_preventing_aa.ApplyPerspectiveDepth(40.0);
2165   transform_preventing_aa.RotateAboutYAxis(-20.0);
2166   transform_preventing_aa.Scale(30.0, 1.0);
2167 
2168   // Verify that the test transform and test rect actually do cause the clipped
2169   // flag to trigger. Otherwise we are not testing the intended scenario.
2170   bool clipped = false;
2171   cc::MathUtil::MapQuad(transform_preventing_aa,
2172                         gfx::QuadF(gfx::RectF(child_rect)), &clipped);
2173   ASSERT_TRUE(clipped);
2174 
2175   child_pass = cc::AddRenderPass(&render_passes_in_draw_order_, child_pass_id,
2176                                  child_rect, transform_preventing_aa,
2177                                  cc::FilterOperations());
2178 
2179   root_pass = cc::AddRenderPass(&render_passes_in_draw_order_, root_pass_id,
2180                                 gfx::Rect(viewport_size), gfx::Transform(),
2181                                 cc::FilterOperations());
2182 
2183   cc::AddRenderPassQuad(root_pass, child_pass, 0, transform_preventing_aa,
2184                         SkBlendMode::kSrcOver);
2185 
2186   renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
2187   DrawFrame(renderer_.get(), viewport_size);
2188 
2189   // If use_aa incorrectly ignores clipping, it will use the
2190   // RenderPassProgramAA shader instead of the RenderPassProgram.
2191   TestRenderPassProgram(TEX_COORD_PRECISION_MEDIUM, BLEND_MODE_NONE);
2192 }
2193 
TEST_F(GLRendererShaderTest,DrawSolidColorShader)2194 TEST_F(GLRendererShaderTest, DrawSolidColorShader) {
2195   gfx::Size viewport_size(30, 30);  // Don't translate out of the viewport.
2196   gfx::Size quad_size(3, 3);
2197   int root_pass_id = 1;
2198   RenderPass* root_pass;
2199 
2200   gfx::Transform pixel_aligned_transform_causing_aa;
2201   pixel_aligned_transform_causing_aa.Translate(25.5f, 25.5f);
2202   pixel_aligned_transform_causing_aa.Scale(0.5f, 0.5f);
2203 
2204   root_pass = cc::AddRenderPass(&render_passes_in_draw_order_, root_pass_id,
2205                                 gfx::Rect(viewport_size), gfx::Transform(),
2206                                 cc::FilterOperations());
2207   cc::AddTransformedQuad(root_pass, gfx::Rect(quad_size), SK_ColorYELLOW,
2208                          pixel_aligned_transform_causing_aa);
2209 
2210   renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
2211   DrawFrame(renderer_.get(), viewport_size);
2212 
2213   TestSolidColorProgramAA();
2214 }
2215 
2216 class OutputSurfaceMockGLES2Interface : public TestGLES2Interface {
2217  public:
2218   OutputSurfaceMockGLES2Interface() = default;
2219 
2220   // Specifically override methods even if they are unused (used in conjunction
2221   // with StrictMock). We need to make sure that GLRenderer does not issue
2222   // framebuffer-related GLuint calls directly. Instead these are supposed to go
2223   // through the OutputSurface abstraction.
2224   MOCK_METHOD2(BindFramebuffer, void(GLenum target, GLuint framebuffer));
2225   MOCK_METHOD5(ResizeCHROMIUM,
2226                void(GLuint width,
2227                     GLuint height,
2228                     float device_scale,
2229                     GLcolorSpace color_space,
2230                     GLboolean has_alpha));
2231   MOCK_METHOD4(
2232       DrawElements,
2233       void(GLenum mode, GLsizei count, GLenum type, const void* indices));
2234 };
2235 
2236 class MockOutputSurface : public OutputSurface {
2237  public:
MockOutputSurface(scoped_refptr<ContextProvider> provider)2238   explicit MockOutputSurface(scoped_refptr<ContextProvider> provider)
2239       : OutputSurface(std::move(provider)) {}
~MockOutputSurface()2240   ~MockOutputSurface() override {}
2241 
BindToClient(OutputSurfaceClient *)2242   void BindToClient(OutputSurfaceClient*) override {}
UpdateGpuFence()2243   unsigned UpdateGpuFence() override { return 0; }
2244 
2245   MOCK_METHOD0(EnsureBackbuffer, void());
2246   MOCK_METHOD0(DiscardBackbuffer, void());
2247   MOCK_METHOD5(Reshape,
2248                void(const gfx::Size& size,
2249                     float scale_factor,
2250                     const gfx::ColorSpace& color_space,
2251                     gfx::BufferFormat format,
2252                     bool use_stencil));
2253   MOCK_METHOD0(BindFramebuffer, void());
2254   MOCK_METHOD1(SetDrawRectangle, void(const gfx::Rect&));
2255   MOCK_METHOD0(GetFramebufferCopyTextureFormat, GLenum());
2256   MOCK_METHOD1(SwapBuffers_, void(OutputSurfaceFrame& frame));  // NOLINT
SwapBuffers(OutputSurfaceFrame frame)2257   void SwapBuffers(OutputSurfaceFrame frame) override { SwapBuffers_(frame); }
2258   MOCK_CONST_METHOD0(IsDisplayedAsOverlayPlane, bool());
2259   MOCK_CONST_METHOD0(GetOverlayTextureId, unsigned());
2260   MOCK_CONST_METHOD0(HasExternalStencilTest, bool());
2261   MOCK_METHOD0(ApplyExternalStencil, void());
2262   MOCK_METHOD1(SetUpdateVSyncParametersCallback,
2263                void(UpdateVSyncParametersCallback));
2264   MOCK_METHOD1(SetDisplayTransformHint, void(gfx::OverlayTransform));
2265   MOCK_METHOD0(GetGpuTaskSchedulerHelper,
2266                scoped_refptr<gpu::GpuTaskSchedulerHelper>());
2267   MOCK_METHOD0(GetMemoryTracker, gpu::MemoryTracker*());
2268 
GetDisplayTransform()2269   gfx::OverlayTransform GetDisplayTransform() override {
2270     return gfx::OVERLAY_TRANSFORM_NONE;
2271   }
2272 };
2273 
2274 class MockOutputSurfaceTest : public GLRendererTest {
2275  protected:
SetUp()2276   void SetUp() override {
2277     auto gl = std::make_unique<StrictMock<OutputSurfaceMockGLES2Interface>>();
2278     gl->set_have_post_sub_buffer(true);
2279     gl_ = gl.get();
2280     auto provider = TestContextProvider::Create(std::move(gl));
2281     provider->BindToCurrentThread();
2282     output_surface_ =
2283         std::make_unique<StrictMock<MockOutputSurface>>(std::move(provider));
2284 
2285     cc::FakeOutputSurfaceClient output_surface_client_;
2286     output_surface_->BindToClient(&output_surface_client_);
2287 
2288     shared_bitmap_manager_ = std::make_unique<TestSharedBitmapManager>();
2289     resource_provider_ = std::make_unique<DisplayResourceProvider>(
2290         DisplayResourceProvider::kGpu, output_surface_->context_provider(),
2291         shared_bitmap_manager_.get());
2292 
2293     renderer_.reset(new FakeRendererGL(&settings_, output_surface_.get(),
2294                                        resource_provider_.get()));
2295     renderer_->Initialize();
2296 
2297     EXPECT_CALL(*output_surface_, EnsureBackbuffer()).Times(1);
2298     renderer_->SetVisible(true);
2299     Mock::VerifyAndClearExpectations(output_surface_.get());
2300   }
2301 
SwapBuffers()2302   void SwapBuffers() {
2303     renderer_->SwapBuffers(DirectRenderer::SwapFrameData());
2304   }
2305 
DrawFrame(float device_scale_factor,const gfx::Size & viewport_size,bool transparent)2306   void DrawFrame(float device_scale_factor,
2307                  const gfx::Size& viewport_size,
2308                  bool transparent) {
2309     gfx::BufferFormat format = transparent ? gfx::BufferFormat::RGBA_8888
2310                                            : gfx::BufferFormat::RGBX_8888;
2311     int render_pass_id = 1;
2312     RenderPass* render_pass = cc::AddRenderPass(
2313         &render_passes_in_draw_order_, render_pass_id, gfx::Rect(viewport_size),
2314         gfx::Transform(), cc::FilterOperations());
2315     cc::AddQuad(render_pass, gfx::Rect(viewport_size), SK_ColorGREEN);
2316     render_pass->has_transparent_background = transparent;
2317 
2318     EXPECT_CALL(*output_surface_, EnsureBackbuffer()).WillRepeatedly(Return());
2319 
2320     EXPECT_CALL(*output_surface_,
2321                 Reshape(viewport_size, device_scale_factor, _, format, _))
2322         .Times(1);
2323 
2324     EXPECT_CALL(*output_surface_, BindFramebuffer()).Times(1);
2325 
2326     EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(1);
2327 
2328     renderer_->DecideRenderPassAllocationsForFrame(
2329         render_passes_in_draw_order_);
2330     renderer_->DrawFrame(&render_passes_in_draw_order_, device_scale_factor,
2331                          viewport_size, gfx::DisplayColorSpaces());
2332   }
2333 
2334   RendererSettings settings_;
2335   cc::FakeOutputSurfaceClient output_surface_client_;
2336   OutputSurfaceMockGLES2Interface* gl_ = nullptr;
2337   std::unique_ptr<StrictMock<MockOutputSurface>> output_surface_;
2338   std::unique_ptr<SharedBitmapManager> shared_bitmap_manager_;
2339   std::unique_ptr<DisplayResourceProvider> resource_provider_;
2340   std::unique_ptr<FakeRendererGL> renderer_;
2341 };
2342 
TEST_F(MockOutputSurfaceTest,BackbufferDiscard)2343 TEST_F(MockOutputSurfaceTest, BackbufferDiscard) {
2344   // Drop backbuffer on hide.
2345   EXPECT_CALL(*output_surface_, DiscardBackbuffer()).Times(1);
2346   renderer_->SetVisible(false);
2347   Mock::VerifyAndClearExpectations(output_surface_.get());
2348 
2349   // Restore backbuffer on show.
2350   EXPECT_CALL(*output_surface_, EnsureBackbuffer()).Times(1);
2351   renderer_->SetVisible(true);
2352   Mock::VerifyAndClearExpectations(output_surface_.get());
2353 }
2354 
2355 #if defined(OS_WIN)
2356 class MockDCLayerOverlayProcessor : public DCLayerOverlayProcessor {
2357  public:
MockDCLayerOverlayProcessor()2358   MockDCLayerOverlayProcessor() : DCLayerOverlayProcessor() {}
2359   ~MockDCLayerOverlayProcessor() override = default;
2360   MOCK_METHOD5(Process,
2361                void(DisplayResourceProvider* resource_provider,
2362                     const gfx::RectF& display_rect,
2363                     RenderPassList* render_passes,
2364                     gfx::Rect* damage_rect,
2365                     DCLayerOverlayList* dc_layer_overlays));
2366 };
2367 class TestOverlayProcessor : public OverlayProcessorWin {
2368  public:
TestOverlayProcessor()2369   TestOverlayProcessor()
2370       : OverlayProcessorWin(true /* enable_dc_overlay */,
2371                             std::make_unique<MockDCLayerOverlayProcessor>()) {}
2372   ~TestOverlayProcessor() override = default;
2373 
GetTestProcessor()2374   MockDCLayerOverlayProcessor* GetTestProcessor() {
2375     return static_cast<MockDCLayerOverlayProcessor*>(GetOverlayProcessor());
2376   }
2377 };
2378 #elif defined(OS_MACOSX)
2379 class MockCALayerOverlayProcessor : public CALayerOverlayProcessor {
2380  public:
2381   MockCALayerOverlayProcessor() = default;
2382   ~MockCALayerOverlayProcessor() override = default;
2383 
2384   MOCK_CONST_METHOD6(
2385       ProcessForCALayerOverlays,
2386       bool(DisplayResourceProvider* resource_provider,
2387            const gfx::RectF& display_rect,
2388            const QuadList& quad_list,
2389            const base::flat_map<RenderPassId, cc::FilterOperations*>&
2390                render_pass_filters,
2391            const base::flat_map<RenderPassId, cc::FilterOperations*>&
2392                render_pass_backdrop_filters,
2393            CALayerOverlayList* ca_layer_overlays));
2394 };
2395 
2396 class TestOverlayProcessor : public OverlayProcessorMac {
2397  public:
TestOverlayProcessor()2398   TestOverlayProcessor()
2399       : OverlayProcessorMac(std::make_unique<MockCALayerOverlayProcessor>()) {}
2400   ~TestOverlayProcessor() override = default;
2401 
GetTestProcessor() const2402   const MockCALayerOverlayProcessor* GetTestProcessor() const {
2403     return static_cast<const MockCALayerOverlayProcessor*>(
2404         GetOverlayProcessor());
2405   }
2406 };
2407 
2408 #elif defined(OS_ANDROID) || defined(USE_OZONE)
2409 
2410 class TestOverlayProcessor : public OverlayProcessorUsingStrategy {
2411  public:
2412   class Strategy : public OverlayProcessorUsingStrategy::Strategy {
2413    public:
2414     Strategy() = default;
2415     ~Strategy() override = default;
2416 
2417     MOCK_METHOD7(
2418         Attempt,
2419         bool(const SkMatrix44& output_color_matrix,
2420              const OverlayProcessorInterface::FilterOperationsMap&
2421                  render_pass_backdrop_filters,
2422              DisplayResourceProvider* resource_provider,
2423              RenderPassList* render_pass_list,
2424              const OverlayProcessorInterface::OutputSurfaceOverlayPlane*
2425                  primary_surface,
2426              OverlayCandidateList* candidates,
2427              std::vector<gfx::Rect>* content_bounds));
2428   };
2429 
IsOverlaySupported() const2430   bool IsOverlaySupported() const override { return true; }
2431 
2432   // A list of possible overlay candidates is presented to this function.
2433   // The expected result is that those candidates that can be in a separate
2434   // plane are marked with |overlay_handled| set to true, otherwise they are
2435   // to be traditionally composited. Candidates with |overlay_handled| set to
2436   // true must also have their |display_rect| converted to integer
2437   // coordinates if necessary.
CheckOverlaySupport(const OverlayProcessorInterface::OutputSurfaceOverlayPlane * primary_plane,OverlayCandidateList * surfaces)2438   void CheckOverlaySupport(
2439       const OverlayProcessorInterface::OutputSurfaceOverlayPlane* primary_plane,
2440       OverlayCandidateList* surfaces) override {}
2441 
strategy()2442   Strategy& strategy() {
2443     auto* strategy = strategies_.back().get();
2444     return *(static_cast<Strategy*>(strategy));
2445   }
2446 
2447   MOCK_CONST_METHOD0(NeedsSurfaceOccludingDamageRect, bool());
TestOverlayProcessor()2448   TestOverlayProcessor() : OverlayProcessorUsingStrategy() {
2449     strategies_.push_back(std::make_unique<Strategy>());
2450   }
2451   ~TestOverlayProcessor() override = default;
2452 };
2453 #else  // Default to no overlay.
2454 class TestOverlayProcessor : public OverlayProcessorStub {
2455  public:
TestOverlayProcessor()2456   TestOverlayProcessor() : OverlayProcessorStub() {}
2457   ~TestOverlayProcessor() override = default;
2458 };
2459 #endif
2460 
MailboxReleased(const gpu::SyncToken & sync_token,bool lost_resource)2461 void MailboxReleased(const gpu::SyncToken& sync_token, bool lost_resource) {}
2462 
CollectResources(std::vector<ReturnedResource> * array,const std::vector<ReturnedResource> & returned)2463 static void CollectResources(std::vector<ReturnedResource>* array,
2464                              const std::vector<ReturnedResource>& returned) {
2465   array->insert(array->end(), returned.begin(), returned.end());
2466 }
2467 
TEST_F(GLRendererTest,DontOverlayWithCopyRequests)2468 TEST_F(GLRendererTest, DontOverlayWithCopyRequests) {
2469   cc::FakeOutputSurfaceClient output_surface_client;
2470   std::unique_ptr<FakeOutputSurface> output_surface(
2471       FakeOutputSurface::Create3d());
2472 #if defined(OS_WIN)
2473   output_surface->set_supports_dc_layers(true);
2474 #endif
2475   output_surface->BindToClient(&output_surface_client);
2476 
2477   std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
2478       std::make_unique<TestSharedBitmapManager>();
2479   auto parent_resource_provider = std::make_unique<DisplayResourceProvider>(
2480       DisplayResourceProvider::kGpu, output_surface->context_provider(),
2481       shared_bitmap_manager.get());
2482 
2483   auto child_context_provider = TestContextProvider::Create();
2484   child_context_provider->BindToCurrentThread();
2485   auto child_resource_provider = std::make_unique<ClientResourceProvider>();
2486 
2487   auto transfer_resource = TransferableResource::MakeGL(
2488       gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken(),
2489       gfx::Size(256, 256), true);
2490   auto release_callback =
2491       SingleReleaseCallback::Create(base::BindOnce(&MailboxReleased));
2492   ResourceId resource_id = child_resource_provider->ImportResource(
2493       transfer_resource, std::move(release_callback));
2494 
2495   std::vector<ReturnedResource> returned_to_child;
2496   int child_id = parent_resource_provider->CreateChild(
2497       base::BindRepeating(&CollectResources, &returned_to_child));
2498 
2499   // Transfer resource to the parent.
2500   std::vector<ResourceId> resource_ids_to_transfer;
2501   resource_ids_to_transfer.push_back(resource_id);
2502   std::vector<TransferableResource> list;
2503   child_resource_provider->PrepareSendToParent(
2504       resource_ids_to_transfer, &list,
2505       static_cast<RasterContextProvider*>(child_context_provider.get()));
2506   parent_resource_provider->ReceiveFromChild(child_id, list);
2507 
2508   // In DisplayResourceProvider's namespace, use the mapped resource id.
2509   std::unordered_map<ResourceId, ResourceId> resource_map =
2510       parent_resource_provider->GetChildToParentMap(child_id);
2511   ResourceId parent_resource_id = resource_map[list[0].id];
2512 
2513   RendererSettings settings;
2514   auto processor = std::make_unique<TestOverlayProcessor>();
2515   FakeRendererGL renderer(&settings, output_surface.get(),
2516                           parent_resource_provider.get(), processor.get(),
2517                           base::ThreadTaskRunnerHandle::Get());
2518   renderer.Initialize();
2519   renderer.SetVisible(true);
2520 
2521 #if defined(OS_MACOSX)
2522   const MockCALayerOverlayProcessor* mock_ca_processor =
2523       processor->GetTestProcessor();
2524 #elif defined(OS_WIN)
2525   MockDCLayerOverlayProcessor* dc_processor = processor->GetTestProcessor();
2526 #endif
2527 
2528   gfx::Size viewport_size(1, 1);
2529   RenderPass* root_pass = cc::AddRenderPass(
2530       &render_passes_in_draw_order_, 1, gfx::Rect(viewport_size),
2531       gfx::Transform(), cc::FilterOperations());
2532   root_pass->has_transparent_background = false;
2533   root_pass->copy_requests.push_back(CopyOutputRequest::CreateStubForTesting());
2534 
2535   bool needs_blending = false;
2536   bool premultiplied_alpha = false;
2537   bool flipped = false;
2538   bool nearest_neighbor = false;
2539   float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
2540 
2541   TextureDrawQuad* overlay_quad =
2542       root_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
2543   overlay_quad->SetNew(
2544       root_pass->CreateAndAppendSharedQuadState(), gfx::Rect(viewport_size),
2545       gfx::Rect(viewport_size), needs_blending, parent_resource_id,
2546       premultiplied_alpha, gfx::PointF(0, 0), gfx::PointF(1, 1),
2547       SK_ColorTRANSPARENT, vertex_opacity, flipped, nearest_neighbor,
2548       /*secure_output_only=*/false, gfx::ProtectedVideoType::kClear);
2549 
2550   // DirectRenderer::DrawFrame calls into OverlayProcessor::ProcessForOverlays.
2551   // Attempt will be called for each strategy in OverlayProcessor. We have
2552   // added a fake strategy, so checking for Attempt calls checks if there was
2553   // any attempt to overlay, which there shouldn't be. We can't use the quad
2554   // list because the render pass is cleaned up by DrawFrame.
2555 #if defined(USE_OZONE) || defined(OS_ANDROID)
2556   EXPECT_CALL(processor->strategy(), Attempt(_, _, _, _, _, _, _)).Times(0);
2557 #elif defined(OS_MACOSX)
2558   EXPECT_CALL(*mock_ca_processor, ProcessForCALayerOverlays(_, _, _, _, _, _))
2559       .Times(0);
2560 #elif defined(OS_WIN)
2561   EXPECT_CALL(*dc_processor, Process(_, _, _, _, _)).Times(0);
2562 #endif
2563   DrawFrame(&renderer, viewport_size);
2564 #if defined(USE_OZONE) || defined(OS_ANDROID)
2565   Mock::VerifyAndClearExpectations(&processor->strategy());
2566 #elif defined(OS_MACOSX)
2567   Mock::VerifyAndClearExpectations(
2568       const_cast<MockCALayerOverlayProcessor*>(mock_ca_processor));
2569 #elif defined(OS_WIN)
2570   Mock::VerifyAndClearExpectations(
2571       const_cast<MockDCLayerOverlayProcessor*>(dc_processor));
2572 #endif
2573 
2574   // Without a copy request Attempt() should be called once.
2575   root_pass = cc::AddRenderPass(&render_passes_in_draw_order_, 1,
2576                                 gfx::Rect(viewport_size), gfx::Transform(),
2577                                 cc::FilterOperations());
2578   root_pass->has_transparent_background = false;
2579 
2580   overlay_quad = root_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
2581   overlay_quad->SetNew(
2582       root_pass->CreateAndAppendSharedQuadState(), gfx::Rect(viewport_size),
2583       gfx::Rect(viewport_size), needs_blending, parent_resource_id,
2584       premultiplied_alpha, gfx::PointF(0, 0), gfx::PointF(1, 1),
2585       SK_ColorTRANSPARENT, vertex_opacity, flipped, nearest_neighbor,
2586       /*secure_output_only=*/false, gfx::ProtectedVideoType::kClear);
2587 #if defined(USE_OZONE) || defined(OS_ANDROID)
2588   EXPECT_CALL(processor->strategy(), Attempt(_, _, _, _, _, _, _)).Times(1);
2589 #elif defined(OS_MACOSX)
2590   EXPECT_CALL(*mock_ca_processor, ProcessForCALayerOverlays(_, _, _, _, _, _))
2591       .Times(1);
2592 #elif defined(OS_WIN)
2593   EXPECT_CALL(*dc_processor, Process(_, _, _, _, _)).Times(1);
2594 #endif
2595   DrawFrame(&renderer, viewport_size);
2596 
2597   // Transfer resources back from the parent to the child. Set no resources as
2598   // being in use.
2599   parent_resource_provider->DeclareUsedResourcesFromChild(child_id,
2600                                                           ResourceIdSet());
2601 
2602   child_resource_provider->RemoveImportedResource(resource_id);
2603   child_resource_provider->ShutdownAndReleaseAllResources();
2604 }
2605 
2606 #if defined(OS_ANDROID) || defined(USE_OZONE)
2607 class SingleOverlayOnTopProcessor : public OverlayProcessorUsingStrategy {
2608  public:
SingleOverlayOnTopProcessor()2609   SingleOverlayOnTopProcessor() : OverlayProcessorUsingStrategy() {
2610     strategies_.push_back(std::make_unique<OverlayStrategySingleOnTop>(this));
2611     strategies_.push_back(std::make_unique<OverlayStrategyUnderlay>(this));
2612   }
2613 
NeedsSurfaceOccludingDamageRect() const2614   bool NeedsSurfaceOccludingDamageRect() const override { return true; }
IsOverlaySupported() const2615   bool IsOverlaySupported() const override { return true; }
2616 
CheckOverlaySupport(const OverlayProcessorInterface::OutputSurfaceOverlayPlane * primary_plane,OverlayCandidateList * surfaces)2617   void CheckOverlaySupport(
2618       const OverlayProcessorInterface::OutputSurfaceOverlayPlane* primary_plane,
2619       OverlayCandidateList* surfaces) override {
2620     if (!multiple_candidates_)
2621       ASSERT_EQ(1U, surfaces->size());
2622     OverlayCandidate& candidate = surfaces->back();
2623     candidate.overlay_handled = true;
2624   }
2625 
AllowMultipleCandidates()2626   void AllowMultipleCandidates() { multiple_candidates_ = true; }
2627 
2628  private:
2629   bool multiple_candidates_ = false;
2630 };
2631 
2632 class WaitSyncTokenCountingGLES2Interface : public TestGLES2Interface {
2633  public:
2634   MOCK_METHOD1(WaitSyncTokenCHROMIUM, void(const GLbyte* sync_token));
2635 };
2636 
2637 class MockOverlayScheduler {
2638  public:
2639   MOCK_METHOD7(Schedule,
2640                void(int plane_z_order,
2641                     gfx::OverlayTransform plane_transform,
2642                     unsigned overlay_texture_id,
2643                     const gfx::Rect& display_bounds,
2644                     const gfx::RectF& uv_rect,
2645                     bool enable_blend,
2646                     unsigned gpu_fence_id));
2647 };
2648 
TEST_F(GLRendererTest,OverlaySyncTokensAreProcessed)2649 TEST_F(GLRendererTest, OverlaySyncTokensAreProcessed) {
2650   auto gl_owned = std::make_unique<WaitSyncTokenCountingGLES2Interface>();
2651   WaitSyncTokenCountingGLES2Interface* gl = gl_owned.get();
2652 
2653   auto provider = TestContextProvider::Create(std::move(gl_owned));
2654   provider->BindToCurrentThread();
2655 
2656   MockOverlayScheduler overlay_scheduler;
2657   provider->support()->SetScheduleOverlayPlaneCallback(base::BindRepeating(
2658       &MockOverlayScheduler::Schedule, base::Unretained(&overlay_scheduler)));
2659 
2660   cc::FakeOutputSurfaceClient output_surface_client;
2661   std::unique_ptr<OutputSurface> output_surface(
2662       FakeOutputSurface::Create3d(std::move(provider)));
2663   output_surface->BindToClient(&output_surface_client);
2664 
2665   std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
2666       std::make_unique<TestSharedBitmapManager>();
2667   auto parent_resource_provider = std::make_unique<DisplayResourceProvider>(
2668       DisplayResourceProvider::kGpu, output_surface->context_provider(),
2669       shared_bitmap_manager.get());
2670 
2671   auto child_context_provider = TestContextProvider::Create();
2672   child_context_provider->BindToCurrentThread();
2673   auto child_resource_provider = std::make_unique<ClientResourceProvider>();
2674 
2675   gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO,
2676                             gpu::CommandBufferId::FromUnsafeValue(0x123), 29);
2677   auto transfer_resource = TransferableResource::MakeGL(
2678       gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, sync_token,
2679       gfx::Size(256, 256), true);
2680   auto release_callback =
2681       SingleReleaseCallback::Create(base::BindOnce(&MailboxReleased));
2682   ResourceId resource_id = child_resource_provider->ImportResource(
2683       transfer_resource, std::move(release_callback));
2684 
2685   std::vector<ReturnedResource> returned_to_child;
2686   int child_id = parent_resource_provider->CreateChild(
2687       base::BindRepeating(&CollectResources, &returned_to_child));
2688 
2689   // Transfer resource to the parent.
2690   std::vector<ResourceId> resource_ids_to_transfer;
2691   resource_ids_to_transfer.push_back(resource_id);
2692   std::vector<TransferableResource> list;
2693   child_resource_provider->PrepareSendToParent(
2694       resource_ids_to_transfer, &list,
2695       static_cast<RasterContextProvider*>(child_context_provider.get()));
2696   parent_resource_provider->ReceiveFromChild(child_id, list);
2697 
2698   // In DisplayResourceProvider's namespace, use the mapped resource id.
2699   std::unordered_map<ResourceId, ResourceId> resource_map =
2700       parent_resource_provider->GetChildToParentMap(child_id);
2701   ResourceId parent_resource_id = resource_map[list[0].id];
2702 
2703   RendererSettings settings;
2704   auto processor = std::make_unique<SingleOverlayOnTopProcessor>();
2705   FakeRendererGL renderer(&settings, output_surface.get(),
2706                           parent_resource_provider.get(), processor.get(),
2707                           base::ThreadTaskRunnerHandle::Get());
2708   renderer.Initialize();
2709   renderer.SetVisible(true);
2710 
2711   gfx::Size viewport_size(1, 1);
2712   RenderPass* root_pass = cc::AddRenderPass(
2713       &render_passes_in_draw_order_, 1, gfx::Rect(viewport_size),
2714       gfx::Transform(), cc::FilterOperations());
2715   root_pass->has_transparent_background = false;
2716 
2717   bool needs_blending = false;
2718   bool premultiplied_alpha = false;
2719   bool flipped = false;
2720   bool nearest_neighbor = false;
2721   float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
2722   gfx::PointF uv_top_left(0, 0);
2723   gfx::PointF uv_bottom_right(1, 1);
2724 
2725   TextureDrawQuad* overlay_quad =
2726       root_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
2727   SharedQuadState* shared_state = root_pass->CreateAndAppendSharedQuadState();
2728   shared_state->SetAll(gfx::Transform(), gfx::Rect(viewport_size),
2729                        gfx::Rect(viewport_size), gfx::RRectF(),
2730                        gfx::Rect(viewport_size), false, false, 1,
2731                        SkBlendMode::kSrcOver, 0);
2732   overlay_quad->SetNew(shared_state, gfx::Rect(viewport_size),
2733                        gfx::Rect(viewport_size), needs_blending,
2734                        parent_resource_id, premultiplied_alpha, uv_top_left,
2735                        uv_bottom_right, SK_ColorTRANSPARENT, vertex_opacity,
2736                        flipped, nearest_neighbor, /*secure_output_only=*/false,
2737                        gfx::ProtectedVideoType::kClear);
2738 
2739   // The verified flush flag will be set by
2740   // ClientResourceProvider::PrepareSendToParent. Before checking if the
2741   // gpu::SyncToken matches, set this flag first.
2742   sync_token.SetVerifyFlush();
2743 
2744   // Verify that overlay_quad actually gets turned into an overlay, and even
2745   // though it's not drawn, that its sync point is waited on.
2746   EXPECT_CALL(*gl, WaitSyncTokenCHROMIUM(MatchesSyncToken(sync_token)))
2747       .Times(1);
2748 
2749   EXPECT_CALL(
2750       overlay_scheduler,
2751       Schedule(1, gfx::OVERLAY_TRANSFORM_NONE, _, gfx::Rect(viewport_size),
2752                BoundingRect(uv_top_left, uv_bottom_right), _, _))
2753       .Times(1);
2754 
2755   DrawFrame(&renderer, viewport_size);
2756 
2757   // Transfer resources back from the parent to the child. Set no resources as
2758   // being in use.
2759   parent_resource_provider->DeclareUsedResourcesFromChild(child_id,
2760                                                           ResourceIdSet());
2761 
2762   child_resource_provider->RemoveImportedResource(resource_id);
2763   child_resource_provider->ShutdownAndReleaseAllResources();
2764 }
2765 #endif  // defined(USE_OZONE) || defined(OS_ANDROID)
2766 
2767 class OutputColorMatrixMockGLES2Interface : public TestGLES2Interface {
2768  public:
2769   OutputColorMatrixMockGLES2Interface() = default;
2770 
2771   MOCK_METHOD4(UniformMatrix4fv,
2772                void(GLint location,
2773                     GLsizei count,
2774                     GLboolean transpose,
2775                     const GLfloat* value));
2776 };
2777 
TEST_F(GLRendererTest,OutputColorMatrixTest)2778 TEST_F(GLRendererTest, OutputColorMatrixTest) {
2779   // Initialize the mock GL interface, the output surface and the renderer.
2780   auto gl_owned = std::make_unique<OutputColorMatrixMockGLES2Interface>();
2781   auto* gl = gl_owned.get();
2782   auto provider = TestContextProvider::Create(std::move(gl_owned));
2783   provider->BindToCurrentThread();
2784   std::unique_ptr<FakeOutputSurface> output_surface(
2785       FakeOutputSurface::Create3d(std::move(provider)));
2786   cc::FakeOutputSurfaceClient output_surface_client;
2787   output_surface->BindToClient(&output_surface_client);
2788   std::unique_ptr<DisplayResourceProvider> resource_provider =
2789       std::make_unique<DisplayResourceProvider>(
2790           DisplayResourceProvider::kGpu, output_surface->context_provider(),
2791           nullptr);
2792   RendererSettings settings;
2793   FakeRendererGL renderer(&settings, output_surface.get(),
2794                           resource_provider.get());
2795   renderer.Initialize();
2796   renderer.SetVisible(true);
2797 
2798   // Set a non-identity color matrix on the output surface.
2799   SkMatrix44 color_matrix(SkMatrix44::kIdentity_Constructor);
2800   color_matrix.set(0, 0, 0.7f);
2801   color_matrix.set(1, 1, 0.4f);
2802   color_matrix.set(2, 2, 0.5f);
2803   output_surface->set_color_matrix(color_matrix);
2804 
2805   // Create a root and a child passes to test that the output color matrix is
2806   // registered only for the root pass.
2807   gfx::Size viewport_size(100, 100);
2808   RenderPassId child_pass_id = 2;
2809   RenderPass* child_pass =
2810       cc::AddRenderPass(&render_passes_in_draw_order_, child_pass_id,
2811                         gfx::Rect(viewport_size) + gfx::Vector2d(1, 2),
2812                         gfx::Transform(), cc::FilterOperations());
2813   RenderPassId root_pass_id = 1;
2814   RenderPass* root_pass = cc::AddRenderPass(
2815       &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
2816       gfx::Transform(), cc::FilterOperations());
2817   root_pass->damage_rect = gfx::Rect(0, 0, 25, 25);
2818   cc::AddRenderPassQuad(root_pass, child_pass);
2819 
2820   // Verify that UniformMatrix4fv() is called only once on the root pass with
2821   // the correct matrix values.
2822   int call_count = 0;
2823   bool output_color_matrix_invoked = false;
2824   EXPECT_CALL(*gl, UniformMatrix4fv(_, 1, false, _))
2825       .WillRepeatedly(testing::WithArgs<0, 3>(testing::Invoke(
2826           [&color_matrix, &renderer, &call_count, &output_color_matrix_invoked](
2827               int matrix_location, const GLfloat* gl_matrix) {
2828             DCHECK(current_program(&renderer));
2829             const int color_matrix_location =
2830                 current_program(&renderer)->output_color_matrix_location();
2831 
2832             if (matrix_location != color_matrix_location)
2833               return;
2834 
2835             call_count++;
2836             output_color_matrix_invoked = true;
2837             float expected_matrix[16];
2838             color_matrix.asColMajorf(expected_matrix);
2839             for (int i = 0; i < 16; ++i)
2840               EXPECT_FLOAT_EQ(expected_matrix[i], gl_matrix[i]);
2841           })));
2842 
2843   renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
2844   DrawFrame(&renderer, viewport_size);
2845 
2846   EXPECT_EQ(1, call_count);
2847   EXPECT_TRUE(output_color_matrix_invoked);
2848 }
2849 
2850 class GenerateMipmapMockGLESInterface : public TestGLES2Interface {
2851  public:
2852   GenerateMipmapMockGLESInterface() = default;
2853 
2854   MOCK_METHOD3(TexParameteri, void(GLenum target, GLenum pname, GLint param));
2855   MOCK_METHOD1(GenerateMipmap, void(GLenum target));
2856 };
2857 
2858 // TODO(crbug.com/803286): Currently npot texture always return false on ubuntu
2859 // desktop.  The npot texture check is probably failing on desktop GL. This test
2860 // crashes DCHECK npot texture to catch this. When
2861 // GLRendererPixelTest.DISABLED_TrilinearFiltering got passed, can remove this.
TEST_F(GLRendererTest,GenerateMipmap)2862 TEST_F(GLRendererTest, GenerateMipmap) {
2863   // Initialize the mock GL interface, the output surface and the renderer.
2864   auto gl_owned = std::make_unique<GenerateMipmapMockGLESInterface>();
2865   gl_owned->set_support_texture_npot(true);
2866 
2867   auto* gl = gl_owned.get();
2868   auto provider = TestContextProvider::Create(std::move(gl_owned));
2869   provider->BindToCurrentThread();
2870 
2871   std::unique_ptr<FakeOutputSurface> output_surface(
2872       FakeOutputSurface::Create3d(std::move(provider)));
2873   cc::FakeOutputSurfaceClient output_surface_client;
2874   output_surface->BindToClient(&output_surface_client);
2875   std::unique_ptr<DisplayResourceProvider> resource_provider =
2876       std::make_unique<DisplayResourceProvider>(
2877           DisplayResourceProvider::kGpu, output_surface->context_provider(),
2878           nullptr);
2879   RendererSettings settings;
2880   FakeRendererGL renderer(&settings, output_surface.get(),
2881                           resource_provider.get());
2882   renderer.Initialize();
2883   renderer.SetVisible(true);
2884 
2885   gfx::Size viewport_size(100, 100);
2886   RenderPassId child_pass_id = 2;
2887   // Create a child pass with mipmap to verify that npot texture is enabled.
2888   RenderPass* child_pass =
2889       cc::AddRenderPass(&render_passes_in_draw_order_, child_pass_id,
2890                         gfx::Rect(viewport_size) + gfx::Vector2d(1, 2),
2891                         gfx::Transform(), cc::FilterOperations());
2892   child_pass->generate_mipmap = true;
2893 
2894   RenderPassId root_pass_id = 1;
2895   RenderPass* root_pass = cc::AddRenderPass(
2896       &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
2897       gfx::Transform(), cc::FilterOperations());
2898   root_pass->damage_rect = gfx::Rect(0, 0, 25, 25);
2899   cc::AddRenderPassQuad(root_pass, child_pass);
2900   renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
2901 
2902   EXPECT_CALL(*gl, TexParameteri(_, _, _)).Times(4);
2903   EXPECT_CALL(*gl, GenerateMipmap(GL_TEXTURE_2D)).Times(1);
2904   // When generate_mipmap enabled, the GL_TEXTURE_MIN_FILTER should be
2905   // GL_LINEAR_MIPMAP_LINEAR.
2906   EXPECT_CALL(*gl, TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2907                                  GL_LINEAR_MIPMAP_LINEAR));
2908   DrawFrame(&renderer, viewport_size);
2909 }
2910 
2911 class PartialSwapMockGLES2Interface : public TestGLES2Interface {
2912  public:
2913   PartialSwapMockGLES2Interface() = default;
2914 
2915   MOCK_METHOD1(Enable, void(GLenum cap));
2916   MOCK_METHOD1(Disable, void(GLenum cap));
2917   MOCK_METHOD4(Scissor, void(GLint x, GLint y, GLsizei width, GLsizei height));
2918   MOCK_METHOD1(SetEnableDCLayersCHROMIUM, void(GLboolean enable));
2919 };
2920 
2921 class GLRendererPartialSwapTest : public GLRendererTest {
2922  protected:
RunTest(bool partial_swap,bool set_draw_rectangle)2923   void RunTest(bool partial_swap, bool set_draw_rectangle) {
2924     auto gl_owned = std::make_unique<PartialSwapMockGLES2Interface>();
2925     gl_owned->set_have_post_sub_buffer(true);
2926 
2927     auto* gl = gl_owned.get();
2928 
2929     auto provider = TestContextProvider::Create(std::move(gl_owned));
2930     provider->BindToCurrentThread();
2931 
2932     cc::FakeOutputSurfaceClient output_surface_client;
2933     std::unique_ptr<FakeOutputSurface> output_surface(
2934         FakeOutputSurface::Create3d(std::move(provider)));
2935     output_surface->set_supports_dc_layers(set_draw_rectangle);
2936     output_surface->BindToClient(&output_surface_client);
2937 
2938     std::unique_ptr<DisplayResourceProvider> resource_provider =
2939         std::make_unique<DisplayResourceProvider>(
2940             DisplayResourceProvider::kGpu, output_surface->context_provider(),
2941             nullptr);
2942 
2943     RendererSettings settings;
2944     settings.partial_swap_enabled = partial_swap;
2945     FakeRendererGL renderer(&settings, output_surface.get(),
2946                             resource_provider.get());
2947     renderer.Initialize();
2948     EXPECT_EQ(partial_swap, renderer.use_partial_swap());
2949     renderer.SetVisible(true);
2950 
2951     gfx::Size viewport_size(100, 100);
2952     gfx::Rect root_pass_output_rect(80, 80);
2953     gfx::Rect root_pass_damage_rect(2, 2, 3, 3);
2954 
2955     // Draw one black frame to make sure the output surface is reshaped before
2956     // tests.
2957     EXPECT_CALL(*gl, Disable(GL_DEPTH_TEST)).Times(1);
2958     EXPECT_CALL(*gl, Disable(GL_CULL_FACE)).Times(1);
2959     EXPECT_CALL(*gl, Disable(GL_STENCIL_TEST)).Times(1);
2960     EXPECT_CALL(*gl, Disable(GL_BLEND)).Times(2);
2961     EXPECT_CALL(*gl, Enable(GL_BLEND)).Times(1);
2962     EXPECT_CALL(*gl, Disable(GL_SCISSOR_TEST)).Times(1);
2963     EXPECT_CALL(*gl, Scissor(0, 0, 0, 0)).Times(1);
2964     if (set_draw_rectangle) {
2965       EXPECT_CALL(*gl, Enable(GL_SCISSOR_TEST)).Times(1);
2966       EXPECT_CALL(*gl, Scissor(0, 0, 100, 100)).Times(1);
2967     }
2968 
2969     int root_pass_id = 1;
2970     RenderPass* root_pass = cc::AddRenderPass(
2971         &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
2972         gfx::Transform(), cc::FilterOperations());
2973     root_pass->damage_rect = gfx::Rect(viewport_size);
2974     cc::AddQuad(root_pass, gfx::Rect(viewport_size), SK_ColorBLACK);
2975 
2976     renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
2977     DrawFrame(&renderer, viewport_size);
2978     Mock::VerifyAndClearExpectations(gl);
2979 
2980     for (int i = 0; i < 2; ++i) {
2981       RenderPass* root_pass = cc::AddRenderPassWithDamage(
2982           &render_passes_in_draw_order_, root_pass_id, root_pass_output_rect,
2983           root_pass_damage_rect, gfx::Transform(), cc::FilterOperations());
2984       cc::AddQuad(root_pass, gfx::Rect(root_pass_output_rect), SK_ColorGREEN);
2985 
2986       InSequence seq;
2987 
2988       // A bunch of initialization that happens.
2989       EXPECT_CALL(*gl, Disable(GL_DEPTH_TEST));
2990       EXPECT_CALL(*gl, Disable(GL_CULL_FACE));
2991       EXPECT_CALL(*gl, Disable(GL_STENCIL_TEST));
2992       EXPECT_CALL(*gl, Enable(GL_BLEND));
2993       EXPECT_CALL(*gl, Disable(GL_SCISSOR_TEST));
2994       EXPECT_CALL(*gl, Scissor(0, 0, 0, 0));
2995 
2996       // Partial frame, we should use a scissor to swap only that part when
2997       // partial swap is enabled.
2998       gfx::Rect output_rectangle =
2999           partial_swap ? root_pass_damage_rect : gfx::Rect(viewport_size);
3000 
3001       if (partial_swap || set_draw_rectangle) {
3002         EXPECT_CALL(*gl, Enable(GL_SCISSOR_TEST));
3003         // The scissor is flipped, so subtract the y coord and height from the
3004         // bottom of the GL viewport.
3005         EXPECT_CALL(
3006             *gl, Scissor(output_rectangle.x(),
3007                          viewport_size.height() - output_rectangle.y() -
3008                              output_rectangle.height(),
3009                          output_rectangle.width(), output_rectangle.height()));
3010       }
3011 
3012       // The quad doesn't need blending.
3013       EXPECT_CALL(*gl, Disable(GL_BLEND));
3014 
3015       // Blending is disabled at the end of the frame.
3016       EXPECT_CALL(*gl, Disable(GL_BLEND));
3017 
3018       renderer.DecideRenderPassAllocationsForFrame(
3019           render_passes_in_draw_order_);
3020       DrawFrame(&renderer, viewport_size);
3021 
3022       if (set_draw_rectangle) {
3023         EXPECT_EQ(output_rectangle, output_surface->last_set_draw_rectangle());
3024       }
3025 
3026       Mock::VerifyAndClearExpectations(gl);
3027     }
3028   }
3029 };
3030 
TEST_F(GLRendererPartialSwapTest,PartialSwap)3031 TEST_F(GLRendererPartialSwapTest, PartialSwap) {
3032   RunTest(true, false);
3033 }
3034 
TEST_F(GLRendererPartialSwapTest,NoPartialSwap)3035 TEST_F(GLRendererPartialSwapTest, NoPartialSwap) {
3036   RunTest(false, false);
3037 }
3038 
3039 #if defined(OS_WIN)
TEST_F(GLRendererPartialSwapTest,SetDrawRectangle_PartialSwap)3040 TEST_F(GLRendererPartialSwapTest, SetDrawRectangle_PartialSwap) {
3041   RunTest(true, true);
3042 }
3043 
TEST_F(GLRendererPartialSwapTest,SetDrawRectangle_NoPartialSwap)3044 TEST_F(GLRendererPartialSwapTest, SetDrawRectangle_NoPartialSwap) {
3045   RunTest(false, true);
3046 }
3047 
3048 // Test that SetEnableDCLayersCHROMIUM is properly called when enabling
3049 // and disabling DC layers.
TEST_F(GLRendererTest,DCLayerOverlaySwitch)3050 TEST_F(GLRendererTest, DCLayerOverlaySwitch) {
3051   base::test::ScopedFeatureList feature_list;
3052   feature_list.InitAndEnableFeature(features::kDirectCompositionUnderlays);
3053   auto gl_owned = std::make_unique<PartialSwapMockGLES2Interface>();
3054   gl_owned->set_have_post_sub_buffer(true);
3055   auto* gl = gl_owned.get();
3056 
3057   auto provider = TestContextProvider::Create(std::move(gl_owned));
3058   provider->BindToCurrentThread();
3059 
3060   cc::FakeOutputSurfaceClient output_surface_client;
3061   std::unique_ptr<FakeOutputSurface> output_surface(
3062       FakeOutputSurface::Create3d(std::move(provider)));
3063   output_surface->set_supports_dc_layers(true);
3064   output_surface->BindToClient(&output_surface_client);
3065 
3066   auto parent_resource_provider = std::make_unique<DisplayResourceProvider>(
3067       DisplayResourceProvider::kGpu, output_surface->context_provider(),
3068       nullptr);
3069 
3070   auto child_context_provider = TestContextProvider::Create();
3071   child_context_provider->BindToCurrentThread();
3072   auto child_resource_provider = std::make_unique<ClientResourceProvider>();
3073 
3074   auto transfer_resource = TransferableResource::MakeGL(
3075       gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken(),
3076       gfx::Size(256, 256), true);
3077   auto release_callback =
3078       SingleReleaseCallback::Create(base::BindOnce(&MailboxReleased));
3079   ResourceId resource_id = child_resource_provider->ImportResource(
3080       transfer_resource, std::move(release_callback));
3081 
3082   std::vector<ReturnedResource> returned_to_child;
3083   int child_id = parent_resource_provider->CreateChild(
3084       base::BindRepeating(&CollectResources, &returned_to_child));
3085 
3086   // Transfer resource to the parent.
3087   std::vector<ResourceId> resource_ids_to_transfer;
3088   resource_ids_to_transfer.push_back(resource_id);
3089   std::vector<TransferableResource> list;
3090   child_resource_provider->PrepareSendToParent(
3091       resource_ids_to_transfer, &list,
3092       static_cast<RasterContextProvider*>(child_context_provider.get()));
3093   parent_resource_provider->ReceiveFromChild(child_id, list);
3094   // In DisplayResourceProvider's namespace, use the mapped resource id.
3095   std::unordered_map<ResourceId, ResourceId> resource_map =
3096       parent_resource_provider->GetChildToParentMap(child_id);
3097   ResourceId parent_resource_id = resource_map[list[0].id];
3098 
3099   RendererSettings settings;
3100   settings.partial_swap_enabled = true;
3101   auto processor = std::make_unique<OverlayProcessorWin>(
3102       true /* enable_dc_overlay */,
3103       std::make_unique<DCLayerOverlayProcessor>());
3104   FakeRendererGL renderer(&settings, output_surface.get(),
3105                           parent_resource_provider.get(), processor.get());
3106   renderer.Initialize();
3107   renderer.SetVisible(true);
3108 
3109   gfx::Size viewport_size(100, 100);
3110 
3111   for (int i = 0; i < 65; i++) {
3112     int root_pass_id = 1;
3113     RenderPass* root_pass = cc::AddRenderPass(
3114         &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
3115         gfx::Transform(), cc::FilterOperations());
3116     if (i == 0) {
3117       gfx::Rect rect(0, 0, 100, 100);
3118       bool needs_blending = false;
3119       gfx::RectF tex_coord_rect(0, 0, 1, 1);
3120       SharedQuadState* shared_state =
3121           root_pass->CreateAndAppendSharedQuadState();
3122       shared_state->SetAll(gfx::Transform(), rect, rect, gfx::RRectF(), rect,
3123                            false, false, 1, SkBlendMode::kSrcOver, 0);
3124       YUVVideoDrawQuad* quad =
3125           root_pass->CreateAndAppendDrawQuad<YUVVideoDrawQuad>();
3126       quad->SetNew(shared_state, rect, rect, needs_blending, tex_coord_rect,
3127                    tex_coord_rect, rect.size(), rect.size(), parent_resource_id,
3128                    parent_resource_id, parent_resource_id, parent_resource_id,
3129                    gfx::ColorSpace::CreateREC601(), 0, 1.0, 8);
3130     }
3131 
3132     // A bunch of initialization that happens.
3133     EXPECT_CALL(*gl, Disable(_)).Times(AnyNumber());
3134     EXPECT_CALL(*gl, Enable(_)).Times(AnyNumber());
3135     EXPECT_CALL(*gl, Scissor(_, _, _, _)).Times(AnyNumber());
3136 
3137     // Partial frame, we should use a scissor to swap only that part when
3138     // partial swap is enabled.
3139     root_pass->damage_rect = gfx::Rect(2, 2, 3, 3);
3140     // Frame 0 should be completely damaged because it's the first.
3141     // Frame 1 should be because it changed. Frame 60 should be
3142     // because it's disabling DC layers.
3143     gfx::Rect output_rectangle = (i == 0 || i == 1 || i == 60)
3144                                      ? root_pass->output_rect
3145                                      : root_pass->damage_rect;
3146 
3147     // Frame 0 should have DC Layers enabled because of the overlay.
3148     // After 60 frames of no overlays DC layers should be disabled again.
3149     if (i == 0)
3150       EXPECT_CALL(*gl, SetEnableDCLayersCHROMIUM(GL_TRUE));
3151     else if (i == 60)
3152       EXPECT_CALL(*gl, SetEnableDCLayersCHROMIUM(GL_FALSE));
3153 
3154     renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
3155     DrawFrame(&renderer, viewport_size);
3156     EXPECT_EQ(output_rectangle, output_surface->last_set_draw_rectangle());
3157     testing::Mock::VerifyAndClearExpectations(gl);
3158   }
3159 
3160   // Transfer resources back from the parent to the child. Set no resources as
3161   // being in use.
3162   parent_resource_provider->DeclareUsedResourcesFromChild(child_id,
3163                                                           ResourceIdSet());
3164 
3165   child_resource_provider->RemoveImportedResource(resource_id);
3166   child_resource_provider->ShutdownAndReleaseAllResources();
3167 }
3168 #endif
3169 
3170 class GLRendererWithMockContextTest : public ::testing::Test {
3171  protected:
3172   class MockContextSupport : public TestContextSupport {
3173    public:
MockContextSupport()3174     MockContextSupport() {}
3175     MOCK_METHOD1(SetAggressivelyFreeResources,
3176                  void(bool aggressively_free_resources));
3177   };
3178 
SetUp()3179   void SetUp() override {
3180     auto context_support = std::make_unique<MockContextSupport>();
3181     context_support_ptr_ = context_support.get();
3182     auto context_provider =
3183         TestContextProvider::Create(std::move(context_support));
3184     ASSERT_EQ(context_provider->BindToCurrentThread(),
3185               gpu::ContextResult::kSuccess);
3186     output_surface_ = FakeOutputSurface::Create3d(std::move(context_provider));
3187     output_surface_->BindToClient(&output_surface_client_);
3188     resource_provider_ = std::make_unique<DisplayResourceProvider>(
3189         DisplayResourceProvider::kGpu, output_surface_->context_provider(),
3190         nullptr);
3191     renderer_ = std::make_unique<GLRenderer>(&settings_, output_surface_.get(),
3192                                              resource_provider_.get(), nullptr,
3193                                              nullptr);
3194     renderer_->Initialize();
3195   }
3196 
3197   RendererSettings settings_;
3198   cc::FakeOutputSurfaceClient output_surface_client_;
3199   MockContextSupport* context_support_ptr_;
3200   std::unique_ptr<OutputSurface> output_surface_;
3201   std::unique_ptr<DisplayResourceProvider> resource_provider_;
3202   std::unique_ptr<GLRenderer> renderer_;
3203 };
3204 
TEST_F(GLRendererWithMockContextTest,ContextPurgedWhenRendererBecomesInvisible)3205 TEST_F(GLRendererWithMockContextTest,
3206        ContextPurgedWhenRendererBecomesInvisible) {
3207   EXPECT_CALL(*context_support_ptr_, SetAggressivelyFreeResources(false));
3208   renderer_->SetVisible(true);
3209   Mock::VerifyAndClearExpectations(context_support_ptr_);
3210 
3211   EXPECT_CALL(*context_support_ptr_, SetAggressivelyFreeResources(true));
3212   renderer_->SetVisible(false);
3213   Mock::VerifyAndClearExpectations(context_support_ptr_);
3214 }
3215 
3216 #if defined(USE_OZONE) || defined(OS_ANDROID)
3217 class ContentBoundsOverlayProcessor : public OverlayProcessorUsingStrategy {
3218  public:
3219   class Strategy : public OverlayProcessorUsingStrategy::Strategy {
3220    public:
Strategy(const std::vector<gfx::Rect> & content_bounds)3221     explicit Strategy(const std::vector<gfx::Rect>& content_bounds)
3222         : content_bounds_(content_bounds) {}
3223     ~Strategy() override = default;
3224 
Attempt(const SkMatrix44 & output_color_matrix,const OverlayProcessorInterface::FilterOperationsMap & render_pass_backdrop_filters,DisplayResourceProvider * resource_provider,RenderPassList * render_pass_list,const PrimaryPlane * primary_plane,OverlayCandidateList * candidates,std::vector<gfx::Rect> * content_bounds)3225     bool Attempt(const SkMatrix44& output_color_matrix,
3226                  const OverlayProcessorInterface::FilterOperationsMap&
3227                      render_pass_backdrop_filters,
3228                  DisplayResourceProvider* resource_provider,
3229                  RenderPassList* render_pass_list,
3230                  const PrimaryPlane* primary_plane,
3231                  OverlayCandidateList* candidates,
3232                  std::vector<gfx::Rect>* content_bounds) override {
3233       content_bounds->insert(content_bounds->end(), content_bounds_.begin(),
3234                              content_bounds_.end());
3235       return true;
3236     }
3237 
3238    private:
3239     const std::vector<gfx::Rect> content_bounds_;
3240   };
3241 
ContentBoundsOverlayProcessor(const std::vector<gfx::Rect> & content_bounds)3242   explicit ContentBoundsOverlayProcessor(
3243       const std::vector<gfx::Rect>& content_bounds)
3244       : OverlayProcessorUsingStrategy(), content_bounds_(content_bounds) {
3245     strategies_.push_back(
3246         std::make_unique<Strategy>(std::move(content_bounds_)));
3247   }
3248 
strategy()3249   Strategy& strategy() { return static_cast<Strategy&>(*strategies_.back()); }
3250   // Empty mock methods since this test set up uses strategies, which are only
3251   // for ozone and android.
3252   MOCK_CONST_METHOD0(NeedsSurfaceOccludingDamageRect, bool());
IsOverlaySupported() const3253   bool IsOverlaySupported() const override { return true; }
3254 
3255   // A list of possible overlay candidates is presented to this function.
3256   // The expected result is that those candidates that can be in a separate
3257   // plane are marked with |overlay_handled| set to true, otherwise they are
3258   // to be traditionally composited. Candidates with |overlay_handled| set to
3259   // true must also have their |display_rect| converted to integer
3260   // coordinates if necessary.
CheckOverlaySupport(const OverlayProcessorInterface::OutputSurfaceOverlayPlane * primary_plane,OverlayCandidateList * surfaces)3261   void CheckOverlaySupport(
3262       const OverlayProcessorInterface::OutputSurfaceOverlayPlane* primary_plane,
3263       OverlayCandidateList* surfaces) override {}
3264 
3265  private:
3266   std::vector<gfx::Rect> content_bounds_;
3267 };
3268 
3269 class GLRendererSwapWithBoundsTest : public GLRendererTest {
3270  protected:
RunTest(const std::vector<gfx::Rect> & content_bounds)3271   void RunTest(const std::vector<gfx::Rect>& content_bounds) {
3272     auto gl_owned = std::make_unique<TestGLES2Interface>();
3273     gl_owned->set_have_swap_buffers_with_bounds(true);
3274 
3275     auto provider = TestContextProvider::Create(std::move(gl_owned));
3276     provider->BindToCurrentThread();
3277 
3278     cc::FakeOutputSurfaceClient output_surface_client;
3279     std::unique_ptr<FakeOutputSurface> output_surface(
3280         FakeOutputSurface::Create3d(std::move(provider)));
3281     output_surface->BindToClient(&output_surface_client);
3282 
3283     std::unique_ptr<DisplayResourceProvider> resource_provider =
3284         std::make_unique<DisplayResourceProvider>(
3285             DisplayResourceProvider::kGpu, output_surface->context_provider(),
3286             nullptr);
3287 
3288     RendererSettings settings;
3289     auto processor =
3290         std::make_unique<ContentBoundsOverlayProcessor>(content_bounds);
3291     FakeRendererGL renderer(&settings, output_surface.get(),
3292                             resource_provider.get(), processor.get());
3293     renderer.Initialize();
3294     EXPECT_EQ(true, renderer.use_swap_with_bounds());
3295     renderer.SetVisible(true);
3296 
3297     gfx::Size viewport_size(100, 100);
3298 
3299     {
3300       int root_pass_id = 1;
3301       cc::AddRenderPass(&render_passes_in_draw_order_, root_pass_id,
3302                         gfx::Rect(viewport_size), gfx::Transform(),
3303                         cc::FilterOperations());
3304 
3305       renderer.DecideRenderPassAllocationsForFrame(
3306           render_passes_in_draw_order_);
3307       DrawFrame(&renderer, viewport_size);
3308       renderer.SwapBuffers({});
3309 
3310       std::vector<gfx::Rect> expected_content_bounds;
3311       EXPECT_EQ(content_bounds,
3312                 output_surface->last_sent_frame()->content_bounds);
3313     }
3314   }
3315 };
3316 
TEST_F(GLRendererSwapWithBoundsTest,EmptyContent)3317 TEST_F(GLRendererSwapWithBoundsTest, EmptyContent) {
3318   std::vector<gfx::Rect> content_bounds;
3319   RunTest(content_bounds);
3320 }
3321 
TEST_F(GLRendererSwapWithBoundsTest,NonEmpty)3322 TEST_F(GLRendererSwapWithBoundsTest, NonEmpty) {
3323   std::vector<gfx::Rect> content_bounds;
3324   content_bounds.push_back(gfx::Rect(0, 0, 10, 10));
3325   content_bounds.push_back(gfx::Rect(20, 20, 30, 30));
3326   RunTest(content_bounds);
3327 }
3328 #endif  // defined(USE_OZONE) || defined(OS_ANDROID)
3329 
3330 #if defined(OS_MACOSX)
3331 class MockCALayerGLES2Interface : public TestGLES2Interface {
3332  public:
3333   MOCK_METHOD6(ScheduleCALayerSharedStateCHROMIUM,
3334                void(GLfloat opacity,
3335                     GLboolean is_clipped,
3336                     const GLfloat* clip_rect,
3337                     const GLfloat* rounded_corner_bounds,
3338                     GLint sorting_context_id,
3339                     const GLfloat* transform));
3340   MOCK_METHOD6(ScheduleCALayerCHROMIUM,
3341                void(GLuint contents_texture_id,
3342                     const GLfloat* contents_rect,
3343                     GLuint background_color,
3344                     GLuint edge_aa_mask,
3345                     const GLfloat* bounds_rect,
3346                     GLuint filter));
3347   MOCK_METHOD2(ScheduleCALayerInUseQueryCHROMIUM,
3348                void(GLsizei count, const GLuint* textures));
3349   MOCK_METHOD5(
3350       Uniform4f,
3351       void(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w));
3352 };
3353 
3354 class CALayerGLRendererTest : public GLRendererTest {
3355  protected:
SetUp()3356   void SetUp() override {
3357     // A mock GLES2Interface that can watch CALayer stuff happen.
3358     auto gles2_interface = std::make_unique<MockCALayerGLES2Interface>();
3359     // Support image storage for GpuMemoryBuffers, needed for
3360     // CALayers/IOSurfaces backed by textures.
3361     gles2_interface->set_support_texture_storage_image(true);
3362     // Allow the renderer to make an empty SwapBuffers - skipping even the
3363     // root RenderPass.
3364     gles2_interface->set_have_commit_overlay_planes(true);
3365 
3366     gl_ = gles2_interface.get();
3367 
3368     auto provider = TestContextProvider::Create(std::move(gles2_interface));
3369     provider->BindToCurrentThread();
3370 
3371     cc::FakeOutputSurfaceClient output_surface_client;
3372     output_surface_ = FakeOutputSurface::Create3d(std::move(provider));
3373     output_surface_->BindToClient(&output_surface_client);
3374 
3375     display_resource_provider_ = std::make_unique<DisplayResourceProvider>(
3376         DisplayResourceProvider::kGpu, output_surface_->context_provider(),
3377         nullptr);
3378 
3379     settings_ = std::make_unique<RendererSettings>();
3380     // This setting is enabled to use CALayer overlays.
3381     settings_->release_overlay_resources_after_gpu_query = true;
3382     // The Mac TestOverlayProcessor default to enable CALayer overlays, then all
3383     // damage is removed and we can skip the root RenderPass, swapping empty.
3384     overlay_processor_ = std::make_unique<OverlayProcessorMac>(
3385         std::make_unique<CALayerOverlayProcessor>());
3386     renderer_ = std::make_unique<FakeRendererGL>(
3387         settings_.get(), output_surface_.get(),
3388         display_resource_provider_.get(), overlay_processor_.get(),
3389         base::ThreadTaskRunnerHandle::Get());
3390     renderer_->Initialize();
3391     renderer_->SetVisible(true);
3392   }
3393 
TearDown()3394   void TearDown() override {
3395     renderer_.reset();
3396     display_resource_provider_.reset();
3397     output_surface_.reset();
3398   }
3399 
DrawBlackFrame(const gfx::Size & viewport_size)3400   void DrawBlackFrame(const gfx::Size& viewport_size) {
3401     RenderPassId root_pass_id = 1;
3402 
3403     RenderPass* root_pass = cc::AddRenderPass(
3404         &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
3405         gfx::Transform(), cc::FilterOperations());
3406     cc::AddQuad(root_pass, gfx::Rect(viewport_size), SK_ColorBLACK);
3407 
3408     renderer().DecideRenderPassAllocationsForFrame(
3409         render_passes_in_draw_order_);
3410 
3411     DrawFrame(&renderer(), viewport_size);
3412     renderer().SwapBuffers(DirectRenderer::SwapFrameData());
3413     renderer().SwapBuffersComplete();
3414     Mock::VerifyAndClearExpectations(&gl());
3415   }
3416 
gl() const3417   MockCALayerGLES2Interface& gl() const { return *gl_; }
renderer() const3418   FakeRendererGL& renderer() const { return *renderer_; }
output_surface() const3419   FakeOutputSurface& output_surface() const { return *output_surface_; }
3420 
3421  private:
3422   MockCALayerGLES2Interface* gl_;
3423   std::unique_ptr<FakeOutputSurface> output_surface_;
3424   std::unique_ptr<DisplayResourceProvider> display_resource_provider_;
3425   std::unique_ptr<RendererSettings> settings_;
3426   std::unique_ptr<OverlayProcessorInterface> overlay_processor_;
3427   std::unique_ptr<FakeRendererGL> renderer_;
3428 };
3429 
TEST_F(CALayerGLRendererTest,CALayerOverlaysWithAllQuadsPromoted)3430 TEST_F(CALayerGLRendererTest, CALayerOverlaysWithAllQuadsPromoted) {
3431   gfx::Size viewport_size(10, 10);
3432 
3433   // Draw an empty frame to make sure output surface is reshaped before tests.
3434   DrawBlackFrame(viewport_size);
3435 
3436   // This frame has a root pass with a RenderPassDrawQuad pointing to a child
3437   // pass that is at 1,2 to make it identifiable.
3438   RenderPassId child_pass_id = 2;
3439   RenderPassId root_pass_id = 1;
3440   {
3441     RenderPass* child_pass =
3442         cc::AddRenderPass(&render_passes_in_draw_order_, child_pass_id,
3443                           gfx::Rect(viewport_size) + gfx::Vector2d(1, 2),
3444                           gfx::Transform(), cc::FilterOperations());
3445     RenderPass* root_pass = cc::AddRenderPass(
3446         &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
3447         gfx::Transform(), cc::FilterOperations());
3448     cc::AddRenderPassQuad(root_pass, child_pass, 0, gfx::Transform(),
3449                           SkBlendMode::kSrcOver);
3450   }
3451 
3452   renderer().DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
3453 
3454   // The child pass is drawn, promoted to an overlay, and scheduled as a
3455   // CALayer.
3456   {
3457     InSequence sequence;
3458     EXPECT_CALL(gl(), ScheduleCALayerSharedStateCHROMIUM(_, _, _, _, _, _));
3459     EXPECT_CALL(gl(), ScheduleCALayerCHROMIUM(_, _, _, _, _, _))
3460         .WillOnce(
3461             Invoke([](GLuint contents_texture_id, const GLfloat* contents_rect,
3462                       GLuint background_color, GLuint edge_aa_mask,
3463                       const GLfloat* bounds_rect, GLuint filter) {
3464               // This is the child RenderPassDrawQuad.
3465               EXPECT_EQ(1, bounds_rect[0]);
3466               EXPECT_EQ(2, bounds_rect[1]);
3467             }));
3468   }
3469   DrawFrame(&renderer(), viewport_size);
3470   Mock::VerifyAndClearExpectations(&gl());
3471 
3472   renderer().SwapBuffers(DirectRenderer::SwapFrameData());
3473 
3474   // The damage was eliminated when everything was promoted to CALayers.
3475   ASSERT_TRUE(output_surface().last_sent_frame()->sub_buffer_rect);
3476   EXPECT_TRUE(output_surface().last_sent_frame()->sub_buffer_rect->IsEmpty());
3477 
3478   // Frame number 2. Same inputs, except...
3479   {
3480     RenderPass* child_pass =
3481         cc::AddRenderPass(&render_passes_in_draw_order_, child_pass_id,
3482                           gfx::Rect(viewport_size) + gfx::Vector2d(1, 2),
3483                           gfx::Transform(), cc::FilterOperations());
3484     RenderPass* root_pass = cc::AddRenderPass(
3485         &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
3486         gfx::Transform(), cc::FilterOperations());
3487     cc::AddRenderPassQuad(root_pass, child_pass, 0, gfx::Transform(),
3488                           SkBlendMode::kSrcOver);
3489 
3490     // Use a cached RenderPass for the child.
3491     child_pass->cache_render_pass = true;
3492   }
3493 
3494   renderer().DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
3495 
3496   // The child RenderPassDrawQuad gets promoted again, but importantly it
3497   // did not itself have to be drawn this time as it can use the cached texture.
3498   // Because we can skip the child pass, and the root pass (all quads were
3499   // promoted), this exposes edge cases in GLRenderer if it assumes we draw
3500   // at least one RenderPass. This still works, doesn't crash, etc, and the
3501   // RenderPassDrawQuad is emitted.
3502   {
3503     InSequence sequence;
3504     EXPECT_CALL(gl(), ScheduleCALayerSharedStateCHROMIUM(_, _, _, _, _, _));
3505     EXPECT_CALL(gl(), ScheduleCALayerCHROMIUM(_, _, _, _, _, _));
3506   }
3507   DrawFrame(&renderer(), viewport_size);
3508   Mock::VerifyAndClearExpectations(&gl());
3509 
3510   renderer().SwapBuffers(DirectRenderer::SwapFrameData());
3511 }
3512 
TEST_F(CALayerGLRendererTest,CALayerRoundRects)3513 TEST_F(CALayerGLRendererTest, CALayerRoundRects) {
3514   gfx::Size viewport_size(10, 10);
3515 
3516   // Draw an empty frame to make sure output surface is reshaped before tests.
3517   DrawBlackFrame(viewport_size);
3518 
3519   for (size_t subtest = 0; subtest < 3; ++subtest) {
3520     RenderPass* child_pass =
3521         cc::AddRenderPass(&render_passes_in_draw_order_, 1, gfx::Rect(250, 250),
3522                           gfx::Transform(), cc::FilterOperations());
3523 
3524     RenderPassId root_pass_id = 1;
3525     RenderPass* root_pass = cc::AddRenderPass(
3526         &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
3527         gfx::Transform(), cc::FilterOperations());
3528     auto* quad = cc::AddRenderPassQuad(root_pass, child_pass);
3529     SharedQuadState* sqs =
3530         const_cast<SharedQuadState*>(quad->shared_quad_state);
3531 
3532     sqs->is_clipped = true;
3533     sqs->clip_rect = gfx::Rect(2, 2, 6, 6);
3534     const float radius = 2;
3535     sqs->rounded_corner_bounds =
3536         gfx::RRectF(gfx::RectF(sqs->clip_rect), radius);
3537 
3538     switch (subtest) {
3539       case 0:
3540         // Subtest 0 is a simple round rect that matches the clip rect, and
3541         // should be handled by CALayers.
3542         EXPECT_CALL(gl(), Uniform4f(_, _, _, _, _)).Times(1);
3543         EXPECT_CALL(gl(), ScheduleCALayerSharedStateCHROMIUM(_, _, _, _, _, _))
3544             .Times(1);
3545         EXPECT_CALL(gl(), ScheduleCALayerCHROMIUM(_, _, _, _, _, _)).Times(1);
3546         break;
3547       case 1:
3548         // Subtest 1 doesn't match clip and rounded rect, but we can still
3549         // use CALayers.
3550         sqs->clip_rect = gfx::Rect(3, 3, 4, 4);
3551         EXPECT_CALL(gl(), Uniform4f(_, _, _, _, _)).Times(1);
3552         EXPECT_CALL(gl(), ScheduleCALayerCHROMIUM(_, _, _, _, _, _)).Times(1);
3553         break;
3554       case 2:
3555         // Subtest 2 has a non-simple rounded rect.
3556         sqs->rounded_corner_bounds.SetCornerRadii(
3557             gfx::RRectF::Corner::kUpperLeft, 1, 1);
3558         // Called 2 extra times in order to set up the rounded corner
3559         // parameters in the shader, because the CALayer is not handling
3560         // the rounded corners.
3561         EXPECT_CALL(gl(), Uniform4f(_, _, _, _, _)).Times(3);
3562         EXPECT_CALL(gl(), ScheduleCALayerCHROMIUM(_, _, _, _, _, _)).Times(0);
3563         break;
3564     }
3565 
3566     renderer().DecideRenderPassAllocationsForFrame(
3567         render_passes_in_draw_order_);
3568     DrawFrame(&renderer(), viewport_size);
3569     Mock::VerifyAndClearExpectations(&gl());
3570   }
3571 }
3572 
TEST_F(CALayerGLRendererTest,CALayerOverlaysReusesTextureWithDifferentSizes)3573 TEST_F(CALayerGLRendererTest, CALayerOverlaysReusesTextureWithDifferentSizes) {
3574   gfx::Size viewport_size(300, 300);
3575 
3576   // Draw an empty frame to make sure output surface is reshaped before tests.
3577   DrawBlackFrame(viewport_size);
3578 
3579   // This frame has a root pass with a RenderPassDrawQuad pointing to a child
3580   // pass that is at 1,2 to make it identifiable.
3581   // The child's size is 250x251, but it will be rounded up to a multiple of 64
3582   // in order to promote easier texture reuse. See https://crbug.com/146070.
3583   RenderPassId child_pass_id = 2;
3584   RenderPassId root_pass_id = 1;
3585   {
3586     RenderPass* child_pass =
3587         cc::AddRenderPass(&render_passes_in_draw_order_, child_pass_id,
3588                           gfx::Rect(250, 251) + gfx::Vector2d(1, 2),
3589                           gfx::Transform(), cc::FilterOperations());
3590     RenderPass* root_pass = cc::AddRenderPass(
3591         &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
3592         gfx::Transform(), cc::FilterOperations());
3593     cc::AddRenderPassQuad(root_pass, child_pass, 0, gfx::Transform(),
3594                           SkBlendMode::kSrcOver);
3595   }
3596 
3597   renderer().DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
3598 
3599   // The child pass is drawn, promoted to an overlay, and scheduled as a
3600   // CALayer. The bounds of the texture are rounded up to 256x256. We save the
3601   // texture ID to make sure we reuse it correctly.
3602   uint32_t saved_texture_id = 0;
3603   {
3604     InSequence sequence;
3605     EXPECT_CALL(gl(), ScheduleCALayerSharedStateCHROMIUM(_, _, _, _, _, _));
3606     EXPECT_CALL(gl(), ScheduleCALayerCHROMIUM(_, _, _, _, _, _))
3607         .WillOnce(
3608             Invoke([&](GLuint contents_texture_id, const GLfloat* contents_rect,
3609                        GLuint background_color, GLuint edge_aa_mask,
3610                        const GLfloat* bounds_rect, GLuint filter) {
3611               // This is the child RenderPassDrawQuad.
3612               EXPECT_EQ(1, bounds_rect[0]);
3613               EXPECT_EQ(2, bounds_rect[1]);
3614               // The size is rounded to a multiple of 64.
3615               EXPECT_EQ(256, bounds_rect[2]);
3616               EXPECT_EQ(256, bounds_rect[3]);
3617               saved_texture_id = contents_texture_id;
3618             }));
3619   }
3620   DrawFrame(&renderer(), viewport_size);
3621   Mock::VerifyAndClearExpectations(&gl());
3622   renderer().SwapBuffers(DirectRenderer::SwapFrameData());
3623 
3624   // ScheduleCALayerCHROMIUM happened and used a non-0 texture.
3625   EXPECT_NE(saved_texture_id, 0u);
3626 
3627   // The damage was eliminated when everything was promoted to CALayers.
3628   ASSERT_TRUE(output_surface().last_sent_frame()->sub_buffer_rect);
3629   EXPECT_TRUE(output_surface().last_sent_frame()->sub_buffer_rect->IsEmpty());
3630 
3631   // The texture will be checked to verify if it is free yet.
3632   EXPECT_CALL(gl(), ScheduleCALayerInUseQueryCHROMIUM(1, _));
3633   renderer().SwapBuffersComplete();
3634   Mock::VerifyAndClearExpectations(&gl());
3635 
3636   // Frame number 2. We change the size of the child RenderPass to be smaller
3637   // than the next multiple of 64, but larger than half the previous size so
3638   // that our texture reuse heuristics will reuse the texture if it is free.
3639   // For now, it is not.
3640   {
3641     RenderPass* child_pass =
3642         cc::AddRenderPass(&render_passes_in_draw_order_, child_pass_id,
3643                           gfx::Rect(190, 191) + gfx::Vector2d(1, 2),
3644                           gfx::Transform(), cc::FilterOperations());
3645     RenderPass* root_pass = cc::AddRenderPass(
3646         &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
3647         gfx::Transform(), cc::FilterOperations());
3648     cc::AddRenderPassQuad(root_pass, child_pass, 0, gfx::Transform(),
3649                           SkBlendMode::kSrcOver);
3650   }
3651 
3652   renderer().DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
3653 
3654   // The child RenderPass will use a new 192x192 texture, since the last texture
3655   // is still in use.
3656   {
3657     InSequence sequence;
3658     EXPECT_CALL(gl(), ScheduleCALayerSharedStateCHROMIUM(_, _, _, _, _, _));
3659     EXPECT_CALL(gl(), ScheduleCALayerCHROMIUM(_, _, _, _, _, _))
3660         .WillOnce(
3661             Invoke([&](GLuint contents_texture_id, const GLfloat* contents_rect,
3662                        GLuint background_color, GLuint edge_aa_mask,
3663                        const GLfloat* bounds_rect, GLuint filter) {
3664               // New texture id.
3665               EXPECT_NE(saved_texture_id, contents_texture_id);
3666               EXPECT_EQ(1, bounds_rect[0]);
3667               EXPECT_EQ(2, bounds_rect[1]);
3668               // The texture is 192x192 since we snap up to multiples of 64.
3669               EXPECT_EQ(192, bounds_rect[2]);
3670               EXPECT_EQ(192, bounds_rect[3]);
3671             }));
3672   }
3673   DrawFrame(&renderer(), viewport_size);
3674   Mock::VerifyAndClearExpectations(&gl());
3675   renderer().SwapBuffers(DirectRenderer::SwapFrameData());
3676 
3677   // There are now 2 textures to check if they are free.
3678   EXPECT_CALL(gl(), ScheduleCALayerInUseQueryCHROMIUM(2, _));
3679   renderer().SwapBuffersComplete();
3680   Mock::VerifyAndClearExpectations(&gl());
3681 
3682   // The first (256x256) texture is returned to the GLRenderer.
3683   renderer().DidReceiveTextureInUseResponses({{saved_texture_id, false}});
3684 
3685   // Frame number 3 looks just like frame number 2. The child RenderPass is
3686   // smaller than the next multiple of 64 from the released texture, but larger
3687   // than half of its size so that our texture reuse heuristics will kick in.
3688   {
3689     RenderPass* child_pass =
3690         cc::AddRenderPass(&render_passes_in_draw_order_, child_pass_id,
3691                           gfx::Rect(190, 191) + gfx::Vector2d(1, 2),
3692                           gfx::Transform(), cc::FilterOperations());
3693     RenderPass* root_pass = cc::AddRenderPass(
3694         &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
3695         gfx::Transform(), cc::FilterOperations());
3696     cc::AddRenderPassQuad(root_pass, child_pass, 0, gfx::Transform(),
3697                           SkBlendMode::kSrcOver);
3698   }
3699 
3700   renderer().DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
3701 
3702   // The child RenderPass would try to use a 192x192 texture, but since we have
3703   // an existing 256x256 texture, we can reuse that.
3704   {
3705     InSequence sequence;
3706     EXPECT_CALL(gl(), ScheduleCALayerSharedStateCHROMIUM(_, _, _, _, _, _));
3707     EXPECT_CALL(gl(), ScheduleCALayerCHROMIUM(_, _, _, _, _, _))
3708         .WillOnce(
3709             Invoke([&](GLuint contents_texture_id, const GLfloat* contents_rect,
3710                        GLuint background_color, GLuint edge_aa_mask,
3711                        const GLfloat* bounds_rect, GLuint filter) {
3712               // The first texture is reused.
3713               EXPECT_EQ(saved_texture_id, contents_texture_id);
3714               // This is the child RenderPassDrawQuad.
3715               EXPECT_EQ(1, bounds_rect[0]);
3716               EXPECT_EQ(2, bounds_rect[1]);
3717               // The size here is the size of the texture being used, not
3718               // the size we tried to use (192x192).
3719               EXPECT_EQ(256, bounds_rect[2]);
3720               EXPECT_EQ(256, bounds_rect[3]);
3721             }));
3722   }
3723   DrawFrame(&renderer(), viewport_size);
3724   Mock::VerifyAndClearExpectations(&gl());
3725   renderer().SwapBuffers(DirectRenderer::SwapFrameData());
3726 }
3727 
TEST_F(CALayerGLRendererTest,CALayerOverlaysDontReuseTooBigTexture)3728 TEST_F(CALayerGLRendererTest, CALayerOverlaysDontReuseTooBigTexture) {
3729   gfx::Size viewport_size(300, 300);
3730 
3731   // Draw an empty frame to make sure output surface is reshaped before tests.
3732   DrawBlackFrame(viewport_size);
3733 
3734   // This frame has a root pass with a RenderPassDrawQuad pointing to a child
3735   // pass that is at 1,2 to make it identifiable.
3736   // The child's size is 250x251, but it will be rounded up to a multiple of 64
3737   // in order to promote easier texture reuse. See https://crbug.com/146070.
3738   RenderPassId child_pass_id = 2;
3739   RenderPassId root_pass_id = 1;
3740   {
3741     RenderPass* child_pass =
3742         cc::AddRenderPass(&render_passes_in_draw_order_, child_pass_id,
3743                           gfx::Rect(250, 251) + gfx::Vector2d(1, 2),
3744                           gfx::Transform(), cc::FilterOperations());
3745     RenderPass* root_pass = cc::AddRenderPass(
3746         &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
3747         gfx::Transform(), cc::FilterOperations());
3748     cc::AddRenderPassQuad(root_pass, child_pass, 0, gfx::Transform(),
3749                           SkBlendMode::kSrcOver);
3750   }
3751 
3752   renderer().DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
3753 
3754   // The child pass is drawn, promoted to an overlay, and scheduled as a
3755   // CALayer. The bounds of the texture are rounded up to 256x256. We save the
3756   // texture ID to make sure we reuse it correctly.
3757   uint32_t saved_texture_id = 0;
3758   {
3759     InSequence sequence;
3760     EXPECT_CALL(gl(), ScheduleCALayerSharedStateCHROMIUM(_, _, _, _, _, _));
3761     EXPECT_CALL(gl(), ScheduleCALayerCHROMIUM(_, _, _, _, _, _))
3762         .WillOnce(
3763             Invoke([&](GLuint contents_texture_id, const GLfloat* contents_rect,
3764                        GLuint background_color, GLuint edge_aa_mask,
3765                        const GLfloat* bounds_rect, GLuint filter) {
3766               // This is the child RenderPassDrawQuad.
3767               EXPECT_EQ(1, bounds_rect[0]);
3768               EXPECT_EQ(2, bounds_rect[1]);
3769               // The size is rounded to a multiple of 64.
3770               EXPECT_EQ(256, bounds_rect[2]);
3771               EXPECT_EQ(256, bounds_rect[3]);
3772               saved_texture_id = contents_texture_id;
3773             }));
3774   }
3775   DrawFrame(&renderer(), viewport_size);
3776   Mock::VerifyAndClearExpectations(&gl());
3777   renderer().SwapBuffers(DirectRenderer::SwapFrameData());
3778 
3779   // ScheduleCALayerCHROMIUM happened and used a non-0 texture.
3780   EXPECT_NE(saved_texture_id, 0u);
3781 
3782   // The damage was eliminated when everything was promoted to CALayers.
3783   ASSERT_TRUE(output_surface().last_sent_frame()->sub_buffer_rect);
3784   EXPECT_TRUE(output_surface().last_sent_frame()->sub_buffer_rect->IsEmpty());
3785 
3786   // The texture will be checked to verify if it is free yet.
3787   EXPECT_CALL(gl(), ScheduleCALayerInUseQueryCHROMIUM(1, _));
3788   renderer().SwapBuffersComplete();
3789   Mock::VerifyAndClearExpectations(&gl());
3790 
3791   // Frame number 2. We change the size of the child RenderPass to be much
3792   // smaller.
3793   {
3794     RenderPass* child_pass =
3795         cc::AddRenderPass(&render_passes_in_draw_order_, child_pass_id,
3796                           gfx::Rect(20, 21) + gfx::Vector2d(1, 2),
3797                           gfx::Transform(), cc::FilterOperations());
3798     RenderPass* root_pass = cc::AddRenderPass(
3799         &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
3800         gfx::Transform(), cc::FilterOperations());
3801     cc::AddRenderPassQuad(root_pass, child_pass, 0, gfx::Transform(),
3802                           SkBlendMode::kSrcOver);
3803   }
3804 
3805   renderer().DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
3806 
3807   // The child RenderPass will use a new 64x64 texture, since the last texture
3808   // is still in use.
3809   {
3810     InSequence sequence;
3811     EXPECT_CALL(gl(), ScheduleCALayerSharedStateCHROMIUM(_, _, _, _, _, _));
3812     EXPECT_CALL(gl(), ScheduleCALayerCHROMIUM(_, _, _, _, _, _))
3813         .WillOnce(
3814             Invoke([&](GLuint contents_texture_id, const GLfloat* contents_rect,
3815                        GLuint background_color, GLuint edge_aa_mask,
3816                        const GLfloat* bounds_rect, GLuint filter) {
3817               // New texture id.
3818               EXPECT_NE(saved_texture_id, contents_texture_id);
3819               EXPECT_EQ(1, bounds_rect[0]);
3820               EXPECT_EQ(2, bounds_rect[1]);
3821               // The texture is 64x64 since we snap up to multiples of 64.
3822               EXPECT_EQ(64, bounds_rect[2]);
3823               EXPECT_EQ(64, bounds_rect[3]);
3824             }));
3825   }
3826   DrawFrame(&renderer(), viewport_size);
3827   Mock::VerifyAndClearExpectations(&gl());
3828   renderer().SwapBuffers(DirectRenderer::SwapFrameData());
3829 
3830   // There are now 2 textures to check if they are free.
3831   EXPECT_CALL(gl(), ScheduleCALayerInUseQueryCHROMIUM(2, _));
3832   renderer().SwapBuffersComplete();
3833   Mock::VerifyAndClearExpectations(&gl());
3834 
3835   // The first (256x256) texture is returned to the GLRenderer.
3836   renderer().DidReceiveTextureInUseResponses({{saved_texture_id, false}});
3837 
3838   // Frame number 3 looks just like frame number 2. The child RenderPass is
3839   // too small to reuse the old texture.
3840   {
3841     RenderPass* child_pass =
3842         cc::AddRenderPass(&render_passes_in_draw_order_, child_pass_id,
3843                           gfx::Rect(20, 21) + gfx::Vector2d(1, 2),
3844                           gfx::Transform(), cc::FilterOperations());
3845     RenderPass* root_pass = cc::AddRenderPass(
3846         &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
3847         gfx::Transform(), cc::FilterOperations());
3848     cc::AddRenderPassQuad(root_pass, child_pass, 0, gfx::Transform(),
3849                           SkBlendMode::kSrcOver);
3850   }
3851 
3852   renderer().DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
3853 
3854   // The child RenderPass would try to use a 64x64 texture. We have a free and
3855   // existing 256x256 texture, but it's too large for us to reuse it.
3856   {
3857     InSequence sequence;
3858     EXPECT_CALL(gl(), ScheduleCALayerSharedStateCHROMIUM(_, _, _, _, _, _));
3859     EXPECT_CALL(gl(), ScheduleCALayerCHROMIUM(_, _, _, _, _, _))
3860         .WillOnce(
3861             Invoke([&](GLuint contents_texture_id, const GLfloat* contents_rect,
3862                        GLuint background_color, GLuint edge_aa_mask,
3863                        const GLfloat* bounds_rect, GLuint filter) {
3864               // The first texture is not reused.
3865               EXPECT_NE(saved_texture_id, contents_texture_id);
3866               // This is the child RenderPassDrawQuad.
3867               EXPECT_EQ(1, bounds_rect[0]);
3868               EXPECT_EQ(2, bounds_rect[1]);
3869               // The new texture has a smaller size.
3870               EXPECT_EQ(64, bounds_rect[2]);
3871               EXPECT_EQ(64, bounds_rect[3]);
3872             }));
3873   }
3874   DrawFrame(&renderer(), viewport_size);
3875   Mock::VerifyAndClearExpectations(&gl());
3876   renderer().SwapBuffers(DirectRenderer::SwapFrameData());
3877 }
3878 
TEST_F(CALayerGLRendererTest,CALayerOverlaysReuseAfterNoSwapBuffers)3879 TEST_F(CALayerGLRendererTest, CALayerOverlaysReuseAfterNoSwapBuffers) {
3880   gfx::Size viewport_size(300, 300);
3881 
3882   // This frame has a root pass with a RenderPassDrawQuad pointing to a child
3883   // pass that is at 1,2 to make it identifiable.
3884   RenderPassId child_pass_id = 2;
3885   RenderPassId root_pass_id = 1;
3886   {
3887     RenderPass* child_pass =
3888         cc::AddRenderPass(&render_passes_in_draw_order_, child_pass_id,
3889                           gfx::Rect(100, 100) + gfx::Vector2d(1, 2),
3890                           gfx::Transform(), cc::FilterOperations());
3891     RenderPass* root_pass = cc::AddRenderPass(
3892         &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
3893         gfx::Transform(), cc::FilterOperations());
3894     cc::AddRenderPassQuad(root_pass, child_pass, 0, gfx::Transform(),
3895                           SkBlendMode::kSrcOver);
3896   }
3897 
3898   renderer().DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
3899 
3900   // The child pass is drawn, promoted to an overlay, and scheduled as a
3901   // CALayer. We save the texture ID to make sure we reuse it correctly.
3902   uint32_t saved_texture_id = 0;
3903   {
3904     InSequence sequence;
3905     EXPECT_CALL(gl(), ScheduleCALayerSharedStateCHROMIUM(_, _, _, _, _, _));
3906     EXPECT_CALL(gl(), ScheduleCALayerCHROMIUM(_, _, _, _, _, _))
3907         .WillOnce(
3908             Invoke([&](GLuint contents_texture_id, const GLfloat* contents_rect,
3909                        GLuint background_color, GLuint edge_aa_mask,
3910                        const GLfloat* bounds_rect, GLuint filter) {
3911               // This is the child RenderPassDrawQuad.
3912               EXPECT_EQ(1, bounds_rect[0]);
3913               EXPECT_EQ(2, bounds_rect[1]);
3914               saved_texture_id = contents_texture_id;
3915             }));
3916   }
3917   DrawFrame(&renderer(), viewport_size);
3918   Mock::VerifyAndClearExpectations(&gl());
3919 
3920   // ScheduleCALayerCHROMIUM happened and used a non-0 texture.
3921   EXPECT_NE(saved_texture_id, 0u);
3922 
3923   // SwapBuffers() is *not* called though! Display can do this sometimes.
3924 
3925   // Frame number 2. We can not reuse the texture since the last one isn't
3926   // returned yet. We use a different size so we can control which texture gets
3927   // reused later.
3928   {
3929     RenderPass* child_pass =
3930         cc::AddRenderPass(&render_passes_in_draw_order_, child_pass_id,
3931                           gfx::Rect(200, 200) + gfx::Vector2d(1, 2),
3932                           gfx::Transform(), cc::FilterOperations());
3933     RenderPass* root_pass = cc::AddRenderPass(
3934         &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
3935         gfx::Transform(), cc::FilterOperations());
3936     cc::AddRenderPassQuad(root_pass, child_pass, 0, gfx::Transform(),
3937                           SkBlendMode::kSrcOver);
3938   }
3939 
3940   renderer().DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
3941 
3942   uint32_t second_saved_texture_id = 0;
3943   {
3944     InSequence sequence;
3945     EXPECT_CALL(gl(), ScheduleCALayerSharedStateCHROMIUM(_, _, _, _, _, _));
3946     EXPECT_CALL(gl(), ScheduleCALayerCHROMIUM(_, _, _, _, _, _))
3947         .WillOnce(
3948             Invoke([&](GLuint contents_texture_id, const GLfloat* contents_rect,
3949                        GLuint background_color, GLuint edge_aa_mask,
3950                        const GLfloat* bounds_rect, GLuint filter) {
3951               // New texture id.
3952               EXPECT_NE(saved_texture_id, contents_texture_id);
3953               EXPECT_EQ(1, bounds_rect[0]);
3954               EXPECT_EQ(2, bounds_rect[1]);
3955               second_saved_texture_id = contents_texture_id;
3956             }));
3957   }
3958   DrawFrame(&renderer(), viewport_size);
3959   Mock::VerifyAndClearExpectations(&gl());
3960 
3961   // SwapBuffers() *does* happen this time.
3962   renderer().SwapBuffers(DirectRenderer::SwapFrameData());
3963 
3964   // There are 2 textures to check if they are free.
3965   EXPECT_CALL(gl(), ScheduleCALayerInUseQueryCHROMIUM(2, _));
3966   renderer().SwapBuffersComplete();
3967   Mock::VerifyAndClearExpectations(&gl());
3968 
3969   // Both textures get returned and the 2nd one can be reused.
3970   renderer().DidReceiveTextureInUseResponses(
3971       {{saved_texture_id, false}, {second_saved_texture_id, false}});
3972 
3973   // Frame number 3 looks just like frame number 2.
3974   {
3975     RenderPass* child_pass =
3976         cc::AddRenderPass(&render_passes_in_draw_order_, child_pass_id,
3977                           gfx::Rect(200, 200) + gfx::Vector2d(1, 2),
3978                           gfx::Transform(), cc::FilterOperations());
3979     RenderPass* root_pass = cc::AddRenderPass(
3980         &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
3981         gfx::Transform(), cc::FilterOperations());
3982     cc::AddRenderPassQuad(root_pass, child_pass, 0, gfx::Transform(),
3983                           SkBlendMode::kSrcOver);
3984   }
3985 
3986   renderer().DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
3987 
3988   // The 2nd texture that we sent has been returned so we can reuse it. We
3989   // verify that happened.
3990   {
3991     InSequence sequence;
3992     EXPECT_CALL(gl(), ScheduleCALayerSharedStateCHROMIUM(_, _, _, _, _, _));
3993     EXPECT_CALL(gl(), ScheduleCALayerCHROMIUM(_, _, _, _, _, _))
3994         .WillOnce(
3995             Invoke([&](GLuint contents_texture_id, const GLfloat* contents_rect,
3996                        GLuint background_color, GLuint edge_aa_mask,
3997                        const GLfloat* bounds_rect, GLuint filter) {
3998               // The second texture is reused.
3999               EXPECT_EQ(second_saved_texture_id, contents_texture_id);
4000               // This is the child RenderPassDrawQuad.
4001               EXPECT_EQ(1, bounds_rect[0]);
4002               EXPECT_EQ(2, bounds_rect[1]);
4003             }));
4004   }
4005   DrawFrame(&renderer(), viewport_size);
4006   Mock::VerifyAndClearExpectations(&gl());
4007   renderer().SwapBuffers(DirectRenderer::SwapFrameData());
4008 }
4009 
TEST_F(CALayerGLRendererTest,CALayerOverlaysReuseManyIfReturnedSlowly)4010 TEST_F(CALayerGLRendererTest, CALayerOverlaysReuseManyIfReturnedSlowly) {
4011   gfx::Size viewport_size(300, 300);
4012 
4013   // Draw an empty frame to make sure output surface is reshaped before tests.
4014   DrawBlackFrame(viewport_size);
4015 
4016   // Each frame has a root pass with a RenderPassDrawQuad pointing to a child
4017   // pass. We generate a bunch of frames and swap them, each with a different
4018   // child RenderPass id, without getting any of the resources back from the OS.
4019   RenderPassId root_pass_id = 1;
4020 
4021   // The number is at least 2 larger than the number of textures we expect to
4022   // reuse, so that we can leave one in the OS, and have 1 texture returned but
4023   // not reused.
4024   const int kNumSendManyTextureIds = 7;
4025   uint32_t sent_texture_ids[kNumSendManyTextureIds];
4026   for (int i = 0; i < kNumSendManyTextureIds; ++i) {
4027     RenderPass* child_pass =
4028         cc::AddRenderPass(&render_passes_in_draw_order_, i + 2,
4029                           gfx::Rect(250, 251) + gfx::Vector2d(1, 2),
4030                           gfx::Transform(), cc::FilterOperations());
4031     RenderPass* root_pass = cc::AddRenderPass(
4032         &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
4033         gfx::Transform(), cc::FilterOperations());
4034     cc::AddRenderPassQuad(root_pass, child_pass, 0, gfx::Transform(),
4035                           SkBlendMode::kSrcOver);
4036 
4037     renderer().DecideRenderPassAllocationsForFrame(
4038         render_passes_in_draw_order_);
4039 
4040     InSequence sequence;
4041     EXPECT_CALL(gl(), ScheduleCALayerSharedStateCHROMIUM(_, _, _, _, _, _));
4042     EXPECT_CALL(gl(), ScheduleCALayerCHROMIUM(_, _, _, _, _, _))
4043         .WillOnce(
4044             Invoke([&](GLuint contents_texture_id, const GLfloat* contents_rect,
4045                        GLuint background_color, GLuint edge_aa_mask,
4046                        const GLfloat* bounds_rect, GLuint filter) {
4047               // This is the child RenderPassDrawQuad.
4048               EXPECT_EQ(1, bounds_rect[0]);
4049               EXPECT_EQ(2, bounds_rect[1]);
4050               sent_texture_ids[i] = contents_texture_id;
4051             }));
4052     DrawFrame(&renderer(), viewport_size);
4053     Mock::VerifyAndClearExpectations(&gl());
4054     renderer().SwapBuffers(DirectRenderer::SwapFrameData());
4055 
4056     // ScheduleCALayerCHROMIUM happened and used a non-0 texture.
4057     EXPECT_NE(sent_texture_ids[i], 0u);
4058 
4059     // The damage was eliminated when everything was promoted to CALayers.
4060     ASSERT_TRUE(output_surface().last_sent_frame()->sub_buffer_rect);
4061     EXPECT_TRUE(output_surface().last_sent_frame()->sub_buffer_rect->IsEmpty());
4062 
4063     // All sent textures will be checked to verify if they are free yet.
4064     EXPECT_CALL(gl(), ScheduleCALayerInUseQueryCHROMIUM(i + 1, _));
4065     renderer().SwapBuffersComplete();
4066     Mock::VerifyAndClearExpectations(&gl());
4067   }
4068 
4069   // Now all but 1 texture get returned by the OS, so they are all inserted
4070   // into the cache for reuse.
4071   std::vector<uint32_t> returned_texture_ids;
4072   for (int i = 0; i < kNumSendManyTextureIds - 1; ++i) {
4073     uint32_t id = sent_texture_ids[i];
4074     renderer().DidReceiveTextureInUseResponses({{id, false}});
4075     returned_texture_ids.push_back(id);
4076   }
4077 
4078   // We should keep *some* of these textures around to reuse them across
4079   // multiple frames. https://crbug.com/146070 motivates this, and empirical
4080   // testing found 5 to be a good number.
4081   const int kNumSendReusedTextures = 5;
4082   // See comment on |kNumSendManyTextureIds|.
4083   ASSERT_LT(kNumSendReusedTextures, kNumSendManyTextureIds - 1);
4084 
4085   for (int i = 0; i < kNumSendReusedTextures + 1; ++i) {
4086     // We use different RenderPass ids to ensure that the cache allows reuse
4087     // even if they don't match.
4088     RenderPass* child_pass =
4089         cc::AddRenderPass(&render_passes_in_draw_order_, i + 100,
4090                           gfx::Rect(250, 251) + gfx::Vector2d(1, 2),
4091                           gfx::Transform(), cc::FilterOperations());
4092     RenderPass* root_pass = cc::AddRenderPass(
4093         &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
4094         gfx::Transform(), cc::FilterOperations());
4095     cc::AddRenderPassQuad(root_pass, child_pass, 0, gfx::Transform(),
4096                           SkBlendMode::kSrcOver);
4097 
4098     renderer().DecideRenderPassAllocationsForFrame(
4099         render_passes_in_draw_order_);
4100 
4101     InSequence sequence;
4102     EXPECT_CALL(gl(), ScheduleCALayerSharedStateCHROMIUM(_, _, _, _, _, _));
4103     EXPECT_CALL(gl(), ScheduleCALayerCHROMIUM(_, _, _, _, _, _))
4104         .WillOnce(Invoke([&](GLuint contents_texture_id,
4105                              const GLfloat* contents_rect,
4106                              GLuint background_color, GLuint edge_aa_mask,
4107                              const GLfloat* bounds_rect, GLuint filter) {
4108           // This is the child RenderPassDrawQuad.
4109           EXPECT_EQ(1, bounds_rect[0]);
4110           EXPECT_EQ(2, bounds_rect[1]);
4111 
4112           if (i < kNumSendReusedTextures) {
4113             // The texture id should be from the set of returned ones.
4114             EXPECT_THAT(returned_texture_ids, Contains(contents_texture_id));
4115             base::Erase(returned_texture_ids, contents_texture_id);
4116           } else {
4117             // More textures were returned at once than we expect to reuse
4118             // so eventually we should be making a new texture to show we're
4119             // not just keeping infinity textures in the cache.
4120             EXPECT_THAT(returned_texture_ids,
4121                         Not(Contains(contents_texture_id)));
4122             // This shows that there was some returned id that we didn't use.
4123             EXPECT_FALSE(returned_texture_ids.empty());
4124           }
4125         }));
4126     DrawFrame(&renderer(), viewport_size);
4127     Mock::VerifyAndClearExpectations(&gl());
4128     renderer().SwapBuffers(DirectRenderer::SwapFrameData());
4129 
4130     // All sent textures will be checked to verify if they are free yet. There's
4131     // also 1 outstanding texture to check for that wasn't returned yet from the
4132     // above loop.
4133     EXPECT_CALL(gl(), ScheduleCALayerInUseQueryCHROMIUM(i + 2, _));
4134     renderer().SwapBuffersComplete();
4135     Mock::VerifyAndClearExpectations(&gl());
4136   }
4137 }
4138 
TEST_F(CALayerGLRendererTest,CALayerOverlaysCachedTexturesAreFreed)4139 TEST_F(CALayerGLRendererTest, CALayerOverlaysCachedTexturesAreFreed) {
4140   gfx::Size viewport_size(300, 300);
4141 
4142   // Draw an empty frame to make sure output surface is reshaped before tests.
4143   DrawBlackFrame(viewport_size);
4144 
4145   // Each frame has a root pass with a RenderPassDrawQuad pointing to a child
4146   // pass. We generate a bunch of frames and swap them, each with a different
4147   // child RenderPass id, without getting any of the resources back from the OS.
4148   RenderPassId child_pass_id = 2;
4149   RenderPassId root_pass_id = 1;
4150 
4151   // We send a whole bunch of textures as overlays to the OS.
4152   const int kNumSendManyTextureIds = 7;
4153   uint32_t sent_texture_ids[kNumSendManyTextureIds];
4154   for (int i = 0; i < kNumSendManyTextureIds; ++i) {
4155     RenderPass* child_pass =
4156         cc::AddRenderPass(&render_passes_in_draw_order_, i + 2,
4157                           gfx::Rect(250, 251) + gfx::Vector2d(1, 2),
4158                           gfx::Transform(), cc::FilterOperations());
4159     RenderPass* root_pass = cc::AddRenderPass(
4160         &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
4161         gfx::Transform(), cc::FilterOperations());
4162     cc::AddRenderPassQuad(root_pass, child_pass, 0, gfx::Transform(),
4163                           SkBlendMode::kSrcOver);
4164 
4165     renderer().DecideRenderPassAllocationsForFrame(
4166         render_passes_in_draw_order_);
4167 
4168     InSequence sequence;
4169     EXPECT_CALL(gl(), ScheduleCALayerSharedStateCHROMIUM(_, _, _, _, _, _));
4170     EXPECT_CALL(gl(), ScheduleCALayerCHROMIUM(_, _, _, _, _, _))
4171         .WillOnce(
4172             Invoke([&](GLuint contents_texture_id, const GLfloat* contents_rect,
4173                        GLuint background_color, GLuint edge_aa_mask,
4174                        const GLfloat* bounds_rect, GLuint filter) {
4175               // This is the child RenderPassDrawQuad.
4176               EXPECT_EQ(1, bounds_rect[0]);
4177               EXPECT_EQ(2, bounds_rect[1]);
4178               sent_texture_ids[i] = contents_texture_id;
4179             }));
4180     DrawFrame(&renderer(), viewport_size);
4181     Mock::VerifyAndClearExpectations(&gl());
4182     renderer().SwapBuffers(DirectRenderer::SwapFrameData());
4183 
4184     // ScheduleCALayerCHROMIUM happened and used a non-0 texture.
4185     EXPECT_NE(sent_texture_ids[i], 0u);
4186 
4187     // The damage was eliminated when everything was promoted to CALayers.
4188     ASSERT_TRUE(output_surface().last_sent_frame()->sub_buffer_rect);
4189     EXPECT_TRUE(output_surface().last_sent_frame()->sub_buffer_rect->IsEmpty());
4190 
4191     // All sent textures will be checked to verify if they are free yet.
4192     EXPECT_CALL(gl(), ScheduleCALayerInUseQueryCHROMIUM(i + 1, _));
4193     renderer().SwapBuffersComplete();
4194     Mock::VerifyAndClearExpectations(&gl());
4195   }
4196 
4197   // Now all but 1 texture get returned by the OS, so they are all inserted
4198   // into the cache for reuse.
4199   std::vector<uint32_t> returned_texture_ids;
4200   for (int i = 0; i < kNumSendManyTextureIds - 1; ++i) {
4201     uint32_t id = sent_texture_ids[i];
4202     renderer().DidReceiveTextureInUseResponses({{id, false}});
4203     returned_texture_ids.push_back(id);
4204   }
4205 
4206   // We generate a bunch of frames that don't use the cache, one less than the
4207   // number of textures returned.
4208   for (int i = 0; i < kNumSendManyTextureIds - 2; ++i) {
4209     RenderPass* root_pass = cc::AddRenderPass(
4210         &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
4211         gfx::Transform(), cc::FilterOperations());
4212     cc::AddQuad(root_pass, gfx::Rect(100, 100), SK_ColorRED);
4213 
4214     renderer().DecideRenderPassAllocationsForFrame(
4215         render_passes_in_draw_order_);
4216 
4217     InSequence sequence;
4218     EXPECT_CALL(gl(), ScheduleCALayerSharedStateCHROMIUM(_, _, _, _, _, _));
4219     EXPECT_CALL(gl(), ScheduleCALayerCHROMIUM(_, _, _, _, _, _));
4220     DrawFrame(&renderer(), viewport_size);
4221     Mock::VerifyAndClearExpectations(&gl());
4222     renderer().SwapBuffers(DirectRenderer::SwapFrameData());
4223 
4224     // There's just 1 outstanding RenderPass texture to query for.
4225     EXPECT_CALL(gl(), ScheduleCALayerInUseQueryCHROMIUM(1, _));
4226     renderer().SwapBuffersComplete();
4227     Mock::VerifyAndClearExpectations(&gl());
4228   }
4229 
4230   // By now the cache should be empty, to show that we don't keep cached
4231   // textures that won't be used forever. We generate a frame with a
4232   // RenderPassDrawQuad and verify that it does not reuse a texture from the
4233   // (empty) cache.
4234   {
4235     RenderPass* child_pass =
4236         cc::AddRenderPass(&render_passes_in_draw_order_, child_pass_id,
4237                           gfx::Rect(250, 251) + gfx::Vector2d(1, 2),
4238                           gfx::Transform(), cc::FilterOperations());
4239     RenderPass* root_pass = cc::AddRenderPass(
4240         &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
4241         gfx::Transform(), cc::FilterOperations());
4242     cc::AddRenderPassQuad(root_pass, child_pass, 0, gfx::Transform(),
4243                           SkBlendMode::kSrcOver);
4244   }
4245 
4246   renderer().DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
4247 
4248   InSequence sequence;
4249   EXPECT_CALL(gl(), ScheduleCALayerSharedStateCHROMIUM(_, _, _, _, _, _));
4250   EXPECT_CALL(gl(), ScheduleCALayerCHROMIUM(_, _, _, _, _, _))
4251       .WillOnce(Invoke([&](GLuint contents_texture_id,
4252                            const GLfloat* contents_rect,
4253                            GLuint background_color, GLuint edge_aa_mask,
4254                            const GLfloat* bounds_rect, GLuint filter) {
4255         // This is the child RenderPassDrawQuad.
4256         EXPECT_EQ(1, bounds_rect[0]);
4257         EXPECT_EQ(2, bounds_rect[1]);
4258 
4259         // More textures were returned at once than we expect to reuse
4260         // so eventually we should be making a new texture to show we're
4261         // not just keeping infinity textures in the cache.
4262         EXPECT_THAT(returned_texture_ids, Not(Contains(contents_texture_id)));
4263         // This shows that there was some returned id that we didn't use.
4264         EXPECT_FALSE(returned_texture_ids.empty());
4265       }));
4266   DrawFrame(&renderer(), viewport_size);
4267   Mock::VerifyAndClearExpectations(&gl());
4268   renderer().SwapBuffers(DirectRenderer::SwapFrameData());
4269 }
4270 #endif
4271 
4272 class FramebufferWatchingGLRenderer : public FakeRendererGL {
4273  public:
FramebufferWatchingGLRenderer(RendererSettings * settings,OutputSurface * output_surface,DisplayResourceProvider * resource_provider)4274   FramebufferWatchingGLRenderer(RendererSettings* settings,
4275                                 OutputSurface* output_surface,
4276                                 DisplayResourceProvider* resource_provider)
4277       : FakeRendererGL(settings, output_surface, resource_provider) {}
4278 
BindFramebufferToOutputSurface()4279   void BindFramebufferToOutputSurface() override {
4280     ++bind_root_framebuffer_calls_;
4281     FakeRendererGL::BindFramebufferToOutputSurface();
4282   }
4283 
BindFramebufferToTexture(const RenderPassId render_pass_id)4284   void BindFramebufferToTexture(const RenderPassId render_pass_id) override {
4285     ++bind_child_framebuffer_calls_;
4286     FakeRendererGL::BindFramebufferToTexture(render_pass_id);
4287   }
4288 
bind_root_framebuffer_calls() const4289   int bind_root_framebuffer_calls() const {
4290     return bind_root_framebuffer_calls_;
4291   }
bind_child_framebuffer_calls() const4292   int bind_child_framebuffer_calls() const {
4293     return bind_child_framebuffer_calls_;
4294   }
4295 
ResetBindCalls()4296   void ResetBindCalls() {
4297     bind_root_framebuffer_calls_ = bind_child_framebuffer_calls_ = 0;
4298   }
4299 
4300  private:
4301   int bind_root_framebuffer_calls_ = 0;
4302   int bind_child_framebuffer_calls_ = 0;
4303 };
4304 
TEST_F(GLRendererTest,UndamagedRenderPassStillDrawnWhenNoPartialSwap)4305 TEST_F(GLRendererTest, UndamagedRenderPassStillDrawnWhenNoPartialSwap) {
4306   auto provider = TestContextProvider::Create();
4307   provider->UnboundTestContextGL()->set_have_post_sub_buffer(true);
4308   provider->BindToCurrentThread();
4309 
4310   cc::FakeOutputSurfaceClient output_surface_client;
4311   auto output_surface = FakeOutputSurface::Create3d(std::move(provider));
4312   output_surface->BindToClient(&output_surface_client);
4313 
4314   std::unique_ptr<DisplayResourceProvider> resource_provider =
4315       std::make_unique<DisplayResourceProvider>(
4316           DisplayResourceProvider::kGpu, output_surface->context_provider(),
4317           nullptr);
4318 
4319   for (int i = 0; i < 2; ++i) {
4320     bool use_partial_swap = i == 0;
4321     SCOPED_TRACE(use_partial_swap);
4322 
4323     RendererSettings settings;
4324     settings.partial_swap_enabled = use_partial_swap;
4325     FramebufferWatchingGLRenderer renderer(&settings, output_surface.get(),
4326                                            resource_provider.get());
4327     renderer.Initialize();
4328     EXPECT_EQ(use_partial_swap, renderer.use_partial_swap());
4329     renderer.SetVisible(true);
4330 
4331     gfx::Size viewport_size(100, 100);
4332     gfx::Rect child_rect(10, 10);
4333 
4334     // First frame, the child and root RenderPass each have damage.
4335     RenderPass* child_pass =
4336         cc::AddRenderPass(&render_passes_in_draw_order_, 2, child_rect,
4337                           gfx::Transform(), cc::FilterOperations());
4338     cc::AddQuad(child_pass, child_rect, SK_ColorGREEN);
4339     child_pass->damage_rect = child_rect;
4340 
4341     RenderPass* root_pass = cc::AddRenderPass(
4342         &render_passes_in_draw_order_, 1, gfx::Rect(viewport_size),
4343         gfx::Transform(), cc::FilterOperations());
4344     cc::AddQuad(root_pass, gfx::Rect(viewport_size), SK_ColorRED);
4345     cc::AddRenderPassQuad(root_pass, child_pass, 0, gfx::Transform(),
4346                           SkBlendMode::kSrcOver);
4347     root_pass->damage_rect = gfx::Rect(viewport_size);
4348 
4349     EXPECT_EQ(0, renderer.bind_root_framebuffer_calls());
4350     EXPECT_EQ(0, renderer.bind_child_framebuffer_calls());
4351 
4352     renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
4353     DrawFrame(&renderer, viewport_size);
4354 
4355     // We had to draw the root, and the child.
4356     EXPECT_EQ(1, renderer.bind_child_framebuffer_calls());
4357     // When the RenderPassDrawQuad in the root is drawn, we may re-bind the root
4358     // framebuffer. So it can be bound more than once.
4359     EXPECT_GE(renderer.bind_root_framebuffer_calls(), 1);
4360 
4361     // Reset counting.
4362     renderer.ResetBindCalls();
4363 
4364     // Second frame, the child RenderPass has no damage in it.
4365     child_pass = cc::AddRenderPass(&render_passes_in_draw_order_, 2, child_rect,
4366                                    gfx::Transform(), cc::FilterOperations());
4367     cc::AddQuad(child_pass, child_rect, SK_ColorGREEN);
4368     child_pass->damage_rect = gfx::Rect();
4369 
4370     // Root RenderPass has some damage that doesn't intersect the child.
4371     root_pass = cc::AddRenderPass(&render_passes_in_draw_order_, 1,
4372                                   gfx::Rect(viewport_size), gfx::Transform(),
4373                                   cc::FilterOperations());
4374     cc::AddQuad(root_pass, gfx::Rect(viewport_size), SK_ColorRED);
4375     cc::AddRenderPassQuad(root_pass, child_pass, 0, gfx::Transform(),
4376                           SkBlendMode::kSrcOver);
4377     root_pass->damage_rect = gfx::Rect(child_rect.right(), 0, 10, 10);
4378 
4379     EXPECT_EQ(0, renderer.bind_root_framebuffer_calls());
4380     EXPECT_EQ(0, renderer.bind_child_framebuffer_calls());
4381 
4382     renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
4383     DrawFrame(&renderer, viewport_size);
4384 
4385     if (use_partial_swap) {
4386       // Without damage overlapping the child, it didn't need to be drawn (it
4387       // may choose to anyway but that'd be a waste). So we don't check for
4388       // |bind_child_framebuffer_calls|. But the root should have been drawn.
4389       EXPECT_EQ(renderer.bind_root_framebuffer_calls(), 1);
4390     } else {
4391       // Without partial swap, we have to draw the child still, this means
4392       // the child is bound as the framebuffer.
4393       EXPECT_EQ(1, renderer.bind_child_framebuffer_calls());
4394       // When the RenderPassDrawQuad in the root is drawn, as it must be since
4395       // we must draw the entire output, we may re-bind the root framebuffer. So
4396       // it can be bound more than once.
4397       EXPECT_GE(renderer.bind_root_framebuffer_calls(), 1);
4398     }
4399   }
4400 }
4401 
4402 #if defined(USE_OZONE) || defined(OS_ANDROID)
4403 class GLRendererWithGpuFenceTest : public GLRendererTest {
4404  protected:
GLRendererWithGpuFenceTest()4405   GLRendererWithGpuFenceTest() {
4406     auto provider = TestContextProvider::Create();
4407     provider->BindToCurrentThread();
4408     provider->TestContextGL()->set_have_commit_overlay_planes(true);
4409     test_context_support_ = provider->support();
4410 
4411     output_surface_ = FakeOutputSurface::Create3d(std::move(provider));
4412     output_surface_->set_overlay_texture_id(kSurfaceOverlayTextureId);
4413     output_surface_->set_gpu_fence_id(kGpuFenceId);
4414     resource_provider_ = std::make_unique<DisplayResourceProvider>(
4415         DisplayResourceProvider::kGpu, output_surface_->context_provider(),
4416         nullptr);
4417     overlay_processor_ = std::make_unique<SingleOverlayOnTopProcessor>();
4418     overlay_processor_->AllowMultipleCandidates();
4419     renderer_ = std::make_unique<FakeRendererGL>(
4420         &settings_, output_surface_.get(), resource_provider_.get(),
4421         overlay_processor_.get(), base::ThreadTaskRunnerHandle::Get());
4422     renderer_->Initialize();
4423     renderer_->SetVisible(true);
4424 
4425     test_context_support_->SetScheduleOverlayPlaneCallback(
4426         base::BindRepeating(&MockOverlayScheduler::Schedule,
4427                             base::Unretained(&overlay_scheduler_)));
4428   }
4429 
~GLRendererWithGpuFenceTest()4430   ~GLRendererWithGpuFenceTest() override {
4431     if (child_resource_provider_)
4432       child_resource_provider_->ShutdownAndReleaseAllResources();
4433   }
4434 
create_overlay_resource()4435   ResourceId create_overlay_resource() {
4436     child_context_provider_ = TestContextProvider::Create();
4437     child_context_provider_->BindToCurrentThread();
4438 
4439     child_resource_provider_ = std::make_unique<ClientResourceProvider>();
4440     auto transfer_resource = TransferableResource::MakeGL(
4441         gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken(),
4442         gfx::Size(256, 256), true);
4443     ResourceId client_resource_id = child_resource_provider_->ImportResource(
4444         transfer_resource, SingleReleaseCallback::Create(base::DoNothing()));
4445 
4446     std::unordered_map<ResourceId, ResourceId> resource_map =
4447         cc::SendResourceAndGetChildToParentMap(
4448             {client_resource_id}, resource_provider_.get(),
4449             child_resource_provider_.get(), child_context_provider_.get());
4450     return resource_map[client_resource_id];
4451   }
4452 
4453   static constexpr unsigned kSurfaceOverlayTextureId = 33;
4454   static constexpr unsigned kGpuFenceId = 66;
4455   static constexpr unsigned kGpuNoFenceId = 0;
4456 
4457   TestContextSupport* test_context_support_;
4458 
4459   cc::FakeOutputSurfaceClient output_surface_client_;
4460   std::unique_ptr<FakeOutputSurface> output_surface_;
4461   std::unique_ptr<DisplayResourceProvider> resource_provider_;
4462   scoped_refptr<TestContextProvider> child_context_provider_;
4463   std::unique_ptr<ClientResourceProvider> child_resource_provider_;
4464   RendererSettings settings_;
4465   std::unique_ptr<SingleOverlayOnTopProcessor> overlay_processor_;
4466   std::unique_ptr<FakeRendererGL> renderer_;
4467   MockOverlayScheduler overlay_scheduler_;
4468 };
4469 
TEST_F(GLRendererWithGpuFenceTest,GpuFenceIdIsUsedWithRootRenderPassOverlay)4470 TEST_F(GLRendererWithGpuFenceTest, GpuFenceIdIsUsedWithRootRenderPassOverlay) {
4471   gfx::Size viewport_size(100, 100);
4472   RenderPass* root_pass = cc::AddRenderPass(
4473       &render_passes_in_draw_order_, 1, gfx::Rect(viewport_size),
4474       gfx::Transform(), cc::FilterOperations());
4475   root_pass->has_transparent_background = false;
4476 
4477   EXPECT_CALL(overlay_scheduler_,
4478               Schedule(0, gfx::OVERLAY_TRANSFORM_NONE, kSurfaceOverlayTextureId,
4479                        gfx::Rect(viewport_size), _, _, kGpuFenceId))
4480       .Times(1);
4481   DrawFrame(renderer_.get(), viewport_size);
4482 }
4483 
TEST_F(GLRendererWithGpuFenceTest,GpuFenceIdIsUsedOnlyForRootRenderPassOverlay)4484 TEST_F(GLRendererWithGpuFenceTest,
4485        GpuFenceIdIsUsedOnlyForRootRenderPassOverlay) {
4486   gfx::Size viewport_size(100, 100);
4487   RenderPass* root_pass = cc::AddRenderPass(
4488       &render_passes_in_draw_order_, 1, gfx::Rect(viewport_size),
4489       gfx::Transform(), cc::FilterOperations());
4490   root_pass->has_transparent_background = false;
4491 
4492   bool needs_blending = false;
4493   bool premultiplied_alpha = false;
4494   bool flipped = false;
4495   bool nearest_neighbor = false;
4496   float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
4497   gfx::PointF uv_top_left(0, 0);
4498   gfx::PointF uv_bottom_right(1, 1);
4499 
4500   TextureDrawQuad* overlay_quad =
4501       root_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
4502   SharedQuadState* shared_state = root_pass->CreateAndAppendSharedQuadState();
4503   shared_state->SetAll(gfx::Transform(), gfx::Rect(viewport_size),
4504                        gfx::Rect(50, 50), gfx::RRectF(),
4505                        gfx::Rect(viewport_size), false, false, 1,
4506                        SkBlendMode::kSrcOver, 0);
4507   overlay_quad->SetNew(
4508       shared_state, gfx::Rect(viewport_size), gfx::Rect(viewport_size),
4509       needs_blending, create_overlay_resource(), premultiplied_alpha,
4510       uv_top_left, uv_bottom_right, SK_ColorTRANSPARENT, vertex_opacity,
4511       flipped, nearest_neighbor,
4512       /*secure_output_only=*/false, gfx::ProtectedVideoType::kClear);
4513 
4514   EXPECT_CALL(overlay_scheduler_,
4515               Schedule(0, gfx::OVERLAY_TRANSFORM_NONE, kSurfaceOverlayTextureId,
4516                        gfx::Rect(viewport_size), _, _, kGpuFenceId))
4517       .Times(1);
4518   EXPECT_CALL(overlay_scheduler_,
4519               Schedule(1, gfx::OVERLAY_TRANSFORM_NONE, _,
4520                        gfx::Rect(viewport_size), _, _, kGpuNoFenceId))
4521       .Times(1);
4522   DrawFrame(renderer_.get(), viewport_size);
4523 }
4524 #endif  // defined(USE_OZONE) || defined(OS_ANDROID)
4525 
4526 }  // namespace
4527 }  // namespace viz
4528