2003-10-11 12:29:40 -04:00
|
|
|
/*
|
2004-06-12 16:28:34 -04:00
|
|
|
* Copyright (c) 2002-2004 LWJGL Project
|
2003-10-11 12:29:40 -04:00
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions are
|
|
|
|
* met:
|
|
|
|
*
|
|
|
|
* * Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
*
|
|
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
2004-06-12 16:28:34 -04:00
|
|
|
* * Neither the name of 'LWJGL' nor the names of
|
2003-10-11 12:29:40 -04:00
|
|
|
* its contributors may be used to endorse or promote products derived
|
|
|
|
* from this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
|
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
* @author elias_naur <elias_naur@users.sourceforge.net>
|
|
|
|
* @version $Revision$
|
|
|
|
*/
|
|
|
|
|
2004-09-22 07:08:21 -04:00
|
|
|
#include <jni.h>
|
2004-03-09 04:25:10 -05:00
|
|
|
#include <stdlib.h>
|
2003-10-11 12:29:40 -04:00
|
|
|
#include "common_tools.h"
|
2005-01-18 15:23:05 -05:00
|
|
|
#include "org_lwjgl_DefaultSysImplementation.h"
|
2003-10-11 12:29:40 -04:00
|
|
|
|
2004-03-27 09:09:55 -05:00
|
|
|
static bool debug = false;
|
2004-11-02 09:43:16 -05:00
|
|
|
static JavaVM *jvm;
|
2004-03-27 09:09:55 -05:00
|
|
|
|
2004-07-02 15:02:00 -04:00
|
|
|
void initAttribList(attrib_list_t *list) {
|
|
|
|
list->current_index = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void putAttrib(attrib_list_t *list, int attrib) {
|
|
|
|
if (list->current_index == ATTRIB_LIST_SIZE) {
|
|
|
|
printfDebug("Ignoring attrib %d: attrib list size too small", attrib);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
list->attribs[list->current_index] = attrib;
|
|
|
|
list->current_index++;
|
|
|
|
}
|
|
|
|
|
2006-07-14 12:14:52 -04:00
|
|
|
JNIEXPORT jint JNICALL Java_org_lwjgl_DefaultSysImplementation_getJNIVersion
|
2005-01-18 15:23:05 -05:00
|
|
|
(JNIEnv *env, jobject ignored) {
|
2006-07-14 12:14:52 -04:00
|
|
|
return org_lwjgl_DefaultSysImplementation_JNI_VERSION;
|
2004-03-27 09:09:55 -05:00
|
|
|
}
|
|
|
|
|
2005-01-18 15:23:05 -05:00
|
|
|
JNIEXPORT void JNICALL Java_org_lwjgl_DefaultSysImplementation_setDebug
|
|
|
|
(JNIEnv *env, jobject ignored, jboolean enable) {
|
|
|
|
debug = enable == JNI_TRUE ? true : false;
|
2004-03-27 09:09:55 -05:00
|
|
|
}
|
2003-12-15 06:49:17 -05:00
|
|
|
|
2005-01-18 15:23:05 -05:00
|
|
|
bool isDebugEnabled(void) {
|
|
|
|
return debug;
|
2003-12-15 06:49:17 -05:00
|
|
|
}
|
|
|
|
|
2005-11-24 06:31:26 -05:00
|
|
|
static jstring sprintfJavaString(JNIEnv *env, const char *format, va_list ap) {
|
|
|
|
#define BUFFER_SIZE 4000
|
2005-11-22 09:03:52 -05:00
|
|
|
char buffer[BUFFER_SIZE];
|
2004-12-12 05:12:49 -05:00
|
|
|
jstring str;
|
2006-07-15 17:01:11 -04:00
|
|
|
#ifdef _MSC_VER
|
2006-05-18 08:11:37 -04:00
|
|
|
vsnprintf_s(buffer, BUFFER_SIZE, _TRUNCATE, format, ap);
|
2005-11-24 06:31:26 -05:00
|
|
|
#else
|
|
|
|
vsnprintf(buffer, BUFFER_SIZE, format, ap);
|
|
|
|
#endif
|
|
|
|
buffer[BUFFER_SIZE - 1] = '\0';
|
|
|
|
str = (*env)->NewStringUTF(env, buffer);
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
void printfDebugJava(JNIEnv *env, const char *format, ...) {
|
|
|
|
jstring str;
|
2005-03-29 13:09:33 -05:00
|
|
|
jclass org_lwjgl_LWJGLUtil_class;
|
2004-12-12 05:12:49 -05:00
|
|
|
jmethodID log_method;
|
2004-12-11 14:44:53 -05:00
|
|
|
va_list ap;
|
2006-06-26 09:50:48 -04:00
|
|
|
if (isDebugEnabled() && !(*env)->ExceptionOccurred(env)) {
|
2005-11-24 06:31:26 -05:00
|
|
|
va_start(ap, format);
|
|
|
|
str = sprintfJavaString(env, format, ap);
|
|
|
|
va_end(ap);
|
2005-03-29 13:09:33 -05:00
|
|
|
org_lwjgl_LWJGLUtil_class = (*env)->FindClass(env, "org/lwjgl/LWJGLUtil");
|
2006-06-26 09:50:48 -04:00
|
|
|
if (org_lwjgl_LWJGLUtil_class == NULL)
|
|
|
|
return;
|
2005-03-29 13:09:33 -05:00
|
|
|
log_method = (*env)->GetStaticMethodID(env, org_lwjgl_LWJGLUtil_class, "log", "(Ljava/lang/String;)V");
|
2006-06-26 09:50:48 -04:00
|
|
|
if (log_method == NULL)
|
|
|
|
return;
|
2005-03-29 13:09:33 -05:00
|
|
|
(*env)->CallStaticVoidMethod(env, org_lwjgl_LWJGLUtil_class, log_method, str);
|
2004-12-11 14:44:53 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-12-20 17:03:25 -05:00
|
|
|
void printfDebug(const char *format, ...) {
|
2003-12-15 06:49:17 -05:00
|
|
|
va_list ap;
|
|
|
|
va_start(ap, format);
|
2004-03-27 09:09:55 -05:00
|
|
|
if (isDebugEnabled())
|
2003-12-24 02:32:03 -05:00
|
|
|
vfprintf(stderr, format, ap);
|
2003-12-15 06:49:17 -05:00
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
2005-11-24 06:31:26 -05:00
|
|
|
static void throwFormattedGeneralException(JNIEnv * env, const char *exception_name, const char *format, va_list ap) {
|
|
|
|
jclass cls;
|
|
|
|
jstring str;
|
|
|
|
jmethodID exception_constructor;
|
|
|
|
jobject exception;
|
|
|
|
|
|
|
|
if ((*env)->ExceptionCheck(env) == JNI_TRUE)
|
|
|
|
return; // The JVM crashes if we try to throw two exceptions from one native call
|
|
|
|
str = sprintfJavaString(env, format, ap);
|
|
|
|
cls = (*env)->FindClass(env, exception_name);
|
|
|
|
exception_constructor = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/lang/String;)V");
|
|
|
|
exception = (*env)->NewObject(env, cls, exception_constructor, str);
|
|
|
|
(*env)->Throw(env, exception);
|
|
|
|
}
|
|
|
|
|
2005-01-11 10:22:12 -05:00
|
|
|
void throwGeneralException(JNIEnv * env, const char *exception_name, const char * err) {
|
2004-09-10 05:56:26 -04:00
|
|
|
jclass cls;
|
|
|
|
|
2004-09-10 04:13:56 -04:00
|
|
|
if ((*env)->ExceptionCheck(env) == JNI_TRUE)
|
2004-04-09 17:52:42 -04:00
|
|
|
return; // The JVM crashes if we try to throw two exceptions from one native call
|
2004-09-10 05:56:26 -04:00
|
|
|
cls = (*env)->FindClass(env, exception_name);
|
2004-09-10 04:13:56 -04:00
|
|
|
(*env)->ThrowNew(env, cls, err);
|
2003-10-11 12:29:40 -04:00
|
|
|
}
|
2003-10-22 06:57:19 -04:00
|
|
|
|
2004-05-23 09:50:08 -04:00
|
|
|
void throwFMODException(JNIEnv * env, const char * err) {
|
2004-07-17 19:31:25 -04:00
|
|
|
throwGeneralException(env, "org/lwjgl/fmod3/FMODException", err);
|
2004-05-23 09:50:08 -04:00
|
|
|
}
|
|
|
|
|
2005-11-24 06:31:26 -05:00
|
|
|
void throwFormattedException(JNIEnv * env, const char *format, ...) {
|
|
|
|
va_list ap;
|
|
|
|
va_start(ap, format);
|
|
|
|
throwFormattedGeneralException(env, "org/lwjgl/LWJGLException", format, ap);
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
2003-10-22 06:57:19 -04:00
|
|
|
void throwException(JNIEnv * env, const char * err) {
|
2004-03-27 10:05:24 -05:00
|
|
|
throwGeneralException(env, "org/lwjgl/LWJGLException", err);
|
2003-10-22 06:57:19 -04:00
|
|
|
}
|
2004-03-09 04:25:10 -05:00
|
|
|
|
2004-11-13 16:06:38 -05:00
|
|
|
// retrieves the locale-specific C string
|
|
|
|
char * GetStringNativeChars(JNIEnv *env, jstring jstr) {
|
|
|
|
jbyteArray bytes = 0;
|
|
|
|
jthrowable exc;
|
|
|
|
char *result = 0;
|
|
|
|
jclass jcls_str;
|
|
|
|
jmethodID MID_String_getBytes;
|
|
|
|
|
|
|
|
/* out of memory error? */
|
|
|
|
if ((*env)->EnsureLocalCapacity(env, 2) < 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// aquire getBytes method
|
|
|
|
jcls_str = (*env)->FindClass(env, "java/lang/String");
|
|
|
|
MID_String_getBytes = (*env)->GetMethodID(env, jcls_str, "getBytes", "()[B");
|
|
|
|
|
|
|
|
// get the bytes
|
|
|
|
bytes = (jbyteArray) (*env)->CallObjectMethod(env, jstr, MID_String_getBytes);
|
|
|
|
exc = (*env)->ExceptionOccurred(env);
|
|
|
|
|
|
|
|
// if no exception occured while getting bytes - continue
|
|
|
|
if (!exc) {
|
|
|
|
jint len = (*env)->GetArrayLength(env, bytes);
|
|
|
|
result = (char *) malloc(len + 1);
|
|
|
|
if (result == 0) {
|
|
|
|
throwGeneralException(env, "java/lang/OutOfMemoryError", NULL);
|
|
|
|
(*env)->DeleteLocalRef(env, bytes);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
(*env)->GetByteArrayRegion(env, bytes, 0, len, (jbyte *) result);
|
|
|
|
result[len] = 0; /* NULL-terminate */
|
|
|
|
} else {
|
|
|
|
(*env)->DeleteLocalRef(env, exc);
|
|
|
|
}
|
|
|
|
(*env)->DeleteLocalRef(env, bytes);
|
|
|
|
return (char*) result;
|
|
|
|
}
|
|
|
|
|
2006-07-07 06:36:26 -04:00
|
|
|
/* creates locale specific string, unsigned argument to
|
|
|
|
* match GLuchar and ALuchar types
|
|
|
|
*/
|
|
|
|
jstring NewStringNativeUnsigned(JNIEnv *env, const unsigned char *str) {
|
|
|
|
return NewStringNative(env, (const char *)str);
|
|
|
|
}
|
|
|
|
|
2004-11-14 05:42:19 -05:00
|
|
|
// creates locale specific string
|
|
|
|
jstring NewStringNative(JNIEnv *env, const char *str) {
|
|
|
|
jclass jcls_str;
|
|
|
|
jmethodID jmethod_str;
|
|
|
|
jstring result;
|
|
|
|
jbyteArray bytes;
|
|
|
|
int len;
|
|
|
|
if (str==NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
jcls_str = (*env)->FindClass(env,"java/lang/String");
|
|
|
|
jmethod_str = (*env)->GetMethodID(env,jcls_str, "<init>", "([B)V");
|
|
|
|
|
|
|
|
bytes = 0;
|
|
|
|
|
|
|
|
if ((*env)->EnsureLocalCapacity(env,2) < 0) {
|
|
|
|
return NULL; /* out of memory error */
|
|
|
|
}
|
|
|
|
len = strlen(str);
|
|
|
|
bytes = (*env)->NewByteArray(env,len);
|
|
|
|
if (bytes != NULL) {
|
|
|
|
(*env)->SetByteArrayRegion(env,bytes, 0, len, (jbyte *)str);
|
|
|
|
result = (jstring)(*env)->NewObject(env,jcls_str, jmethod_str, bytes);
|
|
|
|
(*env)->DeleteLocalRef(env,bytes);
|
|
|
|
return result;
|
|
|
|
} /* else fall through */
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2004-03-11 07:38:13 -05:00
|
|
|
bool ext_InitializeFunctions(ExtGetProcAddressPROC gpa, int num_functions, ExtFunction *functions) {
|
2004-09-10 04:13:56 -04:00
|
|
|
int i;
|
2004-09-10 05:56:26 -04:00
|
|
|
void **ext_function_pointer_pointer;
|
2004-09-10 04:13:56 -04:00
|
|
|
for (i = 0; i < num_functions; i++) {
|
2004-03-11 07:38:13 -05:00
|
|
|
ExtFunction *function = functions + i;
|
|
|
|
if (function->ext_function_name != NULL) {
|
|
|
|
void *ext_func_pointer = gpa(function->ext_function_name);
|
|
|
|
if (ext_func_pointer == NULL)
|
|
|
|
return false;
|
2004-09-10 05:56:26 -04:00
|
|
|
ext_function_pointer_pointer = function->ext_function_pointer;
|
2004-03-11 07:38:13 -05:00
|
|
|
*ext_function_pointer_pointer = ext_func_pointer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2005-02-21 09:46:47 -05:00
|
|
|
jobject newJavaManagedByteBuffer(JNIEnv *env, const int size) {
|
|
|
|
jclass bufferutils_class = (*env)->FindClass(env, "org/lwjgl/BufferUtils");
|
|
|
|
jmethodID createByteBuffer = (*env)->GetStaticMethodID(env, bufferutils_class, "createByteBuffer", "(I)Ljava/nio/ByteBuffer;");
|
|
|
|
jobject buffer = (*env)->CallStaticObjectMethod(env, bufferutils_class, createByteBuffer, size);
|
|
|
|
return buffer;
|
|
|
|
}
|
|
|
|
|
2004-07-04 09:14:06 -04:00
|
|
|
void ext_InitializeClass(JNIEnv *env, jclass clazz, ExtGetProcAddressPROC gpa, int num_functions, JavaMethodAndExtFunction *functions) {
|
2004-09-10 05:56:26 -04:00
|
|
|
JNINativeMethod *methods;
|
|
|
|
JavaMethodAndExtFunction *function;
|
|
|
|
void *ext_func_pointer;
|
|
|
|
void **ext_function_pointer_pointer;
|
|
|
|
JNINativeMethod *method;
|
|
|
|
int i;
|
2004-07-04 05:13:19 -04:00
|
|
|
if (clazz == NULL) {
|
|
|
|
throwException(env, "Null class");
|
2004-07-04 09:14:06 -04:00
|
|
|
return;
|
2004-07-04 05:13:19 -04:00
|
|
|
}
|
2004-09-10 05:56:26 -04:00
|
|
|
methods = (JNINativeMethod *)malloc(num_functions*sizeof(JNINativeMethod));
|
2004-09-10 04:13:56 -04:00
|
|
|
for (i = 0; i < num_functions; i++) {
|
2004-09-10 05:56:26 -04:00
|
|
|
function = functions + i;
|
2004-03-09 04:25:10 -05:00
|
|
|
if (function->ext_function_name != NULL) {
|
2004-09-10 05:56:26 -04:00
|
|
|
ext_func_pointer = gpa(function->ext_function_name);
|
2004-03-09 04:25:10 -05:00
|
|
|
if (ext_func_pointer == NULL) {
|
|
|
|
free(methods);
|
2004-07-03 17:12:33 -04:00
|
|
|
throwException(env, "Missing driver symbols");
|
2004-07-04 09:14:06 -04:00
|
|
|
return;
|
2004-03-09 04:25:10 -05:00
|
|
|
}
|
2004-09-10 05:56:26 -04:00
|
|
|
ext_function_pointer_pointer = function->ext_function_pointer;
|
2004-03-09 04:25:10 -05:00
|
|
|
*ext_function_pointer_pointer = ext_func_pointer;
|
|
|
|
}
|
2004-09-10 05:56:26 -04:00
|
|
|
method = methods + i;
|
2004-03-09 04:25:10 -05:00
|
|
|
method->name = function->method_name;
|
|
|
|
method->signature = function->signature;
|
|
|
|
method->fnPtr = function->method_pointer;
|
|
|
|
}
|
2004-09-10 04:13:56 -04:00
|
|
|
(*env)->RegisterNatives(env, clazz, methods, num_functions);
|
2004-03-09 04:25:10 -05:00
|
|
|
free(methods);
|
|
|
|
}
|
|
|
|
|
2004-03-11 16:30:48 -05:00
|
|
|
bool getBooleanProperty(JNIEnv *env, const char* propertyName) {
|
2004-11-14 05:42:19 -05:00
|
|
|
jstring property = NewStringNative(env, propertyName);
|
2005-05-30 12:21:05 -04:00
|
|
|
jclass org_lwjgl_LWJGLUtil_class = (*env)->FindClass(env, "org/lwjgl/LWJGLUtil");
|
|
|
|
jmethodID getBoolean = (*env)->GetStaticMethodID(env, org_lwjgl_LWJGLUtil_class, "getPrivilegedBoolean", "(Ljava/lang/String;)Z");
|
|
|
|
return (*env)->CallStaticBooleanMethod(env, org_lwjgl_LWJGLUtil_class, getBoolean, property) ? true : false;
|
2004-03-11 16:30:48 -05:00
|
|
|
}
|
2004-05-31 08:39:03 -04:00
|
|
|
|
2004-11-02 09:43:16 -05:00
|
|
|
JavaVM *getJVM() {
|
|
|
|
return jvm;
|
|
|
|
}
|
|
|
|
|
2006-07-09 04:31:49 -04:00
|
|
|
JNIEnv *getThreadEnv() {
|
|
|
|
JNIEnv *env;
|
2006-07-09 20:44:49 -04:00
|
|
|
(*jvm)->GetEnv(jvm, (void *)&env, JNI_VERSION_1_4);
|
2006-07-09 04:31:49 -04:00
|
|
|
return env;
|
|
|
|
}
|
|
|
|
|
2004-05-31 08:39:03 -04:00
|
|
|
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
|
|
|
|
jvm = vm;
|
|
|
|
return JNI_VERSION_1_4;
|
|
|
|
}
|
2004-11-02 09:43:16 -05:00
|
|
|
|
2004-05-31 08:39:03 -04:00
|
|
|
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) {
|
2004-07-02 15:02:00 -04:00
|
|
|
}
|
2006-07-03 14:07:44 -04:00
|
|
|
|
|
|
|
bool positionBuffer(JNIEnv *env, jobject buffer, jint position) {
|
|
|
|
jclass buffer_class;
|
|
|
|
jmethodID position_method;
|
|
|
|
|
|
|
|
buffer_class = (*env)->GetObjectClass(env, buffer);
|
|
|
|
if (buffer_class == NULL)
|
|
|
|
return false;
|
|
|
|
position_method = (*env)->GetMethodID(env, buffer_class, "position", "(I)Ljava/nio/Buffer;");
|
|
|
|
if (position_method == NULL)
|
|
|
|
return false;
|
|
|
|
(*env)->CallObjectMethod(env, buffer, position_method, position);
|
|
|
|
return true;
|
|
|
|
}
|