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
SkFlipPixelRef(SkBitmap::Config config,int width,int height)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
~SkFlipPixelRef()21 SkFlipPixelRef::~SkFlipPixelRef() {
22 sk_free(fStorage);
23 }
24
beginUpdate(SkBitmap * device)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(©Bits);
35
36 SkFlipPixelRef::CopyBitsFromAddr(*device, copyBits, readAddr);
37 return dirty;
38 }
39
endUpdate()40 void SkFlipPixelRef::endUpdate() {
41 this->swapPages();
42 }
43
44 ///////////////////////////////////////////////////////////////////////////////
45
onLockPixels(SkColorTable ** ct)46 void* SkFlipPixelRef::onLockPixels(SkColorTable** ct) {
47 fMutex.acquire();
48 *ct = NULL;
49 return fPage0;
50 }
51
onUnlockPixels()52 void SkFlipPixelRef::onUnlockPixels() {
53 fMutex.release();
54 }
55
swapPages()56 void SkFlipPixelRef::swapPages() {
57 fMutex.acquire();
58 SkTSwap<void*>(fPage0, fPage1);
59 this->notifyPixelsChanged();
60 fMutex.release();
61 }
62
flatten(SkFlattenableWriteBuffer & buffer) const63 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
SkFlipPixelRef(SkFlattenableReadBuffer & buffer)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
Create(SkFlattenableReadBuffer & buffer)80 SkPixelRef* SkFlipPixelRef::Create(SkFlattenableReadBuffer& buffer) {
81 return SkNEW_ARGS(SkFlipPixelRef, (buffer));
82 }
83
SK_DEFINE_PIXEL_REF_REGISTRAR(SkFlipPixelRef)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
getShift(SkBitmap::Config config)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
CopyBitsFromAddr(const SkBitmap & dst,const SkRegion & clip,const void * srcAddr)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