From: commit-bot@chromium.org Date: Wed, 24 Apr 2013 20:03:00 +0000 (+0000) Subject: Move MMap to SkData. X-Git-Tag: accepted/tizen/5.0/unified/20181102.025319~12612 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9711e446676e6bf84b3fff916fd1d7537933a110;p=platform%2Fupstream%2FlibSkiaSharp.git Move MMap to SkData. R=reed@google.com Author: bungeman@google.com Review URL: https://chromiumcodereview.appspot.com/14336003 git-svn-id: http://skia.googlecode.com/svn/trunk@8848 2bbb7eff-a529-9590-31e7-b0007b416f81 --- diff --git a/gm/factory.cpp b/gm/factory.cpp index f4e8ae3..4538cda 100644 --- a/gm/factory.cpp +++ b/gm/factory.cpp @@ -32,12 +32,12 @@ protected: // Copyright-free file from http://openclipart.org/detail/29213/paper-plane-by-ddoo filename.append("plane.png"); - SkFILEStream stream(filename.c_str()); - if (stream.isValid()) { - stream.rewind(); - size_t length = stream.getLength(); + SkAutoTUnref stream(SkStream::NewFromFile(filename.c_str())); + if (NULL != stream.get()) { + stream->rewind(); + size_t length = stream->getLength(); void* buffer = sk_malloc_throw(length); - stream.read(buffer, length); + stream->read(buffer, length); SkAutoDataUnref data(SkData::NewFromMalloc(buffer, length)); SkBitmapFactory factory(&SkImageDecoder::DecodeMemoryToTarget); // Create a cache which will boot the pixels out anytime the diff --git a/include/core/SkData.h b/include/core/SkData.h index fdd3a57..0e8ee22 100644 --- a/include/core/SkData.h +++ b/include/core/SkData.h @@ -13,6 +13,8 @@ #include "SkFlattenable.h" +struct SkFILE; + /** * SkData holds an immutable data buffer. Not only is the data immutable, * but the actual ptr that is returned (by data() or bytes()) is guaranteed @@ -89,10 +91,12 @@ public: static SkData* NewFromMalloc(const void* data, size_t length); /** - * Create a new dataref from a pointer allocated by mmap. The Data object - * will handle calling munmap(). + * Create a new dataref from a SkFILE. + * This does not take ownership of the SkFILE, nor close it. + * The SkFILE must be open for reading only. + * Returns NULL on failure. */ - static SkData* NewFromMMap(const void* data, size_t length); + static SkData* NewFromFILE(SkFILE* f); /** * Create a new dataref using a subset of the data in the specified diff --git a/src/core/SkData.cpp b/src/core/SkData.cpp index 8c22200..53d5f23 100644 --- a/src/core/SkData.cpp +++ b/src/core/SkData.cpp @@ -7,12 +7,16 @@ #include "SkData.h" #include "SkFlattenableBuffers.h" +#include "SkOSFile.h" #if SK_MMAP_SUPPORT #include #include #include #include + #include +#else + #include #endif SK_DEFINE_INST_COUNT(SkData) @@ -94,6 +98,90 @@ static void sk_dataref_releaseproc(const void*, size_t, void* context) { src->unref(); } +#if SK_MMAP_SUPPORT + +static void sk_munmap_releaseproc(const void* addr, size_t length, void*) { + munmap(const_cast(addr), length); +} + +SkData* SkData::NewFromFILE(SkFILE* f) { + size_t size = sk_fgetsize(f); + if (0 == size) { + return NULL; + } + + int fd = fileno((FILE*)f); + if (fd < 0) { + return NULL; + } + + void* addr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + if (MAP_FAILED == addr) { + return NULL; + } + + return SkData::NewWithProc(addr, size, sk_munmap_releaseproc, NULL); +} + +#elif SK_BUILD_FOR_WIN32 + +template +class SkAutoTHandle : SkNoncopyable { +public: + SkAutoTHandle(HandleType handle) : fHandle(handle) { } + ~SkAutoTHandle() { Close(fHandle); } + operator HandleType() { return fHandle; } + bool isValid() { return InvalidValue != fHandle; } +private: + HandleType fHandle; +}; +typedef SkAutoTHandle SkAutoWinFile; +typedef SkAutoTHandle SkAutoWinMMap; + +static void sk_munmap_releaseproc(const void* addr, size_t, void*) { + UnmapViewOfFile(addr); +} + +SkData* SkData::NewFromFILE(SkFILE* f) { + size_t size = sk_fgetsize(f); + if (0 == size) { + return NULL; + } + + int fileno = _fileno((FILE*)f); + if (fileno < 0) { + return NULL; + } + + HANDLE file = (HANDLE)_get_osfhandle(fileno); + if (INVALID_HANDLE_VALUE == file) { + return NULL; + } + + SkAutoWinMMap mmap(CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL)); + if (!mmap.isValid()) { + //TODO: use SK_TRACEHR(GetLastError(), "Could not create file mapping.") to report. + return NULL; + } + + // Eventually call UnmapViewOfFile + void* addr = MapViewOfFile(mmap, FILE_MAP_READ, 0, 0, 0); + if (NULL == addr) { + //TODO: use SK_TRACEHR(GetLastError(), "Could not map view of file.") to report. + return NULL; + } + + return SkData::NewWithProc(addr, size, sk_munmap_releaseproc, NULL); +} + +#else + +SkData* SkData::NewFromFILE(SkFILE* f) { + return NULL; +} + +#endif + SkData* SkData::NewSubset(const SkData* src, size_t offset, size_t length) { /* We could, if we wanted/need to, just make a deep copy of src's data, @@ -127,20 +215,6 @@ SkData* SkData::NewWithCString(const char cstr[]) { return NewWithCopy(cstr, size); } -#if SK_MMAP_SUPPORT -static void sk_munmap_releaseproc(const void* addr, size_t length, void*) { - munmap(const_cast(addr), length); -} - -SkData* SkData::NewFromMMap(const void* addr, size_t length) { - return SkNEW_ARGS(SkData, (addr, length, sk_munmap_releaseproc, NULL)); -} -#else -SkData* SkData::NewFromMMap(const void* addr, size_t length) { - return NULL; -} -#endif - /////////////////////////////////////////////////////////////////////////////// void SkData::flatten(SkFlattenableWriteBuffer& buffer) const { diff --git a/src/core/SkStream.cpp b/src/core/SkStream.cpp index ed1287e..74734e6 100644 --- a/src/core/SkStream.cpp +++ b/src/core/SkStream.cpp @@ -13,14 +13,6 @@ #include "SkString.h" #include "SkOSFile.h" -#if SK_MMAP_SUPPORT - #include - #include - #include - #include - #include -#endif - SK_DEFINE_INST_COUNT(SkStream) SK_DEFINE_INST_COUNT(SkWStream) SK_DEFINE_INST_COUNT(SkFILEStream) @@ -796,46 +788,22 @@ bool SkDebugWStream::write(const void* buffer, size_t size) /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// -static bool mmap_filename(const char path[], void** addrPtr, size_t* sizePtr) { -#if SK_MMAP_SUPPORT - int fd = open(path, O_RDONLY); - if (fd < 0) { - return false; - } - off_t offset = lseek(fd, 0, SEEK_END); // find the file size - if (offset == -1) { - close(fd); - return false; +static SkData* mmap_filename(const char path[]) { + SkFILE* file = sk_fopen(path, kRead_SkFILE_Flag); + if (NULL == file) { + return NULL; } - (void)lseek(fd, 0, SEEK_SET); // restore file offset to beginning - - // to avoid a 64bit->32bit warning, I explicitly create a size_t size - size_t size = static_cast(offset); - void* addr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); - close(fd); - - if (MAP_FAILED == addr) { - return false; - } - - *addrPtr = addr; - *sizePtr = size; - return true; -#else - return false; -#endif + SkData* data = SkData::NewFromFILE(file); + sk_fclose(file); + return data; } SkStream* SkStream::NewFromFile(const char path[]) { - void* addr; - size_t size; - if (mmap_filename(path, &addr, &size)) { - SkAutoTUnref data(SkData::NewFromMMap(addr, size)); - if (data.get()) { - return SkNEW_ARGS(SkMemoryStream, (data.get())); - } + SkAutoTUnref data(mmap_filename(path)); + if (data.get()) { + return SkNEW_ARGS(SkMemoryStream, (data.get())); } // If we get here, then our attempt at using mmap failed, so try normal diff --git a/src/ports/SkOSFile_stdio.cpp b/src/ports/SkOSFile_stdio.cpp index 1d27c6b..40c8745 100644 --- a/src/ports/SkOSFile_stdio.cpp +++ b/src/ports/SkOSFile_stdio.cpp @@ -33,6 +33,8 @@ SkFILE* sk_fopen(const char path[], SkFILE_Flags flags) *p++ = 'b'; *p = 0; + //TODO: on Windows fopen is just ASCII or the current code page, + //convert to utf16 and use _wfopen SkFILE* f = (SkFILE*)::fopen(path, perm); #if 0 if (NULL == f) diff --git a/src/utils/win/SkHRESULT.cpp b/src/utils/win/SkHRESULT.cpp index 8b6b79f..32d9d4c 100644 --- a/src/utils/win/SkHRESULT.cpp +++ b/src/utils/win/SkHRESULT.cpp @@ -29,7 +29,7 @@ void SkTraceHR(const char* file, unsigned long line, if (NULL == errorText) { SkDEBUGF(("\n")); } else { - SkDEBUGF((errorText)); + SkDEBUGF(("%s", errorText)); LocalFree(errorText); errorText = NULL; }