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 #ifndef HEADLESS 27 28 #include <stdlib.h> 29 #include <string.h> 30 31 #include "sun_java2d_SunGraphics2D.h" 32 33 #include "jlong.h" 34 #include "jni_util.h" 35 #import "MTLContext.h" 36 #include "MTLRenderQueue.h" 37 #include "MTLSurfaceDataBase.h" 38 #include "GraphicsPrimitiveMgr.h" 39 #include "Region.h" 40 #include "common.h" 41 42 #include "jvm.h" 43 44 extern jboolean MTLSD_InitMTLWindow(JNIEnv *env, MTLSDOps *mtlsdo); 45 extern MTLContext *MTLSD_MakeMTLContextCurrent(JNIEnv *env, 46 MTLSDOps *srcOps, 47 MTLSDOps *dstOps); 48 49 #define RGBA_TO_V4(c) \ 50 { \ 51 (((c) >> 16) & (0xFF))/255.0f, \ 52 (((c) >> 8) & 0xFF)/255.0f, \ 53 ((c) & 0xFF)/255.0f, \ 54 (((c) >> 24) & 0xFF)/255.0f \ 55 } 56 57 /** 58 * This table contains the standard blending rules (or Porter-Duff compositing 59 * factors) used in glBlendFunc(), indexed by the rule constants from the 60 * AlphaComposite class. 61 */ 62 MTLBlendRule MTStdBlendRules[] = { 63 }; 64 65 static struct TxtVertex verts[PGRAM_VERTEX_COUNT] = { 66 {{-1.0, 1.0, 0.0}, {0.0, 0.0}}, 67 {{1.0, 1.0, 0.0}, {1.0, 0.0}}, 68 {{1.0, -1.0, 0.0}, {1.0, 1.0}}, 69 {{1.0, -1.0, 0.0}, {1.0, 1.0}}, 70 {{-1.0, -1.0, 0.0}, {0.0, 1.0}}, 71 {{-1.0, 1.0, 0.0}, {0.0, 0.0}} 72 }; 73 74 75 static void _traceMatrix(simd_float4x4 * mtx) { 76 for (int row = 0; row < 4; ++row) { 77 J2dTraceLn4(J2D_TRACE_VERBOSE, " [%lf %lf %lf %lf]", 78 mtx->columns[0][row], mtx->columns[1][row], mtx->columns[2][row], mtx->columns[3][row]); 79 } 80 } 81 82 MTLRenderPassDescriptor* createRenderPassDesc(id<MTLTexture> dest) { 83 MTLRenderPassDescriptor * result = [MTLRenderPassDescriptor renderPassDescriptor]; 84 if (result == nil) 85 return nil; 86 87 if (dest == nil) { 88 J2dTraceLn(J2D_TRACE_ERROR, "_createRenderPassDesc: destination texture is null"); 89 return nil; 90 } 91 92 MTLRenderPassColorAttachmentDescriptor * ca = result.colorAttachments[0]; 93 ca.texture = dest; 94 ca.loadAction = MTLLoadActionLoad; 95 ca.clearColor = MTLClearColorMake(0.0f, 0.9f, 0.0f, 1.0f); 96 ca.storeAction = MTLStoreActionStore; 97 return result; 98 } 99 100 @implementation MTLContext { 101 id<MTLCommandBuffer> _commandBuffer; 102 } 103 104 @synthesize compState, extraAlpha, alphaCompositeRule, xorPixel, pixel, p0, 105 p1, p3, cyclic, pixel1, pixel2, r, g, b, a, paintState, useMask, 106 useTransform, transform4x4, blitTextureID, textureFunction, 107 vertexCacheEnabled, device, library, pipelineState, pipelineStateStorage, 108 commandQueue, vertexBuffer, 109 color, clipRect, useClip, texturePool; 110 111 112 - (id<MTLCommandBuffer>) commandBuffer { 113 if (_commandBuffer == nil) { 114 // NOTE: Command queues are thread-safe and allow multiple outstanding command buffers to be encoded simultaneously. 115 _commandBuffer = [[self.commandQueue commandBuffer] retain];// released in [layer blitTexture] 116 } 117 return _commandBuffer; 118 } 119 120 - (void)releaseCommandBuffer { 121 [_commandBuffer release]; 122 _commandBuffer = nil; 123 } 124 125 + (MTLContext*) setSurfacesEnv:(JNIEnv*)env src:(jlong)pSrc dst:(jlong)pDst { 126 BMTLSDOps *srcOps = (BMTLSDOps *)jlong_to_ptr(pSrc); 127 BMTLSDOps *dstOps = (BMTLSDOps *)jlong_to_ptr(pDst); 128 MTLContext *mtlc = NULL; 129 130 if (srcOps == NULL || dstOps == NULL) { 131 J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLContext_SetSurfaces: ops are null"); 132 return NULL; 133 } 134 135 J2dTraceLn6(J2D_TRACE_VERBOSE, "MTLContext_SetSurfaces: bsrc=%p (tex=%p type=%d), bdst=%p (tex=%p type=%d)", srcOps, srcOps->pTexture, srcOps->drawableType, dstOps, dstOps->pTexture, dstOps->drawableType); 136 137 if (dstOps->drawableType == MTLSD_TEXTURE) { 138 J2dRlsTraceLn(J2D_TRACE_ERROR, 139 "MTLContext_SetSurfaces: texture cannot be used as destination"); 140 return NULL; 141 } 142 143 if (dstOps->drawableType == MTLSD_UNDEFINED) { 144 // initialize the surface as an OGLSD_WINDOW 145 if (!MTLSD_InitMTLWindow(env, dstOps)) { 146 J2dRlsTraceLn(J2D_TRACE_ERROR, 147 "MTLContext_SetSurfaces: could not init OGL window"); 148 return NULL; 149 } 150 } 151 152 // make the context current 153 MTLSDOps *dstCGLOps = (MTLSDOps *)dstOps->privOps; 154 mtlc = dstCGLOps->configInfo->context; 155 156 if (mtlc == NULL) { 157 J2dRlsTraceLn(J2D_TRACE_ERROR, 158 "MTLContext_SetSurfaces: could not make context current"); 159 return NULL; 160 } 161 162 // perform additional one-time initialization, if necessary 163 if (dstOps->needsInit) { 164 if (dstOps->isOpaque) { 165 // in this case we are treating the destination as opaque, but 166 // to do so, first we need to ensure that the alpha channel 167 // is filled with fully opaque values (see 6319663) 168 //MTLContext_InitAlphaChannel(); 169 } 170 dstOps->needsInit = JNI_FALSE; 171 } 172 173 return mtlc; 174 } 175 176 - (id)initWithDevice:(id<MTLDevice>)d shadersLib:(NSString*)shadersLib { 177 self = [super init]; 178 if (self) { 179 // Initialization code here. 180 device = d; 181 182 texturePool = [[MTLTexturePool alloc] initWithDevice:device]; 183 pipelineStateStorage = [[MTLPipelineStatesStorage alloc] initWithDevice:device shaderLibPath:shadersLib]; 184 185 vertexBuffer = [device newBufferWithBytes:verts 186 length:sizeof(verts) 187 options:MTLResourceCPUCacheModeDefaultCache]; 188 189 NSError *error = nil; 190 191 library = [device newLibraryWithFile:shadersLib error:&error]; 192 if (!library) { 193 NSLog(@"Failed to load library. error %@", error); 194 exit(0); 195 } 196 197 _commandBuffer = nil; 198 199 // Create command queue 200 commandQueue = [device newCommandQueue]; 201 } 202 return self; 203 } 204 205 - (void)resetClip { 206 //TODO 207 J2dTraceNotImplPrimitive("MTLContext.resetClip"); 208 J2dTraceLn(J2D_TRACE_INFO, "MTLContext.resetClip"); 209 useClip = JNI_FALSE; 210 } 211 212 - (void)setClipRectX1:(jint)x1 Y1:(jint)y1 X2:(jint)x2 Y2:(jint)y2 { 213 //TODO 214 J2dTraceNotImplPrimitive("MTLContext.setClipRectX1:Y1:X2:Y2"); 215 jint width = x2 - x1; 216 jint height = y2 - y1; 217 218 J2dTraceLn4(J2D_TRACE_INFO, "MTLContext.setClipRect: x=%d y=%d w=%d h=%d", x1, y1, width, height); 219 220 clipRect.x = x1; 221 clipRect.y = y1; 222 clipRect.width = width; 223 clipRect.height = height; 224 useClip = JNI_TRUE; 225 } 226 227 - (void)beginShapeClip { 228 //TODO 229 J2dTraceNotImplPrimitive("MTLContext.beginShapeClip"); 230 J2dTraceLn(J2D_TRACE_INFO, "MTLContext.beginShapeClip"); 231 } 232 233 - (void)endShapeClip { 234 //TODO 235 J2dTraceNotImplPrimitive("MTLContext.endShapeClip"); 236 J2dTraceLn(J2D_TRACE_INFO, "MTLContext.endShapeClip"); 237 } 238 239 - (void)resetComposite { 240 //TODO 241 J2dTraceNotImplPrimitive("MTLContext_ResetComposite"); 242 J2dTraceLn(J2D_TRACE_INFO, "MTLContext_ResetComposite"); 243 } 244 245 - (void)setAlphaCompositeRule:(jint)rule extraAlpha:(jfloat)_extraAlpha 246 flags:(jint)flags { 247 J2dTracePrimitive("MTLContext_SetAlphaComposite"); 248 J2dTraceLn3(J2D_TRACE_INFO, "MTLContext_SetAlphaComposite: rule=%d, extraAlpha=%1.2f, flags=%d", rule, extraAlpha, flags); 249 250 extraAlpha = _extraAlpha; 251 alphaCompositeRule = rule; 252 } 253 254 255 - (void)setXorComposite:(jint)xp { 256 //TODO 257 J2dTraceNotImplPrimitive("MTLContext.setXorComposite"); 258 J2dTraceLn1(J2D_TRACE_INFO, 259 "MTLContext.setXorComposite: xorPixel=%08x", xp); 260 } 261 262 - (jboolean)isBlendingDisabled { 263 // TODO: hold case mtlc->alphaCompositeRule == RULE_SrcOver && sun_java2d_pipe_BufferedContext_SRC_IS_OPAQUE 264 return alphaCompositeRule == RULE_Src && (extraAlpha - 1.0f < 0.001f); 265 } 266 267 268 - (void)resetTransform { 269 J2dTracePrimitive("MTLContext_ResetTransform"); 270 J2dTraceLn(J2D_TRACE_INFO, "MTLContext_ResetTransform"); 271 useTransform = JNI_FALSE; 272 } 273 274 - (void)setTransformM00:(jdouble) m00 M10:(jdouble) m10 275 M01:(jdouble) m01 M11:(jdouble) m11 276 M02:(jdouble) m02 M12:(jdouble) m12 { 277 278 279 J2dTraceLn(J2D_TRACE_INFO, "MTLContext_SetTransform"); 280 281 J2dTracePrimitive("MTLContext_SetTransform"); 282 283 memset(&(transform4x4), 0, sizeof(transform4x4)); 284 transform4x4.columns[0][0] = m00; 285 transform4x4.columns[0][1] = m10; 286 transform4x4.columns[1][0] = m01; 287 transform4x4.columns[1][1] = m11; 288 transform4x4.columns[3][0] = m02; 289 transform4x4.columns[3][1] = m12; 290 transform4x4.columns[3][3] = 1.0; 291 transform4x4.columns[4][4] = 1.0; 292 useTransform = JNI_TRUE; 293 } 294 295 - (jboolean)initBlitTileTexture { 296 //TODO 297 J2dTraceNotImplPrimitive("MTLContext_InitBlitTileTexture"); 298 J2dTraceLn(J2D_TRACE_INFO, "MTLContext_InitBlitTileTexture"); 299 300 return JNI_TRUE; 301 } 302 303 - (jint)createBlitTextureFormat:(jint)internalFormat pixelFormat:(jint)pixelFormat 304 width:(jint)width height:(jint)height { 305 //TODO 306 J2dTraceNotImplPrimitive("MTLContext_CreateBlitTexture"); 307 return 0; 308 } 309 310 311 - (void)setColorR:(int)_r G:(int)_g B:(int)_b A:(int)_a { 312 color = 0; 313 color |= (_r & (0xFF)) << 16; 314 color |= (_g & (0xFF)) << 8; 315 color |= _b & (0xFF); 316 color |= (_a & (0xFF)) << 24; 317 J2dTraceLn4(J2D_TRACE_INFO, "MTLContext.setColor (%d, %d, %d) %d", r,g,b,a); 318 } 319 320 - (void)setColorInt:(int)_pixel { 321 color = _pixel; 322 J2dTraceLn5(J2D_TRACE_INFO, "MTLContext.setColorInt: pixel=%08x [r=%d g=%d b=%d a=%d]", pixel, (pixel >> 16) & (0xFF), (pixel >> 8) & 0xFF, (pixel) & 0xFF, (pixel >> 24) & 0xFF); 323 } 324 325 - (id<MTLRenderCommandEncoder>) createEncoderForDest:(id<MTLTexture>) dest { 326 id<MTLCommandBuffer> cb = self.commandBuffer; 327 if (cb == nil) 328 return nil; 329 330 MTLRenderPassDescriptor * rpd = createRenderPassDesc(dest); 331 if (rpd == nil) 332 return nil; 333 334 // J2dTraceLn1(J2D_TRACE_VERBOSE, "MTLContext: created render encoder to draw on tex=%p", dest); 335 return [cb renderCommandEncoderWithDescriptor:rpd]; 336 } 337 338 - (void) setEncoderTransform:(id<MTLRenderCommandEncoder>) encoder dest:(id<MTLTexture>) dest { 339 simd_float4x4 normalize; 340 memset(&normalize, 0, sizeof(normalize)); 341 normalize.columns[0][0] = 2/(double)dest.width; 342 normalize.columns[1][1] = -2/(double)dest.height; 343 normalize.columns[3][0] = -1.f; 344 normalize.columns[3][1] = 1.f; 345 normalize.columns[3][3] = 1.0; 346 normalize.columns[4][4] = 1.0; 347 348 if (useTransform) { 349 simd_float4x4 vertexMatrix = simd_mul(normalize, transform4x4); 350 [encoder setVertexBytes:&(vertexMatrix) length:sizeof(vertexMatrix) atIndex:MatrixBuffer]; 351 } else { 352 [encoder setVertexBytes:&(normalize) length:sizeof(normalize) atIndex:MatrixBuffer]; 353 } 354 } 355 356 - (id<MTLRenderCommandEncoder>) createRenderEncoderForDest:(id<MTLTexture>) dest { 357 id <MTLRenderCommandEncoder> mtlEncoder = [self createEncoderForDest: dest]; 358 if (useClip) 359 [mtlEncoder setScissorRect:clipRect]; 360 361 if (compState == sun_java2d_SunGraphics2D_PAINT_ALPHACOLOR) { 362 // set pipeline state 363 [mtlEncoder setRenderPipelineState:[self.pipelineStateStorage getRenderPipelineState:NO]]; 364 struct FrameUniforms uf = {RGBA_TO_V4(color)}; 365 [mtlEncoder setVertexBytes:&uf length:sizeof(uf) atIndex:FrameUniformBuffer]; 366 } else if (compState == sun_java2d_SunGraphics2D_PAINT_GRADIENT) { 367 // set viewport and pipeline state 368 //[mtlEncoder setRenderPipelineState:gradPipelineState]; 369 [mtlEncoder setRenderPipelineState:[self.pipelineStateStorage getRenderPipelineState:YES]]; 370 371 struct GradFrameUniforms uf = { 372 {p0, p1, p3}, 373 RGBA_TO_V4(pixel1), 374 RGBA_TO_V4(pixel2)}; 375 376 [mtlEncoder setFragmentBytes: &uf length:sizeof(uf) atIndex:0]; 377 } 378 [self setEncoderTransform:mtlEncoder dest:dest]; 379 return mtlEncoder; 380 } 381 382 - (id<MTLRenderCommandEncoder>)createSamplingEncoderForDest:(id<MTLTexture>)dest { 383 id <MTLRenderCommandEncoder> mtlEncoder = [self createRenderEncoderForDest:dest]; 384 [mtlEncoder setRenderPipelineState:[pipelineStateStorage getTexturePipelineState:NO compositeRule:alphaCompositeRule]]; 385 [self setEncoderTransform:mtlEncoder dest:dest]; 386 return mtlEncoder; 387 } 388 389 - (id<MTLBlitCommandEncoder>)createBlitEncoder { 390 return _commandBuffer == nil ? nil : [_commandBuffer blitCommandEncoder]; 391 } 392 393 - (void)dealloc { 394 J2dTracePrimitive("MTLContext.dealloc"); 395 J2dTraceLn(J2D_TRACE_INFO, "MTLContext.dealloc"); 396 397 self.texturePool = nil; 398 self.library = nil; 399 self.vertexBuffer = nil; 400 self.commandQueue = nil; 401 self.pipelineState = nil; 402 self.pipelineStateStorage = nil; 403 [super dealloc]; 404 } 405 406 - (void)setGradientPaintUseMask:(jboolean)_useMask cyclic:(jboolean)_cyclic p0:(jdouble) _p0 p1:(jdouble)_p1 407 p3:(jdouble)_p3 pixel1:(jint)_pixel1 pixel2:(jint)_pixel2 { 408 409 //TODO Resolve gradient distribution problem 410 //TODO Implement useMask 411 //TODO Implement cyclic 412 //fprintf(stderr, 413 // "MTLPaints_SetGradientPaint useMask=%d cyclic=%d " 414 // "p0=%f p1=%f p3=%f pix1=%d pix2=%d\n", useMask, cyclic, 415 // p0, p1, p3, pixel1, pixel2); 416 J2dTraceNotImplPrimitive("MTLContext.setGradientPaint"); 417 418 compState = sun_java2d_SunGraphics2D_PAINT_GRADIENT; 419 useMask = _useMask; 420 pixel1 = _pixel1; 421 pixel2 = _pixel2; 422 p0 = _p0; 423 p1 = _p1; 424 p3 = _p3; 425 cyclic = _cyclic; 426 } 427 428 @end 429 430 /* 431 * Class: sun_java2d_metal_MTLContext 432 * Method: getMTLIdString 433 * Signature: ()Ljava/lang/String; 434 */ 435 JNIEXPORT jstring JNICALL Java_sun_java2d_metal_MTLContext_getMTLIdString 436 (JNIEnv *env, jclass mtlcc) 437 { 438 char *vendor, *renderer, *version; 439 char *pAdapterId; 440 jobject ret = NULL; 441 int len; 442 443 return NULL; 444 } 445 446 447 448 #endif /* !HEADLESS */