Home | History | Annotate | Download | only in images
      1 
      2 /*
      3  * Copyright 2011 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 #include "SkFlipPixelRef.h"
      9 #include "SkFlattenable.h"
     10 #include "SkRegion.h"
     11 
     12 SkFlipPixelRef::SkFlipPixelRef(SkBitmap::Config config, int width, int height)
     13 : fFlipper(width, height) {
     14     fConfig = config;
     15     fSize = SkBitmap::ComputeSize(config, width, height);
     16     fStorage = sk_malloc_throw(fSize << 1);
     17     fPage0 = fStorage;
     18     fPage1 = (char*)fStorage + fSize;
     19 }
     20 
     21 SkFlipPixelRef::~SkFlipPixelRef() {
     22     sk_free(fStorage);
     23 }
     24 
     25 const SkRegion& SkFlipPixelRef::beginUpdate(SkBitmap* device) {
     26     void*       writeAddr;
     27     const void* readAddr;
     28     this->getFrontBack(&readAddr, &writeAddr);
     29 
     30     device->setConfig(fConfig, fFlipper.width(), fFlipper.height());
     31     device->setPixels(writeAddr);
     32 
     33     SkRegion    copyBits;
     34     const SkRegion& dirty = fFlipper.update(&copyBits);
     35 
     36     SkFlipPixelRef::CopyBitsFromAddr(*device, copyBits, readAddr);
     37     return dirty;
     38 }
     39 
     40 void SkFlipPixelRef::endUpdate() {
     41     this->swapPages();
     42 }
     43 
     44 ///////////////////////////////////////////////////////////////////////////////
     45 
     46 void* SkFlipPixelRef::onLockPixels(SkColorTable** ct) {
     47     fMutex.acquire();
     48     *ct = NULL;
     49     return fPage0;
     50 }
     51 
     52 void SkFlipPixelRef::onUnlockPixels() {
     53     fMutex.release();
     54 }
     55 
     56 void SkFlipPixelRef::swapPages() {
     57     fMutex.acquire();
     58     SkTSwap<void*>(fPage0, fPage1);
     59     this->notifyPixelsChanged();
     60     fMutex.release();
     61 }
     62 
     63 void SkFlipPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
     64     this->INHERITED::flatten(buffer);
     65 
     66     buffer.write32(fSize);
     67     // only need to write page0
     68     buffer.writePad(fPage0, fSize);
     69 }
     70 
     71 SkFlipPixelRef::SkFlipPixelRef(SkFlattenableReadBuffer& buffer)
     72         : INHERITED(buffer, NULL) {
     73     fSize = buffer.readU32();
     74     fStorage = sk_malloc_throw(fSize << 1);
     75     fPage0 = fStorage;
     76     fPage1 = (char*)fStorage + fSize;
     77     buffer.read(fPage0, fSize);
     78 }
     79 
     80 SkPixelRef* SkFlipPixelRef::Create(SkFlattenableReadBuffer& buffer) {
     81     return SkNEW_ARGS(SkFlipPixelRef, (buffer));
     82 }
     83 
     84 SK_DEFINE_PIXEL_REF_REGISTRAR(SkFlipPixelRef)
     85 
     86 ///////////////////////////////////////////////////////////////////////////////
     87 
     88 static void copyRect(const SkBitmap& dst, const SkIRect& rect,
     89                      const void* srcAddr, int shift) {
     90     const size_t offset = rect.fTop * dst.rowBytes() + (rect.fLeft << shift);
     91     char* dstP = static_cast<char*>(dst.getPixels()) + offset;
     92     const char* srcP = static_cast<const char*>(srcAddr) + offset;
     93     const size_t rb = dst.rowBytes();
     94     const size_t bytes = rect.width() << shift;
     95 
     96     int height = rect.height();
     97     while (--height >= 0) {
     98         memcpy(dstP, srcP, bytes);
     99         dstP += rb;
    100         srcP += rb;
    101     }
    102 }
    103 
    104 static int getShift(SkBitmap::Config config) {
    105     switch (config) {
    106         case SkBitmap::kARGB_8888_Config:
    107             return 2;
    108         case SkBitmap::kRGB_565_Config:
    109         case SkBitmap::kARGB_4444_Config:
    110             return 1;
    111         case SkBitmap::kIndex8_Config:
    112         case SkBitmap::kA8_Config:
    113             return 0;
    114         default:
    115             return -1;  // signal not supported
    116     }
    117 }
    118 
    119 void SkFlipPixelRef::CopyBitsFromAddr(const SkBitmap& dst, const SkRegion& clip,
    120                                       const void* srcAddr) {
    121     const int shift = getShift(dst.config());
    122     if (shift < 0) {
    123         return;
    124     }
    125 
    126     const SkIRect bounds = {0, 0, dst.width(), dst.height()};
    127     SkRegion::Cliperator iter(clip, bounds);
    128 
    129     while (!iter.done()) {
    130         copyRect(dst, iter.rect(), srcAddr, shift);
    131         iter.next();
    132     }
    133 }
    134