1 #include "SkFlipPixelRef.h" 2 #include "SkFlattenable.h" 3 #include "SkRegion.h" 4 5 SkFlipPixelRef::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 14 SkFlipPixelRef::~SkFlipPixelRef() { 15 sk_free(fStorage); 16 } 17 18 const 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 33 void SkFlipPixelRef::endUpdate() { 34 this->swapPages(); 35 } 36 37 /////////////////////////////////////////////////////////////////////////////// 38 39 void* SkFlipPixelRef::onLockPixels(SkColorTable** ct) { 40 fMutex.acquire(); 41 *ct = NULL; 42 return fPage0; 43 } 44 45 void SkFlipPixelRef::onUnlockPixels() { 46 fMutex.release(); 47 } 48 49 void SkFlipPixelRef::swapPages() { 50 fMutex.acquire(); 51 SkTSwap<void*>(fPage0, fPage1); 52 this->notifyPixelsChanged(); 53 fMutex.release(); 54 } 55 56 void 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 64 SkFlipPixelRef::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 73 SkPixelRef* SkFlipPixelRef::Create(SkFlattenableReadBuffer& buffer) { 74 return SkNEW_ARGS(SkFlipPixelRef, (buffer)); 75 } 76 77 static SkPixelRef::Registrar reg("SkFlipPixelRef", 78 SkFlipPixelRef::Create); 79 80 /////////////////////////////////////////////////////////////////////////////// 81 82 static 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 98 static 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 113 void 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