1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "cc/base/scoped_ptr_vector.h"
6#include "cc/output/gl_renderer.h"
7#include "cc/output/output_surface.h"
8#include "cc/output/output_surface_client.h"
9#include "cc/output/overlay_candidate_validator.h"
10#include "cc/output/overlay_processor.h"
11#include "cc/output/overlay_strategy_single_on_top.h"
12#include "cc/quads/checkerboard_draw_quad.h"
13#include "cc/quads/render_pass.h"
14#include "cc/quads/texture_draw_quad.h"
15#include "cc/resources/resource_provider.h"
16#include "cc/resources/texture_mailbox.h"
17#include "cc/test/fake_output_surface_client.h"
18#include "cc/test/geometry_test_utils.h"
19#include "cc/test/test_context_provider.h"
20#include "cc/test/test_shared_bitmap_manager.h"
21#include "testing/gmock/include/gmock/gmock.h"
22#include "testing/gtest/include/gtest/gtest.h"
23
24using testing::_;
25using testing::Mock;
26
27namespace cc {
28namespace {
29
30const gfx::Rect kOverlayRect(0, 0, 128, 128);
31const gfx::Rect kOverlayTopLeftRect(0, 0, 64, 64);
32const gfx::Rect kOverlayBottomRightRect(64, 64, 64, 64);
33const gfx::PointF kUVTopLeft(0.1f, 0.2f);
34const gfx::PointF kUVBottomRight(1.0f, 1.0f);
35
36void MailboxReleased(unsigned sync_point,
37                     bool lost_resource,
38                     BlockingTaskRunner* main_thread_task_runner) {
39}
40
41class SingleOverlayValidator : public OverlayCandidateValidator {
42 public:
43  virtual void CheckOverlaySupport(OverlayCandidateList* surfaces) OVERRIDE;
44};
45
46void SingleOverlayValidator::CheckOverlaySupport(
47    OverlayCandidateList* surfaces) {
48  ASSERT_EQ(2U, surfaces->size());
49
50  OverlayCandidate& candidate = surfaces->back();
51  if (candidate.display_rect.width() == 64)
52    EXPECT_EQ(kOverlayBottomRightRect, candidate.display_rect);
53  else
54    EXPECT_EQ(kOverlayRect, candidate.display_rect);
55  EXPECT_EQ(BoundingRect(kUVTopLeft, kUVBottomRight).ToString(),
56            candidate.uv_rect.ToString());
57  candidate.overlay_handled = true;
58}
59
60class SingleOverlayProcessor : public OverlayProcessor {
61 public:
62  SingleOverlayProcessor(OutputSurface* surface,
63                         ResourceProvider* resource_provider);
64  // Virtual to allow testing different strategies.
65  virtual void Initialize() OVERRIDE;
66};
67
68SingleOverlayProcessor::SingleOverlayProcessor(
69    OutputSurface* surface,
70    ResourceProvider* resource_provider)
71    : OverlayProcessor(surface, resource_provider) {
72  EXPECT_EQ(surface, surface_);
73  EXPECT_EQ(resource_provider, resource_provider_);
74}
75
76void SingleOverlayProcessor::Initialize() {
77  OverlayCandidateValidator* candidates =
78      surface_->overlay_candidate_validator();
79  ASSERT_TRUE(candidates != NULL);
80  strategies_.push_back(scoped_ptr<Strategy>(
81      new OverlayStrategySingleOnTop(candidates, resource_provider_)));
82}
83
84class DefaultOverlayProcessor : public OverlayProcessor {
85 public:
86  DefaultOverlayProcessor(OutputSurface* surface,
87                          ResourceProvider* resource_provider);
88  size_t GetStrategyCount();
89};
90
91DefaultOverlayProcessor::DefaultOverlayProcessor(
92    OutputSurface* surface,
93    ResourceProvider* resource_provider)
94    : OverlayProcessor(surface, resource_provider) {}
95
96size_t DefaultOverlayProcessor::GetStrategyCount() {
97  return strategies_.size();
98}
99
100class OverlayOutputSurface : public OutputSurface {
101 public:
102  explicit OverlayOutputSurface(scoped_refptr<ContextProvider> context_provider)
103      : OutputSurface(context_provider) {}
104
105  void InitWithSingleOverlayValidator() {
106    overlay_candidate_validator_.reset(new SingleOverlayValidator);
107  }
108};
109
110scoped_ptr<RenderPass> CreateRenderPass() {
111  RenderPassId id(1, 0);
112  gfx::Rect output_rect(0, 0, 256, 256);
113  bool has_transparent_background = true;
114
115  scoped_ptr<RenderPass> pass = RenderPass::Create();
116  pass->SetAll(id,
117               output_rect,
118               output_rect,
119               gfx::Transform(),
120               has_transparent_background);
121
122  SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState();
123  shared_state->opacity = 1.f;
124  return pass.Pass();
125}
126
127ResourceProvider::ResourceId CreateResource(
128    ResourceProvider* resource_provider) {
129  unsigned sync_point = 0;
130  TextureMailbox mailbox =
131      TextureMailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point);
132  mailbox.set_allow_overlay(true);
133  scoped_ptr<SingleReleaseCallbackImpl> release_callback =
134      SingleReleaseCallbackImpl::Create(base::Bind(&MailboxReleased));
135
136  return resource_provider->CreateResourceFromTextureMailbox(
137      mailbox, release_callback.Pass());
138}
139
140TextureDrawQuad* CreateCandidateQuadAt(ResourceProvider* resource_provider,
141                                       const SharedQuadState* shared_quad_state,
142                                       RenderPass* render_pass,
143                                       const gfx::Rect& rect) {
144  ResourceProvider::ResourceId resource_id = CreateResource(resource_provider);
145  bool premultiplied_alpha = false;
146  bool flipped = false;
147  float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
148
149  TextureDrawQuad* overlay_quad =
150      render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
151  overlay_quad->SetNew(shared_quad_state,
152                       rect,
153                       rect,
154                       rect,
155                       resource_id,
156                       premultiplied_alpha,
157                       kUVTopLeft,
158                       kUVBottomRight,
159                       SK_ColorTRANSPARENT,
160                       vertex_opacity,
161                       flipped);
162
163  return overlay_quad;
164}
165
166TextureDrawQuad* CreateFullscreenCandidateQuad(
167    ResourceProvider* resource_provider,
168    const SharedQuadState* shared_quad_state,
169    RenderPass* render_pass) {
170  return CreateCandidateQuadAt(
171      resource_provider, shared_quad_state, render_pass, kOverlayRect);
172}
173
174void CreateCheckeredQuadAt(ResourceProvider* resource_provider,
175                           const SharedQuadState* shared_quad_state,
176                           RenderPass* render_pass,
177                           const gfx::Rect& rect) {
178  CheckerboardDrawQuad* checkerboard_quad =
179      render_pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
180  checkerboard_quad->SetNew(shared_quad_state, rect, rect, SkColor());
181}
182
183void CreateFullscreenCheckeredQuad(ResourceProvider* resource_provider,
184                                   const SharedQuadState* shared_quad_state,
185                                   RenderPass* render_pass) {
186  CreateCheckeredQuadAt(
187      resource_provider, shared_quad_state, render_pass, kOverlayRect);
188}
189
190static void CompareRenderPassLists(const RenderPassList& expected_list,
191                                   const RenderPassList& actual_list) {
192  EXPECT_EQ(expected_list.size(), actual_list.size());
193  for (size_t i = 0; i < actual_list.size(); ++i) {
194    RenderPass* expected = expected_list[i];
195    RenderPass* actual = actual_list[i];
196
197    EXPECT_EQ(expected->id, actual->id);
198    EXPECT_RECT_EQ(expected->output_rect, actual->output_rect);
199    EXPECT_EQ(expected->transform_to_root_target,
200              actual->transform_to_root_target);
201    EXPECT_RECT_EQ(expected->damage_rect, actual->damage_rect);
202    EXPECT_EQ(expected->has_transparent_background,
203              actual->has_transparent_background);
204
205    EXPECT_EQ(expected->shared_quad_state_list.size(),
206              actual->shared_quad_state_list.size());
207    EXPECT_EQ(expected->quad_list.size(), actual->quad_list.size());
208
209    for (QuadList::Iterator exp_iter = expected->quad_list.begin(),
210                            act_iter = actual->quad_list.begin();
211         exp_iter != expected->quad_list.end();
212         ++exp_iter, ++act_iter) {
213      EXPECT_EQ(exp_iter->rect.ToString(), act_iter->rect.ToString());
214      EXPECT_EQ(exp_iter->shared_quad_state->content_bounds.ToString(),
215                act_iter->shared_quad_state->content_bounds.ToString());
216    }
217  }
218}
219
220TEST(OverlayTest, NoOverlaysByDefault) {
221  scoped_refptr<TestContextProvider> provider = TestContextProvider::Create();
222  OverlayOutputSurface output_surface(provider);
223  EXPECT_EQ(NULL, output_surface.overlay_candidate_validator());
224
225  output_surface.InitWithSingleOverlayValidator();
226  EXPECT_TRUE(output_surface.overlay_candidate_validator() != NULL);
227}
228
229TEST(OverlayTest, OverlaysProcessorHasStrategy) {
230  scoped_refptr<TestContextProvider> provider = TestContextProvider::Create();
231  OverlayOutputSurface output_surface(provider);
232  FakeOutputSurfaceClient client;
233  EXPECT_TRUE(output_surface.BindToClient(&client));
234  output_surface.InitWithSingleOverlayValidator();
235  EXPECT_TRUE(output_surface.overlay_candidate_validator() != NULL);
236
237  scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
238      new TestSharedBitmapManager());
239  scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
240      &output_surface, shared_bitmap_manager.get(), NULL, 0, false, 1, false));
241
242  scoped_ptr<DefaultOverlayProcessor> overlay_processor(
243      new DefaultOverlayProcessor(&output_surface, resource_provider.get()));
244  overlay_processor->Initialize();
245  EXPECT_GE(1U, overlay_processor->GetStrategyCount());
246}
247
248class SingleOverlayOnTopTest : public testing::Test {
249 protected:
250  virtual void SetUp() {
251    provider_ = TestContextProvider::Create();
252    output_surface_.reset(new OverlayOutputSurface(provider_));
253    EXPECT_TRUE(output_surface_->BindToClient(&client_));
254    output_surface_->InitWithSingleOverlayValidator();
255    EXPECT_TRUE(output_surface_->overlay_candidate_validator() != NULL);
256
257    shared_bitmap_manager_.reset(new TestSharedBitmapManager());
258    resource_provider_ = ResourceProvider::Create(output_surface_.get(),
259                                                  shared_bitmap_manager_.get(),
260                                                  NULL,
261                                                  0,
262                                                  false,
263                                                  1,
264                                                  false);
265
266    overlay_processor_.reset(new SingleOverlayProcessor(
267        output_surface_.get(), resource_provider_.get()));
268    overlay_processor_->Initialize();
269  }
270
271  scoped_refptr<TestContextProvider> provider_;
272  scoped_ptr<OverlayOutputSurface> output_surface_;
273  FakeOutputSurfaceClient client_;
274  scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
275  scoped_ptr<ResourceProvider> resource_provider_;
276  scoped_ptr<SingleOverlayProcessor> overlay_processor_;
277};
278
279TEST_F(SingleOverlayOnTopTest, SuccessfullOverlay) {
280  scoped_ptr<RenderPass> pass = CreateRenderPass();
281  TextureDrawQuad* original_quad =
282      CreateFullscreenCandidateQuad(resource_provider_.get(),
283                                    pass->shared_quad_state_list.back(),
284                                    pass.get());
285  unsigned original_resource_id = original_quad->resource_id;
286
287  // Add something behind it.
288  CreateFullscreenCheckeredQuad(resource_provider_.get(),
289                                pass->shared_quad_state_list.back(),
290                                pass.get());
291  CreateFullscreenCheckeredQuad(resource_provider_.get(),
292                                pass->shared_quad_state_list.back(),
293                                pass.get());
294
295  RenderPassList pass_list;
296  pass_list.push_back(pass.Pass());
297
298  // Check for potential candidates.
299  OverlayCandidateList candidate_list;
300  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
301
302  ASSERT_EQ(1U, pass_list.size());
303  ASSERT_EQ(2U, candidate_list.size());
304
305  RenderPass* main_pass = pass_list.back();
306  // Check that the quad is gone.
307  EXPECT_EQ(2U, main_pass->quad_list.size());
308  const QuadList& quad_list = main_pass->quad_list;
309  for (QuadList::ConstBackToFrontIterator it = quad_list.BackToFrontBegin();
310       it != quad_list.BackToFrontEnd();
311       ++it) {
312    EXPECT_NE(DrawQuad::TEXTURE_CONTENT, it->material);
313  }
314
315  // Check that the right resource id got extracted.
316  EXPECT_EQ(original_resource_id, candidate_list.back().resource_id);
317}
318
319TEST_F(SingleOverlayOnTopTest, NoCandidates) {
320  scoped_ptr<RenderPass> pass = CreateRenderPass();
321  CreateFullscreenCheckeredQuad(resource_provider_.get(),
322                                pass->shared_quad_state_list.back(),
323                                pass.get());
324  CreateFullscreenCheckeredQuad(resource_provider_.get(),
325                                pass->shared_quad_state_list.back(),
326                                pass.get());
327
328  RenderPassList pass_list;
329  pass_list.push_back(pass.Pass());
330
331  RenderPassList original_pass_list;
332  RenderPass::CopyAll(pass_list, &original_pass_list);
333
334  OverlayCandidateList candidate_list;
335  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
336  EXPECT_EQ(0U, candidate_list.size());
337  // There should be nothing new here.
338  CompareRenderPassLists(pass_list, original_pass_list);
339}
340
341TEST_F(SingleOverlayOnTopTest, OccludedCandidates) {
342  scoped_ptr<RenderPass> pass = CreateRenderPass();
343  CreateFullscreenCheckeredQuad(resource_provider_.get(),
344                                pass->shared_quad_state_list.back(),
345                                pass.get());
346  CreateFullscreenCheckeredQuad(resource_provider_.get(),
347                                pass->shared_quad_state_list.back(),
348                                pass.get());
349
350  CreateFullscreenCandidateQuad(resource_provider_.get(),
351                                pass->shared_quad_state_list.back(),
352                                pass.get());
353
354  RenderPassList pass_list;
355  pass_list.push_back(pass.Pass());
356
357  RenderPassList original_pass_list;
358  RenderPass::CopyAll(pass_list, &original_pass_list);
359
360  OverlayCandidateList candidate_list;
361  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
362  EXPECT_EQ(0U, candidate_list.size());
363  // There should be nothing new here.
364  CompareRenderPassLists(pass_list, original_pass_list);
365}
366
367// Test with multiple render passes.
368TEST_F(SingleOverlayOnTopTest, MultipleRenderPasses) {
369  RenderPassList pass_list;
370  pass_list.push_back(CreateRenderPass());
371
372  scoped_ptr<RenderPass> pass = CreateRenderPass();
373  CreateFullscreenCandidateQuad(resource_provider_.get(),
374                                pass->shared_quad_state_list.back(),
375                                pass.get());
376
377  // Add something behind it.
378  CreateFullscreenCheckeredQuad(resource_provider_.get(),
379                                pass->shared_quad_state_list.back(),
380                                pass.get());
381  CreateFullscreenCheckeredQuad(resource_provider_.get(),
382                                pass->shared_quad_state_list.back(),
383                                pass.get());
384
385  pass_list.push_back(pass.Pass());
386
387  RenderPassList original_pass_list;
388  RenderPass::CopyAll(pass_list, &original_pass_list);
389
390  // Check for potential candidates.
391  OverlayCandidateList candidate_list;
392  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
393  EXPECT_EQ(2U, candidate_list.size());
394
395  // This should be the same.
396  ASSERT_EQ(2U, pass_list.size());
397}
398
399TEST_F(SingleOverlayOnTopTest, RejectPremultipliedAlpha) {
400  scoped_ptr<RenderPass> pass = CreateRenderPass();
401  TextureDrawQuad* quad =
402      CreateFullscreenCandidateQuad(resource_provider_.get(),
403                                    pass->shared_quad_state_list.back(),
404                                    pass.get());
405  quad->premultiplied_alpha = true;
406
407  RenderPassList pass_list;
408  pass_list.push_back(pass.Pass());
409  OverlayCandidateList candidate_list;
410  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
411  EXPECT_EQ(1U, pass_list.size());
412  EXPECT_EQ(0U, candidate_list.size());
413}
414
415TEST_F(SingleOverlayOnTopTest, RejectBlending) {
416  scoped_ptr<RenderPass> pass = CreateRenderPass();
417  TextureDrawQuad* quad =
418      CreateFullscreenCandidateQuad(resource_provider_.get(),
419                                    pass->shared_quad_state_list.back(),
420                                    pass.get());
421  quad->needs_blending = true;
422
423  RenderPassList pass_list;
424  pass_list.push_back(pass.Pass());
425  OverlayCandidateList candidate_list;
426  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
427  ASSERT_EQ(1U, pass_list.size());
428  EXPECT_EQ(0U, candidate_list.size());
429}
430
431TEST_F(SingleOverlayOnTopTest, RejectBackgroundColor) {
432  scoped_ptr<RenderPass> pass = CreateRenderPass();
433  TextureDrawQuad* quad =
434      CreateFullscreenCandidateQuad(resource_provider_.get(),
435                                    pass->shared_quad_state_list.back(),
436                                    pass.get());
437  quad->background_color = SK_ColorBLACK;
438
439  RenderPassList pass_list;
440  pass_list.push_back(pass.Pass());
441  OverlayCandidateList candidate_list;
442  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
443  ASSERT_EQ(1U, pass_list.size());
444  EXPECT_EQ(0U, candidate_list.size());
445}
446
447TEST_F(SingleOverlayOnTopTest, RejectBlendMode) {
448  scoped_ptr<RenderPass> pass = CreateRenderPass();
449  CreateFullscreenCandidateQuad(resource_provider_.get(),
450                                pass->shared_quad_state_list.back(),
451                                pass.get());
452  pass->shared_quad_state_list.back()->blend_mode = SkXfermode::kScreen_Mode;
453
454  RenderPassList pass_list;
455  pass_list.push_back(pass.Pass());
456  OverlayCandidateList candidate_list;
457  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
458  ASSERT_EQ(1U, pass_list.size());
459  EXPECT_EQ(0U, candidate_list.size());
460}
461
462TEST_F(SingleOverlayOnTopTest, RejectOpacity) {
463  scoped_ptr<RenderPass> pass = CreateRenderPass();
464  CreateFullscreenCandidateQuad(resource_provider_.get(),
465                                pass->shared_quad_state_list.back(),
466                                pass.get());
467  pass->shared_quad_state_list.back()->opacity = 0.5f;
468
469  RenderPassList pass_list;
470  pass_list.push_back(pass.Pass());
471  OverlayCandidateList candidate_list;
472  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
473  ASSERT_EQ(1U, pass_list.size());
474  EXPECT_EQ(0U, candidate_list.size());
475}
476
477TEST_F(SingleOverlayOnTopTest, RejectTransform) {
478  scoped_ptr<RenderPass> pass = CreateRenderPass();
479  CreateFullscreenCandidateQuad(resource_provider_.get(),
480                                pass->shared_quad_state_list.back(),
481                                pass.get());
482  pass->shared_quad_state_list.back()->content_to_target_transform.Scale(2.f,
483                                                                         2.f);
484
485  RenderPassList pass_list;
486  pass_list.push_back(pass.Pass());
487  OverlayCandidateList candidate_list;
488  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
489  ASSERT_EQ(1U, pass_list.size());
490  EXPECT_EQ(0U, candidate_list.size());
491}
492
493TEST_F(SingleOverlayOnTopTest, AllowNotTopIfNotOccluded) {
494  scoped_ptr<RenderPass> pass = CreateRenderPass();
495  CreateCheckeredQuadAt(resource_provider_.get(),
496                        pass->shared_quad_state_list.back(),
497                        pass.get(),
498                        kOverlayTopLeftRect);
499  CreateCandidateQuadAt(resource_provider_.get(),
500                        pass->shared_quad_state_list.back(),
501                        pass.get(),
502                        kOverlayBottomRightRect);
503
504  RenderPassList pass_list;
505  pass_list.push_back(pass.Pass());
506
507  RenderPassList original_pass_list;
508  RenderPass::CopyAll(pass_list, &original_pass_list);
509
510  OverlayCandidateList candidate_list;
511  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
512  EXPECT_EQ(1U, pass_list.size());
513  EXPECT_EQ(2U, candidate_list.size());
514}
515
516class OverlayInfoRendererGL : public GLRenderer {
517 public:
518  OverlayInfoRendererGL(RendererClient* client,
519                        const LayerTreeSettings* settings,
520                        OutputSurface* output_surface,
521                        ResourceProvider* resource_provider)
522      : GLRenderer(client,
523                   settings,
524                   output_surface,
525                   resource_provider,
526                   NULL,
527                   0),
528        expect_overlays_(false) {}
529
530  MOCK_METHOD2(DoDrawQuad, void(DrawingFrame* frame, const DrawQuad* quad));
531
532  virtual void FinishDrawingFrame(DrawingFrame* frame) OVERRIDE {
533    GLRenderer::FinishDrawingFrame(frame);
534
535    if (!expect_overlays_) {
536      EXPECT_EQ(0U, frame->overlay_list.size());
537      return;
538    }
539
540    ASSERT_EQ(2U, frame->overlay_list.size());
541    EXPECT_NE(0U, frame->overlay_list.back().resource_id);
542  }
543
544  void set_expect_overlays(bool expect_overlays) {
545    expect_overlays_ = expect_overlays;
546  }
547
548 private:
549  bool expect_overlays_;
550};
551
552class FakeRendererClient : public RendererClient {
553 public:
554  // RendererClient methods.
555  virtual void SetFullRootLayerDamage() OVERRIDE {}
556};
557
558class MockOverlayScheduler {
559 public:
560  MOCK_METHOD5(Schedule,
561               void(int plane_z_order,
562                    gfx::OverlayTransform plane_transform,
563                    unsigned overlay_texture_id,
564                    const gfx::Rect& display_bounds,
565                    const gfx::RectF& uv_rect));
566};
567
568class GLRendererWithOverlaysTest : public testing::Test {
569 protected:
570  GLRendererWithOverlaysTest() {
571    provider_ = TestContextProvider::Create();
572    output_surface_.reset(new OverlayOutputSurface(provider_));
573    CHECK(output_surface_->BindToClient(&output_surface_client_));
574    resource_provider_ = ResourceProvider::Create(
575        output_surface_.get(), NULL, NULL, 0, false, 1, false);
576
577    provider_->support()->SetScheduleOverlayPlaneCallback(base::Bind(
578        &MockOverlayScheduler::Schedule, base::Unretained(&scheduler_)));
579  }
580
581  void Init(bool use_validator) {
582    if (use_validator)
583      output_surface_->InitWithSingleOverlayValidator();
584
585    renderer_ =
586        make_scoped_ptr(new OverlayInfoRendererGL(&renderer_client_,
587                                                  &settings_,
588                                                  output_surface_.get(),
589                                                  resource_provider_.get()));
590  }
591
592  void SwapBuffers() { renderer_->SwapBuffers(CompositorFrameMetadata()); }
593
594  LayerTreeSettings settings_;
595  FakeOutputSurfaceClient output_surface_client_;
596  scoped_ptr<OverlayOutputSurface> output_surface_;
597  FakeRendererClient renderer_client_;
598  scoped_ptr<ResourceProvider> resource_provider_;
599  scoped_ptr<OverlayInfoRendererGL> renderer_;
600  scoped_refptr<TestContextProvider> provider_;
601  MockOverlayScheduler scheduler_;
602};
603
604TEST_F(GLRendererWithOverlaysTest, OverlayQuadNotDrawn) {
605  bool use_validator = true;
606  Init(use_validator);
607  renderer_->set_expect_overlays(true);
608  gfx::Rect viewport_rect(16, 16);
609
610  scoped_ptr<RenderPass> pass = CreateRenderPass();
611
612  CreateFullscreenCandidateQuad(resource_provider_.get(),
613                                pass->shared_quad_state_list.back(),
614                                pass.get());
615
616  CreateFullscreenCheckeredQuad(resource_provider_.get(),
617                                pass->shared_quad_state_list.back(),
618                                pass.get());
619  CreateFullscreenCheckeredQuad(resource_provider_.get(),
620                                pass->shared_quad_state_list.back(),
621                                pass.get());
622
623  RenderPassList pass_list;
624  pass_list.push_back(pass.Pass());
625
626  // Candidate pass was taken out and extra skipped pass added,
627  // so only draw 2 quads.
628  EXPECT_CALL(*renderer_, DoDrawQuad(_, _)).Times(2);
629  EXPECT_CALL(scheduler_,
630              Schedule(1,
631                       gfx::OVERLAY_TRANSFORM_NONE,
632                       _,
633                       kOverlayRect,
634                       BoundingRect(kUVTopLeft, kUVBottomRight))).Times(1);
635  renderer_->DrawFrame(&pass_list, 1.f, viewport_rect, viewport_rect, false);
636
637  SwapBuffers();
638
639  Mock::VerifyAndClearExpectations(renderer_.get());
640  Mock::VerifyAndClearExpectations(&scheduler_);
641}
642
643TEST_F(GLRendererWithOverlaysTest, OccludedQuadDrawn) {
644  bool use_validator = true;
645  Init(use_validator);
646  renderer_->set_expect_overlays(false);
647  gfx::Rect viewport_rect(16, 16);
648
649  scoped_ptr<RenderPass> pass = CreateRenderPass();
650
651  CreateFullscreenCheckeredQuad(resource_provider_.get(),
652                                pass->shared_quad_state_list.back(),
653                                pass.get());
654  CreateFullscreenCheckeredQuad(resource_provider_.get(),
655                                pass->shared_quad_state_list.back(),
656                                pass.get());
657
658  CreateFullscreenCandidateQuad(resource_provider_.get(),
659                                pass->shared_quad_state_list.back(),
660                                pass.get());
661
662  RenderPassList pass_list;
663  pass_list.push_back(pass.Pass());
664
665  // 3 quads in the pass, all should draw.
666  EXPECT_CALL(*renderer_, DoDrawQuad(_, _)).Times(3);
667  EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0);
668  renderer_->DrawFrame(&pass_list, 1.f, viewport_rect, viewport_rect, false);
669
670  SwapBuffers();
671
672  Mock::VerifyAndClearExpectations(renderer_.get());
673  Mock::VerifyAndClearExpectations(&scheduler_);
674}
675
676TEST_F(GLRendererWithOverlaysTest, NoValidatorNoOverlay) {
677  bool use_validator = false;
678  Init(use_validator);
679  renderer_->set_expect_overlays(false);
680  gfx::Rect viewport_rect(16, 16);
681
682  scoped_ptr<RenderPass> pass = CreateRenderPass();
683
684  CreateFullscreenCandidateQuad(resource_provider_.get(),
685                                pass->shared_quad_state_list.back(),
686                                pass.get());
687
688  CreateFullscreenCheckeredQuad(resource_provider_.get(),
689                                pass->shared_quad_state_list.back(),
690                                pass.get());
691  CreateFullscreenCheckeredQuad(resource_provider_.get(),
692                                pass->shared_quad_state_list.back(),
693                                pass.get());
694
695  RenderPassList pass_list;
696  pass_list.push_back(pass.Pass());
697
698  // Should see no overlays.
699  EXPECT_CALL(*renderer_, DoDrawQuad(_, _)).Times(3);
700  EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0);
701  renderer_->DrawFrame(&pass_list, 1.f, viewport_rect, viewport_rect, false);
702
703  SwapBuffers();
704
705  Mock::VerifyAndClearExpectations(renderer_.get());
706  Mock::VerifyAndClearExpectations(&scheduler_);
707}
708
709TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturned) {
710  bool use_validator = true;
711  Init(use_validator);
712  renderer_->set_expect_overlays(true);
713
714  ResourceProvider::ResourceId resource1 =
715      CreateResource(resource_provider_.get());
716  ResourceProvider::ResourceId resource2 =
717      CreateResource(resource_provider_.get());
718
719  DirectRenderer::DrawingFrame frame1;
720  frame1.overlay_list.resize(2);
721  OverlayCandidate& overlay1 = frame1.overlay_list.back();
722  overlay1.resource_id = resource1;
723  overlay1.plane_z_order = 1;
724
725  DirectRenderer::DrawingFrame frame2;
726  frame2.overlay_list.resize(2);
727  OverlayCandidate& overlay2 = frame2.overlay_list.back();
728  overlay2.resource_id = resource2;
729  overlay2.plane_z_order = 1;
730
731  EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1);
732  renderer_->FinishDrawingFrame(&frame1);
733  EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
734  EXPECT_FALSE(resource_provider_->InUseByConsumer(resource2));
735  SwapBuffers();
736  Mock::VerifyAndClearExpectations(&scheduler_);
737
738  EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1);
739  renderer_->FinishDrawingFrame(&frame2);
740  EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
741  EXPECT_TRUE(resource_provider_->InUseByConsumer(resource2));
742  SwapBuffers();
743  EXPECT_FALSE(resource_provider_->InUseByConsumer(resource1));
744  Mock::VerifyAndClearExpectations(&scheduler_);
745
746  EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1);
747  renderer_->FinishDrawingFrame(&frame1);
748  EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
749  EXPECT_TRUE(resource_provider_->InUseByConsumer(resource2));
750  SwapBuffers();
751  EXPECT_FALSE(resource_provider_->InUseByConsumer(resource2));
752  Mock::VerifyAndClearExpectations(&scheduler_);
753
754  // No overlays, release the resource.
755  EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0);
756  DirectRenderer::DrawingFrame frame3;
757  renderer_->set_expect_overlays(false);
758  renderer_->FinishDrawingFrame(&frame3);
759  EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
760  EXPECT_FALSE(resource_provider_->InUseByConsumer(resource2));
761  SwapBuffers();
762  EXPECT_FALSE(resource_provider_->InUseByConsumer(resource1));
763  Mock::VerifyAndClearExpectations(&scheduler_);
764
765  // Use the same buffer twice.
766  renderer_->set_expect_overlays(true);
767  EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1);
768  renderer_->FinishDrawingFrame(&frame1);
769  EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
770  SwapBuffers();
771  Mock::VerifyAndClearExpectations(&scheduler_);
772
773  EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1);
774  renderer_->FinishDrawingFrame(&frame1);
775  EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
776  SwapBuffers();
777  EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
778  Mock::VerifyAndClearExpectations(&scheduler_);
779
780  EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0);
781  renderer_->set_expect_overlays(false);
782  renderer_->FinishDrawingFrame(&frame3);
783  EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
784  SwapBuffers();
785  EXPECT_FALSE(resource_provider_->InUseByConsumer(resource1));
786  Mock::VerifyAndClearExpectations(&scheduler_);
787}
788
789}  // namespace
790}  // namespace cc
791