190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file. 490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <stdio.h> 690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <cmath> 790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <string> 890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <vector> 990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <GLES2/gl2.h> 1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <GLES2/gl2ext.h> 1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <GLES2/gl2extchromium.h> 1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/at_exit.h" 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/bind.h" 1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/command_line.h" 1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/file_util.h" 189ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/run_loop.h" 207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/stringprintf.h" 21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "content/common/gpu/client/gl_helper.h" 2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "content/common/gpu/client/gl_helper_scaling.h" 2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "content/public/test/unittest_test_suite.h" 2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "content/test/content_test_suite.h" 26558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "gpu/config/gpu_util.h" 27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "media/base/video_frame.h" 2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h" 3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "third_party/skia/include/core/SkTypes.h" 3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/gl/gl_surface.h" 3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h" 3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(OS_MACOSX) 3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/mac/scoped_nsautorelease_pool.h" 3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif 3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(TOOLKIT_GTK) 3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/gfx/gtk_util.h" 4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif 4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace content { 4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using WebKit::WebGLId; 457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)using WebKit::WebGraphicsContext3D; 4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)content::GLHelper::ScalerQuality kQualities[] = { 4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) content::GLHelper::SCALER_QUALITY_BEST, 4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) content::GLHelper::SCALER_QUALITY_GOOD, 5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) content::GLHelper::SCALER_QUALITY_FAST, 5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}; 5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char *kQualityNames[] = { 5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "best", 5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "good", 5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "fast", 5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}; 5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class GLHelperTest : public testing::Test { 6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) protected: 6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual void SetUp() { 6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) WebGraphicsContext3D::Attributes attributes; 63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch context_ = webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl:: 64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateOffscreenContext(attributes); 6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) context_->makeContextCurrent(); 6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) helper_.reset(new content::GLHelper(context_.get())); 6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) helper_scaling_.reset(new content::GLHelperScaling( 6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) context_.get(), 6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) helper_.get())); 7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual void TearDown() { 7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) helper_scaling_.reset(NULL); 7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) helper_.reset(NULL); 7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) context_.reset(NULL); 7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Bicubic filter kernel function. 7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) static float Bicubic(float x) { 8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const float a = -0.5; 8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x = std::abs(x); 8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) float x2 = x * x; 8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) float x3 = x2 * x; 8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (x <= 1) { 8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return (a + 2) * x3 - (a + 3) * x2 + 1; 8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else if (x < 2) { 8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return a * x3 - 5 * a * x2 + 8 * a * x - 4 * a; 8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return 0.0f; 9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Look up a single R/G/B/A value. 9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Clamp x/y. 9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int Channel(SkBitmap* pixels, int x, int y, int c) { 9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) uint32 *data = pixels->getAddr32( 9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::max(0, std::min(x, pixels->width() - 1)), 9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::max(0, std::min(y, pixels->height() - 1))); 9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return (*data) >> (c * 8) & 0xff; 10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Set a single R/G/B/A value. 10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void SetChannel(SkBitmap* pixels, int x, int y, int c, int v) { 10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_GE(x, 0); 10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_GE(y, 0); 10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_LT(x, pixels->width()); 10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_LT(y, pixels->height()); 10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) uint32 *data = pixels->getAddr32(x, y); 10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) v = std::max(0, std::min(v, 255)); 11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) *data = (*data & ~(0xffu << (c * 8))) | (v << (c * 8)); 11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Print all the R, G, B or A values from an SkBitmap in a 11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // human-readable format. 11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void PrintChannel(SkBitmap* pixels, int c) { 11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int y = 0; y < pixels->height(); y++) { 11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int x = 0; x < pixels->width(); x++) { 11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) printf("%3d, ", Channel(pixels, x, y, c)); 11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) printf("\n"); 12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Print out the individual steps of a scaler pipeline. 12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string PrintStages( 12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::vector<GLHelperScaling::ScalerStage> &scaler_stages) { 12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string ret; 12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (size_t i = 0; i < scaler_stages.size(); i++) { 12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ret.append(base::StringPrintf("%dx%d -> %dx%d ", 13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scaler_stages[i].src_size.width(), 13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scaler_stages[i].src_size.height(), 13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scaler_stages[i].dst_size.width(), 13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scaler_stages[i].dst_size.height())); 13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) bool xy_matters = false; 13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) switch (scaler_stages[i].shader) { 13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case GLHelperScaling::SHADER_BILINEAR: 13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ret.append("bilinear"); 13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case GLHelperScaling::SHADER_BILINEAR2: 14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ret.append("bilinear2"); 14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) xy_matters = true; 14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case GLHelperScaling::SHADER_BILINEAR3: 14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ret.append("bilinear3"); 14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) xy_matters = true; 14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case GLHelperScaling::SHADER_BILINEAR4: 14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ret.append("bilinear4"); 14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) xy_matters = true; 15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case GLHelperScaling::SHADER_BILINEAR2X2: 15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ret.append("bilinear2x2"); 15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case GLHelperScaling::SHADER_BICUBIC_UPSCALE: 15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ret.append("bicubic upscale"); 15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) xy_matters = true; 15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case GLHelperScaling::SHADER_BICUBIC_HALF_1D: 15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ret.append("bicubic 1/2"); 16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) xy_matters = true; 16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case GLHelperScaling::SHADER_PLANAR: 163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ret.append("planar"); 164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) break; 165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case GLHelperScaling::SHADER_YUV_MRT_PASS1: 166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ret.append("rgb2yuv pass 1"); 167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) break; 168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case GLHelperScaling::SHADER_YUV_MRT_PASS2: 169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ret.append("rgb2yuv pass 2"); 170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) break; 17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (xy_matters) { 17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (scaler_stages[i].scale_x) { 17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ret.append(" X"); 17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ret.append(" Y"); 17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ret.append("\n"); 18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return ret; 18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) bool CheckScale(double scale, int samples, bool already_scaled) { 18690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // 1:1 is valid if there is one sample. 18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (samples == 1 && scale == 1.0) { 18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return true; 18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Is it an exact down-scale (50%, 25%, etc.?) 19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (scale == 2.0 * samples) { 19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return true; 19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Upscales, only valid if we haven't already scaled in this dimension. 19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!already_scaled) { 19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Is it a valid bilinear upscale? 19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (samples == 1 && scale <= 1.0) { 19890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return true; 19990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 20090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Multi-sample upscale-downscale combination? 20190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (scale > samples / 2.0 && scale < samples) { 20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return true; 20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 20590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return false; 20690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 20890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Make sure that the stages of the scaler pipeline are sane. 20990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void ValidateScalerStages( 21090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) content::GLHelper::ScalerQuality quality, 21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::vector<GLHelperScaling::ScalerStage> &scaler_stages, 21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string& message) { 21390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) bool previous_error = HasFailure(); 21490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // First, check that the input size for each stage is equal to 21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // the output size of the previous stage. 21690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (size_t i = 1; i < scaler_stages.size(); i++) { 21790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(scaler_stages[i - 1].dst_size.width(), 21890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scaler_stages[i].src_size.width()); 21990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(scaler_stages[i - 1].dst_size.height(), 22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scaler_stages[i].src_size.height()); 22190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(scaler_stages[i].src_subrect.x(), 0); 22290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(scaler_stages[i].src_subrect.y(), 0); 22390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(scaler_stages[i].src_subrect.width(), 22490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scaler_stages[i].src_size.width()); 22590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(scaler_stages[i].src_subrect.height(), 22690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scaler_stages[i].src_size.height()); 22790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 22890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Used to verify that up-scales are not attempted after some 23090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // other scale. 23190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) bool scaled_x = false; 23290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) bool scaled_y = false; 23390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (size_t i = 0; i < scaler_stages.size(); i++) { 23590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Note: 2.0 means scaling down by 50% 23690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) double x_scale = 23790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) static_cast<double>(scaler_stages[i].src_subrect.width()) / 23890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) static_cast<double>(scaler_stages[i].dst_size.width()); 23990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) double y_scale = 24090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) static_cast<double>(scaler_stages[i].src_subrect.height()) / 24190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) static_cast<double>(scaler_stages[i].dst_size.height()); 24290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 24390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int x_samples = 0; 24490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int y_samples = 0; 24590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 24690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Codify valid scale operations. 24790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) switch (scaler_stages[i].shader) { 248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case GLHelperScaling::SHADER_PLANAR: 249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case GLHelperScaling::SHADER_YUV_MRT_PASS1: 250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case GLHelperScaling::SHADER_YUV_MRT_PASS2: 251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_TRUE(false) << "Invalid shader."; 252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) break; 253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 25490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case GLHelperScaling::SHADER_BILINEAR: 25590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (quality != content::GLHelper::SCALER_QUALITY_FAST) { 25690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_samples = 1; 25790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_samples = 1; 25890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 25990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 26090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case GLHelperScaling::SHADER_BILINEAR2: 26190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_samples = 2; 26290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_samples = 1; 26390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case GLHelperScaling::SHADER_BILINEAR3: 26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_samples = 3; 26690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_samples = 1; 26790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 26890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case GLHelperScaling::SHADER_BILINEAR4: 26990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_samples = 4; 27090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_samples = 1; 27190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 27290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case GLHelperScaling::SHADER_BILINEAR2X2: 27390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_samples = 2; 27490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_samples = 2; 27590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 27690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case GLHelperScaling::SHADER_BICUBIC_UPSCALE: 27790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (scaler_stages[i].scale_x) { 27890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_LT(x_scale, 1.0); 27990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(y_scale, 1.0); 28090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 28190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(x_scale, 1.0); 28290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_LT(y_scale, 1.0); 28390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 28490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 28590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case GLHelperScaling::SHADER_BICUBIC_HALF_1D: 28690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (scaler_stages[i].scale_x) { 28790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(x_scale, 2.0); 28890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(y_scale, 1.0); 28990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 29090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(x_scale, 1.0); 29190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(y_scale, 2.0); 29290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 29390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 29490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 29590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 29690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!scaler_stages[i].scale_x) { 29790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::swap(x_samples, y_samples); 29890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 29990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 30090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (x_samples) { 30190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_TRUE(CheckScale(x_scale, x_samples, scaled_x)) 30290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) << "x_scale = " << x_scale; 30390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 30490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (y_samples) { 30590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_TRUE(CheckScale(y_scale, y_samples, scaled_y)) 30690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) << "y_scale = " << y_scale; 30790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 30890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 30990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (x_scale != 1.0) { 31090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scaled_x = true; 31190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 31290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (y_scale != 1.0) { 31390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scaled_y = true; 31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 31590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 31690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 31790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (HasFailure() && !previous_error) { 31890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) printf("Invalid scaler stages: %s\n", message.c_str()); 31990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) printf("Scaler stages:\n%s", PrintStages(scaler_stages).c_str()); 32090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 32190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 32290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 32390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Compare two bitmaps, make sure that each component of each pixel 32490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // is no more than |maxdiff| apart. If they are not similar enough, 32590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // prints out |truth|, |other|, |source|, |scaler_stages| and |message|. 32690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void Compare(SkBitmap* truth, 32790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SkBitmap* other, 32890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int maxdiff, 32990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SkBitmap* source, 33090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::vector<GLHelperScaling::ScalerStage> &scaler_stages, 33190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string message) { 33290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(truth->width(), other->width()); 33390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(truth->height(), other->height()); 33490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int x = 0; x < truth->width(); x++) { 33590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int y = 0; y < truth->height(); y++) { 33690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int c = 0; c < 4; c++) { 33790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int a = Channel(truth, x, y, c); 33890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int b = Channel(other, x, y, c); 33990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_NEAR(a, b, maxdiff) 34090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) << " x=" << x 34190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) << " y=" << y 34290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) << " c=" << c 34390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) << " " << message; 34490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (std::abs(a - b) > maxdiff) { 34590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) printf("-------expected--------\n"); 34690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) PrintChannel(truth, c); 34790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) printf("-------actual--------\n"); 34890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) PrintChannel(other, c); 34990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (source) { 35090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) printf("-------before scaling--------\n"); 35190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) PrintChannel(source, c); 35290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 35390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) printf("-----Scaler stages------\n%s", 35490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) PrintStages(scaler_stages).c_str()); 35590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 35690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 35790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 35890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 35990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 36090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 36190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 36290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Get a single R, G, B or A value as a float. 36390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) float ChannelAsFloat(SkBitmap* pixels, int x, int y, int c) { 36490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return Channel(pixels, x, y, c) / 255.0; 36590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 36690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 36790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Works like a GL_LINEAR lookup on an SkBitmap. 36890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) float Bilinear(SkBitmap* pixels, float x, float y, int c) { 36990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x -= 0.5; 37090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y -= 0.5; 37190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int base_x = static_cast<int>(floorf(x)); 37290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int base_y = static_cast<int>(floorf(y)); 37390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x -= base_x; 37490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y -= base_y; 37590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return (ChannelAsFloat(pixels, base_x, base_y, c) * (1 - x) * (1 - y) + 37690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ChannelAsFloat(pixels, base_x + 1, base_y, c) * x * (1 - y) + 37790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ChannelAsFloat(pixels, base_x, base_y + 1, c) * (1 - x) * y + 37890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ChannelAsFloat(pixels, base_x + 1, base_y + 1, c) * x * y); 37990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 38090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 38190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Very slow bicubic / bilinear scaler for reference. 38290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void ScaleSlow(SkBitmap* input, 38390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SkBitmap* output, 38490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) content::GLHelper::ScalerQuality quality) { 38590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) float xscale = static_cast<float>(input->width()) / output->width(); 38690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) float yscale = static_cast<float>(input->height()) / output->height(); 38790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) float clamped_xscale = xscale < 1.0 ? 1.0 : 1.0 / xscale; 38890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) float clamped_yscale = yscale < 1.0 ? 1.0 : 1.0 / yscale; 38990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int dst_y = 0; dst_y < output->height(); dst_y++) { 39090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int dst_x = 0; dst_x < output->width(); dst_x++) { 39190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int channel = 0; channel < 4; channel++) { 39290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) float dst_x_in_src = (dst_x + 0.5f) * xscale; 39390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) float dst_y_in_src = (dst_y + 0.5f) * yscale; 39490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 39590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) float value = 0.0f; 39690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) float sum = 0.0f; 39790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) switch (quality) { 39890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case content::GLHelper::SCALER_QUALITY_BEST: 39990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int src_y = -10; src_y < input->height() + 10; ++src_y) { 40090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) float coeff_y = Bicubic( 40190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) (src_y + 0.5f - dst_y_in_src) * clamped_yscale); 40290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (coeff_y == 0.0f) { 40390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) continue; 40490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 40590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int src_x = -10; src_x < input->width() + 10; ++src_x) { 40690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) float coeff = coeff_y * Bicubic( 40790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) (src_x + 0.5f - dst_x_in_src) * clamped_xscale); 40890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (coeff == 0.0f) { 40990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) continue; 41090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 41190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) sum += coeff; 41290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) float c = ChannelAsFloat(input, src_x, src_y, channel); 41390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) value += c * coeff; 41490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 41590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 41690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 41790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 41890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case content::GLHelper::SCALER_QUALITY_GOOD: { 41990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int xshift = 0, yshift = 0; 42090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) while ((output->width() << xshift) < input->width()) { 42190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) xshift++; 42290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 42390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) while ((output->height() << yshift) < input->height()) { 42490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) yshift++; 42590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 42690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int xmag = 1 << xshift; 42790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int ymag = 1 << yshift; 42890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (xmag == 4 && output->width() * 3 >= input->width()) { 42990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) xmag=3; 43090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 43190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (ymag == 4 && output->height() * 3 >= input->height()) { 43290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ymag=3; 43390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 43490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int x = 0; x < xmag; x++) { 43590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int y = 0; y < ymag; y++) { 43690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) value += Bilinear(input, 43790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) (dst_x * xmag + x + 0.5) * xscale / xmag, 43890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) (dst_y * ymag + y + 0.5) * yscale / ymag, 43990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) channel); 44090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) sum += 1.0; 44190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 44290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 44390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 44490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 44590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 44690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case content::GLHelper::SCALER_QUALITY_FAST: 44790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) value = Bilinear(input, dst_x_in_src, dst_y_in_src, channel); 44890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) sum = 1.0; 44990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 45090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) value /= sum; 45190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SetChannel(output, dst_x, dst_y, channel, 45290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) static_cast<int>(value * 255.0f + 0.5f)); 45390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 45490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 45590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 45690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 45790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 45890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 45990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // gl_helper scales recursively, so we'll need to do that 46090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // in the reference implementation too. 46190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void ScaleSlowRecursive(SkBitmap* input, SkBitmap* output, 46290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) content::GLHelper::ScalerQuality quality) { 46390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (quality == content::GLHelper::SCALER_QUALITY_FAST || 46490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) quality == content::GLHelper::SCALER_QUALITY_GOOD) { 46590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ScaleSlow(input, output, quality); 46690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 46790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 46890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 46990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) float xscale = static_cast<float>(output->width()) / input->width(); 47090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 47190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // This corresponds to all the operations we can do directly. 47290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) float yscale = static_cast<float>(output->height()) / input->height(); 47390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if ((xscale == 1.0f && yscale == 1.0f) || 47490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) (xscale == 0.5f && yscale == 1.0f) || 47590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) (xscale == 1.0f && yscale == 0.5f) || 47690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) (xscale >= 1.0f && yscale == 1.0f) || 47790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) (xscale == 1.0f && yscale >= 1.0f)) { 47890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ScaleSlow(input, output, quality); 47990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 48090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 48190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 48290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Now we break the problem down into smaller pieces, using the 48390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // operations available. 48490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int xtmp = input->width(); 48590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int ytmp = input->height(); 48690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 48790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (output->height() != input->height()) { 48890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ytmp = output->height(); 48990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) while (ytmp < input->height() && ytmp * 2 != input->height()) { 49090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ytmp += ytmp; 49190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 49290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 49390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) xtmp = output->width(); 49490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) while (xtmp < input->width() && xtmp * 2 != input->width()) { 49590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) xtmp += xtmp; 49690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 49790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 49890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 49990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SkBitmap tmp; 50090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) tmp.setConfig(SkBitmap::kARGB_8888_Config, xtmp, ytmp); 50190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) tmp.allocPixels(); 50290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SkAutoLockPixels lock(tmp); 50390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 50490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ScaleSlowRecursive(input, &tmp, quality); 50590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ScaleSlowRecursive(&tmp, output, quality); 50690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 50790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 50890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Scaling test: Create a test image, scale it using GLHelperScaling 50990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // and a reference implementation and compare the results. 51090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void TestScale(int xsize, int ysize, 51190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int scaled_xsize, int scaled_ysize, 51290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int test_pattern, 51390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) size_t quality) { 51490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) WebGLId src_texture = context_->createTexture(); 51590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) WebGLId framebuffer = context_->createFramebuffer(); 51690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SkBitmap input_pixels; 51790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) input_pixels.setConfig(SkBitmap::kARGB_8888_Config, xsize, ysize); 51890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) input_pixels.allocPixels(); 51990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SkAutoLockPixels lock(input_pixels); 52090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 52190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int x = 0; x < xsize; ++x) { 52290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int y = 0; y < ysize; ++y) { 52390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) switch (test_pattern) { 524868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case 0: // Smooth test pattern 52590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SetChannel(&input_pixels, x, y, 0, x * 10); 52690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SetChannel(&input_pixels, x, y, 1, y * 10); 52790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SetChannel(&input_pixels, x, y, 2, (x + y) * 10); 52890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SetChannel(&input_pixels, x, y, 3, 255); 52990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 530868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case 1: // Small blocks 53190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SetChannel(&input_pixels, x, y, 0, x & 1 ? 255 : 0); 53290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SetChannel(&input_pixels, x, y, 1, y & 1 ? 255 : 0); 53390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SetChannel(&input_pixels, x, y, 2, (x + y) & 1 ? 255 : 0); 53490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SetChannel(&input_pixels, x, y, 3, 255); 53590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 536868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case 2: // Medium blocks 53790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SetChannel(&input_pixels, x, y, 0, 10 + x/2 * 50); 53890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SetChannel(&input_pixels, x, y, 1, 10 + y/3 * 50); 53990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SetChannel(&input_pixels, x, y, 2, (x + y)/5 * 50 + 5); 54090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SetChannel(&input_pixels, x, y, 3, 255); 54190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 54290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 54390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 54490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 54590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 54690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) context_->bindFramebuffer(GL_FRAMEBUFFER, framebuffer); 54790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) context_->bindTexture(GL_TEXTURE_2D, src_texture); 54890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) context_->texImage2D(GL_TEXTURE_2D, 54990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 0, 55090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) GL_RGBA, 55190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) xsize, 55290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ysize, 55390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 0, 55490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) GL_RGBA, 55590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) GL_UNSIGNED_BYTE, 55690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) input_pixels.getPixels()); 55790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 55890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string message = base::StringPrintf("input size: %dx%d " 55990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "output size: %dx%d " 56090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "pattern: %d quality: %s", 56190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) xsize, ysize, 56290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scaled_xsize, scaled_ysize, 56390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) test_pattern, 56490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) kQualityNames[quality]); 56590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 56690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 56790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<GLHelperScaling::ScalerStage> stages; 56890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) helper_scaling_->ComputeScalerStages( 56990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) kQualities[quality], 57090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) gfx::Size(xsize, ysize), 57190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) gfx::Rect(0, 0, xsize, ysize), 57290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) gfx::Size(scaled_xsize, scaled_ysize), 57390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) false, 57490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) false, 57590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &stages); 57690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ValidateScalerStages(kQualities[quality], stages, message); 57790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 57890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) WebGLId dst_texture = helper_->CopyAndScaleTexture( 57990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) src_texture, 58090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) gfx::Size(xsize, ysize), 58190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) gfx::Size(scaled_xsize, scaled_ysize), 58290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) false, 58390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) kQualities[quality]); 58490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 58590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SkBitmap output_pixels; 58690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) output_pixels.setConfig(SkBitmap::kARGB_8888_Config, 58790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scaled_xsize, scaled_ysize); 58890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) output_pixels.allocPixels(); 58990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SkAutoLockPixels output_lock(output_pixels); 59090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 59190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) helper_->ReadbackTextureSync( 59290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) dst_texture, 59390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) gfx::Rect(0, 0, scaled_xsize, scaled_ysize), 59490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) static_cast<unsigned char *>(output_pixels.getPixels())); 59590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 59690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (xsize == scaled_xsize && ysize == scaled_ysize) { 59790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) Compare(&input_pixels, 59890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &output_pixels, 59990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2, 60090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) NULL, 60190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stages, 60290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) message + " comparing against input"); 60390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 60490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SkBitmap truth_pixels; 60590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) truth_pixels.setConfig(SkBitmap::kARGB_8888_Config, 60690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scaled_xsize, scaled_ysize); 60790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) truth_pixels.allocPixels(); 60890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SkAutoLockPixels truth_lock(truth_pixels); 60990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 61090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ScaleSlowRecursive(&input_pixels, &truth_pixels, kQualities[quality]); 61190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) Compare(&truth_pixels, 61290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &output_pixels, 61390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2, 61490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &input_pixels, 61590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stages, 61690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) message + " comparing against scaled"); 61790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 61890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) context_->deleteTexture(src_texture); 61990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) context_->deleteTexture(dst_texture); 62090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) context_->deleteFramebuffer(framebuffer); 62190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 62290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 62390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Create a scaling pipeline and check that it is made up of 62490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // valid scaling operations. 62590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void TestScalerPipeline(size_t quality, 62690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int xsize, int ysize, 62790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int dst_xsize, int dst_ysize) { 62890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<GLHelperScaling::ScalerStage> stages; 62990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) helper_scaling_->ComputeScalerStages( 63090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) kQualities[quality], 63190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) gfx::Size(xsize, ysize), 63290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) gfx::Rect(0, 0, xsize, ysize), 63390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) gfx::Size(dst_xsize, dst_ysize), 63490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) false, 63590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) false, 63690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &stages); 63790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ValidateScalerStages(kQualities[quality], stages, 63890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::StringPrintf("input size: %dx%d " 63990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "output size: %dx%d " 64090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "quality: %s", 64190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) xsize, ysize, 64290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) dst_xsize, dst_ysize, 64390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) kQualityNames[quality])); 64490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 64590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 64690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Create a scaling pipeline and make sure that the steps 64790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // are exactly the steps we expect. 64890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void CheckPipeline(content::GLHelper::ScalerQuality quality, 64990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int xsize, int ysize, 65090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int dst_xsize, int dst_ysize, 65190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string &description) { 65290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<GLHelperScaling::ScalerStage> stages; 65390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) helper_scaling_->ComputeScalerStages( 65490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) quality, 65590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) gfx::Size(xsize, ysize), 65690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) gfx::Rect(0, 0, xsize, ysize), 65790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) gfx::Size(dst_xsize, dst_ysize), 65890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) false, 65990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) false, 66090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &stages); 66190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ValidateScalerStages( 66290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) content::GLHelper::SCALER_QUALITY_GOOD, 66390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stages, 66490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ""); 66590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(PrintStages(stages), description); 66690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 66790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 668868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Note: Left/Right means Top/Bottom when used for Y dimension. 669868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) enum Margin { 670868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) MarginLeft, 671868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) MarginMiddle, 672868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) MarginRight, 673868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) MarginInvalid, 674868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) }; 675868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 676868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) static Margin NextMargin(Margin m) { 677868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) switch (m) { 678868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case MarginLeft: 679868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return MarginMiddle; 680868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case MarginMiddle: 681868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return MarginRight; 682868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case MarginRight: 683868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return MarginInvalid; 684868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) default: 685868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return MarginInvalid; 686868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 687868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 688868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 689868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int compute_margin(int insize, int outsize, Margin m) { 690868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int available = outsize - insize; 691868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) switch (m) { 692868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) default: 693868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_TRUE(false) << "This should not happen."; 694868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return 0; 695868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case MarginLeft: 696868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return 0; 697868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case MarginMiddle: 698868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return (available / 2) & ~1; 699868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case MarginRight: 700868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return available; 701868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 702868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 703868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 704868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Convert 0.0 - 1.0 to 0 - 255 705868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int float_to_byte(float v) { 706868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int ret = static_cast<int>(floorf(v * 255.0f + 0.5f)); 707868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (ret < 0) { 708868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return 0; 709868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 710868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (ret > 255) { 711868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return 255; 712868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 713868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return ret; 714868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 715868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 716868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) static void callcallback(const base::Callback<void()>& callback, 717868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bool result) { 718868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) callback.Run(); 719868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 720868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 721868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) void PrintPlane(unsigned char *plane, int xsize, int stride, int ysize) { 722868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (int y = 0; y < ysize; y++) { 723868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (int x = 0; x < xsize ; x++) { 724868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) printf("%3d, ", plane[y * stride + x]); 725868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 726868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) printf(" (%p)\n", plane + y * stride); 727868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 728868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 729868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 730868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Compare two planes make sure that each component of each pixel 731868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // is no more than |maxdiff| apart. 732868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) void ComparePlane(unsigned char* truth, 733868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) unsigned char* other, 734868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int maxdiff, 735868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int xsize, 736868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int stride, 737868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int ysize, 738868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SkBitmap* source, 739868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string message) { 740868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (int x = 0; x < xsize; x++) { 741868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (int y = 0; y < ysize; y++) { 742868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int a = other[y * stride + x]; 743868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int b = truth[y * stride + x]; 744868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_NEAR(a, b, maxdiff) 745868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) << " x=" << x 746868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) << " y=" << y 747868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) << " " << message; 748868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (std::abs(a - b) > maxdiff) { 749868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) printf("-------expected--------\n"); 750868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PrintPlane(truth, xsize, stride, ysize); 751868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) printf("-------actual--------\n"); 752868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PrintPlane(other, xsize, stride, ysize); 753868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (source) { 754868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) printf("-------before yuv conversion: red--------\n"); 755868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PrintChannel(source, 0); 756868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) printf("-------before yuv conversion: green------\n"); 757868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PrintChannel(source, 1); 758868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) printf("-------before yuv conversion: blue-------\n"); 759868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PrintChannel(source, 2); 760868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 761868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 762868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 763868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 764868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 765868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 766868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 767868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // YUV readback test. Create a test pattern, convert to YUV 768868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // with reference implementation and compare to what gl_helper 769868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // returns. 770868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) void TestYUVReadback(int xsize, 771868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int ysize, 772868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int output_xsize, 773868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int output_ysize, 774868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int xmargin, 775868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int ymargin, 776868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int test_pattern, 777868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bool use_mrt) { 778868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) WebGLId src_texture = context_->createTexture(); 779868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SkBitmap input_pixels; 780868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) input_pixels.setConfig(SkBitmap::kARGB_8888_Config, xsize, ysize); 781868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) input_pixels.allocPixels(); 782868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SkAutoLockPixels lock(input_pixels); 783868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 784868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (int x = 0; x < xsize; ++x) { 785868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (int y = 0; y < ysize; ++y) { 786868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) switch (test_pattern) { 787868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case 0: // Smooth test pattern 788868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SetChannel(&input_pixels, x, y, 0, x * 10); 789868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SetChannel(&input_pixels, x, y, 1, y * 10); 790868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SetChannel(&input_pixels, x, y, 2, (x + y) * 10); 791868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SetChannel(&input_pixels, x, y, 3, 255); 792868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) break; 793868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case 1: // Small blocks 794868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SetChannel(&input_pixels, x, y, 0, x & 1 ? 255 : 0); 795868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SetChannel(&input_pixels, x, y, 1, y & 1 ? 255 : 0); 796868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SetChannel(&input_pixels, x, y, 2, (x + y) & 1 ? 255 : 0); 797868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SetChannel(&input_pixels, x, y, 3, 255); 798868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) break; 799868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case 2: // Medium blocks 800868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SetChannel(&input_pixels, x, y, 0, 10 + x/2 * 50); 801868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SetChannel(&input_pixels, x, y, 1, 10 + y/3 * 50); 802868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SetChannel(&input_pixels, x, y, 2, (x + y)/5 * 50 + 5); 803868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SetChannel(&input_pixels, x, y, 3, 255); 804868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) break; 805868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 806868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 807868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 808868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 809868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) context_->bindTexture(GL_TEXTURE_2D, src_texture); 810868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) context_->texImage2D(GL_TEXTURE_2D, 811868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 0, 812868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GL_RGBA, 813868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) xsize, 814868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ysize, 815868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 0, 816868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GL_RGBA, 817868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GL_UNSIGNED_BYTE, 818868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) input_pixels.getPixels()); 819868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 8207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch gpu::Mailbox mailbox; 8217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch context_->genMailboxCHROMIUM(mailbox.name); 8227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_FALSE(mailbox.IsZero()); 8237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch context_->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); 8247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch uint32 sync_point = context_->insertSyncPoint(); 8257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 826868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string message = base::StringPrintf("input size: %dx%d " 827868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "output size: %dx%d " 828868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "margin: %dx%d " 829868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "pattern: %d", 830868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) xsize, ysize, 831868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) output_xsize, output_ysize, 832868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) xmargin, ymargin, 833868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) test_pattern); 834868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<ReadbackYUVInterface> yuv_reader( 835868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) helper_->CreateReadbackPipelineYUV( 836868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) content::GLHelper::SCALER_QUALITY_GOOD, 837868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Size(xsize, ysize), 838868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Rect(0, 0, xsize, ysize), 839868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Size(output_xsize, output_ysize), 840868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Rect(xmargin, ymargin, xsize, ysize), 841868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) false, 842868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) use_mrt)); 843868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 844868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_refptr<media::VideoFrame> output_frame = 845868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) media::VideoFrame::CreateFrame( 846868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) media::VideoFrame::YV12, 847868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Size(output_xsize, output_ysize), 848868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Rect(0, 0, output_xsize, output_ysize), 849868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Size(output_xsize, output_ysize), 850868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::TimeDelta::FromSeconds(0)); 851868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_refptr<media::VideoFrame> truth_frame = 852868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) media::VideoFrame::CreateFrame( 853868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) media::VideoFrame::YV12, 854868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Size(output_xsize, output_ysize), 855868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Rect(0, 0, output_xsize, output_ysize), 856868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Size(output_xsize, output_ysize), 857868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::TimeDelta::FromSeconds(0)); 858868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 859868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::RunLoop run_loop; 860868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) yuv_reader->ReadbackYUV( 8617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch mailbox, 8627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch sync_point, 863868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) output_frame.get(), 864868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::Bind(&callcallback, run_loop.QuitClosure())); 865868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) run_loop.Run(); 866868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 867868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) unsigned char* Y = truth_frame->data(media::VideoFrame::kYPlane); 868868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) unsigned char* U = truth_frame->data(media::VideoFrame::kUPlane); 869868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) unsigned char* V = truth_frame->data(media::VideoFrame::kVPlane); 870868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int32 y_stride = truth_frame->stride(media::VideoFrame::kYPlane); 871868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int32 u_stride = truth_frame->stride(media::VideoFrame::kUPlane); 872868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int32 v_stride = truth_frame->stride(media::VideoFrame::kVPlane); 873868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) memset(Y, 0x00, y_stride * output_ysize); 874868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) memset(U, 0x80, u_stride * output_ysize / 2); 875868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) memset(V, 0x80, v_stride * output_ysize / 2); 876868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 877868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (int y = 0; y < ysize; y++) { 878868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (int x = 0; x < xsize; x++) { 879868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Y[(y + ymargin) * y_stride + x + xmargin] = float_to_byte( 880868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ChannelAsFloat(&input_pixels, x, y, 0) * 0.257 + 881868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ChannelAsFloat(&input_pixels, x, y, 1) * 0.504 + 882868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ChannelAsFloat(&input_pixels, x, y, 2) * 0.098 + 883868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 0.0625); 884868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 885868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 886868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 887868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (int y = 0; y < ysize / 2; y++) { 888868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (int x = 0; x < xsize / 2; x++) { 889868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) U[(y + ymargin / 2) * u_stride + x + xmargin / 2] = 890868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) float_to_byte( 891868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 0) * -0.148 + 892868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 1) * -0.291 + 893868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 2) * 0.439 + 894868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 0.5); 895868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) V[(y + ymargin / 2) * v_stride + x + xmargin / 2] = 896868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) float_to_byte( 897868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 0) * 0.439 + 898868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 1) * -0.368 + 899868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 2) * -0.071 + 900868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 0.5); 901868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 902868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 903868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 904868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ComparePlane(Y, output_frame->data(media::VideoFrame::kYPlane), 2, 905868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) output_xsize, y_stride, output_ysize, 906868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) &input_pixels, 907868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) message + " Y plane"); 908868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ComparePlane(U, output_frame->data(media::VideoFrame::kUPlane), 2, 909868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) output_xsize / 2, u_stride, output_ysize / 2, 910868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) &input_pixels, 911868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) message + " U plane"); 912868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ComparePlane(V, output_frame->data(media::VideoFrame::kVPlane), 2, 913868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) output_xsize / 2, v_stride, output_ysize / 2, 914868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) &input_pixels, 915868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) message + " V plane"); 916868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 917868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) context_->deleteTexture(src_texture); 918868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 919868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 92090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void TestAddOps(int src, 92190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int dst, 92290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) bool scale_x, 92390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) bool allow3) { 92490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::deque<GLHelperScaling::ScaleOp> ops; 92590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) GLHelperScaling::ScaleOp::AddOps(src, dst, scale_x, allow3, &ops); 92690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Scale factor 3 is a special case. 92790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // It is currently only allowed by itself. 92890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (allow3 && dst * 3 >= src && dst * 2 < src) { 92990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(ops[0].scale_factor, 3); 93090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(ops.size(), 1U); 93190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(ops[0].scale_x, scale_x); 93290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(ops[0].scale_size, dst); 93390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 93490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 93590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 93690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (size_t i = 0; i < ops.size(); i++) { 93790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(ops[i].scale_x, scale_x); 93890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (i == 0) { 93990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Only the first op is allowed to be a scale up. 94090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // (Scaling up *after* scaling down would make it fuzzy.) 94190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_TRUE(ops[0].scale_factor == 0 || 94290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ops[0].scale_factor == 2); 94390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 94490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // All other operations must be 50% downscales. 94590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(ops[i].scale_factor, 2); 94690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 94790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 94890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Check that the scale factors make sense and add up. 94990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int tmp = dst; 95090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int i = static_cast<int>(ops.size() - 1); i >= 0; i--) { 95190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(tmp, ops[i].scale_size); 95290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (ops[i].scale_factor == 0) { 95390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(i, 0); 95490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_GT(tmp, src); 95590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) tmp = src; 95690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 95790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) tmp *= ops[i].scale_factor; 95890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 95990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 96090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(tmp, src); 96190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 96290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 96390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void CheckPipeline2(int xsize, int ysize, 96490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int dst_xsize, int dst_ysize, 96590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string &description) { 96690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<GLHelperScaling::ScalerStage> stages; 96790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) helper_scaling_->ConvertScalerOpsToScalerStages( 96890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) content::GLHelper::SCALER_QUALITY_GOOD, 96990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) gfx::Size(xsize, ysize), 97090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) gfx::Rect(0, 0, xsize, ysize), 97190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) gfx::Size(dst_xsize, dst_ysize), 97290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) false, 97390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) false, 97490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &x_ops_, 97590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &y_ops_, 97690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &stages); 97790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(x_ops_.size(), 0U); 97890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(y_ops_.size(), 0U); 97990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ValidateScalerStages( 98090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) content::GLHelper::SCALER_QUALITY_GOOD, 98190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stages, 98290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ""); 98390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(PrintStages(stages), description); 98490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 98590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 98690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void CheckOptimizationsTest() { 98790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Basic upscale. X and Y should be combined into one pass. 98890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_ops_.push_back(GLHelperScaling::ScaleOp(0, true, 2000)); 98990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 2000)); 99090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CheckPipeline2(1024, 768, 2000, 2000, 99190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "1024x768 -> 2000x2000 bilinear\n"); 99290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 99390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // X scaled 1/2, Y upscaled, should still be one pass. 99490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 512)); 99590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 2000)); 99690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CheckPipeline2(1024, 768, 512, 2000, 99790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "1024x768 -> 512x2000 bilinear\n"); 99890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 99990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // X upscaled, Y scaled 1/2, one bilinear pass 100090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_ops_.push_back(GLHelperScaling::ScaleOp(0, true, 2000)); 100190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 384)); 100290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CheckPipeline2(1024, 768, 2000, 384, 100390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "1024x768 -> 2000x384 bilinear\n"); 100490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 100590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // X scaled 1/2, Y scaled 1/2, one bilinear pass 100690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 512)); 100790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 384)); 100890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CheckPipeline2(1024, 768, 2000, 384, 100990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "1024x768 -> 512x384 bilinear\n"); 101090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 101190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // X scaled 1/2, Y scaled to 60%, one bilinear2 pass. 101290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 50)); 101390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 120)); 101490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 60)); 101590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CheckPipeline2(100, 100, 50, 60, 101690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "100x100 -> 50x60 bilinear2 Y\n"); 101790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 101890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // X scaled to 60%, Y scaled 1/2, one bilinear2 pass. 101990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_ops_.push_back(GLHelperScaling::ScaleOp(0, true, 120)); 102090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 60)); 102190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 50)); 102290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CheckPipeline2(100, 100, 50, 60, 102390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "100x100 -> 60x50 bilinear2 X\n"); 102490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 102590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // X scaled to 60%, Y scaled 60%, one bilinear2x2 pass. 102690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_ops_.push_back(GLHelperScaling::ScaleOp(0, true, 120)); 102790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 60)); 102890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 120)); 102990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 60)); 103090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CheckPipeline2(100, 100, 60, 60, 103190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "100x100 -> 60x60 bilinear2x2\n"); 103290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 103390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // X scaled to 40%, Y scaled 40%, two bilinear3 passes. 103490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_ops_.push_back(GLHelperScaling::ScaleOp(3, true, 40)); 103590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(3, false, 40)); 103690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CheckPipeline2(100, 100, 40, 40, 103790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "100x100 -> 100x40 bilinear3 Y\n" 103890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "100x40 -> 40x40 bilinear3 X\n"); 103990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 104090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // X scaled to 60%, Y scaled 40% 104190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_ops_.push_back(GLHelperScaling::ScaleOp(0, true, 120)); 104290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 60)); 104390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(3, false, 40)); 104490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CheckPipeline2(100, 100, 60, 40, 104590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "100x100 -> 100x40 bilinear3 Y\n" 104690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "100x40 -> 60x40 bilinear2 X\n"); 104790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 104890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // X scaled to 40%, Y scaled 60% 104990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_ops_.push_back(GLHelperScaling::ScaleOp(3, true, 40)); 105090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 120)); 105190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 60)); 105290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CheckPipeline2(100, 100, 40, 60, 105390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "100x100 -> 100x60 bilinear2 Y\n" 105490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "100x60 -> 40x60 bilinear3 X\n"); 105590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 105690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // X scaled to 30%, Y scaled 30% 105790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_ops_.push_back(GLHelperScaling::ScaleOp(0, true, 120)); 105890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 60)); 105990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 30)); 106090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 120)); 106190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 60)); 106290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 30)); 106390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CheckPipeline2(100, 100, 30, 30, 106490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "100x100 -> 100x30 bilinear4 Y\n" 106590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "100x30 -> 30x30 bilinear4 X\n"); 106690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 106790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // X scaled to 50%, Y scaled 30% 106890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 50)); 106990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 120)); 107090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 60)); 107190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 30)); 107290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CheckPipeline2(100, 100, 50, 30, 107390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "100x100 -> 50x30 bilinear4 Y\n"); 107490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 107590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // X scaled to 150%, Y scaled 30% 107690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Note that we avoid combinding X and Y passes 107790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // as that would probably be LESS efficient here. 107890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_ops_.push_back(GLHelperScaling::ScaleOp(0, true, 150)); 107990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 120)); 108090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 60)); 108190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 30)); 108290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CheckPipeline2(100, 100, 150, 30, 108390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "100x100 -> 100x30 bilinear4 Y\n" 108490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "100x30 -> 150x30 bilinear\n"); 108590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 108690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // X scaled to 1%, Y scaled 1% 108790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_ops_.push_back(GLHelperScaling::ScaleOp(0, true, 128)); 108890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 64)); 108990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 32)); 109090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 16)); 109190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 8)); 109290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 4)); 109390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 2)); 109490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 1)); 109590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 128)); 109690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 64)); 109790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 32)); 109890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 16)); 109990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 8)); 110090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 4)); 110190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 2)); 110290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 1)); 110390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CheckPipeline2(100, 100, 30, 30, 110490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "100x100 -> 100x32 bilinear4 Y\n" 110590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "100x32 -> 100x4 bilinear4 Y\n" 110690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "100x4 -> 64x1 bilinear2x2\n" 110790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "64x1 -> 8x1 bilinear4 X\n" 110890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "8x1 -> 1x1 bilinear4 X\n"); 110990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 111090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 111190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<WebKit::WebGraphicsContext3D> context_; 111290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<content::GLHelper> helper_; 111390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<content::GLHelperScaling> helper_scaling_; 111490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::deque<GLHelperScaling::ScaleOp> x_ops_, y_ops_; 111590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}; 111690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 11177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Reenable once http://crbug.com/162291 is fixed. 1118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(GLHelperTest, YUVReadbackTest) { 1119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int sizes[] = { 2, 4, 14 }; 1120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (int use_mrt = 0; use_mrt <= 1 ; use_mrt++) { 1121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (unsigned int x = 0; x < arraysize(sizes); x++) { 1122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (unsigned int y = 0; y < arraysize(sizes); y++) { 1123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (unsigned int ox = x; ox < arraysize(sizes); ox++) { 1124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (unsigned int oy = y; oy < arraysize(sizes); oy++) { 1125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // If output is a subsection of the destination frame, (letterbox) 1126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // then try different variations of where the subsection goes. 1127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (Margin xm = x < ox ? MarginLeft : MarginRight; 1128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) xm <= MarginRight; 1129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) xm = NextMargin(xm)) { 1130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (Margin ym = y < oy ? MarginLeft : MarginRight; 1131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ym <= MarginRight; 1132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ym = NextMargin(ym)) { 1133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (int pattern = 0; pattern < 3; pattern++) { 1134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) TestYUVReadback( 1135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) sizes[x], 1136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) sizes[y], 1137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) sizes[ox], 1138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) sizes[oy], 1139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) compute_margin(sizes[x], sizes[ox], xm), 1140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) compute_margin(sizes[y], sizes[oy], ym), 1141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) pattern, 1142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) use_mrt == 1); 1143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (HasFailure()) { 1144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 1145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 1146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 1147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 1148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 1149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 1150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 1151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 1152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 1153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 1154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 1155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 115790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Per pixel tests, all sizes are small so that we can print 115890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// out the generated bitmaps. 115990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(GLHelperTest, ScaleTest) { 116090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int sizes[] = {3, 6, 16}; 116190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (size_t q = 0; q < arraysize(kQualities); q++) { 116290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int x = 0; x < 3; x++) { 116390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int y = 0; y < 3; y++) { 116490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int dst_x = 0; dst_x < 3; dst_x++) { 116590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int dst_y = 0; dst_y < 3; dst_y++) { 116690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int pattern = 0; pattern < 3; pattern++) { 116790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) TestScale(sizes[x], 116890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) sizes[y], 116990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) sizes[dst_x], 117090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) sizes[dst_y], 117190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) pattern, 117290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) q); 117390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (HasFailure()) { 117490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 117590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 117690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 117790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 117890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 117990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 118090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 118190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 118290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 118390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 118490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Validate that all scaling generates valid pipelines. 118590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(GLHelperTest, ValidateScalerPipelines) { 118690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int sizes[] = {7, 99, 128, 256, 512, 719, 720, 721, 1920, 2011, 3217, 4096}; 118790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (size_t q = 0; q < arraysize(kQualities); q++) { 118890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (size_t x = 0; x < arraysize(sizes); x++) { 118990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (size_t y = 0; y < arraysize(sizes); y++) { 119090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (size_t dst_x = 0; dst_x < arraysize(sizes); dst_x++) { 119190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (size_t dst_y = 0; dst_y < arraysize(sizes); dst_y++) { 119290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) TestScalerPipeline(q, 119390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) sizes[x], sizes[y], 119490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) sizes[dst_x], sizes[dst_y]); 119590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (HasFailure()) { 119690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 119790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 119890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 119990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 120090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 120190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 120290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 120390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 120490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 120590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Make sure we don't create overly complicated pipelines 120690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// for a few common use cases. 120790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(GLHelperTest, CheckSpecificPipelines) { 120890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Upscale should be single pass. 120990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CheckPipeline(content::GLHelper::SCALER_QUALITY_GOOD, 121090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1024, 700, 1280, 720, 121190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "1024x700 -> 1280x720 bilinear\n"); 121290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Slight downscale should use BILINEAR2X2. 121390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CheckPipeline(content::GLHelper::SCALER_QUALITY_GOOD, 121490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1280, 720, 1024, 700, 121590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "1280x720 -> 1024x700 bilinear2x2\n"); 121690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Most common tab capture pipeline on the Pixel. 121790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Should be using two BILINEAR3 passes. 121890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CheckPipeline(content::GLHelper::SCALER_QUALITY_GOOD, 121990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2560, 1476, 1249, 720, 122090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "2560x1476 -> 2560x720 bilinear3 Y\n" 122190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "2560x720 -> 1249x720 bilinear3 X\n"); 122290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 122390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 122490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(GLHelperTest, ScalerOpTest) { 122590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int allow3 = 0; allow3 <= 1; allow3++) { 122690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int dst = 1; dst < 2049; dst += 1 + (dst >> 3)) { 122790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int src = 1; src < 2049; src++) { 122890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) TestAddOps(src, dst, allow3 == 1, (src & 1) == 1); 122990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (HasFailure()) { 123090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) LOG(ERROR) << "Failed for src=" << src 123190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) << " dst=" << dst 123290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) << " allow3=" << allow3; 123390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 123490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 123590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 123690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 123790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 123890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 123990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 124090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(GLHelperTest, CheckOptimizations) { 124190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Test in baseclass since it is friends with GLHelperScaling 124290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CheckOptimizationsTest(); 124390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 124490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 124590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace 124690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 124790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// These tests needs to run against a proper GL environment, so we 124890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// need to set it up before we can run the tests. 124990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int main(int argc, char** argv) { 125090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CommandLine::Init(argc, argv); 125190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::TestSuite* suite = new content::ContentTestSuite(argc, argv); 125290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(OS_MACOSX) 125390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::mac::ScopedNSAutoreleasePool pool; 125490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif 125590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(TOOLKIT_GTK) 125690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) gfx::GtkInitFromCommandLine(*CommandLine::ForCurrentProcess()); 125790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif 125890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) gfx::GLSurface::InitializeOneOff(); 1259558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch gpu::ApplyGpuDriverBugWorkarounds(CommandLine::ForCurrentProcess()); 126090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) content::UnitTestTestSuite runner(suite); 1262868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::MessageLoop message_loop; 1263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return runner.Run(); 126490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 1265