diff options
Diffstat (limited to 'src/native/ogl/Canvas3D.c')
-rw-r--r-- | src/native/ogl/Canvas3D.c | 3388 |
1 files changed, 3388 insertions, 0 deletions
diff --git a/src/native/ogl/Canvas3D.c b/src/native/ogl/Canvas3D.c new file mode 100644 index 0000000..86d037d --- /dev/null +++ b/src/native/ogl/Canvas3D.c @@ -0,0 +1,3388 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2004 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +/* + * Portions of this code were derived from work done by the Blackdown + * group (www.blackdown.org), who did the initial Linux implementation + * of the Java 3D API. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <jni.h> + + +#include "gldefs.h" + +#ifdef DEBUG +/* Uncomment the following for VERBOSE debug messages */ +/* #define VERBOSE */ +#endif /* DEBUG */ + + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef BOOL +#define BOOL int +#endif + +static char *gl_VERSION; +static char *gl_VENDOR; + +void initializeCtxInfo(JNIEnv *env, GraphicsContextPropertiesInfo* ctxInfo); +void cleanupCtxInfo(GraphicsContextPropertiesInfo* ctxInfo); + +/* + * Class: javax_media_j3d_Canvas3D + * Method: getTextureColorTableSize + * Signature: ()I + */ +int getTextureColorTableSize( + JNIEnv *env, + jobject obj, + jlong ctxInfo, + char *extensionStr, + int minorVersion); + + +#ifdef WIN32 + extern HDC getMonitorDC(int screen); +#endif + +/* + * extract the version numbers + * when return , numbers[0] contains major version number + * numbers[1] contains minor version number + */ +void extractVersionInfo(char *versionStr, int* numbers){ + char *majorNumStr; + char *minorNumStr; + majorNumStr = strtok(versionStr, (char *)"."); + minorNumStr = strtok(0, (char *)"."); + if (majorNumStr != NULL) + numbers[0] = atoi(majorNumStr); + if (minorNumStr != NULL) + numbers[1] = atoi(minorNumStr); + + /* fprintf(stderr, "majorNumStr = %d, minNumStr = %d \n", numbers[0], numbers[1]); */ + return; +} + +/* + * check if the extension is supported + */ +int isExtensionSupported(const char *allExtensions, const char *extension) +{ + const char *start; + const char *where, *terminator; + + /* Extension names should not have spaces. */ + where = (const char *) strchr(extension, ' '); + if (where || *extension == '\0') + return 0; + + /* + * It takes a bit of care to be fool-proof about parsing the + * OpenGL extensions string. Don't be fooled by sub-strings, + * etc. + */ + start = allExtensions; + for (;;) { + where = (const char *) strstr((const char *) start, extension); + if (!where) + break; + terminator = where + strlen(extension); + if (where == start || *(where - 1) == ' ') + if (*terminator == ' ' || *terminator == '\0') + return 1; + start = terminator; + } + return 0; +} + +void checkTextureExtensions( + JNIEnv *env, + jobject obj, + char *tmpExtensionStr, + int versionNumber, + GraphicsContextPropertiesInfo* ctxInfo) { + + if(isExtensionSupported(tmpExtensionStr, "GL_ARB_multitexture")) { + ctxInfo->arb_multitexture = JNI_TRUE ; + ctxInfo->textureExtMask |= javax_media_j3d_Canvas3D_TEXTURE_MULTI_TEXTURE; + glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &ctxInfo->textureUnitCount); + + } + + if(isExtensionSupported(tmpExtensionStr,"GL_SGI_texture_color_table" )){ + ctxInfo->textureColorTableAvailable = JNI_TRUE; + ctxInfo->textureExtMask |= javax_media_j3d_Canvas3D_TEXTURE_COLOR_TABLE; + + /* get texture color table size */ + /* need to check later */ + ctxInfo->textureColorTableSize = getTextureColorTableSize(env, obj, (jlong)ctxInfo, tmpExtensionStr, versionNumber); + if (ctxInfo->textureColorTableSize <= 0) { + ctxInfo->textureColorTableAvailable = JNI_FALSE; + ctxInfo->textureExtMask &= ~javax_media_j3d_Canvas3D_TEXTURE_COLOR_TABLE; + } + if (ctxInfo->textureColorTableSize > 256) { + ctxInfo->textureColorTableSize = 256; + } + } + + if(isExtensionSupported(tmpExtensionStr,"GL_ARB_texture_env_combine" )){ + ctxInfo->textureEnvCombineAvailable = JNI_TRUE; + ctxInfo->textureCombineSubtractAvailable = JNI_TRUE; + + ctxInfo->textureExtMask |= javax_media_j3d_Canvas3D_TEXTURE_COMBINE; + ctxInfo->textureExtMask |= javax_media_j3d_Canvas3D_TEXTURE_COMBINE_SUBTRACT; + ctxInfo->combine_enum = GL_COMBINE_ARB; + ctxInfo->combine_add_signed_enum = GL_ADD_SIGNED_ARB; + ctxInfo->combine_interpolate_enum = GL_INTERPOLATE_ARB; + ctxInfo->combine_subtract_enum = GL_SUBTRACT_ARB; + + } else if(isExtensionSupported(tmpExtensionStr,"GL_EXT_texture_env_combine" )){ + ctxInfo->textureEnvCombineAvailable = JNI_TRUE; + ctxInfo->textureCombineSubtractAvailable = JNI_FALSE; + + ctxInfo->textureExtMask |= javax_media_j3d_Canvas3D_TEXTURE_COMBINE; + ctxInfo->combine_enum = GL_COMBINE_EXT; + ctxInfo->combine_add_signed_enum = GL_ADD_SIGNED_EXT; + ctxInfo->combine_interpolate_enum = GL_INTERPOLATE_EXT; + + /* EXT_texture_env_combine does not include subtract */ + ctxInfo->combine_subtract_enum = 0; + } + + if(isExtensionSupported(tmpExtensionStr,"GL_NV_register_combiners" )) { + ctxInfo->textureRegisterCombinersAvailable = JNI_TRUE; + ctxInfo->textureExtMask |= javax_media_j3d_Canvas3D_TEXTURE_REGISTER_COMBINERS; +#if defined(SOLARIS) || defined(__linux__) + ctxInfo->glCombinerInputNV = + (MYPFNGLCOMBINERINPUTNV) glCombinerInputNV; + ctxInfo->glFinalCombinerInputNV = + (MYPFNGLFINALCOMBINERINPUTNV) glFinalCombinerInputNV; + ctxInfo->glCombinerOutputNV = + (MYPFNGLCOMBINEROUTPUTNV) glCombinerOutputNV; + ctxInfo->glCombinerParameterfvNV = + (MYPFNGLCOMBINERPARAMETERFVNV) glCombinerParameterfvNV; + ctxInfo->glCombinerParameterivNV = + (MYPFNGLCOMBINERPARAMETERIVNV) glCombinerParameterivNV; + ctxInfo->glCombinerParameterfNV = + (MYPFNGLCOMBINERPARAMETERFNV) glCombinerParameterfNV; + ctxInfo->glCombinerParameteriNV = + (MYPFNGLCOMBINERPARAMETERINV) glCombinerParameteriNV; + if (ctxInfo->glCombinerInputNV == NULL || + ctxInfo->glFinalCombinerInputNV == NULL || + ctxInfo->glCombinerOutputNV == NULL || + ctxInfo->glCombinerParameterfvNV == NULL || + ctxInfo->glCombinerParameterivNV == NULL || + ctxInfo->glCombinerParameterfNV == NULL || + ctxInfo->glCombinerParameteriNV == NULL) { + /* lets play safe: */ + ctxInfo->textureExtMask &= + ~javax_media_j3d_Canvas3D_TEXTURE_REGISTER_COMBINERS; + ctxInfo->textureRegisterCombinersAvailable = JNI_FALSE; + } +#endif + +#ifdef WIN32 + ctxInfo->glCombinerInputNV = + (MYPFNGLCOMBINERINPUTNV) wglGetProcAddress("glCombinerInputNV"); + ctxInfo->glFinalCombinerInputNV = + (MYPFNGLFINALCOMBINERINPUTNV) wglGetProcAddress("glFinalCombinerInputNV"); + ctxInfo->glCombinerOutputNV = + (MYPFNGLCOMBINEROUTPUTNV) wglGetProcAddress("glCombinerOutputNV"); + ctxInfo->glCombinerParameterfvNV = + (MYPFNGLCOMBINERPARAMETERFVNV) wglGetProcAddress("glCombinerParameterfvNV"); + ctxInfo->glCombinerParameterivNV = + (MYPFNGLCOMBINERPARAMETERIVNV) wglGetProcAddress("glCombinerParameterivNV"); + ctxInfo->glCombinerParameterfNV = + (MYPFNGLCOMBINERPARAMETERFNV) wglGetProcAddress("glCombinerParameterfNV"); + ctxInfo->glCombinerParameteriNV = + (MYPFNGLCOMBINERPARAMETERINV) wglGetProcAddress("glCombinerParameteriNV"); + + /* + if (ctxInfo->glCombinerInputNV == NULL) { + printf("glCombinerInputNV == NULL\n"); + } + if (ctxInfo->glFinalCombinerInputNV == NULL) { + printf("glFinalCombinerInputNV == NULL\n"); + } + if (ctxInfo->glCombinerOutputNV == NULL) { + printf("ctxInfo->glCombinerOutputNV == NULL\n"); + } + if (ctxInfo->glCombinerParameterfvNV == NULL) { + printf("ctxInfo->glCombinerParameterfvNV == NULL\n"); + } + if (ctxInfo->glCombinerParameterivNV == NULL) { + printf("ctxInfo->glCombinerParameterivNV == NULL\n"); + } + if (ctxInfo->glCombinerParameterfNV == NULL) { + printf("ctxInfo->glCombinerParameterfNV == NULL\n"); + } + if (ctxInfo->glCombinerParameteriNV == NULL) { + printf("ctxInfo->glCombinerParameteriNV == NULL\n"); + } + */ + if ((ctxInfo->glCombinerInputNV == NULL) || + (ctxInfo->glFinalCombinerInputNV == NULL) || + (ctxInfo->glCombinerOutputNV == NULL) || + (ctxInfo->glCombinerParameterfvNV == NULL) || + (ctxInfo->glCombinerParameterivNV == NULL) || + (ctxInfo->glCombinerParameterfNV == NULL) || + (ctxInfo->glCombinerParameteriNV == NULL)) { + ctxInfo->textureExtMask &= ~javax_media_j3d_Canvas3D_TEXTURE_REGISTER_COMBINERS; + ctxInfo->textureRegisterCombinersAvailable = JNI_FALSE; + } + +#endif + + } + + if(isExtensionSupported(tmpExtensionStr,"GL_ARB_texture_env_dot3" )) { + ctxInfo->textureCombineDot3Available = JNI_TRUE; + ctxInfo->textureExtMask |= javax_media_j3d_Canvas3D_TEXTURE_COMBINE_DOT3; + ctxInfo->combine_dot3_rgb_enum = GL_DOT3_RGB_ARB; + ctxInfo->combine_dot3_rgba_enum = GL_DOT3_RGBA_ARB; + } else if(isExtensionSupported(tmpExtensionStr,"GL_EXT_texture_env_dot3" )) { + ctxInfo->textureCombineDot3Available = JNI_TRUE; + ctxInfo->textureExtMask |= javax_media_j3d_Canvas3D_TEXTURE_COMBINE_DOT3; + ctxInfo->combine_dot3_rgb_enum = GL_DOT3_RGB_EXT; + ctxInfo->combine_dot3_rgba_enum = GL_DOT3_RGBA_EXT; + } + + if (isExtensionSupported(tmpExtensionStr, "GL_ARB_texture_cube_map")) { + ctxInfo->texture_cube_map_ext_enum = GL_TEXTURE_CUBE_MAP_ARB; + ctxInfo->textureCubeMapAvailable = JNI_TRUE; + ctxInfo->textureExtMask |= javax_media_j3d_Canvas3D_TEXTURE_CUBE_MAP; + } else if (isExtensionSupported(tmpExtensionStr, "GL_EXT_texture_cube_map")) { + ctxInfo->texture_cube_map_ext_enum = GL_TEXTURE_CUBE_MAP_EXT; + ctxInfo->textureCubeMapAvailable = JNI_TRUE; + ctxInfo->textureExtMask |= javax_media_j3d_Canvas3D_TEXTURE_CUBE_MAP; + } + + if (isExtensionSupported(tmpExtensionStr, "GL_SGIS_sharpen_texture")) { + ctxInfo->textureSharpenAvailable = JNI_TRUE; + ctxInfo->linear_sharpen_enum = GL_LINEAR_SHARPEN_SGIS; + ctxInfo->linear_sharpen_rgb_enum = GL_LINEAR_SHARPEN_COLOR_SGIS; + ctxInfo->linear_sharpen_alpha_enum = GL_LINEAR_SHARPEN_ALPHA_SGIS; + ctxInfo->textureExtMask |= javax_media_j3d_Canvas3D_TEXTURE_SHARPEN; +#if defined(SOLARIS) || defined(__linux__) + ctxInfo->glSharpenTexFuncSGIS = + (MYPFNGLSHARPENTEXFUNCSGI) glSharpenTexFuncSGIS; +#endif +#ifdef WIN32 + ctxInfo->glSharpenTexFuncSGIS = (MYPFNGLSHARPENTEXFUNCSGI) + wglGetProcAddress("glSharpenTexFuncSGIS"); + if (ctxInfo->glSharpenTexFuncSGIS == NULL) { + /* printf("ctxInfo->glSharpenTexFuncSGIS == NULL\n"); */ + ctxInfo->textureExtMask &= ~javax_media_j3d_Canvas3D_TEXTURE_SHARPEN; + ctxInfo->textureSharpenAvailable = JNI_FALSE; + } +#endif + } + + if (isExtensionSupported(tmpExtensionStr, "GL_SGIS_detail_texture")) { + ctxInfo->textureDetailAvailable = JNI_TRUE; + ctxInfo->texture_detail_ext_enum = GL_DETAIL_TEXTURE_2D_SGIS; + ctxInfo->linear_detail_enum = GL_LINEAR_DETAIL_SGIS; + ctxInfo->linear_detail_rgb_enum = GL_LINEAR_DETAIL_COLOR_SGIS; + ctxInfo->linear_detail_alpha_enum = GL_LINEAR_DETAIL_ALPHA_SGIS; + ctxInfo->texture_detail_mode_enum = GL_DETAIL_TEXTURE_MODE_SGIS; + ctxInfo->texture_detail_level_enum = GL_DETAIL_TEXTURE_LEVEL_SGIS; + ctxInfo->textureExtMask |= javax_media_j3d_Canvas3D_TEXTURE_DETAIL; +#if defined(SOLARIS) || defined(__linux__) + ctxInfo->glDetailTexFuncSGIS = + (MYPFNGLDETAILTEXFUNCSGI) glDetailTexFuncSGIS; +#endif +#ifdef WIN32 + ctxInfo->glDetailTexFuncSGIS = (MYPFNGLDETAILTEXFUNCSGI) + wglGetProcAddress("glDetailTexFuncSGIS"); + if (ctxInfo->glDetailTexFuncSGIS == NULL) { + /* printf("ctxInfo->glDetailTexFuncSGIS == NULL\n"); */ + ctxInfo->textureExtMask &= ~javax_media_j3d_Canvas3D_TEXTURE_DETAIL; + ctxInfo->textureDetailAvailable = JNI_FALSE; + } +#endif + } + + if (isExtensionSupported(tmpExtensionStr, "GL_SGIS_texture_filter4")) { + ctxInfo->textureFilter4Available = JNI_TRUE; + ctxInfo->filter4_enum = GL_FILTER4_SGIS; + ctxInfo->textureExtMask |= javax_media_j3d_Canvas3D_TEXTURE_FILTER4; +#if defined(SOLARIS) || defined(__linux__) + ctxInfo->glTexFilterFuncSGIS = + (MYPFNGLTEXFILTERFUNCSGI) glTexFilterFuncSGIS; +#endif +#ifdef WIN32 + ctxInfo->glTexFilterFuncSGIS = (MYPFNGLTEXFILTERFUNCSGI) + wglGetProcAddress("glTexFilterFuncSGIS"); + if (ctxInfo->glTexFilterFuncSGIS == NULL) { + /* printf("ctxInfo->glTexFilterFuncSGIS == NULL\n"); */ + ctxInfo->textureExtMask &= ~javax_media_j3d_Canvas3D_TEXTURE_FILTER4; + ctxInfo->textureFilter4Available = JNI_FALSE; + } +#endif + } + + if (isExtensionSupported(tmpExtensionStr, + "GL_EXT_texture_filter_anisotropic")) { + ctxInfo->textureAnisotropicFilterAvailable = JNI_TRUE; + ctxInfo->texture_filter_anisotropic_ext_enum = + GL_TEXTURE_MAX_ANISOTROPY_EXT; + ctxInfo->max_texture_filter_anisotropy_enum = + GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT; + ctxInfo->textureExtMask |= + javax_media_j3d_Canvas3D_TEXTURE_ANISOTROPIC_FILTER; + } + + if (isExtensionSupported(tmpExtensionStr, + "GL_ARB_texture_border_clamp")) { + ctxInfo->texture_clamp_to_border_enum = GL_CLAMP_TO_BORDER_ARB; + } else if (isExtensionSupported(tmpExtensionStr, + "GL_SGIS_texture_border_clamp")) { + ctxInfo->texture_clamp_to_border_enum = GL_CLAMP_TO_BORDER_SGIS; + } else { + ctxInfo->texture_clamp_to_border_enum = GL_CLAMP; + } + + if (isExtensionSupported(tmpExtensionStr, + "GL_SGIX_texture_lod_bias")) { + ctxInfo->textureLodBiasAvailable = JNI_TRUE; + ctxInfo->textureExtMask |= + javax_media_j3d_Canvas3D_TEXTURE_LOD_OFFSET; + } +} + +BOOL getJavaBoolEnv(JNIEnv *env, char* envStr) +{ + JNIEnv table = *env; + jclass cls; + jfieldID fieldID; + jobject obj; + + cls = (jclass) (*(table->FindClass))(env, "javax/media/j3d/VirtualUniverse"); + + if (cls == NULL) { + return FALSE; + } + + fieldID = (jfieldID) (*(table->GetStaticFieldID))(env, cls, "mc", + "Ljavax/media/j3d/MasterControl;"); + if (fieldID == NULL) { + return FALSE; + } + + obj = (*(table->GetStaticObjectField))(env, cls, fieldID); + + if (obj == NULL) { + return FALSE; + } + + cls = (jclass) (*(table->FindClass))(env, "javax/media/j3d/MasterControl"); + + if (cls == NULL) { + return FALSE; + } + + fieldID = (jfieldID) (*(table->GetFieldID))(env, cls, envStr, "Z"); + + if (fieldID == NULL ) { + return FALSE; + } + + return (*(table->GetBooleanField))(env, obj, fieldID); +} + + +/* + * get properties from current context + */ +BOOL getPropertiesFromCurrentContext( + JNIEnv *env, + jobject obj, + GraphicsContextPropertiesInfo *ctxInfo, + jlong hdc, + int pixelFormat, + long display, + jlong vinfo) +{ + JNIEnv table = *env; + + /* version and extension */ + char *glversion; + char *extensionStr; + char *tmpVersionStr; + char *tmpExtensionStr; + int versionNumbers[2]; + char *cgHwStr = 0; + int stencilSize; + +#ifdef WIN32 + PFNWGLGETPIXELFORMATATTRIBIVEXTPROC wglGetPixelFormatAttribivEXT = NULL; + PIXELFORMATDESCRIPTOR pfd; + int attr[3]; + int piValues[2]; +#endif + + /* get OpenGL version */ + glversion = (char *)glGetString(GL_VERSION); + if (glversion == NULL) { + fprintf(stderr, "glversion == null\n"); + return FALSE; + } + gl_VERSION = glversion; + tmpVersionStr = strdup(glversion); + gl_VENDOR = (char *)glGetString(GL_VENDOR); + if (gl_VENDOR == NULL) { + gl_VENDOR = "<unkown vendor>"; + } + + /* Get the extension */ + extensionStr = (char *)glGetString(GL_EXTENSIONS); + if (extensionStr == NULL) { + fprintf(stderr, "extensionStr == null\n"); + return FALSE; + } + tmpExtensionStr = strdup(extensionStr); + + ctxInfo->versionStr = strdup(glversion); + ctxInfo->extensionStr = strdup(extensionStr); + + + /* find out the version, major and minor version number */ + extractVersionInfo(tmpVersionStr, versionNumbers); + + /* *********************************************************/ + /* setup the graphics context properties */ + if (versionNumbers[1] >= 2) { /* check 1.2 core and above */ + /* 1.2 core */ + ctxInfo->rescale_normal_ext = JNI_TRUE; + ctxInfo->rescale_normal_ext_enum = GL_RESCALE_NORMAL; + ctxInfo->bgr_ext = JNI_TRUE; + ctxInfo->bgr_ext_enum = GL_BGR; + ctxInfo->texture3DAvailable = JNI_TRUE; + ctxInfo->textureExtMask |= javax_media_j3d_Canvas3D_TEXTURE_3D; +#if defined(SOLARIS) || defined(__linux__) + ctxInfo->glTexImage3DEXT = (MYPFNGLTEXIMAGE3DPROC )glTexImage3D; + ctxInfo->glTexSubImage3DEXT = (MYPFNGLTEXSUBIMAGE3DPROC )glTexSubImage3D; +#endif +#ifdef WIN32 + ctxInfo->glTexImage3DEXT = (MYPFNGLTEXIMAGE3DPROC )wglGetProcAddress("glTexImage3D"); + ctxInfo->glTexSubImage3DEXT = (MYPFNGLTEXSUBIMAGE3DPROC )wglGetProcAddress("glTexSubImage3D"); + if ((ctxInfo->glTexImage3DEXT == NULL) || (ctxInfo->glTexSubImage3DEXT == NULL)) { + ctxInfo->textureExtMask &= ~javax_media_j3d_Canvas3D_TEXTURE_3D; + ctxInfo->texture3DAvailable = JNI_FALSE; + } +#endif + ctxInfo->texture_3D_ext_enum = GL_TEXTURE_3D; + ctxInfo->texture_wrap_r_ext_enum = GL_TEXTURE_WRAP_R; + ctxInfo->texture_clamp_to_edge_enum = GL_CLAMP_TO_EDGE; + + if(isExtensionSupported(tmpExtensionStr, "GL_ARB_imaging")){ + ctxInfo->blend_color_ext = JNI_TRUE; + ctxInfo->blendFunctionTable[7] = GL_CONSTANT_COLOR; +#if defined(SOLARIS) || defined(__linux__) + ctxInfo->glBlendColor = (MYPFNGLBLENDCOLORPROC )glBlendColor; +#endif +#ifdef WIN32 + ctxInfo->glBlendColor = (MYPFNGLBLENDCOLORPROC )wglGetProcAddress("glBlendColor"); + if (ctxInfo->glBlendColor == NULL) { + ctxInfo->blend_color_ext = JNI_FALSE; + } +#endif + } + + ctxInfo->seperate_specular_color = JNI_TRUE; + ctxInfo->light_model_color_control_enum = GL_LIGHT_MODEL_COLOR_CONTROL; + ctxInfo->single_color_enum = GL_SINGLE_COLOR; + ctxInfo->seperate_specular_color_enum = GL_SEPARATE_SPECULAR_COLOR; + + ctxInfo->textureLodAvailable = JNI_TRUE; + ctxInfo->textureExtMask |= javax_media_j3d_Canvas3D_TEXTURE_LOD_RANGE; + ctxInfo->texture_min_lod_enum = GL_TEXTURE_MIN_LOD; + ctxInfo->texture_max_lod_enum = GL_TEXTURE_MAX_LOD; + ctxInfo->texture_base_level_enum = GL_TEXTURE_BASE_LEVEL; + ctxInfo->texture_max_level_enum = GL_TEXTURE_MAX_LEVEL; + + /* ... */ + + } else { /* check 1.1 extension */ + if(isExtensionSupported(tmpExtensionStr,"GL_EXT_rescale_normal")){ + ctxInfo->rescale_normal_ext = JNI_TRUE; + ctxInfo->rescale_normal_ext_enum = GL_RESCALE_NORMAL_EXT; + } + if(isExtensionSupported(tmpExtensionStr,"GL_BGR_EXT")) { + ctxInfo->bgr_ext = 1; + ctxInfo->bgr_ext_enum = GL_BGR_EXT; + } + + if(isExtensionSupported(tmpExtensionStr,"GL_EXT_texture3D" )){ + ctxInfo->texture3DAvailable = JNI_TRUE; + ctxInfo->textureExtMask |= javax_media_j3d_Canvas3D_TEXTURE_3D; + ctxInfo->texture_3D_ext_enum = GL_TEXTURE_3D_EXT; + ctxInfo->texture_wrap_r_ext_enum = GL_TEXTURE_WRAP_R_EXT; +#if defined(SOLARIS) || defined(__linux__) + ctxInfo->glTexImage3DEXT = (MYPFNGLTEXIMAGE3DPROC )glTexImage3DEXT; + ctxInfo->glTexSubImage3DEXT = (MYPFNGLTEXSUBIMAGE3DPROC )glTexSubImage3DEXT; + /* Fallback to non-EXT variants, needed for older + NVIDIA drivers which announce GL_EXT_texture3D but + don't have the EXT variants */ + if (ctxInfo->glTexImage3DEXT == NULL || + ctxInfo->glTexSubImage3DEXT == NULL) { + + ctxInfo->glTexImage3DEXT = + (MYPFNGLTEXIMAGE3DPROC) glTexImage3D; + ctxInfo->glTexSubImage3DEXT = + (MYPFNGLTEXSUBIMAGE3DPROC) glTexSubImage3D; + + if (ctxInfo->glTexImage3DEXT == NULL || + ctxInfo->glTexSubImage3DEXT == NULL) { + + ctxInfo->textureExtMask &= + ~javax_media_j3d_Canvas3D_TEXTURE_3D; + ctxInfo->texture3DAvailable = JNI_FALSE; + } + } + +#endif +#ifdef WIN32 + ctxInfo->glTexImage3DEXT = (MYPFNGLTEXIMAGE3DPROC )wglGetProcAddress("glTexImage3DEXT"); + ctxInfo->glTexSubImage3DEXT = (MYPFNGLTEXSUBIMAGE3DPROC )wglGetProcAddress("glTexSubImage3DEXT"); + if ((ctxInfo->glTexImage3DEXT == NULL) || (ctxInfo->glTexSubImage3DEXT == NULL)) { + ctxInfo->textureExtMask &= ~javax_media_j3d_Canvas3D_TEXTURE_3D; + ctxInfo->texture3DAvailable = JNI_FALSE; + } +#endif + } + + + if(isExtensionSupported(tmpExtensionStr, "GL_EXT_texture_edge_clamp")) { + ctxInfo->texture_clamp_to_edge_enum = GL_CLAMP_TO_EDGE_EXT; + } else if(isExtensionSupported(tmpExtensionStr, "GL_SGIS_texture_edge_clamp")) { + ctxInfo->texture_clamp_to_edge_enum = GL_CLAMP_TO_EDGE_SGIS; + } else { + /* fallback to GL_CLAMP */ + ctxInfo->texture_clamp_to_edge_enum = GL_CLAMP; + } + + + if(isExtensionSupported(tmpExtensionStr, "GL_EXT_blend_color")){ + ctxInfo->blend_color_ext = JNI_TRUE; +#if defined(SOLARIS) || defined(__linux__) + ctxInfo->glBlendColor = (MYPFNGLBLENDCOLOREXTPROC )glBlendColorEXT; +#endif +#ifdef WIN32 + ctxInfo->glBlendColor = (MYPFNGLBLENDCOLOREXTPROC )wglGetProcAddress("glBlendColorEXT"); + if (ctxInfo->glBlendColor == NULL) { + ctxInfo->blend_color_ext = JNI_FALSE; + } +#endif + ctxInfo->blendFunctionTable[7] = GL_CONSTANT_COLOR_EXT; + } + + if(isExtensionSupported(tmpExtensionStr,"GL_EXT_separate_specular_color" )){ + ctxInfo->seperate_specular_color = JNI_TRUE; + ctxInfo->light_model_color_control_enum = GL_LIGHT_MODEL_COLOR_CONTROL_EXT; + ctxInfo->single_color_enum = GL_SINGLE_COLOR_EXT; + ctxInfo->seperate_specular_color_enum = GL_SEPARATE_SPECULAR_COLOR_EXT ; + } + + if (isExtensionSupported(tmpExtensionStr,"GL_SGIS_texture_lod")) { + ctxInfo->textureLodAvailable = JNI_TRUE; + ctxInfo->textureExtMask |= javax_media_j3d_Canvas3D_TEXTURE_LOD_RANGE; + ctxInfo->texture_min_lod_enum = GL_TEXTURE_MIN_LOD_SGIS; + ctxInfo->texture_max_lod_enum = GL_TEXTURE_MAX_LOD_SGIS; + ctxInfo->texture_base_level_enum = GL_TEXTURE_BASE_LEVEL_SGIS; + ctxInfo->texture_max_level_enum = GL_TEXTURE_MAX_LEVEL_SGIS; + } + + + /* ... */ + } + + + + /* check extensions for remaining of 1.1 and 1.2 */ + if(isExtensionSupported(tmpExtensionStr, "GL_EXT_multi_draw_arrays")){ + ctxInfo->multi_draw_arrays_ext = JNI_TRUE; + } + if(isExtensionSupported(tmpExtensionStr, "GL_SUN_multi_draw_arrays")){ + ctxInfo->multi_draw_arrays_sun = JNI_TRUE; + } + + + if (isExtensionSupported(tmpExtensionStr, "GL_EXT_compiled_vertex_array") && + getJavaBoolEnv(env, "isCompliedVertexArray")) { + ctxInfo->compiled_vertex_array_ext = JNI_TRUE; + } + + + if(isExtensionSupported(tmpExtensionStr, "GLX_SUN_video_resize")){ + ctxInfo->videoResizeAvailable = JNI_TRUE; + ctxInfo->extMask |= javax_media_j3d_Canvas3D_SUN_VIDEO_RESIZE; + } + + if(isExtensionSupported(tmpExtensionStr, "GL_SUN_global_alpha")){ + ctxInfo->global_alpha_sun = JNI_TRUE; + } + + if(isExtensionSupported(tmpExtensionStr, "GL_SUNX_constant_data")){ + ctxInfo->constant_data_sun = JNI_TRUE; + } + + if(isExtensionSupported(tmpExtensionStr, "GL_EXT_abgr")) { + ctxInfo->abgr_ext = JNI_TRUE; + } + + if(isExtensionSupported(tmpExtensionStr, "GL_ARB_transpose_matrix")) { + ctxInfo->arb_transpose_matrix = JNI_TRUE; + } + + if(isExtensionSupported(tmpExtensionStr, "GL_SUNX_geometry_compression")) { + ctxInfo->geometry_compression_sunx = JNI_TRUE ; + } + +#if defined(SOLARIS) || defined(__linux__) + /* + * setup ARB_multisample, under windows this is setup in + * NativeConfigTemplate when pixel format is choose + */ + if (isExtensionSupported(tmpExtensionStr, "GL_ARB_multisample")){ + ctxInfo->arb_multisample = JNI_TRUE; + + } +#endif + +#ifdef WIN32 + wglGetPixelFormatAttribivEXT = (PFNWGLGETPIXELFORMATATTRIBIVEXTPROC) + wglGetProcAddress("wglGetPixelFormatAttribivARB"); + + if (wglGetPixelFormatAttribivEXT == NULL) { + wglGetPixelFormatAttribivEXT = (PFNWGLGETPIXELFORMATATTRIBIVEXTPROC) + wglGetProcAddress("wglGetPixelFormatAttribivEXT"); + } + + ctxInfo->arb_multisample = JNI_FALSE; + if (wglGetPixelFormatAttribivEXT != NULL) { + attr[0] = WGL_SAMPLE_BUFFERS_ARB; + attr[1] = WGL_SAMPLES_ARB; + attr[2] = 0; + + if (wglGetPixelFormatAttribivEXT((HDC) hdc, pixelFormat, 0, 2, attr, piValues)) { + if ((piValues[0] == TRUE) && (piValues[1] > 1)) { + ctxInfo->arb_multisample = JNI_TRUE; + } + } + } +#endif + + /* + * Disable multisample by default since OpenGL will enable + * it by default if the surface is multisample capable. + */ + if (ctxInfo->arb_multisample && !ctxInfo->implicit_multisample) { + glDisable(MULTISAMPLE_ARB); + } + /* + * checking of the texture extensions is done in checkTextureExtensions(), + * so that the same function can be used for queryContext as well + */ + checkTextureExtensions(env, obj, tmpExtensionStr, versionNumbers[1], + ctxInfo); + + + + + /* ... */ + + /* *********************************************************/ + /* Set up rescale_normal if extension supported */ + if (ctxInfo->rescale_normal_ext ) { + ctxInfo->extMask |= javax_media_j3d_Canvas3D_EXT_RESCALE_NORMAL; + } + + /* Setup the multi_draw_array */ + if(ctxInfo->multi_draw_arrays_ext) { + ctxInfo->extMask |= javax_media_j3d_Canvas3D_EXT_MULTI_DRAW_ARRAYS; + } else if (ctxInfo->multi_draw_arrays_sun) { + ctxInfo->extMask |= javax_media_j3d_Canvas3D_SUN_MULTI_DRAW_ARRAYS; + } + if(ctxInfo->compiled_vertex_array_ext) { + ctxInfo->extMask |= javax_media_j3d_Canvas3D_EXT_COMPILED_VERTEX_ARRAYS; + } + + + /* Setup GL_SUN_gloabl_alpha */ + if (ctxInfo->global_alpha_sun) { + ctxInfo->extMask |= javax_media_j3d_Canvas3D_SUN_GLOBAL_ALPHA; + } + + /* Setup GL_SUNX_constant_data */ + if (ctxInfo->constant_data_sun) { + ctxInfo->extMask |= javax_media_j3d_Canvas3D_SUN_CONSTANT_DATA; + } + + /* Setup GL_EXT_abgr */ + if (ctxInfo->abgr_ext) { + ctxInfo->extMask |= javax_media_j3d_Canvas3D_EXT_ABGR; + } + + /* Setup GL_BGR_EXT */ + if (ctxInfo->bgr_ext) { + ctxInfo->extMask |= javax_media_j3d_Canvas3D_EXT_BGR; + } + + /* Setup GL_ARB_transpose_matrix */ + if (ctxInfo->arb_transpose_matrix) { + ctxInfo->extMask |= javax_media_j3d_Canvas3D_ARB_TRANSPOSE_MATRIX; + } + + /* + * Check for compressed geometry extensions and see if hardware + * acceleration is supported in the runtime environment. + */ + if (ctxInfo->geometry_compression_sunx) { + cgHwStr = (char *)glGetString(GL_COMPRESSED_GEOM_ACCELERATED_SUNX) ; + } + + if (cgHwStr == 0 || strstr(cgHwStr, " ")) { + ctxInfo->geometry_compression_accelerated = 0 ; + + } else { + char *tmp = strdup(cgHwStr) ; + + ctxInfo->geometry_compression_accelerated_major_version = + atoi(strtok(tmp, ".")) ; + ctxInfo->geometry_compression_accelerated_minor_version = + atoi(strtok(0, ".")) ; + ctxInfo->geometry_compression_accelerated_subminor_version = + atoi(strtok(0, ".")) ; + + free(tmp) ; + ctxInfo->geometry_compression_accelerated = 1 ; + } + + + /* Setup GL_EXT_separate_specular_color */ + if(ctxInfo->seperate_specular_color) { + ctxInfo->extMask |= javax_media_j3d_Canvas3D_EXT_SEPARATE_SPECULAR_COLOR; + } + + if (ctxInfo->constant_data_sun) { + /* glPixelStorei(GL_UNPACK_CONSTANT_DATA_SUNX, GL_TRUE); */ + } + + if(ctxInfo->arb_multisample) { + ctxInfo->extMask |= javax_media_j3d_Canvas3D_ARB_MULTISAMPLE; + } + + /* setup those functions pointers */ +#ifdef WIN32 + + if (ctxInfo->multi_draw_arrays_ext) { + ctxInfo->glMultiDrawArraysEXT = (MYPFNGLMULTIDRAWARRAYSEXTPROC)wglGetProcAddress("glMultiDrawArraysEXT"); + ctxInfo->glMultiDrawElementsEXT = (MYPFNGLMULTIDRAWELEMENTSEXTPROC)wglGetProcAddress("glMultiDrawElementsEXT"); + if ((ctxInfo->glMultiDrawArraysEXT == NULL) || + (ctxInfo->glMultiDrawElementsEXT == NULL)) { + ctxInfo->multi_draw_arrays_ext = JNI_FALSE; + } + } + else if (ctxInfo->multi_draw_arrays_sun) { + ctxInfo->glMultiDrawArraysEXT = (MYPFNGLMULTIDRAWARRAYSEXTPROC)wglGetProcAddress("glMultiDrawArraysSUN"); + ctxInfo->glMultiDrawElementsEXT = (MYPFNGLMULTIDRAWELEMENTSEXTPROC)wglGetProcAddress("glMultiDrawElementsSUN"); + if ((ctxInfo->glMultiDrawArraysEXT == NULL) || + (ctxInfo->glMultiDrawElementsEXT == NULL)) { + ctxInfo->multi_draw_arrays_sun = JNI_FALSE; + } + + } + if (ctxInfo->compiled_vertex_array_ext) { + ctxInfo->glLockArraysEXT = (MYPFNGLLOCKARRAYSEXTPROC)wglGetProcAddress("glLockArraysEXT"); + ctxInfo->glUnlockArraysEXT = (MYPFNGLUNLOCKARRAYSEXTPROC)wglGetProcAddress("glUnlockArraysEXT"); + if ((ctxInfo->glLockArraysEXT == NULL) || + (ctxInfo->glUnlockArraysEXT == NULL)) { + ctxInfo->compiled_vertex_array_ext = JNI_FALSE; + } + } + + if (ctxInfo->arb_multitexture) { + ctxInfo->glClientActiveTextureARB = (MYPFNGLCLIENTACTIVETEXTUREARBPROC)wglGetProcAddress("glClientActiveTextureARB"); + ctxInfo->glMultiTexCoord2fvARB = (MYPFNGLMULTITEXCOORD2FVARBPROC)wglGetProcAddress("glMultiTexCoord2fvARB"); + ctxInfo->glMultiTexCoord3fvARB = (MYPFNGLMULTITEXCOORD3FVARBPROC)wglGetProcAddress("glMultiTexCoord3fvARB"); + ctxInfo->glMultiTexCoord4fvARB = (MYPFNGLMULTITEXCOORD4FVARBPROC)wglGetProcAddress("glMultiTexCoord4fvARB"); + ctxInfo->glActiveTextureARB = (MYPFNGLACTIVETEXTUREARBPROC) wglGetProcAddress("glActiveTextureARB"); + /* + if (ctxInfo->glClientActiveTextureARB == NULL) { + printf("ctxInfo->glClientActiveTextureARB == NULL\n"); + } + if (ctxInfo->glMultiTexCoord2fvARB == NULL) { + printf("ctxInfo->glMultiTexCoord2fvARB == NULL\n"); + } + if (ctxInfo->glMultiTexCoord3fvARB == NULL) { + printf("ctxInfo->glMultiTexCoord3fvARB == NULL\n"); + } + if (ctxInfo->glMultiTexCoord4fvARB == NULL) { + printf("ctxInfo->glMultiTexCoord4fvARB == NULL\n"); + } + if (ctxInfo->glActiveTextureARB == NULL) { + printf("ctxInfo->glActiveTextureARB == NULL\n"); + } + */ + if ((ctxInfo->glClientActiveTextureARB == NULL) || + (ctxInfo->glMultiTexCoord2fvARB == NULL) || + (ctxInfo->glMultiTexCoord3fvARB == NULL) || + (ctxInfo->glMultiTexCoord4fvARB == NULL) || + (ctxInfo->glActiveTextureARB == NULL)) { + ctxInfo->arb_multitexture = JNI_FALSE; + } + } + + if(ctxInfo->arb_transpose_matrix) { + ctxInfo->glLoadTransposeMatrixdARB = (MYPFNGLLOADTRANSPOSEMATRIXDARBPROC)wglGetProcAddress("glLoadTransposeMatrixdARB"); + ctxInfo->glMultTransposeMatrixdARB = (MYPFNGLMULTTRANSPOSEMATRIXDARBPROC)wglGetProcAddress("glMultTransposeMatrixdARB"); + /* + if (ctxInfo->glLoadTransposeMatrixdARB == NULL) { + printf("ctxInfo->glLoadTransposeMatrixdARB == NULL\n"); + } + if (ctxInfo->glMultTransposeMatrixdARB == NULL) { + printf("ctxInfo->glMultTransposeMatrixdARB == NULL\n"); + } + */ + if ((ctxInfo->glLoadTransposeMatrixdARB == NULL) || + (ctxInfo->glMultTransposeMatrixdARB == NULL)) { + ctxInfo->arb_transpose_matrix = JNI_FALSE; + } + } + + if (ctxInfo->global_alpha_sun) { + ctxInfo->glGlobalAlphaFactorfSUN = (MYPFNGLGLOBALALPHAFACTORFSUNPROC )wglGetProcAddress("glGlobalAlphaFactorfSUN"); + + if (ctxInfo->glGlobalAlphaFactorfSUN == NULL) { + /* printf("ctxInfo->glGlobalAlphaFactorfSUN == NULL\n");*/ + ctxInfo->global_alpha_sun = JNI_FALSE; + } + } + + + DescribePixelFormat((HDC) hdc, pixelFormat, sizeof(pfd), &pfd); + + stencilSize = pfd.cStencilBits; +#endif + +#if defined(SOLARIS) || defined(__linux__) + if(ctxInfo->multi_draw_arrays_ext) { + ctxInfo->glMultiDrawArraysEXT = glMultiDrawArraysEXT; + ctxInfo->glMultiDrawElementsEXT = glMultiDrawElementsEXT; + } + else if (ctxInfo->multi_draw_arrays_sun) { + ctxInfo->glMultiDrawArraysEXT = glMultiDrawArraysSUN; + ctxInfo->glMultiDrawElementsEXT = glMultiDrawElementsSUN; + } + if(ctxInfo->compiled_vertex_array_ext) { + ctxInfo->glLockArraysEXT = glLockArraysEXT; + ctxInfo->glUnlockArraysEXT = glUnlockArraysEXT; + } + + if(ctxInfo->arb_multitexture){ + ctxInfo->glClientActiveTextureARB = glClientActiveTextureARB; + ctxInfo->glMultiTexCoord2fvARB = glMultiTexCoord2fvARB; + ctxInfo->glMultiTexCoord3fvARB = glMultiTexCoord3fvARB; + ctxInfo->glMultiTexCoord4fvARB = glMultiTexCoord4fvARB; + ctxInfo->glActiveTextureARB = glActiveTextureARB; + } + if(ctxInfo->arb_transpose_matrix) { + ctxInfo->glLoadTransposeMatrixdARB = glLoadTransposeMatrixdARB; + ctxInfo->glMultTransposeMatrixdARB = glMultTransposeMatrixdARB; + } + if(ctxInfo->global_alpha_sun) + ctxInfo->glGlobalAlphaFactorfSUN = glGlobalAlphaFactorfSUN; + + + glXGetConfig((Display *) display, (XVisualInfo *) vinfo, GLX_STENCIL_SIZE, &stencilSize); + +#endif + + if (stencilSize > 1) { + ctxInfo->extMask |= javax_media_j3d_Canvas3D_STENCIL_BUFFER; + } + + + /* ... */ + + /* clearing up the memory */ + free(tmpExtensionStr); + free(tmpVersionStr); + return TRUE; +} + + +/* + * put properties to the java side + */ +void setupCanvasProperties( + JNIEnv *env, + jobject obj, + GraphicsContextPropertiesInfo *ctxInfo) +{ + jclass cv_class; + jfieldID rsc_field; + JNIEnv table = *env; + GLint param; + + cv_class = (jclass) (*(table->GetObjectClass))(env, obj); + + /* set the canvas.multiTexAccelerated flag */ + rsc_field = (jfieldID) (*(table->GetFieldID))(env, cv_class, "multiTexAccelerated", "Z"); + (*(table->SetBooleanField))(env, obj, rsc_field, ctxInfo->arb_multitexture); + + if (ctxInfo->arb_multitexture) { + rsc_field = (jfieldID) (*(table->GetFieldID))(env, cv_class, "numTexUnitSupported", "I"); + (*(table->SetIntField))(env, obj, rsc_field, ctxInfo->textureUnitCount); + rsc_field = (jfieldID) (*(table->GetFieldID))(env, cv_class, "numTexCoordSupported", "I"); + (*(table->SetIntField))(env, obj, rsc_field, ctxInfo->textureUnitCount); + } + + rsc_field = (jfieldID) (*(table->GetFieldID))(env, cv_class, "extensionsSupported", "I"); + (*(table->SetIntField))(env, obj, rsc_field, ctxInfo->extMask); + + rsc_field = (jfieldID) (*(table->GetFieldID))(env, cv_class, "textureExtendedFeatures", "I"); + (*(table->SetIntField))(env, obj, rsc_field, ctxInfo->textureExtMask); + + /* get texture color table size */ + rsc_field = (jfieldID) (*(table->GetFieldID))(env, cv_class, "textureColorTableSize", "I"); + (*(table->SetIntField))(env, obj, rsc_field, ctxInfo->textureColorTableSize); + + rsc_field = (jfieldID) (*(table->GetFieldID))(env, cv_class, "nativeGraphicsVersion", "Ljava/lang/String;"); + (*(table->SetObjectField))(env, obj, rsc_field, (*env)->NewStringUTF(env, ctxInfo->versionStr)); + + if (ctxInfo->textureAnisotropicFilterAvailable) { + + float degree; + + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, °ree); + rsc_field = (jfieldID) (*(table->GetFieldID))(env, cv_class, "anisotropicDegreeMax", "F"); + (*(table->SetFloatField))(env, obj, rsc_field, degree); + } + + rsc_field = (jfieldID) (*(table->GetFieldID))(env, cv_class, "textureBoundaryWidthMax", "I"); + (*(table->SetIntField))(env, obj, rsc_field, 1); + + glGetIntegerv(GL_MAX_TEXTURE_SIZE, ¶m); + rsc_field = (jfieldID) (*(table->GetFieldID))(env, cv_class, "textureWidthMax", "I"); + (*(table->SetIntField))(env, obj, rsc_field, param); + + rsc_field = (jfieldID) (*(table->GetFieldID))(env, cv_class, "textureHeightMax", "I"); + (*(table->SetIntField))(env, obj, rsc_field, param); +} + +JNIEXPORT +void JNICALL Java_javax_media_j3d_Canvas3D_destroyContext( + JNIEnv *env, + jclass cl, + jlong display, + jint window, + jlong ctxInfo) +{ + GraphicsContextPropertiesInfo* s = (GraphicsContextPropertiesInfo* )ctxInfo; + jlong context = s->context; + +#ifdef WIN32 + /* + * It is possible the window is removed by removeNotify() + * before the following is invoked : + * wglMakeCurrent((HDC)window, NULL); + * This will cause WinMe crash on swapBuffers() + */ + wglDeleteContext((HGLRC)context); +#endif /* WIN32 */ + +#if defined(SOLARIS) || defined(__linux__) + /* + glXMakeCurrent((Display *)display, (GLXDrawable)window, NULL); + */ + glXDestroyContext((Display *)display, (GLXContext)context); +#endif /* SOLARIS */ + /* cleanup CtxInfo and free its memory */ + cleanupCtxInfo(s); + + free(s); + + +} + +/* + * A dummy WndProc for dummy window + */ +#ifdef WIN32 +LONG WINAPI WndProc( HWND hWnd, UINT msg, + WPARAM wParam, LPARAM lParam ) +{ + + /* This function handles any messages that we didn't. */ + /* (Which is most messages) It belongs to the OS. */ + return DefWindowProc( hWnd, msg, wParam, lParam ); +} +#endif /*end of WIN32 */ + + + + +JNIEXPORT +jlong JNICALL Java_javax_media_j3d_Canvas3D_createContext( + JNIEnv *env, + jobject obj, + jlong display, + jint window, + jint vid, + jlong visInfo, + jlong sharedCtxInfo, + jboolean isSharedCtx, + jboolean offScreen) +{ + jlong gctx; + jlong sharedCtx; + + static GLboolean first_time = GL_TRUE; + static GLboolean force_normalize = GL_FALSE; + + GraphicsContextPropertiesInfo *ctxInfo = NULL; + GraphicsContextPropertiesInfo *sharedCtxStructure; + int PixelFormatID=0; + +#if defined(SOLARIS) || defined(__linux__) + GLXContext ctx; + jlong hdc; + + if(sharedCtxInfo == 0) + sharedCtx = 0; + else { + sharedCtxStructure = (GraphicsContextPropertiesInfo *)sharedCtxInfo; + sharedCtx = sharedCtxStructure->context; + } + + if (display == 0) { + fprintf(stderr, "Canvas3D_createContext: display is null\n"); + ctx = NULL; + } + else if (visInfo == 0) { + /* + * visInfo must be a valid pointer to an XVisualInfo struct returned + * by glXChooseVisual() for a physical screen. The visual id in vid + * is not sufficient for handling OpenGL with Xinerama mode disabled: + * it doesn't distinguish between the physical screens making up the + * virtual screen when the X server is running in Xinerama mode. + */ + fprintf(stderr, "Canvas3D_createContext: visual is null\n"); + ctx = NULL; + } + else { + ctx = glXCreateContext((Display *)display, (XVisualInfo *)visInfo, + (GLXContext)sharedCtx, True); + } + + + if (ctx == NULL) { + fprintf(stderr, "Canvas3D_createContext: couldn't create context\n"); + return 0; + } + + if (!glXMakeCurrent((Display *)display, (GLXDrawable)window, + (GLXContext)ctx)) { + fprintf( stderr, "Canvas3D_createContext: couldn't make current\n"); + return 0; + } + + gctx = (jlong)ctx; +#endif /* SOLARIS */ + +#ifdef WIN32 + HGLRC hrc; /* HW Rendering Context */ + HDC hdc; /* HW Device Context */ + jboolean rescale = JNI_FALSE; + JNIEnv table = *env; + DWORD err; + LPTSTR errString; + + + static PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), + 1, /* Version number */ + PFD_DRAW_TO_WINDOW | + PFD_SUPPORT_OPENGL| + PFD_DOUBLEBUFFER, + PFD_TYPE_RGBA, + 24, /* 24 bit color depth */ + 0, 0, 0, /* RGB bits and pixel sizes */ + 0, 0, 0, /* Do not care about them */ + 0, 0, /* no alpha buffer info */ + 0, 0, 0, 0, 0, /* no accumulation buffer */ + 32, /* 16 bit depth buffer */ + 0, /* no stencil buffer */ + 0, /* no auxiliary buffers */ + PFD_MAIN_PLANE, /* layer type */ + 0, /* reserved, must be 0 */ + 0, /* no layer mask */ + 0, /* no visible mask */ + 0 /* no damage mask */ + }; + + jboolean result; + + /* hWnd = (HWND) window; */ + /* or could use: hDC = GetDC(hWnd); */ + + if(sharedCtxInfo == 0) + sharedCtx = 0; + else { + sharedCtxStructure = (GraphicsContextPropertiesInfo *)sharedCtxInfo; + sharedCtx = sharedCtxStructure->context; + } + + + hdc = (HDC) window; + + if (offScreen) { + pfd.dwFlags = PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL | + PFD_SUPPORT_GDI; + vid = -1; + sharedCtx = 0; + } + + /* vid of -1 means no vid was specified - do the old way */ + if (vid == -1) { + /* choose the "pixel format", terminology is equivalent */ + /* to UNIX "visual" */ + PixelFormatID = ChoosePixelFormat(hdc, &pfd); + + if(PixelFormatID == 0) { + fprintf(stderr,"\nERROR: pixel format ID = 0"); + return 0; + } + } + else { + PixelFormatID = vid; + } + + + SetPixelFormat(hdc, PixelFormatID, &pfd); + + hrc = wglCreateContext( hdc ); + + if (!hrc) { + err = GetLastError(); + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, err, 0, (LPTSTR)&errString, 0, NULL); + + fprintf(stderr, "wglCreateContext Failed: %s\n", errString); + return 0; + } + + if (sharedCtx != 0) { + wglShareLists( (HGLRC) sharedCtx, hrc ); + } + + result = wglMakeCurrent(hdc, hrc); + + if (!result) { + err = GetLastError(); + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, err, 0, (LPTSTR)&errString, 0, NULL); + fprintf(stderr, "wglMakeCurrent Failed: %s\n", errString); + return 0; + } + + gctx = (jlong)hrc; +#endif /* WIN32 */ + + /* allocate the structure */ + ctxInfo = (GraphicsContextPropertiesInfo *)malloc(sizeof(GraphicsContextPropertiesInfo)); + + /* initialize the structure */ + initializeCtxInfo(env, ctxInfo); + ctxInfo->context = gctx; + + if (!getPropertiesFromCurrentContext(env, obj, ctxInfo, (jlong) hdc, PixelFormatID, display, (jlong) visInfo)) { + return 0; + } + + + /* setup structure */ + + if(!isSharedCtx){ + /* Setup field in Java side */ + setupCanvasProperties(env, obj, ctxInfo); + } + + /* Set up rescale_normal if extension supported */ + if (first_time && getJavaBoolEnv(env, "isForceNormalized")) { + force_normalize = GL_TRUE; + first_time = GL_FALSE; + } + + if (force_normalize) { + /* Disable rescale normal */ + ctxInfo->rescale_normal_ext = GL_FALSE; + } + + if (ctxInfo->rescale_normal_ext ) { + glEnable(ctxInfo->rescale_normal_ext_enum); + } + else { + glEnable(GL_NORMALIZE); + } + + glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); + glDepthFunc(GL_LEQUAL); + glEnable(GL_COLOR_MATERIAL); + glReadBuffer(GL_FRONT); + return ((jlong)ctxInfo); +} + + +JNIEXPORT +void JNICALL Java_javax_media_j3d_Canvas3D_useCtx( + JNIEnv *env, + jclass cl, + jlong ctxInfo, + jlong display, + jint window) +{ + GraphicsContextPropertiesInfo *ctxProperties = (GraphicsContextPropertiesInfo *)ctxInfo; + jlong ctx = ctxProperties->context; +#if defined(SOLARIS) || defined(__linux__) + glXMakeCurrent((Display *)display, (GLXDrawable)window, (GLXContext)ctx); +#endif + +#ifdef WIN32 + wglMakeCurrent((HDC) window, (HGLRC) ctx); +#endif +} + +JNIEXPORT +jint JNICALL Java_javax_media_j3d_Canvas3D_getNumCtxLights( + JNIEnv *env, + jobject obj, + jlong ctxInfo) +{ + GLint nlights; + + glGetIntegerv(GL_MAX_LIGHTS, &nlights); + return((jint)nlights); +} + + + +JNIEXPORT +void JNICALL Java_javax_media_j3d_Canvas3D_composite( + JNIEnv *env, + jobject obj, + jlong ctxInfo, + jint px, + jint py, + jint minX, + jint minY, + jint maxX, + jint maxY, + jint rasWidth, + jbyteArray imageYdown, + jint winWidth, + jint winHeight) +{ + GLenum gltype; + JNIEnv table; + jbyte *byteData; + GraphicsContextPropertiesInfo *ctxProperties = (GraphicsContextPropertiesInfo *)ctxInfo; + jlong ctx = ctxProperties->context; + GLboolean tex3d, texCubeMap; + + table = *env; + +#ifdef VERBOSE + fprintf(stderr, "Canvas3D.composite()\n"); +#endif + /* temporarily disable fragment operations */ + /* TODO: the GL_TEXTURE_BIT may not be necessary */ + glPushAttrib(GL_ENABLE_BIT|GL_TEXTURE_BIT|GL_DEPTH_BUFFER_BIT); + + if(ctxProperties->texture3DAvailable) + tex3d = glIsEnabled(ctxProperties->texture_3D_ext_enum); + + if(ctxProperties->textureCubeMapAvailable) + texCubeMap = glIsEnabled(ctxProperties->texture_cube_map_ext_enum); + + glDisable(GL_DEPTH_TEST); + glDisable(GL_FOG); + glDisable(GL_LIGHTING); + glDisable(GL_TEXTURE_2D); + if(ctxProperties->texture3DAvailable) + glDisable(ctxProperties->texture_3D_ext_enum); + if(ctxProperties->textureCubeMapAvailable) + glDisable(ctxProperties->texture_cube_map_ext_enum); + + glEnable(GL_BLEND); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + /* loaded identity modelview and projection matrix */ + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0.0, (double)winWidth, 0.0, (double)winHeight, -1.0, 1.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + /* start from upper left corner */ + glRasterPos2i(px + minX, winHeight-(py + minY)); + + glPixelZoom(1.0, -1.0); + + byteData = (jbyte *)(*(table->GetPrimitiveArrayCritical))(env, + imageYdown, + NULL); + /* if abgr_ext is supported then the data will be in that format */ + if (ctxProperties->abgr_ext) { + gltype = GL_ABGR_EXT; + } else { + gltype = GL_RGBA; + } + + /* + * set the actual width of data which is the width of the canvas + * because what needs to be drawn may be smaller than the canvas + */ + glPixelStorei(GL_UNPACK_ROW_LENGTH, rasWidth); + + /* + * we only need to skip pixels if width of the area to draw is smaller + * than the width of the raster + */ + + /* + * skip this many rows in the data because the size of what + * needs to be drawn may be smaller than the canvas + */ + glPixelStorei(GL_UNPACK_SKIP_ROWS, minY); + /* + * skip this many pixels in the data before drawing because + * the size of what needs to be drawn may be smaller than the + * canvas + */ + glPixelStorei(GL_UNPACK_SKIP_PIXELS, minX); + + + glDrawPixels(maxX - minX, maxY - minY, + gltype, GL_UNSIGNED_BYTE, byteData); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + + glMatrixMode(GL_PROJECTION); + + glLoadIdentity(); + + (*(table->ReleasePrimitiveArrayCritical))(env, imageYdown, byteData, 0); + + /* re-enable fragment operation if necessary */ + if(ctxProperties->texture3DAvailable) + if (tex3d) glEnable(ctxProperties->texture_3D_ext_enum); + + if(ctxProperties->textureCubeMapAvailable) + if (texCubeMap) glEnable(ctxProperties->texture_cube_map_ext_enum); + + /* Java 3D always clears the Z-buffer */ + glDepthMask(GL_TRUE); + glClear(GL_DEPTH_BUFFER_BIT); + + glPopAttrib(); +} + + +JNIEXPORT +jboolean JNICALL Java_javax_media_j3d_Canvas3D_initTexturemapping( + JNIEnv *env, + jobject obj, + jlong ctxInfo, + jint texWidth, + jint texHeight, + jint objectId) +{ + GraphicsContextPropertiesInfo *ctxProperties = + (GraphicsContextPropertiesInfo *)ctxInfo; + GLint gltype; + GLint width; + + gltype = (ctxProperties->abgr_ext ? GL_ABGR_EXT : GL_RGBA); + + glBindTexture(GL_TEXTURE_2D, objectId); + + + glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, texWidth, + texHeight, 0, gltype, GL_UNSIGNED_BYTE, NULL); + + glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, + GL_TEXTURE_WIDTH, &width); + + if (width <= 0) { + return JNI_FALSE; + } + + /* init texture size only without filling the pixels */ + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, + texHeight, 0, gltype, GL_UNSIGNED_BYTE, NULL); + + + return JNI_TRUE; +} + + +JNIEXPORT +void JNICALL Java_javax_media_j3d_Canvas3D_texturemapping( + JNIEnv *env, + jobject obj, + jlong ctxInfo, + jint px, + jint py, + jint minX, + jint minY, + jint maxX, + jint maxY, + jint texWidth, + jint texHeight, + jint rasWidth, + jint format, + jint objectId, + jbyteArray imageYdown, + jint winWidth, + jint winHeight) +{ + JNIEnv table; + GLint gltype; + GLfloat texMinU,texMinV,texMaxU,texMaxV; + GLfloat mapMinX,mapMinY,mapMaxX,mapMaxY; + GLfloat halfWidth,halfHeight; + jbyte *byteData; + GraphicsContextPropertiesInfo *ctxProperties = (GraphicsContextPropertiesInfo *)ctxInfo; + jlong ctx = ctxProperties->context; + GLboolean tex3d, texCubeMap; + + table = *env; + gltype = GL_RGBA; + + /* temporary disable fragment operation */ + glPushAttrib(GL_ENABLE_BIT|GL_TEXTURE_BIT|GL_DEPTH_BUFFER_BIT); + + if (ctxProperties->texture3DAvailable) { + tex3d = glIsEnabled(ctxProperties->texture_3D_ext_enum); + } + + if (ctxProperties->textureCubeMapAvailable) { + texCubeMap = glIsEnabled(ctxProperties->texture_cube_map_ext_enum); + } + glDisable(GL_ALPHA_TEST); + glDisable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + glDisable(GL_FOG); + glDisable(GL_LIGHTING); + glDisable(GL_TEXTURE_2D); + if (ctxProperties->texture3DAvailable) { + glDisable(ctxProperties->texture_3D_ext_enum); + } + if (ctxProperties->textureCubeMapAvailable) { + glDisable(ctxProperties->texture_cube_map_ext_enum); + } + /* glGetIntegerv(GL_TEXTURE_BINDING_2D,&binding); */ + glDepthMask(GL_FALSE); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glBindTexture(GL_TEXTURE_2D, objectId); + /* set up texture parameter */ + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + +#ifdef VERBOSE + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); +#endif + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glEnable(GL_TEXTURE_2D); + + /* glGetIntegerv (GL_VIEWPORT, viewport); */ + + /* loaded identity modelview and projection matrix */ + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + glOrtho(0.0, (double)winWidth, 0.0, (double)winHeight,0.0, 0.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + byteData = (jbyte *)(*(table->GetPrimitiveArrayCritical))(env, + imageYdown, + NULL); + + if (ctxProperties->abgr_ext) { + gltype = GL_ABGR_EXT; + } else { + switch (format) { + case FORMAT_BYTE_RGBA: + gltype = GL_RGBA; + break; + case FORMAT_BYTE_RGB: + gltype = GL_RGB; + break; + } + } + glPixelStorei(GL_UNPACK_ROW_LENGTH, rasWidth); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, minX); + glPixelStorei(GL_UNPACK_SKIP_ROWS, minY); + glTexSubImage2D(GL_TEXTURE_2D, 0, minX, minY, + maxX - minX, maxY - minY, + gltype, GL_UNSIGNED_BYTE, + byteData); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + + + (*(table->ReleasePrimitiveArrayCritical))(env, imageYdown, byteData, 0); + + texMinU = (float) minX/ (float) texWidth; + texMinV = (float) minY/ (float) texHeight; + texMaxU = (float) maxX/ (float) texWidth; + texMaxV = (float) maxY/ (float) texHeight; + halfWidth = (GLfloat)winWidth/2.0f; + halfHeight = (GLfloat)winHeight/2.0f; + + mapMinX = (float) (((px + minX)- halfWidth)/halfWidth); + mapMinY = (float) ((halfHeight - (py + maxY))/halfHeight); + mapMaxX = (float) ((px + maxX - halfWidth)/halfWidth); + mapMaxY = (float) ((halfHeight - (py + minY))/halfHeight); + +#ifdef VERBOSE + printf("(texMinU,texMinV,texMaxU,texMaxV) = (%3.2f,%3.2f,%3.2f,%3.2f)\n", + texMinU,texMinV,texMaxU,texMaxV); + printf("(mapMinX,mapMinY,mapMaxX,mapMaxY) = (%3.2f,%3.2f,%3.2f,%3.2f)\n", + mapMinX,mapMinY,mapMaxX,mapMaxY); + +#endif + glBegin(GL_QUADS); + + glTexCoord2f(texMinU, texMaxV); glVertex2f(mapMinX,mapMinY); + glTexCoord2f(texMaxU, texMaxV); glVertex2f(mapMaxX,mapMinY); + glTexCoord2f(texMaxU, texMinV); glVertex2f(mapMaxX,mapMaxY); + glTexCoord2f(texMinU, texMinV); glVertex2f(mapMinX,mapMaxY); + glEnd(); + + /* re-enable fragment operation if necessary */ + if (ctxProperties->texture3DAvailable) + if (tex3d) glEnable(ctxProperties->texture_3D_ext_enum); + + if (ctxProperties->textureCubeMapAvailable) + if (texCubeMap) glEnable(ctxProperties->texture_cube_map_ext_enum); + + + /* Java 3D always clears the Z-buffer */ + glDepthMask(GL_TRUE); + glClear(GL_DEPTH_BUFFER_BIT); + glPopAttrib(); +} + +JNIEXPORT +void JNICALL Java_javax_media_j3d_Canvas3D_clear( + JNIEnv *env, + jobject obj, + jlong ctxInfo, + jfloat r, + jfloat g, + jfloat b, + jint winWidth, + jint winHeight, + jobject pa2d, + jint imageScaleMode, + jbyteArray pixels_obj) + +{ + jclass pa2d_class; + jfieldID format_field, width_field, height_field; + int format, width, height; + GLubyte * pixels; + JNIEnv table; + GLenum gltype; + float xzoom, yzoom, zoom; + float rasterX, rasterY; + int repeatX, repeatY, i, j; + int row_length, skip_pixels, skip_rows, subwidth, subheight; + GraphicsContextPropertiesInfo *ctxProperties = (GraphicsContextPropertiesInfo *)ctxInfo; + jlong ctx = ctxProperties->context; + table = *env; + +#ifdef VERBOSE + fprintf(stderr, "Canvas3D.clear()\n"); +#endif + + if(!pa2d) { + glClearColor((float)r, (float)g, (float)b, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + } + else { + GLboolean tex3d, texCubeMap; + + /* Do a cool image blit */ + pa2d_class = (jclass) (*(table->GetObjectClass))(env, pa2d); + format_field = (jfieldID) (*(table->GetFieldID))(env, pa2d_class, + "storedYdownFormat", "I"); + width_field = (jfieldID) (*(table->GetFieldID))(env, pa2d_class, + "width", "I"); + height_field = (jfieldID) (*(table->GetFieldID))(env, pa2d_class, + "height", "I"); + + format = (int) (*(table->GetIntField))(env, pa2d, format_field); + width = (int) (*(table->GetIntField))(env, pa2d, width_field); + height = (int) (*(table->GetIntField))(env, pa2d, height_field); + + pixels = (GLubyte *) (*(table->GetPrimitiveArrayCritical))(env, + pixels_obj, NULL); + + /* temporarily disable fragment operations */ + /* TODO: the GL_TEXTURE_BIT may not be necessary */ + glPushAttrib(GL_ENABLE_BIT|GL_TEXTURE_BIT); + + if(ctxProperties->texture3DAvailable) + tex3d = glIsEnabled(ctxProperties->texture_3D_ext_enum); + + if(ctxProperties->textureCubeMapAvailable) + texCubeMap = glIsEnabled(ctxProperties->texture_cube_map_ext_enum); + + glDisable(GL_ALPHA_TEST); + glDisable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + glDisable(GL_FOG); + glDisable(GL_LIGHTING); + glDisable(GL_TEXTURE_2D); + if(ctxProperties->texture3DAvailable) + glDisable(ctxProperties->texture_3D_ext_enum); + + if(ctxProperties->textureCubeMapAvailable) + glDisable(ctxProperties->texture_cube_map_ext_enum); + + /* loaded identity modelview and projection matrix */ + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + switch (format) { + case FORMAT_BYTE_RGBA: + gltype = GL_RGBA; + break; + case FORMAT_BYTE_RGB: + gltype = GL_RGB; + break; + + case FORMAT_BYTE_ABGR: + if (ctxProperties->abgr_ext) { /* If its zero, should never come here! */ + gltype = GL_ABGR_EXT; + } + break; + + case FORMAT_BYTE_BGR: + if (ctxProperties->bgr_ext) { /* If its zero, should never come here! */ + gltype = ctxProperties->bgr_ext_enum ; + } + break; + + case FORMAT_BYTE_LA: + gltype = GL_LUMINANCE_ALPHA; + break; + case FORMAT_BYTE_GRAY: + case FORMAT_USHORT_GRAY: + /* TODO: throw exception */ + break; + } + + /* start from upper left corner */ + glRasterPos3f(-1.0, 1.0, 0.0); + + /* setup the pixel zoom */ + xzoom = (float)winWidth/width; + yzoom = (float)winHeight/height; + switch(imageScaleMode){ + case javax_media_j3d_Background_SCALE_NONE: + if(xzoom > 1.0f || yzoom > 1.0f) + { + /* else don't need to clear the background with background color */ + glClearColor((float)r, (float)g, (float)b, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + } + glPixelZoom(1.0, -1.0); + glDrawPixels(width, height, gltype, GL_UNSIGNED_BYTE, + pixels); + + break; + case javax_media_j3d_Background_SCALE_FIT_MIN: + if(xzoom != yzoom ) { + glClearColor((float)r, (float)g, (float)b, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + } + zoom = xzoom < yzoom? xzoom:yzoom; + glPixelZoom(zoom, -zoom); + glDrawPixels(width, height, gltype, GL_UNSIGNED_BYTE, + pixels); + + break; + case javax_media_j3d_Background_SCALE_FIT_MAX: + zoom = xzoom > yzoom? xzoom:yzoom; + glPixelZoom(zoom, -zoom); + glDrawPixels(width, height, gltype, GL_UNSIGNED_BYTE, + pixels); + + break; + case javax_media_j3d_Background_SCALE_FIT_ALL: + glPixelZoom(xzoom, -yzoom); + glDrawPixels(width, height, gltype, GL_UNSIGNED_BYTE, + pixels); + break; + case javax_media_j3d_Background_SCALE_REPEAT: + glPixelZoom(1.0, -1.0); + /* get those raster positions */ + repeatX = winWidth/width; + if(repeatX * width < winWidth) + repeatX++; + repeatY = winHeight/height; + if(repeatY * height < winHeight) + repeatY++; + for(i = 0; i < repeatX; i++) + for(j = 0; j < repeatY; j++) { + rasterX = -1.0f + (float)width/winWidth * i * 2; + rasterY = 1.0f - (float)height/winHeight * j * 2; + glRasterPos3f(rasterX, rasterY, 0.0); + glDrawPixels(width, height, gltype, GL_UNSIGNED_BYTE, + pixels); + } + break; + + case javax_media_j3d_Background_SCALE_NONE_CENTER: + if(xzoom > 1.0f || yzoom > 1.0f){ + glClearColor((float)r, (float)g, (float)b, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + } + if(xzoom >= 1.0f){ + rasterX = -(float)width/winWidth; + subwidth = width; + } + else { + rasterX = -1.0; + row_length = width; + glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); + skip_pixels = (width-winWidth)/2; + glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels); + subwidth = winWidth; + } + if(yzoom >= 1.0f){ + rasterY = (float)height/winHeight; + subheight = height; + } + else { + rasterY = 1.0f; + skip_rows = (height-winHeight)/2; + glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows); + subheight = winHeight; + } + glRasterPos3f(rasterX, rasterY, 0.0); + glPixelZoom(1.0, -1.0); + glDrawPixels(subwidth, subheight, gltype, GL_UNSIGNED_BYTE, + pixels); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + break; + } + /* re-enable fragment operation if necessary */ + glPopAttrib(); + + if(ctxProperties->texture3DAvailable) + if (tex3d) glEnable(ctxProperties->texture_3D_ext_enum); + + if(ctxProperties->textureCubeMapAvailable) + if (texCubeMap) glEnable(ctxProperties->texture_cube_map_ext_enum); + + (*(table->ReleasePrimitiveArrayCritical))(env, pixels_obj, + (jbyte *)pixels, 0); + } + /* Java 3D always clears the Z-buffer */ + glPushAttrib(GL_DEPTH_BUFFER_BIT); + glDepthMask(GL_TRUE); + glClear(GL_DEPTH_BUFFER_BIT); + glPopAttrib(); +} + +JNIEXPORT +void JNICALL Java_javax_media_j3d_Canvas3D_textureclear(JNIEnv *env, + jobject obj, + jlong ctxInfo, + jint maxX, + jint maxY, + jfloat r, + jfloat g, + jfloat b, + jint winWidth, + jint winHeight, + jint objectId, + jint imageScaleMode, + jobject pa2d, + jboolean update) +{ + jclass pa2d_class; + jfieldID pixels_field, format_field, width_field, height_field; + jbyteArray pixels_obj; + int format, width, height; + GLubyte * pixels; + JNIEnv table; + GLenum gltype; + GLfloat texMinU, texMinV, texMaxU, texMaxV, adjustV; + GLfloat mapMinX, mapMinY, mapMaxX, mapMaxY; + GLfloat halfWidth, halfHeight; + float xzoom, yzoom, zoom; + int i, j; + GraphicsContextPropertiesInfo *ctxProperties = (GraphicsContextPropertiesInfo *)ctxInfo; + jlong ctx = ctxProperties->context; + + table = *env; + + /* update = 1; */ + +#ifdef VERBOSE + fprintf(stderr, "Canvas3D.textureclear()\n"); +#endif + if(!pa2d){ + glClearColor((float)r, (float)g, (float)b, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + } + /* glPushAttrib(GL_DEPTH_BUFFER_BIT); */ + if (pa2d) { + GLboolean tex3d, texCubeMap; + + + /* Do a cool image blit */ + pa2d_class = (jclass) (*(table->GetObjectClass))(env, pa2d); + + pixels_field = (jfieldID) (*(table->GetFieldID))(env, pa2d_class, + "imageYup", "[B"); + format_field = (jfieldID) (*(table->GetFieldID))(env, pa2d_class, + "storedYupFormat", "I"); + pixels_obj = (jbyteArray)(*(table->GetObjectField))(env, pa2d, + pixels_field); + + width_field = (jfieldID) (*(table->GetFieldID))(env, pa2d_class, + "width", "I"); + height_field = (jfieldID) (*(table->GetFieldID))(env, pa2d_class, + "height", "I"); + + format = (int) (*(table->GetIntField))(env, pa2d, format_field); + width = (int) (*(table->GetIntField))(env, pa2d, width_field); + height = (int) (*(table->GetIntField))(env, pa2d, height_field); + pixels = (GLubyte *) (*(table->GetPrimitiveArrayCritical))(env, + pixels_obj, NULL); + +#ifdef VERBOSE + fprintf(stderr, "width = %d height = %d \n", width, height); +#endif + + /* temporary disable fragment operation */ + glPushAttrib(GL_ENABLE_BIT|GL_TEXTURE_BIT|GL_POLYGON_BIT); + + if(ctxProperties->texture3DAvailable) + tex3d = glIsEnabled(ctxProperties->texture_3D_ext_enum); + if(ctxProperties->textureCubeMapAvailable) + texCubeMap = glIsEnabled(ctxProperties->texture_cube_map_ext_enum); + glDisable(GL_ALPHA_TEST); + glDisable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + glDisable(GL_FOG); + glDisable(GL_LIGHTING); + + if(ctxProperties->texture3DAvailable) + glDisable(ctxProperties->texture_3D_ext_enum); + + if(ctxProperties->textureCubeMapAvailable) + glDisable(ctxProperties->texture_cube_map_ext_enum); + + Java_javax_media_j3d_Canvas3D_resetTexCoordGeneration(env, obj, ctxInfo); + + glEnable(GL_TEXTURE_2D); + + /* reset the polygon mode */ + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + glDepthMask(GL_FALSE); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glBindTexture(GL_TEXTURE_2D, objectId); + + /* set up texture parameter */ + if(update){ + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + } +#ifdef VERBOSE + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); +#endif + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + + + + if(update){ + switch (format) { + case FORMAT_BYTE_RGBA: + gltype = GL_RGBA; +#ifdef VERBOSE + fprintf(stderr, "FORMAT_BYTE_RGBA\n"); +#endif + break; + case FORMAT_BYTE_RGB: + gltype = GL_RGB; +#ifdef VERBOSE + fprintf(stderr, "FORMAT_BYTE_RGB\n"); +#endif + break; + + /* GL_ABGR_EXT */ + case FORMAT_BYTE_ABGR: + if (ctxProperties->abgr_ext) { /* If its zero, should never come here! */ + gltype = GL_ABGR_EXT; + } + break; + + /* GL_BGR_EXT or GL_BGR */ + case FORMAT_BYTE_BGR: + if (ctxProperties->bgr_ext) { /* If its zero, should never come here! */ + gltype = ctxProperties->bgr_ext_enum; + } + break; + + case FORMAT_BYTE_LA: + gltype = GL_LUMINANCE_ALPHA; + break; + case FORMAT_BYTE_GRAY: + case FORMAT_USHORT_GRAY: + /* TODO: throw exception */ + break; + } + + /* texture map here! */ + glTexImage2D(GL_TEXTURE_2D, 0, gltype, width, + height, 0, gltype, GL_UNSIGNED_BYTE, + pixels); + } + /* loaded identity modelview and projection matrix */ + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glMatrixMode(GL_TEXTURE); + glPushMatrix(); + glLoadIdentity(); + + xzoom = (float)winWidth/maxX; + yzoom = (float)winHeight/maxY; + switch(imageScaleMode) { + case javax_media_j3d_Background_SCALE_NONE: + if(xzoom > 1.0f || yzoom > 1.0f){ + glClearColor((float)r, (float)g, (float)b, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + } + texMinU = 0.0f; + texMinV = 0.0f; + texMaxU = 1.0f; + texMaxV = 1.0f; + halfWidth = (GLfloat)winWidth/2.0f; + halfHeight = (GLfloat)winHeight/2.0f; + mapMinX = (float) ((0 - halfWidth)/halfWidth); + mapMinY = (float) ((0 - halfHeight)/halfHeight); + mapMaxX = (float) ((maxX - halfWidth)/halfWidth); + mapMaxY = (float) ((maxY - halfHeight)/halfHeight); + adjustV = ((float)winHeight - (float)maxY)/halfHeight; + mapMinY += adjustV; + mapMaxY += adjustV; + break; + case javax_media_j3d_Background_SCALE_FIT_MIN: + if(xzoom != yzoom){ + glClearColor((float)r, (float)g, (float)b, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + } + + zoom = xzoom < yzoom? xzoom: yzoom; + texMinU = 0.0f; + texMinV = 0.0f; + texMaxU = 1.0f; + texMaxV = 1.0f; + mapMinX = -1.0f; + mapMaxY = 1.0f; + if(xzoom < yzoom){ + mapMaxX = 1.0f; + mapMinY = -1.0f + 2.0f * ( 1.0f - zoom * (float)maxY/(float) winHeight ); + } else { + mapMaxX = -1.0f + zoom * (float)maxX/winWidth * 2; + mapMinY = -1.0f; + } + break; + case javax_media_j3d_Background_SCALE_FIT_MAX: + zoom = xzoom > yzoom? xzoom: yzoom; + /*fprintf(stderr, "zoom: %f, xzoom: %f, yzoom: %f\n", zoom, xzoom, yzoom);*/ + mapMinX = -1.0f; + mapMinY = -1.0f; + mapMaxX = 1.0f; + mapMaxY = 1.0f; + if(xzoom < yzoom) { + texMinU = 0.0f; + texMinV = 0.0f; + texMaxU = (float)winWidth/maxX/zoom; + texMaxV = 1.0f; + } else { + texMinU = 0.0f; + texMinV = 1.0f - (float)winHeight/maxY/zoom; + texMaxU = 1.0f; + texMaxV = 1.0f; + } + break; + case javax_media_j3d_Background_SCALE_FIT_ALL: + texMinU = 0.0f; + texMinV = 0.0f; + texMaxU = 1.0f; + texMaxV = 1.0f; + mapMinX = -1.0f; + mapMinY = -1.0f; + mapMaxX = 1.0f; + mapMaxY = 1.0f; + break; + case javax_media_j3d_Background_SCALE_REPEAT: + /* glScalef(1.0f, -1.0f, 1.0f); */ + i = winWidth/width; + j = winHeight/height; + texMinU = 0.0f; + texMinV = (float)(j + 1) - yzoom; + texMaxU = xzoom; + texMaxV = (float)(j + 1); + mapMinX = -1.0f; + mapMinY = -1.0f; + mapMaxX = 1.0f; + mapMaxY = 1.0f; + break; + case javax_media_j3d_Background_SCALE_NONE_CENTER: + if(xzoom > 1.0f || yzoom > 1.0f){ + glClearColor((float)r, (float)g, (float)b, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + } + if(xzoom >= 1.0f){ + texMinU = 0.0f; + texMaxU = 1.0f; + mapMinX = -(float)maxX/winWidth; + mapMaxX = (float)maxX/winWidth; + } else { + texMinU = 0.5f - (float)winWidth/maxX/2; + texMaxU = 0.5f + (float)winWidth/maxX/2; + mapMinX = -1.0f; + mapMaxX = 1.0f; + } + if(yzoom >= 1.0f) { + texMinV = 0.0f; + texMaxV = 1.0f; + mapMinY = -(float)maxY/winHeight; + mapMaxY = (float)maxY/winHeight; + }else { + texMinV = 0.5f - (float)winHeight/maxY/2; + texMaxV = 0.5f + (float)winHeight/maxY/2; + mapMinY = -1.0f; + mapMaxY = 1.0f; + } + break; + } +#ifdef VERBOSE + printf("adjustV = %3.2f\n",adjustV); + printf("(texMinU,texMinV,texMaxU,texMaxV) = (%3.2f,%3.2f,%3.2f,%3.2f)\n", + texMinU,texMinV,texMaxU,texMaxV); + printf("(mapMinX,mapMinY,mapMaxX,mapMaxY) = (%3.2f,%3.2f,%3.2f,%3.2f)\n", + mapMinX,mapMinY,mapMaxX,mapMaxY); +#endif + + + glBegin(GL_QUADS); +#ifdef VERBOSE + /* glTexCoord2f(0.2, 0.2); glVertex2f(0.0,0.0); */ + /* glTexCoord2f(0.4, 0.2); glVertex2f(0.2,0.0); */ + /* glTexCoord2f(0.4, 0.4); glVertex2f(0.2,0.2); */ + /* glTexCoord2f(0.2, 0.4); glVertex2f(0.0,0.2); */ + glColor3f(1.0, 0.0, 0.0); +#endif + glTexCoord2f(texMinU, texMinV); glVertex2f(mapMinX,mapMinY); + glTexCoord2f(texMaxU, texMinV); glVertex2f(mapMaxX,mapMinY); + glTexCoord2f(texMaxU, texMaxV); glVertex2f(mapMaxX,mapMaxY); + glTexCoord2f(texMinU, texMaxV); glVertex2f(mapMinX,mapMaxY); + glEnd(); + + /* Restore texture Matrix transform */ + glPopMatrix(); + + glMatrixMode(GL_MODELVIEW); + /* re-enable fragment operation if necessary */ + glPopAttrib(); + if(ctxProperties->texture3DAvailable) + if (tex3d) glEnable(ctxProperties->texture_3D_ext_enum); + + if(ctxProperties->textureCubeMapAvailable) + if (texCubeMap) glEnable(ctxProperties->texture_cube_map_ext_enum); + + (*(table->ReleasePrimitiveArrayCritical))(env, pixels_obj, + (jbyte *)pixels, 0); + } + + /* Java 3D always clears the Z-buffer */ + glPushAttrib(GL_DEPTH_BUFFER_BIT); + glDepthMask(GL_TRUE); + glClear(GL_DEPTH_BUFFER_BIT); + glPopAttrib(); + +} + +JNIEXPORT +void JNICALL Java_javax_media_j3d_Canvas3D_setRenderMode( + JNIEnv *env, + jobject obj, + jlong ctxInfo, + jint mode, + jboolean dbEnable) +{ + GLint drawBuf; + + if (dbEnable) { + drawBuf = GL_BACK; + switch (mode) { + case 0: /* FIELD_LEFT */ + drawBuf = GL_BACK_LEFT; + break; + case 1: /* FIELD_RIGHT */ + drawBuf = GL_BACK_RIGHT; + break; + case 2: /* FIELD_ALL */ + drawBuf = GL_BACK; + break; + } + } + else { + drawBuf = GL_FRONT; + switch (mode) { + case 0: /* FIELD_LEFT */ + drawBuf = GL_FRONT_LEFT; + break; + case 1: /* FIELD_RIGHT */ + drawBuf = GL_FRONT_RIGHT; + break; + case 2: /* FIELD_ALL */ + drawBuf = GL_FRONT; + break; + } + } + +#ifdef VERBOSE + switch (drawBuf) { + case GL_FRONT_LEFT: + fprintf(stderr, "glDrawBuffer(GL_FRONT_LEFT)\n"); + break; + case GL_FRONT_RIGHT: + fprintf(stderr, "glDrawBuffer(GL_FRONT_RIGHT)\n"); + break; + case GL_FRONT: + fprintf(stderr, "glDrawBuffer(GL_FRONT)\n"); + break; + case GL_BACK_LEFT: + fprintf(stderr, "glDrawBuffer(GL_BACK_LEFT)\n"); + break; + case GL_BACK_RIGHT: + fprintf(stderr, "glDrawBuffer(GL_BACK_RIGHT)\n"); + break; + case GL_BACK: + fprintf(stderr, "glDrawBuffer(GL_BACK)\n"); + break; + default: + fprintf(stderr, "Unknown glDrawBuffer!!!\n"); + break; + } +#endif + + glDrawBuffer(drawBuf); +} + + +JNIEXPORT +void JNICALL Java_javax_media_j3d_Canvas3D_clearAccum( + JNIEnv *env, + jobject obj, + jlong ctxInfo) +{ + + glClear(GL_ACCUM_BUFFER_BIT); + +} + +JNIEXPORT +void JNICALL Java_javax_media_j3d_Canvas3D_accum( + JNIEnv *env, + jobject obj, + jlong ctxInfo, + jfloat value) +{ + + glReadBuffer(GL_BACK); + + glAccum(GL_ACCUM, (float)value); + + glReadBuffer(GL_FRONT); + +} + +JNIEXPORT +void JNICALL Java_javax_media_j3d_Canvas3D_accumReturn( + JNIEnv *env, + jobject obj, + jlong ctxInfo) +{ + + glAccum(GL_RETURN, 1.0); + +} + +JNIEXPORT +void JNICALL Java_javax_media_j3d_Canvas3D_setDepthBufferWriteEnable( + JNIEnv *env, + jobject obj, + jlong ctxInfo, + jboolean mode) +{ + if (mode) + glDepthMask(GL_TRUE); + else + glDepthMask(GL_FALSE); + +} + + +JNIEXPORT +jint JNICALL Java_javax_media_j3d_Canvas3D_swapBuffers( + JNIEnv *env, + jobject obj, + jlong ctxInfo, + jlong display, + jint win) +{ + +#if defined(SOLARIS) || defined(__linux__) + glXSwapBuffers((Display *)display, (Window)win); + +#endif + +#ifdef WIN32 + HDC hdc; + + hdc = (HDC) win; + + SwapBuffers(hdc); +#endif + /* + * It would be nice to do a glFinish here, but we can't do this + * in the ViewThread Java thread in MT-aware OGL libraries without + * switching from the ViewThread to the Renderer thread an extra time + * per frame. Instead, we do glFinish after every rendering but before + * swap in the Renderer thread. + */ + /* glFinish(); */ + return 0; +} + +JNIEXPORT +void JNICALL Java_javax_media_j3d_Canvas3D_syncRender( + JNIEnv *env, + jobject obj, + jlong ctxInfo, + jboolean waitFlag) +{ + + if (waitFlag == JNI_TRUE) + glFinish(); + else + glFlush(); +} + + +JNIEXPORT +void JNICALL Java_javax_media_j3d_Canvas3D_newDisplayList( + JNIEnv *env, + jobject obj, + jlong ctxInfo, + jint id) +{ + + glNewList(id, GL_COMPILE); +} + +JNIEXPORT +void JNICALL Java_javax_media_j3d_Canvas3D_endDisplayList( + JNIEnv *env, + jobject obj, + jlong ctxInfo) +{ + + glEndList(); +} + +JNIEXPORT +void JNICALL Java_javax_media_j3d_Canvas3D_setGlobalAlpha( + JNIEnv *env, + jobject obj, + jlong ctxInfo, + jfloat alpha) +{ + GraphicsContextPropertiesInfo *ctxProperties = (GraphicsContextPropertiesInfo *)ctxInfo; + jlong ctx = ctxProperties->context; + + /* GL_GLOBAL_ALPHA_SUN */ + if(ctxProperties->global_alpha_sun){ + glEnable(GL_GLOBAL_ALPHA_SUN); + ctxProperties->glGlobalAlphaFactorfSUN(alpha); + } +} + +JNIEXPORT +void JNICALL Java_javax_media_j3d_Canvas3D_disableGlobalAlpha( + JNIEnv *env, + jobject obj, + jlong ctxInfo) +{ + + GraphicsContextPropertiesInfo *ctxProperties = (GraphicsContextPropertiesInfo *)ctxInfo; + jlong ctx = ctxProperties->context; + + /* GL_GLOBAL_ALPHA_SUN */ + if(ctxProperties->global_alpha_sun){ + glDisable(GL_GLOBAL_ALPHA_SUN); + } +} + +JNIEXPORT +void JNICALL Java_javax_media_j3d_Canvas3D_callDisplayList( + JNIEnv *env, + jobject obj, + jlong ctxInfo, + jint id, + jboolean isNonUniformScale) +{ + GraphicsContextPropertiesInfo *ctxProperties = (GraphicsContextPropertiesInfo *)ctxInfo; + jlong ctx = ctxProperties->context; + + /* resale_normal_ext */ + if (ctxProperties->rescale_normal_ext && isNonUniformScale) { + glEnable(GL_NORMALIZE); + } + + glCallList(id); + + if (ctxProperties->rescale_normal_ext && isNonUniformScale) { + glDisable(GL_NORMALIZE); + } +} + +JNIEXPORT +void JNICALL Java_javax_media_j3d_Canvas3D_freeDisplayList( + JNIEnv *env, + jclass cl, + jlong ctxInfo, + jint id) +{ + + glDeleteLists(id, 1); +} + +JNIEXPORT +void JNICALL Java_javax_media_j3d_Canvas3D_freeTexture( + JNIEnv *env, + jclass cl, + jlong ctxInfo, + jint id) +{ + GLuint texObj; + + if(id > 0) { + texObj = id; + glDeleteTextures(1, &texObj); + } + else + fprintf(stderr, "try to delete tex with texid <= 0. \n"); + +} + + + +JNIEXPORT jint JNICALL Java_javax_media_j3d_Canvas3D_getTextureUnitCount( + JNIEnv *env, + jobject obj, + jlong ctxInfo) +{ + GraphicsContextPropertiesInfo *ctxProperties = (GraphicsContextPropertiesInfo *)ctxInfo; + + return ctxProperties->textureUnitCount; +} + +/* + * Method: getTextureColorTableSize + */ +int getTextureColorTableSize( + JNIEnv *env, + jobject obj, + jlong ctxInfo, + char *extensionStr, + int minorVersion) +{ + GraphicsContextPropertiesInfo* ctxProperties = (GraphicsContextPropertiesInfo* )ctxInfo; + int size; + + if(minorVersion >= 2 && isExtensionSupported(extensionStr, "GL_ARB_imaging")){ + +#ifdef WIN32 + ctxProperties->glColorTable = (MYPFNGLCOLORTABLEPROC)wglGetProcAddress("glColorTable"); + ctxProperties->glGetColorTableParameteriv = + (MYPFNGLGETCOLORTABLEPARAMETERIVPROC)wglGetProcAddress("glGetColorTableParameteriv"); +#endif +#if defined(SOLARIS) || defined(__linux__) + ctxProperties->glColorTable = glColorTable; + ctxProperties->glGetColorTableParameteriv = glGetColorTableParameteriv; +#endif + + } else if(isExtensionSupported(extensionStr, "GL_SGI_color_table")) { +#ifdef WIN32 + ctxProperties->glColorTable = (MYPFNGLCOLORTABLEPROC)wglGetProcAddress("glColorTableSGI"); + ctxProperties->glGetColorTableParameteriv = + (MYPFNGLGETCOLORTABLEPARAMETERIVPROC)wglGetProcAddress("glGetColorTableParameterivSGI"); +#endif +#if defined(SOLARIS) || defined(__linux__) + ctxProperties->glColorTable = glColorTableSGI; + ctxProperties->glGetColorTableParameteriv = glGetColorTableParameterivSGI; +#endif + + } else { + return 0; + } + + if ((ctxProperties->glColorTable == NULL) || + (ctxProperties->glGetColorTableParameteriv == NULL)) { + return 0; + } + + ctxProperties->glColorTable(GL_PROXY_TEXTURE_COLOR_TABLE_SGI, GL_RGBA, 256, GL_RGB, + GL_INT, NULL); + ctxProperties->glGetColorTableParameteriv(GL_PROXY_TEXTURE_COLOR_TABLE_SGI, + GL_COLOR_TABLE_WIDTH_SGI, &size); + return size; +} + +/* we want to use this if available: */ +#define GLX_SGIX_pbuffer 1 + +#ifndef GLX_VERSION_1_3 +#ifdef GLX_SGIX_pbuffer +#ifdef __linux__ +typedef XID GLXPbuffer; +typedef struct __GLXFBConfigRec *GLXFBConfig; +typedef struct __GLXFBConfigRec *GLXFBConfigSGIX; +extern GLXFBConfig * glXChooseFBConfig (Display *dpy, int screen, const int *attrib_list, int *nelements); +extern GLXPbuffer glXCreatePbuffer (Display *dpy, GLXFBConfig config, const int *attrib_list); +extern void glXDestroyPbuffer (Display *dpy, GLXPbuffer pbuf); +extern GLXFBConfigSGIX *glXChooseFBConfigSGIX(Display *dpy, int screen, const int *attribList, int *nitems); +extern GLXPbuffer glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfig config, unsigned int width, unsigned int height, const int *attribList); +extern void glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbuffer pbuf); +#define GLX_DRAWABLE_TYPE 0x8010 +#define GLX_PBUFFER_BIT 0x00000004 +#define GLX_RENDER_TYPE 0x8011 +#define GLX_RGBA_BIT 0x00000001 +#define GLX_MAX_PBUFFER_WIDTH 0x8016 +#define GLX_MAX_PBUFFER_HEIGHT 0x8017 +#define GLX_PRESERVED_CONTENTS 0x801B +#define GLX_PBUFFER_HEIGHT 0x8040 /* New for GLX 1.3 */ +#define GLX_PBUFFER_WIDTH 0x8041 /* New for GLX 1.3 */ +#define GLX_LARGEST_PBUFFER 0x801C +#define GLX_LARGEST_PBUFFER_SGIX GLX_LARGEST_PBUFFER +#else + +#define GLX_DRAWABLE_TYPE GLX_DRAWABLE_TYPE_SGIX +#define GLX_PBUFFER_BIT GLX_PBUFFER_BIT_SGIX +#define GLX_RENDER_TYPE GLX_RENDER_TYPE_SGIX +#define GLX_RGBA_BIT GLX_RGBA_BIT_SGIX +#endif +#endif /* GLX_SGIX_pbuffer */ +#else +#ifdef __linux__ +typedef struct __GLXFBConfigRec *GLXFBConfigSGIX; +#endif /* __linux__ */ +#endif /* GLX_VERSION_1_3 */ + +#if defined(SOLARIS) || defined(__linux__) +#pragma weak glXChooseFBConfig +#pragma weak glXCreatePbuffer +#pragma weak glXDestroyPbuffer +#pragma weak glXChooseFBConfigSGIX +#pragma weak glXCreateGLXPbufferSGIX +#pragma weak glXDestroyGLXPbufferSGIX +#endif /* SOLARIS */ + + + +/* For dvr support */ +JNIEXPORT +void JNICALL Java_javax_media_j3d_Canvas3D_videoResize( + JNIEnv *env, + jobject obj, + jlong ctxInfo, + jlong display, + jint win, + jfloat dvrFactor) +{ + +#if defined(SOLARIS) || defined(__linux__) + /* Not need to do ext. supported checking. This check is done in java. */ + + /* fprintf(stderr, "Canvas3D.c -- glXVideoResize -- %d %f\n", win, dvrFactor); */ + glXVideoResizeSUN((Display *)display, (Window)win, (float) dvrFactor); +#endif + +} + +JNIEXPORT +void JNICALL Java_javax_media_j3d_Canvas3D_videoResizeCompensation( + JNIEnv *env, + jobject obj, + jlong ctxInfo, + jboolean enable) +{ + +#if defined(SOLARIS) || defined(__linux__) + GraphicsContextPropertiesInfo *ctxProperties = + (GraphicsContextPropertiesInfo *)ctxInfo; + + if (ctxProperties->videoResizeAvailable) { + if(enable == JNI_TRUE) { + /* fprintf(stderr, "videoResizeCompensation - glEnable"); */ + glEnable(GL_VIDEO_RESIZE_COMPENSATION_SUN); + } + else { + /* fprintf(stderr, "videoResizeCompensation - glDisable"); */ + glDisable(GL_VIDEO_RESIZE_COMPENSATION_SUN); + } + } + +#endif + +} + +JNIEXPORT +jint JNICALL Java_javax_media_j3d_Canvas3D_createOffScreenBuffer( + JNIEnv *env, + jobject obj, + jlong ctxInfo, + jlong display, + jint vid, + jint width, + jint height) +{ + +#if defined(SOLARIS) || defined(__linux__) + XVisualInfo *vinfo, template; + int nitems, depth, redSize; + Display *dpy; + static GLboolean pbufferSupported = GL_FALSE; + static GLboolean pbufferExtSupported = GL_FALSE; + int major, minor; + const char *extStr; + int status; + + dpy = (Display *)display; + + if (dpy == NULL) + dpy = XOpenDisplay(NULL); + + template.visualid = vid; + vinfo = XGetVisualInfo(dpy, VisualIDMask, &template, &nitems); + if (nitems != 1) { + fprintf(stderr, "Warning Canvas3D_createContext got unexpected number of matching visuals %d\n", nitems); + } + + glXGetConfig (dpy, vinfo, GLX_BUFFER_SIZE, &depth); + glXGetConfig (dpy, vinfo, GLX_RED_SIZE, &redSize); + + if (status = glXQueryVersion(dpy, &major, &minor)) { + +#if 0 + /* don't use the 1.3 pbuffer interface for now. */ + if ((major > 1) || (major == 1 && minor >= 3)) + pbufferSupported = GL_TRUE; + else +#endif + { + extStr = glXQueryExtensionsString(dpy, DefaultScreen(dpy)); + if ((extStr != NULL) && (strstr(extStr, "GLX_SGIX_pbuffer"))) { + pbufferExtSupported = GL_TRUE; + } + } + } + +#if defined(GLX_VERSION_1_3) || defined(GLX_SGIX_pbuffer) + if (pbufferExtSupported || pbufferSupported) { + + + int attrCount, configAttr[10], numConfig, val; + GLXPbuffer pbuff; + + /* Initialize the attribute list to be used for choosing FBConfig */ + attrCount = 0; + configAttr[attrCount++] = GLX_DRAWABLE_TYPE; + configAttr[attrCount++] = GLX_PBUFFER_BIT; + configAttr[attrCount++] = GLX_RENDER_TYPE; + configAttr[attrCount++] = GLX_RGBA_BIT; + configAttr[attrCount++] = GLX_RED_SIZE; + configAttr[attrCount++] = redSize; + configAttr[attrCount++] = None; +/* + configAttr[attrCount++] = GLX_DEPTH_SIZE; + configAttr[attrCount++] = depth; +*/ + + +#ifdef GLX_VERSION_1_3 + if (pbufferSupported) { + GLXFBConfig *fbconfiglst; + + fbconfiglst = glXChooseFBConfig(dpy, DefaultScreen(dpy), + configAttr, &numConfig); + + if (numConfig < 1) { + fprintf(stderr, "# of configs returned is %d\n", numConfig); + return None; + } + + attrCount = 0; + configAttr[attrCount++] = GLX_PBUFFER_WIDTH; + configAttr[attrCount++] = width; + configAttr[attrCount++] = GLX_PBUFFER_HEIGHT; + configAttr[attrCount++] = height; + configAttr[attrCount++] = GLX_PRESERVED_CONTENTS; + configAttr[attrCount++] = GL_TRUE; + configAttr[attrCount++] = None; + + + pbuff = glXCreatePbuffer(dpy, fbconfiglst[0], configAttr); + } +#endif /* GLX_VERSION_1_3 */ + +#ifdef GLX_SGIX_pbuffer + if (pbufferExtSupported && !pbufferSupported) { + GLXFBConfigSGIX *fbconfiglst; + + + /* Determine what config to use according to config_attr */ + fbconfiglst = glXChooseFBConfigSGIX(dpy, DefaultScreen(dpy), + configAttr, &numConfig); + + if (numConfig < 1) { + fprintf(stderr, "# of configs returned is %d\n", numConfig); + return None; + } + + attrCount = 0; + configAttr[attrCount++] = GLX_PRESERVED_CONTENTS; + configAttr[attrCount++] = GL_TRUE; + configAttr[attrCount++] = None; + pbuff = glXCreateGLXPbufferSGIX(dpy, fbconfiglst[0], width, height, + configAttr ); + } +#endif /* GLX_SGIX_pbuffer */ + if (pbuff == None) { + fprintf(stderr, "glXCreateGLXPbuffer() returns None\n"); + } + + return pbuff; + + } else +#endif /* GLX_VERSION_1_3 || GLX_SGIX_pbuffer */ + + { + Pixmap pixmap; + GLXPixmap glxpixmap; + + /* fall back to pixmap */ + pixmap = XCreatePixmap(dpy, DefaultRootWindow(dpy), width, height, + vinfo->depth); + + glxpixmap = glXCreateGLXPixmap(dpy, vinfo, pixmap); + if (glxpixmap == None) { + fprintf(stderr, "glXCreateGLXPixmap() returns None\n"); + } + + return glxpixmap; + } + +#endif /* SOLARIS */ + +#ifdef WIN32 + int PixelFormatID=0; + int dpy = (int)display; + HDC hdc; /* HW Device Context */ + jboolean rescale = JNI_FALSE; + JNIEnv table = *env; + + HBITMAP hbitmap, oldhbitmap; + + BITMAPINFOHEADER bih; + void *ppvBits; + int err; + LPTSTR errString; + HDC hdcMonitor; + + /* create a DIB */ + memset(&bih, 0, sizeof(BITMAPINFOHEADER)); + + bih.biSize = sizeof(BITMAPINFOHEADER); + bih.biWidth = width; + bih.biHeight = height; + bih.biPlanes = 1; + bih.biBitCount = 24; + bih.biCompression = BI_RGB; + + /* create a new device context */ + + if (dpy == 0) { + hdc = CreateCompatibleDC(0); + } else { + /* + * Should be getMonitorDC(screen) + * but display and screen are the same under windows + * They are return from NativeScreenInfo + */ + hdcMonitor = getMonitorDC((int) display); + hdc = CreateCompatibleDC(hdcMonitor); + DeleteDC(hdcMonitor); + + } + hbitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bih, + DIB_PAL_COLORS, &ppvBits, NULL, 0); + + if (!hbitmap) { + err = GetLastError(); + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, err, 0, (LPTSTR)&errString, 0, NULL); + fprintf(stderr, "CreateDIBSection failed: %s\n", errString); + } + + oldhbitmap = SelectObject(hdc, hbitmap); + + /* Choosing and setting of pixel format is done in createContext */ + + return ((jint)hdc); +#endif /* WIN32 */ +} + +JNIEXPORT +void JNICALL Java_javax_media_j3d_Canvas3D_destroyOffScreenBuffer( + JNIEnv *env, + jobject obj, + jlong ctxInfo, + jlong display, + jint window) +{ +#if defined(SOLARIS) || defined(__linux__) + Display *dpy = (Display*)display; + + GLboolean pbufferSupported = GL_FALSE; + GLboolean pbufferExtSupported = GL_TRUE; + int major, minor; + char *extStr; + + if (glXQueryVersion(dpy, &major, &minor)) { + +#if 0 + /* don't use the 1.3 pbuffer interface for now. */ + if ((major > 1) || (major == 1 && minor >= 3)) + pbufferSupported = GL_TRUE; + else +#endif + { + extStr = (char *)glXQueryExtensionsString(dpy, + DefaultScreen(dpy)); + if ((extStr != NULL) && (strstr(extStr, "GLX_SGIX_pbuffer"))) { + pbufferExtSupported = GL_TRUE; + } + } + } + +#if defined(GLX_VERSION_1_3) || defined(GLX_SGIX_pbuffer) + + if (pbufferSupported) { + glXDestroyPbuffer(dpy, (GLXPbuffer)window); + } else if (pbufferExtSupported) { + glXDestroyGLXPbufferSGIX(dpy, (GLXPbuffer)window); + } else +#endif + + { + glXDestroyGLXPixmap(dpy, (GLXPixmap)window); + } +#endif /* SOLARIS */ + +#ifdef WIN32 + HBITMAP oldhbitmap; + HDC hdc = (HDC) window; + + oldhbitmap = SelectObject(hdc, NULL); + DeleteObject(oldhbitmap); + DeleteDC(hdc); +#endif /* WIN32 */ +} + + +JNIEXPORT +void JNICALL Java_javax_media_j3d_Canvas3D_readOffScreenBuffer( + JNIEnv *env, + jobject obj, + jlong ctxInfo, + jint format, + jint width, + jint height) +{ + JNIEnv table = *env; + jclass cv_class; + jfieldID byteData_field; + jbyteArray byteData_array; + jbyte *byteData; + int type; + + GraphicsContextPropertiesInfo *ctxProperties = (GraphicsContextPropertiesInfo *)ctxInfo; + jlong ctx = ctxProperties->context; + + glPixelStorei(GL_PACK_ROW_LENGTH, width); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + + cv_class = (jclass) (*(table->GetObjectClass))(env, obj); + byteData_field = (jfieldID) (*(table->GetFieldID))(env, cv_class, + "byteBuffer", "[B"); + byteData_array = (jbyteArray)(*(table->GetObjectField))(env, obj, + byteData_field); + byteData = (jbyte *)(*(table->GetPrimitiveArrayCritical))(env, + byteData_array, NULL); + + + switch (format) { + case FORMAT_BYTE_RGBA: + type = GL_RGBA; + break; + case FORMAT_BYTE_RGB: + type = GL_RGB; + break; + + /* GL_ABGR_EXT */ + case FORMAT_BYTE_ABGR: + if (ctxProperties->abgr_ext) { /* If its zero, should never come here! */ + type = GL_ABGR_EXT; + } + break; + + /* GL_BGR_EXT */ + case FORMAT_BYTE_BGR: + if (ctxProperties->bgr_ext) { /* If its zero, should never come here! */ + type = ctxProperties->bgr_ext_enum; + } + break; + + case FORMAT_BYTE_LA: + type = GL_LUMINANCE_ALPHA; + break; + case FORMAT_BYTE_GRAY: + case FORMAT_USHORT_GRAY: + /* TODO: throw exception */ + break; + } + + + glReadPixels(0, 0, width, height, type, GL_UNSIGNED_BYTE, byteData); + + (*(table->ReleasePrimitiveArrayCritical))(env, byteData_array, + byteData, 0); +} + +void initializeCtxInfo(JNIEnv *env , GraphicsContextPropertiesInfo* ctxInfo){ + ctxInfo->context = 0; + + /* version and extension info */ + ctxInfo->versionStr = NULL; + ctxInfo->extensionStr = NULL; + ctxInfo->versionNumbers[0] = 1; + ctxInfo->versionNumbers[1] = 1; + + /* both in 1.2 core part and 1.1 extensions */ + ctxInfo->rescale_normal_ext = JNI_FALSE; + ctxInfo->bgr_ext = JNI_FALSE; + ctxInfo->texture3DAvailable = JNI_FALSE; + ctxInfo->seperate_specular_color = JNI_FALSE; + + /* 1.2 and GL_ARB_imaging */ + ctxInfo->blend_color_ext = JNI_FALSE; + ctxInfo->color_table_ext = JNI_FALSE; + ctxInfo->blendFunctionTable[0] = GL_ZERO; + ctxInfo->blendFunctionTable[1] = GL_ONE; + ctxInfo->blendFunctionTable[2] = GL_SRC_ALPHA; + ctxInfo->blendFunctionTable[3] = GL_ONE_MINUS_SRC_ALPHA; + ctxInfo->blendFunctionTable[4] = GL_DST_COLOR; + ctxInfo->blendFunctionTable[5] = GL_SRC_COLOR; + ctxInfo->blendFunctionTable[6] = GL_ONE_MINUS_SRC_COLOR; + ctxInfo->blendFunctionTable[7] = GL_SRC_COLOR; + + /* 1.1 extensions or 1.2 extensions */ + /* sun extensions */ + ctxInfo->multi_draw_arrays_sun = JNI_FALSE; + ctxInfo->compiled_vertex_array_ext = JNI_FALSE; + + ctxInfo->videoResizeAvailable = JNI_FALSE; + ctxInfo->global_alpha_sun = JNI_FALSE; + ctxInfo->constant_data_sun = JNI_FALSE; + ctxInfo->geometry_compression_sunx = JNI_FALSE; + + /* EXT extensions */ + ctxInfo->abgr_ext = JNI_FALSE; + + ctxInfo->multi_draw_arrays_ext = JNI_FALSE; + + ctxInfo->implicit_multisample = getJavaBoolEnv(env, "implicitAntialiasing"); + + /* ARB extensions */ + ctxInfo->arb_transpose_matrix = JNI_FALSE; + ctxInfo->arb_multitexture = JNI_FALSE; + + ctxInfo->arb_multisample = JNI_FALSE; + ctxInfo->textureUnitCount = 1; + ctxInfo->textureEnvCombineAvailable = JNI_FALSE; + ctxInfo->textureCombineDot3Available = JNI_FALSE; + ctxInfo->textureCombineSubtractAvailable = JNI_FALSE; + ctxInfo->textureCubeMapAvailable = JNI_FALSE; + + /* NV extensions */ + ctxInfo->textureRegisterCombinersAvailable = JNI_FALSE; + + /* SGI extensions */ + ctxInfo->textureSharpenAvailable = JNI_FALSE; + ctxInfo->textureDetailAvailable = JNI_FALSE; + ctxInfo->textureFilter4Available = JNI_FALSE; + ctxInfo->textureAnisotropicFilterAvailable = JNI_FALSE; + ctxInfo->textureColorTableAvailable = JNI_FALSE; + ctxInfo->textureColorTableSize = 0; + ctxInfo->textureLodAvailable = JNI_FALSE; + ctxInfo->textureLodBiasAvailable = JNI_FALSE; + + ctxInfo->geometry_compression_accelerated = JNI_FALSE; + ctxInfo->geometry_compression_accelerated_major_version = 0; + ctxInfo->geometry_compression_accelerated_minor_version = 0; + ctxInfo->geometry_compression_accelerated_subminor_version = 0; + + /* extension mask */ + ctxInfo->extMask = 0; + ctxInfo->textureExtMask = 0; + + ctxInfo->glBlendColor = NULL; + ctxInfo->glBlendColorEXT = NULL; + ctxInfo->glColorTable = NULL; + ctxInfo->glGetColorTableParameteriv = NULL; + ctxInfo->glTexImage3DEXT = NULL; + ctxInfo->glTexSubImage3DEXT = NULL; + ctxInfo->glClientActiveTextureARB = NULL; + ctxInfo->glMultiDrawArraysEXT = NULL; + ctxInfo->glMultiDrawElementsEXT = NULL; + ctxInfo->glLockArraysEXT = NULL; + ctxInfo->glUnlockArraysEXT = NULL; + ctxInfo->glMultiTexCoord2fvARB = NULL; + ctxInfo->glMultiTexCoord3fvARB = NULL; + ctxInfo->glMultiTexCoord4fvARB = NULL; + ctxInfo->glLoadTransposeMatrixdARB = NULL; + ctxInfo->glMultTransposeMatrixdARB = NULL; + ctxInfo->glActiveTextureARB = NULL; + ctxInfo->glGlobalAlphaFactorfSUN = NULL; + + ctxInfo->glCombinerInputNV = NULL; + ctxInfo->glCombinerOutputNV = NULL; + ctxInfo->glFinalCombinerInputNV = NULL; + ctxInfo->glCombinerParameterfvNV = NULL; + ctxInfo->glCombinerParameterivNV= NULL; + ctxInfo->glCombinerParameterfNV = NULL; + ctxInfo->glCombinerParameteriNV = NULL; + + ctxInfo->glSharpenTexFuncSGIS = NULL; + ctxInfo->glDetailTexFuncSGIS = NULL; + ctxInfo->glTexFilterFuncSGIS = NULL; +} + +void cleanupCtxInfo(GraphicsContextPropertiesInfo* ctxInfo){ + if( ctxInfo->versionStr != NULL) + free(ctxInfo->versionStr); + if( ctxInfo->extensionStr != NULL) + free(ctxInfo->extensionStr); + ctxInfo->versionStr = NULL; + ctxInfo->extensionStr = NULL; +} + +#ifdef WIN32 +HWND createDummyWindow(const char* szAppName) { + static char szTitle[]="A Simple C OpenGL Program"; + WNDCLASS wc; /* windows class sruct */ + + HWND hWnd; + + /* Fill in window class structure with parameters that */ + /* describe the main window. */ + + wc.style = + CS_HREDRAW | CS_VREDRAW;/* Class style(s). */ + wc.lpfnWndProc = + (WNDPROC)WndProc; /* Window Procedure */ + wc.cbClsExtra = 0; /* No per-class extra data. */ + wc.cbWndExtra = 0; /* No per-window extra data. */ + wc.hInstance = + NULL; /* Owner of this class */ + wc.hIcon = NULL; /* Icon name */ + wc.hCursor = + NULL;/* Cursor */ + wc.hbrBackground = + (HBRUSH)(COLOR_WINDOW+1);/* Default color */ + wc.lpszMenuName = NULL; /* Menu from .RC */ + wc.lpszClassName = + szAppName; /* Name to register as + + /* Register the window class */ + + if(RegisterClass( &wc )==0) + fprintf(stdout, "Couldn't register class\n"); + + /* Create a main window for this application instance. */ + + hWnd = CreateWindow( + szAppName, /* app name */ + szTitle, /* Text for window title bar */ + WS_OVERLAPPEDWINDOW/* Window style */ + /* NEED THESE for OpenGL calls to work!*/ + | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, + CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, + NULL, /* no parent window */ + NULL, /* Use the window class menu.*/ + NULL, /* This instance owns this window */ + NULL /* We don't use any extra data */ + ); + + /* If window could not be created, return zero */ + if ( !hWnd ){ + fprintf(stdout, "Couldn't Create window\n"); + return NULL; + } + return hWnd; +} +#endif + +JNIEXPORT +void JNICALL Java_javax_media_j3d_Canvas3D_createQueryContext( + JNIEnv *env, + jobject obj, + jlong display, + jint window, + jint vid, + jboolean offScreen, + jint width, + jint height) +{ + JNIEnv table = *env; + jlong gctx; + long newWin; + int PixelFormatID=0; + GraphicsContextPropertiesInfo* ctxInfo = (GraphicsContextPropertiesInfo *)malloc(sizeof(GraphicsContextPropertiesInfo)); + +#if defined(SOLARIS) || defined(__linux__) + XVisualInfo *vinfo, template; + int nitems; + GLXContext ctx; + int result; + Window root; + Window glWin; + XSetWindowAttributes win_attrs; + Colormap cmap; + unsigned long win_mask; + jlong hdc; + + template.visualid = vid; + vinfo = XGetVisualInfo((Display *)display, VisualIDMask, &template, &nitems); + if (nitems != 1) { + fprintf(stderr, "Warning Canvas3D_createQueryContext got unexpected number of matching visuals %d\n", nitems); + } + + ctx = glXCreateContext((Display *)display, vinfo, NULL, True); + if (ctx == NULL) { + fprintf(stderr, "Error Canvas3D_createQueryContext: couldn't create context.\n"); + } + + + /* create window if window == 0 and offscreen == true */ + if(window == 0 && !offScreen) { + + root = RootWindow((Display *)display, vinfo->screen); + + /* Create a colormap */ + cmap = XCreateColormap((Display *)display, root, vinfo->visual, AllocNone); + + /* Create a window */ + win_attrs.colormap = cmap; + win_attrs.border_pixel = 0; + win_attrs.event_mask = KeyPressMask | ExposureMask | StructureNotifyMask; + win_mask = CWColormap | CWBorderPixel | CWEventMask; + glWin = XCreateWindow((Display *)display, root, 0, 0, width, height, 0, vinfo->depth, + InputOutput, vinfo->visual, win_mask, &win_attrs); + newWin = (unsigned long)glWin; + } + else if(window == 0 && offScreen){ + newWin = Java_javax_media_j3d_Canvas3D_createOffScreenBuffer( env, obj, 0, display, vid, width, height); + } + else if(window != 0) { + newWin = window; + } + + result = glXMakeCurrent((Display *)display, (GLXDrawable)newWin, (GLXContext)ctx); + if (result == GL_FALSE) + fprintf(stderr, "glXMakeCurrent fails\n"); + gctx = (jlong)ctx; +#endif + +#ifdef WIN32 + HGLRC hrc; /* HW Rendering Context */ + HDC hdc; /* HW Device Context */ + DWORD err; + LPTSTR errString; + HWND hWnd; + static char szAppName[] = "OpenGL"; + jlong vinfo = 0; + + static PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), + 1, /* Version number */ + PFD_DRAW_TO_WINDOW | + PFD_SUPPORT_OPENGL| + PFD_DOUBLEBUFFER, + PFD_TYPE_RGBA, + 24, /* 24 bit color depth */ + 0, 0, 0, /* RGB bits and pixel sizes */ + 0, 0, 0, /* Donnot care about them */ + 0, 0, /* no alpha buffer info */ + 0, 0, 0, 0, 0, /* no accumulation buffer */ + 32, /* 16 bit depth buffer */ + 0, /* no stencil buffer */ + 0, /* no auxiliary buffers */ + PFD_MAIN_PLANE, /* layer type */ + 0, /* reserved, must be 0 */ + 0, /* no layer mask */ + 0, /* no visible mask */ + 0 /* no damage mask */ + }; + + jboolean result; + + /* onscreen rendering and window is 0 now */ + if(window == 0 && !offScreen){ + hWnd = createDummyWindow((const char *)szAppName); + if (!hWnd) + return; + hdc = GetDC(hWnd); + } + else if(window == 0 && offScreen){ + hdc = (HDC)Java_javax_media_j3d_Canvas3D_createOffScreenBuffer( env, obj, 0, display, vid, width, height); + pfd.dwFlags = PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL | + PFD_SUPPORT_GDI; + vid = -1; + } + else if(window != 0 && offScreen){ + pfd.dwFlags = PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL | + PFD_SUPPORT_GDI; + vid = -1; + hdc = (HDC) window; + } + else if(window !=0 && !offScreen){ + hdc = (HDC) window; + } + + newWin = (int)hdc; + + /* vid of -1 means no vid was specified - do the old way */ + if (vid == -1) { + /* + * choose the "pixel format", terminology is equivalent + * to UNIX "visual" + */ + PixelFormatID = ChoosePixelFormat(hdc, &pfd); + + if(PixelFormatID == 0) { + fprintf(stderr,"\nERROR: pixel format ID = 0"); + return; + } + } + else + PixelFormatID = vid; + + SetPixelFormat(hdc, PixelFormatID, &pfd); + + hrc = wglCreateContext( hdc ); + + if (!hrc) { + err = GetLastError(); + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, err, 0, (LPTSTR)&errString, 0, NULL); + + fprintf(stderr, "wglCreateContext Failed: %s\n", errString); + } + + + result = wglMakeCurrent(hdc, hrc); + + if (!result) { + err = GetLastError(); + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, err, 0, (LPTSTR)&errString, 0, NULL); + fprintf(stderr, "wglMakeCurrent Failed: %s\n", errString); + } + + gctx = (jlong)hrc; + +#endif + + initializeCtxInfo(env, ctxInfo); + ctxInfo->context = gctx; + + /* get current context properties */ + if (getPropertiesFromCurrentContext(env, obj, ctxInfo, (jlong) hdc, PixelFormatID, display, (jlong) vinfo)) { + /* put the properties to the Java side */ + setupCanvasProperties(env, obj, ctxInfo); + } + + + /* clear up the context , colormap and window if appropriate */ + if(window == 0 && !offScreen){ +#if defined(SOLARIS) || defined(__linux__) + Java_javax_media_j3d_Canvas3D_destroyContext(env, obj, display, newWin, (jlong)ctxInfo); + XDestroyWindow((Display *)display, glWin); + XFreeColormap((Display *)display, cmap); +#endif /* SOLARIS */ +#ifdef WIN32 + /* Release DC */ + ReleaseDC(hWnd, hdc); + /* Destroy context */ + /* This will free ctxInfo also */ + Java_javax_media_j3d_Canvas3D_destroyContext(env, obj, display,newWin, (jlong)ctxInfo); + DestroyWindow(hWnd); + UnregisterClass(szAppName, (HINSTANCE)NULL); +#endif /* WIN32 */ + } + else if(window == 0 && offScreen) { + Java_javax_media_j3d_Canvas3D_destroyOffScreenBuffer(env, obj, gctx, display, newWin); + Java_javax_media_j3d_Canvas3D_destroyContext(env, obj, display, newWin, (jlong)ctxInfo); + } + else if(window != 0){ + Java_javax_media_j3d_Canvas3D_destroyContext(env, obj, display, newWin, (jlong)ctxInfo); + } +} + + +JNIEXPORT +void JNICALL Java_javax_media_j3d_Canvas3D_beginScene( + JNIEnv *env, + jobject obj, + jlong ctxInfo) +{ + /* Not used by OGL version */ +} + + +JNIEXPORT +void JNICALL Java_javax_media_j3d_Canvas3D_endScene( + JNIEnv *env, + jobject obj, + jlong ctxInfo) +{ + /* This function is a no-op */ + /* + GraphicsContextPropertiesInfo *ctxProperties = (GraphicsContextPropertiesInfo *)ctxInfo; + */ +} + +/* Setup the multisampling for full scene antialiasing */ +JNIEXPORT void JNICALL Java_javax_media_j3d_Canvas3D_setFullSceneAntialiasing +(JNIEnv *env, jobject obj, jlong ctxInfo, jboolean enable) +{ + GraphicsContextPropertiesInfo *ctxProperties = (GraphicsContextPropertiesInfo *)ctxInfo; + jlong ctx = ctxProperties->context; + + if (ctxProperties->arb_multisample && !ctxProperties->implicit_multisample) { + if(enable == JNI_TRUE) { + glEnable(MULTISAMPLE_ARB); + } + else { + glDisable(MULTISAMPLE_ARB); + + } + } + +} + + +/* + * Return false if <= 8 bit color under windows + */ +JNIEXPORT +jboolean JNICALL Java_javax_media_j3d_Canvas3D_validGraphicsMode( + JNIEnv *env, + jobject obj) +{ +#ifdef WIN32 + DEVMODE devMode; + + EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devMode); + return (devMode.dmBitsPerPel > 8); +#endif + +#if defined(SOLARIS) || defined(__linux__) + return TRUE; +#endif +} |