src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalGraphicsConfig.m
branchmetal-prototype-branch
changeset 57196 a95707a39ff5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalGraphicsConfig.m	Wed Feb 20 17:00:40 2019 +0530
@@ -0,0 +1,454 @@
+/*
+ * Copyright (c) 2019, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#import "sun_java2d_metal_MetalGraphicsConfig.h"
+
+#import "MetalGraphicsConfig.h"
+//#import "CGLSurfaceData.h"
+#import "ThreadUtilities.h"
+
+#import <stdlib.h>
+#import <string.h>
+#import <ApplicationServices/ApplicationServices.h>
+#import <JavaNativeFoundation/JavaNativeFoundation.h>
+
+#pragma mark -
+#pragma mark "--- Mac OS X specific methods for Metal pipeline ---"
+
+/**
+ * Disposes all memory and resources associated with the given
+ * CGLGraphicsConfigInfo (including its native OGLContext data).
+ */
+/*void
+OGLGC_DestroyOGLGraphicsConfig(jlong pConfigInfo)
+{
+    J2dTraceLn(J2D_TRACE_INFO, "OGLGC_DestroyOGLGraphicsConfig");
+
+    CGLGraphicsConfigInfo *cglinfo =
+        (CGLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo);
+    if (cglinfo == NULL) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR,
+                      "OGLGC_DestroyOGLGraphicsConfig: info is null");
+        return;
+    }
+
+    OGLContext *oglc = (OGLContext*)cglinfo->context;
+    if (oglc != NULL) {
+        OGLContext_DestroyContextResources(oglc);
+
+        CGLCtxInfo *ctxinfo = (CGLCtxInfo *)oglc->ctxInfo;
+        if (ctxinfo != NULL) {
+            NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+            [NSOpenGLContext clearCurrentContext];
+            [ctxinfo->context clearDrawable];
+            [ctxinfo->context release];
+            if (ctxinfo->scratchSurface != 0) {
+                [ctxinfo->scratchSurface release];
+            }
+            [pool drain];
+            free(ctxinfo);
+            oglc->ctxInfo = NULL;
+        }
+        cglinfo->context = NULL;
+    }
+
+    free(cglinfo);
+}*/
+
+#pragma mark -
+#pragma mark "--- MetalGraphicsConfig methods ---"
+
+/*#ifdef REMOTELAYER
+mach_port_t JRSRemotePort;
+int remoteSocketFD = -1;
+
+static void *JRSRemoteThreadFn(void *data) {
+    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+
+    // Negotiate a unix domain socket to communicate the
+    // out of band data: to read the mach port server name, and
+    // subsequently write out the layer ID.
+    static char* sock_path = "/tmp/JRSRemoteDemoSocket";
+    struct sockaddr_un address;
+    int  socket_fd, nbytes;
+    int BUFLEN = 256;
+    char buffer[BUFLEN];
+
+    remoteSocketFD = socket(PF_LOCAL, SOCK_STREAM, 0);
+    if (remoteSocketFD < 0) {
+        NSLog(@"socket() failed");
+        return NULL;
+    }
+    memset(&address, 0, sizeof(struct sockaddr_un));
+    address.sun_family = AF_UNIX;
+    memcpy(address.sun_path, sock_path, strlen(sock_path)+1);
+    int tries=0, status=-1;
+    while (status !=0 && tries<600) {
+        status = connect(remoteSocketFD, (struct sockaddr *) &address,
+                         sizeof(struct sockaddr_un));
+        if (status != 0) {
+            tries++;
+            NSLog(@"connection attempt %d failed.", tries);
+            usleep(5000000);
+        }
+    }
+    if (status != 0) {
+        NSLog(@"failed to connect");
+        return NULL;
+    }
+    nbytes = read(remoteSocketFD, buffer, BUFLEN);
+    NSString* serverString = [[NSString alloc] initWithUTF8String:buffer];
+    CFRetain(serverString);
+    NSLog(@"Read server name %@", serverString);
+    JRSRemotePort = [JRSRenderServer recieveRenderServer:serverString];
+    NSLog(@"Read server port %d", JRSRemotePort);
+
+    [pool drain];
+    return NULL;
+}
+
+void sendLayerID(int layerID) {
+    if (JRSRemotePort == 0 || remoteSocketFD < 0) {
+        NSLog(@"No connection to send ID");
+        return;
+    }
+    int BUFLEN = 256;
+    char buffer[BUFLEN];
+    snprintf(buffer, BUFLEN, "%d", layerID);
+    write(remoteSocketFD, buffer, BUFLEN);
+}
+#endif*/  /* REMOTELAYER */
+
+/**
+ * This is a globally shared context used when creating textures.  When any
+ * new contexts are created, they specify this context as the "share list"
+ * context, which means any texture objects created when this shared context
+ * is current will be available to any other context in any other thread.
+ */
+//NSOpenGLContext *sharedContext = NULL;
+//NSOpenGLPixelFormat *sharedPixelFormat = NULL;
+
+/**
+ * Attempts to initialize CGL and the core OpenGL library.
+ */
+/*JNIEXPORT jboolean JNICALL
+Java_sun_java2d_opengl_CGLGraphicsConfig_initCGL
+    (JNIEnv *env, jclass cglgc)
+{
+    J2dRlsTraceLn(J2D_TRACE_INFO, "CGLGraphicsConfig_initCGL");
+
+    if (!OGLFuncs_OpenLibrary()) {
+        return JNI_FALSE;
+    }
+
+    if (!OGLFuncs_InitPlatformFuncs() ||
+        !OGLFuncs_InitBaseFuncs() ||
+        !OGLFuncs_InitExtFuncs())
+    {
+        OGLFuncs_CloseLibrary();
+        return JNI_FALSE;
+    }
+#ifdef REMOTELAYER
+    pthread_t jrsRemoteThread;
+    pthread_create(&jrsRemoteThread, NULL, JRSRemoteThreadFn, NULL);
+#endif
+    return JNI_TRUE;
+}*/
+
+
+/**
+ * Determines whether the CGL pipeline can be used for a given GraphicsConfig
+ * provided its screen number and visual ID.  If the minimum requirements are
+ * met, the native CGLGraphicsConfigInfo structure is initialized for this
+ * GraphicsConfig with the necessary information (pixel format, etc.)
+ * and a pointer to this structure is returned as a jlong.  If
+ * initialization fails at any point, zero is returned, indicating that CGL
+ * cannot be used for this GraphicsConfig (we should fallback on an existing
+ * 2D pipeline).
+ */
+JNIEXPORT jlong JNICALL
+Java_sun_java2d_metal_MetalGraphicsConfig_getMetalConfigInfo
+    (JNIEnv *env, jclass metalgc,
+     jint displayID, jint pixfmt)
+{
+    //fprintf(stdout, "Jay : MetalGraphicsConfig_getMetalConfigInfo\n");fflush(stdout);
+  jlong ret = 0L;
+  JNF_COCOA_ENTER(env);
+  NSMutableArray * retArray = [NSMutableArray arrayWithCapacity:2];
+  [retArray addObject: [NSNumber numberWithInt: (int)displayID]];
+  [retArray addObject: [NSNumber numberWithInt: (int)pixfmt]];
+  //if ([NSThread isMainThread]) {
+      //[GraphicsConfigUtil _getCGLConfigInfo: retArray];
+  //} else {
+      [MetalGraphicsConfigUtil performSelectorOnMainThread: @selector(_getMetalConfigInfo:) withObject: retArray waitUntilDone: YES];
+  //}
+  NSNumber * num = (NSNumber *)[retArray objectAtIndex: 0];
+  ret = (jlong)[num longValue];
+  JNF_COCOA_EXIT(env);
+  return ret;
+}
+
+@implementation MetalGraphicsConfigUtil
++ (void) _getMetalConfigInfo: (NSMutableArray *)argValue {
+    AWT_ASSERT_APPKIT_THREAD;
+
+    //fprintf(stdout, "Jay : MetalGraphicsConfig_MetalGraphicsConfigUtil\n");fflush(stdout);
+    jint displayID = (jint)[(NSNumber *)[argValue objectAtIndex: 0] intValue];
+    jint pixfmt = (jint)[(NSNumber *)[argValue objectAtIndex: 1] intValue];
+    JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
+    [argValue removeAllObjects];
+
+    //J2dRlsTraceLn(J2D_TRACE_INFO, "MetalGraphicsConfig_getMetalConfigInfo");
+
+    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+    /*CGOpenGLDisplayMask glMask = (CGOpenGLDisplayMask)pixfmt;
+    if (sharedContext == NULL) {
+        if (glMask == 0) {
+            glMask = CGDisplayIDToOpenGLDisplayMask(displayID);
+        }
+
+        NSOpenGLPixelFormatAttribute attrs[] = {
+            NSOpenGLPFAAllowOfflineRenderers,
+            NSOpenGLPFAClosestPolicy,
+            NSOpenGLPFAWindow,
+            NSOpenGLPFAPixelBuffer,
+            NSOpenGLPFADoubleBuffer,
+            NSOpenGLPFAColorSize, 32,
+            NSOpenGLPFAAlphaSize, 8,
+            NSOpenGLPFADepthSize, 16,
+            NSOpenGLPFAScreenMask, glMask,
+            0
+        };
+
+        sharedPixelFormat =
+            [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
+        if (sharedPixelFormat == nil) {
+            J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGraphicsConfig_getCGLConfigInfo: shared NSOpenGLPixelFormat is NULL");
+            [argValue addObject: [NSNumber numberWithLong: 0L]];
+            return;
+        }
+
+        sharedContext =
+            [[NSOpenGLContext alloc]
+                initWithFormat:sharedPixelFormat
+                shareContext: NULL];
+        if (sharedContext == nil) {
+            J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGraphicsConfig_getCGLConfigInfo: shared NSOpenGLContext is NULL");
+            [argValue addObject: [NSNumber numberWithLong: 0L]];
+            return;
+        }
+    }*/
+    id<MTLDevice> device = MTLCreateSystemDefaultDevice();
+    
+    id<MTLCommandQueue> commandQueue = [device newCommandQueue];
+    
+    // Jay : Looks like no need to create MetaLayer here and we were creating
+    // scratch surface only to make OGL context current. So no need to create any layer for
+    // Metal. Just create device and commandQueue for Metal.
+    //defaultLibrary = [device newDefaultLibrary];
+    /*CAMetalLayer *metalLayer = [CAMetalLayer layer];
+    metalLayer.device = device;
+    metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;*/
+    
+#if USE_NSVIEW_FOR_SCRATCH
+    /*NSRect contentRect = NSMakeRect(0, 0, 64, 64);
+    NSWindow *window =
+        [[NSWindow alloc]
+            initWithContentRect: contentRect
+            styleMask: NSBorderlessWindowMask
+            backing: NSBackingStoreBuffered
+            defer: false];
+    if (window == nil) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "MetalGraphicsConfig_getMetalConfigInfo: NSWindow is NULL");
+        [argValue addObject: [NSNumber numberWithLong: 0L]];
+        return;
+    }
+
+    NSView *scratchSurface =
+        [[NSView alloc]
+            initWithFrame: contentRect];
+    if (scratchSurface == nil) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "MetalGraphicsConfig_getMetalConfigInfo: NSView is NULL");
+        [argValue addObject: [NSNumber numberWithLong: 0L]];
+        return;
+    }
+    [window setContentView: scratchSurface];*/
+#else
+    /*NSOpenGLPixelBuffer *scratchSurface =
+        [[NSOpenGLPixelBuffer alloc]
+            initWithTextureTarget:GL_TEXTURE_2D
+            textureInternalFormat:GL_RGB
+            textureMaxMipMapLevel:0
+            pixelsWide:64
+            pixelsHigh:64];*/
+#endif
+
+    /*NSOpenGLContext *context =
+        [[NSOpenGLContext alloc]
+            initWithFormat: sharedPixelFormat
+            shareContext: sharedContext];
+    if (context == nil) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGraphicsConfig_getCGLConfigInfo: NSOpenGLContext is NULL");
+        [argValue addObject: [NSNumber numberWithLong: 0L]];
+        return;
+    }
+
+    GLint contextVirtualScreen = [context currentVirtualScreen];*/
+#if USE_NSVIEW_FOR_SCRATCH
+    //[context setView: scratchSurface];
+    // Jay : no need of scratch layer for metal
+    //metalLayer.frame = scratchSurface.layer.frame;
+    //[scratchSurface.layer addSublayer: metalLayer];
+#else
+    /*[context
+        setPixelBuffer: scratchSurface
+        cubeMapFace:0
+        mipMapLevel:0
+        currentVirtualScreen: contextVirtualScreen];*/
+#endif
+    /*[context makeCurrentContext];
+
+    // get version and extension strings
+    const unsigned char *versionstr = j2d_glGetString(GL_VERSION);
+    if (!OGLContext_IsVersionSupported(versionstr)) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGraphicsConfig_getCGLConfigInfo: OpenGL 1.2 is required");
+        [NSOpenGLContext clearCurrentContext];
+        [argValue addObject: [NSNumber numberWithLong: 0L]];
+        return;
+    }
+    J2dRlsTraceLn1(J2D_TRACE_INFO, "CGLGraphicsConfig_getCGLConfigInfo: OpenGL version=%s", versionstr);
+
+    jint caps = CAPS_EMPTY;
+    OGLContext_GetExtensionInfo(env, &caps);
+
+    GLint value = 0;
+    [sharedPixelFormat
+        getValues: &value
+        forAttribute: NSOpenGLPFADoubleBuffer
+        forVirtualScreen: contextVirtualScreen];
+    if (value != 0) {
+        caps |= CAPS_DOUBLEBUFFERED;
+    }
+
+    J2dRlsTraceLn1(J2D_TRACE_INFO,
+                   "CGLGraphicsConfig_getCGLConfigInfo: db=%d",
+                   (caps & CAPS_DOUBLEBUFFERED) != 0);*/
+
+    // remove before shipping (?)
+#if 1
+    /*[sharedPixelFormat
+        getValues: &value
+        forAttribute: NSOpenGLPFAAccelerated
+        forVirtualScreen: contextVirtualScreen];
+    if (value == 0) {
+        [sharedPixelFormat
+            getValues: &value
+            forAttribute: NSOpenGLPFARendererID
+            forVirtualScreen: contextVirtualScreen];
+        fprintf(stderr, "WARNING: GL pipe is running in software mode (Renderer ID=0x%x)\n", (int)value);
+    }*/
+#endif
+
+    // 0: the buffers are swapped with no regard to the vertical refresh rate
+    // 1: the buffers are swapped only during the vertical retrace
+    /*GLint params = swapInterval;
+    [context setValues: &params forParameter: NSOpenGLCPSwapInterval];
+
+    CGLCtxInfo *ctxinfo = (CGLCtxInfo *)malloc(sizeof(CGLCtxInfo));
+    if (ctxinfo == NULL) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGC_InitOGLContext: could not allocate memory for ctxinfo");
+        [NSOpenGLContext clearCurrentContext];
+        [argValue addObject: [NSNumber numberWithLong: 0L]];
+        return;
+    }
+    memset(ctxinfo, 0, sizeof(CGLCtxInfo));
+    ctxinfo->context = context;
+    ctxinfo->scratchSurface = scratchSurface;
+
+    OGLContext *oglc = (OGLContext *)malloc(sizeof(OGLContext));
+    if (oglc == 0L) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGC_InitOGLContext: could not allocate memory for oglc");
+        [NSOpenGLContext clearCurrentContext];
+        free(ctxinfo);
+        [argValue addObject: [NSNumber numberWithLong: 0L]];
+        return;
+    }
+    memset(oglc, 0, sizeof(OGLContext));
+    oglc->ctxInfo = ctxinfo;
+    oglc->caps = caps;*/
+
+    // create the CGLGraphicsConfigInfo record for this config
+    MetalGraphicsConfigInfo *metalinfo = (MetalGraphicsConfigInfo *)malloc(sizeof(MetalGraphicsConfigInfo));
+    if (metalinfo == NULL) {
+        //J2dRlsTraceLn(J2D_TRACE_ERROR, "MetalGraphicsConfig_getMetalConfigInfo: could not allocate memory for cglinfo");
+        //[NSOpenGLContext clearCurrentContext];
+        //free(oglc);
+        //free(ctxinfo);
+        //[argValue addObject: [NSNumber numberWithLong: 0L]];
+        return;
+    }
+    memset(metalinfo, 0, sizeof(MetalGraphicsConfigInfo));
+    metalinfo->screen = displayID;
+    metalinfo->device = device;
+    metalinfo->commandQueue = commandQueue;
+
+    //[NSOpenGLContext clearCurrentContext];
+    [argValue addObject: [NSNumber numberWithLong:ptr_to_jlong(metalinfo)]];
+    [pool drain];
+}
+@end //GraphicsConfigUtil
+
+/*JNIEXPORT jint JNICALL
+Java_sun_java2d_opengl_CGLGraphicsConfig_getOGLCapabilities
+    (JNIEnv *env, jclass cglgc, jlong configInfo)
+{
+    J2dTraceLn(J2D_TRACE_INFO, "CGLGraphicsConfig_getOGLCapabilities");
+
+    CGLGraphicsConfigInfo *cglinfo =
+        (CGLGraphicsConfigInfo *)jlong_to_ptr(configInfo);
+    if ((cglinfo == NULL) || (cglinfo->context == NULL)) {
+        return CAPS_EMPTY;
+    } else {
+        return cglinfo->context->caps;
+    }
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_java2d_opengl_CGLGraphicsConfig_nativeGetMaxTextureSize
+    (JNIEnv *env, jclass cglgc)
+{
+    J2dTraceLn(J2D_TRACE_INFO, "CGLGraphicsConfig_nativeGetMaxTextureSize");
+
+    __block int max = 0;
+
+    [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
+        [sharedContext makeCurrentContext];
+        j2d_glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max);
+        [NSOpenGLContext clearCurrentContext];
+    }];
+
+    return (jint)max;
+}*/