ColorCodecBench.cpp revision 43d6651111374b5d1e4ddd9030dcf079b448ec47
1/* 2 * Copyright 2016 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "ColorCodecBench.h" 9#include "Resources.h" 10#include "SkCodec.h" 11#include "SkCodecPriv.h" 12#include "SkColorSpaceXform.h" 13#include "SkCommandLineFlags.h" 14 15#if defined(SK_TEST_QCMS) 16DEFINE_bool(qcms, false, "Bench qcms color conversion"); 17#endif 18DEFINE_bool(xform_only, false, "Only time the color xform, do not include the decode time"); 19DEFINE_bool(srgb, false, "Convert to srgb dst space"); 20DEFINE_bool(half, false, "Convert to half floats"); 21 22ColorCodecBench::ColorCodecBench(const char* name, sk_sp<SkData> encoded) 23 : fEncoded(std::move(encoded)) 24#if defined(SK_TEST_QCMS) 25 , fDstSpaceQCMS(nullptr) 26#endif 27{ 28 fName.appendf("Color%s", FLAGS_xform_only ? "Xform" : "Codec"); 29#if defined(SK_TEST_QCMS) 30 fName.appendf("%s", FLAGS_qcms ? "QCMS" : ""); 31#endif 32 fName.appendf("_%s", name); 33} 34 35const char* ColorCodecBench::onGetName() { 36 return fName.c_str(); 37} 38 39bool ColorCodecBench::isSuitableFor(Backend backend) { 40 return kNonRendering_Backend == backend; 41} 42 43void ColorCodecBench::decodeAndXform() { 44 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(fEncoded)); 45 SkASSERT(codec); 46 47#ifdef SK_DEBUG 48 SkCodec::Result result = 49#endif 50 codec->getPixels(fDstInfo, fDst.get(), fDstInfo.minRowBytes()); 51 SkASSERT(SkCodec::kSuccess == result); 52} 53 54#if defined(SK_TEST_QCMS) 55void ColorCodecBench::decodeAndXformQCMS() { 56 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(fEncoded)); 57#ifdef SK_DEBUG 58 const SkCodec::Result result = 59#endif 60 codec->startScanlineDecode(fSrcInfo); 61 SkASSERT(SkCodec::kSuccess == result); 62 63 SkAutoTCallVProc<qcms_profile, qcms_profile_release> 64 srcSpace(qcms_profile_from_memory(fSrcData->data(), fSrcData->size())); 65 SkASSERT(srcSpace); 66 67 SkAutoTCallVProc<qcms_transform, qcms_transform_release> 68 transform (qcms_transform_create(srcSpace, QCMS_DATA_RGBA_8, fDstSpaceQCMS.get(), 69 QCMS_DATA_RGBA_8, QCMS_INTENT_PERCEPTUAL)); 70 SkASSERT(transform); 71 72#ifdef SK_PMCOLOR_IS_RGBA 73 qcms_output_type outType = QCMS_OUTPUT_RGBX; 74#else 75 qcms_output_type outType = QCMS_OUTPUT_BGRX; 76#endif 77 78 void* dst = fDst.get(); 79 for (int y = 0; y < fSrcInfo.height(); y++) { 80#ifdef SK_DEBUG 81 const int rows = 82#endif 83 codec->getScanlines(fSrc.get(), 1, 0); 84 SkASSERT(1 == rows); 85 86 qcms_transform_data_type(transform, fSrc.get(), dst, fSrcInfo.width(), outType); 87 dst = SkTAddOffset<void>(dst, fDstInfo.minRowBytes()); 88 } 89} 90#endif 91 92void ColorCodecBench::xformOnly() { 93 sk_sp<SkColorSpace> srcSpace = SkColorSpace::NewICC(fSrcData->data(), fSrcData->size()); 94 if (!srcSpace) { 95 srcSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named); 96 } 97 std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New(srcSpace, fDstSpace); 98 SkASSERT(xform); 99 100 void* dst = fDst.get(); 101 void* src = fSrc.get(); 102 for (int y = 0; y < fSrcInfo.height(); y++) { 103 xform->apply(dst, (uint32_t*) src, fSrcInfo.width(), 104 select_xform_format(fDstInfo.colorType()), fDstInfo.alphaType()); 105 dst = SkTAddOffset<void>(dst, fDstInfo.minRowBytes()); 106 src = SkTAddOffset<void>(src, fSrcInfo.minRowBytes()); 107 } 108} 109 110#if defined(SK_TEST_QCMS) 111void ColorCodecBench::xformOnlyQCMS() { 112 SkAutoTCallVProc<qcms_profile, qcms_profile_release> 113 srcSpace(qcms_profile_from_memory(fSrcData->data(), fSrcData->size())); 114 SkASSERT(srcSpace); 115 116 SkAutoTCallVProc<qcms_transform, qcms_transform_release> 117 transform (qcms_transform_create(srcSpace, QCMS_DATA_RGBA_8, fDstSpaceQCMS.get(), 118 QCMS_DATA_RGBA_8, QCMS_INTENT_PERCEPTUAL)); 119 SkASSERT(transform); 120 121#ifdef SK_PMCOLOR_IS_RGBA 122 qcms_output_type outType = QCMS_OUTPUT_RGBX; 123#else 124 qcms_output_type outType = QCMS_OUTPUT_BGRX; 125#endif 126 127 void* dst = fDst.get(); 128 void* src = fSrc.get(); 129 for (int y = 0; y < fSrcInfo.height(); y++) { 130 // Transform in place 131 qcms_transform_data_type(transform, src, dst, fSrcInfo.width(), outType); 132 dst = SkTAddOffset<void>(dst, fDstInfo.minRowBytes()); 133 src = SkTAddOffset<void>(src, fSrcInfo.minRowBytes()); 134 } 135} 136#endif 137 138void ColorCodecBench::onDelayedSetup() { 139 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(fEncoded)); 140 fSrcData = codec->getICCData(); 141 sk_sp<SkData> dstData = SkData::MakeFromFileName( 142 GetResourcePath("icc_profiles/HP_ZR30w.icc").c_str()); 143 SkASSERT(dstData); 144 145 fDstSpace = nullptr; 146#if defined(SK_TEST_QCMS) 147 if (FLAGS_qcms) { 148 fDstSpaceQCMS.reset(FLAGS_srgb ? 149 qcms_profile_sRGB() : 150 qcms_profile_from_memory(dstData->data(), dstData->size())); 151 SkASSERT(fDstSpaceQCMS); 152 153 // This call takes a non-trivial amount of time, but I think it's the most fair to 154 // treat it as overhead. It only needs to happen once. 155 qcms_profile_precache_output_transform(fDstSpaceQCMS); 156 } else 157#endif 158 { 159 fDstSpace = FLAGS_srgb ? SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named) : 160 SkColorSpace::NewICC(dstData->data(), dstData->size()); 161 SkASSERT(fDstSpace); 162 } 163 164 fSrcInfo = codec->getInfo().makeColorType(kRGBA_8888_SkColorType); 165 fDstInfo = fSrcInfo; 166 167 if (FLAGS_half) { 168 fDstInfo = fDstInfo.makeColorType(kRGBA_F16_SkColorType); 169 fDstSpace = fDstSpace->makeLinearGamma(); 170 } 171 172 fDstInfo = fDstInfo.makeColorSpace(fDstSpace); 173 174 fDst.reset(fDstInfo.getSafeSize(fDstInfo.minRowBytes())); 175 176 if (FLAGS_xform_only) { 177 fSrc.reset(fSrcInfo.getSafeSize(fSrcInfo.minRowBytes())); 178 codec->getPixels(fSrcInfo, fSrc.get(), fSrcInfo.minRowBytes()); 179 } 180#if defined(SK_TEST_QCMS) 181 else if (FLAGS_qcms) { 182 // Set-up a row buffer to decode into before transforming to dst. 183 fSrc.reset(fSrcInfo.minRowBytes()); 184 } 185#endif 186} 187 188void ColorCodecBench::onDraw(int n, SkCanvas*) { 189#if defined(SK_TEST_QCMS) 190 if (FLAGS_qcms && FLAGS_half) { 191 SkDebugf("Error: Contradicting flags.\n"); 192 return; 193 } 194#endif 195 196 for (int i = 0; i < n; i++) { 197#if defined(SK_TEST_QCMS) 198 if (FLAGS_qcms) { 199 if (FLAGS_xform_only) { 200 this->xformOnlyQCMS(); 201 } else { 202 this->decodeAndXformQCMS(); 203 } 204 } else 205#endif 206 { 207 if (FLAGS_xform_only) { 208 this->xformOnly(); 209 } else { 210 this->decodeAndXform(); 211 } 212 } 213 } 214} 215