Lots of random cleanups, mostly for native_theme_win.cc:
[chromium-blink-merge.git] / cc / test / layer_tree_pixel_test.cc
blobcbb936bea2c534ae47ebf6231c7946158b2d7049
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_(GL_WITH_DEFAULT),
32 pending_texture_mailbox_callbacks_(0),
33 impl_side_painting_(true) {}
35 LayerTreePixelTest::~LayerTreePixelTest() {}
37 scoped_ptr<OutputSurface> LayerTreePixelTest::CreateOutputSurface(
38 bool fallback) {
39 gfx::Size surface_expansion_size(40, 60);
40 scoped_ptr<PixelTestOutputSurface> output_surface;
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;
55 case GL_WITH_DEFAULT:
56 case GL_WITH_BITMAP: {
57 output_surface = make_scoped_ptr(
58 new PixelTestOutputSurface(new TestInProcessContextProvider));
59 break;
63 output_surface->set_surface_expansion_size(surface_expansion_size);
64 return output_surface.PassAs<OutputSurface>();
67 void LayerTreePixelTest::CommitCompleteOnThread(LayerTreeHostImpl* impl) {
68 LayerTreeImpl* commit_tree =
69 impl->pending_tree() ? impl->pending_tree() : impl->active_tree();
70 if (commit_tree->source_frame_number() != 0)
71 return;
73 gfx::Rect viewport = impl->DeviceViewport();
74 // The viewport has a 0,0 origin without external influence.
75 EXPECT_EQ(gfx::Point().ToString(), viewport.origin().ToString());
76 // Be that influence!
77 viewport += gfx::Vector2d(20, 10);
78 bool resourceless_software_draw = false;
79 impl->SetExternalDrawConstraints(
80 gfx::Transform(), viewport, viewport, resourceless_software_draw);
81 EXPECT_EQ(viewport.ToString(), impl->DeviceViewport().ToString());
84 scoped_ptr<CopyOutputRequest> LayerTreePixelTest::CreateCopyOutputRequest() {
85 return CopyOutputRequest::CreateBitmapRequest(
86 base::Bind(&LayerTreePixelTest::ReadbackResult, base::Unretained(this)));
89 void LayerTreePixelTest::ReadbackResult(scoped_ptr<CopyOutputResult> result) {
90 ASSERT_TRUE(result->HasBitmap());
91 result_bitmap_ = result->TakeBitmap().Pass();
92 EndTest();
95 void LayerTreePixelTest::BeginTest() {
96 Layer* target = readback_target_ ? readback_target_
97 : layer_tree_host()->root_layer();
98 target->RequestCopyOfOutput(CreateCopyOutputRequest().Pass());
99 PostSetNeedsCommitToMainThread();
102 void LayerTreePixelTest::AfterTest() {
103 base::FilePath test_data_dir;
104 EXPECT_TRUE(PathService::Get(CCPaths::DIR_TEST_DATA, &test_data_dir));
105 base::FilePath ref_file_path = test_data_dir.Append(ref_file_);
107 CommandLine* cmd = CommandLine::ForCurrentProcess();
108 if (cmd->HasSwitch(switches::kCCRebaselinePixeltests))
109 EXPECT_TRUE(WritePNGFile(*result_bitmap_, ref_file_path, true));
110 EXPECT_TRUE(MatchesPNGFile(*result_bitmap_,
111 ref_file_path,
112 *pixel_comparator_));
115 scoped_refptr<SolidColorLayer> LayerTreePixelTest::CreateSolidColorLayer(
116 const gfx::Rect& rect, SkColor color) {
117 scoped_refptr<SolidColorLayer> layer = SolidColorLayer::Create();
118 layer->SetIsDrawable(true);
119 layer->SetBounds(rect.size());
120 layer->SetPosition(rect.origin());
121 layer->SetBackgroundColor(color);
122 return layer;
125 void LayerTreePixelTest::EndTest() {
126 // Drop TextureMailboxes on the main thread so that they can be cleaned up and
127 // the pending callbacks will fire.
128 for (size_t i = 0; i < texture_layers_.size(); ++i) {
129 texture_layers_[i]->SetTextureMailbox(TextureMailbox(),
130 scoped_ptr<SingleReleaseCallback>());
133 TryEndTest();
136 void LayerTreePixelTest::TryEndTest() {
137 if (!result_bitmap_)
138 return;
139 if (pending_texture_mailbox_callbacks_)
140 return;
141 LayerTreeTest::EndTest();
144 scoped_refptr<SolidColorLayer> LayerTreePixelTest::
145 CreateSolidColorLayerWithBorder(
146 const gfx::Rect& rect, SkColor color,
147 int border_width, SkColor border_color) {
148 scoped_refptr<SolidColorLayer> layer = CreateSolidColorLayer(rect, color);
149 scoped_refptr<SolidColorLayer> border_top = CreateSolidColorLayer(
150 gfx::Rect(0, 0, rect.width(), border_width), border_color);
151 scoped_refptr<SolidColorLayer> border_left = CreateSolidColorLayer(
152 gfx::Rect(0,
153 border_width,
154 border_width,
155 rect.height() - border_width * 2),
156 border_color);
157 scoped_refptr<SolidColorLayer> border_right =
158 CreateSolidColorLayer(gfx::Rect(rect.width() - border_width,
159 border_width,
160 border_width,
161 rect.height() - border_width * 2),
162 border_color);
163 scoped_refptr<SolidColorLayer> border_bottom = CreateSolidColorLayer(
164 gfx::Rect(0, rect.height() - border_width, rect.width(), border_width),
165 border_color);
166 layer->AddChild(border_top);
167 layer->AddChild(border_left);
168 layer->AddChild(border_right);
169 layer->AddChild(border_bottom);
170 return layer;
173 scoped_refptr<TextureLayer> LayerTreePixelTest::CreateTextureLayer(
174 const gfx::Rect& rect, const SkBitmap& bitmap) {
175 scoped_refptr<TextureLayer> layer = TextureLayer::CreateForMailbox(NULL);
176 layer->SetIsDrawable(true);
177 layer->SetBounds(rect.size());
178 layer->SetPosition(rect.origin());
180 TextureMailbox texture_mailbox;
181 scoped_ptr<SingleReleaseCallback> release_callback;
182 CopyBitmapToTextureMailboxAsTexture(
183 bitmap, &texture_mailbox, &release_callback);
184 layer->SetTextureMailbox(texture_mailbox, release_callback.Pass());
186 texture_layers_.push_back(layer);
187 pending_texture_mailbox_callbacks_++;
188 return layer;
191 void LayerTreePixelTest::RunPixelTest(
192 PixelTestType test_type,
193 scoped_refptr<Layer> content_root,
194 base::FilePath file_name) {
195 test_type_ = test_type;
196 content_root_ = content_root;
197 readback_target_ = NULL;
198 ref_file_ = file_name;
199 RunTest(true, false, impl_side_painting_);
202 void LayerTreePixelTest::RunPixelTestWithReadbackTarget(
203 PixelTestType test_type,
204 scoped_refptr<Layer> content_root,
205 Layer* target,
206 base::FilePath file_name) {
207 test_type_ = test_type;
208 content_root_ = content_root;
209 readback_target_ = target;
210 ref_file_ = file_name;
211 RunTest(true, false, impl_side_painting_);
214 void LayerTreePixelTest::SetupTree() {
215 scoped_refptr<Layer> root = Layer::Create();
216 root->SetBounds(content_root_->bounds());
217 root->AddChild(content_root_);
218 layer_tree_host()->SetRootLayer(root);
219 LayerTreeTest::SetupTree();
222 scoped_ptr<SkBitmap> LayerTreePixelTest::CopyTextureMailboxToBitmap(
223 const gfx::Size& size,
224 const TextureMailbox& texture_mailbox) {
225 DCHECK(texture_mailbox.IsTexture());
226 if (!texture_mailbox.IsTexture())
227 return scoped_ptr<SkBitmap>();
229 scoped_ptr<gpu::GLInProcessContext> context = CreateTestInProcessContext();
230 GLES2Interface* gl = context->GetImplementation();
232 if (texture_mailbox.sync_point())
233 gl->WaitSyncPointCHROMIUM(texture_mailbox.sync_point());
235 GLuint texture_id = 0;
236 gl->GenTextures(1, &texture_id);
237 gl->BindTexture(GL_TEXTURE_2D, texture_id);
238 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
239 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
240 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
241 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
242 gl->ConsumeTextureCHROMIUM(texture_mailbox.target(), texture_mailbox.name());
243 gl->BindTexture(GL_TEXTURE_2D, 0);
245 GLuint fbo = 0;
246 gl->GenFramebuffers(1, &fbo);
247 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo);
248 gl->FramebufferTexture2D(
249 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_id, 0);
250 EXPECT_EQ(static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE),
251 gl->CheckFramebufferStatus(GL_FRAMEBUFFER));
253 scoped_ptr<uint8[]> pixels(new uint8[size.GetArea() * 4]);
254 gl->ReadPixels(0,
256 size.width(),
257 size.height(),
258 GL_RGBA,
259 GL_UNSIGNED_BYTE,
260 pixels.get());
262 gl->DeleteFramebuffers(1, &fbo);
263 gl->DeleteTextures(1, &texture_id);
265 scoped_ptr<SkBitmap> bitmap(new SkBitmap);
266 bitmap->allocN32Pixels(size.width(), size.height());
268 uint8* out_pixels = static_cast<uint8*>(bitmap->getPixels());
270 size_t row_bytes = size.width() * 4;
271 size_t total_bytes = size.height() * row_bytes;
272 for (size_t dest_y = 0; dest_y < total_bytes; dest_y += row_bytes) {
273 // Flip Y axis.
274 size_t src_y = total_bytes - dest_y - row_bytes;
275 // Swizzle OpenGL -> Skia byte order.
276 for (size_t x = 0; x < row_bytes; x += 4) {
277 out_pixels[dest_y + x + SK_R32_SHIFT/8] = pixels.get()[src_y + x + 0];
278 out_pixels[dest_y + x + SK_G32_SHIFT/8] = pixels.get()[src_y + x + 1];
279 out_pixels[dest_y + x + SK_B32_SHIFT/8] = pixels.get()[src_y + x + 2];
280 out_pixels[dest_y + x + SK_A32_SHIFT/8] = pixels.get()[src_y + x + 3];
284 return bitmap.Pass();
287 void LayerTreePixelTest::ReleaseTextureMailbox(
288 scoped_ptr<gpu::GLInProcessContext> context,
289 uint32 texture,
290 uint32 sync_point,
291 bool lost_resource) {
292 GLES2Interface* gl = context->GetImplementation();
293 if (sync_point)
294 gl->WaitSyncPointCHROMIUM(sync_point);
295 gl->DeleteTextures(1, &texture);
296 pending_texture_mailbox_callbacks_--;
297 TryEndTest();
300 void LayerTreePixelTest::CopyBitmapToTextureMailboxAsTexture(
301 const SkBitmap& bitmap,
302 TextureMailbox* texture_mailbox,
303 scoped_ptr<SingleReleaseCallback>* release_callback) {
304 DCHECK_GT(bitmap.width(), 0);
305 DCHECK_GT(bitmap.height(), 0);
307 scoped_ptr<gpu::GLInProcessContext> context = CreateTestInProcessContext();
308 GLES2Interface* gl = context->GetImplementation();
310 GLuint texture_id = 0;
311 gl->GenTextures(1, &texture_id);
312 gl->BindTexture(GL_TEXTURE_2D, texture_id);
313 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
314 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
315 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
316 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
318 DCHECK_EQ(kN32_SkColorType, bitmap.colorType());
321 SkAutoLockPixels lock(bitmap);
323 size_t row_bytes = bitmap.width() * 4;
324 size_t total_bytes = bitmap.height() * row_bytes;
326 scoped_ptr<uint8[]> gl_pixels(new uint8[total_bytes]);
327 uint8* bitmap_pixels = static_cast<uint8*>(bitmap.getPixels());
329 for (size_t y = 0; y < total_bytes; y += row_bytes) {
330 // Flip Y axis.
331 size_t src_y = total_bytes - y - row_bytes;
332 // Swizzle Skia -> OpenGL byte order.
333 for (size_t x = 0; x < row_bytes; x += 4) {
334 gl_pixels.get()[y + x + 0] = bitmap_pixels[src_y + x + SK_R32_SHIFT/8];
335 gl_pixels.get()[y + x + 1] = bitmap_pixels[src_y + x + SK_G32_SHIFT/8];
336 gl_pixels.get()[y + x + 2] = bitmap_pixels[src_y + x + SK_B32_SHIFT/8];
337 gl_pixels.get()[y + x + 3] = bitmap_pixels[src_y + x + SK_A32_SHIFT/8];
341 gl->TexImage2D(GL_TEXTURE_2D,
343 GL_RGBA,
344 bitmap.width(),
345 bitmap.height(),
347 GL_RGBA,
348 GL_UNSIGNED_BYTE,
349 gl_pixels.get());
352 gpu::Mailbox mailbox;
353 gl->GenMailboxCHROMIUM(mailbox.name);
354 gl->ProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
355 gl->BindTexture(GL_TEXTURE_2D, 0);
356 uint32 sync_point = gl->InsertSyncPointCHROMIUM();
358 *texture_mailbox = TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point);
359 *release_callback = SingleReleaseCallback::Create(
360 base::Bind(&LayerTreePixelTest::ReleaseTextureMailbox,
361 base::Unretained(this),
362 base::Passed(&context),
363 texture_id));
366 } // namespace cc