1 /*
   2  * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include <JAbstractSurface.h>
  27 
  28 #include <PiscesUtil.h>
  29 #include <PiscesSysutils.h>
  30 #include <JNIUtil.h>
  31 #include <com_sun_pisces_JavaSurface.h>
  32 
  33 #define SURFACE_NATIVE_PTR 0
  34 #define SURFACE_DATA_INT 1
  35 #define SURFACE_LAST SURFACE_DATA_INT
  36 
  37 static jfieldID fieldIds[SURFACE_LAST + 1];
  38 static jboolean fieldIdsInitialized = JNI_FALSE;
  39 
  40 static jboolean initializeSurfaceFieldIds(JNIEnv *env, jobject objectHandle);
  41 
  42 static void surface_acquire(AbstractSurface* surface, JNIEnv* env, jobject surfaceHandle);
  43 static void surface_release(AbstractSurface* surface, JNIEnv* env,  jobject surfaceHandle);
  44 static void surface_cleanup(AbstractSurface* surface);
  45 
  46 typedef struct _JavaSurface {
  47     AbstractSurface super;
  48     jfieldID javaArrayFieldID;
  49     jobject dataHandle;
  50 } JavaSurface;
  51 
  52 /*
  53  * Class:     com_sun_pisces_JavaSurface
  54  * Method:    initialize
  55  * Signature: (III)V
  56  */
  57 JNIEXPORT void JNICALL
  58 Java_com_sun_pisces_JavaSurface_initialize
  59   (JNIEnv *env, jobject objectHandle, jint dataType, jint width, jint height)
  60 {
  61     if (surface_initialize(env, objectHandle)
  62             && initializeSurfaceFieldIds(env, objectHandle))
  63     {
  64         // NOTE: when is this freed?
  65         JavaSurface* jSurface = my_malloc(JavaSurface, 1);
  66         AbstractSurface* surface = &jSurface->super;
  67         if (surface != NULL) {
  68             surface->super.width = width;
  69             surface->super.height = height;
  70             surface->super.offset = 0;
  71             surface->super.scanlineStride = width;
  72             surface->super.pixelStride = 1;
  73             surface->super.imageType = dataType;
  74 
  75             surface->acquire = surface_acquire;
  76             surface->release = surface_release;
  77             surface->cleanup = surface_cleanup;
  78 
  79             switch(surface->super.imageType){
  80                 case TYPE_INT_ARGB_PRE:
  81                     jSurface->javaArrayFieldID = fieldIds[SURFACE_DATA_INT];
  82                     break;
  83                 default: //errorneous - should never happen
  84                     jSurface->javaArrayFieldID = NULL;
  85             }
  86 
  87             (*env)->SetLongField(env, objectHandle, fieldIds[SURFACE_NATIVE_PTR],
  88                                 PointerToJLong(jSurface));
  89             //    JNI_registerCleanup(objectHandle, disposeNativeImpl);
  90         } else {
  91             JNI_ThrowNew(env, "java/lang/OutOfMemoryError",
  92                          "Allocation of internal renderer buffer failed.");
  93         }
  94     } else {
  95         JNI_ThrowNew(env, "java/lang/IllegalStateException", "");
  96     }
  97 }
  98 
  99 static jboolean
 100 initializeSurfaceFieldIds(JNIEnv* env, jobject objectHandle) {
 101     static const FieldDesc surfaceFieldDesc[] = {
 102                 { "nativePtr", "J" },
 103                 { "dataInt", "[I" },
 104                 { NULL, NULL }
 105             };
 106 
 107     jboolean retVal;
 108     jclass classHandle;
 109 
 110     if (fieldIdsInitialized) {
 111         return JNI_TRUE;
 112     }
 113 
 114     retVal = JNI_FALSE;
 115 
 116     classHandle = (*env)->GetObjectClass(env, objectHandle);
 117 
 118     if (initializeFieldIds(fieldIds, env, classHandle, surfaceFieldDesc)) {
 119         retVal = JNI_TRUE;
 120         fieldIdsInitialized = JNI_TRUE;
 121     }
 122 
 123     return retVal;
 124 }
 125 
 126 static void
 127 surface_acquire(AbstractSurface* surface, JNIEnv* env, jobject surfaceHandle) {
 128     jint width = 0;
 129     jint height = 0;
 130     jint dataArrayLength = 0;
 131 
 132     ((JavaSurface *) surface)->dataHandle = (*env)->GetObjectField(env, surfaceHandle,
 133                                 ((JavaSurface *) surface)->javaArrayFieldID);
 134 
 135     dataArrayLength = (*env)->GetArrayLength(env, ((JavaSurface *) surface)->dataHandle);
 136 
 137     width = surface->super.width;
 138     height = surface->super.height;
 139     if (width < 0 || height < 0 || dataArrayLength / width < height) {
 140         // Set data to NULL indicating invalid width and height
 141         surface->super.data = NULL;
 142         ((JavaSurface *) surface)->dataHandle = NULL;
 143         JNI_ThrowNew(env, "java/lang/IllegalArgumentException", "Out of range access of buffer");
 144         return;
 145     }
 146 
 147     surface->super.data =
 148         (void *)(*env)->GetPrimitiveArrayCritical(env, ((JavaSurface *) surface)->dataHandle, NULL);
 149     if (surface->super.data == NULL) {
 150         ((JavaSurface *) surface)->dataHandle = NULL;
 151         setMemErrorFlag();
 152     }
 153 }
 154 
 155 static void
 156 surface_release(AbstractSurface* surface, JNIEnv* env, jobject surfaceHandle) {
 157     if (surface->super.data == NULL) return;
 158     (*env)->ReleasePrimitiveArrayCritical(env, ((JavaSurface *) surface)->dataHandle, surface->super.data, 0);
 159     ((JavaSurface *) surface)->dataHandle = NULL;
 160 }
 161 
 162 static void
 163 surface_cleanup(AbstractSurface* surface) {
 164     // do nothing
 165 }