1 /*
   2  * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include <jni.h>
  27 #include <stdlib.h>
  28 #include <assert.h>
  29 #include <stdio.h>
  30 #include <string.h>
  31 #include <math.h>
  32 
  33 #include "../PrismES2Defs.h"
  34 #include "com_sun_prism_es2_X11GLContext.h"
  35 
  36 /*
  37  * Class:     com_sun_prism_es2_X11GLContext
  38  * Method:    nInitialize
  39  * Signature: (JJZ)J
  40  */
  41 JNIEXPORT jlong JNICALL Java_com_sun_prism_es2_X11GLContext_nInitialize
  42 (JNIEnv *env, jclass class, jlong nativeDInfo, jlong nativePFInfo,
  43         jboolean vSyncRequested) {
  44     const char *glVersion;
  45     const char *glVendor;
  46     const char *glRenderer;
  47     char *tmpVersionStr;
  48     int versionNumbers[2];
  49     const char *glExtensions;
  50     const char *glxExtensions;
  51 
  52     Window win = None;
  53     GLXFBConfig fbConfig = NULL;
  54     GLXContext ctx = NULL;
  55     XVisualInfo *visualInfo = NULL;
  56     int numFBConfigs, index, visualID;
  57     Display *display = NULL;
  58     ContextInfo *ctxInfo = NULL;
  59     DrawableInfo *dInfo = (DrawableInfo *) jlong_to_ptr(nativeDInfo);
  60     PixelFormatInfo *pfInfo = (PixelFormatInfo *) jlong_to_ptr(nativePFInfo);
  61 
  62     if ((dInfo == NULL) || (pfInfo == NULL)) {
  63         return 0;
  64     }
  65     display = pfInfo->display;
  66     fbConfig = pfInfo->fbConfig;
  67     win = dInfo->win;
  68 
  69     ctx = glXCreateNewContext(display, fbConfig, GLX_RGBA_TYPE, NULL, True);
  70 
  71     if (ctx == NULL) {
  72         fprintf(stderr, "Failed in glXCreateNewContext");
  73         return 0;
  74     }
  75 
  76     if (!glXMakeCurrent(display, win, ctx)) {
  77         glXDestroyContext(display, ctx);
  78         fprintf(stderr, "Failed in glXMakeCurrent");
  79         return 0;
  80     }
  81 
  82     /* Get the OpenGL version */
  83     glVersion = (char *) glGetString(GL_VERSION);
  84     if (glVersion == NULL) {
  85         glXDestroyContext(display, ctx);
  86         fprintf(stderr, "glVersion == null");
  87         return 0;
  88     }
  89 
  90     /* find out the version, major and minor version number */
  91     tmpVersionStr = strdup(glVersion);
  92     extractVersionInfo(tmpVersionStr, versionNumbers);
  93     free(tmpVersionStr);
  94 
  95 /*
  96     fprintf(stderr, "GL_VERSION string = %s\n", glVersion);
  97     fprintf(stderr, "GL_VERSION (major.minor) = %d.%d\n",
  98             versionNumbers[0], versionNumbers[1]);
  99 */
 100 
 101     /*
 102      * Targeted Cards: Intel HD Graphics, Intel HD Graphics 2000/3000,
 103      * Radeon HD 2350, GeForce FX (with newer drivers), GeForce 7 series or higher
 104      *
 105      * Check for OpenGL 2.1 or later. 
 106      */
 107     if ((versionNumbers[0] < 2) || ((versionNumbers[0] == 2) && (versionNumbers[1] < 1))) {
 108         glXDestroyContext(display, ctx);
 109         fprintf(stderr, "Prism-ES2 Error : GL_VERSION (major.minor) = %d.%d\n",
 110                 versionNumbers[0], versionNumbers[1]);
 111         return 0;
 112     }
 113 
 114     /* Get the OpenGL vendor and renderer */
 115     glVendor = (const char *) glGetString(GL_VENDOR);
 116     if (glVendor == NULL) {
 117         glVendor = "<UNKNOWN>";
 118     }
 119     glRenderer = (const char *) glGetString(GL_RENDERER);
 120     if (glRenderer == NULL) {
 121         glRenderer = "<UNKNOWN>";
 122     }
 123 
 124     glExtensions = (const char *) glGetString(GL_EXTENSIONS);
 125     if (glExtensions == NULL) {
 126         glXDestroyContext(display, ctx);
 127         fprintf(stderr, "glExtensions == null");
 128         return 0;
 129     }
 130 
 131     // We use GL_ARB_pixel_buffer_object as an guide to
 132     // determine PS 3.0 capable.
 133     if (!isExtensionSupported(glExtensions, "GL_ARB_pixel_buffer_object")) {
 134         glXDestroyContext(display, ctx);
 135         fprintf(stderr, "GL profile isn't PS 3.0 capable");
 136         return 0;
 137     }
 138 
 139     glxExtensions = (const char *) glXGetClientString(display, GLX_EXTENSIONS);
 140     if (glxExtensions == NULL) {
 141         glXDestroyContext(display, ctx);
 142         fprintf(stderr, "glxExtensions == null");
 143         return 0;
 144     }
 145 
 146     /*
 147         fprintf(stderr, "glExtensions: %s\n", glExtensions);
 148         fprintf(stderr, "glxExtensions: %s\n", glxExtensions);
 149      */
 150 
 151     /* allocate the structure */
 152     ctxInfo = (ContextInfo *) malloc(sizeof (ContextInfo));
 153     if (ctxInfo == NULL) {
 154         fprintf(stderr, "nInitialize: Failed in malloc\n");
 155         return 0;
 156     }
 157 
 158     /* initialize the structure */
 159     initializeCtxInfo(ctxInfo);
 160     ctxInfo->versionStr = strdup(glVersion);
 161     ctxInfo->vendorStr = strdup(glVendor);
 162     ctxInfo->rendererStr = strdup(glRenderer);
 163     ctxInfo->glExtensionStr = strdup(glExtensions);
 164     ctxInfo->glxExtensionStr = strdup(glxExtensions);
 165     ctxInfo->versionNumbers[0] = versionNumbers[0];
 166     ctxInfo->versionNumbers[1] = versionNumbers[1];
 167     ctxInfo->display = display;
 168     ctxInfo->context = ctx;
 169 
 170     /* set function pointers */
 171     ctxInfo->glActiveTexture = (PFNGLACTIVETEXTUREPROC)
 172             dlsym(RTLD_DEFAULT, "glActiveTexture");
 173     ctxInfo->glAttachShader = (PFNGLATTACHSHADERPROC)
 174             dlsym(RTLD_DEFAULT, "glAttachShader");
 175     ctxInfo->glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)
 176             dlsym(RTLD_DEFAULT, "glBindAttribLocation");
 177     ctxInfo->glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)
 178             dlsym(RTLD_DEFAULT, "glBindFramebuffer");
 179     ctxInfo->glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)
 180             dlsym(RTLD_DEFAULT, "glBindRenderbuffer");
 181     ctxInfo->glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)
 182             dlsym(RTLD_DEFAULT, "glCheckFramebufferStatus");
 183     ctxInfo->glCreateProgram = (PFNGLCREATEPROGRAMPROC)
 184             dlsym(RTLD_DEFAULT, "glCreateProgram");
 185     ctxInfo->glCreateShader = (PFNGLCREATESHADERPROC)
 186             dlsym(RTLD_DEFAULT, "glCreateShader");
 187     ctxInfo->glCompileShader = (PFNGLCOMPILESHADERPROC)
 188             dlsym(RTLD_DEFAULT, "glCompileShader");
 189     ctxInfo->glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)
 190             dlsym(RTLD_DEFAULT, "glDeleteBuffers");
 191     ctxInfo->glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)
 192             dlsym(RTLD_DEFAULT, "glDeleteFramebuffers");
 193     ctxInfo->glDeleteProgram = (PFNGLDELETEPROGRAMPROC)
 194             dlsym(RTLD_DEFAULT, "glDeleteProgram");
 195     ctxInfo->glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)
 196             dlsym(RTLD_DEFAULT, "glDeleteRenderbuffers");
 197     ctxInfo->glDeleteShader = (PFNGLDELETESHADERPROC)
 198             dlsym(RTLD_DEFAULT, "glDeleteShader");
 199     ctxInfo->glDetachShader = (PFNGLDETACHSHADERPROC)
 200             dlsym(RTLD_DEFAULT, "glDetachShader");
 201     ctxInfo->glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC)
 202             dlsym(RTLD_DEFAULT, "glDisableVertexAttribArray");
 203     ctxInfo->glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)
 204             dlsym(RTLD_DEFAULT, "glEnableVertexAttribArray");
 205     ctxInfo->glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)
 206             dlsym(RTLD_DEFAULT, "glFramebufferRenderbuffer");
 207     ctxInfo->glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)
 208             dlsym(RTLD_DEFAULT, "glFramebufferTexture2D");
 209     ctxInfo->glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)
 210             dlsym(RTLD_DEFAULT, "glGenFramebuffers");
 211     ctxInfo->glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)
 212             dlsym(RTLD_DEFAULT, "glGenRenderbuffers");
 213     ctxInfo->glGetProgramiv = (PFNGLGETPROGRAMIVPROC)
 214             dlsym(RTLD_DEFAULT, "glGetProgramiv");
 215     ctxInfo->glGetShaderiv = (PFNGLGETSHADERIVPROC)
 216             dlsym(RTLD_DEFAULT, "glGetShaderiv");
 217     ctxInfo->glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)
 218             dlsym(RTLD_DEFAULT, "glGetUniformLocation");
 219     ctxInfo->glLinkProgram = (PFNGLLINKPROGRAMPROC)
 220             dlsym(RTLD_DEFAULT, "glLinkProgram");
 221     ctxInfo->glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)
 222             dlsym(RTLD_DEFAULT, "glRenderbufferStorage");
 223     ctxInfo->glShaderSource = (PFNGLSHADERSOURCEPROC)
 224             dlsym(RTLD_DEFAULT, "glShaderSource");
 225     ctxInfo->glUniform1f = (PFNGLUNIFORM1FPROC)
 226             dlsym(RTLD_DEFAULT, "glUniform1f");
 227     ctxInfo->glUniform2f = (PFNGLUNIFORM2FPROC)
 228             dlsym(RTLD_DEFAULT, "glUniform2f");
 229     ctxInfo->glUniform3f = (PFNGLUNIFORM3FPROC)
 230             dlsym(RTLD_DEFAULT, "glUniform3f");
 231     ctxInfo->glUniform4f = (PFNGLUNIFORM4FPROC)
 232             dlsym(RTLD_DEFAULT, "glUniform4f");
 233     ctxInfo->glUniform4fv = (PFNGLUNIFORM4FVPROC)
 234             dlsym(RTLD_DEFAULT, "glUniform4fv");
 235     ctxInfo->glUniform1i = (PFNGLUNIFORM1IPROC)
 236             dlsym(RTLD_DEFAULT, "glUniform1i");
 237     ctxInfo->glUniform2i = (PFNGLUNIFORM2IPROC)
 238             dlsym(RTLD_DEFAULT, "glUniform2i");
 239     ctxInfo->glUniform3i = (PFNGLUNIFORM3IPROC)
 240             dlsym(RTLD_DEFAULT, "glUniform3i");
 241     ctxInfo->glUniform4i = (PFNGLUNIFORM4IPROC)
 242             dlsym(RTLD_DEFAULT, "glUniform4i");
 243     ctxInfo->glUniform4iv = (PFNGLUNIFORM4IVPROC)
 244             dlsym(RTLD_DEFAULT, "glUniform4iv");
 245     ctxInfo->glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)
 246             dlsym(RTLD_DEFAULT, "glUniformMatrix4fv");
 247     ctxInfo->glUseProgram = (PFNGLUSEPROGRAMPROC)
 248             dlsym(RTLD_DEFAULT, "glUseProgram");
 249     ctxInfo->glValidateProgram = (PFNGLVALIDATEPROGRAMPROC)
 250             dlsym(RTLD_DEFAULT, "glValidateProgram");
 251     ctxInfo->glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)
 252             dlsym(RTLD_DEFAULT, "glVertexAttribPointer");
 253     ctxInfo->glGenBuffers = (PFNGLGENBUFFERSPROC)
 254             dlsym(RTLD_DEFAULT, "glGenBuffers");
 255     ctxInfo->glBindBuffer = (PFNGLBINDBUFFERPROC)
 256             dlsym(RTLD_DEFAULT, "glBindBuffer");
 257     ctxInfo->glBufferData = (PFNGLBUFFERDATAPROC)
 258             dlsym(RTLD_DEFAULT, "glBufferData");
 259     ctxInfo->glBufferSubData = (PFNGLBUFFERSUBDATAPROC)
 260             dlsym(RTLD_DEFAULT, "glBufferSubData");
 261     ctxInfo->glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)
 262             dlsym(RTLD_DEFAULT, "glGetShaderInfoLog");
 263     ctxInfo->glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC)
 264             dlsym(RTLD_DEFAULT,"glTexImage2DMultisample");
 265     ctxInfo->glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)
 266             dlsym(RTLD_DEFAULT,"glRenderbufferStorageMultisample");
 267     ctxInfo->glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC)
 268             dlsym(RTLD_DEFAULT,"glBlitFramebuffer");
 269 
 270     if (isExtensionSupported(ctxInfo->glxExtensionStr,
 271             "GLX_SGI_swap_control")) {
 272         ctxInfo->glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)
 273                 dlsym(RTLD_DEFAULT, "glXSwapIntervalSGI");
 274 
 275         if (ctxInfo->glXSwapIntervalSGI == NULL) {
 276             ctxInfo->glXSwapIntervalSGI = glXGetProcAddress("glXSwapIntervalSGI");
 277         }
 278 
 279     }
 280 
 281     // initialize platform states and properties to match
 282     // cached states and properties
 283     if (ctxInfo->glXSwapIntervalSGI != NULL) {
 284         ctxInfo->glXSwapIntervalSGI(0);
 285     }
 286     ctxInfo->state.vSyncEnabled = JNI_FALSE;
 287     ctxInfo->vSyncRequested = vSyncRequested;
 288 
 289     initState(ctxInfo);
 290 
 291     // Release context once we are all done
 292     glXMakeCurrent(display, None, NULL);
 293 
 294     return ptr_to_jlong(ctxInfo);
 295 }
 296 
 297 /*
 298  * Class:     com_sun_prism_es2_X11GLContext
 299  * Method:    nGetNativeHandle
 300  * Signature: (J)J
 301  */
 302 JNIEXPORT jlong JNICALL Java_com_sun_prism_es2_X11GLContext_nGetNativeHandle
 303 (JNIEnv *env, jclass class, jlong nativeCtxInfo) {
 304     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
 305     if (ctxInfo == NULL) {
 306         return 0;
 307     }
 308     return ptr_to_jlong(ctxInfo->context);
 309 }
 310 
 311 /*
 312  * Class:     com_sun_prism_es2_X11GLContext
 313  * Method:    nMakeCurrent
 314  * Signature: (JJ)V
 315  */
 316 JNIEXPORT void JNICALL Java_com_sun_prism_es2_X11GLContext_nMakeCurrent
 317 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jlong nativeDInfo) {
 318     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
 319     DrawableInfo *dInfo = (DrawableInfo *) jlong_to_ptr(nativeDInfo);
 320     int interval;
 321     jboolean vSyncNeeded;
 322 
 323     if (!glXMakeCurrent(ctxInfo->display, dInfo->win, ctxInfo->context)) {
 324         fprintf(stderr, "Failed in glXMakeCurrent");
 325     }
 326 
 327     vSyncNeeded = ctxInfo->vSyncRequested && dInfo->onScreen;
 328     if (vSyncNeeded == ctxInfo->state.vSyncEnabled) {
 329         return;
 330     }
 331     interval = (vSyncNeeded) ? 1 : 0;
 332     ctxInfo->state.vSyncEnabled = vSyncNeeded;
 333     if (ctxInfo->glXSwapIntervalSGI != NULL) {
 334         ctxInfo->glXSwapIntervalSGI(interval);
 335     }
 336 }