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