1*e1eccf28SAndroid Build Coastguard Worker /* <lambda>null2*e1eccf28SAndroid Build Coastguard Worker * Copyright (C) 2021 The Android Open Source Project 3*e1eccf28SAndroid Build Coastguard Worker * 4*e1eccf28SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*e1eccf28SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*e1eccf28SAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*e1eccf28SAndroid Build Coastguard Worker * 8*e1eccf28SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*e1eccf28SAndroid Build Coastguard Worker * 10*e1eccf28SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*e1eccf28SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*e1eccf28SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*e1eccf28SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*e1eccf28SAndroid Build Coastguard Worker * limitations under the License. 15*e1eccf28SAndroid Build Coastguard Worker */ 16*e1eccf28SAndroid Build Coastguard Worker 17*e1eccf28SAndroid Build Coastguard Worker // TODO Rename to something better 18*e1eccf28SAndroid Build Coastguard Worker package com.example.testapp 19*e1eccf28SAndroid Build Coastguard Worker 20*e1eccf28SAndroid Build Coastguard Worker import android.content.Context 21*e1eccf28SAndroid Build Coastguard Worker import android.graphics.Bitmap 22*e1eccf28SAndroid Build Coastguard Worker import android.graphics.BitmapFactory 23*e1eccf28SAndroid Build Coastguard Worker import android.renderscript.RenderScript 24*e1eccf28SAndroid Build Coastguard Worker import android.renderscript.toolkit.BlendingMode 25*e1eccf28SAndroid Build Coastguard Worker import android.renderscript.toolkit.LookupTable 26*e1eccf28SAndroid Build Coastguard Worker import android.renderscript.toolkit.Range2d 27*e1eccf28SAndroid Build Coastguard Worker import android.renderscript.toolkit.Rgba3dArray 28*e1eccf28SAndroid Build Coastguard Worker import android.renderscript.toolkit.Toolkit 29*e1eccf28SAndroid Build Coastguard Worker import android.renderscript.toolkit.YuvFormat 30*e1eccf28SAndroid Build Coastguard Worker import kotlin.math.abs 31*e1eccf28SAndroid Build Coastguard Worker import kotlin.math.min 32*e1eccf28SAndroid Build Coastguard Worker 33*e1eccf28SAndroid Build Coastguard Worker data class TestLayout( 34*e1eccf28SAndroid Build Coastguard Worker val sizeX: Int, 35*e1eccf28SAndroid Build Coastguard Worker val sizeY: Int, 36*e1eccf28SAndroid Build Coastguard Worker val restriction: Range2d? 37*e1eccf28SAndroid Build Coastguard Worker ) 38*e1eccf28SAndroid Build Coastguard Worker 39*e1eccf28SAndroid Build Coastguard Worker // List of dimensions (sizeX, sizeY) to try when generating random data. 40*e1eccf28SAndroid Build Coastguard Worker val commonLayoutsToTry = listOf( 41*e1eccf28SAndroid Build Coastguard Worker // Small layouts to start with 42*e1eccf28SAndroid Build Coastguard Worker TestLayout(3, 4, null), 43*e1eccf28SAndroid Build Coastguard Worker TestLayout(3, 4, Range2d(0, 1, 0, 3)), 44*e1eccf28SAndroid Build Coastguard Worker TestLayout(3, 4, Range2d(2, 3, 1, 4)), 45*e1eccf28SAndroid Build Coastguard Worker TestLayout(10, 14, null), 46*e1eccf28SAndroid Build Coastguard Worker TestLayout(10, 14, Range2d(2, 3, 8, 14)), 47*e1eccf28SAndroid Build Coastguard Worker // The size of most CTS intrinsic tests 48*e1eccf28SAndroid Build Coastguard Worker TestLayout(160, 100, null), 49*e1eccf28SAndroid Build Coastguard Worker TestLayout(125, 227, Range2d(50, 125, 100, 227)), 50*e1eccf28SAndroid Build Coastguard Worker // A larger one 51*e1eccf28SAndroid Build Coastguard Worker TestLayout(800, 600, null), 52*e1eccf28SAndroid Build Coastguard Worker // Weirdly shaped ones 53*e1eccf28SAndroid Build Coastguard Worker TestLayout(1, 1, null), // A single item 54*e1eccf28SAndroid Build Coastguard Worker // TODO This size makes Intrinsic Blur fail. 55*e1eccf28SAndroid Build Coastguard Worker TestLayout(16000, 1, null), // A single item 56*e1eccf28SAndroid Build Coastguard Worker TestLayout(1, 16000, null), // One large row 57*e1eccf28SAndroid Build Coastguard Worker // A very large test 58*e1eccf28SAndroid Build Coastguard Worker TestLayout(1024, 2048, null), 59*e1eccf28SAndroid Build Coastguard Worker ) 60*e1eccf28SAndroid Build Coastguard Worker 61*e1eccf28SAndroid Build Coastguard Worker 62*e1eccf28SAndroid Build Coastguard Worker class Tester(context: Context, private val validate: Boolean) { 63*e1eccf28SAndroid Build Coastguard Worker private val renderscriptContext = RenderScript.create(context) 64*e1eccf28SAndroid Build Coastguard Worker private val toolkit = Toolkit() 65*e1eccf28SAndroid Build Coastguard Worker private val testImage1 = BitmapFactory.decodeResource(context.resources, R.drawable.img800x450a) 66*e1eccf28SAndroid Build Coastguard Worker private val testImage2 = BitmapFactory.decodeResource(context.resources, R.drawable.img800x450b) 67*e1eccf28SAndroid Build Coastguard Worker 68*e1eccf28SAndroid Build Coastguard Worker init { 69*e1eccf28SAndroid Build Coastguard Worker validateTestImage(testImage1) 70*e1eccf28SAndroid Build Coastguard Worker validateTestImage(testImage2) 71*e1eccf28SAndroid Build Coastguard Worker } 72*e1eccf28SAndroid Build Coastguard Worker 73*e1eccf28SAndroid Build Coastguard Worker /** 74*e1eccf28SAndroid Build Coastguard Worker * Verify that the test images are in format that works for our tests. 75*e1eccf28SAndroid Build Coastguard Worker */ 76*e1eccf28SAndroid Build Coastguard Worker private fun validateTestImage(bitmap: Bitmap) { 77*e1eccf28SAndroid Build Coastguard Worker require(bitmap.config == Bitmap.Config.ARGB_8888) 78*e1eccf28SAndroid Build Coastguard Worker require(bitmap.rowBytes == bitmap.width * 4) { 79*e1eccf28SAndroid Build Coastguard Worker "Can't handle bitmaps that have extra padding. " + 80*e1eccf28SAndroid Build Coastguard Worker "${bitmap.rowBytes} != ${bitmap.width} * 4." } 81*e1eccf28SAndroid Build Coastguard Worker require(bitmap.byteCount == bitmap.rowBytes * bitmap.height) 82*e1eccf28SAndroid Build Coastguard Worker } 83*e1eccf28SAndroid Build Coastguard Worker 84*e1eccf28SAndroid Build Coastguard Worker fun destroy() { 85*e1eccf28SAndroid Build Coastguard Worker renderscriptContext.destroy() 86*e1eccf28SAndroid Build Coastguard Worker } 87*e1eccf28SAndroid Build Coastguard Worker 88*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 89*e1eccf28SAndroid Build Coastguard Worker fun testAll(timer: TimingTracker): String { 90*e1eccf28SAndroid Build Coastguard Worker val tests = listOf( 91*e1eccf28SAndroid Build Coastguard Worker Pair("blend", ::testBlend), 92*e1eccf28SAndroid Build Coastguard Worker Pair("blur", ::testBlur), 93*e1eccf28SAndroid Build Coastguard Worker Pair("colorMatrix", ::testColorMatrix), 94*e1eccf28SAndroid Build Coastguard Worker Pair("convolve", ::testConvolve), 95*e1eccf28SAndroid Build Coastguard Worker Pair("histogram", ::testHistogram), 96*e1eccf28SAndroid Build Coastguard Worker Pair("lut", ::testLut), 97*e1eccf28SAndroid Build Coastguard Worker Pair("lut3d", ::testLut3d), 98*e1eccf28SAndroid Build Coastguard Worker Pair("resize", ::testResize), 99*e1eccf28SAndroid Build Coastguard Worker Pair("yuvToRgb", ::testYuvToRgb), 100*e1eccf28SAndroid Build Coastguard Worker ) 101*e1eccf28SAndroid Build Coastguard Worker val results = Array(tests.size) { "" } 102*e1eccf28SAndroid Build Coastguard Worker for (i in tests.indices) { 103*e1eccf28SAndroid Build Coastguard Worker val (name, test) = tests[i] 104*e1eccf28SAndroid Build Coastguard Worker println("Doing $name") 105*e1eccf28SAndroid Build Coastguard Worker val success = test(timer) 106*e1eccf28SAndroid Build Coastguard Worker results[i] = "$name " + if (success) "succeeded" else "FAILED! FAILED! FAILED! FAILED!" 107*e1eccf28SAndroid Build Coastguard Worker println(" ${results[i]}") 108*e1eccf28SAndroid Build Coastguard Worker } 109*e1eccf28SAndroid Build Coastguard Worker 110*e1eccf28SAndroid Build Coastguard Worker return results.joinToString("\n") 111*e1eccf28SAndroid Build Coastguard Worker } 112*e1eccf28SAndroid Build Coastguard Worker 113*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 114*e1eccf28SAndroid Build Coastguard Worker private fun testBlend(timer: TimingTracker): Boolean { 115*e1eccf28SAndroid Build Coastguard Worker return BlendingMode.values().all { mode -> 116*e1eccf28SAndroid Build Coastguard Worker testOneBitmapBlend(timer, testImage1, testImage2, mode, null) and 117*e1eccf28SAndroid Build Coastguard Worker testOneBitmapBlend( 118*e1eccf28SAndroid Build Coastguard Worker timer, testImage1, testImage2, mode, 119*e1eccf28SAndroid Build Coastguard Worker Range2d(6, 23, 2, 4) 120*e1eccf28SAndroid Build Coastguard Worker ) and 121*e1eccf28SAndroid Build Coastguard Worker commonLayoutsToTry.all { (sizeX, sizeY, restriction) -> 122*e1eccf28SAndroid Build Coastguard Worker testOneRandomBlend(timer, sizeX, sizeY, mode, restriction) 123*e1eccf28SAndroid Build Coastguard Worker } 124*e1eccf28SAndroid Build Coastguard Worker } 125*e1eccf28SAndroid Build Coastguard Worker } 126*e1eccf28SAndroid Build Coastguard Worker 127*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 128*e1eccf28SAndroid Build Coastguard Worker private fun testOneRandomBlend( 129*e1eccf28SAndroid Build Coastguard Worker timer: TimingTracker, 130*e1eccf28SAndroid Build Coastguard Worker sizeX: Int, 131*e1eccf28SAndroid Build Coastguard Worker sizeY: Int, 132*e1eccf28SAndroid Build Coastguard Worker mode: BlendingMode, 133*e1eccf28SAndroid Build Coastguard Worker restriction: Range2d? 134*e1eccf28SAndroid Build Coastguard Worker ): Boolean { 135*e1eccf28SAndroid Build Coastguard Worker val sourceArray = randomByteArray(0x50521f0, sizeX, sizeY, 4) 136*e1eccf28SAndroid Build Coastguard Worker val destArray = randomByteArray(0x2932147, sizeX, sizeY, 4) 137*e1eccf28SAndroid Build Coastguard Worker // Make clones because these will be modified by the blend. 138*e1eccf28SAndroid Build Coastguard Worker val intrinsicDestArray = destArray.clone() 139*e1eccf28SAndroid Build Coastguard Worker val referenceDestArray = destArray.clone() 140*e1eccf28SAndroid Build Coastguard Worker val toolkitDestArray = destArray.clone() 141*e1eccf28SAndroid Build Coastguard Worker 142*e1eccf28SAndroid Build Coastguard Worker timer.measure("IntrinsicBlend") { 143*e1eccf28SAndroid Build Coastguard Worker intrinsicBlend( 144*e1eccf28SAndroid Build Coastguard Worker renderscriptContext, mode, sourceArray, intrinsicDestArray, sizeX, sizeY, 145*e1eccf28SAndroid Build Coastguard Worker restriction 146*e1eccf28SAndroid Build Coastguard Worker ) 147*e1eccf28SAndroid Build Coastguard Worker } 148*e1eccf28SAndroid Build Coastguard Worker timer.measure("ToolkitBlend") { 149*e1eccf28SAndroid Build Coastguard Worker toolkit.blend(mode, sourceArray, toolkitDestArray, sizeX, sizeY, restriction) 150*e1eccf28SAndroid Build Coastguard Worker } 151*e1eccf28SAndroid Build Coastguard Worker if (!validate) return true 152*e1eccf28SAndroid Build Coastguard Worker 153*e1eccf28SAndroid Build Coastguard Worker timer.measure("ReferenceBlend") { 154*e1eccf28SAndroid Build Coastguard Worker referenceBlend(mode, sourceArray, referenceDestArray, sizeX, sizeY, restriction) 155*e1eccf28SAndroid Build Coastguard Worker } 156*e1eccf28SAndroid Build Coastguard Worker 157*e1eccf28SAndroid Build Coastguard Worker return validateSame( 158*e1eccf28SAndroid Build Coastguard Worker "Blend_$mode", intrinsicDestArray, referenceDestArray, toolkitDestArray 159*e1eccf28SAndroid Build Coastguard Worker ) { 160*e1eccf28SAndroid Build Coastguard Worker println("blend $mode ($sizeX, $sizeY) $restriction") 161*e1eccf28SAndroid Build Coastguard Worker logArray("Blend_$mode src", sourceArray, 48) 162*e1eccf28SAndroid Build Coastguard Worker logArray("Blend_$mode dst", destArray, 48) 163*e1eccf28SAndroid Build Coastguard Worker logArray("Blend_$mode reference out", referenceDestArray, 48) 164*e1eccf28SAndroid Build Coastguard Worker logArray("Blend_$mode intrinsic out", intrinsicDestArray, 48) 165*e1eccf28SAndroid Build Coastguard Worker logArray("Blend_$mode toolkit out", toolkitDestArray, 48) 166*e1eccf28SAndroid Build Coastguard Worker } 167*e1eccf28SAndroid Build Coastguard Worker } 168*e1eccf28SAndroid Build Coastguard Worker 169*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 170*e1eccf28SAndroid Build Coastguard Worker private fun testOneBitmapBlend( 171*e1eccf28SAndroid Build Coastguard Worker timer: TimingTracker, 172*e1eccf28SAndroid Build Coastguard Worker sourceBitmap: Bitmap, 173*e1eccf28SAndroid Build Coastguard Worker destBitmap: Bitmap, 174*e1eccf28SAndroid Build Coastguard Worker mode: BlendingMode, 175*e1eccf28SAndroid Build Coastguard Worker restriction: Range2d? 176*e1eccf28SAndroid Build Coastguard Worker ): Boolean { 177*e1eccf28SAndroid Build Coastguard Worker // Make clones because these will be modified by the blend. 178*e1eccf28SAndroid Build Coastguard Worker val intrinsicDestBitmap = duplicateBitmap(destBitmap) 179*e1eccf28SAndroid Build Coastguard Worker val toolkitDestBitmap = duplicateBitmap(destBitmap) 180*e1eccf28SAndroid Build Coastguard Worker val referenceDestBitmap = duplicateBitmap(destBitmap) 181*e1eccf28SAndroid Build Coastguard Worker 182*e1eccf28SAndroid Build Coastguard Worker timer.measure("IntrinsicBlend") { 183*e1eccf28SAndroid Build Coastguard Worker intrinsicBlend( 184*e1eccf28SAndroid Build Coastguard Worker renderscriptContext, mode, sourceBitmap, intrinsicDestBitmap, restriction 185*e1eccf28SAndroid Build Coastguard Worker ) 186*e1eccf28SAndroid Build Coastguard Worker } 187*e1eccf28SAndroid Build Coastguard Worker timer.measure("ToolkitBlend") { 188*e1eccf28SAndroid Build Coastguard Worker toolkit.blend(mode, sourceBitmap, toolkitDestBitmap, restriction) 189*e1eccf28SAndroid Build Coastguard Worker } 190*e1eccf28SAndroid Build Coastguard Worker if (!validate) return true 191*e1eccf28SAndroid Build Coastguard Worker 192*e1eccf28SAndroid Build Coastguard Worker val referenceDestArray = getBitmapBytes(referenceDestBitmap) 193*e1eccf28SAndroid Build Coastguard Worker timer.measure("ReferenceBlend") { 194*e1eccf28SAndroid Build Coastguard Worker referenceBlend( 195*e1eccf28SAndroid Build Coastguard Worker mode, getBitmapBytes(sourceBitmap), referenceDestArray, sourceBitmap.width, 196*e1eccf28SAndroid Build Coastguard Worker sourceBitmap.height, restriction 197*e1eccf28SAndroid Build Coastguard Worker ) 198*e1eccf28SAndroid Build Coastguard Worker } 199*e1eccf28SAndroid Build Coastguard Worker 200*e1eccf28SAndroid Build Coastguard Worker val intrinsicDestArray = getBitmapBytes(intrinsicDestBitmap) 201*e1eccf28SAndroid Build Coastguard Worker val toolkitDestArray = getBitmapBytes(toolkitDestBitmap) 202*e1eccf28SAndroid Build Coastguard Worker return validateSame( 203*e1eccf28SAndroid Build Coastguard Worker "BlendBitmap_$mode", intrinsicDestArray, referenceDestArray, toolkitDestArray 204*e1eccf28SAndroid Build Coastguard Worker ) { 205*e1eccf28SAndroid Build Coastguard Worker println("BlendBitmap $mode $restriction") 206*e1eccf28SAndroid Build Coastguard Worker //logArray("BlendBitmap_$mode src", sourceArray, 48) 207*e1eccf28SAndroid Build Coastguard Worker //logArray("BlendBitmap_$mode dst", destArray, 48) 208*e1eccf28SAndroid Build Coastguard Worker logArray("BlendBitmap_$mode reference out", referenceDestArray, 48) 209*e1eccf28SAndroid Build Coastguard Worker logArray("BlendBitmap_$mode intrinsic out", intrinsicDestArray, 48) 210*e1eccf28SAndroid Build Coastguard Worker logArray("BlendBitmap_$mode toolkit out", toolkitDestArray, 48) 211*e1eccf28SAndroid Build Coastguard Worker } 212*e1eccf28SAndroid Build Coastguard Worker } 213*e1eccf28SAndroid Build Coastguard Worker 214*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 215*e1eccf28SAndroid Build Coastguard Worker private fun testBlur(timer: TimingTracker): Boolean { 216*e1eccf28SAndroid Build Coastguard Worker return arrayOf(1, 3, 8, 25).all { radius -> 217*e1eccf28SAndroid Build Coastguard Worker testOneBitmapBlur(timer, testImage1, radius, null) and 218*e1eccf28SAndroid Build Coastguard Worker testOneBitmapBlur(timer, testImage1, radius, Range2d(6, 23, 2, 4)) and 219*e1eccf28SAndroid Build Coastguard Worker commonLayoutsToTry.all { (sizeX, sizeY, restriction) -> 220*e1eccf28SAndroid Build Coastguard Worker arrayOf(1, 4).all { vectorSize -> 221*e1eccf28SAndroid Build Coastguard Worker testOneRandomBlur(timer, vectorSize, sizeX, sizeY, radius, restriction) 222*e1eccf28SAndroid Build Coastguard Worker } 223*e1eccf28SAndroid Build Coastguard Worker } 224*e1eccf28SAndroid Build Coastguard Worker } 225*e1eccf28SAndroid Build Coastguard Worker } 226*e1eccf28SAndroid Build Coastguard Worker 227*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 228*e1eccf28SAndroid Build Coastguard Worker private fun testOneRandomBlur( 229*e1eccf28SAndroid Build Coastguard Worker timer: TimingTracker, 230*e1eccf28SAndroid Build Coastguard Worker vectorSize: Int, 231*e1eccf28SAndroid Build Coastguard Worker sizeX: Int, 232*e1eccf28SAndroid Build Coastguard Worker sizeY: Int, 233*e1eccf28SAndroid Build Coastguard Worker radius: Int, 234*e1eccf28SAndroid Build Coastguard Worker restriction: Range2d? 235*e1eccf28SAndroid Build Coastguard Worker ): Boolean { 236*e1eccf28SAndroid Build Coastguard Worker val inputArray = randomByteArray(0x50521f0, sizeX, sizeY, vectorSize) 237*e1eccf28SAndroid Build Coastguard Worker val intrinsicOutArray = timer.measure("IntrinsicBlur") { 238*e1eccf28SAndroid Build Coastguard Worker intrinsicBlur( 239*e1eccf28SAndroid Build Coastguard Worker renderscriptContext, inputArray, vectorSize, sizeX, sizeY, radius, restriction 240*e1eccf28SAndroid Build Coastguard Worker ) 241*e1eccf28SAndroid Build Coastguard Worker } 242*e1eccf28SAndroid Build Coastguard Worker val toolkitOutArray = timer.measure("ToolkitBlur") { 243*e1eccf28SAndroid Build Coastguard Worker toolkit.blur(inputArray, vectorSize, sizeX, sizeY, radius, restriction) 244*e1eccf28SAndroid Build Coastguard Worker } 245*e1eccf28SAndroid Build Coastguard Worker if (!validate) return true 246*e1eccf28SAndroid Build Coastguard Worker 247*e1eccf28SAndroid Build Coastguard Worker val referenceOutArray = timer.measure("ReferenceBlur") { 248*e1eccf28SAndroid Build Coastguard Worker referenceBlur(inputArray, vectorSize, sizeX, sizeY, radius, restriction) 249*e1eccf28SAndroid Build Coastguard Worker } 250*e1eccf28SAndroid Build Coastguard Worker return validateSame("blur", intrinsicOutArray, referenceOutArray, toolkitOutArray) { 251*e1eccf28SAndroid Build Coastguard Worker println("blur $vectorSize ($sizeX, $sizeY) radius = $radius $restriction") 252*e1eccf28SAndroid Build Coastguard Worker logArray("blur input ", inputArray) 253*e1eccf28SAndroid Build Coastguard Worker logArray("blur reference out", referenceOutArray) 254*e1eccf28SAndroid Build Coastguard Worker logArray("blur intrinsic out", intrinsicOutArray) 255*e1eccf28SAndroid Build Coastguard Worker logArray("blur toolkit out", toolkitOutArray) 256*e1eccf28SAndroid Build Coastguard Worker } 257*e1eccf28SAndroid Build Coastguard Worker } 258*e1eccf28SAndroid Build Coastguard Worker 259*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 260*e1eccf28SAndroid Build Coastguard Worker private fun testOneBitmapBlur( 261*e1eccf28SAndroid Build Coastguard Worker timer: TimingTracker, 262*e1eccf28SAndroid Build Coastguard Worker bitmap: Bitmap, 263*e1eccf28SAndroid Build Coastguard Worker radius: Int, 264*e1eccf28SAndroid Build Coastguard Worker restriction: Range2d? 265*e1eccf28SAndroid Build Coastguard Worker ): Boolean { 266*e1eccf28SAndroid Build Coastguard Worker val intrinsicOutArray = timer.measure("IntrinsicBlur") { 267*e1eccf28SAndroid Build Coastguard Worker intrinsicBlur(renderscriptContext, bitmap, radius, restriction) 268*e1eccf28SAndroid Build Coastguard Worker } 269*e1eccf28SAndroid Build Coastguard Worker 270*e1eccf28SAndroid Build Coastguard Worker val toolkitOutBitmap = timer.measure("ToolkitBlur") { 271*e1eccf28SAndroid Build Coastguard Worker toolkit.blur(bitmap, radius, restriction) 272*e1eccf28SAndroid Build Coastguard Worker } 273*e1eccf28SAndroid Build Coastguard Worker if (!validate) return true 274*e1eccf28SAndroid Build Coastguard Worker 275*e1eccf28SAndroid Build Coastguard Worker val referenceOutArray = timer.measure("ReferenceBlur") { 276*e1eccf28SAndroid Build Coastguard Worker referenceBlur( 277*e1eccf28SAndroid Build Coastguard Worker getBitmapBytes(bitmap), 278*e1eccf28SAndroid Build Coastguard Worker vectorSizeOfBitmap(bitmap), 279*e1eccf28SAndroid Build Coastguard Worker bitmap.width, 280*e1eccf28SAndroid Build Coastguard Worker bitmap.height, 281*e1eccf28SAndroid Build Coastguard Worker radius, 282*e1eccf28SAndroid Build Coastguard Worker restriction 283*e1eccf28SAndroid Build Coastguard Worker ) 284*e1eccf28SAndroid Build Coastguard Worker } 285*e1eccf28SAndroid Build Coastguard Worker 286*e1eccf28SAndroid Build Coastguard Worker val toolkitOutArray = getBitmapBytes(toolkitOutBitmap) 287*e1eccf28SAndroid Build Coastguard Worker return validateSame("blur", intrinsicOutArray, referenceOutArray, toolkitOutArray) { 288*e1eccf28SAndroid Build Coastguard Worker println("BlurBitmap ${bitmap.config} $radius $restriction") 289*e1eccf28SAndroid Build Coastguard Worker logArray("blur reference out", referenceOutArray) 290*e1eccf28SAndroid Build Coastguard Worker logArray("blur intrinsic out", intrinsicOutArray) 291*e1eccf28SAndroid Build Coastguard Worker logArray("blur toolkit out", toolkitOutArray) 292*e1eccf28SAndroid Build Coastguard Worker } 293*e1eccf28SAndroid Build Coastguard Worker } 294*e1eccf28SAndroid Build Coastguard Worker 295*e1eccf28SAndroid Build Coastguard Worker enum class ColorMatrixConversionType { 296*e1eccf28SAndroid Build Coastguard Worker RGB_TO_YUV, 297*e1eccf28SAndroid Build Coastguard Worker YUV_TO_RGB, 298*e1eccf28SAndroid Build Coastguard Worker GREYSCALE, 299*e1eccf28SAndroid Build Coastguard Worker RANDOM 300*e1eccf28SAndroid Build Coastguard Worker } 301*e1eccf28SAndroid Build Coastguard Worker 302*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 303*e1eccf28SAndroid Build Coastguard Worker private fun testColorMatrix(timer: TimingTracker): Boolean { 304*e1eccf28SAndroid Build Coastguard Worker return ColorMatrixConversionType.values().all { conversion -> 305*e1eccf28SAndroid Build Coastguard Worker testOneBitmapColorMatrix(timer, testImage1, conversion, null) and 306*e1eccf28SAndroid Build Coastguard Worker testOneBitmapColorMatrix( 307*e1eccf28SAndroid Build Coastguard Worker timer, 308*e1eccf28SAndroid Build Coastguard Worker testImage1, 309*e1eccf28SAndroid Build Coastguard Worker conversion, 310*e1eccf28SAndroid Build Coastguard Worker Range2d(6, 23, 2, 4) 311*e1eccf28SAndroid Build Coastguard Worker ) and 312*e1eccf28SAndroid Build Coastguard Worker commonLayoutsToTry.all { (sizeX, sizeY, restriction) -> 313*e1eccf28SAndroid Build Coastguard Worker (1..4).all { inputVectorSize -> 314*e1eccf28SAndroid Build Coastguard Worker (1..4).all { outputVectorSize -> 315*e1eccf28SAndroid Build Coastguard Worker testOneRandomColorMatrix( 316*e1eccf28SAndroid Build Coastguard Worker timer, 317*e1eccf28SAndroid Build Coastguard Worker inputVectorSize, 318*e1eccf28SAndroid Build Coastguard Worker sizeX, 319*e1eccf28SAndroid Build Coastguard Worker sizeY, 320*e1eccf28SAndroid Build Coastguard Worker outputVectorSize, 321*e1eccf28SAndroid Build Coastguard Worker conversion, 322*e1eccf28SAndroid Build Coastguard Worker restriction 323*e1eccf28SAndroid Build Coastguard Worker ) 324*e1eccf28SAndroid Build Coastguard Worker } 325*e1eccf28SAndroid Build Coastguard Worker } 326*e1eccf28SAndroid Build Coastguard Worker } 327*e1eccf28SAndroid Build Coastguard Worker } 328*e1eccf28SAndroid Build Coastguard Worker } 329*e1eccf28SAndroid Build Coastguard Worker 330*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 331*e1eccf28SAndroid Build Coastguard Worker private fun testOneRandomColorMatrix( 332*e1eccf28SAndroid Build Coastguard Worker timer: TimingTracker, 333*e1eccf28SAndroid Build Coastguard Worker inputVectorSize: Int, 334*e1eccf28SAndroid Build Coastguard Worker sizeX: Int, 335*e1eccf28SAndroid Build Coastguard Worker sizeY: Int, 336*e1eccf28SAndroid Build Coastguard Worker outputVectorSize: Int, 337*e1eccf28SAndroid Build Coastguard Worker conversion: ColorMatrixConversionType, 338*e1eccf28SAndroid Build Coastguard Worker restriction: Range2d? 339*e1eccf28SAndroid Build Coastguard Worker ): Boolean { 340*e1eccf28SAndroid Build Coastguard Worker val inputArray = randomByteArray(0x50521f0, sizeX, sizeY, paddedSize(inputVectorSize)) 341*e1eccf28SAndroid Build Coastguard Worker val addVector = randomFloatArray(0x243238, 4, 1, 1, 0.3f) 342*e1eccf28SAndroid Build Coastguard Worker val matrix = when (conversion) { 343*e1eccf28SAndroid Build Coastguard Worker ColorMatrixConversionType.RGB_TO_YUV -> toolkit.rgbToYuvMatrix 344*e1eccf28SAndroid Build Coastguard Worker ColorMatrixConversionType.YUV_TO_RGB -> toolkit.yuvToRgbMatrix 345*e1eccf28SAndroid Build Coastguard Worker ColorMatrixConversionType.GREYSCALE -> toolkit.greyScaleColorMatrix 346*e1eccf28SAndroid Build Coastguard Worker ColorMatrixConversionType.RANDOM -> randomFloatArray(0x234348, 4, 4, 1) 347*e1eccf28SAndroid Build Coastguard Worker } 348*e1eccf28SAndroid Build Coastguard Worker 349*e1eccf28SAndroid Build Coastguard Worker val intrinsicOutArray = timer.measure("IntrinsicColorMatrix") { 350*e1eccf28SAndroid Build Coastguard Worker intrinsicColorMatrix( 351*e1eccf28SAndroid Build Coastguard Worker renderscriptContext, 352*e1eccf28SAndroid Build Coastguard Worker conversion, 353*e1eccf28SAndroid Build Coastguard Worker inputArray, 354*e1eccf28SAndroid Build Coastguard Worker inputVectorSize, 355*e1eccf28SAndroid Build Coastguard Worker sizeX, 356*e1eccf28SAndroid Build Coastguard Worker sizeY, 357*e1eccf28SAndroid Build Coastguard Worker outputVectorSize, 358*e1eccf28SAndroid Build Coastguard Worker matrix, 359*e1eccf28SAndroid Build Coastguard Worker addVector, 360*e1eccf28SAndroid Build Coastguard Worker restriction 361*e1eccf28SAndroid Build Coastguard Worker ) 362*e1eccf28SAndroid Build Coastguard Worker } 363*e1eccf28SAndroid Build Coastguard Worker val toolkitOutArray = timer.measure("ToolkitColorMatrix") { 364*e1eccf28SAndroid Build Coastguard Worker toolkit.colorMatrix( 365*e1eccf28SAndroid Build Coastguard Worker inputArray, 366*e1eccf28SAndroid Build Coastguard Worker inputVectorSize, 367*e1eccf28SAndroid Build Coastguard Worker sizeX, 368*e1eccf28SAndroid Build Coastguard Worker sizeY, 369*e1eccf28SAndroid Build Coastguard Worker outputVectorSize, 370*e1eccf28SAndroid Build Coastguard Worker matrix, 371*e1eccf28SAndroid Build Coastguard Worker addVector, 372*e1eccf28SAndroid Build Coastguard Worker restriction 373*e1eccf28SAndroid Build Coastguard Worker ) 374*e1eccf28SAndroid Build Coastguard Worker } 375*e1eccf28SAndroid Build Coastguard Worker if (!validate) return true 376*e1eccf28SAndroid Build Coastguard Worker 377*e1eccf28SAndroid Build Coastguard Worker val referenceOutArray = timer.measure("ReferenceColorMatrix") { 378*e1eccf28SAndroid Build Coastguard Worker referenceColorMatrix( 379*e1eccf28SAndroid Build Coastguard Worker inputArray, inputVectorSize, sizeX, sizeY, outputVectorSize, matrix, addVector, 380*e1eccf28SAndroid Build Coastguard Worker restriction 381*e1eccf28SAndroid Build Coastguard Worker ) 382*e1eccf28SAndroid Build Coastguard Worker } 383*e1eccf28SAndroid Build Coastguard Worker 384*e1eccf28SAndroid Build Coastguard Worker return validateSame("colorMatrix", intrinsicOutArray, referenceOutArray, toolkitOutArray, 385*e1eccf28SAndroid Build Coastguard Worker outputVectorSize == 3) { 386*e1eccf28SAndroid Build Coastguard Worker println("colorMatrix ($sizeX, $sizeY) $inputVectorSize->$outputVectorSize $restriction") 387*e1eccf28SAndroid Build Coastguard Worker logArray("colorMatrix matrix ", matrix, 16) 388*e1eccf28SAndroid Build Coastguard Worker logArray("colorMatrix addVector", addVector, 4) 389*e1eccf28SAndroid Build Coastguard Worker logArray("colorMatrix in ", inputArray) 390*e1eccf28SAndroid Build Coastguard Worker logArray("colorMatrix reference out", referenceOutArray, 300) 391*e1eccf28SAndroid Build Coastguard Worker logArray("colorMatrix intrinsic out", intrinsicOutArray, 300) 392*e1eccf28SAndroid Build Coastguard Worker logArray("colorMatrix toolkit out", toolkitOutArray, 300) 393*e1eccf28SAndroid Build Coastguard Worker } 394*e1eccf28SAndroid Build Coastguard Worker } 395*e1eccf28SAndroid Build Coastguard Worker 396*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 397*e1eccf28SAndroid Build Coastguard Worker private fun testOneBitmapColorMatrix( 398*e1eccf28SAndroid Build Coastguard Worker timer: TimingTracker, 399*e1eccf28SAndroid Build Coastguard Worker bitmap: Bitmap, 400*e1eccf28SAndroid Build Coastguard Worker conversion: ColorMatrixConversionType, 401*e1eccf28SAndroid Build Coastguard Worker restriction: Range2d? 402*e1eccf28SAndroid Build Coastguard Worker ): Boolean { 403*e1eccf28SAndroid Build Coastguard Worker val addVector = randomFloatArray(0x243238, 4, 1, 1, 0.3f) 404*e1eccf28SAndroid Build Coastguard Worker val matrix = when (conversion) { 405*e1eccf28SAndroid Build Coastguard Worker ColorMatrixConversionType.RGB_TO_YUV -> toolkit.rgbToYuvMatrix 406*e1eccf28SAndroid Build Coastguard Worker ColorMatrixConversionType.YUV_TO_RGB -> toolkit.yuvToRgbMatrix 407*e1eccf28SAndroid Build Coastguard Worker ColorMatrixConversionType.GREYSCALE -> toolkit.greyScaleColorMatrix 408*e1eccf28SAndroid Build Coastguard Worker ColorMatrixConversionType.RANDOM -> randomFloatArray(0x234348, 4, 4, 1) 409*e1eccf28SAndroid Build Coastguard Worker } 410*e1eccf28SAndroid Build Coastguard Worker 411*e1eccf28SAndroid Build Coastguard Worker val intrinsicOutArray = timer.measure("IntrinsicColorMatrix") { 412*e1eccf28SAndroid Build Coastguard Worker intrinsicColorMatrix( 413*e1eccf28SAndroid Build Coastguard Worker renderscriptContext, conversion, bitmap, matrix, addVector, restriction 414*e1eccf28SAndroid Build Coastguard Worker ) 415*e1eccf28SAndroid Build Coastguard Worker } 416*e1eccf28SAndroid Build Coastguard Worker val toolkitOutBitmap = timer.measure("ToolkitColorMatrix") { 417*e1eccf28SAndroid Build Coastguard Worker toolkit.colorMatrix(bitmap, matrix, addVector, restriction) 418*e1eccf28SAndroid Build Coastguard Worker } 419*e1eccf28SAndroid Build Coastguard Worker if (!validate) return true 420*e1eccf28SAndroid Build Coastguard Worker 421*e1eccf28SAndroid Build Coastguard Worker val referenceOutArray = timer.measure("ReferenceColorMatrix") { 422*e1eccf28SAndroid Build Coastguard Worker referenceColorMatrix( 423*e1eccf28SAndroid Build Coastguard Worker getBitmapBytes(bitmap), vectorSizeOfBitmap(bitmap), bitmap.width, bitmap.height, 424*e1eccf28SAndroid Build Coastguard Worker vectorSizeOfBitmap(bitmap), matrix, addVector, restriction 425*e1eccf28SAndroid Build Coastguard Worker ) 426*e1eccf28SAndroid Build Coastguard Worker } 427*e1eccf28SAndroid Build Coastguard Worker 428*e1eccf28SAndroid Build Coastguard Worker val toolkitOutArray = getBitmapBytes(toolkitOutBitmap) 429*e1eccf28SAndroid Build Coastguard Worker return validateSame("ColorMatrix", intrinsicOutArray, referenceOutArray, toolkitOutArray) { 430*e1eccf28SAndroid Build Coastguard Worker println("colorMatrixBitmap $restriction") 431*e1eccf28SAndroid Build Coastguard Worker logArray("colorMatrixBitmap matrix ", matrix, 16) 432*e1eccf28SAndroid Build Coastguard Worker logArray("colorMatrixBitmap addVector", addVector, 4) 433*e1eccf28SAndroid Build Coastguard Worker logArray("colorMatrixBitmap reference out", referenceOutArray) 434*e1eccf28SAndroid Build Coastguard Worker logArray("colorMatrixBitmap intrinsic out", intrinsicOutArray) 435*e1eccf28SAndroid Build Coastguard Worker logArray("colorMatrixBitmap toolkit out", toolkitOutArray) 436*e1eccf28SAndroid Build Coastguard Worker } 437*e1eccf28SAndroid Build Coastguard Worker } 438*e1eccf28SAndroid Build Coastguard Worker 439*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 440*e1eccf28SAndroid Build Coastguard Worker private fun testConvolve(timer: TimingTracker): Boolean { 441*e1eccf28SAndroid Build Coastguard Worker val coefficientsToTry = listOf( 442*e1eccf28SAndroid Build Coastguard Worker randomFloatArray(0x2937021, 3, 3, 1, 0.1f), 443*e1eccf28SAndroid Build Coastguard Worker randomFloatArray(0x2937021, 5, 5, 1, 0.05f) 444*e1eccf28SAndroid Build Coastguard Worker ) 445*e1eccf28SAndroid Build Coastguard Worker return coefficientsToTry.all { coefficients -> 446*e1eccf28SAndroid Build Coastguard Worker testOneBitmapConvolve(timer, testImage1, coefficients, null) and 447*e1eccf28SAndroid Build Coastguard Worker testOneBitmapConvolve(timer, testImage1, coefficients, Range2d(6, 23, 2, 4)) and 448*e1eccf28SAndroid Build Coastguard Worker 449*e1eccf28SAndroid Build Coastguard Worker commonLayoutsToTry.all { (sizeX, sizeY, restriction) -> 450*e1eccf28SAndroid Build Coastguard Worker (1..4).all { vectorSize -> 451*e1eccf28SAndroid Build Coastguard Worker testOneRandomConvolve( 452*e1eccf28SAndroid Build Coastguard Worker timer, 453*e1eccf28SAndroid Build Coastguard Worker vectorSize, 454*e1eccf28SAndroid Build Coastguard Worker sizeX, 455*e1eccf28SAndroid Build Coastguard Worker sizeY, 456*e1eccf28SAndroid Build Coastguard Worker coefficients, 457*e1eccf28SAndroid Build Coastguard Worker restriction 458*e1eccf28SAndroid Build Coastguard Worker ) 459*e1eccf28SAndroid Build Coastguard Worker } 460*e1eccf28SAndroid Build Coastguard Worker } 461*e1eccf28SAndroid Build Coastguard Worker } 462*e1eccf28SAndroid Build Coastguard Worker } 463*e1eccf28SAndroid Build Coastguard Worker 464*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 465*e1eccf28SAndroid Build Coastguard Worker private fun testOneRandomConvolve( 466*e1eccf28SAndroid Build Coastguard Worker timer: TimingTracker, 467*e1eccf28SAndroid Build Coastguard Worker vectorSize: Int, 468*e1eccf28SAndroid Build Coastguard Worker sizeX: Int, 469*e1eccf28SAndroid Build Coastguard Worker sizeY: Int, 470*e1eccf28SAndroid Build Coastguard Worker coefficients: FloatArray, 471*e1eccf28SAndroid Build Coastguard Worker restriction: Range2d? 472*e1eccf28SAndroid Build Coastguard Worker ): Boolean { 473*e1eccf28SAndroid Build Coastguard Worker val inputArray = randomByteArray(0x50521f0, sizeX, sizeY, paddedSize(vectorSize)) 474*e1eccf28SAndroid Build Coastguard Worker 475*e1eccf28SAndroid Build Coastguard Worker val intrinsicOutArray = timer.measure("IntrinsicConvolve") { 476*e1eccf28SAndroid Build Coastguard Worker intrinsicConvolve( 477*e1eccf28SAndroid Build Coastguard Worker renderscriptContext, inputArray, vectorSize, sizeX, sizeY, coefficients, restriction 478*e1eccf28SAndroid Build Coastguard Worker ) 479*e1eccf28SAndroid Build Coastguard Worker } 480*e1eccf28SAndroid Build Coastguard Worker val toolkitOutArray = timer.measure("ToolkitConvolve") { 481*e1eccf28SAndroid Build Coastguard Worker toolkit.convolve(inputArray, vectorSize, sizeX, sizeY, coefficients, restriction) 482*e1eccf28SAndroid Build Coastguard Worker } 483*e1eccf28SAndroid Build Coastguard Worker if (!validate) return true 484*e1eccf28SAndroid Build Coastguard Worker 485*e1eccf28SAndroid Build Coastguard Worker val referenceOutArray = timer.measure("ReferenceConvolve") { 486*e1eccf28SAndroid Build Coastguard Worker referenceConvolve(inputArray, vectorSize, sizeX, sizeY, coefficients, restriction) 487*e1eccf28SAndroid Build Coastguard Worker } 488*e1eccf28SAndroid Build Coastguard Worker 489*e1eccf28SAndroid Build Coastguard Worker val task = if (coefficients.size == 9) "convolve3x3 $vectorSize" else "convolve5x5 $vectorSize" 490*e1eccf28SAndroid Build Coastguard Worker return validateSame(task, intrinsicOutArray, referenceOutArray, toolkitOutArray) { 491*e1eccf28SAndroid Build Coastguard Worker println("Convolve $vectorSize ($sizeX, $sizeY) $restriction") 492*e1eccf28SAndroid Build Coastguard Worker logArray("Convolve coefficients", coefficients, 25) 493*e1eccf28SAndroid Build Coastguard Worker logArray("Convolve in ", inputArray) 494*e1eccf28SAndroid Build Coastguard Worker logArray("Convolve reference out", referenceOutArray) 495*e1eccf28SAndroid Build Coastguard Worker logArray("Convolve intrinsic out", intrinsicOutArray) 496*e1eccf28SAndroid Build Coastguard Worker logArray("Convolve toolkit out", toolkitOutArray) 497*e1eccf28SAndroid Build Coastguard Worker } 498*e1eccf28SAndroid Build Coastguard Worker } 499*e1eccf28SAndroid Build Coastguard Worker 500*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 501*e1eccf28SAndroid Build Coastguard Worker private fun testOneBitmapConvolve( 502*e1eccf28SAndroid Build Coastguard Worker timer: TimingTracker, 503*e1eccf28SAndroid Build Coastguard Worker bitmap: Bitmap, 504*e1eccf28SAndroid Build Coastguard Worker coefficients: FloatArray, 505*e1eccf28SAndroid Build Coastguard Worker restriction: Range2d? 506*e1eccf28SAndroid Build Coastguard Worker ): Boolean { 507*e1eccf28SAndroid Build Coastguard Worker val intrinsicOutArray = timer.measure("IntrinsicConvolve") { 508*e1eccf28SAndroid Build Coastguard Worker intrinsicConvolve(renderscriptContext, bitmap, coefficients, restriction) 509*e1eccf28SAndroid Build Coastguard Worker } 510*e1eccf28SAndroid Build Coastguard Worker val toolkitOutBitmap = timer.measure("ToolkitConvolve") { 511*e1eccf28SAndroid Build Coastguard Worker toolkit.convolve(bitmap, coefficients, restriction) 512*e1eccf28SAndroid Build Coastguard Worker } 513*e1eccf28SAndroid Build Coastguard Worker if (!validate) return true 514*e1eccf28SAndroid Build Coastguard Worker 515*e1eccf28SAndroid Build Coastguard Worker val referenceOutArray = timer.measure("ReferenceConvolve") { 516*e1eccf28SAndroid Build Coastguard Worker referenceConvolve( 517*e1eccf28SAndroid Build Coastguard Worker getBitmapBytes(bitmap), vectorSizeOfBitmap(bitmap), bitmap.width, bitmap.height, 518*e1eccf28SAndroid Build Coastguard Worker coefficients, restriction 519*e1eccf28SAndroid Build Coastguard Worker ) 520*e1eccf28SAndroid Build Coastguard Worker } 521*e1eccf28SAndroid Build Coastguard Worker 522*e1eccf28SAndroid Build Coastguard Worker val task = if (coefficients.size == 9) "convolve3x3" else "convolve5x5" 523*e1eccf28SAndroid Build Coastguard Worker val toolkitOutArray = getBitmapBytes(toolkitOutBitmap) 524*e1eccf28SAndroid Build Coastguard Worker return validateSame(task, intrinsicOutArray, referenceOutArray, toolkitOutArray) { 525*e1eccf28SAndroid Build Coastguard Worker println("ConvolveBitmap $restriction") 526*e1eccf28SAndroid Build Coastguard Worker logArray("ConvolveBitmap coefficients", coefficients, 25) 527*e1eccf28SAndroid Build Coastguard Worker //logArray("ConvolveBitmap in ", inputArray) 528*e1eccf28SAndroid Build Coastguard Worker logArray("ConvolveBitmap reference out", referenceOutArray) 529*e1eccf28SAndroid Build Coastguard Worker logArray("ConvolveBitmap intrinsic out", intrinsicOutArray) 530*e1eccf28SAndroid Build Coastguard Worker logArray("ConvolveBitmap toolkit out", toolkitOutArray) 531*e1eccf28SAndroid Build Coastguard Worker } 532*e1eccf28SAndroid Build Coastguard Worker } 533*e1eccf28SAndroid Build Coastguard Worker 534*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 535*e1eccf28SAndroid Build Coastguard Worker private fun testHistogram(timer: TimingTracker): Boolean { 536*e1eccf28SAndroid Build Coastguard Worker val coefficients = floatArrayOf(0.1f, 0.3f, 0.5f, 0.05f) 537*e1eccf28SAndroid Build Coastguard Worker return testOneBitmapHistogram(timer, testImage1, null) and 538*e1eccf28SAndroid Build Coastguard Worker testOneBitmapHistogram(timer, testImage1, Range2d(6, 23, 2, 4)) and 539*e1eccf28SAndroid Build Coastguard Worker testOneBitmapHistogramDot(timer, testImage1, null, null) and 540*e1eccf28SAndroid Build Coastguard Worker testOneBitmapHistogramDot(timer, testImage1, coefficients, null) and 541*e1eccf28SAndroid Build Coastguard Worker testOneBitmapHistogramDot(timer, testImage1, coefficients, Range2d(6, 23, 2, 4)) and 542*e1eccf28SAndroid Build Coastguard Worker commonLayoutsToTry.all { (sizeX, sizeY, restriction) -> 543*e1eccf28SAndroid Build Coastguard Worker (1..4).all { vectorSize -> 544*e1eccf28SAndroid Build Coastguard Worker testOneRandomHistogram(timer, vectorSize, sizeX, sizeY, restriction) && 545*e1eccf28SAndroid Build Coastguard Worker testOneRandomHistogramDot( 546*e1eccf28SAndroid Build Coastguard Worker timer, 547*e1eccf28SAndroid Build Coastguard Worker vectorSize, 548*e1eccf28SAndroid Build Coastguard Worker sizeX, 549*e1eccf28SAndroid Build Coastguard Worker sizeY, 550*e1eccf28SAndroid Build Coastguard Worker null, 551*e1eccf28SAndroid Build Coastguard Worker restriction 552*e1eccf28SAndroid Build Coastguard Worker ) && 553*e1eccf28SAndroid Build Coastguard Worker testOneRandomHistogramDot( 554*e1eccf28SAndroid Build Coastguard Worker timer, 555*e1eccf28SAndroid Build Coastguard Worker vectorSize, 556*e1eccf28SAndroid Build Coastguard Worker sizeX, 557*e1eccf28SAndroid Build Coastguard Worker sizeY, 558*e1eccf28SAndroid Build Coastguard Worker coefficients.sliceArray(0 until vectorSize), 559*e1eccf28SAndroid Build Coastguard Worker restriction 560*e1eccf28SAndroid Build Coastguard Worker ) 561*e1eccf28SAndroid Build Coastguard Worker } 562*e1eccf28SAndroid Build Coastguard Worker } 563*e1eccf28SAndroid Build Coastguard Worker } 564*e1eccf28SAndroid Build Coastguard Worker 565*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 566*e1eccf28SAndroid Build Coastguard Worker private fun testOneRandomHistogram( 567*e1eccf28SAndroid Build Coastguard Worker timer: TimingTracker, 568*e1eccf28SAndroid Build Coastguard Worker vectorSize: Int, 569*e1eccf28SAndroid Build Coastguard Worker sizeX: Int, 570*e1eccf28SAndroid Build Coastguard Worker sizeY: Int, 571*e1eccf28SAndroid Build Coastguard Worker restriction: Range2d? 572*e1eccf28SAndroid Build Coastguard Worker ): Boolean { 573*e1eccf28SAndroid Build Coastguard Worker val inputArray = randomByteArray(0x50521f0, sizeX, sizeY, paddedSize(vectorSize)) 574*e1eccf28SAndroid Build Coastguard Worker 575*e1eccf28SAndroid Build Coastguard Worker val intrinsicOutput = timer.measure("IntrinsicHistogram") { 576*e1eccf28SAndroid Build Coastguard Worker intrinsicHistogram( 577*e1eccf28SAndroid Build Coastguard Worker renderscriptContext, inputArray, vectorSize, sizeX, sizeY, restriction 578*e1eccf28SAndroid Build Coastguard Worker ) 579*e1eccf28SAndroid Build Coastguard Worker } 580*e1eccf28SAndroid Build Coastguard Worker val toolkitOutput = timer.measure("ToolkitHistogram") { 581*e1eccf28SAndroid Build Coastguard Worker toolkit.histogram(inputArray, vectorSize, sizeX, sizeY, restriction) 582*e1eccf28SAndroid Build Coastguard Worker } 583*e1eccf28SAndroid Build Coastguard Worker if (!validate) return true 584*e1eccf28SAndroid Build Coastguard Worker 585*e1eccf28SAndroid Build Coastguard Worker val referenceOutput = timer.measure("ReferenceHistogram") { 586*e1eccf28SAndroid Build Coastguard Worker referenceHistogram( 587*e1eccf28SAndroid Build Coastguard Worker inputArray, vectorSize, sizeX, sizeY, restriction 588*e1eccf28SAndroid Build Coastguard Worker ) 589*e1eccf28SAndroid Build Coastguard Worker } 590*e1eccf28SAndroid Build Coastguard Worker 591*e1eccf28SAndroid Build Coastguard Worker return validateSame("histogram", intrinsicOutput, referenceOutput, toolkitOutput, 0) { 592*e1eccf28SAndroid Build Coastguard Worker println("histogram $vectorSize ($sizeX, $sizeY) $restriction") 593*e1eccf28SAndroid Build Coastguard Worker logArray("histogram in ", inputArray, 200) 594*e1eccf28SAndroid Build Coastguard Worker logArray("histogram reference out", referenceOutput, 200) 595*e1eccf28SAndroid Build Coastguard Worker logArray("histogram intrinsic out", intrinsicOutput, 200) 596*e1eccf28SAndroid Build Coastguard Worker logArray("histogram toolkit out", toolkitOutput, 200) 597*e1eccf28SAndroid Build Coastguard Worker } 598*e1eccf28SAndroid Build Coastguard Worker } 599*e1eccf28SAndroid Build Coastguard Worker 600*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 601*e1eccf28SAndroid Build Coastguard Worker private fun testOneBitmapHistogram( 602*e1eccf28SAndroid Build Coastguard Worker timer: TimingTracker, 603*e1eccf28SAndroid Build Coastguard Worker bitmap: Bitmap, 604*e1eccf28SAndroid Build Coastguard Worker restriction: Range2d? 605*e1eccf28SAndroid Build Coastguard Worker ): Boolean { 606*e1eccf28SAndroid Build Coastguard Worker val intrinsicOutput = timer.measure("IntrinsicHistogram") { 607*e1eccf28SAndroid Build Coastguard Worker intrinsicHistogram(renderscriptContext, bitmap, restriction) 608*e1eccf28SAndroid Build Coastguard Worker } 609*e1eccf28SAndroid Build Coastguard Worker val toolkitOutput = timer.measure("ToolkitHistogram") { 610*e1eccf28SAndroid Build Coastguard Worker toolkit.histogram(bitmap, restriction) 611*e1eccf28SAndroid Build Coastguard Worker } 612*e1eccf28SAndroid Build Coastguard Worker if (!validate) return true 613*e1eccf28SAndroid Build Coastguard Worker 614*e1eccf28SAndroid Build Coastguard Worker val referenceOutput = timer.measure("ReferenceHistogram") { 615*e1eccf28SAndroid Build Coastguard Worker referenceHistogram( 616*e1eccf28SAndroid Build Coastguard Worker getBitmapBytes(bitmap), vectorSizeOfBitmap(bitmap), bitmap.width, bitmap.height, 617*e1eccf28SAndroid Build Coastguard Worker restriction 618*e1eccf28SAndroid Build Coastguard Worker ) 619*e1eccf28SAndroid Build Coastguard Worker } 620*e1eccf28SAndroid Build Coastguard Worker 621*e1eccf28SAndroid Build Coastguard Worker return validateSame("histogram", intrinsicOutput, referenceOutput, toolkitOutput, 0) { 622*e1eccf28SAndroid Build Coastguard Worker println("HistogramBitmap $restriction") 623*e1eccf28SAndroid Build Coastguard Worker logArray("HistogramBitmap reference out", referenceOutput) 624*e1eccf28SAndroid Build Coastguard Worker logArray("HistogramBitmap intrinsic out", intrinsicOutput) 625*e1eccf28SAndroid Build Coastguard Worker logArray("HistogramBitmap toolkit out", toolkitOutput) 626*e1eccf28SAndroid Build Coastguard Worker } 627*e1eccf28SAndroid Build Coastguard Worker } 628*e1eccf28SAndroid Build Coastguard Worker 629*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 630*e1eccf28SAndroid Build Coastguard Worker private fun testOneRandomHistogramDot( 631*e1eccf28SAndroid Build Coastguard Worker timer: TimingTracker, 632*e1eccf28SAndroid Build Coastguard Worker vectorSize: Int, 633*e1eccf28SAndroid Build Coastguard Worker sizeX: Int, 634*e1eccf28SAndroid Build Coastguard Worker sizeY: Int, 635*e1eccf28SAndroid Build Coastguard Worker coefficients: FloatArray?, restriction: Range2d? 636*e1eccf28SAndroid Build Coastguard Worker ): Boolean { 637*e1eccf28SAndroid Build Coastguard Worker val inputArray = randomByteArray(0x50521f0, sizeX, sizeY, paddedSize(vectorSize)) 638*e1eccf28SAndroid Build Coastguard Worker 639*e1eccf28SAndroid Build Coastguard Worker val intrinsicOutArray = timer.measure("IntrinsicHistogramDot") { 640*e1eccf28SAndroid Build Coastguard Worker intrinsicHistogramDot( 641*e1eccf28SAndroid Build Coastguard Worker renderscriptContext, inputArray, vectorSize, sizeX, sizeY, coefficients, restriction 642*e1eccf28SAndroid Build Coastguard Worker ) 643*e1eccf28SAndroid Build Coastguard Worker } 644*e1eccf28SAndroid Build Coastguard Worker val toolkitOutArray = timer.measure("ToolkitHistogramDot") { 645*e1eccf28SAndroid Build Coastguard Worker toolkit.histogramDot( 646*e1eccf28SAndroid Build Coastguard Worker inputArray, vectorSize, sizeX, sizeY, coefficients, restriction 647*e1eccf28SAndroid Build Coastguard Worker ) 648*e1eccf28SAndroid Build Coastguard Worker } 649*e1eccf28SAndroid Build Coastguard Worker if (!validate) return true 650*e1eccf28SAndroid Build Coastguard Worker 651*e1eccf28SAndroid Build Coastguard Worker val referenceOutArray = timer.measure("ReferenceHistogramDot") { 652*e1eccf28SAndroid Build Coastguard Worker referenceHistogramDot(inputArray, vectorSize, sizeX, sizeY, coefficients, restriction) 653*e1eccf28SAndroid Build Coastguard Worker } 654*e1eccf28SAndroid Build Coastguard Worker 655*e1eccf28SAndroid Build Coastguard Worker return validateSame("histogramDot", intrinsicOutArray, referenceOutArray, toolkitOutArray) { 656*e1eccf28SAndroid Build Coastguard Worker println("histogramDot $vectorSize ($sizeX, $sizeY) $restriction") 657*e1eccf28SAndroid Build Coastguard Worker logArray("histogramDot coefficients ", coefficients) 658*e1eccf28SAndroid Build Coastguard Worker logArray("histogramDot in ", inputArray) 659*e1eccf28SAndroid Build Coastguard Worker logArray("histogramDot reference out", referenceOutArray, 256) 660*e1eccf28SAndroid Build Coastguard Worker logArray("histogramDot intrinsic out", intrinsicOutArray, 256) 661*e1eccf28SAndroid Build Coastguard Worker logArray("histogramDot toolkit out", toolkitOutArray, 256) 662*e1eccf28SAndroid Build Coastguard Worker } 663*e1eccf28SAndroid Build Coastguard Worker } 664*e1eccf28SAndroid Build Coastguard Worker 665*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 666*e1eccf28SAndroid Build Coastguard Worker private fun testOneBitmapHistogramDot( 667*e1eccf28SAndroid Build Coastguard Worker timer: TimingTracker, 668*e1eccf28SAndroid Build Coastguard Worker bitmap: Bitmap, 669*e1eccf28SAndroid Build Coastguard Worker coefficients: FloatArray?, 670*e1eccf28SAndroid Build Coastguard Worker restriction: Range2d? 671*e1eccf28SAndroid Build Coastguard Worker ): Boolean { 672*e1eccf28SAndroid Build Coastguard Worker val intrinsicOutArray = timer.measure("IntrinsicHistogramDot") { 673*e1eccf28SAndroid Build Coastguard Worker intrinsicHistogramDot(renderscriptContext, bitmap, coefficients, restriction) 674*e1eccf28SAndroid Build Coastguard Worker } 675*e1eccf28SAndroid Build Coastguard Worker val toolkitOutArray = timer.measure("ToolkitHistogramDot") { 676*e1eccf28SAndroid Build Coastguard Worker toolkit.histogramDot(bitmap, coefficients, restriction) 677*e1eccf28SAndroid Build Coastguard Worker } 678*e1eccf28SAndroid Build Coastguard Worker if (!validate) return true 679*e1eccf28SAndroid Build Coastguard Worker 680*e1eccf28SAndroid Build Coastguard Worker val referenceOutArray = timer.measure("ReferenceHistogramDot") { 681*e1eccf28SAndroid Build Coastguard Worker referenceHistogramDot( 682*e1eccf28SAndroid Build Coastguard Worker getBitmapBytes(bitmap), 683*e1eccf28SAndroid Build Coastguard Worker vectorSizeOfBitmap(bitmap), 684*e1eccf28SAndroid Build Coastguard Worker bitmap.width, 685*e1eccf28SAndroid Build Coastguard Worker bitmap.height, 686*e1eccf28SAndroid Build Coastguard Worker coefficients, 687*e1eccf28SAndroid Build Coastguard Worker restriction 688*e1eccf28SAndroid Build Coastguard Worker ) 689*e1eccf28SAndroid Build Coastguard Worker } 690*e1eccf28SAndroid Build Coastguard Worker 691*e1eccf28SAndroid Build Coastguard Worker return validateSame( 692*e1eccf28SAndroid Build Coastguard Worker "HistogramDotBitmap", 693*e1eccf28SAndroid Build Coastguard Worker intrinsicOutArray, 694*e1eccf28SAndroid Build Coastguard Worker referenceOutArray, 695*e1eccf28SAndroid Build Coastguard Worker toolkitOutArray 696*e1eccf28SAndroid Build Coastguard Worker ) { 697*e1eccf28SAndroid Build Coastguard Worker println("HistogramDotBitmap $restriction") 698*e1eccf28SAndroid Build Coastguard Worker logArray("HistogramDotBitmap coefficients ", coefficients) 699*e1eccf28SAndroid Build Coastguard Worker //logArray("HistogramDotBitmap in ", inputArray) 700*e1eccf28SAndroid Build Coastguard Worker logArray("HistogramDotBitmap reference out", referenceOutArray, 256) 701*e1eccf28SAndroid Build Coastguard Worker logArray("HistogramDotBitmap intrinsic out", intrinsicOutArray, 256) 702*e1eccf28SAndroid Build Coastguard Worker logArray("HistogramDotBitmap toolkit out", toolkitOutArray, 256) 703*e1eccf28SAndroid Build Coastguard Worker } 704*e1eccf28SAndroid Build Coastguard Worker } 705*e1eccf28SAndroid Build Coastguard Worker 706*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 707*e1eccf28SAndroid Build Coastguard Worker private fun testLut(timer: TimingTracker): Boolean { 708*e1eccf28SAndroid Build Coastguard Worker return testOneBitmapLut(timer, testImage1, null) and 709*e1eccf28SAndroid Build Coastguard Worker testOneBitmapLut(timer, testImage1, Range2d(6, 23, 2, 4)) and 710*e1eccf28SAndroid Build Coastguard Worker commonLayoutsToTry.all { (sizeX, sizeY, restriction) -> 711*e1eccf28SAndroid Build Coastguard Worker testOneRandomLut(timer, sizeX, sizeY, restriction) 712*e1eccf28SAndroid Build Coastguard Worker } 713*e1eccf28SAndroid Build Coastguard Worker } 714*e1eccf28SAndroid Build Coastguard Worker 715*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 716*e1eccf28SAndroid Build Coastguard Worker private fun testOneRandomLut( 717*e1eccf28SAndroid Build Coastguard Worker timer: TimingTracker, 718*e1eccf28SAndroid Build Coastguard Worker sizeX: Int, 719*e1eccf28SAndroid Build Coastguard Worker sizeY: Int, 720*e1eccf28SAndroid Build Coastguard Worker restriction: Range2d? 721*e1eccf28SAndroid Build Coastguard Worker ): Boolean { 722*e1eccf28SAndroid Build Coastguard Worker val inputArray = randomByteArray(0x50521f0, sizeX, sizeY, 4) 723*e1eccf28SAndroid Build Coastguard Worker val newRed = randomByteArray(0x32425, 256, 1, 1) 724*e1eccf28SAndroid Build Coastguard Worker val newGreen = randomByteArray(0x1F3225, 256, 1, 1) 725*e1eccf28SAndroid Build Coastguard Worker val newBlue = randomByteArray(0x32D4F27, 256, 1, 1) 726*e1eccf28SAndroid Build Coastguard Worker val newAlpha = randomByteArray(0x3A20001, 256, 1, 1) 727*e1eccf28SAndroid Build Coastguard Worker val table = LookupTable() 728*e1eccf28SAndroid Build Coastguard Worker table.red = newRed 729*e1eccf28SAndroid Build Coastguard Worker table.blue = newBlue 730*e1eccf28SAndroid Build Coastguard Worker table.green = newGreen 731*e1eccf28SAndroid Build Coastguard Worker table.alpha = newAlpha 732*e1eccf28SAndroid Build Coastguard Worker 733*e1eccf28SAndroid Build Coastguard Worker val intrinsicOutArray = timer.measure("IntrinsicLUT") { 734*e1eccf28SAndroid Build Coastguard Worker intrinsicLut( 735*e1eccf28SAndroid Build Coastguard Worker renderscriptContext, inputArray, sizeX, sizeY, newRed, newGreen, newBlue, newAlpha, 736*e1eccf28SAndroid Build Coastguard Worker restriction 737*e1eccf28SAndroid Build Coastguard Worker ) 738*e1eccf28SAndroid Build Coastguard Worker } 739*e1eccf28SAndroid Build Coastguard Worker val toolkitOutArray = timer.measure("ToolkitLUT") { 740*e1eccf28SAndroid Build Coastguard Worker toolkit.lut(inputArray, sizeX, sizeY, table, restriction) 741*e1eccf28SAndroid Build Coastguard Worker } 742*e1eccf28SAndroid Build Coastguard Worker if (!validate) return true 743*e1eccf28SAndroid Build Coastguard Worker 744*e1eccf28SAndroid Build Coastguard Worker val referenceOutArray = timer.measure("ReferenceLUT") { 745*e1eccf28SAndroid Build Coastguard Worker referenceLut(inputArray, sizeX, sizeY, table, restriction) 746*e1eccf28SAndroid Build Coastguard Worker } 747*e1eccf28SAndroid Build Coastguard Worker 748*e1eccf28SAndroid Build Coastguard Worker return validateSame("LUT", intrinsicOutArray, referenceOutArray, toolkitOutArray) { 749*e1eccf28SAndroid Build Coastguard Worker println("lut ($sizeX, $sizeY) $restriction") 750*e1eccf28SAndroid Build Coastguard Worker logArray("LUT red ", newRed, 256) 751*e1eccf28SAndroid Build Coastguard Worker logArray("LUT green", newGreen, 256) 752*e1eccf28SAndroid Build Coastguard Worker logArray("LUT blue ", newBlue, 256) 753*e1eccf28SAndroid Build Coastguard Worker logArray("LUT alpha", newAlpha, 256) 754*e1eccf28SAndroid Build Coastguard Worker logArray("LUT in ", inputArray) 755*e1eccf28SAndroid Build Coastguard Worker logArray("LUT reference out", referenceOutArray) 756*e1eccf28SAndroid Build Coastguard Worker logArray("LUT intrinsic out", intrinsicOutArray) 757*e1eccf28SAndroid Build Coastguard Worker logArray("LUT toolkit out", toolkitOutArray) 758*e1eccf28SAndroid Build Coastguard Worker } 759*e1eccf28SAndroid Build Coastguard Worker } 760*e1eccf28SAndroid Build Coastguard Worker 761*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 762*e1eccf28SAndroid Build Coastguard Worker private fun testOneBitmapLut( 763*e1eccf28SAndroid Build Coastguard Worker timer: TimingTracker, 764*e1eccf28SAndroid Build Coastguard Worker bitmap: Bitmap, 765*e1eccf28SAndroid Build Coastguard Worker restriction: Range2d? 766*e1eccf28SAndroid Build Coastguard Worker ): Boolean { 767*e1eccf28SAndroid Build Coastguard Worker val newRed = randomByteArray(0x32425, 256, 1, 1) 768*e1eccf28SAndroid Build Coastguard Worker val newGreen = randomByteArray(0x1F3225, 256, 1, 1) 769*e1eccf28SAndroid Build Coastguard Worker val newBlue = randomByteArray(0x32D4F27, 256, 1, 1) 770*e1eccf28SAndroid Build Coastguard Worker val newAlpha = randomByteArray(0x3A20001, 256, 1, 1) 771*e1eccf28SAndroid Build Coastguard Worker val table = LookupTable() 772*e1eccf28SAndroid Build Coastguard Worker table.red = newRed 773*e1eccf28SAndroid Build Coastguard Worker table.blue = newBlue 774*e1eccf28SAndroid Build Coastguard Worker table.green = newGreen 775*e1eccf28SAndroid Build Coastguard Worker table.alpha = newAlpha 776*e1eccf28SAndroid Build Coastguard Worker 777*e1eccf28SAndroid Build Coastguard Worker val intrinsicOutArray = timer.measure("IntrinsicLUT") { 778*e1eccf28SAndroid Build Coastguard Worker intrinsicLut( 779*e1eccf28SAndroid Build Coastguard Worker renderscriptContext, bitmap, newRed, newGreen, newBlue, newAlpha, restriction 780*e1eccf28SAndroid Build Coastguard Worker ) 781*e1eccf28SAndroid Build Coastguard Worker } 782*e1eccf28SAndroid Build Coastguard Worker val toolkitOutBitmap = timer.measure("ToolkitLUT") { 783*e1eccf28SAndroid Build Coastguard Worker toolkit.lut(bitmap, table, restriction) 784*e1eccf28SAndroid Build Coastguard Worker } 785*e1eccf28SAndroid Build Coastguard Worker if (!validate) return true 786*e1eccf28SAndroid Build Coastguard Worker 787*e1eccf28SAndroid Build Coastguard Worker val referenceOutArray = timer.measure("ReferenceLUT") { 788*e1eccf28SAndroid Build Coastguard Worker referenceLut( 789*e1eccf28SAndroid Build Coastguard Worker getBitmapBytes(bitmap), 790*e1eccf28SAndroid Build Coastguard Worker bitmap.width, 791*e1eccf28SAndroid Build Coastguard Worker bitmap.height, 792*e1eccf28SAndroid Build Coastguard Worker table, 793*e1eccf28SAndroid Build Coastguard Worker restriction 794*e1eccf28SAndroid Build Coastguard Worker ) 795*e1eccf28SAndroid Build Coastguard Worker } 796*e1eccf28SAndroid Build Coastguard Worker 797*e1eccf28SAndroid Build Coastguard Worker val toolkitOutArray = getBitmapBytes(toolkitOutBitmap) 798*e1eccf28SAndroid Build Coastguard Worker return validateSame("LutBitmap", intrinsicOutArray, referenceOutArray, toolkitOutArray) { 799*e1eccf28SAndroid Build Coastguard Worker println("LutBitmap $restriction") 800*e1eccf28SAndroid Build Coastguard Worker logArray("LutBitmap red ", newRed, 256) 801*e1eccf28SAndroid Build Coastguard Worker logArray("LutBitmap green", newGreen, 256) 802*e1eccf28SAndroid Build Coastguard Worker logArray("LutBitmap blue ", newBlue, 256) 803*e1eccf28SAndroid Build Coastguard Worker logArray("LutBitmap alpha", newAlpha, 256) 804*e1eccf28SAndroid Build Coastguard Worker //logArray("LutBitmap in ", inputArray, 80) 805*e1eccf28SAndroid Build Coastguard Worker logArray("LutBitmap reference out", referenceOutArray) 806*e1eccf28SAndroid Build Coastguard Worker logArray("LutBitmap intrinsic out", intrinsicOutArray) 807*e1eccf28SAndroid Build Coastguard Worker logArray("LutBitmap toolkit out", toolkitOutArray) 808*e1eccf28SAndroid Build Coastguard Worker } 809*e1eccf28SAndroid Build Coastguard Worker } 810*e1eccf28SAndroid Build Coastguard Worker 811*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 812*e1eccf28SAndroid Build Coastguard Worker private fun testLut3d(timer: TimingTracker): Boolean { 813*e1eccf28SAndroid Build Coastguard Worker val cubeSizesToTry = listOf( 814*e1eccf28SAndroid Build Coastguard Worker Dimension(2, 2, 2), 815*e1eccf28SAndroid Build Coastguard Worker Dimension(32, 32, 16), 816*e1eccf28SAndroid Build Coastguard Worker Dimension(256, 256, 256) 817*e1eccf28SAndroid Build Coastguard Worker ) 818*e1eccf28SAndroid Build Coastguard Worker return cubeSizesToTry.all { cubeSize -> 819*e1eccf28SAndroid Build Coastguard Worker val identityCube = identityCube(cubeSize) 820*e1eccf28SAndroid Build Coastguard Worker val randomCube = randomCube(0x23424, cubeSize) 821*e1eccf28SAndroid Build Coastguard Worker testOneBitmapLut3d(timer, testImage1, cubeSize, identityCube, 1, null) and 822*e1eccf28SAndroid Build Coastguard Worker testOneBitmapLut3d(timer, testImage2, cubeSize, randomCube, 3, null) and 823*e1eccf28SAndroid Build Coastguard Worker testOneBitmapLut3d(timer, testImage2, cubeSize, randomCube, 3, Range2d(6, 23, 2, 4)) and 824*e1eccf28SAndroid Build Coastguard Worker commonLayoutsToTry.all { (sizeX, sizeY, restriction) -> 825*e1eccf28SAndroid Build Coastguard Worker testOneRandomLut3d(timer, sizeX, sizeY, cubeSize, identityCube, 1, restriction) && 826*e1eccf28SAndroid Build Coastguard Worker testOneRandomLut3d( 827*e1eccf28SAndroid Build Coastguard Worker timer, 828*e1eccf28SAndroid Build Coastguard Worker sizeX, 829*e1eccf28SAndroid Build Coastguard Worker sizeY, 830*e1eccf28SAndroid Build Coastguard Worker cubeSize, 831*e1eccf28SAndroid Build Coastguard Worker randomCube, 832*e1eccf28SAndroid Build Coastguard Worker 3, 833*e1eccf28SAndroid Build Coastguard Worker restriction 834*e1eccf28SAndroid Build Coastguard Worker ) 835*e1eccf28SAndroid Build Coastguard Worker } 836*e1eccf28SAndroid Build Coastguard Worker } 837*e1eccf28SAndroid Build Coastguard Worker } 838*e1eccf28SAndroid Build Coastguard Worker 839*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 840*e1eccf28SAndroid Build Coastguard Worker private fun testOneRandomLut3d( 841*e1eccf28SAndroid Build Coastguard Worker timer: TimingTracker, 842*e1eccf28SAndroid Build Coastguard Worker sizeX: Int, 843*e1eccf28SAndroid Build Coastguard Worker sizeY: Int, 844*e1eccf28SAndroid Build Coastguard Worker cubeSize: Dimension, 845*e1eccf28SAndroid Build Coastguard Worker cubeArray: ByteArray, 846*e1eccf28SAndroid Build Coastguard Worker allowedIntError: Int, restriction: Range2d? 847*e1eccf28SAndroid Build Coastguard Worker ): Boolean { 848*e1eccf28SAndroid Build Coastguard Worker val inputArray = randomByteArray(0x50521f0, sizeX, sizeY, 4) 849*e1eccf28SAndroid Build Coastguard Worker 850*e1eccf28SAndroid Build Coastguard Worker val intrinsicOutArray = timer.measure("IntrinsicLut3d") { 851*e1eccf28SAndroid Build Coastguard Worker intrinsicLut3d( 852*e1eccf28SAndroid Build Coastguard Worker renderscriptContext, inputArray, sizeX, sizeY, cubeArray, cubeSize, restriction 853*e1eccf28SAndroid Build Coastguard Worker ) 854*e1eccf28SAndroid Build Coastguard Worker } 855*e1eccf28SAndroid Build Coastguard Worker val toolkitOutArray = timer.measure("ToolkitLut3d") { 856*e1eccf28SAndroid Build Coastguard Worker val toolkitCube = Rgba3dArray(cubeArray, cubeSize.sizeX, cubeSize.sizeY, cubeSize.sizeZ) 857*e1eccf28SAndroid Build Coastguard Worker toolkit.lut3d(inputArray, sizeX, sizeY, toolkitCube, restriction) 858*e1eccf28SAndroid Build Coastguard Worker } 859*e1eccf28SAndroid Build Coastguard Worker if (!validate) return true 860*e1eccf28SAndroid Build Coastguard Worker 861*e1eccf28SAndroid Build Coastguard Worker val referenceOutArray = timer.measure("ReferenceLut3d") { 862*e1eccf28SAndroid Build Coastguard Worker val cube = Rgba3dArray(cubeArray, cubeSize.sizeX, cubeSize.sizeY, cubeSize.sizeZ) 863*e1eccf28SAndroid Build Coastguard Worker referenceLut3d(inputArray, sizeX, sizeY, cube, restriction) 864*e1eccf28SAndroid Build Coastguard Worker } 865*e1eccf28SAndroid Build Coastguard Worker 866*e1eccf28SAndroid Build Coastguard Worker return validateSame( 867*e1eccf28SAndroid Build Coastguard Worker "lut3d", 868*e1eccf28SAndroid Build Coastguard Worker intrinsicOutArray, 869*e1eccf28SAndroid Build Coastguard Worker referenceOutArray, 870*e1eccf28SAndroid Build Coastguard Worker toolkitOutArray, 871*e1eccf28SAndroid Build Coastguard Worker false, 872*e1eccf28SAndroid Build Coastguard Worker allowedIntError 873*e1eccf28SAndroid Build Coastguard Worker ) { 874*e1eccf28SAndroid Build Coastguard Worker println("lut3d ($sizeX, $sizeY) $restriction") 875*e1eccf28SAndroid Build Coastguard Worker logArray("lut3d cube", cubeArray, 256) 876*e1eccf28SAndroid Build Coastguard Worker logArray("lut3d in ", inputArray, 64) 877*e1eccf28SAndroid Build Coastguard Worker logArray("lut3d reference out", referenceOutArray, 64) 878*e1eccf28SAndroid Build Coastguard Worker logArray("lut3d intrinsic out", intrinsicOutArray, 64) 879*e1eccf28SAndroid Build Coastguard Worker logArray("lut3d toolkit out", toolkitOutArray) 880*e1eccf28SAndroid Build Coastguard Worker } 881*e1eccf28SAndroid Build Coastguard Worker } 882*e1eccf28SAndroid Build Coastguard Worker 883*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 884*e1eccf28SAndroid Build Coastguard Worker private fun testOneBitmapLut3d( 885*e1eccf28SAndroid Build Coastguard Worker timer: TimingTracker, 886*e1eccf28SAndroid Build Coastguard Worker bitmap: Bitmap, 887*e1eccf28SAndroid Build Coastguard Worker cubeSize: Dimension, 888*e1eccf28SAndroid Build Coastguard Worker cubeArray: ByteArray, 889*e1eccf28SAndroid Build Coastguard Worker allowedIntError: Int, restriction: Range2d? 890*e1eccf28SAndroid Build Coastguard Worker ): Boolean { 891*e1eccf28SAndroid Build Coastguard Worker val intrinsicOutArray = timer.measure("IntrinsicLut3d") { 892*e1eccf28SAndroid Build Coastguard Worker intrinsicLut3d(renderscriptContext, bitmap, cubeArray, cubeSize, restriction) 893*e1eccf28SAndroid Build Coastguard Worker } 894*e1eccf28SAndroid Build Coastguard Worker val toolkitOutBitmap = timer.measure("ToolkitLut3d") { 895*e1eccf28SAndroid Build Coastguard Worker val toolkitCube = Rgba3dArray(cubeArray, cubeSize.sizeX, cubeSize.sizeY, cubeSize.sizeZ) 896*e1eccf28SAndroid Build Coastguard Worker toolkit.lut3d(bitmap, toolkitCube, restriction) 897*e1eccf28SAndroid Build Coastguard Worker } 898*e1eccf28SAndroid Build Coastguard Worker if (!validate) return true 899*e1eccf28SAndroid Build Coastguard Worker 900*e1eccf28SAndroid Build Coastguard Worker val referenceOutArray = timer.measure("ReferenceLut3d") { 901*e1eccf28SAndroid Build Coastguard Worker val cube = Rgba3dArray(cubeArray, cubeSize.sizeX, cubeSize.sizeY, cubeSize.sizeZ) 902*e1eccf28SAndroid Build Coastguard Worker referenceLut3d(getBitmapBytes(bitmap), bitmap.width, bitmap.height, cube, restriction) 903*e1eccf28SAndroid Build Coastguard Worker } 904*e1eccf28SAndroid Build Coastguard Worker 905*e1eccf28SAndroid Build Coastguard Worker val toolkitOutArray = getBitmapBytes(toolkitOutBitmap) 906*e1eccf28SAndroid Build Coastguard Worker return validateSame( 907*e1eccf28SAndroid Build Coastguard Worker "Lut3dBitmap", 908*e1eccf28SAndroid Build Coastguard Worker intrinsicOutArray, 909*e1eccf28SAndroid Build Coastguard Worker referenceOutArray, 910*e1eccf28SAndroid Build Coastguard Worker toolkitOutArray, 911*e1eccf28SAndroid Build Coastguard Worker false, 912*e1eccf28SAndroid Build Coastguard Worker allowedIntError 913*e1eccf28SAndroid Build Coastguard Worker ) { 914*e1eccf28SAndroid Build Coastguard Worker println("Lut3dBitmap $restriction") 915*e1eccf28SAndroid Build Coastguard Worker logArray("Lut3dBitmap cube", cubeArray, 256) 916*e1eccf28SAndroid Build Coastguard Worker //logArray("Lut3dBitmap in ", inputArray, 64) 917*e1eccf28SAndroid Build Coastguard Worker logArray("Lut3dBitmap reference out", referenceOutArray, 64) 918*e1eccf28SAndroid Build Coastguard Worker logArray("Lut3dBitmap intrinsic out", intrinsicOutArray, 64) 919*e1eccf28SAndroid Build Coastguard Worker logArray("Lut3dBitmap toolkit out", toolkitOutArray) 920*e1eccf28SAndroid Build Coastguard Worker } 921*e1eccf28SAndroid Build Coastguard Worker } 922*e1eccf28SAndroid Build Coastguard Worker 923*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 924*e1eccf28SAndroid Build Coastguard Worker private fun testResize(timer: TimingTracker): Boolean { 925*e1eccf28SAndroid Build Coastguard Worker val factorsToTry = listOf( 926*e1eccf28SAndroid Build Coastguard Worker Pair(1f, 1f), 927*e1eccf28SAndroid Build Coastguard Worker Pair(0.5f, 1f), 928*e1eccf28SAndroid Build Coastguard Worker Pair(2f, 2f), 929*e1eccf28SAndroid Build Coastguard Worker Pair(0.5f, 2f), 930*e1eccf28SAndroid Build Coastguard Worker Pair(2f, 0.5f), 931*e1eccf28SAndroid Build Coastguard Worker // The RenderScript Intrinsic tests used the above factors. It's tempting to use 932*e1eccf28SAndroid Build Coastguard Worker // less regular ones like Pair(6.37f, 0.17f) however this creates small offset 933*e1eccf28SAndroid Build Coastguard Worker // errors between the result provided by the C++ code and the SIMD code. This is 934*e1eccf28SAndroid Build Coastguard Worker // due to the SIMD code using a scaled integer to increment going from one pixel to the 935*e1eccf28SAndroid Build Coastguard Worker // next, while the C++ code uses float operations. 936*e1eccf28SAndroid Build Coastguard Worker ) 937*e1eccf28SAndroid Build Coastguard Worker val layoutsToTry = listOf( 938*e1eccf28SAndroid Build Coastguard Worker TestLayout(37, 47, null), 939*e1eccf28SAndroid Build Coastguard Worker TestLayout(60, 10, null), 940*e1eccf28SAndroid Build Coastguard Worker TestLayout(6, 4, Range2d(1, 3, 0, 2)), 941*e1eccf28SAndroid Build Coastguard Worker TestLayout(10, 14, Range2d(2, 3, 3, 7)), 942*e1eccf28SAndroid Build Coastguard Worker ) 943*e1eccf28SAndroid Build Coastguard Worker 944*e1eccf28SAndroid Build Coastguard Worker return factorsToTry.all { (scaleX, scaleY) -> 945*e1eccf28SAndroid Build Coastguard Worker // Do one resize that's greater than 4x, as that's used in the code but don't do it 946*e1eccf28SAndroid Build Coastguard Worker // for everything, as some images will get very large 947*e1eccf28SAndroid Build Coastguard Worker testOneRandomResize(timer, 1, 25, 30, 6f, 6f, null) and 948*e1eccf28SAndroid Build Coastguard Worker testOneBitmapResize(timer, testImage1, scaleX, scaleY, null) and 949*e1eccf28SAndroid Build Coastguard Worker testOneBitmapResize(timer, testImage1, scaleX, scaleY, Range2d(6, 23, 2, 4)) and 950*e1eccf28SAndroid Build Coastguard Worker layoutsToTry.all { (sizeX, sizeY, restriction) -> 951*e1eccf28SAndroid Build Coastguard Worker (1..4).all { vectorSize -> 952*e1eccf28SAndroid Build Coastguard Worker testOneRandomResize( 953*e1eccf28SAndroid Build Coastguard Worker timer, 954*e1eccf28SAndroid Build Coastguard Worker vectorSize, 955*e1eccf28SAndroid Build Coastguard Worker sizeX, 956*e1eccf28SAndroid Build Coastguard Worker sizeY, 957*e1eccf28SAndroid Build Coastguard Worker scaleX, 958*e1eccf28SAndroid Build Coastguard Worker scaleY, 959*e1eccf28SAndroid Build Coastguard Worker restriction 960*e1eccf28SAndroid Build Coastguard Worker ) 961*e1eccf28SAndroid Build Coastguard Worker } 962*e1eccf28SAndroid Build Coastguard Worker } 963*e1eccf28SAndroid Build Coastguard Worker } 964*e1eccf28SAndroid Build Coastguard Worker } 965*e1eccf28SAndroid Build Coastguard Worker 966*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 967*e1eccf28SAndroid Build Coastguard Worker private fun testOneRandomResize( 968*e1eccf28SAndroid Build Coastguard Worker timer: TimingTracker, 969*e1eccf28SAndroid Build Coastguard Worker vectorSize: Int, 970*e1eccf28SAndroid Build Coastguard Worker inSizeX: Int, 971*e1eccf28SAndroid Build Coastguard Worker inSizeY: Int, 972*e1eccf28SAndroid Build Coastguard Worker scaleX: Float, 973*e1eccf28SAndroid Build Coastguard Worker scaleY: Float, 974*e1eccf28SAndroid Build Coastguard Worker restriction: Range2d? 975*e1eccf28SAndroid Build Coastguard Worker ): Boolean { 976*e1eccf28SAndroid Build Coastguard Worker val inputArray = randomByteArray(0x50521f0, inSizeX, inSizeY, paddedSize(vectorSize)) 977*e1eccf28SAndroid Build Coastguard Worker val outSizeX = (inSizeX * scaleX).toInt() 978*e1eccf28SAndroid Build Coastguard Worker val outSizeY = (inSizeY * scaleY).toInt() 979*e1eccf28SAndroid Build Coastguard Worker 980*e1eccf28SAndroid Build Coastguard Worker val intrinsicOutArray = timer.measure("IntrinsicResize") { 981*e1eccf28SAndroid Build Coastguard Worker intrinsicResize( 982*e1eccf28SAndroid Build Coastguard Worker renderscriptContext, inputArray, vectorSize, inSizeX, inSizeY, outSizeX, outSizeY, 983*e1eccf28SAndroid Build Coastguard Worker restriction 984*e1eccf28SAndroid Build Coastguard Worker ) 985*e1eccf28SAndroid Build Coastguard Worker } 986*e1eccf28SAndroid Build Coastguard Worker val toolkitOutArray = timer.measure("ToolkitResize") { 987*e1eccf28SAndroid Build Coastguard Worker toolkit.resize( 988*e1eccf28SAndroid Build Coastguard Worker inputArray, vectorSize, inSizeX, inSizeY, outSizeX, outSizeY, restriction 989*e1eccf28SAndroid Build Coastguard Worker ) 990*e1eccf28SAndroid Build Coastguard Worker } 991*e1eccf28SAndroid Build Coastguard Worker if (!validate) return true 992*e1eccf28SAndroid Build Coastguard Worker 993*e1eccf28SAndroid Build Coastguard Worker val referenceOutArray = timer.measure("ReferenceResize") { 994*e1eccf28SAndroid Build Coastguard Worker referenceResize( 995*e1eccf28SAndroid Build Coastguard Worker inputArray, vectorSize, inSizeX, inSizeY, outSizeX, outSizeY, restriction 996*e1eccf28SAndroid Build Coastguard Worker ) 997*e1eccf28SAndroid Build Coastguard Worker } 998*e1eccf28SAndroid Build Coastguard Worker 999*e1eccf28SAndroid Build Coastguard Worker return validateSame("resize", intrinsicOutArray, referenceOutArray, toolkitOutArray) { 1000*e1eccf28SAndroid Build Coastguard Worker println("resize $vectorSize ($inSizeX, $inSizeY) by ($scaleX, $scaleY) to ($outSizeX, $outSizeY), $restriction") 1001*e1eccf28SAndroid Build Coastguard Worker logArray("resize in ", inputArray) 1002*e1eccf28SAndroid Build Coastguard Worker logArray("resize reference out", referenceOutArray) 1003*e1eccf28SAndroid Build Coastguard Worker logArray("resize intrinsic out", intrinsicOutArray) 1004*e1eccf28SAndroid Build Coastguard Worker logArray("resize toolkit out", toolkitOutArray) 1005*e1eccf28SAndroid Build Coastguard Worker } 1006*e1eccf28SAndroid Build Coastguard Worker } 1007*e1eccf28SAndroid Build Coastguard Worker 1008*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 1009*e1eccf28SAndroid Build Coastguard Worker private fun testOneBitmapResize( 1010*e1eccf28SAndroid Build Coastguard Worker timer: TimingTracker, 1011*e1eccf28SAndroid Build Coastguard Worker bitmap: Bitmap, 1012*e1eccf28SAndroid Build Coastguard Worker scaleX: Float, 1013*e1eccf28SAndroid Build Coastguard Worker scaleY: Float, 1014*e1eccf28SAndroid Build Coastguard Worker restriction: Range2d? 1015*e1eccf28SAndroid Build Coastguard Worker ): Boolean { 1016*e1eccf28SAndroid Build Coastguard Worker // println("Doing resize $inSizeX x $inSizeY x $vectorSize, $scaleX x $scaleY, $restriction") 1017*e1eccf28SAndroid Build Coastguard Worker val outSizeX = (bitmap.width * scaleX).toInt() 1018*e1eccf28SAndroid Build Coastguard Worker val outSizeY = (bitmap.height * scaleY).toInt() 1019*e1eccf28SAndroid Build Coastguard Worker 1020*e1eccf28SAndroid Build Coastguard Worker val intrinsicOutArray = timer.measure("IntrinsicResize") { 1021*e1eccf28SAndroid Build Coastguard Worker intrinsicResize(renderscriptContext, bitmap, outSizeX, outSizeY, restriction) 1022*e1eccf28SAndroid Build Coastguard Worker } 1023*e1eccf28SAndroid Build Coastguard Worker val toolkitOutBitmap = timer.measure("ToolkitResize") { 1024*e1eccf28SAndroid Build Coastguard Worker toolkit.resize(bitmap, outSizeX, outSizeY, restriction) 1025*e1eccf28SAndroid Build Coastguard Worker } 1026*e1eccf28SAndroid Build Coastguard Worker if (!validate) return true 1027*e1eccf28SAndroid Build Coastguard Worker 1028*e1eccf28SAndroid Build Coastguard Worker val referenceOutArray = timer.measure("ReferenceResize") { 1029*e1eccf28SAndroid Build Coastguard Worker referenceResize( 1030*e1eccf28SAndroid Build Coastguard Worker getBitmapBytes(bitmap), 1031*e1eccf28SAndroid Build Coastguard Worker vectorSizeOfBitmap(bitmap), 1032*e1eccf28SAndroid Build Coastguard Worker bitmap.width, 1033*e1eccf28SAndroid Build Coastguard Worker bitmap.height, 1034*e1eccf28SAndroid Build Coastguard Worker outSizeX, 1035*e1eccf28SAndroid Build Coastguard Worker outSizeY, 1036*e1eccf28SAndroid Build Coastguard Worker restriction 1037*e1eccf28SAndroid Build Coastguard Worker ) 1038*e1eccf28SAndroid Build Coastguard Worker } 1039*e1eccf28SAndroid Build Coastguard Worker 1040*e1eccf28SAndroid Build Coastguard Worker val toolkitOutArray = getBitmapBytes(toolkitOutBitmap) 1041*e1eccf28SAndroid Build Coastguard Worker return validateSame("ResizeBitmap", intrinsicOutArray, referenceOutArray, toolkitOutArray) { 1042*e1eccf28SAndroid Build Coastguard Worker println("ResizeBitmap by ($scaleX, $scaleY) to ($outSizeX, $outSizeY), $restriction") 1043*e1eccf28SAndroid Build Coastguard Worker //logArray("ResizeBitmap in ", inputArray, 100) 1044*e1eccf28SAndroid Build Coastguard Worker logArray("ResizeBitmap reference out", referenceOutArray) 1045*e1eccf28SAndroid Build Coastguard Worker logArray("ResizeBitmap intrinsic out", intrinsicOutArray) 1046*e1eccf28SAndroid Build Coastguard Worker logArray("ResizeBitmap toolkit out", toolkitOutArray) 1047*e1eccf28SAndroid Build Coastguard Worker } 1048*e1eccf28SAndroid Build Coastguard Worker } 1049*e1eccf28SAndroid Build Coastguard Worker 1050*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 1051*e1eccf28SAndroid Build Coastguard Worker private fun testYuvToRgb(timer: TimingTracker): Boolean { 1052*e1eccf28SAndroid Build Coastguard Worker val layoutsToTry = listOf( 1053*e1eccf28SAndroid Build Coastguard Worker // Don't try sizeX with odd values. That's not allowed by definition of some 1054*e1eccf28SAndroid Build Coastguard Worker // of the video formats. 1055*e1eccf28SAndroid Build Coastguard Worker TestLayout(10, 14, null), 1056*e1eccf28SAndroid Build Coastguard Worker TestLayout(64, 40, null), 1057*e1eccf28SAndroid Build Coastguard Worker TestLayout(96, 94, null), 1058*e1eccf28SAndroid Build Coastguard Worker ) 1059*e1eccf28SAndroid Build Coastguard Worker return layoutsToTry.all { (sizeX, sizeY, _) -> 1060*e1eccf28SAndroid Build Coastguard Worker YuvFormat.values().all { format -> 1061*e1eccf28SAndroid Build Coastguard Worker testOneRandomYuvToRgb(timer, sizeX, sizeY, format) and 1062*e1eccf28SAndroid Build Coastguard Worker testOneRandomYuvToRgbBitmap(timer, sizeX, sizeY, format) 1063*e1eccf28SAndroid Build Coastguard Worker } 1064*e1eccf28SAndroid Build Coastguard Worker } 1065*e1eccf28SAndroid Build Coastguard Worker } 1066*e1eccf28SAndroid Build Coastguard Worker 1067*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 1068*e1eccf28SAndroid Build Coastguard Worker private fun testOneRandomYuvToRgb( 1069*e1eccf28SAndroid Build Coastguard Worker timer: TimingTracker, 1070*e1eccf28SAndroid Build Coastguard Worker sizeX: Int, 1071*e1eccf28SAndroid Build Coastguard Worker sizeY: Int, 1072*e1eccf28SAndroid Build Coastguard Worker format: YuvFormat 1073*e1eccf28SAndroid Build Coastguard Worker ): Boolean { 1074*e1eccf28SAndroid Build Coastguard Worker // The RenderScript Intrinsic does not handle this combination correctly. 1075*e1eccf28SAndroid Build Coastguard Worker if (format == YuvFormat.YV12 && sizeX % 32 != 0) { 1076*e1eccf28SAndroid Build Coastguard Worker return true 1077*e1eccf28SAndroid Build Coastguard Worker } 1078*e1eccf28SAndroid Build Coastguard Worker val inputArray = randomYuvArray(0x50521f0, sizeX, sizeY, format) 1079*e1eccf28SAndroid Build Coastguard Worker 1080*e1eccf28SAndroid Build Coastguard Worker val intrinsicOutArray = timer.measure("IntrinsicYuvToRgb") { 1081*e1eccf28SAndroid Build Coastguard Worker intrinsicYuvToRgb(renderscriptContext, inputArray, sizeX, sizeY, format) 1082*e1eccf28SAndroid Build Coastguard Worker } 1083*e1eccf28SAndroid Build Coastguard Worker val toolkitOutArray = timer.measure("ToolkitYuvToRgb") { 1084*e1eccf28SAndroid Build Coastguard Worker toolkit.yuvToRgb(inputArray, sizeX, sizeY, format) 1085*e1eccf28SAndroid Build Coastguard Worker } 1086*e1eccf28SAndroid Build Coastguard Worker if (!validate) return true 1087*e1eccf28SAndroid Build Coastguard Worker 1088*e1eccf28SAndroid Build Coastguard Worker val referenceOutArray = timer.measure("ReferenceYuvToRgb") { 1089*e1eccf28SAndroid Build Coastguard Worker referenceYuvToRgb(inputArray, sizeX, sizeY, format) 1090*e1eccf28SAndroid Build Coastguard Worker } 1091*e1eccf28SAndroid Build Coastguard Worker 1092*e1eccf28SAndroid Build Coastguard Worker return validateSame("yuvToRgb", intrinsicOutArray, referenceOutArray, toolkitOutArray) { 1093*e1eccf28SAndroid Build Coastguard Worker println("yuvToRgb ($sizeX, $sizeY) $format") 1094*e1eccf28SAndroid Build Coastguard Worker logArray("yuvToRgb in ", inputArray) 1095*e1eccf28SAndroid Build Coastguard Worker logArray("yuvToRgb reference out", referenceOutArray) 1096*e1eccf28SAndroid Build Coastguard Worker logArray("yuvToRgb intrinsic out", intrinsicOutArray) 1097*e1eccf28SAndroid Build Coastguard Worker logArray("yuvToRgb toolkit out", toolkitOutArray) 1098*e1eccf28SAndroid Build Coastguard Worker } 1099*e1eccf28SAndroid Build Coastguard Worker } 1100*e1eccf28SAndroid Build Coastguard Worker 1101*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 1102*e1eccf28SAndroid Build Coastguard Worker private fun testOneRandomYuvToRgbBitmap( 1103*e1eccf28SAndroid Build Coastguard Worker timer: TimingTracker, 1104*e1eccf28SAndroid Build Coastguard Worker sizeX: Int, 1105*e1eccf28SAndroid Build Coastguard Worker sizeY: Int, 1106*e1eccf28SAndroid Build Coastguard Worker format: YuvFormat 1107*e1eccf28SAndroid Build Coastguard Worker ): Boolean { 1108*e1eccf28SAndroid Build Coastguard Worker // The RenderScript Intrinsic does not handle this combination correctly. 1109*e1eccf28SAndroid Build Coastguard Worker if (format == YuvFormat.YV12 && sizeX % 32 != 0) { 1110*e1eccf28SAndroid Build Coastguard Worker return true 1111*e1eccf28SAndroid Build Coastguard Worker } 1112*e1eccf28SAndroid Build Coastguard Worker val inputArray = randomYuvArray(0x50521f0, sizeX, sizeY, format) 1113*e1eccf28SAndroid Build Coastguard Worker 1114*e1eccf28SAndroid Build Coastguard Worker val intrinsicOutArray = timer.measure("IntrinsicYuvToRgb") { 1115*e1eccf28SAndroid Build Coastguard Worker intrinsicYuvToRgb(renderscriptContext, inputArray, sizeX, sizeY, format) 1116*e1eccf28SAndroid Build Coastguard Worker } 1117*e1eccf28SAndroid Build Coastguard Worker val toolkitOutBitmap = timer.measure("ToolkitYuvToRgb") { 1118*e1eccf28SAndroid Build Coastguard Worker toolkit.yuvToRgbBitmap(inputArray, sizeX, sizeY, format) 1119*e1eccf28SAndroid Build Coastguard Worker } 1120*e1eccf28SAndroid Build Coastguard Worker if (!validate) return true 1121*e1eccf28SAndroid Build Coastguard Worker 1122*e1eccf28SAndroid Build Coastguard Worker val referenceOutArray = timer.measure("ReferenceYuvToRgb") { 1123*e1eccf28SAndroid Build Coastguard Worker referenceYuvToRgb(inputArray, sizeX, sizeY, format) 1124*e1eccf28SAndroid Build Coastguard Worker } 1125*e1eccf28SAndroid Build Coastguard Worker 1126*e1eccf28SAndroid Build Coastguard Worker val toolkitOutArray = getBitmapBytes(toolkitOutBitmap) 1127*e1eccf28SAndroid Build Coastguard Worker return validateSame("yuvToRgb", intrinsicOutArray, referenceOutArray, toolkitOutArray) { 1128*e1eccf28SAndroid Build Coastguard Worker println("yuvToRgb ($sizeX, $sizeY) $format") 1129*e1eccf28SAndroid Build Coastguard Worker logArray("yuvToRgb in ", inputArray) 1130*e1eccf28SAndroid Build Coastguard Worker logArray("yuvToRgb reference out", referenceOutArray) 1131*e1eccf28SAndroid Build Coastguard Worker logArray("yuvToRgb intrinsic out", intrinsicOutArray) 1132*e1eccf28SAndroid Build Coastguard Worker logArray("yuvToRgb toolkit out", toolkitOutArray) 1133*e1eccf28SAndroid Build Coastguard Worker } 1134*e1eccf28SAndroid Build Coastguard Worker } 1135*e1eccf28SAndroid Build Coastguard Worker 1136*e1eccf28SAndroid Build Coastguard Worker /** 1137*e1eccf28SAndroid Build Coastguard Worker * Verifies that the arrays returned by the Intrinsic, the reference code, and the Toolkit 1138*e1eccf28SAndroid Build Coastguard Worker * are all within a margin of error. 1139*e1eccf28SAndroid Build Coastguard Worker * 1140*e1eccf28SAndroid Build Coastguard Worker * RenderScript Intrinsic test (rc/android/cts/rscpp/RSCppTest.java) used 3 for ints. 1141*e1eccf28SAndroid Build Coastguard Worker * For floats, rc/android/cts/rscpp/verify.rscript uses 0.0001f. 1142*e1eccf28SAndroid Build Coastguard Worker */ 1143*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 1144*e1eccf28SAndroid Build Coastguard Worker private fun validateSame( 1145*e1eccf28SAndroid Build Coastguard Worker task: String, 1146*e1eccf28SAndroid Build Coastguard Worker intrinsic: ByteArray, 1147*e1eccf28SAndroid Build Coastguard Worker reference: ByteArray, 1148*e1eccf28SAndroid Build Coastguard Worker toolkit: ByteArray, 1149*e1eccf28SAndroid Build Coastguard Worker skipFourth: Boolean = false, 1150*e1eccf28SAndroid Build Coastguard Worker allowedIntDelta: Int = 3, 1151*e1eccf28SAndroid Build Coastguard Worker errorLogging: () -> Unit 1152*e1eccf28SAndroid Build Coastguard Worker ): Boolean { 1153*e1eccf28SAndroid Build Coastguard Worker val success = validateAgainstReference( 1154*e1eccf28SAndroid Build Coastguard Worker task, reference, "Intrinsic", intrinsic, skipFourth, allowedIntDelta 1155*e1eccf28SAndroid Build Coastguard Worker ) and validateAgainstReference( 1156*e1eccf28SAndroid Build Coastguard Worker task, reference, "Toolkit", toolkit, skipFourth, allowedIntDelta 1157*e1eccf28SAndroid Build Coastguard Worker ) 1158*e1eccf28SAndroid Build Coastguard Worker if (!success) { 1159*e1eccf28SAndroid Build Coastguard Worker println("$task FAIL!FAIL!FAIL!FAIL!FAIL!FAIL!FAIL!FAIL!FAIL!") 1160*e1eccf28SAndroid Build Coastguard Worker errorLogging() 1161*e1eccf28SAndroid Build Coastguard Worker } 1162*e1eccf28SAndroid Build Coastguard Worker return success 1163*e1eccf28SAndroid Build Coastguard Worker } 1164*e1eccf28SAndroid Build Coastguard Worker 1165*e1eccf28SAndroid Build Coastguard Worker private fun validateSame( 1166*e1eccf28SAndroid Build Coastguard Worker task: String, 1167*e1eccf28SAndroid Build Coastguard Worker intrinsic: IntArray, 1168*e1eccf28SAndroid Build Coastguard Worker reference: IntArray, 1169*e1eccf28SAndroid Build Coastguard Worker toolkit: IntArray, 1170*e1eccf28SAndroid Build Coastguard Worker allowedIntDelta: Int = 3, 1171*e1eccf28SAndroid Build Coastguard Worker errorLogging: () -> Unit 1172*e1eccf28SAndroid Build Coastguard Worker ): Boolean { 1173*e1eccf28SAndroid Build Coastguard Worker val success = validateAgainstReference( 1174*e1eccf28SAndroid Build Coastguard Worker task, reference, "Intrinsic", intrinsic, allowedIntDelta 1175*e1eccf28SAndroid Build Coastguard Worker ) and validateAgainstReference( 1176*e1eccf28SAndroid Build Coastguard Worker task, reference, "Toolkit", toolkit, allowedIntDelta 1177*e1eccf28SAndroid Build Coastguard Worker ) 1178*e1eccf28SAndroid Build Coastguard Worker if (!success) { 1179*e1eccf28SAndroid Build Coastguard Worker println("$task FAIL!FAIL!FAIL!FAIL!FAIL!FAIL!FAIL!FAIL!FAIL!") 1180*e1eccf28SAndroid Build Coastguard Worker errorLogging() 1181*e1eccf28SAndroid Build Coastguard Worker } 1182*e1eccf28SAndroid Build Coastguard Worker return success 1183*e1eccf28SAndroid Build Coastguard Worker } 1184*e1eccf28SAndroid Build Coastguard Worker 1185*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes 1186*e1eccf28SAndroid Build Coastguard Worker private fun validateAgainstReference( 1187*e1eccf28SAndroid Build Coastguard Worker task: String, 1188*e1eccf28SAndroid Build Coastguard Worker in1: ByteArray, 1189*e1eccf28SAndroid Build Coastguard Worker name2: String, 1190*e1eccf28SAndroid Build Coastguard Worker in2: ByteArray, 1191*e1eccf28SAndroid Build Coastguard Worker skipFourth: Boolean, 1192*e1eccf28SAndroid Build Coastguard Worker allowedIntDelta: Int 1193*e1eccf28SAndroid Build Coastguard Worker ): Boolean { 1194*e1eccf28SAndroid Build Coastguard Worker if (in1.size != in2.size) { 1195*e1eccf28SAndroid Build Coastguard Worker println("$task. Sizes don't match: Reference ${in1.size}, $name2 ${in2.size}") 1196*e1eccf28SAndroid Build Coastguard Worker return false 1197*e1eccf28SAndroid Build Coastguard Worker } 1198*e1eccf28SAndroid Build Coastguard Worker var same = true 1199*e1eccf28SAndroid Build Coastguard Worker val maxDetails = 80 1200*e1eccf28SAndroid Build Coastguard Worker val diffs = CharArray(min(in1.size, maxDetails)) {'.'} 1201*e1eccf28SAndroid Build Coastguard Worker for (i in in1.indices) { 1202*e1eccf28SAndroid Build Coastguard Worker if (skipFourth && i % 4 == 3) { 1203*e1eccf28SAndroid Build Coastguard Worker continue 1204*e1eccf28SAndroid Build Coastguard Worker } 1205*e1eccf28SAndroid Build Coastguard Worker val delta = abs(in1[i].toUByte().toInt() - in2[i].toUByte().toInt()) 1206*e1eccf28SAndroid Build Coastguard Worker if (delta > allowedIntDelta) { 1207*e1eccf28SAndroid Build Coastguard Worker if (same) { 1208*e1eccf28SAndroid Build Coastguard Worker println( 1209*e1eccf28SAndroid Build Coastguard Worker "$task. At $i, Reference is ${in1[i].toUByte()}, $name2 is ${in2[i].toUByte()}" 1210*e1eccf28SAndroid Build Coastguard Worker ) 1211*e1eccf28SAndroid Build Coastguard Worker } 1212*e1eccf28SAndroid Build Coastguard Worker if (i < maxDetails) diffs[i] = 'X' 1213*e1eccf28SAndroid Build Coastguard Worker same = false 1214*e1eccf28SAndroid Build Coastguard Worker } 1215*e1eccf28SAndroid Build Coastguard Worker } 1216*e1eccf28SAndroid Build Coastguard Worker if (!same) { 1217*e1eccf28SAndroid Build Coastguard Worker for (i in 0 until (min(in1.size, maxDetails) / 4)) print("%-3d|".format(i)) 1218*e1eccf28SAndroid Build Coastguard Worker println() 1219*e1eccf28SAndroid Build Coastguard Worker println(diffs) 1220*e1eccf28SAndroid Build Coastguard Worker } 1221*e1eccf28SAndroid Build Coastguard Worker return same 1222*e1eccf28SAndroid Build Coastguard Worker } 1223*e1eccf28SAndroid Build Coastguard Worker 1224*e1eccf28SAndroid Build Coastguard Worker private fun validateAgainstReference( 1225*e1eccf28SAndroid Build Coastguard Worker task: String, 1226*e1eccf28SAndroid Build Coastguard Worker in1: IntArray, 1227*e1eccf28SAndroid Build Coastguard Worker name2: String, 1228*e1eccf28SAndroid Build Coastguard Worker in2: IntArray, 1229*e1eccf28SAndroid Build Coastguard Worker allowedIntDelta: Int 1230*e1eccf28SAndroid Build Coastguard Worker ): Boolean { 1231*e1eccf28SAndroid Build Coastguard Worker if (in1.size != in2.size) { 1232*e1eccf28SAndroid Build Coastguard Worker println("$task. Sizes don't match: Reference ${in1.size}, $name2 ${in2.size}") 1233*e1eccf28SAndroid Build Coastguard Worker return false 1234*e1eccf28SAndroid Build Coastguard Worker } 1235*e1eccf28SAndroid Build Coastguard Worker for (i in in1.indices) { 1236*e1eccf28SAndroid Build Coastguard Worker val delta = abs(in1[i] - in2[i]) 1237*e1eccf28SAndroid Build Coastguard Worker if (delta > allowedIntDelta) { 1238*e1eccf28SAndroid Build Coastguard Worker println("$task. At $i, Reference is ${in1[i]}, $name2 is ${in2[i]}") 1239*e1eccf28SAndroid Build Coastguard Worker return false 1240*e1eccf28SAndroid Build Coastguard Worker } 1241*e1eccf28SAndroid Build Coastguard Worker } 1242*e1eccf28SAndroid Build Coastguard Worker return true 1243*e1eccf28SAndroid Build Coastguard Worker } 1244*e1eccf28SAndroid Build Coastguard Worker } 1245