1 /* 2 * Copyright (c) 2019, 2019, 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_metal_MetalGraphicsConfig.h" 27 28 #import "MetalGraphicsConfig.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 #pragma mark - 38 #pragma mark "--- Mac OS X specific methods for Metal pipeline ---" 39 40 /** 41 * Disposes all memory and resources associated with the given 42 * CGLGraphicsConfigInfo (including its native OGLContext data). 43 */ 44 /*void 45 OGLGC_DestroyOGLGraphicsConfig(jlong pConfigInfo) 46 { 47 J2dTraceLn(J2D_TRACE_INFO, "OGLGC_DestroyOGLGraphicsConfig"); 48 49 CGLGraphicsConfigInfo *cglinfo = 50 (CGLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo); 51 if (cglinfo == NULL) { 52 J2dRlsTraceLn(J2D_TRACE_ERROR, 53 "OGLGC_DestroyOGLGraphicsConfig: info is null"); 54 return; 55 } 56 57 OGLContext *oglc = (OGLContext*)cglinfo->context; 58 if (oglc != NULL) { 59 OGLContext_DestroyContextResources(oglc); 60 61 CGLCtxInfo *ctxinfo = (CGLCtxInfo *)oglc->ctxInfo; 62 if (ctxinfo != NULL) { 63 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 64 [NSOpenGLContext clearCurrentContext]; 65 [ctxinfo->context clearDrawable]; 66 [ctxinfo->context release]; 67 if (ctxinfo->scratchSurface != 0) { 68 [ctxinfo->scratchSurface release]; 69 } 70 [pool drain]; 71 free(ctxinfo); 72 oglc->ctxInfo = NULL; 73 } 74 cglinfo->context = NULL; 75 } 76 77 free(cglinfo); 78 }*/ 79 80 #pragma mark - 81 #pragma mark "--- MetalGraphicsConfig methods ---" 82 83 /*#ifdef REMOTELAYER 84 mach_port_t JRSRemotePort; 85 int remoteSocketFD = -1; 86 87 static void *JRSRemoteThreadFn(void *data) { 88 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 89 90 // Negotiate a unix domain socket to communicate the 91 // out of band data: to read the mach port server name, and 92 // subsequently write out the layer ID. 93 static char* sock_path = "/tmp/JRSRemoteDemoSocket"; 94 struct sockaddr_un address; 95 int socket_fd, nbytes; 96 int BUFLEN = 256; 97 char buffer[BUFLEN]; 98 99 remoteSocketFD = socket(PF_LOCAL, SOCK_STREAM, 0); 100 if (remoteSocketFD < 0) { 101 NSLog(@"socket() failed"); 102 return NULL; 103 } 104 memset(&address, 0, sizeof(struct sockaddr_un)); 105 address.sun_family = AF_UNIX; 106 memcpy(address.sun_path, sock_path, strlen(sock_path)+1); 107 int tries=0, status=-1; 108 while (status !=0 && tries<600) { 109 status = connect(remoteSocketFD, (struct sockaddr *) &address, 110 sizeof(struct sockaddr_un)); 111 if (status != 0) { 112 tries++; 113 NSLog(@"connection attempt %d failed.", tries); 114 usleep(5000000); 115 } 116 } 117 if (status != 0) { 118 NSLog(@"failed to connect"); 119 return NULL; 120 } 121 nbytes = read(remoteSocketFD, buffer, BUFLEN); 122 NSString* serverString = [[NSString alloc] initWithUTF8String:buffer]; 123 CFRetain(serverString); 124 NSLog(@"Read server name %@", serverString); 125 JRSRemotePort = [JRSRenderServer recieveRenderServer:serverString]; 126 NSLog(@"Read server port %d", JRSRemotePort); 127 128 [pool drain]; 129 return NULL; 130 } 131 132 void sendLayerID(int layerID) { 133 if (JRSRemotePort == 0 || remoteSocketFD < 0) { 134 NSLog(@"No connection to send ID"); 135 return; 136 } 137 int BUFLEN = 256; 138 char buffer[BUFLEN]; 139 snprintf(buffer, BUFLEN, "%d", layerID); 140 write(remoteSocketFD, buffer, BUFLEN); 141 } 142 #endif*/ /* REMOTELAYER */ 143 144 /** 145 * This is a globally shared context used when creating textures. When any 146 * new contexts are created, they specify this context as the "share list" 147 * context, which means any texture objects created when this shared context 148 * is current will be available to any other context in any other thread. 149 */ 150 //NSOpenGLContext *sharedContext = NULL; 151 //NSOpenGLPixelFormat *sharedPixelFormat = NULL; 152 153 /** 154 * Attempts to initialize CGL and the core OpenGL library. 155 */ 156 /*JNIEXPORT jboolean JNICALL 157 Java_sun_java2d_opengl_CGLGraphicsConfig_initCGL 158 (JNIEnv *env, jclass cglgc) 159 { 160 J2dRlsTraceLn(J2D_TRACE_INFO, "CGLGraphicsConfig_initCGL"); 161 162 if (!OGLFuncs_OpenLibrary()) { 163 return JNI_FALSE; 164 } 165 166 if (!OGLFuncs_InitPlatformFuncs() || 167 !OGLFuncs_InitBaseFuncs() || 168 !OGLFuncs_InitExtFuncs()) 169 { 170 OGLFuncs_CloseLibrary(); 171 return JNI_FALSE; 172 } 173 #ifdef REMOTELAYER 174 pthread_t jrsRemoteThread; 175 pthread_create(&jrsRemoteThread, NULL, JRSRemoteThreadFn, NULL); 176 #endif 177 return JNI_TRUE; 178 }*/ 179 180 181 /** 182 * Determines whether the CGL pipeline can be used for a given GraphicsConfig 183 * provided its screen number and visual ID. If the minimum requirements are 184 * met, the native CGLGraphicsConfigInfo structure is initialized for this 185 * GraphicsConfig with the necessary information (pixel format, etc.) 186 * and a pointer to this structure is returned as a jlong. If 187 * initialization fails at any point, zero is returned, indicating that CGL 188 * cannot be used for this GraphicsConfig (we should fallback on an existing 189 * 2D pipeline). 190 */ 191 JNIEXPORT jlong JNICALL 192 Java_sun_java2d_metal_MetalGraphicsConfig_getMetalConfigInfo 193 (JNIEnv *env, jclass metalgc, 194 jint displayID, jint pixfmt) 195 { 196 //fprintf(stdout, "Jay : MetalGraphicsConfig_getMetalConfigInfo\n");fflush(stdout); 197 jlong ret = 0L; 198 JNF_COCOA_ENTER(env); 199 NSMutableArray * retArray = [NSMutableArray arrayWithCapacity:2]; 200 [retArray addObject: [NSNumber numberWithInt: (int)displayID]]; 201 [retArray addObject: [NSNumber numberWithInt: (int)pixfmt]]; 202 //if ([NSThread isMainThread]) { 203 //[GraphicsConfigUtil _getCGLConfigInfo: retArray]; 204 //} else { 205 [MetalGraphicsConfigUtil performSelectorOnMainThread: @selector(_getMetalConfigInfo:) withObject: retArray waitUntilDone: YES]; 206 //} 207 NSNumber * num = (NSNumber *)[retArray objectAtIndex: 0]; 208 ret = (jlong)[num longValue]; 209 JNF_COCOA_EXIT(env); 210 return ret; 211 } 212 213 @implementation MetalGraphicsConfigUtil 214 + (void) _getMetalConfigInfo: (NSMutableArray *)argValue { 215 AWT_ASSERT_APPKIT_THREAD; 216 217 //fprintf(stdout, "Jay : MetalGraphicsConfig_MetalGraphicsConfigUtil\n");fflush(stdout); 218 jint displayID = (jint)[(NSNumber *)[argValue objectAtIndex: 0] intValue]; 219 jint pixfmt = (jint)[(NSNumber *)[argValue objectAtIndex: 1] intValue]; 220 JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; 221 [argValue removeAllObjects]; 222 223 //J2dRlsTraceLn(J2D_TRACE_INFO, "MetalGraphicsConfig_getMetalConfigInfo"); 224 225 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 226 227 /*CGOpenGLDisplayMask glMask = (CGOpenGLDisplayMask)pixfmt; 228 if (sharedContext == NULL) { 229 if (glMask == 0) { 230 glMask = CGDisplayIDToOpenGLDisplayMask(displayID); 231 } 232 233 NSOpenGLPixelFormatAttribute attrs[] = { 234 NSOpenGLPFAAllowOfflineRenderers, 235 NSOpenGLPFAClosestPolicy, 236 NSOpenGLPFAWindow, 237 NSOpenGLPFAPixelBuffer, 238 NSOpenGLPFADoubleBuffer, 239 NSOpenGLPFAColorSize, 32, 240 NSOpenGLPFAAlphaSize, 8, 241 NSOpenGLPFADepthSize, 16, 242 NSOpenGLPFAScreenMask, glMask, 243 0 244 }; 245 246 sharedPixelFormat = 247 [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs]; 248 if (sharedPixelFormat == nil) { 249 J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGraphicsConfig_getCGLConfigInfo: shared NSOpenGLPixelFormat is NULL"); 250 [argValue addObject: [NSNumber numberWithLong: 0L]]; 251 return; 252 } 253 254 sharedContext = 255 [[NSOpenGLContext alloc] 256 initWithFormat:sharedPixelFormat 257 shareContext: NULL]; 258 if (sharedContext == nil) { 259 J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGraphicsConfig_getCGLConfigInfo: shared NSOpenGLContext is NULL"); 260 [argValue addObject: [NSNumber numberWithLong: 0L]]; 261 return; 262 } 263 }*/ 264 id<MTLDevice> device = MTLCreateSystemDefaultDevice(); 265 266 id<MTLCommandQueue> commandQueue = [device newCommandQueue]; 267 268 // Jay : Looks like no need to create MetaLayer here and we were creating 269 // scratch surface only to make OGL context current. So no need to create any layer for 270 // Metal. Just create device and commandQueue for Metal. 271 //defaultLibrary = [device newDefaultLibrary]; 272 /*CAMetalLayer *metalLayer = [CAMetalLayer layer]; 273 metalLayer.device = device; 274 metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;*/ 275 276 #if USE_NSVIEW_FOR_SCRATCH 277 /*NSRect contentRect = NSMakeRect(0, 0, 64, 64); 278 NSWindow *window = 279 [[NSWindow alloc] 280 initWithContentRect: contentRect 281 styleMask: NSBorderlessWindowMask 282 backing: NSBackingStoreBuffered 283 defer: false]; 284 if (window == nil) { 285 J2dRlsTraceLn(J2D_TRACE_ERROR, "MetalGraphicsConfig_getMetalConfigInfo: NSWindow is NULL"); 286 [argValue addObject: [NSNumber numberWithLong: 0L]]; 287 return; 288 } 289 290 NSView *scratchSurface = 291 [[NSView alloc] 292 initWithFrame: contentRect]; 293 if (scratchSurface == nil) { 294 J2dRlsTraceLn(J2D_TRACE_ERROR, "MetalGraphicsConfig_getMetalConfigInfo: NSView is NULL"); 295 [argValue addObject: [NSNumber numberWithLong: 0L]]; 296 return; 297 } 298 [window setContentView: scratchSurface];*/ 299 #else 300 /*NSOpenGLPixelBuffer *scratchSurface = 301 [[NSOpenGLPixelBuffer alloc] 302 initWithTextureTarget:GL_TEXTURE_2D 303 textureInternalFormat:GL_RGB 304 textureMaxMipMapLevel:0 305 pixelsWide:64 306 pixelsHigh:64];*/ 307 #endif 308 309 /*NSOpenGLContext *context = 310 [[NSOpenGLContext alloc] 311 initWithFormat: sharedPixelFormat 312 shareContext: sharedContext]; 313 if (context == nil) { 314 J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGraphicsConfig_getCGLConfigInfo: NSOpenGLContext is NULL"); 315 [argValue addObject: [NSNumber numberWithLong: 0L]]; 316 return; 317 } 318 319 GLint contextVirtualScreen = [context currentVirtualScreen];*/ 320 #if USE_NSVIEW_FOR_SCRATCH 321 //[context setView: scratchSurface]; 322 // Jay : no need of scratch layer for metal 323 //metalLayer.frame = scratchSurface.layer.frame; 324 //[scratchSurface.layer addSublayer: metalLayer]; 325 #else 326 /*[context 327 setPixelBuffer: scratchSurface 328 cubeMapFace:0 329 mipMapLevel:0 330 currentVirtualScreen: contextVirtualScreen];*/ 331 #endif 332 /*[context makeCurrentContext]; 333 334 // get version and extension strings 335 const unsigned char *versionstr = j2d_glGetString(GL_VERSION); 336 if (!OGLContext_IsVersionSupported(versionstr)) { 337 J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGraphicsConfig_getCGLConfigInfo: OpenGL 1.2 is required"); 338 [NSOpenGLContext clearCurrentContext]; 339 [argValue addObject: [NSNumber numberWithLong: 0L]]; 340 return; 341 } 342 J2dRlsTraceLn1(J2D_TRACE_INFO, "CGLGraphicsConfig_getCGLConfigInfo: OpenGL version=%s", versionstr); 343 344 jint caps = CAPS_EMPTY; 345 OGLContext_GetExtensionInfo(env, &caps); 346 347 GLint value = 0; 348 [sharedPixelFormat 349 getValues: &value 350 forAttribute: NSOpenGLPFADoubleBuffer 351 forVirtualScreen: contextVirtualScreen]; 352 if (value != 0) { 353 caps |= CAPS_DOUBLEBUFFERED; 354 } 355 356 J2dRlsTraceLn1(J2D_TRACE_INFO, 357 "CGLGraphicsConfig_getCGLConfigInfo: db=%d", 358 (caps & CAPS_DOUBLEBUFFERED) != 0);*/ 359 360 // remove before shipping (?) 361 #if 1 362 /*[sharedPixelFormat 363 getValues: &value 364 forAttribute: NSOpenGLPFAAccelerated 365 forVirtualScreen: contextVirtualScreen]; 366 if (value == 0) { 367 [sharedPixelFormat 368 getValues: &value 369 forAttribute: NSOpenGLPFARendererID 370 forVirtualScreen: contextVirtualScreen]; 371 fprintf(stderr, "WARNING: GL pipe is running in software mode (Renderer ID=0x%x)\n", (int)value); 372 }*/ 373 #endif 374 375 // 0: the buffers are swapped with no regard to the vertical refresh rate 376 // 1: the buffers are swapped only during the vertical retrace 377 /*GLint params = swapInterval; 378 [context setValues: ¶ms forParameter: NSOpenGLCPSwapInterval]; 379 380 CGLCtxInfo *ctxinfo = (CGLCtxInfo *)malloc(sizeof(CGLCtxInfo)); 381 if (ctxinfo == NULL) { 382 J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGC_InitOGLContext: could not allocate memory for ctxinfo"); 383 [NSOpenGLContext clearCurrentContext]; 384 [argValue addObject: [NSNumber numberWithLong: 0L]]; 385 return; 386 } 387 memset(ctxinfo, 0, sizeof(CGLCtxInfo)); 388 ctxinfo->context = context; 389 ctxinfo->scratchSurface = scratchSurface; 390 391 OGLContext *oglc = (OGLContext *)malloc(sizeof(OGLContext)); 392 if (oglc == 0L) { 393 J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGC_InitOGLContext: could not allocate memory for oglc"); 394 [NSOpenGLContext clearCurrentContext]; 395 free(ctxinfo); 396 [argValue addObject: [NSNumber numberWithLong: 0L]]; 397 return; 398 } 399 memset(oglc, 0, sizeof(OGLContext)); 400 oglc->ctxInfo = ctxinfo; 401 oglc->caps = caps;*/ 402 403 // create the CGLGraphicsConfigInfo record for this config 404 MetalGraphicsConfigInfo *metalinfo = (MetalGraphicsConfigInfo *)malloc(sizeof(MetalGraphicsConfigInfo)); 405 if (metalinfo == NULL) { 406 //J2dRlsTraceLn(J2D_TRACE_ERROR, "MetalGraphicsConfig_getMetalConfigInfo: could not allocate memory for cglinfo"); 407 //[NSOpenGLContext clearCurrentContext]; 408 //free(oglc); 409 //free(ctxinfo); 410 //[argValue addObject: [NSNumber numberWithLong: 0L]]; 411 return; 412 } 413 memset(metalinfo, 0, sizeof(MetalGraphicsConfigInfo)); 414 metalinfo->screen = displayID; 415 metalinfo->device = device; 416 metalinfo->commandQueue = commandQueue; 417 418 //[NSOpenGLContext clearCurrentContext]; 419 [argValue addObject: [NSNumber numberWithLong:ptr_to_jlong(metalinfo)]]; 420 [pool drain]; 421 } 422 @end //GraphicsConfigUtil 423 424 /*JNIEXPORT jint JNICALL 425 Java_sun_java2d_opengl_CGLGraphicsConfig_getOGLCapabilities 426 (JNIEnv *env, jclass cglgc, jlong configInfo) 427 { 428 J2dTraceLn(J2D_TRACE_INFO, "CGLGraphicsConfig_getOGLCapabilities"); 429 430 CGLGraphicsConfigInfo *cglinfo = 431 (CGLGraphicsConfigInfo *)jlong_to_ptr(configInfo); 432 if ((cglinfo == NULL) || (cglinfo->context == NULL)) { 433 return CAPS_EMPTY; 434 } else { 435 return cglinfo->context->caps; 436 } 437 } 438 439 JNIEXPORT jint JNICALL 440 Java_sun_java2d_opengl_CGLGraphicsConfig_nativeGetMaxTextureSize 441 (JNIEnv *env, jclass cglgc) 442 { 443 J2dTraceLn(J2D_TRACE_INFO, "CGLGraphicsConfig_nativeGetMaxTextureSize"); 444 445 __block int max = 0; 446 447 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ 448 [sharedContext makeCurrentContext]; 449 j2d_glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max); 450 [NSOpenGLContext clearCurrentContext]; 451 }]; 452 453 return (jint)max; 454 }*/