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_WinGLContext.h"
  35 
  36 extern void printAndReleaseResources(HWND hwnd, HGLRC hglrc,
  37         HDC hdc, LPCTSTR szAppName, char *message);
  38 extern HWND createDummyWindow(LPCTSTR szAppName);
  39 extern LONG WINAPI WndProc(HWND hWnd, UINT msg,
  40         WPARAM wParam, LPARAM lParam);
  41 extern PIXELFORMATDESCRIPTOR getPFD(jint *attrArr);
  42 
  43 /*
  44  * Class:     com_sun_prism_es2_WinGLContext
  45  * Method:    nInitialize
  46  * Signature: (JJZ)J
  47  */
  48 JNIEXPORT jlong JNICALL Java_com_sun_prism_es2_WinGLContext_nInitialize
  49 (JNIEnv *env, jclass class, jlong nativeDInfo, jlong nativePFInfo,
  50         jboolean vSyncRequested) {
  51     HDC hdc = NULL;
  52     HGLRC hglrc = NULL;
  53     ContextInfo *ctxInfo = NULL;
  54     int pixelFormat;
  55 
  56     const char *glVersion;
  57     const char *glVendor;
  58     const char *glRenderer;
  59     char *tmpVersionStr;
  60     int versionNumbers[2];
  61     const char *glExtensions;
  62     const char *wglExtensions;
  63     PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = NULL;
  64     PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL;
  65 
  66     DrawableInfo *dInfo = (DrawableInfo *) jlong_to_ptr(nativeDInfo);
  67     PixelFormatInfo *pfInfo = (PixelFormatInfo *) jlong_to_ptr(nativePFInfo);
  68 
  69     if ((dInfo == NULL) || (pfInfo == NULL)) {
  70         return 0;
  71     }
  72 
  73     hdc = dInfo->hdc;
  74     pixelFormat = pfInfo->pixelFormat;
  75 
  76     if (!SetPixelFormat(hdc, pixelFormat, NULL)) {
  77         fprintf(stderr, "Failed in SetPixelFormat");
  78         return 0;
  79     }
  80 
  81     hglrc = wglCreateContext(hdc);
  82     if (hglrc == NULL) {
  83         printAndReleaseResources(NULL, hglrc, NULL, NULL,
  84                 "Failed in wglCreateContext");
  85         return 0;
  86     }
  87 
  88     if (!wglMakeCurrent(hdc, hglrc)) {
  89         printAndReleaseResources(NULL, hglrc, NULL, NULL,
  90                 "Failed in wglMakeCurrent");
  91         return 0;
  92     }
  93 
  94     /* Get the OpenGL version */
  95     glVersion = (const char *) glGetString(GL_VERSION);
  96     if (glVersion == NULL) {
  97         printAndReleaseResources(NULL, hglrc, NULL, NULL,
  98                 "glVersion == null");
  99         return 0;
 100     }
 101 
 102     /* find out the version, major and minor version number */
 103     tmpVersionStr = _strdup(glVersion);
 104     extractVersionInfo(tmpVersionStr, versionNumbers);
 105     free(tmpVersionStr);
 106 
 107     /*
 108      * Supported Cards: Intel HD Graphics, Intel HD Graphics 2000/3000,
 109      * Radeon HD 2350, GeForce FX (with newer drivers), GeForce 6 series or higher
 110      *
 111      * Check for OpenGL 2.0 or later.
 112      */
 113     if (versionNumbers[0] < 2) {
 114         fprintf(stderr, "GL_VERSION (major.minor) = %d.%d",
 115                 versionNumbers[0], versionNumbers[1]);
 116         printAndReleaseResources(NULL, hglrc, NULL, NULL, NULL);
 117         return 0;
 118     }
 119 
 120     /* Get the OpenGL vendor and renderer */
 121     glVendor = (const char *) glGetString(GL_VENDOR);
 122     if (glVendor == NULL) {
 123         glVendor = "<UNKNOWN>";
 124     }
 125     glRenderer = (const char *) glGetString(GL_RENDERER);
 126     if (glRenderer == NULL) {
 127         glRenderer = "<UNKNOWN>";
 128     }
 129 
 130     glExtensions = (const char *) glGetString(GL_EXTENSIONS);
 131     if (glExtensions == NULL) {
 132         printAndReleaseResources(NULL, hglrc, NULL, NULL,
 133                 "glExtensions == null");
 134         return 0;
 135     }
 136 
 137     // We use GL 2.0 and GL_ARB_pixel_buffer_object as an guide to
 138     // determine PS 3.0 capable.
 139     if (!isExtensionSupported(glExtensions, "GL_ARB_pixel_buffer_object")) {
 140         printAndReleaseResources(NULL, hglrc, NULL, NULL,
 141                 "GL profile isn't PS 3.0 capable");
 142         return 0;
 143     }
 144 
 145     wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)
 146             wglGetProcAddress("wglGetExtensionsStringARB");
 147     if (wglGetExtensionsStringARB == NULL) {
 148         printAndReleaseResources(NULL, hglrc, NULL, NULL,
 149                 "wglGetExtensionsStringARB is not supported!");
 150         return 0;
 151     }
 152     wglExtensions = (char *) wglGetExtensionsStringARB(hdc);
 153     if (wglExtensions == NULL) {
 154         printAndReleaseResources(NULL, hglrc, NULL, NULL,
 155                 "wglExtensions == null");
 156         return 0;
 157     }
 158 
 159     /*
 160         fprintf(stderr, "glExtensions: %s\n", glExtensions);
 161         fprintf(stderr, "wglExtensions: %s\n", wglExtensions);
 162      */
 163 
 164     /* allocate the structure */
 165     ctxInfo = (ContextInfo *) malloc(sizeof (ContextInfo));
 166     if (ctxInfo == NULL) {
 167         fprintf(stderr, "nInitialize: Failed in malloc\n");
 168         return 0;
 169     }
 170 
 171     /* initialize the structure */
 172     initializeCtxInfo(ctxInfo);
 173     ctxInfo->versionStr = _strdup(glVersion);
 174     ctxInfo->vendorStr = _strdup(glVendor);
 175     ctxInfo->rendererStr = _strdup(glRenderer);
 176     ctxInfo->glExtensionStr = _strdup(glExtensions);
 177     ctxInfo->wglExtensionStr = _strdup(wglExtensions);
 178     ctxInfo->versionNumbers[0] = versionNumbers[0];
 179     ctxInfo->versionNumbers[1] = versionNumbers[1];
 180     ctxInfo->hglrc = hglrc;
 181 
 182     /* set function pointers */
 183     ctxInfo->glActiveTexture = (PFNGLACTIVETEXTUREPROC)
 184             wglGetProcAddress("glActiveTexture");
 185     ctxInfo->glAttachShader = (PFNGLATTACHSHADERPROC)
 186             wglGetProcAddress("glAttachShader");
 187     ctxInfo->glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)
 188             wglGetProcAddress("glBindAttribLocation");
 189     ctxInfo->glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)
 190             wglGetProcAddress("glBindFramebuffer");
 191     ctxInfo->glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)
 192             wglGetProcAddress("glBindRenderbuffer");
 193     ctxInfo->glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)
 194             wglGetProcAddress("glCheckFramebufferStatus");
 195     ctxInfo->glCreateProgram = (PFNGLCREATEPROGRAMPROC)
 196             wglGetProcAddress("glCreateProgram");
 197     ctxInfo->glCreateShader = (PFNGLCREATESHADERPROC)
 198             wglGetProcAddress("glCreateShader");
 199     ctxInfo->glCompileShader = (PFNGLCOMPILESHADERPROC)
 200             wglGetProcAddress("glCompileShader");
 201     ctxInfo->glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)
 202             wglGetProcAddress("glDeleteBuffers");
 203     ctxInfo->glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)
 204             wglGetProcAddress("glDeleteFramebuffers");
 205     ctxInfo->glDeleteProgram = (PFNGLDELETEPROGRAMPROC)
 206             wglGetProcAddress("glDeleteProgram");
 207     ctxInfo->glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)
 208             wglGetProcAddress("glDeleteRenderbuffers");
 209     ctxInfo->glDeleteShader = (PFNGLDELETESHADERPROC)
 210             wglGetProcAddress("glDeleteShader");
 211     ctxInfo->glDetachShader = (PFNGLDETACHSHADERPROC)
 212             wglGetProcAddress("glDetachShader");
 213     ctxInfo->glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC)
 214             wglGetProcAddress("glDisableVertexAttribArray");
 215     ctxInfo->glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)
 216             wglGetProcAddress("glEnableVertexAttribArray");
 217     ctxInfo->glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)
 218             wglGetProcAddress("glFramebufferRenderbuffer");
 219     ctxInfo->glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)
 220             wglGetProcAddress("glFramebufferTexture2D");
 221     ctxInfo->glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)
 222             wglGetProcAddress("glGenFramebuffers");
 223     ctxInfo->glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)
 224             wglGetProcAddress("glGenRenderbuffers");
 225     ctxInfo->glGetProgramiv = (PFNGLGETPROGRAMIVPROC)
 226             wglGetProcAddress("glGetProgramiv");
 227     ctxInfo->glGetShaderiv = (PFNGLGETSHADERIVPROC)
 228             wglGetProcAddress("glGetShaderiv");
 229     ctxInfo->glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)
 230             wglGetProcAddress("glGetUniformLocation");
 231     ctxInfo->glLinkProgram = (PFNGLLINKPROGRAMPROC)
 232             wglGetProcAddress("glLinkProgram");
 233     ctxInfo->glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)
 234             wglGetProcAddress("glRenderbufferStorage");
 235     ctxInfo->glShaderSource = (PFNGLSHADERSOURCEPROC)
 236             wglGetProcAddress("glShaderSource");
 237     ctxInfo->glUniform1f = (PFNGLUNIFORM1FPROC)
 238             wglGetProcAddress("glUniform1f");
 239     ctxInfo->glUniform2f = (PFNGLUNIFORM2FPROC)
 240             wglGetProcAddress("glUniform2f");
 241     ctxInfo->glUniform3f = (PFNGLUNIFORM3FPROC)
 242             wglGetProcAddress("glUniform3f");
 243     ctxInfo->glUniform4f = (PFNGLUNIFORM4FPROC)
 244             wglGetProcAddress("glUniform4f");
 245     ctxInfo->glUniform4fv = (PFNGLUNIFORM4FVPROC)
 246             wglGetProcAddress("glUniform4fv");
 247     ctxInfo->glUniform1i = (PFNGLUNIFORM1IPROC)
 248             wglGetProcAddress("glUniform1i");
 249     ctxInfo->glUniform2i = (PFNGLUNIFORM2IPROC)
 250             wglGetProcAddress("glUniform2i");
 251     ctxInfo->glUniform3i = (PFNGLUNIFORM3IPROC)
 252             wglGetProcAddress("glUniform3i");
 253     ctxInfo->glUniform4i = (PFNGLUNIFORM4IPROC)
 254             wglGetProcAddress("glUniform4i");
 255     ctxInfo->glUniform4iv = (PFNGLUNIFORM4IVPROC)
 256             wglGetProcAddress("glUniform4iv");
 257     ctxInfo->glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)
 258             wglGetProcAddress("glUniformMatrix4fv");
 259     ctxInfo->glUseProgram = (PFNGLUSEPROGRAMPROC)
 260             wglGetProcAddress("glUseProgram");
 261     ctxInfo->glValidateProgram = (PFNGLVALIDATEPROGRAMPROC)
 262             wglGetProcAddress("glValidateProgram");
 263     ctxInfo->glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)
 264             wglGetProcAddress("glVertexAttribPointer");
 265     ctxInfo->glGenBuffers = (PFNGLGENBUFFERSPROC)
 266             wglGetProcAddress("glGenBuffers");
 267     ctxInfo->glBindBuffer = (PFNGLBINDBUFFERPROC)
 268             wglGetProcAddress("glBindBuffer");
 269     ctxInfo->glBufferData = (PFNGLBUFFERDATAPROC)
 270             wglGetProcAddress("glBufferData");
 271     ctxInfo->glBufferSubData = (PFNGLBUFFERSUBDATAPROC)
 272             wglGetProcAddress("glBufferSubData");
 273     ctxInfo->glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)
 274             wglGetProcAddress("glGetShaderInfoLog");
 275     ctxInfo->glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)
 276             wglGetProcAddress("glGetProgramInfoLog");
 277     ctxInfo->glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC)
 278             wglGetProcAddress("glTexImage2DMultisample");
 279     ctxInfo->glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)
 280             wglGetProcAddress("glRenderbufferStorageMultisample");
 281     ctxInfo->glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC)
 282             wglGetProcAddress("glBlitFramebuffer");
 283 
 284     if (isExtensionSupported(ctxInfo->wglExtensionStr,
 285             "WGL_EXT_swap_control")) {
 286         ctxInfo->wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)
 287                 wglGetProcAddress("wglSwapIntervalEXT");
 288     }
 289 
 290     // initialize platform states and properties to match
 291     // cached states and properties
 292     if (ctxInfo->wglSwapIntervalEXT != NULL) {
 293         ctxInfo->wglSwapIntervalEXT(0);
 294     }
 295     ctxInfo->state.vSyncEnabled = JNI_FALSE;
 296     ctxInfo->vSyncRequested = vSyncRequested;
 297 
 298     initState(ctxInfo);
 299 
 300     // Release context once we are all done
 301     wglMakeCurrent(NULL, NULL);
 302 
 303     return ptr_to_jlong(ctxInfo);
 304 }
 305 
 306 /*
 307  * Class:     com_sun_prism_es2_WinGLContext
 308  * Method:    nGetNativeHandle
 309  * Signature: (J)J
 310  */
 311 JNIEXPORT jlong JNICALL Java_com_sun_prism_es2_WinGLContext_nGetNativeHandle
 312 (JNIEnv *env, jclass class, jlong nativeCtxInfo) {
 313     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
 314     if (ctxInfo == NULL) {
 315         return 0;
 316     }
 317     return ptr_to_jlong(ctxInfo->hglrc);
 318 }
 319 
 320 /*
 321  * Class:     com_sun_prism_es2_WinGLContext
 322  * Method:    nMakeCurrent
 323  * Signature: (JJ)V
 324  */
 325 JNIEXPORT void JNICALL Java_com_sun_prism_es2_WinGLContext_nMakeCurrent
 326 (JNIEnv *env, jclass class, jlong nativeCtxInfo, jlong nativeDInfo) {
 327     ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
 328     DrawableInfo *dInfo = (DrawableInfo *) jlong_to_ptr(nativeDInfo);
 329     int interval;
 330     jboolean vSyncNeeded;
 331 
 332     if ((ctxInfo == NULL) || (dInfo == NULL)) {
 333         return;
 334     }
 335 
 336     if (!wglMakeCurrent(dInfo->hdc, ctxInfo->hglrc)) {
 337         fprintf(stderr, "Failed in wglMakeCurrent");
 338     }
 339 
 340     vSyncNeeded = ctxInfo->vSyncRequested && dInfo->onScreen;
 341     if (vSyncNeeded == ctxInfo->state.vSyncEnabled) {
 342         return;
 343     }
 344     interval = (vSyncNeeded) ? 1 : 0;
 345     ctxInfo->state.vSyncEnabled = vSyncNeeded;
 346     if (ctxInfo->wglSwapIntervalEXT != NULL) {
 347         ctxInfo->wglSwapIntervalEXT(interval);
 348     }
 349 }