diff options
author | Kevin Rushforth <[email protected]> | 2007-03-06 19:13:44 +0000 |
---|---|---|
committer | Kevin Rushforth <[email protected]> | 2007-03-06 19:13:44 +0000 |
commit | db3cc8f8ece5a7231c069450d1985e132dfda7e8 (patch) | |
tree | fbfee4a6a3127143393b9e1ba34abf209bd07467 /src/native | |
parent | ce4454ea2fba291eedd5f1623c48faaec5d34e1a (diff) |
Fixed issue 452: Java 3D should fall back to D3D if OpenGL not available
git-svn-id: https://svn.java.net/svn/j3d-core~svn/trunk@785 ba19aa83-45c5-6ac9-afd3-db810772062c
Diffstat (limited to 'src/native')
-rw-r--r-- | src/native/ogl/OglCheck.c | 402 | ||||
-rw-r--r-- | src/native/ogl/build-windows-i586-gcc.xml | 23 | ||||
-rw-r--r-- | src/native/ogl/build-windows-i586-vc.xml | 16 |
3 files changed, 433 insertions, 8 deletions
diff --git a/src/native/ogl/OglCheck.c b/src/native/ogl/OglCheck.c new file mode 100644 index 0000000..866612c --- /dev/null +++ b/src/native/ogl/OglCheck.c @@ -0,0 +1,402 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +#ifdef DEBUG +/* #define VERBOSE */ +#endif /* DEBUG */ + +/* This entire file is Windows-only */ +#ifdef WIN32 + +/* j3dsys.h needs to be included before any other include files to suppres VC warning */ +#include "j3dsys.h" + +#include <jni.h> +#include <math.h> +#include <stdlib.h> +#include <string.h> +#include <windows.h> + +#include <GL/gl.h> +#include "wglext.h" +#include "javax_media_j3d_NativePipeline.h" + + +static 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, "Java 3D ERROR : %s - %s\n", message, errString); + LocalFree(errString); +} + + +/* + * A dummy WndProc for dummy window + */ +static 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 ); +} + + +static 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; +} + + +static PIXELFORMATDESCRIPTOR +getDummyPFD() +{ + + /* Dummy pixel format. -- Chien */ + static PIXELFORMATDESCRIPTOR dummy_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 */ + }; + + return dummy_pfd; +} + + +static 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; +} + + +/* +static HDC +getMonitorDC(int screen) +{ + return CreateDC("DISPLAY", NULL, NULL, NULL); +} +*/ + + +/* + * 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. + */ +static void +extractVersionInfo(char *versionStr, int* numbers) +{ + char *majorNumStr; + char *minorNumStr; + + numbers[0] = numbers[1] = -1; + majorNumStr = strtok(versionStr, (char *)"."); + minorNumStr = strtok(0, (char *)"."); + if (majorNumStr != NULL) + numbers[0] = atoi(majorNumStr); + if (minorNumStr != NULL) + numbers[1] = atoi(minorNumStr); +} + + +/* + * get properties from current context + */ +static char* +queryVendorString(HDC hdc, HGLRC hrc) +{ + char *glVersion; + char *tmpVersionStr; + int versionNumbers[2]; + char *glVendor; + char *supportedExtensions; + PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB; + + if (!wglMakeCurrent(hdc, hrc)) { +#ifdef DEBUG + printErrorMessage("getSupportedOglVendorNative : Failed in wglMakeCurrent"); +#endif /* DEBUG */ + return NULL; + } + + wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC) + wglGetProcAddress("wglGetExtensionsStringARB"); + if (wglGetExtensionsStringARB == NULL) { +#ifdef DEBUG + printErrorMessage("getSupportedOglVendorNative : wglGetExtensionsStringARB not supported\n"); +#endif /* DEBUG */ + return NULL; + } + + /* get the list of supported extensions */ + supportedExtensions = (char *)wglGetExtensionsStringARB(hdc); + +#ifdef VERBOSE + fprintf(stderr, "WGL Supported extensions: %s\n", + supportedExtensions); +#endif /* VERBOSE */ + + if (supportedExtensions == NULL || + !isSupportedWGL(supportedExtensions, "WGL_ARB_pixel_format") || + wglGetProcAddress("wglChoosePixelFormatARB") == NULL || + wglGetProcAddress("wglGetPixelFormatAttribivARB") == NULL) { +#ifdef DEBUG + printErrorMessage("getSupportedOglVendorNative : wglChoosePixelFormatARB/GetPixelFormatAttribivARB not supported\n"); +#endif /* DEBUG */ + return NULL; + } + + /* Get the OpenGL version */ + glVersion = (char *)glGetString(GL_VERSION); + if (glVersion == NULL) { +#ifdef DEBUG + fprintf(stderr, "JAVA 3D ERROR : glVersion == null\n"); +#endif /* DEBUG */ + return NULL; + } + + /* find out the version, major and minor version number */ + tmpVersionStr = strdup(glVersion); + extractVersionInfo(tmpVersionStr, versionNumbers); + free(tmpVersionStr); + +#ifdef VERBOSE + fprintf(stderr, "GL_VERSION string = %s\n", glVersion); + fprintf(stderr, "GL_VERSION (major.minor) = %d.%d\n", + versionNumbers[0], versionNumbers[1]); +#endif /* VERBOSE */ + + /* + * Check for OpenGL 1.2 or later. + */ + if (versionNumbers[0] < 1 || + (versionNumbers[0] == 1 && versionNumbers[1] < 2)) { +#ifdef DEBUG + fprintf(stderr, + "Java 3D ERROR : OpenGL 1.2 or better is required (GL_VERSION=%d.%d)\n", + versionNumbers[0], versionNumbers[1]); +#endif /* DEBUG */ + return NULL; + } + + /* Get the OpenGL vendor */ + glVendor = (char *)glGetString(GL_VENDOR); + if (glVendor == NULL) { +#ifdef DEBUG + fprintf(stderr, "JAVA 3D ERROR : glVendor == null\n"); +#endif /* DEBUG */ + return NULL; + } + +#ifdef VERBOSE + fprintf(stderr, "GL_VENDOR = %s\n", glVendor); +#endif /* VERBOSE */ + + return glVendor; +} + + +/* + * Class: javax_media_j3d_NativePipeline + * Method: getSupportedOglVendorNative + * Signature: ()Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_javax_media_j3d_NativePipeline_getSupportedOglVendorNative( + JNIEnv *env, + jclass clazz) +{ + static char szAppName[] = "OglCheck"; + + static int wglAttrs[] = { + WGL_SUPPORT_OPENGL_ARB, + TRUE, + WGL_ACCELERATION_ARB, + WGL_FULL_ACCELERATION_ARB, + WGL_DRAW_TO_WINDOW_ARB, + TRUE, + WGL_RED_BITS_ARB, + 4, + WGL_GREEN_BITS_ARB, + 4, + WGL_BLUE_BITS_ARB, + 4, + WGL_DEPTH_BITS_ARB, + 16, + }; + + HWND hwnd; + HGLRC hrc; + HDC hdc; + int pixelFormat; + PIXELFORMATDESCRIPTOR dummy_pfd = getDummyPFD(); + char *glVendor = NULL; + jstring glVendorString = NULL; + + JNIEnv table = *env; + +#ifdef VERBOSE + fprintf(stderr, "NativePipeline.getSupportedOglVendorNative()\n"); +#endif /* VERBOSE */ + + /* + * 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 NULL; + } + hdc = GetDC(hwnd); + + pixelFormat = ChoosePixelFormat(hdc, &dummy_pfd); + + if (pixelFormat<1) { +#ifdef DEBUG + printErrorMessage("getSupportedOglVendorNative : Failed in ChoosePixelFormat"); +#endif /* DEBUG */ + DestroyWindow(hwnd); + UnregisterClass(szAppName, (HINSTANCE)NULL); + return NULL; + } + + if (!SetPixelFormat(hdc, pixelFormat, NULL)) { +#ifdef DEBUG + printErrorMessage("getSupportedOglVendorNative : Failed in SetPixelFormat"); +#endif /* DEBUG */ + DestroyWindow(hwnd); + UnregisterClass(szAppName, (HINSTANCE)NULL); + return NULL; + } + + hrc = wglCreateContext(hdc); + if (!hrc) { +#ifdef DEBUG + printErrorMessage("getSupportedOglVendorNative : Failed in wglCreateContext"); +#endif /* DEBUG */ + DestroyWindow(hwnd); + UnregisterClass(szAppName, (HINSTANCE)NULL); + return NULL; + } + + /* Check OpenGL extensions & version, and return vendor string */ + glVendor = queryVendorString(hdc, hrc); + if (glVendor != NULL) { + glVendorString = table->NewStringUTF(env, glVendor); + } + + /* Destroy all dummy objects */ + ReleaseDC(hwnd, hdc); + wglDeleteContext(hrc); + DestroyWindow(hwnd); + UnregisterClass(szAppName, (HINSTANCE)NULL); + + return glVendorString; +} + +#endif /* WIN32 */ diff --git a/src/native/ogl/build-windows-i586-gcc.xml b/src/native/ogl/build-windows-i586-gcc.xml index 8cc5edd..4a931f9 100644 --- a/src/native/ogl/build-windows-i586-gcc.xml +++ b/src/native/ogl/build-windows-i586-gcc.xml @@ -48,21 +48,34 @@ <property name="oglsrc" location="${src}/native/ogl"/> - <!-- Compile the c source files--> <!-- Inhibit all warning for native build. Remove -w to switch warning on --> + <!-- Compile the c source files for the core ogl library --> <exec dir="${build}/${platform}/${bldType}/native/ogl/objs" executable="gcc"> <arg line="-w -D_WINGDI_ -D_JNI_IMPLEMENTATION_ -I"${oglsrc}" -I"${javaInclude}" -I"${javaWin32Include}" -I"${javahCoreTarget}" ${bldFlag} -c "${oglsrc}/DrawingSurfaceObjectAWT.c" "${oglsrc}/Canvas3D.c" "${oglsrc}/GraphicsContext3D.c" "${oglsrc}/NativeScreenInfo.c" "${oglsrc}/NativeConfigTemplate3D.c" "${oglsrc}/MasterControl.c" "${oglsrc}/GeometryArrayRetained.c" "${oglsrc}/Attributes.c" "${oglsrc}/CgShaderProgram.c" "${oglsrc}/GLSLShaderProgram.c" "${oglsrc}/Lights.c""/> </exec> - <!-- Create the library file--> + <!-- Create the core ogl library file--> <exec dir="${build}/${platform}/${bldType}/native/ogl/objs" executable="gcc"> <arg line="-shared -o j3dcore-ogl.dll DrawingSurfaceObjectAWT.o Canvas3D.o GraphicsContext3D.o NativeScreenInfo.o NativeConfigTemplate3D.o MasterControl.o GeometryArrayRetained.o Attributes.o CgShaderProgram.o GLSLShaderProgram.o Lights.o -Wl,--kill-at -L"${java.home}\..\lib" -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32 -lopengl32 -ljawt"/> </exec> - <!-- Copy the copyright library file --> - <copy file="${build}/${platform}/${bldType}/native/ogl/objs/j3dcore-ogl.dll" - todir="${build}/${platform}/${bldType}/bin"/> + <!-- Compile the c source files for the ogl-chk library --> + <exec dir="${build}/${platform}/${bldType}/native/ogl/objs" executable="gcc"> + <arg line="-w -D_WINGDI_ -D_JNI_IMPLEMENTATION_ -I"${oglsrc}" -I"${javaInclude}" -I"${javaWin32Include}" -I"${javahCoreTarget}" ${bldFlag} -c "${oglsrc}/OglCheck.c""/> + </exec> + + <!-- Create the ogl-chk library file--> + <exec dir="${build}/${platform}/${bldType}/native/ogl/objs" executable="gcc"> + <arg line="-shared -o j3dcore-ogl-chk.dll OglCheck.o -Wl,--kill-at -L"${java.home}\..\lib" -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32 -lopengl32"/> + </exec> + + <!-- Copy the library files --> + <copy todir="${build}/${platform}/${bldType}/bin"> + <fileset dir="${build}/${platform}/${bldType}/native/ogl/objs" + includes="j3dcore-ogl*.dll" + /> + </copy> </target> diff --git a/src/native/ogl/build-windows-i586-vc.xml b/src/native/ogl/build-windows-i586-vc.xml index 9276c72..52e6957 100644 --- a/src/native/ogl/build-windows-i586-vc.xml +++ b/src/native/ogl/build-windows-i586-vc.xml @@ -53,16 +53,26 @@ </target> <target name="compile-ogl"> - <!-- Compile the c source files--> + <!-- Compile the c source files for the core ogl library --> <exec dir="${build}/${platform}/${bldType}/native/ogl/objs" executable="cl"> <arg line="-I"${oglsrc}" -I"${javaInclude}" -I"${javaWin32Include}" -I"${javahCoreTarget}" -I"${cg.home}\include" -nologo -MT -W3 -EHsc -O2 -FD ${bldFlag} ${cflags.cg} -c "${oglsrc}/DrawingSurfaceObjectAWT.c" "${oglsrc}/Canvas3D.c" "${oglsrc}/GraphicsContext3D.c" "${oglsrc}/NativeScreenInfo.c" "${oglsrc}/NativeConfigTemplate3D.c" "${oglsrc}/MasterControl.c" "${oglsrc}/GeometryArrayRetained.c" "${oglsrc}/Attributes.c" "${oglsrc}/CgShaderProgram.c" "${oglsrc}/GLSLShaderProgram.c" "${oglsrc}/Lights.c""/> </exec> - <!-- Create the library file--> + <!-- Create the core ogl library file--> <exec dir="${build}/${platform}/${bldType}/native/ogl/objs" executable="link"> <arg line="-nologo -dll -subsystem:windows -machine:I386 -out:j3dcore-ogl.dll DrawingSurfaceObjectAWT.obj Canvas3D.obj GraphicsContext3D.obj NativeScreenInfo.obj NativeConfigTemplate3D.obj MasterControl.obj GeometryArrayRetained.obj Attributes.obj CgShaderProgram.obj GLSLShaderProgram.obj Lights.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib opengl32.lib delayimp.lib -DELAYLOAD:jawt.dll -LIBPATH:"${java.home}\..\lib" jawt.lib"/> </exec> + <!-- Compile the c source files for the ogl-chk library --> + <exec dir="${build}/${platform}/${bldType}/native/ogl/objs" executable="cl"> + <arg line="-I"${oglsrc}" -I"${javaInclude}" -I"${javaWin32Include}" -I"${javahCoreTarget}" -nologo -MT -W3 -EHsc -O2 -FD ${bldFlag} -c "${oglsrc}/OglCheck.c" "/> + </exec> + + <!-- Create the ogl-chk library file--> + <exec dir="${build}/${platform}/${bldType}/native/ogl/objs" executable="link"> + <arg line="-nologo -dll -subsystem:windows -machine:I386 -out:j3dcore-ogl-chk.dll OglCheck.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib opengl32.lib delayimp.lib"/> + </exec> + </target> @@ -83,7 +93,7 @@ <target name="compile" depends="init,compile-ogl,compile-ogl-cg"> - <!-- Copy the library file --> + <!-- Copy the library files --> <copy todir="${build}/${platform}/${bldType}/bin"> <fileset dir="${build}/${platform}/${bldType}/native/ogl/objs" includes="j3dcore-ogl*.dll" |