ColorCodecBench.cpp revision 2cee902847a940c4bab56b42dabbb3721be3f9ac
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 "SkColorSpaceXform.h" 12#include "SkCommandLineFlags.h" 13 14#if !defined(GOOGLE3) 15DEFINE_bool(qcms, false, "Bench qcms color conversion"); 16#endif 17DEFINE_bool(xform_only, false, "Only time the color xform, do not include the decode time"); 18 19ColorCodecBench::ColorCodecBench(const char* name, sk_sp<SkData> encoded) 20 : fEncoded(std::move(encoded)) 21#if !defined(GOOGLE3) 22 , fDstSpaceQCMS(nullptr) 23#endif 24{ 25 fName.appendf("Color%s", FLAGS_xform_only ? "Xform" : "Codec"); 26#if !defined(GOOGLE3) 27 fName.appendf("%s", FLAGS_qcms ? "QCMS" : ""); 28#endif 29 fName.appendf("_%s", name); 30} 31 32const char* ColorCodecBench::onGetName() { 33 return fName.c_str(); 34} 35 36bool ColorCodecBench::isSuitableFor(Backend backend) { 37 return kNonRendering_Backend == backend; 38} 39 40void ColorCodecBench::decodeAndXform() { 41 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(fEncoded.get())); 42#ifdef SK_DEBUG 43 const SkCodec::Result result = 44#endif 45 codec->startScanlineDecode(fInfo); 46 SkASSERT(SkCodec::kSuccess == result); 47 48 sk_sp<SkColorSpace> srcSpace = sk_ref_sp(codec->getColorSpace()); 49 if (!srcSpace) { 50 srcSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named); 51 } 52 std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New(srcSpace, fDstSpace); 53 SkASSERT(xform); 54 55 void* dst = fDst.get(); 56 for (int y = 0; y < fInfo.height(); y++) { 57#ifdef SK_DEBUG 58 const int rows = 59#endif 60 codec->getScanlines(fSrc.get(), 1, 0); 61 SkASSERT(1 == rows); 62 63 xform->xform_RGBA_8888((uint32_t*) dst, (uint32_t*) fSrc.get(), fInfo.width()); 64 dst = SkTAddOffset<void>(dst, fInfo.minRowBytes()); 65 } 66} 67 68#if !defined(GOOGLE3) 69void ColorCodecBench::decodeAndXformQCMS() { 70 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(fEncoded.get())); 71#ifdef SK_DEBUG 72 const SkCodec::Result result = 73#endif 74 codec->startScanlineDecode(fInfo); 75 SkASSERT(SkCodec::kSuccess == result); 76 77 SkAutoTCallVProc<qcms_profile, qcms_profile_release> 78 srcSpace(qcms_profile_from_memory(fSrcData->data(), fSrcData->size())); 79 SkASSERT(srcSpace); 80 81 SkAutoTCallVProc<qcms_transform, qcms_transform_release> 82 transform (qcms_transform_create(srcSpace, QCMS_DATA_RGBA_8, fDstSpaceQCMS.get(), 83 QCMS_DATA_RGBA_8, QCMS_INTENT_PERCEPTUAL)); 84 SkASSERT(transform); 85 86#ifdef SK_PMCOLOR_IS_RGBA 87 qcms_output_type outType = QCMS_OUTPUT_RGBX; 88#else 89 qcms_output_type outType = QCMS_OUTPUT_BGRX; 90#endif 91 92 void* dst = fDst.get(); 93 for (int y = 0; y < fInfo.height(); y++) { 94#ifdef SK_DEBUG 95 const int rows = 96#endif 97 codec->getScanlines(fSrc.get(), 1, 0); 98 SkASSERT(1 == rows); 99 100 qcms_transform_data_type(transform, fSrc.get(), dst, fInfo.width(), outType); 101 dst = SkTAddOffset<void>(dst, fInfo.minRowBytes()); 102 } 103} 104#endif 105 106void ColorCodecBench::xformOnly() { 107 sk_sp<SkColorSpace> srcSpace = SkColorSpace::NewICC(fSrcData->data(), fSrcData->size()); 108 if (!srcSpace) { 109 srcSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named); 110 } 111 std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New(srcSpace, fDstSpace); 112 SkASSERT(xform); 113 114 void* dst = fDst.get(); 115 void* src = fSrc.get(); 116 for (int y = 0; y < fInfo.height(); y++) { 117 // Transform in place 118 xform->xform_RGBA_8888((uint32_t*) dst, (uint32_t*) src, fInfo.width()); 119 dst = SkTAddOffset<void>(dst, fInfo.minRowBytes()); 120 src = SkTAddOffset<void>(src, fInfo.minRowBytes()); 121 } 122} 123 124#if !defined(GOOGLE3) 125void ColorCodecBench::xformOnlyQCMS() { 126 SkAutoTCallVProc<qcms_profile, qcms_profile_release> 127 srcSpace(qcms_profile_from_memory(fSrcData->data(), fSrcData->size())); 128 SkASSERT(srcSpace); 129 130 SkAutoTCallVProc<qcms_transform, qcms_transform_release> 131 transform (qcms_transform_create(srcSpace, QCMS_DATA_RGBA_8, fDstSpaceQCMS.get(), 132 QCMS_DATA_RGBA_8, QCMS_INTENT_PERCEPTUAL)); 133 SkASSERT(transform); 134 135#ifdef SK_PMCOLOR_IS_RGBA 136 qcms_output_type outType = QCMS_OUTPUT_RGBX; 137#else 138 qcms_output_type outType = QCMS_OUTPUT_BGRX; 139#endif 140 141 void* dst = fDst.get(); 142 void* src = fSrc.get(); 143 for (int y = 0; y < fInfo.height(); y++) { 144 // Transform in place 145 qcms_transform_data_type(transform, src, dst, fInfo.width(), outType); 146 dst = SkTAddOffset<void>(dst, fInfo.minRowBytes()); 147 src = SkTAddOffset<void>(src, fInfo.minRowBytes()); 148 } 149} 150#endif 151 152void ColorCodecBench::onDelayedSetup() { 153 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(fEncoded.get())); 154 fInfo = codec->getInfo().makeColorType(kRGBA_8888_SkColorType); 155 156 fDst.reset(fInfo.getSafeSize(fInfo.minRowBytes())); 157 if (FLAGS_xform_only) { 158 fSrc.reset(fInfo.getSafeSize(fInfo.minRowBytes())); 159 codec->getPixels(fInfo, fSrc.get(), fInfo.minRowBytes()); 160 } else { 161 // Set-up a row buffer to decode into before transforming to dst. 162 fSrc.reset(fInfo.minRowBytes()); 163 } 164 165 fSrcData = codec->getICCData(); 166 sk_sp<SkData> dstData = SkData::MakeFromFileName( 167 GetResourcePath("monitor_profiles/HP_ZR30w.icc").c_str()); 168 SkASSERT(dstData); 169 170 171#if !defined(GOOGLE3) 172 if (FLAGS_qcms) { 173 fDstSpaceQCMS.reset(qcms_profile_from_memory(dstData->data(), dstData->size())); 174 SkASSERT(fDstSpaceQCMS); 175 } else 176#endif 177 { 178 fDstSpace = SkColorSpace::NewICC(dstData->data(), dstData->size()); 179 SkASSERT(fDstSpace); 180 } 181} 182 183void ColorCodecBench::onDraw(int n, SkCanvas*) { 184 for (int i = 0; i < n; i++) { 185#if !defined(GOOGLE3) 186 if (FLAGS_qcms) { 187 if (FLAGS_xform_only) { 188 this->xformOnlyQCMS(); 189 } else { 190 this->decodeAndXformQCMS(); 191 } 192 } else 193#endif 194 { 195 if (FLAGS_xform_only) { 196 this->xformOnly(); 197 } else { 198 this->decodeAndXform(); 199 } 200 } 201 } 202} 203