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 12SkFlipPixelRef::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 21SkFlipPixelRef::~SkFlipPixelRef() { 22 sk_free(fStorage); 23} 24 25const 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(©Bits); 35 36 SkFlipPixelRef::CopyBitsFromAddr(*device, copyBits, readAddr); 37 return dirty; 38} 39 40void SkFlipPixelRef::endUpdate() { 41 this->swapPages(); 42} 43 44/////////////////////////////////////////////////////////////////////////////// 45 46void* SkFlipPixelRef::onLockPixels(SkColorTable** ct) { 47 fMutex.acquire(); 48 *ct = NULL; 49 return fPage0; 50} 51 52void SkFlipPixelRef::onUnlockPixels() { 53 fMutex.release(); 54} 55 56void SkFlipPixelRef::swapPages() { 57 fMutex.acquire(); 58 SkTSwap<void*>(fPage0, fPage1); 59 this->notifyPixelsChanged(); 60 fMutex.release(); 61} 62 63void 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 71SkFlipPixelRef::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 80SkPixelRef* SkFlipPixelRef::Create(SkFlattenableReadBuffer& buffer) { 81 return SkNEW_ARGS(SkFlipPixelRef, (buffer)); 82} 83 84SK_DEFINE_PIXEL_REF_REGISTRAR(SkFlipPixelRef) 85 86/////////////////////////////////////////////////////////////////////////////// 87 88static 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 104static 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 119void 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