src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLGraphicsConfig.m
changeset 47216 71c04702a3d5
parent 33513 1804980c8ed7
child 54873 442e683e65fa
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 2011, 2015, 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 #pragma mark -
       
    38 #pragma mark "--- Mac OS X specific methods for GL 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 "--- CGLGraphicsConfig 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_opengl_CGLGraphicsConfig_getCGLConfigInfo
       
   193     (JNIEnv *env, jclass cglgc,
       
   194      jint displayID, jint pixfmt, jint swapInterval)
       
   195 {
       
   196   jlong ret = 0L;
       
   197   JNF_COCOA_ENTER(env);
       
   198   NSMutableArray * retArray = [NSMutableArray arrayWithCapacity:3];
       
   199   [retArray addObject: [NSNumber numberWithInt: (int)displayID]];
       
   200   [retArray addObject: [NSNumber numberWithInt: (int)pixfmt]];
       
   201   [retArray addObject: [NSNumber numberWithInt: (int)swapInterval]];
       
   202   if ([NSThread isMainThread]) {
       
   203       [GraphicsConfigUtil _getCGLConfigInfo: retArray];
       
   204   } else {
       
   205       [GraphicsConfigUtil performSelectorOnMainThread: @selector(_getCGLConfigInfo:) 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 
       
   214 
       
   215 @implementation GraphicsConfigUtil
       
   216 + (void) _getCGLConfigInfo: (NSMutableArray *)argValue {
       
   217     AWT_ASSERT_APPKIT_THREAD;
       
   218 
       
   219     jint displayID = (jint)[(NSNumber *)[argValue objectAtIndex: 0] intValue];
       
   220     jint pixfmt = (jint)[(NSNumber *)[argValue objectAtIndex: 1] intValue];
       
   221     jint swapInterval = (jint)[(NSNumber *)[argValue objectAtIndex: 2] intValue];
       
   222     JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
       
   223     [argValue removeAllObjects];
       
   224 
       
   225     J2dRlsTraceLn(J2D_TRACE_INFO, "CGLGraphicsConfig_getCGLConfigInfo");
       
   226 
       
   227     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
       
   228 
       
   229     CGOpenGLDisplayMask glMask = (CGOpenGLDisplayMask)pixfmt;
       
   230     if (sharedContext == NULL) {
       
   231         if (glMask == 0) {
       
   232             glMask = CGDisplayIDToOpenGLDisplayMask(displayID);
       
   233         }
       
   234 
       
   235         NSOpenGLPixelFormatAttribute attrs[] = {
       
   236             NSOpenGLPFAAllowOfflineRenderers,
       
   237             NSOpenGLPFAClosestPolicy,
       
   238             NSOpenGLPFAWindow,
       
   239             NSOpenGLPFAPixelBuffer,
       
   240             NSOpenGLPFADoubleBuffer,
       
   241             NSOpenGLPFAColorSize, 32,
       
   242             NSOpenGLPFAAlphaSize, 8,
       
   243             NSOpenGLPFADepthSize, 16,
       
   244             NSOpenGLPFAScreenMask, glMask,
       
   245             0
       
   246         };
       
   247 
       
   248         sharedPixelFormat =
       
   249             [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
       
   250         if (sharedPixelFormat == nil) {
       
   251             J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGraphicsConfig_getCGLConfigInfo: shared NSOpenGLPixelFormat is NULL");
       
   252             [argValue addObject: [NSNumber numberWithLong: 0L]];
       
   253             return;
       
   254         }
       
   255 
       
   256         sharedContext =
       
   257             [[NSOpenGLContext alloc]
       
   258                 initWithFormat:sharedPixelFormat
       
   259                 shareContext: NULL];
       
   260         if (sharedContext == nil) {
       
   261             J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGraphicsConfig_getCGLConfigInfo: shared NSOpenGLContext is NULL");
       
   262             [argValue addObject: [NSNumber numberWithLong: 0L]];
       
   263             return;
       
   264         }
       
   265     }
       
   266 
       
   267 #if USE_NSVIEW_FOR_SCRATCH
       
   268     NSRect contentRect = NSMakeRect(0, 0, 64, 64);
       
   269     NSWindow *window =
       
   270         [[NSWindow alloc]
       
   271             initWithContentRect: contentRect
       
   272             styleMask: NSBorderlessWindowMask
       
   273             backing: NSBackingStoreBuffered
       
   274             defer: false];
       
   275     if (window == nil) {
       
   276         J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGraphicsConfig_getCGLConfigInfo: NSWindow is NULL");
       
   277         [argValue addObject: [NSNumber numberWithLong: 0L]];
       
   278         return;
       
   279     }
       
   280 
       
   281     NSView *scratchSurface =
       
   282         [[NSView alloc]
       
   283             initWithFrame: contentRect];
       
   284     if (scratchSurface == nil) {
       
   285         J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGraphicsConfig_getCGLConfigInfo: NSView is NULL");
       
   286         [argValue addObject: [NSNumber numberWithLong: 0L]];
       
   287         return;
       
   288     }
       
   289     [window setContentView: scratchSurface];
       
   290 #else
       
   291     NSOpenGLPixelBuffer *scratchSurface =
       
   292         [[NSOpenGLPixelBuffer alloc]
       
   293             initWithTextureTarget:GL_TEXTURE_2D
       
   294             textureInternalFormat:GL_RGB
       
   295             textureMaxMipMapLevel:0
       
   296             pixelsWide:64
       
   297             pixelsHigh:64];
       
   298 #endif
       
   299 
       
   300     NSOpenGLContext *context =
       
   301         [[NSOpenGLContext alloc]
       
   302             initWithFormat: sharedPixelFormat
       
   303             shareContext: sharedContext];
       
   304     if (context == nil) {
       
   305         J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGraphicsConfig_getCGLConfigInfo: NSOpenGLContext is NULL");
       
   306         [argValue addObject: [NSNumber numberWithLong: 0L]];
       
   307         return;
       
   308     }
       
   309 
       
   310     GLint contextVirtualScreen = [context currentVirtualScreen];
       
   311 #if USE_NSVIEW_FOR_SCRATCH
       
   312     [context setView: scratchSurface];
       
   313 #else
       
   314     [context
       
   315         setPixelBuffer: scratchSurface
       
   316         cubeMapFace:0
       
   317         mipMapLevel:0
       
   318         currentVirtualScreen: contextVirtualScreen];
       
   319 #endif
       
   320     [context makeCurrentContext];
       
   321 
       
   322     // get version and extension strings
       
   323     const unsigned char *versionstr = j2d_glGetString(GL_VERSION);
       
   324     if (!OGLContext_IsVersionSupported(versionstr)) {
       
   325         J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGraphicsConfig_getCGLConfigInfo: OpenGL 1.2 is required");
       
   326         [NSOpenGLContext clearCurrentContext];
       
   327         [argValue addObject: [NSNumber numberWithLong: 0L]];
       
   328         return;
       
   329     }
       
   330     J2dRlsTraceLn1(J2D_TRACE_INFO, "CGLGraphicsConfig_getCGLConfigInfo: OpenGL version=%s", versionstr);
       
   331 
       
   332     jint caps = CAPS_EMPTY;
       
   333     OGLContext_GetExtensionInfo(env, &caps);
       
   334 
       
   335     GLint value = 0;
       
   336     [sharedPixelFormat
       
   337         getValues: &value
       
   338         forAttribute: NSOpenGLPFADoubleBuffer
       
   339         forVirtualScreen: contextVirtualScreen];
       
   340     if (value != 0) {
       
   341         caps |= CAPS_DOUBLEBUFFERED;
       
   342     }
       
   343 
       
   344     J2dRlsTraceLn1(J2D_TRACE_INFO,
       
   345                    "CGLGraphicsConfig_getCGLConfigInfo: db=%d",
       
   346                    (caps & CAPS_DOUBLEBUFFERED) != 0);
       
   347 
       
   348     // remove before shipping (?)
       
   349 #if 1
       
   350     [sharedPixelFormat
       
   351         getValues: &value
       
   352         forAttribute: NSOpenGLPFAAccelerated
       
   353         forVirtualScreen: contextVirtualScreen];
       
   354     if (value == 0) {
       
   355         [sharedPixelFormat
       
   356             getValues: &value
       
   357             forAttribute: NSOpenGLPFARendererID
       
   358             forVirtualScreen: contextVirtualScreen];
       
   359         fprintf(stderr, "WARNING: GL pipe is running in software mode (Renderer ID=0x%x)\n", (int)value);
       
   360     }
       
   361 #endif
       
   362 
       
   363     // 0: the buffers are swapped with no regard to the vertical refresh rate
       
   364     // 1: the buffers are swapped only during the vertical retrace
       
   365     GLint params = swapInterval;
       
   366     [context setValues: &params forParameter: NSOpenGLCPSwapInterval];
       
   367 
       
   368     CGLCtxInfo *ctxinfo = (CGLCtxInfo *)malloc(sizeof(CGLCtxInfo));
       
   369     if (ctxinfo == NULL) {
       
   370         J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGC_InitOGLContext: could not allocate memory for ctxinfo");
       
   371         [NSOpenGLContext clearCurrentContext];
       
   372         [argValue addObject: [NSNumber numberWithLong: 0L]];
       
   373         return;
       
   374     }
       
   375     memset(ctxinfo, 0, sizeof(CGLCtxInfo));
       
   376     ctxinfo->context = context;
       
   377     ctxinfo->scratchSurface = scratchSurface;
       
   378 
       
   379     OGLContext *oglc = (OGLContext *)malloc(sizeof(OGLContext));
       
   380     if (oglc == 0L) {
       
   381         J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGC_InitOGLContext: could not allocate memory for oglc");
       
   382         [NSOpenGLContext clearCurrentContext];
       
   383         free(ctxinfo);
       
   384         [argValue addObject: [NSNumber numberWithLong: 0L]];
       
   385         return;
       
   386     }
       
   387     memset(oglc, 0, sizeof(OGLContext));
       
   388     oglc->ctxInfo = ctxinfo;
       
   389     oglc->caps = caps;
       
   390 
       
   391     // create the CGLGraphicsConfigInfo record for this config
       
   392     CGLGraphicsConfigInfo *cglinfo = (CGLGraphicsConfigInfo *)malloc(sizeof(CGLGraphicsConfigInfo));
       
   393     if (cglinfo == NULL) {
       
   394         J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGraphicsConfig_getCGLConfigInfo: could not allocate memory for cglinfo");
       
   395         [NSOpenGLContext clearCurrentContext];
       
   396         free(oglc);
       
   397         free(ctxinfo);
       
   398         [argValue addObject: [NSNumber numberWithLong: 0L]];
       
   399         return;
       
   400     }
       
   401     memset(cglinfo, 0, sizeof(CGLGraphicsConfigInfo));
       
   402     cglinfo->screen = displayID;
       
   403     cglinfo->pixfmt = sharedPixelFormat;
       
   404     cglinfo->context = oglc;
       
   405 
       
   406     [NSOpenGLContext clearCurrentContext];
       
   407     [argValue addObject: [NSNumber numberWithLong:ptr_to_jlong(cglinfo)]];
       
   408     [pool drain];
       
   409 }
       
   410 @end //GraphicsConfigUtil
       
   411 
       
   412 JNIEXPORT jint JNICALL
       
   413 Java_sun_java2d_opengl_CGLGraphicsConfig_getOGLCapabilities
       
   414     (JNIEnv *env, jclass cglgc, jlong configInfo)
       
   415 {
       
   416     J2dTraceLn(J2D_TRACE_INFO, "CGLGraphicsConfig_getOGLCapabilities");
       
   417 
       
   418     CGLGraphicsConfigInfo *cglinfo =
       
   419         (CGLGraphicsConfigInfo *)jlong_to_ptr(configInfo);
       
   420     if ((cglinfo == NULL) || (cglinfo->context == NULL)) {
       
   421         return CAPS_EMPTY;
       
   422     } else {
       
   423         return cglinfo->context->caps;
       
   424     }
       
   425 }
       
   426 
       
   427 JNIEXPORT jint JNICALL
       
   428 Java_sun_java2d_opengl_CGLGraphicsConfig_nativeGetMaxTextureSize
       
   429     (JNIEnv *env, jclass cglgc)
       
   430 {
       
   431     J2dTraceLn(J2D_TRACE_INFO, "CGLGraphicsConfig_nativeGetMaxTextureSize");
       
   432 
       
   433     __block int max = 0;
       
   434 
       
   435     [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
       
   436         [sharedContext makeCurrentContext];
       
   437         j2d_glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max);
       
   438         [NSOpenGLContext clearCurrentContext];
       
   439     }];
       
   440 
       
   441     return (jint)max;
       
   442 }