13b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy/* 23b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * Copyright (C) 2013 The Android Open Source Project 33b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * 43b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * Licensed under the Apache License, Version 2.0 (the "License"); 53b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * you may not use this file except in compliance with the License. 63b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * You may obtain a copy of the License at 73b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * 83b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * http://www.apache.org/licenses/LICENSE-2.0 93b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * 103b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * Unless required by applicable law or agreed to in writing, software 113b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * distributed under the License is distributed on an "AS IS" BASIS, 123b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * See the License for the specific language governing permissions and 143b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * limitations under the License. 153b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy */ 163b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 173b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#define LOG_TAG "AssetAtlasService" 183b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 193b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#include "jni.h" 203b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#include "JNIHelp.h" 215c3d927e17e98e8fd4a9f3c86f7f4def0bcfa816Florin Malita#include "android/graphics/GraphicsJNI.h" 223b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 233b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#include <android_view_GraphicBuffer.h> 2487eac99a21772ae56018cb81db6966557b459554Ruben Brunk#include <cutils/log.h> 253b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 263b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#include <GLES2/gl2.h> 273b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#include <GLES2/gl2ext.h> 283b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 293b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#include <EGL/egl.h> 303b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#include <EGL/eglext.h> 313b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 323b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#include <SkCanvas.h> 333b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#include <SkBitmap.h> 343b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 353b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guynamespace android { 363b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 373b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy// ---------------------------------------------------------------------------- 383b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy// Defines 393b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy// ---------------------------------------------------------------------------- 403b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 413b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy// Defines how long to wait for the GPU when uploading the atlas 423b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy// This timeout is defined in nanoseconds (see EGL_KHR_fence_sync extension) 433b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#define FENCE_TIMEOUT 2000000000 443b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 453b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy// ---------------------------------------------------------------------------- 463b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy// JNI Helpers 473b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy// ---------------------------------------------------------------------------- 483b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 493b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guystatic struct { 505c3d927e17e98e8fd4a9f3c86f7f4def0bcfa816Florin Malita jmethodID setNativeBitmap; 513b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy} gCanvasClassInfo; 523b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 53c677675e9c465dc1de21ecf2e0421835c7eb55b4Florin Malita#define INVOKEV(object, method, ...) \ 54c677675e9c465dc1de21ecf2e0421835c7eb55b4Florin Malita env->CallVoidMethod(object, method, __VA_ARGS__) 553b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 563b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy// ---------------------------------------------------------------------------- 573b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy// Canvas management 583b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy// ---------------------------------------------------------------------------- 593b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 6017ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhatstatic jlong com_android_server_AssetAtlasService_acquireCanvas(JNIEnv* env, jobject, 613b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy jobject canvas, jint width, jint height) { 623b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 633b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy SkBitmap* bitmap = new SkBitmap; 64b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed bitmap->allocN32Pixels(width, height); 653b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy bitmap->eraseColor(0); 665c3d927e17e98e8fd4a9f3c86f7f4def0bcfa816Florin Malita INVOKEV(canvas, gCanvasClassInfo.setNativeBitmap, reinterpret_cast<jlong>(bitmap)); 673b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 6817ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat return reinterpret_cast<jlong>(bitmap); 693b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy} 703b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 713b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guystatic void com_android_server_AssetAtlasService_releaseCanvas(JNIEnv* env, jobject, 7217ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat jobject canvas, jlong bitmapHandle) { 733b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 7417ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle); 755c3d927e17e98e8fd4a9f3c86f7f4def0bcfa816Florin Malita INVOKEV(canvas, gCanvasClassInfo.setNativeBitmap, (jlong)0); 763b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 773b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy delete bitmap; 783b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy} 793b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 803b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#define CLEANUP_GL_AND_RETURN(result) \ 813b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy if (fence != EGL_NO_SYNC_KHR) eglDestroySyncKHR(display, fence); \ 823b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy if (image) eglDestroyImageKHR(display, image); \ 833b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy if (texture) glDeleteTextures(1, &texture); \ 843b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy if (surface != EGL_NO_SURFACE) eglDestroySurface(display, surface); \ 853b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy if (context != EGL_NO_CONTEXT) eglDestroyContext(display, context); \ 863b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); \ 873b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy eglReleaseThread(); \ 883b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy eglTerminate(display); \ 893b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy return result; 903b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 913b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guystatic jboolean com_android_server_AssetAtlasService_upload(JNIEnv* env, jobject, 9217ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat jobject graphicBuffer, jlong bitmapHandle) { 933b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 9417ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle); 953b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy // The goal of this method is to copy the bitmap into the GraphicBuffer 963b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy // using the GPU to swizzle the texture content 973b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy sp<GraphicBuffer> buffer(graphicBufferForJavaObject(env, graphicBuffer)); 983b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 993b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy if (buffer != NULL) { 1003b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 10117ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat if (display == EGL_NO_DISPLAY) return JNI_FALSE; 1023b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 1033b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy EGLint major; 1043b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy EGLint minor; 1053b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy if (!eglInitialize(display, &major, &minor)) { 1063b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy ALOGW("Could not initialize EGL"); 10717ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat return JNI_FALSE; 1083b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy } 1093b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 1103b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy // We're going to use a 1x1 pbuffer surface later on 1113b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy // The configuration doesn't really matter for what we're trying to do 1123b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy EGLint configAttrs[] = { 1133b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 1143b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy EGL_RED_SIZE, 8, 1153b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy EGL_GREEN_SIZE, 8, 1163b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy EGL_BLUE_SIZE, 8, 1173b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy EGL_ALPHA_SIZE, 0, 1183b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy EGL_DEPTH_SIZE, 0, 1193b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy EGL_STENCIL_SIZE, 0, 1203b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy EGL_NONE 1213b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy }; 1223b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy EGLConfig configs[1]; 1233b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy EGLint configCount; 1243b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy if (!eglChooseConfig(display, configAttrs, configs, 1, &configCount)) { 1253b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy ALOGW("Could not select EGL configuration"); 1263b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy eglReleaseThread(); 1273b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy eglTerminate(display); 12817ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat return JNI_FALSE; 1293b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy } 1303b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy if (configCount <= 0) { 1313b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy ALOGW("Could not find EGL configuration"); 1323b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy eglReleaseThread(); 1333b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy eglTerminate(display); 13417ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat return JNI_FALSE; 1353b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy } 1363b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 1373b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy // These objects are initialized below but the default "null" 1383b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy // values are used to cleanup properly at any point in the 1393b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy // initialization sequence 1403b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy GLuint texture = 0; 1413b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy EGLImageKHR image = EGL_NO_IMAGE_KHR; 1423b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy EGLSurface surface = EGL_NO_SURFACE; 1433b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy EGLSyncKHR fence = EGL_NO_SYNC_KHR; 1443b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 1453b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy EGLint attrs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; 1463b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy EGLContext context = eglCreateContext(display, configs[0], EGL_NO_CONTEXT, attrs); 1473b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy if (context == EGL_NO_CONTEXT) { 1483b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy ALOGW("Could not create EGL context"); 14917ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat CLEANUP_GL_AND_RETURN(JNI_FALSE); 1503b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy } 1513b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 1523b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy // Create the 1x1 pbuffer 1533b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy EGLint surfaceAttrs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE }; 1543b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy surface = eglCreatePbufferSurface(display, configs[0], surfaceAttrs); 1553b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy if (surface == EGL_NO_SURFACE) { 1563b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy ALOGW("Could not create EGL surface"); 15717ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat CLEANUP_GL_AND_RETURN(JNI_FALSE); 1583b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy } 1593b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 1603b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy if (!eglMakeCurrent(display, surface, surface, context)) { 1613b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy ALOGW("Could not change current EGL context"); 16217ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat CLEANUP_GL_AND_RETURN(JNI_FALSE); 1633b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy } 1643b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 1653b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy // We use an EGLImage to access the content of the GraphicBuffer 1663b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy // The EGL image is later bound to a 2D texture 1673b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy EGLClientBuffer clientBuffer = (EGLClientBuffer) buffer->getNativeBuffer(); 1683b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy EGLint imageAttrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE }; 1693b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy image = eglCreateImageKHR(display, EGL_NO_CONTEXT, 1703b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy EGL_NATIVE_BUFFER_ANDROID, clientBuffer, imageAttrs); 1713b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy if (image == EGL_NO_IMAGE_KHR) { 1723b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy ALOGW("Could not create EGL image"); 17317ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat CLEANUP_GL_AND_RETURN(JNI_FALSE); 1743b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy } 1753b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 1763b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy glGenTextures(1, &texture); 1773b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy glBindTexture(GL_TEXTURE_2D, texture); 1783b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); 1793b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy if (glGetError() != GL_NO_ERROR) { 1803b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy ALOGW("Could not create/bind texture"); 18117ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat CLEANUP_GL_AND_RETURN(JNI_FALSE); 1823b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy } 1833b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 1843b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy // Upload the content of the bitmap in the GraphicBuffer 1853b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel()); 1863b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap->width(), bitmap->height(), 1873b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy GL_RGBA, GL_UNSIGNED_BYTE, bitmap->getPixels()); 1883b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy if (glGetError() != GL_NO_ERROR) { 1893b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy ALOGW("Could not upload to texture"); 19017ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat CLEANUP_GL_AND_RETURN(JNI_FALSE); 1913b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy } 1923b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 1933b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy // The fence is used to wait for the texture upload to finish 1943b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy // properly. We cannot rely on glFlush() and glFinish() as 1953b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy // some drivers completely ignore these API calls 1963b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy fence = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, NULL); 1973b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy if (fence == EGL_NO_SYNC_KHR) { 1983b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy ALOGW("Could not create sync fence %#x", eglGetError()); 19917ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat CLEANUP_GL_AND_RETURN(JNI_FALSE); 2003b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy } 2013b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 2023b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy // The flag EGL_SYNC_FLUSH_COMMANDS_BIT_KHR will trigger a 2033b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy // pipeline flush (similar to what a glFlush() would do.) 2043b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy EGLint waitStatus = eglClientWaitSyncKHR(display, fence, 2053b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, FENCE_TIMEOUT); 2063b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy if (waitStatus != EGL_CONDITION_SATISFIED_KHR) { 2073b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy ALOGW("Failed to wait for the fence %#x", eglGetError()); 20817ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat CLEANUP_GL_AND_RETURN(JNI_FALSE); 2093b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy } 2103b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 21117ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat CLEANUP_GL_AND_RETURN(JNI_TRUE); 2123b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy } 2133b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 21417ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat return JNI_FALSE; 2153b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy} 2163b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 2173b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy// ---------------------------------------------------------------------------- 2183b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy// JNI Glue 2193b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy// ---------------------------------------------------------------------------- 2203b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 2213b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#define FIND_CLASS(var, className) \ 2223b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy var = env->FindClass(className); \ 2233b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy LOG_FATAL_IF(! var, "Unable to find class " className); 2243b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 225c677675e9c465dc1de21ecf2e0421835c7eb55b4Florin Malita#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \ 226c677675e9c465dc1de21ecf2e0421835c7eb55b4Florin Malita var = env->GetMethodID(clazz, methodName, methodDescriptor); \ 227c677675e9c465dc1de21ecf2e0421835c7eb55b4Florin Malita LOG_FATAL_IF(!var, "Unable to find method " methodName); 2283b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 2293b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guyconst char* const kClassPathName = "com/android/server/AssetAtlasService"; 2303b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 2313b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guystatic JNINativeMethod gMethods[] = { 23217ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat { "nAcquireAtlasCanvas", "(Landroid/graphics/Canvas;II)J", 2333b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy (void*) com_android_server_AssetAtlasService_acquireCanvas }, 23417ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat { "nReleaseAtlasCanvas", "(Landroid/graphics/Canvas;J)V", 2353b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy (void*) com_android_server_AssetAtlasService_releaseCanvas }, 23617ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat { "nUploadAtlas", "(Landroid/view/GraphicBuffer;J)Z", 2373b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy (void*) com_android_server_AssetAtlasService_upload }, 2383b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy}; 2393b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 2403b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guyint register_android_server_AssetAtlasService(JNIEnv* env) { 2413b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy jclass clazz; 2423b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 2433b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy FIND_CLASS(clazz, "android/graphics/Canvas"); 2445c3d927e17e98e8fd4a9f3c86f7f4def0bcfa816Florin Malita GET_METHOD_ID(gCanvasClassInfo.setNativeBitmap, clazz, "setNativeBitmap", "(J)V"); 2453b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 2463b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy return jniRegisterNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)); 2473b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy} 2483b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 2493b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy}; 250