Home | History | Annotate | Download | only in effects
      1 /*
      2  * Copyright 2017 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 "SkPM4fPriv.h"
      9 #include "SkRasterPipeline.h"
     10 #include "SkReadBuffer.h"
     11 #include "SkString.h"
     12 #include "SkToSRGBColorFilter.h"
     13 #include "SkWriteBuffer.h"
     14 
     15 #if SK_SUPPORT_GPU
     16     #include "effects/GrNonlinearColorSpaceXformEffect.h"
     17 #endif
     18 
     19 void SkToSRGBColorFilter::onAppendStages(SkRasterPipeline* p,
     20                                          SkColorSpace* /*dst color space*/,
     21                                          SkArenaAlloc* alloc,
     22                                          bool shaderIsOpaque) const {
     23     // Step 1: Linearize by undoing the src transfer function.
     24     // Linear and sRGB will return true to isNumericalTransferFn(), so we check them first.
     25     SkColorSpaceTransferFn srcFn;
     26     if (fSrcColorSpace->gammaIsLinear()) {
     27         // Nothing to do.
     28     } else if (fSrcColorSpace->gammaCloseToSRGB()) {
     29         p->append(SkRasterPipeline::from_srgb);
     30     } else if (fSrcColorSpace->isNumericalTransferFn(&srcFn)) {
     31         auto copy = alloc->make<SkColorSpaceTransferFn>(srcFn);
     32         p->append(SkRasterPipeline::parametric_r, copy);
     33         p->append(SkRasterPipeline::parametric_g, copy);
     34         p->append(SkRasterPipeline::parametric_b, copy);
     35     } else {
     36         SkDEBUGFAIL("Looks like we got a table transfer function here, quite unexpectedly.");
     37         // TODO: If we really need to handle this, we can, but I don't think Ganesh does.
     38     }
     39 
     40     // Step 2: Transform to sRGB gamut, without clamping.
     41     // TODO: because...
     42     float* gamut_transform = alloc->makeArrayDefault<float>(12);
     43     (void)append_gamut_transform_noclamp(p,
     44                                          gamut_transform,
     45                                          fSrcColorSpace.get(),
     46                                          SkColorSpace::MakeSRGB().get());
     47 
     48     // Step 3: Back to sRGB encoding.
     49     p->append(SkRasterPipeline::to_srgb);
     50 }
     51 
     52 sk_sp<SkColorFilter> SkToSRGBColorFilter::Make(sk_sp<SkColorSpace> srcColorSpace) {
     53     if (!srcColorSpace || srcColorSpace->isSRGB()) {
     54         return nullptr;
     55     } else {
     56         return sk_sp<SkColorFilter>(new SkToSRGBColorFilter(std::move(srcColorSpace)));
     57     }
     58 }
     59 
     60 SkToSRGBColorFilter::SkToSRGBColorFilter(sk_sp<SkColorSpace> srcColorSpace)
     61         : fSrcColorSpace(std::move(srcColorSpace)) {
     62     SkASSERT(fSrcColorSpace);
     63 }
     64 
     65 sk_sp<SkFlattenable> SkToSRGBColorFilter::CreateProc(SkReadBuffer& buffer) {
     66     auto data = buffer.readByteArrayAsData();
     67     if (data) {
     68         return Make(SkColorSpace::Deserialize(data->data(), data->size()));
     69     }
     70     return nullptr;
     71 }
     72 
     73 void SkToSRGBColorFilter::flatten(SkWriteBuffer& buffer) const {
     74     buffer.writeDataAsByteArray(fSrcColorSpace->serialize().get());
     75 }
     76 
     77 #ifndef SK_IGNORE_TO_STRING
     78 void SkToSRGBColorFilter::toString(SkString* str) const {
     79     // TODO
     80     str->append("SkToSRGBColorFilter ");
     81 }
     82 #endif
     83 
     84 #if SK_SUPPORT_GPU
     85 std::unique_ptr<GrFragmentProcessor> SkToSRGBColorFilter::asFragmentProcessor(
     86         GrContext*, const GrColorSpaceInfo&) const {
     87     return GrNonlinearColorSpaceXformEffect::Make(fSrcColorSpace.get(),
     88                                                   SkColorSpace::MakeSRGB().get());
     89 }
     90 #endif
     91