cc: Added inline to Tile::IsReadyToDraw
[chromium-blink-merge.git] / cc / output / gl_renderer_unittest.cc
blobc12bbfe3c0e93e331984dde7f644635e3aecc82a
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.
5 #include "cc/output/gl_renderer.h"
7 #include <set>
9 #include "cc/base/math_util.h"
10 #include "cc/debug/test_web_graphics_context_3d.h"
11 #include "cc/output/compositor_frame_metadata.h"
12 #include "cc/resources/prioritized_resource_manager.h"
13 #include "cc/resources/resource_provider.h"
14 #include "cc/resources/sync_point_helper.h"
15 #include "cc/test/fake_impl_proxy.h"
16 #include "cc/test/fake_layer_tree_host_impl.h"
17 #include "cc/test/fake_output_surface.h"
18 #include "cc/test/fake_output_surface_client.h"
19 #include "cc/test/mock_quad_culler.h"
20 #include "cc/test/pixel_test.h"
21 #include "cc/test/render_pass_test_common.h"
22 #include "cc/test/render_pass_test_utils.h"
23 #include "gpu/GLES2/gl2extchromium.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"
33 using testing::_;
34 using testing::AnyNumber;
35 using testing::AtLeast;
36 using testing::Expectation;
37 using testing::InSequence;
38 using testing::Mock;
39 using testing::Return;
40 using testing::StrictMock;
41 using WebKit::WebGLId;
42 using WebKit::WebString;
43 using WebKit::WGC3Dbitfield;
44 using WebKit::WGC3Dboolean;
45 using WebKit::WGC3Dchar;
46 using WebKit::WGC3Denum;
47 using WebKit::WGC3Dfloat;
48 using WebKit::WGC3Dint;
49 using WebKit::WGC3Dintptr;
50 using WebKit::WGC3Dsizei;
51 using WebKit::WGC3Dsizeiptr;
52 using WebKit::WGC3Duint;
54 namespace cc {
56 #define EXPECT_PROGRAM_VALID(program_binding) \
57 do { \
58 EXPECT_TRUE(program_binding->program()); \
59 EXPECT_TRUE(program_binding->initialized()); \
60 } while (false)
62 // Explicitly named to be a friend in GLRenderer for shader access.
63 class GLRendererShaderPixelTest : public GLRendererPixelTest {
64 public:
65 void TestShaders() {
66 ASSERT_FALSE(renderer()->IsContextLost());
67 EXPECT_PROGRAM_VALID(renderer()->GetTileCheckerboardProgram());
68 EXPECT_PROGRAM_VALID(renderer()->GetDebugBorderProgram());
69 EXPECT_PROGRAM_VALID(renderer()->GetSolidColorProgram());
70 EXPECT_PROGRAM_VALID(renderer()->GetSolidColorProgramAA());
71 TestShadersWithTexCoordPrecision(TexCoordPrecisionMedium);
72 TestShadersWithTexCoordPrecision(TexCoordPrecisionHigh);
73 ASSERT_FALSE(renderer()->IsContextLost());
76 void TestShadersWithTexCoordPrecision(TexCoordPrecision precision) {
77 EXPECT_PROGRAM_VALID(renderer()->GetTileProgram(precision));
78 EXPECT_PROGRAM_VALID(renderer()->GetTileProgramOpaque(precision));
79 EXPECT_PROGRAM_VALID(renderer()->GetTileProgramAA(precision));
80 EXPECT_PROGRAM_VALID(renderer()->GetTileProgramSwizzle(precision));
81 EXPECT_PROGRAM_VALID(renderer()->GetTileProgramSwizzleOpaque(precision));
82 EXPECT_PROGRAM_VALID(renderer()->GetTileProgramSwizzleAA(precision));
83 EXPECT_PROGRAM_VALID(renderer()->GetRenderPassProgram(precision));
84 EXPECT_PROGRAM_VALID(renderer()->GetRenderPassProgramAA(precision));
85 EXPECT_PROGRAM_VALID(renderer()->GetRenderPassMaskProgram(precision));
86 EXPECT_PROGRAM_VALID(renderer()->GetRenderPassMaskProgramAA(precision));
87 EXPECT_PROGRAM_VALID(
88 renderer()->GetRenderPassColorMatrixProgram(precision));
89 EXPECT_PROGRAM_VALID(
90 renderer()->GetRenderPassMaskColorMatrixProgramAA(precision));
91 EXPECT_PROGRAM_VALID(
92 renderer()->GetRenderPassColorMatrixProgramAA(precision));
93 EXPECT_PROGRAM_VALID(
94 renderer()->GetRenderPassMaskColorMatrixProgram(precision));
95 EXPECT_PROGRAM_VALID(renderer()->GetTextureProgram(precision));
96 EXPECT_PROGRAM_VALID(
97 renderer()->GetNonPremultipliedTextureProgram(precision));
98 EXPECT_PROGRAM_VALID(renderer()->GetTextureBackgroundProgram(precision));
99 EXPECT_PROGRAM_VALID(
100 renderer()->GetNonPremultipliedTextureBackgroundProgram(precision));
101 EXPECT_PROGRAM_VALID(renderer()->GetTextureIOSurfaceProgram(precision));
102 EXPECT_PROGRAM_VALID(renderer()->GetVideoYUVProgram(precision));
103 EXPECT_PROGRAM_VALID(renderer()->GetVideoYUVAProgram(precision));
104 // This is unlikely to be ever true in tests due to usage of osmesa.
105 if (renderer()->Capabilities().using_egl_image)
106 EXPECT_PROGRAM_VALID(renderer()->GetVideoStreamTextureProgram(precision));
107 else
108 EXPECT_FALSE(renderer()->GetVideoStreamTextureProgram(precision));
112 namespace {
114 #if !defined(OS_ANDROID)
115 TEST_F(GLRendererShaderPixelTest, AllShadersCompile) { TestShaders(); }
116 #endif
118 class FrameCountingContext : public TestWebGraphicsContext3D {
119 public:
120 FrameCountingContext()
121 : frame_(0) {
122 test_capabilities_.set_visibility = true;
123 test_capabilities_.discard_backbuffer = true;
126 // WebGraphicsContext3D methods.
128 // This method would normally do a glSwapBuffers under the hood.
129 virtual void prepareTexture() { frame_++; }
131 // Methods added for test.
132 int frame_count() { return frame_; }
134 private:
135 int frame_;
138 class FakeRendererClient : public RendererClient {
139 public:
140 FakeRendererClient()
141 : host_impl_(&proxy_),
142 set_full_root_layer_damage_count_(0),
143 root_layer_(LayerImpl::Create(host_impl_.active_tree(), 1)),
144 viewport_size_(gfx::Size(1, 1)),
145 scale_factor_(1.f),
146 external_stencil_test_enabled_(false) {
147 root_layer_->CreateRenderSurface();
148 RenderPass::Id render_pass_id =
149 root_layer_->render_surface()->RenderPassId();
150 scoped_ptr<RenderPass> root_render_pass = RenderPass::Create();
151 root_render_pass->SetNew(
152 render_pass_id, gfx::Rect(), gfx::Rect(), gfx::Transform());
153 render_passes_in_draw_order_.push_back(root_render_pass.Pass());
156 // RendererClient methods.
157 virtual gfx::Rect DeviceViewport() const OVERRIDE {
158 static gfx::Size fake_size(1, 1);
159 return gfx::Rect(fake_size);
161 virtual float DeviceScaleFactor() const OVERRIDE {
162 return scale_factor_;
164 virtual const LayerTreeSettings& Settings() const OVERRIDE {
165 static LayerTreeSettings fake_settings;
166 return fake_settings;
168 virtual void SetFullRootLayerDamage() OVERRIDE {
169 set_full_root_layer_damage_count_++;
171 virtual bool HasImplThread() const OVERRIDE { return false; }
172 virtual bool ShouldClearRootRenderPass() const OVERRIDE { return true; }
173 virtual CompositorFrameMetadata MakeCompositorFrameMetadata() const OVERRIDE {
174 return CompositorFrameMetadata();
176 virtual bool AllowPartialSwap() const OVERRIDE {
177 return true;
179 virtual bool ExternalStencilTestEnabled() const OVERRIDE {
180 return external_stencil_test_enabled_;
183 void EnableExternalStencilTest() {
184 external_stencil_test_enabled_ = true;
187 // Methods added for test.
188 int set_full_root_layer_damage_count() const {
189 return set_full_root_layer_damage_count_;
191 void set_viewport_and_scale(
192 gfx::Size viewport_size, float scale_factor) {
193 viewport_size_ = viewport_size;
194 scale_factor_ = scale_factor;
197 RenderPass* root_render_pass() { return render_passes_in_draw_order_.back(); }
198 RenderPassList* render_passes_in_draw_order() {
199 return &render_passes_in_draw_order_;
202 private:
203 FakeImplProxy proxy_;
204 FakeLayerTreeHostImpl host_impl_;
205 int set_full_root_layer_damage_count_;
206 scoped_ptr<LayerImpl> root_layer_;
207 RenderPassList render_passes_in_draw_order_;
208 gfx::Size viewport_size_;
209 float scale_factor_;
210 bool external_stencil_test_enabled_;
213 class FakeRendererGL : public GLRenderer {
214 public:
215 FakeRendererGL(RendererClient* client,
216 OutputSurface* output_surface,
217 ResourceProvider* resource_provider)
218 : GLRenderer(client, output_surface, resource_provider, 0) {}
220 // GLRenderer methods.
222 // Changing visibility to public.
223 using GLRenderer::Initialize;
224 using GLRenderer::IsBackbufferDiscarded;
225 using GLRenderer::DoDrawQuad;
226 using GLRenderer::BeginDrawingFrame;
227 using GLRenderer::FinishDrawingQuadList;
228 using GLRenderer::stencil_enabled;
231 class GLRendererTest : public testing::Test {
232 protected:
233 GLRendererTest() {
234 scoped_ptr<FrameCountingContext> context3d(new FrameCountingContext);
235 context3d_ = context3d.get();
237 output_surface_ = FakeOutputSurface::Create3d(
238 context3d.PassAs<TestWebGraphicsContext3D>()).Pass();
239 CHECK(output_surface_->BindToClient(&output_surface_client_));
241 resource_provider_ =
242 ResourceProvider::Create(output_surface_.get(), 0).Pass();
243 renderer_ = make_scoped_ptr(new FakeRendererGL(
244 &renderer_client_,
245 output_surface_.get(),
246 resource_provider_.get()));
249 virtual void SetUp() { renderer_->Initialize(); }
251 void SwapBuffers() { renderer_->SwapBuffers(); }
253 FrameCountingContext* context3d_;
254 FakeOutputSurfaceClient output_surface_client_;
255 scoped_ptr<FakeOutputSurface> output_surface_;
256 FakeRendererClient renderer_client_;
257 scoped_ptr<ResourceProvider> resource_provider_;
258 scoped_ptr<FakeRendererGL> renderer_;
261 // Closing the namespace here so that GLRendererShaderTest can take advantage
262 // of the friend relationship with GLRenderer and all of the mock classes
263 // declared above it.
264 } // namespace
267 // Gives unique shader ids and unique program ids for tests that need them.
268 class ShaderCreatorMockGraphicsContext : public TestWebGraphicsContext3D {
269 public:
270 ShaderCreatorMockGraphicsContext()
271 : next_program_id_number_(10000),
272 next_shader_id_number_(1) {}
274 bool hasShader(WebGLId shader) {
275 return shader_set_.find(shader) != shader_set_.end();
278 bool hasProgram(WebGLId program) {
279 return program_set_.find(program) != program_set_.end();
282 virtual WebGLId createProgram() {
283 unsigned program = next_program_id_number_;
284 program_set_.insert(program);
285 next_program_id_number_++;
286 return program;
289 virtual void deleteProgram(WebGLId program) {
290 ASSERT_TRUE(hasProgram(program));
291 program_set_.erase(program);
294 virtual void useProgram(WebGLId program) {
295 if (!program)
296 return;
297 ASSERT_TRUE(hasProgram(program));
300 virtual WebKit::WebGLId createShader(WebKit::WGC3Denum) {
301 unsigned shader = next_shader_id_number_;
302 shader_set_.insert(shader);
303 next_shader_id_number_++;
304 return shader;
307 virtual void deleteShader(WebKit::WebGLId shader) {
308 ASSERT_TRUE(hasShader(shader));
309 shader_set_.erase(shader);
312 virtual void attachShader(WebGLId program, WebGLId shader) {
313 ASSERT_TRUE(hasProgram(program));
314 ASSERT_TRUE(hasShader(shader));
317 protected:
318 unsigned next_program_id_number_;
319 unsigned next_shader_id_number_;
320 std::set<unsigned> program_set_;
321 std::set<unsigned> shader_set_;
324 class GLRendererShaderTest : public testing::Test {
325 protected:
326 GLRendererShaderTest() {
327 output_surface_ = FakeOutputSurface::Create3d(
328 scoped_ptr<TestWebGraphicsContext3D>(
329 new ShaderCreatorMockGraphicsContext())).Pass();
330 CHECK(output_surface_->BindToClient(&output_surface_client_));
332 resource_provider_ = ResourceProvider::Create(output_surface_.get(),
333 0).Pass();
334 renderer_.reset(new FakeRendererGL(&renderer_client_,
335 output_surface_.get(),
336 resource_provider_.get()));
337 renderer_->Initialize();
340 void TestRenderPassProgram() {
341 EXPECT_PROGRAM_VALID(renderer_->render_pass_program_);
342 EXPECT_EQ(renderer_->render_pass_program_->program(),
343 renderer_->program_shadow_);
346 void TestRenderPassColorMatrixProgram() {
347 EXPECT_PROGRAM_VALID(renderer_->render_pass_color_matrix_program_);
348 EXPECT_EQ(renderer_->render_pass_color_matrix_program_->program(),
349 renderer_->program_shadow_);
352 void TestRenderPassMaskProgram() {
353 EXPECT_PROGRAM_VALID(renderer_->render_pass_mask_program_);
354 EXPECT_EQ(renderer_->render_pass_mask_program_->program(),
355 renderer_->program_shadow_);
358 void TestRenderPassMaskColorMatrixProgram() {
359 EXPECT_PROGRAM_VALID(renderer_->render_pass_mask_color_matrix_program_);
360 EXPECT_EQ(renderer_->render_pass_mask_color_matrix_program_->program(),
361 renderer_->program_shadow_);
364 void TestRenderPassProgramAA() {
365 EXPECT_PROGRAM_VALID(renderer_->render_pass_program_aa_);
366 EXPECT_EQ(renderer_->render_pass_program_aa_->program(),
367 renderer_->program_shadow_);
370 void TestRenderPassColorMatrixProgramAA() {
371 EXPECT_PROGRAM_VALID(renderer_->render_pass_color_matrix_program_aa_);
372 EXPECT_EQ(renderer_->render_pass_color_matrix_program_aa_->program(),
373 renderer_->program_shadow_);
376 void TestRenderPassMaskProgramAA() {
377 EXPECT_PROGRAM_VALID(renderer_->render_pass_mask_program_aa_);
378 EXPECT_EQ(renderer_->render_pass_mask_program_aa_->program(),
379 renderer_->program_shadow_);
382 void TestRenderPassMaskColorMatrixProgramAA() {
383 EXPECT_PROGRAM_VALID(renderer_->render_pass_mask_color_matrix_program_aa_);
384 EXPECT_EQ(renderer_->render_pass_mask_color_matrix_program_aa_->program(),
385 renderer_->program_shadow_);
388 void TestSolidColorProgramAA() {
389 EXPECT_PROGRAM_VALID(renderer_->solid_color_program_aa_);
390 EXPECT_EQ(renderer_->solid_color_program_aa_->program(),
391 renderer_->program_shadow_);
394 FakeOutputSurfaceClient output_surface_client_;
395 scoped_ptr<FakeOutputSurface> output_surface_;
396 FakeRendererClient renderer_client_;
397 scoped_ptr<ResourceProvider> resource_provider_;
398 scoped_ptr<FakeRendererGL> renderer_;
401 namespace {
403 // Test GLRenderer discardBackbuffer functionality:
404 // Suggest recreating framebuffer when one already exists.
405 // Expected: it does nothing.
406 TEST_F(GLRendererTest, SuggestBackbufferYesWhenItAlreadyExistsShouldDoNothing) {
407 renderer_->SetDiscardBackBufferWhenNotVisible(false);
408 EXPECT_EQ(0, renderer_client_.set_full_root_layer_damage_count());
409 EXPECT_FALSE(renderer_->IsBackbufferDiscarded());
411 SwapBuffers();
412 EXPECT_EQ(1, context3d_->frame_count());
415 // Test GLRenderer DiscardBackbuffer functionality:
416 // Suggest discarding framebuffer when one exists and the renderer is not
417 // visible.
418 // Expected: it is discarded and damage tracker is reset.
419 TEST_F(
420 GLRendererTest,
421 SuggestBackbufferNoShouldDiscardBackbufferAndDamageRootLayerIfNotVisible) {
422 renderer_->SetVisible(false);
423 renderer_->SetDiscardBackBufferWhenNotVisible(true);
424 EXPECT_EQ(1, renderer_client_.set_full_root_layer_damage_count());
425 EXPECT_TRUE(renderer_->IsBackbufferDiscarded());
428 // Test GLRenderer DiscardBackbuffer functionality:
429 // Suggest discarding framebuffer when one exists and the renderer is visible.
430 // Expected: the allocation is ignored.
431 TEST_F(GLRendererTest, SuggestBackbufferNoDoNothingWhenVisible) {
432 renderer_->SetVisible(true);
433 renderer_->SetDiscardBackBufferWhenNotVisible(true);
434 EXPECT_EQ(0, renderer_client_.set_full_root_layer_damage_count());
435 EXPECT_FALSE(renderer_->IsBackbufferDiscarded());
438 // Test GLRenderer DiscardBackbuffer functionality:
439 // Suggest discarding framebuffer when one does not exist.
440 // Expected: it does nothing.
441 TEST_F(GLRendererTest, SuggestBackbufferNoWhenItDoesntExistShouldDoNothing) {
442 renderer_->SetVisible(false);
443 renderer_->SetDiscardBackBufferWhenNotVisible(true);
444 EXPECT_EQ(1, renderer_client_.set_full_root_layer_damage_count());
445 EXPECT_TRUE(renderer_->IsBackbufferDiscarded());
447 renderer_->SetDiscardBackBufferWhenNotVisible(true);
448 EXPECT_EQ(1, renderer_client_.set_full_root_layer_damage_count());
449 EXPECT_TRUE(renderer_->IsBackbufferDiscarded());
452 // Test GLRenderer DiscardBackbuffer functionality:
453 // Begin drawing a frame while a framebuffer is discarded.
454 // Expected: will recreate framebuffer.
455 TEST_F(GLRendererTest, DiscardedBackbufferIsRecreatedForScopeDuration) {
456 renderer_->SetVisible(false);
457 renderer_->SetDiscardBackBufferWhenNotVisible(true);
458 EXPECT_TRUE(renderer_->IsBackbufferDiscarded());
459 EXPECT_EQ(1, renderer_client_.set_full_root_layer_damage_count());
461 renderer_->SetVisible(true);
462 renderer_->DrawFrame(renderer_client_.render_passes_in_draw_order(), NULL);
463 EXPECT_FALSE(renderer_->IsBackbufferDiscarded());
465 SwapBuffers();
466 EXPECT_EQ(1, context3d_->frame_count());
469 TEST_F(GLRendererTest, FramebufferDiscardedAfterReadbackWhenNotVisible) {
470 renderer_->SetVisible(false);
471 renderer_->SetDiscardBackBufferWhenNotVisible(true);
472 EXPECT_TRUE(renderer_->IsBackbufferDiscarded());
473 EXPECT_EQ(1, renderer_client_.set_full_root_layer_damage_count());
475 char pixels[4];
476 renderer_->DrawFrame(renderer_client_.render_passes_in_draw_order(), NULL);
477 EXPECT_FALSE(renderer_->IsBackbufferDiscarded());
479 renderer_->GetFramebufferPixels(pixels, gfx::Rect(0, 0, 1, 1));
480 EXPECT_TRUE(renderer_->IsBackbufferDiscarded());
481 EXPECT_EQ(2, renderer_client_.set_full_root_layer_damage_count());
484 TEST_F(GLRendererTest, ExternalStencil) {
485 EXPECT_FALSE(renderer_->stencil_enabled());
487 renderer_client_.EnableExternalStencilTest();
488 renderer_client_.root_render_pass()->has_transparent_background = false;
490 renderer_->DrawFrame(renderer_client_.render_passes_in_draw_order(), NULL);
491 EXPECT_TRUE(renderer_->stencil_enabled());
494 class ForbidSynchronousCallContext : public TestWebGraphicsContext3D {
495 public:
496 ForbidSynchronousCallContext() {}
498 virtual bool getActiveAttrib(WebGLId program,
499 WGC3Duint index,
500 ActiveInfo& info) {
501 ADD_FAILURE();
502 return false;
504 virtual bool getActiveUniform(WebGLId program,
505 WGC3Duint index,
506 ActiveInfo& info) {
507 ADD_FAILURE();
508 return false;
510 virtual void getAttachedShaders(WebGLId program,
511 WGC3Dsizei max_count,
512 WGC3Dsizei* count,
513 WebGLId* shaders) {
514 ADD_FAILURE();
516 virtual WGC3Dint getAttribLocation(WebGLId program, const WGC3Dchar* name) {
517 ADD_FAILURE();
518 return 0;
520 virtual void getBooleanv(WGC3Denum pname, WGC3Dboolean* value) {
521 ADD_FAILURE();
523 virtual void getBufferParameteriv(WGC3Denum target,
524 WGC3Denum pname,
525 WGC3Dint* value) {
526 ADD_FAILURE();
528 virtual Attributes getContextAttributes() {
529 ADD_FAILURE();
530 return attributes_;
532 virtual WGC3Denum getError() {
533 ADD_FAILURE();
534 return 0;
536 virtual void getFloatv(WGC3Denum pname, WGC3Dfloat* value) { ADD_FAILURE(); }
537 virtual void getFramebufferAttachmentParameteriv(WGC3Denum target,
538 WGC3Denum attachment,
539 WGC3Denum pname,
540 WGC3Dint* value) {
541 ADD_FAILURE();
543 virtual void getIntegerv(WGC3Denum pname, WGC3Dint* value) {
544 if (pname == GL_MAX_TEXTURE_SIZE) {
545 // MAX_TEXTURE_SIZE is cached client side, so it's OK to query.
546 *value = 1024;
547 } else {
548 ADD_FAILURE();
552 // We allow querying the shader compilation and program link status in debug
553 // mode, but not release.
554 virtual void getProgramiv(WebGLId program, WGC3Denum pname, WGC3Dint* value) {
555 #ifndef NDEBUG
556 *value = 1;
557 #else
558 ADD_FAILURE();
559 #endif
562 virtual void getShaderiv(WebGLId shader, WGC3Denum pname, WGC3Dint* value) {
563 #ifndef NDEBUG
564 *value = 1;
565 #else
566 ADD_FAILURE();
567 #endif
570 virtual WebString getString(WGC3Denum name) {
571 ADD_FAILURE() << name;
572 return WebString();
575 virtual WebString getProgramInfoLog(WebGLId program) {
576 ADD_FAILURE();
577 return WebString();
579 virtual void getRenderbufferParameteriv(WGC3Denum target,
580 WGC3Denum pname,
581 WGC3Dint* value) {
582 ADD_FAILURE();
585 virtual WebString getShaderInfoLog(WebGLId shader) {
586 ADD_FAILURE();
587 return WebString();
589 virtual void getShaderPrecisionFormat(WGC3Denum shadertype,
590 WGC3Denum precisiontype,
591 WGC3Dint* range,
592 WGC3Dint* precision) {
593 ADD_FAILURE();
595 virtual WebString getShaderSource(WebGLId shader) {
596 ADD_FAILURE();
597 return WebString();
599 virtual void getTexParameterfv(WGC3Denum target,
600 WGC3Denum pname,
601 WGC3Dfloat* value) {
602 ADD_FAILURE();
604 virtual void getTexParameteriv(WGC3Denum target,
605 WGC3Denum pname,
606 WGC3Dint* value) {
607 ADD_FAILURE();
609 virtual void getUniformfv(WebGLId program,
610 WGC3Dint location,
611 WGC3Dfloat* value) {
612 ADD_FAILURE();
614 virtual void getUniformiv(WebGLId program,
615 WGC3Dint location,
616 WGC3Dint* value) {
617 ADD_FAILURE();
619 virtual WGC3Dint getUniformLocation(WebGLId program, const WGC3Dchar* name) {
620 ADD_FAILURE();
621 return 0;
623 virtual void getVertexAttribfv(WGC3Duint index,
624 WGC3Denum pname,
625 WGC3Dfloat* value) {
626 ADD_FAILURE();
628 virtual void getVertexAttribiv(WGC3Duint index,
629 WGC3Denum pname,
630 WGC3Dint* value) {
631 ADD_FAILURE();
633 virtual WGC3Dsizeiptr getVertexAttribOffset(WGC3Duint index,
634 WGC3Denum pname) {
635 ADD_FAILURE();
636 return 0;
640 // This test isn't using the same fixture as GLRendererTest, and you can't mix
641 // TEST() and TEST_F() with the same name, Hence LRC2.
642 TEST(GLRendererTest2, 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));
648 scoped_ptr<ResourceProvider> resource_provider(
649 ResourceProvider::Create(output_surface.get(), 0));
651 FakeRendererClient renderer_client;
652 FakeRendererGL renderer(
653 &renderer_client, output_surface.get(), resource_provider.get());
655 EXPECT_TRUE(renderer.Initialize());
658 class LoseContextOnFirstGetContext : public TestWebGraphicsContext3D {
659 public:
660 LoseContextOnFirstGetContext() : context_lost_(false) {}
662 virtual bool makeContextCurrent() OVERRIDE { return !context_lost_; }
664 virtual void getProgramiv(WebGLId program, WGC3Denum pname, WGC3Dint* value)
665 OVERRIDE {
666 context_lost_ = true;
667 *value = 0;
670 virtual void getShaderiv(WebGLId shader, WGC3Denum pname, WGC3Dint* value)
671 OVERRIDE {
672 context_lost_ = true;
673 *value = 0;
676 virtual WGC3Denum getGraphicsResetStatusARB() OVERRIDE {
677 return context_lost_ ? 1 : 0;
680 private:
681 bool context_lost_;
684 TEST(GLRendererTest2, InitializationWithQuicklyLostContextDoesNotAssert) {
685 FakeOutputSurfaceClient output_surface_client;
686 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
687 scoped_ptr<TestWebGraphicsContext3D>(new LoseContextOnFirstGetContext)));
688 CHECK(output_surface->BindToClient(&output_surface_client));
690 scoped_ptr<ResourceProvider> resource_provider(
691 ResourceProvider::Create(output_surface.get(), 0));
693 FakeRendererClient renderer_client;
694 FakeRendererGL renderer(
695 &renderer_client, output_surface.get(), resource_provider.get());
697 renderer.Initialize();
700 class ClearCountingContext : public TestWebGraphicsContext3D {
701 public:
702 ClearCountingContext() : clear_(0) {}
704 virtual void clear(WGC3Dbitfield) { clear_++; }
706 int clear_count() const { return clear_; }
708 private:
709 int clear_;
712 TEST(GLRendererTest2, OpaqueBackground) {
713 scoped_ptr<ClearCountingContext> context_owned(new ClearCountingContext);
714 ClearCountingContext* context = context_owned.get();
716 FakeOutputSurfaceClient output_surface_client;
717 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
718 context_owned.PassAs<TestWebGraphicsContext3D>()));
719 CHECK(output_surface->BindToClient(&output_surface_client));
721 scoped_ptr<ResourceProvider> resource_provider(
722 ResourceProvider::Create(output_surface.get(), 0));
724 FakeRendererClient renderer_client;
725 FakeRendererGL renderer(
726 &renderer_client, output_surface.get(), resource_provider.get());
728 renderer_client.root_render_pass()->has_transparent_background = false;
730 EXPECT_TRUE(renderer.Initialize());
732 renderer.DrawFrame(renderer_client.render_passes_in_draw_order(), NULL);
734 // On DEBUG builds, render passes with opaque background clear to blue to
735 // easily see regions that were not drawn on the screen.
736 #ifdef NDEBUG
737 EXPECT_EQ(0, context->clear_count());
738 #else
739 EXPECT_EQ(1, context->clear_count());
740 #endif
743 TEST(GLRendererTest2, TransparentBackground) {
744 scoped_ptr<ClearCountingContext> context_owned(new ClearCountingContext);
745 ClearCountingContext* context = context_owned.get();
747 FakeOutputSurfaceClient output_surface_client;
748 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
749 context_owned.PassAs<TestWebGraphicsContext3D>()));
750 CHECK(output_surface->BindToClient(&output_surface_client));
752 scoped_ptr<ResourceProvider> resource_provider(
753 ResourceProvider::Create(output_surface.get(), 0));
755 FakeRendererClient renderer_client;
756 FakeRendererGL renderer(
757 &renderer_client, output_surface.get(), resource_provider.get());
759 renderer_client.root_render_pass()->has_transparent_background = true;
761 EXPECT_TRUE(renderer.Initialize());
763 renderer.DrawFrame(renderer_client.render_passes_in_draw_order(), NULL);
765 EXPECT_EQ(1, context->clear_count());
768 class VisibilityChangeIsLastCallTrackingContext
769 : public TestWebGraphicsContext3D {
770 public:
771 VisibilityChangeIsLastCallTrackingContext()
772 : last_call_was_set_visibility_(false) {
773 test_capabilities_.set_visibility = true;
774 test_capabilities_.discard_backbuffer = true;
777 // WebGraphicsContext3D methods.
778 virtual void setVisibilityCHROMIUM(bool visible) {
779 DCHECK(last_call_was_set_visibility_ == false);
780 last_call_was_set_visibility_ = true;
782 virtual void flush() {
783 last_call_was_set_visibility_ = false;
785 virtual void deleteTexture(WebGLId) {
786 last_call_was_set_visibility_ = false;
788 virtual void deleteFramebuffer(WebGLId) {
789 last_call_was_set_visibility_ = false;
791 virtual void deleteQueryEXT(WebGLId) {
792 last_call_was_set_visibility_ = false;
794 virtual void deleteRenderbuffer(WebGLId) {
795 last_call_was_set_visibility_ = false;
797 virtual void discardBackbufferCHROMIUM() {
798 last_call_was_set_visibility_ = false;
800 virtual void ensureBackbufferCHROMIUM() {
801 last_call_was_set_visibility_ = false;
804 // Methods added for test.
805 bool last_call_was_set_visibility() const {
806 return last_call_was_set_visibility_;
809 private:
810 bool last_call_was_set_visibility_;
813 TEST(GLRendererTest2, VisibilityChangeIsLastCall) {
814 scoped_ptr<VisibilityChangeIsLastCallTrackingContext> context_owned(
815 new VisibilityChangeIsLastCallTrackingContext);
816 VisibilityChangeIsLastCallTrackingContext* context = context_owned.get();
818 FakeOutputSurfaceClient output_surface_client;
819 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
820 context_owned.PassAs<TestWebGraphicsContext3D>()));
821 CHECK(output_surface->BindToClient(&output_surface_client));
823 scoped_ptr<ResourceProvider> resource_provider(
824 ResourceProvider::Create(output_surface.get(), 0));
826 FakeRendererClient renderer_client;
827 FakeRendererGL renderer(
828 &renderer_client, output_surface.get(), resource_provider.get());
830 EXPECT_TRUE(renderer.Initialize());
832 // Ensure that the call to setVisibilityCHROMIUM is the last call issue to the
833 // GPU process, after glFlush is called, and after the RendererClient's
834 // SetManagedMemoryPolicy is called. Plumb this tracking between both the
835 // RenderClient and the Context by giving them both a pointer to a variable on
836 // the stack.
837 renderer.SetVisible(true);
838 renderer.DrawFrame(renderer_client.render_passes_in_draw_order(), NULL);
839 renderer.SetVisible(false);
840 EXPECT_TRUE(context->last_call_was_set_visibility());
843 class TextureStateTrackingContext : public TestWebGraphicsContext3D {
844 public:
845 TextureStateTrackingContext()
846 : active_texture_(GL_INVALID_ENUM) {
847 test_capabilities_.egl_image_external = true;
850 MOCK_METHOD3(texParameteri,
851 void(WGC3Denum target, WGC3Denum pname, WGC3Dint param));
852 MOCK_METHOD4(drawElements,
853 void(WGC3Denum mode,
854 WGC3Dsizei count,
855 WGC3Denum type,
856 WGC3Dintptr offset));
858 virtual void activeTexture(WGC3Denum texture) {
859 EXPECT_NE(texture, active_texture_);
860 active_texture_ = texture;
863 WGC3Denum active_texture() const { return active_texture_; }
865 private:
866 WGC3Denum active_texture_;
869 TEST(GLRendererTest2, ActiveTextureState) {
870 scoped_ptr<TextureStateTrackingContext> context_owned(
871 new TextureStateTrackingContext);
872 TextureStateTrackingContext* context = context_owned.get();
874 FakeOutputSurfaceClient output_surface_client;
875 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
876 context_owned.PassAs<TestWebGraphicsContext3D>()));
877 CHECK(output_surface->BindToClient(&output_surface_client));
879 scoped_ptr<ResourceProvider> resource_provider(
880 ResourceProvider::Create(output_surface.get(), 0));
882 FakeRendererClient renderer_client;
883 FakeRendererGL renderer(
884 &renderer_client, output_surface.get(), resource_provider.get());
886 // During initialization we are allowed to set any texture parameters.
887 EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
888 EXPECT_TRUE(renderer.Initialize());
890 cc::RenderPass::Id id(1, 1);
891 scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
892 pass->SetNew(id,
893 gfx::Rect(0, 0, 100, 100),
894 gfx::Rect(0, 0, 100, 100),
895 gfx::Transform());
896 pass->AppendOneOfEveryQuadType(resource_provider.get(), RenderPass::Id(2, 1));
898 // Set up expected texture filter state transitions that match the quads
899 // created in AppendOneOfEveryQuadType().
900 Mock::VerifyAndClearExpectations(context);
902 InSequence sequence;
904 // yuv_quad is drawn with the default linear filter.
905 EXPECT_CALL(*context, drawElements(_, _, _, _));
907 // tile_quad is drawn with GL_NEAREST because it is not transformed or
908 // scaled.
909 EXPECT_CALL(
910 *context,
911 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
912 EXPECT_CALL(
913 *context,
914 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
915 EXPECT_CALL(*context, drawElements(_, _, _, _));
917 // transformed_tile_quad uses GL_LINEAR.
918 EXPECT_CALL(*context, drawElements(_, _, _, _));
920 // scaled_tile_quad also uses GL_LINEAR.
921 EXPECT_CALL(*context, drawElements(_, _, _, _));
923 // The remaining quads also use GL_LINEAR because nearest neighbor
924 // filtering is currently only used with tile quads.
925 EXPECT_CALL(*context, drawElements(_, _, _, _)).Times(6);
928 cc::DirectRenderer::DrawingFrame drawing_frame;
929 renderer.BeginDrawingFrame(&drawing_frame);
930 EXPECT_EQ(static_cast<unsigned>(GL_TEXTURE0), context->active_texture());
932 for (cc::QuadList::BackToFrontIterator
933 it = pass->quad_list.BackToFrontBegin();
934 it != pass->quad_list.BackToFrontEnd();
935 ++it) {
936 renderer.DoDrawQuad(&drawing_frame, *it);
938 renderer.FinishDrawingQuadList();
939 EXPECT_EQ(static_cast<unsigned>(GL_TEXTURE0), context->active_texture());
940 Mock::VerifyAndClearExpectations(context);
943 class NoClearRootRenderPassFakeClient : public FakeRendererClient {
944 public:
945 virtual bool ShouldClearRootRenderPass() const OVERRIDE { return false; }
948 class NoClearRootRenderPassMockContext : public TestWebGraphicsContext3D {
949 public:
950 MOCK_METHOD1(clear, void(WGC3Dbitfield mask));
951 MOCK_METHOD4(drawElements,
952 void(WGC3Denum mode,
953 WGC3Dsizei count,
954 WGC3Denum type,
955 WGC3Dintptr offset));
958 TEST(GLRendererTest2, ShouldClearRootRenderPass) {
959 scoped_ptr<NoClearRootRenderPassMockContext> mock_context_owned(
960 new NoClearRootRenderPassMockContext);
961 NoClearRootRenderPassMockContext* mock_context = mock_context_owned.get();
963 FakeOutputSurfaceClient output_surface_client;
964 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
965 mock_context_owned.PassAs<TestWebGraphicsContext3D>()));
966 CHECK(output_surface->BindToClient(&output_surface_client));
968 scoped_ptr<ResourceProvider> resource_provider(
969 ResourceProvider::Create(output_surface.get(), 0));
971 NoClearRootRenderPassFakeClient renderer_client;
972 FakeRendererGL renderer(
973 &renderer_client, output_surface.get(), resource_provider.get());
974 EXPECT_TRUE(renderer.Initialize());
976 gfx::Rect viewport_rect(renderer_client.DeviceViewport());
977 ScopedPtrVector<RenderPass>& render_passes =
978 *renderer_client.render_passes_in_draw_order();
979 render_passes.clear();
981 RenderPass::Id root_pass_id(1, 0);
982 TestRenderPass* root_pass = AddRenderPass(
983 &render_passes, root_pass_id, viewport_rect, gfx::Transform());
984 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
986 RenderPass::Id child_pass_id(2, 0);
987 TestRenderPass* child_pass = AddRenderPass(
988 &render_passes, child_pass_id, viewport_rect, gfx::Transform());
989 AddQuad(child_pass, viewport_rect, SK_ColorBLUE);
991 AddRenderPassQuad(root_pass, child_pass);
993 #ifdef NDEBUG
994 GLint clear_bits = GL_COLOR_BUFFER_BIT;
995 #else
996 GLint clear_bits = GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
997 #endif
999 // First render pass is not the root one, clearing should happen.
1000 EXPECT_CALL(*mock_context, clear(clear_bits)).Times(AtLeast(1));
1002 Expectation first_render_pass =
1003 EXPECT_CALL(*mock_context, drawElements(_, _, _, _)).Times(1);
1005 // The second render pass is the root one, clearing should be prevented.
1006 EXPECT_CALL(*mock_context, clear(clear_bits)).Times(0)
1007 .After(first_render_pass);
1009 EXPECT_CALL(*mock_context, drawElements(_, _, _, _)).Times(AnyNumber())
1010 .After(first_render_pass);
1012 renderer.DecideRenderPassAllocationsForFrame(
1013 *renderer_client.render_passes_in_draw_order());
1014 renderer.DrawFrame(renderer_client.render_passes_in_draw_order(), NULL);
1016 // In multiple render passes all but the root pass should clear the
1017 // framebuffer.
1018 Mock::VerifyAndClearExpectations(&mock_context);
1021 class ScissorTestOnClearCheckingContext : public TestWebGraphicsContext3D {
1022 public:
1023 ScissorTestOnClearCheckingContext() : scissor_enabled_(false) {}
1025 virtual void clear(WGC3Dbitfield) { EXPECT_FALSE(scissor_enabled_); }
1027 virtual void enable(WGC3Denum cap) {
1028 if (cap == GL_SCISSOR_TEST)
1029 scissor_enabled_ = true;
1032 virtual void disable(WGC3Denum cap) {
1033 if (cap == GL_SCISSOR_TEST)
1034 scissor_enabled_ = false;
1037 private:
1038 bool scissor_enabled_;
1041 TEST(GLRendererTest2, ScissorTestWhenClearing) {
1042 scoped_ptr<ScissorTestOnClearCheckingContext> context_owned(
1043 new ScissorTestOnClearCheckingContext);
1045 FakeOutputSurfaceClient output_surface_client;
1046 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
1047 context_owned.PassAs<TestWebGraphicsContext3D>()));
1048 CHECK(output_surface->BindToClient(&output_surface_client));
1050 scoped_ptr<ResourceProvider> resource_provider(
1051 ResourceProvider::Create(output_surface.get(), 0));
1053 FakeRendererClient renderer_client;
1054 FakeRendererGL renderer(
1055 &renderer_client, output_surface.get(), resource_provider.get());
1056 EXPECT_TRUE(renderer.Initialize());
1057 EXPECT_FALSE(renderer.Capabilities().using_partial_swap);
1059 gfx::Rect viewport_rect(renderer_client.DeviceViewport());
1060 ScopedPtrVector<RenderPass>& render_passes =
1061 *renderer_client.render_passes_in_draw_order();
1062 render_passes.clear();
1064 gfx::Rect grand_child_rect(25, 25);
1065 RenderPass::Id grand_child_pass_id(3, 0);
1066 TestRenderPass* grand_child_pass = AddRenderPass(
1067 &render_passes, grand_child_pass_id, grand_child_rect, gfx::Transform());
1068 AddClippedQuad(grand_child_pass, grand_child_rect, SK_ColorYELLOW);
1070 gfx::Rect child_rect(50, 50);
1071 RenderPass::Id child_pass_id(2, 0);
1072 TestRenderPass* child_pass = AddRenderPass(
1073 &render_passes, child_pass_id, child_rect, gfx::Transform());
1074 AddQuad(child_pass, child_rect, SK_ColorBLUE);
1076 RenderPass::Id root_pass_id(1, 0);
1077 TestRenderPass* root_pass = AddRenderPass(
1078 &render_passes, root_pass_id, viewport_rect, gfx::Transform());
1079 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1081 AddRenderPassQuad(root_pass, child_pass);
1082 AddRenderPassQuad(child_pass, grand_child_pass);
1084 renderer.DecideRenderPassAllocationsForFrame(
1085 *renderer_client.render_passes_in_draw_order());
1086 renderer.DrawFrame(renderer_client.render_passes_in_draw_order(), NULL);
1089 class NonReshapableOutputSurface : public FakeOutputSurface {
1090 public:
1091 explicit NonReshapableOutputSurface(
1092 scoped_ptr<TestWebGraphicsContext3D> context3d)
1093 : FakeOutputSurface(
1094 TestContextProvider::Create(context3d.Pass()),
1095 false) {}
1096 virtual gfx::Size SurfaceSize() const OVERRIDE { return gfx::Size(500, 500); }
1099 class OffsetViewportRendererClient : public FakeRendererClient {
1100 public:
1101 virtual gfx::Rect DeviceViewport() const OVERRIDE {
1102 return gfx::Rect(10, 10, 100, 100);
1106 class FlippedScissorAndViewportContext : public TestWebGraphicsContext3D {
1107 public:
1108 FlippedScissorAndViewportContext()
1109 : did_call_viewport_(false), did_call_scissor_(false) {}
1110 virtual ~FlippedScissorAndViewportContext() {
1111 EXPECT_TRUE(did_call_viewport_);
1112 EXPECT_TRUE(did_call_scissor_);
1115 virtual void viewport(GLint x, GLint y, GLsizei width, GLsizei height) {
1116 EXPECT_EQ(10, x);
1117 EXPECT_EQ(390, y);
1118 EXPECT_EQ(100, width);
1119 EXPECT_EQ(100, height);
1120 did_call_viewport_ = true;
1123 virtual void scissor(GLint x, GLint y, GLsizei width, GLsizei height) {
1124 EXPECT_EQ(30, x);
1125 EXPECT_EQ(450, y);
1126 EXPECT_EQ(20, width);
1127 EXPECT_EQ(20, height);
1128 did_call_scissor_ = true;
1131 private:
1132 bool did_call_viewport_;
1133 bool did_call_scissor_;
1136 TEST(GLRendererTest2, ScissorAndViewportWithinNonreshapableSurface) {
1137 // In Android WebView, the OutputSurface is unable to respect reshape() calls
1138 // and maintains a fixed size. This test verifies that glViewport and
1139 // glScissor's Y coordinate is flipped correctly in this environment, and that
1140 // the glViewport can be at a nonzero origin within the surface.
1141 scoped_ptr<FlippedScissorAndViewportContext> context_owned(
1142 new FlippedScissorAndViewportContext);
1144 FakeOutputSurfaceClient output_surface_client;
1145 scoped_ptr<OutputSurface> output_surface(new NonReshapableOutputSurface(
1146 context_owned.PassAs<TestWebGraphicsContext3D>()));
1147 CHECK(output_surface->BindToClient(&output_surface_client));
1149 scoped_ptr<ResourceProvider> resource_provider(
1150 ResourceProvider::Create(output_surface.get(), 0));
1152 OffsetViewportRendererClient renderer_client;
1153 FakeRendererGL renderer(
1154 &renderer_client, output_surface.get(), resource_provider.get());
1155 EXPECT_TRUE(renderer.Initialize());
1156 EXPECT_FALSE(renderer.Capabilities().using_partial_swap);
1158 gfx::Rect viewport_rect(renderer_client.DeviceViewport().size());
1159 gfx::Rect quad_rect = gfx::Rect(20, 20, 20, 20);
1160 ScopedPtrVector<RenderPass>& render_passes =
1161 *renderer_client.render_passes_in_draw_order();
1162 render_passes.clear();
1164 RenderPass::Id root_pass_id(1, 0);
1165 TestRenderPass* root_pass = AddRenderPass(
1166 &render_passes, root_pass_id, viewport_rect, gfx::Transform());
1167 AddClippedQuad(root_pass, quad_rect, SK_ColorGREEN);
1169 renderer.DecideRenderPassAllocationsForFrame(
1170 *renderer_client.render_passes_in_draw_order());
1171 renderer.DrawFrame(renderer_client.render_passes_in_draw_order(), NULL);
1174 TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) {
1175 gfx::Rect viewport_rect(renderer_client_.DeviceViewport());
1176 ScopedPtrVector<RenderPass>* render_passes =
1177 renderer_client_.render_passes_in_draw_order();
1179 gfx::Rect child_rect(50, 50);
1180 RenderPass::Id child_pass_id(2, 0);
1181 TestRenderPass* child_pass;
1183 RenderPass::Id root_pass_id(1, 0);
1184 TestRenderPass* root_pass;
1186 cc::ResourceProvider::ResourceId mask =
1187 resource_provider_->CreateResource(gfx::Size(20, 12),
1188 resource_provider_->best_texture_format(),
1189 ResourceProvider::TextureUsageAny);
1190 resource_provider_->AllocateForTesting(mask);
1192 SkScalar matrix[20];
1193 float amount = 0.5f;
1194 matrix[0] = 0.213f + 0.787f * amount;
1195 matrix[1] = 0.715f - 0.715f * amount;
1196 matrix[2] = 1.f - (matrix[0] + matrix[1]);
1197 matrix[3] = matrix[4] = 0;
1198 matrix[5] = 0.213f - 0.213f * amount;
1199 matrix[6] = 0.715f + 0.285f * amount;
1200 matrix[7] = 1.f - (matrix[5] + matrix[6]);
1201 matrix[8] = matrix[9] = 0;
1202 matrix[10] = 0.213f - 0.213f * amount;
1203 matrix[11] = 0.715f - 0.715f * amount;
1204 matrix[12] = 1.f - (matrix[10] + matrix[11]);
1205 matrix[13] = matrix[14] = 0;
1206 matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0;
1207 matrix[18] = 1;
1208 skia::RefPtr<SkColorFilter> color_filter(
1209 skia::AdoptRef(new SkColorMatrixFilter(matrix)));
1210 skia::RefPtr<SkImageFilter> filter = skia::AdoptRef(
1211 SkColorFilterImageFilter::Create(color_filter.get(), NULL));
1213 gfx::Transform transform_causing_aa;
1214 transform_causing_aa.Rotate(20.0);
1216 // RenderPassProgram
1217 render_passes->clear();
1219 child_pass = AddRenderPass(
1220 render_passes, child_pass_id, child_rect, gfx::Transform());
1222 root_pass = AddRenderPass(
1223 render_passes, root_pass_id, viewport_rect, gfx::Transform());
1225 AddRenderPassQuad(root_pass,
1226 child_pass,
1228 skia::RefPtr<SkImageFilter>(),
1229 gfx::Transform());
1231 renderer_->DecideRenderPassAllocationsForFrame(
1232 *renderer_client_.render_passes_in_draw_order());
1233 renderer_->DrawFrame(renderer_client_.render_passes_in_draw_order(), NULL);
1234 TestRenderPassProgram();
1236 // RenderPassColorMatrixProgram
1237 render_passes->clear();
1239 child_pass = AddRenderPass(
1240 render_passes, child_pass_id, child_rect, transform_causing_aa);
1242 root_pass = AddRenderPass(
1243 render_passes, root_pass_id, viewport_rect, gfx::Transform());
1245 AddRenderPassQuad(root_pass, child_pass, 0, filter, gfx::Transform());
1247 renderer_->DecideRenderPassAllocationsForFrame(
1248 *renderer_client_.render_passes_in_draw_order());
1249 renderer_->DrawFrame(renderer_client_.render_passes_in_draw_order(), NULL);
1250 TestRenderPassColorMatrixProgram();
1252 // RenderPassMaskProgram
1253 render_passes->clear();
1255 child_pass = AddRenderPass(
1256 render_passes, child_pass_id, child_rect, gfx::Transform());
1258 root_pass = AddRenderPass(
1259 render_passes, root_pass_id, viewport_rect, gfx::Transform());
1261 AddRenderPassQuad(root_pass,
1262 child_pass,
1263 mask,
1264 skia::RefPtr<SkImageFilter>(),
1265 gfx::Transform());
1267 renderer_->DecideRenderPassAllocationsForFrame(
1268 *renderer_client_.render_passes_in_draw_order());
1269 renderer_->DrawFrame(renderer_client_.render_passes_in_draw_order(), NULL);
1270 TestRenderPassMaskProgram();
1272 // RenderPassMaskColorMatrixProgram
1273 render_passes->clear();
1275 child_pass = AddRenderPass(
1276 render_passes, child_pass_id, child_rect, gfx::Transform());
1278 root_pass = AddRenderPass(
1279 render_passes, root_pass_id, viewport_rect, gfx::Transform());
1281 AddRenderPassQuad(root_pass, child_pass, mask, filter, gfx::Transform());
1283 renderer_->DecideRenderPassAllocationsForFrame(
1284 *renderer_client_.render_passes_in_draw_order());
1285 renderer_->DrawFrame(renderer_client_.render_passes_in_draw_order(), NULL);
1286 TestRenderPassMaskColorMatrixProgram();
1288 // RenderPassProgramAA
1289 render_passes->clear();
1291 child_pass = AddRenderPass(
1292 render_passes, child_pass_id, child_rect, transform_causing_aa);
1294 root_pass = AddRenderPass(
1295 render_passes, root_pass_id, viewport_rect, gfx::Transform());
1297 AddRenderPassQuad(root_pass,
1298 child_pass,
1300 skia::RefPtr<SkImageFilter>(),
1301 transform_causing_aa);
1303 renderer_->DecideRenderPassAllocationsForFrame(
1304 *renderer_client_.render_passes_in_draw_order());
1305 renderer_->DrawFrame(renderer_client_.render_passes_in_draw_order(), NULL);
1306 TestRenderPassProgramAA();
1308 // RenderPassColorMatrixProgramAA
1309 render_passes->clear();
1311 child_pass = AddRenderPass(
1312 render_passes, child_pass_id, child_rect, transform_causing_aa);
1314 root_pass = AddRenderPass(
1315 render_passes, root_pass_id, viewport_rect, gfx::Transform());
1317 AddRenderPassQuad(root_pass, child_pass, 0, filter, transform_causing_aa);
1319 renderer_->DecideRenderPassAllocationsForFrame(
1320 *renderer_client_.render_passes_in_draw_order());
1321 renderer_->DrawFrame(renderer_client_.render_passes_in_draw_order(), NULL);
1322 TestRenderPassColorMatrixProgramAA();
1324 // RenderPassMaskProgramAA
1325 render_passes->clear();
1327 child_pass = AddRenderPass(render_passes, child_pass_id, child_rect,
1328 transform_causing_aa);
1330 root_pass = AddRenderPass(render_passes, root_pass_id, viewport_rect,
1331 gfx::Transform());
1333 AddRenderPassQuad(root_pass, child_pass, mask, skia::RefPtr<SkImageFilter>(),
1334 transform_causing_aa);
1336 renderer_->DecideRenderPassAllocationsForFrame(
1337 *renderer_client_.render_passes_in_draw_order());
1338 renderer_->DrawFrame(renderer_client_.render_passes_in_draw_order(), NULL);
1339 TestRenderPassMaskProgramAA();
1341 // RenderPassMaskColorMatrixProgramAA
1342 render_passes->clear();
1344 child_pass = AddRenderPass(render_passes, child_pass_id, child_rect,
1345 transform_causing_aa);
1347 root_pass = AddRenderPass(render_passes, root_pass_id, viewport_rect,
1348 transform_causing_aa);
1350 AddRenderPassQuad(root_pass, child_pass, mask, filter, transform_causing_aa);
1352 renderer_->DecideRenderPassAllocationsForFrame(
1353 *renderer_client_.render_passes_in_draw_order());
1354 renderer_->DrawFrame(renderer_client_.render_passes_in_draw_order(), NULL);
1355 TestRenderPassMaskColorMatrixProgramAA();
1358 // At this time, the AA code path cannot be taken if the surface's rect would
1359 // project incorrectly by the given transform, because of w<0 clipping.
1360 TEST_F(GLRendererShaderTest, DrawRenderPassQuadSkipsAAForClippingTransform) {
1361 gfx::Rect child_rect(50, 50);
1362 RenderPass::Id child_pass_id(2, 0);
1363 TestRenderPass* child_pass;
1365 gfx::Rect viewport_rect(renderer_client_.DeviceViewport());
1366 RenderPass::Id root_pass_id(1, 0);
1367 TestRenderPass* root_pass;
1369 gfx::Transform transform_preventing_aa;
1370 transform_preventing_aa.ApplyPerspectiveDepth(40.0);
1371 transform_preventing_aa.RotateAboutYAxis(-20.0);
1372 transform_preventing_aa.Scale(30.0, 1.0);
1374 // Verify that the test transform and test rect actually do cause the clipped
1375 // flag to trigger. Otherwise we are not testing the intended scenario.
1376 bool clipped = false;
1377 MathUtil::MapQuad(transform_preventing_aa,
1378 gfx::QuadF(child_rect),
1379 &clipped);
1380 ASSERT_TRUE(clipped);
1382 // Set up the render pass quad to be drawn
1383 ScopedPtrVector<RenderPass>* render_passes =
1384 renderer_client_.render_passes_in_draw_order();
1386 render_passes->clear();
1388 child_pass = AddRenderPass(
1389 render_passes, child_pass_id, child_rect, transform_preventing_aa);
1391 root_pass = AddRenderPass(
1392 render_passes, root_pass_id, viewport_rect, gfx::Transform());
1394 AddRenderPassQuad(root_pass,
1395 child_pass,
1397 skia::RefPtr<SkImageFilter>(),
1398 transform_preventing_aa);
1400 renderer_->DecideRenderPassAllocationsForFrame(
1401 *renderer_client_.render_passes_in_draw_order());
1402 renderer_->DrawFrame(renderer_client_.render_passes_in_draw_order(), NULL);
1404 // If use_aa incorrectly ignores clipping, it will use the
1405 // RenderPassProgramAA shader instead of the RenderPassProgram.
1406 TestRenderPassProgram();
1409 TEST_F(GLRendererShaderTest, DrawSolidColorShader) {
1410 gfx::Rect viewport_rect(renderer_client_.DeviceViewport());
1411 ScopedPtrVector<RenderPass>* render_passes =
1412 renderer_client_.render_passes_in_draw_order();
1414 RenderPass::Id root_pass_id(1, 0);
1415 TestRenderPass* root_pass;
1417 gfx::Transform pixel_aligned_transform_causing_aa;
1418 pixel_aligned_transform_causing_aa.Translate(25.5f, 25.5f);
1419 pixel_aligned_transform_causing_aa.Scale(0.5f, 0.5f);
1421 render_passes->clear();
1423 root_pass = AddRenderPass(
1424 render_passes, root_pass_id, viewport_rect, gfx::Transform());
1425 AddTransformedQuad(root_pass,
1426 viewport_rect,
1427 SK_ColorYELLOW,
1428 pixel_aligned_transform_causing_aa);
1430 renderer_->DecideRenderPassAllocationsForFrame(
1431 *renderer_client_.render_passes_in_draw_order());
1432 renderer_->DrawFrame(renderer_client_.render_passes_in_draw_order(), NULL);
1434 TestSolidColorProgramAA();
1437 class OutputSurfaceMockContext : public TestWebGraphicsContext3D {
1438 public:
1439 OutputSurfaceMockContext() {
1440 test_capabilities_.discard_backbuffer = true;
1441 test_capabilities_.post_sub_buffer = true;
1444 // Specifically override methods even if they are unused (used in conjunction
1445 // with StrictMock). We need to make sure that GLRenderer does not issue
1446 // framebuffer-related GL calls directly. Instead these are supposed to go
1447 // through the OutputSurface abstraction.
1448 MOCK_METHOD0(ensureBackbufferCHROMIUM, void());
1449 MOCK_METHOD0(discardBackbufferCHROMIUM, void());
1450 MOCK_METHOD2(bindFramebuffer, void(WGC3Denum target, WebGLId framebuffer));
1451 MOCK_METHOD0(prepareTexture, void());
1452 MOCK_METHOD3(reshapeWithScaleFactor,
1453 void(int width, int height, float scale_factor));
1454 MOCK_METHOD4(drawElements,
1455 void(WGC3Denum mode,
1456 WGC3Dsizei count,
1457 WGC3Denum type,
1458 WGC3Dintptr offset));
1461 class MockOutputSurface : public OutputSurface {
1462 public:
1463 MockOutputSurface()
1464 : OutputSurface(TestContextProvider::Create(
1465 scoped_ptr<TestWebGraphicsContext3D>(
1466 new StrictMock<OutputSurfaceMockContext>))) {
1467 surface_size_ = gfx::Size(100, 100);
1469 virtual ~MockOutputSurface() {}
1471 MOCK_METHOD0(EnsureBackbuffer, void());
1472 MOCK_METHOD0(DiscardBackbuffer, void());
1473 MOCK_METHOD2(Reshape, void(gfx::Size size, float scale_factor));
1474 MOCK_METHOD0(BindFramebuffer, void());
1475 MOCK_METHOD1(SwapBuffers, void(CompositorFrame* frame));
1478 class MockOutputSurfaceTest : public testing::Test, public FakeRendererClient {
1479 protected:
1480 virtual void SetUp() {
1481 FakeOutputSurfaceClient output_surface_client_;
1482 CHECK(output_surface_.BindToClient(&output_surface_client_));
1484 resource_provider_ = ResourceProvider::Create(&output_surface_, 0).Pass();
1486 renderer_.reset(new FakeRendererGL(this,
1487 &output_surface_,
1488 resource_provider_.get()));
1489 EXPECT_TRUE(renderer_->Initialize());
1492 void SwapBuffers() { renderer_->SwapBuffers(); }
1494 void DrawFrame() {
1495 gfx::Rect viewport_rect(DeviceViewport());
1496 ScopedPtrVector<RenderPass>* render_passes = render_passes_in_draw_order();
1497 render_passes->clear();
1499 RenderPass::Id render_pass_id(1, 0);
1500 TestRenderPass* render_pass = AddRenderPass(
1501 render_passes, render_pass_id, viewport_rect, gfx::Transform());
1502 AddQuad(render_pass, viewport_rect, SK_ColorGREEN);
1504 EXPECT_CALL(output_surface_, EnsureBackbuffer()).WillRepeatedly(Return());
1506 EXPECT_CALL(output_surface_,
1507 Reshape(DeviceViewport().size(), DeviceScaleFactor())).Times(1);
1509 EXPECT_CALL(output_surface_, BindFramebuffer()).Times(1);
1511 EXPECT_CALL(*Context(), drawElements(_, _, _, _)).Times(1);
1513 renderer_->DecideRenderPassAllocationsForFrame(
1514 *render_passes_in_draw_order());
1515 renderer_->DrawFrame(render_passes_in_draw_order(), NULL);
1518 OutputSurfaceMockContext* Context() {
1519 return static_cast<OutputSurfaceMockContext*>(
1520 output_surface_.context_provider()->Context3d());
1523 FakeOutputSurfaceClient output_surface_client_;
1524 StrictMock<MockOutputSurface> output_surface_;
1525 scoped_ptr<ResourceProvider> resource_provider_;
1526 scoped_ptr<FakeRendererGL> renderer_;
1529 TEST_F(MockOutputSurfaceTest, DrawFrameAndSwap) {
1530 DrawFrame();
1532 EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1);
1533 renderer_->SwapBuffers();
1536 TEST_F(MockOutputSurfaceTest, DrawFrameAndResizeAndSwap) {
1537 DrawFrame();
1538 EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1);
1539 renderer_->SwapBuffers();
1541 set_viewport_and_scale(gfx::Size(2, 2), 2.f);
1542 renderer_->ViewportChanged();
1544 DrawFrame();
1545 EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1);
1546 renderer_->SwapBuffers();
1548 DrawFrame();
1549 EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1);
1550 renderer_->SwapBuffers();
1552 set_viewport_and_scale(gfx::Size(1, 1), 1.f);
1553 renderer_->ViewportChanged();
1555 DrawFrame();
1556 EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1);
1557 renderer_->SwapBuffers();
1560 class GLRendererTestSyncPoint : public GLRendererPixelTest {
1561 protected:
1562 static void SyncPointCallback(int* callback_count) {
1563 ++(*callback_count);
1564 base::MessageLoop::current()->QuitWhenIdle();
1567 static void OtherCallback(int* callback_count) {
1568 ++(*callback_count);
1569 base::MessageLoop::current()->QuitWhenIdle();
1573 #if !defined(OS_ANDROID)
1574 TEST_F(GLRendererTestSyncPoint, SignalSyncPointOnLostContext) {
1575 int sync_point_callback_count = 0;
1576 int other_callback_count = 0;
1577 unsigned sync_point =
1578 output_surface_->context_provider()->Context3d()->insertSyncPoint();
1580 output_surface_->context_provider()->Context3d()->loseContextCHROMIUM(
1581 GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB);
1583 SyncPointHelper::SignalSyncPoint(
1584 output_surface_->context_provider()->Context3d(),
1585 sync_point,
1586 base::Bind(&SyncPointCallback, &sync_point_callback_count));
1587 EXPECT_EQ(0, sync_point_callback_count);
1588 EXPECT_EQ(0, other_callback_count);
1590 // Make the sync point happen.
1591 output_surface_->context_provider()->Context3d()->finish();
1592 // Post a task after the sync point.
1593 base::MessageLoop::current()->PostTask(
1594 FROM_HERE,
1595 base::Bind(&OtherCallback, &other_callback_count));
1597 base::MessageLoop::current()->Run();
1599 // The sync point shouldn't have happened since the context was lost.
1600 EXPECT_EQ(0, sync_point_callback_count);
1601 EXPECT_EQ(1, other_callback_count);
1604 TEST_F(GLRendererTestSyncPoint, SignalSyncPoint) {
1605 int sync_point_callback_count = 0;
1606 int other_callback_count = 0;
1607 unsigned sync_point =
1608 output_surface_->context_provider()->Context3d()->insertSyncPoint();
1610 SyncPointHelper::SignalSyncPoint(
1611 output_surface_->context_provider()->Context3d(),
1612 sync_point,
1613 base::Bind(&SyncPointCallback, &sync_point_callback_count));
1614 EXPECT_EQ(0, sync_point_callback_count);
1615 EXPECT_EQ(0, other_callback_count);
1617 // Make the sync point happen.
1618 output_surface_->context_provider()->Context3d()->finish();
1619 // Post a task after the sync point.
1620 base::MessageLoop::current()->PostTask(
1621 FROM_HERE,
1622 base::Bind(&OtherCallback, &other_callback_count));
1624 base::MessageLoop::current()->Run();
1626 // The sync point should have happened.
1627 EXPECT_EQ(1, sync_point_callback_count);
1628 EXPECT_EQ(1, other_callback_count);
1630 #endif // OS_ANDROID
1632 } // namespace
1633 } // namespace cc