Infer appropriate GNU_STACK alignment for a shared library.
[chromium-blink-merge.git] / cc / test / layer_tree_pixel_test.cc
blob8a053fabb188072b989688452edd8d905168f1b4
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.
5 #include "cc/test/layer_tree_pixel_test.h"
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"
25 using gpu::gles2::GLES2Interface;
27 namespace cc {
29 LayerTreePixelTest::LayerTreePixelTest()
30 : pixel_comparator_(new ExactPixelComparator(true)),
31 test_type_(PIXEL_TEST_GL),
32 pending_texture_mailbox_callbacks_(0),
33 impl_side_painting_(true) {
36 LayerTreePixelTest::~LayerTreePixelTest() {}
38 scoped_ptr<OutputSurface> LayerTreePixelTest::CreateOutputSurface() {
39 gfx::Size surface_expansion_size(40, 60);
40 scoped_ptr<PixelTestOutputSurface> output_surface;
42 switch (test_type_) {
43 case PIXEL_TEST_SOFTWARE: {
44 scoped_ptr<PixelTestSoftwareOutputDevice> software_output_device(
45 new PixelTestSoftwareOutputDevice);
46 software_output_device->set_surface_expansion_size(
47 surface_expansion_size);
48 output_surface = make_scoped_ptr(
49 new PixelTestOutputSurface(software_output_device.Pass()));
50 break;
52 case PIXEL_TEST_GL: {
53 bool flipped_output_surface = false;
54 output_surface = make_scoped_ptr(new PixelTestOutputSurface(
55 new TestInProcessContextProvider, flipped_output_surface));
56 break;
60 output_surface->set_surface_expansion_size(surface_expansion_size);
61 return output_surface.Pass();
64 void LayerTreePixelTest::CommitCompleteOnThread(LayerTreeHostImpl* impl) {
65 LayerTreeImpl* commit_tree =
66 impl->pending_tree() ? impl->pending_tree() : impl->active_tree();
67 if (commit_tree->source_frame_number() != 0)
68 return;
70 gfx::Rect viewport = impl->DeviceViewport();
71 // The viewport has a 0,0 origin without external influence.
72 EXPECT_EQ(gfx::Point().ToString(), viewport.origin().ToString());
73 // Be that influence!
74 viewport += gfx::Vector2d(20, 10);
75 bool resourceless_software_draw = false;
76 gfx::Transform identity = gfx::Transform();
77 impl->SetExternalDrawConstraints(identity,
78 viewport,
79 viewport,
80 viewport,
81 identity,
82 resourceless_software_draw);
83 EXPECT_EQ(viewport.ToString(), impl->DeviceViewport().ToString());
86 scoped_ptr<CopyOutputRequest> LayerTreePixelTest::CreateCopyOutputRequest() {
87 return CopyOutputRequest::CreateBitmapRequest(
88 base::Bind(&LayerTreePixelTest::ReadbackResult, base::Unretained(this)));
91 void LayerTreePixelTest::ReadbackResult(scoped_ptr<CopyOutputResult> result) {
92 ASSERT_TRUE(result->HasBitmap());
93 result_bitmap_ = result->TakeBitmap().Pass();
94 EndTest();
97 void LayerTreePixelTest::BeginTest() {
98 Layer* target = readback_target_ ? readback_target_
99 : layer_tree_host()->root_layer();
100 target->RequestCopyOfOutput(CreateCopyOutputRequest().Pass());
101 PostSetNeedsCommitToMainThread();
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_);
109 base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
110 if (cmd->HasSwitch(switches::kCCRebaselinePixeltests))
111 EXPECT_TRUE(WritePNGFile(*result_bitmap_, ref_file_path, true));
112 EXPECT_TRUE(MatchesPNGFile(*result_bitmap_,
113 ref_file_path,
114 *pixel_comparator_));
117 scoped_refptr<SolidColorLayer> LayerTreePixelTest::CreateSolidColorLayer(
118 const gfx::Rect& rect, SkColor color) {
119 scoped_refptr<SolidColorLayer> layer = SolidColorLayer::Create();
120 layer->SetIsDrawable(true);
121 layer->SetBounds(rect.size());
122 layer->SetPosition(rect.origin());
123 layer->SetBackgroundColor(color);
124 return layer;
127 void LayerTreePixelTest::EndTest() {
128 // Drop TextureMailboxes on the main thread so that they can be cleaned up and
129 // the pending callbacks will fire.
130 for (size_t i = 0; i < texture_layers_.size(); ++i) {
131 texture_layers_[i]->SetTextureMailbox(TextureMailbox(), nullptr);
134 TryEndTest();
137 void LayerTreePixelTest::TryEndTest() {
138 if (!result_bitmap_)
139 return;
140 if (pending_texture_mailbox_callbacks_)
141 return;
142 LayerTreeTest::EndTest();
145 scoped_refptr<SolidColorLayer> LayerTreePixelTest::
146 CreateSolidColorLayerWithBorder(
147 const gfx::Rect& rect, SkColor color,
148 int border_width, SkColor border_color) {
149 scoped_refptr<SolidColorLayer> layer = CreateSolidColorLayer(rect, color);
150 scoped_refptr<SolidColorLayer> border_top = CreateSolidColorLayer(
151 gfx::Rect(0, 0, rect.width(), border_width), border_color);
152 scoped_refptr<SolidColorLayer> border_left = CreateSolidColorLayer(
153 gfx::Rect(0,
154 border_width,
155 border_width,
156 rect.height() - border_width * 2),
157 border_color);
158 scoped_refptr<SolidColorLayer> border_right =
159 CreateSolidColorLayer(gfx::Rect(rect.width() - border_width,
160 border_width,
161 border_width,
162 rect.height() - border_width * 2),
163 border_color);
164 scoped_refptr<SolidColorLayer> border_bottom = CreateSolidColorLayer(
165 gfx::Rect(0, rect.height() - border_width, rect.width(), border_width),
166 border_color);
167 layer->AddChild(border_top);
168 layer->AddChild(border_left);
169 layer->AddChild(border_right);
170 layer->AddChild(border_bottom);
171 return layer;
174 scoped_refptr<TextureLayer> LayerTreePixelTest::CreateTextureLayer(
175 const gfx::Rect& rect, const SkBitmap& bitmap) {
176 scoped_refptr<TextureLayer> layer = TextureLayer::CreateForMailbox(NULL);
177 layer->SetIsDrawable(true);
178 layer->SetBounds(rect.size());
179 layer->SetPosition(rect.origin());
181 TextureMailbox texture_mailbox;
182 scoped_ptr<SingleReleaseCallback> release_callback;
183 CopyBitmapToTextureMailboxAsTexture(
184 bitmap, &texture_mailbox, &release_callback);
185 layer->SetTextureMailbox(texture_mailbox, release_callback.Pass());
187 texture_layers_.push_back(layer);
188 pending_texture_mailbox_callbacks_++;
189 return layer;
192 void LayerTreePixelTest::RunPixelTest(
193 PixelTestType test_type,
194 scoped_refptr<Layer> content_root,
195 base::FilePath file_name) {
196 test_type_ = test_type;
197 content_root_ = content_root;
198 readback_target_ = NULL;
199 ref_file_ = file_name;
200 bool threaded = true;
201 RunTest(threaded, false, impl_side_painting_);
204 void LayerTreePixelTest::RunSingleThreadedPixelTest(
205 PixelTestType test_type,
206 scoped_refptr<Layer> content_root,
207 base::FilePath file_name) {
208 test_type_ = test_type;
209 content_root_ = content_root;
210 readback_target_ = NULL;
211 ref_file_ = file_name;
212 bool threaded = false;
213 RunTest(threaded, false, impl_side_painting_);
216 void LayerTreePixelTest::RunPixelTestWithReadbackTarget(
217 PixelTestType test_type,
218 scoped_refptr<Layer> content_root,
219 Layer* target,
220 base::FilePath file_name) {
221 test_type_ = test_type;
222 content_root_ = content_root;
223 readback_target_ = target;
224 ref_file_ = file_name;
225 RunTest(true, false, impl_side_painting_);
228 void LayerTreePixelTest::SetupTree() {
229 scoped_refptr<Layer> root = Layer::Create();
230 root->SetBounds(content_root_->bounds());
231 root->AddChild(content_root_);
232 layer_tree_host()->SetRootLayer(root);
233 LayerTreeTest::SetupTree();
236 scoped_ptr<SkBitmap> LayerTreePixelTest::CopyTextureMailboxToBitmap(
237 const gfx::Size& size,
238 const TextureMailbox& texture_mailbox) {
239 DCHECK(texture_mailbox.IsTexture());
240 if (!texture_mailbox.IsTexture())
241 return nullptr;
243 scoped_ptr<gpu::GLInProcessContext> context = CreateTestInProcessContext();
244 GLES2Interface* gl = context->GetImplementation();
246 if (texture_mailbox.sync_point())
247 gl->WaitSyncPointCHROMIUM(texture_mailbox.sync_point());
249 GLuint texture_id = 0;
250 gl->GenTextures(1, &texture_id);
251 gl->BindTexture(GL_TEXTURE_2D, texture_id);
252 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
253 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
254 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
255 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
256 gl->ConsumeTextureCHROMIUM(texture_mailbox.target(), texture_mailbox.name());
257 gl->BindTexture(GL_TEXTURE_2D, 0);
259 GLuint fbo = 0;
260 gl->GenFramebuffers(1, &fbo);
261 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo);
262 gl->FramebufferTexture2D(
263 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_id, 0);
264 EXPECT_EQ(static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE),
265 gl->CheckFramebufferStatus(GL_FRAMEBUFFER));
267 scoped_ptr<uint8[]> pixels(new uint8[size.GetArea() * 4]);
268 gl->ReadPixels(0,
270 size.width(),
271 size.height(),
272 GL_RGBA,
273 GL_UNSIGNED_BYTE,
274 pixels.get());
276 gl->DeleteFramebuffers(1, &fbo);
277 gl->DeleteTextures(1, &texture_id);
279 scoped_ptr<SkBitmap> bitmap(new SkBitmap);
280 bitmap->allocN32Pixels(size.width(), size.height());
282 uint8* out_pixels = static_cast<uint8*>(bitmap->getPixels());
284 size_t row_bytes = size.width() * 4;
285 size_t total_bytes = size.height() * row_bytes;
286 for (size_t dest_y = 0; dest_y < total_bytes; dest_y += row_bytes) {
287 // Flip Y axis.
288 size_t src_y = total_bytes - dest_y - row_bytes;
289 // Swizzle OpenGL -> Skia byte order.
290 for (size_t x = 0; x < row_bytes; x += 4) {
291 out_pixels[dest_y + x + SK_R32_SHIFT/8] = pixels.get()[src_y + x + 0];
292 out_pixels[dest_y + x + SK_G32_SHIFT/8] = pixels.get()[src_y + x + 1];
293 out_pixels[dest_y + x + SK_B32_SHIFT/8] = pixels.get()[src_y + x + 2];
294 out_pixels[dest_y + x + SK_A32_SHIFT/8] = pixels.get()[src_y + x + 3];
298 return bitmap.Pass();
301 void LayerTreePixelTest::ReleaseTextureMailbox(
302 scoped_ptr<gpu::GLInProcessContext> context,
303 uint32 texture,
304 uint32 sync_point,
305 bool lost_resource) {
306 GLES2Interface* gl = context->GetImplementation();
307 if (sync_point)
308 gl->WaitSyncPointCHROMIUM(sync_point);
309 gl->DeleteTextures(1, &texture);
310 pending_texture_mailbox_callbacks_--;
311 TryEndTest();
314 void LayerTreePixelTest::CopyBitmapToTextureMailboxAsTexture(
315 const SkBitmap& bitmap,
316 TextureMailbox* texture_mailbox,
317 scoped_ptr<SingleReleaseCallback>* release_callback) {
318 DCHECK_GT(bitmap.width(), 0);
319 DCHECK_GT(bitmap.height(), 0);
321 scoped_ptr<gpu::GLInProcessContext> context = CreateTestInProcessContext();
322 GLES2Interface* gl = context->GetImplementation();
324 GLuint texture_id = 0;
325 gl->GenTextures(1, &texture_id);
326 gl->BindTexture(GL_TEXTURE_2D, texture_id);
327 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
328 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
329 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
330 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
332 DCHECK_EQ(kN32_SkColorType, bitmap.colorType());
335 SkAutoLockPixels lock(bitmap);
337 size_t row_bytes = bitmap.width() * 4;
338 size_t total_bytes = bitmap.height() * row_bytes;
340 scoped_ptr<uint8[]> gl_pixels(new uint8[total_bytes]);
341 uint8* bitmap_pixels = static_cast<uint8*>(bitmap.getPixels());
343 for (size_t y = 0; y < total_bytes; y += row_bytes) {
344 // Flip Y axis.
345 size_t src_y = total_bytes - y - row_bytes;
346 // Swizzle Skia -> OpenGL byte order.
347 for (size_t x = 0; x < row_bytes; x += 4) {
348 gl_pixels.get()[y + x + 0] = bitmap_pixels[src_y + x + SK_R32_SHIFT/8];
349 gl_pixels.get()[y + x + 1] = bitmap_pixels[src_y + x + SK_G32_SHIFT/8];
350 gl_pixels.get()[y + x + 2] = bitmap_pixels[src_y + x + SK_B32_SHIFT/8];
351 gl_pixels.get()[y + x + 3] = bitmap_pixels[src_y + x + SK_A32_SHIFT/8];
355 gl->TexImage2D(GL_TEXTURE_2D,
357 GL_RGBA,
358 bitmap.width(),
359 bitmap.height(),
361 GL_RGBA,
362 GL_UNSIGNED_BYTE,
363 gl_pixels.get());
366 gpu::Mailbox mailbox;
367 gl->GenMailboxCHROMIUM(mailbox.name);
368 gl->ProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
369 gl->BindTexture(GL_TEXTURE_2D, 0);
370 uint32 sync_point = gl->InsertSyncPointCHROMIUM();
372 *texture_mailbox = TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point);
373 *release_callback = SingleReleaseCallback::Create(
374 base::Bind(&LayerTreePixelTest::ReleaseTextureMailbox,
375 base::Unretained(this),
376 base::Passed(&context),
377 texture_id));
380 } // namespace cc