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