ColorCodecBench.cpp revision 31d097e865f266c8398f45114e4c75c0dfdef058
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.get(), 98 fDstSpace.get()); 99 SkASSERT(xform); 100 101 void* dst = fDst.get(); 102 void* src = fSrc.get(); 103 for (int y = 0; y < fSrcInfo.height(); y++) { 104 SkAssertResult(xform->apply(select_xform_format(fDstInfo.colorType()), dst, 105 SkColorSpaceXform::kRGBA_8888_ColorFormat, src, 106 fSrcInfo.width(), fDstInfo.alphaType())); 107 dst = SkTAddOffset<void>(dst, fDstInfo.minRowBytes()); 108 src = SkTAddOffset<void>(src, fSrcInfo.minRowBytes()); 109 } 110} 111 112#if defined(SK_TEST_QCMS) 113void ColorCodecBench::xformOnlyQCMS() { 114 SkAutoTCallVProc<qcms_profile, qcms_profile_release> 115 srcSpace(qcms_profile_from_memory(fSrcData->data(), fSrcData->size())); 116 SkASSERT(srcSpace); 117 118 SkAutoTCallVProc<qcms_transform, qcms_transform_release> 119 transform (qcms_transform_create(srcSpace, QCMS_DATA_RGBA_8, fDstSpaceQCMS.get(), 120 QCMS_DATA_RGBA_8, QCMS_INTENT_PERCEPTUAL)); 121 SkASSERT(transform); 122 123#ifdef SK_PMCOLOR_IS_RGBA 124 qcms_output_type outType = QCMS_OUTPUT_RGBX; 125#else 126 qcms_output_type outType = QCMS_OUTPUT_BGRX; 127#endif 128 129 void* dst = fDst.get(); 130 void* src = fSrc.get(); 131 for (int y = 0; y < fSrcInfo.height(); y++) { 132 // Transform in place 133 qcms_transform_data_type(transform, src, dst, fSrcInfo.width(), outType); 134 dst = SkTAddOffset<void>(dst, fDstInfo.minRowBytes()); 135 src = SkTAddOffset<void>(src, fSrcInfo.minRowBytes()); 136 } 137} 138#endif 139 140void ColorCodecBench::onDelayedSetup() { 141 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(fEncoded)); 142 fSrcData = codec->getICCData(); 143 sk_sp<SkData> dstData = SkData::MakeFromFileName( 144 GetResourcePath("icc_profiles/HP_ZR30w.icc").c_str()); 145 SkASSERT(dstData); 146 147 fDstSpace = nullptr; 148#if defined(SK_TEST_QCMS) 149 if (FLAGS_qcms) { 150 fDstSpaceQCMS.reset(FLAGS_srgb ? 151 qcms_profile_sRGB() : 152 qcms_profile_from_memory(dstData->data(), dstData->size())); 153 SkASSERT(fDstSpaceQCMS); 154 155 // This call takes a non-trivial amount of time, but I think it's the most fair to 156 // treat it as overhead. It only needs to happen once. 157 qcms_profile_precache_output_transform(fDstSpaceQCMS); 158 } else 159#endif 160 { 161 fDstSpace = FLAGS_srgb ? SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named) : 162 SkColorSpace::NewICC(dstData->data(), dstData->size()); 163 SkASSERT(fDstSpace); 164 } 165 166 fSrcInfo = codec->getInfo().makeColorType(kRGBA_8888_SkColorType); 167 fDstInfo = fSrcInfo; 168 169 if (FLAGS_half) { 170 fDstInfo = fDstInfo.makeColorType(kRGBA_F16_SkColorType); 171 fDstSpace = fDstSpace->makeLinearGamma(); 172 } 173 174 fDstInfo = fDstInfo.makeColorSpace(fDstSpace); 175 176 fDst.reset(fDstInfo.getSafeSize(fDstInfo.minRowBytes())); 177 178 if (FLAGS_xform_only) { 179 fSrc.reset(fSrcInfo.getSafeSize(fSrcInfo.minRowBytes())); 180 codec->getPixels(fSrcInfo, fSrc.get(), fSrcInfo.minRowBytes()); 181 } 182#if defined(SK_TEST_QCMS) 183 else if (FLAGS_qcms) { 184 // Set-up a row buffer to decode into before transforming to dst. 185 fSrc.reset(fSrcInfo.minRowBytes()); 186 } 187#endif 188} 189 190void ColorCodecBench::onDraw(int n, SkCanvas*) { 191#if defined(SK_TEST_QCMS) 192 if (FLAGS_qcms && FLAGS_half) { 193 SkDebugf("Error: Contradicting flags.\n"); 194 return; 195 } 196#endif 197 198 for (int i = 0; i < n; i++) { 199#if defined(SK_TEST_QCMS) 200 if (FLAGS_qcms) { 201 if (FLAGS_xform_only) { 202 this->xformOnlyQCMS(); 203 } else { 204 this->decodeAndXformQCMS(); 205 } 206 } else 207#endif 208 { 209 if (FLAGS_xform_only) { 210 this->xformOnly(); 211 } else { 212 this->decodeAndXform(); 213 } 214 } 215 } 216} 217