/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "Sk64.h"
#include "SkLazyPixelRef.h"
#include "SkColorTable.h"
#include "SkData.h"
#include "SkImageCache.h"
#include "SkImagePriv.h"

#if LAZY_CACHE_STATS
#include "SkThread.h"

int32_t SkLazyPixelRef::gCacheHits;
int32_t SkLazyPixelRef::gCacheMisses;
#endif

SkLazyPixelRef::SkLazyPixelRef(SkData* data, SkBitmapFactory::DecodeProc proc, SkImageCache* cache)
    // Pass NULL for the Mutex so that the default (ring buffer) will be used.
    : INHERITED(NULL)
    , fDecodeProc(proc)
    , fImageCache(cache)
    , fCacheId(SkImageCache::UNINITIALIZED_ID)
    , fRowBytes(0) {
    SkASSERT(fDecodeProc != NULL);
    if (NULL == data) {
        fData = SkData::NewEmpty();
        fErrorInDecoding = true;
    } else {
        fData = data;
        fData->ref();
        fErrorInDecoding = data->size() == 0;
    }
    SkASSERT(cache != NULL);
    cache->ref();

    // mark as uninitialized -- all fields are -1
    memset(&fLazilyCachedInfo, 0xFF, sizeof(fLazilyCachedInfo));

    // Since this pixel ref bases its data on encoded data, it should never change.
    this->setImmutable();
}

SkLazyPixelRef::~SkLazyPixelRef() {
    SkASSERT(fData != NULL);
    fData->unref();
    SkASSERT(fImageCache);
    if (fCacheId != SkImageCache::UNINITIALIZED_ID) {
        fImageCache->throwAwayCache(fCacheId);
    }
    fImageCache->unref();
}

static size_t ComputeMinRowBytesAndSize(const SkImage::Info& info, size_t* rowBytes) {
    *rowBytes = SkImageMinRowBytes(info);

    Sk64 safeSize;
    safeSize.setZero();
    if (info.fHeight > 0) {
        safeSize.setMul(info.fHeight, SkToS32(*rowBytes));
    }
    SkASSERT(!safeSize.isNeg());
    return safeSize.is32() ? safeSize.get32() : 0;
}

const SkImage::Info* SkLazyPixelRef::getCachedInfo() {
    if (fLazilyCachedInfo.fWidth < 0) {
        SkImage::Info info;
        fErrorInDecoding = !fDecodeProc(fData->data(), fData->size(), &info, NULL);
        if (fErrorInDecoding) {
            return NULL;
        }
        fLazilyCachedInfo = info;
    }
    return &fLazilyCachedInfo;
}

void* SkLazyPixelRef::onLockPixels(SkColorTable**) {
    if (fErrorInDecoding) {
        return NULL;
    }
    SkBitmapFactory::Target target;
    // Check to see if the pixels still exist in the cache.
    if (SkImageCache::UNINITIALIZED_ID == fCacheId) {
        target.fAddr = NULL;
    } else {
        SkImageCache::DataStatus status;
        target.fAddr = fImageCache->pinCache(fCacheId, &status);
        if (target.fAddr == NULL) {
            fCacheId = SkImageCache::UNINITIALIZED_ID;
        } else {
            if (SkImageCache::kRetained_DataStatus == status) {
#if LAZY_CACHE_STATS
                sk_atomic_inc(&gCacheHits);
#endif
                return target.fAddr;
            }
            SkASSERT(SkImageCache::kUninitialized_DataStatus == status);
        }
        // Cache miss. Either pinCache returned NULL or it returned a memory address without the old
        // data
#if LAZY_CACHE_STATS
        sk_atomic_inc(&gCacheMisses);
#endif
    }

    SkASSERT(fData != NULL && fData->size() > 0);
    if (NULL == target.fAddr) {
        const SkImage::Info* info = this->getCachedInfo();
        if (NULL == info) {
            SkASSERT(SkImageCache::UNINITIALIZED_ID == fCacheId);
            return NULL;
        }
        size_t bytes = ComputeMinRowBytesAndSize(*info, &target.fRowBytes);
        target.fAddr = fImageCache->allocAndPinCache(bytes, &fCacheId);
        if (NULL == target.fAddr) {
            // Space could not be allocated.
            // Just like the last assert, fCacheId must be UNINITIALIZED_ID.
            SkASSERT(SkImageCache::UNINITIALIZED_ID == fCacheId);
            return NULL;
        }
    } else {
        // pinCache returned purged memory to which target.fAddr already points. Set
        // target.fRowBytes properly.
        target.fRowBytes = fRowBytes;
        // Assume that the size is correct, since it was determined by this same function
        // previously.
    }
    SkASSERT(target.fAddr != NULL);
    SkASSERT(SkImageCache::UNINITIALIZED_ID != fCacheId);
    fErrorInDecoding = !fDecodeProc(fData->data(), fData->size(), NULL, &target);
    if (fErrorInDecoding) {
        fImageCache->throwAwayCache(fCacheId);
        fCacheId = SkImageCache::UNINITIALIZED_ID;
        return NULL;
    }
    // Upon success, store fRowBytes so it can be used in case pinCache later returns purged memory.
    fRowBytes = target.fRowBytes;
    return target.fAddr;
}

void SkLazyPixelRef::onUnlockPixels() {
    if (fErrorInDecoding) {
        return;
    }
    if (fCacheId != SkImageCache::UNINITIALIZED_ID) {
        fImageCache->releaseCache(fCacheId);
    }
}

SkData* SkLazyPixelRef::onRefEncodedData() {
    fData->ref();
    return fData;
}

#include "SkImagePriv.h"

static bool init_from_info(SkBitmap* bm, const SkImage::Info& info,
                           size_t rowBytes) {
    SkBitmap::Config config = SkImageInfoToBitmapConfig(info);
    if (SkBitmap::kNo_Config == config) {
        return false;
    }

    return bm->setConfig(config, info.fWidth, info.fHeight, rowBytes, info.fAlphaType)
           &&
           bm->allocPixels();
}

bool SkLazyPixelRef::onImplementsDecodeInto() {
    return true;
}

bool SkLazyPixelRef::onDecodeInto(int pow2, SkBitmap* bitmap) {
    SkASSERT(fData != NULL && fData->size() > 0);
    if (fErrorInDecoding) {
        return false;
    }

    SkImage::Info info;
    // Determine the size of the image in order to determine how much memory to allocate.
    // FIXME: As an optimization, only do this part once.
    fErrorInDecoding = !fDecodeProc(fData->data(), fData->size(), &info, NULL);
    if (fErrorInDecoding) {
        return false;
    }

    SkBitmapFactory::Target target;
    (void)ComputeMinRowBytesAndSize(info, &target.fRowBytes);

    SkBitmap tmp;
    if (!init_from_info(&tmp, info, target.fRowBytes)) {
        return false;
    }

    target.fAddr = tmp.getPixels();
    fErrorInDecoding = !fDecodeProc(fData->data(), fData->size(), &info, &target);
    if (fErrorInDecoding) {
        return false;
    }

    *bitmap = tmp;
    return true;
}
