1 /* 2 * Copyright (c) 2011, 2020, 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 #import "sun_java2d_opengl_CGLGraphicsConfig.h" 27 28 #import "CGLGraphicsConfig.h" 29 #import "CGLSurfaceData.h" 30 #import "ThreadUtilities.h" 31 32 #import <stdlib.h> 33 #import <string.h> 34 #import <ApplicationServices/ApplicationServices.h> 35 #import <JavaNativeFoundation/JavaNativeFoundation.h> 36 37 /** 38 * Disposes all memory and resources associated with the given 39 * CGLGraphicsConfigInfo (including its native OGLContext data). 40 */ 41 void 42 OGLGC_DestroyOGLGraphicsConfig(jlong pConfigInfo) 43 { 44 J2dTraceLn(J2D_TRACE_INFO, "OGLGC_DestroyOGLGraphicsConfig"); 45 46 CGLGraphicsConfigInfo *cglinfo = 47 (CGLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo); 48 if (cglinfo == NULL) { 49 J2dRlsTraceLn(J2D_TRACE_ERROR, 50 "OGLGC_DestroyOGLGraphicsConfig: info is null"); 51 return; 52 } 53 54 OGLContext *oglc = (OGLContext*)cglinfo->context; 55 if (oglc != NULL) { 56 OGLContext_DestroyContextResources(oglc); 57 58 CGLCtxInfo *ctxinfo = (CGLCtxInfo *)oglc->ctxInfo; 59 if (ctxinfo != NULL) { 60 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 61 [NSOpenGLContext clearCurrentContext]; 62 [ctxinfo->context clearDrawable]; 63 [ctxinfo->context release]; 64 if (ctxinfo->scratchSurface != 0) { 65 [ctxinfo->scratchSurface release]; 66 } 67 [pool drain]; 68 free(ctxinfo); 69 oglc->ctxInfo = NULL; 70 } 71 cglinfo->context = NULL; 72 } 73 74 free(cglinfo); 75 } 76 77 /** 78 * This is a globally shared context used when creating textures. When any 79 * new contexts are created, they specify this context as the "share list" 80 * context, which means any texture objects created when this shared context 81 * is current will be available to any other context in any other thread. 82 */ 83 NSOpenGLContext *sharedContext = NULL; 84 NSOpenGLPixelFormat *sharedPixelFormat = NULL; 85 86 /** 87 * Attempts to initialize CGL and the core OpenGL library. 88 */ 89 JNIEXPORT jboolean JNICALL 90 Java_sun_java2d_opengl_CGLGraphicsConfig_initCGL 91 (JNIEnv *env, jclass cglgc) 92 { 93 J2dRlsTraceLn(J2D_TRACE_INFO, "CGLGraphicsConfig_initCGL"); 94 95 if (!OGLFuncs_OpenLibrary()) { 96 return JNI_FALSE; 97 } 98 99 if (!OGLFuncs_InitPlatformFuncs() || 100 !OGLFuncs_InitBaseFuncs() || 101 !OGLFuncs_InitExtFuncs()) 102 { 103 OGLFuncs_CloseLibrary(); 104 return JNI_FALSE; 105 } 106 return JNI_TRUE; 107 } 108 109 /** 110 * Determines whether the CGL pipeline can be used for a given GraphicsConfig. 111 * If the minimum requirements are met, the native CGLGraphicsConfigInfo 112 * structure is initialized for this GraphicsConfig with the necessary 113 * information and a pointer to this structure is returned as a jlong. If 114 * initialization fails at any point, zero is returned, indicating that CGL 115 * cannot be used for this GraphicsConfig (we should fallback on an existing 2D 116 * pipeline). 117 */ 118 JNIEXPORT jlong JNICALL 119 Java_sun_java2d_opengl_CGLGraphicsConfig_getCGLConfigInfo 120 (JNIEnv *env, jclass cglgc) 121 { 122 __block jlong ret = 0L; 123 JNF_COCOA_ENTER(env); 124 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ 125 JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; 126 127 J2dRlsTraceLn(J2D_TRACE_INFO, "CGLGraphicsConfig_getCGLConfigInfo"); 128 129 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 130 131 if (sharedContext == NULL) { 132 133 NSOpenGLPixelFormatAttribute attrs[] = { 134 NSOpenGLPFAAllowOfflineRenderers, 135 NSOpenGLPFAClosestPolicy, 136 NSOpenGLPFAWindow, 137 NSOpenGLPFAPixelBuffer, 138 NSOpenGLPFADoubleBuffer, 139 NSOpenGLPFAColorSize, 32, 140 NSOpenGLPFAAlphaSize, 8, 141 NSOpenGLPFADepthSize, 16, 142 0 143 }; 144 145 sharedPixelFormat = 146 [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs]; 147 if (sharedPixelFormat == nil) { 148 J2dRlsTraceLn(J2D_TRACE_ERROR, 149 "CGLGraphicsConfig_getCGLConfigInfo: shared NSOpenGLPixelFormat is NULL"); 150 return; 151 } 152 153 sharedContext = 154 [[NSOpenGLContext alloc] 155 initWithFormat:sharedPixelFormat 156 shareContext: NULL]; 157 if (sharedContext == nil) { 158 J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGraphicsConfig_getCGLConfigInfo: shared NSOpenGLContext is NULL"); 159 return; 160 } 161 } 162 163 #if USE_NSVIEW_FOR_SCRATCH 164 NSRect contentRect = NSMakeRect(0, 0, 64, 64); 165 NSWindow *window = 166 [[NSWindow alloc] 167 initWithContentRect: contentRect 168 styleMask: NSBorderlessWindowMask 169 backing: NSBackingStoreBuffered 170 defer: false]; 171 if (window == nil) { 172 J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGraphicsConfig_getCGLConfigInfo: NSWindow is NULL"); 173 return; 174 } 175 176 NSView *scratchSurface = 177 [[NSView alloc] 178 initWithFrame: contentRect]; 179 if (scratchSurface == nil) { 180 J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGraphicsConfig_getCGLConfigInfo: NSView is NULL"); 181 return; 182 } 183 [window setContentView: scratchSurface]; 184 #else 185 NSOpenGLPixelBuffer *scratchSurface = 186 [[NSOpenGLPixelBuffer alloc] 187 initWithTextureTarget:GL_TEXTURE_2D 188 textureInternalFormat:GL_RGB 189 textureMaxMipMapLevel:0 190 pixelsWide:64 191 pixelsHigh:64]; 192 #endif 193 194 NSOpenGLContext *context = 195 [[NSOpenGLContext alloc] 196 initWithFormat: sharedPixelFormat 197 shareContext: sharedContext]; 198 if (context == nil) { 199 J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGraphicsConfig_getCGLConfigInfo: NSOpenGLContext is NULL"); 200 return; 201 } 202 203 GLint contextVirtualScreen = [context currentVirtualScreen]; 204 #if USE_NSVIEW_FOR_SCRATCH 205 [context setView: scratchSurface]; 206 #else 207 [context 208 setPixelBuffer: scratchSurface 209 cubeMapFace:0 210 mipMapLevel:0 211 currentVirtualScreen: contextVirtualScreen]; 212 #endif 213 [context makeCurrentContext]; 214 215 // get version and extension strings 216 const unsigned char *versionstr = j2d_glGetString(GL_VERSION); 217 if (!OGLContext_IsVersionSupported(versionstr)) { 218 J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGraphicsConfig_getCGLConfigInfo: OpenGL 1.2 is required"); 219 [NSOpenGLContext clearCurrentContext]; 220 return; 221 } 222 J2dRlsTraceLn1(J2D_TRACE_INFO, "CGLGraphicsConfig_getCGLConfigInfo: OpenGL version=%s", versionstr); 223 224 jint caps = CAPS_EMPTY; 225 OGLContext_GetExtensionInfo(env, &caps); 226 227 GLint value = 0; 228 [sharedPixelFormat 229 getValues: &value 230 forAttribute: NSOpenGLPFADoubleBuffer 231 forVirtualScreen: contextVirtualScreen]; 232 if (value != 0) { 233 caps |= CAPS_DOUBLEBUFFERED; 234 } 235 236 J2dRlsTraceLn1(J2D_TRACE_INFO, 237 "CGLGraphicsConfig_getCGLConfigInfo: db=%d", 238 (caps & CAPS_DOUBLEBUFFERED) != 0); 239 240 // remove before shipping (?) 241 #if 1 242 [sharedPixelFormat 243 getValues: &value 244 forAttribute: NSOpenGLPFAAccelerated 245 forVirtualScreen: contextVirtualScreen]; 246 if (value == 0) { 247 [sharedPixelFormat 248 getValues: &value 249 forAttribute: NSOpenGLPFARendererID 250 forVirtualScreen: contextVirtualScreen]; 251 fprintf(stderr, "WARNING: GL pipe is running in software mode (Renderer ID=0x%x)\n", (int)value); 252 } 253 #endif 254 CGLCtxInfo *ctxinfo = (CGLCtxInfo *)malloc(sizeof(CGLCtxInfo)); 255 if (ctxinfo == NULL) { 256 J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGC_InitOGLContext: could not allocate memory for ctxinfo"); 257 [NSOpenGLContext clearCurrentContext]; 258 return; 259 } 260 memset(ctxinfo, 0, sizeof(CGLCtxInfo)); 261 ctxinfo->context = context; 262 ctxinfo->scratchSurface = scratchSurface; 263 264 OGLContext *oglc = (OGLContext *)malloc(sizeof(OGLContext)); 265 if (oglc == 0L) { 266 J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGC_InitOGLContext: could not allocate memory for oglc"); 267 [NSOpenGLContext clearCurrentContext]; 268 free(ctxinfo); 269 return; 270 } 271 memset(oglc, 0, sizeof(OGLContext)); 272 oglc->ctxInfo = ctxinfo; 273 oglc->caps = caps; 274 275 // create the CGLGraphicsConfigInfo record for this config 276 CGLGraphicsConfigInfo *cglinfo = (CGLGraphicsConfigInfo *)malloc(sizeof(CGLGraphicsConfigInfo)); 277 if (cglinfo == NULL) { 278 J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGraphicsConfig_getCGLConfigInfo: could not allocate memory for cglinfo"); 279 [NSOpenGLContext clearCurrentContext]; 280 free(oglc); 281 free(ctxinfo); 282 return; 283 } 284 memset(cglinfo, 0, sizeof(CGLGraphicsConfigInfo)); 285 cglinfo->context = oglc; 286 287 [NSOpenGLContext clearCurrentContext]; 288 ret = ptr_to_jlong(cglinfo); 289 [pool drain]; 290 }]; 291 JNF_COCOA_EXIT(env); 292 return ret; 293 } 294 295 JNIEXPORT jint JNICALL 296 Java_sun_java2d_opengl_CGLGraphicsConfig_getOGLCapabilities 297 (JNIEnv *env, jclass cglgc, jlong configInfo) 298 { 299 J2dTraceLn(J2D_TRACE_INFO, "CGLGraphicsConfig_getOGLCapabilities"); 300 301 CGLGraphicsConfigInfo *cglinfo = 302 (CGLGraphicsConfigInfo *)jlong_to_ptr(configInfo); 303 if ((cglinfo == NULL) || (cglinfo->context == NULL)) { 304 return CAPS_EMPTY; 305 } else { 306 return cglinfo->context->caps; 307 } 308 } 309 310 JNIEXPORT jint JNICALL 311 Java_sun_java2d_opengl_CGLGraphicsConfig_nativeGetMaxTextureSize 312 (JNIEnv *env, jclass cglgc) 313 { 314 J2dTraceLn(J2D_TRACE_INFO, "CGLGraphicsConfig_nativeGetMaxTextureSize"); 315 316 __block int max = 0; 317 318 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ 319 [sharedContext makeCurrentContext]; 320 j2d_glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max); 321 [NSOpenGLContext clearCurrentContext]; 322 }]; 323 324 return (jint)max; 325 }