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 |