OLD | NEW |
| (Empty) |
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 "cc/output/gl_renderer.h" | |
6 | |
7 #include <set> | |
8 | |
9 #include "cc/base/math_util.h" | |
10 #include "cc/output/compositor_frame_metadata.h" | |
11 #include "cc/resources/resource_provider.h" | |
12 #include "cc/test/fake_impl_proxy.h" | |
13 #include "cc/test/fake_layer_tree_host_impl.h" | |
14 #include "cc/test/fake_output_surface.h" | |
15 #include "cc/test/fake_output_surface_client.h" | |
16 #include "cc/test/fake_renderer_client.h" | |
17 #include "cc/test/pixel_test.h" | |
18 #include "cc/test/render_pass_test_common.h" | |
19 #include "cc/test/render_pass_test_utils.h" | |
20 #include "cc/test/test_shared_bitmap_manager.h" | |
21 #include "cc/test/test_web_graphics_context_3d.h" | |
22 #include "gpu/GLES2/gl2extchromium.h" | |
23 #include "gpu/command_buffer/client/context_support.h" | |
24 #include "testing/gmock/include/gmock/gmock.h" | |
25 #include "testing/gtest/include/gtest/gtest.h" | |
26 #include "third_party/skia/include/core/SkImageFilter.h" | |
27 #include "third_party/skia/include/core/SkMatrix.h" | |
28 #include "third_party/skia/include/effects/SkColorFilterImageFilter.h" | |
29 #include "third_party/skia/include/effects/SkColorMatrixFilter.h" | |
30 #include "ui/gfx/transform.h" | |
31 | |
32 using testing::_; | |
33 using testing::AnyNumber; | |
34 using testing::Args; | |
35 using testing::AtLeast; | |
36 using testing::ElementsAre; | |
37 using testing::Expectation; | |
38 using testing::InSequence; | |
39 using testing::Mock; | |
40 using testing::Return; | |
41 using testing::StrictMock; | |
42 | |
43 namespace cc { | |
44 | |
45 class GLRendererTest : public testing::Test { | |
46 protected: | |
47 RenderPass* root_render_pass() { return render_passes_in_draw_order_.back(); } | |
48 | |
49 RenderPassList render_passes_in_draw_order_; | |
50 }; | |
51 | |
52 #define EXPECT_PROGRAM_VALID(program_binding) \ | |
53 do { \ | |
54 EXPECT_TRUE((program_binding)->program()); \ | |
55 EXPECT_TRUE((program_binding)->initialized()); \ | |
56 } while (false) | |
57 | |
58 static inline SkXfermode::Mode BlendModeToSkXfermode(BlendMode blend_mode) { | |
59 switch (blend_mode) { | |
60 case BLEND_MODE_NONE: | |
61 case BLEND_MODE_NORMAL: | |
62 return SkXfermode::kSrcOver_Mode; | |
63 case BLEND_MODE_SCREEN: | |
64 return SkXfermode::kScreen_Mode; | |
65 case BLEND_MODE_OVERLAY: | |
66 return SkXfermode::kOverlay_Mode; | |
67 case BLEND_MODE_DARKEN: | |
68 return SkXfermode::kDarken_Mode; | |
69 case BLEND_MODE_LIGHTEN: | |
70 return SkXfermode::kLighten_Mode; | |
71 case BLEND_MODE_COLOR_DODGE: | |
72 return SkXfermode::kColorDodge_Mode; | |
73 case BLEND_MODE_COLOR_BURN: | |
74 return SkXfermode::kColorBurn_Mode; | |
75 case BLEND_MODE_HARD_LIGHT: | |
76 return SkXfermode::kHardLight_Mode; | |
77 case BLEND_MODE_SOFT_LIGHT: | |
78 return SkXfermode::kSoftLight_Mode; | |
79 case BLEND_MODE_DIFFERENCE: | |
80 return SkXfermode::kDifference_Mode; | |
81 case BLEND_MODE_EXCLUSION: | |
82 return SkXfermode::kExclusion_Mode; | |
83 case BLEND_MODE_MULTIPLY: | |
84 return SkXfermode::kMultiply_Mode; | |
85 case BLEND_MODE_HUE: | |
86 return SkXfermode::kHue_Mode; | |
87 case BLEND_MODE_SATURATION: | |
88 return SkXfermode::kSaturation_Mode; | |
89 case BLEND_MODE_COLOR: | |
90 return SkXfermode::kColor_Mode; | |
91 case BLEND_MODE_LUMINOSITY: | |
92 return SkXfermode::kLuminosity_Mode; | |
93 } | |
94 return SkXfermode::kSrcOver_Mode; | |
95 } | |
96 | |
97 // Explicitly named to be a friend in GLRenderer for shader access. | |
98 class GLRendererShaderPixelTest : public GLRendererPixelTest { | |
99 public: | |
100 void SetUp() override { | |
101 GLRendererPixelTest::SetUp(); | |
102 ASSERT_FALSE(renderer()->IsContextLost()); | |
103 } | |
104 | |
105 void TearDown() override { | |
106 GLRendererPixelTest::TearDown(); | |
107 ASSERT_FALSE(renderer()->IsContextLost()); | |
108 } | |
109 | |
110 void TestBasicShaders() { | |
111 EXPECT_PROGRAM_VALID(renderer()->GetTileCheckerboardProgram()); | |
112 EXPECT_PROGRAM_VALID(renderer()->GetDebugBorderProgram()); | |
113 EXPECT_PROGRAM_VALID(renderer()->GetSolidColorProgram()); | |
114 EXPECT_PROGRAM_VALID(renderer()->GetSolidColorProgramAA()); | |
115 } | |
116 | |
117 void TestShadersWithPrecision(TexCoordPrecision precision) { | |
118 EXPECT_PROGRAM_VALID(renderer()->GetTextureProgram(precision)); | |
119 EXPECT_PROGRAM_VALID( | |
120 renderer()->GetNonPremultipliedTextureProgram(precision)); | |
121 EXPECT_PROGRAM_VALID(renderer()->GetTextureBackgroundProgram(precision)); | |
122 EXPECT_PROGRAM_VALID( | |
123 renderer()->GetNonPremultipliedTextureBackgroundProgram(precision)); | |
124 EXPECT_PROGRAM_VALID(renderer()->GetTextureIOSurfaceProgram(precision)); | |
125 EXPECT_PROGRAM_VALID(renderer()->GetVideoYUVProgram(precision)); | |
126 EXPECT_PROGRAM_VALID(renderer()->GetVideoYUVAProgram(precision)); | |
127 if (renderer()->Capabilities().using_egl_image) | |
128 EXPECT_PROGRAM_VALID(renderer()->GetVideoStreamTextureProgram(precision)); | |
129 else | |
130 EXPECT_FALSE(renderer()->GetVideoStreamTextureProgram(precision)); | |
131 } | |
132 | |
133 void TestShadersWithPrecisionAndBlend(TexCoordPrecision precision, | |
134 BlendMode blend_mode) { | |
135 EXPECT_PROGRAM_VALID( | |
136 renderer()->GetRenderPassProgram(precision, blend_mode)); | |
137 EXPECT_PROGRAM_VALID( | |
138 renderer()->GetRenderPassProgramAA(precision, blend_mode)); | |
139 } | |
140 | |
141 void TestShadersWithPrecisionAndSampler(TexCoordPrecision precision, | |
142 SamplerType sampler) { | |
143 if (!renderer()->Capabilities().using_egl_image && | |
144 sampler == SAMPLER_TYPE_EXTERNAL_OES) { | |
145 // This will likely be hit in tests due to usage of osmesa. | |
146 return; | |
147 } | |
148 | |
149 EXPECT_PROGRAM_VALID(renderer()->GetTileProgram(precision, sampler)); | |
150 EXPECT_PROGRAM_VALID(renderer()->GetTileProgramOpaque(precision, sampler)); | |
151 EXPECT_PROGRAM_VALID(renderer()->GetTileProgramAA(precision, sampler)); | |
152 EXPECT_PROGRAM_VALID(renderer()->GetTileProgramSwizzle(precision, sampler)); | |
153 EXPECT_PROGRAM_VALID( | |
154 renderer()->GetTileProgramSwizzleOpaque(precision, sampler)); | |
155 EXPECT_PROGRAM_VALID( | |
156 renderer()->GetTileProgramSwizzleAA(precision, sampler)); | |
157 } | |
158 | |
159 void TestShadersWithMasks(TexCoordPrecision precision, | |
160 SamplerType sampler, | |
161 BlendMode blend_mode, | |
162 bool mask_for_background) { | |
163 if (!renderer()->Capabilities().using_egl_image && | |
164 sampler == SAMPLER_TYPE_EXTERNAL_OES) { | |
165 // This will likely be hit in tests due to usage of osmesa. | |
166 return; | |
167 } | |
168 | |
169 EXPECT_PROGRAM_VALID(renderer()->GetRenderPassMaskProgram( | |
170 precision, sampler, blend_mode, mask_for_background)); | |
171 EXPECT_PROGRAM_VALID(renderer()->GetRenderPassMaskProgramAA( | |
172 precision, sampler, blend_mode, mask_for_background)); | |
173 EXPECT_PROGRAM_VALID(renderer()->GetRenderPassMaskColorMatrixProgramAA( | |
174 precision, sampler, blend_mode, mask_for_background)); | |
175 EXPECT_PROGRAM_VALID(renderer()->GetRenderPassMaskColorMatrixProgram( | |
176 precision, sampler, blend_mode, mask_for_background)); | |
177 } | |
178 }; | |
179 | |
180 namespace { | |
181 | |
182 #if !defined(OS_ANDROID) && !defined(OS_WIN) | |
183 static const TexCoordPrecision kPrecisionList[] = {TEX_COORD_PRECISION_MEDIUM, | |
184 TEX_COORD_PRECISION_HIGH}; | |
185 | |
186 static const BlendMode kBlendModeList[LAST_BLEND_MODE + 1] = { | |
187 BLEND_MODE_NONE, | |
188 BLEND_MODE_NORMAL, | |
189 BLEND_MODE_SCREEN, | |
190 BLEND_MODE_OVERLAY, | |
191 BLEND_MODE_DARKEN, | |
192 BLEND_MODE_LIGHTEN, | |
193 BLEND_MODE_COLOR_DODGE, | |
194 BLEND_MODE_COLOR_BURN, | |
195 BLEND_MODE_HARD_LIGHT, | |
196 BLEND_MODE_SOFT_LIGHT, | |
197 BLEND_MODE_DIFFERENCE, | |
198 BLEND_MODE_EXCLUSION, | |
199 BLEND_MODE_MULTIPLY, | |
200 BLEND_MODE_HUE, | |
201 BLEND_MODE_SATURATION, | |
202 BLEND_MODE_COLOR, | |
203 BLEND_MODE_LUMINOSITY, | |
204 }; | |
205 | |
206 static const SamplerType kSamplerList[] = { | |
207 SAMPLER_TYPE_2D, | |
208 SAMPLER_TYPE_2D_RECT, | |
209 SAMPLER_TYPE_EXTERNAL_OES, | |
210 }; | |
211 | |
212 TEST_F(GLRendererShaderPixelTest, BasicShadersCompile) { | |
213 TestBasicShaders(); | |
214 } | |
215 | |
216 class PrecisionShaderPixelTest | |
217 : public GLRendererShaderPixelTest, | |
218 public ::testing::WithParamInterface<TexCoordPrecision> {}; | |
219 | |
220 TEST_P(PrecisionShaderPixelTest, ShadersCompile) { | |
221 TestShadersWithPrecision(GetParam()); | |
222 } | |
223 | |
224 INSTANTIATE_TEST_CASE_P(PrecisionShadersCompile, | |
225 PrecisionShaderPixelTest, | |
226 ::testing::ValuesIn(kPrecisionList)); | |
227 | |
228 class PrecisionBlendShaderPixelTest | |
229 : public GLRendererShaderPixelTest, | |
230 public ::testing::WithParamInterface< | |
231 std::tr1::tuple<TexCoordPrecision, BlendMode>> {}; | |
232 | |
233 TEST_P(PrecisionBlendShaderPixelTest, ShadersCompile) { | |
234 TestShadersWithPrecisionAndBlend(std::tr1::get<0>(GetParam()), | |
235 std::tr1::get<1>(GetParam())); | |
236 } | |
237 | |
238 INSTANTIATE_TEST_CASE_P( | |
239 PrecisionBlendShadersCompile, | |
240 PrecisionBlendShaderPixelTest, | |
241 ::testing::Combine(::testing::ValuesIn(kPrecisionList), | |
242 ::testing::ValuesIn(kBlendModeList))); | |
243 | |
244 class PrecisionSamplerShaderPixelTest | |
245 : public GLRendererShaderPixelTest, | |
246 public ::testing::WithParamInterface< | |
247 std::tr1::tuple<TexCoordPrecision, SamplerType>> {}; | |
248 | |
249 TEST_P(PrecisionSamplerShaderPixelTest, ShadersCompile) { | |
250 TestShadersWithPrecisionAndSampler(std::tr1::get<0>(GetParam()), | |
251 std::tr1::get<1>(GetParam())); | |
252 } | |
253 | |
254 INSTANTIATE_TEST_CASE_P(PrecisionSamplerShadersCompile, | |
255 PrecisionSamplerShaderPixelTest, | |
256 ::testing::Combine(::testing::ValuesIn(kPrecisionList), | |
257 ::testing::ValuesIn(kSamplerList))); | |
258 | |
259 class MaskShaderPixelTest | |
260 : public GLRendererShaderPixelTest, | |
261 public ::testing::WithParamInterface< | |
262 std::tr1::tuple<TexCoordPrecision, SamplerType, BlendMode, bool>> {}; | |
263 | |
264 TEST_P(MaskShaderPixelTest, ShadersCompile) { | |
265 TestShadersWithMasks( | |
266 std::tr1::get<0>(GetParam()), std::tr1::get<1>(GetParam()), | |
267 std::tr1::get<2>(GetParam()), std::tr1::get<3>(GetParam())); | |
268 } | |
269 | |
270 INSTANTIATE_TEST_CASE_P(MaskShadersCompile, | |
271 MaskShaderPixelTest, | |
272 ::testing::Combine(::testing::ValuesIn(kPrecisionList), | |
273 ::testing::ValuesIn(kSamplerList), | |
274 ::testing::ValuesIn(kBlendModeList), | |
275 ::testing::Bool())); | |
276 | |
277 #endif | |
278 | |
279 class FakeRendererGL : public GLRenderer { | |
280 public: | |
281 FakeRendererGL(RendererClient* client, | |
282 const RendererSettings* settings, | |
283 OutputSurface* output_surface, | |
284 ResourceProvider* resource_provider) | |
285 : GLRenderer(client, | |
286 settings, | |
287 output_surface, | |
288 resource_provider, | |
289 NULL, | |
290 0) {} | |
291 | |
292 // GLRenderer methods. | |
293 | |
294 // Changing visibility to public. | |
295 using GLRenderer::IsBackbufferDiscarded; | |
296 using GLRenderer::DoDrawQuad; | |
297 using GLRenderer::BeginDrawingFrame; | |
298 using GLRenderer::FinishDrawingQuadList; | |
299 using GLRenderer::stencil_enabled; | |
300 }; | |
301 | |
302 class GLRendererWithDefaultHarnessTest : public GLRendererTest { | |
303 protected: | |
304 GLRendererWithDefaultHarnessTest() { | |
305 output_surface_ = | |
306 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()).Pass(); | |
307 CHECK(output_surface_->BindToClient(&output_surface_client_)); | |
308 | |
309 shared_bitmap_manager_.reset(new TestSharedBitmapManager()); | |
310 resource_provider_ = ResourceProvider::Create(output_surface_.get(), | |
311 shared_bitmap_manager_.get(), | |
312 NULL, | |
313 NULL, | |
314 0, | |
315 false, | |
316 1).Pass(); | |
317 renderer_ = make_scoped_ptr(new FakeRendererGL(&renderer_client_, | |
318 &settings_, | |
319 output_surface_.get(), | |
320 resource_provider_.get())); | |
321 } | |
322 | |
323 void SwapBuffers() { renderer_->SwapBuffers(CompositorFrameMetadata()); } | |
324 | |
325 RendererSettings settings_; | |
326 FakeOutputSurfaceClient output_surface_client_; | |
327 scoped_ptr<FakeOutputSurface> output_surface_; | |
328 FakeRendererClient renderer_client_; | |
329 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_; | |
330 scoped_ptr<ResourceProvider> resource_provider_; | |
331 scoped_ptr<FakeRendererGL> renderer_; | |
332 }; | |
333 | |
334 // Closing the namespace here so that GLRendererShaderTest can take advantage | |
335 // of the friend relationship with GLRenderer and all of the mock classes | |
336 // declared above it. | |
337 } // namespace | |
338 | |
339 class GLRendererShaderTest : public GLRendererTest { | |
340 protected: | |
341 GLRendererShaderTest() { | |
342 output_surface_ = FakeOutputSurface::Create3d().Pass(); | |
343 CHECK(output_surface_->BindToClient(&output_surface_client_)); | |
344 | |
345 shared_bitmap_manager_.reset(new TestSharedBitmapManager()); | |
346 resource_provider_ = ResourceProvider::Create(output_surface_.get(), | |
347 shared_bitmap_manager_.get(), | |
348 NULL, | |
349 NULL, | |
350 0, | |
351 false, | |
352 1).Pass(); | |
353 renderer_.reset(new FakeRendererGL(&renderer_client_, | |
354 &settings_, | |
355 output_surface_.get(), | |
356 resource_provider_.get())); | |
357 } | |
358 | |
359 void TestRenderPassProgram(TexCoordPrecision precision, | |
360 BlendMode blend_mode) { | |
361 EXPECT_PROGRAM_VALID( | |
362 &renderer_->render_pass_program_[precision][blend_mode]); | |
363 EXPECT_EQ(renderer_->render_pass_program_[precision][blend_mode].program(), | |
364 renderer_->program_shadow_); | |
365 } | |
366 | |
367 void TestRenderPassColorMatrixProgram(TexCoordPrecision precision, | |
368 BlendMode blend_mode) { | |
369 EXPECT_PROGRAM_VALID( | |
370 &renderer_->render_pass_color_matrix_program_[precision][blend_mode]); | |
371 EXPECT_EQ( | |
372 renderer_->render_pass_color_matrix_program_[precision][blend_mode] | |
373 .program(), | |
374 renderer_->program_shadow_); | |
375 } | |
376 | |
377 void TestRenderPassMaskProgram(TexCoordPrecision precision, | |
378 SamplerType sampler, | |
379 BlendMode blend_mode) { | |
380 EXPECT_PROGRAM_VALID( | |
381 &renderer_->render_pass_mask_program_[precision] | |
382 [sampler] | |
383 [blend_mode] | |
384 [NO_MASK]); | |
385 EXPECT_EQ( | |
386 renderer_->render_pass_mask_program_[precision] | |
387 [sampler] | |
388 [blend_mode] | |
389 [NO_MASK].program(), | |
390 renderer_->program_shadow_); | |
391 } | |
392 | |
393 void TestRenderPassMaskColorMatrixProgram(TexCoordPrecision precision, | |
394 SamplerType sampler, | |
395 BlendMode blend_mode) { | |
396 EXPECT_PROGRAM_VALID(&renderer_->render_pass_mask_color_matrix_program_ | |
397 [precision][sampler][blend_mode][NO_MASK]); | |
398 EXPECT_EQ(renderer_->render_pass_mask_color_matrix_program_ | |
399 [precision][sampler][blend_mode][NO_MASK].program(), | |
400 renderer_->program_shadow_); | |
401 } | |
402 | |
403 void TestRenderPassProgramAA(TexCoordPrecision precision, | |
404 BlendMode blend_mode) { | |
405 EXPECT_PROGRAM_VALID( | |
406 &renderer_->render_pass_program_aa_[precision][blend_mode]); | |
407 EXPECT_EQ( | |
408 renderer_->render_pass_program_aa_[precision][blend_mode].program(), | |
409 renderer_->program_shadow_); | |
410 } | |
411 | |
412 void TestRenderPassColorMatrixProgramAA(TexCoordPrecision precision, | |
413 BlendMode blend_mode) { | |
414 EXPECT_PROGRAM_VALID( | |
415 &renderer_ | |
416 ->render_pass_color_matrix_program_aa_[precision][blend_mode]); | |
417 EXPECT_EQ( | |
418 renderer_->render_pass_color_matrix_program_aa_[precision][blend_mode] | |
419 .program(), | |
420 renderer_->program_shadow_); | |
421 } | |
422 | |
423 void TestRenderPassMaskProgramAA(TexCoordPrecision precision, | |
424 SamplerType sampler, | |
425 BlendMode blend_mode) { | |
426 EXPECT_PROGRAM_VALID( | |
427 &renderer_ | |
428 ->render_pass_mask_program_aa_ | |
429 [precision][sampler][blend_mode][NO_MASK]); | |
430 EXPECT_EQ( | |
431 renderer_->render_pass_mask_program_aa_[precision][sampler][blend_mode] | |
432 [NO_MASK].program(), | |
433 renderer_->program_shadow_); | |
434 } | |
435 | |
436 void TestRenderPassMaskColorMatrixProgramAA(TexCoordPrecision precision, | |
437 SamplerType sampler, | |
438 BlendMode blend_mode) { | |
439 EXPECT_PROGRAM_VALID(&renderer_->render_pass_mask_color_matrix_program_aa_ | |
440 [precision][sampler][blend_mode][NO_MASK]); | |
441 EXPECT_EQ(renderer_->render_pass_mask_color_matrix_program_aa_ | |
442 [precision][sampler][blend_mode][NO_MASK].program(), | |
443 renderer_->program_shadow_); | |
444 } | |
445 | |
446 void TestSolidColorProgramAA() { | |
447 EXPECT_PROGRAM_VALID(&renderer_->solid_color_program_aa_); | |
448 EXPECT_EQ(renderer_->solid_color_program_aa_.program(), | |
449 renderer_->program_shadow_); | |
450 } | |
451 | |
452 RendererSettings settings_; | |
453 FakeOutputSurfaceClient output_surface_client_; | |
454 scoped_ptr<FakeOutputSurface> output_surface_; | |
455 FakeRendererClient renderer_client_; | |
456 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_; | |
457 scoped_ptr<ResourceProvider> resource_provider_; | |
458 scoped_ptr<FakeRendererGL> renderer_; | |
459 }; | |
460 | |
461 namespace { | |
462 | |
463 // Test GLRenderer DiscardBackbuffer functionality: | |
464 // Suggest discarding framebuffer when one exists and the renderer is not | |
465 // visible. | |
466 // Expected: it is discarded and damage tracker is reset. | |
467 TEST_F( | |
468 GLRendererWithDefaultHarnessTest, | |
469 SuggestBackbufferNoShouldDiscardBackbufferAndDamageRootLayerIfNotVisible) { | |
470 renderer_->SetVisible(false); | |
471 EXPECT_EQ(1, renderer_client_.set_full_root_layer_damage_count()); | |
472 EXPECT_TRUE(renderer_->IsBackbufferDiscarded()); | |
473 } | |
474 | |
475 // Test GLRenderer DiscardBackbuffer functionality: | |
476 // Suggest discarding framebuffer when one exists and the renderer is visible. | |
477 // Expected: the allocation is ignored. | |
478 TEST_F(GLRendererWithDefaultHarnessTest, | |
479 SuggestBackbufferNoDoNothingWhenVisible) { | |
480 renderer_->SetVisible(true); | |
481 EXPECT_EQ(0, renderer_client_.set_full_root_layer_damage_count()); | |
482 EXPECT_FALSE(renderer_->IsBackbufferDiscarded()); | |
483 } | |
484 | |
485 // Test GLRenderer DiscardBackbuffer functionality: | |
486 // Suggest discarding framebuffer when one does not exist. | |
487 // Expected: it does nothing. | |
488 TEST_F(GLRendererWithDefaultHarnessTest, | |
489 SuggestBackbufferNoWhenItDoesntExistShouldDoNothing) { | |
490 renderer_->SetVisible(false); | |
491 EXPECT_EQ(1, renderer_client_.set_full_root_layer_damage_count()); | |
492 EXPECT_TRUE(renderer_->IsBackbufferDiscarded()); | |
493 | |
494 EXPECT_EQ(1, renderer_client_.set_full_root_layer_damage_count()); | |
495 EXPECT_TRUE(renderer_->IsBackbufferDiscarded()); | |
496 } | |
497 | |
498 // Test GLRenderer DiscardBackbuffer functionality: | |
499 // Begin drawing a frame while a framebuffer is discarded. | |
500 // Expected: will recreate framebuffer. | |
501 TEST_F(GLRendererWithDefaultHarnessTest, | |
502 DiscardedBackbufferIsRecreatedForScopeDuration) { | |
503 gfx::Rect viewport_rect(1, 1); | |
504 renderer_->SetVisible(false); | |
505 EXPECT_TRUE(renderer_->IsBackbufferDiscarded()); | |
506 EXPECT_EQ(1, renderer_client_.set_full_root_layer_damage_count()); | |
507 | |
508 AddRenderPass(&render_passes_in_draw_order_, | |
509 RenderPassId(1, 0), | |
510 viewport_rect, | |
511 gfx::Transform()); | |
512 | |
513 renderer_->SetVisible(true); | |
514 renderer_->DrawFrame(&render_passes_in_draw_order_, | |
515 1.f, | |
516 viewport_rect, | |
517 viewport_rect, | |
518 false); | |
519 EXPECT_FALSE(renderer_->IsBackbufferDiscarded()); | |
520 | |
521 SwapBuffers(); | |
522 EXPECT_EQ(1u, output_surface_->num_sent_frames()); | |
523 } | |
524 | |
525 TEST_F(GLRendererWithDefaultHarnessTest, ExternalStencil) { | |
526 gfx::Rect viewport_rect(1, 1); | |
527 EXPECT_FALSE(renderer_->stencil_enabled()); | |
528 | |
529 output_surface_->set_has_external_stencil_test(true); | |
530 | |
531 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_, | |
532 RenderPassId(1, 0), | |
533 viewport_rect, | |
534 gfx::Transform()); | |
535 root_pass->has_transparent_background = false; | |
536 | |
537 renderer_->DrawFrame(&render_passes_in_draw_order_, | |
538 1.f, | |
539 viewport_rect, | |
540 viewport_rect, | |
541 false); | |
542 EXPECT_TRUE(renderer_->stencil_enabled()); | |
543 } | |
544 | |
545 class ForbidSynchronousCallContext : public TestWebGraphicsContext3D { | |
546 public: | |
547 ForbidSynchronousCallContext() {} | |
548 | |
549 void getAttachedShaders(GLuint program, | |
550 GLsizei max_count, | |
551 GLsizei* count, | |
552 GLuint* shaders) override { | |
553 ADD_FAILURE(); | |
554 } | |
555 GLint getAttribLocation(GLuint program, const GLchar* name) override { | |
556 ADD_FAILURE(); | |
557 return 0; | |
558 } | |
559 void getBooleanv(GLenum pname, GLboolean* value) override { ADD_FAILURE(); } | |
560 void getBufferParameteriv(GLenum target, | |
561 GLenum pname, | |
562 GLint* value) override { | |
563 ADD_FAILURE(); | |
564 } | |
565 GLenum getError() override { | |
566 ADD_FAILURE(); | |
567 return GL_NO_ERROR; | |
568 } | |
569 void getFloatv(GLenum pname, GLfloat* value) override { ADD_FAILURE(); } | |
570 void getFramebufferAttachmentParameteriv(GLenum target, | |
571 GLenum attachment, | |
572 GLenum pname, | |
573 GLint* value) override { | |
574 ADD_FAILURE(); | |
575 } | |
576 void getIntegerv(GLenum pname, GLint* value) override { | |
577 if (pname == GL_MAX_TEXTURE_SIZE) { | |
578 // MAX_TEXTURE_SIZE is cached client side, so it's OK to query. | |
579 *value = 1024; | |
580 } else { | |
581 ADD_FAILURE(); | |
582 } | |
583 } | |
584 | |
585 // We allow querying the shader compilation and program link status in debug | |
586 // mode, but not release. | |
587 void getProgramiv(GLuint program, GLenum pname, GLint* value) override { | |
588 #ifndef NDEBUG | |
589 *value = 1; | |
590 #else | |
591 ADD_FAILURE(); | |
592 #endif | |
593 } | |
594 | |
595 void getShaderiv(GLuint shader, GLenum pname, GLint* value) override { | |
596 #ifndef NDEBUG | |
597 *value = 1; | |
598 #else | |
599 ADD_FAILURE(); | |
600 #endif | |
601 } | |
602 | |
603 void getRenderbufferParameteriv(GLenum target, | |
604 GLenum pname, | |
605 GLint* value) override { | |
606 ADD_FAILURE(); | |
607 } | |
608 | |
609 void getShaderPrecisionFormat(GLenum shadertype, | |
610 GLenum precisiontype, | |
611 GLint* range, | |
612 GLint* precision) override { | |
613 ADD_FAILURE(); | |
614 } | |
615 void getTexParameterfv(GLenum target, GLenum pname, GLfloat* value) override { | |
616 ADD_FAILURE(); | |
617 } | |
618 void getTexParameteriv(GLenum target, GLenum pname, GLint* value) override { | |
619 ADD_FAILURE(); | |
620 } | |
621 void getUniformfv(GLuint program, GLint location, GLfloat* value) override { | |
622 ADD_FAILURE(); | |
623 } | |
624 void getUniformiv(GLuint program, GLint location, GLint* value) override { | |
625 ADD_FAILURE(); | |
626 } | |
627 GLint getUniformLocation(GLuint program, const GLchar* name) override { | |
628 ADD_FAILURE(); | |
629 return 0; | |
630 } | |
631 void getVertexAttribfv(GLuint index, GLenum pname, GLfloat* value) override { | |
632 ADD_FAILURE(); | |
633 } | |
634 void getVertexAttribiv(GLuint index, GLenum pname, GLint* value) override { | |
635 ADD_FAILURE(); | |
636 } | |
637 GLsizeiptr getVertexAttribOffset(GLuint index, GLenum pname) override { | |
638 ADD_FAILURE(); | |
639 return 0; | |
640 } | |
641 }; | |
642 TEST_F(GLRendererTest, InitializationDoesNotMakeSynchronousCalls) { | |
643 FakeOutputSurfaceClient output_surface_client; | |
644 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d( | |
645 scoped_ptr<TestWebGraphicsContext3D>(new ForbidSynchronousCallContext))); | |
646 CHECK(output_surface->BindToClient(&output_surface_client)); | |
647 | |
648 scoped_ptr<SharedBitmapManager> shared_bitmap_manager( | |
649 new TestSharedBitmapManager()); | |
650 scoped_ptr<ResourceProvider> resource_provider( | |
651 ResourceProvider::Create(output_surface.get(), | |
652 shared_bitmap_manager.get(), | |
653 NULL, | |
654 NULL, | |
655 0, | |
656 false, | |
657 1)); | |
658 | |
659 RendererSettings settings; | |
660 FakeRendererClient renderer_client; | |
661 FakeRendererGL renderer(&renderer_client, | |
662 &settings, | |
663 output_surface.get(), | |
664 resource_provider.get()); | |
665 } | |
666 | |
667 class LoseContextOnFirstGetContext : public TestWebGraphicsContext3D { | |
668 public: | |
669 LoseContextOnFirstGetContext() {} | |
670 | |
671 void getProgramiv(GLuint program, GLenum pname, GLint* value) override { | |
672 context_lost_ = true; | |
673 *value = 0; | |
674 } | |
675 | |
676 void getShaderiv(GLuint shader, GLenum pname, GLint* value) override { | |
677 context_lost_ = true; | |
678 *value = 0; | |
679 } | |
680 }; | |
681 | |
682 TEST_F(GLRendererTest, InitializationWithQuicklyLostContextDoesNotAssert) { | |
683 FakeOutputSurfaceClient output_surface_client; | |
684 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d( | |
685 scoped_ptr<TestWebGraphicsContext3D>(new LoseContextOnFirstGetContext))); | |
686 CHECK(output_surface->BindToClient(&output_surface_client)); | |
687 | |
688 scoped_ptr<SharedBitmapManager> shared_bitmap_manager( | |
689 new TestSharedBitmapManager()); | |
690 scoped_ptr<ResourceProvider> resource_provider( | |
691 ResourceProvider::Create(output_surface.get(), | |
692 shared_bitmap_manager.get(), | |
693 NULL, | |
694 NULL, | |
695 0, | |
696 false, | |
697 1)); | |
698 | |
699 RendererSettings settings; | |
700 FakeRendererClient renderer_client; | |
701 FakeRendererGL renderer(&renderer_client, | |
702 &settings, | |
703 output_surface.get(), | |
704 resource_provider.get()); | |
705 } | |
706 | |
707 class ClearCountingContext : public TestWebGraphicsContext3D { | |
708 public: | |
709 ClearCountingContext() { test_capabilities_.gpu.discard_framebuffer = true; } | |
710 | |
711 MOCK_METHOD3(discardFramebufferEXT, | |
712 void(GLenum target, | |
713 GLsizei numAttachments, | |
714 const GLenum* attachments)); | |
715 MOCK_METHOD1(clear, void(GLbitfield mask)); | |
716 }; | |
717 | |
718 TEST_F(GLRendererTest, OpaqueBackground) { | |
719 scoped_ptr<ClearCountingContext> context_owned(new ClearCountingContext); | |
720 ClearCountingContext* context = context_owned.get(); | |
721 | |
722 FakeOutputSurfaceClient output_surface_client; | |
723 scoped_ptr<OutputSurface> output_surface( | |
724 FakeOutputSurface::Create3d(context_owned.Pass())); | |
725 CHECK(output_surface->BindToClient(&output_surface_client)); | |
726 | |
727 scoped_ptr<SharedBitmapManager> shared_bitmap_manager( | |
728 new TestSharedBitmapManager()); | |
729 scoped_ptr<ResourceProvider> resource_provider( | |
730 ResourceProvider::Create(output_surface.get(), | |
731 shared_bitmap_manager.get(), | |
732 NULL, | |
733 NULL, | |
734 0, | |
735 false, | |
736 1)); | |
737 | |
738 RendererSettings settings; | |
739 FakeRendererClient renderer_client; | |
740 FakeRendererGL renderer(&renderer_client, | |
741 &settings, | |
742 output_surface.get(), | |
743 resource_provider.get()); | |
744 | |
745 gfx::Rect viewport_rect(1, 1); | |
746 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_, | |
747 RenderPassId(1, 0), | |
748 viewport_rect, | |
749 gfx::Transform()); | |
750 root_pass->has_transparent_background = false; | |
751 | |
752 // On DEBUG builds, render passes with opaque background clear to blue to | |
753 // easily see regions that were not drawn on the screen. | |
754 EXPECT_CALL(*context, discardFramebufferEXT(GL_FRAMEBUFFER, _, _)) | |
755 .With(Args<2, 1>(ElementsAre(GL_COLOR_EXT))) | |
756 .Times(1); | |
757 #ifdef NDEBUG | |
758 EXPECT_CALL(*context, clear(_)).Times(0); | |
759 #else | |
760 EXPECT_CALL(*context, clear(_)).Times(1); | |
761 #endif | |
762 renderer.DrawFrame(&render_passes_in_draw_order_, | |
763 1.f, | |
764 viewport_rect, | |
765 viewport_rect, | |
766 false); | |
767 Mock::VerifyAndClearExpectations(context); | |
768 } | |
769 | |
770 TEST_F(GLRendererTest, TransparentBackground) { | |
771 scoped_ptr<ClearCountingContext> context_owned(new ClearCountingContext); | |
772 ClearCountingContext* context = context_owned.get(); | |
773 | |
774 FakeOutputSurfaceClient output_surface_client; | |
775 scoped_ptr<OutputSurface> output_surface( | |
776 FakeOutputSurface::Create3d(context_owned.Pass())); | |
777 CHECK(output_surface->BindToClient(&output_surface_client)); | |
778 | |
779 scoped_ptr<SharedBitmapManager> shared_bitmap_manager( | |
780 new TestSharedBitmapManager()); | |
781 scoped_ptr<ResourceProvider> resource_provider( | |
782 ResourceProvider::Create(output_surface.get(), | |
783 shared_bitmap_manager.get(), | |
784 NULL, | |
785 NULL, | |
786 0, | |
787 false, | |
788 1)); | |
789 | |
790 RendererSettings settings; | |
791 FakeRendererClient renderer_client; | |
792 FakeRendererGL renderer(&renderer_client, | |
793 &settings, | |
794 output_surface.get(), | |
795 resource_provider.get()); | |
796 | |
797 gfx::Rect viewport_rect(1, 1); | |
798 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_, | |
799 RenderPassId(1, 0), | |
800 viewport_rect, | |
801 gfx::Transform()); | |
802 root_pass->has_transparent_background = true; | |
803 | |
804 EXPECT_CALL(*context, discardFramebufferEXT(GL_FRAMEBUFFER, 1, _)).Times(1); | |
805 EXPECT_CALL(*context, clear(_)).Times(1); | |
806 renderer.DrawFrame(&render_passes_in_draw_order_, | |
807 1.f, | |
808 viewport_rect, | |
809 viewport_rect, | |
810 false); | |
811 | |
812 Mock::VerifyAndClearExpectations(context); | |
813 } | |
814 | |
815 TEST_F(GLRendererTest, OffscreenOutputSurface) { | |
816 scoped_ptr<ClearCountingContext> context_owned(new ClearCountingContext); | |
817 ClearCountingContext* context = context_owned.get(); | |
818 | |
819 FakeOutputSurfaceClient output_surface_client; | |
820 scoped_ptr<OutputSurface> output_surface( | |
821 FakeOutputSurface::CreateOffscreen(context_owned.Pass())); | |
822 CHECK(output_surface->BindToClient(&output_surface_client)); | |
823 | |
824 scoped_ptr<SharedBitmapManager> shared_bitmap_manager( | |
825 new TestSharedBitmapManager()); | |
826 scoped_ptr<ResourceProvider> resource_provider( | |
827 ResourceProvider::Create(output_surface.get(), | |
828 shared_bitmap_manager.get(), | |
829 NULL, | |
830 NULL, | |
831 0, | |
832 false, | |
833 1)); | |
834 | |
835 RendererSettings settings; | |
836 FakeRendererClient renderer_client; | |
837 FakeRendererGL renderer(&renderer_client, | |
838 &settings, | |
839 output_surface.get(), | |
840 resource_provider.get()); | |
841 | |
842 gfx::Rect viewport_rect(1, 1); | |
843 AddRenderPass(&render_passes_in_draw_order_, | |
844 RenderPassId(1, 0), | |
845 viewport_rect, | |
846 gfx::Transform()); | |
847 | |
848 EXPECT_CALL(*context, discardFramebufferEXT(GL_FRAMEBUFFER, _, _)) | |
849 .With(Args<2, 1>(ElementsAre(GL_COLOR_ATTACHMENT0))) | |
850 .Times(1); | |
851 EXPECT_CALL(*context, clear(_)).Times(AnyNumber()); | |
852 renderer.DrawFrame(&render_passes_in_draw_order_, | |
853 1.f, | |
854 viewport_rect, | |
855 viewport_rect, | |
856 false); | |
857 Mock::VerifyAndClearExpectations(context); | |
858 } | |
859 | |
860 class VisibilityChangeIsLastCallTrackingContext | |
861 : public TestWebGraphicsContext3D { | |
862 public: | |
863 VisibilityChangeIsLastCallTrackingContext() | |
864 : last_call_was_set_visibility_(false) {} | |
865 | |
866 // TestWebGraphicsContext3D methods. | |
867 void flush() override { last_call_was_set_visibility_ = false; } | |
868 void deleteTexture(GLuint) override { last_call_was_set_visibility_ = false; } | |
869 void deleteFramebuffer(GLuint) override { | |
870 last_call_was_set_visibility_ = false; | |
871 } | |
872 void deleteQueryEXT(GLuint) override { | |
873 last_call_was_set_visibility_ = false; | |
874 } | |
875 void deleteRenderbuffer(GLuint) override { | |
876 last_call_was_set_visibility_ = false; | |
877 } | |
878 | |
879 // Methods added for test. | |
880 void set_last_call_was_visibility(bool visible) { | |
881 DCHECK(last_call_was_set_visibility_ == false); | |
882 last_call_was_set_visibility_ = true; | |
883 } | |
884 bool last_call_was_set_visibility() const { | |
885 return last_call_was_set_visibility_; | |
886 } | |
887 | |
888 private: | |
889 bool last_call_was_set_visibility_; | |
890 }; | |
891 | |
892 TEST_F(GLRendererTest, VisibilityChangeIsLastCall) { | |
893 scoped_ptr<VisibilityChangeIsLastCallTrackingContext> context_owned( | |
894 new VisibilityChangeIsLastCallTrackingContext); | |
895 VisibilityChangeIsLastCallTrackingContext* context = context_owned.get(); | |
896 | |
897 scoped_refptr<TestContextProvider> provider = | |
898 TestContextProvider::Create(context_owned.Pass()); | |
899 | |
900 provider->support()->SetSurfaceVisibleCallback(base::Bind( | |
901 &VisibilityChangeIsLastCallTrackingContext::set_last_call_was_visibility, | |
902 base::Unretained(context))); | |
903 | |
904 FakeOutputSurfaceClient output_surface_client; | |
905 scoped_ptr<OutputSurface> output_surface( | |
906 FakeOutputSurface::Create3d(provider)); | |
907 CHECK(output_surface->BindToClient(&output_surface_client)); | |
908 | |
909 scoped_ptr<SharedBitmapManager> shared_bitmap_manager( | |
910 new TestSharedBitmapManager()); | |
911 scoped_ptr<ResourceProvider> resource_provider( | |
912 ResourceProvider::Create(output_surface.get(), | |
913 shared_bitmap_manager.get(), | |
914 NULL, | |
915 NULL, | |
916 0, | |
917 false, | |
918 1)); | |
919 | |
920 RendererSettings settings; | |
921 FakeRendererClient renderer_client; | |
922 FakeRendererGL renderer(&renderer_client, | |
923 &settings, | |
924 output_surface.get(), | |
925 resource_provider.get()); | |
926 | |
927 gfx::Rect viewport_rect(1, 1); | |
928 AddRenderPass(&render_passes_in_draw_order_, | |
929 RenderPassId(1, 0), | |
930 viewport_rect, | |
931 gfx::Transform()); | |
932 | |
933 // Ensure that the call to SetSurfaceVisible is the last call issue to the | |
934 // GPU process, after glFlush is called, and after the RendererClient's | |
935 // SetManagedMemoryPolicy is called. Plumb this tracking between both the | |
936 // RenderClient and the Context by giving them both a pointer to a variable on | |
937 // the stack. | |
938 renderer.SetVisible(true); | |
939 renderer.DrawFrame(&render_passes_in_draw_order_, | |
940 1.f, | |
941 viewport_rect, | |
942 viewport_rect, | |
943 false); | |
944 renderer.SetVisible(false); | |
945 EXPECT_TRUE(context->last_call_was_set_visibility()); | |
946 } | |
947 | |
948 class TextureStateTrackingContext : public TestWebGraphicsContext3D { | |
949 public: | |
950 TextureStateTrackingContext() : active_texture_(GL_INVALID_ENUM) { | |
951 test_capabilities_.gpu.egl_image_external = true; | |
952 } | |
953 | |
954 MOCK_METHOD1(waitSyncPoint, void(unsigned sync_point)); | |
955 MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param)); | |
956 MOCK_METHOD4(drawElements, | |
957 void(GLenum mode, GLsizei count, GLenum type, GLintptr offset)); | |
958 | |
959 virtual void activeTexture(GLenum texture) { | |
960 EXPECT_NE(texture, active_texture_); | |
961 active_texture_ = texture; | |
962 } | |
963 | |
964 GLenum active_texture() const { return active_texture_; } | |
965 | |
966 private: | |
967 GLenum active_texture_; | |
968 }; | |
969 | |
970 TEST_F(GLRendererTest, ActiveTextureState) { | |
971 scoped_ptr<TextureStateTrackingContext> context_owned( | |
972 new TextureStateTrackingContext); | |
973 TextureStateTrackingContext* context = context_owned.get(); | |
974 | |
975 FakeOutputSurfaceClient output_surface_client; | |
976 scoped_ptr<OutputSurface> output_surface( | |
977 FakeOutputSurface::Create3d(context_owned.Pass())); | |
978 CHECK(output_surface->BindToClient(&output_surface_client)); | |
979 | |
980 scoped_ptr<SharedBitmapManager> shared_bitmap_manager( | |
981 new TestSharedBitmapManager()); | |
982 scoped_ptr<ResourceProvider> resource_provider( | |
983 ResourceProvider::Create(output_surface.get(), | |
984 shared_bitmap_manager.get(), | |
985 NULL, | |
986 NULL, | |
987 0, | |
988 false, | |
989 1)); | |
990 | |
991 RendererSettings settings; | |
992 FakeRendererClient renderer_client; | |
993 FakeRendererGL renderer(&renderer_client, | |
994 &settings, | |
995 output_surface.get(), | |
996 resource_provider.get()); | |
997 | |
998 // During initialization we are allowed to set any texture parameters. | |
999 EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber()); | |
1000 | |
1001 RenderPassId id(1, 1); | |
1002 TestRenderPass* root_pass = AddRenderPass( | |
1003 &render_passes_in_draw_order_, id, gfx::Rect(100, 100), gfx::Transform()); | |
1004 root_pass->AppendOneOfEveryQuadType(resource_provider.get(), | |
1005 RenderPassId(2, 1)); | |
1006 | |
1007 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_); | |
1008 | |
1009 // Set up expected texture filter state transitions that match the quads | |
1010 // created in AppendOneOfEveryQuadType(). | |
1011 Mock::VerifyAndClearExpectations(context); | |
1012 { | |
1013 InSequence sequence; | |
1014 | |
1015 // The sync points for all quads are waited on first. This sync point is | |
1016 // for a texture quad drawn later in the frame. | |
1017 EXPECT_CALL(*context, | |
1018 waitSyncPoint(TestRenderPass::kSyncPointForMailboxTextureQuad)) | |
1019 .Times(1); | |
1020 | |
1021 // yuv_quad is drawn with the default linear filter. | |
1022 EXPECT_CALL(*context, drawElements(_, _, _, _)); | |
1023 | |
1024 // tile_quad is drawn with GL_NEAREST because it is not transformed or | |
1025 // scaled. | |
1026 EXPECT_CALL( | |
1027 *context, | |
1028 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); | |
1029 EXPECT_CALL( | |
1030 *context, | |
1031 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); | |
1032 EXPECT_CALL(*context, drawElements(_, _, _, _)); | |
1033 | |
1034 // transformed_tile_quad uses GL_LINEAR. | |
1035 EXPECT_CALL(*context, drawElements(_, _, _, _)); | |
1036 | |
1037 // scaled_tile_quad also uses GL_LINEAR. | |
1038 EXPECT_CALL(*context, drawElements(_, _, _, _)); | |
1039 | |
1040 // The remaining quads also use GL_LINEAR because nearest neighbor | |
1041 // filtering is currently only used with tile quads. | |
1042 EXPECT_CALL(*context, drawElements(_, _, _, _)).Times(7); | |
1043 } | |
1044 | |
1045 gfx::Rect viewport_rect(100, 100); | |
1046 renderer.DrawFrame(&render_passes_in_draw_order_, | |
1047 1.f, | |
1048 viewport_rect, | |
1049 viewport_rect, | |
1050 false); | |
1051 Mock::VerifyAndClearExpectations(context); | |
1052 } | |
1053 | |
1054 class NoClearRootRenderPassMockContext : public TestWebGraphicsContext3D { | |
1055 public: | |
1056 MOCK_METHOD1(clear, void(GLbitfield mask)); | |
1057 MOCK_METHOD4(drawElements, | |
1058 void(GLenum mode, GLsizei count, GLenum type, GLintptr offset)); | |
1059 }; | |
1060 | |
1061 TEST_F(GLRendererTest, ShouldClearRootRenderPass) { | |
1062 scoped_ptr<NoClearRootRenderPassMockContext> mock_context_owned( | |
1063 new NoClearRootRenderPassMockContext); | |
1064 NoClearRootRenderPassMockContext* mock_context = mock_context_owned.get(); | |
1065 | |
1066 FakeOutputSurfaceClient output_surface_client; | |
1067 scoped_ptr<OutputSurface> output_surface( | |
1068 FakeOutputSurface::Create3d(mock_context_owned.Pass())); | |
1069 CHECK(output_surface->BindToClient(&output_surface_client)); | |
1070 | |
1071 scoped_ptr<SharedBitmapManager> shared_bitmap_manager( | |
1072 new TestSharedBitmapManager()); | |
1073 scoped_ptr<ResourceProvider> resource_provider( | |
1074 ResourceProvider::Create(output_surface.get(), | |
1075 shared_bitmap_manager.get(), | |
1076 NULL, | |
1077 NULL, | |
1078 0, | |
1079 false, | |
1080 1)); | |
1081 | |
1082 RendererSettings settings; | |
1083 settings.should_clear_root_render_pass = false; | |
1084 | |
1085 FakeRendererClient renderer_client; | |
1086 FakeRendererGL renderer(&renderer_client, | |
1087 &settings, | |
1088 output_surface.get(), | |
1089 resource_provider.get()); | |
1090 | |
1091 gfx::Rect viewport_rect(10, 10); | |
1092 | |
1093 RenderPassId root_pass_id(1, 0); | |
1094 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1095 root_pass_id, | |
1096 viewport_rect, | |
1097 gfx::Transform()); | |
1098 AddQuad(root_pass, viewport_rect, SK_ColorGREEN); | |
1099 | |
1100 RenderPassId child_pass_id(2, 0); | |
1101 TestRenderPass* child_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1102 child_pass_id, | |
1103 viewport_rect, | |
1104 gfx::Transform()); | |
1105 AddQuad(child_pass, viewport_rect, SK_ColorBLUE); | |
1106 | |
1107 AddRenderPassQuad(root_pass, child_pass); | |
1108 | |
1109 #ifdef NDEBUG | |
1110 GLint clear_bits = GL_COLOR_BUFFER_BIT; | |
1111 #else | |
1112 GLint clear_bits = GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; | |
1113 #endif | |
1114 | |
1115 // First render pass is not the root one, clearing should happen. | |
1116 EXPECT_CALL(*mock_context, clear(clear_bits)).Times(AtLeast(1)); | |
1117 | |
1118 Expectation first_render_pass = | |
1119 EXPECT_CALL(*mock_context, drawElements(_, _, _, _)).Times(1); | |
1120 | |
1121 // The second render pass is the root one, clearing should be prevented. | |
1122 EXPECT_CALL(*mock_context, clear(clear_bits)).Times(0).After( | |
1123 first_render_pass); | |
1124 | |
1125 EXPECT_CALL(*mock_context, drawElements(_, _, _, _)).Times(AnyNumber()).After( | |
1126 first_render_pass); | |
1127 | |
1128 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_); | |
1129 renderer.DrawFrame(&render_passes_in_draw_order_, | |
1130 1.f, | |
1131 viewport_rect, | |
1132 viewport_rect, | |
1133 false); | |
1134 | |
1135 // In multiple render passes all but the root pass should clear the | |
1136 // framebuffer. | |
1137 Mock::VerifyAndClearExpectations(&mock_context); | |
1138 } | |
1139 | |
1140 class ScissorTestOnClearCheckingContext : public TestWebGraphicsContext3D { | |
1141 public: | |
1142 ScissorTestOnClearCheckingContext() : scissor_enabled_(false) {} | |
1143 | |
1144 void clear(GLbitfield) override { EXPECT_FALSE(scissor_enabled_); } | |
1145 | |
1146 void enable(GLenum cap) override { | |
1147 if (cap == GL_SCISSOR_TEST) | |
1148 scissor_enabled_ = true; | |
1149 } | |
1150 | |
1151 void disable(GLenum cap) override { | |
1152 if (cap == GL_SCISSOR_TEST) | |
1153 scissor_enabled_ = false; | |
1154 } | |
1155 | |
1156 private: | |
1157 bool scissor_enabled_; | |
1158 }; | |
1159 | |
1160 TEST_F(GLRendererTest, ScissorTestWhenClearing) { | |
1161 scoped_ptr<ScissorTestOnClearCheckingContext> context_owned( | |
1162 new ScissorTestOnClearCheckingContext); | |
1163 | |
1164 FakeOutputSurfaceClient output_surface_client; | |
1165 scoped_ptr<OutputSurface> output_surface( | |
1166 FakeOutputSurface::Create3d(context_owned.Pass())); | |
1167 CHECK(output_surface->BindToClient(&output_surface_client)); | |
1168 | |
1169 scoped_ptr<SharedBitmapManager> shared_bitmap_manager( | |
1170 new TestSharedBitmapManager()); | |
1171 scoped_ptr<ResourceProvider> resource_provider( | |
1172 ResourceProvider::Create(output_surface.get(), | |
1173 shared_bitmap_manager.get(), | |
1174 NULL, | |
1175 NULL, | |
1176 0, | |
1177 false, | |
1178 1)); | |
1179 | |
1180 RendererSettings settings; | |
1181 FakeRendererClient renderer_client; | |
1182 FakeRendererGL renderer(&renderer_client, | |
1183 &settings, | |
1184 output_surface.get(), | |
1185 resource_provider.get()); | |
1186 EXPECT_FALSE(renderer.Capabilities().using_partial_swap); | |
1187 | |
1188 gfx::Rect viewport_rect(1, 1); | |
1189 | |
1190 gfx::Rect grand_child_rect(25, 25); | |
1191 RenderPassId grand_child_pass_id(3, 0); | |
1192 TestRenderPass* grand_child_pass = | |
1193 AddRenderPass(&render_passes_in_draw_order_, | |
1194 grand_child_pass_id, | |
1195 grand_child_rect, | |
1196 gfx::Transform()); | |
1197 AddClippedQuad(grand_child_pass, grand_child_rect, SK_ColorYELLOW); | |
1198 | |
1199 gfx::Rect child_rect(50, 50); | |
1200 RenderPassId child_pass_id(2, 0); | |
1201 TestRenderPass* child_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1202 child_pass_id, | |
1203 child_rect, | |
1204 gfx::Transform()); | |
1205 AddQuad(child_pass, child_rect, SK_ColorBLUE); | |
1206 | |
1207 RenderPassId root_pass_id(1, 0); | |
1208 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1209 root_pass_id, | |
1210 viewport_rect, | |
1211 gfx::Transform()); | |
1212 AddQuad(root_pass, viewport_rect, SK_ColorGREEN); | |
1213 | |
1214 AddRenderPassQuad(root_pass, child_pass); | |
1215 AddRenderPassQuad(child_pass, grand_child_pass); | |
1216 | |
1217 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_); | |
1218 renderer.DrawFrame(&render_passes_in_draw_order_, | |
1219 1.f, | |
1220 viewport_rect, | |
1221 viewport_rect, | |
1222 false); | |
1223 } | |
1224 | |
1225 class DiscardCheckingContext : public TestWebGraphicsContext3D { | |
1226 public: | |
1227 DiscardCheckingContext() : discarded_(0) { | |
1228 set_have_post_sub_buffer(true); | |
1229 set_have_discard_framebuffer(true); | |
1230 } | |
1231 | |
1232 void discardFramebufferEXT(GLenum target, | |
1233 GLsizei numAttachments, | |
1234 const GLenum* attachments) override { | |
1235 ++discarded_; | |
1236 } | |
1237 | |
1238 int discarded() const { return discarded_; } | |
1239 void reset() { discarded_ = 0; } | |
1240 | |
1241 private: | |
1242 int discarded_; | |
1243 }; | |
1244 | |
1245 class NonReshapableOutputSurface : public FakeOutputSurface { | |
1246 public: | |
1247 explicit NonReshapableOutputSurface( | |
1248 scoped_ptr<TestWebGraphicsContext3D> context3d) | |
1249 : FakeOutputSurface(TestContextProvider::Create(context3d.Pass()), | |
1250 false) { | |
1251 surface_size_ = gfx::Size(500, 500); | |
1252 } | |
1253 void Reshape(const gfx::Size& size, float scale_factor) override {} | |
1254 void set_fixed_size(const gfx::Size& size) { surface_size_ = size; } | |
1255 }; | |
1256 | |
1257 TEST_F(GLRendererTest, NoDiscardOnPartialUpdates) { | |
1258 scoped_ptr<DiscardCheckingContext> context_owned(new DiscardCheckingContext); | |
1259 DiscardCheckingContext* context = context_owned.get(); | |
1260 | |
1261 FakeOutputSurfaceClient output_surface_client; | |
1262 scoped_ptr<NonReshapableOutputSurface> output_surface( | |
1263 new NonReshapableOutputSurface(context_owned.Pass())); | |
1264 CHECK(output_surface->BindToClient(&output_surface_client)); | |
1265 output_surface->set_fixed_size(gfx::Size(100, 100)); | |
1266 | |
1267 scoped_ptr<SharedBitmapManager> shared_bitmap_manager( | |
1268 new TestSharedBitmapManager()); | |
1269 scoped_ptr<ResourceProvider> resource_provider( | |
1270 ResourceProvider::Create(output_surface.get(), | |
1271 shared_bitmap_manager.get(), | |
1272 NULL, | |
1273 NULL, | |
1274 0, | |
1275 false, | |
1276 1)); | |
1277 | |
1278 RendererSettings settings; | |
1279 settings.partial_swap_enabled = true; | |
1280 FakeRendererClient renderer_client; | |
1281 FakeRendererGL renderer(&renderer_client, | |
1282 &settings, | |
1283 output_surface.get(), | |
1284 resource_provider.get()); | |
1285 EXPECT_TRUE(renderer.Capabilities().using_partial_swap); | |
1286 | |
1287 gfx::Rect viewport_rect(100, 100); | |
1288 gfx::Rect clip_rect(100, 100); | |
1289 | |
1290 { | |
1291 // Partial frame, should not discard. | |
1292 RenderPassId root_pass_id(1, 0); | |
1293 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1294 root_pass_id, | |
1295 viewport_rect, | |
1296 gfx::Transform()); | |
1297 AddQuad(root_pass, viewport_rect, SK_ColorGREEN); | |
1298 root_pass->damage_rect = gfx::Rect(2, 2, 3, 3); | |
1299 | |
1300 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_); | |
1301 renderer.DrawFrame(&render_passes_in_draw_order_, | |
1302 1.f, | |
1303 viewport_rect, | |
1304 clip_rect, | |
1305 false); | |
1306 EXPECT_EQ(0, context->discarded()); | |
1307 context->reset(); | |
1308 } | |
1309 { | |
1310 // Full frame, should discard. | |
1311 RenderPassId root_pass_id(1, 0); | |
1312 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1313 root_pass_id, | |
1314 viewport_rect, | |
1315 gfx::Transform()); | |
1316 AddQuad(root_pass, viewport_rect, SK_ColorGREEN); | |
1317 root_pass->damage_rect = root_pass->output_rect; | |
1318 | |
1319 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_); | |
1320 renderer.DrawFrame(&render_passes_in_draw_order_, | |
1321 1.f, | |
1322 viewport_rect, | |
1323 clip_rect, | |
1324 false); | |
1325 EXPECT_EQ(1, context->discarded()); | |
1326 context->reset(); | |
1327 } | |
1328 { | |
1329 // Full frame, external scissor is set, should not discard. | |
1330 output_surface->set_has_external_stencil_test(true); | |
1331 RenderPassId root_pass_id(1, 0); | |
1332 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1333 root_pass_id, | |
1334 viewport_rect, | |
1335 gfx::Transform()); | |
1336 AddQuad(root_pass, viewport_rect, SK_ColorGREEN); | |
1337 root_pass->damage_rect = root_pass->output_rect; | |
1338 root_pass->has_transparent_background = false; | |
1339 | |
1340 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_); | |
1341 renderer.DrawFrame(&render_passes_in_draw_order_, | |
1342 1.f, | |
1343 viewport_rect, | |
1344 clip_rect, | |
1345 false); | |
1346 EXPECT_EQ(0, context->discarded()); | |
1347 context->reset(); | |
1348 output_surface->set_has_external_stencil_test(false); | |
1349 } | |
1350 { | |
1351 // Full frame, clipped, should not discard. | |
1352 clip_rect = gfx::Rect(10, 10, 10, 10); | |
1353 RenderPassId root_pass_id(1, 0); | |
1354 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1355 root_pass_id, | |
1356 viewport_rect, | |
1357 gfx::Transform()); | |
1358 AddQuad(root_pass, viewport_rect, SK_ColorGREEN); | |
1359 root_pass->damage_rect = root_pass->output_rect; | |
1360 | |
1361 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_); | |
1362 renderer.DrawFrame(&render_passes_in_draw_order_, | |
1363 1.f, | |
1364 viewport_rect, | |
1365 clip_rect, | |
1366 false); | |
1367 EXPECT_EQ(0, context->discarded()); | |
1368 context->reset(); | |
1369 } | |
1370 { | |
1371 // Full frame, doesn't cover the surface, should not discard. | |
1372 viewport_rect = gfx::Rect(10, 10, 10, 10); | |
1373 RenderPassId root_pass_id(1, 0); | |
1374 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1375 root_pass_id, | |
1376 viewport_rect, | |
1377 gfx::Transform()); | |
1378 AddQuad(root_pass, viewport_rect, SK_ColorGREEN); | |
1379 root_pass->damage_rect = root_pass->output_rect; | |
1380 | |
1381 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_); | |
1382 renderer.DrawFrame(&render_passes_in_draw_order_, | |
1383 1.f, | |
1384 viewport_rect, | |
1385 clip_rect, | |
1386 false); | |
1387 EXPECT_EQ(0, context->discarded()); | |
1388 context->reset(); | |
1389 } | |
1390 { | |
1391 // Full frame, doesn't cover the surface (no offset), should not discard. | |
1392 clip_rect = gfx::Rect(100, 100); | |
1393 viewport_rect = gfx::Rect(50, 50); | |
1394 RenderPassId root_pass_id(1, 0); | |
1395 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1396 root_pass_id, | |
1397 viewport_rect, | |
1398 gfx::Transform()); | |
1399 AddQuad(root_pass, viewport_rect, SK_ColorGREEN); | |
1400 root_pass->damage_rect = root_pass->output_rect; | |
1401 | |
1402 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_); | |
1403 renderer.DrawFrame(&render_passes_in_draw_order_, | |
1404 1.f, | |
1405 viewport_rect, | |
1406 clip_rect, | |
1407 false); | |
1408 EXPECT_EQ(0, context->discarded()); | |
1409 context->reset(); | |
1410 } | |
1411 } | |
1412 | |
1413 class FlippedScissorAndViewportContext : public TestWebGraphicsContext3D { | |
1414 public: | |
1415 MOCK_METHOD4(viewport, void(GLint x, GLint y, GLsizei width, GLsizei height)); | |
1416 MOCK_METHOD4(scissor, void(GLint x, GLint y, GLsizei width, GLsizei height)); | |
1417 }; | |
1418 | |
1419 TEST_F(GLRendererTest, ScissorAndViewportWithinNonreshapableSurface) { | |
1420 // In Android WebView, the OutputSurface is unable to respect reshape() calls | |
1421 // and maintains a fixed size. This test verifies that glViewport and | |
1422 // glScissor's Y coordinate is flipped correctly in this environment, and that | |
1423 // the glViewport can be at a nonzero origin within the surface. | |
1424 scoped_ptr<FlippedScissorAndViewportContext> context_owned( | |
1425 new FlippedScissorAndViewportContext); | |
1426 | |
1427 // We expect exactly one call to viewport on this context and exactly two | |
1428 // to scissor (one to scissor the clear, one to scissor the quad draw). | |
1429 EXPECT_CALL(*context_owned, viewport(10, 390, 100, 100)); | |
1430 EXPECT_CALL(*context_owned, scissor(10, 390, 100, 100)); | |
1431 EXPECT_CALL(*context_owned, scissor(30, 450, 20, 20)); | |
1432 | |
1433 FakeOutputSurfaceClient output_surface_client; | |
1434 scoped_ptr<OutputSurface> output_surface( | |
1435 new NonReshapableOutputSurface(context_owned.Pass())); | |
1436 CHECK(output_surface->BindToClient(&output_surface_client)); | |
1437 | |
1438 scoped_ptr<SharedBitmapManager> shared_bitmap_manager( | |
1439 new TestSharedBitmapManager()); | |
1440 scoped_ptr<ResourceProvider> resource_provider( | |
1441 ResourceProvider::Create(output_surface.get(), | |
1442 shared_bitmap_manager.get(), | |
1443 NULL, | |
1444 NULL, | |
1445 0, | |
1446 false, | |
1447 1)); | |
1448 | |
1449 RendererSettings settings; | |
1450 FakeRendererClient renderer_client; | |
1451 FakeRendererGL renderer(&renderer_client, | |
1452 &settings, | |
1453 output_surface.get(), | |
1454 resource_provider.get()); | |
1455 EXPECT_FALSE(renderer.Capabilities().using_partial_swap); | |
1456 | |
1457 gfx::Rect device_viewport_rect(10, 10, 100, 100); | |
1458 gfx::Rect viewport_rect(device_viewport_rect.size()); | |
1459 gfx::Rect quad_rect = gfx::Rect(20, 20, 20, 20); | |
1460 | |
1461 RenderPassId root_pass_id(1, 0); | |
1462 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1463 root_pass_id, | |
1464 viewport_rect, | |
1465 gfx::Transform()); | |
1466 AddClippedQuad(root_pass, quad_rect, SK_ColorGREEN); | |
1467 | |
1468 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_); | |
1469 renderer.DrawFrame(&render_passes_in_draw_order_, | |
1470 1.f, | |
1471 device_viewport_rect, | |
1472 device_viewport_rect, | |
1473 false); | |
1474 } | |
1475 | |
1476 TEST_F(GLRendererTest, DrawFramePreservesFramebuffer) { | |
1477 // When using render-to-FBO to display the surface, all rendering is done | |
1478 // to a non-zero FBO. Make sure that the framebuffer is always restored to | |
1479 // the correct framebuffer during rendering, if changed. | |
1480 // Note: there is one path that will set it to 0, but that is after the render | |
1481 // has finished. | |
1482 FakeOutputSurfaceClient output_surface_client; | |
1483 scoped_ptr<FakeOutputSurface> output_surface( | |
1484 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create().Pass())); | |
1485 CHECK(output_surface->BindToClient(&output_surface_client)); | |
1486 | |
1487 scoped_ptr<SharedBitmapManager> shared_bitmap_manager( | |
1488 new TestSharedBitmapManager()); | |
1489 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( | |
1490 output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0, false, | |
1491 1)); | |
1492 | |
1493 RendererSettings settings; | |
1494 FakeRendererClient renderer_client; | |
1495 FakeRendererGL renderer(&renderer_client, &settings, output_surface.get(), | |
1496 resource_provider.get()); | |
1497 EXPECT_FALSE(renderer.Capabilities().using_partial_swap); | |
1498 | |
1499 gfx::Rect device_viewport_rect(0, 0, 100, 100); | |
1500 gfx::Rect viewport_rect(device_viewport_rect.size()); | |
1501 gfx::Rect quad_rect = gfx::Rect(20, 20, 20, 20); | |
1502 | |
1503 RenderPassId root_pass_id(1, 0); | |
1504 TestRenderPass* root_pass = | |
1505 AddRenderPass(&render_passes_in_draw_order_, root_pass_id, viewport_rect, | |
1506 gfx::Transform()); | |
1507 AddClippedQuad(root_pass, quad_rect, SK_ColorGREEN); | |
1508 | |
1509 unsigned fbo; | |
1510 gpu::gles2::GLES2Interface* gl = | |
1511 output_surface->context_provider()->ContextGL(); | |
1512 gl->GenFramebuffers(1, &fbo); | |
1513 output_surface->set_framebuffer(fbo); | |
1514 | |
1515 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_); | |
1516 renderer.DrawFrame(&render_passes_in_draw_order_, 1.f, device_viewport_rect, | |
1517 device_viewport_rect, false); | |
1518 | |
1519 int bound_fbo; | |
1520 gl->GetIntegerv(GL_FRAMEBUFFER_BINDING, &bound_fbo); | |
1521 EXPECT_EQ(static_cast<int>(fbo), bound_fbo); | |
1522 } | |
1523 | |
1524 TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) { | |
1525 gfx::Rect viewport_rect(1, 1); | |
1526 | |
1527 gfx::Rect child_rect(50, 50); | |
1528 RenderPassId child_pass_id(2, 0); | |
1529 TestRenderPass* child_pass; | |
1530 | |
1531 RenderPassId root_pass_id(1, 0); | |
1532 TestRenderPass* root_pass; | |
1533 | |
1534 ResourceProvider::ResourceId mask = resource_provider_->CreateResource( | |
1535 gfx::Size(20, 12), GL_CLAMP_TO_EDGE, | |
1536 ResourceProvider::TEXTURE_HINT_IMMUTABLE, | |
1537 resource_provider_->best_texture_format()); | |
1538 resource_provider_->AllocateForTesting(mask); | |
1539 | |
1540 SkScalar matrix[20]; | |
1541 float amount = 0.5f; | |
1542 matrix[0] = 0.213f + 0.787f * amount; | |
1543 matrix[1] = 0.715f - 0.715f * amount; | |
1544 matrix[2] = 1.f - (matrix[0] + matrix[1]); | |
1545 matrix[3] = matrix[4] = 0; | |
1546 matrix[5] = 0.213f - 0.213f * amount; | |
1547 matrix[6] = 0.715f + 0.285f * amount; | |
1548 matrix[7] = 1.f - (matrix[5] + matrix[6]); | |
1549 matrix[8] = matrix[9] = 0; | |
1550 matrix[10] = 0.213f - 0.213f * amount; | |
1551 matrix[11] = 0.715f - 0.715f * amount; | |
1552 matrix[12] = 1.f - (matrix[10] + matrix[11]); | |
1553 matrix[13] = matrix[14] = 0; | |
1554 matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0; | |
1555 matrix[18] = 1; | |
1556 skia::RefPtr<SkColorFilter> color_filter( | |
1557 skia::AdoptRef(SkColorMatrixFilter::Create(matrix))); | |
1558 skia::RefPtr<SkImageFilter> filter = skia::AdoptRef( | |
1559 SkColorFilterImageFilter::Create(color_filter.get(), NULL)); | |
1560 FilterOperations filters; | |
1561 filters.Append(FilterOperation::CreateReferenceFilter(filter)); | |
1562 | |
1563 gfx::Transform transform_causing_aa; | |
1564 transform_causing_aa.Rotate(20.0); | |
1565 | |
1566 for (int i = 0; i <= LAST_BLEND_MODE; ++i) { | |
1567 BlendMode blend_mode = static_cast<BlendMode>(i); | |
1568 SkXfermode::Mode xfer_mode = BlendModeToSkXfermode(blend_mode); | |
1569 settings_.force_blending_with_shaders = (blend_mode != BLEND_MODE_NONE); | |
1570 // RenderPassProgram | |
1571 render_passes_in_draw_order_.clear(); | |
1572 child_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1573 child_pass_id, | |
1574 child_rect, | |
1575 gfx::Transform()); | |
1576 | |
1577 root_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1578 root_pass_id, | |
1579 viewport_rect, | |
1580 gfx::Transform()); | |
1581 | |
1582 AddRenderPassQuad(root_pass, | |
1583 child_pass, | |
1584 0, | |
1585 FilterOperations(), | |
1586 gfx::Transform(), | |
1587 xfer_mode); | |
1588 | |
1589 renderer_->DecideRenderPassAllocationsForFrame( | |
1590 render_passes_in_draw_order_); | |
1591 renderer_->DrawFrame(&render_passes_in_draw_order_, | |
1592 1.f, | |
1593 viewport_rect, | |
1594 viewport_rect, | |
1595 false); | |
1596 TestRenderPassProgram(TEX_COORD_PRECISION_MEDIUM, blend_mode); | |
1597 | |
1598 // RenderPassColorMatrixProgram | |
1599 render_passes_in_draw_order_.clear(); | |
1600 | |
1601 child_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1602 child_pass_id, | |
1603 child_rect, | |
1604 transform_causing_aa); | |
1605 | |
1606 root_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1607 root_pass_id, | |
1608 viewport_rect, | |
1609 gfx::Transform()); | |
1610 | |
1611 AddRenderPassQuad( | |
1612 root_pass, child_pass, 0, filters, gfx::Transform(), xfer_mode); | |
1613 | |
1614 renderer_->DecideRenderPassAllocationsForFrame( | |
1615 render_passes_in_draw_order_); | |
1616 renderer_->DrawFrame(&render_passes_in_draw_order_, | |
1617 1.f, | |
1618 viewport_rect, | |
1619 viewport_rect, | |
1620 false); | |
1621 TestRenderPassColorMatrixProgram(TEX_COORD_PRECISION_MEDIUM, blend_mode); | |
1622 | |
1623 // RenderPassMaskProgram | |
1624 render_passes_in_draw_order_.clear(); | |
1625 | |
1626 child_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1627 child_pass_id, | |
1628 child_rect, | |
1629 gfx::Transform()); | |
1630 | |
1631 root_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1632 root_pass_id, | |
1633 viewport_rect, | |
1634 gfx::Transform()); | |
1635 | |
1636 AddRenderPassQuad(root_pass, | |
1637 child_pass, | |
1638 mask, | |
1639 FilterOperations(), | |
1640 gfx::Transform(), | |
1641 xfer_mode); | |
1642 | |
1643 renderer_->DecideRenderPassAllocationsForFrame( | |
1644 render_passes_in_draw_order_); | |
1645 renderer_->DrawFrame(&render_passes_in_draw_order_, | |
1646 1.f, | |
1647 viewport_rect, | |
1648 viewport_rect, | |
1649 false); | |
1650 TestRenderPassMaskProgram(TEX_COORD_PRECISION_MEDIUM, SAMPLER_TYPE_2D, | |
1651 blend_mode); | |
1652 | |
1653 // RenderPassMaskColorMatrixProgram | |
1654 render_passes_in_draw_order_.clear(); | |
1655 | |
1656 child_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1657 child_pass_id, | |
1658 child_rect, | |
1659 gfx::Transform()); | |
1660 | |
1661 root_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1662 root_pass_id, | |
1663 viewport_rect, | |
1664 gfx::Transform()); | |
1665 | |
1666 AddRenderPassQuad( | |
1667 root_pass, child_pass, mask, filters, gfx::Transform(), xfer_mode); | |
1668 | |
1669 renderer_->DecideRenderPassAllocationsForFrame( | |
1670 render_passes_in_draw_order_); | |
1671 renderer_->DrawFrame(&render_passes_in_draw_order_, | |
1672 1.f, | |
1673 viewport_rect, | |
1674 viewport_rect, | |
1675 false); | |
1676 TestRenderPassMaskColorMatrixProgram(TEX_COORD_PRECISION_MEDIUM, | |
1677 SAMPLER_TYPE_2D, blend_mode); | |
1678 | |
1679 // RenderPassProgramAA | |
1680 render_passes_in_draw_order_.clear(); | |
1681 | |
1682 child_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1683 child_pass_id, | |
1684 child_rect, | |
1685 transform_causing_aa); | |
1686 | |
1687 root_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1688 root_pass_id, | |
1689 viewport_rect, | |
1690 gfx::Transform()); | |
1691 | |
1692 AddRenderPassQuad(root_pass, | |
1693 child_pass, | |
1694 0, | |
1695 FilterOperations(), | |
1696 transform_causing_aa, | |
1697 xfer_mode); | |
1698 | |
1699 renderer_->DecideRenderPassAllocationsForFrame( | |
1700 render_passes_in_draw_order_); | |
1701 renderer_->DrawFrame(&render_passes_in_draw_order_, | |
1702 1.f, | |
1703 viewport_rect, | |
1704 viewport_rect, | |
1705 false); | |
1706 TestRenderPassProgramAA(TEX_COORD_PRECISION_MEDIUM, blend_mode); | |
1707 | |
1708 // RenderPassColorMatrixProgramAA | |
1709 render_passes_in_draw_order_.clear(); | |
1710 | |
1711 child_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1712 child_pass_id, | |
1713 child_rect, | |
1714 transform_causing_aa); | |
1715 | |
1716 root_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1717 root_pass_id, | |
1718 viewport_rect, | |
1719 gfx::Transform()); | |
1720 | |
1721 AddRenderPassQuad( | |
1722 root_pass, child_pass, 0, filters, transform_causing_aa, xfer_mode); | |
1723 | |
1724 renderer_->DecideRenderPassAllocationsForFrame( | |
1725 render_passes_in_draw_order_); | |
1726 renderer_->DrawFrame(&render_passes_in_draw_order_, | |
1727 1.f, | |
1728 viewport_rect, | |
1729 viewport_rect, | |
1730 false); | |
1731 TestRenderPassColorMatrixProgramAA(TEX_COORD_PRECISION_MEDIUM, blend_mode); | |
1732 | |
1733 // RenderPassMaskProgramAA | |
1734 render_passes_in_draw_order_.clear(); | |
1735 | |
1736 child_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1737 child_pass_id, | |
1738 child_rect, | |
1739 transform_causing_aa); | |
1740 | |
1741 root_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1742 root_pass_id, | |
1743 viewport_rect, | |
1744 gfx::Transform()); | |
1745 | |
1746 AddRenderPassQuad(root_pass, | |
1747 child_pass, | |
1748 mask, | |
1749 FilterOperations(), | |
1750 transform_causing_aa, | |
1751 xfer_mode); | |
1752 | |
1753 renderer_->DecideRenderPassAllocationsForFrame( | |
1754 render_passes_in_draw_order_); | |
1755 renderer_->DrawFrame(&render_passes_in_draw_order_, | |
1756 1.f, | |
1757 viewport_rect, | |
1758 viewport_rect, | |
1759 false); | |
1760 TestRenderPassMaskProgramAA(TEX_COORD_PRECISION_MEDIUM, SAMPLER_TYPE_2D, | |
1761 blend_mode); | |
1762 | |
1763 // RenderPassMaskColorMatrixProgramAA | |
1764 render_passes_in_draw_order_.clear(); | |
1765 | |
1766 child_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1767 child_pass_id, | |
1768 child_rect, | |
1769 transform_causing_aa); | |
1770 | |
1771 root_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1772 root_pass_id, | |
1773 viewport_rect, | |
1774 transform_causing_aa); | |
1775 | |
1776 AddRenderPassQuad( | |
1777 root_pass, child_pass, mask, filters, transform_causing_aa, xfer_mode); | |
1778 | |
1779 renderer_->DecideRenderPassAllocationsForFrame( | |
1780 render_passes_in_draw_order_); | |
1781 renderer_->DrawFrame(&render_passes_in_draw_order_, | |
1782 1.f, | |
1783 viewport_rect, | |
1784 viewport_rect, | |
1785 false); | |
1786 TestRenderPassMaskColorMatrixProgramAA(TEX_COORD_PRECISION_MEDIUM, | |
1787 SAMPLER_TYPE_2D, blend_mode); | |
1788 } | |
1789 } | |
1790 | |
1791 // At this time, the AA code path cannot be taken if the surface's rect would | |
1792 // project incorrectly by the given transform, because of w<0 clipping. | |
1793 TEST_F(GLRendererShaderTest, DrawRenderPassQuadSkipsAAForClippingTransform) { | |
1794 gfx::Rect child_rect(50, 50); | |
1795 RenderPassId child_pass_id(2, 0); | |
1796 TestRenderPass* child_pass; | |
1797 | |
1798 gfx::Rect viewport_rect(1, 1); | |
1799 RenderPassId root_pass_id(1, 0); | |
1800 TestRenderPass* root_pass; | |
1801 | |
1802 gfx::Transform transform_preventing_aa; | |
1803 transform_preventing_aa.ApplyPerspectiveDepth(40.0); | |
1804 transform_preventing_aa.RotateAboutYAxis(-20.0); | |
1805 transform_preventing_aa.Scale(30.0, 1.0); | |
1806 | |
1807 // Verify that the test transform and test rect actually do cause the clipped | |
1808 // flag to trigger. Otherwise we are not testing the intended scenario. | |
1809 bool clipped = false; | |
1810 MathUtil::MapQuad(transform_preventing_aa, gfx::QuadF(child_rect), &clipped); | |
1811 ASSERT_TRUE(clipped); | |
1812 | |
1813 child_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1814 child_pass_id, | |
1815 child_rect, | |
1816 transform_preventing_aa); | |
1817 | |
1818 root_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1819 root_pass_id, | |
1820 viewport_rect, | |
1821 gfx::Transform()); | |
1822 | |
1823 AddRenderPassQuad(root_pass, | |
1824 child_pass, | |
1825 0, | |
1826 FilterOperations(), | |
1827 transform_preventing_aa, | |
1828 SkXfermode::kSrcOver_Mode); | |
1829 | |
1830 renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_); | |
1831 renderer_->DrawFrame(&render_passes_in_draw_order_, | |
1832 1.f, | |
1833 viewport_rect, | |
1834 viewport_rect, | |
1835 false); | |
1836 | |
1837 // If use_aa incorrectly ignores clipping, it will use the | |
1838 // RenderPassProgramAA shader instead of the RenderPassProgram. | |
1839 TestRenderPassProgram(TEX_COORD_PRECISION_MEDIUM, BLEND_MODE_NONE); | |
1840 } | |
1841 | |
1842 TEST_F(GLRendererShaderTest, DrawSolidColorShader) { | |
1843 gfx::Rect viewport_rect(1, 1); | |
1844 RenderPassId root_pass_id(1, 0); | |
1845 TestRenderPass* root_pass; | |
1846 | |
1847 gfx::Transform pixel_aligned_transform_causing_aa; | |
1848 pixel_aligned_transform_causing_aa.Translate(25.5f, 25.5f); | |
1849 pixel_aligned_transform_causing_aa.Scale(0.5f, 0.5f); | |
1850 | |
1851 root_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1852 root_pass_id, | |
1853 viewport_rect, | |
1854 gfx::Transform()); | |
1855 AddTransformedQuad(root_pass, | |
1856 viewport_rect, | |
1857 SK_ColorYELLOW, | |
1858 pixel_aligned_transform_causing_aa); | |
1859 | |
1860 renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_); | |
1861 renderer_->DrawFrame(&render_passes_in_draw_order_, | |
1862 1.f, | |
1863 viewport_rect, | |
1864 viewport_rect, | |
1865 false); | |
1866 | |
1867 TestSolidColorProgramAA(); | |
1868 } | |
1869 | |
1870 class OutputSurfaceMockContext : public TestWebGraphicsContext3D { | |
1871 public: | |
1872 OutputSurfaceMockContext() { test_capabilities_.gpu.post_sub_buffer = true; } | |
1873 | |
1874 // Specifically override methods even if they are unused (used in conjunction | |
1875 // with StrictMock). We need to make sure that GLRenderer does not issue | |
1876 // framebuffer-related GLuint calls directly. Instead these are supposed to go | |
1877 // through the OutputSurface abstraction. | |
1878 MOCK_METHOD2(bindFramebuffer, void(GLenum target, GLuint framebuffer)); | |
1879 MOCK_METHOD3(reshapeWithScaleFactor, | |
1880 void(int width, int height, float scale_factor)); | |
1881 MOCK_METHOD4(drawElements, | |
1882 void(GLenum mode, GLsizei count, GLenum type, GLintptr offset)); | |
1883 }; | |
1884 | |
1885 class MockOutputSurface : public OutputSurface { | |
1886 public: | |
1887 MockOutputSurface() | |
1888 : OutputSurface( | |
1889 TestContextProvider::Create(scoped_ptr<TestWebGraphicsContext3D>( | |
1890 new StrictMock<OutputSurfaceMockContext>))) { | |
1891 surface_size_ = gfx::Size(100, 100); | |
1892 } | |
1893 virtual ~MockOutputSurface() {} | |
1894 | |
1895 MOCK_METHOD0(EnsureBackbuffer, void()); | |
1896 MOCK_METHOD0(DiscardBackbuffer, void()); | |
1897 MOCK_METHOD2(Reshape, void(const gfx::Size& size, float scale_factor)); | |
1898 MOCK_METHOD0(BindFramebuffer, void()); | |
1899 MOCK_METHOD1(SwapBuffers, void(CompositorFrame* frame)); | |
1900 }; | |
1901 | |
1902 class MockOutputSurfaceTest : public GLRendererTest { | |
1903 protected: | |
1904 virtual void SetUp() { | |
1905 FakeOutputSurfaceClient output_surface_client_; | |
1906 CHECK(output_surface_.BindToClient(&output_surface_client_)); | |
1907 | |
1908 shared_bitmap_manager_.reset(new TestSharedBitmapManager()); | |
1909 resource_provider_ = ResourceProvider::Create(&output_surface_, | |
1910 shared_bitmap_manager_.get(), | |
1911 NULL, | |
1912 NULL, | |
1913 0, | |
1914 false, | |
1915 1).Pass(); | |
1916 | |
1917 renderer_.reset(new FakeRendererGL(&renderer_client_, | |
1918 &settings_, | |
1919 &output_surface_, | |
1920 resource_provider_.get())); | |
1921 } | |
1922 | |
1923 void SwapBuffers() { renderer_->SwapBuffers(CompositorFrameMetadata()); } | |
1924 | |
1925 void DrawFrame(float device_scale_factor, | |
1926 const gfx::Rect& device_viewport_rect) { | |
1927 RenderPassId render_pass_id(1, 0); | |
1928 TestRenderPass* render_pass = AddRenderPass(&render_passes_in_draw_order_, | |
1929 render_pass_id, | |
1930 device_viewport_rect, | |
1931 gfx::Transform()); | |
1932 AddQuad(render_pass, device_viewport_rect, SK_ColorGREEN); | |
1933 | |
1934 EXPECT_CALL(output_surface_, EnsureBackbuffer()).WillRepeatedly(Return()); | |
1935 | |
1936 EXPECT_CALL(output_surface_, | |
1937 Reshape(device_viewport_rect.size(), device_scale_factor)) | |
1938 .Times(1); | |
1939 | |
1940 EXPECT_CALL(output_surface_, BindFramebuffer()).Times(1); | |
1941 | |
1942 EXPECT_CALL(*Context(), drawElements(_, _, _, _)).Times(1); | |
1943 | |
1944 renderer_->DecideRenderPassAllocationsForFrame( | |
1945 render_passes_in_draw_order_); | |
1946 renderer_->DrawFrame(&render_passes_in_draw_order_, | |
1947 device_scale_factor, | |
1948 device_viewport_rect, | |
1949 device_viewport_rect, | |
1950 false); | |
1951 } | |
1952 | |
1953 OutputSurfaceMockContext* Context() { | |
1954 return static_cast<OutputSurfaceMockContext*>( | |
1955 static_cast<TestContextProvider*>(output_surface_.context_provider()) | |
1956 ->TestContext3d()); | |
1957 } | |
1958 | |
1959 RendererSettings settings_; | |
1960 FakeOutputSurfaceClient output_surface_client_; | |
1961 StrictMock<MockOutputSurface> output_surface_; | |
1962 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_; | |
1963 scoped_ptr<ResourceProvider> resource_provider_; | |
1964 FakeRendererClient renderer_client_; | |
1965 scoped_ptr<FakeRendererGL> renderer_; | |
1966 }; | |
1967 | |
1968 TEST_F(MockOutputSurfaceTest, DrawFrameAndSwap) { | |
1969 gfx::Rect device_viewport_rect(1, 1); | |
1970 DrawFrame(1.f, device_viewport_rect); | |
1971 | |
1972 EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1); | |
1973 renderer_->SwapBuffers(CompositorFrameMetadata()); | |
1974 } | |
1975 | |
1976 TEST_F(MockOutputSurfaceTest, DrawFrameAndResizeAndSwap) { | |
1977 gfx::Rect device_viewport_rect(1, 1); | |
1978 | |
1979 DrawFrame(1.f, device_viewport_rect); | |
1980 EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1); | |
1981 renderer_->SwapBuffers(CompositorFrameMetadata()); | |
1982 | |
1983 device_viewport_rect = gfx::Rect(2, 2); | |
1984 | |
1985 DrawFrame(2.f, device_viewport_rect); | |
1986 EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1); | |
1987 renderer_->SwapBuffers(CompositorFrameMetadata()); | |
1988 | |
1989 DrawFrame(2.f, device_viewport_rect); | |
1990 EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1); | |
1991 renderer_->SwapBuffers(CompositorFrameMetadata()); | |
1992 | |
1993 device_viewport_rect = gfx::Rect(1, 1); | |
1994 | |
1995 DrawFrame(1.f, device_viewport_rect); | |
1996 EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1); | |
1997 renderer_->SwapBuffers(CompositorFrameMetadata()); | |
1998 } | |
1999 | |
2000 class GLRendererTestSyncPoint : public GLRendererPixelTest { | |
2001 protected: | |
2002 static void SyncPointCallback(int* callback_count) { | |
2003 ++(*callback_count); | |
2004 base::MessageLoop::current()->QuitWhenIdle(); | |
2005 } | |
2006 | |
2007 static void OtherCallback(int* callback_count) { | |
2008 ++(*callback_count); | |
2009 base::MessageLoop::current()->QuitWhenIdle(); | |
2010 } | |
2011 }; | |
2012 | |
2013 #if !defined(OS_ANDROID) | |
2014 TEST_F(GLRendererTestSyncPoint, SignalSyncPointOnLostContext) { | |
2015 int sync_point_callback_count = 0; | |
2016 int other_callback_count = 0; | |
2017 gpu::gles2::GLES2Interface* gl = | |
2018 output_surface_->context_provider()->ContextGL(); | |
2019 gpu::ContextSupport* context_support = | |
2020 output_surface_->context_provider()->ContextSupport(); | |
2021 | |
2022 uint32 sync_point = gl->InsertSyncPointCHROMIUM(); | |
2023 | |
2024 gl->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB, | |
2025 GL_INNOCENT_CONTEXT_RESET_ARB); | |
2026 | |
2027 context_support->SignalSyncPoint( | |
2028 sync_point, base::Bind(&SyncPointCallback, &sync_point_callback_count)); | |
2029 EXPECT_EQ(0, sync_point_callback_count); | |
2030 EXPECT_EQ(0, other_callback_count); | |
2031 | |
2032 // Make the sync point happen. | |
2033 gl->Finish(); | |
2034 // Post a task after the sync point. | |
2035 base::MessageLoop::current()->PostTask( | |
2036 FROM_HERE, base::Bind(&OtherCallback, &other_callback_count)); | |
2037 | |
2038 base::MessageLoop::current()->Run(); | |
2039 | |
2040 // The sync point shouldn't have happened since the context was lost. | |
2041 EXPECT_EQ(0, sync_point_callback_count); | |
2042 EXPECT_EQ(1, other_callback_count); | |
2043 } | |
2044 | |
2045 TEST_F(GLRendererTestSyncPoint, SignalSyncPoint) { | |
2046 int sync_point_callback_count = 0; | |
2047 int other_callback_count = 0; | |
2048 | |
2049 gpu::gles2::GLES2Interface* gl = | |
2050 output_surface_->context_provider()->ContextGL(); | |
2051 gpu::ContextSupport* context_support = | |
2052 output_surface_->context_provider()->ContextSupport(); | |
2053 | |
2054 uint32 sync_point = gl->InsertSyncPointCHROMIUM(); | |
2055 | |
2056 context_support->SignalSyncPoint( | |
2057 sync_point, base::Bind(&SyncPointCallback, &sync_point_callback_count)); | |
2058 EXPECT_EQ(0, sync_point_callback_count); | |
2059 EXPECT_EQ(0, other_callback_count); | |
2060 | |
2061 // Make the sync point happen. | |
2062 gl->Finish(); | |
2063 // Post a task after the sync point. | |
2064 base::MessageLoop::current()->PostTask( | |
2065 FROM_HERE, base::Bind(&OtherCallback, &other_callback_count)); | |
2066 | |
2067 base::MessageLoop::current()->Run(); | |
2068 | |
2069 // The sync point should have happened. | |
2070 EXPECT_EQ(1, sync_point_callback_count); | |
2071 EXPECT_EQ(1, other_callback_count); | |
2072 } | |
2073 #endif // OS_ANDROID | |
2074 | |
2075 } // namespace | |
2076 } // namespace cc | |
OLD | NEW |