OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stdio.h> | 5 #include <stdio.h> |
6 #include <cmath> | 6 #include <cmath> |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include <GLES2/gl2.h> | 10 #include <GLES2/gl2.h> |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 #include "ui/gfx/gtk_util.h" | 42 #include "ui/gfx/gtk_util.h" |
43 #endif | 43 #endif |
44 | 44 |
45 namespace content { | 45 namespace content { |
46 | 46 |
47 using blink::WebGLId; | 47 using blink::WebGLId; |
48 using blink::WebGraphicsContext3D; | 48 using blink::WebGraphicsContext3D; |
49 using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl; | 49 using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl; |
50 | 50 |
51 content::GLHelper::ScalerQuality kQualities[] = { | 51 content::GLHelper::ScalerQuality kQualities[] = { |
52 content::GLHelper::SCALER_QUALITY_BEST, | 52 content::GLHelper::SCALER_QUALITY_BEST, |
53 content::GLHelper::SCALER_QUALITY_GOOD, | 53 content::GLHelper::SCALER_QUALITY_GOOD, |
54 content::GLHelper::SCALER_QUALITY_FAST, | 54 content::GLHelper::SCALER_QUALITY_FAST, }; |
55 }; | |
56 | 55 |
57 const char *kQualityNames[] = { | 56 const char* kQualityNames[] = {"best", "good", "fast", }; |
58 "best", | |
59 "good", | |
60 "fast", | |
61 }; | |
62 | 57 |
63 class GLHelperTest : public testing::Test { | 58 class GLHelperTest : public testing::Test { |
64 protected: | 59 protected: |
65 virtual void SetUp() { | 60 virtual void SetUp() { |
66 WebGraphicsContext3D::Attributes attributes; | 61 WebGraphicsContext3D::Attributes attributes; |
67 context_ = WebGraphicsContext3DInProcessCommandBufferImpl:: | 62 context_ = |
68 CreateOffscreenContext(attributes); | 63 WebGraphicsContext3DInProcessCommandBufferImpl::CreateOffscreenContext( |
| 64 attributes); |
69 context_->makeContextCurrent(); | 65 context_->makeContextCurrent(); |
70 context_support_ = context_->GetContextSupport(); | 66 context_support_ = context_->GetContextSupport(); |
71 helper_.reset(new content::GLHelper(context_.get(), context_support_)); | 67 helper_.reset( |
| 68 new content::GLHelper(context_->GetGLInterface(), context_support_)); |
72 helper_scaling_.reset(new content::GLHelperScaling( | 69 helper_scaling_.reset(new content::GLHelperScaling( |
73 context_.get(), | 70 context_->GetGLInterface(), helper_.get())); |
74 helper_.get())); | |
75 } | 71 } |
76 | 72 |
77 virtual void TearDown() { | 73 virtual void TearDown() { |
78 helper_scaling_.reset(NULL); | 74 helper_scaling_.reset(NULL); |
79 helper_.reset(NULL); | 75 helper_.reset(NULL); |
80 context_.reset(NULL); | 76 context_.reset(NULL); |
81 } | 77 } |
82 | 78 |
83 void StartTracing(const std::string& filter) { | 79 void StartTracing(const std::string& filter) { |
84 base::debug::TraceLog::GetInstance()->SetEnabled( | 80 base::debug::TraceLog::GetInstance()->SetEnabled( |
(...skipping 10 matching lines...) Expand all Loading... |
95 output->append(","); | 91 output->append(","); |
96 } | 92 } |
97 output->append(json_events_str->data()); | 93 output->append(json_events_str->data()); |
98 if (!has_more_events) { | 94 if (!has_more_events) { |
99 callback.Run(); | 95 callback.Run(); |
100 } | 96 } |
101 } | 97 } |
102 | 98 |
103 // End tracing, return tracing data in a simple map | 99 // End tracing, return tracing data in a simple map |
104 // of event name->counts. | 100 // of event name->counts. |
105 void EndTracing(std::map<std::string, int> *event_counts) { | 101 void EndTracing(std::map<std::string, int>* event_counts) { |
106 std::string json_data = "["; | 102 std::string json_data = "["; |
107 base::debug::TraceLog::GetInstance()->SetDisabled(); | 103 base::debug::TraceLog::GetInstance()->SetDisabled(); |
108 base::RunLoop run_loop; | 104 base::RunLoop run_loop; |
109 base::debug::TraceLog::GetInstance()->Flush( | 105 base::debug::TraceLog::GetInstance()->Flush( |
110 base::Bind(&GLHelperTest::TraceDataCB, | 106 base::Bind(&GLHelperTest::TraceDataCB, |
111 run_loop.QuitClosure(), | 107 run_loop.QuitClosure(), |
112 base::Unretained(&json_data))); | 108 base::Unretained(&json_data))); |
113 run_loop.Run(); | 109 run_loop.Run(); |
114 json_data.append("]"); | 110 json_data.append("]"); |
115 | 111 |
116 scoped_ptr<base::Value> trace_data(base::JSONReader::Read(json_data)); | 112 scoped_ptr<base::Value> trace_data(base::JSONReader::Read(json_data)); |
117 base::ListValue* list; | 113 base::ListValue* list; |
118 CHECK(trace_data->GetAsList(&list)); | 114 CHECK(trace_data->GetAsList(&list)); |
119 for (size_t i = 0; i < list->GetSize(); i++) { | 115 for (size_t i = 0; i < list->GetSize(); i++) { |
120 base::Value *item = NULL; | 116 base::Value* item = NULL; |
121 if (list->Get(i, &item)) { | 117 if (list->Get(i, &item)) { |
122 base::DictionaryValue *dict; | 118 base::DictionaryValue* dict; |
123 CHECK(item->GetAsDictionary(&dict)); | 119 CHECK(item->GetAsDictionary(&dict)); |
124 std::string name; | 120 std::string name; |
125 CHECK(dict->GetString("name", &name)); | 121 CHECK(dict->GetString("name", &name)); |
126 (*event_counts)[name]++; | 122 (*event_counts)[name]++; |
127 VLOG(1) << "trace name: " << name; | 123 VLOG(1) << "trace name: " << name; |
128 } | 124 } |
129 } | 125 } |
130 } | 126 } |
131 | 127 |
132 // Bicubic filter kernel function. | 128 // Bicubic filter kernel function. |
133 static float Bicubic(float x) { | 129 static float Bicubic(float x) { |
134 const float a = -0.5; | 130 const float a = -0.5; |
135 x = std::abs(x); | 131 x = std::abs(x); |
136 float x2 = x * x; | 132 float x2 = x * x; |
137 float x3 = x2 * x; | 133 float x3 = x2 * x; |
138 if (x <= 1) { | 134 if (x <= 1) { |
139 return (a + 2) * x3 - (a + 3) * x2 + 1; | 135 return (a + 2) * x3 - (a + 3) * x2 + 1; |
140 } else if (x < 2) { | 136 } else if (x < 2) { |
141 return a * x3 - 5 * a * x2 + 8 * a * x - 4 * a; | 137 return a * x3 - 5 * a * x2 + 8 * a * x - 4 * a; |
142 } else { | 138 } else { |
143 return 0.0f; | 139 return 0.0f; |
144 } | 140 } |
145 } | 141 } |
146 | 142 |
147 // Look up a single R/G/B/A value. | 143 // Look up a single R/G/B/A value. |
148 // Clamp x/y. | 144 // Clamp x/y. |
149 int Channel(SkBitmap* pixels, int x, int y, int c) { | 145 int Channel(SkBitmap* pixels, int x, int y, int c) { |
150 uint32 *data = pixels->getAddr32( | 146 uint32* data = |
151 std::max(0, std::min(x, pixels->width() - 1)), | 147 pixels->getAddr32(std::max(0, std::min(x, pixels->width() - 1)), |
152 std::max(0, std::min(y, pixels->height() - 1))); | 148 std::max(0, std::min(y, pixels->height() - 1))); |
153 return (*data) >> (c * 8) & 0xff; | 149 return (*data) >> (c * 8) & 0xff; |
154 } | 150 } |
155 | 151 |
156 // Set a single R/G/B/A value. | 152 // Set a single R/G/B/A value. |
157 void SetChannel(SkBitmap* pixels, int x, int y, int c, int v) { | 153 void SetChannel(SkBitmap* pixels, int x, int y, int c, int v) { |
158 DCHECK_GE(x, 0); | 154 DCHECK_GE(x, 0); |
159 DCHECK_GE(y, 0); | 155 DCHECK_GE(y, 0); |
160 DCHECK_LT(x, pixels->width()); | 156 DCHECK_LT(x, pixels->width()); |
161 DCHECK_LT(y, pixels->height()); | 157 DCHECK_LT(y, pixels->height()); |
162 uint32 *data = pixels->getAddr32(x, y); | 158 uint32* data = pixels->getAddr32(x, y); |
163 v = std::max(0, std::min(v, 255)); | 159 v = std::max(0, std::min(v, 255)); |
164 *data = (*data & ~(0xffu << (c * 8))) | (v << (c * 8)); | 160 *data = (*data & ~(0xffu << (c * 8))) | (v << (c * 8)); |
165 } | 161 } |
166 | 162 |
167 // Print all the R, G, B or A values from an SkBitmap in a | 163 // Print all the R, G, B or A values from an SkBitmap in a |
168 // human-readable format. | 164 // human-readable format. |
169 void PrintChannel(SkBitmap* pixels, int c) { | 165 void PrintChannel(SkBitmap* pixels, int c) { |
170 for (int y = 0; y < pixels->height(); y++) { | 166 for (int y = 0; y < pixels->height(); y++) { |
| 167 std::string formatted; |
171 for (int x = 0; x < pixels->width(); x++) { | 168 for (int x = 0; x < pixels->width(); x++) { |
172 printf("%3d, ", Channel(pixels, x, y, c)); | 169 formatted.append(base::StringPrintf("%3d, ", Channel(pixels, x, y, c))); |
173 } | 170 } |
174 printf("\n"); | 171 LOG(ERROR) << formatted; |
175 } | 172 } |
176 } | 173 } |
177 | 174 |
178 // Print out the individual steps of a scaler pipeline. | 175 // Print out the individual steps of a scaler pipeline. |
179 std::string PrintStages( | 176 std::string PrintStages( |
180 const std::vector<GLHelperScaling::ScalerStage> &scaler_stages) { | 177 const std::vector<GLHelperScaling::ScalerStage>& scaler_stages) { |
181 std::string ret; | 178 std::string ret; |
182 for (size_t i = 0; i < scaler_stages.size(); i++) { | 179 for (size_t i = 0; i < scaler_stages.size(); i++) { |
183 ret.append(base::StringPrintf("%dx%d -> %dx%d ", | 180 ret.append(base::StringPrintf("%dx%d -> %dx%d ", |
184 scaler_stages[i].src_size.width(), | 181 scaler_stages[i].src_size.width(), |
185 scaler_stages[i].src_size.height(), | 182 scaler_stages[i].src_size.height(), |
186 scaler_stages[i].dst_size.width(), | 183 scaler_stages[i].dst_size.width(), |
187 scaler_stages[i].dst_size.height())); | 184 scaler_stages[i].dst_size.height())); |
188 bool xy_matters = false; | 185 bool xy_matters = false; |
189 switch (scaler_stages[i].shader) { | 186 switch (scaler_stages[i].shader) { |
190 case GLHelperScaling::SHADER_BILINEAR: | 187 case GLHelperScaling::SHADER_BILINEAR: |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 if (scale > samples / 2.0 && scale < samples) { | 252 if (scale > samples / 2.0 && scale < samples) { |
256 return true; | 253 return true; |
257 } | 254 } |
258 } | 255 } |
259 return false; | 256 return false; |
260 } | 257 } |
261 | 258 |
262 // Make sure that the stages of the scaler pipeline are sane. | 259 // Make sure that the stages of the scaler pipeline are sane. |
263 void ValidateScalerStages( | 260 void ValidateScalerStages( |
264 content::GLHelper::ScalerQuality quality, | 261 content::GLHelper::ScalerQuality quality, |
265 const std::vector<GLHelperScaling::ScalerStage> &scaler_stages, | 262 const std::vector<GLHelperScaling::ScalerStage>& scaler_stages, |
266 const std::string& message) { | 263 const std::string& message) { |
267 bool previous_error = HasFailure(); | 264 bool previous_error = HasFailure(); |
268 // First, check that the input size for each stage is equal to | 265 // First, check that the input size for each stage is equal to |
269 // the output size of the previous stage. | 266 // the output size of the previous stage. |
270 for (size_t i = 1; i < scaler_stages.size(); i++) { | 267 for (size_t i = 1; i < scaler_stages.size(); i++) { |
271 EXPECT_EQ(scaler_stages[i - 1].dst_size.width(), | 268 EXPECT_EQ(scaler_stages[i - 1].dst_size.width(), |
272 scaler_stages[i].src_size.width()); | 269 scaler_stages[i].src_size.width()); |
273 EXPECT_EQ(scaler_stages[i - 1].dst_size.height(), | 270 EXPECT_EQ(scaler_stages[i - 1].dst_size.height(), |
274 scaler_stages[i].src_size.height()); | 271 scaler_stages[i].src_size.height()); |
275 EXPECT_EQ(scaler_stages[i].src_subrect.x(), 0); | 272 EXPECT_EQ(scaler_stages[i].src_subrect.x(), 0); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
362 | 359 |
363 if (x_scale != 1.0) { | 360 if (x_scale != 1.0) { |
364 scaled_x = true; | 361 scaled_x = true; |
365 } | 362 } |
366 if (y_scale != 1.0) { | 363 if (y_scale != 1.0) { |
367 scaled_y = true; | 364 scaled_y = true; |
368 } | 365 } |
369 } | 366 } |
370 | 367 |
371 if (HasFailure() && !previous_error) { | 368 if (HasFailure() && !previous_error) { |
372 printf("Invalid scaler stages: %s\n", message.c_str()); | 369 LOG(ERROR) << "Invalid scaler stages: " << message; |
373 printf("Scaler stages:\n%s", PrintStages(scaler_stages).c_str()); | 370 LOG(ERROR) << "Scaler stages:"; |
| 371 LOG(ERROR) << PrintStages(scaler_stages); |
374 } | 372 } |
375 } | 373 } |
376 | 374 |
377 // Compare two bitmaps, make sure that each component of each pixel | 375 // Compare two bitmaps, make sure that each component of each pixel |
378 // is no more than |maxdiff| apart. If they are not similar enough, | 376 // is no more than |maxdiff| apart. If they are not similar enough, |
379 // prints out |truth|, |other|, |source|, |scaler_stages| and |message|. | 377 // prints out |truth|, |other|, |source|, |scaler_stages| and |message|. |
380 void Compare(SkBitmap* truth, | 378 void Compare(SkBitmap* truth, |
381 SkBitmap* other, | 379 SkBitmap* other, |
382 int maxdiff, | 380 int maxdiff, |
383 SkBitmap* source, | 381 SkBitmap* source, |
384 const std::vector<GLHelperScaling::ScalerStage> &scaler_stages, | 382 const std::vector<GLHelperScaling::ScalerStage>& scaler_stages, |
385 std::string message) { | 383 std::string message) { |
386 EXPECT_EQ(truth->width(), other->width()); | 384 EXPECT_EQ(truth->width(), other->width()); |
387 EXPECT_EQ(truth->height(), other->height()); | 385 EXPECT_EQ(truth->height(), other->height()); |
388 for (int x = 0; x < truth->width(); x++) { | 386 for (int x = 0; x < truth->width(); x++) { |
389 for (int y = 0; y < truth->height(); y++) { | 387 for (int y = 0; y < truth->height(); y++) { |
390 for (int c = 0; c < 4; c++) { | 388 for (int c = 0; c < 4; c++) { |
391 int a = Channel(truth, x, y, c); | 389 int a = Channel(truth, x, y, c); |
392 int b = Channel(other, x, y, c); | 390 int b = Channel(other, x, y, c); |
393 EXPECT_NEAR(a, b, maxdiff) | 391 EXPECT_NEAR(a, b, maxdiff) << " x=" << x << " y=" << y << " c=" << c |
394 << " x=" << x | 392 << " " << message; |
395 << " y=" << y | |
396 << " c=" << c | |
397 << " " << message; | |
398 if (std::abs(a - b) > maxdiff) { | 393 if (std::abs(a - b) > maxdiff) { |
399 printf("-------expected--------\n"); | 394 LOG(ERROR) << "-------expected--------"; |
400 PrintChannel(truth, c); | 395 PrintChannel(truth, c); |
401 printf("-------actual--------\n"); | 396 LOG(ERROR) << "-------actual--------"; |
402 PrintChannel(other, c); | 397 PrintChannel(other, c); |
403 if (source) { | 398 if (source) { |
404 printf("-------before scaling--------\n"); | 399 LOG(ERROR) << "-------before scaling--------"; |
405 PrintChannel(source, c); | 400 PrintChannel(source, c); |
406 } | 401 } |
407 printf("-----Scaler stages------\n%s", | 402 LOG(ERROR) << "-----Scaler stages------"; |
408 PrintStages(scaler_stages).c_str()); | 403 LOG(ERROR) << PrintStages(scaler_stages); |
409 return; | 404 return; |
410 } | 405 } |
411 } | 406 } |
412 } | 407 } |
413 } | 408 } |
414 } | 409 } |
415 | 410 |
416 // Get a single R, G, B or A value as a float. | 411 // Get a single R, G, B or A value as a float. |
417 float ChannelAsFloat(SkBitmap* pixels, int x, int y, int c) { | 412 float ChannelAsFloat(SkBitmap* pixels, int x, int y, int c) { |
418 return Channel(pixels, x, y, c) / 255.0; | 413 return Channel(pixels, x, y, c) / 255.0; |
(...skipping 25 matching lines...) Expand all Loading... |
444 for (int dst_x = 0; dst_x < output->width(); dst_x++) { | 439 for (int dst_x = 0; dst_x < output->width(); dst_x++) { |
445 for (int channel = 0; channel < 4; channel++) { | 440 for (int channel = 0; channel < 4; channel++) { |
446 float dst_x_in_src = (dst_x + 0.5f) * xscale; | 441 float dst_x_in_src = (dst_x + 0.5f) * xscale; |
447 float dst_y_in_src = (dst_y + 0.5f) * yscale; | 442 float dst_y_in_src = (dst_y + 0.5f) * yscale; |
448 | 443 |
449 float value = 0.0f; | 444 float value = 0.0f; |
450 float sum = 0.0f; | 445 float sum = 0.0f; |
451 switch (quality) { | 446 switch (quality) { |
452 case content::GLHelper::SCALER_QUALITY_BEST: | 447 case content::GLHelper::SCALER_QUALITY_BEST: |
453 for (int src_y = -10; src_y < input->height() + 10; ++src_y) { | 448 for (int src_y = -10; src_y < input->height() + 10; ++src_y) { |
454 float coeff_y = Bicubic( | 449 float coeff_y = |
455 (src_y + 0.5f - dst_y_in_src) * clamped_yscale); | 450 Bicubic((src_y + 0.5f - dst_y_in_src) * clamped_yscale); |
456 if (coeff_y == 0.0f) { | 451 if (coeff_y == 0.0f) { |
457 continue; | 452 continue; |
458 } | 453 } |
459 for (int src_x = -10; src_x < input->width() + 10; ++src_x) { | 454 for (int src_x = -10; src_x < input->width() + 10; ++src_x) { |
460 float coeff = coeff_y * Bicubic( | 455 float coeff = |
461 (src_x + 0.5f - dst_x_in_src) * clamped_xscale); | 456 coeff_y * |
| 457 Bicubic((src_x + 0.5f - dst_x_in_src) * clamped_xscale); |
462 if (coeff == 0.0f) { | 458 if (coeff == 0.0f) { |
463 continue; | 459 continue; |
464 } | 460 } |
465 sum += coeff; | 461 sum += coeff; |
466 float c = ChannelAsFloat(input, src_x, src_y, channel); | 462 float c = ChannelAsFloat(input, src_x, src_y, channel); |
467 value += c * coeff; | 463 value += c * coeff; |
468 } | 464 } |
469 } | 465 } |
470 break; | 466 break; |
471 | 467 |
472 case content::GLHelper::SCALER_QUALITY_GOOD: { | 468 case content::GLHelper::SCALER_QUALITY_GOOD: { |
473 int xshift = 0, yshift = 0; | 469 int xshift = 0, yshift = 0; |
474 while ((output->width() << xshift) < input->width()) { | 470 while ((output->width() << xshift) < input->width()) { |
475 xshift++; | 471 xshift++; |
476 } | 472 } |
477 while ((output->height() << yshift) < input->height()) { | 473 while ((output->height() << yshift) < input->height()) { |
478 yshift++; | 474 yshift++; |
479 } | 475 } |
480 int xmag = 1 << xshift; | 476 int xmag = 1 << xshift; |
481 int ymag = 1 << yshift; | 477 int ymag = 1 << yshift; |
482 if (xmag == 4 && output->width() * 3 >= input->width()) { | 478 if (xmag == 4 && output->width() * 3 >= input->width()) { |
483 xmag=3; | 479 xmag = 3; |
484 } | 480 } |
485 if (ymag == 4 && output->height() * 3 >= input->height()) { | 481 if (ymag == 4 && output->height() * 3 >= input->height()) { |
486 ymag=3; | 482 ymag = 3; |
487 } | 483 } |
488 for (int x = 0; x < xmag; x++) { | 484 for (int x = 0; x < xmag; x++) { |
489 for (int y = 0; y < ymag; y++) { | 485 for (int y = 0; y < ymag; y++) { |
490 value += Bilinear(input, | 486 value += Bilinear(input, |
491 (dst_x * xmag + x + 0.5) * xscale / xmag, | 487 (dst_x * xmag + x + 0.5) * xscale / xmag, |
492 (dst_y * ymag + y + 0.5) * yscale / ymag, | 488 (dst_y * ymag + y + 0.5) * yscale / ymag, |
493 channel); | 489 channel); |
494 sum += 1.0; | 490 sum += 1.0; |
495 } | 491 } |
496 } | 492 } |
497 break; | 493 break; |
498 } | 494 } |
499 | 495 |
500 case content::GLHelper::SCALER_QUALITY_FAST: | 496 case content::GLHelper::SCALER_QUALITY_FAST: |
501 value = Bilinear(input, dst_x_in_src, dst_y_in_src, channel); | 497 value = Bilinear(input, dst_x_in_src, dst_y_in_src, channel); |
502 sum = 1.0; | 498 sum = 1.0; |
503 } | 499 } |
504 value /= sum; | 500 value /= sum; |
505 SetChannel(output, dst_x, dst_y, channel, | 501 SetChannel(output, |
| 502 dst_x, |
| 503 dst_y, |
| 504 channel, |
506 static_cast<int>(value * 255.0f + 0.5f)); | 505 static_cast<int>(value * 255.0f + 0.5f)); |
507 } | 506 } |
508 } | 507 } |
509 } | 508 } |
510 } | 509 } |
511 | 510 |
512 void FlipSKBitmap(SkBitmap* bitmap) { | 511 void FlipSKBitmap(SkBitmap* bitmap) { |
513 int top_line = 0; | 512 int top_line = 0; |
514 int bottom_line = bitmap->height() - 1; | 513 int bottom_line = bitmap->height() - 1; |
515 while (top_line < bottom_line) { | 514 while (top_line < bottom_line) { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
567 tmp.setConfig(SkBitmap::kARGB_8888_Config, xtmp, ytmp); | 566 tmp.setConfig(SkBitmap::kARGB_8888_Config, xtmp, ytmp); |
568 tmp.allocPixels(); | 567 tmp.allocPixels(); |
569 SkAutoLockPixels lock(tmp); | 568 SkAutoLockPixels lock(tmp); |
570 | 569 |
571 ScaleSlowRecursive(input, &tmp, quality); | 570 ScaleSlowRecursive(input, &tmp, quality); |
572 ScaleSlowRecursive(&tmp, output, quality); | 571 ScaleSlowRecursive(&tmp, output, quality); |
573 } | 572 } |
574 | 573 |
575 // Scaling test: Create a test image, scale it using GLHelperScaling | 574 // Scaling test: Create a test image, scale it using GLHelperScaling |
576 // and a reference implementation and compare the results. | 575 // and a reference implementation and compare the results. |
577 void TestScale(int xsize, int ysize, | 576 void TestScale(int xsize, |
578 int scaled_xsize, int scaled_ysize, | 577 int ysize, |
| 578 int scaled_xsize, |
| 579 int scaled_ysize, |
579 int test_pattern, | 580 int test_pattern, |
580 size_t quality, | 581 size_t quality, |
581 bool flip) { | 582 bool flip) { |
582 WebGLId src_texture = context_->createTexture(); | 583 WebGLId src_texture = context_->createTexture(); |
583 WebGLId framebuffer = context_->createFramebuffer(); | 584 WebGLId framebuffer = context_->createFramebuffer(); |
584 SkBitmap input_pixels; | 585 SkBitmap input_pixels; |
585 input_pixels.setConfig(SkBitmap::kARGB_8888_Config, xsize, ysize); | 586 input_pixels.setConfig(SkBitmap::kARGB_8888_Config, xsize, ysize); |
586 input_pixels.allocPixels(); | 587 input_pixels.allocPixels(); |
587 SkAutoLockPixels lock(input_pixels); | 588 SkAutoLockPixels lock(input_pixels); |
588 | 589 |
589 for (int x = 0; x < xsize; ++x) { | 590 for (int x = 0; x < xsize; ++x) { |
590 for (int y = 0; y < ysize; ++y) { | 591 for (int y = 0; y < ysize; ++y) { |
591 switch (test_pattern) { | 592 switch (test_pattern) { |
592 case 0: // Smooth test pattern | 593 case 0: // Smooth test pattern |
593 SetChannel(&input_pixels, x, y, 0, x * 10); | 594 SetChannel(&input_pixels, x, y, 0, x * 10); |
594 SetChannel(&input_pixels, x, y, 1, y * 10); | 595 SetChannel(&input_pixels, x, y, 1, y * 10); |
595 SetChannel(&input_pixels, x, y, 2, (x + y) * 10); | 596 SetChannel(&input_pixels, x, y, 2, (x + y) * 10); |
596 SetChannel(&input_pixels, x, y, 3, 255); | 597 SetChannel(&input_pixels, x, y, 3, 255); |
597 break; | 598 break; |
598 case 1: // Small blocks | 599 case 1: // Small blocks |
599 SetChannel(&input_pixels, x, y, 0, x & 1 ? 255 : 0); | 600 SetChannel(&input_pixels, x, y, 0, x & 1 ? 255 : 0); |
600 SetChannel(&input_pixels, x, y, 1, y & 1 ? 255 : 0); | 601 SetChannel(&input_pixels, x, y, 1, y & 1 ? 255 : 0); |
601 SetChannel(&input_pixels, x, y, 2, (x + y) & 1 ? 255 : 0); | 602 SetChannel(&input_pixels, x, y, 2, (x + y) & 1 ? 255 : 0); |
602 SetChannel(&input_pixels, x, y, 3, 255); | 603 SetChannel(&input_pixels, x, y, 3, 255); |
603 break; | 604 break; |
604 case 2: // Medium blocks | 605 case 2: // Medium blocks |
605 SetChannel(&input_pixels, x, y, 0, 10 + x/2 * 50); | 606 SetChannel(&input_pixels, x, y, 0, 10 + x / 2 * 50); |
606 SetChannel(&input_pixels, x, y, 1, 10 + y/3 * 50); | 607 SetChannel(&input_pixels, x, y, 1, 10 + y / 3 * 50); |
607 SetChannel(&input_pixels, x, y, 2, (x + y)/5 * 50 + 5); | 608 SetChannel(&input_pixels, x, y, 2, (x + y) / 5 * 50 + 5); |
608 SetChannel(&input_pixels, x, y, 3, 255); | 609 SetChannel(&input_pixels, x, y, 3, 255); |
609 break; | 610 break; |
610 } | 611 } |
611 } | 612 } |
612 } | 613 } |
613 | 614 |
614 context_->bindFramebuffer(GL_FRAMEBUFFER, framebuffer); | 615 context_->bindFramebuffer(GL_FRAMEBUFFER, framebuffer); |
615 context_->bindTexture(GL_TEXTURE_2D, src_texture); | 616 context_->bindTexture(GL_TEXTURE_2D, src_texture); |
616 context_->texImage2D(GL_TEXTURE_2D, | 617 context_->texImage2D(GL_TEXTURE_2D, |
617 0, | 618 0, |
618 GL_RGBA, | 619 GL_RGBA, |
619 xsize, | 620 xsize, |
620 ysize, | 621 ysize, |
621 0, | 622 0, |
622 GL_RGBA, | 623 GL_RGBA, |
623 GL_UNSIGNED_BYTE, | 624 GL_UNSIGNED_BYTE, |
624 input_pixels.getPixels()); | 625 input_pixels.getPixels()); |
625 | 626 |
626 std::string message = base::StringPrintf("input size: %dx%d " | 627 std::string message = base::StringPrintf( |
627 "output size: %dx%d " | 628 "input size: %dx%d " |
628 "pattern: %d quality: %s", | 629 "output size: %dx%d " |
629 xsize, ysize, | 630 "pattern: %d quality: %s", |
630 scaled_xsize, scaled_ysize, | 631 xsize, |
631 test_pattern, | 632 ysize, |
632 kQualityNames[quality]); | 633 scaled_xsize, |
633 | 634 scaled_ysize, |
| 635 test_pattern, |
| 636 kQualityNames[quality]); |
634 | 637 |
635 std::vector<GLHelperScaling::ScalerStage> stages; | 638 std::vector<GLHelperScaling::ScalerStage> stages; |
636 helper_scaling_->ComputeScalerStages( | 639 helper_scaling_->ComputeScalerStages(kQualities[quality], |
637 kQualities[quality], | 640 gfx::Size(xsize, ysize), |
638 gfx::Size(xsize, ysize), | 641 gfx::Rect(0, 0, xsize, ysize), |
639 gfx::Rect(0, 0, xsize, ysize), | 642 gfx::Size(scaled_xsize, scaled_ysize), |
640 gfx::Size(scaled_xsize, scaled_ysize), | 643 flip, |
641 flip, | 644 false, |
642 false, | 645 &stages); |
643 &stages); | |
644 ValidateScalerStages(kQualities[quality], stages, message); | 646 ValidateScalerStages(kQualities[quality], stages, message); |
645 | 647 |
646 WebGLId dst_texture = helper_->CopyAndScaleTexture( | 648 WebGLId dst_texture = |
647 src_texture, | 649 helper_->CopyAndScaleTexture(src_texture, |
648 gfx::Size(xsize, ysize), | 650 gfx::Size(xsize, ysize), |
649 gfx::Size(scaled_xsize, scaled_ysize), | 651 gfx::Size(scaled_xsize, scaled_ysize), |
650 flip, | 652 flip, |
651 kQualities[quality]); | 653 kQualities[quality]); |
652 | 654 |
653 SkBitmap output_pixels; | 655 SkBitmap output_pixels; |
654 output_pixels.setConfig(SkBitmap::kARGB_8888_Config, | 656 output_pixels.setConfig( |
655 scaled_xsize, scaled_ysize); | 657 SkBitmap::kARGB_8888_Config, scaled_xsize, scaled_ysize); |
656 output_pixels.allocPixels(); | 658 output_pixels.allocPixels(); |
657 SkAutoLockPixels output_lock(output_pixels); | 659 SkAutoLockPixels output_lock(output_pixels); |
658 | 660 |
659 helper_->ReadbackTextureSync( | 661 helper_->ReadbackTextureSync( |
660 dst_texture, | 662 dst_texture, |
661 gfx::Rect(0, 0, scaled_xsize, scaled_ysize), | 663 gfx::Rect(0, 0, scaled_xsize, scaled_ysize), |
662 static_cast<unsigned char *>(output_pixels.getPixels())); | 664 static_cast<unsigned char*>(output_pixels.getPixels())); |
663 if (flip) { | 665 if (flip) { |
664 // Flip the pixels back. | 666 // Flip the pixels back. |
665 FlipSKBitmap(&output_pixels); | 667 FlipSKBitmap(&output_pixels); |
666 } | 668 } |
667 if (xsize == scaled_xsize && ysize == scaled_ysize) { | 669 if (xsize == scaled_xsize && ysize == scaled_ysize) { |
668 Compare(&input_pixels, | 670 Compare(&input_pixels, |
669 &output_pixels, | 671 &output_pixels, |
670 2, | 672 2, |
671 NULL, | 673 NULL, |
672 stages, | 674 stages, |
673 message + " comparing against input"); | 675 message + " comparing against input"); |
674 } | 676 } |
675 SkBitmap truth_pixels; | 677 SkBitmap truth_pixels; |
676 truth_pixels.setConfig(SkBitmap::kARGB_8888_Config, | 678 truth_pixels.setConfig( |
677 scaled_xsize, scaled_ysize); | 679 SkBitmap::kARGB_8888_Config, scaled_xsize, scaled_ysize); |
678 truth_pixels.allocPixels(); | 680 truth_pixels.allocPixels(); |
679 SkAutoLockPixels truth_lock(truth_pixels); | 681 SkAutoLockPixels truth_lock(truth_pixels); |
680 | 682 |
681 ScaleSlowRecursive(&input_pixels, &truth_pixels, kQualities[quality]); | 683 ScaleSlowRecursive(&input_pixels, &truth_pixels, kQualities[quality]); |
682 Compare(&truth_pixels, | 684 Compare(&truth_pixels, |
683 &output_pixels, | 685 &output_pixels, |
684 2, | 686 2, |
685 &input_pixels, | 687 &input_pixels, |
686 stages, | 688 stages, |
687 message + " comparing against scaled"); | 689 message + " comparing against scaled"); |
688 | 690 |
689 context_->deleteTexture(src_texture); | 691 context_->deleteTexture(src_texture); |
690 context_->deleteTexture(dst_texture); | 692 context_->deleteTexture(dst_texture); |
691 context_->deleteFramebuffer(framebuffer); | 693 context_->deleteFramebuffer(framebuffer); |
692 } | 694 } |
693 | 695 |
694 // Create a scaling pipeline and check that it is made up of | 696 // Create a scaling pipeline and check that it is made up of |
695 // valid scaling operations. | 697 // valid scaling operations. |
696 void TestScalerPipeline(size_t quality, | 698 void TestScalerPipeline(size_t quality, |
697 int xsize, int ysize, | 699 int xsize, |
698 int dst_xsize, int dst_ysize) { | 700 int ysize, |
| 701 int dst_xsize, |
| 702 int dst_ysize) { |
699 std::vector<GLHelperScaling::ScalerStage> stages; | 703 std::vector<GLHelperScaling::ScalerStage> stages; |
700 helper_scaling_->ComputeScalerStages( | 704 helper_scaling_->ComputeScalerStages(kQualities[quality], |
701 kQualities[quality], | 705 gfx::Size(xsize, ysize), |
702 gfx::Size(xsize, ysize), | 706 gfx::Rect(0, 0, xsize, ysize), |
703 gfx::Rect(0, 0, xsize, ysize), | 707 gfx::Size(dst_xsize, dst_ysize), |
704 gfx::Size(dst_xsize, dst_ysize), | 708 false, |
705 false, | 709 false, |
706 false, | 710 &stages); |
707 &stages); | 711 ValidateScalerStages(kQualities[quality], |
708 ValidateScalerStages(kQualities[quality], stages, | 712 stages, |
709 base::StringPrintf("input size: %dx%d " | 713 base::StringPrintf( |
710 "output size: %dx%d " | 714 "input size: %dx%d " |
711 "quality: %s", | 715 "output size: %dx%d " |
712 xsize, ysize, | 716 "quality: %s", |
713 dst_xsize, dst_ysize, | 717 xsize, |
714 kQualityNames[quality])); | 718 ysize, |
| 719 dst_xsize, |
| 720 dst_ysize, |
| 721 kQualityNames[quality])); |
715 } | 722 } |
716 | 723 |
717 // Create a scaling pipeline and make sure that the steps | 724 // Create a scaling pipeline and make sure that the steps |
718 // are exactly the steps we expect. | 725 // are exactly the steps we expect. |
719 void CheckPipeline(content::GLHelper::ScalerQuality quality, | 726 void CheckPipeline(content::GLHelper::ScalerQuality quality, |
720 int xsize, int ysize, | 727 int xsize, |
721 int dst_xsize, int dst_ysize, | 728 int ysize, |
722 const std::string &description) { | 729 int dst_xsize, |
| 730 int dst_ysize, |
| 731 const std::string& description) { |
723 std::vector<GLHelperScaling::ScalerStage> stages; | 732 std::vector<GLHelperScaling::ScalerStage> stages; |
724 helper_scaling_->ComputeScalerStages( | 733 helper_scaling_->ComputeScalerStages(quality, |
725 quality, | 734 gfx::Size(xsize, ysize), |
726 gfx::Size(xsize, ysize), | 735 gfx::Rect(0, 0, xsize, ysize), |
727 gfx::Rect(0, 0, xsize, ysize), | 736 gfx::Size(dst_xsize, dst_ysize), |
728 gfx::Size(dst_xsize, dst_ysize), | 737 false, |
729 false, | 738 false, |
730 false, | 739 &stages); |
731 &stages); | 740 ValidateScalerStages(content::GLHelper::SCALER_QUALITY_GOOD, stages, ""); |
732 ValidateScalerStages( | |
733 content::GLHelper::SCALER_QUALITY_GOOD, | |
734 stages, | |
735 ""); | |
736 EXPECT_EQ(PrintStages(stages), description); | 741 EXPECT_EQ(PrintStages(stages), description); |
737 } | 742 } |
738 | 743 |
739 // Note: Left/Right means Top/Bottom when used for Y dimension. | 744 // Note: Left/Right means Top/Bottom when used for Y dimension. |
740 enum Margin { | 745 enum Margin { |
741 MarginLeft, | 746 MarginLeft, |
742 MarginMiddle, | 747 MarginMiddle, |
743 MarginRight, | 748 MarginRight, |
744 MarginInvalid, | 749 MarginInvalid, |
745 }; | 750 }; |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
782 return 255; | 787 return 255; |
783 } | 788 } |
784 return ret; | 789 return ret; |
785 } | 790 } |
786 | 791 |
787 static void callcallback(const base::Callback<void()>& callback, | 792 static void callcallback(const base::Callback<void()>& callback, |
788 bool result) { | 793 bool result) { |
789 callback.Run(); | 794 callback.Run(); |
790 } | 795 } |
791 | 796 |
792 void PrintPlane(unsigned char *plane, int xsize, int stride, int ysize) { | 797 void PrintPlane(unsigned char* plane, int xsize, int stride, int ysize) { |
793 for (int y = 0; y < ysize; y++) { | 798 for (int y = 0; y < ysize; y++) { |
794 for (int x = 0; x < xsize ; x++) { | 799 std::string formatted; |
795 printf("%3d, ", plane[y * stride + x]); | 800 for (int x = 0; x < xsize; x++) { |
| 801 formatted.append(base::StringPrintf("%3d, ", plane[y * stride + x])); |
796 } | 802 } |
797 printf(" (%p)\n", plane + y * stride); | 803 LOG(ERROR) << formatted << " (" << (plane + y * stride) << ")"; |
798 } | 804 } |
799 } | 805 } |
800 | 806 |
801 // Compare two planes make sure that each component of each pixel | 807 // Compare two planes make sure that each component of each pixel |
802 // is no more than |maxdiff| apart. | 808 // is no more than |maxdiff| apart. |
803 void ComparePlane(unsigned char* truth, | 809 void ComparePlane(unsigned char* truth, |
804 unsigned char* other, | 810 unsigned char* other, |
805 int maxdiff, | 811 int maxdiff, |
806 int xsize, | 812 int xsize, |
807 int stride, | 813 int stride, |
808 int ysize, | 814 int ysize, |
809 SkBitmap* source, | 815 SkBitmap* source, |
810 std::string message) { | 816 std::string message) { |
811 int truth_stride = stride; | 817 int truth_stride = stride; |
812 for (int x = 0; x < xsize; x++) { | 818 for (int x = 0; x < xsize; x++) { |
813 for (int y = 0; y < ysize; y++) { | 819 for (int y = 0; y < ysize; y++) { |
814 int a = other[y * stride + x]; | 820 int a = other[y * stride + x]; |
815 int b = truth[y * stride + x]; | 821 int b = truth[y * stride + x]; |
816 EXPECT_NEAR(a, b, maxdiff) | 822 EXPECT_NEAR(a, b, maxdiff) << " x=" << x << " y=" << y << " " |
817 << " x=" << x | 823 << message; |
818 << " y=" << y | |
819 << " " << message; | |
820 if (std::abs(a - b) > maxdiff) { | 824 if (std::abs(a - b) > maxdiff) { |
821 printf("-------expected--------\n"); | 825 LOG(ERROR) << "-------expected--------"; |
822 PrintPlane(truth, xsize, truth_stride, ysize); | 826 PrintPlane(truth, xsize, truth_stride, ysize); |
823 printf("-------actual--------\n"); | 827 LOG(ERROR) << "-------actual--------"; |
824 PrintPlane(other, xsize, stride, ysize); | 828 PrintPlane(other, xsize, stride, ysize); |
825 if (source) { | 829 if (source) { |
826 printf("-------before yuv conversion: red--------\n"); | 830 LOG(ERROR) << "-------before yuv conversion: red--------"; |
827 PrintChannel(source, 0); | 831 PrintChannel(source, 0); |
828 printf("-------before yuv conversion: green------\n"); | 832 LOG(ERROR) << "-------before yuv conversion: green------"; |
829 PrintChannel(source, 1); | 833 PrintChannel(source, 1); |
830 printf("-------before yuv conversion: blue-------\n"); | 834 LOG(ERROR) << "-------before yuv conversion: blue-------"; |
831 PrintChannel(source, 2); | 835 PrintChannel(source, 2); |
832 } | 836 } |
833 return; | 837 return; |
834 } | 838 } |
835 } | 839 } |
836 } | 840 } |
837 } | 841 } |
838 | 842 |
839 // YUV readback test. Create a test pattern, convert to YUV | 843 // YUV readback test. Create a test pattern, convert to YUV |
840 // with reference implementation and compare to what gl_helper | 844 // with reference implementation and compare to what gl_helper |
(...skipping 23 matching lines...) Expand all Loading... |
864 SetChannel(&input_pixels, x, y, 2, (x + y) * 10); | 868 SetChannel(&input_pixels, x, y, 2, (x + y) * 10); |
865 SetChannel(&input_pixels, x, y, 3, 255); | 869 SetChannel(&input_pixels, x, y, 3, 255); |
866 break; | 870 break; |
867 case 1: // Small blocks | 871 case 1: // Small blocks |
868 SetChannel(&input_pixels, x, y, 0, x & 1 ? 255 : 0); | 872 SetChannel(&input_pixels, x, y, 0, x & 1 ? 255 : 0); |
869 SetChannel(&input_pixels, x, y, 1, y & 1 ? 255 : 0); | 873 SetChannel(&input_pixels, x, y, 1, y & 1 ? 255 : 0); |
870 SetChannel(&input_pixels, x, y, 2, (x + y) & 1 ? 255 : 0); | 874 SetChannel(&input_pixels, x, y, 2, (x + y) & 1 ? 255 : 0); |
871 SetChannel(&input_pixels, x, y, 3, 255); | 875 SetChannel(&input_pixels, x, y, 3, 255); |
872 break; | 876 break; |
873 case 2: // Medium blocks | 877 case 2: // Medium blocks |
874 SetChannel(&input_pixels, x, y, 0, 10 + x/2 * 50); | 878 SetChannel(&input_pixels, x, y, 0, 10 + x / 2 * 50); |
875 SetChannel(&input_pixels, x, y, 1, 10 + y/3 * 50); | 879 SetChannel(&input_pixels, x, y, 1, 10 + y / 3 * 50); |
876 SetChannel(&input_pixels, x, y, 2, (x + y)/5 * 50 + 5); | 880 SetChannel(&input_pixels, x, y, 2, (x + y) / 5 * 50 + 5); |
877 SetChannel(&input_pixels, x, y, 3, 255); | 881 SetChannel(&input_pixels, x, y, 3, 255); |
878 break; | 882 break; |
879 } | 883 } |
880 } | 884 } |
881 } | 885 } |
882 | 886 |
883 context_->bindTexture(GL_TEXTURE_2D, src_texture); | 887 context_->bindTexture(GL_TEXTURE_2D, src_texture); |
884 context_->texImage2D(GL_TEXTURE_2D, | 888 context_->texImage2D(GL_TEXTURE_2D, |
885 0, | 889 0, |
886 GL_RGBA, | 890 GL_RGBA, |
887 xsize, | 891 xsize, |
888 ysize, | 892 ysize, |
889 0, | 893 0, |
890 GL_RGBA, | 894 GL_RGBA, |
891 GL_UNSIGNED_BYTE, | 895 GL_UNSIGNED_BYTE, |
892 input_pixels.getPixels()); | 896 input_pixels.getPixels()); |
893 | 897 |
894 gpu::Mailbox mailbox; | 898 gpu::Mailbox mailbox; |
895 context_->genMailboxCHROMIUM(mailbox.name); | 899 context_->genMailboxCHROMIUM(mailbox.name); |
896 EXPECT_FALSE(mailbox.IsZero()); | 900 EXPECT_FALSE(mailbox.IsZero()); |
897 context_->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); | 901 context_->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); |
898 uint32 sync_point = context_->insertSyncPoint(); | 902 uint32 sync_point = context_->insertSyncPoint(); |
899 | 903 |
900 std::string message = base::StringPrintf("input size: %dx%d " | 904 std::string message = base::StringPrintf( |
901 "output size: %dx%d " | 905 "input size: %dx%d " |
902 "margin: %dx%d " | 906 "output size: %dx%d " |
903 "pattern: %d %s %s", | 907 "margin: %dx%d " |
904 xsize, ysize, | 908 "pattern: %d %s %s", |
905 output_xsize, output_ysize, | 909 xsize, |
906 xmargin, ymargin, | 910 ysize, |
907 test_pattern, | 911 output_xsize, |
908 flip ? "flip" : "noflip", | 912 output_ysize, |
909 flip ? "mrt" : "nomrt"); | 913 xmargin, |
| 914 ymargin, |
| 915 test_pattern, |
| 916 flip ? "flip" : "noflip", |
| 917 flip ? "mrt" : "nomrt"); |
910 scoped_ptr<ReadbackYUVInterface> yuv_reader( | 918 scoped_ptr<ReadbackYUVInterface> yuv_reader( |
911 helper_->CreateReadbackPipelineYUV( | 919 helper_->CreateReadbackPipelineYUV( |
912 quality, | 920 quality, |
913 gfx::Size(xsize, ysize), | 921 gfx::Size(xsize, ysize), |
914 gfx::Rect(0, 0, xsize, ysize), | 922 gfx::Rect(0, 0, xsize, ysize), |
915 gfx::Size(output_xsize, output_ysize), | 923 gfx::Size(output_xsize, output_ysize), |
916 gfx::Rect(xmargin, ymargin, xsize, ysize), | 924 gfx::Rect(xmargin, ymargin, xsize, ysize), |
917 flip, | 925 flip, |
918 use_mrt)); | 926 use_mrt)); |
919 | 927 |
920 scoped_refptr<media::VideoFrame> output_frame = | 928 scoped_refptr<media::VideoFrame> output_frame = |
921 media::VideoFrame::CreateFrame( | 929 media::VideoFrame::CreateFrame( |
922 media::VideoFrame::YV12, | 930 media::VideoFrame::YV12, |
923 gfx::Size(output_xsize, output_ysize), | 931 gfx::Size(output_xsize, output_ysize), |
924 gfx::Rect(0, 0, output_xsize, output_ysize), | 932 gfx::Rect(0, 0, output_xsize, output_ysize), |
925 gfx::Size(output_xsize, output_ysize), | 933 gfx::Size(output_xsize, output_ysize), |
926 base::TimeDelta::FromSeconds(0)); | 934 base::TimeDelta::FromSeconds(0)); |
927 scoped_refptr<media::VideoFrame> truth_frame = | 935 scoped_refptr<media::VideoFrame> truth_frame = |
928 media::VideoFrame::CreateFrame( | 936 media::VideoFrame::CreateFrame( |
929 media::VideoFrame::YV12, | 937 media::VideoFrame::YV12, |
930 gfx::Size(output_xsize, output_ysize), | 938 gfx::Size(output_xsize, output_ysize), |
931 gfx::Rect(0, 0, output_xsize, output_ysize), | 939 gfx::Rect(0, 0, output_xsize, output_ysize), |
932 gfx::Size(output_xsize, output_ysize), | 940 gfx::Size(output_xsize, output_ysize), |
933 base::TimeDelta::FromSeconds(0)); | 941 base::TimeDelta::FromSeconds(0)); |
934 | 942 |
935 base::RunLoop run_loop; | 943 base::RunLoop run_loop; |
936 yuv_reader->ReadbackYUV( | 944 yuv_reader->ReadbackYUV(mailbox, |
937 mailbox, | 945 sync_point, |
938 sync_point, | 946 output_frame.get(), |
939 output_frame.get(), | 947 base::Bind(&callcallback, run_loop.QuitClosure())); |
940 base::Bind(&callcallback, run_loop.QuitClosure())); | |
941 run_loop.Run(); | 948 run_loop.Run(); |
942 | 949 |
943 if (flip) { | 950 if (flip) { |
944 FlipSKBitmap(&input_pixels); | 951 FlipSKBitmap(&input_pixels); |
945 } | 952 } |
946 | 953 |
947 unsigned char* Y = truth_frame->data(media::VideoFrame::kYPlane); | 954 unsigned char* Y = truth_frame->data(media::VideoFrame::kYPlane); |
948 unsigned char* U = truth_frame->data(media::VideoFrame::kUPlane); | 955 unsigned char* U = truth_frame->data(media::VideoFrame::kUPlane); |
949 unsigned char* V = truth_frame->data(media::VideoFrame::kVPlane); | 956 unsigned char* V = truth_frame->data(media::VideoFrame::kVPlane); |
950 int32 y_stride = truth_frame->stride(media::VideoFrame::kYPlane); | 957 int32 y_stride = truth_frame->stride(media::VideoFrame::kYPlane); |
951 int32 u_stride = truth_frame->stride(media::VideoFrame::kUPlane); | 958 int32 u_stride = truth_frame->stride(media::VideoFrame::kUPlane); |
952 int32 v_stride = truth_frame->stride(media::VideoFrame::kVPlane); | 959 int32 v_stride = truth_frame->stride(media::VideoFrame::kVPlane); |
953 memset(Y, 0x00, y_stride * output_ysize); | 960 memset(Y, 0x00, y_stride * output_ysize); |
954 memset(U, 0x80, u_stride * output_ysize / 2); | 961 memset(U, 0x80, u_stride * output_ysize / 2); |
955 memset(V, 0x80, v_stride * output_ysize / 2); | 962 memset(V, 0x80, v_stride * output_ysize / 2); |
956 | 963 |
957 for (int y = 0; y < ysize; y++) { | 964 for (int y = 0; y < ysize; y++) { |
958 for (int x = 0; x < xsize; x++) { | 965 for (int x = 0; x < xsize; x++) { |
959 Y[(y + ymargin) * y_stride + x + xmargin] = float_to_byte( | 966 Y[(y + ymargin) * y_stride + x + xmargin] = float_to_byte( |
960 ChannelAsFloat(&input_pixels, x, y, 0) * 0.257 + | 967 ChannelAsFloat(&input_pixels, x, y, 0) * 0.257 + |
961 ChannelAsFloat(&input_pixels, x, y, 1) * 0.504 + | 968 ChannelAsFloat(&input_pixels, x, y, 1) * 0.504 + |
962 ChannelAsFloat(&input_pixels, x, y, 2) * 0.098 + | 969 ChannelAsFloat(&input_pixels, x, y, 2) * 0.098 + 0.0625); |
963 0.0625); | |
964 } | 970 } |
965 } | 971 } |
966 | 972 |
967 for (int y = 0; y < ysize / 2; y++) { | 973 for (int y = 0; y < ysize / 2; y++) { |
968 for (int x = 0; x < xsize / 2; x++) { | 974 for (int x = 0; x < xsize / 2; x++) { |
969 U[(y + ymargin / 2) * u_stride + x + xmargin / 2] = | 975 U[(y + ymargin / 2) * u_stride + x + xmargin / 2] = float_to_byte( |
970 float_to_byte( | 976 Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 0) * -0.148 + |
971 Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 0) * -0.148 + | 977 Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 1) * -0.291 + |
972 Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 1) * -0.291 + | 978 Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 2) * 0.439 + 0.5); |
973 Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 2) * 0.439 + | 979 V[(y + ymargin / 2) * v_stride + x + xmargin / 2] = float_to_byte( |
974 0.5); | 980 Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 0) * 0.439 + |
975 V[(y + ymargin / 2) * v_stride + x + xmargin / 2] = | 981 Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 1) * -0.368 + |
976 float_to_byte( | 982 Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 2) * -0.071 + |
977 Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 0) * 0.439 + | 983 0.5); |
978 Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 1) * -0.368 + | |
979 Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 2) * -0.071 + | |
980 0.5); | |
981 } | 984 } |
982 } | 985 } |
983 | 986 |
984 ComparePlane(Y, | 987 ComparePlane(Y, |
985 output_frame->data(media::VideoFrame::kYPlane), 2, | 988 output_frame->data(media::VideoFrame::kYPlane), |
| 989 2, |
986 output_xsize, | 990 output_xsize, |
987 y_stride, | 991 y_stride, |
988 output_ysize, | 992 output_ysize, |
989 &input_pixels, | 993 &input_pixels, |
990 message + " Y plane"); | 994 message + " Y plane"); |
991 ComparePlane(U, | 995 ComparePlane(U, |
992 output_frame->data(media::VideoFrame::kUPlane), 2, | 996 output_frame->data(media::VideoFrame::kUPlane), |
| 997 2, |
993 output_xsize / 2, | 998 output_xsize / 2, |
994 u_stride, | 999 u_stride, |
995 output_ysize / 2, | 1000 output_ysize / 2, |
996 &input_pixels, | 1001 &input_pixels, |
997 message + " U plane"); | 1002 message + " U plane"); |
998 ComparePlane(V, | 1003 ComparePlane(V, |
999 output_frame->data(media::VideoFrame::kVPlane), 2, | 1004 output_frame->data(media::VideoFrame::kVPlane), |
| 1005 2, |
1000 output_xsize / 2, | 1006 output_xsize / 2, |
1001 v_stride, | 1007 v_stride, |
1002 output_ysize / 2, | 1008 output_ysize / 2, |
1003 &input_pixels, | 1009 &input_pixels, |
1004 message + " V plane"); | 1010 message + " V plane"); |
1005 | 1011 |
1006 context_->deleteTexture(src_texture); | 1012 context_->deleteTexture(src_texture); |
1007 } | 1013 } |
1008 | 1014 |
1009 void TestAddOps(int src, | 1015 void TestAddOps(int src, int dst, bool scale_x, bool allow3) { |
1010 int dst, | |
1011 bool scale_x, | |
1012 bool allow3) { | |
1013 std::deque<GLHelperScaling::ScaleOp> ops; | 1016 std::deque<GLHelperScaling::ScaleOp> ops; |
1014 GLHelperScaling::ScaleOp::AddOps(src, dst, scale_x, allow3, &ops); | 1017 GLHelperScaling::ScaleOp::AddOps(src, dst, scale_x, allow3, &ops); |
1015 // Scale factor 3 is a special case. | 1018 // Scale factor 3 is a special case. |
1016 // It is currently only allowed by itself. | 1019 // It is currently only allowed by itself. |
1017 if (allow3 && dst * 3 >= src && dst * 2 < src) { | 1020 if (allow3 && dst * 3 >= src && dst * 2 < src) { |
1018 EXPECT_EQ(ops[0].scale_factor, 3); | 1021 EXPECT_EQ(ops[0].scale_factor, 3); |
1019 EXPECT_EQ(ops.size(), 1U); | 1022 EXPECT_EQ(ops.size(), 1U); |
1020 EXPECT_EQ(ops[0].scale_x, scale_x); | 1023 EXPECT_EQ(ops[0].scale_x, scale_x); |
1021 EXPECT_EQ(ops[0].scale_size, dst); | 1024 EXPECT_EQ(ops[0].scale_size, dst); |
1022 return; | 1025 return; |
1023 } | 1026 } |
1024 | 1027 |
1025 for (size_t i = 0; i < ops.size(); i++) { | 1028 for (size_t i = 0; i < ops.size(); i++) { |
1026 EXPECT_EQ(ops[i].scale_x, scale_x); | 1029 EXPECT_EQ(ops[i].scale_x, scale_x); |
1027 if (i == 0) { | 1030 if (i == 0) { |
1028 // Only the first op is allowed to be a scale up. | 1031 // Only the first op is allowed to be a scale up. |
1029 // (Scaling up *after* scaling down would make it fuzzy.) | 1032 // (Scaling up *after* scaling down would make it fuzzy.) |
1030 EXPECT_TRUE(ops[0].scale_factor == 0 || | 1033 EXPECT_TRUE(ops[0].scale_factor == 0 || ops[0].scale_factor == 2); |
1031 ops[0].scale_factor == 2); | |
1032 } else { | 1034 } else { |
1033 // All other operations must be 50% downscales. | 1035 // All other operations must be 50% downscales. |
1034 EXPECT_EQ(ops[i].scale_factor, 2); | 1036 EXPECT_EQ(ops[i].scale_factor, 2); |
1035 } | 1037 } |
1036 } | 1038 } |
1037 // Check that the scale factors make sense and add up. | 1039 // Check that the scale factors make sense and add up. |
1038 int tmp = dst; | 1040 int tmp = dst; |
1039 for (int i = static_cast<int>(ops.size() - 1); i >= 0; i--) { | 1041 for (int i = static_cast<int>(ops.size() - 1); i >= 0; i--) { |
1040 EXPECT_EQ(tmp, ops[i].scale_size); | 1042 EXPECT_EQ(tmp, ops[i].scale_size); |
1041 if (ops[i].scale_factor == 0) { | 1043 if (ops[i].scale_factor == 0) { |
1042 EXPECT_EQ(i, 0); | 1044 EXPECT_EQ(i, 0); |
1043 EXPECT_GT(tmp, src); | 1045 EXPECT_GT(tmp, src); |
1044 tmp = src; | 1046 tmp = src; |
1045 } else { | 1047 } else { |
1046 tmp *= ops[i].scale_factor; | 1048 tmp *= ops[i].scale_factor; |
1047 } | 1049 } |
1048 } | 1050 } |
1049 EXPECT_EQ(tmp, src); | 1051 EXPECT_EQ(tmp, src); |
1050 } | 1052 } |
1051 | 1053 |
1052 void CheckPipeline2(int xsize, int ysize, | 1054 void CheckPipeline2(int xsize, |
1053 int dst_xsize, int dst_ysize, | 1055 int ysize, |
1054 const std::string &description) { | 1056 int dst_xsize, |
| 1057 int dst_ysize, |
| 1058 const std::string& description) { |
1055 std::vector<GLHelperScaling::ScalerStage> stages; | 1059 std::vector<GLHelperScaling::ScalerStage> stages; |
1056 helper_scaling_->ConvertScalerOpsToScalerStages( | 1060 helper_scaling_->ConvertScalerOpsToScalerStages( |
1057 content::GLHelper::SCALER_QUALITY_GOOD, | 1061 content::GLHelper::SCALER_QUALITY_GOOD, |
1058 gfx::Size(xsize, ysize), | 1062 gfx::Size(xsize, ysize), |
1059 gfx::Rect(0, 0, xsize, ysize), | 1063 gfx::Rect(0, 0, xsize, ysize), |
1060 gfx::Size(dst_xsize, dst_ysize), | 1064 gfx::Size(dst_xsize, dst_ysize), |
1061 false, | 1065 false, |
1062 false, | 1066 false, |
1063 &x_ops_, | 1067 &x_ops_, |
1064 &y_ops_, | 1068 &y_ops_, |
1065 &stages); | 1069 &stages); |
1066 EXPECT_EQ(x_ops_.size(), 0U); | 1070 EXPECT_EQ(x_ops_.size(), 0U); |
1067 EXPECT_EQ(y_ops_.size(), 0U); | 1071 EXPECT_EQ(y_ops_.size(), 0U); |
1068 ValidateScalerStages( | 1072 ValidateScalerStages(content::GLHelper::SCALER_QUALITY_GOOD, stages, ""); |
1069 content::GLHelper::SCALER_QUALITY_GOOD, | |
1070 stages, | |
1071 ""); | |
1072 EXPECT_EQ(PrintStages(stages), description); | 1073 EXPECT_EQ(PrintStages(stages), description); |
1073 } | 1074 } |
1074 | 1075 |
1075 void CheckOptimizationsTest() { | 1076 void CheckOptimizationsTest() { |
1076 // Basic upscale. X and Y should be combined into one pass. | 1077 // Basic upscale. X and Y should be combined into one pass. |
1077 x_ops_.push_back(GLHelperScaling::ScaleOp(0, true, 2000)); | 1078 x_ops_.push_back(GLHelperScaling::ScaleOp(0, true, 2000)); |
1078 y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 2000)); | 1079 y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 2000)); |
1079 CheckPipeline2(1024, 768, 2000, 2000, | 1080 CheckPipeline2(1024, 768, 2000, 2000, "1024x768 -> 2000x2000 bilinear\n"); |
1080 "1024x768 -> 2000x2000 bilinear\n"); | |
1081 | 1081 |
1082 // X scaled 1/2, Y upscaled, should still be one pass. | 1082 // X scaled 1/2, Y upscaled, should still be one pass. |
1083 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 512)); | 1083 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 512)); |
1084 y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 2000)); | 1084 y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 2000)); |
1085 CheckPipeline2(1024, 768, 512, 2000, | 1085 CheckPipeline2(1024, 768, 512, 2000, "1024x768 -> 512x2000 bilinear\n"); |
1086 "1024x768 -> 512x2000 bilinear\n"); | |
1087 | 1086 |
1088 // X upscaled, Y scaled 1/2, one bilinear pass | 1087 // X upscaled, Y scaled 1/2, one bilinear pass |
1089 x_ops_.push_back(GLHelperScaling::ScaleOp(0, true, 2000)); | 1088 x_ops_.push_back(GLHelperScaling::ScaleOp(0, true, 2000)); |
1090 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 384)); | 1089 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 384)); |
1091 CheckPipeline2(1024, 768, 2000, 384, | 1090 CheckPipeline2(1024, 768, 2000, 384, "1024x768 -> 2000x384 bilinear\n"); |
1092 "1024x768 -> 2000x384 bilinear\n"); | |
1093 | 1091 |
1094 // X scaled 1/2, Y scaled 1/2, one bilinear pass | 1092 // X scaled 1/2, Y scaled 1/2, one bilinear pass |
1095 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 512)); | 1093 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 512)); |
1096 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 384)); | 1094 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 384)); |
1097 CheckPipeline2(1024, 768, 2000, 384, | 1095 CheckPipeline2(1024, 768, 2000, 384, "1024x768 -> 512x384 bilinear\n"); |
1098 "1024x768 -> 512x384 bilinear\n"); | |
1099 | 1096 |
1100 // X scaled 1/2, Y scaled to 60%, one bilinear2 pass. | 1097 // X scaled 1/2, Y scaled to 60%, one bilinear2 pass. |
1101 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 50)); | 1098 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 50)); |
1102 y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 120)); | 1099 y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 120)); |
1103 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 60)); | 1100 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 60)); |
1104 CheckPipeline2(100, 100, 50, 60, | 1101 CheckPipeline2(100, 100, 50, 60, "100x100 -> 50x60 bilinear2 Y\n"); |
1105 "100x100 -> 50x60 bilinear2 Y\n"); | |
1106 | 1102 |
1107 // X scaled to 60%, Y scaled 1/2, one bilinear2 pass. | 1103 // X scaled to 60%, Y scaled 1/2, one bilinear2 pass. |
1108 x_ops_.push_back(GLHelperScaling::ScaleOp(0, true, 120)); | 1104 x_ops_.push_back(GLHelperScaling::ScaleOp(0, true, 120)); |
1109 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 60)); | 1105 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 60)); |
1110 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 50)); | 1106 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 50)); |
1111 CheckPipeline2(100, 100, 50, 60, | 1107 CheckPipeline2(100, 100, 50, 60, "100x100 -> 60x50 bilinear2 X\n"); |
1112 "100x100 -> 60x50 bilinear2 X\n"); | |
1113 | 1108 |
1114 // X scaled to 60%, Y scaled 60%, one bilinear2x2 pass. | 1109 // X scaled to 60%, Y scaled 60%, one bilinear2x2 pass. |
1115 x_ops_.push_back(GLHelperScaling::ScaleOp(0, true, 120)); | 1110 x_ops_.push_back(GLHelperScaling::ScaleOp(0, true, 120)); |
1116 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 60)); | 1111 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 60)); |
1117 y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 120)); | 1112 y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 120)); |
1118 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 60)); | 1113 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 60)); |
1119 CheckPipeline2(100, 100, 60, 60, | 1114 CheckPipeline2(100, 100, 60, 60, "100x100 -> 60x60 bilinear2x2\n"); |
1120 "100x100 -> 60x60 bilinear2x2\n"); | |
1121 | 1115 |
1122 // X scaled to 40%, Y scaled 40%, two bilinear3 passes. | 1116 // X scaled to 40%, Y scaled 40%, two bilinear3 passes. |
1123 x_ops_.push_back(GLHelperScaling::ScaleOp(3, true, 40)); | 1117 x_ops_.push_back(GLHelperScaling::ScaleOp(3, true, 40)); |
1124 y_ops_.push_back(GLHelperScaling::ScaleOp(3, false, 40)); | 1118 y_ops_.push_back(GLHelperScaling::ScaleOp(3, false, 40)); |
1125 CheckPipeline2(100, 100, 40, 40, | 1119 CheckPipeline2(100, |
| 1120 100, |
| 1121 40, |
| 1122 40, |
1126 "100x100 -> 100x40 bilinear3 Y\n" | 1123 "100x100 -> 100x40 bilinear3 Y\n" |
1127 "100x40 -> 40x40 bilinear3 X\n"); | 1124 "100x40 -> 40x40 bilinear3 X\n"); |
1128 | 1125 |
1129 // X scaled to 60%, Y scaled 40% | 1126 // X scaled to 60%, Y scaled 40% |
1130 x_ops_.push_back(GLHelperScaling::ScaleOp(0, true, 120)); | 1127 x_ops_.push_back(GLHelperScaling::ScaleOp(0, true, 120)); |
1131 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 60)); | 1128 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 60)); |
1132 y_ops_.push_back(GLHelperScaling::ScaleOp(3, false, 40)); | 1129 y_ops_.push_back(GLHelperScaling::ScaleOp(3, false, 40)); |
1133 CheckPipeline2(100, 100, 60, 40, | 1130 CheckPipeline2(100, |
| 1131 100, |
| 1132 60, |
| 1133 40, |
1134 "100x100 -> 100x40 bilinear3 Y\n" | 1134 "100x100 -> 100x40 bilinear3 Y\n" |
1135 "100x40 -> 60x40 bilinear2 X\n"); | 1135 "100x40 -> 60x40 bilinear2 X\n"); |
1136 | 1136 |
1137 // X scaled to 40%, Y scaled 60% | 1137 // X scaled to 40%, Y scaled 60% |
1138 x_ops_.push_back(GLHelperScaling::ScaleOp(3, true, 40)); | 1138 x_ops_.push_back(GLHelperScaling::ScaleOp(3, true, 40)); |
1139 y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 120)); | 1139 y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 120)); |
1140 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 60)); | 1140 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 60)); |
1141 CheckPipeline2(100, 100, 40, 60, | 1141 CheckPipeline2(100, |
| 1142 100, |
| 1143 40, |
| 1144 60, |
1142 "100x100 -> 100x60 bilinear2 Y\n" | 1145 "100x100 -> 100x60 bilinear2 Y\n" |
1143 "100x60 -> 40x60 bilinear3 X\n"); | 1146 "100x60 -> 40x60 bilinear3 X\n"); |
1144 | 1147 |
1145 // X scaled to 30%, Y scaled 30% | 1148 // X scaled to 30%, Y scaled 30% |
1146 x_ops_.push_back(GLHelperScaling::ScaleOp(0, true, 120)); | 1149 x_ops_.push_back(GLHelperScaling::ScaleOp(0, true, 120)); |
1147 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 60)); | 1150 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 60)); |
1148 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 30)); | 1151 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 30)); |
1149 y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 120)); | 1152 y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 120)); |
1150 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 60)); | 1153 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 60)); |
1151 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 30)); | 1154 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 30)); |
1152 CheckPipeline2(100, 100, 30, 30, | 1155 CheckPipeline2(100, |
| 1156 100, |
| 1157 30, |
| 1158 30, |
1153 "100x100 -> 100x30 bilinear4 Y\n" | 1159 "100x100 -> 100x30 bilinear4 Y\n" |
1154 "100x30 -> 30x30 bilinear4 X\n"); | 1160 "100x30 -> 30x30 bilinear4 X\n"); |
1155 | 1161 |
1156 // X scaled to 50%, Y scaled 30% | 1162 // X scaled to 50%, Y scaled 30% |
1157 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 50)); | 1163 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 50)); |
1158 y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 120)); | 1164 y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 120)); |
1159 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 60)); | 1165 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 60)); |
1160 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 30)); | 1166 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 30)); |
1161 CheckPipeline2(100, 100, 50, 30, | 1167 CheckPipeline2(100, 100, 50, 30, "100x100 -> 50x30 bilinear4 Y\n"); |
1162 "100x100 -> 50x30 bilinear4 Y\n"); | |
1163 | 1168 |
1164 // X scaled to 150%, Y scaled 30% | 1169 // X scaled to 150%, Y scaled 30% |
1165 // Note that we avoid combinding X and Y passes | 1170 // Note that we avoid combinding X and Y passes |
1166 // as that would probably be LESS efficient here. | 1171 // as that would probably be LESS efficient here. |
1167 x_ops_.push_back(GLHelperScaling::ScaleOp(0, true, 150)); | 1172 x_ops_.push_back(GLHelperScaling::ScaleOp(0, true, 150)); |
1168 y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 120)); | 1173 y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 120)); |
1169 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 60)); | 1174 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 60)); |
1170 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 30)); | 1175 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 30)); |
1171 CheckPipeline2(100, 100, 150, 30, | 1176 CheckPipeline2(100, |
| 1177 100, |
| 1178 150, |
| 1179 30, |
1172 "100x100 -> 100x30 bilinear4 Y\n" | 1180 "100x100 -> 100x30 bilinear4 Y\n" |
1173 "100x30 -> 150x30 bilinear\n"); | 1181 "100x30 -> 150x30 bilinear\n"); |
1174 | 1182 |
1175 // X scaled to 1%, Y scaled 1% | 1183 // X scaled to 1%, Y scaled 1% |
1176 x_ops_.push_back(GLHelperScaling::ScaleOp(0, true, 128)); | 1184 x_ops_.push_back(GLHelperScaling::ScaleOp(0, true, 128)); |
1177 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 64)); | 1185 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 64)); |
1178 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 32)); | 1186 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 32)); |
1179 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 16)); | 1187 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 16)); |
1180 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 8)); | 1188 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 8)); |
1181 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 4)); | 1189 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 4)); |
1182 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 2)); | 1190 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 2)); |
1183 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 1)); | 1191 x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 1)); |
1184 y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 128)); | 1192 y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 128)); |
1185 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 64)); | 1193 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 64)); |
1186 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 32)); | 1194 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 32)); |
1187 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 16)); | 1195 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 16)); |
1188 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 8)); | 1196 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 8)); |
1189 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 4)); | 1197 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 4)); |
1190 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 2)); | 1198 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 2)); |
1191 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 1)); | 1199 y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 1)); |
1192 CheckPipeline2(100, 100, 30, 30, | 1200 CheckPipeline2(100, |
| 1201 100, |
| 1202 30, |
| 1203 30, |
1193 "100x100 -> 100x32 bilinear4 Y\n" | 1204 "100x100 -> 100x32 bilinear4 Y\n" |
1194 "100x32 -> 100x4 bilinear4 Y\n" | 1205 "100x32 -> 100x4 bilinear4 Y\n" |
1195 "100x4 -> 64x1 bilinear2x2\n" | 1206 "100x4 -> 64x1 bilinear2x2\n" |
1196 "64x1 -> 8x1 bilinear4 X\n" | 1207 "64x1 -> 8x1 bilinear4 X\n" |
1197 "8x1 -> 1x1 bilinear4 X\n"); | 1208 "8x1 -> 1x1 bilinear4 X\n"); |
1198 } | 1209 } |
1199 | 1210 |
1200 scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> context_; | 1211 scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> context_; |
1201 gpu::ContextSupport* context_support_; | 1212 gpu::ContextSupport* context_support_; |
1202 scoped_ptr<content::GLHelper> helper_; | 1213 scoped_ptr<content::GLHelper> helper_; |
1203 scoped_ptr<content::GLHelperScaling> helper_scaling_; | 1214 scoped_ptr<content::GLHelperScaling> helper_scaling_; |
1204 std::deque<GLHelperScaling::ScaleOp> x_ops_, y_ops_; | 1215 std::deque<GLHelperScaling::ScaleOp> x_ops_, y_ops_; |
1205 }; | 1216 }; |
1206 | 1217 |
1207 TEST_F(GLHelperTest, YUVReadbackOptTest) { | 1218 TEST_F(GLHelperTest, YUVReadbackOptTest) { |
1208 // This test uses the cb_command tracing events to detect how many | 1219 // This test uses the cb_command tracing events to detect how many |
1209 // scaling passes are actually performed by the YUV readback pipeline. | 1220 // scaling passes are actually performed by the YUV readback pipeline. |
1210 StartTracing(TRACE_DISABLED_BY_DEFAULT("cb_command")); | 1221 StartTracing(TRACE_DISABLED_BY_DEFAULT("cb_command")); |
1211 | 1222 |
1212 TestYUVReadback( | 1223 TestYUVReadback(800, |
1213 800, 400, | 1224 400, |
1214 800, 400, | 1225 800, |
1215 0, 0, | 1226 400, |
1216 1, | 1227 0, |
1217 false, | 1228 0, |
1218 true, | 1229 1, |
1219 content::GLHelper::SCALER_QUALITY_FAST); | 1230 false, |
| 1231 true, |
| 1232 content::GLHelper::SCALER_QUALITY_FAST); |
1220 | 1233 |
1221 std::map<std::string, int> event_counts; | 1234 std::map<std::string, int> event_counts; |
1222 EndTracing(&event_counts); | 1235 EndTracing(&event_counts); |
1223 int draw_buffer_calls = event_counts["kDrawBuffersEXTImmediate"]; | 1236 int draw_buffer_calls = event_counts["kDrawBuffersEXTImmediate"]; |
1224 int draw_arrays_calls = event_counts["kDrawArrays"]; | 1237 int draw_arrays_calls = event_counts["kDrawArrays"]; |
1225 VLOG(1) << "Draw buffer calls: " << draw_buffer_calls; | 1238 VLOG(1) << "Draw buffer calls: " << draw_buffer_calls; |
1226 VLOG(1) << "DrawArrays calls: " << draw_arrays_calls; | 1239 VLOG(1) << "DrawArrays calls: " << draw_arrays_calls; |
1227 | 1240 |
1228 if (draw_buffer_calls) { | 1241 if (draw_buffer_calls) { |
1229 // When using MRT, the YUV readback code should only | 1242 // When using MRT, the YUV readback code should only |
1230 // execute two draw arrays, and scaling should be integrated | 1243 // execute two draw arrays, and scaling should be integrated |
1231 // into those two calls since we are using the FAST scalign | 1244 // into those two calls since we are using the FAST scalign |
1232 // quality. | 1245 // quality. |
1233 EXPECT_EQ(2, draw_arrays_calls); | 1246 EXPECT_EQ(2, draw_arrays_calls); |
1234 } else { | 1247 } else { |
1235 // When not using MRT, there are three passes for the YUV, | 1248 // When not using MRT, there are three passes for the YUV, |
1236 // and one for the scaling. | 1249 // and one for the scaling. |
1237 EXPECT_EQ(4, draw_arrays_calls); | 1250 EXPECT_EQ(4, draw_arrays_calls); |
1238 } | 1251 } |
1239 } | 1252 } |
1240 | 1253 |
1241 TEST_F(GLHelperTest, YUVReadbackTest) { | 1254 TEST_F(GLHelperTest, YUVReadbackTest) { |
1242 int sizes[] = { 2, 4, 14 }; | 1255 int sizes[] = {2, 4, 14}; |
1243 for (int flip = 0; flip <= 1; flip++) { | 1256 for (int flip = 0; flip <= 1; flip++) { |
1244 for (int use_mrt = 0; use_mrt <= 1; use_mrt++) { | 1257 for (int use_mrt = 0; use_mrt <= 1; use_mrt++) { |
1245 for (unsigned int x = 0; x < arraysize(sizes); x++) { | 1258 for (unsigned int x = 0; x < arraysize(sizes); x++) { |
1246 for (unsigned int y = 0; y < arraysize(sizes); y++) { | 1259 for (unsigned int y = 0; y < arraysize(sizes); y++) { |
1247 for (unsigned int ox = x; ox < arraysize(sizes); ox++) { | 1260 for (unsigned int ox = x; ox < arraysize(sizes); ox++) { |
1248 for (unsigned int oy = y; oy < arraysize(sizes); oy++) { | 1261 for (unsigned int oy = y; oy < arraysize(sizes); oy++) { |
1249 // If output is a subsection of the destination frame, (letterbox) | 1262 // If output is a subsection of the destination frame, (letterbox) |
1250 // then try different variations of where the subsection goes. | 1263 // then try different variations of where the subsection goes. |
1251 for (Margin xm = x < ox ? MarginLeft : MarginRight; | 1264 for (Margin xm = x < ox ? MarginLeft : MarginRight; |
1252 xm <= MarginRight; | 1265 xm <= MarginRight; |
1253 xm = NextMargin(xm)) { | 1266 xm = NextMargin(xm)) { |
1254 for (Margin ym = y < oy ? MarginLeft : MarginRight; | 1267 for (Margin ym = y < oy ? MarginLeft : MarginRight; |
1255 ym <= MarginRight; | 1268 ym <= MarginRight; |
1256 ym = NextMargin(ym)) { | 1269 ym = NextMargin(ym)) { |
1257 for (int pattern = 0; pattern < 3; pattern++) { | 1270 for (int pattern = 0; pattern < 3; pattern++) { |
1258 TestYUVReadback( | 1271 TestYUVReadback(sizes[x], |
1259 sizes[x], | 1272 sizes[y], |
1260 sizes[y], | 1273 sizes[ox], |
1261 sizes[ox], | 1274 sizes[oy], |
1262 sizes[oy], | 1275 compute_margin(sizes[x], sizes[ox], xm), |
1263 compute_margin(sizes[x], sizes[ox], xm), | 1276 compute_margin(sizes[y], sizes[oy], ym), |
1264 compute_margin(sizes[y], sizes[oy], ym), | 1277 pattern, |
1265 pattern, | 1278 flip == 1, |
1266 flip == 1, | 1279 use_mrt == 1, |
1267 use_mrt == 1, | 1280 content::GLHelper::SCALER_QUALITY_GOOD); |
1268 content::GLHelper::SCALER_QUALITY_GOOD); | |
1269 if (HasFailure()) { | 1281 if (HasFailure()) { |
1270 return; | 1282 return; |
1271 } | 1283 } |
1272 } | 1284 } |
1273 } | 1285 } |
1274 } | 1286 } |
1275 } | 1287 } |
1276 } | 1288 } |
1277 } | 1289 } |
1278 } | 1290 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1311 } | 1323 } |
1312 | 1324 |
1313 // Validate that all scaling generates valid pipelines. | 1325 // Validate that all scaling generates valid pipelines. |
1314 TEST_F(GLHelperTest, ValidateScalerPipelines) { | 1326 TEST_F(GLHelperTest, ValidateScalerPipelines) { |
1315 int sizes[] = {7, 99, 128, 256, 512, 719, 720, 721, 1920, 2011, 3217, 4096}; | 1327 int sizes[] = {7, 99, 128, 256, 512, 719, 720, 721, 1920, 2011, 3217, 4096}; |
1316 for (size_t q = 0; q < arraysize(kQualities); q++) { | 1328 for (size_t q = 0; q < arraysize(kQualities); q++) { |
1317 for (size_t x = 0; x < arraysize(sizes); x++) { | 1329 for (size_t x = 0; x < arraysize(sizes); x++) { |
1318 for (size_t y = 0; y < arraysize(sizes); y++) { | 1330 for (size_t y = 0; y < arraysize(sizes); y++) { |
1319 for (size_t dst_x = 0; dst_x < arraysize(sizes); dst_x++) { | 1331 for (size_t dst_x = 0; dst_x < arraysize(sizes); dst_x++) { |
1320 for (size_t dst_y = 0; dst_y < arraysize(sizes); dst_y++) { | 1332 for (size_t dst_y = 0; dst_y < arraysize(sizes); dst_y++) { |
1321 TestScalerPipeline(q, | 1333 TestScalerPipeline( |
1322 sizes[x], sizes[y], | 1334 q, sizes[x], sizes[y], sizes[dst_x], sizes[dst_y]); |
1323 sizes[dst_x], sizes[dst_y]); | |
1324 if (HasFailure()) { | 1335 if (HasFailure()) { |
1325 return; | 1336 return; |
1326 } | 1337 } |
1327 } | 1338 } |
1328 } | 1339 } |
1329 } | 1340 } |
1330 } | 1341 } |
1331 } | 1342 } |
1332 } | 1343 } |
1333 | 1344 |
1334 // Make sure we don't create overly complicated pipelines | 1345 // Make sure we don't create overly complicated pipelines |
1335 // for a few common use cases. | 1346 // for a few common use cases. |
1336 TEST_F(GLHelperTest, CheckSpecificPipelines) { | 1347 TEST_F(GLHelperTest, CheckSpecificPipelines) { |
1337 // Upscale should be single pass. | 1348 // Upscale should be single pass. |
1338 CheckPipeline(content::GLHelper::SCALER_QUALITY_GOOD, | 1349 CheckPipeline(content::GLHelper::SCALER_QUALITY_GOOD, |
1339 1024, 700, 1280, 720, | 1350 1024, |
| 1351 700, |
| 1352 1280, |
| 1353 720, |
1340 "1024x700 -> 1280x720 bilinear\n"); | 1354 "1024x700 -> 1280x720 bilinear\n"); |
1341 // Slight downscale should use BILINEAR2X2. | 1355 // Slight downscale should use BILINEAR2X2. |
1342 CheckPipeline(content::GLHelper::SCALER_QUALITY_GOOD, | 1356 CheckPipeline(content::GLHelper::SCALER_QUALITY_GOOD, |
1343 1280, 720, 1024, 700, | 1357 1280, |
| 1358 720, |
| 1359 1024, |
| 1360 700, |
1344 "1280x720 -> 1024x700 bilinear2x2\n"); | 1361 "1280x720 -> 1024x700 bilinear2x2\n"); |
1345 // Most common tab capture pipeline on the Pixel. | 1362 // Most common tab capture pipeline on the Pixel. |
1346 // Should be using two BILINEAR3 passes. | 1363 // Should be using two BILINEAR3 passes. |
1347 CheckPipeline(content::GLHelper::SCALER_QUALITY_GOOD, | 1364 CheckPipeline(content::GLHelper::SCALER_QUALITY_GOOD, |
1348 2560, 1476, 1249, 720, | 1365 2560, |
| 1366 1476, |
| 1367 1249, |
| 1368 720, |
1349 "2560x1476 -> 2560x720 bilinear3 Y\n" | 1369 "2560x1476 -> 2560x720 bilinear3 Y\n" |
1350 "2560x720 -> 1249x720 bilinear3 X\n"); | 1370 "2560x720 -> 1249x720 bilinear3 X\n"); |
1351 } | 1371 } |
1352 | 1372 |
1353 TEST_F(GLHelperTest, ScalerOpTest) { | 1373 TEST_F(GLHelperTest, ScalerOpTest) { |
1354 for (int allow3 = 0; allow3 <= 1; allow3++) { | 1374 for (int allow3 = 0; allow3 <= 1; allow3++) { |
1355 for (int dst = 1; dst < 2049; dst += 1 + (dst >> 3)) { | 1375 for (int dst = 1; dst < 2049; dst += 1 + (dst >> 3)) { |
1356 for (int src = 1; src < 2049; src++) { | 1376 for (int src = 1; src < 2049; src++) { |
1357 TestAddOps(src, dst, allow3 == 1, (src & 1) == 1); | 1377 TestAddOps(src, dst, allow3 == 1, (src & 1) == 1); |
1358 if (HasFailure()) { | 1378 if (HasFailure()) { |
1359 LOG(ERROR) << "Failed for src=" << src | 1379 LOG(ERROR) << "Failed for src=" << src << " dst=" << dst |
1360 << " dst=" << dst | |
1361 << " allow3=" << allow3; | 1380 << " allow3=" << allow3; |
1362 return; | 1381 return; |
1363 } | 1382 } |
1364 } | 1383 } |
1365 } | 1384 } |
1366 } | 1385 } |
1367 } | 1386 } |
1368 | 1387 |
1369 TEST_F(GLHelperTest, CheckOptimizations) { | 1388 TEST_F(GLHelperTest, CheckOptimizations) { |
1370 // Test in baseclass since it is friends with GLHelperScaling | 1389 // Test in baseclass since it is friends with GLHelperScaling |
(...skipping 13 matching lines...) Expand all Loading... |
1384 #if defined(TOOLKIT_GTK) | 1403 #if defined(TOOLKIT_GTK) |
1385 gfx::GtkInitFromCommandLine(*CommandLine::ForCurrentProcess()); | 1404 gfx::GtkInitFromCommandLine(*CommandLine::ForCurrentProcess()); |
1386 #endif | 1405 #endif |
1387 gfx::GLSurface::InitializeOneOff(); | 1406 gfx::GLSurface::InitializeOneOff(); |
1388 gpu::ApplyGpuDriverBugWorkarounds(CommandLine::ForCurrentProcess()); | 1407 gpu::ApplyGpuDriverBugWorkarounds(CommandLine::ForCurrentProcess()); |
1389 | 1408 |
1390 content::UnitTestTestSuite runner(suite); | 1409 content::UnitTestTestSuite runner(suite); |
1391 base::MessageLoop message_loop; | 1410 base::MessageLoop message_loop; |
1392 return runner.Run(); | 1411 return runner.Run(); |
1393 } | 1412 } |
OLD | NEW |