| 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 |