180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2011 Google Inc.
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
7910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkImageRef_ashmem.h"
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkImageDecoder.h"
10363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#include "SkFlattenableBuffers.h"
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkThread.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#include "android/ashmem.h"
14363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include <sys/mman.h>
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include <unistd.h>
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//#define TRACE_ASH_PURGE     // just trace purges
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef DUMP_IMAGEREF_LIFECYCLE
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define DUMP_ASHMEM_LIFECYCLE
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//    #define DUMP_ASHMEM_LIFECYCLE
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// ashmem likes lengths on page boundaries
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic size_t roundToPageSize(size_t size) {
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const size_t mask = getpagesize() - 1;
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t newsize = (size + mask) & ~mask;
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//    SkDebugf("---- oldsize %d newsize %d\n", size, newsize);
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return newsize;
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
34910f694aefb0b671dd8522a9afe9b6be645701c1Derek SollenbergerSkImageRef_ashmem::SkImageRef_ashmem(const SkImageInfo& info,
35910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                                     SkStreamRewindable* stream,
36910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                                     int sampleSize)
37910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    : SkImageRef(info, stream, sampleSize)
38910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger{
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fRec.fFD = -1;
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fRec.fAddr = NULL;
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fRec.fSize = 0;
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fRec.fPinned = false;
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fCT = NULL;
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkImageRef_ashmem::~SkImageRef_ashmem() {
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkSafeUnref(fCT);
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->closeFD();
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkImageRef_ashmem::closeFD() {
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (-1 != fRec.fFD) {
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef DUMP_ASHMEM_LIFECYCLE
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkDebugf("=== ashmem close %d\n", fRec.fFD);
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(fRec.fAddr);
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(fRec.fSize);
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        munmap(fRec.fAddr, fRec.fSize);
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        close(fRec.fFD);
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fRec.fFD = -1;
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass AshmemAllocator : public SkBitmap::Allocator {
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    AshmemAllocator(SkAshmemRec* rec, const char name[])
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        : fRec(rec), fName(name) {}
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) {
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const size_t size = roundToPageSize(bm->getSize());
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int fd = fRec->fFD;
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        void* addr = fRec->fAddr;
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(!fRec->fPinned);
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (-1 == fd) {
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(NULL == addr);
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(0 == fRec->fSize);
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fd = ashmem_create_region(fName, size);
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef DUMP_ASHMEM_LIFECYCLE
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkDebugf("=== ashmem_create_region %s size=%d fd=%d\n", fName, size, fd);
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (-1 == fd) {
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkDebugf("------- imageref_ashmem create failed <%s> %d\n",
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         fName, size);
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            int err = ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE);
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (err) {
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkDebugf("------ ashmem_set_prot_region(%d) failed %d\n",
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         fd, err);
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                close(fd);
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (-1 == (long)addr) {
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkDebugf("---------- mmap failed for imageref_ashmem size=%d\n",
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         size);
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                close(fd);
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fRec->fFD = fd;
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fRec->fAddr = addr;
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fRec->fSize = size;
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(addr);
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(size == fRec->fSize);
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            (void)ashmem_pin_region(fd, 0, 0);
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        bm->setPixels(addr, ct);
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fRec->fPinned = true;
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate:
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // we just point to our caller's memory, these are not copies
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkAshmemRec* fRec;
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const char*  fName;
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1290a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerbool SkImageRef_ashmem::onDecode(SkImageDecoder* codec, SkStreamRewindable* stream,
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                 SkBitmap* bitmap, SkBitmap::Config config,
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                 SkImageDecoder::Mode mode) {
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (SkImageDecoder::kDecodeBounds_Mode == mode) {
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return this->INHERITED::onDecode(codec, stream, bitmap, config, mode);
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1370a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    // Ashmem memory is guaranteed to be initialized to 0.
1380a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    codec->setSkipWritingZeroes(true);
1390a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    AshmemAllocator alloc(&fRec, this->getURI());
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    codec->setAllocator(&alloc);
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool success = this->INHERITED::onDecode(codec, stream, bitmap, config,
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             mode);
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // remove the allocator, since its on the stack
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    codec->setAllocator(NULL);
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (success) {
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // remember the colortable (if any)
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkRefCnt_SafeAssign(fCT, bitmap->getColorTable());
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (fRec.fPinned) {
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            ashmem_unpin_region(fRec.fFD, 0, 0);
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fRec.fPinned = false;
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->closeFD();
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid* SkImageRef_ashmem::onLockPixels(SkColorTable** ct) {
16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(fBitmap.getPixels() == NULL);
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(fBitmap.getColorTable() == NULL);
16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // fast case: check if we can just pin and get the cached data
16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (-1 != fRec.fFD) {
16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(fRec.fAddr);
16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(!fRec.fPinned);
17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int pin = ashmem_pin_region(fRec.fFD, 0, 0);
17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (ASHMEM_NOT_PURGED == pin) { // yea, fast case!
17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fBitmap.setPixels(fRec.fAddr, fCT);
17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fRec.fPinned = true;
17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else if (ASHMEM_WAS_PURGED == pin) {
17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            ashmem_unpin_region(fRec.fFD, 0, 0);
17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // let go of our colortable if we lost the pixels. Well get it back
17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // again when we re-decode
17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (fCT) {
18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fCT->unref();
18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fCT = NULL;
18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if defined(DUMP_ASHMEM_LIFECYCLE) || defined(TRACE_ASH_PURGE)
18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkDebugf("===== ashmem purged %d\n", fBitmap.getSize());
18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkDebugf("===== ashmem pin_region(%d) returned %d\n", fRec.fFD, pin);
18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // return null result for failure
18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (ct) {
19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                *ct = NULL;
19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return NULL;
19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // no FD, will create an ashmem region in allocator
19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return this->INHERITED::onLockPixels(ct);
19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkImageRef_ashmem::onUnlockPixels() {
20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->INHERITED::onUnlockPixels();
20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (-1 != fRec.fFD) {
20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(fRec.fAddr);
20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(fRec.fPinned);
20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        ashmem_unpin_region(fRec.fFD, 0, 0);
20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fRec.fPinned = false;
21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // we clear this with or without an error, since we've either closed or
21380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // unpinned the region
21480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fBitmap.setPixels(NULL, NULL);
21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
21680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkImageRef_ashmem::flatten(SkFlattenableWriteBuffer& buffer) const {
21880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->INHERITED::flatten(buffer);
21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    buffer.writeString(getURI());
22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
22180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkImageRef_ashmem::SkImageRef_ashmem(SkFlattenableReadBuffer& buffer)
22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        : INHERITED(buffer) {
22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fRec.fFD = -1;
22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fRec.fAddr = NULL;
22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fRec.fSize = 0;
22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fRec.fPinned = false;
22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fCT = NULL;
2297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
2307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkString uri;
2317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    buffer.readString(&uri);
2327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    this->setURI(uri);
23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
234