1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef BITMAP_H_
#define BITMAP_H_
#include <jni.h>
#include <SkBitmap.h>
#include <SkColorTable.h>
#include <SkImageInfo.h>
#include <utils/Mutex.h>
#include <memory>
namespace android {
enum class PixelStorageType {
Invalid,
External,
Java,
};
class WrappedPixelRef;
typedef void (*FreeFunc)(void* addr, void* context);
/**
* Glue-thingy that deals with managing the interaction between the Java
* Bitmap object & SkBitmap along with trying to map a notion of strong/weak
* lifecycles onto SkPixelRef which only has strong counts to avoid requiring
* two GC passes to free the byte[] that backs a Bitmap.
*
* Since not all Bitmaps are byte[]-backed it also supports external allocations,
* which currently is used by screenshots to wrap a gralloc buffer.
*/
class Bitmap {
public:
Bitmap(JNIEnv* env, jbyteArray storageObj, void* address,
const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable);
Bitmap(void* address, void* context, FreeFunc freeFunc,
const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable);
const SkImageInfo& info() const;
// Returns nullptr if it is not backed by a jbyteArray
jbyteArray javaByteArray() const {
return mPixelStorageType == PixelStorageType::Java
? mPixelStorage.java.jstrongRef : nullptr;
}
int width() const { return info().width(); }
int height() const { return info().height(); }
size_t rowBytes() const;
SkPixelRef* pixelRef() const;
bool valid() const { return mPixelStorageType != PixelStorageType::Invalid; }
void reconfigure(const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable);
void reconfigure(const SkImageInfo& info);
void getSkBitmap(SkBitmap* outBitmap);
void detachFromJava();
void freePixels();
bool hasHardwareMipMap();
void setHasHardwareMipMap(bool hasMipMap);
private:
friend class WrappedPixelRef;
~Bitmap();
void doFreePixels();
void onStrongRefDestroyed();
void pinPixelsLocked();
void unpinPixelsLocked();
JNIEnv* jniEnv();
bool shouldDisposeSelfLocked();
void assertValid() const;
android::Mutex mLock;
int mPinnedRefCount = 0;
std::unique_ptr<WrappedPixelRef> mPixelRef;
PixelStorageType mPixelStorageType;
bool mAttachedToJava = true;
union {
struct {
void* address;
void* context;
FreeFunc freeFunc;
} external;
struct {
JavaVM* jvm;
jweak jweakRef;
jbyteArray jstrongRef;
} java;
} mPixelStorage;
};
} // namespace android
#endif /* BITMAP_H_ */
|