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