Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / cc / output / gl_renderer_unittest.cc
blobb8a43e7b7c6d8f1261f50442e38c95104d3dad86
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_->GetTileProgram());
63 EXPECT_PROGRAM_VALID(renderer_->GetTileProgramOpaque());
64 EXPECT_PROGRAM_VALID(renderer_->GetTileProgramAA());
65 EXPECT_PROGRAM_VALID(renderer_->GetTileProgramSwizzle());
66 EXPECT_PROGRAM_VALID(renderer_->GetTileProgramSwizzleOpaque());
67 EXPECT_PROGRAM_VALID(renderer_->GetTileProgramSwizzleAA());
68 EXPECT_PROGRAM_VALID(renderer_->GetTileCheckerboardProgram());
69 EXPECT_PROGRAM_VALID(renderer_->GetDebugBorderProgram());
70 EXPECT_PROGRAM_VALID(renderer_->GetSolidColorProgram());
71 EXPECT_PROGRAM_VALID(renderer_->GetSolidColorProgramAA());
72 //TestShadersWithTexCoordPrecision(TexCoordPrecisionMedium);
73 TestShadersWithTexCoordPrecision(TexCoordPrecisionHigh);
74 ASSERT_FALSE(renderer_->IsContextLost());
77 void TestShadersWithTexCoordPrecision(TexCoordPrecision 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 DidLoseOutputSurface() OVERRIDE {}
169 virtual void OnSwapBuffersComplete() OVERRIDE {}
170 virtual void SetFullRootLayerDamage() OVERRIDE {
171 set_full_root_layer_damage_count_++;
173 virtual void SetManagedMemoryPolicy(const ManagedMemoryPolicy& policy)
174 OVERRIDE {
175 memory_allocation_limit_bytes_ = policy.bytes_limit_when_visible;
177 virtual void EnforceManagedMemoryPolicy(const ManagedMemoryPolicy& policy)
178 OVERRIDE {
179 if (last_call_was_set_visibility_)
180 *last_call_was_set_visibility_ = false;
182 virtual bool HasImplThread() const OVERRIDE { return false; }
183 virtual bool ShouldClearRootRenderPass() const OVERRIDE { return true; }
184 virtual CompositorFrameMetadata MakeCompositorFrameMetadata() const OVERRIDE {
185 return CompositorFrameMetadata();
187 virtual bool AllowPartialSwap() const OVERRIDE {
188 return true;
191 // Methods added for test.
192 int set_full_root_layer_damage_count() const {
193 return set_full_root_layer_damage_count_;
195 void set_last_call_was_set_visibility_pointer(
196 bool* last_call_was_set_visibility) {
197 last_call_was_set_visibility_ = last_call_was_set_visibility;
200 RenderPass* root_render_pass() { return render_passes_in_draw_order_.back(); }
201 RenderPassList* render_passes_in_draw_order() {
202 return &render_passes_in_draw_order_;
205 size_t memory_allocation_limit_bytes() const {
206 return memory_allocation_limit_bytes_;
209 private:
210 FakeImplProxy proxy_;
211 FakeLayerTreeHostImpl host_impl_;
212 int set_full_root_layer_damage_count_;
213 bool* last_call_was_set_visibility_;
214 scoped_ptr<LayerImpl> root_layer_;
215 RenderPassList render_passes_in_draw_order_;
216 size_t memory_allocation_limit_bytes_;
219 class FakeRendererGL : public GLRenderer {
220 public:
221 FakeRendererGL(RendererClient* client,
222 OutputSurface* output_surface,
223 ResourceProvider* resource_provider)
224 : GLRenderer(client, output_surface, resource_provider, 0) {}
226 // GLRenderer methods.
228 // Changing visibility to public.
229 using GLRenderer::Initialize;
230 using GLRenderer::IsBackbufferDiscarded;
231 using GLRenderer::DoDrawQuad;
232 using GLRenderer::BeginDrawingFrame;
233 using GLRenderer::FinishDrawingQuadList;
236 class GLRendererTest : public testing::Test {
237 protected:
238 GLRendererTest()
239 : suggest_have_backbuffer_yes_(1, true),
240 suggest_have_backbuffer_no_(1, false),
241 output_surface_(FakeOutputSurface::Create3d(
242 scoped_ptr<WebKit::WebGraphicsContext3D>(
243 new FrameCountingMemoryAllocationSettingContext()))),
244 resource_provider_(ResourceProvider::Create(output_surface_.get(), 0)),
245 renderer_(&mock_client_,
246 output_surface_.get(),
247 resource_provider_.get()) {}
249 virtual void SetUp() { renderer_.Initialize(); }
251 void SwapBuffers() { renderer_.SwapBuffers(); }
253 FrameCountingMemoryAllocationSettingContext* context() {
254 return static_cast<FrameCountingMemoryAllocationSettingContext*>(
255 output_surface_->context3d());
258 WebGraphicsMemoryAllocation suggest_have_backbuffer_yes_;
259 WebGraphicsMemoryAllocation suggest_have_backbuffer_no_;
261 scoped_ptr<OutputSurface> output_surface_;
262 FakeRendererClient mock_client_;
263 scoped_ptr<ResourceProvider> resource_provider_;
264 FakeRendererGL renderer_;
267 // Closing the namespace here so that GLRendererShaderTest can take advantage
268 // of the friend relationship with GLRenderer and all of the mock classes
269 // declared above it.
270 } // namespace
272 class GLRendererShaderTest : public testing::Test {
273 protected:
274 GLRendererShaderTest()
275 : output_surface_(FakeOutputSurface::Create3d()),
276 resource_provider_(ResourceProvider::Create(output_surface_.get(), 0)),
277 renderer_(GLRenderer::Create(&mock_client_, output_surface_.get(),
278 resource_provider_.get(), 0)) {
281 void TestRenderPassProgram() {
282 EXPECT_PROGRAM_VALID(renderer_->render_pass_program_);
283 EXPECT_TRUE(renderer_->program_shadow_ ==
284 renderer_->render_pass_program_->program());
287 void TestRenderPassColorMatrixProgram() {
288 EXPECT_PROGRAM_VALID(renderer_->render_pass_color_matrix_program_);
289 EXPECT_TRUE(renderer_->program_shadow_ ==
290 renderer_->render_pass_color_matrix_program_->program());
293 void TestRenderPassMaskProgram() {
294 EXPECT_PROGRAM_VALID(renderer_->render_pass_mask_program_);
295 EXPECT_TRUE(renderer_->program_shadow_ ==
296 renderer_->render_pass_mask_program_->program());
299 void TestRenderPassMaskColorMatrixProgram() {
300 EXPECT_PROGRAM_VALID(renderer_->render_pass_mask_color_matrix_program_);
301 EXPECT_TRUE(renderer_->program_shadow_ ==
302 renderer_->render_pass_mask_color_matrix_program_->program());
305 void TestRenderPassProgramAA() {
306 EXPECT_PROGRAM_VALID(renderer_->render_pass_program_aa_);
307 EXPECT_TRUE(renderer_->program_shadow_ ==
308 renderer_->render_pass_program_aa_->program());
311 void TestRenderPassColorMatrixProgramAA() {
312 EXPECT_PROGRAM_VALID(renderer_->render_pass_color_matrix_program_aa_);
313 EXPECT_TRUE(renderer_->program_shadow_ ==
314 renderer_->render_pass_color_matrix_program_aa_->program());
317 void TestRenderPassMaskProgramAA() {
318 EXPECT_PROGRAM_VALID(renderer_->render_pass_mask_program_);
319 EXPECT_TRUE(renderer_->program_shadow_ ==
320 renderer_->render_pass_program_aa_->program());
323 void TestRenderPassMaskColorMatrixProgramAA() {
324 EXPECT_PROGRAM_VALID(renderer_->render_pass_mask_color_matrix_program_aa_);
325 EXPECT_TRUE(renderer_->program_shadow_ ==
326 renderer_->render_pass_color_matrix_program_aa_->program());
329 scoped_ptr<OutputSurface> output_surface_;
330 FakeRendererClient mock_client_;
331 scoped_ptr<ResourceProvider> resource_provider_;
332 scoped_ptr<GLRenderer> renderer_;
335 namespace {
337 // Test GLRenderer discardBackbuffer functionality:
338 // Suggest recreating framebuffer when one already exists.
339 // Expected: it does nothing.
340 TEST_F(GLRendererTest, SuggestBackbufferYesWhenItAlreadyExistsShouldDoNothing) {
341 context()->SetMemoryAllocation(suggest_have_backbuffer_yes_);
342 EXPECT_EQ(0, mock_client_.set_full_root_layer_damage_count());
343 EXPECT_FALSE(renderer_.IsBackbufferDiscarded());
345 SwapBuffers();
346 EXPECT_EQ(1, context()->frame_count());
349 // Test GLRenderer DiscardBackbuffer functionality:
350 // Suggest discarding framebuffer when one exists and the renderer is not
351 // visible.
352 // Expected: it is discarded and damage tracker is reset.
353 TEST_F(
354 GLRendererTest,
355 SuggestBackbufferNoShouldDiscardBackbufferAndDamageRootLayerIfNotVisible) {
356 renderer_.SetVisible(false);
357 context()->SetMemoryAllocation(suggest_have_backbuffer_no_);
358 EXPECT_EQ(1, mock_client_.set_full_root_layer_damage_count());
359 EXPECT_TRUE(renderer_.IsBackbufferDiscarded());
362 // Test GLRenderer DiscardBackbuffer functionality:
363 // Suggest discarding framebuffer when one exists and the renderer is visible.
364 // Expected: the allocation is ignored.
365 TEST_F(GLRendererTest, SuggestBackbufferNoDoNothingWhenVisible) {
366 renderer_.SetVisible(true);
367 context()->SetMemoryAllocation(suggest_have_backbuffer_no_);
368 EXPECT_EQ(0, mock_client_.set_full_root_layer_damage_count());
369 EXPECT_FALSE(renderer_.IsBackbufferDiscarded());
372 // Test GLRenderer DiscardBackbuffer functionality:
373 // Suggest discarding framebuffer when one does not exist.
374 // Expected: it does nothing.
375 TEST_F(GLRendererTest, SuggestBackbufferNoWhenItDoesntExistShouldDoNothing) {
376 renderer_.SetVisible(false);
377 context()->SetMemoryAllocation(suggest_have_backbuffer_no_);
378 EXPECT_EQ(1, mock_client_.set_full_root_layer_damage_count());
379 EXPECT_TRUE(renderer_.IsBackbufferDiscarded());
381 context()->SetMemoryAllocation(suggest_have_backbuffer_no_);
382 EXPECT_EQ(1, mock_client_.set_full_root_layer_damage_count());
383 EXPECT_TRUE(renderer_.IsBackbufferDiscarded());
386 // Test GLRenderer DiscardBackbuffer functionality:
387 // Begin drawing a frame while a framebuffer is discarded.
388 // Expected: will recreate framebuffer.
389 TEST_F(GLRendererTest, DiscardedBackbufferIsRecreatedForScopeDuration) {
390 renderer_.SetVisible(false);
391 context()->SetMemoryAllocation(suggest_have_backbuffer_no_);
392 EXPECT_TRUE(renderer_.IsBackbufferDiscarded());
393 EXPECT_EQ(1, mock_client_.set_full_root_layer_damage_count());
395 renderer_.SetVisible(true);
396 renderer_.DrawFrame(mock_client_.render_passes_in_draw_order());
397 EXPECT_FALSE(renderer_.IsBackbufferDiscarded());
399 SwapBuffers();
400 EXPECT_EQ(1, context()->frame_count());
403 TEST_F(GLRendererTest, FramebufferDiscardedAfterReadbackWhenNotVisible) {
404 renderer_.SetVisible(false);
405 context()->SetMemoryAllocation(suggest_have_backbuffer_no_);
406 EXPECT_TRUE(renderer_.IsBackbufferDiscarded());
407 EXPECT_EQ(1, mock_client_.set_full_root_layer_damage_count());
409 char pixels[4];
410 renderer_.DrawFrame(mock_client_.render_passes_in_draw_order());
411 EXPECT_FALSE(renderer_.IsBackbufferDiscarded());
413 renderer_.GetFramebufferPixels(pixels, gfx::Rect(0, 0, 1, 1));
414 EXPECT_TRUE(renderer_.IsBackbufferDiscarded());
415 EXPECT_EQ(2, mock_client_.set_full_root_layer_damage_count());
418 class ForbidSynchronousCallContext : public TestWebGraphicsContext3D {
419 public:
420 ForbidSynchronousCallContext() {}
422 virtual bool getActiveAttrib(WebGLId program,
423 WGC3Duint index,
424 ActiveInfo& info) {
425 ADD_FAILURE();
426 return false;
428 virtual bool getActiveUniform(WebGLId program,
429 WGC3Duint index,
430 ActiveInfo& info) {
431 ADD_FAILURE();
432 return false;
434 virtual void getAttachedShaders(WebGLId program,
435 WGC3Dsizei max_count,
436 WGC3Dsizei* count,
437 WebGLId* shaders) {
438 ADD_FAILURE();
440 virtual WGC3Dint getAttribLocation(WebGLId program, const WGC3Dchar* name) {
441 ADD_FAILURE();
442 return 0;
444 virtual void getBooleanv(WGC3Denum pname, WGC3Dboolean* value) {
445 ADD_FAILURE();
447 virtual void getBufferParameteriv(WGC3Denum target,
448 WGC3Denum pname,
449 WGC3Dint* value) {
450 ADD_FAILURE();
452 virtual Attributes getContextAttributes() {
453 ADD_FAILURE();
454 return attributes_;
456 virtual WGC3Denum getError() {
457 ADD_FAILURE();
458 return 0;
460 virtual void getFloatv(WGC3Denum pname, WGC3Dfloat* value) { ADD_FAILURE(); }
461 virtual void getFramebufferAttachmentParameteriv(WGC3Denum target,
462 WGC3Denum attachment,
463 WGC3Denum pname,
464 WGC3Dint* value) {
465 ADD_FAILURE();
467 virtual void getIntegerv(WGC3Denum pname, WGC3Dint* value) {
468 if (pname == GL_MAX_TEXTURE_SIZE) {
469 // MAX_TEXTURE_SIZE is cached client side, so it's OK to query.
470 *value = 1024;
471 } else {
472 ADD_FAILURE();
476 // We allow querying the shader compilation and program link status in debug
477 // mode, but not release.
478 virtual void getProgramiv(WebGLId program, WGC3Denum pname, WGC3Dint* value) {
479 #ifndef NDEBUG
480 *value = 1;
481 #else
482 ADD_FAILURE();
483 #endif
486 virtual void getShaderiv(WebGLId shader, WGC3Denum pname, WGC3Dint* value) {
487 #ifndef NDEBUG
488 *value = 1;
489 #else
490 ADD_FAILURE();
491 #endif
494 virtual WebString getString(WGC3Denum name) {
495 // We allow querying the extension string.
496 // FIXME: It'd be better to check that we only do this before starting any
497 // other expensive work (like starting a compilation)
498 if (name != GL_EXTENSIONS)
499 ADD_FAILURE();
500 return WebString();
503 virtual WebString getProgramInfoLog(WebGLId program) {
504 ADD_FAILURE();
505 return WebString();
507 virtual void getRenderbufferParameteriv(WGC3Denum target,
508 WGC3Denum pname,
509 WGC3Dint* value) {
510 ADD_FAILURE();
513 virtual WebString getShaderInfoLog(WebGLId shader) {
514 ADD_FAILURE();
515 return WebString();
517 virtual void getShaderPrecisionFormat(WGC3Denum shadertype,
518 WGC3Denum precisiontype,
519 WGC3Dint* range,
520 WGC3Dint* precision) {
521 ADD_FAILURE();
523 virtual WebString getShaderSource(WebGLId shader) {
524 ADD_FAILURE();
525 return WebString();
527 virtual void getTexParameterfv(WGC3Denum target,
528 WGC3Denum pname,
529 WGC3Dfloat* value) {
530 ADD_FAILURE();
532 virtual void getTexParameteriv(WGC3Denum target,
533 WGC3Denum pname,
534 WGC3Dint* value) {
535 ADD_FAILURE();
537 virtual void getUniformfv(WebGLId program,
538 WGC3Dint location,
539 WGC3Dfloat* value) {
540 ADD_FAILURE();
542 virtual void getUniformiv(WebGLId program,
543 WGC3Dint location,
544 WGC3Dint* value) {
545 ADD_FAILURE();
547 virtual WGC3Dint getUniformLocation(WebGLId program, const WGC3Dchar* name) {
548 ADD_FAILURE();
549 return 0;
551 virtual void getVertexAttribfv(WGC3Duint index,
552 WGC3Denum pname,
553 WGC3Dfloat* value) {
554 ADD_FAILURE();
556 virtual void getVertexAttribiv(WGC3Duint index,
557 WGC3Denum pname,
558 WGC3Dint* value) {
559 ADD_FAILURE();
561 virtual WGC3Dsizeiptr getVertexAttribOffset(WGC3Duint index,
562 WGC3Denum pname) {
563 ADD_FAILURE();
564 return 0;
568 // This test isn't using the same fixture as GLRendererTest, and you can't mix
569 // TEST() and TEST_F() with the same name, Hence LRC2.
570 TEST(GLRendererTest2, InitializationDoesNotMakeSynchronousCalls) {
571 FakeRendererClient mock_client;
572 scoped_ptr<OutputSurface> output_surface(
573 FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
574 new ForbidSynchronousCallContext)));
575 scoped_ptr<ResourceProvider> resource_provider(
576 ResourceProvider::Create(output_surface.get(), 0));
577 FakeRendererGL renderer(
578 &mock_client, output_surface.get(), resource_provider.get());
580 EXPECT_TRUE(renderer.Initialize());
583 class LoseContextOnFirstGetContext : public TestWebGraphicsContext3D {
584 public:
585 LoseContextOnFirstGetContext() : context_lost_(false) {}
587 virtual bool makeContextCurrent() OVERRIDE { return !context_lost_; }
589 virtual void getProgramiv(WebGLId program, WGC3Denum pname, WGC3Dint* value)
590 OVERRIDE {
591 context_lost_ = true;
592 *value = 0;
595 virtual void getShaderiv(WebGLId shader, WGC3Denum pname, WGC3Dint* value)
596 OVERRIDE {
597 context_lost_ = true;
598 *value = 0;
601 virtual WGC3Denum getGraphicsResetStatusARB() OVERRIDE {
602 return context_lost_ ? 1 : 0;
605 private:
606 bool context_lost_;
609 TEST(GLRendererTest2, InitializationWithQuicklyLostContextDoesNotAssert) {
610 FakeRendererClient mock_client;
611 scoped_ptr<OutputSurface> output_surface(
612 FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
613 new LoseContextOnFirstGetContext)));
614 scoped_ptr<ResourceProvider> resource_provider(
615 ResourceProvider::Create(output_surface.get(), 0));
616 FakeRendererGL renderer(
617 &mock_client, output_surface.get(), resource_provider.get());
619 renderer.Initialize();
622 class ContextThatDoesNotSupportMemoryManagmentExtensions
623 : public TestWebGraphicsContext3D {
624 public:
625 ContextThatDoesNotSupportMemoryManagmentExtensions() {}
627 // WebGraphicsContext3D methods.
629 // This method would normally do a glSwapBuffers under the hood.
630 virtual void prepareTexture() {}
631 virtual void setMemoryAllocationChangedCallbackCHROMIUM(
632 WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* callback) {}
633 virtual WebString getString(WebKit::WGC3Denum name) { return WebString(); }
636 TEST(
637 GLRendererTest2,
638 InitWithoutGpuMemManagerExtensionSupportShouldDefaultToNonZeroAllocation) {
639 FakeRendererClient mock_client;
640 scoped_ptr<OutputSurface> output_surface(
641 FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
642 new ContextThatDoesNotSupportMemoryManagmentExtensions)));
643 scoped_ptr<ResourceProvider> resource_provider(
644 ResourceProvider::Create(output_surface.get(), 0));
645 FakeRendererGL renderer(
646 &mock_client, output_surface.get(), resource_provider.get());
648 renderer.Initialize();
650 EXPECT_GT(mock_client.memory_allocation_limit_bytes(), 0ul);
653 class ClearCountingContext : public TestWebGraphicsContext3D {
654 public:
655 ClearCountingContext() : clear_(0) {}
657 virtual void clear(WGC3Dbitfield) { clear_++; }
659 int clear_count() const { return clear_; }
661 private:
662 int clear_;
665 TEST(GLRendererTest2, OpaqueBackground) {
666 FakeRendererClient mock_client;
667 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
668 scoped_ptr<WebKit::WebGraphicsContext3D>(new ClearCountingContext)));
669 ClearCountingContext* context =
670 static_cast<ClearCountingContext*>(output_surface->context3d());
671 scoped_ptr<ResourceProvider> resource_provider(
672 ResourceProvider::Create(output_surface.get(), 0));
673 FakeRendererGL renderer(
674 &mock_client, output_surface.get(), resource_provider.get());
676 mock_client.root_render_pass()->has_transparent_background = false;
678 EXPECT_TRUE(renderer.Initialize());
680 renderer.DrawFrame(mock_client.render_passes_in_draw_order());
682 // On DEBUG builds, render passes with opaque background clear to blue to
683 // easily see regions that were not drawn on the screen.
684 #ifdef NDEBUG
685 EXPECT_EQ(0, context->clear_count());
686 #else
687 EXPECT_EQ(1, context->clear_count());
688 #endif
691 TEST(GLRendererTest2, TransparentBackground) {
692 FakeRendererClient mock_client;
693 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
694 scoped_ptr<WebKit::WebGraphicsContext3D>(new ClearCountingContext)));
695 ClearCountingContext* context =
696 static_cast<ClearCountingContext*>(output_surface->context3d());
697 scoped_ptr<ResourceProvider> resource_provider(
698 ResourceProvider::Create(output_surface.get(), 0));
699 FakeRendererGL renderer(
700 &mock_client, output_surface.get(), resource_provider.get());
702 mock_client.root_render_pass()->has_transparent_background = true;
704 EXPECT_TRUE(renderer.Initialize());
706 renderer.DrawFrame(mock_client.render_passes_in_draw_order());
708 EXPECT_EQ(1, context->clear_count());
711 class VisibilityChangeIsLastCallTrackingContext
712 : public TestWebGraphicsContext3D {
713 public:
714 VisibilityChangeIsLastCallTrackingContext()
715 : last_call_was_set_visibility_(0) {}
717 // WebGraphicsContext3D methods.
718 virtual void setVisibilityCHROMIUM(bool visible) {
719 if (!last_call_was_set_visibility_)
720 return;
721 DCHECK(*last_call_was_set_visibility_ == false);
722 *last_call_was_set_visibility_ = true;
724 virtual void flush() {
725 if (last_call_was_set_visibility_)
726 *last_call_was_set_visibility_ = false;
728 virtual void deleteTexture(WebGLId) {
729 if (last_call_was_set_visibility_)
730 *last_call_was_set_visibility_ = false;
732 virtual void deleteFramebuffer(WebGLId) {
733 if (last_call_was_set_visibility_)
734 *last_call_was_set_visibility_ = false;
736 virtual void deleteRenderbuffer(WebGLId) {
737 if (last_call_was_set_visibility_)
738 *last_call_was_set_visibility_ = false;
741 // This method would normally do a glSwapBuffers under the hood.
742 virtual WebString getString(WebKit::WGC3Denum name) {
743 if (name == GL_EXTENSIONS)
744 return WebString(
745 "GL_CHROMIUM_set_visibility GL_CHROMIUM_gpu_memory_manager "
746 "GL_CHROMIUM_discard_backbuffer");
747 return WebString();
750 // Methods added for test.
751 void set_last_call_was_set_visibility_pointer(
752 bool* last_call_was_set_visibility) {
753 last_call_was_set_visibility_ = last_call_was_set_visibility;
756 private:
757 bool* last_call_was_set_visibility_;
760 TEST(GLRendererTest2, VisibilityChangeIsLastCall) {
761 FakeRendererClient mock_client;
762 scoped_ptr<OutputSurface> output_surface(
763 FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
764 new VisibilityChangeIsLastCallTrackingContext)));
765 VisibilityChangeIsLastCallTrackingContext* context =
766 static_cast<VisibilityChangeIsLastCallTrackingContext*>(
767 output_surface->context3d());
768 scoped_ptr<ResourceProvider> resource_provider(
769 ResourceProvider::Create(output_surface.get(), 0));
770 FakeRendererGL renderer(
771 &mock_client, output_surface.get(), resource_provider.get());
773 EXPECT_TRUE(renderer.Initialize());
775 bool last_call_was_set_visiblity = false;
776 // Ensure that the call to setVisibilityCHROMIUM is the last call issue to the
777 // GPU process, after glFlush is called, and after the RendererClient's
778 // EnforceManagedMemoryPolicy is called. Plumb this tracking between both the
779 // RenderClient and the Context by giving them both a pointer to a variable on
780 // the stack.
781 context->set_last_call_was_set_visibility_pointer(
782 &last_call_was_set_visiblity);
783 mock_client.set_last_call_was_set_visibility_pointer(
784 &last_call_was_set_visiblity);
785 renderer.SetVisible(true);
786 renderer.DrawFrame(mock_client.render_passes_in_draw_order());
787 renderer.SetVisible(false);
788 EXPECT_TRUE(last_call_was_set_visiblity);
791 class TextureStateTrackingContext : public TestWebGraphicsContext3D {
792 public:
793 TextureStateTrackingContext() : active_texture_(GL_INVALID_ENUM) {}
795 virtual WebString getString(WGC3Denum name) {
796 if (name == GL_EXTENSIONS)
797 return WebString("GL_OES_EGL_image_external");
798 return WebString();
801 MOCK_METHOD3(texParameteri,
802 void(WGC3Denum target, WGC3Denum pname, WGC3Dint param));
803 MOCK_METHOD4(drawElements,
804 void(WGC3Denum mode,
805 WGC3Dsizei count,
806 WGC3Denum type,
807 WGC3Dintptr offset));
809 virtual void activeTexture(WGC3Denum texture) {
810 EXPECT_NE(texture, active_texture_);
811 active_texture_ = texture;
814 WGC3Denum active_texture() const { return active_texture_; }
816 private:
817 WGC3Denum active_texture_;
820 TEST(GLRendererTest2, ActiveTextureState) {
821 FakeRendererClient fake_client;
822 scoped_ptr<OutputSurface> output_surface(
823 FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
824 new TextureStateTrackingContext)));
825 TextureStateTrackingContext* context =
826 static_cast<TextureStateTrackingContext*>(output_surface->context3d());
827 scoped_ptr<ResourceProvider> resource_provider(
828 ResourceProvider::Create(output_surface.get(), 0));
829 FakeRendererGL renderer(
830 &fake_client, output_surface.get(), resource_provider.get());
832 // During initialization we are allowed to set any texture parameters.
833 EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
834 EXPECT_TRUE(renderer.Initialize());
836 cc::RenderPass::Id id(1, 1);
837 scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
838 pass->SetNew(id,
839 gfx::Rect(0, 0, 100, 100),
840 gfx::Rect(0, 0, 100, 100),
841 gfx::Transform());
842 pass->AppendOneOfEveryQuadType(resource_provider.get(), RenderPass::Id(2, 1));
844 // Set up expected texture filter state transitions that match the quads
845 // created in AppendOneOfEveryQuadType().
846 Mock::VerifyAndClearExpectations(context);
848 InSequence sequence;
850 // yuv_quad is drawn with the default linear filter.
851 EXPECT_CALL(*context, drawElements(_, _, _, _));
853 // tile_quad is drawn with GL_NEAREST because it is not transformed or
854 // scaled.
855 EXPECT_CALL(
856 *context,
857 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
858 EXPECT_CALL(
859 *context,
860 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
861 EXPECT_CALL(*context, drawElements(_, _, _, _));
863 // transformed_tile_quad uses GL_LINEAR.
864 EXPECT_CALL(*context, drawElements(_, _, _, _));
866 // scaled_tile_quad also uses GL_LINEAR.
867 EXPECT_CALL(*context, drawElements(_, _, _, _));
869 // The remaining quads also use GL_LINEAR because nearest neighbor
870 // filtering is currently only used with tile quads.
871 EXPECT_CALL(*context, drawElements(_, _, _, _)).Times(6);
874 cc::DirectRenderer::DrawingFrame drawing_frame;
875 renderer.BeginDrawingFrame(&drawing_frame);
876 EXPECT_EQ(static_cast<unsigned>(GL_TEXTURE0), context->active_texture());
878 for (cc::QuadList::BackToFrontIterator
879 it = pass->quad_list.BackToFrontBegin();
880 it != pass->quad_list.BackToFrontEnd();
881 ++it) {
882 renderer.DoDrawQuad(&drawing_frame, *it);
884 renderer.FinishDrawingQuadList();
885 EXPECT_EQ(static_cast<unsigned>(GL_TEXTURE0), context->active_texture());
886 Mock::VerifyAndClearExpectations(context);
889 class NoClearRootRenderPassFakeClient : public FakeRendererClient {
890 public:
891 virtual bool ShouldClearRootRenderPass() const OVERRIDE { return false; }
894 class NoClearRootRenderPassMockContext : public TestWebGraphicsContext3D {
895 public:
896 MOCK_METHOD1(clear, void(WGC3Dbitfield mask));
897 MOCK_METHOD4(drawElements,
898 void(WGC3Denum mode,
899 WGC3Dsizei count,
900 WGC3Denum type,
901 WGC3Dintptr offset));
904 TEST(GLRendererTest2, ShouldClearRootRenderPass) {
905 NoClearRootRenderPassFakeClient mock_client;
906 scoped_ptr<OutputSurface> output_surface(
907 FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
908 new NoClearRootRenderPassMockContext)));
909 NoClearRootRenderPassMockContext* mock_context =
910 static_cast<NoClearRootRenderPassMockContext*>(
911 output_surface->context3d());
912 scoped_ptr<ResourceProvider> resource_provider(
913 ResourceProvider::Create(output_surface.get(), 0));
914 FakeRendererGL renderer(
915 &mock_client, output_surface.get(), resource_provider.get());
916 EXPECT_TRUE(renderer.Initialize());
918 gfx::Rect viewport_rect(mock_client.DeviceViewportSize());
919 ScopedPtrVector<RenderPass>& render_passes =
920 *mock_client.render_passes_in_draw_order();
921 render_passes.clear();
923 RenderPass::Id root_pass_id(1, 0);
924 TestRenderPass* root_pass = AddRenderPass(
925 &render_passes, root_pass_id, viewport_rect, gfx::Transform());
926 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
928 RenderPass::Id child_pass_id(2, 0);
929 TestRenderPass* child_pass = AddRenderPass(
930 &render_passes, child_pass_id, viewport_rect, gfx::Transform());
931 AddQuad(child_pass, viewport_rect, SK_ColorBLUE);
933 AddRenderPassQuad(root_pass, child_pass);
935 // First render pass is not the root one, clearing should happen.
936 EXPECT_CALL(*mock_context, clear(GL_COLOR_BUFFER_BIT)).Times(AtLeast(1));
938 Expectation first_render_pass =
939 EXPECT_CALL(*mock_context, drawElements(_, _, _, _)).Times(1);
941 // The second render pass is the root one, clearing should be prevented.
942 EXPECT_CALL(*mock_context, clear(GL_COLOR_BUFFER_BIT)).Times(0)
943 .After(first_render_pass);
945 EXPECT_CALL(*mock_context, drawElements(_, _, _, _)).Times(AnyNumber())
946 .After(first_render_pass);
948 renderer.DecideRenderPassAllocationsForFrame(
949 *mock_client.render_passes_in_draw_order());
950 renderer.DrawFrame(mock_client.render_passes_in_draw_order());
952 // In multiple render passes all but the root pass should clear the
953 // framebuffer.
954 Mock::VerifyAndClearExpectations(&mock_context);
957 class ScissorTestOnClearCheckingContext : public TestWebGraphicsContext3D {
958 public:
959 ScissorTestOnClearCheckingContext() : scissor_enabled_(false) {}
961 virtual void clear(WGC3Dbitfield) { EXPECT_FALSE(scissor_enabled_); }
963 virtual void enable(WGC3Denum cap) {
964 if (cap == GL_SCISSOR_TEST)
965 scissor_enabled_ = true;
968 virtual void disable(WGC3Denum cap) {
969 if (cap == GL_SCISSOR_TEST)
970 scissor_enabled_ = false;
973 private:
974 bool scissor_enabled_;
977 TEST(GLRendererTest2, ScissorTestWhenClearing) {
978 FakeRendererClient mock_client;
979 scoped_ptr<OutputSurface> output_surface(
980 FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
981 new ScissorTestOnClearCheckingContext)));
982 scoped_ptr<ResourceProvider> resource_provider(
983 ResourceProvider::Create(output_surface.get(), 0));
984 FakeRendererGL renderer(
985 &mock_client, output_surface.get(), resource_provider.get());
986 EXPECT_TRUE(renderer.Initialize());
987 EXPECT_FALSE(renderer.Capabilities().using_partial_swap);
989 gfx::Rect viewport_rect(mock_client.DeviceViewportSize());
990 ScopedPtrVector<RenderPass>& render_passes =
991 *mock_client.render_passes_in_draw_order();
992 render_passes.clear();
994 gfx::Rect grand_child_rect(25, 25);
995 RenderPass::Id grand_child_pass_id(3, 0);
996 TestRenderPass* grand_child_pass = AddRenderPass(
997 &render_passes, grand_child_pass_id, grand_child_rect, gfx::Transform());
998 AddClippedQuad(grand_child_pass, grand_child_rect, SK_ColorYELLOW);
1000 gfx::Rect child_rect(50, 50);
1001 RenderPass::Id child_pass_id(2, 0);
1002 TestRenderPass* child_pass = AddRenderPass(
1003 &render_passes, child_pass_id, child_rect, gfx::Transform());
1004 AddQuad(child_pass, child_rect, SK_ColorBLUE);
1006 RenderPass::Id root_pass_id(1, 0);
1007 TestRenderPass* root_pass = AddRenderPass(
1008 &render_passes, root_pass_id, viewport_rect, gfx::Transform());
1009 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1011 AddRenderPassQuad(root_pass, child_pass);
1012 AddRenderPassQuad(child_pass, grand_child_pass);
1014 renderer.DecideRenderPassAllocationsForFrame(
1015 *mock_client.render_passes_in_draw_order());
1016 renderer.DrawFrame(mock_client.render_passes_in_draw_order());
1019 TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) {
1020 gfx::Rect viewportRect(mock_client_.DeviceViewportSize());
1021 ScopedPtrVector<RenderPass>* renderPasses =
1022 mock_client_.render_passes_in_draw_order();
1024 gfx::Rect grandChildRect(25, 25);
1025 RenderPass::Id grandChildPassId(3, 0);
1026 TestRenderPass* grandChildPass;
1028 gfx::Rect childRect(50, 50);
1029 RenderPass::Id childPassId(2, 0);
1030 TestRenderPass* childPass;
1032 RenderPass::Id rootPassId(1, 0);
1033 TestRenderPass* rootPass;
1035 cc::ResourceProvider::ResourceId mask =
1036 resource_provider_->CreateResource(gfx::Size(20, 12),
1037 resource_provider_->best_texture_format(),
1038 ResourceProvider::TextureUsageAny);
1039 resource_provider_->AllocateForTesting(mask);
1041 SkScalar matrix[20];
1042 float amount = 0.5f;
1043 matrix[0] = 0.213f + 0.787f * amount;
1044 matrix[1] = 0.715f - 0.715f * amount;
1045 matrix[2] = 1.f - (matrix[0] + matrix[1]);
1046 matrix[3] = matrix[4] = 0;
1047 matrix[5] = 0.213f - 0.213f * amount;
1048 matrix[6] = 0.715f + 0.285f * amount;
1049 matrix[7] = 1.f - (matrix[5] + matrix[6]);
1050 matrix[8] = matrix[9] = 0;
1051 matrix[10] = 0.213f - 0.213f * amount;
1052 matrix[11] = 0.715f - 0.715f * amount;
1053 matrix[12] = 1.f - (matrix[10] + matrix[11]);
1054 matrix[13] = matrix[14] = 0;
1055 matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0;
1056 matrix[18] = 1;
1057 skia::RefPtr<SkColorFilter> colorFilter(skia::AdoptRef(
1058 new SkColorMatrixFilter(matrix)));
1059 skia::RefPtr<SkImageFilter> filter =
1060 skia::AdoptRef(SkColorFilterImageFilter::Create(colorFilter.get(), NULL));
1062 gfx::Transform transform_causing_aa;
1063 transform_causing_aa.Rotate(20.0);
1065 // RenderPassProgram
1066 renderPasses->clear();
1068 grandChildPass = AddRenderPass(renderPasses, grandChildPassId, grandChildRect,
1069 gfx::Transform());
1070 AddClippedQuad(grandChildPass, grandChildRect, SK_ColorYELLOW);
1072 childPass = AddRenderPass(renderPasses, childPassId, childRect,
1073 gfx::Transform());
1074 AddQuad(childPass, childRect, SK_ColorBLUE);
1076 rootPass = AddRenderPass(renderPasses, rootPassId, viewportRect,
1077 gfx::Transform());
1078 AddQuad(rootPass, viewportRect, SK_ColorGREEN);
1080 AddRenderPassQuad(rootPass, childPass, 0, skia::RefPtr<SkImageFilter>(),
1081 gfx::Transform());
1082 AddRenderPassQuad(childPass, grandChildPass);
1084 renderer_->DecideRenderPassAllocationsForFrame(
1085 *mock_client_.render_passes_in_draw_order());
1086 renderer_->DrawFrame(mock_client_.render_passes_in_draw_order());
1087 TestRenderPassProgram();
1089 // RenderPassColorMatrixProgram
1090 renderPasses->clear();
1092 grandChildPass = AddRenderPass(renderPasses, grandChildPassId, grandChildRect,
1093 transform_causing_aa);
1094 AddClippedQuad(grandChildPass, grandChildRect, SK_ColorYELLOW);
1096 childPass = AddRenderPass(renderPasses, childPassId, childRect,
1097 transform_causing_aa);
1098 AddQuad(childPass, childRect, SK_ColorBLUE);
1100 rootPass = AddRenderPass(renderPasses, rootPassId, viewportRect,
1101 gfx::Transform());
1102 AddQuad(rootPass, viewportRect, SK_ColorGREEN);
1104 AddRenderPassQuad(rootPass, childPass, 0, filter, gfx::Transform());
1105 AddRenderPassQuad(childPass, grandChildPass);
1107 renderer_->DecideRenderPassAllocationsForFrame(
1108 *mock_client_.render_passes_in_draw_order());
1109 renderer_->DrawFrame(mock_client_.render_passes_in_draw_order());
1110 TestRenderPassColorMatrixProgram();
1112 // RenderPassMaskProgram
1113 renderPasses->clear();
1115 grandChildPass = AddRenderPass(renderPasses, grandChildPassId, grandChildRect,
1116 gfx::Transform());
1117 AddClippedQuad(grandChildPass, grandChildRect, SK_ColorYELLOW);
1119 childPass = AddRenderPass(renderPasses, childPassId, childRect,
1120 gfx::Transform());
1121 AddQuad(childPass, childRect, SK_ColorBLUE);
1123 rootPass = AddRenderPass(renderPasses, rootPassId, viewportRect,
1124 gfx::Transform());
1125 AddQuad(rootPass, viewportRect, SK_ColorGREEN);
1127 AddRenderPassQuad(rootPass, childPass, mask, skia::RefPtr<SkImageFilter>(),
1128 gfx::Transform());
1129 AddRenderPassQuad(childPass, grandChildPass);
1131 renderer_->DecideRenderPassAllocationsForFrame(
1132 *mock_client_.render_passes_in_draw_order());
1133 renderer_->DrawFrame(mock_client_.render_passes_in_draw_order());
1134 TestRenderPassMaskProgram();
1136 // RenderPassMaskColorMatrixProgram
1137 renderPasses->clear();
1139 grandChildPass = AddRenderPass(renderPasses, grandChildPassId, grandChildRect,
1140 gfx::Transform());
1141 AddClippedQuad(grandChildPass, grandChildRect, SK_ColorYELLOW);
1143 childPass = AddRenderPass(renderPasses, childPassId, childRect,
1144 gfx::Transform());
1145 AddQuad(childPass, childRect, SK_ColorBLUE);
1147 rootPass = AddRenderPass(renderPasses, rootPassId, viewportRect,
1148 gfx::Transform());
1149 AddQuad(rootPass, viewportRect, SK_ColorGREEN);
1151 AddRenderPassQuad(rootPass, childPass, mask, filter, gfx::Transform());
1152 AddRenderPassQuad(childPass, grandChildPass);
1154 renderer_->DecideRenderPassAllocationsForFrame(
1155 *mock_client_.render_passes_in_draw_order());
1156 renderer_->DrawFrame(mock_client_.render_passes_in_draw_order());
1157 TestRenderPassMaskColorMatrixProgram();
1159 // RenderPassProgramAA
1160 renderPasses->clear();
1162 grandChildPass = AddRenderPass(renderPasses, grandChildPassId, grandChildRect,
1163 transform_causing_aa);
1164 AddClippedQuad(grandChildPass, grandChildRect, SK_ColorYELLOW);
1166 childPass = AddRenderPass(renderPasses, childPassId, childRect,
1167 transform_causing_aa);
1168 AddQuad(childPass, childRect, SK_ColorBLUE);
1170 rootPass = AddRenderPass(renderPasses, rootPassId, viewportRect,
1171 gfx::Transform());
1172 AddQuad(rootPass, viewportRect, SK_ColorGREEN);
1174 AddRenderPassQuad(rootPass, childPass, 0, skia::RefPtr<SkImageFilter>(),
1175 transform_causing_aa);
1176 AddRenderPassQuad(childPass, grandChildPass);
1178 renderer_->DecideRenderPassAllocationsForFrame(
1179 *mock_client_.render_passes_in_draw_order());
1180 renderer_->DrawFrame(mock_client_.render_passes_in_draw_order());
1181 TestRenderPassProgramAA();
1183 // RenderPassColorMatrixProgramAA
1184 renderPasses->clear();
1186 grandChildPass = AddRenderPass(renderPasses, grandChildPassId, grandChildRect,
1187 transform_causing_aa);
1188 AddClippedQuad(grandChildPass, grandChildRect, SK_ColorYELLOW);
1190 childPass = AddRenderPass(renderPasses, childPassId, childRect,
1191 transform_causing_aa);
1192 AddQuad(childPass, childRect, SK_ColorBLUE);
1194 rootPass = AddRenderPass(renderPasses, rootPassId, viewportRect,
1195 gfx::Transform());
1196 AddQuad(rootPass, viewportRect, SK_ColorGREEN);
1198 AddRenderPassQuad(rootPass, childPass, 0, filter, transform_causing_aa);
1199 AddRenderPassQuad(childPass, grandChildPass);
1201 renderer_->DecideRenderPassAllocationsForFrame(
1202 *mock_client_.render_passes_in_draw_order());
1203 renderer_->DrawFrame(mock_client_.render_passes_in_draw_order());
1204 TestRenderPassColorMatrixProgramAA();
1206 // RenderPassMaskProgramAA
1207 renderPasses->clear();
1209 grandChildPass = AddRenderPass(renderPasses, grandChildPassId, grandChildRect,
1210 transform_causing_aa);
1211 AddClippedQuad(grandChildPass, grandChildRect, SK_ColorYELLOW);
1213 childPass = AddRenderPass(renderPasses, childPassId, childRect,
1214 transform_causing_aa);
1215 AddQuad(childPass, childRect, SK_ColorBLUE);
1217 rootPass = AddRenderPass(renderPasses, rootPassId, viewportRect,
1218 gfx::Transform());
1219 AddQuad(rootPass, viewportRect, SK_ColorGREEN);
1221 AddRenderPassQuad(rootPass, childPass, mask, skia::RefPtr<SkImageFilter>(),
1222 transform_causing_aa);
1223 AddRenderPassQuad(childPass, grandChildPass);
1225 renderer_->DecideRenderPassAllocationsForFrame(
1226 *mock_client_.render_passes_in_draw_order());
1227 renderer_->DrawFrame(mock_client_.render_passes_in_draw_order());
1228 TestRenderPassMaskProgramAA();
1230 // RenderPassMaskColorMatrixProgramAA
1231 renderPasses->clear();
1233 grandChildPass = AddRenderPass(renderPasses, grandChildPassId, grandChildRect,
1234 transform_causing_aa);
1235 AddClippedQuad(grandChildPass, grandChildRect, SK_ColorYELLOW);
1237 childPass = AddRenderPass(renderPasses, childPassId, childRect,
1238 transform_causing_aa);
1239 AddQuad(childPass, childRect, SK_ColorBLUE);
1241 rootPass = AddRenderPass(renderPasses, rootPassId, viewportRect,
1242 transform_causing_aa);
1243 AddQuad(rootPass, viewportRect, SK_ColorGREEN);
1245 AddRenderPassQuad(rootPass, childPass, mask, filter, transform_causing_aa);
1246 AddRenderPassQuad(childPass, grandChildPass);
1248 renderer_->DecideRenderPassAllocationsForFrame(
1249 *mock_client_.render_passes_in_draw_order());
1250 renderer_->DrawFrame(mock_client_.render_passes_in_draw_order());
1251 TestRenderPassMaskColorMatrixProgramAA();
1254 class OutputSurfaceMockContext : public TestWebGraphicsContext3D {
1255 public:
1256 // Specifically override methods even if they are unused (used in conjunction
1257 // with StrictMock). We need to make sure that GLRenderer does not issue
1258 // framebuffer-related GL calls directly. Instead these are supposed to go
1259 // through the OutputSurface abstraction.
1260 MOCK_METHOD0(ensureBackbufferCHROMIUM, void());
1261 MOCK_METHOD0(discardBackbufferCHROMIUM, void());
1262 MOCK_METHOD2(bindFramebuffer, void(WGC3Denum target, WebGLId framebuffer));
1263 MOCK_METHOD0(prepareTexture, void());
1264 MOCK_METHOD2(reshape, void(int width, int height));
1265 MOCK_METHOD4(drawElements,
1266 void(WGC3Denum mode,
1267 WGC3Dsizei count,
1268 WGC3Denum type,
1269 WGC3Dintptr offset));
1271 virtual WebString getString(WebKit::WGC3Denum name) {
1272 if (name == GL_EXTENSIONS)
1273 return WebString(
1274 "GL_CHROMIUM_post_sub_buffer GL_CHROMIUM_discard_backbuffer");
1275 return WebString();
1279 class MockOutputSurface : public OutputSurface {
1280 public:
1281 MockOutputSurface()
1282 : OutputSurface(scoped_ptr<WebKit::WebGraphicsContext3D>(
1283 new StrictMock<OutputSurfaceMockContext>)) {}
1284 virtual ~MockOutputSurface() {}
1286 MOCK_METHOD1(SendFrameToParentCompositor, void(CompositorFrame* frame));
1287 MOCK_METHOD0(EnsureBackbuffer, void());
1288 MOCK_METHOD0(DiscardBackbuffer, void());
1289 MOCK_METHOD1(Reshape, void(gfx::Size size));
1290 MOCK_METHOD0(BindFramebuffer, void());
1291 MOCK_METHOD1(PostSubBuffer, void(gfx::Rect rect));
1292 MOCK_METHOD0(SwapBuffers, void());
1295 class MockOutputSurfaceTest : public testing::Test, public FakeRendererClient {
1296 protected:
1297 MockOutputSurfaceTest()
1298 : resource_provider_(ResourceProvider::Create(&output_surface_, 0)),
1299 renderer_(this, &output_surface_, resource_provider_.get()) {}
1301 virtual void SetUp() { EXPECT_TRUE(renderer_.Initialize()); }
1303 void SwapBuffers() { renderer_.SwapBuffers(); }
1305 void DrawFrame() {
1306 gfx::Rect viewport_rect(DeviceViewportSize());
1307 ScopedPtrVector<RenderPass>* render_passes = render_passes_in_draw_order();
1308 render_passes->clear();
1310 RenderPass::Id render_pass_id(1, 0);
1311 TestRenderPass* render_pass = AddRenderPass(
1312 render_passes, render_pass_id, viewport_rect, gfx::Transform());
1313 AddQuad(render_pass, viewport_rect, SK_ColorGREEN);
1315 EXPECT_CALL(output_surface_, EnsureBackbuffer()).WillRepeatedly(Return());
1317 EXPECT_CALL(output_surface_, Reshape(_)).Times(1);
1319 EXPECT_CALL(output_surface_, BindFramebuffer()).Times(1);
1321 EXPECT_CALL(*context(), drawElements(_, _, _, _)).Times(1);
1323 renderer_.DecideRenderPassAllocationsForFrame(
1324 *render_passes_in_draw_order());
1325 renderer_.DrawFrame(render_passes_in_draw_order());
1328 OutputSurfaceMockContext* context() {
1329 return static_cast<OutputSurfaceMockContext*>(output_surface_.context3d());
1332 StrictMock<MockOutputSurface> output_surface_;
1333 scoped_ptr<ResourceProvider> resource_provider_;
1334 FakeRendererGL renderer_;
1337 TEST_F(MockOutputSurfaceTest, DrawFrameAndSwap) {
1338 DrawFrame();
1340 EXPECT_CALL(output_surface_, SwapBuffers()).Times(1);
1341 renderer_.SwapBuffers();
1344 class MockOutputSurfaceTestWithPartialSwap : public MockOutputSurfaceTest {
1345 public:
1346 virtual const LayerTreeSettings& Settings() const OVERRIDE {
1347 static LayerTreeSettings fake_settings;
1348 fake_settings.partial_swap_enabled = true;
1349 return fake_settings;
1353 TEST_F(MockOutputSurfaceTestWithPartialSwap, DrawFrameAndSwap) {
1354 DrawFrame();
1356 EXPECT_CALL(output_surface_, PostSubBuffer(_)).Times(1);
1357 renderer_.SwapBuffers();
1360 class MockOutputSurfaceTestWithSendCompositorFrame
1361 : public MockOutputSurfaceTest {
1362 public:
1363 virtual const LayerTreeSettings& Settings() const OVERRIDE {
1364 static LayerTreeSettings fake_settings;
1365 fake_settings.compositor_frame_message = true;
1366 return fake_settings;
1370 TEST_F(MockOutputSurfaceTestWithSendCompositorFrame, DrawFrame) {
1371 EXPECT_CALL(output_surface_, SendFrameToParentCompositor(_)).Times(1);
1372 DrawFrame();
1375 } // namespace
1376 } // namespace cc