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 "MetalGraphicsConfig.h" |
|
27 #import "MetalLayer.h" |
|
28 #import "shaders/MetalShaderTypes.h" |
|
29 #import "ThreadUtilities.h" |
|
30 #import "LWCToolkit.h" |
|
31 #import "MetalSurfaceData.h" |
|
32 #import "VertexDataManager.h" |
|
33 |
|
34 |
|
35 //extern NSOpenGLPixelFormat *sharedPixelFormat; |
|
36 //extern NSOpenGLContext *sharedContext; |
|
37 |
|
38 @implementation MetalLayer |
|
39 |
|
40 @synthesize javaLayer; |
|
41 @synthesize mtlTexture; |
|
42 //@synthesize target; |
|
43 @synthesize textureWidth; |
|
44 @synthesize textureHeight; |
|
45 @synthesize mtlLibrary; |
|
46 @synthesize mtlRenderPipelineDescriptor; |
|
47 @synthesize renderPipelineState; |
|
48 //@synthesize LineVertexBuffer; |
|
49 //@synthesize QuadVertexBuffer; |
|
50 #ifdef REMOTELAYER |
|
51 //@synthesize parentLayer; |
|
52 //@synthesize remoteLayer; |
|
53 //@synthesize jrsRemoteLayer; |
|
54 #endif |
|
55 |
|
56 - (id) initWithJavaLayer:(JNFWeakJObjectWrapper *)layer; |
|
57 { |
|
58 AWT_ASSERT_APPKIT_THREAD; |
|
59 // Initialize ourselves |
|
60 self = [super init]; |
|
61 if (self == nil) return self; |
|
62 |
|
63 self.javaLayer = layer; |
|
64 |
|
65 // NOTE: async=YES means that the layer is re-cached periodically |
|
66 //self.displaySyncEnabled = NO; |
|
67 self.contentsGravity = kCAGravityTopLeft; |
|
68 //Layer backed view |
|
69 //self.needsDisplayOnBoundsChange = YES; |
|
70 //self.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable; |
|
71 |
|
72 //fprintf(stdout, "MetalLayer_initWithJavaLayer\n");fflush(stdout); |
|
73 //Disable CALayer's default animation |
|
74 NSMutableDictionary * actions = [[NSMutableDictionary alloc] initWithObjectsAndKeys: |
|
75 [NSNull null], @"anchorPoint", |
|
76 [NSNull null], @"bounds", |
|
77 [NSNull null], @"contents", |
|
78 [NSNull null], @"contentsScale", |
|
79 [NSNull null], @"onOrderIn", |
|
80 [NSNull null], @"onOrderOut", |
|
81 [NSNull null], @"position", |
|
82 [NSNull null], @"sublayers", |
|
83 nil]; |
|
84 self.actions = actions; |
|
85 [actions release]; |
|
86 |
|
87 //textureID = 0; // texture will be created by rendering pipe |
|
88 mtlTexture = NULL; |
|
89 //target = 0; |
|
90 |
|
91 return self; |
|
92 } |
|
93 |
|
94 - (void) dealloc { |
|
95 self.javaLayer = nil; |
|
96 [super dealloc]; |
|
97 |
|
98 VertexDataManager_freeAllPrimitives(); |
|
99 } |
|
100 |
|
101 /* |
|
102 - (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask { |
|
103 return CGLRetainPixelFormat(sharedPixelFormat.CGLPixelFormatObj); |
|
104 } |
|
105 |
|
106 - (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat { |
|
107 CGLContextObj contextObj = NULL; |
|
108 CGLCreateContext(pixelFormat, sharedContext.CGLContextObj, &contextObj); |
|
109 return contextObj; |
|
110 }*/ |
|
111 |
|
112 // use texture (intermediate buffer) as src and blit it to the layer |
|
113 /*- (void) blitTexture |
|
114 { |
|
115 if (textureID == 0) { |
|
116 return; |
|
117 } |
|
118 |
|
119 glEnable(target); |
|
120 glBindTexture(target, textureID); |
|
121 |
|
122 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); // srccopy |
|
123 |
|
124 float swid = 1.0f, shgt = 1.0f; |
|
125 if (target == GL_TEXTURE_RECTANGLE_ARB) { |
|
126 swid = textureWidth; |
|
127 shgt = textureHeight; |
|
128 } |
|
129 glBegin(GL_QUADS); |
|
130 glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f); |
|
131 glTexCoord2f(swid, 0.0f); glVertex2f( 1.0f, -1.0f); |
|
132 glTexCoord2f(swid, shgt); glVertex2f( 1.0f, 1.0f); |
|
133 glTexCoord2f(0.0f, shgt); glVertex2f(-1.0f, 1.0f); |
|
134 glEnd(); |
|
135 |
|
136 glBindTexture(target, 0); |
|
137 glDisable(target); |
|
138 }*/ |
|
139 |
|
140 /*-(BOOL)canDrawInCGLContext:(CGLContextObj)glContext pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp{ |
|
141 return textureID == 0 ? NO : YES; |
|
142 } |
|
143 |
|
144 -(void)drawInCGLContext:(CGLContextObj)glContext pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp |
|
145 { |
|
146 AWT_ASSERT_APPKIT_THREAD; |
|
147 |
|
148 JNIEnv *env = [ThreadUtilities getJNIEnv]; |
|
149 static JNF_CLASS_CACHE(jc_JavaLayer, "sun/java2d/opengl/CGLLayer"); |
|
150 static JNF_MEMBER_CACHE(jm_drawInCGLContext, jc_JavaLayer, "drawInCGLContext", "()V"); |
|
151 |
|
152 jobject javaLayerLocalRef = [self.javaLayer jObjectWithEnv:env]; |
|
153 if ((*env)->IsSameObject(env, javaLayerLocalRef, NULL)) { |
|
154 return; |
|
155 } |
|
156 |
|
157 // Set the current context to the one given to us. |
|
158 CGLSetCurrentContext(glContext); |
|
159 |
|
160 // Should clear the whole CALayer, because it can be larger than our texture. |
|
161 glClearColor(0.0, 0.0, 0.0, 0.0); |
|
162 glClear(GL_COLOR_BUFFER_BIT); |
|
163 |
|
164 glViewport(0, 0, textureWidth, textureHeight); |
|
165 |
|
166 JNFCallVoidMethod(env, javaLayerLocalRef, jm_drawInCGLContext); |
|
167 (*env)->DeleteLocalRef(env, javaLayerLocalRef); |
|
168 |
|
169 // Call super to finalize the drawing. By default all it does is call glFlush(). |
|
170 [super drawInCGLContext:glContext pixelFormat:pixelFormat forLayerTime:timeInterval displayTime:timeStamp]; |
|
171 |
|
172 CGLSetCurrentContext(NULL); |
|
173 }*/ |
|
174 |
|
175 @end |
|
176 |
|
177 |
|
178 |
|
179 static jlong cachedLayer = 0; |
|
180 static float drawColor[4] = {0.0, 0.0, 0.0, 0.0}; |
|
181 /* |
|
182 * Class: sun_java2d_metal_MetalLayer |
|
183 * Method: nativeCreateLayer |
|
184 * Signature: ()J |
|
185 */ |
|
186 JNIEXPORT jlong JNICALL |
|
187 Java_sun_java2d_metal_MetalLayer_nativeCreateLayer |
|
188 (JNIEnv *env, jobject obj) |
|
189 { |
|
190 __block MetalLayer *layer = nil; |
|
191 |
|
192 //fprintf(stdout, "MetalLayer_nativeCreateLayer\n");fflush(stdout); |
|
193 JNF_COCOA_ENTER(env); |
|
194 |
|
195 JNFWeakJObjectWrapper *javaLayer = [JNFWeakJObjectWrapper wrapperWithJObject:obj withEnv:env]; |
|
196 |
|
197 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ |
|
198 AWT_ASSERT_APPKIT_THREAD; |
|
199 |
|
200 layer = [[MetalLayer alloc] initWithJavaLayer: javaLayer]; |
|
201 |
|
202 //cachedLayer = ptr_to_jlong(layer); |
|
203 }]; |
|
204 |
|
205 JNF_COCOA_EXIT(env); |
|
206 |
|
207 return ptr_to_jlong(layer); |
|
208 } |
|
209 |
|
210 |
|
211 |
|
212 JNIEXPORT jlong JNICALL |
|
213 Java_sun_java2d_metal_MetalLayer_nativeInitLayer |
|
214 (JNIEnv *env, jobject obj, jlong configInfo, jlong layer) |
|
215 { |
|
216 |
|
217 JNF_COCOA_ENTER(env); |
|
218 MetalGraphicsConfigInfo *pInfo = |
|
219 (MetalGraphicsConfigInfo *)jlong_to_ptr(configInfo); |
|
220 if ((pInfo == NULL)) { |
|
221 return -1; |
|
222 } |
|
223 |
|
224 MetalLayer *mtlLayer = jlong_to_ptr(layer); |
|
225 |
|
226 mtlLayer.device = pInfo->device; |
|
227 mtlLayer.pixelFormat = MTLPixelFormatBGRA8Unorm; |
|
228 |
|
229 //mtlLayer.commandQueue = pInfo->commandQueue; |
|
230 |
|
231 // ------------------------------------------------------------------------------------------------ |
|
232 // TODO : Currently we manually compile and copy the shader library to /tmp. |
|
233 // Need to complete build changes - to build it and read from some other location within jdk |
|
234 // ------------------------------------------------------------------------------------------------ |
|
235 // Load shader library |
|
236 /*NSError *error = nil; |
|
237 mtlLayer.mtlLibrary = [mtlLayer.device newLibraryWithFile: @"/tmp/BaseShader.metallib" error:&error]; |
|
238 if (!mtlLayer.mtlLibrary) { |
|
239 NSLog(@"Failed to load library. error %@", error); |
|
240 //exit(0); |
|
241 }*/ |
|
242 |
|
243 NSError* error = nil; |
|
244 NSString* content = @"#include <metal_stdlib>\n" |
|
245 "#include <simd/simd.h>\n" |
|
246 "using namespace metal;\n" |
|
247 "struct MetalVertex" |
|
248 "{" |
|
249 "vector_float4 position;" |
|
250 "vector_float4 color;" |
|
251 "};\n" |
|
252 "struct VertexOut {" |
|
253 "float4 color;" |
|
254 "float4 pos [[position]];" |
|
255 "};\n" |
|
256 "vertex VertexOut vertexShader(device MetalVertex *vertices [[buffer(0)]]," |
|
257 "constant unsigned int *viewportSize [[buffer(1)]]," |
|
258 "uint vid [[vertex_id]]) {\n" |
|
259 "VertexOut out;" |
|
260 "out.pos = vertices[vid].position;" |
|
261 "\n" |
|
262 "float halfViewWidth = (float)(viewportSize[0] >> 1);" |
|
263 "float halfViewHeight = (float)(viewportSize[1] >> 1);" |
|
264 "\n" |
|
265 "out.pos.x = (out.pos.x - halfViewWidth) / halfViewWidth;" |
|
266 "out.pos.y = (halfViewHeight - out.pos.y) / halfViewHeight;" |
|
267 "\n" |
|
268 "out.color = vertices[vid].color;" |
|
269 "\n" |
|
270 "return out;" |
|
271 "}\n" |
|
272 "fragment float4 fragmentShader(MetalVertex in [[stage_in]]) {" |
|
273 "return in.color;" |
|
274 "}"; |
|
275 |
|
276 mtlLayer.mtlLibrary = [mtlLayer.device newLibraryWithSource:content options:nil error:&error]; |
|
277 if (!mtlLayer.mtlLibrary) { |
|
278 NSLog(@"Failed to create shader library from source. error %@", error); |
|
279 //exit(0); |
|
280 } |
|
281 |
|
282 //create a vertex and fragment objects |
|
283 id<MTLFunction> vertexProgram = [mtlLayer.mtlLibrary newFunctionWithName:@"vertexShader"]; |
|
284 id<MTLFunction> fragmentProgram = [mtlLayer.mtlLibrary newFunctionWithName:@"fragmentShader"]; |
|
285 |
|
286 |
|
287 mtlLayer.mtlRenderPipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init]; |
|
288 |
|
289 [mtlLayer.mtlRenderPipelineDescriptor setVertexFunction:vertexProgram]; |
|
290 [mtlLayer.mtlRenderPipelineDescriptor setFragmentFunction:fragmentProgram]; |
|
291 |
|
292 //specify the target-texture pixel format |
|
293 mtlLayer.mtlRenderPipelineDescriptor.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm; |
|
294 |
|
295 //create the Rendering Pipeline Object |
|
296 mtlLayer.renderPipelineState = [mtlLayer.device newRenderPipelineStateWithDescriptor:mtlLayer.mtlRenderPipelineDescriptor error:nil]; |
|
297 |
|
298 VertexDataManager_init(mtlLayer.device); |
|
299 |
|
300 |
|
301 JNF_COCOA_EXIT(env); |
|
302 |
|
303 return ptr_to_jlong(layer); |
|
304 } |
|
305 |
|
306 |
|
307 |
|
308 // Must be called under the RQ lock. |
|
309 /*JNIEXPORT void JNICALL |
|
310 Java_sun_java2d_metal_MetalLayer_nativeValidate |
|
311 (JNIEnv *env, jclass cls, jlong layer, jlong view) |
|
312 { |
|
313 |
|
314 JNF_COCOA_ENTER(env); |
|
315 |
|
316 MetalLayer *mtlLayer = jlong_to_ptr(layer); |
|
317 NSView *nsView = jlong_to_ptr(view); |
|
318 |
|
319 mtlLayer.frame = nsView.bounds; |
|
320 [mtlLayer setDrawableSize: nsView.bounds.size]; |
|
321 |
|
322 mtlLayer.textureWidth = nsView.bounds.size.width; |
|
323 mtlLayer.textureHeight = nsView.bounds.size.height; |
|
324 |
|
325 NSLog(@"Validate : Width : %f", nsView.bounds.size.width); |
|
326 NSLog(@"Validate : Height : %f", nsView.bounds.size.height); |
|
327 |
|
328 JNF_COCOA_EXIT(env); |
|
329 }*/ |
|
330 |
|
331 // Must be called under the RQ lock. |
|
332 JNIEXPORT void JNICALL |
|
333 Java_sun_java2d_metal_MetalLayer_validate |
|
334 (JNIEnv *env, jclass cls, jlong layerPtr, jobject surfaceData) |
|
335 { |
|
336 MetalLayer *layer = OBJC(layerPtr); |
|
337 //fprintf(stdout, "MetalLayer_validate\n");fflush(stdout); |
|
338 if (surfaceData != NULL) { |
|
339 MetalSDOps *metalsdo = (MetalSDOps*) SurfaceData_GetOps(env, surfaceData); |
|
340 // TODO : Check whether we have to use pointer or instance variable |
|
341 //fprintf(stdout, "MetalLayer_validate replace mtlTexture\n");fflush(stdout); |
|
342 layer.mtlTexture = metalsdo->mtlTexture; |
|
343 //layer.target = GL_TEXTURE_2D; |
|
344 layer.textureWidth = metalsdo->width; |
|
345 layer.textureHeight = metalsdo->height; |
|
346 |
|
347 VertexDataManager_reset(metalsdo->configInfo->device); |
|
348 |
|
349 NSLog(@"Validate : Width : %f", layer.textureWidth); |
|
350 NSLog(@"Validate : height : %f", layer.textureHeight); |
|
351 |
|
352 } else { |
|
353 //fprintf(stdout, "MetalLayer_validate Null SD \n");fflush(stdout); |
|
354 //layer.textureID = 0; |
|
355 } |
|
356 } |
|
357 |
|
358 |
|
359 |
|
360 /* |
|
361 // Must be called on the AppKit thread and under the RQ lock. |
|
362 JNIEXPORT void JNICALL |
|
363 Java_sun_java2d_opengl_CGLLayer_blitTexture |
|
364 (JNIEnv *env, jclass cls, jlong layerPtr) |
|
365 { |
|
366 CGLLayer *layer = jlong_to_ptr(layerPtr); |
|
367 |
|
368 [layer blitTexture]; |
|
369 }*/ |
|
370 |
|
371 JNIEXPORT void JNICALL |
|
372 Java_sun_java2d_metal_MetalLayer_nativeSetScale |
|
373 (JNIEnv *env, jclass cls, jlong layerPtr, jdouble scale) |
|
374 { |
|
375 JNF_COCOA_ENTER(env); |
|
376 MetalLayer *layer = jlong_to_ptr(layerPtr); |
|
377 // We always call all setXX methods asynchronously, exception is only in |
|
378 // this method where we need to change native texture size and layer's scale |
|
379 // in one call on appkit, otherwise we'll get window's contents blinking, |
|
380 // during screen-2-screen moving. |
|
381 [ThreadUtilities performOnMainThreadWaiting:[NSThread isMainThread] block:^(){ |
|
382 layer.contentsScale = scale; |
|
383 }]; |
|
384 JNF_COCOA_EXIT(env); |
|
385 } |
|