12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/test/pixel_test.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
71e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/command_line.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/path_service.h"
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/run_loop.h"
101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "cc/base/switches.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/output/compositor_frame_metadata.h"
1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "cc/output/copy_output_request.h"
137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "cc/output/copy_output_result.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/output/gl_renderer.h"
157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "cc/output/output_surface_client.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "cc/output/software_renderer.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/resources/resource_provider.h"
1858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "cc/resources/texture_mailbox_deleter.h"
19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "cc/test/fake_output_surface_client.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/test/paths.h"
217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "cc/test/pixel_test_output_surface.h"
227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "cc/test/pixel_test_software_output_device.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/test/pixel_test_utils.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gl/gl_implementation.h"
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "webkit/common/gpu/context_provider_in_process.h"
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace cc {
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)PixelTest::PixelTest()
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : device_viewport_size_(gfx::Size(200, 200)),
334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      disable_picture_quad_image_filtering_(false),
34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      output_surface_client_(new FakeOutputSurfaceClient) {}
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PixelTest::~PixelTest() {}
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool PixelTest::RunPixelTest(RenderPassList* pass_list,
39424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                             OffscreenContextOption provide_offscreen_context,
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             const base::FilePath& ref_file,
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             const PixelComparator& comparator) {
42b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return RunPixelTestWithReadbackTarget(pass_list,
43b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                        pass_list->back(),
44424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                        provide_offscreen_context,
45b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                        ref_file,
46b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                        comparator);
47b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
48b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
49b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool PixelTest::RunPixelTestWithReadbackTarget(
50b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    RenderPassList* pass_list,
51b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    RenderPass* target,
52424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    OffscreenContextOption provide_offscreen_context,
53b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const base::FilePath& ref_file,
54b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const PixelComparator& comparator) {
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::RunLoop run_loop;
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  target->copy_requests.push_back(CopyOutputRequest::CreateBitmapRequest(
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&PixelTest::ReadbackResult,
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this),
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 run_loop.QuitClosure())));
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
62424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_refptr<webkit::gpu::ContextProviderInProcess> offscreen_contexts;
63424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  switch (provide_offscreen_context) {
64424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case NoOffscreenContext:
65424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      break;
66424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case WithOffscreenContext:
67424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      offscreen_contexts =
68424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          webkit::gpu::ContextProviderInProcess::CreateOffscreen();
69424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      CHECK(offscreen_contexts->BindToCurrentThread());
70424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      break;
71424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
72424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
7358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  float device_scale_factor = 1.f;
74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  gfx::Rect device_viewport_rect =
75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      gfx::Rect(device_viewport_size_) + external_device_viewport_offset_;
76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  gfx::Rect device_clip_rect = external_device_clip_rect_.IsEmpty()
77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                   ? device_viewport_rect
78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                   : external_device_clip_rect_;
7958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  bool allow_partial_swap = true;
8058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  renderer_->DecideRenderPassAllocationsForFrame(*pass_list);
8258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  renderer_->DrawFrame(pass_list,
8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                       offscreen_contexts.get(),
8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                       device_scale_factor,
85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                       device_viewport_rect,
86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                       device_clip_rect,
874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                       allow_partial_swap,
884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                       disable_picture_quad_image_filtering_);
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Wait for the readback to complete.
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  resource_provider_->Finish();
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  run_loop.Run();
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return PixelsMatchReference(ref_file, comparator);
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void PixelTest::ReadbackResult(base::Closure quit_run_loop,
987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                               scoped_ptr<CopyOutputResult> result) {
997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_TRUE(result->HasBitmap());
1007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  result_bitmap_ = result->TakeBitmap().Pass();
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  quit_run_loop.Run();
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool PixelTest::PixelsMatchReference(const base::FilePath& ref_file,
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     const PixelComparator& comparator) {
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::FilePath test_data_dir;
107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!PathService::Get(CCPaths::DIR_TEST_DATA, &test_data_dir))
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // If this is false, we didn't set up a readback on a render pass.
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!result_bitmap_)
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  CommandLine* cmd = CommandLine::ForCurrentProcess();
1151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (cmd->HasSwitch(switches::kCCRebaselinePixeltests))
1161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return WritePNGFile(*result_bitmap_, test_data_dir.Append(ref_file), true);
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return MatchesPNGFile(*result_bitmap_,
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        test_data_dir.Append(ref_file),
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        comparator);
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void PixelTest::SetUpGLRenderer(bool use_skia_gpu_backend) {
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(gfx::InitializeGLBindings(gfx::kGLImplementationOSMesaGL));
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  using webkit::gpu::ContextProviderInProcess;
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  output_surface_.reset(new PixelTestOutputSurface(
1283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      ContextProviderInProcess::CreateOffscreen()));
129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  output_surface_->BindToClient(output_surface_client_.get());
1307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
131d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  resource_provider_ =
1320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      ResourceProvider::Create(output_surface_.get(), NULL, 0, false, 1);
13358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
13458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  texture_mailbox_deleter_ = make_scoped_ptr(new TextureMailboxDeleter);
13558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  renderer_ = GLRenderer::Create(this,
13758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                 &settings_,
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 output_surface_.get(),
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 resource_provider_.get(),
14058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                 texture_mailbox_deleter_.get(),
141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                 0).PassAs<DirectRenderer>();
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void PixelTest::ForceExpandedViewport(gfx::Size surface_expansion) {
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  static_cast<PixelTestOutputSurface*>(output_surface_.get())
1467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      ->set_surface_expansion_size(surface_expansion);
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SoftwareOutputDevice* device = output_surface_->software_device();
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (device) {
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    static_cast<PixelTestSoftwareOutputDevice*>(device)
1507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        ->set_surface_expansion_size(surface_expansion);
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void PixelTest::ForceViewportOffset(gfx::Vector2d viewport_offset) {
155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  external_device_viewport_offset_ = viewport_offset;
156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
15858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void PixelTest::ForceDeviceClip(gfx::Rect clip) {
159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  external_device_clip_rect_ = clip;
16058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
16158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
162fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdochvoid PixelTest::EnableExternalStencilTest() {
16358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  static_cast<PixelTestOutputSurface*>(output_surface_.get())
16458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      ->set_has_external_stencil_test(true);
165fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch}
166fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void PixelTest::SetUpSoftwareRenderer() {
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<SoftwareOutputDevice> device(new PixelTestSoftwareOutputDevice());
169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  output_surface_.reset(new PixelTestOutputSurface(device.Pass()));
170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  output_surface_->BindToClient(output_surface_client_.get());
171d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  resource_provider_ =
1720f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      ResourceProvider::Create(output_surface_.get(), NULL, 0, false, 1);
173a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  renderer_ = SoftwareRenderer::Create(
174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      this, &settings_, output_surface_.get(), resource_provider_.get())
175a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                  .PassAs<DirectRenderer>();
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace cc
179