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 30 #include "sun_java2d_SunGraphics2D.h" 31 32 #include "jlong.h" 33 #import "MTLContext.h" 34 #include "MTLRenderQueue.h" 35 36 37 extern jboolean MTLSD_InitMTLWindow(JNIEnv *env, MTLSDOps *mtlsdo); 38 39 static struct TxtVertex verts[PGRAM_VERTEX_COUNT] = { 40 {{-1.0, 1.0}, {0.0, 0.0}}, 41 {{1.0, 1.0}, {1.0, 0.0}}, 42 {{1.0, -1.0}, {1.0, 1.0}}, 43 {{1.0, -1.0}, {1.0, 1.0}}, 44 {{-1.0, -1.0}, {0.0, 1.0}}, 45 {{-1.0, 1.0}, {0.0, 0.0}} 46 }; 47 48 @implementation MTLCommandBufferWrapper { 49 id<MTLCommandBuffer> _commandBuffer; 50 NSMutableArray * _pooledTextures; 51 } 52 53 - (id) initWithCommandBuffer:(id<MTLCommandBuffer>)cmdBuf { 54 self = [super init]; 55 if (self) { 56 _commandBuffer = [cmdBuf retain]; 57 _pooledTextures = [[NSMutableArray alloc] init]; 58 } 59 return self; 60 } 61 62 - (id<MTLCommandBuffer>) getCommandBuffer { 63 return _commandBuffer; 64 } 65 66 - (void) onComplete { // invoked from completion handler in some pooled thread 67 for (int c = 0; c < [_pooledTextures count]; ++c) 68 [[_pooledTextures objectAtIndex:c] releaseTexture]; 69 [_pooledTextures removeAllObjects]; 70 } 71 72 - (void) registerPooledTexture:(MTLPooledTextureHandle *)handle { 73 [_pooledTextures addObject:handle]; 74 } 75 76 - (void) dealloc { 77 [self onComplete]; 78 79 [self->_pooledTextures release]; 80 [self->_commandBuffer release]; 81 [super dealloc]; 82 } 83 84 @end 85 86 @implementation MTLContext { 87 MTLCommandBufferWrapper * _commandBufferWrapper; 88 89 MTLComposite * _composite; 90 MTLPaint * _paint; 91 MTLTransform * _transform; 92 MTLClip * _clip; 93 94 EncoderManager * _encoderManager; 95 } 96 97 @synthesize textureFunction, 98 vertexCacheEnabled, aaEnabled, device, library, pipelineStateStorage, 99 commandQueue, vertexBuffer, 100 texturePool; 101 102 - (id)initWithDevice:(id<MTLDevice>)d shadersLib:(NSString*)shadersLib { 103 self = [super init]; 104 if (self) { 105 // Initialization code here. 106 device = d; 107 108 texturePool = [[MTLTexturePool alloc] initWithDevice:device]; 109 pipelineStateStorage = [[MTLPipelineStatesStorage alloc] initWithDevice:device shaderLibPath:shadersLib]; 110 111 vertexBuffer = [device newBufferWithBytes:verts 112 length:sizeof(verts) 113 options:MTLResourceCPUCacheModeDefaultCache]; 114 115 NSError *error = nil; 116 117 library = [device newLibraryWithFile:shadersLib error:&error]; 118 if (!library) { 119 NSLog(@"Failed to load library. error %@", error); 120 exit(0); 121 } 122 123 _encoderManager = [[EncoderManager alloc] init]; 124 [_encoderManager setContext:self]; 125 _composite = [[MTLComposite alloc] init]; 126 _paint = [[MTLPaint alloc] init]; 127 _transform = [[MTLTransform alloc] init]; 128 _clip = [[MTLClip alloc] init]; 129 130 _commandBufferWrapper = nil; 131 132 // Create command queue 133 commandQueue = [device newCommandQueue]; 134 } 135 return self; 136 } 137 138 - (void)dealloc { 139 J2dTraceLn(J2D_TRACE_INFO, "MTLContext.dealloc"); 140 141 self.texturePool = nil; 142 self.library = nil; 143 self.vertexBuffer = nil; 144 self.commandQueue = nil; 145 self.pipelineStateStorage = nil; 146 [_encoderManager release]; 147 [_composite release]; 148 [_paint release]; 149 [_transform release]; 150 [_clip release]; 151 [super dealloc]; 152 } 153 154 - (MTLCommandBufferWrapper *) getCommandBufferWrapper { 155 if (_commandBufferWrapper == nil) { 156 J2dTraceLn(J2D_TRACE_VERBOSE, "MTLContext : commandBuffer is NULL"); 157 // NOTE: Command queues are thread-safe and allow multiple outstanding command buffers to be encoded simultaneously. 158 _commandBufferWrapper = [[MTLCommandBufferWrapper alloc] initWithCommandBuffer:[self.commandQueue commandBuffer]];// released in [layer blitTexture] 159 } 160 return _commandBufferWrapper; 161 } 162 163 - (MTLCommandBufferWrapper *) pullCommandBufferWrapper { 164 MTLCommandBufferWrapper * result = _commandBufferWrapper; 165 _commandBufferWrapper = nil; 166 return result; 167 } 168 169 + (MTLContext*) setSurfacesEnv:(JNIEnv*)env src:(jlong)pSrc dst:(jlong)pDst { 170 BMTLSDOps *srcOps = (BMTLSDOps *)jlong_to_ptr(pSrc); 171 BMTLSDOps *dstOps = (BMTLSDOps *)jlong_to_ptr(pDst); 172 MTLContext *mtlc = NULL; 173 174 if (srcOps == NULL || dstOps == NULL) { 175 J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLContext_SetSurfaces: ops are null"); 176 return NULL; 177 } 178 179 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); 180 181 if (dstOps->drawableType == MTLSD_TEXTURE) { 182 J2dRlsTraceLn(J2D_TRACE_ERROR, 183 "MTLContext_SetSurfaces: texture cannot be used as destination"); 184 return NULL; 185 } 186 187 if (dstOps->drawableType == MTLSD_UNDEFINED) { 188 // initialize the surface as an OGLSD_WINDOW 189 if (!MTLSD_InitMTLWindow(env, dstOps)) { 190 J2dRlsTraceLn(J2D_TRACE_ERROR, 191 "MTLContext_SetSurfaces: could not init OGL window"); 192 return NULL; 193 } 194 } 195 196 // make the context current 197 MTLSDOps *dstCGLOps = (MTLSDOps *)dstOps->privOps; 198 mtlc = dstCGLOps->configInfo->context; 199 200 if (mtlc == NULL) { 201 J2dRlsTraceLn(J2D_TRACE_ERROR, 202 "MTLContext_SetSurfaces: could not make context current"); 203 return NULL; 204 } 205 206 // perform additional one-time initialization, if necessary 207 if (dstOps->needsInit) { 208 if (dstOps->isOpaque) { 209 // in this case we are treating the destination as opaque, but 210 // to do so, first we need to ensure that the alpha channel 211 // is filled with fully opaque values (see 6319663) 212 //MTLContext_InitAlphaChannel(); 213 } 214 dstOps->needsInit = JNI_FALSE; 215 } 216 217 return mtlc; 218 } 219 220 - (void)resetClip { 221 J2dTraceLn(J2D_TRACE_INFO, "MTLContext.resetClip"); 222 [_clip reset]; 223 } 224 225 - (void)setClipRectX1:(jint)x1 Y1:(jint)y1 X2:(jint)x2 Y2:(jint)y2 { 226 [_clip setClipRectX1:x1 Y1:y1 X2:x2 Y2:y2]; 227 } 228 229 - (void)beginShapeClip:(BMTLSDOps *)dstOps { 230 J2dTraceLn(J2D_TRACE_INFO, "MTLContext.beginShapeClip"); 231 [_clip beginShapeClip:dstOps context:self]; 232 } 233 234 - (void)endShapeClip:(BMTLSDOps *)dstOps { 235 J2dTraceLn(J2D_TRACE_INFO, "MTLContext.endShapeClip"); 236 [_clip endShapeClip:dstOps context:self]; 237 } 238 239 - (void)resetComposite { 240 J2dTraceLn(J2D_TRACE_VERBOSE, "MTLContext_ResetComposite"); 241 [_composite reset]; 242 } 243 244 - (void)setAlphaCompositeRule:(jint)rule extraAlpha:(jfloat)extraAlpha 245 flags:(jint)flags { 246 J2dTraceLn3(J2D_TRACE_INFO, "MTLContext_SetAlphaComposite: rule=%d, extraAlpha=%1.2f, flags=%d", rule, extraAlpha, flags); 247 248 [_composite setRule:rule extraAlpha:extraAlpha]; 249 } 250 251 - (NSString*)getCompositeDescription { 252 return [_composite getDescription]; 253 } 254 255 - (NSString*)getPaintDescription { 256 return [_paint getDescription]; 257 } 258 259 - (void)setXorComposite:(jint)xp { 260 J2dTraceLn1(J2D_TRACE_INFO, "MTLContext.setXorComposite: xorPixel=%08x", xp); 261 262 [_composite setXORComposite:xp]; 263 } 264 265 - (jboolean)isBlendingDisabled:(jboolean) isSrcOpaque { 266 return [_composite isBlendingDisabled:isSrcOpaque]; 267 } 268 269 270 - (void)resetTransform { 271 J2dTraceLn(J2D_TRACE_INFO, "MTLContext_ResetTransform"); 272 [_transform resetTransform]; 273 } 274 275 - (void)setTransformM00:(jdouble) m00 M10:(jdouble) m10 276 M01:(jdouble) m01 M11:(jdouble) m11 277 M02:(jdouble) m02 M12:(jdouble) m12 { 278 J2dTraceLn(J2D_TRACE_INFO, "MTLContext_SetTransform"); 279 [_transform setTransformM00:m00 M10:m10 M01:m01 M11:m11 M02:m02 M12:m12]; 280 } 281 282 - (jboolean)initBlitTileTexture { 283 //TODO 284 J2dTraceLn(J2D_TRACE_INFO, "MTLContext_InitBlitTileTexture -- :TODO"); 285 286 return JNI_TRUE; 287 } 288 289 - (jint)createBlitTextureFormat:(jint)internalFormat pixelFormat:(jint)pixelFormat 290 width:(jint)width height:(jint)height { 291 J2dTraceLn(J2D_TRACE_INFO, "MTLContext_InitBlitTileTexture -- :TODO"); 292 293 //TODO 294 return 0; 295 } 296 297 - (void)resetPaint { 298 J2dTraceLn(J2D_TRACE_INFO, "MTLContext.resetPaint"); 299 [_paint reset]; 300 } 301 302 - (void)setColorPaint:(int)pixel { 303 J2dTraceLn5(J2D_TRACE_INFO, "MTLContext.setColorPaint: pixel=%08x [r=%d g=%d b=%d a=%d]", pixel, (pixel >> 16) & (0xFF), (pixel >> 8) & 0xFF, (pixel) & 0xFF, (pixel >> 24) & 0xFF); 304 [_paint setColor:pixel]; 305 } 306 307 - (void)setGradientPaintUseMask:(jboolean)useMask 308 cyclic:(jboolean)cyclic 309 p0:(jdouble)p0 310 p1:(jdouble)p1 311 p3:(jdouble)p3 312 pixel1:(jint)pixel1 313 pixel2:(jint) pixel2 314 { 315 J2dTraceLn(J2D_TRACE_INFO, "MTLContext.setGradientPaintUseMask"); 316 [_paint setGradientUseMask:useMask 317 cyclic:cyclic 318 p0:p0 319 p1:p1 320 p3:p3 321 pixel1:pixel1 322 pixel2:pixel2]; 323 } 324 325 - (void)setLinearGradientPaint:(jboolean)useMask 326 linear:(jboolean)linear 327 cycleMethod:(jboolean)cycleMethod 328 numStops:(jint)numStops 329 p0:(jfloat)p0 330 p1:(jfloat)p1 331 p3:(jfloat)p3 332 fractions:(void *)fractions 333 pixels:(void *)pixels 334 { 335 J2dTraceLn(J2D_TRACE_INFO, "MTLContext.setLinearGradientPaint"); 336 [_paint setLinearGradient:useMask 337 linear:linear 338 cycleMethod:cycleMethod 339 numStops:numStops 340 p0:p0 341 p1:p1 342 p3:p3 343 fractions:fractions 344 pixels:pixels]; 345 } 346 347 - (void)setRadialGradientPaint:(jboolean)useMask 348 linear:(jboolean)linear 349 cycleMethod:(jboolean)cycleMethod 350 numStops:(jint)numStops 351 m00:(jfloat)m00 352 m01:(jfloat)m01 353 m02:(jfloat)m02 354 m10:(jfloat)m10 355 m11:(jfloat)m11 356 m12:(jfloat)m12 357 focusX:(jfloat)focusX 358 fractions:(void *)fractions 359 pixels:(void *)pixels 360 { 361 J2dTraceLn(J2D_TRACE_INFO, "MTLContext.setRadialGradientPaint"); 362 [_paint setRadialGradient:useMask 363 linear:linear 364 cycleMethod:cycleMethod 365 numStops:numStops 366 m00:m00 367 m01:m01 368 m02:m02 369 m10:m10 370 m11:m11 371 m12:m12 372 focusX:focusX 373 fractions:fractions 374 pixels:pixels]; 375 } 376 377 - (void)setTexturePaint:(jboolean)useMask 378 pSrcOps:(jlong)pSrcOps 379 filter:(jboolean)filter 380 xp0:(jdouble)xp0 381 xp1:(jdouble)xp1 382 xp3:(jdouble)xp3 383 yp0:(jdouble)yp0 384 yp1:(jdouble)yp1 385 yp3:(jdouble)yp3 386 { 387 BMTLSDOps *srcOps = (BMTLSDOps *)jlong_to_ptr(pSrcOps); 388 389 if (srcOps == NULL || srcOps->pTexture == NULL) { 390 J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLContext_setTexturePaint: texture paint - texture is null"); 391 return; 392 } 393 394 J2dTraceLn1(J2D_TRACE_INFO, "MTLContext.setTexturePaint [tex=%p]", srcOps->pTexture); 395 396 397 [_paint setTexture:useMask 398 textureID:srcOps->pTexture 399 filter:filter 400 xp0:xp0 401 xp1:xp1 402 xp3:xp3 403 yp0:yp0 404 yp1:yp1 405 yp3:yp3]; 406 } 407 408 - (id<MTLCommandBuffer>)createBlitCommandBuffer { 409 return [self.commandQueue commandBuffer]; 410 } 411 412 @end 413 414 /* 415 * Class: sun_java2d_metal_MTLContext 416 * Method: getMTLIdString 417 * Signature: ()Ljava/lang/String; 418 */ 419 JNIEXPORT jstring JNICALL Java_sun_java2d_metal_MTLContext_getMTLIdString 420 (JNIEnv *env, jclass mtlcc) 421 { 422 char *vendor, *renderer, *version; 423 char *pAdapterId; 424 jobject ret = NULL; 425 int len; 426 427 return NULL; 428 } 429 430 #endif /* !HEADLESS */