Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(62)

Side by Side Diff: content/common/gpu/client/gl_helper_unittests.cc

Issue 117233006: Port content::GLHelper over to GLES2Interface (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: NULL-check gl->GetString(GL_EXTENSIONS) Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « content/common/gpu/client/gl_helper_scaling.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « content/common/gpu/client/gl_helper_scaling.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698