blob: fadf8a47f7146f90f0a5ce6477264b0619fc7a9c [file] [log] [blame]
Craig Donner1a4d07d2017-01-09 13:01:22 -08001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "HardwareBuffer"
18
19#include "jni.h"
20#include "JNIHelp.h"
21
22#include "android_os_Parcel.h"
23#include "android/graphics/GraphicsJNI.h"
24
25#include <android/hardware_buffer.h>
26#include <android_runtime/android_hardware_HardwareBuffer.h>
27#include <android_runtime/AndroidRuntime.h>
28#include <android_runtime/Log.h>
29
30#include <binder/Parcel.h>
31#include <gui/IGraphicBufferAlloc.h>
32#include <gui/ISurfaceComposer.h>
33#include <ui/GraphicBuffer.h>
34
35#include <private/gui/ComposerService.h>
36
37#include "core_jni_helpers.h"
38
39using namespace android;
40
41// ----------------------------------------------------------------------------
42// Defines
43// ----------------------------------------------------------------------------
44
45// Debug
46static const bool kDebugGraphicBuffer = false;
47
48// ----------------------------------------------------------------------------
49// Types
50// ----------------------------------------------------------------------------
51
52static struct {
53 jclass clazz;
54 jfieldID mNativeObject;
55 jmethodID ctor;
56} gHardwareBufferClassInfo;
57
58class GraphicBufferWrapper {
59public:
60 explicit GraphicBufferWrapper(const sp<GraphicBuffer>& buffer)
61 : buffer(buffer) {}
62
63 sp<GraphicBuffer> buffer;
64};
65
66
67// ----------------------------------------------------------------------------
68// Helper functions
69// ----------------------------------------------------------------------------
70
71static inline bool containsBits(uint64_t mask, uint64_t bitsToCheck) {
72 return (mask & bitsToCheck) == bitsToCheck;
73}
74
75// ----------------------------------------------------------------------------
76// HardwareBuffer lifecycle
77// ----------------------------------------------------------------------------
78
79static jlong android_hardware_HardwareBuffer_create(JNIEnv* env, jobject clazz,
80 jint width, jint height, jint format, jint layers, jlong usage) {
81
82 sp<ISurfaceComposer> composer(ComposerService::getComposerService());
83 sp<IGraphicBufferAlloc> alloc(composer->createGraphicBufferAlloc());
84 if (alloc == NULL) {
85 if (kDebugGraphicBuffer) {
86 ALOGW("createGraphicBufferAlloc() failed in HardwareBuffer.create()");
87 }
88 return NULL;
89 }
90
91 // TODO: update createGraphicBuffer to take two 64-bit values.
92 int pixelFormat = android_hardware_HardwareBuffer_convertToPixelFormat(format);
93 if (pixelFormat == 0) {
94 if (kDebugGraphicBuffer) {
95 ALOGW("createGraphicBufferAlloc() invalid pixel format in HardwareBuffer.create()");
96 }
97 return NULL;
98 }
99 uint32_t grallocUsage = android_hardware_HardwareBuffer_convertToGrallocUsageBits(usage, 0);
100 status_t error;
101 sp<GraphicBuffer> buffer(alloc->createGraphicBuffer(width, height, pixelFormat,
102 layers, grallocUsage, &error));
103 if (buffer == NULL) {
104 if (kDebugGraphicBuffer) {
105 ALOGW("createGraphicBuffer() failed in HardwareBuffer.create()");
106 }
107 return NULL;
108 }
109
110 GraphicBufferWrapper* wrapper = new GraphicBufferWrapper(buffer);
111 return reinterpret_cast<jlong>(wrapper);
112}
113
114static void destroyWrapper(GraphicBufferWrapper* wrapper) {
115 delete wrapper;
116}
117
118static jlong android_hardware_HardwareBuffer_getNativeFinalizer(JNIEnv* env,
119 jobject clazz) {
120 return static_cast<jlong>(reinterpret_cast<uintptr_t>(&destroyWrapper));
121}
122
123//----------------------------------------------------------------------------
124// Accessors
125// ----------------------------------------------------------------------------
126
127static inline GraphicBuffer* GraphicBufferWrapper_to_GraphicBuffer(
128 jlong nativeObject) {
129 return reinterpret_cast<GraphicBufferWrapper*>(nativeObject)->buffer.get();
130}
131
132static jint android_hardware_HardwareBuffer_getWidth(JNIEnv* env, jobject clazz,
133 jlong nativeObject) {
134 GraphicBuffer* buffer = GraphicBufferWrapper_to_GraphicBuffer(nativeObject);
135 return static_cast<jint>(buffer->getWidth());
136}
137
138static jint android_hardware_HardwareBuffer_getHeight(JNIEnv* env,
139 jobject clazz, jlong nativeObject) {
140 GraphicBuffer* buffer = GraphicBufferWrapper_to_GraphicBuffer(nativeObject);
141 return static_cast<jint>(buffer->getHeight());
142}
143
144static jint android_hardware_HardwareBuffer_getFormat(JNIEnv* env,
145 jobject clazz, jlong nativeObject) {
146 GraphicBuffer* buffer = GraphicBufferWrapper_to_GraphicBuffer(nativeObject);
147 return static_cast<jint>(android_hardware_HardwareBuffer_convertFromPixelFormat(
148 buffer->getPixelFormat()));
149}
150
151static jint android_hardware_HardwareBuffer_getLayers(JNIEnv* env,
152 jobject clazz, jlong nativeObject) {
153 GraphicBuffer* buffer = GraphicBufferWrapper_to_GraphicBuffer(nativeObject);
154 return static_cast<jint>(buffer->getLayerCount());
155}
156
157static jlong android_hardware_HardwareBuffer_getUsage(JNIEnv* env,
158 jobject clazz, jlong nativeObject) {
159 GraphicBuffer* buffer = GraphicBufferWrapper_to_GraphicBuffer(nativeObject);
160 return android_hardware_HardwareBuffer_convertFromGrallocUsageBits(
161 buffer->getUsage());
162}
163
164// ----------------------------------------------------------------------------
165// Serialization
166// ----------------------------------------------------------------------------
167
168static void android_hardware_HardwareBuffer_write(JNIEnv* env, jobject clazz,
169 jlong nativeObject, jobject dest) {
170 GraphicBuffer* buffer = GraphicBufferWrapper_to_GraphicBuffer(nativeObject);
171 Parcel* parcel = parcelForJavaObject(env, dest);
172 if (parcel) {
173 parcel->write(*buffer);
174 }
175}
176
177static jlong android_hardware_HardwareBuffer_read(JNIEnv* env, jobject clazz,
178 jobject in) {
179 Parcel* parcel = parcelForJavaObject(env, in);
180 if (parcel) {
181 sp<GraphicBuffer> buffer = new GraphicBuffer();
182 parcel->read(*buffer);
183 return reinterpret_cast<jlong>(new GraphicBufferWrapper(buffer));
184 }
185
186 return NULL;
187}
188
189// ----------------------------------------------------------------------------
190// Public functions
191// ----------------------------------------------------------------------------
192
193namespace android {
194
195AHardwareBuffer* android_hardware_HardwareBuffer_getNativeHardwareBuffer(
196 JNIEnv* env, jobject hardwareBufferObj) {
197 if (env->IsInstanceOf(hardwareBufferObj, gHardwareBufferClassInfo.clazz)) {
198 GraphicBuffer* buffer = GraphicBufferWrapper_to_GraphicBuffer(
199 env->GetLongField(hardwareBufferObj, gHardwareBufferClassInfo.mNativeObject));
200 return reinterpret_cast<AHardwareBuffer*>(buffer);
201 } else {
202 return nullptr;
203 }
204}
205
206jobject android_hardware_HardwareBuffer_createFromAHardwareBuffer(
207 JNIEnv* env, AHardwareBuffer* hardwareBuffer) {
208 GraphicBuffer* buffer = reinterpret_cast<GraphicBuffer*>(hardwareBuffer);
209 GraphicBufferWrapper* wrapper = new GraphicBufferWrapper(buffer);
210 jobject hardwareBufferObj = env->NewObject(gHardwareBufferClassInfo.clazz,
211 gHardwareBufferClassInfo.ctor, reinterpret_cast<jlong>(wrapper));
212 if (hardwareBufferObj == NULL) {
213 delete wrapper;
214 if (env->ExceptionCheck()) {
215 ALOGE("Could not create instance of HardwareBuffer from AHardwareBuffer.");
216 LOGE_EX(env);
217 env->ExceptionClear();
218 }
219 return nullptr;
220 }
221 return hardwareBufferObj;
222}
223
224uint32_t android_hardware_HardwareBuffer_convertFromPixelFormat(uint32_t format) {
225 switch (format) {
Craig Donner2be5b9f2017-01-24 18:14:44 -0800226 case HAL_PIXEL_FORMAT_RGBA_8888:
Craig Donner1a4d07d2017-01-09 13:01:22 -0800227 return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
Craig Donner2be5b9f2017-01-24 18:14:44 -0800228 case HAL_PIXEL_FORMAT_RGBX_8888:
Craig Donner1a4d07d2017-01-09 13:01:22 -0800229 return AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM;
Craig Donner2be5b9f2017-01-24 18:14:44 -0800230 case HAL_PIXEL_FORMAT_RGB_565:
Craig Donner1a4d07d2017-01-09 13:01:22 -0800231 return AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
Craig Donner2be5b9f2017-01-24 18:14:44 -0800232 case HAL_PIXEL_FORMAT_RGB_888:
Craig Donner1a4d07d2017-01-09 13:01:22 -0800233 return AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM;
Craig Donner2be5b9f2017-01-24 18:14:44 -0800234 case HAL_PIXEL_FORMAT_RGBA_FP16:
Craig Donner1a4d07d2017-01-09 13:01:22 -0800235 return AHARDWAREBUFFER_FORMAT_R16G16B16A16_SFLOAT;
Craig Donner2be5b9f2017-01-24 18:14:44 -0800236 case HAL_PIXEL_FORMAT_BLOB:
237 return AHARDWAREBUFFER_FORMAT_BLOB;
Craig Donner1a4d07d2017-01-09 13:01:22 -0800238 default:
239 ALOGE("Unknown pixel format %u", format);
240 return 0;
241 }
242}
243
244uint32_t android_hardware_HardwareBuffer_convertToPixelFormat(uint32_t format) {
245 switch (format) {
246 case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
Craig Donner2be5b9f2017-01-24 18:14:44 -0800247 return HAL_PIXEL_FORMAT_RGBA_8888;
Craig Donner1a4d07d2017-01-09 13:01:22 -0800248 case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
Craig Donner2be5b9f2017-01-24 18:14:44 -0800249 return HAL_PIXEL_FORMAT_RGBX_8888;
Craig Donner1a4d07d2017-01-09 13:01:22 -0800250 case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
Craig Donner2be5b9f2017-01-24 18:14:44 -0800251 return HAL_PIXEL_FORMAT_RGB_565;
Craig Donner1a4d07d2017-01-09 13:01:22 -0800252 case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
Craig Donner2be5b9f2017-01-24 18:14:44 -0800253 return HAL_PIXEL_FORMAT_RGB_888;
Craig Donner1a4d07d2017-01-09 13:01:22 -0800254 case AHARDWAREBUFFER_FORMAT_R16G16B16A16_SFLOAT:
Craig Donner2be5b9f2017-01-24 18:14:44 -0800255 return HAL_PIXEL_FORMAT_RGBA_FP16;
256 case AHARDWAREBUFFER_FORMAT_BLOB:
257 return HAL_PIXEL_FORMAT_BLOB;
Craig Donner1a4d07d2017-01-09 13:01:22 -0800258 default:
259 ALOGE("Unknown AHardwareBuffer format %u", format);
260 return 0;
261 }
262}
263
264uint32_t android_hardware_HardwareBuffer_convertToGrallocUsageBits(uint64_t usage0,
265 uint64_t usage1) {
266 uint32_t bits = 0;
267 if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_CPU_READ))
268 bits |= GRALLOC_USAGE_SW_READ_RARELY;
269 if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_CPU_READ_OFTEN))
270 bits |= GRALLOC_USAGE_SW_READ_OFTEN;
271 if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_CPU_WRITE))
272 bits |= GRALLOC_USAGE_SW_WRITE_RARELY;
273 if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_CPU_WRITE_OFTEN))
274 bits |= GRALLOC_USAGE_SW_WRITE_OFTEN;
275 if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_GPU_SAMPLED_IMAGE))
276 bits |= GRALLOC_USAGE_HW_TEXTURE;
277 if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_GPU_COLOR_OUTPUT))
278 bits |= GRALLOC_USAGE_HW_RENDER;
279 // Not sure what this should be.
280 if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_GPU_CUBEMAP)) bits |= 0;
281 //if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_GPU_DATA_BUFFER) bits |= 0;
282 if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_VIDEO_ENCODE))
283 bits |= GRALLOC_USAGE_HW_VIDEO_ENCODER;
284 if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_PROTECTED_CONTENT))
285 bits |= GRALLOC_USAGE_PROTECTED;
286
287 (void)usage1;
288
289 return bits;
290}
291
292uint64_t android_hardware_HardwareBuffer_convertFromGrallocUsageBits(uint64_t usage0) {
293 uint64_t bits = 0;
294 if (containsBits(usage0, GRALLOC_USAGE_SW_READ_RARELY))
295 bits |= AHARDWAREBUFFER_USAGE0_CPU_READ;
296 if (containsBits(usage0, GRALLOC_USAGE_SW_READ_OFTEN))
297 bits |= AHARDWAREBUFFER_USAGE0_CPU_READ_OFTEN;
298 if (containsBits(usage0, GRALLOC_USAGE_SW_WRITE_RARELY))
299 bits |= AHARDWAREBUFFER_USAGE0_CPU_WRITE;
300 if (containsBits(usage0, GRALLOC_USAGE_SW_WRITE_OFTEN))
301 bits |= AHARDWAREBUFFER_USAGE0_CPU_WRITE_OFTEN;
302 if (containsBits(usage0, GRALLOC_USAGE_HW_TEXTURE))
303 bits |= AHARDWAREBUFFER_USAGE0_GPU_SAMPLED_IMAGE;
304 if (containsBits(usage0, GRALLOC_USAGE_HW_RENDER))
305 bits |= AHARDWAREBUFFER_USAGE0_GPU_COLOR_OUTPUT;
306 if (containsBits(usage0, GRALLOC_USAGE_HW_VIDEO_ENCODER))
307 bits |= AHARDWAREBUFFER_USAGE0_VIDEO_ENCODE;
308 if (containsBits(usage0, GRALLOC_USAGE_PROTECTED))
309 bits |= AHARDWAREBUFFER_USAGE0_PROTECTED_CONTENT;
310
311 return bits;
312}
313
314} // namespace android
315
316// ----------------------------------------------------------------------------
317// JNI Glue
318// ----------------------------------------------------------------------------
319
320const char* const kClassPathName = "android/hardware/HardwareBuffer";
321
322static const JNINativeMethod gMethods[] = {
323 { "nCreateHardwareBuffer", "(IIIIJ)J", (void*) android_hardware_HardwareBuffer_create },
324 { "nGetNativeFinalizer", "()J", (void*) android_hardware_HardwareBuffer_getNativeFinalizer },
325 { "nWriteHardwareBufferToParcel", "(JLandroid/os/Parcel;)V",
326 (void*) android_hardware_HardwareBuffer_write },
327 { "nReadHardwareBufferFromParcel", "(Landroid/os/Parcel;)J",
328 (void*) android_hardware_HardwareBuffer_read },
329
330 // --------------- @FastNative ----------------------
331 { "nGetWidth", "(J)I", (void*) android_hardware_HardwareBuffer_getWidth },
332 { "nGetHeight", "(J)I", (void*) android_hardware_HardwareBuffer_getHeight },
333 { "nGetFormat", "(J)I", (void*) android_hardware_HardwareBuffer_getFormat },
334 { "nGetLayers", "(J)I", (void*) android_hardware_HardwareBuffer_getLayers },
335 { "nGetUsage", "(J)J", (void*) android_hardware_HardwareBuffer_getUsage },
336};
337
338int register_android_hardware_HardwareBuffer(JNIEnv* env) {
339 int err = RegisterMethodsOrDie(env, kClassPathName, gMethods,
340 NELEM(gMethods));
341
342 jclass clazz = FindClassOrDie(env, "android/hardware/HardwareBuffer");
343 gHardwareBufferClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
344 gHardwareBufferClassInfo.mNativeObject = GetFieldIDOrDie(env,
345 gHardwareBufferClassInfo.clazz, "mNativeObject", "J");
346 gHardwareBufferClassInfo.ctor = GetMethodIDOrDie(env,
347 gHardwareBufferClassInfo.clazz, "<init>", "(J)V");
348
349 return err;
350}