Reland "Add an SkImageGenerator that uses NDK APIs"
This reverts commit 07438b0cda
.
Bug: skia:10369
Bug: skia:10371
This will allow Skia clients developing for Android 11+ to rely on
Android's NDK APIs for decoding, which will allow them to decode
without including their own decoding libraries (e.g. libjpeg-turbo).
Using these APIs also provides support for static HEIF images.
Run ImageGenSrc in kPlatform_Mode on Android to verify decoding
visually.
Add tests and a grayscale png.
Update some test bots running Android R to specify ndk_api so they will
run the new code.
Change-Id: I4ca07d832dbd6a9d8cff0faea975fd70da00718f
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/308185
Reviewed-by: Mike Klein <mtklein@google.com>
Commit-Queue: Leon Scroggins <scroggo@google.com>
This commit is contained in:
parent
749149278c
commit
f21d6b9b71
8
BUILD.gn
8
BUILD.gn
@ -820,6 +820,13 @@ optional("jpeg_encode") {
|
||||
]
|
||||
}
|
||||
|
||||
optional("ndk_decode") {
|
||||
enabled = skia_use_ndk_decode
|
||||
public_defines = [ "SK_ENABLE_NDK_DECODING" ]
|
||||
sources = [ "src/ports/SkImageGeneratorNDK.cpp" ]
|
||||
libs = [ "jnigraphics" ]
|
||||
}
|
||||
|
||||
optional("pdf") {
|
||||
enabled = skia_use_zlib && skia_enable_pdf
|
||||
public_defines = [ "SK_SUPPORT_PDF" ]
|
||||
@ -1044,6 +1051,7 @@ component("skia") {
|
||||
":hsw",
|
||||
":jpeg_decode",
|
||||
":jpeg_encode",
|
||||
":ndk_decode",
|
||||
":none",
|
||||
":png_decode",
|
||||
":png_encode",
|
||||
|
@ -7,6 +7,9 @@ This file includes a list of high level updates for each milestone release.
|
||||
Milestone 86
|
||||
------------
|
||||
|
||||
* Add SkImageGeneratorNDK for using Android's NDK APIs to decode.
|
||||
https://review.skia.org/305689
|
||||
|
||||
* SkImage:remove DecodeToRaster, DecodeToTexture
|
||||
https://review.skia.org/306331
|
||||
|
||||
|
@ -838,6 +838,8 @@ static void push_codec_srcs(Path path) {
|
||||
{
|
||||
push_image_gen_src(path, ImageGenSrc::kPlatform_Mode, alphaType, false);
|
||||
}
|
||||
#elif defined(SK_ENABLE_NDK_DECODING)
|
||||
push_image_gen_src(path, ImageGenSrc::kPlatform_Mode, alphaType, false);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "include/gpu/GrBackendSurface.h"
|
||||
#include "include/gpu/GrDirectContext.h"
|
||||
#include "include/ports/SkImageGeneratorCG.h"
|
||||
#include "include/ports/SkImageGeneratorNDK.h"
|
||||
#include "include/ports/SkImageGeneratorWIC.h"
|
||||
#include "include/private/SkImageInfoPriv.h"
|
||||
#include "include/private/SkTLogic.h"
|
||||
@ -923,6 +924,8 @@ Result ImageGenSrc::draw(GrDirectContext*, SkCanvas* canvas) const {
|
||||
gen = SkImageGeneratorCG::MakeFromEncodedCG(encoded);
|
||||
#elif defined(SK_BUILD_FOR_WIN)
|
||||
gen = SkImageGeneratorWIC::MakeFromEncodedWIC(encoded);
|
||||
#elif defined(SK_ENABLE_NDK_DECODING)
|
||||
gen = SkImageGeneratorNDK::MakeFromEncodedNDK(encoded);
|
||||
#endif
|
||||
if (!gen) {
|
||||
return Result::Fatal("Could not create platform image generator.");
|
||||
|
@ -64,6 +64,7 @@ declare_args() {
|
||||
skia_use_libwebp_encode = true
|
||||
skia_use_lua = is_skia_dev_build && !is_ios
|
||||
skia_use_metal = false
|
||||
skia_use_ndk_decode = is_android && defined(ndk_api) && ndk_api >= 30
|
||||
skia_use_opencl = false
|
||||
skia_use_piex = !is_win
|
||||
skia_use_wuffs = false
|
||||
|
@ -161,6 +161,7 @@ tests_sources = [
|
||||
"$_tests/MetaDataTest.cpp",
|
||||
"$_tests/MipMapTest.cpp",
|
||||
"$_tests/MultiPictureDocumentTest.cpp",
|
||||
"$_tests/NdkDecodeTest.cpp",
|
||||
"$_tests/NonlinearBlendingTest.cpp",
|
||||
"$_tests/OSPathTest.cpp",
|
||||
"$_tests/OctoBoundsTest.cpp",
|
||||
|
36
include/ports/SkImageGeneratorNDK.h
Normal file
36
include/ports/SkImageGeneratorNDK.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "include/core/SkTypes.h"
|
||||
#ifdef SK_ENABLE_NDK_DECODING
|
||||
|
||||
#include "include/core/SkData.h"
|
||||
#include "include/core/SkImageGenerator.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace SkImageGeneratorNDK {
|
||||
/**
|
||||
* Create a generator that uses the Android NDK's APIs for decoding images.
|
||||
*
|
||||
* Only supported on devices where __ANDROID_API__ >= 30.
|
||||
*
|
||||
* As with SkCodec, the SkColorSpace passed to getPixels() determines the
|
||||
* type of color space transformations to apply. A null SkColorSpace means to
|
||||
* apply none.
|
||||
*
|
||||
* A note on scaling: Calling getPixels() on the resulting SkImageGenerator
|
||||
* with dimensions that do not match getInfo() requests a scale. For WebP
|
||||
* files, dimensions smaller than those of getInfo are supported. For Jpeg
|
||||
* files, dimensions of 1/2, 1/4, and 1/8 are supported. TODO: Provide an
|
||||
* API like SkCodecImageGenerator::getScaledDimensions() to report which
|
||||
* dimensions are supported?
|
||||
*/
|
||||
SK_API std::unique_ptr<SkImageGenerator> MakeFromEncodedNDK(sk_sp<SkData>);
|
||||
}
|
||||
|
||||
#endif
|
@ -17,10 +17,12 @@
|
||||
"Build-Debian10-Clang-arm-Release-Android_Vulkan",
|
||||
"Build-Debian10-Clang-arm-Release-Chromebook_GLES",
|
||||
"Build-Debian10-Clang-arm64-Debug-Android",
|
||||
"Build-Debian10-Clang-arm64-Debug-Android_API30",
|
||||
"Build-Debian10-Clang-arm64-Debug-Android_ASAN",
|
||||
"Build-Debian10-Clang-arm64-Debug-Android_ASAN_Vulkan",
|
||||
"Build-Debian10-Clang-arm64-Debug-Android_Vulkan",
|
||||
"Build-Debian10-Clang-arm64-Release-Android",
|
||||
"Build-Debian10-Clang-arm64-Release-Android_API30",
|
||||
"Build-Debian10-Clang-arm64-Release-Android_Vulkan",
|
||||
"Build-Debian10-Clang-arm64-Release-Android_Wuffs",
|
||||
"Build-Debian10-Clang-x64-Debug-Android",
|
||||
@ -386,9 +388,9 @@
|
||||
"Test-Android-Clang-Pixel3a-GPU-Adreno615-arm64-Debug-All-Android_Vulkan",
|
||||
"Test-Android-Clang-Pixel3a-GPU-Adreno615-arm64-Release-All-Android",
|
||||
"Test-Android-Clang-Pixel3a-GPU-Adreno615-arm64-Release-All-Android_Vulkan",
|
||||
"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Debug-All-Android",
|
||||
"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Debug-All-Android_API30",
|
||||
"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Debug-All-Android_Vulkan",
|
||||
"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Release-All-Android",
|
||||
"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Release-All-Android_API30",
|
||||
"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Release-All-Android_Vulkan",
|
||||
"Test-Android-Clang-Pixel4XL-GPU-Adreno640-arm64-Debug-All-Android",
|
||||
"Test-Android-Clang-Pixel4XL-GPU-Adreno640-arm64-Debug-All-Android_Vulkan",
|
||||
|
@ -50,6 +50,11 @@
|
||||
"Build-Debian10-Clang-arm64-Debug-Android"
|
||||
]
|
||||
},
|
||||
"Build-Debian10-Clang-arm64-Debug-Android_API30": {
|
||||
"tasks": [
|
||||
"Build-Debian10-Clang-arm64-Debug-Android_API30"
|
||||
]
|
||||
},
|
||||
"Build-Debian10-Clang-arm64-Debug-Android_ASAN": {
|
||||
"tasks": [
|
||||
"Build-Debian10-Clang-arm64-Debug-Android_ASAN"
|
||||
@ -70,6 +75,11 @@
|
||||
"Build-Debian10-Clang-arm64-Release-Android"
|
||||
]
|
||||
},
|
||||
"Build-Debian10-Clang-arm64-Release-Android_API30": {
|
||||
"tasks": [
|
||||
"Build-Debian10-Clang-arm64-Release-Android_API30"
|
||||
]
|
||||
},
|
||||
"Build-Debian10-Clang-arm64-Release-Android_Vulkan": {
|
||||
"tasks": [
|
||||
"Build-Debian10-Clang-arm64-Release-Android_Vulkan"
|
||||
@ -1953,9 +1963,9 @@
|
||||
"Upload-Test-Android-Clang-Pixel3a-GPU-Adreno615-arm64-Release-All-Android_Vulkan"
|
||||
]
|
||||
},
|
||||
"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Debug-All-Android": {
|
||||
"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Debug-All-Android_API30": {
|
||||
"tasks": [
|
||||
"Upload-Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Debug-All-Android"
|
||||
"Upload-Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Debug-All-Android_API30"
|
||||
]
|
||||
},
|
||||
"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Debug-All-Android_Vulkan": {
|
||||
@ -1963,9 +1973,9 @@
|
||||
"Upload-Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Debug-All-Android_Vulkan"
|
||||
]
|
||||
},
|
||||
"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Release-All-Android": {
|
||||
"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Release-All-Android_API30": {
|
||||
"tasks": [
|
||||
"Upload-Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Release-All-Android"
|
||||
"Upload-Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Release-All-Android_API30"
|
||||
]
|
||||
},
|
||||
"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Release-All-Android_Vulkan": {
|
||||
@ -4062,6 +4072,76 @@
|
||||
],
|
||||
"service_account": "skia-external-compile-tasks@skia-swarming-bots.iam.gserviceaccount.com"
|
||||
},
|
||||
"Build-Debian10-Clang-arm64-Debug-Android_API30": {
|
||||
"caches": [
|
||||
{
|
||||
"name": "vpython",
|
||||
"path": "cache/vpython"
|
||||
}
|
||||
],
|
||||
"cipd_packages": [
|
||||
{
|
||||
"name": "infra/tools/luci-auth/${platform}",
|
||||
"path": "cipd_bin_packages",
|
||||
"version": "git_revision:08768c6d238082f3c552dcabef6aaf4c6792d91a"
|
||||
},
|
||||
{
|
||||
"name": "infra/tools/luci/kitchen/${platform}",
|
||||
"path": ".",
|
||||
"version": "git_revision:08768c6d238082f3c552dcabef6aaf4c6792d91a"
|
||||
},
|
||||
{
|
||||
"name": "infra/tools/luci/vpython/${platform}",
|
||||
"path": "cipd_bin_packages",
|
||||
"version": "git_revision:08768c6d238082f3c552dcabef6aaf4c6792d91a"
|
||||
},
|
||||
{
|
||||
"name": "skia/bots/android_ndk_linux",
|
||||
"path": "android_ndk_linux",
|
||||
"version": "version:16"
|
||||
}
|
||||
],
|
||||
"command": [
|
||||
"cipd_bin_packages/vpython${EXECUTABLE_SUFFIX}",
|
||||
"-u",
|
||||
"skia/infra/bots/run_recipe.py",
|
||||
"${ISOLATED_OUTDIR}",
|
||||
"compile",
|
||||
"{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"buildername\":\"Build-Debian10-Clang-arm64-Debug-Android_API30\",\"swarm_out_dir\":\"build\"}",
|
||||
"skia"
|
||||
],
|
||||
"dependencies": [
|
||||
"Housekeeper-PerCommit-BundleRecipes"
|
||||
],
|
||||
"dimensions": [
|
||||
"cpu:x86-64-Haswell_GCE",
|
||||
"gpu:none",
|
||||
"machine_type:n1-highcpu-64",
|
||||
"os:Debian-10.3",
|
||||
"pool:Skia"
|
||||
],
|
||||
"env_prefixes": {
|
||||
"PATH": [
|
||||
"cipd_bin_packages",
|
||||
"cipd_bin_packages/bin"
|
||||
],
|
||||
"VPYTHON_VIRTUALENV_ROOT": [
|
||||
"cache/vpython"
|
||||
]
|
||||
},
|
||||
"execution_timeout_ns": 3600000000000,
|
||||
"extra_tags": {
|
||||
"log_location": "logdog://logs.chromium.org/skia/${SWARMING_TASK_ID}/+/annotations"
|
||||
},
|
||||
"idempotent": true,
|
||||
"io_timeout_ns": 3600000000000,
|
||||
"isolate": "compile.isolate",
|
||||
"max_attempts": 2,
|
||||
"outputs": [
|
||||
"build"
|
||||
],
|
||||
"service_account": "skia-external-compile-tasks@skia-swarming-bots.iam.gserviceaccount.com"
|
||||
},
|
||||
"Build-Debian10-Clang-arm64-Debug-Android_ASAN": {
|
||||
"caches": [
|
||||
{
|
||||
@ -4342,6 +4422,76 @@
|
||||
],
|
||||
"service_account": "skia-external-compile-tasks@skia-swarming-bots.iam.gserviceaccount.com"
|
||||
},
|
||||
"Build-Debian10-Clang-arm64-Release-Android_API30": {
|
||||
"caches": [
|
||||
{
|
||||
"name": "vpython",
|
||||
"path": "cache/vpython"
|
||||
}
|
||||
],
|
||||
"cipd_packages": [
|
||||
{
|
||||
"name": "infra/tools/luci-auth/${platform}",
|
||||
"path": "cipd_bin_packages",
|
||||
"version": "git_revision:08768c6d238082f3c552dcabef6aaf4c6792d91a"
|
||||
},
|
||||
{
|
||||
"name": "infra/tools/luci/kitchen/${platform}",
|
||||
"path": ".",
|
||||
"version": "git_revision:08768c6d238082f3c552dcabef6aaf4c6792d91a"
|
||||
},
|
||||
{
|
||||
"name": "infra/tools/luci/vpython/${platform}",
|
||||
"path": "cipd_bin_packages",
|
||||
"version": "git_revision:08768c6d238082f3c552dcabef6aaf4c6792d91a"
|
||||
},
|
||||
{
|
||||
"name": "skia/bots/android_ndk_linux",
|
||||
"path": "android_ndk_linux",
|
||||
"version": "version:16"
|
||||
}
|
||||
],
|
||||
"command": [
|
||||
"cipd_bin_packages/vpython${EXECUTABLE_SUFFIX}",
|
||||
"-u",
|
||||
"skia/infra/bots/run_recipe.py",
|
||||
"${ISOLATED_OUTDIR}",
|
||||
"compile",
|
||||
"{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"buildername\":\"Build-Debian10-Clang-arm64-Release-Android_API30\",\"swarm_out_dir\":\"build\"}",
|
||||
"skia"
|
||||
],
|
||||
"dependencies": [
|
||||
"Housekeeper-PerCommit-BundleRecipes"
|
||||
],
|
||||
"dimensions": [
|
||||
"cpu:x86-64-Haswell_GCE",
|
||||
"gpu:none",
|
||||
"machine_type:n1-highcpu-64",
|
||||
"os:Debian-10.3",
|
||||
"pool:Skia"
|
||||
],
|
||||
"env_prefixes": {
|
||||
"PATH": [
|
||||
"cipd_bin_packages",
|
||||
"cipd_bin_packages/bin"
|
||||
],
|
||||
"VPYTHON_VIRTUALENV_ROOT": [
|
||||
"cache/vpython"
|
||||
]
|
||||
},
|
||||
"execution_timeout_ns": 3600000000000,
|
||||
"extra_tags": {
|
||||
"log_location": "logdog://logs.chromium.org/skia/${SWARMING_TASK_ID}/+/annotations"
|
||||
},
|
||||
"idempotent": true,
|
||||
"io_timeout_ns": 3600000000000,
|
||||
"isolate": "compile.isolate",
|
||||
"max_attempts": 2,
|
||||
"outputs": [
|
||||
"build"
|
||||
],
|
||||
"service_account": "skia-external-compile-tasks@skia-swarming-bots.iam.gserviceaccount.com"
|
||||
},
|
||||
"Build-Debian10-Clang-arm64-Release-Android_Vulkan": {
|
||||
"caches": [
|
||||
{
|
||||
@ -32290,7 +32440,7 @@
|
||||
"test"
|
||||
]
|
||||
},
|
||||
"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Debug-All-Android": {
|
||||
"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Debug-All-Android_API30": {
|
||||
"caches": [
|
||||
{
|
||||
"name": "vpython",
|
||||
@ -32320,11 +32470,11 @@
|
||||
"skia/infra/bots/run_recipe.py",
|
||||
"${ISOLATED_OUTDIR}",
|
||||
"test",
|
||||
"{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"buildbucket_build_id\":\"<(BUILDBUCKET_BUILD_ID)\",\"buildername\":\"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Debug-All-Android\",\"dm_flags\":\"[\\\"dm\\\",\\\"--nameByHash\\\",\\\"--key\\\",\\\"arch\\\",\\\"arm64\\\",\\\"compiler\\\",\\\"Clang\\\",\\\"configuration\\\",\\\"Debug\\\",\\\"cpu_or_gpu\\\",\\\"GPU\\\",\\\"cpu_or_gpu_value\\\",\\\"Adreno640\\\",\\\"extra_config\\\",\\\"Android\\\",\\\"model\\\",\\\"Pixel4\\\",\\\"os\\\",\\\"Android\\\",\\\"style\\\",\\\"default\\\",\\\"--nocpu\\\",\\\"--config\\\",\\\"gles\\\",\\\"glesdft\\\",\\\"glessrgb\\\",\\\"glesmsaa4\\\",\\\"--src\\\",\\\"tests\\\",\\\"gm\\\",\\\"image\\\",\\\"colorImage\\\",\\\"svg\\\",\\\"--skip\\\",\\\"_\\\",\\\"svg\\\",\\\"_\\\",\\\"svgparse_\\\",\\\"glessrgb\\\",\\\"image\\\",\\\"_\\\",\\\"_\\\",\\\"_\\\",\\\"image\\\",\\\"gen_platf\\\",\\\"error\\\",\\\"_\\\",\\\"test\\\",\\\"_\\\",\\\"GrStyledShape\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\"interlaced1.png\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\"interlaced2.png\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\"interlaced3.png\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".arw\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".cr2\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".dng\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".nef\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".nrw\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".orf\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".raf\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".rw2\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".pef\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".srw\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".ARW\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".CR2\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".DNG\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".NEF\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".NRW\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".ORF\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".RAF\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".RW2\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".PEF\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".SRW\\\",\\\"--nonativeFonts\\\",\\\"--verbose\\\"]\",\"dm_properties\":\"{\\\"buildbucket_build_id\\\":\\\"<(BUILDBUCKET_BUILD_ID)\\\",\\\"builder\\\":\\\"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Debug-All-Android\\\",\\\"gitHash\\\":\\\"<(REVISION)\\\",\\\"issue\\\":\\\"<(ISSUE)\\\",\\\"patch_storage\\\":\\\"<(PATCH_STORAGE)\\\",\\\"patchset\\\":\\\"<(PATCHSET)\\\",\\\"swarming_bot_id\\\":\\\"${SWARMING_BOT_ID}\\\",\\\"swarming_task_id\\\":\\\"${SWARMING_TASK_ID}\\\",\\\"task_id\\\":\\\"<(TASK_ID)\\\"}\",\"do_upload\":\"true\",\"gold_hashes_url\":\"https://storage.googleapis.com/skia-infra-gm/hash_files/gold-prod-hashes.txt\",\"images\":\"true\",\"patch_issue\":\"<(ISSUE_INT)\",\"patch_ref\":\"<(PATCH_REF)\",\"patch_repo\":\"<(PATCH_REPO)\",\"patch_set\":\"<(PATCHSET_INT)\",\"patch_storage\":\"<(PATCH_STORAGE)\",\"repository\":\"<(REPO)\",\"resources\":\"true\",\"revision\":\"<(REVISION)\",\"skps\":\"true\",\"svgs\":\"true\",\"swarm_out_dir\":\"test\",\"task_id\":\"<(TASK_ID)\"}",
|
||||
"{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"buildbucket_build_id\":\"<(BUILDBUCKET_BUILD_ID)\",\"buildername\":\"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Debug-All-Android_API30\",\"dm_flags\":\"[\\\"dm\\\",\\\"--nameByHash\\\",\\\"--key\\\",\\\"arch\\\",\\\"arm64\\\",\\\"compiler\\\",\\\"Clang\\\",\\\"configuration\\\",\\\"Debug\\\",\\\"cpu_or_gpu\\\",\\\"GPU\\\",\\\"cpu_or_gpu_value\\\",\\\"Adreno640\\\",\\\"extra_config\\\",\\\"Android_API30\\\",\\\"model\\\",\\\"Pixel4\\\",\\\"os\\\",\\\"Android\\\",\\\"style\\\",\\\"default\\\",\\\"--nocpu\\\",\\\"--config\\\",\\\"gles\\\",\\\"glesdft\\\",\\\"glessrgb\\\",\\\"glesmsaa4\\\",\\\"--src\\\",\\\"tests\\\",\\\"gm\\\",\\\"image\\\",\\\"colorImage\\\",\\\"svg\\\",\\\"--skip\\\",\\\"_\\\",\\\"svg\\\",\\\"_\\\",\\\"svgparse_\\\",\\\"glessrgb\\\",\\\"image\\\",\\\"_\\\",\\\"_\\\",\\\"_\\\",\\\"image\\\",\\\"gen_platf\\\",\\\"error\\\",\\\"_\\\",\\\"test\\\",\\\"_\\\",\\\"GrStyledShape\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\"interlaced1.png\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\"interlaced2.png\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\"interlaced3.png\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".arw\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".cr2\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".dng\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".nef\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".nrw\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".orf\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".raf\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".rw2\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".pef\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".srw\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".ARW\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".CR2\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".DNG\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".NEF\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".NRW\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".ORF\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".RAF\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".RW2\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".PEF\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".SRW\\\",\\\"--nonativeFonts\\\",\\\"--verbose\\\"]\",\"dm_properties\":\"{\\\"buildbucket_build_id\\\":\\\"<(BUILDBUCKET_BUILD_ID)\\\",\\\"builder\\\":\\\"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Debug-All-Android_API30\\\",\\\"gitHash\\\":\\\"<(REVISION)\\\",\\\"issue\\\":\\\"<(ISSUE)\\\",\\\"patch_storage\\\":\\\"<(PATCH_STORAGE)\\\",\\\"patchset\\\":\\\"<(PATCHSET)\\\",\\\"swarming_bot_id\\\":\\\"${SWARMING_BOT_ID}\\\",\\\"swarming_task_id\\\":\\\"${SWARMING_TASK_ID}\\\",\\\"task_id\\\":\\\"<(TASK_ID)\\\"}\",\"do_upload\":\"true\",\"gold_hashes_url\":\"https://storage.googleapis.com/skia-infra-gm/hash_files/gold-prod-hashes.txt\",\"images\":\"true\",\"patch_issue\":\"<(ISSUE_INT)\",\"patch_ref\":\"<(PATCH_REF)\",\"patch_repo\":\"<(PATCH_REPO)\",\"patch_set\":\"<(PATCHSET_INT)\",\"patch_storage\":\"<(PATCH_STORAGE)\",\"repository\":\"<(REPO)\",\"resources\":\"true\",\"revision\":\"<(REVISION)\",\"skps\":\"true\",\"svgs\":\"true\",\"swarm_out_dir\":\"test\",\"task_id\":\"<(TASK_ID)\"}",
|
||||
"skia"
|
||||
],
|
||||
"dependencies": [
|
||||
"Build-Debian10-Clang-arm64-Debug-Android",
|
||||
"Build-Debian10-Clang-arm64-Debug-Android_API30",
|
||||
"Housekeeper-PerCommit-BundleRecipes",
|
||||
"Housekeeper-PerCommit-IsolateSKP",
|
||||
"Housekeeper-PerCommit-IsolateSVG",
|
||||
@ -32424,7 +32574,7 @@
|
||||
"test"
|
||||
]
|
||||
},
|
||||
"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Release-All-Android": {
|
||||
"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Release-All-Android_API30": {
|
||||
"caches": [
|
||||
{
|
||||
"name": "vpython",
|
||||
@ -32454,11 +32604,11 @@
|
||||
"skia/infra/bots/run_recipe.py",
|
||||
"${ISOLATED_OUTDIR}",
|
||||
"test",
|
||||
"{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"buildbucket_build_id\":\"<(BUILDBUCKET_BUILD_ID)\",\"buildername\":\"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Release-All-Android\",\"dm_flags\":\"[\\\"dm\\\",\\\"--nameByHash\\\",\\\"--key\\\",\\\"arch\\\",\\\"arm64\\\",\\\"compiler\\\",\\\"Clang\\\",\\\"configuration\\\",\\\"Release\\\",\\\"cpu_or_gpu\\\",\\\"GPU\\\",\\\"cpu_or_gpu_value\\\",\\\"Adreno640\\\",\\\"extra_config\\\",\\\"Android\\\",\\\"model\\\",\\\"Pixel4\\\",\\\"os\\\",\\\"Android\\\",\\\"style\\\",\\\"default\\\",\\\"--nocpu\\\",\\\"--config\\\",\\\"gles\\\",\\\"glesdft\\\",\\\"glessrgb\\\",\\\"glesmsaa4\\\",\\\"--src\\\",\\\"tests\\\",\\\"gm\\\",\\\"image\\\",\\\"colorImage\\\",\\\"svg\\\",\\\"--skip\\\",\\\"_\\\",\\\"svg\\\",\\\"_\\\",\\\"svgparse_\\\",\\\"glessrgb\\\",\\\"image\\\",\\\"_\\\",\\\"_\\\",\\\"_\\\",\\\"image\\\",\\\"gen_platf\\\",\\\"error\\\",\\\"_\\\",\\\"test\\\",\\\"_\\\",\\\"GrStyledShape\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\"interlaced1.png\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\"interlaced2.png\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\"interlaced3.png\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".arw\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".cr2\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".dng\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".nef\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".nrw\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".orf\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".raf\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".rw2\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".pef\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".srw\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".ARW\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".CR2\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".DNG\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".NEF\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".NRW\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".ORF\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".RAF\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".RW2\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".PEF\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".SRW\\\",\\\"--nonativeFonts\\\",\\\"--verbose\\\"]\",\"dm_properties\":\"{\\\"buildbucket_build_id\\\":\\\"<(BUILDBUCKET_BUILD_ID)\\\",\\\"builder\\\":\\\"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Release-All-Android\\\",\\\"gitHash\\\":\\\"<(REVISION)\\\",\\\"issue\\\":\\\"<(ISSUE)\\\",\\\"patch_storage\\\":\\\"<(PATCH_STORAGE)\\\",\\\"patchset\\\":\\\"<(PATCHSET)\\\",\\\"swarming_bot_id\\\":\\\"${SWARMING_BOT_ID}\\\",\\\"swarming_task_id\\\":\\\"${SWARMING_TASK_ID}\\\",\\\"task_id\\\":\\\"<(TASK_ID)\\\"}\",\"do_upload\":\"true\",\"gold_hashes_url\":\"https://storage.googleapis.com/skia-infra-gm/hash_files/gold-prod-hashes.txt\",\"images\":\"true\",\"patch_issue\":\"<(ISSUE_INT)\",\"patch_ref\":\"<(PATCH_REF)\",\"patch_repo\":\"<(PATCH_REPO)\",\"patch_set\":\"<(PATCHSET_INT)\",\"patch_storage\":\"<(PATCH_STORAGE)\",\"repository\":\"<(REPO)\",\"resources\":\"true\",\"revision\":\"<(REVISION)\",\"skps\":\"true\",\"svgs\":\"true\",\"swarm_out_dir\":\"test\",\"task_id\":\"<(TASK_ID)\"}",
|
||||
"{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"buildbucket_build_id\":\"<(BUILDBUCKET_BUILD_ID)\",\"buildername\":\"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Release-All-Android_API30\",\"dm_flags\":\"[\\\"dm\\\",\\\"--nameByHash\\\",\\\"--key\\\",\\\"arch\\\",\\\"arm64\\\",\\\"compiler\\\",\\\"Clang\\\",\\\"configuration\\\",\\\"Release\\\",\\\"cpu_or_gpu\\\",\\\"GPU\\\",\\\"cpu_or_gpu_value\\\",\\\"Adreno640\\\",\\\"extra_config\\\",\\\"Android_API30\\\",\\\"model\\\",\\\"Pixel4\\\",\\\"os\\\",\\\"Android\\\",\\\"style\\\",\\\"default\\\",\\\"--nocpu\\\",\\\"--config\\\",\\\"gles\\\",\\\"glesdft\\\",\\\"glessrgb\\\",\\\"glesmsaa4\\\",\\\"--src\\\",\\\"tests\\\",\\\"gm\\\",\\\"image\\\",\\\"colorImage\\\",\\\"svg\\\",\\\"--skip\\\",\\\"_\\\",\\\"svg\\\",\\\"_\\\",\\\"svgparse_\\\",\\\"glessrgb\\\",\\\"image\\\",\\\"_\\\",\\\"_\\\",\\\"_\\\",\\\"image\\\",\\\"gen_platf\\\",\\\"error\\\",\\\"_\\\",\\\"test\\\",\\\"_\\\",\\\"GrStyledShape\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\"interlaced1.png\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\"interlaced2.png\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\"interlaced3.png\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".arw\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".cr2\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".dng\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".nef\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".nrw\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".orf\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".raf\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".rw2\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".pef\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".srw\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".ARW\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".CR2\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".DNG\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".NEF\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".NRW\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".ORF\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".RAF\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".RW2\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".PEF\\\",\\\"_\\\",\\\"image\\\",\\\"_\\\",\\\".SRW\\\",\\\"--nonativeFonts\\\",\\\"--verbose\\\"]\",\"dm_properties\":\"{\\\"buildbucket_build_id\\\":\\\"<(BUILDBUCKET_BUILD_ID)\\\",\\\"builder\\\":\\\"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Release-All-Android_API30\\\",\\\"gitHash\\\":\\\"<(REVISION)\\\",\\\"issue\\\":\\\"<(ISSUE)\\\",\\\"patch_storage\\\":\\\"<(PATCH_STORAGE)\\\",\\\"patchset\\\":\\\"<(PATCHSET)\\\",\\\"swarming_bot_id\\\":\\\"${SWARMING_BOT_ID}\\\",\\\"swarming_task_id\\\":\\\"${SWARMING_TASK_ID}\\\",\\\"task_id\\\":\\\"<(TASK_ID)\\\"}\",\"do_upload\":\"true\",\"gold_hashes_url\":\"https://storage.googleapis.com/skia-infra-gm/hash_files/gold-prod-hashes.txt\",\"images\":\"true\",\"patch_issue\":\"<(ISSUE_INT)\",\"patch_ref\":\"<(PATCH_REF)\",\"patch_repo\":\"<(PATCH_REPO)\",\"patch_set\":\"<(PATCHSET_INT)\",\"patch_storage\":\"<(PATCH_STORAGE)\",\"repository\":\"<(REPO)\",\"resources\":\"true\",\"revision\":\"<(REVISION)\",\"skps\":\"true\",\"svgs\":\"true\",\"swarm_out_dir\":\"test\",\"task_id\":\"<(TASK_ID)\"}",
|
||||
"skia"
|
||||
],
|
||||
"dependencies": [
|
||||
"Build-Debian10-Clang-arm64-Release-Android",
|
||||
"Build-Debian10-Clang-arm64-Release-Android_API30",
|
||||
"Housekeeper-PerCommit-BundleRecipes",
|
||||
"Housekeeper-PerCommit-IsolateSKP",
|
||||
"Housekeeper-PerCommit-IsolateSVG",
|
||||
@ -68689,7 +68839,7 @@
|
||||
"max_attempts": 2,
|
||||
"service_account": "skia-external-gm-uploader@skia-swarming-bots.iam.gserviceaccount.com"
|
||||
},
|
||||
"Upload-Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Debug-All-Android": {
|
||||
"Upload-Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Debug-All-Android_API30": {
|
||||
"caches": [
|
||||
{
|
||||
"name": "vpython",
|
||||
@ -68724,12 +68874,12 @@
|
||||
"skia/infra/bots/run_recipe.py",
|
||||
"${ISOLATED_OUTDIR}",
|
||||
"upload_dm_results",
|
||||
"{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"buildbucket_build_id\":\"<(BUILDBUCKET_BUILD_ID)\",\"buildername\":\"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Debug-All-Android\",\"gs_bucket\":\"skia-infra-gm\",\"patch_issue\":\"<(ISSUE_INT)\",\"patch_ref\":\"<(PATCH_REF)\",\"patch_repo\":\"<(PATCH_REPO)\",\"patch_set\":\"<(PATCHSET_INT)\",\"patch_storage\":\"<(PATCH_STORAGE)\",\"repository\":\"<(REPO)\",\"revision\":\"<(REVISION)\",\"swarm_out_dir\":\"output_ignored\",\"task_id\":\"<(TASK_ID)\"}",
|
||||
"{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"buildbucket_build_id\":\"<(BUILDBUCKET_BUILD_ID)\",\"buildername\":\"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Debug-All-Android_API30\",\"gs_bucket\":\"skia-infra-gm\",\"patch_issue\":\"<(ISSUE_INT)\",\"patch_ref\":\"<(PATCH_REF)\",\"patch_repo\":\"<(PATCH_REPO)\",\"patch_set\":\"<(PATCHSET_INT)\",\"patch_storage\":\"<(PATCH_STORAGE)\",\"repository\":\"<(REPO)\",\"revision\":\"<(REVISION)\",\"swarm_out_dir\":\"output_ignored\",\"task_id\":\"<(TASK_ID)\"}",
|
||||
"skia"
|
||||
],
|
||||
"dependencies": [
|
||||
"Housekeeper-PerCommit-BundleRecipes",
|
||||
"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Debug-All-Android"
|
||||
"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Debug-All-Android_API30"
|
||||
],
|
||||
"dimensions": [
|
||||
"cpu:x86-64-Haswell_GCE",
|
||||
@ -68823,7 +68973,7 @@
|
||||
"max_attempts": 2,
|
||||
"service_account": "skia-external-gm-uploader@skia-swarming-bots.iam.gserviceaccount.com"
|
||||
},
|
||||
"Upload-Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Release-All-Android": {
|
||||
"Upload-Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Release-All-Android_API30": {
|
||||
"caches": [
|
||||
{
|
||||
"name": "vpython",
|
||||
@ -68858,12 +69008,12 @@
|
||||
"skia/infra/bots/run_recipe.py",
|
||||
"${ISOLATED_OUTDIR}",
|
||||
"upload_dm_results",
|
||||
"{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"buildbucket_build_id\":\"<(BUILDBUCKET_BUILD_ID)\",\"buildername\":\"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Release-All-Android\",\"gs_bucket\":\"skia-infra-gm\",\"patch_issue\":\"<(ISSUE_INT)\",\"patch_ref\":\"<(PATCH_REF)\",\"patch_repo\":\"<(PATCH_REPO)\",\"patch_set\":\"<(PATCHSET_INT)\",\"patch_storage\":\"<(PATCH_STORAGE)\",\"repository\":\"<(REPO)\",\"revision\":\"<(REVISION)\",\"swarm_out_dir\":\"output_ignored\",\"task_id\":\"<(TASK_ID)\"}",
|
||||
"{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"buildbucket_build_id\":\"<(BUILDBUCKET_BUILD_ID)\",\"buildername\":\"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Release-All-Android_API30\",\"gs_bucket\":\"skia-infra-gm\",\"patch_issue\":\"<(ISSUE_INT)\",\"patch_ref\":\"<(PATCH_REF)\",\"patch_repo\":\"<(PATCH_REPO)\",\"patch_set\":\"<(PATCHSET_INT)\",\"patch_storage\":\"<(PATCH_STORAGE)\",\"repository\":\"<(REPO)\",\"revision\":\"<(REVISION)\",\"swarm_out_dir\":\"output_ignored\",\"task_id\":\"<(TASK_ID)\"}",
|
||||
"skia"
|
||||
],
|
||||
"dependencies": [
|
||||
"Housekeeper-PerCommit-BundleRecipes",
|
||||
"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Release-All-Android"
|
||||
"Test-Android-Clang-Pixel4-GPU-Adreno640-arm64-Release-All-Android_API30"
|
||||
],
|
||||
"dimensions": [
|
||||
"cpu:x86-64-Haswell_GCE",
|
||||
|
@ -289,6 +289,7 @@ PORTS_SRCS_UNIX = struct(
|
||||
"src/ports/*mozalloc*",
|
||||
"src/ports/*nacl*",
|
||||
"src/ports/*win*",
|
||||
"src/ports/*NDK*",
|
||||
"src/ports/SkFontMgr_custom_directory_factory.cpp",
|
||||
"src/ports/SkFontMgr_custom_embedded_factory.cpp",
|
||||
"src/ports/SkFontMgr_custom_empty_factory.cpp",
|
||||
@ -324,6 +325,7 @@ PORTS_SRCS_ANDROID = struct(
|
||||
"src/ports/*mozalloc*",
|
||||
"src/ports/*nacl*",
|
||||
"src/ports/*win*",
|
||||
"src/ports/*NDK*", # TODO (scroggo): enable NDK decoding/encoding in Google3
|
||||
"src/ports/SkDebug_stdio.cpp",
|
||||
"src/ports/SkFontMgr_custom_directory_factory.cpp",
|
||||
"src/ports/SkFontMgr_custom_embedded_factory.cpp",
|
||||
@ -360,6 +362,7 @@ PORTS_SRCS_IOS = struct(
|
||||
"src/ports/*mozalloc*",
|
||||
"src/ports/*nacl*",
|
||||
"src/ports/*win*",
|
||||
"src/ports/*NDK*",
|
||||
"src/ports/SkFontMgr_custom.cpp",
|
||||
"src/ports/SkFontMgr_custom_directory.cpp",
|
||||
"src/ports/SkFontMgr_custom_embedded.cpp",
|
||||
@ -403,6 +406,7 @@ PORTS_SRCS_WASM = struct(
|
||||
"src/ports/*mozalloc*",
|
||||
"src/ports/*nacl*",
|
||||
"src/ports/*win*",
|
||||
"src/ports/*NDK*",
|
||||
#"src/ports/SkDebug_stdio.cpp",
|
||||
"src/ports/SkFontMgr_custom.cpp",
|
||||
"src/ports/SkFontMgr_custom_directory.cpp",
|
||||
@ -441,6 +445,7 @@ PORTS_SRCS_FUCHSIA = struct(
|
||||
"src/ports/*mozalloc*",
|
||||
"src/ports/*nacl*",
|
||||
"src/ports/*win*",
|
||||
"src/ports/*NDK*",
|
||||
#"src/ports/SkDebug_stdio.cpp",
|
||||
#"src/ports/SkFontMgr_custom.cpp",
|
||||
"src/ports/SkFontMgr_custom_directory.cpp",
|
||||
|
BIN
resources/images/grayscale.png
Normal file
BIN
resources/images/grayscale.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
307
src/ports/SkImageGeneratorNDK.cpp
Normal file
307
src/ports/SkImageGeneratorNDK.cpp
Normal file
@ -0,0 +1,307 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "include/core/SkImageGenerator.h"
|
||||
#include "include/core/SkImageInfo.h"
|
||||
#include "include/ports/SkImageGeneratorNDK.h"
|
||||
|
||||
#include <android/bitmap.h>
|
||||
#include <android/data_space.h>
|
||||
#include <android/imagedecoder.h>
|
||||
|
||||
namespace {
|
||||
class ImageGeneratorNDK : public SkImageGenerator {
|
||||
public:
|
||||
ImageGeneratorNDK(const SkImageInfo&, sk_sp<SkData>, AImageDecoder*);
|
||||
~ImageGeneratorNDK() override;
|
||||
|
||||
protected:
|
||||
sk_sp<SkData> onRefEncodedData() override;
|
||||
|
||||
bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
|
||||
const Options& opts) override;
|
||||
|
||||
private:
|
||||
sk_sp<SkData> fData;
|
||||
AImageDecoder* fDecoder;
|
||||
// Setting the ADataSpace is sticky - it is set for all future decodes
|
||||
// until it is set again. But as of R there is no way to reset it to
|
||||
// ADATASPACE_UNKNOWN to skip color correction. If the client requests
|
||||
// skipping correction after having set it to something else, we need
|
||||
// to recreate the AImageDecoder.
|
||||
bool fPreviouslySetADataSpace;
|
||||
|
||||
typedef SkImageGenerator INHERITED;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
static bool ok(int result) {
|
||||
return result == ANDROID_IMAGE_DECODER_SUCCESS;
|
||||
}
|
||||
|
||||
namespace {
|
||||
static const struct {
|
||||
SkColorType colorType;
|
||||
AndroidBitmapFormat format;
|
||||
} gColorTypeTable[] = {
|
||||
{ kRGBA_8888_SkColorType, ANDROID_BITMAP_FORMAT_RGBA_8888 },
|
||||
{ kRGBA_F16_SkColorType, ANDROID_BITMAP_FORMAT_RGBA_F16 },
|
||||
{ kRGB_565_SkColorType, ANDROID_BITMAP_FORMAT_RGB_565 },
|
||||
// Android allows using its alpha 8 format to get 8 bit gray pixels.
|
||||
{ kGray_8_SkColorType, ANDROID_BITMAP_FORMAT_A_8 },
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
static bool set_android_bitmap_format(AImageDecoder* decoder, SkColorType colorType) {
|
||||
for (const auto& entry : gColorTypeTable) {
|
||||
if (entry.colorType == colorType) {
|
||||
return ok(AImageDecoder_setAndroidBitmapFormat(decoder, entry.format));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static SkColorType colorType(AImageDecoder* decoder, const AImageDecoderHeaderInfo* headerInfo) {
|
||||
// AImageDecoder never defaults to gray, but allows setting it if the image is 8 bit gray.
|
||||
if (set_android_bitmap_format(decoder, kGray_8_SkColorType)) {
|
||||
return kGray_8_SkColorType;
|
||||
}
|
||||
|
||||
const auto format = AImageDecoderHeaderInfo_getAndroidBitmapFormat(headerInfo);
|
||||
for (const auto& entry : gColorTypeTable) {
|
||||
if (format == entry.format) {
|
||||
return entry.colorType;
|
||||
}
|
||||
}
|
||||
|
||||
SkUNREACHABLE;
|
||||
}
|
||||
|
||||
static constexpr skcms_TransferFunction k2Dot6 = {2.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
|
||||
|
||||
static constexpr skcms_Matrix3x3 kDCIP3 = {{
|
||||
{0.486143, 0.323835, 0.154234},
|
||||
{0.226676, 0.710327, 0.0629966},
|
||||
{0.000800549, 0.0432385, 0.78275},
|
||||
}};
|
||||
|
||||
namespace {
|
||||
static const struct {
|
||||
ADataSpace dataSpace;
|
||||
skcms_TransferFunction transferFunction;
|
||||
skcms_Matrix3x3 gamut;
|
||||
} gColorSpaceTable[] = {
|
||||
// Note: ADATASPACE_SCRGB would look the same as ADATASPACE_SRGB. Leaving it out of the table is
|
||||
// fine, since users of the table will will still use SRGB.
|
||||
{ ADATASPACE_SRGB, SkNamedTransferFn::kSRGB, SkNamedGamut::kSRGB },
|
||||
{ ADATASPACE_SCRGB_LINEAR, SkNamedTransferFn::kLinear, SkNamedGamut::kSRGB },
|
||||
{ ADATASPACE_SRGB_LINEAR, SkNamedTransferFn::kLinear, SkNamedGamut::kSRGB },
|
||||
{ ADATASPACE_ADOBE_RGB, SkNamedTransferFn::k2Dot2, SkNamedGamut::kAdobeRGB },
|
||||
{ ADATASPACE_DISPLAY_P3, SkNamedTransferFn::kSRGB, SkNamedGamut::kDisplayP3 },
|
||||
{ ADATASPACE_BT2020, SkNamedTransferFn::kRec2020, SkNamedGamut::kRec2020 },
|
||||
{ ADATASPACE_BT709, SkNamedTransferFn::kRec2020, SkNamedGamut::kSRGB },
|
||||
{ ADATASPACE_DCI_P3, k2Dot6, kDCIP3 },
|
||||
};
|
||||
} // anonymous namespace
|
||||
|
||||
static sk_sp<SkColorSpace> get_default_colorSpace(const AImageDecoderHeaderInfo* headerInfo) {
|
||||
auto dataSpace = AImageDecoderHeaderInfo_getDataSpace(headerInfo);
|
||||
for (const auto& entry : gColorSpaceTable) {
|
||||
if (entry.dataSpace == dataSpace) {
|
||||
return SkColorSpace::MakeRGB(entry.transferFunction, entry.gamut);
|
||||
}
|
||||
}
|
||||
|
||||
return SkColorSpace::MakeSRGB();
|
||||
}
|
||||
|
||||
std::unique_ptr<SkImageGenerator> SkImageGeneratorNDK::MakeFromEncodedNDK(sk_sp<SkData> data) {
|
||||
if (!data) return nullptr;
|
||||
|
||||
AImageDecoder* rawDecoder;
|
||||
if (!ok(AImageDecoder_createFromBuffer(data->data(), data->size(), &rawDecoder))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const AImageDecoderHeaderInfo* headerInfo = AImageDecoder_getHeaderInfo(rawDecoder);
|
||||
int32_t width = AImageDecoderHeaderInfo_getWidth(headerInfo);
|
||||
int32_t height = AImageDecoderHeaderInfo_getHeight(headerInfo);
|
||||
SkColorType ct = colorType(rawDecoder, headerInfo);
|
||||
|
||||
// Although the encoded data stores unpremultiplied pixels, AImageDecoder defaults to premul
|
||||
// (if the image may have alpha).
|
||||
SkAlphaType at = AImageDecoderHeaderInfo_getAlphaFlags(headerInfo)
|
||||
== ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
|
||||
auto imageInfo = SkImageInfo::Make(width, height, ct, at, get_default_colorSpace(headerInfo));
|
||||
return std::unique_ptr<SkImageGenerator>(
|
||||
new ImageGeneratorNDK(imageInfo, std::move(data), rawDecoder));
|
||||
}
|
||||
|
||||
ImageGeneratorNDK::ImageGeneratorNDK(const SkImageInfo& info, sk_sp<SkData> data,
|
||||
AImageDecoder* decoder)
|
||||
: INHERITED(info)
|
||||
, fData(std::move(data))
|
||||
, fDecoder(decoder)
|
||||
, fPreviouslySetADataSpace(false)
|
||||
{
|
||||
SkASSERT(fDecoder);
|
||||
}
|
||||
|
||||
ImageGeneratorNDK::~ImageGeneratorNDK() {
|
||||
AImageDecoder_delete(fDecoder);
|
||||
}
|
||||
|
||||
static bool nearly_equal(float a, float b) {
|
||||
return fabs(a - b) < .002f;
|
||||
}
|
||||
|
||||
static bool nearly_equal(const skcms_TransferFunction& x, const skcms_TransferFunction& y) {
|
||||
return nearly_equal(x.g, y.g)
|
||||
&& nearly_equal(x.a, y.a)
|
||||
&& nearly_equal(x.b, y.b)
|
||||
&& nearly_equal(x.c, y.c)
|
||||
&& nearly_equal(x.d, y.d)
|
||||
&& nearly_equal(x.e, y.e)
|
||||
&& nearly_equal(x.f, y.f);
|
||||
}
|
||||
|
||||
static bool nearly_equal(const skcms_Matrix3x3& a, const skcms_Matrix3x3& b) {
|
||||
for (int i = 0; i < 3; i++)
|
||||
for (int j = 0; j < 3; j++) {
|
||||
if (!nearly_equal(a.vals[i][j], b.vals[i][j])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool set_target_size(AImageDecoder* decoder, const SkISize& size, const SkISize targetSize) {
|
||||
if (size != targetSize) {
|
||||
// AImageDecoder will scale to arbitrary sizes. Only support a size if it's supported by the
|
||||
// underlying library.
|
||||
const AImageDecoderHeaderInfo* headerInfo = AImageDecoder_getHeaderInfo(decoder);
|
||||
const char* mimeType = AImageDecoderHeaderInfo_getMimeType(headerInfo);
|
||||
if (0 == strcmp(mimeType, "image/jpeg")) {
|
||||
bool supported = false;
|
||||
for (int sampleSize : { 2, 4, 8 }) {
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
if (ok(AImageDecoder_computeSampledSize(decoder, sampleSize, &width, &height))
|
||||
&& targetSize == SkISize::Make(width, height)) {
|
||||
supported = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!supported) return false;
|
||||
} else if (0 == strcmp(mimeType, "image/webp")) {
|
||||
// libwebp supports arbitrary downscaling.
|
||||
if (targetSize.width() > size.width() || targetSize.height() > size.height()) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return ok(AImageDecoder_setTargetSize(decoder, targetSize.width(), targetSize.height()));
|
||||
}
|
||||
|
||||
bool ImageGeneratorNDK::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
|
||||
const Options& opts) {
|
||||
if (auto* cs = info.colorSpace()) {
|
||||
skcms_TransferFunction fn;
|
||||
skcms_Matrix3x3 gamut;
|
||||
if (!cs->isNumericalTransferFn(&fn) || !cs->toXYZD50(&gamut)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ADataSpace dataSpace = ADATASPACE_UNKNOWN;
|
||||
for (const auto& entry : gColorSpaceTable) {
|
||||
if (nearly_equal(gamut, entry.gamut) && nearly_equal(fn, entry.transferFunction)) {
|
||||
dataSpace = entry.dataSpace;
|
||||
}
|
||||
}
|
||||
if (!ok(AImageDecoder_setDataSpace(fDecoder, dataSpace))) {
|
||||
return false;
|
||||
}
|
||||
fPreviouslySetADataSpace = true;
|
||||
} else {
|
||||
// If the requested SkColorSpace is null, the client wants the "raw" colors, without color
|
||||
// space transformations applied. (This is primarily useful for a client that wants to do
|
||||
// their own color transformations.) This is AImageDecoder's default, but if a previous call
|
||||
// set an ADataSpace, AImageDecoder is no longer using its default, so we need to set it
|
||||
// back.
|
||||
if (fPreviouslySetADataSpace) {
|
||||
// AImageDecoderHeaderInfo_getDataSpace always returns the same value for the same
|
||||
// image, regardless of prior calls to AImageDecoder_setDataSpace. Check if it's
|
||||
// ADATASPACE_UNKNOWN, which needs to be handled specially.
|
||||
const AImageDecoderHeaderInfo* headerInfo = AImageDecoder_getHeaderInfo(fDecoder);
|
||||
const auto defaultDataSpace = AImageDecoderHeaderInfo_getDataSpace(headerInfo);
|
||||
if (defaultDataSpace == ADATASPACE_UNKNOWN) {
|
||||
// As of R, there's no way to reset AImageDecoder to ADATASPACE_UNKNOWN, so
|
||||
// create a new one.
|
||||
AImageDecoder* decoder;
|
||||
if (!ok(AImageDecoder_createFromBuffer(fData->data(), fData->size(), &decoder))) {
|
||||
return false;
|
||||
}
|
||||
AImageDecoder_delete(fDecoder);
|
||||
fDecoder = decoder;
|
||||
} else {
|
||||
if (!ok(AImageDecoder_setDataSpace(fDecoder, defaultDataSpace))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Whether by recreating AImageDecoder or calling AImageDecoder_setDataSpace, the
|
||||
// AImageDecoder is back to its default, so if the next call has a null SkColorSpace, it
|
||||
// does not need to reset it again.
|
||||
fPreviouslySetADataSpace = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!set_android_bitmap_format(fDecoder, info.colorType())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (info.alphaType()) {
|
||||
case kUnknown_SkAlphaType:
|
||||
return false;
|
||||
case kOpaque_SkAlphaType:
|
||||
if (this->getInfo().alphaType() != kOpaque_SkAlphaType) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case kUnpremul_SkAlphaType:
|
||||
if (!ok(AImageDecoder_setUnpremultipliedRequired(fDecoder, true))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case kPremul_SkAlphaType:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!set_target_size(fDecoder, getInfo().dimensions(), info.dimensions())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto byteSize = info.computeByteSize(rowBytes);
|
||||
switch (AImageDecoder_decodeImage(fDecoder, pixels, rowBytes, byteSize)) {
|
||||
case ANDROID_IMAGE_DECODER_INCOMPLETE:
|
||||
// The image was partially decoded, but the input was truncated. The client may be
|
||||
// happy with the partial image.
|
||||
case ANDROID_IMAGE_DECODER_ERROR:
|
||||
// Similarly, the image was partially decoded, but the input had an error. The client
|
||||
// may be happy with the partial image.
|
||||
case ANDROID_IMAGE_DECODER_SUCCESS:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
sk_sp<SkData> ImageGeneratorNDK::onRefEncodedData() {
|
||||
return fData;
|
||||
}
|
565
tests/NdkDecodeTest.cpp
Normal file
565
tests/NdkDecodeTest.cpp
Normal file
@ -0,0 +1,565 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "include/core/SkTypes.h"
|
||||
#ifdef SK_ENABLE_NDK_DECODING
|
||||
#include "include/ports/SkImageGeneratorNDK.h"
|
||||
#include "tests/Test.h"
|
||||
#include "tools/Resources.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
static std::unique_ptr<SkImageGenerator> make_generator(const char* path, skiatest::Reporter* r) {
|
||||
auto data = GetResourceAsData(path);
|
||||
if (data) {
|
||||
auto gen = SkImageGeneratorNDK::MakeFromEncodedNDK(std::move(data));
|
||||
if (gen) {
|
||||
return gen;
|
||||
}
|
||||
ERRORF(r, "Failed to create NDK generator from %s\n", path);
|
||||
} else {
|
||||
// Silently fail so developers can skip using --resources
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DEF_TEST(NdkDecode, r) {
|
||||
static const struct {
|
||||
const char* fPath;
|
||||
SkISize fSize;
|
||||
} recs[] = {
|
||||
{"images/CMYK.jpg", {642, 516}},
|
||||
{"images/arrow.png", {187, 312}},
|
||||
{"images/baby_tux.webp", {386, 395}},
|
||||
{"images/color_wheel.gif", {128, 128}},
|
||||
{"images/rle.bmp", {320, 240}},
|
||||
{"images/color_wheel.ico", {128, 128}},
|
||||
{"images/google_chrome.ico", {256, 256}},
|
||||
{"images/mandrill.wbmp", {512, 512}},
|
||||
};
|
||||
for (auto& rec : recs) {
|
||||
auto gen = make_generator(rec.fPath, r);
|
||||
if (!gen) continue;
|
||||
|
||||
const auto& info = gen->getInfo();
|
||||
REPORTER_ASSERT(r, info.dimensions() == rec.fSize);
|
||||
|
||||
SkBitmap bm;
|
||||
bm.allocPixels(info);
|
||||
REPORTER_ASSERT(r, gen->getPixels(bm.pixmap()));
|
||||
|
||||
REPORTER_ASSERT(r, info.alphaType() != kUnpremul_SkAlphaType);
|
||||
auto unpremulInfo = info.makeAlphaType(kUnpremul_SkAlphaType);
|
||||
bm.allocPixels(unpremulInfo);
|
||||
REPORTER_ASSERT(r, gen->getPixels(bm.pixmap()));
|
||||
}
|
||||
}
|
||||
|
||||
DEF_TEST(NdkDecode_nullData, r) {
|
||||
auto gen = SkImageGeneratorNDK::MakeFromEncodedNDK(nullptr);
|
||||
REPORTER_ASSERT(r, !gen);
|
||||
}
|
||||
|
||||
static constexpr skcms_TransferFunction k2Dot6 = {2.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
|
||||
|
||||
static constexpr skcms_Matrix3x3 kDCIP3 = {{
|
||||
{0.486143, 0.323835, 0.154234},
|
||||
{0.226676, 0.710327, 0.0629966},
|
||||
{0.000800549, 0.0432385, 0.78275},
|
||||
}};
|
||||
|
||||
DEF_TEST(NdkDecode_reportedColorSpace, r) {
|
||||
for (sk_sp<SkColorSpace> cs : {
|
||||
sk_sp<SkColorSpace>(nullptr),
|
||||
SkColorSpace::MakeSRGB(),
|
||||
SkColorSpace::MakeSRGBLinear(),
|
||||
SkColorSpace::MakeRGB(SkNamedTransferFn::kRec2020, SkNamedGamut::kSRGB),
|
||||
SkColorSpace::MakeRGB(SkNamedTransferFn::kRec2020, SkNamedGamut::kRec2020),
|
||||
SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDisplayP3),
|
||||
SkColorSpace::MakeRGB(SkNamedTransferFn::k2Dot2, SkNamedGamut::kAdobeRGB),
|
||||
SkColorSpace::MakeRGB(k2Dot6, kDCIP3),
|
||||
}) {
|
||||
SkBitmap bm;
|
||||
bm.allocPixels(SkImageInfo::Make(10, 10, kRGBA_F16_SkColorType, kOpaque_SkAlphaType, cs));
|
||||
bm.eraseColor(SK_ColorBLUE);
|
||||
|
||||
for (auto format : { SkEncodedImageFormat::kPNG,
|
||||
SkEncodedImageFormat::kJPEG,
|
||||
SkEncodedImageFormat::kWEBP }) {
|
||||
auto data = SkEncodeBitmap(bm, format, 80);
|
||||
auto gen = SkImageGeneratorNDK::MakeFromEncodedNDK(std::move(data));
|
||||
if (!gen) {
|
||||
ERRORF(r, "Failed to encode!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cs) cs = SkColorSpace::MakeSRGB();
|
||||
REPORTER_ASSERT(r, SkColorSpace::Equals(gen->getInfo().colorSpace(), cs.get()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEF_TEST(NdkDecode_ColorSpace, r) {
|
||||
for (const char* path: {
|
||||
"images/CMYK.jpg",
|
||||
"images/arrow.png",
|
||||
"images/baby_tux.webp",
|
||||
"images/color_wheel.gif",
|
||||
"images/rle.bmp",
|
||||
"images/color_wheel.ico",
|
||||
"images/google_chrome.ico",
|
||||
"images/mandrill.wbmp",
|
||||
}) {
|
||||
auto gen = make_generator(path, r);
|
||||
if (!gen) continue;
|
||||
|
||||
for (sk_sp<SkColorSpace> cs : {
|
||||
sk_sp<SkColorSpace>(nullptr),
|
||||
SkColorSpace::MakeSRGB(),
|
||||
SkColorSpace::MakeSRGBLinear(),
|
||||
SkColorSpace::MakeRGB(SkNamedTransferFn::kRec2020, SkNamedGamut::kSRGB),
|
||||
SkColorSpace::MakeRGB(SkNamedTransferFn::kRec2020, SkNamedGamut::kRec2020),
|
||||
SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDisplayP3),
|
||||
SkColorSpace::MakeRGB(SkNamedTransferFn::k2Dot2, SkNamedGamut::kAdobeRGB),
|
||||
SkColorSpace::MakeRGB(k2Dot6, kDCIP3),
|
||||
}) {
|
||||
auto info = gen->getInfo().makeColorSpace(cs);
|
||||
|
||||
SkBitmap bm;
|
||||
bm.allocPixels(info);
|
||||
REPORTER_ASSERT(r, gen->getPixels(bm.pixmap()));
|
||||
}
|
||||
|
||||
std::vector<sk_sp<SkColorSpace>> unsupportedCs;
|
||||
for (auto gamut : { SkNamedGamut::kSRGB, SkNamedGamut::kAdobeRGB, SkNamedGamut::kDisplayP3,
|
||||
SkNamedGamut::kRec2020, SkNamedGamut::kXYZ }) {
|
||||
unsupportedCs.push_back(SkColorSpace::MakeRGB(SkNamedTransferFn::kPQ, gamut));
|
||||
unsupportedCs.push_back(SkColorSpace::MakeRGB(SkNamedTransferFn::kHLG, gamut));
|
||||
unsupportedCs.push_back(SkColorSpace::MakeRGB(k2Dot6, gamut));
|
||||
}
|
||||
|
||||
for (auto gamut : { SkNamedGamut::kSRGB, SkNamedGamut::kDisplayP3,
|
||||
SkNamedGamut::kRec2020, SkNamedGamut::kXYZ }) {
|
||||
unsupportedCs.push_back(SkColorSpace::MakeRGB(SkNamedTransferFn::k2Dot2, gamut));
|
||||
}
|
||||
|
||||
for (auto gamut : { SkNamedGamut::kAdobeRGB, SkNamedGamut::kDisplayP3,
|
||||
SkNamedGamut::kXYZ }) {
|
||||
unsupportedCs.push_back(SkColorSpace::MakeRGB(SkNamedTransferFn::kRec2020, gamut));
|
||||
}
|
||||
|
||||
for (auto gamut : { SkNamedGamut::kAdobeRGB, SkNamedGamut::kDisplayP3,
|
||||
SkNamedGamut::kRec2020, SkNamedGamut::kXYZ }) {
|
||||
unsupportedCs.push_back(SkColorSpace::MakeRGB(SkNamedTransferFn::kLinear, gamut));
|
||||
}
|
||||
|
||||
for (auto gamut : { SkNamedGamut::kAdobeRGB,
|
||||
SkNamedGamut::kRec2020, SkNamedGamut::kXYZ }) {
|
||||
unsupportedCs.push_back(SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, gamut));
|
||||
}
|
||||
|
||||
for (auto fn : { SkNamedTransferFn::kSRGB, SkNamedTransferFn::k2Dot2,
|
||||
SkNamedTransferFn::kLinear, SkNamedTransferFn::kRec2020 }) {
|
||||
unsupportedCs.push_back(SkColorSpace::MakeRGB(fn, kDCIP3));
|
||||
}
|
||||
|
||||
for (auto unsupported : unsupportedCs) {
|
||||
auto info = gen->getInfo().makeColorSpace(unsupported);
|
||||
|
||||
SkBitmap bm;
|
||||
bm.allocPixels(info);
|
||||
REPORTER_ASSERT(r, !gen->getPixels(bm.pixmap()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEF_TEST(NdkDecode_reuseNoColorSpace, r) {
|
||||
static const struct {
|
||||
const char* fPath;
|
||||
sk_sp<SkColorSpace> fCorrectedColorSpace;
|
||||
bool fIsOpaque;
|
||||
} recs[] = {
|
||||
// AImageDecoder defaults to ADATASPACE_UNKNOWN for this image.
|
||||
{"images/wide_gamut_yellow_224_224_64.jpeg", SkColorSpace::MakeSRGB(), true},
|
||||
// This image is SRGB, so convert to a different color space.
|
||||
{"images/example_1.png", SkColorSpace::MakeRGB(SkNamedTransferFn::k2Dot2,
|
||||
SkNamedGamut::kAdobeRGB), false},
|
||||
};
|
||||
for (auto& rec : recs) {
|
||||
auto gen = make_generator(rec.fPath, r);
|
||||
if (!gen) continue;
|
||||
|
||||
REPORTER_ASSERT(r, gen->getInfo().colorSpace()->isSRGB());
|
||||
REPORTER_ASSERT(r, gen->getInfo().isOpaque() == rec.fIsOpaque);
|
||||
|
||||
auto noColorCorrection = gen->getInfo().makeColorSpace(nullptr);
|
||||
if (rec.fIsOpaque) {
|
||||
// Use something other than the default color type to verify that the modified color
|
||||
// type is used even when the color space is reset.
|
||||
noColorCorrection = noColorCorrection.makeColorType(kRGB_565_SkColorType);
|
||||
}
|
||||
|
||||
SkBitmap orig;
|
||||
orig.allocPixels(noColorCorrection);
|
||||
REPORTER_ASSERT(r, gen->getPixels(orig.pixmap()));
|
||||
|
||||
SkBitmap corrected;
|
||||
corrected.allocPixels(noColorCorrection.makeColorSpace(rec.fCorrectedColorSpace));
|
||||
REPORTER_ASSERT(r, gen->getPixels(corrected.pixmap()));
|
||||
|
||||
bool same = true;
|
||||
for (int y = 0; y < gen->getInfo().height(); y++) {
|
||||
auto* origLine = orig.getAddr(0, y);
|
||||
auto* correctedLine = corrected.getAddr(0, y);
|
||||
if (memcmp(origLine, correctedLine, orig.rowBytes()) != 0) {
|
||||
same = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
REPORTER_ASSERT(r, !same);
|
||||
|
||||
SkBitmap reuse;
|
||||
reuse.allocPixels(noColorCorrection);
|
||||
REPORTER_ASSERT(r, gen->getPixels(reuse.pixmap()));
|
||||
|
||||
for (int y = 0; y < gen->getInfo().height(); y++) {
|
||||
auto* origLine = orig.getAddr(0, y);
|
||||
auto* reuseLine = reuse.getAddr(0, y);
|
||||
if (memcmp(origLine, reuseLine, orig.rowBytes()) != 0) {
|
||||
ERRORF(r, "Bitmaps do not match!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The NDK supports scaling up to arbitrary dimensions. Skia forces clients to do this in a
|
||||
// separate step, so the client is in charge of how to do the upscale.
|
||||
DEF_TEST(NdkDecode_noUpscale, r) {
|
||||
for (const char* path: {
|
||||
"images/CMYK.jpg",
|
||||
"images/arrow.png",
|
||||
"images/baby_tux.webp",
|
||||
"images/color_wheel.gif",
|
||||
"images/rle.bmp",
|
||||
"images/color_wheel.ico",
|
||||
"images/google_chrome.ico",
|
||||
"images/mandrill.wbmp",
|
||||
}) {
|
||||
auto gen = make_generator(path, r);
|
||||
if (!gen) continue;
|
||||
|
||||
const auto actualDimensions = gen->getInfo().dimensions();
|
||||
const int width = actualDimensions.width();
|
||||
const int height = actualDimensions.height();
|
||||
for (SkISize dims : {
|
||||
SkISize{width*2, height*2},
|
||||
SkISize{width + 1, height + 1},
|
||||
}) {
|
||||
auto info = gen->getInfo().makeDimensions(dims);
|
||||
SkBitmap bm;
|
||||
bm.allocPixels(info);
|
||||
REPORTER_ASSERT(r, !gen->getPixels(bm.pixmap()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// libwebp supports downscaling to an arbitrary scale factor, and this is supported by the NDK.
|
||||
DEF_TEST(NdkDecode_webpArbitraryDownscale, r) {
|
||||
for (const char* path: {
|
||||
"images/baby_tux.webp",
|
||||
"images/yellow_rose.webp",
|
||||
"images/webp-color-profile-lossless.webp",
|
||||
}) {
|
||||
auto gen = make_generator(path, r);
|
||||
if (!gen) continue;
|
||||
|
||||
const auto actualDimensions = gen->getInfo().dimensions();
|
||||
const int width = actualDimensions.width();
|
||||
const int height = actualDimensions.height();
|
||||
for (SkISize dims : {
|
||||
SkISize{width/2, height/2},
|
||||
SkISize{width/4, height/4},
|
||||
SkISize{width/7, height/7},
|
||||
SkISize{width - 1, height - 1},
|
||||
SkISize{1, 1},
|
||||
SkISize{5, 20}
|
||||
}) {
|
||||
auto info = gen->getInfo().makeDimensions(dims);
|
||||
SkBitmap bm;
|
||||
bm.allocPixels(info);
|
||||
REPORTER_ASSERT(r, gen->getPixels(bm.pixmap()));
|
||||
|
||||
REPORTER_ASSERT(r, info.alphaType() != kUnpremul_SkAlphaType);
|
||||
auto unpremulInfo = info.makeAlphaType(kUnpremul_SkAlphaType);
|
||||
bm.allocPixels(unpremulInfo);
|
||||
REPORTER_ASSERT(r, gen->getPixels(bm.pixmap()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// libjpeg-turbo supports downscaling to some scale factors.
|
||||
DEF_TEST(NdkDecode_jpegDownscale, r) {
|
||||
static const struct {
|
||||
const char* fPath;
|
||||
SkISize fSupportedSizes[4];
|
||||
} recs[] = {
|
||||
{"images/CMYK.jpg", {{642,516},{321,258},{161,129},{81,65}}},
|
||||
{"images/dog.jpg", {{180,180},{90,90},{45,45},{23,23}}},
|
||||
{"images/grayscale.jpg", {{128,128},{64,64},{32,32},{16,16}}},
|
||||
{"images/brickwork-texture.jpg", {{512,512},{256,256},{128,128},{64,64}}},
|
||||
{"images/mandrill_h2v1.jpg", {{512,512},{256,256},{128,128},{64,64}}},
|
||||
{"images/ducky.jpg", {{489,537},{245,269},{123,135},{62,68}}},
|
||||
};
|
||||
for (auto& rec : recs) {
|
||||
auto gen = make_generator(rec.fPath, r);
|
||||
if (!gen) continue;
|
||||
|
||||
for (SkISize dims : rec.fSupportedSizes) {
|
||||
auto info = gen->getInfo().makeDimensions(dims);
|
||||
SkBitmap bm;
|
||||
bm.allocPixels(info);
|
||||
if (!gen->getPixels(bm.pixmap())) {
|
||||
ERRORF(r, "failed to decode %s to {%i,%i}\n", rec.fPath, dims.width(),
|
||||
dims.height());
|
||||
}
|
||||
|
||||
REPORTER_ASSERT(r, info.alphaType() != kUnpremul_SkAlphaType);
|
||||
auto unpremulInfo = info.makeAlphaType(kUnpremul_SkAlphaType);
|
||||
bm.allocPixels(unpremulInfo);
|
||||
REPORTER_ASSERT(r, gen->getPixels(bm.pixmap()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEF_TEST(NdkDecode_reuseJpeg, r) {
|
||||
auto gen = make_generator("images/CMYK.jpg", r);
|
||||
if (!gen) return;
|
||||
|
||||
SkImageInfo info = gen->getInfo();
|
||||
SkBitmap orig;
|
||||
orig.allocPixels(info);
|
||||
REPORTER_ASSERT(r, gen->getPixels(orig.pixmap()));
|
||||
|
||||
info = info.makeWH(321, 258);
|
||||
SkBitmap downscaled;
|
||||
downscaled.allocPixels(info);
|
||||
REPORTER_ASSERT(r, gen->getPixels(downscaled.pixmap()));
|
||||
|
||||
SkBitmap reuse;
|
||||
reuse.allocPixels(gen->getInfo());
|
||||
REPORTER_ASSERT(r, gen->getPixels(reuse.pixmap()));
|
||||
|
||||
for (int y = 0; y < gen->getInfo().height(); y++) {
|
||||
auto* origLine = orig.getAddr32(0, y);
|
||||
auto* reuseLine = reuse.getAddr32(0, y);
|
||||
if (memcmp(origLine, reuseLine, orig.rowBytes()) != 0) {
|
||||
ERRORF(r, "Bitmaps do not match!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The NDK supports scaling down to arbitrary dimensions. Skia forces clients to do this in a
|
||||
// separate step, so the client is in charge of how to do the downscale.
|
||||
DEF_TEST(NdkDecode_noDownscale, r) {
|
||||
for (const char* path: {
|
||||
"images/arrow.png",
|
||||
"images/color_wheel.gif",
|
||||
"images/rle.bmp",
|
||||
"images/color_wheel.ico",
|
||||
"images/google_chrome.ico",
|
||||
"images/mandrill.wbmp",
|
||||
}) {
|
||||
auto gen = make_generator(path, r);
|
||||
if (!gen) continue;
|
||||
|
||||
const auto actualDimensions = gen->getInfo().dimensions();
|
||||
const int width = actualDimensions.width();
|
||||
const int height = actualDimensions.height();
|
||||
for (SkISize dims : {
|
||||
SkISize{width/2, height/2},
|
||||
SkISize{width/3, height/3},
|
||||
SkISize{width/4, height/4},
|
||||
SkISize{width/8, height/8},
|
||||
SkISize{width - 1, height - 1},
|
||||
}) {
|
||||
auto info = gen->getInfo().makeDimensions(dims);
|
||||
SkBitmap bm;
|
||||
bm.allocPixels(info);
|
||||
REPORTER_ASSERT(r, !gen->getPixels(bm.pixmap()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEF_TEST(NdkDecode_Gray8, r) {
|
||||
static const struct {
|
||||
const char* fPath;
|
||||
bool fGrayscale;
|
||||
} recs[] = {
|
||||
{"images/CMYK.jpg", false},
|
||||
{"images/arrow.png", false},
|
||||
{"images/baby_tux.webp", false},
|
||||
{"images/color_wheel.gif", false},
|
||||
{"images/rle.bmp", false},
|
||||
{"images/color_wheel.ico", false},
|
||||
{"images/google_chrome.ico", false},
|
||||
{"images/mandrill.wbmp", true},
|
||||
{"images/grayscale.jpg", true},
|
||||
{"images/grayscale.png", true},
|
||||
};
|
||||
for (auto& rec : recs) {
|
||||
auto gen = make_generator(rec.fPath, r);
|
||||
if (!gen) continue;
|
||||
|
||||
SkImageInfo info = gen->getInfo();
|
||||
if (rec.fGrayscale) {
|
||||
REPORTER_ASSERT(r, info.colorType() == kGray_8_SkColorType);
|
||||
REPORTER_ASSERT(r, info.alphaType() == kOpaque_SkAlphaType);
|
||||
} else {
|
||||
info = info.makeColorType(kGray_8_SkColorType);
|
||||
}
|
||||
SkBitmap bm;
|
||||
bm.allocPixels(info);
|
||||
bool success = gen->getPixels(bm.pixmap());
|
||||
if (success != rec.fGrayscale) {
|
||||
ERRORF(r, "Expected decoding %s to Gray8 to %s. Actual: %s\n", rec.fPath,
|
||||
(rec.fGrayscale ? "succeed" : "fail"), (success ? "succeed" : "fail"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEF_TEST(NdkDecode_Opaque_and_565, r) {
|
||||
for (const char* path: {
|
||||
"images/CMYK.jpg",
|
||||
"images/dog.jpg",
|
||||
"images/ducky.jpg",
|
||||
"images/arrow.png",
|
||||
"images/example_1.png",
|
||||
"images/explosion_sprites.png",
|
||||
"images/lut_identity.png",
|
||||
"images/grayscale.png",
|
||||
"images/baby_tux.webp",
|
||||
"images/yellow_rose.webp",
|
||||
"images/webp-color-profile-lossless.webp",
|
||||
"images/colorTables.gif",
|
||||
"images/color_wheel.gif",
|
||||
"images/flightAnim.gif",
|
||||
"images/randPixels.gif",
|
||||
"images/rle.bmp",
|
||||
"images/color_wheel.ico",
|
||||
"images/google_chrome.ico",
|
||||
"images/mandrill.wbmp",
|
||||
}) {
|
||||
auto gen = make_generator(path, r);
|
||||
if (!gen) continue;
|
||||
|
||||
auto info = gen->getInfo().makeAlphaType(kOpaque_SkAlphaType);
|
||||
SkBitmap bm;
|
||||
bm.allocPixels(info);
|
||||
bool success = gen->getPixels(bm.pixmap());
|
||||
REPORTER_ASSERT(r, success == gen->getInfo().isOpaque());
|
||||
|
||||
info = info.makeColorType(kRGB_565_SkColorType);
|
||||
bm.allocPixels(info);
|
||||
success = gen->getPixels(bm.pixmap());
|
||||
REPORTER_ASSERT(r, success == gen->getInfo().isOpaque());
|
||||
}
|
||||
}
|
||||
|
||||
DEF_TEST(NdkDecode_AlwaysSupportedColorTypes, r) {
|
||||
for (const char* path: {
|
||||
"images/CMYK.jpg",
|
||||
"images/dog.jpg",
|
||||
"images/ducky.jpg",
|
||||
"images/arrow.png",
|
||||
"images/example_1.png",
|
||||
"images/explosion_sprites.png",
|
||||
"images/lut_identity.png",
|
||||
"images/grayscale.png",
|
||||
"images/baby_tux.webp",
|
||||
"images/yellow_rose.webp",
|
||||
"images/webp-color-profile-lossless.webp",
|
||||
"images/colorTables.gif",
|
||||
"images/color_wheel.gif",
|
||||
"images/flightAnim.gif",
|
||||
"images/randPixels.gif",
|
||||
"images/rle.bmp",
|
||||
"images/color_wheel.ico",
|
||||
"images/google_chrome.ico",
|
||||
"images/mandrill.wbmp",
|
||||
}) {
|
||||
auto gen = make_generator(path, r);
|
||||
if (!gen) continue;
|
||||
|
||||
auto info = gen->getInfo().makeColorType(kRGBA_F16_SkColorType);
|
||||
SkBitmap bm;
|
||||
bm.allocPixels(info);
|
||||
REPORTER_ASSERT(r, gen->getPixels(bm.pixmap()));
|
||||
|
||||
// This also tests that we can reuse the same generator for a different
|
||||
// color type.
|
||||
info = info.makeColorType(kRGBA_8888_SkColorType);
|
||||
bm.allocPixels(info);
|
||||
REPORTER_ASSERT(r, gen->getPixels(bm.pixmap()));
|
||||
}
|
||||
}
|
||||
|
||||
DEF_TEST(NdkDecode_UnsupportedColorTypes, r) {
|
||||
for (const char* path: {
|
||||
"images/CMYK.jpg",
|
||||
"images/dog.jpg",
|
||||
"images/ducky.jpg",
|
||||
"images/arrow.png",
|
||||
"images/example_1.png",
|
||||
"images/explosion_sprites.png",
|
||||
"images/lut_identity.png",
|
||||
"images/grayscale.png",
|
||||
"images/baby_tux.webp",
|
||||
"images/yellow_rose.webp",
|
||||
"images/webp-color-profile-lossless.webp",
|
||||
"images/colorTables.gif",
|
||||
"images/color_wheel.gif",
|
||||
"images/flightAnim.gif",
|
||||
"images/randPixels.gif",
|
||||
"images/rle.bmp",
|
||||
"images/color_wheel.ico",
|
||||
"images/google_chrome.ico",
|
||||
"images/mandrill.wbmp",
|
||||
}) {
|
||||
auto gen = make_generator(path, r);
|
||||
if (!gen) continue;
|
||||
|
||||
for (SkColorType ct : {
|
||||
kUnknown_SkColorType,
|
||||
kAlpha_8_SkColorType,
|
||||
kARGB_4444_SkColorType,
|
||||
kRGB_888x_SkColorType,
|
||||
kBGRA_8888_SkColorType,
|
||||
kRGBA_1010102_SkColorType,
|
||||
kBGRA_1010102_SkColorType,
|
||||
kRGB_101010x_SkColorType,
|
||||
kBGR_101010x_SkColorType,
|
||||
kRGBA_F16Norm_SkColorType,
|
||||
kRGBA_F32_SkColorType,
|
||||
kR8G8_unorm_SkColorType,
|
||||
kA16_float_SkColorType,
|
||||
kR16G16_float_SkColorType,
|
||||
kA16_unorm_SkColorType,
|
||||
kR16G16_unorm_SkColorType,
|
||||
kR16G16B16A16_unorm_SkColorType,
|
||||
}) {
|
||||
auto info = gen->getInfo().makeColorType(ct);
|
||||
SkBitmap bm;
|
||||
bm.allocPixels(info);
|
||||
if (gen->getPixels(bm.pixmap())) {
|
||||
ERRORF(r, "Expected decoding %s to %i to fail!", path, ct);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // SK_ENABLE_NDK_DECODING
|
Loading…
Reference in New Issue
Block a user