/* * $RCSfile$ * * Copyright (c) 2007 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. */ /* j3dsys.h needs to be included before any other include files to suppres VC warning */ #include "j3dsys.h" #include #include #include #include #include #include "gldefs.h" #if defined(UNIX) #include #endif #ifdef DEBUG /* Uncomment the following for VERBOSE debug messages */ /* #define VERBOSE */ #endif /* DEBUG */ extern void throwAssert(JNIEnv *env, char *str); jboolean getJavaBoolEnv(JNIEnv *env, char* envStr); static void initializeCtxInfo(JNIEnv *env, GraphicsContextPropertiesInfo* ctxInfo); static void cleanupCtxInfo(GraphicsContextPropertiesInfo* ctxInfo); static void disableAttribFor2D(GraphicsContextPropertiesInfo *ctxProperties); static void disableAttribForRaster(GraphicsContextPropertiesInfo *ctxProperties); /* * Class: javax_media_j3d_Canvas3D * Method: getTextureColorTableSize * Signature: ()I */ static int getTextureColorTableSize( JNIEnv *env, jobject obj, GraphicsContextPropertiesInfo *ctxInfo, char *extensionStr); extern void checkGLSLShaderExtensions( JNIEnv *env, jobject obj, char *tmpExtensionStr, GraphicsContextPropertiesInfo *ctxInfo, jboolean glslLibraryAvailable); extern void checkCgShaderExtensions( JNIEnv *env, jobject obj, char *tmpExtensionStr, GraphicsContextPropertiesInfo *ctxInfo, jboolean cgLibraryAvailable); #ifdef WIN32 extern void printErrorMessage(char *message); extern PIXELFORMATDESCRIPTOR getDummyPFD(); extern HDC getMonitorDC(int screen); HWND createDummyWindow(const char* szAppName); #endif /* * Extract the version numbers from a copy of the version string. * Upon return, numbers[0] contains major version number * numbers[1] contains minor version number * Note that the passed in version string is modified. */ 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); 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; } static void checkTextureExtensions( JNIEnv *env, jobject obj, char *tmpExtensionStr, GraphicsContextPropertiesInfo* ctxInfo) { if (ctxInfo->gl13) { ctxInfo->textureExtMask |= javax_media_j3d_Canvas3D_TEXTURE_MULTI_TEXTURE; glGetIntegerv(GL_MAX_TEXTURE_UNITS, &ctxInfo->maxTextureUnits); ctxInfo->maxTexCoordSets = ctxInfo->maxTextureUnits; if (isExtensionSupported(tmpExtensionStr, "GL_ARB_vertex_shader")) { glGetIntegerv(GL_MAX_TEXTURE_COORDS_ARB, &ctxInfo->maxTexCoordSets); } } 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, ctxInfo, tmpExtensionStr); 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(UNIX) ctxInfo->glCombinerInputNV = (MYPFNGLCOMBINERINPUTNV) dlsym(RTLD_DEFAULT, "glCombinerInputNV"); ctxInfo->glFinalCombinerInputNV = (MYPFNGLFINALCOMBINERINPUTNV) dlsym(RTLD_DEFAULT, "glFinalCombinerInputNV"); ctxInfo->glCombinerOutputNV = (MYPFNGLCOMBINEROUTPUTNV) dlsym(RTLD_DEFAULT, "glCombinerOutputNV"); ctxInfo->glCombinerParameterfvNV = (MYPFNGLCOMBINERPARAMETERFVNV) dlsym(RTLD_DEFAULT, "glCombinerParameterfvNV"); ctxInfo->glCombinerParameterivNV = (MYPFNGLCOMBINERPARAMETERIVNV) dlsym(RTLD_DEFAULT, "glCombinerParameterivNV"); ctxInfo->glCombinerParameterfNV = (MYPFNGLCOMBINERPARAMETERFNV) dlsym(RTLD_DEFAULT, "glCombinerParameterfNV"); ctxInfo->glCombinerParameteriNV = (MYPFNGLCOMBINERPARAMETERINV) dlsym(RTLD_DEFAULT, "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 (ctxInfo->gl13) { 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(UNIX) ctxInfo->glSharpenTexFuncSGIS = (MYPFNGLSHARPENTEXFUNCSGI) dlsym(RTLD_DEFAULT, "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(UNIX) ctxInfo->glDetailTexFuncSGIS = (MYPFNGLDETAILTEXFUNCSGI) dlsym(RTLD_DEFAULT, "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(UNIX) ctxInfo->glTexFilterFuncSGIS = (MYPFNGLTEXFILTERFUNCSGI) dlsym(RTLD_DEFAULT, "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 (ctxInfo->gl13) { ctxInfo->texture_clamp_to_border_enum = GL_CLAMP_TO_BORDER; } 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; } if (isExtensionSupported(tmpExtensionStr, "GL_ARB_texture_non_power_of_two") && !getJavaBoolEnv(env, "enforcePowerOfTwo")) { ctxInfo->textureExtMask |= javax_media_j3d_Canvas3D_TEXTURE_NON_POWER_OF_TWO; } if (isExtensionSupported(tmpExtensionStr, "GL_SGIS_generate_mipmap")) { ctxInfo->textureExtMask |= javax_media_j3d_Canvas3D_TEXTURE_AUTO_MIPMAP_GENERATION; } } jboolean 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 JNI_FALSE; } fieldID = (jfieldID) (*(table->GetStaticFieldID))(env, cls, "mc", "Ljavax/media/j3d/MasterControl;"); if (fieldID == NULL) { return JNI_FALSE; } obj = (*(table->GetStaticObjectField))(env, cls, fieldID); if (obj == NULL) { return JNI_FALSE; } cls = (jclass) (*(table->FindClass))(env, "javax/media/j3d/MasterControl"); if (cls == NULL) { return JNI_FALSE; } fieldID = (jfieldID) (*(table->GetFieldID))(env, cls, envStr, "Z"); if (fieldID == NULL ) { return JNI_FALSE; } return (*(table->GetBooleanField))(env, obj, fieldID); } jint getJavaIntEnv(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 JNI_FALSE; } fieldID = (jfieldID) (*(table->GetStaticFieldID))(env, cls, "mc", "Ljavax/media/j3d/MasterControl;"); if (fieldID == NULL) { return JNI_FALSE; } obj = (*(table->GetStaticObjectField))(env, cls, fieldID); if (obj == NULL) { return JNI_FALSE; } cls = (jclass) (*(table->FindClass))(env, "javax/media/j3d/MasterControl"); if (cls == NULL) { return JNI_FALSE; } fieldID = (jfieldID) (*(table->GetFieldID))(env, cls, envStr, "I"); if (fieldID == NULL ) { return JNI_FALSE; } return (*(table->GetIntField))(env, obj, fieldID); } /* * Dummy functions for language-independent vertex attribute functions */ static void dummyVertexAttrPointer( GraphicsContextPropertiesInfo *ctxProperties, int index, int size, int type, int stride, const void *pointer) { #ifdef DEBUG fprintf(stderr, "dummyVertexAttrPointer()\n"); #endif /* DEBUG */ } static void dummyEnDisableVertexAttrArray( GraphicsContextPropertiesInfo *ctxProperties, int index) { #ifdef DEBUG fprintf(stderr, "dummyEnDisableVertexAttrArray()\n"); #endif /* DEBUG */ } static void dummyVertexAttr( GraphicsContextPropertiesInfo *ctxProperties, int index, const float *v) { #ifdef DEBUG fprintf(stderr, "dummyVertexAttr()\n"); #endif /* DEBUG */ } /* * get properties from current context */ static jboolean getPropertiesFromCurrentContext( JNIEnv *env, jobject obj, GraphicsContextPropertiesInfo *ctxInfo, jlong hdc, int pixelFormat, jlong fbConfigListPtr, jboolean offScreen, jboolean glslLibraryAvailable, jboolean cgLibraryAvailable) { JNIEnv table = *env; /* version and extension */ char *glVersion; char *glVendor; char *glRenderer; char *extensionStr; char *tmpVersionStr; char *tmpExtensionStr; int versionNumbers[2]; char *cgHwStr = 0; #ifdef WIN32 PixelFormatInfo *PixelFormatInfoPtr = (PixelFormatInfo *)fbConfigListPtr; #endif /* Get the list of extension */ extensionStr = (char *)glGetString(GL_EXTENSIONS); if (extensionStr == NULL) { fprintf(stderr, "extensionStr == null\n"); return JNI_FALSE; } tmpExtensionStr = strdup(extensionStr); /* Get the OpenGL version */ glVersion = (char *)glGetString(GL_VERSION); if (glVersion == NULL) { fprintf(stderr, "glVersion == null\n"); return JNI_FALSE; } tmpVersionStr = strdup(glVersion); /* Get the OpenGL vendor and renderer */ glVendor = (char *)glGetString(GL_VENDOR); if (glVendor == NULL) { glVendor = ""; } glRenderer = (char *)glGetString(GL_RENDERER); if (glRenderer == NULL) { glRenderer = ""; } /* fprintf(stderr, " pixelFormat : %d\n", pixelFormat); fprintf(stderr, " extensionStr : %s\n", tmpExtensionStr); */ ctxInfo->versionStr = strdup(glVersion); ctxInfo->vendorStr = strdup(glVendor); ctxInfo->rendererStr = strdup(glRenderer); ctxInfo->extensionStr = strdup(extensionStr); /* find out the version, major and minor version number */ extractVersionInfo(tmpVersionStr, versionNumbers); /* *********************************************************/ /* setup the graphics context properties */ /* * NOTE: Java 3D now requires OpenGL 1.3 for full functionality. * For backwards compatibility with certain older graphics cards and * drivers (e.g., the Linux DRI driver for older ATI cards), * we will try to run on OpenGL 1.2 in an unsupported manner. However, * we will not attempt to use OpenGL extensions for any features that * are available in OpenGL 1.3, specifically multitexture, multisample, * and cube map textures. */ if (versionNumbers[0] < 1 || (versionNumbers[0] == 1 && versionNumbers[1] < 2)) { jclass rte; fprintf(stderr, "Java 3D ERROR : OpenGL 1.2 or better is required (GL_VERSION=%d.%d)\n", versionNumbers[0], versionNumbers[1]); if ((rte = (*(table->FindClass))(env, "javax/media/j3d/IllegalRenderingStateException")) != NULL) { (*(table->ThrowNew))(env, rte, "GL_VERSION"); } return JNI_FALSE; } if (versionNumbers[0] > 1) { /* OpenGL 2.x -- set flags for 1.3, 1.4 and 2.0 or greater */ ctxInfo->gl20 = JNI_TRUE; ctxInfo->gl14 = JNI_TRUE; ctxInfo->gl13 = JNI_TRUE; } else { if (versionNumbers[1] == 2) { fprintf(stderr, "JAVA 3D: OpenGL 1.2 detected; will run with reduced functionality\n"); } else if (versionNumbers[1] == 4) { ctxInfo->gl14 = JNI_TRUE; ctxInfo->gl13 = JNI_TRUE; } else { // OpenGL 1.x (1.3 or greater) ctxInfo->gl13 = JNI_TRUE; } } /* Setup function pointers for core OpenGL 1.3 features */ ctxInfo->textureExtMask |= javax_media_j3d_Canvas3D_TEXTURE_3D; #if defined(UNIX) ctxInfo->glTexImage3DEXT = (MYPFNGLTEXIMAGE3DPROC )dlsym(RTLD_DEFAULT, "glTexImage3D"); ctxInfo->glTexSubImage3DEXT = (MYPFNGLTEXSUBIMAGE3DPROC )dlsym(RTLD_DEFAULT, "glTexSubImage3D"); #endif #ifdef WIN32 ctxInfo->glTexImage3DEXT = (MYPFNGLTEXIMAGE3DPROC )wglGetProcAddress("glTexImage3D"); ctxInfo->glTexSubImage3DEXT = (MYPFNGLTEXSUBIMAGE3DPROC )wglGetProcAddress("glTexSubImage3D"); #endif if(isExtensionSupported(tmpExtensionStr, "GL_ARB_imaging")){ ctxInfo->blend_color_ext = JNI_TRUE; ctxInfo->blendFunctionTable[BLEND_CONSTANT_COLOR] = GL_CONSTANT_COLOR; #if defined(UNIX) ctxInfo->glBlendColor = (MYPFNGLBLENDCOLORPROC )dlsym(RTLD_DEFAULT, "glBlendColor"); #endif #ifdef WIN32 ctxInfo->glBlendColor = (MYPFNGLBLENDCOLORPROC )wglGetProcAddress("glBlendColor"); if (ctxInfo->glBlendColor == NULL) { ctxInfo->blend_color_ext = JNI_FALSE; } #endif } 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; if (ctxInfo->gl14) { ctxInfo->textureExtMask |= javax_media_j3d_Canvas3D_TEXTURE_AUTO_MIPMAP_GENERATION; } /* look for OpenGL 2.0 features */ /* // Fix to Issue 455 : Need to disable NPOT textures for older cards that claim to support it. // Some older cards (e.g., Nvidia fx500 and ATI 9800) claim to support OpenGL 2.0. // This means that these cards have to support non-power-of-two (NPOT) texture, // but their lack the necessary HW force the vendors the emulate this feature in software. // The result is a ~100x slower down compare to power-of-two textures. // Do not check for gl20 but instead check of GL_ARB_texture_non_power_of_two extension string if (ctxInfo->gl20) { if (!getJavaBoolEnv(env, "enforcePowerOfTwo")) { ctxInfo->textureExtMask |= javax_media_j3d_Canvas3D_TEXTURE_NON_POWER_OF_TWO; } } */ /* 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, "isCompiledVertexArray")) { ctxInfo->compiled_vertex_array_ext = JNI_TRUE; } if(isExtensionSupported(tmpExtensionStr, "GL_SUN_global_alpha")){ ctxInfo->global_alpha_sun = JNI_TRUE; } if(isExtensionSupported(tmpExtensionStr, "GL_EXT_abgr")) { ctxInfo->abgr_ext = JNI_TRUE; } /* * Setup ctxInfo->multisample; under windows this is setup in * NativeConfigTemplate when pixel format is choose */ #if defined(UNIX) ctxInfo->multisample = ctxInfo->gl13; #endif #ifdef WIN32 if(offScreen) { ctxInfo->multisample = PixelFormatInfoPtr->offScreenHasMultisample; } else { ctxInfo->multisample = PixelFormatInfoPtr->onScreenHasMultisample; } /* fprintf(stderr, "Canvas3D - onScreenHasMultisample = %d, offScreenHasMultisample = %d\n", PixelFormatInfoPtr->onScreenHasMultisample, PixelFormatInfoPtr->offScreenHasMultisample); fprintf(stderr, "Canvas3D - ctxInfo->multisample = %d, offScreen = %d\n", ctxInfo->multisample, offScreen); */ #endif /* * Disable multisample by default since OpenGL will enable * it by default if the surface is multisample capable. */ if (ctxInfo->multisample && !ctxInfo->implicit_multisample) { glDisable(GL_MULTISAMPLE); } /* Check texture extensions */ checkTextureExtensions(env, obj, tmpExtensionStr, ctxInfo); /* Check shader extensions */ if (ctxInfo->gl13) { checkGLSLShaderExtensions(env, obj, tmpExtensionStr, ctxInfo, glslLibraryAvailable); checkCgShaderExtensions(env, obj, tmpExtensionStr, ctxInfo, cgLibraryAvailable); } else { /* Force shaders to be disabled, since no multitexture support */ char *emptyExtStr = " "; checkGLSLShaderExtensions(env, obj, emptyExtStr, ctxInfo, JNI_FALSE); checkCgShaderExtensions(env, obj, emptyExtStr, ctxInfo, JNI_FALSE); } /* *********************************************************/ /* Setup GL_SUN_gloabl_alpha */ if (ctxInfo->global_alpha_sun) { ctxInfo->extMask |= javax_media_j3d_Canvas3D_SUN_GLOBAL_ALPHA; } /* Setup GL_EXT_abgr */ if (ctxInfo->abgr_ext) { ctxInfo->extMask |= javax_media_j3d_Canvas3D_EXT_ABGR; } /* GL_BGR is always supported */ ctxInfo->extMask |= javax_media_j3d_Canvas3D_EXT_BGR; if(ctxInfo->multisample) { ctxInfo->extMask |= javax_media_j3d_Canvas3D_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->gl13) { ctxInfo->glClientActiveTexture = (MYPFNGLCLIENTACTIVETEXTUREPROC)wglGetProcAddress("glClientActiveTexture"); ctxInfo->glActiveTexture = (MYPFNGLACTIVETEXTUREPROC) wglGetProcAddress("glActiveTexture"); ctxInfo->glMultiTexCoord2fv = (MYPFNGLMULTITEXCOORD2FVPROC)wglGetProcAddress("glMultiTexCoord2fv"); ctxInfo->glMultiTexCoord3fv = (MYPFNGLMULTITEXCOORD3FVPROC)wglGetProcAddress("glMultiTexCoord3fv"); ctxInfo->glMultiTexCoord4fv = (MYPFNGLMULTITEXCOORD4FVPROC)wglGetProcAddress("glMultiTexCoord4fv"); ctxInfo->glLoadTransposeMatrixd = (MYPFNGLLOADTRANSPOSEMATRIXDPROC)wglGetProcAddress("glLoadTransposeMatrixd"); ctxInfo->glMultTransposeMatrixd = (MYPFNGLMULTTRANSPOSEMATRIXDPROC)wglGetProcAddress("glMultTransposeMatrixd"); } 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; } } #endif #if defined(UNIX) if(ctxInfo->multi_draw_arrays_ext) { ctxInfo->glMultiDrawArraysEXT = (MYPFNGLMULTIDRAWARRAYSEXTPROC)dlsym(RTLD_DEFAULT, "glMultiDrawArraysEXT"); ctxInfo->glMultiDrawElementsEXT = (MYPFNGLMULTIDRAWELEMENTSEXTPROC)dlsym(RTLD_DEFAULT, "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)dlsym(RTLD_DEFAULT, "glMultiDrawArraysSUN"); ctxInfo->glMultiDrawElementsEXT = (MYPFNGLMULTIDRAWELEMENTSEXTPROC)dlsym(RTLD_DEFAULT, "glMultiDrawElementsSUN"); if ((ctxInfo->glMultiDrawArraysEXT == NULL) || (ctxInfo->glMultiDrawElementsEXT == NULL)) { ctxInfo->multi_draw_arrays_ext = JNI_FALSE; } } if(ctxInfo->compiled_vertex_array_ext) { ctxInfo->glLockArraysEXT = (MYPFNGLLOCKARRAYSEXTPROC)dlsym(RTLD_DEFAULT, "glLockArraysEXT"); ctxInfo->glUnlockArraysEXT = (MYPFNGLUNLOCKARRAYSEXTPROC)dlsym(RTLD_DEFAULT, "glUnlockArraysEXT"); if ((ctxInfo->glLockArraysEXT == NULL) || (ctxInfo->glUnlockArraysEXT == NULL)) { ctxInfo->compiled_vertex_array_ext = JNI_FALSE; } } if(ctxInfo->gl13){ ctxInfo->glClientActiveTexture = (MYPFNGLCLIENTACTIVETEXTUREPROC)dlsym(RTLD_DEFAULT, "glClientActiveTexture"); ctxInfo->glMultiTexCoord2fv = (MYPFNGLMULTITEXCOORD2FVPROC)dlsym(RTLD_DEFAULT, "glMultiTexCoord2fv"); ctxInfo->glMultiTexCoord3fv = (MYPFNGLMULTITEXCOORD3FVPROC)dlsym(RTLD_DEFAULT, "glMultiTexCoord3fv"); ctxInfo->glMultiTexCoord4fv = (MYPFNGLMULTITEXCOORD4FVPROC)dlsym(RTLD_DEFAULT, "glMultiTexCoord4fv"); ctxInfo->glActiveTexture = (MYPFNGLACTIVETEXTUREPROC)dlsym(RTLD_DEFAULT, "glActiveTexture"); ctxInfo->glLoadTransposeMatrixd = (MYPFNGLLOADTRANSPOSEMATRIXDPROC)dlsym(RTLD_DEFAULT, "glLoadTransposeMatrixd"); ctxInfo->glMultTransposeMatrixd = (MYPFNGLMULTTRANSPOSEMATRIXDPROC)dlsym(RTLD_DEFAULT, "glMultTransposeMatrixd"); } if(ctxInfo->global_alpha_sun) { ctxInfo->glGlobalAlphaFactorfSUN = (MYPFNGLGLOBALALPHAFACTORFSUNPROC)dlsym(RTLD_DEFAULT, "glGlobalAlphaFactorfSUN"); if (ctxInfo->glGlobalAlphaFactorfSUN == NULL) { ctxInfo->global_alpha_sun = JNI_FALSE; } } #endif /* UNIX */ /* clearing up the memory */ free(tmpExtensionStr); free(tmpVersionStr); return JNI_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->gl13); rsc_field = (jfieldID) (*(table->GetFieldID))(env, cv_class, "maxTextureUnits", "I"); (*(table->SetIntField))(env, obj, rsc_field, ctxInfo->maxTextureUnits); rsc_field = (jfieldID) (*(table->GetFieldID))(env, cv_class, "maxTexCoordSets", "I"); (*(table->SetIntField))(env, obj, rsc_field, ctxInfo->maxTexCoordSets); rsc_field = (jfieldID) (*(table->GetFieldID))(env, cv_class, "maxTextureImageUnits", "I"); (*(table->SetIntField))(env, obj, rsc_field, ctxInfo->maxTextureImageUnits); rsc_field = (jfieldID) (*(table->GetFieldID))(env, cv_class, "maxVertexTextureImageUnits", "I"); (*(table->SetIntField))(env, obj, rsc_field, ctxInfo->maxVertexTextureImageUnits); rsc_field = (jfieldID) (*(table->GetFieldID))(env, cv_class, "maxCombinedTextureImageUnits", "I"); (*(table->SetIntField))(env, obj, rsc_field, ctxInfo->maxCombinedTextureImageUnits); rsc_field = (jfieldID) (*(table->GetFieldID))(env, cv_class, "maxVertexAttrs", "I"); (*(table->SetIntField))(env, obj, rsc_field, ctxInfo->maxVertexAttrs); 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)); rsc_field = (jfieldID) (*(table->GetFieldID))(env, cv_class, "nativeGraphicsVendor", "Ljava/lang/String;"); (*(table->SetObjectField))(env, obj, rsc_field, (*env)->NewStringUTF(env, ctxInfo->vendorStr)); rsc_field = (jfieldID) (*(table->GetFieldID))(env, cv_class, "nativeGraphicsRenderer", "Ljava/lang/String;"); (*(table->SetObjectField))(env, obj, rsc_field, (*env)->NewStringUTF(env, ctxInfo->rendererStr)); 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); param = -1; glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, ¶m); rsc_field = (jfieldID) (*(table->GetFieldID))(env, cv_class, "texture3DWidthMax", "I"); (*(table->SetIntField))(env, obj, rsc_field, param); rsc_field = (jfieldID) (*(table->GetFieldID))(env, cv_class, "texture3DHeightMax", "I"); (*(table->SetIntField))(env, obj, rsc_field, param); rsc_field = (jfieldID) (*(table->GetFieldID))(env, cv_class, "texture3DDepthMax", "I"); (*(table->SetIntField))(env, obj, rsc_field, param); rsc_field = (jfieldID) (*(table->GetFieldID))(env, cv_class, "shadingLanguageGLSL", "Z"); (*(table->SetBooleanField))(env, obj, rsc_field, ctxInfo->shadingLanguageGLSL); rsc_field = (jfieldID) (*(table->GetFieldID))(env, cv_class, "shadingLanguageCg", "Z"); (*(table->SetBooleanField))(env, obj, rsc_field, ctxInfo->shadingLanguageCg); } JNIEXPORT void JNICALL Java_javax_media_j3d_NativePipeline_destroyContext( JNIEnv *env, jobject obj, jlong display, jlong 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(UNIX) /* glXMakeCurrent((Display *)display, None, NULL); */ glXDestroyContext((Display *)display, (GLXContext)context); #endif /* UNIX */ /* 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 (LONG) DefWindowProc( hWnd, msg, wParam, lParam ); } #endif /*end of WIN32 */ JNIEXPORT jlong JNICALL Java_javax_media_j3d_NativePipeline_createNewContext( JNIEnv *env, jobject obj, jobject cv, jlong display, jlong window, jlong fbConfigListPtr, jlong sharedCtxInfo, jboolean isSharedCtx, jboolean offScreen, jboolean glslLibraryAvailable, jboolean cgLibraryAvailable) { jlong gctx; jlong sharedCtx; int stencilSize=0; GraphicsContextPropertiesInfo *ctxInfo = NULL; GraphicsContextPropertiesInfo *sharedCtxStructure; int PixelFormatID=0; #if defined(UNIX) /* Fix for issue 20 */ GLXContext ctx; jlong hdc; GLXFBConfig *fbConfigList = NULL; fbConfigList = (GLXFBConfig *)fbConfigListPtr; /* fprintf(stderr, "Canvas3D_createNewContext: \n"); fprintf(stderr, " fbConfigListPtr 0x%x\n", (int) fbConfigListPtr); fprintf(stderr, " fbConfigList 0x%x, fbConfigList[0] 0x%x\n", (int) fbConfigList, (int) fbConfigList[0]); fprintf(stderr, " glslLibraryAvailable = %d\n", glslLibraryAvailable); fprintf(stderr, " cgLibraryAvailable = %d\n", cgLibraryAvailable); */ if(sharedCtxInfo == 0) sharedCtx = 0; else { sharedCtxStructure = (GraphicsContextPropertiesInfo *)sharedCtxInfo; sharedCtx = sharedCtxStructure->context; } if (display == 0) { fprintf(stderr, "Canvas3D_createNewContext: display is null\n"); ctx = NULL; } else if((fbConfigList == NULL) || (fbConfigList[0] == NULL)) { /* * fbConfig must be a valid pointer to an GLXFBConfig struct returned * by glXChooseFBConfig() for a physical screen. The visual id * 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_createNewContext: FBConfig is null\n"); ctx = NULL; } else { ctx = glXCreateNewContext((Display *)display, fbConfigList[0], GLX_RGBA_TYPE, (GLXContext)sharedCtx, True); } if (ctx == NULL) { fprintf(stderr, "Canvas3D_createNewContext: couldn't create context\n"); return 0; } /* There is a known interportability issue between Solaris and Linux(Nvidia) on the new glxMakeContextCurrent() call. Bug Id 5109045. if (!glXMakeContextCurrent((Display *)display, (GLXDrawable)window, (GLXDrawable)window,(GLXContext)ctx)) { */ if (!glXMakeCurrent((Display *)display, (GLXDrawable)window,(GLXContext)ctx)) { fprintf( stderr, "Canvas3D_createNewContext: couldn't make current\n"); return 0; } /* Shouldn't this be moved to NativeConfig. ? */ glXGetFBConfigAttrib((Display *) display, fbConfigList[0], GLX_STENCIL_SIZE, &stencilSize); gctx = (jlong)ctx; #endif /* UNIX */ #ifdef WIN32 HGLRC hrc; /* HW Rendering Context */ HDC hdc; /* HW Device Context */ jboolean rescale = JNI_FALSE; JNIEnv table = *env; DWORD err; LPTSTR errString; jboolean result; PixelFormatInfo *PixelFormatInfoPtr = (PixelFormatInfo *)fbConfigListPtr; /* Fix for issue 76 */ /* fprintf(stderr, "Canvas3D_createNewContext: \n"); fprintf(stderr, "window 0x%x\n", window); */ if(sharedCtxInfo == 0) sharedCtx = 0; else { sharedCtxStructure = (GraphicsContextPropertiesInfo *)sharedCtxInfo; sharedCtx = sharedCtxStructure->context; } hdc = (HDC) window; /* Need to handle onScreen and offScreen differently */ /* fbConfigListPtr has both an on-screen and off-screen pixel format */ if(!offScreen) { /* Fix to issue 104 */ if ((PixelFormatInfoPtr == NULL) || (PixelFormatInfoPtr->onScreenPFormat <= 0)) { printErrorMessage("Canvas3D_createNewContext: onScreen PixelFormat is invalid"); return 0; } else { PixelFormatID = PixelFormatInfoPtr->onScreenPFormat; } } else { /* offScreen case */ if ((PixelFormatInfoPtr == NULL) || (PixelFormatInfoPtr->offScreenPFormat <= 0)) { printErrorMessage("Canvas3D_createNewContext: offScreen PixelFormat is invalid"); return 0; } else { PixelFormatID = PixelFormatInfoPtr->offScreenPFormat; } } if (!SetPixelFormat(hdc, PixelFormatID, NULL)) { printErrorMessage("Canvas3D_createNewContext: Failed in SetPixelFormat"); return 0; } /* fprintf(stderr, "Before wglCreateContext\n"); */ hrc = wglCreateContext( hdc ); /* fprintf(stderr, "After wglCreateContext hrc = 0x%x\n", hrc); */ 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 ); } /* fprintf(stderr, "Before wglMakeCurrent\n"); */ result = wglMakeCurrent(hdc, hrc); /* fprintf(stderr, "After wglMakeCurrent result = %d\n", result); */ 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, cv, ctxInfo, (jlong) hdc, PixelFormatID, fbConfigListPtr, offScreen, glslLibraryAvailable, cgLibraryAvailable)) { return 0; } /* setup structure */ if(!isSharedCtx){ /* Setup field in Java side */ setupCanvasProperties(env, cv, ctxInfo); } /* Enable rescale normal */ glEnable(GL_RESCALE_NORMAL); glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); glDepthFunc(GL_LEQUAL); glEnable(GL_COLOR_MATERIAL); glReadBuffer(GL_FRONT); /* Java 3D images are aligned to 1 byte */ glPixelStorei(GL_UNPACK_ALIGNMENT, 1); return ((jlong)ctxInfo); } JNIEXPORT jboolean JNICALL Java_javax_media_j3d_NativePipeline_useCtx( JNIEnv *env, jobject obj, jlong ctxInfo, jlong display, jlong window) { GraphicsContextPropertiesInfo *ctxProperties = (GraphicsContextPropertiesInfo *)ctxInfo; jlong ctx = ctxProperties->context; int result; #if defined(UNIX) result = glXMakeCurrent((Display *)display, (GLXDrawable)window, (GLXContext)ctx); if (!result) { fprintf(stderr, "Java 3D ERROR : In Canvas3D.useCtx() glXMakeCurrent fails\n"); return JNI_FALSE; } #endif #ifdef WIN32 DWORD err; LPTSTR errString; result = wglMakeCurrent((HDC) window, (HGLRC) ctx); /* fprintf(stderr, "useCtx : wglMakeCurrent : window %d, ctx %d, result = %d\n", window, (int) ctx, result); */ 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 JNI_FALSE; } #endif return JNI_TRUE; } JNIEXPORT jint JNICALL Java_javax_media_j3d_NativePipeline_getNumCtxLights( JNIEnv *env, jobject obj, jlong ctxInfo) { GLint nlights; glGetIntegerv(GL_MAX_LIGHTS, &nlights); return((jint)nlights); } JNIEXPORT jboolean JNICALL Java_javax_media_j3d_NativePipeline_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_NativePipeline_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; table = *env; gltype = GL_RGBA; /* Temporarily disable fragment and most 3D operations */ glPushAttrib(GL_ENABLE_BIT|GL_TEXTURE_BIT|GL_DEPTH_BUFFER_BIT|GL_POLYGON_BIT); disableAttribFor2D(ctxProperties); /* Reset the polygon mode */ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); /* glGetIntegerv(GL_TEXTURE_BINDING_2D,&binding); */ glDepthMask(GL_FALSE); glBindTexture(GL_TEXTURE_2D, objectId); /* set up texture parameter */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(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 IMAGE_FORMAT_BYTE_RGBA: gltype = GL_RGBA; break; case IMAGE_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(); /* Java 3D always clears the Z-buffer */ glDepthMask(GL_TRUE); glClear(GL_DEPTH_BUFFER_BIT); glPopAttrib(); } JNIEXPORT void JNICALL Java_javax_media_j3d_NativePipeline_clear(JNIEnv *env, jobject obj, jlong ctxInfo, jfloat r, jfloat g, jfloat b) { GraphicsContextPropertiesInfo *ctxProperties = (GraphicsContextPropertiesInfo *)ctxInfo; jlong ctx = ctxProperties->context; #ifdef VERBOSE fprintf(stderr, "Canvas3D.clear()\n"); #endif glClearColor((float)r, (float)g, (float)b, ctxProperties->alphaClearValue); glClear(GL_COLOR_BUFFER_BIT); /* Java 3D always clears the Z-buffer */ glPushAttrib(GL_DEPTH_BUFFER_BIT); glDepthMask(GL_TRUE); glClear(GL_DEPTH_BUFFER_BIT); glPopAttrib(); #if 0 /* Java 3D always clears the Z-buffer */ glPushAttrib(GL_DEPTH_BUFFER_BIT); glDepthMask(GL_TRUE); glClearColor((float)r, (float)g, (float)b, ctxProperties->alphaClearValue); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); glPopAttrib(); #endif } JNIEXPORT void JNICALL Java_javax_media_j3d_NativePipeline_textureFillBackground(JNIEnv *env, jobject obj, jlong ctxInfo, jfloat texMinU, jfloat texMaxU, jfloat texMinV, jfloat texMaxV, jfloat mapMinX, jfloat mapMaxX, jfloat mapMinY, jfloat mapMaxY, jboolean useBilinearFilter ) { JNIEnv table; GraphicsContextPropertiesInfo *ctxProperties = (GraphicsContextPropertiesInfo *)ctxInfo; jlong ctx = ctxProperties->context; table = *env; #ifdef VERBOSE fprintf(stderr, "Canvas3D.textureFillBackground()\n"); #endif /* Temporarily disable fragment and most 3D operations */ glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_POLYGON_BIT); disableAttribFor2D(ctxProperties); glDepthMask(GL_FALSE); glEnable(GL_TEXTURE_2D); /* Setup filter mode if needed */ if(useBilinearFilter) { /* fprintf(stderr, "Background : use bilinear filter\n"); */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } /* For debugging only else { fprintf(stderr, "Background : Not use bilinear filter\n"); } */ /* reset the polygon mode */ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); /* 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(); #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((float) texMinU, (float) texMinV); glVertex2f((float) mapMinX, (float) mapMinY); glTexCoord2f((float) texMaxU, (float) texMinV); glVertex2f((float) mapMaxX, (float) mapMinY); glTexCoord2f((float) texMaxU, (float) texMaxV); glVertex2f((float) mapMaxX, (float) mapMaxY); glTexCoord2f((float) texMinU, (float) texMaxV); glVertex2f((float) mapMinX, (float) mapMaxY); glEnd(); /* Restore texture Matrix transform */ glPopMatrix(); glMatrixMode(GL_MODELVIEW); /* Restore attributes */ glPopAttrib(); } JNIEXPORT void JNICALL Java_javax_media_j3d_NativePipeline_textureFillRaster(JNIEnv *env, jobject obj, jlong ctxInfo, jfloat texMinU, jfloat texMaxU, jfloat texMinV, jfloat texMaxV, jfloat mapMinX, jfloat mapMaxX, jfloat mapMinY, jfloat mapMaxY, jfloat mapZ, jfloat alpha, jboolean useBilinearFilter ) { JNIEnv table; GraphicsContextPropertiesInfo *ctxProperties = (GraphicsContextPropertiesInfo *)ctxInfo; jlong ctx = ctxProperties->context; table = *env; #ifdef VERBOSE fprintf(stderr, "Canvas3D.textureFillRaster()\n"); #endif /* Temporarily disable fragment and most 3D operations */ glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_POLYGON_BIT | GL_CURRENT_BIT); disableAttribForRaster(ctxProperties); /* Setup filter mode if needed */ if(useBilinearFilter) { /* fprintf(stderr, "Raster : use bilinear filter\n"); */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } /* For debugging only else { fprintf(stderr, "Raster : Not use bilinear filter\n"); } */ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glColor4f(1.0f, 1.0f, 1.0f, (float) alpha); /* reset the polygon mode */ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); /* loaded identity modelview and projection matrix */ glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0.0, 1.0, 0.0, 1.0, 0.0, 1.0); #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((float) texMinU, (float) texMinV); glVertex3f((float) mapMinX, (float) mapMinY, (float) mapZ); glTexCoord2f((float) texMaxU, (float) texMinV); glVertex3f((float) mapMaxX, (float) mapMinY, (float) mapZ); glTexCoord2f((float) texMaxU, (float) texMaxV); glVertex3f((float) mapMaxX, (float) mapMaxY, (float) mapZ); glTexCoord2f((float) texMinU, (float) texMaxV); glVertex3f((float) mapMinX, (float) mapMaxY, (float) mapZ); glEnd(); /* Restore matrices */ glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); /* Restore attributes */ glPopAttrib(); } JNIEXPORT void JNICALL Java_javax_media_j3d_NativePipeline_executeRasterDepth(JNIEnv *env, jobject obj, jlong ctxInfo, jfloat posX, jfloat posY, jfloat posZ, jint srcOffsetX, jint srcOffsetY, jint rasterWidth, jint rasterHeight, jint depthWidth, jint depthHeight, jint depthFormat, jobject depthData) { GLint drawBuf; void *depthObjPtr; JNIEnv table; GraphicsContextPropertiesInfo *ctxProperties = (GraphicsContextPropertiesInfo *)ctxInfo; jlong ctx = ctxProperties->context; table = *env; #ifdef VERBOSE fprintf(stderr, "Canvas3D.executeRasterDepth()\n"); #endif glRasterPos3f(posX, posY, posZ); glGetIntegerv(GL_DRAW_BUFFER, &drawBuf); /* disable draw buffer */ glDrawBuffer(GL_NONE); /* * raster position is upper left corner, default for Java3D * ImageComponent currently has the data reverse in Y */ glPixelZoom(1.0, -1.0); glPixelStorei(GL_UNPACK_ROW_LENGTH, depthWidth); if (srcOffsetX >= 0) { glPixelStorei(GL_UNPACK_SKIP_PIXELS, srcOffsetX); if (srcOffsetX + rasterWidth > depthWidth) { rasterWidth = depthWidth - srcOffsetX; } } else { rasterWidth += srcOffsetX; if (rasterWidth > depthWidth) { rasterWidth = depthWidth; } } if (srcOffsetY >= 0) { glPixelStorei(GL_UNPACK_SKIP_ROWS, srcOffsetY); if (srcOffsetY + rasterHeight > depthHeight) { rasterHeight = depthHeight - srcOffsetY; } } else { rasterHeight += srcOffsetY; if (rasterHeight > depthHeight) { rasterHeight = depthHeight; } } depthObjPtr = (void *)(*(table->GetPrimitiveArrayCritical))(env, (jarray)depthData, NULL); if (depthFormat == javax_media_j3d_DepthComponentRetained_DEPTH_COMPONENT_TYPE_INT) { glDrawPixels(rasterWidth, rasterHeight, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, depthObjPtr); } else { /* javax_media_j3d_DepthComponentRetained_DEPTH_COMPONENT_TYPE_FLOAT */ glDrawPixels(rasterWidth, rasterHeight, GL_DEPTH_COMPONENT, GL_FLOAT, depthObjPtr); } (*(table->ReleasePrimitiveArrayCritical))(env, depthData, depthObjPtr, 0); /* re-enable draw buffer */ glDrawBuffer(drawBuf); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); } JNIEXPORT void JNICALL Java_javax_media_j3d_NativePipeline_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_NativePipeline_clearAccum( JNIEnv *env, jobject obj, jlong ctxInfo) { glClear(GL_ACCUM_BUFFER_BIT); } JNIEXPORT void JNICALL Java_javax_media_j3d_NativePipeline_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_NativePipeline_accumReturn( JNIEnv *env, jobject obj, jlong ctxInfo) { glAccum(GL_RETURN, 1.0); } JNIEXPORT void JNICALL Java_javax_media_j3d_NativePipeline_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_NativePipeline_swapBuffers( JNIEnv *env, jobject obj, jobject cv, jlong ctxInfo, jlong display, jlong window) { #if defined(UNIX) glXSwapBuffers((Display *)display, (Window)window); #endif #ifdef WIN32 HDC hdc; hdc = (HDC) window; 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_NativePipeline_syncRender( JNIEnv *env, jobject obj, jlong ctxInfo, jboolean waitFlag) { if (waitFlag == JNI_TRUE) glFinish(); else glFlush(); } JNIEXPORT void JNICALL Java_javax_media_j3d_NativePipeline_newDisplayList( JNIEnv *env, jobject obj, jlong ctxInfo, jint id) { if (id <= 0) { fprintf(stderr, "JAVA 3D ERROR : glNewList(%d) -- IGNORED\n", id); return; } glNewList(id, GL_COMPILE); } JNIEXPORT void JNICALL Java_javax_media_j3d_NativePipeline_endDisplayList( JNIEnv *env, jobject obj, jlong ctxInfo) { glEndList(); } JNIEXPORT void JNICALL Java_javax_media_j3d_NativePipeline_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_NativePipeline_callDisplayList( JNIEnv *env, jobject obj, jlong ctxInfo, jint id, jboolean isNonUniformScale) { GraphicsContextPropertiesInfo *ctxProperties = (GraphicsContextPropertiesInfo *)ctxInfo; jlong ctx = ctxProperties->context; static int numInvalidLists = 0; if (id <= 0) { if (numInvalidLists < 3) { fprintf(stderr, "JAVA 3D ERROR : glCallList(%d) -- IGNORED\n", id); ++numInvalidLists; } else if (numInvalidLists == 3) { fprintf(stderr, "JAVA 3D : further glCallList error messages discarded\n"); ++numInvalidLists; } return; } /* Set normalization if non-uniform scale */ if (isNonUniformScale) { glEnable(GL_NORMALIZE); } glCallList(id); /* Turn normalization back off */ if (isNonUniformScale) { glDisable(GL_NORMALIZE); } } JNIEXPORT void JNICALL Java_javax_media_j3d_NativePipeline_freeDisplayList( JNIEnv *env, jobject obj, jlong ctxInfo, jint id) { if (id <= 0) { fprintf(stderr, "JAVA 3D ERROR : glDeleteLists(%d,1) -- IGNORED\n", id); return; } glDeleteLists(id, 1); } JNIEXPORT void JNICALL Java_javax_media_j3d_NativePipeline_freeTexture( JNIEnv *env, jobject obj, 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"); } /* * Method: getTextureColorTableSize */ int getTextureColorTableSize( JNIEnv *env, jobject obj, GraphicsContextPropertiesInfo *ctxInfo, char *extensionStr) { GraphicsContextPropertiesInfo* ctxProperties = ctxInfo; int size; if (isExtensionSupported(extensionStr, "GL_ARB_imaging")) { #ifdef WIN32 ctxProperties->glColorTable = (MYPFNGLCOLORTABLEPROC)wglGetProcAddress("glColorTable"); ctxProperties->glGetColorTableParameteriv = (MYPFNGLGETCOLORTABLEPARAMETERIVPROC)wglGetProcAddress("glGetColorTableParameteriv"); #endif #if defined(UNIX) ctxProperties->glColorTable = (MYPFNGLCOLORTABLEPROC)dlsym(RTLD_DEFAULT, "glColorTable"); ctxProperties->glGetColorTableParameteriv = (MYPFNGLGETCOLORTABLEPARAMETERIVPROC)dlsym(RTLD_DEFAULT, "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(UNIX) ctxProperties->glColorTable = (MYPFNGLCOLORTABLEPROC)dlsym(RTLD_DEFAULT, "glColorTableSGI"); ctxProperties->glGetColorTableParameteriv = (MYPFNGLGETCOLORTABLEPARAMETERIVPROC)dlsym(RTLD_DEFAULT, "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; } JNIEXPORT jlong JNICALL Java_javax_media_j3d_NativePipeline_createOffScreenBuffer( JNIEnv *env, jobject obj, jobject cv, jlong ctxInfo, jlong display, jlong fbConfigListPtr, jint width, jint height) { #if defined(UNIX) /* Fix for issue 20 */ const char *extStr; int attrCount, configAttr[10]; GLXPbuffer pbuff = None; GLXFBConfig *fbConfigList = (GLXFBConfig *)fbConfigListPtr; int val; /* glXGetFBConfigAttrib((Display *) display, fbConfigList[0], GLX_FBCONFIG_ID, &val); fprintf(stderr, "GLX_FBCONFIG_ID returns %d\n", val); fprintf(stderr, "display 0x%x, fbConfigList[0] 0x%x, width %d, height %d\n", (int) display, (int) fbConfigList[0], width, height); */ /* Query DRAWABLE_TYPE. Will use Pbuffer if fbConfig support it, else will try for Pixmap. If neither one exists, flag error message and return None */ glXGetFBConfigAttrib((Display *) display, fbConfigList[0], GLX_DRAWABLE_TYPE, &val); /* fprintf(stderr, "GLX_DRAWABLE_TYPE returns %d\n", val); */ if (getJavaBoolEnv(env,"usePbuffer") && (val & GLX_PBUFFER_BIT) != 0) { /* fprintf(stderr, "Using pbuffer %d\n", val); */ /* Initialize the attribute list to be used for choosing FBConfig */ 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((Display *) display, fbConfigList[0], configAttr); if (pbuff == None) { fprintf(stderr, "Java 3D ERROR : glXCreateGLXPbuffer() returns None\n"); } return (jlong)pbuff; } else if((val & GLX_PIXMAP_BIT) != 0) { Pixmap pixmap; GLXPixmap glxpixmap = None; XVisualInfo *vinfo; Window root; Window glWin; XSetWindowAttributes win_attrs; Colormap cmap; unsigned long win_mask; /* fprintf(stderr, "Using pixmap %d\n", val); */ vinfo = glXGetVisualFromFBConfig((Display*)display, fbConfigList[0]); if (vinfo == NULL) { fprintf(stderr, "Java 3D ERROR : glXGetVisualFromFBConfig failed\n"); } else { /* fprintf(stderr, "found a %d-bit visual (visual ID = 0x%x)\n", vinfo->depth, vinfo->visualid); */ /* fall back to pixmap */ 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_mask = CWColormap | CWBorderPixel; glWin = XCreateWindow((Display *)display, root, 0, 0, 1, 1, 0, vinfo->depth, InputOutput, vinfo->visual, win_mask, &win_attrs); /* fprintf(stderr, "glWin %d\n",(int) glWin); */ pixmap = XCreatePixmap((Display*)display, (GLXDrawable)glWin, width, height, vinfo->depth); /* fprintf(stderr, "XCreatePixmap returns %d\n", (int) pixmap); */ glxpixmap = glXCreatePixmap((Display*)display, fbConfigList[0], pixmap, NULL); if (glxpixmap == None) { fprintf(stderr, "Java 3D ERROR : glXCreateGLXPixmap() returns None\n"); } } /* fprintf(stderr, "glxpixmap %d\n",(int) glxpixmap); */ return (jlong)glxpixmap; } else { fprintf(stderr, "Java 3D ERROR : FBConfig doesn't support pbuffer or pixmap returns None\n"); return (jlong)None; } #endif /* UNIX */ #ifdef WIN32 /* Fix for issue 76 */ int dpy = (int)display; static char szAppName[] = "CreateOffScreen"; HWND hwnd; HGLRC hrc; HDC hdc; int pixelFormat; PixelFormatInfo *pFormatInfoPtr = (PixelFormatInfo *)fbConfigListPtr; int piAttrs[2]; HPBUFFERARB hpbuf = NULL; /* Handle to the Pbuffer */ HDC hpbufdc = NULL; /* Handle to the Pbuffer's device context */ HDC bitmapHdc; HBITMAP hbitmap; BITMAPINFOHEADER bih; void *ppvBits; int err; LPTSTR errString; OffScreenBufferInfo *offScreenBufferInfo = NULL; PIXELFORMATDESCRIPTOR dummy_pfd = getDummyPFD(); jclass cv_class; jfieldID offScreenBuffer_field; JNIEnv table = *env; /* fprintf(stderr, "****** CreateOffScreenBuffer ******\n"); fprintf(stderr, "display 0x%x, pFormat %d, width %d, height %d\n", (int) display, pFormatInfoPtr->offScreenPFormat, width, height); */ cv_class = (jclass) (*(table->GetObjectClass))(env, cv); offScreenBuffer_field = (jfieldID) (*(table->GetFieldID))(env, cv_class, "offScreenBufferInfo", "J"); /* * Select any pixel format and bound current context to * it so that we can get the wglChoosePixelFormatARB entry point. * Otherwise wglxxx entry point will always return null. * That's why we need to create a dummy window also. */ hwnd = createDummyWindow((const char *)szAppName); if (!hwnd) { return 0; } hdc = GetDC(hwnd); pixelFormat = ChoosePixelFormat(hdc, &dummy_pfd); if (pixelFormat<1) { printErrorMessage("In Canvas3D : Failed in ChoosePixelFormat"); DestroyWindow(hwnd); UnregisterClass(szAppName, (HINSTANCE)NULL); return 0; } SetPixelFormat(hdc, pixelFormat, NULL); hrc = wglCreateContext(hdc); if (!hrc) { printErrorMessage("In Canvas3D : Failed in wglCreateContext"); DestroyWindow(hwnd); UnregisterClass(szAppName, (HINSTANCE)NULL); return 0; } if (!wglMakeCurrent(hdc, hrc)) { printErrorMessage("In Canvas3D : Failed in wglMakeCurrent"); ReleaseDC(hwnd, hdc); wglDeleteContext(hrc); DestroyWindow(hwnd); UnregisterClass(szAppName, (HINSTANCE)NULL); return 0; } if (pFormatInfoPtr->drawToPbuffer) { /* fprintf(stderr, "***** Use PBuffer for offscreen ******\n"); */ piAttrs[0] = 0; piAttrs[1] = 0; hpbuf = pFormatInfoPtr->wglCreatePbufferARB( hdc, pFormatInfoPtr->offScreenPFormat, width, height, piAttrs); if(hpbuf == NULL) { printErrorMessage("In Canvas3D : wglCreatePbufferARB FAIL."); ReleaseDC(hwnd, hdc); wglDeleteContext(hrc); DestroyWindow(hwnd); UnregisterClass(szAppName, (HINSTANCE)NULL); return 0; } hpbufdc = pFormatInfoPtr->wglGetPbufferDCARB(hpbuf); if(hpbufdc == NULL) { printErrorMessage("In Canvas3D : Can't get pbuffer's device context."); ReleaseDC(hwnd, hdc); wglDeleteContext(hrc); DestroyWindow(hwnd); UnregisterClass(szAppName, (HINSTANCE)NULL); return 0; } /* fprintf(stderr, "Successfully created PBuffer = 0x%x, hdc = 0x%x\n", (int)hpbuf, (int)hpbufdc); */ /* Destroy all dummy objects */ ReleaseDC(hwnd, hdc); wglDeleteContext(hrc); DestroyWindow(hwnd); UnregisterClass(szAppName, (HINSTANCE)NULL); offScreenBufferInfo = (OffScreenBufferInfo *) malloc(sizeof(OffScreenBufferInfo)); offScreenBufferInfo->isPbuffer = GL_TRUE; offScreenBufferInfo->hpbuf = hpbuf; (*(table->SetLongField))(env, cv, offScreenBuffer_field, (jlong)offScreenBufferInfo); return (jlong) hpbufdc; } /* fprintf(stderr, "***** Use Bitmap for offscreen ******\n"); */ /* create a DIB */ memset(&bih, 0, sizeof(BITMAPINFOHEADER)); bih.biSize = sizeof(BITMAPINFOHEADER); bih.biWidth = width; bih.biHeight = height; bih.biPlanes = 1; /* by MIK OF CLASSX */ if (getJavaBoolEnv(env, "transparentOffScreen")) { bih.biBitCount = 32; } else { bih.biBitCount = 24; } bih.biCompression = BI_RGB; bitmapHdc = CreateCompatibleDC(hdc); hbitmap = CreateDIBSection(bitmapHdc, (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); } SelectObject(bitmapHdc, hbitmap); /* Choosing and setting of pixel format is done in createContext */ /* Destroy all dummy objects and fall BitMap */ ReleaseDC(hwnd, hdc); wglDeleteContext(hrc); DestroyWindow(hwnd); UnregisterClass(szAppName, (HINSTANCE)NULL); offScreenBufferInfo = (OffScreenBufferInfo *) malloc(sizeof(OffScreenBufferInfo)); offScreenBufferInfo->isPbuffer = GL_FALSE; offScreenBufferInfo->hpbuf = 0; (*(table->SetLongField))(env, cv, offScreenBuffer_field, (jlong)offScreenBufferInfo); return ((jlong)bitmapHdc); #endif /* WIN32 */ } JNIEXPORT void JNICALL Java_javax_media_j3d_NativePipeline_destroyOffScreenBuffer( JNIEnv *env, jobject obj, jobject cv, jlong ctxInfo, jlong display, jlong fbConfigListPtr, jlong window) { jclass cv_class; jfieldID offScreenBuffer_field; JNIEnv table = *env; #if defined(UNIX) /* Fix for Issue 20 */ GLXFBConfig *fbConfigList = (GLXFBConfig *)fbConfigListPtr; int val; glXGetFBConfigAttrib((Display *) display, (GLXFBConfig) fbConfigList[0], GLX_DRAWABLE_TYPE, &val); /* fprintf(stderr, "GLX_DRAWABLE_TYPE returns %d\n", val); */ if((val & GLX_PBUFFER_BIT) != 0) { glXDestroyPbuffer((Display *) display, (GLXPbuffer)window); } else if((val & GLX_PIXMAP_BIT) != 0) { glXDestroyPixmap((Display *) display, (GLXPixmap)window); } #endif /* UNIX */ #ifdef WIN32 /* Fix for issue 76 */ PixelFormatInfo *pFormatInfoPtr = (PixelFormatInfo *)fbConfigListPtr; OffScreenBufferInfo *offScreenBufferInfo = NULL; HDC hpbufdc = (HDC) window; cv_class = (jclass) (*(table->GetObjectClass))(env, cv); offScreenBuffer_field = (jfieldID) (*(table->GetFieldID))(env, cv_class, "offScreenBufferInfo", "J"); offScreenBufferInfo = (OffScreenBufferInfo *) (*(table->GetLongField))(env, cv, offScreenBuffer_field); /* fprintf(stderr,"Canvas3D_destroyOffScreenBuffer : offScreenBufferInfo 0x%x\n", offScreenBufferInfo); */ if(offScreenBufferInfo == NULL) { return; } if(offScreenBufferInfo->isPbuffer) { /* fprintf(stderr,"Canvas3D_destroyOffScreenBuffer : Pbuffer\n"); */ pFormatInfoPtr->wglReleasePbufferDCARB(offScreenBufferInfo->hpbuf, hpbufdc); pFormatInfoPtr->wglDestroyPbufferARB(offScreenBufferInfo->hpbuf); } else { HBITMAP oldhbitmap; HDC hdc = (HDC) window; /* fprintf(stderr,"Canvas3D_destroyOffScreenBuffer : BitMap\n"); */ oldhbitmap = SelectObject(hdc, NULL); DeleteObject(oldhbitmap); DeleteDC(hdc); } free(offScreenBufferInfo); (*(table->SetLongField))(env, cv, offScreenBuffer_field, (jlong)0); #endif /* WIN32 */ } JNIEXPORT void JNICALL Java_javax_media_j3d_NativePipeline_readOffScreenBuffer( JNIEnv *env, jobject obj, jobject cv, jlong ctxInfo, jint format, jint dataType, jobject data, jint width, jint height) { JNIEnv table = *env; int type; void *imageObjPtr; GraphicsContextPropertiesInfo *ctxProperties = (GraphicsContextPropertiesInfo *)ctxInfo; jlong ctx = ctxProperties->context; glPixelStorei(GL_PACK_ROW_LENGTH, width); glPixelStorei(GL_PACK_ALIGNMENT, 1); if((dataType == IMAGE_DATA_TYPE_BYTE_ARRAY) || (dataType == IMAGE_DATA_TYPE_INT_ARRAY)) { imageObjPtr = (void *)(*(table->GetPrimitiveArrayCritical))(env, (jarray)data, NULL); } else { imageObjPtr = (void *)(*(table->GetDirectBufferAddress))(env, data); } if((dataType == IMAGE_DATA_TYPE_BYTE_ARRAY) || (dataType == IMAGE_DATA_TYPE_BYTE_BUFFER)) { switch (format) { /* GL_BGR */ case IMAGE_FORMAT_BYTE_BGR: type = GL_BGR; break; case IMAGE_FORMAT_BYTE_RGB: type = GL_RGB; break; /* GL_ABGR_EXT */ case IMAGE_FORMAT_BYTE_ABGR: if (ctxProperties->abgr_ext) { /* If its zero, should never come here! */ type = GL_ABGR_EXT; } else { throwAssert(env, "GL_ABGR_EXT format is unsupported"); return; } break; case IMAGE_FORMAT_BYTE_RGBA: type = GL_RGBA; break; /* This method only supports 3 and 4 components formats and BYTE types. */ case IMAGE_FORMAT_BYTE_LA: case IMAGE_FORMAT_BYTE_GRAY: case IMAGE_FORMAT_USHORT_GRAY: case IMAGE_FORMAT_INT_BGR: case IMAGE_FORMAT_INT_RGB: case IMAGE_FORMAT_INT_ARGB: default: throwAssert(env, "illegal format"); return; } glReadPixels(0, 0, width, height, type, GL_UNSIGNED_BYTE, imageObjPtr); } else if((dataType == IMAGE_DATA_TYPE_INT_ARRAY) || (dataType == IMAGE_DATA_TYPE_INT_BUFFER)) { GLenum intType = GL_UNSIGNED_INT_8_8_8_8; GLboolean forceAlphaToOne = GL_FALSE; switch (format) { /* GL_BGR */ case IMAGE_FORMAT_INT_BGR: /* Assume XBGR format */ type = GL_RGBA; intType = GL_UNSIGNED_INT_8_8_8_8_REV; forceAlphaToOne = GL_TRUE; break; case IMAGE_FORMAT_INT_RGB: /* Assume XRGB format */ forceAlphaToOne = GL_TRUE; /* Fall through to next case */ case IMAGE_FORMAT_INT_ARGB: type = GL_BGRA; intType = GL_UNSIGNED_INT_8_8_8_8_REV; break; /* This method only supports 3 and 4 components formats and INT types. */ case IMAGE_FORMAT_BYTE_LA: case IMAGE_FORMAT_BYTE_GRAY: case IMAGE_FORMAT_USHORT_GRAY: case IMAGE_FORMAT_BYTE_BGR: case IMAGE_FORMAT_BYTE_RGB: case IMAGE_FORMAT_BYTE_RGBA: case IMAGE_FORMAT_BYTE_ABGR: default: throwAssert(env, "illegal format"); return; } /* Force Alpha to 1.0 if needed */ if(forceAlphaToOne) { glPixelTransferf(GL_ALPHA_SCALE, 0.0f); glPixelTransferf(GL_ALPHA_BIAS, 1.0f); } glReadPixels(0, 0, width, height, type, intType, imageObjPtr); /* Restore Alpha scale and bias */ if(forceAlphaToOne) { glPixelTransferf(GL_ALPHA_SCALE, 1.0f); glPixelTransferf(GL_ALPHA_BIAS, 0.0f); } } else { throwAssert(env, "illegal image data type"); } if((dataType == IMAGE_DATA_TYPE_BYTE_ARRAY) || (dataType == IMAGE_DATA_TYPE_INT_ARRAY)) { (*(table->ReleasePrimitiveArrayCritical))(env, data, imageObjPtr, 0); } } static void initializeCtxInfo(JNIEnv *env , GraphicsContextPropertiesInfo* ctxInfo) { ctxInfo->context = 0; /* version and extension info */ ctxInfo->versionStr = NULL; ctxInfo->vendorStr = NULL; ctxInfo->rendererStr = NULL; ctxInfo->extensionStr = NULL; ctxInfo->versionNumbers[0] = 1; ctxInfo->versionNumbers[1] = 1; ctxInfo->gl13 = JNI_FALSE; ctxInfo->gl14 = JNI_FALSE; ctxInfo->gl20 = JNI_FALSE; /* 1.2 and GL_ARB_imaging */ ctxInfo->blend_color_ext = JNI_FALSE; ctxInfo->blendFunctionTable[BLEND_ZERO] = GL_ZERO; ctxInfo->blendFunctionTable[BLEND_ONE] = GL_ONE; ctxInfo->blendFunctionTable[BLEND_SRC_ALPHA] = GL_SRC_ALPHA; ctxInfo->blendFunctionTable[BLEND_ONE_MINUS_SRC_ALPHA] = GL_ONE_MINUS_SRC_ALPHA; ctxInfo->blendFunctionTable[BLEND_DST_COLOR] = GL_DST_COLOR; ctxInfo->blendFunctionTable[BLEND_ONE_MINUS_DST_COLOR] = GL_ONE_MINUS_DST_COLOR; ctxInfo->blendFunctionTable[BLEND_SRC_COLOR] = GL_SRC_COLOR; ctxInfo->blendFunctionTable[BLEND_ONE_MINUS_SRC_COLOR] = GL_ONE_MINUS_SRC_COLOR; ctxInfo->blendFunctionTable[BLEND_CONSTANT_COLOR] = GL_CONSTANT_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->texture_clamp_to_border_enum = GL_CLAMP; ctxInfo->global_alpha_sun = JNI_FALSE; /* EXT extensions */ ctxInfo->abgr_ext = JNI_FALSE; ctxInfo->multi_draw_arrays_ext = JNI_FALSE; ctxInfo->implicit_multisample = getJavaBoolEnv(env, "implicitAntialiasing"); /* by MIK OF CLASSX */ ctxInfo->alphaClearValue = (getJavaBoolEnv(env, "transparentOffScreen") ? 0.0f : 1.0f); ctxInfo->multisample = JNI_FALSE; /* Multitexture support */ ctxInfo->maxTexCoordSets = 1; ctxInfo->maxTextureUnits = 1; ctxInfo->maxTextureImageUnits = 0; ctxInfo->maxVertexTextureImageUnits = 0; ctxInfo->maxCombinedTextureImageUnits = 0; ctxInfo->textureEnvCombineAvailable = JNI_FALSE; ctxInfo->textureCombineDot3Available = JNI_FALSE; ctxInfo->textureCombineSubtractAvailable = 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; /* extension mask */ ctxInfo->extMask = 0; ctxInfo->textureExtMask = 0; ctxInfo->shadingLanguageGLSL = JNI_FALSE; ctxInfo->shadingLanguageCg = JNI_FALSE; ctxInfo->glBlendColor = NULL; ctxInfo->glBlendColorEXT = NULL; ctxInfo->glColorTable = NULL; ctxInfo->glGetColorTableParameteriv = NULL; ctxInfo->glTexImage3DEXT = NULL; ctxInfo->glTexSubImage3DEXT = NULL; ctxInfo->glClientActiveTexture = NULL; ctxInfo->glMultiDrawArraysEXT = NULL; ctxInfo->glMultiDrawElementsEXT = NULL; ctxInfo->glLockArraysEXT = NULL; ctxInfo->glUnlockArraysEXT = NULL; ctxInfo->glMultiTexCoord2fv = NULL; ctxInfo->glMultiTexCoord3fv = NULL; ctxInfo->glMultiTexCoord4fv = NULL; ctxInfo->glLoadTransposeMatrixd = NULL; ctxInfo->glMultTransposeMatrixd = NULL; ctxInfo->glActiveTexture = 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; /* Initialize shader program Id */ ctxInfo->shaderProgramId = 0; /* Initialize maximum number of vertex attrs */ ctxInfo->maxVertexAttrs = 0; /* Initialize shader vertex attribute function pointers */ ctxInfo->vertexAttrPointer = dummyVertexAttrPointer; ctxInfo->enableVertexAttrArray = dummyEnDisableVertexAttrArray; ctxInfo->disableVertexAttrArray = dummyEnDisableVertexAttrArray; ctxInfo->vertexAttr1fv = dummyVertexAttr; ctxInfo->vertexAttr2fv = dummyVertexAttr; ctxInfo->vertexAttr3fv = dummyVertexAttr; ctxInfo->vertexAttr4fv = dummyVertexAttr; /* Initialize shader info pointers */ ctxInfo->glslCtxInfo = NULL; ctxInfo->cgCtxInfo = NULL; } static void cleanupCtxInfo(GraphicsContextPropertiesInfo* ctxInfo) { if( ctxInfo->versionStr != NULL) free(ctxInfo->versionStr); if( ctxInfo->vendorStr != NULL) free(ctxInfo->vendorStr); if( ctxInfo->rendererStr != NULL) free(ctxInfo->rendererStr); if( ctxInfo->extensionStr != NULL) free(ctxInfo->extensionStr); ctxInfo->versionStr = NULL; ctxInfo->vendorStr = NULL; ctxInfo->rendererStr = NULL; ctxInfo->extensionStr = NULL; } #ifdef WIN32 HWND createDummyWindow(const char* szAppName) { static const char *szTitle = "Dummy Window"; 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) { printErrorMessage("createDummyWindow: couldn't register class"); return NULL; } /* 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 ){ printErrorMessage("createDummyWindow: couldn't create window"); UnregisterClass(szAppName, (HINSTANCE)NULL); return NULL; } return hWnd; } #endif JNIEXPORT void JNICALL Java_javax_media_j3d_NativePipeline_createQueryContext( JNIEnv *env, jobject obj, jobject cv, jlong display, jlong window, jlong fbConfigListPtr, jboolean offScreen, jint width, jint height, jboolean glslLibraryAvailable, jboolean cgLibraryAvailable) { JNIEnv table = *env; jlong gctx; int stencilSize=0; jlong newWin; int PixelFormatID=0; GraphicsContextPropertiesInfo* ctxInfo = (GraphicsContextPropertiesInfo *)malloc(sizeof(GraphicsContextPropertiesInfo)); #if defined(UNIX) /* Fix for issue 20 */ XVisualInfo *vinfo, template; int nitems; GLXContext ctx; int result; Window root; Window glWin; XSetWindowAttributes win_attrs; Colormap cmap; unsigned long win_mask; jlong hdc; GLXFBConfig *fbConfigList = NULL; fbConfigList = (GLXFBConfig *)fbConfigListPtr; /* fprintf(stderr, "Canvas3D_createQueryContext:\n"); fprintf(stderr, "fbConfigListPtr 0x%x\n", (int) fbConfigListPtr); fprintf(stderr, "fbConfigList 0x%x, fbConfigList[0] 0x%x\n", (int) fbConfigList, (int) fbConfigList[0]); */ ctx = glXCreateNewContext((Display *)display, fbConfigList[0], GLX_RGBA_TYPE, NULL, True); if (ctx == NULL) { fprintf(stderr, "Java 3D ERROR : Canvas3D_createQueryContext: couldn't create context.\n"); } /* onscreen rendering and window is 0 now */ if(window == 0 && !offScreen) { vinfo = glXGetVisualFromFBConfig((Display*)display, fbConfigList[0]); if (vinfo == NULL) { fprintf(stderr, "Java 3D ERROR : glXGetVisualFromFBConfig failed\n"); } else { /* fprintf(stderr, "found a %d-bit visual (visual ID = 0x%x)\n", vinfo->depth, vinfo->visualid); */ 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 = (jlong)glWin; } } else if(window == 0 && offScreen){ newWin = Java_javax_media_j3d_NativePipeline_createOffScreenBuffer(env, obj, cv, 0, display, fbConfigListPtr, width, height); } else if(window != 0) { newWin = window; } result = glXMakeCurrent((Display *)display, (GLXDrawable)newWin, (GLXContext)ctx); if (!result) fprintf(stderr, "Java 3D ERROR : glXMakeCurrent fails\n"); glXGetFBConfigAttrib((Display *) display, fbConfigList[0], GLX_STENCIL_SIZE, &stencilSize); gctx = (jlong)ctx; #endif #ifdef WIN32 HGLRC hrc; /* HW Rendering Context */ HDC hdc; /* HW Device Context */ DWORD err; LPTSTR errString; HWND hDummyWnd = 0; static char szAppName[] = "OpenGL"; jlong vinfo = 0; jboolean result; PixelFormatInfo *PixelFormatInfoPtr = (PixelFormatInfo *)fbConfigListPtr; /* Fix for issue 76 */ /* fprintf(stderr, "Canvas3D_createQueryContext:\n"); fprintf(stderr, "window is 0x%x, offScreen %d\n", window, offScreen); */ /* Fix to issue 104 */ if(!offScreen) { if ((PixelFormatInfoPtr == NULL) || (PixelFormatInfoPtr->onScreenPFormat <= 0)) { printErrorMessage("Canvas3D_createNewContext: onScreen PixelFormat is invalid"); return; } else { PixelFormatID = PixelFormatInfoPtr->onScreenPFormat; } } else { if ((PixelFormatInfoPtr == NULL) || (PixelFormatInfoPtr->offScreenPFormat <= 0)) { printErrorMessage("Canvas3D_createNewContext: offScreen PixelFormat is invalid"); return; } else { PixelFormatID = PixelFormatInfoPtr->offScreenPFormat; } } /* onscreen rendering and window is 0 now */ if(window == 0 && !offScreen){ /* fprintf(stderr, "CreateQueryContext : window == 0 && !offScreen\n"); */ hDummyWnd = createDummyWindow(szAppName); if (!hDummyWnd) { return; } hdc = GetDC(hDummyWnd); } else if(window == 0 && offScreen){ /* fprintf(stderr, "CreateQueryContext : window == 0 && offScreen\n"); */ hdc = (HDC)Java_javax_media_j3d_NativePipeline_createOffScreenBuffer(env, obj, cv, 0, display, fbConfigListPtr, width, height); } else if(window != 0){ /* fprintf(stderr, "CreateQueryContext : window != 0 0x%x\n", window); */ hdc = (HDC) window; } newWin = (jlong)hdc; SetPixelFormat(hdc, PixelFormatID, NULL); 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, cv, ctxInfo, (jlong) hdc, PixelFormatID, fbConfigListPtr, offScreen, glslLibraryAvailable, cgLibraryAvailable)) { /* put the properties to the Java side */ setupCanvasProperties(env, cv, ctxInfo); } /* clear up the context , colormap and window if appropriate */ if(window == 0 && !offScreen){ #if defined(UNIX) Java_javax_media_j3d_NativePipeline_destroyContext(env, obj, display, newWin, (jlong)ctxInfo); XDestroyWindow((Display *)display, glWin); XFreeColormap((Display *)display, cmap); #endif /* UNIX */ #ifdef WIN32 /* Release DC */ ReleaseDC(hDummyWnd, hdc); /* Destroy context */ /* This will free ctxInfo also */ Java_javax_media_j3d_NativePipeline_destroyContext(env, obj, display,newWin, (jlong)ctxInfo); DestroyWindow(hDummyWnd); UnregisterClass(szAppName, (HINSTANCE)NULL); #endif /* WIN32 */ } else if(window == 0 && offScreen) { Java_javax_media_j3d_NativePipeline_destroyOffScreenBuffer(env, obj, cv, gctx, display, fbConfigListPtr, newWin); Java_javax_media_j3d_NativePipeline_destroyContext(env, obj, display, newWin, (jlong)ctxInfo); } else if(window != 0){ Java_javax_media_j3d_NativePipeline_destroyContext(env, obj, display, newWin, (jlong)ctxInfo); } } JNIEXPORT void JNICALL Java_javax_media_j3d_NativePipeline_beginScene( JNIEnv *env, jobject obj, jlong ctxInfo) { /* Not used by OGL renderer */ } JNIEXPORT void JNICALL Java_javax_media_j3d_NativePipeline_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_NativePipeline_setFullSceneAntialiasing (JNIEnv *env, jobject obj, jlong ctxInfo, jboolean enable) { GraphicsContextPropertiesInfo *ctxProperties = (GraphicsContextPropertiesInfo *)ctxInfo; jlong ctx = ctxProperties->context; if (ctxProperties->multisample && !ctxProperties->implicit_multisample) { if(enable == JNI_TRUE) { glEnable(GL_MULTISAMPLE); } else { glDisable(GL_MULTISAMPLE); } } } /* * Return false if <= 8 bit color under windows */ JNIEXPORT jboolean JNICALL Java_javax_media_j3d_NativePipeline_validGraphicsMode( JNIEnv *env, jobject obj) { #ifdef WIN32 DEVMODE devMode; EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devMode); return (devMode.dmBitsPerPel > 8); #endif #if defined(UNIX) return JNI_TRUE; #endif } JNIEXPORT void JNICALL Java_javax_media_j3d_NativePipeline_cleanupRenderer( JNIEnv *env, jobject obj) { /* No-op for OGL pipeline */ } /* * Function to disable most rendering attributes when doing a 2D * clear, or image copy operation. Note that the * caller must save/restore the attributes with * pushAttrib(GL_ENABLE_BIT|...) and popAttrib() */ static void disableAttribFor2D(GraphicsContextPropertiesInfo *ctxProperties) { int i; glDisable(GL_ALPHA_TEST); glDisable(GL_BLEND); glDisable(GL_COLOR_LOGIC_OP); glDisable(GL_COLOR_MATERIAL); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glDisable(GL_FOG); glDisable(GL_LIGHTING); glDisable(GL_POLYGON_OFFSET_FILL); glDisable(GL_POLYGON_STIPPLE); glDisable(GL_STENCIL_TEST); glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_GEN_Q); glDisable(GL_TEXTURE_GEN_R); glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); for (i = 0; i < 6; i++) { glDisable(GL_CLIP_PLANE0 + i); } glDisable(GL_TEXTURE_3D); glDisable(GL_TEXTURE_CUBE_MAP); if (ctxProperties->textureRegisterCombinersAvailable) { glDisable(GL_REGISTER_COMBINERS_NV); } if (ctxProperties->textureColorTableAvailable) { glDisable(GL_TEXTURE_COLOR_TABLE_SGI); } if (ctxProperties->global_alpha_sun) { glDisable(GL_GLOBAL_ALPHA_SUN); } } /* * Function to disable most rendering attributes when doing a Raster * clear, or image copy operation. Note that the * caller must save/restore the attributes with * pushAttrib(GL_ENABLE_BIT|...) and popAttrib() */ static void disableAttribForRaster(GraphicsContextPropertiesInfo *ctxProperties) { glDisable(GL_COLOR_MATERIAL); glDisable(GL_CULL_FACE); glDisable(GL_LIGHTING); glDisable(GL_POLYGON_OFFSET_FILL); glDisable(GL_POLYGON_STIPPLE); // TODO: Disable if Raster.CLIP_POSITION is true // for (int i = 0; i < 6; i++) { // glDisable(GL_CLIP_PLANE0 + i); // } if (ctxProperties->global_alpha_sun) { glDisable(GL_GLOBAL_ALPHA_SUN); } }