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