Path: blob/master/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLContext.m
41159 views
/*1* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include <stdlib.h>2627#include "sun_java2d_SunGraphics2D.h"2829#include "jlong.h"30#import "MTLContext.h"31#include "MTLRenderQueue.h"32#import "MTLSamplerManager.h"33#import "MTLStencilManager.h"343536extern jboolean MTLSD_InitMTLWindow(JNIEnv *env, MTLSDOps *mtlsdo);3738static struct TxtVertex verts[PGRAM_VERTEX_COUNT] = {39{{-1.0, 1.0}, {0.0, 0.0}},40{{1.0, 1.0}, {1.0, 0.0}},41{{1.0, -1.0}, {1.0, 1.0}},42{{1.0, -1.0}, {1.0, 1.0}},43{{-1.0, -1.0}, {0.0, 1.0}},44{{-1.0, 1.0}, {0.0, 0.0}}45};4647MTLTransform* tempTransform = nil;4849@implementation MTLCommandBufferWrapper {50id<MTLCommandBuffer> _commandBuffer;51NSMutableArray * _pooledTextures;52NSLock* _lock;53}5455- (id) initWithCommandBuffer:(id<MTLCommandBuffer>)cmdBuf {56self = [super init];57if (self) {58_commandBuffer = [cmdBuf retain];59_pooledTextures = [[NSMutableArray alloc] init];60_lock = [[NSLock alloc] init];61}62return self;63}6465- (id<MTLCommandBuffer>) getCommandBuffer {66return _commandBuffer;67}6869- (void) onComplete { // invoked from completion handler in some pooled thread70[_lock lock];71@try {72for (int c = 0; c < [_pooledTextures count]; ++c)73[[_pooledTextures objectAtIndex:c] releaseTexture];74[_pooledTextures removeAllObjects];75} @finally {76[_lock unlock];77}7879}8081- (void) registerPooledTexture:(MTLPooledTextureHandle *)handle {82[_lock lock];83@try {84[_pooledTextures addObject:handle];85} @finally {86[_lock unlock];87}88}8990- (void) dealloc {91[self onComplete];9293[_pooledTextures release];94_pooledTextures = nil;9596[_commandBuffer release];97_commandBuffer = nil;9899[_lock release];100_lock = nil;101[super dealloc];102}103104@end105106@implementation MTLContext {107MTLCommandBufferWrapper * _commandBufferWrapper;108109MTLComposite * _composite;110MTLPaint * _paint;111MTLTransform * _transform;112MTLTransform * _tempTransform;113MTLClip * _clip;114NSObject* _bufImgOp; // TODO: pass as parameter of IsoBlit115116EncoderManager * _encoderManager;117MTLSamplerManager * _samplerManager;118MTLStencilManager * _stencilManager;119}120121@synthesize textureFunction,122vertexCacheEnabled, aaEnabled, device, pipelineStateStorage,123commandQueue, blitCommandQueue, vertexBuffer,124texturePool, paint=_paint, encoderManager=_encoderManager,125samplerManager=_samplerManager, stencilManager=_stencilManager;126127extern void initSamplers(id<MTLDevice> device);128129- (id)initWithDevice:(id<MTLDevice>)d shadersLib:(NSString*)shadersLib {130self = [super init];131if (self) {132// Initialization code here.133device = d;134135pipelineStateStorage = [[MTLPipelineStatesStorage alloc] initWithDevice:device shaderLibPath:shadersLib];136if (pipelineStateStorage == nil) {137J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLContext.initWithDevice(): Failed to initialize MTLPipelineStatesStorage.");138return nil;139}140141texturePool = [[MTLTexturePool alloc] initWithDevice:device];142143vertexBuffer = [device newBufferWithBytes:verts144length:sizeof(verts)145options:MTLResourceCPUCacheModeDefaultCache];146147_encoderManager = [[EncoderManager alloc] init];148[_encoderManager setContext:self];149_samplerManager = [[MTLSamplerManager alloc] initWithDevice:device];150_stencilManager = [[MTLStencilManager alloc] initWithDevice:device];151_composite = [[MTLComposite alloc] init];152_paint = [[MTLPaint alloc] init];153_transform = [[MTLTransform alloc] init];154_clip = [[MTLClip alloc] init];155_bufImgOp = nil;156157_commandBufferWrapper = nil;158159// Create command queue160commandQueue = [device newCommandQueue];161blitCommandQueue = [device newCommandQueue];162163_tempTransform = [[MTLTransform alloc] init];164}165return self;166}167168- (void)dealloc {169J2dTraceLn(J2D_TRACE_INFO, "MTLContext.dealloc");170171// TODO : Check that texturePool is completely released.172// texturePool content is released in MTLCommandBufferWrapper.onComplete()173//self.texturePool = nil;174self.vertexBuffer = nil;175self.commandQueue = nil;176self.blitCommandQueue = nil;177self.pipelineStateStorage = nil;178179if (_encoderManager != nil) {180[_encoderManager release];181_encoderManager = nil;182}183184if (_samplerManager != nil) {185[_samplerManager release];186_samplerManager = nil;187}188189if (_stencilManager != nil) {190[_stencilManager release];191_stencilManager = nil;192}193194if (_composite != nil) {195[_composite release];196_composite = nil;197}198199if (_paint != nil) {200[_paint release];201_paint = nil;202}203204if (_transform != nil) {205[_transform release];206_transform = nil;207}208209if (_tempTransform != nil) {210[_tempTransform release];211_tempTransform = nil;212}213214if (_clip != nil) {215[_clip release];216_clip = nil;217}218219[super dealloc];220}221222- (void) reset {223J2dTraceLn(J2D_TRACE_VERBOSE, "MTLContext : reset");224225// Add code for context state reset here226}227228- (MTLCommandBufferWrapper *) getCommandBufferWrapper {229if (_commandBufferWrapper == nil) {230J2dTraceLn(J2D_TRACE_VERBOSE, "MTLContext : commandBuffer is NULL");231// NOTE: Command queues are thread-safe and allow multiple outstanding command buffers to be encoded simultaneously.232_commandBufferWrapper = [[MTLCommandBufferWrapper alloc] initWithCommandBuffer:[self.commandQueue commandBuffer]];// released in [layer blitTexture]233}234return _commandBufferWrapper;235}236237- (MTLCommandBufferWrapper *) pullCommandBufferWrapper {238MTLCommandBufferWrapper * result = _commandBufferWrapper;239_commandBufferWrapper = nil;240return result;241}242243+ (MTLContext*) setSurfacesEnv:(JNIEnv*)env src:(jlong)pSrc dst:(jlong)pDst {244BMTLSDOps *srcOps = (BMTLSDOps *)jlong_to_ptr(pSrc);245BMTLSDOps *dstOps = (BMTLSDOps *)jlong_to_ptr(pDst);246MTLContext *mtlc = NULL;247248if (srcOps == NULL || dstOps == NULL) {249J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLContext_SetSurfaces: ops are null");250return NULL;251}252253J2dTraceLn6(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);254255if (dstOps->drawableType == MTLSD_TEXTURE) {256J2dRlsTraceLn(J2D_TRACE_ERROR,257"MTLContext_SetSurfaces: texture cannot be used as destination");258return NULL;259}260261if (dstOps->drawableType == MTLSD_UNDEFINED) {262// initialize the surface as an MTLSD_WINDOW263if (!MTLSD_InitMTLWindow(env, dstOps)) {264J2dRlsTraceLn(J2D_TRACE_ERROR,265"MTLContext_SetSurfaces: could not init MTL window");266return NULL;267}268}269270// make the context current271MTLSDOps *dstMTLOps = (MTLSDOps *)dstOps->privOps;272mtlc = dstMTLOps->configInfo->context;273274if (mtlc == NULL) {275J2dRlsTraceLn(J2D_TRACE_ERROR,276"MTLContext_SetSurfaces: could not make context current");277return NULL;278}279280return mtlc;281}282283- (void)resetClip {284J2dTraceLn(J2D_TRACE_INFO, "MTLContext.resetClip");285[_clip reset];286}287288- (void)setClipRectX1:(jint)x1 Y1:(jint)y1 X2:(jint)x2 Y2:(jint)y2 {289J2dTraceLn4(J2D_TRACE_INFO, "MTLContext.setClipRect: %d,%d - %d,%d", x1, y1, x2, y2);290[_clip setClipRectX1:x1 Y1:y1 X2:x2 Y2:y2];291}292293- (void)beginShapeClip:(BMTLSDOps *)dstOps {294J2dTraceLn(J2D_TRACE_INFO, "MTLContext.beginShapeClip");295[_clip beginShapeClip:dstOps context:self];296297// Store the current transform as we need to use identity transform298// for clip spans rendering299[_tempTransform copyFrom:_transform];300[self resetTransform];301}302303- (void)endShapeClip:(BMTLSDOps *)dstOps {304J2dTraceLn(J2D_TRACE_INFO, "MTLContext.endShapeClip");305[_clip endShapeClip:dstOps context:self];306307// Reset transform for further rendering308[_transform copyFrom:_tempTransform];309}310311- (void)resetComposite {312J2dTraceLn(J2D_TRACE_VERBOSE, "MTLContext_ResetComposite");313[_composite reset];314}315316- (void)setAlphaCompositeRule:(jint)rule extraAlpha:(jfloat)extraAlpha317flags:(jint)flags {318J2dTraceLn3(J2D_TRACE_INFO, "MTLContext_SetAlphaComposite: rule=%d, extraAlpha=%1.2f, flags=%d", rule, extraAlpha, flags);319320[_composite setRule:rule extraAlpha:extraAlpha];321}322323- (NSString*)getCompositeDescription {324return [_composite getDescription];325}326327- (NSString*)getPaintDescription {328return [_paint getDescription];329}330331- (void)setXorComposite:(jint)xp {332J2dTraceLn1(J2D_TRACE_INFO, "MTLContext.setXorComposite: xorPixel=%08x", xp);333334[_composite setXORComposite:xp];335}336337- (jboolean) useXORComposite {338return ([_composite getCompositeState] == sun_java2d_SunGraphics2D_COMP_XOR);339}340341- (void)resetTransform {342J2dTraceLn(J2D_TRACE_INFO, "MTLContext_ResetTransform");343[_transform resetTransform];344}345346- (void)setTransformM00:(jdouble) m00 M10:(jdouble) m10347M01:(jdouble) m01 M11:(jdouble) m11348M02:(jdouble) m02 M12:(jdouble) m12 {349J2dTraceLn(J2D_TRACE_INFO, "MTLContext_SetTransform");350[_transform setTransformM00:m00 M10:m10 M01:m01 M11:m11 M02:m02 M12:m12];351}352353- (void)resetPaint {354J2dTraceLn(J2D_TRACE_INFO, "MTLContext.resetPaint");355self.paint = [[[MTLPaint alloc] init] autorelease];356}357358- (void)setColorPaint:(int)pixel {359J2dTraceLn5(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);360self.paint = [[[MTLColorPaint alloc] initWithColor:pixel] autorelease];361}362363- (void)setGradientPaintUseMask:(jboolean)useMask364cyclic:(jboolean)cyclic365p0:(jdouble)p0366p1:(jdouble)p1367p3:(jdouble)p3368pixel1:(jint)pixel1369pixel2:(jint) pixel2370{371J2dTraceLn(J2D_TRACE_INFO, "MTLContext.setGradientPaintUseMask");372self.paint = [[[MTLGradPaint alloc] initWithUseMask:useMask373cyclic:cyclic374p0:p0375p1:p1376p3:p3377pixel1:pixel1378pixel2:pixel2] autorelease];379}380381- (void)setLinearGradientPaint:(jboolean)useMask382linear:(jboolean)linear383cycleMethod:(jint)cycleMethod384// 0 - NO_CYCLE385// 1 - REFLECT386// 2 - REPEAT387388numStops:(jint)numStops389p0:(jfloat)p0390p1:(jfloat)p1391p3:(jfloat)p3392fractions:(jfloat*)fractions393pixels:(jint*)pixels394{395J2dTraceLn(J2D_TRACE_INFO, "MTLContext.setLinearGradientPaint");396self.paint = [[[MTLLinearGradPaint alloc] initWithUseMask:useMask397linear:linear398cycleMethod:cycleMethod399numStops:numStops400p0:p0401p1:p1402p3:p3403fractions:fractions404pixels:pixels] autorelease];405}406407- (void)setRadialGradientPaint:(jboolean)useMask408linear:(jboolean)linear409cycleMethod:(jboolean)cycleMethod410numStops:(jint)numStops411m00:(jfloat)m00412m01:(jfloat)m01413m02:(jfloat)m02414m10:(jfloat)m10415m11:(jfloat)m11416m12:(jfloat)m12417focusX:(jfloat)focusX418fractions:(void *)fractions419pixels:(void *)pixels420{421J2dTraceLn(J2D_TRACE_INFO, "MTLContext.setRadialGradientPaint");422self.paint = [[[MTLRadialGradPaint alloc] initWithUseMask:useMask423linear:linear424cycleMethod:cycleMethod425numStops:numStops426m00:m00427m01:m01428m02:m02429m10:m10430m11:m11431m12:m12432focusX:focusX433fractions:fractions434pixels:pixels] autorelease];435}436437- (void)setTexturePaint:(jboolean)useMask438pSrcOps:(jlong)pSrcOps439filter:(jboolean)filter440xp0:(jdouble)xp0441xp1:(jdouble)xp1442xp3:(jdouble)xp3443yp0:(jdouble)yp0444yp1:(jdouble)yp1445yp3:(jdouble)yp3446{447BMTLSDOps *srcOps = (BMTLSDOps *)jlong_to_ptr(pSrcOps);448449if (srcOps == NULL || srcOps->pTexture == NULL) {450J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLContext_setTexturePaint: texture paint - texture is null");451return;452}453454J2dTraceLn1(J2D_TRACE_INFO, "MTLContext.setTexturePaint [tex=%p]", srcOps->pTexture);455456self.paint = [[[MTLTexturePaint alloc] initWithUseMask:useMask457textureID:srcOps->pTexture458isOpaque:srcOps->isOpaque459filter:filter460xp0:xp0461xp1:xp1462xp3:xp3463yp0:yp0464yp1:yp1465yp3:yp3] autorelease];466}467468- (id<MTLCommandBuffer>)createCommandBuffer {469return [self.commandQueue commandBuffer];470}471472/*473* This should be exclusively used only for final blit474* and present of CAMetalDrawable in MTLLayer475*/476- (id<MTLCommandBuffer>)createBlitCommandBuffer {477return [self.blitCommandQueue commandBuffer];478}479480-(void)setBufImgOp:(NSObject*)bufImgOp {481if (_bufImgOp != nil) {482[_bufImgOp release]; // context owns bufImgOp object483}484_bufImgOp = bufImgOp;485}486487-(NSObject*)getBufImgOp {488return _bufImgOp;489}490491@end492493494