aboutsummaryrefslogtreecommitdiffstats
path: root/src/native/ogl/NativeConfigTemplate3D.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/native/ogl/NativeConfigTemplate3D.c')
-rw-r--r--src/native/ogl/NativeConfigTemplate3D.c1277
1 files changed, 1277 insertions, 0 deletions
diff --git a/src/native/ogl/NativeConfigTemplate3D.c b/src/native/ogl/NativeConfigTemplate3D.c
new file mode 100644
index 0000000..66a5324
--- /dev/null
+++ b/src/native/ogl/NativeConfigTemplate3D.c
@@ -0,0 +1,1277 @@
+/*
+ * $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 <jni.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include "gldefs.h"
+
+#if defined(SOLARIS) || defined(__linux__)
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#endif
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+/* check if the extension is supported */
+extern int isExtensionSupported(const char *allExtensions, const char *extension);
+
+#if defined(SOLARIS) || defined(__linux__)
+
+XVisualInfo *findVisualInfoSwitchDoubleBufferAndStereo(jlong display,
+ jint screen,
+ int* glxAttrs,
+ int sVal, int sIndex,
+ int dbVal, int dbIndex ) {
+ int stereoLoop;
+ int doubleBufferLoop;
+ XVisualInfo *vis_info = NULL;
+
+ int i, j;
+ /*
+ * set all "enums" to user's preferred state
+ */
+ if (dbVal == REQUIRED || dbVal == PREFERRED)
+ glxAttrs[dbIndex] = GLX_DOUBLEBUFFER;
+ else
+ glxAttrs[dbIndex] = GLX_USE_GL;
+
+ if (sVal == REQUIRED || sVal == PREFERRED)
+ glxAttrs[sIndex] = GLX_STEREO;
+ else
+ glxAttrs[sIndex] = GLX_USE_GL;
+
+ vis_info = glXChooseVisual((Display*)display, screen, glxAttrs);
+ if (vis_info == NULL) {
+ /*
+ * coudn't match visual with default values - try
+ * enabling UNNECESSARY attributes.
+ */
+ if(sVal == UNNECESSARY)
+ stereoLoop = 1;
+ else
+ stereoLoop = 0;
+
+ if(dbVal == UNNECESSARY)
+ doubleBufferLoop = 1;
+ else
+ doubleBufferLoop = 0;
+
+ i = 0;
+ while(i <= stereoLoop && vis_info == NULL ) {
+ if (sVal == UNNECESSARY)
+ glxAttrs[sIndex] = i? GLX_STEREO : GLX_USE_GL;
+ j = 0;
+ while(j <= doubleBufferLoop && vis_info == NULL) {
+ if(dbVal == UNNECESSARY) {
+ glxAttrs[dbIndex] = j? GLX_USE_GL: GLX_DOUBLEBUFFER;
+ }
+ vis_info = glXChooseVisual((Display*)display, screen, glxAttrs);
+ j++;
+ } /* end of doubleBufferLoop */
+ i++;
+ } /* end of stereoLoop */
+ }
+
+ if (vis_info == NULL) {
+ /*
+ * still coudn't match visual with default values - try
+ * disabling PREFERRED attributes.
+ */
+ /* restore default values */
+ if (sVal == REQUIRED || sVal == PREFERRED)
+ glxAttrs[sIndex] = GLX_STEREO;
+ else
+ glxAttrs[sIndex] = GLX_USE_GL;
+
+ if (dbVal == REQUIRED || dbVal == PREFERRED)
+ glxAttrs[dbIndex] = GLX_DOUBLEBUFFER;
+ else
+ glxAttrs[dbIndex] = GLX_USE_GL;
+
+ if(sVal == PREFERRED)
+ stereoLoop = 1;
+ else
+ stereoLoop = 0;
+
+ if(dbVal == PREFERRED)
+ doubleBufferLoop = 1;
+ else
+ doubleBufferLoop = 0;
+
+ i = 0;
+ while(i <= stereoLoop && vis_info == NULL ) {
+ if (sVal == PREFERRED)
+ glxAttrs[sIndex] = i? GLX_USE_GL : GLX_STEREO ;
+ j = 0;
+ while(j <= doubleBufferLoop && vis_info == NULL) {
+ if(dbVal == PREFERRED) {
+ glxAttrs[dbIndex] = j? GLX_DOUBLEBUFFER : GLX_USE_GL;
+ }
+ vis_info = glXChooseVisual((Display*)display, screen, glxAttrs);
+ j++;
+ } /* end of doubleBufferLoop */
+ i++;
+ } /* end of stereoLoop */
+ }
+
+ if (vis_info == NULL) {
+
+ /*
+ * STILL coudn't match visual with default values - try
+ * disabling PREFERRED attributes and enabling UNNECESSARY.
+ */
+
+ /* restore default values */
+ if (sVal == REQUIRED || sVal == PREFERRED)
+ glxAttrs[sIndex] = GLX_STEREO;
+ else
+ glxAttrs[sIndex] = GLX_USE_GL;
+
+ if (dbVal == REQUIRED || dbVal == PREFERRED)
+ glxAttrs[dbIndex] = GLX_DOUBLEBUFFER;
+ else
+ glxAttrs[dbIndex] = GLX_USE_GL;
+
+ if(sVal != REQUIRED)
+ stereoLoop = 1;
+ else
+ stereoLoop = 0;
+
+ if(dbVal != REQUIRED)
+ doubleBufferLoop = 1;
+ else
+ doubleBufferLoop = 0;
+
+ i = 0;
+ while(i <= stereoLoop && vis_info == NULL ) {
+ if (sVal == PREFERRED || sVal == UNNECESSARY)
+ glxAttrs[sIndex] = i? GLX_USE_GL : GLX_STEREO ;
+ j = 0;
+ while(j <= doubleBufferLoop && vis_info == NULL) {
+ if(dbVal == PREFERRED || dbVal == UNNECESSARY) {
+ glxAttrs[dbIndex] = j? GLX_DOUBLEBUFFER : GLX_USE_GL;
+ }
+ vis_info = glXChooseVisual((Display*)display, screen, glxAttrs);
+ j++;
+ } /* end of doubleBufferLoop */
+ i++;
+ } /* end of stereoLoop */
+ }
+ return vis_info;
+}
+
+/*
+ * Uses the past in array to choose the best OpenGL visual.
+ * When the "best" visual cannot be used, the "enums" (three
+ * state attributes) are looped through setting/resetting in all
+ * combinations in hopes of finding an valid visual.
+ */
+JNIEXPORT
+jint JNICALL Java_javax_media_j3d_NativeConfigTemplate3D_chooseOglVisual(
+ JNIEnv *env,
+ jobject obj,
+ jlong display,
+ jint screen,
+ jintArray attrList,
+ jlongArray vInfArray)
+{
+ VisualID vis_id = 0;
+ jint *mx_ptr;
+ int glxAttrs[256]; /* value, attr pair plus a None */
+ int index;
+ XVisualInfo *vis_info = NULL;
+
+ /* use to cycle through when attr is not REQUIRED */
+ int sVal;
+ int sIndex;
+
+ int dbVal;
+ int dbIndex;
+
+ int antialiasVal;
+ int antialiasIndex;
+
+ const char *glxExtensions = NULL;
+ jlong *visInfo = (*env)->GetLongArrayElements(env, vInfArray, NULL);
+
+ mx_ptr = (jint *)(*env)->GetPrimitiveArrayCritical(env, attrList, NULL);
+
+ /*
+ * convert Java 3D values to GLX
+ */
+ index = 0;
+ glxAttrs[index++] = GLX_RGBA; /* only interested in RGB visuals */
+ glxAttrs[index++] = GLX_RED_SIZE;
+ glxAttrs[index++] = mx_ptr[RED_SIZE];
+ glxAttrs[index++] = GLX_GREEN_SIZE;
+ glxAttrs[index++] = mx_ptr[GREEN_SIZE];
+ glxAttrs[index++] = GLX_BLUE_SIZE;
+ glxAttrs[index++] = mx_ptr[BLUE_SIZE];
+ glxAttrs[index++] = GLX_DEPTH_SIZE;
+ glxAttrs[index++] = mx_ptr[DEPTH_SIZE];
+
+
+ dbIndex = index++;
+ dbVal = mx_ptr[DOUBLEBUFFER];
+
+ sIndex = index++;
+ sVal = mx_ptr[STEREO];
+
+ antialiasIndex = index++;
+ antialiasVal = mx_ptr[ANTIALIASING];
+
+ /* glxAttrs[index] = None; */
+
+ (*env)->ReleasePrimitiveArrayCritical(env, attrList, mx_ptr, 0);
+
+
+ if(antialiasVal == REQUIRED || antialiasVal== PREFERRED) {
+ /* try GLX_ARB_multisample */
+ glxExtensions = (const char *)glXGetClientString((Display*)display, GLX_EXTENSIONS);
+
+
+ if(isExtensionSupported(glxExtensions, "GLX_ARB_multisample")){
+ /* path 1: */
+ /* Query the visual with mulitsamples */
+
+ index = antialiasIndex;
+ glxAttrs[index++] = GLX_SAMPLE_BUFFERS_ARB;
+ glxAttrs[index++] = 1;
+ glxAttrs[index++] = GLX_SAMPLES_ARB;
+ glxAttrs[index++] = 1;
+ glxAttrs[index++] = None;
+ vis_info = findVisualInfoSwitchDoubleBufferAndStereo(display, screen, glxAttrs, sVal, sIndex,
+ dbVal, dbIndex);
+
+ if(vis_info != NULL) {
+ vis_id = XVisualIDFromVisual(vis_info->visual);
+ visInfo[0] = (jlong)vis_info;
+ (*env)->ReleaseLongArrayElements(env, vInfArray, visInfo, 0);
+ return vis_id;
+ }
+ }
+ }
+
+ /* normal path */
+ if ( antialiasVal == REQUIRED || antialiasVal == PREFERRED) {
+ /* step 1 : enable antialiasing */
+ index = antialiasIndex;
+ glxAttrs[index++] = GLX_ACCUM_RED_SIZE;
+ glxAttrs[index++] = 8;
+ glxAttrs[index++] = GLX_ACCUM_GREEN_SIZE;
+ glxAttrs[index++] = 8;
+ glxAttrs[index++] = GLX_ACCUM_BLUE_SIZE;
+ glxAttrs[index++] = 8;
+ glxAttrs[index++] = None;
+ vis_info = findVisualInfoSwitchDoubleBufferAndStereo(display, screen, glxAttrs, sVal, sIndex,
+ dbVal, dbIndex);
+
+ if( vis_info == NULL) {
+ /* try disable antialiasing if it is PREFERRED */
+ if(antialiasVal == PREFERRED) {
+ glxAttrs[antialiasIndex] = None;
+ vis_info = findVisualInfoSwitchDoubleBufferAndStereo(display, screen, glxAttrs, sVal, sIndex,
+ dbVal, dbIndex);
+ }
+ }
+
+ visInfo[0] = (jlong)vis_info;
+ (*env)->ReleaseLongArrayElements(env, vInfArray, visInfo, 0);
+
+ if( vis_info != NULL) {
+ vis_id = XVisualIDFromVisual(vis_info->visual);
+ return vis_id;
+ } else {
+ return 0;
+ }
+ }
+
+
+ glxAttrs[antialiasIndex] = None;
+ vis_info = findVisualInfoSwitchDoubleBufferAndStereo(display, screen, glxAttrs, sVal, sIndex,
+ dbVal, dbIndex);
+
+ visInfo[0] = (jlong)vis_info;
+ (*env)->ReleaseLongArrayElements(env, vInfArray, visInfo, 0);
+
+ if( vis_info != NULL) {
+ vis_id = XVisualIDFromVisual(vis_info->visual);
+ return vis_id;
+ } else {
+ return 0;
+ }
+}
+
+
+JNIEXPORT
+void JNICALL Java_javax_media_j3d_NativeConfigTemplate3D_freeVisual(
+ JNIEnv *env,
+ jclass class, /* this is a static native method */
+ jlong visInfo)
+{
+ XFree((XVisualInfo *)visInfo);
+}
+
+
+JNIEXPORT
+jboolean JNICALL Java_javax_media_j3d_NativeConfigTemplate3D_isStereoAvailable(
+ JNIEnv *env,
+ jobject obj,
+ jlong display,
+ jint screen,
+ jint vid)
+{
+ Display *dpy = (Display*) display;
+ XVisualInfo *vinfo, template;
+ int nitems;
+ int stereoFlag;
+ static GLboolean first_time = GL_TRUE;
+ static GLboolean force_no_stereo = GL_FALSE;
+
+ if (first_time) {
+ if (getenv("J3D_NO_STEREO") != NULL) {
+ fprintf(stderr, "Java 3D: stereo mode disabled\n");
+ force_no_stereo = GL_TRUE;
+ }
+ first_time = GL_FALSE;
+ }
+
+ if (force_no_stereo)
+ return JNI_FALSE;
+
+ template.visualid = vid;
+ vinfo = XGetVisualInfo(dpy, VisualIDMask, &template, &nitems);
+ if (nitems != 1) {
+ fprintf(stderr, "Warning Canvas3D_isStereoAvailable got unexpected number of matching visuals %d\n", nitems);
+ }
+
+ glXGetConfig(dpy, vinfo, GLX_STEREO, &stereoFlag);
+
+ return (stereoFlag ? JNI_TRUE : JNI_FALSE);
+}
+
+JNIEXPORT
+jboolean JNICALL Java_javax_media_j3d_NativeConfigTemplate3D_isDoubleBufferAvailable(
+ JNIEnv *env,
+ jobject obj,
+ jlong display,
+ jint screen,
+ jint vid)
+{
+ Display *dpy = (Display*) display;
+ XVisualInfo *vinfo, template;
+ int nitems;
+ int doubleBufferFlag;
+
+ template.visualid = vid;
+ vinfo = XGetVisualInfo(dpy, VisualIDMask, &template, &nitems);
+ if (nitems != 1) {
+ fprintf(stderr, "Warning Canvas3D_isDoubleBufferAvailable got unexpected number of matching visuals %d\n", nitems);
+ }
+
+ glXGetConfig(dpy, vinfo, GLX_DOUBLEBUFFER, &doubleBufferFlag);
+
+ return (doubleBufferFlag ? JNI_TRUE : JNI_FALSE);
+}
+
+JNIEXPORT
+jboolean JNICALL Java_javax_media_j3d_NativeConfigTemplate3D_isSceneAntialiasingAccumAvailable(
+ JNIEnv *env,
+ jobject obj,
+ jlong display,
+ jint screen,
+ jint vid)
+{
+ Display *dpy = (Display*) display;
+ XVisualInfo *vinfo, template;
+ int nitems;
+ int numAccumRedBits;
+
+ template.visualid = vid;
+ vinfo = XGetVisualInfo(dpy, VisualIDMask, &template, &nitems);
+ if (nitems != 1) {
+ fprintf(stderr, "Warning Canvas3D_isSceneAntialiasingAvailable got unexpected number of matching visuals %d\n", nitems);
+ }
+
+ glXGetConfig(dpy, vinfo, GLX_ACCUM_RED_SIZE, &numAccumRedBits);
+
+ return (numAccumRedBits > 0 ? JNI_TRUE : JNI_FALSE);
+}
+
+JNIEXPORT
+jboolean JNICALL Java_javax_media_j3d_NativeConfigTemplate3D_isSceneAntialiasingMultiSamplesAvailable(
+ JNIEnv *env,
+ jobject obj,
+ jlong display,
+ jint screen,
+ jint vid)
+{
+ Display *dpy = (Display*) display;
+ XVisualInfo *vinfo, template;
+ int nitems;
+
+ const char *glxExtensions;
+ int numSampleBuffers;
+ int numSamples;
+
+ template.visualid = vid;
+ vinfo = XGetVisualInfo(dpy, VisualIDMask, &template, &nitems);
+ if (nitems != 1) {
+ fprintf(stderr, "Warning Canvas3D_isSceneAntialiasingAvailable got unexpected number of matching visuals %d\n", nitems);
+ }
+ /* try GLX_ARB_multisample */
+ glxExtensions = (const char *)glXGetClientString((Display*)display, GLX_EXTENSIONS);
+
+ if(isExtensionSupported(glxExtensions, "GLX_ARB_multisample")){
+ glXGetConfig(dpy, vinfo, GLX_SAMPLE_BUFFERS_ARB, &numSampleBuffers);
+ glXGetConfig(dpy, vinfo, GLX_SAMPLES_ARB, &numSamples);
+ if(numSampleBuffers > 0 && numSamples > 1){
+ return JNI_TRUE;
+ }
+ }
+
+ return JNI_FALSE;
+}
+
+
+JNIEXPORT
+jboolean JNICALL Java_javax_media_j3d_J3dGraphicsConfig_isValidVisualID(
+ JNIEnv *env,
+ jclass cls,
+ jlong display,
+ jint vid)
+{
+ XVisualInfo template;
+ int nitems;
+
+ template.visualid = vid;
+ XGetVisualInfo((Display *)display, VisualIDMask, &template, &nitems);
+ return (nitems == 1);
+
+}
+#endif /* SOLARIS || __linux__ */
+
+
+#ifdef WIN32
+
+extern HWND createDummyWindow(const char* szAppName);
+
+/*
+void printPixelDescriptor(PIXELFORMATDESCRIPTOR *pfd)
+{
+
+ printf("color : r=%d, g=%d, b=%d, a=%d, shift r=%d, g=%d, b=%d, a=%d\n",
+ pfd->cRedBits, pfd->cGreenBits, pfd->cBlueBits, pfd->cAlphaBits,
+ pfd->cRedShift, pfd->cGreenShift, pfd->cBlueShift, pfd->cAlphaShift);
+ printf("Accum r=%d, g=%d, b=%d, a=%d, depth %d, stencil %d, AuxBuffers %d\n",
+ pfd->cAccumRedBits, pfd->cAccumGreenBits, pfd->cAccumBlueBits,
+ pfd->cAccumAlphaBits, pfd->cDepthBits, pfd->cStencilBits, pfd->cAuxBuffers);
+ printf("iLayerType %x, bReserved %x, dwLayerMask %x, dwVisibleMask %x, dwDamageMask %x\n",
+ pfd->iLayerType, pfd->bReserved, pfd->dwLayerMask, pfd->dwVisibleMask, pfd->dwDamageMask);
+ if (pfd->dwFlags & PFD_SUPPORT_OPENGL) {
+ printf("SUPPORT_OPENGL ");
+ }
+ if (pfd->dwFlags & PFD_DRAW_TO_WINDOW) {
+ printf("DRAW_TO_WINDOW ");
+ }
+ if (pfd->dwFlags & PFD_DRAW_TO_BITMAP) {
+ printf("DRAW_TO_BITMAP ");
+ }
+ if (pfd->dwFlags & PFD_SUPPORT_GDI) {
+ printf("SUPPORT_GDI ");
+ }
+ if (pfd->dwFlags & PFD_SUPPORT_GDI) {
+ printf("NEED_PALETTE ");
+ }
+ if (pfd->dwFlags & PFD_SUPPORT_GDI) {
+ printf("NEED_SYSTEM_PALETTE ");
+ }
+ if (pfd->dwFlags & PFD_STEREO) {
+ printf("STEREO ");
+ }
+ if (pfd->dwFlags & PFD_SUPPORT_GDI) {
+ printf("SWAP_LAYER_BUFFERS ");
+ }
+ if (pfd->dwFlags & PFD_GENERIC_FORMAT) {
+ printf("PFD_GENERIC_FORMAT ");
+ }
+ if (pfd->dwFlags & PFD_GENERIC_ACCELERATED) {
+ printf("PFD_GENERIC_FORMAT ");
+ }
+ if (pfd->dwFlags & PFD_DOUBLEBUFFER) {
+ printf("PFD_DOUBLEBUFFER ");
+ }
+ printf("\n");
+
+}
+
+*/
+
+BOOL isSupportedWGL(const char * extensions, const char *extension_string) {
+ /* get the list of supported extensions */
+ const char *p = extensions;
+
+ /* search for extension_string in the list */
+ while(p = strstr(p, extension_string)){
+ const char *q = p + strlen(extension_string);
+
+ /* must be terminated by <space> or <nul> */
+ if(*q == ' ' || *q == '\0') {
+ return TRUE;
+ }
+
+ /* try to find another match */
+ p = q;
+ }
+ return FALSE;
+}
+
+HDC getMonitorDC(int screen)
+{
+ return CreateDC("DISPLAY", NULL, NULL, NULL);
+}
+
+int findPixelFormatSwitchDoubleBufferAndStereo (PIXELFORMATDESCRIPTOR* pfd, HDC hdc, int *mx_ptr)
+{
+
+ int pf;
+
+ pf = ChoosePixelFormat(hdc, pfd);
+
+ /* Check if pixel format support min. requirement */
+ DescribePixelFormat(hdc, pf, sizeof(*pfd), pfd);
+
+ if ((pfd->cRedBits < (unsigned char) mx_ptr[RED_SIZE]) ||
+ (pfd->cGreenBits < (unsigned char) mx_ptr[GREEN_SIZE]) ||
+ (pfd->cBlueBits < (unsigned char) mx_ptr[BLUE_SIZE]) ||
+ (pfd->cDepthBits < (unsigned char) mx_ptr[DEPTH_SIZE]) ||
+ ((mx_ptr[DOUBLEBUFFER] == REQUIRED) && ((pfd->dwFlags & PFD_DOUBLEBUFFER) == 0)) ||
+ ((mx_ptr[STEREO] == REQUIRED) && ((pfd->dwFlags & PFD_STEREO) == 0)))
+ {
+ return -1;
+ }
+
+ if ((mx_ptr[ANTIALIASING] == REQUIRED) &&
+ ((pfd->cAccumRedBits <= 0) ||
+ (pfd->cAccumGreenBits <= 0) ||
+ (pfd->cAccumBlueBits <= 0)))
+ {
+ return -1;
+ }
+ return pf;
+}
+
+
+void printErrorMessage(char *message)
+{
+ DWORD err;
+ char * errString;
+
+ err = GetLastError();
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, err, 0, (LPTSTR)&errString, 0, NULL);
+ fprintf(stderr, "%s - %s\n", message, errString);
+ LocalFree(errString);
+}
+
+/* Prefer multiSample in following order
+ 4, 5, 6, 3, 7, 8, 2, 9, 10, 11, ...
+*/
+int getMultiSampleScore(int s)
+{
+ static int multiSampleScore[9] = {9999, 9999, 6, 3, 0, 1, 2, 4, 5};
+
+ if (s < 9) {
+ return multiSampleScore[s];
+ }
+ return s-2;
+}
+
+
+/* Max no of format wglChoosePixelFormatEXT can return */
+#define NFORMAT 100
+
+int getExtPixelFormat(int *nativeConfigAttrs)
+{
+ static const BOOL debug = FALSE;
+ static char szAppName[] = "Choose Pixel Format";
+
+ static PIXELFORMATDESCRIPTOR pfd = {
+ sizeof(PIXELFORMATDESCRIPTOR),
+ 1, /* Version number */
+ PFD_DRAW_TO_WINDOW |
+ PFD_SUPPORT_OPENGL,
+ PFD_TYPE_RGBA,
+ 16, /* 16 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 */
+ 8, /* 8 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 */
+ };
+
+ HWND hwnd;
+ HGLRC hrc;
+ HDC hdc;
+ int attr[22];
+ int piValues[12];
+ int i, idx;
+ int pNumFormats[NFORMAT], nAvailableFormat;
+ const char* supportedExtensions;
+ int score;
+ int highestScore, highestScorePF;
+ int highestScoreAlpha, lowestScoreMultiSample;
+
+ /* declare function pointers for WGL functions */
+ PFNWGLGETEXTENSIONSSTRINGEXTPROC wglGetExtensionsStringEXT = NULL;
+ PFNWGLCHOOSEPIXELFORMATEXTPROC wglChoosePixelFormatEXT = NULL;
+ PFNWGLGETPIXELFORMATATTRIBIVEXTPROC wglGetPixelFormatAttribivEXT = NULL;
+
+ /*
+ * 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 -1;
+ }
+ hdc = GetDC(hwnd);
+
+ pNumFormats[0] = ChoosePixelFormat(hdc, &pfd);
+ if (!pNumFormats[0]) {
+ printErrorMessage("Failed in ChoosePixelFormat");
+ DestroyWindow(hwnd);
+ UnregisterClass(szAppName, (HINSTANCE)NULL);
+ return -1;
+ }
+
+ SetPixelFormat(hdc, pNumFormats[0], &pfd);
+
+ hrc = wglCreateContext(hdc);
+ if (!hrc) {
+ printErrorMessage("Failed in wglCreateContext");
+ DestroyWindow(hwnd);
+ UnregisterClass(szAppName, (HINSTANCE)NULL);
+ return -1;
+ }
+
+ if (!wglMakeCurrent(hdc, hrc)) {
+ printErrorMessage("Failed in wglMakeCurrent");
+ ReleaseDC(hwnd, hdc);
+ wglDeleteContext(hrc);
+ DestroyWindow(hwnd);
+ UnregisterClass(szAppName, (HINSTANCE)NULL);
+ return -1;
+ }
+
+ wglGetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)
+ wglGetProcAddress("wglGetExtensionsStringARB");
+
+ if (wglGetExtensionsStringEXT == NULL) {
+ wglGetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)
+ wglGetProcAddress("wglGetExtensionsStringEXT");
+ if (wglGetExtensionsStringEXT == NULL) {
+ if (debug) {
+ printf("wglGetExtensionsStringEXT/ARB not support !\n");
+ }
+ ReleaseDC(hwnd, hdc);
+ wglDeleteContext(hrc);
+ DestroyWindow(hwnd);
+ UnregisterClass(szAppName, (HINSTANCE)NULL);
+ return -1;
+ }
+ if (debug) {
+ printf("Support wglGetExtensionsStringEXT\n");
+ }
+ } else {
+ if (debug) {
+ printf("Support wglGetExtensionsStringARB\n");
+ }
+ }
+
+ /* get the list of supported extensions */
+ supportedExtensions = (const char *)wglGetExtensionsStringEXT(hdc);
+
+ if (debug) {
+ fprintf(stderr, "WGL Supported extensions: %s.\n", supportedExtensions);
+ }
+
+ if (!isSupportedWGL(supportedExtensions, "WGL_ARB_multisample") &&
+ !isSupportedWGL(supportedExtensions, "WGL_EXT_multisample") &&
+ !isSupportedWGL(supportedExtensions, "WGL_SGIS_multisample")) {
+
+ /* Under Wildcat III it doesn't use wglGetExtensionString */
+ supportedExtensions = (char *) glGetString(GL_EXTENSIONS);
+
+ if (debug) {
+ fprintf(stderr, "GL Supported extensions: %s.\n", supportedExtensions);
+ }
+
+ if (!isSupportedWGL(supportedExtensions, "GL_ARB_multisample") &&
+ !isSupportedWGL(supportedExtensions, "GL_EXT_multisample") &&
+ !isSupportedWGL(supportedExtensions, "GL_SGIS_multisample")) {
+ ReleaseDC(hwnd, hdc);
+ wglDeleteContext(hrc);
+ DestroyWindow(hwnd);
+ UnregisterClass(szAppName, (HINSTANCE)NULL);
+ return -1;
+ }
+ }
+
+ wglChoosePixelFormatEXT = (PFNWGLCHOOSEPIXELFORMATEXTPROC)
+ wglGetProcAddress("wglChoosePixelFormatARB");
+
+ if (wglChoosePixelFormatEXT == NULL) {
+ wglChoosePixelFormatEXT = (PFNWGLCHOOSEPIXELFORMATEXTPROC)
+ wglGetProcAddress("wglChoosePixelFormatEXT");
+ if (wglChoosePixelFormatEXT == NULL) {
+ if (debug) {
+ printf("wglChoosePixelFormatARB/EXT not support !\n");
+ }
+ ReleaseDC(hwnd, hdc);
+ wglDeleteContext(hrc);
+ DestroyWindow(hwnd);
+ UnregisterClass(szAppName, (HINSTANCE)NULL);
+ return -1;
+ }
+ if (debug) {
+ printf("Support wglChoosePixelFormatEXT\n");
+ }
+ } else {
+ if (debug) {
+ printf("Support wglChoosePixelFormatARB\n");
+ }
+ }
+
+ idx = 0;
+ attr[idx++] = WGL_SUPPORT_OPENGL_EXT;
+ attr[idx++] = TRUE;
+ attr[idx++] = WGL_DRAW_TO_WINDOW_EXT;
+ attr[idx++] = TRUE;
+ attr[idx++] = WGL_RED_BITS_EXT;
+ attr[idx++] = nativeConfigAttrs[RED_SIZE];
+ attr[idx++] = WGL_GREEN_BITS_EXT;
+ attr[idx++] = nativeConfigAttrs[GREEN_SIZE];
+ attr[idx++] = WGL_BLUE_BITS_EXT;
+ attr[idx++] = nativeConfigAttrs[BLUE_SIZE];
+ attr[idx++] = WGL_DEPTH_BITS_EXT;
+ attr[idx++] = nativeConfigAttrs[DEPTH_SIZE];
+
+ if (nativeConfigAttrs[DOUBLEBUFFER] == REQUIRED) {
+ attr[idx++] = WGL_DOUBLE_BUFFER_EXT;
+ attr[idx++] = TRUE;
+ }
+ if (nativeConfigAttrs[STEREO] == REQUIRED) {
+ attr[idx++] = WGL_STEREO_EXT;
+ attr[idx++] = TRUE;
+ }
+
+ if (nativeConfigAttrs[ANTIALIASING] == REQUIRED) {
+ attr[idx++] = WGL_SAMPLE_BUFFERS_ARB;
+ attr[idx++] = TRUE;
+ attr[idx++] = WGL_SAMPLES_ARB;
+ attr[idx++] = 2;
+ }
+
+ /*
+ * Terminate by 2 zeros to avoid driver bugs
+ * that assume attributes always come in pairs.
+ */
+ attr[idx++] = 0;
+ attr[idx++] = 0;
+
+ if (!wglChoosePixelFormatEXT(hdc, (const int *)attr, NULL, NFORMAT,
+ pNumFormats, &nAvailableFormat)) {
+ printErrorMessage("Failed in wglChoosePixelFormatEXT");
+ ReleaseDC(hwnd, hdc);
+ wglDeleteContext(hrc);
+ DestroyWindow(hwnd);
+ UnregisterClass(szAppName, (HINSTANCE)NULL);
+ return -1;
+ }
+
+ if (debug) {
+ printf("No. of available pixel format is: %d\n", nAvailableFormat);
+ }
+
+ if (nAvailableFormat <= 0) {
+ ReleaseDC(hwnd, hdc);
+ wglDeleteContext(hrc);
+ DestroyWindow(hwnd);
+ UnregisterClass(szAppName, (HINSTANCE)NULL);
+ return -1;
+ }
+
+ wglGetPixelFormatAttribivEXT = (PFNWGLGETPIXELFORMATATTRIBIVEXTPROC)
+ wglGetProcAddress("wglGetPixelFormatAttribivARB");
+
+ if (wglGetPixelFormatAttribivEXT == NULL) {
+ wglGetPixelFormatAttribivEXT = (PFNWGLGETPIXELFORMATATTRIBIVEXTPROC)
+ wglGetProcAddress("wglGetPixelFormatAttribivEXT");
+
+ if (wglGetPixelFormatAttribivEXT == NULL) {
+ if (debug) {
+ printf("wglGetPixelFormatAttribivEXT/ARB not support !\n");
+ }
+ ReleaseDC(hwnd, hdc);
+ wglDeleteContext(hrc);
+ DestroyWindow(hwnd);
+ UnregisterClass(szAppName, (HINSTANCE)NULL);
+ return -1;
+ }
+ if (debug) {
+ printf("Support wglGetPixelFormatAttribivEXT\n");
+ }
+ } else {
+ if (debug) {
+ printf("Support wglGetPixelFormatAttribivARB\n");
+ }
+ }
+
+ idx = 0;
+ attr[idx++] = WGL_ACCELERATION_EXT;
+ attr[idx++] = WGL_RED_BITS_EXT;
+ attr[idx++] = WGL_GREEN_BITS_EXT;
+ attr[idx++] = WGL_BLUE_BITS_EXT;
+ attr[idx++] = WGL_ALPHA_BITS_EXT;
+ attr[idx++] = WGL_DEPTH_BITS_EXT;
+ attr[idx++] = WGL_STENCIL_BITS_EXT;
+ attr[idx++] = WGL_SAMPLE_BUFFERS_ARB;
+ attr[idx++] = WGL_SAMPLES_ARB;
+ attr[idx++] = WGL_DOUBLE_BUFFER_EXT;
+ attr[idx++] = WGL_STEREO_EXT;
+ attr[idx] = 0;
+
+ /* Select the best pixel format based on score */
+ highestScore = 0;
+ highestScorePF = -1;
+ highestScoreAlpha = 0;
+ lowestScoreMultiSample = 9999;
+
+ for (i=0; i < nAvailableFormat; i++) {
+ if (!wglGetPixelFormatAttribivEXT(hdc, pNumFormats[i], 0, idx, attr, piValues)) {
+ printErrorMessage("Failed in wglGetPixelFormatAttribivEXT");
+ ReleaseDC(hwnd, hdc);
+ wglDeleteContext(hrc);
+ DestroyWindow(hwnd);
+ UnregisterClass(szAppName, (HINSTANCE)NULL);
+ return -1;
+ }
+ if (debug) {
+ printf("Format %d\n", pNumFormats[i]);
+
+ if (piValues[0] == WGL_FULL_ACCELERATION_EXT) {
+ printf("WGL_FULL_ACCELERATION_EXT");
+ } else if (piValues[0] == WGL_GENERIC_ACCELERATION_EXT) {
+ printf("WGL_GENERIC_ACCELERATION_EXT");
+ } else {
+ printf("WGL_NO_ACCELERATION_EXT");
+ }
+
+ printf(" R %d, G %d, B %d, A %d, Depth %d, Stencil %d",
+ piValues[1], piValues[2], piValues[3], piValues[4],
+ piValues[5], piValues[6]);
+
+ if (piValues[7] == TRUE) {
+ printf(" MultiSample %d", piValues[8]);
+ }
+
+ if (piValues[9] == TRUE) {
+ printf(" DoubleBuffer");
+ }
+
+ if (piValues[10] == TRUE) {
+ printf(" Stereo");
+ }
+ printf("\n");
+ }
+
+ /* Red, Green, Blue are fixed under windows so they are not checked */
+ score = 0;
+
+ if (piValues[0] == WGL_FULL_ACCELERATION_EXT) {
+ score += 20000;
+ } else if (piValues[0] == WGL_GENERIC_ACCELERATION_EXT) {
+ score += 10000;
+ }
+ if ((nativeConfigAttrs[DOUBLEBUFFER] == PREFERRED) &&
+ (piValues[9] == TRUE)) {
+ score += 5000;
+ }
+ if (piValues[4] > 0) { /* Alpha */
+ score += 2500;
+ }
+ if ((nativeConfigAttrs[STEREO] == PREFERRED) &&
+ (piValues[10] == TRUE)) {
+ score += 1250;
+ }
+ if ((nativeConfigAttrs[ANTIALIASING] == PREFERRED) &&
+ (piValues[7] == TRUE)) {
+ score += 624;
+ }
+
+ /* Stencil bit * 10 + Depth bit */
+ score += piValues[6]*10 + piValues[5];
+
+ if (score > highestScore) {
+ highestScore = score;
+ highestScorePF = i;
+ highestScoreAlpha = piValues[4];
+ lowestScoreMultiSample = getMultiSampleScore(piValues[8]);
+ } else if (score == highestScore) {
+ if (piValues[4] > highestScoreAlpha) {
+ highestScore = score;
+ highestScorePF = i;
+ highestScoreAlpha = piValues[4];
+ lowestScoreMultiSample = getMultiSampleScore(piValues[8]);
+ } else if (piValues[4] == highestScoreAlpha) {
+ if (getMultiSampleScore(piValues[8]) < lowestScoreMultiSample) {
+ highestScore = score;
+ highestScorePF = i;
+ highestScoreAlpha = piValues[4];
+ lowestScoreMultiSample = getMultiSampleScore(piValues[8]);
+ }
+ }
+ }
+
+ }
+
+ if (debug) {
+ printf("Select Pixel Format %d\n", pNumFormats[highestScorePF]);
+ }
+
+ ReleaseDC(hwnd, hdc);
+ wglDeleteContext(hrc);
+ DestroyWindow(hwnd);
+ UnregisterClass(szAppName, (HINSTANCE)NULL);
+ return pNumFormats[highestScorePF];
+}
+
+
+JNIEXPORT
+jint JNICALL Java_javax_media_j3d_NativeConfigTemplate3D_choosePixelFormat(
+ JNIEnv *env,
+ jobject obj,
+ jlong ctxInfo,
+ jint screen,
+ jintArray attrList)
+{
+ int *mx_ptr;
+ int dbVal; /* value for double buffering */
+ int sVal; /* value for stereo */
+ HDC hdc;
+ int pf; /* PixelFormat */
+ PIXELFORMATDESCRIPTOR pfd;
+
+ mx_ptr = (int *)(*env)->GetIntArrayElements(env, attrList, NULL);
+
+ if (mx_ptr[ANTIALIASING] != UNNECESSARY) {
+ pf = getExtPixelFormat(mx_ptr);
+ if (pf > 0) {
+ return pf;
+ }
+
+ /* fallback to use standard ChoosePixelFormat and accumulation buffer */
+ }
+
+ hdc = getMonitorDC(screen);
+
+ ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));
+ pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
+ pfd.nVersion = 1; /*TODO: when would this change? */
+ pfd.iPixelType = PFD_TYPE_RGBA;
+
+ /*
+ * Convert Java 3D values to PixelFormat
+ */
+
+ pfd.cRedBits = (unsigned char) mx_ptr[RED_SIZE];
+ pfd.cGreenBits = (unsigned char) mx_ptr[GREEN_SIZE];
+ pfd.cBlueBits = (unsigned char) mx_ptr[BLUE_SIZE];
+ pfd.cDepthBits = (unsigned char) mx_ptr[DEPTH_SIZE];
+
+ if (mx_ptr[DOUBLEBUFFER] == REQUIRED || mx_ptr[DOUBLEBUFFER] == PREFERRED)
+ dbVal = PFD_DOUBLEBUFFER;
+ else
+ dbVal = PFD_DOUBLEBUFFER_DONTCARE;
+
+ sVal = 0;
+ if (mx_ptr[STEREO] == REQUIRED || mx_ptr[STEREO] == PREFERRED) {
+ sVal = PFD_STEREO;
+ } else {
+ sVal = 0;
+ }
+
+ pfd.dwFlags = dbVal | sVal | PFD_SUPPORT_OPENGL;
+ pfd.cStencilBits = 2;
+
+ if (mx_ptr[ANTIALIASING] == REQUIRED || mx_ptr[ANTIALIASING] == PREFERRED) {
+ pfd.cAccumRedBits = 8;
+ pfd.cAccumGreenBits = 8;
+ pfd.cAccumBlueBits = 8;
+ }
+
+ pf = findPixelFormatSwitchDoubleBufferAndStereo(&pfd, hdc, mx_ptr);
+
+ if (pf == -1) {
+ /* try disable stencil buffer */
+ pfd.cStencilBits = 0;
+ pf = findPixelFormatSwitchDoubleBufferAndStereo(&pfd, hdc, mx_ptr);
+
+ if (pf == -1) {
+ /* try disable accumulate buffer */
+ if (mx_ptr[ANTIALIASING] == PREFERRED) {
+ pfd.cStencilBits = 2;
+ pfd.cAccumRedBits = 0;
+ pfd.cAccumGreenBits = 0;
+ pfd.cAccumBlueBits = 0;
+ pf = findPixelFormatSwitchDoubleBufferAndStereo(&pfd, hdc, mx_ptr);
+
+ if (pf == -1) {
+ /* try disable stencil buffer */
+ pfd.cStencilBits = 0;
+ pf = findPixelFormatSwitchDoubleBufferAndStereo(&pfd, hdc, mx_ptr);
+ }
+ }
+ }
+ }
+
+ DeleteDC(hdc);
+
+ (*env)->ReleaseIntArrayElements(env, attrList, mx_ptr, JNI_ABORT);
+ return pf;
+}
+
+
+JNIEXPORT
+jboolean JNICALL Java_javax_media_j3d_NativeConfigTemplate3D_isStereoAvailable(
+ JNIEnv *env,
+ jobject obj,
+ jlong ctxInfo,
+ jlong display,
+ jint screen,
+ jint pixelFormat)
+{
+ HDC hdc; /* HW Device Context */
+
+ PIXELFORMATDESCRIPTOR pfd;
+
+ static GLboolean first_time = GL_TRUE;
+ static GLboolean force_no_stereo = GL_FALSE;
+
+ if (first_time) {
+ if (getenv("J3D_NO_STEREO") != NULL) {
+ fprintf(stderr, "Java 3D: stereo mode disabled\n");
+ force_no_stereo = GL_TRUE;
+ }
+ first_time = GL_FALSE;
+ }
+
+ if (force_no_stereo)
+ return JNI_FALSE;
+
+ hdc = getMonitorDC(screen);
+
+ /* Check the chosen PixelFormat to see if it is stereo capable */
+ DescribePixelFormat(hdc, pixelFormat, sizeof(pfd), &pfd);
+
+ DeleteDC(hdc);
+ if (pfd.dwFlags & PFD_STEREO)
+ return JNI_TRUE;
+ else
+ return JNI_FALSE;
+
+ return JNI_TRUE;
+}
+
+
+JNIEXPORT
+jboolean JNICALL Java_javax_media_j3d_NativeConfigTemplate3D_isDoubleBufferAvailable(
+ JNIEnv *env,
+ jobject obj,
+ jlong ctxInfo,
+ jlong display,
+ jint screen,
+ jint pixelFormat)
+{
+ HDC hdc; /* HW Device Context */
+
+ PIXELFORMATDESCRIPTOR pfd;
+
+ hdc = getMonitorDC(screen);
+
+ /* Check the chosen PixelFormat to see if it is doubleBuffer capable */
+ DescribePixelFormat(hdc, pixelFormat, sizeof(pfd), &pfd);
+
+ DeleteDC(hdc);
+ if (pfd.dwFlags & PFD_DOUBLEBUFFER)
+ return JNI_TRUE;
+ else
+ return JNI_FALSE;
+}
+
+
+
+JNIEXPORT
+jboolean JNICALL Java_javax_media_j3d_NativeConfigTemplate3D_isSceneAntialiasingAccumAvailable(
+ JNIEnv *env,
+ jobject obj,
+ jlong ctxInfo,
+ jlong display,
+ jint screen,
+ jint pixelFormat)
+{
+ HDC hdc; /* HW Device Context */
+ PIXELFORMATDESCRIPTOR pfd;
+
+ hdc = getMonitorDC(screen);
+ /* Check the chosen PixelFormat to see if it is sceneAntialiasing capable */
+ DescribePixelFormat(hdc, pixelFormat, sizeof(pfd), &pfd);
+
+ DeleteDC(hdc);
+ if (pfd.cAccumRedBits > 0)
+ return JNI_TRUE;
+ else
+ return JNI_FALSE;
+}
+
+JNIEXPORT
+jboolean JNICALL Java_javax_media_j3d_NativeConfigTemplate3D_isSceneAntialiasingMultiSamplesAvailable(
+ JNIEnv *env,
+ jobject obj,
+ jlong ctxInfo,
+ jlong display,
+ jint screen,
+ jint pixelFormat)
+{
+ static char szAppName[] = "Choose Pixel Format";
+ HWND hwnd;
+ HGLRC hrc;
+ HDC hdc;
+ int attr[3];
+ int piValues[2];
+ int pf;
+ BOOL support;
+
+ static PIXELFORMATDESCRIPTOR pfd = {
+ sizeof(PIXELFORMATDESCRIPTOR),
+ 1, /* Version number */
+ PFD_DRAW_TO_WINDOW |
+ PFD_SUPPORT_OPENGL,
+ PFD_TYPE_RGBA,
+ 16, /* 16 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 */
+ 8, /* 8 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 */
+ };
+
+ PFNWGLGETPIXELFORMATATTRIBIVEXTPROC wglGetPixelFormatAttribivEXT = NULL;
+
+ hwnd = createDummyWindow((const char *)szAppName);
+
+ if (!hwnd) {
+ return -1;
+ }
+ hdc = GetDC(hwnd);
+
+ pf = ChoosePixelFormat(hdc, &pfd);
+ if (!pf) {
+ printErrorMessage("Failed in ChoosePixelFormat");
+ DestroyWindow(hwnd);
+ UnregisterClass(szAppName, (HINSTANCE)NULL);
+ return -1;
+ }
+
+ SetPixelFormat(hdc, pf, &pfd);
+
+ hrc = wglCreateContext(hdc);
+ if (!hrc) {
+ printErrorMessage("Failed in wglCreateContext");
+ DestroyWindow(hwnd);
+ UnregisterClass(szAppName, (HINSTANCE)NULL);
+ return -1;
+ }
+
+ if (!wglMakeCurrent(hdc, hrc)) {
+ printErrorMessage("Failed in wglMakeCurrent");
+ ReleaseDC(hwnd, hdc);
+ wglDeleteContext(hrc);
+ DestroyWindow(hwnd);
+ UnregisterClass(szAppName, (HINSTANCE)NULL);
+ return -1;
+ }
+
+ wglGetPixelFormatAttribivEXT = (PFNWGLGETPIXELFORMATATTRIBIVEXTPROC)
+ wglGetProcAddress("wglGetPixelFormatAttribivARB");
+
+ if (wglGetPixelFormatAttribivEXT == NULL) {
+ wglGetPixelFormatAttribivEXT = (PFNWGLGETPIXELFORMATATTRIBIVEXTPROC)
+ wglGetProcAddress("wglGetPixelFormatAttribivEXT");
+
+ if (wglGetPixelFormatAttribivEXT == NULL) {
+ ReleaseDC(hwnd, hdc);
+ wglDeleteContext(hrc);
+ DestroyWindow(hwnd);
+ UnregisterClass(szAppName, (HINSTANCE)NULL);
+ return FALSE;
+ }
+ }
+
+ attr[0] = WGL_SAMPLE_BUFFERS_ARB;
+ attr[1] = WGL_SAMPLES_ARB;
+ attr[2] = 0;
+ support = FALSE;
+
+ if (wglGetPixelFormatAttribivEXT(hdc, pixelFormat, 0, 2, attr, piValues)) {
+ if ((piValues[0] == TRUE) && (piValues[1] > 1)) {
+ support = TRUE;
+ }
+ }
+
+ ReleaseDC(hwnd, hdc);
+ wglDeleteContext(hrc);
+ DestroyWindow(hwnd);
+ UnregisterClass(szAppName, (HINSTANCE)NULL);
+ return support;
+}
+#endif /* WIN32 */