1 /* 2 * Copyright (c) 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_MTLGraphicsConfig.h" 27 28 #import "MTLGraphicsConfig.h" 29 #import "MTLSurfaceData.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 MTLContext data). 43 */ 44 void 45 MTLGC_DestroyMTLGraphicsConfig(jlong pConfigInfo) 46 { 47 J2dTraceLn(J2D_TRACE_INFO, "MTLGC_DestroyMTLGraphicsConfig"); 48 49 MTLGraphicsConfigInfo *mtlinfo = 50 (MTLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo); 51 if (mtlinfo == NULL) { 52 J2dRlsTraceLn(J2D_TRACE_ERROR, 53 "MTLGC_DestroyMTLGraphicsConfig: info is null"); 54 return; 55 } 56 57 MTLContext *mtlc = (MTLContext*)mtlinfo->context; 58 if (mtlc != NULL) { 59 MTLContext_DestroyContextResources(mtlc); 60 mtlinfo->context = NULL; 61 } 62 free(mtlinfo); 63 } 64 65 #pragma mark - 66 #pragma mark "--- MTLGraphicsConfig methods ---" 67 68 69 /** 70 * Attempts to initialize CGL and the core OpenGL library. 71 */ 72 JNIEXPORT jboolean JNICALL 73 Java_sun_java2d_metal_MTLGraphicsConfig_initMTL 74 (JNIEnv *env, jclass cglgc) 75 { 76 J2dRlsTraceLn(J2D_TRACE_INFO, "MTLGraphicsConfig_initMTL"); 77 78 if (!MTLFuncs_OpenLibrary()) { 79 return JNI_FALSE; 80 } 81 82 if (!MTLFuncs_InitPlatformFuncs() || 83 !MTLFuncs_InitBaseFuncs() || 84 !MTLFuncs_InitExtFuncs()) 85 { 86 MTLFuncs_CloseLibrary(); 87 return JNI_FALSE; 88 } 89 90 return JNI_TRUE; 91 } 92 93 94 /** 95 * Determines whether the CGL pipeline can be used for a given GraphicsConfig 96 * provided its screen number and visual ID. If the minimum requirements are 97 * met, the native CGLGraphicsConfigInfo structure is initialized for this 98 * GraphicsConfig with the necessary information (pixel format, etc.) 99 * and a pointer to this structure is returned as a jlong. If 100 * initialization fails at any point, zero is returned, indicating that CGL 101 * cannot be used for this GraphicsConfig (we should fallback on an existing 102 * 2D pipeline). 103 */ 104 JNIEXPORT jlong JNICALL 105 Java_sun_java2d_metal_MTLGraphicsConfig_getMTLConfigInfo 106 (JNIEnv *env, jclass cglgc, jint displayID, jstring mtlShadersLib) 107 { 108 jlong ret = 0L; 109 JNF_COCOA_ENTER(env); 110 NSMutableArray * retArray = [NSMutableArray arrayWithCapacity:3]; 111 [retArray addObject: [NSNumber numberWithInt: (int)displayID]]; 112 [retArray addObject: [NSString stringWithUTF8String: JNU_GetStringPlatformChars(env, mtlShadersLib, 0)]]; 113 if ([NSThread isMainThread]) { 114 [MTLGraphicsConfigUtil _getMTLConfigInfo: retArray]; 115 } else { 116 [MTLGraphicsConfigUtil performSelectorOnMainThread: @selector(_getMTLConfigInfo:) withObject: retArray waitUntilDone: YES]; 117 } 118 NSNumber * num = (NSNumber *)[retArray objectAtIndex: 0]; 119 ret = (jlong)[num longValue]; 120 JNF_COCOA_EXIT(env); 121 return ret; 122 } 123 124 125 static struct TxtVertex verts[PGRAM_VERTEX_COUNT] = { 126 {{-1.0, 1.0, 0.0}, {0.0, 0.0}}, 127 {{1.0, 1.0, 0.0}, {1.0, 0.0}}, 128 {{1.0, -1.0, 0.0}, {1.0, 1.0}}, 129 {{1.0, -1.0, 0.0}, {1.0, 1.0}}, 130 {{-1.0, -1.0, 0.0}, {0.0, 1.0}}, 131 {{-1.0, 1.0, 0.0}, {0.0, 0.0}} 132 }; 133 134 135 @implementation MTLGraphicsConfigUtil 136 + (void) _getMTLConfigInfo: (NSMutableArray *)argValue { 137 AWT_ASSERT_APPKIT_THREAD; 138 139 jint displayID = (jint)[(NSNumber *)[argValue objectAtIndex: 0] intValue]; 140 NSString *mtlShadersLib = (NSString *)[argValue objectAtIndex: 1]; 141 JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; 142 [argValue removeAllObjects]; 143 144 J2dRlsTraceLn(J2D_TRACE_INFO, "MTLGraphicsConfig_getMTLConfigInfo"); 145 146 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 147 148 149 NSRect contentRect = NSMakeRect(0, 0, 64, 64); 150 NSWindow *window = 151 [[NSWindow alloc] 152 initWithContentRect: contentRect 153 styleMask: NSBorderlessWindowMask 154 backing: NSBackingStoreBuffered 155 defer: false]; 156 if (window == nil) { 157 J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLGraphicsConfig_getMTLConfigInfo: NSWindow is NULL"); 158 [argValue addObject: [NSNumber numberWithLong: 0L]]; 159 return; 160 } 161 162 NSView *scratchSurface = 163 [[NSView alloc] 164 initWithFrame: contentRect]; 165 if (scratchSurface == nil) { 166 J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLGraphicsConfig_getMTLConfigInfo: NSView is NULL"); 167 [argValue addObject: [NSNumber numberWithLong: 0L]]; 168 return; 169 } 170 [window setContentView: scratchSurface]; 171 172 MTLContext *mtlc = (MTLContext *)malloc(sizeof(MTLContext)); 173 if (mtlc == 0L) { 174 J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLGC_InitMTLContext: could not allocate memory for mtlc"); 175 [argValue addObject: [NSNumber numberWithLong: 0L]]; 176 return; 177 } 178 memset(mtlc, 0, sizeof(MTLContext)); 179 180 181 mtlc->mtlDevice = [CGDirectDisplayCopyCurrentMetalDevice(displayID) retain]; 182 183 mtlc->mtlVertexBuffer = [[mtlc->mtlDevice newBufferWithBytes:verts 184 length:sizeof(verts) 185 options:MTLResourceCPUCacheModeDefaultCache] retain]; 186 187 NSError *error = nil; 188 189 mtlc->mtlLibrary = [mtlc->mtlDevice newLibraryWithFile: mtlShadersLib error:&error]; 190 if (!mtlc->mtlLibrary) { 191 NSLog(@"Failed to load library. error %@", error); 192 exit(0); 193 } 194 id <MTLFunction> vertColFunc = [mtlc->mtlLibrary newFunctionWithName:@"vert_col"]; 195 id <MTLFunction> vertTxtFunc = [mtlc->mtlLibrary newFunctionWithName:@"vert_txt"]; 196 id <MTLFunction> fragColFunc = [mtlc->mtlLibrary newFunctionWithName:@"frag_col"]; 197 id <MTLFunction> fragTxtFunc = [mtlc->mtlLibrary newFunctionWithName:@"frag_txt"]; 198 199 // Create depth state. 200 MTLDepthStencilDescriptor *depthDesc = [MTLDepthStencilDescriptor new]; 201 depthDesc.depthCompareFunction = MTLCompareFunctionLess; 202 depthDesc.depthWriteEnabled = YES; 203 204 MTLVertexDescriptor *vertDesc = [MTLVertexDescriptor new]; 205 vertDesc.attributes[VertexAttributePosition].format = MTLVertexFormatFloat3; 206 vertDesc.attributes[VertexAttributePosition].offset = 0; 207 vertDesc.attributes[VertexAttributePosition].bufferIndex = MeshVertexBuffer; 208 vertDesc.layouts[MeshVertexBuffer].stride = sizeof(struct Vertex); 209 vertDesc.layouts[MeshVertexBuffer].stepRate = 1; 210 vertDesc.layouts[MeshVertexBuffer].stepFunction = MTLVertexStepFunctionPerVertex; 211 212 // Create pipeline state. 213 MTLRenderPipelineDescriptor *pipelineDesc = [MTLRenderPipelineDescriptor new]; 214 pipelineDesc.sampleCount = 1; 215 pipelineDesc.vertexFunction = vertColFunc; 216 pipelineDesc.fragmentFunction = fragColFunc; 217 pipelineDesc.vertexDescriptor = vertDesc; 218 pipelineDesc.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm; 219 mtlc->mtlPipelineState = [mtlc->mtlDevice newRenderPipelineStateWithDescriptor:pipelineDesc error:&error]; 220 if (!mtlc->mtlPipelineState) { 221 NSLog(@"Failed to create pipeline state, error %@", error); 222 exit(0); 223 } 224 225 vertDesc = [MTLVertexDescriptor new]; 226 vertDesc.attributes[VertexAttributePosition].format = MTLVertexFormatFloat3; 227 vertDesc.attributes[VertexAttributePosition].offset = 0; 228 vertDesc.attributes[VertexAttributePosition].bufferIndex = MeshVertexBuffer; 229 vertDesc.attributes[VertexAttributeTexPos].format = MTLVertexFormatFloat2; 230 vertDesc.attributes[VertexAttributeTexPos].offset = 3*sizeof(float); 231 vertDesc.attributes[VertexAttributeTexPos].bufferIndex = MeshVertexBuffer; 232 vertDesc.layouts[MeshVertexBuffer].stride = sizeof(struct TxtVertex); 233 vertDesc.layouts[MeshVertexBuffer].stepRate = 1; 234 vertDesc.layouts[MeshVertexBuffer].stepFunction = MTLVertexStepFunctionPerVertex; 235 // Create pipeline state. 236 pipelineDesc = [MTLRenderPipelineDescriptor new]; 237 pipelineDesc.sampleCount = 1; 238 pipelineDesc.vertexFunction = vertTxtFunc; 239 pipelineDesc.fragmentFunction = fragTxtFunc; 240 pipelineDesc.vertexDescriptor = vertDesc; 241 pipelineDesc.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm; 242 mtlc->mtlBlitPipelineState = [mtlc->mtlDevice newRenderPipelineStateWithDescriptor:pipelineDesc error:&error]; 243 if (!mtlc->mtlBlitPipelineState) { 244 NSLog(@"Failed to create pipeline state, error %@", error); 245 exit(0); 246 } 247 248 mtlc->mtlCommandBuffer = nil; 249 250 // Create command queue 251 mtlc->mtlCommandQueue = [mtlc->mtlDevice newCommandQueue]; 252 mtlc->mtlEmptyCommandBuffer = YES; 253 254 // create the MTLGraphicsConfigInfo record for this config 255 MTLGraphicsConfigInfo *mtlinfo = (MTLGraphicsConfigInfo *)malloc(sizeof(MTLGraphicsConfigInfo)); 256 if (mtlinfo == NULL) { 257 J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLGraphicsConfig_getMTLConfigInfo: could not allocate memory for mtlinfo"); 258 free(mtlc); 259 [argValue addObject: [NSNumber numberWithLong: 0L]]; 260 return; 261 } 262 memset(mtlinfo, 0, sizeof(MTLGraphicsConfigInfo)); 263 mtlinfo->screen = displayID; 264 mtlinfo->context = mtlc; 265 266 [argValue addObject: [NSNumber numberWithLong:ptr_to_jlong(mtlinfo)]]; 267 [pool drain]; 268 } 269 @end //GraphicsConfigUtil 270 271 272 JNIEXPORT jint JNICALL 273 Java_sun_java2d_metal_MTLGraphicsConfig_nativeGetMaxTextureSize 274 (JNIEnv *env, jclass mtlgc) 275 { 276 J2dTraceLn(J2D_TRACE_INFO, "MTLGraphicsConfig_nativeGetMaxTextureSize"); 277 278 __block int max = 0; 279 280 // [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ 281 // }]; 282 283 return (jint)max; 284 }