Roll ICU to r205936
[chromium-blink-merge.git] / cc / output / gl_renderer_unittest.cc
blob22180ca176499b3f5b41b88e6fcc2747d2ce2241
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/output/compositor_frame_metadata.h"
11 #include "cc/resources/prioritized_resource_manager.h"
12 #include "cc/resources/resource_provider.h"
13 #include "cc/resources/sync_point_helper.h"
14 #include "cc/test/fake_impl_proxy.h"
15 #include "cc/test/fake_layer_tree_host_impl.h"
16 #include "cc/test/fake_output_surface.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 "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "third_party/khronos/GLES2/gl2.h"
26 #include "third_party/skia/include/core/SkImageFilter.h"
27 #include "third_party/skia/include/core/SkMatrix.h"
28 #include "third_party/skia/include/effects/SkColorFilterImageFilter.h"
29 #include "third_party/skia/include/effects/SkColorMatrixFilter.h"
30 #include "ui/gfx/transform.h"
32 using testing::_;
33 using testing::AnyNumber;
34 using testing::AtLeast;
35 using testing::Expectation;
36 using testing::InSequence;
37 using testing::Mock;
38 using testing::Return;
39 using testing::StrictMock;
40 using WebKit::WebGraphicsMemoryAllocation;
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(renderer()->GetTextureProgramFlip(precision));
97 EXPECT_PROGRAM_VALID(renderer()->GetTextureIOSurfaceProgram(precision));
98 EXPECT_PROGRAM_VALID(renderer()->GetVideoYUVProgram(precision));
99 EXPECT_PROGRAM_VALID(renderer()->GetVideoYUVAProgram(precision));
100 // This is unlikely to be ever true in tests due to usage of osmesa.
101 if (renderer()->Capabilities().using_egl_image)
102 EXPECT_PROGRAM_VALID(renderer()->GetVideoStreamTextureProgram(precision));
103 else
104 EXPECT_FALSE(renderer()->GetVideoStreamTextureProgram(precision));
108 namespace {
110 #if !defined(OS_ANDROID)
111 TEST_F(GLRendererShaderPixelTest, AllShadersCompile) { TestShaders(); }
112 #endif
114 class FrameCountingMemoryAllocationSettingContext
115 : public TestWebGraphicsContext3D {
116 public:
117 FrameCountingMemoryAllocationSettingContext() : frame_(0) {}
119 // WebGraphicsContext3D methods.
121 // This method would normally do a glSwapBuffers under the hood.
122 virtual void prepareTexture() { frame_++; }
123 virtual void setMemoryAllocationChangedCallbackCHROMIUM(
124 WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* callback) {
125 memory_allocation_changed_callback_ = callback;
127 virtual WebString getString(WebKit::WGC3Denum name) {
128 if (name == GL_EXTENSIONS)
129 return WebString(
130 "GL_CHROMIUM_set_visibility GL_CHROMIUM_gpu_memory_manager "
131 "GL_CHROMIUM_discard_backbuffer");
132 return WebString();
135 // Methods added for test.
136 int frame_count() { return frame_; }
137 void SetMemoryAllocation(WebGraphicsMemoryAllocation allocation) {
138 memory_allocation_changed_callback_->onMemoryAllocationChanged(allocation);
141 private:
142 int frame_;
143 WebGraphicsMemoryAllocationChangedCallbackCHROMIUM*
144 memory_allocation_changed_callback_;
147 class FakeRendererClient : public RendererClient {
148 public:
149 FakeRendererClient()
150 : host_impl_(&proxy_),
151 set_full_root_layer_damage_count_(0),
152 last_call_was_set_visibility_(0),
153 root_layer_(LayerImpl::Create(host_impl_.active_tree(), 1)),
154 memory_allocation_limit_bytes_(
155 PrioritizedResourceManager::DefaultMemoryAllocationLimit()),
156 viewport_size_(gfx::Size(1, 1)),
157 scale_factor_(1.f) {
158 root_layer_->CreateRenderSurface();
159 RenderPass::Id render_pass_id =
160 root_layer_->render_surface()->RenderPassId();
161 scoped_ptr<RenderPass> root_render_pass = RenderPass::Create();
162 root_render_pass->SetNew(
163 render_pass_id, gfx::Rect(), gfx::Rect(), gfx::Transform());
164 render_passes_in_draw_order_.push_back(root_render_pass.Pass());
167 // RendererClient methods.
168 virtual gfx::Rect DeviceViewport() const OVERRIDE {
169 static gfx::Size fake_size(1, 1);
170 return gfx::Rect(fake_size);
172 virtual float DeviceScaleFactor() const OVERRIDE {
173 return scale_factor_;
175 virtual const LayerTreeSettings& Settings() const OVERRIDE {
176 static LayerTreeSettings fake_settings;
177 return fake_settings;
179 virtual void SetFullRootLayerDamage() OVERRIDE {
180 set_full_root_layer_damage_count_++;
182 virtual void SetManagedMemoryPolicy(const ManagedMemoryPolicy& policy)
183 OVERRIDE {
184 memory_allocation_limit_bytes_ = policy.bytes_limit_when_visible;
186 virtual void EnforceManagedMemoryPolicy(const ManagedMemoryPolicy& policy)
187 OVERRIDE {
188 if (last_call_was_set_visibility_)
189 *last_call_was_set_visibility_ = false;
191 virtual bool HasImplThread() const OVERRIDE { return false; }
192 virtual bool ShouldClearRootRenderPass() const OVERRIDE { return true; }
193 virtual CompositorFrameMetadata MakeCompositorFrameMetadata() const OVERRIDE {
194 return CompositorFrameMetadata();
196 virtual bool AllowPartialSwap() const OVERRIDE {
197 return true;
200 // Methods added for test.
201 int set_full_root_layer_damage_count() const {
202 return set_full_root_layer_damage_count_;
204 void set_last_call_was_set_visibility_pointer(
205 bool* last_call_was_set_visibility) {
206 last_call_was_set_visibility_ = last_call_was_set_visibility;
208 void set_viewport_and_scale(
209 gfx::Size viewport_size, float scale_factor) {
210 viewport_size_ = viewport_size;
211 scale_factor_ = scale_factor;
214 RenderPass* root_render_pass() { return render_passes_in_draw_order_.back(); }
215 RenderPassList* render_passes_in_draw_order() {
216 return &render_passes_in_draw_order_;
219 size_t memory_allocation_limit_bytes() const {
220 return memory_allocation_limit_bytes_;
223 private:
224 FakeImplProxy proxy_;
225 FakeLayerTreeHostImpl host_impl_;
226 int set_full_root_layer_damage_count_;
227 bool* last_call_was_set_visibility_;
228 scoped_ptr<LayerImpl> root_layer_;
229 RenderPassList render_passes_in_draw_order_;
230 size_t memory_allocation_limit_bytes_;
231 gfx::Size viewport_size_;
232 float scale_factor_;
235 class FakeRendererGL : public GLRenderer {
236 public:
237 FakeRendererGL(RendererClient* client,
238 OutputSurface* output_surface,
239 ResourceProvider* resource_provider)
240 : GLRenderer(client, output_surface, resource_provider, 0) {}
242 // GLRenderer methods.
244 // Changing visibility to public.
245 using GLRenderer::Initialize;
246 using GLRenderer::IsBackbufferDiscarded;
247 using GLRenderer::DoDrawQuad;
248 using GLRenderer::BeginDrawingFrame;
249 using GLRenderer::FinishDrawingQuadList;
252 class GLRendererTest : public testing::Test {
253 protected:
254 GLRendererTest()
255 : suggest_have_backbuffer_yes_(1, true),
256 suggest_have_backbuffer_no_(1, false),
257 output_surface_(FakeOutputSurface::Create3d(
258 scoped_ptr<WebKit::WebGraphicsContext3D>(
259 new FrameCountingMemoryAllocationSettingContext()))),
260 resource_provider_(ResourceProvider::Create(output_surface_.get(), 0)),
261 renderer_(&mock_client_,
262 output_surface_.get(),
263 resource_provider_.get()) {}
265 virtual void SetUp() { renderer_.Initialize(); }
267 void SwapBuffers() { renderer_.SwapBuffers(); }
269 FrameCountingMemoryAllocationSettingContext* Context() {
270 return static_cast<FrameCountingMemoryAllocationSettingContext*>(
271 output_surface_->context3d());
274 WebGraphicsMemoryAllocation suggest_have_backbuffer_yes_;
275 WebGraphicsMemoryAllocation suggest_have_backbuffer_no_;
277 scoped_ptr<OutputSurface> output_surface_;
278 FakeRendererClient mock_client_;
279 scoped_ptr<ResourceProvider> resource_provider_;
280 FakeRendererGL renderer_;
283 // Closing the namespace here so that GLRendererShaderTest can take advantage
284 // of the friend relationship with GLRenderer and all of the mock classes
285 // declared above it.
286 } // namespace
289 // Gives unique shader ids and unique program ids for tests that need them.
290 class ShaderCreatorMockGraphicsContext : public TestWebGraphicsContext3D {
291 public:
292 ShaderCreatorMockGraphicsContext()
293 : next_program_id_number_(10000),
294 next_shader_id_number_(1) {}
296 bool hasShader(WebGLId shader) {
297 return shader_set_.find(shader) != shader_set_.end();
300 bool hasProgram(WebGLId program) {
301 return program_set_.find(program) != program_set_.end();
304 virtual WebGLId createProgram() {
305 unsigned program = next_program_id_number_;
306 program_set_.insert(program);
307 next_program_id_number_++;
308 return program;
311 virtual void deleteProgram(WebGLId program) {
312 ASSERT_TRUE(hasProgram(program));
313 program_set_.erase(program);
316 virtual void useProgram(WebGLId program) {
317 if (!program)
318 return;
319 ASSERT_TRUE(hasProgram(program));
322 virtual WebKit::WebGLId createShader(WebKit::WGC3Denum) {
323 unsigned shader = next_shader_id_number_;
324 shader_set_.insert(shader);
325 next_shader_id_number_++;
326 return shader;
329 virtual void deleteShader(WebKit::WebGLId shader) {
330 ASSERT_TRUE(hasShader(shader));
331 shader_set_.erase(shader);
334 virtual void attachShader(WebGLId program, WebGLId shader) {
335 ASSERT_TRUE(hasProgram(program));
336 ASSERT_TRUE(hasShader(shader));
339 protected:
340 unsigned next_program_id_number_;
341 unsigned next_shader_id_number_;
342 std::set<unsigned> program_set_;
343 std::set<unsigned> shader_set_;
346 class GLRendererShaderTest : public testing::Test {
347 protected:
348 GLRendererShaderTest()
349 : output_surface_(FakeOutputSurface::Create3d(
350 scoped_ptr<WebKit::WebGraphicsContext3D>(
351 new ShaderCreatorMockGraphicsContext()))),
352 resource_provider_(ResourceProvider::Create(output_surface_.get(), 0)),
353 renderer_(scoped_ptr<FakeRendererGL>(
354 new FakeRendererGL(&mock_client_,
355 output_surface_.get(),
356 resource_provider_.get()))) {
357 renderer_->Initialize();
360 void TestRenderPassProgram() {
361 EXPECT_PROGRAM_VALID(renderer_->render_pass_program_);
362 EXPECT_EQ(renderer_->render_pass_program_->program(),
363 renderer_->program_shadow_);
366 void TestRenderPassColorMatrixProgram() {
367 EXPECT_PROGRAM_VALID(renderer_->render_pass_color_matrix_program_);
368 EXPECT_EQ(renderer_->render_pass_color_matrix_program_->program(),
369 renderer_->program_shadow_);
372 void TestRenderPassMaskProgram() {
373 EXPECT_PROGRAM_VALID(renderer_->render_pass_mask_program_);
374 EXPECT_EQ(renderer_->render_pass_mask_program_->program(),
375 renderer_->program_shadow_);
378 void TestRenderPassMaskColorMatrixProgram() {
379 EXPECT_PROGRAM_VALID(renderer_->render_pass_mask_color_matrix_program_);
380 EXPECT_EQ(renderer_->render_pass_mask_color_matrix_program_->program(),
381 renderer_->program_shadow_);
384 void TestRenderPassProgramAA() {
385 EXPECT_PROGRAM_VALID(renderer_->render_pass_program_aa_);
386 EXPECT_EQ(renderer_->render_pass_program_aa_->program(),
387 renderer_->program_shadow_);
390 void TestRenderPassColorMatrixProgramAA() {
391 EXPECT_PROGRAM_VALID(renderer_->render_pass_color_matrix_program_aa_);
392 EXPECT_EQ(renderer_->render_pass_color_matrix_program_aa_->program(),
393 renderer_->program_shadow_);
396 void TestRenderPassMaskProgramAA() {
397 EXPECT_PROGRAM_VALID(renderer_->render_pass_mask_program_aa_);
398 EXPECT_EQ(renderer_->render_pass_mask_program_aa_->program(),
399 renderer_->program_shadow_);
402 void TestRenderPassMaskColorMatrixProgramAA() {
403 EXPECT_PROGRAM_VALID(renderer_->render_pass_mask_color_matrix_program_aa_);
404 EXPECT_EQ(renderer_->render_pass_mask_color_matrix_program_aa_->program(),
405 renderer_->program_shadow_);
408 void TestSolidColorProgramAA() {
409 EXPECT_PROGRAM_VALID(renderer_->solid_color_program_aa_);
410 EXPECT_EQ(renderer_->solid_color_program_aa_->program(),
411 renderer_->program_shadow_);
414 scoped_ptr<OutputSurface> output_surface_;
415 FakeRendererClient mock_client_;
416 scoped_ptr<ResourceProvider> resource_provider_;
417 scoped_ptr<FakeRendererGL> renderer_;
420 namespace {
422 // Test GLRenderer discardBackbuffer functionality:
423 // Suggest recreating framebuffer when one already exists.
424 // Expected: it does nothing.
425 TEST_F(GLRendererTest, SuggestBackbufferYesWhenItAlreadyExistsShouldDoNothing) {
426 Context()->SetMemoryAllocation(suggest_have_backbuffer_yes_);
427 EXPECT_EQ(0, mock_client_.set_full_root_layer_damage_count());
428 EXPECT_FALSE(renderer_.IsBackbufferDiscarded());
430 SwapBuffers();
431 EXPECT_EQ(1, Context()->frame_count());
434 // Test GLRenderer DiscardBackbuffer functionality:
435 // Suggest discarding framebuffer when one exists and the renderer is not
436 // visible.
437 // Expected: it is discarded and damage tracker is reset.
438 TEST_F(
439 GLRendererTest,
440 SuggestBackbufferNoShouldDiscardBackbufferAndDamageRootLayerIfNotVisible) {
441 renderer_.SetVisible(false);
442 Context()->SetMemoryAllocation(suggest_have_backbuffer_no_);
443 EXPECT_EQ(1, mock_client_.set_full_root_layer_damage_count());
444 EXPECT_TRUE(renderer_.IsBackbufferDiscarded());
447 // Test GLRenderer DiscardBackbuffer functionality:
448 // Suggest discarding framebuffer when one exists and the renderer is visible.
449 // Expected: the allocation is ignored.
450 TEST_F(GLRendererTest, SuggestBackbufferNoDoNothingWhenVisible) {
451 renderer_.SetVisible(true);
452 Context()->SetMemoryAllocation(suggest_have_backbuffer_no_);
453 EXPECT_EQ(0, mock_client_.set_full_root_layer_damage_count());
454 EXPECT_FALSE(renderer_.IsBackbufferDiscarded());
457 // Test GLRenderer DiscardBackbuffer functionality:
458 // Suggest discarding framebuffer when one does not exist.
459 // Expected: it does nothing.
460 TEST_F(GLRendererTest, SuggestBackbufferNoWhenItDoesntExistShouldDoNothing) {
461 renderer_.SetVisible(false);
462 Context()->SetMemoryAllocation(suggest_have_backbuffer_no_);
463 EXPECT_EQ(1, mock_client_.set_full_root_layer_damage_count());
464 EXPECT_TRUE(renderer_.IsBackbufferDiscarded());
466 Context()->SetMemoryAllocation(suggest_have_backbuffer_no_);
467 EXPECT_EQ(1, mock_client_.set_full_root_layer_damage_count());
468 EXPECT_TRUE(renderer_.IsBackbufferDiscarded());
471 // Test GLRenderer DiscardBackbuffer functionality:
472 // Begin drawing a frame while a framebuffer is discarded.
473 // Expected: will recreate framebuffer.
474 TEST_F(GLRendererTest, DiscardedBackbufferIsRecreatedForScopeDuration) {
475 renderer_.SetVisible(false);
476 Context()->SetMemoryAllocation(suggest_have_backbuffer_no_);
477 EXPECT_TRUE(renderer_.IsBackbufferDiscarded());
478 EXPECT_EQ(1, mock_client_.set_full_root_layer_damage_count());
480 renderer_.SetVisible(true);
481 renderer_.DrawFrame(mock_client_.render_passes_in_draw_order());
482 EXPECT_FALSE(renderer_.IsBackbufferDiscarded());
484 SwapBuffers();
485 EXPECT_EQ(1, Context()->frame_count());
488 TEST_F(GLRendererTest, FramebufferDiscardedAfterReadbackWhenNotVisible) {
489 renderer_.SetVisible(false);
490 Context()->SetMemoryAllocation(suggest_have_backbuffer_no_);
491 EXPECT_TRUE(renderer_.IsBackbufferDiscarded());
492 EXPECT_EQ(1, mock_client_.set_full_root_layer_damage_count());
494 char pixels[4];
495 renderer_.DrawFrame(mock_client_.render_passes_in_draw_order());
496 EXPECT_FALSE(renderer_.IsBackbufferDiscarded());
498 renderer_.GetFramebufferPixels(pixels, gfx::Rect(0, 0, 1, 1));
499 EXPECT_TRUE(renderer_.IsBackbufferDiscarded());
500 EXPECT_EQ(2, mock_client_.set_full_root_layer_damage_count());
503 class ForbidSynchronousCallContext : public TestWebGraphicsContext3D {
504 public:
505 ForbidSynchronousCallContext() {}
507 virtual bool getActiveAttrib(WebGLId program,
508 WGC3Duint index,
509 ActiveInfo& info) {
510 ADD_FAILURE();
511 return false;
513 virtual bool getActiveUniform(WebGLId program,
514 WGC3Duint index,
515 ActiveInfo& info) {
516 ADD_FAILURE();
517 return false;
519 virtual void getAttachedShaders(WebGLId program,
520 WGC3Dsizei max_count,
521 WGC3Dsizei* count,
522 WebGLId* shaders) {
523 ADD_FAILURE();
525 virtual WGC3Dint getAttribLocation(WebGLId program, const WGC3Dchar* name) {
526 ADD_FAILURE();
527 return 0;
529 virtual void getBooleanv(WGC3Denum pname, WGC3Dboolean* value) {
530 ADD_FAILURE();
532 virtual void getBufferParameteriv(WGC3Denum target,
533 WGC3Denum pname,
534 WGC3Dint* value) {
535 ADD_FAILURE();
537 virtual Attributes getContextAttributes() {
538 ADD_FAILURE();
539 return attributes_;
541 virtual WGC3Denum getError() {
542 ADD_FAILURE();
543 return 0;
545 virtual void getFloatv(WGC3Denum pname, WGC3Dfloat* value) { ADD_FAILURE(); }
546 virtual void getFramebufferAttachmentParameteriv(WGC3Denum target,
547 WGC3Denum attachment,
548 WGC3Denum pname,
549 WGC3Dint* value) {
550 ADD_FAILURE();
552 virtual void getIntegerv(WGC3Denum pname, WGC3Dint* value) {
553 if (pname == GL_MAX_TEXTURE_SIZE) {
554 // MAX_TEXTURE_SIZE is cached client side, so it's OK to query.
555 *value = 1024;
556 } else {
557 ADD_FAILURE();
561 // We allow querying the shader compilation and program link status in debug
562 // mode, but not release.
563 virtual void getProgramiv(WebGLId program, WGC3Denum pname, WGC3Dint* value) {
564 #ifndef NDEBUG
565 *value = 1;
566 #else
567 ADD_FAILURE();
568 #endif
571 virtual void getShaderiv(WebGLId shader, WGC3Denum pname, WGC3Dint* value) {
572 #ifndef NDEBUG
573 *value = 1;
574 #else
575 ADD_FAILURE();
576 #endif
579 virtual WebString getString(WGC3Denum name) {
580 // We allow querying the extension string.
581 // FIXME: It'd be better to check that we only do this before starting any
582 // other expensive work (like starting a compilation)
583 if (name != GL_EXTENSIONS)
584 ADD_FAILURE();
585 return WebString();
588 virtual WebString getProgramInfoLog(WebGLId program) {
589 ADD_FAILURE();
590 return WebString();
592 virtual void getRenderbufferParameteriv(WGC3Denum target,
593 WGC3Denum pname,
594 WGC3Dint* value) {
595 ADD_FAILURE();
598 virtual WebString getShaderInfoLog(WebGLId shader) {
599 ADD_FAILURE();
600 return WebString();
602 virtual void getShaderPrecisionFormat(WGC3Denum shadertype,
603 WGC3Denum precisiontype,
604 WGC3Dint* range,
605 WGC3Dint* precision) {
606 ADD_FAILURE();
608 virtual WebString getShaderSource(WebGLId shader) {
609 ADD_FAILURE();
610 return WebString();
612 virtual void getTexParameterfv(WGC3Denum target,
613 WGC3Denum pname,
614 WGC3Dfloat* value) {
615 ADD_FAILURE();
617 virtual void getTexParameteriv(WGC3Denum target,
618 WGC3Denum pname,
619 WGC3Dint* value) {
620 ADD_FAILURE();
622 virtual void getUniformfv(WebGLId program,
623 WGC3Dint location,
624 WGC3Dfloat* value) {
625 ADD_FAILURE();
627 virtual void getUniformiv(WebGLId program,
628 WGC3Dint location,
629 WGC3Dint* value) {
630 ADD_FAILURE();
632 virtual WGC3Dint getUniformLocation(WebGLId program, const WGC3Dchar* name) {
633 ADD_FAILURE();
634 return 0;
636 virtual void getVertexAttribfv(WGC3Duint index,
637 WGC3Denum pname,
638 WGC3Dfloat* value) {
639 ADD_FAILURE();
641 virtual void getVertexAttribiv(WGC3Duint index,
642 WGC3Denum pname,
643 WGC3Dint* value) {
644 ADD_FAILURE();
646 virtual WGC3Dsizeiptr getVertexAttribOffset(WGC3Duint index,
647 WGC3Denum pname) {
648 ADD_FAILURE();
649 return 0;
653 // This test isn't using the same fixture as GLRendererTest, and you can't mix
654 // TEST() and TEST_F() with the same name, Hence LRC2.
655 TEST(GLRendererTest2, InitializationDoesNotMakeSynchronousCalls) {
656 FakeRendererClient mock_client;
657 scoped_ptr<OutputSurface> output_surface(
658 FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
659 new ForbidSynchronousCallContext)));
660 scoped_ptr<ResourceProvider> resource_provider(
661 ResourceProvider::Create(output_surface.get(), 0));
662 FakeRendererGL renderer(
663 &mock_client, output_surface.get(), resource_provider.get());
665 EXPECT_TRUE(renderer.Initialize());
668 class LoseContextOnFirstGetContext : public TestWebGraphicsContext3D {
669 public:
670 LoseContextOnFirstGetContext() : context_lost_(false) {}
672 virtual bool makeContextCurrent() OVERRIDE { return !context_lost_; }
674 virtual void getProgramiv(WebGLId program, WGC3Denum pname, WGC3Dint* value)
675 OVERRIDE {
676 context_lost_ = true;
677 *value = 0;
680 virtual void getShaderiv(WebGLId shader, WGC3Denum pname, WGC3Dint* value)
681 OVERRIDE {
682 context_lost_ = true;
683 *value = 0;
686 virtual WGC3Denum getGraphicsResetStatusARB() OVERRIDE {
687 return context_lost_ ? 1 : 0;
690 private:
691 bool context_lost_;
694 TEST(GLRendererTest2, InitializationWithQuicklyLostContextDoesNotAssert) {
695 FakeRendererClient mock_client;
696 scoped_ptr<OutputSurface> output_surface(
697 FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
698 new LoseContextOnFirstGetContext)));
699 scoped_ptr<ResourceProvider> resource_provider(
700 ResourceProvider::Create(output_surface.get(), 0));
701 FakeRendererGL renderer(
702 &mock_client, output_surface.get(), resource_provider.get());
704 renderer.Initialize();
707 class ContextThatDoesNotSupportMemoryManagmentExtensions
708 : public TestWebGraphicsContext3D {
709 public:
710 ContextThatDoesNotSupportMemoryManagmentExtensions() {}
712 // WebGraphicsContext3D methods.
714 // This method would normally do a glSwapBuffers under the hood.
715 virtual void prepareTexture() {}
716 virtual void setMemoryAllocationChangedCallbackCHROMIUM(
717 WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* callback) {}
718 virtual WebString getString(WebKit::WGC3Denum name) { return WebString(); }
721 TEST(
722 GLRendererTest2,
723 InitWithoutGpuMemManagerExtensionSupportShouldDefaultToNonZeroAllocation) {
724 FakeRendererClient mock_client;
725 scoped_ptr<OutputSurface> output_surface(
726 FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
727 new ContextThatDoesNotSupportMemoryManagmentExtensions)));
728 scoped_ptr<ResourceProvider> resource_provider(
729 ResourceProvider::Create(output_surface.get(), 0));
730 FakeRendererGL renderer(
731 &mock_client, output_surface.get(), resource_provider.get());
733 renderer.Initialize();
735 EXPECT_GT(mock_client.memory_allocation_limit_bytes(), 0ul);
738 class ClearCountingContext : public TestWebGraphicsContext3D {
739 public:
740 ClearCountingContext() : clear_(0) {}
742 virtual void clear(WGC3Dbitfield) { clear_++; }
744 int clear_count() const { return clear_; }
746 private:
747 int clear_;
750 TEST(GLRendererTest2, OpaqueBackground) {
751 FakeRendererClient mock_client;
752 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
753 scoped_ptr<WebKit::WebGraphicsContext3D>(new ClearCountingContext)));
754 ClearCountingContext* context =
755 static_cast<ClearCountingContext*>(output_surface->context3d());
756 scoped_ptr<ResourceProvider> resource_provider(
757 ResourceProvider::Create(output_surface.get(), 0));
758 FakeRendererGL renderer(
759 &mock_client, output_surface.get(), resource_provider.get());
761 mock_client.root_render_pass()->has_transparent_background = false;
763 EXPECT_TRUE(renderer.Initialize());
765 renderer.DrawFrame(mock_client.render_passes_in_draw_order());
767 // On DEBUG builds, render passes with opaque background clear to blue to
768 // easily see regions that were not drawn on the screen.
769 #ifdef NDEBUG
770 EXPECT_EQ(0, context->clear_count());
771 #else
772 EXPECT_EQ(1, context->clear_count());
773 #endif
776 TEST(GLRendererTest2, TransparentBackground) {
777 FakeRendererClient mock_client;
778 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
779 scoped_ptr<WebKit::WebGraphicsContext3D>(new ClearCountingContext)));
780 ClearCountingContext* context =
781 static_cast<ClearCountingContext*>(output_surface->context3d());
782 scoped_ptr<ResourceProvider> resource_provider(
783 ResourceProvider::Create(output_surface.get(), 0));
784 FakeRendererGL renderer(
785 &mock_client, output_surface.get(), resource_provider.get());
787 mock_client.root_render_pass()->has_transparent_background = true;
789 EXPECT_TRUE(renderer.Initialize());
791 renderer.DrawFrame(mock_client.render_passes_in_draw_order());
793 EXPECT_EQ(1, context->clear_count());
796 class VisibilityChangeIsLastCallTrackingContext
797 : public TestWebGraphicsContext3D {
798 public:
799 VisibilityChangeIsLastCallTrackingContext()
800 : last_call_was_set_visibility_(0) {}
802 // WebGraphicsContext3D methods.
803 virtual void setVisibilityCHROMIUM(bool visible) {
804 if (!last_call_was_set_visibility_)
805 return;
806 DCHECK(*last_call_was_set_visibility_ == false);
807 *last_call_was_set_visibility_ = true;
809 virtual void flush() {
810 if (last_call_was_set_visibility_)
811 *last_call_was_set_visibility_ = false;
813 virtual void deleteTexture(WebGLId) {
814 if (last_call_was_set_visibility_)
815 *last_call_was_set_visibility_ = false;
817 virtual void deleteFramebuffer(WebGLId) {
818 if (last_call_was_set_visibility_)
819 *last_call_was_set_visibility_ = false;
821 virtual void deleteRenderbuffer(WebGLId) {
822 if (last_call_was_set_visibility_)
823 *last_call_was_set_visibility_ = false;
826 // This method would normally do a glSwapBuffers under the hood.
827 virtual WebString getString(WebKit::WGC3Denum name) {
828 if (name == GL_EXTENSIONS)
829 return WebString(
830 "GL_CHROMIUM_set_visibility GL_CHROMIUM_gpu_memory_manager "
831 "GL_CHROMIUM_discard_backbuffer");
832 return WebString();
835 // Methods added for test.
836 void set_last_call_was_set_visibility_pointer(
837 bool* last_call_was_set_visibility) {
838 last_call_was_set_visibility_ = last_call_was_set_visibility;
841 private:
842 bool* last_call_was_set_visibility_;
845 TEST(GLRendererTest2, VisibilityChangeIsLastCall) {
846 FakeRendererClient mock_client;
847 scoped_ptr<OutputSurface> output_surface(
848 FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
849 new VisibilityChangeIsLastCallTrackingContext)));
850 VisibilityChangeIsLastCallTrackingContext* context =
851 static_cast<VisibilityChangeIsLastCallTrackingContext*>(
852 output_surface->context3d());
853 scoped_ptr<ResourceProvider> resource_provider(
854 ResourceProvider::Create(output_surface.get(), 0));
855 FakeRendererGL renderer(
856 &mock_client, output_surface.get(), resource_provider.get());
858 EXPECT_TRUE(renderer.Initialize());
860 bool last_call_was_set_visiblity = false;
861 // Ensure that the call to setVisibilityCHROMIUM is the last call issue to the
862 // GPU process, after glFlush is called, and after the RendererClient's
863 // EnforceManagedMemoryPolicy is called. Plumb this tracking between both the
864 // RenderClient and the Context by giving them both a pointer to a variable on
865 // the stack.
866 context->set_last_call_was_set_visibility_pointer(
867 &last_call_was_set_visiblity);
868 mock_client.set_last_call_was_set_visibility_pointer(
869 &last_call_was_set_visiblity);
870 renderer.SetVisible(true);
871 renderer.DrawFrame(mock_client.render_passes_in_draw_order());
872 renderer.SetVisible(false);
873 EXPECT_TRUE(last_call_was_set_visiblity);
876 class TextureStateTrackingContext : public TestWebGraphicsContext3D {
877 public:
878 TextureStateTrackingContext() : active_texture_(GL_INVALID_ENUM) {}
880 virtual WebString getString(WGC3Denum name) {
881 if (name == GL_EXTENSIONS)
882 return WebString("GL_OES_EGL_image_external");
883 return WebString();
886 MOCK_METHOD3(texParameteri,
887 void(WGC3Denum target, WGC3Denum pname, WGC3Dint param));
888 MOCK_METHOD4(drawElements,
889 void(WGC3Denum mode,
890 WGC3Dsizei count,
891 WGC3Denum type,
892 WGC3Dintptr offset));
894 virtual void activeTexture(WGC3Denum texture) {
895 EXPECT_NE(texture, active_texture_);
896 active_texture_ = texture;
899 WGC3Denum active_texture() const { return active_texture_; }
901 private:
902 WGC3Denum active_texture_;
905 TEST(GLRendererTest2, ActiveTextureState) {
906 FakeRendererClient fake_client;
907 scoped_ptr<OutputSurface> output_surface(
908 FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
909 new TextureStateTrackingContext)));
910 TextureStateTrackingContext* context =
911 static_cast<TextureStateTrackingContext*>(output_surface->context3d());
912 scoped_ptr<ResourceProvider> resource_provider(
913 ResourceProvider::Create(output_surface.get(), 0));
914 FakeRendererGL renderer(
915 &fake_client, output_surface.get(), resource_provider.get());
917 // During initialization we are allowed to set any texture parameters.
918 EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
919 EXPECT_TRUE(renderer.Initialize());
921 cc::RenderPass::Id id(1, 1);
922 scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
923 pass->SetNew(id,
924 gfx::Rect(0, 0, 100, 100),
925 gfx::Rect(0, 0, 100, 100),
926 gfx::Transform());
927 pass->AppendOneOfEveryQuadType(resource_provider.get(), RenderPass::Id(2, 1));
929 // Set up expected texture filter state transitions that match the quads
930 // created in AppendOneOfEveryQuadType().
931 Mock::VerifyAndClearExpectations(context);
933 InSequence sequence;
935 // yuv_quad is drawn with the default linear filter.
936 EXPECT_CALL(*context, drawElements(_, _, _, _));
938 // tile_quad is drawn with GL_NEAREST because it is not transformed or
939 // scaled.
940 EXPECT_CALL(
941 *context,
942 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
943 EXPECT_CALL(
944 *context,
945 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
946 EXPECT_CALL(*context, drawElements(_, _, _, _));
948 // transformed_tile_quad uses GL_LINEAR.
949 EXPECT_CALL(*context, drawElements(_, _, _, _));
951 // scaled_tile_quad also uses GL_LINEAR.
952 EXPECT_CALL(*context, drawElements(_, _, _, _));
954 // The remaining quads also use GL_LINEAR because nearest neighbor
955 // filtering is currently only used with tile quads.
956 EXPECT_CALL(*context, drawElements(_, _, _, _)).Times(6);
959 cc::DirectRenderer::DrawingFrame drawing_frame;
960 renderer.BeginDrawingFrame(&drawing_frame);
961 EXPECT_EQ(static_cast<unsigned>(GL_TEXTURE0), context->active_texture());
963 for (cc::QuadList::BackToFrontIterator
964 it = pass->quad_list.BackToFrontBegin();
965 it != pass->quad_list.BackToFrontEnd();
966 ++it) {
967 renderer.DoDrawQuad(&drawing_frame, *it);
969 renderer.FinishDrawingQuadList();
970 EXPECT_EQ(static_cast<unsigned>(GL_TEXTURE0), context->active_texture());
971 Mock::VerifyAndClearExpectations(context);
974 class NoClearRootRenderPassFakeClient : public FakeRendererClient {
975 public:
976 virtual bool ShouldClearRootRenderPass() const OVERRIDE { return false; }
979 class NoClearRootRenderPassMockContext : public TestWebGraphicsContext3D {
980 public:
981 MOCK_METHOD1(clear, void(WGC3Dbitfield mask));
982 MOCK_METHOD4(drawElements,
983 void(WGC3Denum mode,
984 WGC3Dsizei count,
985 WGC3Denum type,
986 WGC3Dintptr offset));
989 TEST(GLRendererTest2, ShouldClearRootRenderPass) {
990 NoClearRootRenderPassFakeClient mock_client;
991 scoped_ptr<OutputSurface> output_surface(
992 FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
993 new NoClearRootRenderPassMockContext)));
994 NoClearRootRenderPassMockContext* mock_context =
995 static_cast<NoClearRootRenderPassMockContext*>(
996 output_surface->context3d());
997 scoped_ptr<ResourceProvider> resource_provider(
998 ResourceProvider::Create(output_surface.get(), 0));
999 FakeRendererGL renderer(
1000 &mock_client, output_surface.get(), resource_provider.get());
1001 EXPECT_TRUE(renderer.Initialize());
1003 gfx::Rect viewport_rect(mock_client.DeviceViewport());
1004 ScopedPtrVector<RenderPass>& render_passes =
1005 *mock_client.render_passes_in_draw_order();
1006 render_passes.clear();
1008 RenderPass::Id root_pass_id(1, 0);
1009 TestRenderPass* root_pass = AddRenderPass(
1010 &render_passes, root_pass_id, viewport_rect, gfx::Transform());
1011 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1013 RenderPass::Id child_pass_id(2, 0);
1014 TestRenderPass* child_pass = AddRenderPass(
1015 &render_passes, child_pass_id, viewport_rect, gfx::Transform());
1016 AddQuad(child_pass, viewport_rect, SK_ColorBLUE);
1018 AddRenderPassQuad(root_pass, child_pass);
1020 // First render pass is not the root one, clearing should happen.
1021 EXPECT_CALL(*mock_context, clear(GL_COLOR_BUFFER_BIT)).Times(AtLeast(1));
1023 Expectation first_render_pass =
1024 EXPECT_CALL(*mock_context, drawElements(_, _, _, _)).Times(1);
1026 // The second render pass is the root one, clearing should be prevented.
1027 EXPECT_CALL(*mock_context, clear(GL_COLOR_BUFFER_BIT)).Times(0)
1028 .After(first_render_pass);
1030 EXPECT_CALL(*mock_context, drawElements(_, _, _, _)).Times(AnyNumber())
1031 .After(first_render_pass);
1033 renderer.DecideRenderPassAllocationsForFrame(
1034 *mock_client.render_passes_in_draw_order());
1035 renderer.DrawFrame(mock_client.render_passes_in_draw_order());
1037 // In multiple render passes all but the root pass should clear the
1038 // framebuffer.
1039 Mock::VerifyAndClearExpectations(&mock_context);
1042 class ScissorTestOnClearCheckingContext : public TestWebGraphicsContext3D {
1043 public:
1044 ScissorTestOnClearCheckingContext() : scissor_enabled_(false) {}
1046 virtual void clear(WGC3Dbitfield) { EXPECT_FALSE(scissor_enabled_); }
1048 virtual void enable(WGC3Denum cap) {
1049 if (cap == GL_SCISSOR_TEST)
1050 scissor_enabled_ = true;
1053 virtual void disable(WGC3Denum cap) {
1054 if (cap == GL_SCISSOR_TEST)
1055 scissor_enabled_ = false;
1058 private:
1059 bool scissor_enabled_;
1062 TEST(GLRendererTest2, ScissorTestWhenClearing) {
1063 FakeRendererClient mock_client;
1064 scoped_ptr<OutputSurface> output_surface(
1065 FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
1066 new ScissorTestOnClearCheckingContext)));
1067 scoped_ptr<ResourceProvider> resource_provider(
1068 ResourceProvider::Create(output_surface.get(), 0));
1069 FakeRendererGL renderer(
1070 &mock_client, output_surface.get(), resource_provider.get());
1071 EXPECT_TRUE(renderer.Initialize());
1072 EXPECT_FALSE(renderer.Capabilities().using_partial_swap);
1074 gfx::Rect viewport_rect(mock_client.DeviceViewport());
1075 ScopedPtrVector<RenderPass>& render_passes =
1076 *mock_client.render_passes_in_draw_order();
1077 render_passes.clear();
1079 gfx::Rect grand_child_rect(25, 25);
1080 RenderPass::Id grand_child_pass_id(3, 0);
1081 TestRenderPass* grand_child_pass = AddRenderPass(
1082 &render_passes, grand_child_pass_id, grand_child_rect, gfx::Transform());
1083 AddClippedQuad(grand_child_pass, grand_child_rect, SK_ColorYELLOW);
1085 gfx::Rect child_rect(50, 50);
1086 RenderPass::Id child_pass_id(2, 0);
1087 TestRenderPass* child_pass = AddRenderPass(
1088 &render_passes, child_pass_id, child_rect, gfx::Transform());
1089 AddQuad(child_pass, child_rect, SK_ColorBLUE);
1091 RenderPass::Id root_pass_id(1, 0);
1092 TestRenderPass* root_pass = AddRenderPass(
1093 &render_passes, root_pass_id, viewport_rect, gfx::Transform());
1094 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1096 AddRenderPassQuad(root_pass, child_pass);
1097 AddRenderPassQuad(child_pass, grand_child_pass);
1099 renderer.DecideRenderPassAllocationsForFrame(
1100 *mock_client.render_passes_in_draw_order());
1101 renderer.DrawFrame(mock_client.render_passes_in_draw_order());
1104 class NonReshapableOutputSurface : public FakeOutputSurface {
1105 public:
1106 explicit NonReshapableOutputSurface(
1107 scoped_ptr<WebKit::WebGraphicsContext3D> context3d)
1108 : FakeOutputSurface(context3d.Pass(), false) {}
1109 virtual gfx::Size SurfaceSize() const OVERRIDE { return gfx::Size(500, 500); }
1112 class OffsetViewportRendererClient : public FakeRendererClient {
1113 public:
1114 virtual gfx::Rect DeviceViewport() const OVERRIDE {
1115 return gfx::Rect(10, 10, 100, 100);
1119 class FlippedScissorAndViewportContext : public TestWebGraphicsContext3D {
1120 public:
1121 FlippedScissorAndViewportContext()
1122 : did_call_viewport_(false), did_call_scissor_(false) {}
1123 virtual ~FlippedScissorAndViewportContext() {
1124 EXPECT_TRUE(did_call_viewport_);
1125 EXPECT_TRUE(did_call_scissor_);
1128 virtual void viewport(GLint x, GLint y, GLsizei width, GLsizei height) {
1129 EXPECT_EQ(10, x);
1130 EXPECT_EQ(390, y);
1131 EXPECT_EQ(100, width);
1132 EXPECT_EQ(100, height);
1133 did_call_viewport_ = true;
1136 virtual void scissor(GLint x, GLint y, GLsizei width, GLsizei height) {
1137 EXPECT_EQ(30, x);
1138 EXPECT_EQ(450, y);
1139 EXPECT_EQ(20, width);
1140 EXPECT_EQ(20, height);
1141 did_call_scissor_ = true;
1144 private:
1145 bool did_call_viewport_;
1146 bool did_call_scissor_;
1149 TEST(GLRendererTest2, ScissorAndViewportWithinNonreshapableSurface) {
1150 // In Android WebView, the OutputSurface is unable to respect reshape() calls
1151 // and maintains a fixed size. This test verifies that glViewport and
1152 // glScissor's Y coordinate is flipped correctly in this environment, and that
1153 // the glViewport can be at a nonzero origin within the surface.
1154 OffsetViewportRendererClient mock_client;
1155 scoped_ptr<OutputSurface> output_surface(make_scoped_ptr(
1156 new NonReshapableOutputSurface(scoped_ptr<WebKit::WebGraphicsContext3D>(
1157 new FlippedScissorAndViewportContext))));
1158 scoped_ptr<ResourceProvider> resource_provider(
1159 ResourceProvider::Create(output_surface.get(), 0));
1160 FakeRendererGL renderer(
1161 &mock_client, output_surface.get(), resource_provider.get());
1162 EXPECT_TRUE(renderer.Initialize());
1163 EXPECT_FALSE(renderer.Capabilities().using_partial_swap);
1165 gfx::Rect viewport_rect(mock_client.DeviceViewport().size());
1166 gfx::Rect quad_rect = gfx::Rect(20, 20, 20, 20);
1167 ScopedPtrVector<RenderPass>& render_passes =
1168 *mock_client.render_passes_in_draw_order();
1169 render_passes.clear();
1171 RenderPass::Id root_pass_id(1, 0);
1172 TestRenderPass* root_pass = AddRenderPass(
1173 &render_passes, root_pass_id, viewport_rect, gfx::Transform());
1174 AddClippedQuad(root_pass, quad_rect, SK_ColorGREEN);
1176 renderer.DecideRenderPassAllocationsForFrame(
1177 *mock_client.render_passes_in_draw_order());
1178 renderer.DrawFrame(mock_client.render_passes_in_draw_order());
1181 TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) {
1182 gfx::Rect viewport_rect(mock_client_.DeviceViewport());
1183 ScopedPtrVector<RenderPass>* render_passes =
1184 mock_client_.render_passes_in_draw_order();
1186 gfx::Rect child_rect(50, 50);
1187 RenderPass::Id child_pass_id(2, 0);
1188 TestRenderPass* child_pass;
1190 RenderPass::Id root_pass_id(1, 0);
1191 TestRenderPass* root_pass;
1193 cc::ResourceProvider::ResourceId mask =
1194 resource_provider_->CreateResource(gfx::Size(20, 12),
1195 resource_provider_->best_texture_format(),
1196 ResourceProvider::TextureUsageAny);
1197 resource_provider_->AllocateForTesting(mask);
1199 SkScalar matrix[20];
1200 float amount = 0.5f;
1201 matrix[0] = 0.213f + 0.787f * amount;
1202 matrix[1] = 0.715f - 0.715f * amount;
1203 matrix[2] = 1.f - (matrix[0] + matrix[1]);
1204 matrix[3] = matrix[4] = 0;
1205 matrix[5] = 0.213f - 0.213f * amount;
1206 matrix[6] = 0.715f + 0.285f * amount;
1207 matrix[7] = 1.f - (matrix[5] + matrix[6]);
1208 matrix[8] = matrix[9] = 0;
1209 matrix[10] = 0.213f - 0.213f * amount;
1210 matrix[11] = 0.715f - 0.715f * amount;
1211 matrix[12] = 1.f - (matrix[10] + matrix[11]);
1212 matrix[13] = matrix[14] = 0;
1213 matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0;
1214 matrix[18] = 1;
1215 skia::RefPtr<SkColorFilter> color_filter(
1216 skia::AdoptRef(new SkColorMatrixFilter(matrix)));
1217 skia::RefPtr<SkImageFilter> filter = skia::AdoptRef(
1218 SkColorFilterImageFilter::Create(color_filter.get(), NULL));
1220 gfx::Transform transform_causing_aa;
1221 transform_causing_aa.Rotate(20.0);
1223 // RenderPassProgram
1224 render_passes->clear();
1226 child_pass = AddRenderPass(
1227 render_passes, child_pass_id, child_rect, gfx::Transform());
1229 root_pass = AddRenderPass(
1230 render_passes, root_pass_id, viewport_rect, gfx::Transform());
1232 AddRenderPassQuad(root_pass,
1233 child_pass,
1235 skia::RefPtr<SkImageFilter>(),
1236 gfx::Transform());
1238 renderer_->DecideRenderPassAllocationsForFrame(
1239 *mock_client_.render_passes_in_draw_order());
1240 renderer_->DrawFrame(mock_client_.render_passes_in_draw_order());
1241 TestRenderPassProgram();
1243 // RenderPassColorMatrixProgram
1244 render_passes->clear();
1246 child_pass = AddRenderPass(
1247 render_passes, child_pass_id, child_rect, transform_causing_aa);
1249 root_pass = AddRenderPass(
1250 render_passes, root_pass_id, viewport_rect, gfx::Transform());
1252 AddRenderPassQuad(root_pass, child_pass, 0, filter, gfx::Transform());
1254 renderer_->DecideRenderPassAllocationsForFrame(
1255 *mock_client_.render_passes_in_draw_order());
1256 renderer_->DrawFrame(mock_client_.render_passes_in_draw_order());
1257 TestRenderPassColorMatrixProgram();
1259 // RenderPassMaskProgram
1260 render_passes->clear();
1262 child_pass = AddRenderPass(
1263 render_passes, child_pass_id, child_rect, gfx::Transform());
1265 root_pass = AddRenderPass(
1266 render_passes, root_pass_id, viewport_rect, gfx::Transform());
1268 AddRenderPassQuad(root_pass,
1269 child_pass,
1270 mask,
1271 skia::RefPtr<SkImageFilter>(),
1272 gfx::Transform());
1274 renderer_->DecideRenderPassAllocationsForFrame(
1275 *mock_client_.render_passes_in_draw_order());
1276 renderer_->DrawFrame(mock_client_.render_passes_in_draw_order());
1277 TestRenderPassMaskProgram();
1279 // RenderPassMaskColorMatrixProgram
1280 render_passes->clear();
1282 child_pass = AddRenderPass(
1283 render_passes, child_pass_id, child_rect, gfx::Transform());
1285 root_pass = AddRenderPass(
1286 render_passes, root_pass_id, viewport_rect, gfx::Transform());
1288 AddRenderPassQuad(root_pass, child_pass, mask, filter, gfx::Transform());
1290 renderer_->DecideRenderPassAllocationsForFrame(
1291 *mock_client_.render_passes_in_draw_order());
1292 renderer_->DrawFrame(mock_client_.render_passes_in_draw_order());
1293 TestRenderPassMaskColorMatrixProgram();
1295 // RenderPassProgramAA
1296 render_passes->clear();
1298 child_pass = AddRenderPass(
1299 render_passes, child_pass_id, child_rect, transform_causing_aa);
1301 root_pass = AddRenderPass(
1302 render_passes, root_pass_id, viewport_rect, gfx::Transform());
1304 AddRenderPassQuad(root_pass,
1305 child_pass,
1307 skia::RefPtr<SkImageFilter>(),
1308 transform_causing_aa);
1310 renderer_->DecideRenderPassAllocationsForFrame(
1311 *mock_client_.render_passes_in_draw_order());
1312 renderer_->DrawFrame(mock_client_.render_passes_in_draw_order());
1313 TestRenderPassProgramAA();
1315 // RenderPassColorMatrixProgramAA
1316 render_passes->clear();
1318 child_pass = AddRenderPass(
1319 render_passes, child_pass_id, child_rect, transform_causing_aa);
1321 root_pass = AddRenderPass(
1322 render_passes, root_pass_id, viewport_rect, gfx::Transform());
1324 AddRenderPassQuad(root_pass, child_pass, 0, filter, transform_causing_aa);
1326 renderer_->DecideRenderPassAllocationsForFrame(
1327 *mock_client_.render_passes_in_draw_order());
1328 renderer_->DrawFrame(mock_client_.render_passes_in_draw_order());
1329 TestRenderPassColorMatrixProgramAA();
1331 // RenderPassMaskProgramAA
1332 render_passes->clear();
1334 child_pass = AddRenderPass(render_passes, child_pass_id, child_rect,
1335 transform_causing_aa);
1337 root_pass = AddRenderPass(render_passes, root_pass_id, viewport_rect,
1338 gfx::Transform());
1340 AddRenderPassQuad(root_pass, child_pass, mask, skia::RefPtr<SkImageFilter>(),
1341 transform_causing_aa);
1343 renderer_->DecideRenderPassAllocationsForFrame(
1344 *mock_client_.render_passes_in_draw_order());
1345 renderer_->DrawFrame(mock_client_.render_passes_in_draw_order());
1346 TestRenderPassMaskProgramAA();
1348 // RenderPassMaskColorMatrixProgramAA
1349 render_passes->clear();
1351 child_pass = AddRenderPass(render_passes, child_pass_id, child_rect,
1352 transform_causing_aa);
1354 root_pass = AddRenderPass(render_passes, root_pass_id, viewport_rect,
1355 transform_causing_aa);
1357 AddRenderPassQuad(root_pass, child_pass, mask, filter, transform_causing_aa);
1359 renderer_->DecideRenderPassAllocationsForFrame(
1360 *mock_client_.render_passes_in_draw_order());
1361 renderer_->DrawFrame(mock_client_.render_passes_in_draw_order());
1362 TestRenderPassMaskColorMatrixProgramAA();
1365 // At this time, the AA code path cannot be taken if the surface's rect would
1366 // project incorrectly by the given transform, because of w<0 clipping.
1367 TEST_F(GLRendererShaderTest, DrawRenderPassQuadSkipsAAForClippingTransform) {
1368 gfx::Rect child_rect(50, 50);
1369 RenderPass::Id child_pass_id(2, 0);
1370 TestRenderPass* child_pass;
1372 gfx::Rect viewport_rect(mock_client_.DeviceViewport());
1373 RenderPass::Id root_pass_id(1, 0);
1374 TestRenderPass* root_pass;
1376 gfx::Transform transform_preventing_aa;
1377 transform_preventing_aa.ApplyPerspectiveDepth(40.0);
1378 transform_preventing_aa.RotateAboutYAxis(-20.0);
1379 transform_preventing_aa.Scale(30.0, 1.0);
1381 // Verify that the test transform and test rect actually do cause the clipped
1382 // flag to trigger. Otherwise we are not testing the intended scenario.
1383 bool clipped = false;
1384 MathUtil::MapQuad(transform_preventing_aa,
1385 gfx::QuadF(child_rect),
1386 &clipped);
1387 ASSERT_TRUE(clipped);
1389 // Set up the render pass quad to be drawn
1390 ScopedPtrVector<RenderPass>* render_passes =
1391 mock_client_.render_passes_in_draw_order();
1393 render_passes->clear();
1395 child_pass = AddRenderPass(
1396 render_passes, child_pass_id, child_rect, transform_preventing_aa);
1398 root_pass = AddRenderPass(
1399 render_passes, root_pass_id, viewport_rect, gfx::Transform());
1401 AddRenderPassQuad(root_pass,
1402 child_pass,
1404 skia::RefPtr<SkImageFilter>(),
1405 transform_preventing_aa);
1407 renderer_->DecideRenderPassAllocationsForFrame(
1408 *mock_client_.render_passes_in_draw_order());
1409 renderer_->DrawFrame(mock_client_.render_passes_in_draw_order());
1411 // If use_aa incorrectly ignores clipping, it will use the
1412 // RenderPassProgramAA shader instead of the RenderPassProgram.
1413 TestRenderPassProgram();
1416 TEST_F(GLRendererShaderTest, DrawSolidColorShader) {
1417 gfx::Rect viewport_rect(mock_client_.DeviceViewport());
1418 ScopedPtrVector<RenderPass>* render_passes =
1419 mock_client_.render_passes_in_draw_order();
1421 RenderPass::Id root_pass_id(1, 0);
1422 TestRenderPass* root_pass;
1424 gfx::Transform pixel_aligned_transform_causing_aa;
1425 pixel_aligned_transform_causing_aa.Translate(25.5f, 25.5f);
1426 pixel_aligned_transform_causing_aa.Scale(0.5f, 0.5f);
1428 render_passes->clear();
1430 root_pass = AddRenderPass(
1431 render_passes, root_pass_id, viewport_rect, gfx::Transform());
1432 AddTransformedQuad(root_pass,
1433 viewport_rect,
1434 SK_ColorYELLOW,
1435 pixel_aligned_transform_causing_aa);
1437 renderer_->DecideRenderPassAllocationsForFrame(
1438 *mock_client_.render_passes_in_draw_order());
1439 renderer_->DrawFrame(mock_client_.render_passes_in_draw_order());
1441 TestSolidColorProgramAA();
1444 class OutputSurfaceMockContext : public TestWebGraphicsContext3D {
1445 public:
1446 // Specifically override methods even if they are unused (used in conjunction
1447 // with StrictMock). We need to make sure that GLRenderer does not issue
1448 // framebuffer-related GL calls directly. Instead these are supposed to go
1449 // through the OutputSurface abstraction.
1450 MOCK_METHOD0(ensureBackbufferCHROMIUM, void());
1451 MOCK_METHOD0(discardBackbufferCHROMIUM, void());
1452 MOCK_METHOD2(bindFramebuffer, void(WGC3Denum target, WebGLId framebuffer));
1453 MOCK_METHOD0(prepareTexture, void());
1454 MOCK_METHOD3(reshapeWithScaleFactor,
1455 void(int width, int height, float scale_factor));
1456 MOCK_METHOD4(drawElements,
1457 void(WGC3Denum mode,
1458 WGC3Dsizei count,
1459 WGC3Denum type,
1460 WGC3Dintptr offset));
1462 virtual WebString getString(WebKit::WGC3Denum name) {
1463 if (name == GL_EXTENSIONS)
1464 return WebString(
1465 "GL_CHROMIUM_post_sub_buffer GL_CHROMIUM_discard_backbuffer");
1466 return WebString();
1470 class MockOutputSurface : public OutputSurface {
1471 public:
1472 MockOutputSurface()
1473 : OutputSurface(scoped_ptr<WebKit::WebGraphicsContext3D>(
1474 new StrictMock<OutputSurfaceMockContext>)) {
1475 surface_size_ = gfx::Size(100, 100);
1477 virtual ~MockOutputSurface() {}
1479 MOCK_METHOD0(EnsureBackbuffer, void());
1480 MOCK_METHOD0(DiscardBackbuffer, void());
1481 MOCK_METHOD2(Reshape, void(gfx::Size size, float scale_factor));
1482 MOCK_METHOD0(BindFramebuffer, void());
1483 MOCK_METHOD1(SwapBuffers, void(CompositorFrame* frame));
1486 class MockOutputSurfaceTest : public testing::Test, public FakeRendererClient {
1487 protected:
1488 MockOutputSurfaceTest()
1489 : resource_provider_(ResourceProvider::Create(&output_surface_, 0)),
1490 renderer_(this, &output_surface_, resource_provider_.get()) {}
1492 virtual void SetUp() { EXPECT_TRUE(renderer_.Initialize()); }
1494 void SwapBuffers() { renderer_.SwapBuffers(); }
1496 void DrawFrame() {
1497 gfx::Rect viewport_rect(DeviceViewport());
1498 ScopedPtrVector<RenderPass>* render_passes = render_passes_in_draw_order();
1499 render_passes->clear();
1501 RenderPass::Id render_pass_id(1, 0);
1502 TestRenderPass* render_pass = AddRenderPass(
1503 render_passes, render_pass_id, viewport_rect, gfx::Transform());
1504 AddQuad(render_pass, viewport_rect, SK_ColorGREEN);
1506 EXPECT_CALL(output_surface_, EnsureBackbuffer()).WillRepeatedly(Return());
1508 EXPECT_CALL(output_surface_,
1509 Reshape(DeviceViewport().size(), DeviceScaleFactor())).Times(1);
1511 EXPECT_CALL(output_surface_, BindFramebuffer()).Times(1);
1513 EXPECT_CALL(*Context(), drawElements(_, _, _, _)).Times(1);
1515 renderer_.DecideRenderPassAllocationsForFrame(
1516 *render_passes_in_draw_order());
1517 renderer_.DrawFrame(render_passes_in_draw_order());
1520 OutputSurfaceMockContext* Context() {
1521 return static_cast<OutputSurfaceMockContext*>(output_surface_.context3d());
1524 StrictMock<MockOutputSurface> output_surface_;
1525 scoped_ptr<ResourceProvider> resource_provider_;
1526 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 = output_surface_->context3d()->insertSyncPoint();
1579 output_surface_->context3d()->loseContextCHROMIUM(
1580 GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB);
1582 SyncPointHelper::SignalSyncPoint(
1583 output_surface_->context3d(),
1584 sync_point,
1585 base::Bind(&SyncPointCallback, &sync_point_callback_count));
1586 EXPECT_EQ(0, sync_point_callback_count);
1587 EXPECT_EQ(0, other_callback_count);
1589 // Make the sync point happen.
1590 output_surface_->context3d()->finish();
1591 // Post a task after the sync point.
1592 base::MessageLoop::current()->PostTask(
1593 FROM_HERE,
1594 base::Bind(&OtherCallback, &other_callback_count));
1596 base::MessageLoop::current()->Run();
1598 // The sync point shouldn't have happened since the context was lost.
1599 EXPECT_EQ(0, sync_point_callback_count);
1600 EXPECT_EQ(1, other_callback_count);
1603 TEST_F(GLRendererTestSyncPoint, SignalSyncPoint) {
1604 int sync_point_callback_count = 0;
1605 int other_callback_count = 0;
1606 unsigned sync_point = output_surface_->context3d()->insertSyncPoint();
1608 SyncPointHelper::SignalSyncPoint(
1609 output_surface_->context3d(),
1610 sync_point,
1611 base::Bind(&SyncPointCallback, &sync_point_callback_count));
1612 EXPECT_EQ(0, sync_point_callback_count);
1613 EXPECT_EQ(0, other_callback_count);
1615 // Make the sync point happen.
1616 output_surface_->context3d()->finish();
1617 // Post a task after the sync point.
1618 base::MessageLoop::current()->PostTask(
1619 FROM_HERE,
1620 base::Bind(&OtherCallback, &other_callback_count));
1622 base::MessageLoop::current()->Run();
1624 // The sync point should have happened.
1625 EXPECT_EQ(1, sync_point_callback_count);
1626 EXPECT_EQ(1, other_callback_count);
1628 #endif // OS_ANDROID
1630 } // namespace
1631 } // namespace cc