src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalLayer.m
branchmetal-prototype-branch
changeset 57416 e153174dba06
parent 57400 978ffc56771f
child 57417 28582d575a98
equal deleted inserted replaced
57400:978ffc56771f 57416:e153174dba06
     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 }