Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / cc / test / layer_tree_pixel_test.cc
1 // Copyright 2013 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/test/layer_tree_pixel_test.h"
6
7 #include "base/command_line.h"
8 #include "base/path_service.h"
9 #include "cc/base/switches.h"
10 #include "cc/layers/solid_color_layer.h"
11 #include "cc/layers/texture_layer.h"
12 #include "cc/output/copy_output_request.h"
13 #include "cc/output/copy_output_result.h"
14 #include "cc/resources/texture_mailbox.h"
15 #include "cc/test/paths.h"
16 #include "cc/test/pixel_comparator.h"
17 #include "cc/test/pixel_test_output_surface.h"
18 #include "cc/test/pixel_test_software_output_device.h"
19 #include "cc/test/pixel_test_utils.h"
20 #include "cc/test/test_in_process_context_provider.h"
21 #include "cc/trees/layer_tree_impl.h"
22 #include "gpu/command_buffer/client/gl_in_process_context.h"
23 #include "gpu/command_buffer/client/gles2_implementation.h"
24
25 using gpu::gles2::GLES2Interface;
26
27 namespace cc {
28
29 LayerTreePixelTest::LayerTreePixelTest()
30     : pixel_comparator_(new ExactPixelComparator(true)),
31       test_type_(GL_WITH_DEFAULT),
32       pending_texture_mailbox_callbacks_(0),
33       impl_side_painting_(true) {}
34
35 LayerTreePixelTest::~LayerTreePixelTest() {}
36
37 scoped_ptr<OutputSurface> LayerTreePixelTest::CreateOutputSurface(
38     bool fallback) {
39   gfx::Size surface_expansion_size(40, 60);
40   scoped_ptr<PixelTestOutputSurface> output_surface;
41
42   switch (test_type_) {
43     case SOFTWARE_WITH_DEFAULT:
44     case SOFTWARE_WITH_BITMAP: {
45       scoped_ptr<PixelTestSoftwareOutputDevice> software_output_device(
46           new PixelTestSoftwareOutputDevice);
47       software_output_device->set_surface_expansion_size(
48           surface_expansion_size);
49       output_surface = make_scoped_ptr(
50           new PixelTestOutputSurface(
51               software_output_device.PassAs<SoftwareOutputDevice>()));
52       break;
53     }
54
55     case GL_WITH_DEFAULT:
56     case GL_WITH_BITMAP: {
57       output_surface = make_scoped_ptr(
58           new PixelTestOutputSurface(new TestInProcessContextProvider));
59       break;
60     }
61   }
62
63   output_surface->set_surface_expansion_size(surface_expansion_size);
64   return output_surface.PassAs<OutputSurface>();
65 }
66
67 scoped_refptr<ContextProvider> LayerTreePixelTest::OffscreenContextProvider() {
68   return scoped_refptr<ContextProvider>(new TestInProcessContextProvider);
69 }
70
71 void LayerTreePixelTest::CommitCompleteOnThread(LayerTreeHostImpl* impl) {
72   LayerTreeImpl* commit_tree =
73       impl->pending_tree() ? impl->pending_tree() : impl->active_tree();
74   if (commit_tree->source_frame_number() != 0)
75     return;
76
77   gfx::Rect viewport = impl->DeviceViewport();
78   // The viewport has a 0,0 origin without external influence.
79   EXPECT_EQ(gfx::Point().ToString(), viewport.origin().ToString());
80   // Be that influence!
81   viewport += gfx::Vector2d(20, 10);
82   impl->SetExternalDrawConstraints(gfx::Transform(), viewport, viewport, true);
83   EXPECT_EQ(viewport.ToString(), impl->DeviceViewport().ToString());
84 }
85
86 scoped_ptr<CopyOutputRequest> LayerTreePixelTest::CreateCopyOutputRequest() {
87   return CopyOutputRequest::CreateBitmapRequest(
88       base::Bind(&LayerTreePixelTest::ReadbackResult, base::Unretained(this)));
89 }
90
91 void LayerTreePixelTest::ReadbackResult(scoped_ptr<CopyOutputResult> result) {
92   ASSERT_TRUE(result->HasBitmap());
93   result_bitmap_ = result->TakeBitmap().Pass();
94   EndTest();
95 }
96
97 void LayerTreePixelTest::BeginTest() {
98   Layer* target = readback_target_ ? readback_target_
99                                    : layer_tree_host()->root_layer();
100   target->RequestCopyOfOutput(CreateCopyOutputRequest().Pass());
101   PostSetNeedsCommitToMainThread();
102 }
103
104 void LayerTreePixelTest::AfterTest() {
105   base::FilePath test_data_dir;
106   EXPECT_TRUE(PathService::Get(CCPaths::DIR_TEST_DATA, &test_data_dir));
107   base::FilePath ref_file_path = test_data_dir.Append(ref_file_);
108
109   CommandLine* cmd = CommandLine::ForCurrentProcess();
110   if (cmd->HasSwitch(switches::kCCRebaselinePixeltests))
111     EXPECT_TRUE(WritePNGFile(*result_bitmap_, ref_file_path, true));
112
113   EXPECT_TRUE(MatchesPNGFile(*result_bitmap_,
114                              ref_file_path,
115                              *pixel_comparator_));
116 }
117
118 scoped_refptr<SolidColorLayer> LayerTreePixelTest::CreateSolidColorLayer(
119     const gfx::Rect& rect, SkColor color) {
120   scoped_refptr<SolidColorLayer> layer = SolidColorLayer::Create();
121   layer->SetIsDrawable(true);
122   layer->SetAnchorPoint(gfx::PointF());
123   layer->SetBounds(rect.size());
124   layer->SetPosition(rect.origin());
125   layer->SetBackgroundColor(color);
126   return layer;
127 }
128
129 void LayerTreePixelTest::EndTest() {
130   // Drop TextureMailboxes on the main thread so that they can be cleaned up and
131   // the pending callbacks will fire.
132   for (size_t i = 0; i < texture_layers_.size(); ++i) {
133     texture_layers_[i]->SetTextureMailbox(TextureMailbox(),
134                                           scoped_ptr<SingleReleaseCallback>());
135   }
136
137   TryEndTest();
138 }
139
140 void LayerTreePixelTest::TryEndTest() {
141   if (!result_bitmap_)
142     return;
143   if (pending_texture_mailbox_callbacks_)
144     return;
145   LayerTreeTest::EndTest();
146 }
147
148 scoped_refptr<SolidColorLayer> LayerTreePixelTest::
149     CreateSolidColorLayerWithBorder(
150         const gfx::Rect& rect, SkColor color,
151         int border_width, SkColor border_color) {
152   scoped_refptr<SolidColorLayer> layer = CreateSolidColorLayer(rect, color);
153   scoped_refptr<SolidColorLayer> border_top = CreateSolidColorLayer(
154       gfx::Rect(0, 0, rect.width(), border_width), border_color);
155   scoped_refptr<SolidColorLayer> border_left = CreateSolidColorLayer(
156       gfx::Rect(0,
157                 border_width,
158                 border_width,
159                 rect.height() - border_width * 2),
160       border_color);
161   scoped_refptr<SolidColorLayer> border_right =
162       CreateSolidColorLayer(gfx::Rect(rect.width() - border_width,
163                                       border_width,
164                                       border_width,
165                                       rect.height() - border_width * 2),
166                             border_color);
167   scoped_refptr<SolidColorLayer> border_bottom = CreateSolidColorLayer(
168       gfx::Rect(0, rect.height() - border_width, rect.width(), border_width),
169       border_color);
170   layer->AddChild(border_top);
171   layer->AddChild(border_left);
172   layer->AddChild(border_right);
173   layer->AddChild(border_bottom);
174   return layer;
175 }
176
177 scoped_refptr<TextureLayer> LayerTreePixelTest::CreateTextureLayer(
178     const gfx::Rect& rect, const SkBitmap& bitmap) {
179   scoped_refptr<TextureLayer> layer = TextureLayer::CreateForMailbox(NULL);
180   layer->SetIsDrawable(true);
181   layer->SetAnchorPoint(gfx::PointF());
182   layer->SetBounds(rect.size());
183   layer->SetPosition(rect.origin());
184
185   TextureMailbox texture_mailbox;
186   scoped_ptr<SingleReleaseCallback> release_callback;
187   CopyBitmapToTextureMailboxAsTexture(
188       bitmap, &texture_mailbox, &release_callback);
189   layer->SetTextureMailbox(texture_mailbox, release_callback.Pass());
190
191   texture_layers_.push_back(layer);
192   pending_texture_mailbox_callbacks_++;
193   return layer;
194 }
195
196 void LayerTreePixelTest::RunPixelTest(
197     PixelTestType test_type,
198     scoped_refptr<Layer> content_root,
199     base::FilePath file_name) {
200   test_type_ = test_type;
201   content_root_ = content_root;
202   readback_target_ = NULL;
203   ref_file_ = file_name;
204   RunTest(true, false, impl_side_painting_);
205 }
206
207 void LayerTreePixelTest::RunPixelTestWithReadbackTarget(
208     PixelTestType test_type,
209     scoped_refptr<Layer> content_root,
210     Layer* target,
211     base::FilePath file_name) {
212   test_type_ = test_type;
213   content_root_ = content_root;
214   readback_target_ = target;
215   ref_file_ = file_name;
216   RunTest(true, false, impl_side_painting_);
217 }
218
219 void LayerTreePixelTest::SetupTree() {
220   scoped_refptr<Layer> root = Layer::Create();
221   root->SetBounds(content_root_->bounds());
222   root->AddChild(content_root_);
223   layer_tree_host()->SetRootLayer(root);
224   LayerTreeTest::SetupTree();
225 }
226
227 scoped_ptr<SkBitmap> LayerTreePixelTest::CopyTextureMailboxToBitmap(
228     const gfx::Size& size,
229     const TextureMailbox& texture_mailbox) {
230   DCHECK(texture_mailbox.IsTexture());
231   if (!texture_mailbox.IsTexture())
232     return scoped_ptr<SkBitmap>();
233
234   scoped_ptr<gpu::GLInProcessContext> context = CreateTestInProcessContext();
235   GLES2Interface* gl = context->GetImplementation();
236
237   if (texture_mailbox.sync_point())
238     gl->WaitSyncPointCHROMIUM(texture_mailbox.sync_point());
239
240   GLuint texture_id = 0;
241   gl->GenTextures(1, &texture_id);
242   gl->BindTexture(GL_TEXTURE_2D, texture_id);
243   gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
244   gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
245   gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
246   gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
247   gl->ConsumeTextureCHROMIUM(texture_mailbox.target(), texture_mailbox.name());
248   gl->BindTexture(GL_TEXTURE_2D, 0);
249
250   GLuint fbo = 0;
251   gl->GenFramebuffers(1, &fbo);
252   gl->BindFramebuffer(GL_FRAMEBUFFER, fbo);
253   gl->FramebufferTexture2D(
254       GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_id, 0);
255   EXPECT_EQ(static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE),
256             gl->CheckFramebufferStatus(GL_FRAMEBUFFER));
257
258   scoped_ptr<uint8[]> pixels(new uint8[size.GetArea() * 4]);
259   gl->ReadPixels(0,
260                  0,
261                  size.width(),
262                  size.height(),
263                  GL_RGBA,
264                  GL_UNSIGNED_BYTE,
265                  pixels.get());
266
267   gl->DeleteFramebuffers(1, &fbo);
268   gl->DeleteTextures(1, &texture_id);
269
270   scoped_ptr<SkBitmap> bitmap(new SkBitmap);
271   bitmap->setConfig(SkBitmap::kARGB_8888_Config,
272                     size.width(),
273                     size.height());
274   bitmap->allocPixels();
275
276   scoped_ptr<SkAutoLockPixels> lock(new SkAutoLockPixels(*bitmap));
277   uint8* out_pixels = static_cast<uint8*>(bitmap->getPixels());
278
279   size_t row_bytes = size.width() * 4;
280   size_t total_bytes = size.height() * row_bytes;
281   for (size_t dest_y = 0; dest_y < total_bytes; dest_y += row_bytes) {
282     // Flip Y axis.
283     size_t src_y = total_bytes - dest_y - row_bytes;
284     // Swizzle OpenGL -> Skia byte order.
285     for (size_t x = 0; x < row_bytes; x += 4) {
286       out_pixels[dest_y + x + SK_R32_SHIFT/8] = pixels.get()[src_y + x + 0];
287       out_pixels[dest_y + x + SK_G32_SHIFT/8] = pixels.get()[src_y + x + 1];
288       out_pixels[dest_y + x + SK_B32_SHIFT/8] = pixels.get()[src_y + x + 2];
289       out_pixels[dest_y + x + SK_A32_SHIFT/8] = pixels.get()[src_y + x + 3];
290     }
291   }
292
293   return bitmap.Pass();
294 }
295
296 void LayerTreePixelTest::ReleaseTextureMailbox(
297     scoped_ptr<gpu::GLInProcessContext> context,
298     uint32 texture,
299     uint32 sync_point,
300     bool lost_resource) {
301   GLES2Interface* gl = context->GetImplementation();
302   if (sync_point)
303     gl->WaitSyncPointCHROMIUM(sync_point);
304   gl->DeleteTextures(1, &texture);
305   pending_texture_mailbox_callbacks_--;
306   TryEndTest();
307 }
308
309 void LayerTreePixelTest::CopyBitmapToTextureMailboxAsTexture(
310     const SkBitmap& bitmap,
311     TextureMailbox* texture_mailbox,
312     scoped_ptr<SingleReleaseCallback>* release_callback) {
313   DCHECK_GT(bitmap.width(), 0);
314   DCHECK_GT(bitmap.height(), 0);
315
316   scoped_ptr<gpu::GLInProcessContext> context = CreateTestInProcessContext();
317   GLES2Interface* gl = context->GetImplementation();
318
319   GLuint texture_id = 0;
320   gl->GenTextures(1, &texture_id);
321   gl->BindTexture(GL_TEXTURE_2D, texture_id);
322   gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
323   gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
324   gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
325   gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
326
327   DCHECK_EQ(SkBitmap::kARGB_8888_Config, bitmap.getConfig());
328
329   {
330     SkAutoLockPixels lock(bitmap);
331
332     size_t row_bytes = bitmap.width() * 4;
333     size_t total_bytes = bitmap.height() * row_bytes;
334
335     scoped_ptr<uint8[]> gl_pixels(new uint8[total_bytes]);
336     uint8* bitmap_pixels = static_cast<uint8*>(bitmap.getPixels());
337
338     for (size_t y = 0; y < total_bytes; y += row_bytes) {
339       // Flip Y axis.
340       size_t src_y = total_bytes - y - row_bytes;
341       // Swizzle Skia -> OpenGL byte order.
342       for (size_t x = 0; x < row_bytes; x += 4) {
343         gl_pixels.get()[y + x + 0] = bitmap_pixels[src_y + x + SK_R32_SHIFT/8];
344         gl_pixels.get()[y + x + 1] = bitmap_pixels[src_y + x + SK_G32_SHIFT/8];
345         gl_pixels.get()[y + x + 2] = bitmap_pixels[src_y + x + SK_B32_SHIFT/8];
346         gl_pixels.get()[y + x + 3] = bitmap_pixels[src_y + x + SK_A32_SHIFT/8];
347       }
348     }
349
350     gl->TexImage2D(GL_TEXTURE_2D,
351                    0,
352                    GL_RGBA,
353                    bitmap.width(),
354                    bitmap.height(),
355                    0,
356                    GL_RGBA,
357                    GL_UNSIGNED_BYTE,
358                    gl_pixels.get());
359   }
360
361   gpu::Mailbox mailbox;
362   gl->GenMailboxCHROMIUM(mailbox.name);
363   gl->ProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
364   gl->BindTexture(GL_TEXTURE_2D, 0);
365   uint32 sync_point = gl->InsertSyncPointCHROMIUM();
366
367   *texture_mailbox = TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point);
368   *release_callback = SingleReleaseCallback::Create(
369       base::Bind(&LayerTreePixelTest::ReleaseTextureMailbox,
370                  base::Unretained(this),
371                  base::Passed(&context),
372                  texture_id));
373 }
374
375 }  // namespace cc