blob: eadba5c0e634166b5a7f47d41fcf8d4589790c73 [file] [log] [blame]
/*
* 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,
Ashmem,
};
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);
Bitmap(void* address, int fd, 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* peekAtPixelRef() const;
SkPixelRef* refPixelRef();
bool valid() const { return mPixelStorageType != PixelStorageType::Invalid; }
void reconfigure(const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable);
void reconfigure(const SkImageInfo& info);
void setAlphaType(SkAlphaType alphaType);
void getSkBitmap(SkBitmap* outBitmap);
void detachFromJava();
void freePixels();
bool hasHardwareMipMap();
void setHasHardwareMipMap(bool hasMipMap);
int getAshmemFd() const;
private:
friend class WrappedPixelRef;
~Bitmap();
void doFreePixels();
void onStrongRefDestroyed();
void pinPixelsLocked();
void unpinPixelsLocked();
JNIEnv* jniEnv();
bool shouldDisposeSelfLocked();
void assertValid() const;
SkPixelRef* refPixelRefLocked();
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 {
void* address;
int fd;
size_t size;
} ashmem;
struct {
JavaVM* jvm;
jweak jweakRef;
jbyteArray jstrongRef;
} java;
} mPixelStorage;
};
} // namespace android
#endif /* BITMAP_H_ */