blob: 6ab5bbc68fe80076e498930c197aa426bbdb98c1 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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 */
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#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(&copyBits);
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);
reed@android.com44a63122009-05-30 02:40:28 +000059 this->notifyPixelsChanged();
reed@android.com8a1c16f2008-12-17 15:59:43 +000060 fMutex.release();
61}
62
djsollen@google.com54924242012-03-29 15:18:04 +000063void SkFlipPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
reed@android.com8a1c16f2008-12-17 15:59:43 +000064 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
djsollen@google.com5370cd92012-03-28 20:47:01 +000080SK_DEFINE_FLATTENABLE_REGISTRAR(SkFlipPixelRef)
reed@android.com8a1c16f2008-12-17 15:59:43 +000081
82///////////////////////////////////////////////////////////////////////////////
83
84static void copyRect(const SkBitmap& dst, const SkIRect& rect,
85 const void* srcAddr, int shift) {
86 const size_t offset = rect.fTop * dst.rowBytes() + (rect.fLeft << shift);
87 char* dstP = static_cast<char*>(dst.getPixels()) + offset;
88 const char* srcP = static_cast<const char*>(srcAddr) + offset;
89 const size_t rb = dst.rowBytes();
90 const size_t bytes = rect.width() << shift;
91
92 int height = rect.height();
93 while (--height >= 0) {
94 memcpy(dstP, srcP, bytes);
95 dstP += rb;
96 srcP += rb;
97 }
98}
99
100static int getShift(SkBitmap::Config config) {
101 switch (config) {
102 case SkBitmap::kARGB_8888_Config:
103 return 2;
104 case SkBitmap::kRGB_565_Config:
105 case SkBitmap::kARGB_4444_Config:
106 return 1;
107 case SkBitmap::kIndex8_Config:
108 case SkBitmap::kA8_Config:
109 return 0;
110 default:
111 return -1; // signal not supported
112 }
113}
114
115void SkFlipPixelRef::CopyBitsFromAddr(const SkBitmap& dst, const SkRegion& clip,
116 const void* srcAddr) {
117 const int shift = getShift(dst.config());
118 if (shift < 0) {
119 return;
120 }
121
122 const SkIRect bounds = {0, 0, dst.width(), dst.height()};
123 SkRegion::Cliperator iter(clip, bounds);
124
125 while (!iter.done()) {
126 copyRect(dst, iter.rect(), srcAddr, shift);
127 iter.next();
128 }
129}