LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/gpu - GrColorSpaceXform.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 55 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 8 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 "GrColorSpaceXform.h"
       9             : #include "SkColorSpace.h"
      10             : #include "SkColorSpace_Base.h"
      11             : #include "SkMatrix44.h"
      12             : #include "SkSpinlock.h"
      13             : 
      14             : class GrColorSpaceXformCache {
      15             : public:
      16             :     using NewValueFn = std::function<sk_sp<GrColorSpaceXform>(void)>;
      17             : 
      18           0 :     GrColorSpaceXformCache() : fSequence(0) {}
      19             : 
      20           0 :     sk_sp<GrColorSpaceXform> findOrAdd(uint64_t key, NewValueFn newValue) {
      21           0 :         int oldest = 0;
      22           0 :         for (int i = 0; i < kEntryCount; ++i) {
      23           0 :             if (fEntries[i].fKey == key) {
      24           0 :                 fEntries[i].fLastUse = fSequence++;
      25           0 :                 return fEntries[i].fXform;
      26             :             }
      27           0 :             if (fEntries[i].fLastUse < fEntries[oldest].fLastUse) {
      28           0 :                 oldest = i;
      29             :             }
      30             :         }
      31           0 :         fEntries[oldest].fKey = key;
      32           0 :         fEntries[oldest].fXform = newValue();
      33           0 :         fEntries[oldest].fLastUse = fSequence++;
      34           0 :         return fEntries[oldest].fXform;
      35             :     }
      36             : 
      37             : private:
      38             :     enum { kEntryCount = 32 };
      39             : 
      40             :     struct Entry {
      41             :         // The default Entry is "valid". Any 64-bit key that is the same 32-bit value repeated
      42             :         // implies no xform is necessary, so nullptr should be returned. This particular case should
      43             :         // never happen, but by initializing all entries with this data, we can avoid special cases
      44             :         // for the array not yet being full.
      45           0 :         Entry() : fKey(0), fXform(nullptr), fLastUse(0) {}
      46             : 
      47             :         uint64_t fKey;
      48             :         sk_sp<GrColorSpaceXform> fXform;
      49             :         uint64_t fLastUse;
      50             :     };
      51             : 
      52             :     Entry fEntries[kEntryCount];
      53             :     uint64_t fSequence;
      54             : };
      55             : 
      56           0 : GrColorSpaceXform::GrColorSpaceXform(const SkMatrix44& srcToDst)
      57           0 :     : fSrcToDst(srcToDst) {}
      58             : 
      59             : static SkSpinlock gColorSpaceXformCacheSpinlock;
      60             : 
      61           0 : sk_sp<GrColorSpaceXform> GrColorSpaceXform::Make(const SkColorSpace* src, const SkColorSpace* dst) {
      62           0 :     if (!src || !dst) {
      63             :         // Invalid
      64           0 :         return nullptr;
      65             :     }
      66             : 
      67           0 :     if (src == dst) {
      68             :         // Quick equality check - no conversion needed in this case
      69           0 :         return nullptr;
      70             :     }
      71             : 
      72           0 :     const SkMatrix44* toXYZD50   = as_CSB(src)->toXYZD50();
      73           0 :     const SkMatrix44* fromXYZD50 = as_CSB(dst)->fromXYZD50();
      74           0 :     if (!toXYZD50 || !fromXYZD50) {
      75             :         // unsupported colour spaces -- cannot specify gamut as a matrix
      76           0 :         return nullptr;
      77             :     }
      78             : 
      79           0 :     uint32_t srcHash = as_CSB(src)->toXYZD50Hash();
      80           0 :     uint32_t dstHash = as_CSB(dst)->toXYZD50Hash();
      81           0 :     if (srcHash == dstHash) {
      82             :         // Identical gamut - no conversion needed in this case
      83           0 :         SkASSERT(*toXYZD50 == *as_CSB(dst)->toXYZD50() && "Hash collision");
      84           0 :         return nullptr;
      85             :     }
      86             : 
      87           0 :     auto deferredResult = [fromXYZD50, toXYZD50]() {
      88           0 :         SkMatrix44 srcToDst(SkMatrix44::kUninitialized_Constructor);
      89           0 :         srcToDst.setConcat(*fromXYZD50, *toXYZD50);
      90           0 :         return sk_make_sp<GrColorSpaceXform>(srcToDst);
      91           0 :     };
      92             : 
      93           0 :     if (gColorSpaceXformCacheSpinlock.tryAcquire()) {
      94             :         static GrColorSpaceXformCache* gCache;
      95           0 :         if (nullptr == gCache) {
      96           0 :             gCache = new GrColorSpaceXformCache();
      97             :         }
      98             : 
      99           0 :         uint64_t key = static_cast<uint64_t>(srcHash) << 32 | static_cast<uint64_t>(dstHash);
     100           0 :         sk_sp<GrColorSpaceXform> xform = gCache->findOrAdd(key, deferredResult);
     101           0 :         gColorSpaceXformCacheSpinlock.release();
     102           0 :         return xform;
     103             :     } else {
     104             :         // Rather than wait for the spin lock, just bypass the cache
     105           0 :         return deferredResult();
     106             :     }
     107             : }
     108             : 
     109           0 : bool GrColorSpaceXform::Equals(const GrColorSpaceXform* a, const GrColorSpaceXform* b) {
     110           0 :     if (a == b) {
     111           0 :         return true;
     112             :     }
     113             : 
     114           0 :     if (!a || !b) {
     115           0 :         return false;
     116             :     }
     117             : 
     118           0 :     return a->fSrcToDst == b->fSrcToDst;
     119             : }
     120             : 
     121           0 : GrColor4f GrColorSpaceXform::apply(const GrColor4f& srcColor) {
     122           0 :     GrColor4f result;
     123           0 :     fSrcToDst.mapScalars(srcColor.fRGBA, result.fRGBA);
     124             :     // We always operate on unpremul colors, so clamp to [0,1].
     125           0 :     for (int i = 0; i < 4; ++i) {
     126           0 :         result.fRGBA[i] = SkTPin(result.fRGBA[i], 0.0f, 1.0f);
     127             :     }
     128           0 :     return result;
     129             : }

Generated by: LCOV version 1.13