Add signalSyncPoint to the WebGraphicsContext3D command buffer impls.
[chromium-blink-merge.git] / cc / output / gl_renderer_unittest.cc
blobbbd261aa03b087e280534bbfe9223f7d405f07cc
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 "cc/output/compositor_frame_metadata.h"
8 #include "cc/resources/prioritized_resource_manager.h"
9 #include "cc/resources/resource_provider.h"
10 #include "cc/test/fake_impl_proxy.h"
11 #include "cc/test/fake_layer_tree_host_impl.h"
12 #include "cc/test/fake_output_surface.h"
13 #include "cc/test/mock_quad_culler.h"
14 #include "cc/test/pixel_test.h"
15 #include "cc/test/render_pass_test_common.h"
16 #include "cc/test/render_pass_test_utils.h"
17 #include "cc/test/test_web_graphics_context_3d.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "third_party/khronos/GLES2/gl2.h"
21 #include "third_party/skia/include/core/SkImageFilter.h"
22 #include "third_party/skia/include/core/SkMatrix.h"
23 #include "third_party/skia/include/effects/SkColorFilterImageFilter.h"
24 #include "third_party/skia/include/effects/SkColorMatrixFilter.h"
25 #include "ui/gfx/transform.h"
27 using testing::_;
28 using testing::AnyNumber;
29 using testing::AtLeast;
30 using testing::Expectation;
31 using testing::InSequence;
32 using testing::Mock;
33 using testing::Return;
34 using testing::StrictMock;
35 using WebKit::WebGraphicsMemoryAllocation;
36 using WebKit::WebGLId;
37 using WebKit::WebString;
38 using WebKit::WGC3Dbitfield;
39 using WebKit::WGC3Dboolean;
40 using WebKit::WGC3Dchar;
41 using WebKit::WGC3Denum;
42 using WebKit::WGC3Dfloat;
43 using WebKit::WGC3Dint;
44 using WebKit::WGC3Dintptr;
45 using WebKit::WGC3Dsizei;
46 using WebKit::WGC3Dsizeiptr;
47 using WebKit::WGC3Duint;
49 namespace cc {
51 #define EXPECT_PROGRAM_VALID(program_binding) \
52 do { \
53 EXPECT_TRUE(program_binding->program()); \
54 EXPECT_TRUE(program_binding->initialized()); \
55 } while (false)
57 // Explicitly named to be a friend in GLRenderer for shader access.
58 class GLRendererShaderPixelTest : public PixelTest {
59 public:
60 void TestShaders() {
61 ASSERT_FALSE(renderer_->IsContextLost());
62 EXPECT_PROGRAM_VALID(renderer_->GetTileCheckerboardProgram());
63 EXPECT_PROGRAM_VALID(renderer_->GetDebugBorderProgram());
64 EXPECT_PROGRAM_VALID(renderer_->GetSolidColorProgram());
65 EXPECT_PROGRAM_VALID(renderer_->GetSolidColorProgramAA());
66 TestShadersWithTexCoordPrecision(TexCoordPrecisionMedium);
67 TestShadersWithTexCoordPrecision(TexCoordPrecisionHigh);
68 ASSERT_FALSE(renderer_->IsContextLost());
71 void TestShadersWithTexCoordPrecision(TexCoordPrecision precision) {
72 EXPECT_PROGRAM_VALID(renderer_->GetTileProgram(precision));
73 EXPECT_PROGRAM_VALID(renderer_->GetTileProgramOpaque(precision));
74 EXPECT_PROGRAM_VALID(renderer_->GetTileProgramAA(precision));
75 EXPECT_PROGRAM_VALID(renderer_->GetTileProgramSwizzle(precision));
76 EXPECT_PROGRAM_VALID(renderer_->GetTileProgramSwizzleOpaque(precision));
77 EXPECT_PROGRAM_VALID(renderer_->GetTileProgramSwizzleAA(precision));
78 EXPECT_PROGRAM_VALID(renderer_->GetRenderPassProgram(precision));
79 EXPECT_PROGRAM_VALID(renderer_->GetRenderPassProgramAA(precision));
80 EXPECT_PROGRAM_VALID(renderer_->GetRenderPassMaskProgram(precision));
81 EXPECT_PROGRAM_VALID(renderer_->GetRenderPassMaskProgramAA(precision));
82 EXPECT_PROGRAM_VALID(
83 renderer_->GetRenderPassColorMatrixProgram(precision));
84 EXPECT_PROGRAM_VALID(
85 renderer_->GetRenderPassMaskColorMatrixProgramAA(precision));
86 EXPECT_PROGRAM_VALID(
87 renderer_->GetRenderPassColorMatrixProgramAA(precision));
88 EXPECT_PROGRAM_VALID(
89 renderer_->GetRenderPassMaskColorMatrixProgram(precision));
90 EXPECT_PROGRAM_VALID(renderer_->GetTextureProgram(precision));
91 EXPECT_PROGRAM_VALID(renderer_->GetTextureProgramFlip(precision));
92 EXPECT_PROGRAM_VALID(renderer_->GetTextureIOSurfaceProgram(precision));
93 EXPECT_PROGRAM_VALID(renderer_->GetVideoYUVProgram(precision));
94 // This is unlikely to be ever true in tests due to usage of osmesa.
95 if (renderer_->Capabilities().using_egl_image)
96 EXPECT_PROGRAM_VALID(renderer_->GetVideoStreamTextureProgram(precision));
97 else
98 EXPECT_FALSE(renderer_->GetVideoStreamTextureProgram(precision));
102 namespace {
104 #if !defined(OS_ANDROID)
105 TEST_F(GLRendererShaderPixelTest, AllShadersCompile) { TestShaders(); }
106 #endif
108 class FrameCountingMemoryAllocationSettingContext
109 : public TestWebGraphicsContext3D {
110 public:
111 FrameCountingMemoryAllocationSettingContext() : frame_(0) {}
113 // WebGraphicsContext3D methods.
115 // This method would normally do a glSwapBuffers under the hood.
116 virtual void prepareTexture() { frame_++; }
117 virtual void setMemoryAllocationChangedCallbackCHROMIUM(
118 WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* callback) {
119 memory_allocation_changed_callback_ = callback;
121 virtual WebString getString(WebKit::WGC3Denum name) {
122 if (name == GL_EXTENSIONS)
123 return WebString(
124 "GL_CHROMIUM_set_visibility GL_CHROMIUM_gpu_memory_manager "
125 "GL_CHROMIUM_discard_backbuffer");
126 return WebString();
129 // Methods added for test.
130 int frame_count() { return frame_; }
131 void SetMemoryAllocation(WebGraphicsMemoryAllocation allocation) {
132 memory_allocation_changed_callback_->onMemoryAllocationChanged(allocation);
135 private:
136 int frame_;
137 WebGraphicsMemoryAllocationChangedCallbackCHROMIUM*
138 memory_allocation_changed_callback_;
141 class FakeRendererClient : public RendererClient {
142 public:
143 FakeRendererClient()
144 : host_impl_(&proxy_),
145 set_full_root_layer_damage_count_(0),
146 last_call_was_set_visibility_(0),
147 root_layer_(LayerImpl::Create(host_impl_.active_tree(), 1)),
148 memory_allocation_limit_bytes_(
149 PrioritizedResourceManager::DefaultMemoryAllocationLimit()) {
150 root_layer_->CreateRenderSurface();
151 RenderPass::Id render_pass_id =
152 root_layer_->render_surface()->RenderPassId();
153 scoped_ptr<RenderPass> root_render_pass = RenderPass::Create();
154 root_render_pass->SetNew(
155 render_pass_id, gfx::Rect(), gfx::Rect(), gfx::Transform());
156 render_passes_in_draw_order_.push_back(root_render_pass.Pass());
159 // RendererClient methods.
160 virtual gfx::Size DeviceViewportSize() const OVERRIDE {
161 static gfx::Size fake_size(1, 1);
162 return fake_size;
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 void SetManagedMemoryPolicy(const ManagedMemoryPolicy& policy)
172 OVERRIDE {
173 memory_allocation_limit_bytes_ = policy.bytes_limit_when_visible;
175 virtual void EnforceManagedMemoryPolicy(const ManagedMemoryPolicy& policy)
176 OVERRIDE {
177 if (last_call_was_set_visibility_)
178 *last_call_was_set_visibility_ = false;
180 virtual bool HasImplThread() const OVERRIDE { return false; }
181 virtual bool ShouldClearRootRenderPass() const OVERRIDE { return true; }
182 virtual CompositorFrameMetadata MakeCompositorFrameMetadata() const OVERRIDE {
183 return CompositorFrameMetadata();
185 virtual bool AllowPartialSwap() const OVERRIDE {
186 return true;
189 // Methods added for test.
190 int set_full_root_layer_damage_count() const {
191 return set_full_root_layer_damage_count_;
193 void set_last_call_was_set_visibility_pointer(
194 bool* last_call_was_set_visibility) {
195 last_call_was_set_visibility_ = last_call_was_set_visibility;
198 RenderPass* root_render_pass() { return render_passes_in_draw_order_.back(); }
199 RenderPassList* render_passes_in_draw_order() {
200 return &render_passes_in_draw_order_;
203 size_t memory_allocation_limit_bytes() const {
204 return memory_allocation_limit_bytes_;
207 private:
208 FakeImplProxy proxy_;
209 FakeLayerTreeHostImpl host_impl_;
210 int set_full_root_layer_damage_count_;
211 bool* last_call_was_set_visibility_;
212 scoped_ptr<LayerImpl> root_layer_;
213 RenderPassList render_passes_in_draw_order_;
214 size_t memory_allocation_limit_bytes_;
217 class FakeRendererGL : public GLRenderer {
218 public:
219 FakeRendererGL(RendererClient* client,
220 OutputSurface* output_surface,
221 ResourceProvider* resource_provider)
222 : GLRenderer(client, output_surface, resource_provider, 0) {}
224 // GLRenderer methods.
226 // Changing visibility to public.
227 using GLRenderer::Initialize;
228 using GLRenderer::IsBackbufferDiscarded;
229 using GLRenderer::DoDrawQuad;
230 using GLRenderer::BeginDrawingFrame;
231 using GLRenderer::FinishDrawingQuadList;
234 class GLRendererTest : public testing::Test {
235 protected:
236 GLRendererTest()
237 : suggest_have_backbuffer_yes_(1, true),
238 suggest_have_backbuffer_no_(1, false),
239 output_surface_(FakeOutputSurface::Create3d(
240 scoped_ptr<WebKit::WebGraphicsContext3D>(
241 new FrameCountingMemoryAllocationSettingContext()))),
242 resource_provider_(ResourceProvider::Create(output_surface_.get(), 0)),
243 renderer_(&mock_client_,
244 output_surface_.get(),
245 resource_provider_.get()) {}
247 virtual void SetUp() { renderer_.Initialize(); }
249 void SwapBuffers() { renderer_.SwapBuffers(LatencyInfo()); }
251 FrameCountingMemoryAllocationSettingContext* Context() {
252 return static_cast<FrameCountingMemoryAllocationSettingContext*>(
253 output_surface_->context3d());
256 WebGraphicsMemoryAllocation suggest_have_backbuffer_yes_;
257 WebGraphicsMemoryAllocation suggest_have_backbuffer_no_;
259 scoped_ptr<OutputSurface> output_surface_;
260 FakeRendererClient mock_client_;
261 scoped_ptr<ResourceProvider> resource_provider_;
262 FakeRendererGL renderer_;
265 // Closing the namespace here so that GLRendererShaderTest can take advantage
266 // of the friend relationship with GLRenderer and all of the mock classes
267 // declared above it.
268 } // namespace
270 class GLRendererShaderTest : public testing::Test {
271 protected:
272 GLRendererShaderTest()
273 : output_surface_(FakeOutputSurface::Create3d()),
274 resource_provider_(ResourceProvider::Create(output_surface_.get(), 0)),
275 renderer_(GLRenderer::Create(&mock_client_,
276 output_surface_.get(),
277 resource_provider_.get(),
278 0)) {}
280 void TestRenderPassProgram() {
281 EXPECT_PROGRAM_VALID(renderer_->render_pass_program_);
282 EXPECT_TRUE(renderer_->program_shadow_ ==
283 renderer_->render_pass_program_->program());
286 void TestRenderPassColorMatrixProgram() {
287 EXPECT_PROGRAM_VALID(renderer_->render_pass_color_matrix_program_);
288 EXPECT_TRUE(renderer_->program_shadow_ ==
289 renderer_->render_pass_color_matrix_program_->program());
292 void TestRenderPassMaskProgram() {
293 EXPECT_PROGRAM_VALID(renderer_->render_pass_mask_program_);
294 EXPECT_TRUE(renderer_->program_shadow_ ==
295 renderer_->render_pass_mask_program_->program());
298 void TestRenderPassMaskColorMatrixProgram() {
299 EXPECT_PROGRAM_VALID(renderer_->render_pass_mask_color_matrix_program_);
300 EXPECT_TRUE(renderer_->program_shadow_ ==
301 renderer_->render_pass_mask_color_matrix_program_->program());
304 void TestRenderPassProgramAA() {
305 EXPECT_PROGRAM_VALID(renderer_->render_pass_program_aa_);
306 EXPECT_TRUE(renderer_->program_shadow_ ==
307 renderer_->render_pass_program_aa_->program());
310 void TestRenderPassColorMatrixProgramAA() {
311 EXPECT_PROGRAM_VALID(renderer_->render_pass_color_matrix_program_aa_);
312 EXPECT_TRUE(renderer_->program_shadow_ ==
313 renderer_->render_pass_color_matrix_program_aa_->program());
316 void TestRenderPassMaskProgramAA() {
317 EXPECT_PROGRAM_VALID(renderer_->render_pass_mask_program_);
318 EXPECT_TRUE(renderer_->program_shadow_ ==
319 renderer_->render_pass_program_aa_->program());
322 void TestRenderPassMaskColorMatrixProgramAA() {
323 EXPECT_PROGRAM_VALID(renderer_->render_pass_mask_color_matrix_program_aa_);
324 EXPECT_TRUE(renderer_->program_shadow_ ==
325 renderer_->render_pass_color_matrix_program_aa_->program());
328 void TestSolidColorProgramAA() {
329 EXPECT_PROGRAM_VALID(renderer_->solid_color_program_aa_);
330 EXPECT_TRUE(renderer_->program_shadow_ ==
331 renderer_->solid_color_program_aa_->program());
334 scoped_ptr<OutputSurface> output_surface_;
335 FakeRendererClient mock_client_;
336 scoped_ptr<ResourceProvider> resource_provider_;
337 scoped_ptr<GLRenderer> renderer_;
340 namespace {
342 // Test GLRenderer discardBackbuffer functionality:
343 // Suggest recreating framebuffer when one already exists.
344 // Expected: it does nothing.
345 TEST_F(GLRendererTest, SuggestBackbufferYesWhenItAlreadyExistsShouldDoNothing) {
346 Context()->SetMemoryAllocation(suggest_have_backbuffer_yes_);
347 EXPECT_EQ(0, mock_client_.set_full_root_layer_damage_count());
348 EXPECT_FALSE(renderer_.IsBackbufferDiscarded());
350 SwapBuffers();
351 EXPECT_EQ(1, Context()->frame_count());
354 // Test GLRenderer DiscardBackbuffer functionality:
355 // Suggest discarding framebuffer when one exists and the renderer is not
356 // visible.
357 // Expected: it is discarded and damage tracker is reset.
358 TEST_F(
359 GLRendererTest,
360 SuggestBackbufferNoShouldDiscardBackbufferAndDamageRootLayerIfNotVisible) {
361 renderer_.SetVisible(false);
362 Context()->SetMemoryAllocation(suggest_have_backbuffer_no_);
363 EXPECT_EQ(1, mock_client_.set_full_root_layer_damage_count());
364 EXPECT_TRUE(renderer_.IsBackbufferDiscarded());
367 // Test GLRenderer DiscardBackbuffer functionality:
368 // Suggest discarding framebuffer when one exists and the renderer is visible.
369 // Expected: the allocation is ignored.
370 TEST_F(GLRendererTest, SuggestBackbufferNoDoNothingWhenVisible) {
371 renderer_.SetVisible(true);
372 Context()->SetMemoryAllocation(suggest_have_backbuffer_no_);
373 EXPECT_EQ(0, mock_client_.set_full_root_layer_damage_count());
374 EXPECT_FALSE(renderer_.IsBackbufferDiscarded());
377 // Test GLRenderer DiscardBackbuffer functionality:
378 // Suggest discarding framebuffer when one does not exist.
379 // Expected: it does nothing.
380 TEST_F(GLRendererTest, SuggestBackbufferNoWhenItDoesntExistShouldDoNothing) {
381 renderer_.SetVisible(false);
382 Context()->SetMemoryAllocation(suggest_have_backbuffer_no_);
383 EXPECT_EQ(1, mock_client_.set_full_root_layer_damage_count());
384 EXPECT_TRUE(renderer_.IsBackbufferDiscarded());
386 Context()->SetMemoryAllocation(suggest_have_backbuffer_no_);
387 EXPECT_EQ(1, mock_client_.set_full_root_layer_damage_count());
388 EXPECT_TRUE(renderer_.IsBackbufferDiscarded());
391 // Test GLRenderer DiscardBackbuffer functionality:
392 // Begin drawing a frame while a framebuffer is discarded.
393 // Expected: will recreate framebuffer.
394 TEST_F(GLRendererTest, DiscardedBackbufferIsRecreatedForScopeDuration) {
395 renderer_.SetVisible(false);
396 Context()->SetMemoryAllocation(suggest_have_backbuffer_no_);
397 EXPECT_TRUE(renderer_.IsBackbufferDiscarded());
398 EXPECT_EQ(1, mock_client_.set_full_root_layer_damage_count());
400 renderer_.SetVisible(true);
401 renderer_.DrawFrame(mock_client_.render_passes_in_draw_order());
402 EXPECT_FALSE(renderer_.IsBackbufferDiscarded());
404 SwapBuffers();
405 EXPECT_EQ(1, Context()->frame_count());
408 TEST_F(GLRendererTest, FramebufferDiscardedAfterReadbackWhenNotVisible) {
409 renderer_.SetVisible(false);
410 Context()->SetMemoryAllocation(suggest_have_backbuffer_no_);
411 EXPECT_TRUE(renderer_.IsBackbufferDiscarded());
412 EXPECT_EQ(1, mock_client_.set_full_root_layer_damage_count());
414 char pixels[4];
415 renderer_.DrawFrame(mock_client_.render_passes_in_draw_order());
416 EXPECT_FALSE(renderer_.IsBackbufferDiscarded());
418 renderer_.GetFramebufferPixels(pixels, gfx::Rect(0, 0, 1, 1));
419 EXPECT_TRUE(renderer_.IsBackbufferDiscarded());
420 EXPECT_EQ(2, mock_client_.set_full_root_layer_damage_count());
423 class ForbidSynchronousCallContext : public TestWebGraphicsContext3D {
424 public:
425 ForbidSynchronousCallContext() {}
427 virtual bool getActiveAttrib(WebGLId program,
428 WGC3Duint index,
429 ActiveInfo& info) {
430 ADD_FAILURE();
431 return false;
433 virtual bool getActiveUniform(WebGLId program,
434 WGC3Duint index,
435 ActiveInfo& info) {
436 ADD_FAILURE();
437 return false;
439 virtual void getAttachedShaders(WebGLId program,
440 WGC3Dsizei max_count,
441 WGC3Dsizei* count,
442 WebGLId* shaders) {
443 ADD_FAILURE();
445 virtual WGC3Dint getAttribLocation(WebGLId program, const WGC3Dchar* name) {
446 ADD_FAILURE();
447 return 0;
449 virtual void getBooleanv(WGC3Denum pname, WGC3Dboolean* value) {
450 ADD_FAILURE();
452 virtual void getBufferParameteriv(WGC3Denum target,
453 WGC3Denum pname,
454 WGC3Dint* value) {
455 ADD_FAILURE();
457 virtual Attributes getContextAttributes() {
458 ADD_FAILURE();
459 return attributes_;
461 virtual WGC3Denum getError() {
462 ADD_FAILURE();
463 return 0;
465 virtual void getFloatv(WGC3Denum pname, WGC3Dfloat* value) { ADD_FAILURE(); }
466 virtual void getFramebufferAttachmentParameteriv(WGC3Denum target,
467 WGC3Denum attachment,
468 WGC3Denum pname,
469 WGC3Dint* value) {
470 ADD_FAILURE();
472 virtual void getIntegerv(WGC3Denum pname, WGC3Dint* value) {
473 if (pname == GL_MAX_TEXTURE_SIZE) {
474 // MAX_TEXTURE_SIZE is cached client side, so it's OK to query.
475 *value = 1024;
476 } else {
477 ADD_FAILURE();
481 // We allow querying the shader compilation and program link status in debug
482 // mode, but not release.
483 virtual void getProgramiv(WebGLId program, WGC3Denum pname, WGC3Dint* value) {
484 #ifndef NDEBUG
485 *value = 1;
486 #else
487 ADD_FAILURE();
488 #endif
491 virtual void getShaderiv(WebGLId shader, WGC3Denum pname, WGC3Dint* value) {
492 #ifndef NDEBUG
493 *value = 1;
494 #else
495 ADD_FAILURE();
496 #endif
499 virtual WebString getString(WGC3Denum name) {
500 // We allow querying the extension string.
501 // FIXME: It'd be better to check that we only do this before starting any
502 // other expensive work (like starting a compilation)
503 if (name != GL_EXTENSIONS)
504 ADD_FAILURE();
505 return WebString();
508 virtual WebString getProgramInfoLog(WebGLId program) {
509 ADD_FAILURE();
510 return WebString();
512 virtual void getRenderbufferParameteriv(WGC3Denum target,
513 WGC3Denum pname,
514 WGC3Dint* value) {
515 ADD_FAILURE();
518 virtual WebString getShaderInfoLog(WebGLId shader) {
519 ADD_FAILURE();
520 return WebString();
522 virtual void getShaderPrecisionFormat(WGC3Denum shadertype,
523 WGC3Denum precisiontype,
524 WGC3Dint* range,
525 WGC3Dint* precision) {
526 ADD_FAILURE();
528 virtual WebString getShaderSource(WebGLId shader) {
529 ADD_FAILURE();
530 return WebString();
532 virtual void getTexParameterfv(WGC3Denum target,
533 WGC3Denum pname,
534 WGC3Dfloat* value) {
535 ADD_FAILURE();
537 virtual void getTexParameteriv(WGC3Denum target,
538 WGC3Denum pname,
539 WGC3Dint* value) {
540 ADD_FAILURE();
542 virtual void getUniformfv(WebGLId program,
543 WGC3Dint location,
544 WGC3Dfloat* value) {
545 ADD_FAILURE();
547 virtual void getUniformiv(WebGLId program,
548 WGC3Dint location,
549 WGC3Dint* value) {
550 ADD_FAILURE();
552 virtual WGC3Dint getUniformLocation(WebGLId program, const WGC3Dchar* name) {
553 ADD_FAILURE();
554 return 0;
556 virtual void getVertexAttribfv(WGC3Duint index,
557 WGC3Denum pname,
558 WGC3Dfloat* value) {
559 ADD_FAILURE();
561 virtual void getVertexAttribiv(WGC3Duint index,
562 WGC3Denum pname,
563 WGC3Dint* value) {
564 ADD_FAILURE();
566 virtual WGC3Dsizeiptr getVertexAttribOffset(WGC3Duint index,
567 WGC3Denum pname) {
568 ADD_FAILURE();
569 return 0;
573 // This test isn't using the same fixture as GLRendererTest, and you can't mix
574 // TEST() and TEST_F() with the same name, Hence LRC2.
575 TEST(GLRendererTest2, InitializationDoesNotMakeSynchronousCalls) {
576 FakeRendererClient mock_client;
577 scoped_ptr<OutputSurface> output_surface(
578 FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
579 new ForbidSynchronousCallContext)));
580 scoped_ptr<ResourceProvider> resource_provider(
581 ResourceProvider::Create(output_surface.get(), 0));
582 FakeRendererGL renderer(
583 &mock_client, output_surface.get(), resource_provider.get());
585 EXPECT_TRUE(renderer.Initialize());
588 class LoseContextOnFirstGetContext : public TestWebGraphicsContext3D {
589 public:
590 LoseContextOnFirstGetContext() : context_lost_(false) {}
592 virtual bool makeContextCurrent() OVERRIDE { return !context_lost_; }
594 virtual void getProgramiv(WebGLId program, WGC3Denum pname, WGC3Dint* value)
595 OVERRIDE {
596 context_lost_ = true;
597 *value = 0;
600 virtual void getShaderiv(WebGLId shader, WGC3Denum pname, WGC3Dint* value)
601 OVERRIDE {
602 context_lost_ = true;
603 *value = 0;
606 virtual WGC3Denum getGraphicsResetStatusARB() OVERRIDE {
607 return context_lost_ ? 1 : 0;
610 private:
611 bool context_lost_;
614 TEST(GLRendererTest2, InitializationWithQuicklyLostContextDoesNotAssert) {
615 FakeRendererClient mock_client;
616 scoped_ptr<OutputSurface> output_surface(
617 FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
618 new LoseContextOnFirstGetContext)));
619 scoped_ptr<ResourceProvider> resource_provider(
620 ResourceProvider::Create(output_surface.get(), 0));
621 FakeRendererGL renderer(
622 &mock_client, output_surface.get(), resource_provider.get());
624 renderer.Initialize();
627 class ContextThatDoesNotSupportMemoryManagmentExtensions
628 : public TestWebGraphicsContext3D {
629 public:
630 ContextThatDoesNotSupportMemoryManagmentExtensions() {}
632 // WebGraphicsContext3D methods.
634 // This method would normally do a glSwapBuffers under the hood.
635 virtual void prepareTexture() {}
636 virtual void setMemoryAllocationChangedCallbackCHROMIUM(
637 WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* callback) {}
638 virtual WebString getString(WebKit::WGC3Denum name) { return WebString(); }
641 TEST(
642 GLRendererTest2,
643 InitWithoutGpuMemManagerExtensionSupportShouldDefaultToNonZeroAllocation) {
644 FakeRendererClient mock_client;
645 scoped_ptr<OutputSurface> output_surface(
646 FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
647 new ContextThatDoesNotSupportMemoryManagmentExtensions)));
648 scoped_ptr<ResourceProvider> resource_provider(
649 ResourceProvider::Create(output_surface.get(), 0));
650 FakeRendererGL renderer(
651 &mock_client, output_surface.get(), resource_provider.get());
653 renderer.Initialize();
655 EXPECT_GT(mock_client.memory_allocation_limit_bytes(), 0ul);
658 class ClearCountingContext : public TestWebGraphicsContext3D {
659 public:
660 ClearCountingContext() : clear_(0) {}
662 virtual void clear(WGC3Dbitfield) { clear_++; }
664 int clear_count() const { return clear_; }
666 private:
667 int clear_;
670 TEST(GLRendererTest2, OpaqueBackground) {
671 FakeRendererClient mock_client;
672 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
673 scoped_ptr<WebKit::WebGraphicsContext3D>(new ClearCountingContext)));
674 ClearCountingContext* context =
675 static_cast<ClearCountingContext*>(output_surface->context3d());
676 scoped_ptr<ResourceProvider> resource_provider(
677 ResourceProvider::Create(output_surface.get(), 0));
678 FakeRendererGL renderer(
679 &mock_client, output_surface.get(), resource_provider.get());
681 mock_client.root_render_pass()->has_transparent_background = false;
683 EXPECT_TRUE(renderer.Initialize());
685 renderer.DrawFrame(mock_client.render_passes_in_draw_order());
687 // On DEBUG builds, render passes with opaque background clear to blue to
688 // easily see regions that were not drawn on the screen.
689 #ifdef NDEBUG
690 EXPECT_EQ(0, context->clear_count());
691 #else
692 EXPECT_EQ(1, context->clear_count());
693 #endif
696 TEST(GLRendererTest2, TransparentBackground) {
697 FakeRendererClient mock_client;
698 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
699 scoped_ptr<WebKit::WebGraphicsContext3D>(new ClearCountingContext)));
700 ClearCountingContext* context =
701 static_cast<ClearCountingContext*>(output_surface->context3d());
702 scoped_ptr<ResourceProvider> resource_provider(
703 ResourceProvider::Create(output_surface.get(), 0));
704 FakeRendererGL renderer(
705 &mock_client, output_surface.get(), resource_provider.get());
707 mock_client.root_render_pass()->has_transparent_background = true;
709 EXPECT_TRUE(renderer.Initialize());
711 renderer.DrawFrame(mock_client.render_passes_in_draw_order());
713 EXPECT_EQ(1, context->clear_count());
716 class VisibilityChangeIsLastCallTrackingContext
717 : public TestWebGraphicsContext3D {
718 public:
719 VisibilityChangeIsLastCallTrackingContext()
720 : last_call_was_set_visibility_(0) {}
722 // WebGraphicsContext3D methods.
723 virtual void setVisibilityCHROMIUM(bool visible) {
724 if (!last_call_was_set_visibility_)
725 return;
726 DCHECK(*last_call_was_set_visibility_ == false);
727 *last_call_was_set_visibility_ = true;
729 virtual void flush() {
730 if (last_call_was_set_visibility_)
731 *last_call_was_set_visibility_ = false;
733 virtual void deleteTexture(WebGLId) {
734 if (last_call_was_set_visibility_)
735 *last_call_was_set_visibility_ = false;
737 virtual void deleteFramebuffer(WebGLId) {
738 if (last_call_was_set_visibility_)
739 *last_call_was_set_visibility_ = false;
741 virtual void deleteRenderbuffer(WebGLId) {
742 if (last_call_was_set_visibility_)
743 *last_call_was_set_visibility_ = false;
746 // This method would normally do a glSwapBuffers under the hood.
747 virtual WebString getString(WebKit::WGC3Denum name) {
748 if (name == GL_EXTENSIONS)
749 return WebString(
750 "GL_CHROMIUM_set_visibility GL_CHROMIUM_gpu_memory_manager "
751 "GL_CHROMIUM_discard_backbuffer");
752 return WebString();
755 // Methods added for test.
756 void set_last_call_was_set_visibility_pointer(
757 bool* last_call_was_set_visibility) {
758 last_call_was_set_visibility_ = last_call_was_set_visibility;
761 private:
762 bool* last_call_was_set_visibility_;
765 TEST(GLRendererTest2, VisibilityChangeIsLastCall) {
766 FakeRendererClient mock_client;
767 scoped_ptr<OutputSurface> output_surface(
768 FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
769 new VisibilityChangeIsLastCallTrackingContext)));
770 VisibilityChangeIsLastCallTrackingContext* context =
771 static_cast<VisibilityChangeIsLastCallTrackingContext*>(
772 output_surface->context3d());
773 scoped_ptr<ResourceProvider> resource_provider(
774 ResourceProvider::Create(output_surface.get(), 0));
775 FakeRendererGL renderer(
776 &mock_client, output_surface.get(), resource_provider.get());
778 EXPECT_TRUE(renderer.Initialize());
780 bool last_call_was_set_visiblity = false;
781 // Ensure that the call to setVisibilityCHROMIUM is the last call issue to the
782 // GPU process, after glFlush is called, and after the RendererClient's
783 // EnforceManagedMemoryPolicy is called. Plumb this tracking between both the
784 // RenderClient and the Context by giving them both a pointer to a variable on
785 // the stack.
786 context->set_last_call_was_set_visibility_pointer(
787 &last_call_was_set_visiblity);
788 mock_client.set_last_call_was_set_visibility_pointer(
789 &last_call_was_set_visiblity);
790 renderer.SetVisible(true);
791 renderer.DrawFrame(mock_client.render_passes_in_draw_order());
792 renderer.SetVisible(false);
793 EXPECT_TRUE(last_call_was_set_visiblity);
796 class TextureStateTrackingContext : public TestWebGraphicsContext3D {
797 public:
798 TextureStateTrackingContext() : active_texture_(GL_INVALID_ENUM) {}
800 virtual WebString getString(WGC3Denum name) {
801 if (name == GL_EXTENSIONS)
802 return WebString("GL_OES_EGL_image_external");
803 return WebString();
806 MOCK_METHOD3(texParameteri,
807 void(WGC3Denum target, WGC3Denum pname, WGC3Dint param));
808 MOCK_METHOD4(drawElements,
809 void(WGC3Denum mode,
810 WGC3Dsizei count,
811 WGC3Denum type,
812 WGC3Dintptr offset));
814 virtual void activeTexture(WGC3Denum texture) {
815 EXPECT_NE(texture, active_texture_);
816 active_texture_ = texture;
819 WGC3Denum active_texture() const { return active_texture_; }
821 private:
822 WGC3Denum active_texture_;
825 TEST(GLRendererTest2, ActiveTextureState) {
826 FakeRendererClient fake_client;
827 scoped_ptr<OutputSurface> output_surface(
828 FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
829 new TextureStateTrackingContext)));
830 TextureStateTrackingContext* context =
831 static_cast<TextureStateTrackingContext*>(output_surface->context3d());
832 scoped_ptr<ResourceProvider> resource_provider(
833 ResourceProvider::Create(output_surface.get(), 0));
834 FakeRendererGL renderer(
835 &fake_client, output_surface.get(), resource_provider.get());
837 // During initialization we are allowed to set any texture parameters.
838 EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
839 EXPECT_TRUE(renderer.Initialize());
841 cc::RenderPass::Id id(1, 1);
842 scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
843 pass->SetNew(id,
844 gfx::Rect(0, 0, 100, 100),
845 gfx::Rect(0, 0, 100, 100),
846 gfx::Transform());
847 pass->AppendOneOfEveryQuadType(resource_provider.get(), RenderPass::Id(2, 1));
849 // Set up expected texture filter state transitions that match the quads
850 // created in AppendOneOfEveryQuadType().
851 Mock::VerifyAndClearExpectations(context);
853 InSequence sequence;
855 // yuv_quad is drawn with the default linear filter.
856 EXPECT_CALL(*context, drawElements(_, _, _, _));
858 // tile_quad is drawn with GL_NEAREST because it is not transformed or
859 // scaled.
860 EXPECT_CALL(
861 *context,
862 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
863 EXPECT_CALL(
864 *context,
865 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
866 EXPECT_CALL(*context, drawElements(_, _, _, _));
868 // transformed_tile_quad uses GL_LINEAR.
869 EXPECT_CALL(*context, drawElements(_, _, _, _));
871 // scaled_tile_quad also uses GL_LINEAR.
872 EXPECT_CALL(*context, drawElements(_, _, _, _));
874 // The remaining quads also use GL_LINEAR because nearest neighbor
875 // filtering is currently only used with tile quads.
876 EXPECT_CALL(*context, drawElements(_, _, _, _)).Times(6);
879 cc::DirectRenderer::DrawingFrame drawing_frame;
880 renderer.BeginDrawingFrame(&drawing_frame);
881 EXPECT_EQ(static_cast<unsigned>(GL_TEXTURE0), context->active_texture());
883 for (cc::QuadList::BackToFrontIterator
884 it = pass->quad_list.BackToFrontBegin();
885 it != pass->quad_list.BackToFrontEnd();
886 ++it) {
887 renderer.DoDrawQuad(&drawing_frame, *it);
889 renderer.FinishDrawingQuadList();
890 EXPECT_EQ(static_cast<unsigned>(GL_TEXTURE0), context->active_texture());
891 Mock::VerifyAndClearExpectations(context);
894 class NoClearRootRenderPassFakeClient : public FakeRendererClient {
895 public:
896 virtual bool ShouldClearRootRenderPass() const OVERRIDE { return false; }
899 class NoClearRootRenderPassMockContext : public TestWebGraphicsContext3D {
900 public:
901 MOCK_METHOD1(clear, void(WGC3Dbitfield mask));
902 MOCK_METHOD4(drawElements,
903 void(WGC3Denum mode,
904 WGC3Dsizei count,
905 WGC3Denum type,
906 WGC3Dintptr offset));
909 TEST(GLRendererTest2, ShouldClearRootRenderPass) {
910 NoClearRootRenderPassFakeClient mock_client;
911 scoped_ptr<OutputSurface> output_surface(
912 FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
913 new NoClearRootRenderPassMockContext)));
914 NoClearRootRenderPassMockContext* mock_context =
915 static_cast<NoClearRootRenderPassMockContext*>(
916 output_surface->context3d());
917 scoped_ptr<ResourceProvider> resource_provider(
918 ResourceProvider::Create(output_surface.get(), 0));
919 FakeRendererGL renderer(
920 &mock_client, output_surface.get(), resource_provider.get());
921 EXPECT_TRUE(renderer.Initialize());
923 gfx::Rect viewport_rect(mock_client.DeviceViewportSize());
924 ScopedPtrVector<RenderPass>& render_passes =
925 *mock_client.render_passes_in_draw_order();
926 render_passes.clear();
928 RenderPass::Id root_pass_id(1, 0);
929 TestRenderPass* root_pass = AddRenderPass(
930 &render_passes, root_pass_id, viewport_rect, gfx::Transform());
931 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
933 RenderPass::Id child_pass_id(2, 0);
934 TestRenderPass* child_pass = AddRenderPass(
935 &render_passes, child_pass_id, viewport_rect, gfx::Transform());
936 AddQuad(child_pass, viewport_rect, SK_ColorBLUE);
938 AddRenderPassQuad(root_pass, child_pass);
940 // First render pass is not the root one, clearing should happen.
941 EXPECT_CALL(*mock_context, clear(GL_COLOR_BUFFER_BIT)).Times(AtLeast(1));
943 Expectation first_render_pass =
944 EXPECT_CALL(*mock_context, drawElements(_, _, _, _)).Times(1);
946 // The second render pass is the root one, clearing should be prevented.
947 EXPECT_CALL(*mock_context, clear(GL_COLOR_BUFFER_BIT)).Times(0)
948 .After(first_render_pass);
950 EXPECT_CALL(*mock_context, drawElements(_, _, _, _)).Times(AnyNumber())
951 .After(first_render_pass);
953 renderer.DecideRenderPassAllocationsForFrame(
954 *mock_client.render_passes_in_draw_order());
955 renderer.DrawFrame(mock_client.render_passes_in_draw_order());
957 // In multiple render passes all but the root pass should clear the
958 // framebuffer.
959 Mock::VerifyAndClearExpectations(&mock_context);
962 class ScissorTestOnClearCheckingContext : public TestWebGraphicsContext3D {
963 public:
964 ScissorTestOnClearCheckingContext() : scissor_enabled_(false) {}
966 virtual void clear(WGC3Dbitfield) { EXPECT_FALSE(scissor_enabled_); }
968 virtual void enable(WGC3Denum cap) {
969 if (cap == GL_SCISSOR_TEST)
970 scissor_enabled_ = true;
973 virtual void disable(WGC3Denum cap) {
974 if (cap == GL_SCISSOR_TEST)
975 scissor_enabled_ = false;
978 private:
979 bool scissor_enabled_;
982 TEST(GLRendererTest2, ScissorTestWhenClearing) {
983 FakeRendererClient mock_client;
984 scoped_ptr<OutputSurface> output_surface(
985 FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
986 new ScissorTestOnClearCheckingContext)));
987 scoped_ptr<ResourceProvider> resource_provider(
988 ResourceProvider::Create(output_surface.get(), 0));
989 FakeRendererGL renderer(
990 &mock_client, output_surface.get(), resource_provider.get());
991 EXPECT_TRUE(renderer.Initialize());
992 EXPECT_FALSE(renderer.Capabilities().using_partial_swap);
994 gfx::Rect viewport_rect(mock_client.DeviceViewportSize());
995 ScopedPtrVector<RenderPass>& render_passes =
996 *mock_client.render_passes_in_draw_order();
997 render_passes.clear();
999 gfx::Rect grand_child_rect(25, 25);
1000 RenderPass::Id grand_child_pass_id(3, 0);
1001 TestRenderPass* grand_child_pass = AddRenderPass(
1002 &render_passes, grand_child_pass_id, grand_child_rect, gfx::Transform());
1003 AddClippedQuad(grand_child_pass, grand_child_rect, SK_ColorYELLOW);
1005 gfx::Rect child_rect(50, 50);
1006 RenderPass::Id child_pass_id(2, 0);
1007 TestRenderPass* child_pass = AddRenderPass(
1008 &render_passes, child_pass_id, child_rect, gfx::Transform());
1009 AddQuad(child_pass, child_rect, SK_ColorBLUE);
1011 RenderPass::Id root_pass_id(1, 0);
1012 TestRenderPass* root_pass = AddRenderPass(
1013 &render_passes, root_pass_id, viewport_rect, gfx::Transform());
1014 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1016 AddRenderPassQuad(root_pass, child_pass);
1017 AddRenderPassQuad(child_pass, grand_child_pass);
1019 renderer.DecideRenderPassAllocationsForFrame(
1020 *mock_client.render_passes_in_draw_order());
1021 renderer.DrawFrame(mock_client.render_passes_in_draw_order());
1024 TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) {
1025 gfx::Rect viewport_rect(mock_client_.DeviceViewportSize());
1026 ScopedPtrVector<RenderPass>* render_passes =
1027 mock_client_.render_passes_in_draw_order();
1029 gfx::Rect grand_child_rect(25, 25);
1030 RenderPass::Id grand_child_pass_id(3, 0);
1031 TestRenderPass* grand_child_pass;
1033 gfx::Rect child_rect(50, 50);
1034 RenderPass::Id child_pass_id(2, 0);
1035 TestRenderPass* child_pass;
1037 RenderPass::Id root_pass_id(1, 0);
1038 TestRenderPass* root_pass;
1040 cc::ResourceProvider::ResourceId mask =
1041 resource_provider_->CreateResource(gfx::Size(20, 12),
1042 resource_provider_->best_texture_format(),
1043 ResourceProvider::TextureUsageAny);
1044 resource_provider_->AllocateForTesting(mask);
1046 SkScalar matrix[20];
1047 float amount = 0.5f;
1048 matrix[0] = 0.213f + 0.787f * amount;
1049 matrix[1] = 0.715f - 0.715f * amount;
1050 matrix[2] = 1.f - (matrix[0] + matrix[1]);
1051 matrix[3] = matrix[4] = 0;
1052 matrix[5] = 0.213f - 0.213f * amount;
1053 matrix[6] = 0.715f + 0.285f * amount;
1054 matrix[7] = 1.f - (matrix[5] + matrix[6]);
1055 matrix[8] = matrix[9] = 0;
1056 matrix[10] = 0.213f - 0.213f * amount;
1057 matrix[11] = 0.715f - 0.715f * amount;
1058 matrix[12] = 1.f - (matrix[10] + matrix[11]);
1059 matrix[13] = matrix[14] = 0;
1060 matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0;
1061 matrix[18] = 1;
1062 skia::RefPtr<SkColorFilter> color_filter(
1063 skia::AdoptRef(new SkColorMatrixFilter(matrix)));
1064 skia::RefPtr<SkImageFilter> filter = skia::AdoptRef(
1065 SkColorFilterImageFilter::Create(color_filter.get(), NULL));
1067 gfx::Transform transform_causing_aa;
1068 transform_causing_aa.Rotate(20.0);
1070 // RenderPassProgram
1071 render_passes->clear();
1073 grand_child_pass = AddRenderPass(
1074 render_passes, grand_child_pass_id, grand_child_rect, gfx::Transform());
1075 AddClippedQuad(grand_child_pass, grand_child_rect, SK_ColorYELLOW);
1077 child_pass = AddRenderPass(
1078 render_passes, child_pass_id, child_rect, gfx::Transform());
1079 AddQuad(child_pass, child_rect, SK_ColorBLUE);
1081 root_pass = AddRenderPass(
1082 render_passes, root_pass_id, viewport_rect, gfx::Transform());
1083 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1085 AddRenderPassQuad(root_pass,
1086 child_pass,
1088 skia::RefPtr<SkImageFilter>(),
1089 gfx::Transform());
1090 AddRenderPassQuad(child_pass, grand_child_pass);
1092 renderer_->DecideRenderPassAllocationsForFrame(
1093 *mock_client_.render_passes_in_draw_order());
1094 renderer_->DrawFrame(mock_client_.render_passes_in_draw_order());
1095 TestRenderPassProgram();
1097 // RenderPassColorMatrixProgram
1098 render_passes->clear();
1100 grand_child_pass = AddRenderPass(render_passes,
1101 grand_child_pass_id,
1102 grand_child_rect,
1103 transform_causing_aa);
1104 AddClippedQuad(grand_child_pass, grand_child_rect, SK_ColorYELLOW);
1106 child_pass = AddRenderPass(
1107 render_passes, child_pass_id, child_rect, transform_causing_aa);
1108 AddQuad(child_pass, child_rect, SK_ColorBLUE);
1110 root_pass = AddRenderPass(
1111 render_passes, root_pass_id, viewport_rect, gfx::Transform());
1112 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1114 AddRenderPassQuad(root_pass, child_pass, 0, filter, gfx::Transform());
1115 AddRenderPassQuad(child_pass, grand_child_pass);
1117 renderer_->DecideRenderPassAllocationsForFrame(
1118 *mock_client_.render_passes_in_draw_order());
1119 renderer_->DrawFrame(mock_client_.render_passes_in_draw_order());
1120 TestRenderPassColorMatrixProgram();
1122 // RenderPassMaskProgram
1123 render_passes->clear();
1125 grand_child_pass = AddRenderPass(render_passes,
1126 grand_child_pass_id,
1127 grand_child_rect,
1128 gfx::Transform());
1129 AddClippedQuad(grand_child_pass, grand_child_rect, SK_ColorYELLOW);
1131 child_pass = AddRenderPass(
1132 render_passes, child_pass_id, child_rect, gfx::Transform());
1133 AddQuad(child_pass, child_rect, SK_ColorBLUE);
1135 root_pass = AddRenderPass(
1136 render_passes, root_pass_id, viewport_rect, gfx::Transform());
1137 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1139 AddRenderPassQuad(root_pass,
1140 child_pass,
1141 mask,
1142 skia::RefPtr<SkImageFilter>(),
1143 gfx::Transform());
1144 AddRenderPassQuad(child_pass, grand_child_pass);
1146 renderer_->DecideRenderPassAllocationsForFrame(
1147 *mock_client_.render_passes_in_draw_order());
1148 renderer_->DrawFrame(mock_client_.render_passes_in_draw_order());
1149 TestRenderPassMaskProgram();
1151 // RenderPassMaskColorMatrixProgram
1152 render_passes->clear();
1154 grand_child_pass = AddRenderPass(
1155 render_passes, grand_child_pass_id, grand_child_rect, gfx::Transform());
1156 AddClippedQuad(grand_child_pass, grand_child_rect, SK_ColorYELLOW);
1158 child_pass = AddRenderPass(
1159 render_passes, child_pass_id, child_rect, gfx::Transform());
1160 AddQuad(child_pass, child_rect, SK_ColorBLUE);
1162 root_pass = AddRenderPass(
1163 render_passes, root_pass_id, viewport_rect, gfx::Transform());
1164 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1166 AddRenderPassQuad(root_pass, child_pass, mask, filter, gfx::Transform());
1167 AddRenderPassQuad(child_pass, grand_child_pass);
1169 renderer_->DecideRenderPassAllocationsForFrame(
1170 *mock_client_.render_passes_in_draw_order());
1171 renderer_->DrawFrame(mock_client_.render_passes_in_draw_order());
1172 TestRenderPassMaskColorMatrixProgram();
1174 // RenderPassProgramAA
1175 render_passes->clear();
1177 grand_child_pass = AddRenderPass(render_passes,
1178 grand_child_pass_id,
1179 grand_child_rect,
1180 transform_causing_aa);
1181 AddClippedQuad(grand_child_pass, grand_child_rect, SK_ColorYELLOW);
1183 child_pass = AddRenderPass(
1184 render_passes, child_pass_id, child_rect, transform_causing_aa);
1185 AddQuad(child_pass, child_rect, SK_ColorBLUE);
1187 root_pass = AddRenderPass(
1188 render_passes, root_pass_id, viewport_rect, gfx::Transform());
1189 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1191 AddRenderPassQuad(root_pass,
1192 child_pass,
1194 skia::RefPtr<SkImageFilter>(),
1195 transform_causing_aa);
1196 AddRenderPassQuad(child_pass, grand_child_pass);
1198 renderer_->DecideRenderPassAllocationsForFrame(
1199 *mock_client_.render_passes_in_draw_order());
1200 renderer_->DrawFrame(mock_client_.render_passes_in_draw_order());
1201 TestRenderPassProgramAA();
1203 // RenderPassColorMatrixProgramAA
1204 render_passes->clear();
1206 grand_child_pass = AddRenderPass(render_passes,
1207 grand_child_pass_id,
1208 grand_child_rect,
1209 transform_causing_aa);
1210 AddClippedQuad(grand_child_pass, grand_child_rect, SK_ColorYELLOW);
1212 child_pass = AddRenderPass(
1213 render_passes, child_pass_id, child_rect, transform_causing_aa);
1214 AddQuad(child_pass, child_rect, SK_ColorBLUE);
1216 root_pass = AddRenderPass(
1217 render_passes, root_pass_id, viewport_rect, gfx::Transform());
1218 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1220 AddRenderPassQuad(root_pass, child_pass, 0, filter, transform_causing_aa);
1221 AddRenderPassQuad(child_pass, grand_child_pass);
1223 renderer_->DecideRenderPassAllocationsForFrame(
1224 *mock_client_.render_passes_in_draw_order());
1225 renderer_->DrawFrame(mock_client_.render_passes_in_draw_order());
1226 TestRenderPassColorMatrixProgramAA();
1228 // RenderPassMaskProgramAA
1229 render_passes->clear();
1231 grand_child_pass = AddRenderPass(render_passes,
1232 grand_child_pass_id,
1233 grand_child_rect,
1234 transform_causing_aa);
1235 AddClippedQuad(grand_child_pass, grand_child_rect, SK_ColorYELLOW);
1237 child_pass = AddRenderPass(render_passes, child_pass_id, child_rect,
1238 transform_causing_aa);
1239 AddQuad(child_pass, child_rect, SK_ColorBLUE);
1241 root_pass = AddRenderPass(render_passes, root_pass_id, viewport_rect,
1242 gfx::Transform());
1243 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1245 AddRenderPassQuad(root_pass, child_pass, mask, skia::RefPtr<SkImageFilter>(),
1246 transform_causing_aa);
1247 AddRenderPassQuad(child_pass, grand_child_pass);
1249 renderer_->DecideRenderPassAllocationsForFrame(
1250 *mock_client_.render_passes_in_draw_order());
1251 renderer_->DrawFrame(mock_client_.render_passes_in_draw_order());
1252 TestRenderPassMaskProgramAA();
1254 // RenderPassMaskColorMatrixProgramAA
1255 render_passes->clear();
1257 grand_child_pass = AddRenderPass(render_passes,
1258 grand_child_pass_id,
1259 grand_child_rect,
1260 transform_causing_aa);
1261 AddClippedQuad(grand_child_pass, grand_child_rect, SK_ColorYELLOW);
1263 child_pass = AddRenderPass(render_passes, child_pass_id, child_rect,
1264 transform_causing_aa);
1265 AddQuad(child_pass, child_rect, SK_ColorBLUE);
1267 root_pass = AddRenderPass(render_passes, root_pass_id, viewport_rect,
1268 transform_causing_aa);
1269 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1271 AddRenderPassQuad(root_pass, child_pass, mask, filter, transform_causing_aa);
1272 AddRenderPassQuad(child_pass, grand_child_pass);
1274 renderer_->DecideRenderPassAllocationsForFrame(
1275 *mock_client_.render_passes_in_draw_order());
1276 renderer_->DrawFrame(mock_client_.render_passes_in_draw_order());
1277 TestRenderPassMaskColorMatrixProgramAA();
1280 TEST_F(GLRendererShaderTest, DrawSolidColorShader) {
1281 gfx::Rect viewport_rect(mock_client_.DeviceViewportSize());
1282 ScopedPtrVector<RenderPass>* render_passes =
1283 mock_client_.render_passes_in_draw_order();
1285 RenderPass::Id root_pass_id(1, 0);
1286 TestRenderPass* root_pass;
1288 gfx::Transform pixel_aligned_transform_causing_aa;
1289 pixel_aligned_transform_causing_aa.Translate(25.5f, 25.5f);
1290 pixel_aligned_transform_causing_aa.Scale(0.5f, 0.5f);
1292 render_passes->clear();
1294 root_pass = AddRenderPass(
1295 render_passes, root_pass_id, viewport_rect, gfx::Transform());
1296 AddTransformedQuad(root_pass,
1297 viewport_rect,
1298 SK_ColorYELLOW,
1299 pixel_aligned_transform_causing_aa);
1301 renderer_->DecideRenderPassAllocationsForFrame(
1302 *mock_client_.render_passes_in_draw_order());
1303 renderer_->DrawFrame(mock_client_.render_passes_in_draw_order());
1305 TestSolidColorProgramAA();
1308 class OutputSurfaceMockContext : public TestWebGraphicsContext3D {
1309 public:
1310 // Specifically override methods even if they are unused (used in conjunction
1311 // with StrictMock). We need to make sure that GLRenderer does not issue
1312 // framebuffer-related GL calls directly. Instead these are supposed to go
1313 // through the OutputSurface abstraction.
1314 MOCK_METHOD0(ensureBackbufferCHROMIUM, void());
1315 MOCK_METHOD0(discardBackbufferCHROMIUM, void());
1316 MOCK_METHOD2(bindFramebuffer, void(WGC3Denum target, WebGLId framebuffer));
1317 MOCK_METHOD0(prepareTexture, void());
1318 MOCK_METHOD2(reshape, void(int width, int height));
1319 MOCK_METHOD4(drawElements,
1320 void(WGC3Denum mode,
1321 WGC3Dsizei count,
1322 WGC3Denum type,
1323 WGC3Dintptr offset));
1325 virtual WebString getString(WebKit::WGC3Denum name) {
1326 if (name == GL_EXTENSIONS)
1327 return WebString(
1328 "GL_CHROMIUM_post_sub_buffer GL_CHROMIUM_discard_backbuffer");
1329 return WebString();
1333 class MockOutputSurface : public OutputSurface {
1334 public:
1335 MockOutputSurface()
1336 : OutputSurface(scoped_ptr<WebKit::WebGraphicsContext3D>(
1337 new StrictMock<OutputSurfaceMockContext>)) {}
1338 virtual ~MockOutputSurface() {}
1340 MOCK_METHOD1(SendFrameToParentCompositor, void(CompositorFrame* frame));
1341 MOCK_METHOD0(EnsureBackbuffer, void());
1342 MOCK_METHOD0(DiscardBackbuffer, void());
1343 MOCK_METHOD1(Reshape, void(gfx::Size size));
1344 MOCK_METHOD0(BindFramebuffer, void());
1345 MOCK_METHOD2(PostSubBuffer, void(gfx::Rect rect, const LatencyInfo&));
1346 MOCK_METHOD1(SwapBuffers, void(const LatencyInfo&));
1349 class MockOutputSurfaceTest : public testing::Test, public FakeRendererClient {
1350 protected:
1351 MockOutputSurfaceTest()
1352 : resource_provider_(ResourceProvider::Create(&output_surface_, 0)),
1353 renderer_(this, &output_surface_, resource_provider_.get()) {}
1355 virtual void SetUp() { EXPECT_TRUE(renderer_.Initialize()); }
1357 void SwapBuffers() { renderer_.SwapBuffers(LatencyInfo()); }
1359 void DrawFrame() {
1360 gfx::Rect viewport_rect(DeviceViewportSize());
1361 ScopedPtrVector<RenderPass>* render_passes = render_passes_in_draw_order();
1362 render_passes->clear();
1364 RenderPass::Id render_pass_id(1, 0);
1365 TestRenderPass* render_pass = AddRenderPass(
1366 render_passes, render_pass_id, viewport_rect, gfx::Transform());
1367 AddQuad(render_pass, viewport_rect, SK_ColorGREEN);
1369 EXPECT_CALL(output_surface_, EnsureBackbuffer()).WillRepeatedly(Return());
1371 EXPECT_CALL(output_surface_, Reshape(_)).Times(1);
1373 EXPECT_CALL(output_surface_, BindFramebuffer()).Times(1);
1375 EXPECT_CALL(*Context(), drawElements(_, _, _, _)).Times(1);
1377 renderer_.DecideRenderPassAllocationsForFrame(
1378 *render_passes_in_draw_order());
1379 renderer_.DrawFrame(render_passes_in_draw_order());
1382 OutputSurfaceMockContext* Context() {
1383 return static_cast<OutputSurfaceMockContext*>(output_surface_.context3d());
1386 StrictMock<MockOutputSurface> output_surface_;
1387 scoped_ptr<ResourceProvider> resource_provider_;
1388 FakeRendererGL renderer_;
1391 TEST_F(MockOutputSurfaceTest, DrawFrameAndSwap) {
1392 DrawFrame();
1394 EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1);
1395 renderer_.SwapBuffers(LatencyInfo());
1398 class MockOutputSurfaceTestWithPartialSwap : public MockOutputSurfaceTest {
1399 public:
1400 virtual const LayerTreeSettings& Settings() const OVERRIDE {
1401 static LayerTreeSettings fake_settings;
1402 fake_settings.partial_swap_enabled = true;
1403 return fake_settings;
1407 TEST_F(MockOutputSurfaceTestWithPartialSwap, DrawFrameAndSwap) {
1408 DrawFrame();
1410 EXPECT_CALL(output_surface_, PostSubBuffer(_, _)).Times(1);
1411 renderer_.SwapBuffers(LatencyInfo());
1414 class MockOutputSurfaceTestWithSendCompositorFrame
1415 : public MockOutputSurfaceTest {
1416 public:
1417 virtual const LayerTreeSettings& Settings() const OVERRIDE {
1418 static LayerTreeSettings fake_settings;
1419 fake_settings.compositor_frame_message = true;
1420 return fake_settings;
1424 TEST_F(MockOutputSurfaceTestWithSendCompositorFrame, DrawFrame) {
1425 EXPECT_CALL(output_surface_, SendFrameToParentCompositor(_)).Times(1);
1426 DrawFrame();
1429 } // namespace
1430 } // namespace cc