blob: 6928f38ee2dbf5e08c606c25d49e34cd26760158 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
reed@google.combf790232013-12-13 19:45:58 +00007
reed@android.com49099b22010-09-09 16:07:53 +00008#include "SkMallocPixelRef.h"
9#include "SkBitmap.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000010#include "SkReadBuffer.h"
11#include "SkWriteBuffer.h"
reed@android.com49099b22010-09-09 16:07:53 +000012
halcanary@google.com1bed6872014-01-02 17:29:28 +000013// assumes ptr was allocated via sk_malloc
14static void sk_free_releaseproc(void* ptr, void*) {
15 sk_free(ptr);
16}
17
Mike Reed086a4272017-07-18 10:53:11 -040018static bool is_valid(const SkImageInfo& info) {
reede5ea5002014-09-03 11:54:58 -070019 if (info.width() < 0 || info.height() < 0 ||
20 (unsigned)info.colorType() > (unsigned)kLastEnum_SkColorType ||
21 (unsigned)info.alphaType() > (unsigned)kLastEnum_SkAlphaType)
reed@google.combf790232013-12-13 19:45:58 +000022 {
23 return false;
reed@android.com49099b22010-09-09 16:07:53 +000024 }
reed@google.combf790232013-12-13 19:45:58 +000025 return true;
26}
robertphillips@google.com0daa1ad2013-12-13 15:24:37 +000027
Mike Reed6b3155c2017-04-03 14:41:44 -040028sk_sp<SkPixelRef> SkMallocPixelRef::MakeDirect(const SkImageInfo& info,
29 void* addr,
Mike Reed086a4272017-07-18 10:53:11 -040030 size_t rowBytes) {
31 if (!is_valid(info)) {
halcanary96fcdcc2015-08-27 07:41:13 -070032 return nullptr;
reed@google.combf790232013-12-13 19:45:58 +000033 }
Mike Reed086a4272017-07-18 10:53:11 -040034 return sk_sp<SkPixelRef>(new SkMallocPixelRef(info, addr, rowBytes, nullptr, nullptr));
reed@google.combf790232013-12-13 19:45:58 +000035}
36
commit-bot@chromium.org2c4e75c2014-04-21 21:08:14 +000037
Mike Reed6b3155c2017-04-03 14:41:44 -040038 sk_sp<SkPixelRef> SkMallocPixelRef::MakeUsing(void*(*alloc)(size_t),
39 const SkImageInfo& info,
Mike Reed086a4272017-07-18 10:53:11 -040040 size_t requestedRowBytes) {
41 if (!is_valid(info)) {
halcanary96fcdcc2015-08-27 07:41:13 -070042 return nullptr;
reed@google.combf790232013-12-13 19:45:58 +000043 }
44
reed2ff257b2015-01-23 07:51:14 -080045 // only want to permit 31bits of rowBytes
46 int64_t minRB = (int64_t)info.minRowBytes64();
47 if (minRB < 0 || !sk_64_isS32(minRB)) {
halcanary96fcdcc2015-08-27 07:41:13 -070048 return nullptr; // allocation will be too large
reed@google.combf790232013-12-13 19:45:58 +000049 }
50 if (requestedRowBytes > 0 && (int32_t)requestedRowBytes < minRB) {
halcanary96fcdcc2015-08-27 07:41:13 -070051 return nullptr; // cannot meet requested rowbytes
reed@google.combf790232013-12-13 19:45:58 +000052 }
53
54 int32_t rowBytes;
55 if (requestedRowBytes) {
commit-bot@chromium.orga8c7f772014-01-24 21:46:29 +000056 rowBytes = SkToS32(requestedRowBytes);
reed@google.combf790232013-12-13 19:45:58 +000057 } else {
58 rowBytes = minRB;
59 }
60
reede5ea5002014-09-03 11:54:58 -070061 int64_t bigSize = (int64_t)info.height() * rowBytes;
reed@google.com57212f92013-12-30 14:40:38 +000062 if (!sk_64_isS32(bigSize)) {
halcanary96fcdcc2015-08-27 07:41:13 -070063 return nullptr;
reed@google.combf790232013-12-13 19:45:58 +000064 }
65
reed@google.com57212f92013-12-30 14:40:38 +000066 size_t size = sk_64_asS32(bigSize);
halcanary@google.com1bed6872014-01-02 17:29:28 +000067 SkASSERT(size >= info.getSafeSize(rowBytes));
mtkleincd495412015-11-05 09:46:23 -080068 void* addr = alloc(size);
halcanary96fcdcc2015-08-27 07:41:13 -070069 if (nullptr == addr) {
70 return nullptr;
reed@google.combf790232013-12-13 19:45:58 +000071 }
72
Mike Reed086a4272017-07-18 10:53:11 -040073 return sk_sp<SkPixelRef>(new SkMallocPixelRef(info, addr, rowBytes,
Mike Reed6b3155c2017-04-03 14:41:44 -040074 sk_free_releaseproc, nullptr));
halcanary@google.com1bed6872014-01-02 17:29:28 +000075}
76
Mike Reed6b3155c2017-04-03 14:41:44 -040077sk_sp<SkPixelRef> SkMallocPixelRef::MakeAllocate(const SkImageInfo& info,
Mike Reed086a4272017-07-18 10:53:11 -040078 size_t rowBytes) {
mtkleincd495412015-11-05 09:46:23 -080079 auto sk_malloc_nothrow = [](size_t size) { return sk_malloc_flags(size, 0); };
Mike Reed086a4272017-07-18 10:53:11 -040080 return MakeUsing(sk_malloc_nothrow, info, rowBytes);
mtkleincd495412015-11-05 09:46:23 -080081}
82
Mike Reed6b3155c2017-04-03 14:41:44 -040083sk_sp<SkPixelRef> SkMallocPixelRef::MakeZeroed(const SkImageInfo& info,
Mike Reed086a4272017-07-18 10:53:11 -040084 size_t rowBytes) {
85 return MakeUsing(sk_calloc, info, rowBytes);
halcanary@google.com1bed6872014-01-02 17:29:28 +000086}
87
88static void sk_data_releaseproc(void*, void* dataPtr) {
89 (static_cast<SkData*>(dataPtr))->unref();
90}
91
Mike Reed6b3155c2017-04-03 14:41:44 -040092sk_sp<SkPixelRef> SkMallocPixelRef::MakeWithProc(const SkImageInfo& info,
93 size_t rowBytes,
Mike Reed6b3155c2017-04-03 14:41:44 -040094 void* addr,
95 SkMallocPixelRef::ReleaseProc proc,
96 void* context) {
Mike Reed086a4272017-07-18 10:53:11 -040097 if (!is_valid(info)) {
Mike Reed6b3155c2017-04-03 14:41:44 -040098 if (proc) {
99 proc(addr, context);
100 }
101 return nullptr;
102 }
Mike Reed086a4272017-07-18 10:53:11 -0400103 return sk_sp<SkPixelRef>(new SkMallocPixelRef(info, addr, rowBytes, proc, context));
Mike Reed6b3155c2017-04-03 14:41:44 -0400104}
105
106sk_sp<SkPixelRef> SkMallocPixelRef::MakeWithData(const SkImageInfo& info,
halcanary@google.com1bed6872014-01-02 17:29:28 +0000107 size_t rowBytes,
Mike Reed6b3155c2017-04-03 14:41:44 -0400108 sk_sp<SkData> data) {
halcanary96fcdcc2015-08-27 07:41:13 -0700109 SkASSERT(data != nullptr);
Mike Reed086a4272017-07-18 10:53:11 -0400110 if (!is_valid(info)) {
halcanary96fcdcc2015-08-27 07:41:13 -0700111 return nullptr;
halcanary@google.com1bed6872014-01-02 17:29:28 +0000112 }
Mike Reeda00f3472017-04-11 15:50:02 -0400113 if ((rowBytes < info.minRowBytes()) || (data->size() < info.getSafeSize(rowBytes))) {
halcanary96fcdcc2015-08-27 07:41:13 -0700114 return nullptr;
halcanary@google.com1bed6872014-01-02 17:29:28 +0000115 }
Mike Reed6b3155c2017-04-03 14:41:44 -0400116 // must get this address before we call release
117 void* pixels = const_cast<void*>(data->data());
Mike Reed086a4272017-07-18 10:53:11 -0400118 SkPixelRef* pr = new SkMallocPixelRef(info, pixels, rowBytes,
Mike Reed6b3155c2017-04-03 14:41:44 -0400119 sk_data_releaseproc, data.release());
120 pr->setImmutable(); // since we were created with (immutable) data
121 return sk_sp<SkPixelRef>(pr);
reed@google.combf790232013-12-13 19:45:58 +0000122}
123
124///////////////////////////////////////////////////////////////////////////////
125
halcanary@google.com1bed6872014-01-02 17:29:28 +0000126SkMallocPixelRef::SkMallocPixelRef(const SkImageInfo& info, void* storage,
Mike Reed086a4272017-07-18 10:53:11 -0400127 size_t rowBytes,
halcanary@google.com1bed6872014-01-02 17:29:28 +0000128 SkMallocPixelRef::ReleaseProc proc,
129 void* context)
Mike Reed086a4272017-07-18 10:53:11 -0400130 : INHERITED(info.width(), info.height(), storage, rowBytes)
halcanary@google.com1bed6872014-01-02 17:29:28 +0000131 , fReleaseProc(proc)
132 , fReleaseProcContext(context)
Mike Reeda00f3472017-04-11 15:50:02 -0400133{}
reed@android.com49099b22010-09-09 16:07:53 +0000134
halcanary@google.com1bed6872014-01-02 17:29:28 +0000135
reed@android.com49099b22010-09-09 16:07:53 +0000136SkMallocPixelRef::~SkMallocPixelRef() {
halcanary96fcdcc2015-08-27 07:41:13 -0700137 if (fReleaseProc != nullptr) {
Mike Reeda00f3472017-04-11 15:50:02 -0400138 fReleaseProc(this->pixels(), fReleaseProcContext);
djsollen@google.comc84b8332012-07-27 13:41:44 +0000139 }
reed@android.com49099b22010-09-09 16:07:53 +0000140}