• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&copyBits);
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 
63 ///////////////////////////////////////////////////////////////////////////////
64 
copyRect(const SkBitmap & dst,const SkIRect & rect,const void * srcAddr,int shift)65 static void copyRect(const SkBitmap& dst, const SkIRect& rect,
66                      const void* srcAddr, int shift) {
67     const size_t offset = rect.fTop * dst.rowBytes() + (rect.fLeft << shift);
68     char* dstP = static_cast<char*>(dst.getPixels()) + offset;
69     const char* srcP = static_cast<const char*>(srcAddr) + offset;
70     const size_t rb = dst.rowBytes();
71     const size_t bytes = rect.width() << shift;
72 
73     int height = rect.height();
74     while (--height >= 0) {
75         memcpy(dstP, srcP, bytes);
76         dstP += rb;
77         srcP += rb;
78     }
79 }
80 
getShift(SkBitmap::Config config)81 static int getShift(SkBitmap::Config config) {
82     switch (config) {
83         case SkBitmap::kARGB_8888_Config:
84             return 2;
85         case SkBitmap::kRGB_565_Config:
86         case SkBitmap::kARGB_4444_Config:
87             return 1;
88         case SkBitmap::kIndex8_Config:
89         case SkBitmap::kA8_Config:
90             return 0;
91         default:
92             return -1;  // signal not supported
93     }
94 }
95 
CopyBitsFromAddr(const SkBitmap & dst,const SkRegion & clip,const void * srcAddr)96 void SkFlipPixelRef::CopyBitsFromAddr(const SkBitmap& dst, const SkRegion& clip,
97                                       const void* srcAddr) {
98     const int shift = getShift(dst.config());
99     if (shift < 0) {
100         return;
101     }
102 
103     const SkIRect bounds = {0, 0, dst.width(), dst.height()};
104     SkRegion::Cliperator iter(clip, bounds);
105 
106     while (!iter.done()) {
107         copyRect(dst, iter.rect(), srcAddr, shift);
108         iter.next();
109     }
110 }
111