Path: blob/master/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPaints.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 "MTLPaints.h"26#include "MTLClip.h"27#include "common.h"2829#include "sun_java2d_SunGraphics2D.h"30#include "sun_java2d_pipe_BufferedPaints.h"31#import "MTLComposite.h"32#import "MTLBufImgOps.h"33#include "MTLRenderQueue.h"3435#define RGBA_TO_V4(c) \36{ \37(((c) >> 16) & (0xFF))/255.0f, \38(((c) >> 8) & 0xFF)/255.0f, \39((c) & 0xFF)/255.0f, \40(((c) >> 24) & 0xFF)/255.0f \41}4243#define FLOAT_ARR_TO_V4(p) \44{ \45p[0], \46p[1], \47p[2], \48p[3] \49}5051static MTLRenderPipelineDescriptor * templateRenderPipelineDesc = nil;52static MTLRenderPipelineDescriptor * templateTexturePipelineDesc = nil;53static MTLRenderPipelineDescriptor * templateAATexturePipelineDesc = nil;54static MTLRenderPipelineDescriptor * templateLCDPipelineDesc = nil;55static MTLRenderPipelineDescriptor * templateAAPipelineDesc = nil;56static void57setTxtUniforms(MTLContext *mtlc, int color, id <MTLRenderCommandEncoder> encoder, int interpolation, bool repeat,58jfloat extraAlpha, const SurfaceRasterFlags *srcFlags, const SurfaceRasterFlags *dstFlags, int mode);5960static void initTemplatePipelineDescriptors() {61if (templateRenderPipelineDesc != nil && templateTexturePipelineDesc != nil &&62templateAATexturePipelineDesc != nil && templateLCDPipelineDesc != nil &&63templateAAPipelineDesc != nil)64return;6566MTLVertexDescriptor *vertDesc = [[MTLVertexDescriptor new] autorelease];67vertDesc.attributes[VertexAttributePosition].format = MTLVertexFormatFloat2;68vertDesc.attributes[VertexAttributePosition].offset = 0;69vertDesc.attributes[VertexAttributePosition].bufferIndex = MeshVertexBuffer;70vertDesc.layouts[MeshVertexBuffer].stride = sizeof(struct Vertex);71vertDesc.layouts[MeshVertexBuffer].stepRate = 1;72vertDesc.layouts[MeshVertexBuffer].stepFunction = MTLVertexStepFunctionPerVertex;7374templateRenderPipelineDesc = [MTLRenderPipelineDescriptor new];75templateRenderPipelineDesc.sampleCount = 1;76templateRenderPipelineDesc.vertexDescriptor = vertDesc;77templateRenderPipelineDesc.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;78templateRenderPipelineDesc.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;79templateRenderPipelineDesc.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;80templateRenderPipelineDesc.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorOne;81templateRenderPipelineDesc.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne;82templateRenderPipelineDesc.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;83templateRenderPipelineDesc.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;84templateRenderPipelineDesc.label = @"template_render";8586templateTexturePipelineDesc = [templateRenderPipelineDesc copy];87templateTexturePipelineDesc.vertexDescriptor.attributes[VertexAttributeTexPos].format = MTLVertexFormatFloat2;88templateTexturePipelineDesc.vertexDescriptor.attributes[VertexAttributeTexPos].offset = 2*sizeof(float);89templateTexturePipelineDesc.vertexDescriptor.attributes[VertexAttributeTexPos].bufferIndex = MeshVertexBuffer;90templateTexturePipelineDesc.vertexDescriptor.layouts[MeshVertexBuffer].stride = sizeof(struct TxtVertex);91templateTexturePipelineDesc.vertexDescriptor.layouts[MeshVertexBuffer].stepRate = 1;92templateTexturePipelineDesc.vertexDescriptor.layouts[MeshVertexBuffer].stepFunction = MTLVertexStepFunctionPerVertex;93templateTexturePipelineDesc.label = @"template_texture";9495templateAATexturePipelineDesc = [templateTexturePipelineDesc copy];96templateAATexturePipelineDesc.label = @"template_aa_texture";9798templateLCDPipelineDesc = [MTLRenderPipelineDescriptor new];99templateLCDPipelineDesc.sampleCount = 1;100templateLCDPipelineDesc.vertexDescriptor = vertDesc;101templateLCDPipelineDesc.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;102templateLCDPipelineDesc.vertexDescriptor.attributes[VertexAttributeTexPos].format = MTLVertexFormatFloat2;103templateLCDPipelineDesc.vertexDescriptor.attributes[VertexAttributeTexPos].offset = 2*sizeof(float);104templateLCDPipelineDesc.vertexDescriptor.attributes[VertexAttributeTexPos].bufferIndex = MeshVertexBuffer;105templateLCDPipelineDesc.vertexDescriptor.layouts[MeshVertexBuffer].stride = sizeof(struct TxtVertex);106templateLCDPipelineDesc.vertexDescriptor.layouts[MeshVertexBuffer].stepRate = 1;107templateLCDPipelineDesc.vertexDescriptor.layouts[MeshVertexBuffer].stepFunction = MTLVertexStepFunctionPerVertex;108templateLCDPipelineDesc.label = @"template_lcd";109110vertDesc = [[MTLVertexDescriptor new] autorelease];111vertDesc.attributes[VertexAttributePosition].format = MTLVertexFormatFloat2;112vertDesc.attributes[VertexAttributePosition].offset = 0;113vertDesc.attributes[VertexAttributePosition].bufferIndex = MeshVertexBuffer;114vertDesc.layouts[MeshVertexBuffer].stride = sizeof(struct AAVertex);115vertDesc.layouts[MeshVertexBuffer].stepRate = 1;116vertDesc.layouts[MeshVertexBuffer].stepFunction = MTLVertexStepFunctionPerVertex;117118templateAAPipelineDesc = [MTLRenderPipelineDescriptor new];119templateAAPipelineDesc.sampleCount = 1;120templateAAPipelineDesc.vertexDescriptor = vertDesc;121templateAAPipelineDesc.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;122templateAAPipelineDesc.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;123templateAAPipelineDesc.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;124templateAAPipelineDesc.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorOne;125templateAAPipelineDesc.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne;126templateAAPipelineDesc.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;127templateAAPipelineDesc.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;128templateAAPipelineDesc.colorAttachments[0].blendingEnabled = YES;129templateAAPipelineDesc.vertexDescriptor.attributes[VertexAttributeTexPos].format = MTLVertexFormatFloat2;130templateAAPipelineDesc.vertexDescriptor.attributes[VertexAttributeTexPos].offset = 2*sizeof(float);131templateAAPipelineDesc.vertexDescriptor.attributes[VertexAttributeTexPos].bufferIndex = MeshVertexBuffer;132templateAAPipelineDesc.vertexDescriptor.attributes[VertexAttributeITexPos].format = MTLVertexFormatFloat2;133templateAAPipelineDesc.vertexDescriptor.attributes[VertexAttributeITexPos].offset = 4*sizeof(float);134templateAAPipelineDesc.vertexDescriptor.attributes[VertexAttributeITexPos].bufferIndex = MeshVertexBuffer;135templateAAPipelineDesc.label = @"template_aa";136}137138139@implementation MTLColorPaint {140// color-mode141jint _color;142}143- (id)initWithColor:(jint)color {144self = [super initWithState:sun_java2d_SunGraphics2D_PAINT_ALPHACOLOR];145146if (self) {147_color = color;148}149return self;150}151152- (jint)color {153return _color;154}155156- (BOOL)isEqual:(MTLColorPaint *)other {157if (other == self)158return YES;159if (!other || ![[other class] isEqual:[self class]])160return NO;161162return _color == other->_color;163}164165- (NSUInteger)hash {166NSUInteger h = [super hash];167h = h*31 + _color;168return h;169}170171- (NSString *)description {172return [NSString stringWithFormat:173@"[r=%d g=%d b=%d a=%d]",174(_color >> 16) & (0xFF),175(_color >> 8) & 0xFF,176(_color) & 0xFF,177(_color >> 24) & 0xFF];178}179180- (void)setPipelineState:(id<MTLRenderCommandEncoder>)encoder181context:(MTLContext *)mtlc182renderOptions:(const RenderOptions *)renderOptions183pipelineStateStorage:(MTLPipelineStatesStorage *)pipelineStateStorage184{185initTemplatePipelineDescriptors();186187MTLRenderPipelineDescriptor *rpDesc = nil;188189NSString *vertShader = @"vert_col";190NSString *fragShader = @"frag_col";191192if (renderOptions->isTexture) {193vertShader = @"vert_txt";194fragShader = @"frag_txt";195rpDesc = [[templateTexturePipelineDesc copy] autorelease];196if (renderOptions->isAA) {197fragShader = @"aa_frag_txt";198rpDesc = [[templateAATexturePipelineDesc copy] autorelease];199}200if (renderOptions->isText) {201fragShader = @"frag_text";202}203if (renderOptions->isLCD) {204vertShader = @"vert_txt_lcd";205fragShader = @"lcd_color";206rpDesc = [[templateLCDPipelineDesc copy] autorelease];207}208setTxtUniforms(mtlc, _color, encoder,209renderOptions->interpolation, NO, [mtlc.composite getExtraAlpha], &renderOptions->srcFlags,210&renderOptions->dstFlags, 1);211} else if (renderOptions->isAAShader) {212vertShader = @"vert_col_aa";213fragShader = @"frag_col_aa";214rpDesc = [[templateAAPipelineDesc copy] autorelease];215} else {216rpDesc = [[templateRenderPipelineDesc copy] autorelease];217}218219struct FrameUniforms uf = {RGBA_TO_V4(_color)};220[encoder setVertexBytes:&uf length:sizeof(uf) atIndex:FrameUniformBuffer];221222id <MTLRenderPipelineState> pipelineState = [pipelineStateStorage getPipelineState:rpDesc223vertexShaderId:vertShader224fragmentShaderId:fragShader225composite:mtlc.composite226renderOptions:renderOptions227stencilNeeded:[mtlc.clip isShape]];228[encoder setRenderPipelineState:pipelineState];229}230231- (void)setXorModePipelineState:(id<MTLRenderCommandEncoder>)encoder232context:(MTLContext *)mtlc233renderOptions:(const RenderOptions *)renderOptions234pipelineStateStorage:(MTLPipelineStatesStorage *)pipelineStateStorage235{236initTemplatePipelineDescriptors();237NSString * vertShader = @"vert_col_xorMode";238NSString * fragShader = @"frag_col_xorMode";239MTLRenderPipelineDescriptor * rpDesc = nil;240jint xorColor = (jint) [mtlc.composite getXorColor];241// Calculate _color ^ xorColor for RGB components242// This color gets XORed with destination framebuffer pixel color243const int col = _color ^ xorColor;244BMTLSDOps *dstOps = MTLRenderQueue_GetCurrentDestination();245246if (renderOptions->isTexture) {247vertShader = @"vert_txt_xorMode";248fragShader = @"frag_txt_xorMode";249rpDesc = [[templateTexturePipelineDesc copy] autorelease];250251setTxtUniforms(mtlc, col, encoder,252renderOptions->interpolation, NO, [mtlc.composite getExtraAlpha],253&renderOptions->srcFlags, &renderOptions->dstFlags, 1);254[encoder setFragmentBytes:&xorColor length:sizeof(xorColor) atIndex:0];255256[encoder setFragmentTexture:dstOps->pTexture atIndex:1];257} else {258struct FrameUniforms uf = {RGBA_TO_V4(col)};259rpDesc = [[templateRenderPipelineDesc copy] autorelease];260261[encoder setVertexBytes:&uf length:sizeof(uf) atIndex:FrameUniformBuffer];262[encoder setFragmentTexture:dstOps->pTexture atIndex:0];263}264265id <MTLRenderPipelineState> pipelineState = [pipelineStateStorage getPipelineState:rpDesc266vertexShaderId:vertShader267fragmentShaderId:fragShader268composite:mtlc.composite269renderOptions:renderOptions270stencilNeeded:[mtlc.clip isShape]];271[encoder setRenderPipelineState:pipelineState];272}273@end274275@implementation MTLBaseGradPaint {276jboolean _useMask;277@protected278jint _cyclic;279}280281- (id)initWithState:(jint)state mask:(jboolean)useMask cyclic:(jboolean)cyclic {282self = [super initWithState:state];283284if (self) {285_useMask = useMask;286_cyclic = cyclic;287}288return self;289}290291- (BOOL)isEqual:(MTLBaseGradPaint *)other {292if (other == self)293return YES;294if (!other || ![[other class] isEqual:[self class]])295return NO;296297return [super isEqual:self] && _cyclic == other->_cyclic && _useMask == other->_useMask;298}299300- (NSUInteger)hash {301NSUInteger h = [super hash];302h = h*31 + _cyclic;303h = h*31 + _useMask;304return h;305}306307@end308309@implementation MTLGradPaint {310jdouble _p0;311jdouble _p1;312jdouble _p3;313jint _pixel1;314jint _pixel2;315}316- (id)initWithUseMask:(jboolean)useMask317cyclic:(jboolean)cyclic318p0:(jdouble)p0319p1:(jdouble)p1320p3:(jdouble)p3321pixel1:(jint)pixel1322pixel2:(jint)pixel2323{324self = [super initWithState:sun_java2d_SunGraphics2D_PAINT_GRADIENT325mask:useMask326cyclic:cyclic];327328if (self) {329_p0 = p0;330_p1 = p1;331_p3 = p3;332_pixel1 = pixel1;333_pixel2 = pixel2;334}335return self;336}337338- (BOOL)isEqual:(MTLGradPaint *)other {339if (other == self)340return YES;341if (!other || ![[other class] isEqual:[self class]])342return NO;343344return [super isEqual:self] && _p0 == other->_p0 &&345_p1 == other->_p1 && _p3 == other->_p3 &&346_pixel1 == other->_pixel1 && _pixel2 == other->_pixel2;347}348349- (NSUInteger)hash {350NSUInteger h = [super hash];351h = h*31 + [@(_p0) hash];352h = h*31 + [@(_p1) hash];;353h = h*31 + [@(_p3) hash];;354h = h*31 + _pixel1;355h = h*31 + _pixel2;356return h;357}358- (NSString *)description {359return [NSString stringWithFormat:@"gradient"];360}361362- (void)setPipelineState:(id)encoder363context:(MTLContext *)mtlc364renderOptions:(const RenderOptions *)renderOptions365pipelineStateStorage:(MTLPipelineStatesStorage *)pipelineStateStorage366{367initTemplatePipelineDescriptors();368MTLRenderPipelineDescriptor *rpDesc = nil;369370NSString *vertShader = @"vert_grad";371NSString *fragShader = @"frag_grad";372373struct GradFrameUniforms uf = {374{_p0, _p1, _p3},375RGBA_TO_V4(_pixel1),376RGBA_TO_V4(_pixel2),377_cyclic,378[mtlc.composite getExtraAlpha]379};380[encoder setFragmentBytes:&uf length:sizeof(uf) atIndex:0];381382if (renderOptions->isTexture) {383vertShader = @"vert_txt_grad";384fragShader = @"frag_txt_grad";385rpDesc = [[templateTexturePipelineDesc copy] autorelease];386} else {387rpDesc = [[templateRenderPipelineDesc copy] autorelease];388}389390id <MTLRenderPipelineState> pipelineState = [pipelineStateStorage getPipelineState:rpDesc391vertexShaderId:vertShader392fragmentShaderId:fragShader393composite:mtlc.composite394renderOptions:renderOptions395stencilNeeded:[mtlc.clip isShape]];396[encoder setRenderPipelineState:pipelineState];397}398399- (void)setXorModePipelineState:(id)encoder400context:(MTLContext *)mtlc401renderOptions:(const RenderOptions *)renderOptions402pipelineStateStorage:(MTLPipelineStatesStorage *)pipelineStateStorage403{404// This block is not reached in current implementation.405// Gradient paint XOR mode rendering uses a tile based rendering using a SW pipe (similar to OGL)406initTemplatePipelineDescriptors();407NSString* vertShader = @"vert_grad_xorMode";408NSString* fragShader = @"frag_grad_xorMode";409MTLRenderPipelineDescriptor *rpDesc = [[templateRenderPipelineDesc copy] autorelease];410jint xorColor = (jint) [mtlc.composite getXorColor];411412struct GradFrameUniforms uf = {413{_p0, _p1, _p3},414RGBA_TO_V4(_pixel1 ^ xorColor),415RGBA_TO_V4(_pixel2 ^ xorColor),416_cyclic,417[mtlc.composite getExtraAlpha]418};419420[encoder setFragmentBytes: &uf length:sizeof(uf) atIndex:0];421BMTLSDOps *dstOps = MTLRenderQueue_GetCurrentDestination();422[encoder setFragmentTexture:dstOps->pTexture atIndex:0];423424J2dTraceLn(J2D_TRACE_INFO, "MTLPaints - setXorModePipelineState -- PAINT_GRADIENT");425426id <MTLRenderPipelineState> pipelineState = [pipelineStateStorage getPipelineState:rpDesc427vertexShaderId:vertShader428fragmentShaderId:fragShader429composite:mtlc.composite430renderOptions:renderOptions431stencilNeeded:[mtlc.clip isShape]];432[encoder setRenderPipelineState:pipelineState];433}434435@end436437@implementation MTLBaseMultiGradPaint {438@protected439jboolean _linear;440jint _numFracts;441jfloat _fract[GRAD_MAX_FRACTIONS];442jint _pixel[GRAD_MAX_FRACTIONS];443}444445- (id)initWithState:(jint)state446mask:(jboolean)useMask447linear:(jboolean)linear448cycleMethod:(jboolean)cycleMethod449numStops:(jint)numStops450fractions:(jfloat *)fractions451pixels:(jint *)pixels452{453self = [super initWithState:state454mask:useMask455cyclic:cycleMethod];456457if (self) {458_linear = linear;459memcpy(_fract, fractions,numStops*sizeof(jfloat));460memcpy(_pixel, pixels, numStops*sizeof(jint));461_numFracts = numStops;462}463return self;464}465466- (BOOL)isEqual:(MTLBaseMultiGradPaint *)other {467if (other == self)468return YES;469if (!other || ![[other class] isEqual:[self class]])470return NO;471472if (_numFracts != other->_numFracts || ![super isEqual:self])473return NO;474for (int i = 0; i < _numFracts; i++) {475if (_fract[i] != other->_fract[i]) return NO;476if (_pixel[i] != other->_pixel[i]) return NO;477}478return YES;479}480481- (NSUInteger)hash {482NSUInteger h = [super hash];483h = h*31 + _numFracts;484for (int i = 0; i < _numFracts; i++) {485h = h*31 + [@(_fract[i]) hash];486h = h*31 + _pixel[i];487}488return h;489}490491@end492493@implementation MTLLinearGradPaint {494jdouble _p0;495jdouble _p1;496jdouble _p3;497}498- (void)setPipelineState:(id)encoder499context:(MTLContext *)mtlc500renderOptions:(const RenderOptions *)renderOptions501pipelineStateStorage:(MTLPipelineStatesStorage *)pipelineStateStorage502503{504initTemplatePipelineDescriptors();505MTLRenderPipelineDescriptor *rpDesc = nil;506507NSString *vertShader = @"vert_grad";508NSString *fragShader = @"frag_lin_grad";509510if (renderOptions->isTexture) {511vertShader = @"vert_txt_grad";512fragShader = @"frag_txt_lin_grad";513rpDesc = [[templateTexturePipelineDesc copy] autorelease];514} else {515rpDesc = [[templateRenderPipelineDesc copy] autorelease];516}517518struct LinGradFrameUniforms uf = {519{_p0, _p1, _p3},520{},521{},522_numFracts,523_linear,524_cyclic,525[mtlc.composite getExtraAlpha]526};527528memcpy(uf.fract, _fract, _numFracts*sizeof(jfloat));529for (int i = 0; i < _numFracts; i++) {530vector_float4 v = RGBA_TO_V4(_pixel[i]);531uf.color[i] = v;532}533[encoder setFragmentBytes:&uf length:sizeof(uf) atIndex:0];534535id <MTLRenderPipelineState> pipelineState = [pipelineStateStorage getPipelineState:rpDesc536vertexShaderId:vertShader537fragmentShaderId:fragShader538composite:mtlc.composite539renderOptions:renderOptions540stencilNeeded:[mtlc.clip isShape]];541[encoder setRenderPipelineState:pipelineState];542}543544- (id)initWithUseMask:(jboolean)useMask545linear:(jboolean)linear546cycleMethod:(jboolean)cycleMethod547numStops:(jint)numStops548p0:(jfloat)p0549p1:(jfloat)p1550p3:(jfloat)p3551fractions:(jfloat *)fractions552pixels:(jint *)pixels553{554self = [super initWithState:sun_java2d_SunGraphics2D_PAINT_LIN_GRADIENT555mask:useMask556linear:linear557cycleMethod:cycleMethod558numStops:numStops559fractions:fractions560pixels:pixels];561562if (self) {563_p0 = p0;564_p1 = p1;565_p3 = p3;566}567return self;568}569570- (BOOL)isEqual:(MTLLinearGradPaint *)other {571if (other == self)572return YES;573if (!other || ![[other class] isEqual:[self class]] || ![super isEqual:other])574return NO;575576return _p0 == other->_p0 && _p1 == other->_p1 && _p3 == other->_p3;577}578579- (NSUInteger)hash {580NSUInteger h = [super hash];581h = h*31 + [@(_p0) hash];582h = h*31 + [@(_p1) hash];583h = h*31 + [@(_p3) hash];584return h;585}586587- (NSString *)description {588return [NSString stringWithFormat:@"linear_gradient"];589}590@end591592@implementation MTLRadialGradPaint {593jfloat _m00;594jfloat _m01;595jfloat _m02;596jfloat _m10;597jfloat _m11;598jfloat _m12;599jfloat _focusX;600}601602- (id)initWithUseMask:(jboolean)useMask603linear:(jboolean)linear604cycleMethod:(jint)cycleMethod605numStops:(jint)numStops606m00:(jfloat)m00607m01:(jfloat)m01608m02:(jfloat)m02609m10:(jfloat)m10610m11:(jfloat)m11611m12:(jfloat)m12612focusX:(jfloat)focusX613fractions:(void *)fractions614pixels:(void *)pixels615{616self = [super initWithState:sun_java2d_SunGraphics2D_PAINT_RAD_GRADIENT617mask:useMask618linear:linear619cycleMethod:cycleMethod620numStops:numStops621fractions:fractions622pixels:pixels];623624if (self) {625_m00 = m00;626_m01 = m01;627_m02 = m02;628_m10 = m10;629_m11 = m11;630_m12 = m12;631_focusX = focusX;632}633return self;634}635636- (BOOL)isEqual:(MTLRadialGradPaint *)other {637if (other == self)638return YES;639if (!other || ![[other class] isEqual:[self class]]640|| ![super isEqual:self])641return NO;642643return _m00 == other->_m00 && _m01 == other->_m01 && _m02 == other->_m02 &&644_m10 == other->_m10 && _m11 == other->_m11 && _m12 == other->_m12 &&645_focusX == other->_focusX;646}647648- (NSUInteger)hash {649NSUInteger h = [super hash];650h = h*31 + [@(_m00) hash];651h = h*31 + [@(_m01) hash];652h = h*31 + [@(_m02) hash];653h = h*31 + [@(_m10) hash];654h = h*31 + [@(_m11) hash];655h = h*31 + [@(_m12) hash];656return h;657}658659- (NSString *)description {660return [NSString stringWithFormat:@"radial_gradient"];661}662663- (void)setPipelineState:(id)encoder664context:(MTLContext *)mtlc665renderOptions:(const RenderOptions *)renderOptions666pipelineStateStorage:(MTLPipelineStatesStorage *)pipelineStateStorage667{668initTemplatePipelineDescriptors();669MTLRenderPipelineDescriptor *rpDesc = nil;670671NSString *vertShader = @"vert_grad";672NSString *fragShader = @"frag_rad_grad";673674if (renderOptions->isTexture) {675vertShader = @"vert_txt_grad";676fragShader = @"frag_txt_rad_grad";677rpDesc = [[templateTexturePipelineDesc copy] autorelease];678} else {679rpDesc = [[templateRenderPipelineDesc copy] autorelease];680}681682struct RadGradFrameUniforms uf = {683{},684{},685_numFracts,686_linear,687_cyclic,688{_m00, _m01, _m02},689{_m10, _m11, _m12},690{},691[mtlc.composite getExtraAlpha]692};693694uf.precalc[0] = _focusX;695uf.precalc[1] = 1.0 - (_focusX * _focusX);696uf.precalc[2] = 1.0 / uf.precalc[1];697698memcpy(uf.fract, _fract, _numFracts*sizeof(jfloat));699for (int i = 0; i < _numFracts; i++) {700vector_float4 v = RGBA_TO_V4(_pixel[i]);701uf.color[i] = v;702}703[encoder setFragmentBytes:&uf length:sizeof(uf) atIndex:0];704id <MTLRenderPipelineState> pipelineState = [pipelineStateStorage getPipelineState:rpDesc705vertexShaderId:vertShader706fragmentShaderId:fragShader707composite:mtlc.composite708renderOptions:renderOptions709stencilNeeded:[mtlc.clip isShape]];710[encoder setRenderPipelineState:pipelineState];711}712713714@end715716@implementation MTLTexturePaint {717struct AnchorData _anchor;718id <MTLTexture> _paintTexture;719jboolean _isOpaque;720}721722- (id)initWithUseMask:(jboolean)useMask723textureID:(id)textureId724isOpaque:(jboolean)isOpaque725filter:(jboolean)filter726xp0:(jdouble)xp0727xp1:(jdouble)xp1728xp3:(jdouble)xp3729yp0:(jdouble)yp0730yp1:(jdouble)yp1731yp3:(jdouble)yp3732{733self = [super initWithState:sun_java2d_SunGraphics2D_PAINT_TEXTURE];734735if (self) {736_paintTexture = textureId;737_anchor.xParams[0] = xp0;738_anchor.xParams[1] = xp1;739_anchor.xParams[2] = xp3;740741_anchor.yParams[0] = yp0;742_anchor.yParams[1] = yp1;743_anchor.yParams[2] = yp3;744_isOpaque = isOpaque;745}746return self;747748}749750- (BOOL)isEqual:(MTLTexturePaint *)other {751if (other == self)752return YES;753if (!other || ![[other class] isEqual:[self class]])754return NO;755756return [_paintTexture isEqual:other->_paintTexture]757&& _anchor.xParams[0] == other->_anchor.xParams[0]758&& _anchor.xParams[1] == other->_anchor.xParams[1]759&& _anchor.xParams[2] == other->_anchor.xParams[2]760&& _anchor.yParams[0] == other->_anchor.yParams[0]761&& _anchor.yParams[1] == other->_anchor.yParams[1]762&& _anchor.yParams[2] == other->_anchor.yParams[2];763}764765- (NSString *)description {766return [NSString stringWithFormat:@"texture_paint"];767}768769- (void)setPipelineState:(id)encoder770context:(MTLContext *)mtlc771renderOptions:(const RenderOptions *)renderOptions772pipelineStateStorage:(MTLPipelineStatesStorage *)pipelineStateStorage773{774initTemplatePipelineDescriptors();775MTLRenderPipelineDescriptor *rpDesc = nil;776777NSString* vertShader = @"vert_tp";778NSString* fragShader = @"frag_tp";779780[encoder setVertexBytes:&_anchor length:sizeof(_anchor) atIndex:FrameUniformBuffer];781782if (renderOptions->isTexture) {783vertShader = @"vert_txt_tp";784fragShader = @"frag_txt_tp";785rpDesc = [[templateTexturePipelineDesc copy] autorelease];786[encoder setFragmentTexture:_paintTexture atIndex:1];787} else {788rpDesc = [[templateRenderPipelineDesc copy] autorelease];789[encoder setFragmentTexture:_paintTexture atIndex:0];790}791const SurfaceRasterFlags srcFlags = {_isOpaque, renderOptions->srcFlags.isPremultiplied};792setTxtUniforms(mtlc, 0, encoder,793renderOptions->interpolation, YES, [mtlc.composite getExtraAlpha],794&srcFlags, &renderOptions->dstFlags, 0);795796id <MTLRenderPipelineState> pipelineState = [pipelineStateStorage getPipelineState:rpDesc797vertexShaderId:vertShader798fragmentShaderId:fragShader799composite:mtlc.composite800renderOptions:renderOptions801stencilNeeded:[mtlc.clip isShape]];802[encoder setRenderPipelineState:pipelineState];803}804805- (void)setXorModePipelineState:(id)encoder806context:(MTLContext *)mtlc807renderOptions:(const RenderOptions *)renderOptions808pipelineStateStorage:(MTLPipelineStatesStorage *)pipelineStateStorage809{810initTemplatePipelineDescriptors();811// This block is not reached in current implementation.812// Texture paint XOR mode rendering uses a tile based rendering using a SW pipe (similar to OGL)813NSString* vertShader = @"vert_tp_xorMode";814NSString* fragShader = @"frag_tp_xorMode";815MTLRenderPipelineDescriptor *rpDesc = [[templateRenderPipelineDesc copy] autorelease];816jint xorColor = (jint) [mtlc.composite getXorColor];817818[encoder setVertexBytes:&_anchor length:sizeof(_anchor) atIndex:FrameUniformBuffer];819[encoder setFragmentTexture:_paintTexture atIndex: 0];820BMTLSDOps *dstOps = MTLRenderQueue_GetCurrentDestination();821[encoder setFragmentTexture:dstOps->pTexture atIndex:1];822[encoder setFragmentBytes:&xorColor length:sizeof(xorColor) atIndex: 0];823824J2dTraceLn(J2D_TRACE_INFO, "MTLPaints - setXorModePipelineState -- PAINT_TEXTURE");825826id <MTLRenderPipelineState> pipelineState = [pipelineStateStorage getPipelineState:rpDesc827vertexShaderId:vertShader828fragmentShaderId:fragShader829composite:mtlc.composite830renderOptions:renderOptions831stencilNeeded:[mtlc.clip isShape]];832[encoder setRenderPipelineState:pipelineState];833}834835@end836837@implementation MTLPaint {838jint _paintState;839}840841- (instancetype)init {842self = [super init];843if (self) {844_paintState = sun_java2d_SunGraphics2D_PAINT_UNDEFINED;845}846847return self;848}849850- (instancetype)initWithState:(jint)state {851self = [super init];852if (self) {853_paintState = state;854}855return self;856}857858- (BOOL)isEqual:(MTLPaint *)other {859if (other == self)860return YES;861if (!other || ![other isKindOfClass:[self class]])862return NO;863return _paintState == other->_paintState;864}865866- (NSUInteger)hash {867return _paintState;868}869870- (NSString *)description {871return @"unknown-paint";872}873874static void875setTxtUniforms(MTLContext *mtlc, int color, id <MTLRenderCommandEncoder> encoder, int interpolation, bool repeat,876jfloat extraAlpha, const SurfaceRasterFlags *srcFlags, const SurfaceRasterFlags *dstFlags, int mode) {877struct TxtFrameUniforms uf = {RGBA_TO_V4(color), mode, srcFlags->isOpaque, dstFlags->isOpaque, extraAlpha};878[encoder setFragmentBytes:&uf length:sizeof(uf) atIndex:FrameUniformBuffer];879[mtlc.samplerManager setSamplerWithEncoder:encoder interpolation:interpolation repeat:repeat];880}881882// For the current paint mode:883// 1. Selects vertex+fragment shaders (and corresponding pipelineDesc) and set pipelineState884// 2. Set vertex and fragment buffers885// Base implementation is used in drawTex2Tex886- (void)setPipelineState:(id <MTLRenderCommandEncoder>)encoder887context:(MTLContext *)mtlc888renderOptions:(const RenderOptions *)renderOptions889pipelineStateStorage:(MTLPipelineStatesStorage *)pipelineStateStorage890{891initTemplatePipelineDescriptors();892// Called from drawTex2Tex used in flushBuffer and for buffered image ops893if (renderOptions->isTexture) {894NSString * vertShader = @"vert_txt";895NSString * fragShader = @"frag_txt";896MTLRenderPipelineDescriptor* rpDesc = [[templateTexturePipelineDesc copy] autorelease];897898NSObject *bufImgOp = [mtlc getBufImgOp];899if (bufImgOp != nil) {900if ([bufImgOp isKindOfClass:[MTLRescaleOp class]]) {901MTLRescaleOp *rescaleOp = bufImgOp;902fragShader = @"frag_txt_op_rescale";903904struct TxtFrameOpRescaleUniforms uf = {905RGBA_TO_V4(0), [mtlc.composite getExtraAlpha], renderOptions->srcFlags.isOpaque,906rescaleOp.isNonPremult,907FLOAT_ARR_TO_V4([rescaleOp getScaleFactors]), FLOAT_ARR_TO_V4([rescaleOp getOffsets])908};909[encoder setFragmentBytes:&uf length:sizeof(uf) atIndex:FrameUniformBuffer];910[mtlc.samplerManager setSamplerWithEncoder:encoder interpolation:renderOptions->interpolation repeat:NO];911} else if ([bufImgOp isKindOfClass:[MTLConvolveOp class]]) {912MTLConvolveOp *convolveOp = bufImgOp;913fragShader = @"frag_txt_op_convolve";914915struct TxtFrameOpConvolveUniforms uf = {916[mtlc.composite getExtraAlpha], renderOptions->srcFlags.isOpaque,917FLOAT_ARR_TO_V4([convolveOp getImgEdge]),918convolveOp.kernelSize, convolveOp.isEdgeZeroFill,919};920[encoder setFragmentBytes:&uf length:sizeof(uf) atIndex:FrameUniformBuffer];921[mtlc.samplerManager setSamplerWithEncoder:encoder interpolation:renderOptions->interpolation repeat:NO];922923[encoder setFragmentBuffer:[convolveOp getBuffer] offset:0 atIndex:2];924} else if ([bufImgOp isKindOfClass:[MTLLookupOp class]]) {925MTLLookupOp *lookupOp = bufImgOp;926fragShader = @"frag_txt_op_lookup";927928struct TxtFrameOpLookupUniforms uf = {929[mtlc.composite getExtraAlpha], renderOptions->srcFlags.isOpaque,930FLOAT_ARR_TO_V4([lookupOp getOffset]), lookupOp.isUseSrcAlpha, lookupOp.isNonPremult,931};932[encoder setFragmentBytes:&uf length:sizeof(uf) atIndex:FrameUniformBuffer];933[mtlc.samplerManager setSamplerWithEncoder:encoder interpolation:renderOptions->interpolation repeat:NO];934[encoder setFragmentTexture:[lookupOp getLookupTexture] atIndex:1];935}936} else {937setTxtUniforms(mtlc, 0, encoder,938renderOptions->interpolation, NO, [mtlc.composite getExtraAlpha],939&renderOptions->srcFlags,940&renderOptions->dstFlags, 0);941942}943id <MTLRenderPipelineState> pipelineState = [pipelineStateStorage getPipelineState:rpDesc944vertexShaderId:vertShader945fragmentShaderId:fragShader946composite:mtlc.composite947renderOptions:renderOptions948stencilNeeded:[mtlc.clip isShape]];949[encoder setRenderPipelineState:pipelineState];950}951}952953// For the current paint mode:954// 1. Selects vertex+fragment shaders (and corresponding pipelineDesc) and set pipelineState955// 2. Set vertex and fragment buffers956- (void)setXorModePipelineState:(id <MTLRenderCommandEncoder>)encoder957context:(MTLContext *)mtlc958renderOptions:(const RenderOptions *)renderOptions959pipelineStateStorage:(MTLPipelineStatesStorage *)pipelineStateStorage960{961initTemplatePipelineDescriptors();962if (renderOptions->isTexture) {963jint xorColor = (jint) [mtlc.composite getXorColor];964NSString * vertShader = @"vert_txt_xorMode";965NSString * fragShader = @"frag_txt_xorMode";966MTLRenderPipelineDescriptor * rpDesc = [[templateTexturePipelineDesc copy] autorelease];967968const int col = 0 ^ xorColor;969setTxtUniforms(mtlc, col, encoder,970renderOptions->interpolation, NO, [mtlc.composite getExtraAlpha],971&renderOptions->srcFlags, &renderOptions->dstFlags, 0);972[encoder setFragmentBytes:&xorColor length:sizeof(xorColor) atIndex: 0];973974BMTLSDOps *dstOps = MTLRenderQueue_GetCurrentDestination();975[encoder setFragmentTexture:dstOps->pTexture atIndex:1];976977setTxtUniforms(mtlc, 0, encoder,978renderOptions->interpolation, NO, [mtlc.composite getExtraAlpha],979&renderOptions->srcFlags,980&renderOptions->dstFlags, 0);981982id <MTLRenderPipelineState> pipelineState = [pipelineStateStorage getPipelineState:rpDesc983vertexShaderId:vertShader984fragmentShaderId:fragShader985composite:mtlc.composite986renderOptions:renderOptions987stencilNeeded:[mtlc.clip isShape]];988[encoder setRenderPipelineState:pipelineState];989}990}991992@end993994995