diff --git a/src/demo/share/java2d/RenderPerfTest/src/renderperf/RenderPerfTest.java b/src/demo/share/java2d/RenderPerfTest/src/renderperf/RenderPerfTest.java index cccc3482172..d29f2398ebf 100644 --- a/src/demo/share/java2d/RenderPerfTest/src/renderperf/RenderPerfTest.java +++ b/src/demo/share/java2d/RenderPerfTest/src/renderperf/RenderPerfTest.java @@ -324,6 +324,28 @@ void setPaint(Graphics2D g2d, int id) { } } + static class LinGrad3OvalRotParticleRenderer extends FlatOvalRotParticleRenderer { + + + LinGrad3OvalRotParticleRenderer(int n, float r) { + super(n, r); + } + + @Override + void setPaint(Graphics2D g2d, int id) { + Point2D start = new Point2D.Double(- r, - 0.5*r); + Point2D end = new Point2D.Double( 2 * r, r); + float[] dist = {0.0f, 0.5f, 1.0f}; + Color[] cls = { + colors[id %colors.length], + colors[(colors.length - id) %colors.length], + colors[(id*5) %colors.length]}; + LinearGradientPaint p = + new LinearGradientPaint(start, end, dist, cls); + g2d.setPaint(p); + } + } + static class FlatBoxParticleRenderer extends FlatParticleRenderer { @@ -616,6 +638,7 @@ private boolean isAlmostEqual(Color c1, Color c2) { private static final ParticleRenderer clipFlatBoxParticleRenderer = new ClipFlatBoxParticleRenderer(N, R); private static final ParticleRenderer flatBoxRotRenderer = new FlatBoxRotParticleRenderer(N, R); private static final ParticleRenderer linGradOvalRotRenderer = new LinGradOvalRotParticleRenderer(N, R); + private static final ParticleRenderer linGrad3OvalRotRenderer = new LinGrad3OvalRotParticleRenderer(N, R); private static final ParticleRenderer wiredRenderer = new WiredParticleRenderer(N, R); private static final ParticleRenderer wiredBoxRenderer = new WiredBoxParticleRenderer(N, R); private static final ParticleRenderer segRenderer = new SegParticleRenderer(N, R); @@ -694,6 +717,14 @@ public void testFlatOvalRotBubblesAA() throws Exception { (new PerfMeter("RotatedOvalAA")).exec(createPR(flatOvalRotRenderer).configure(AA)).report(); } + public void testLinGrad3OvalRotBubbles() throws Exception { + (new PerfMeter("LinGrad3RotatedOval")).exec(createPR(linGrad3OvalRotRenderer)).report(); + } + + public void testLinGrad3OvalRotBubblesAA() throws Exception { + (new PerfMeter("LinGrad3RotatedOvalAA")).exec(createPR(linGrad3OvalRotRenderer).configure(AA)).report(); + } + public void testLinGradOvalRotBubbles() throws Exception { (new PerfMeter("LinGradRotatedOval")).exec(createPR(linGradOvalRotRenderer)).report(); } diff --git a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLGraphicsConfig.java b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLGraphicsConfig.java index bc4a94555c8..9221d330dc4 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLGraphicsConfig.java +++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLGraphicsConfig.java @@ -48,6 +48,7 @@ import java.security.AccessController; import java.security.PrivilegedAction; +import static sun.java2d.metal.MTLContext.MTLContextCaps.CAPS_EXT_GRAD_SHADER; import static sun.java2d.opengl.OGLSurfaceData.TEXTURE; import static sun.java2d.pipe.hw.AccelSurface.RT_TEXTURE; import static sun.java2d.pipe.hw.ContextCapabilities.*; @@ -159,7 +160,8 @@ public static MTLGraphicsConfig getConfig(CGraphicsDevice device, ContextCapabilities caps = new MTLContext.MTLContextCaps( CAPS_PS30 | CAPS_PS20 | CAPS_RT_PLAIN_ALPHA | CAPS_RT_TEXTURE_ALPHA | CAPS_RT_TEXTURE_OPAQUE | - CAPS_MULTITEXTURE | CAPS_TEXNONPOW2 | CAPS_TEXNONSQUARE | CAPS_EXT_BIOP_SHADER, + CAPS_MULTITEXTURE | CAPS_TEXNONPOW2 | CAPS_TEXNONSQUARE | + CAPS_EXT_BIOP_SHADER | CAPS_EXT_GRAD_SHADER, ids[0]); return new MTLGraphicsConfig(device, pixfmt, cfginfo, textureSize, caps); } diff --git a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLPaints.java b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLPaints.java index 5e22758671e..96072c31693 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/metal/MTLPaints.java +++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLPaints.java @@ -193,5 +193,9 @@ boolean isPaintValid(SunGraphics2D sg2d) { private static class RadialGradient extends MultiGradient { private RadialGradient() {} + @Override + boolean isPaintValid(SunGraphics2D sg2d) { + return false; + } } } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/common.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/common.h index f777aa891cc..00e8b243ad9 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/common.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/common.h @@ -30,7 +30,13 @@ #define PGRAM_VERTEX_COUNT 6 #define QUAD_VERTEX_COUNT 4 +#define GRAD_MAX_FRACTIONS 12 +enum GradCycleMethod { + GradNoCycle = 0, + GradReflect = 1, + GradRepeat = 2 +}; enum VertexAttributes { VertexAttributePosition = 0, VertexAttributeTexPos = 1 @@ -57,6 +63,14 @@ struct GradFrameUniforms { int isCyclic; }; +struct LinGradFrameUniforms { + vector_float3 params; + float fract[GRAD_MAX_FRACTIONS]; + vector_float4 color[GRAD_MAX_FRACTIONS]; + int numFracts; + int cycleMethod; +}; + struct Vertex { float position[2]; }; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/shaders.metal b/src/java.desktop/macosx/native/libawt_lwawt/awt/shaders.metal index 25e20a9bb40..f7ff8a06a68 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/shaders.metal +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/shaders.metal @@ -221,6 +221,42 @@ fragment half4 frag_txt_grad(GradShaderInOut in [[stage_in]], renderColor.a); } +fragment half4 frag_txt_lin_grad(GradShaderInOut in [[stage_in]], + constant LinGradFrameUniforms& uniforms [[buffer(0)]], + texture2d renderTexture [[texture(0)]]) +{ + constexpr sampler textureSampler (address::repeat, mag_filter::nearest, + min_filter::nearest); + + float4 renderColor = renderTexture.sample(textureSampler, in.texCoords); + + float3 v = float3(in.position.x, in.position.y, 1); + float a = dot(v,uniforms.params); + float lf = 1.0/(uniforms.numFracts - 1); + + if (uniforms.cycleMethod > GradNoCycle) { + int fa = floor(a); + a = a - fa; + if (uniforms.cycleMethod == GradReflect && fa%2) { + a = 1.0 - a; + } + } + + int n = floor(a/lf); + if (uniforms.cycleMethod > GradNoCycle) { + n = ((n % uniforms.numFracts) + uniforms.numFracts) % uniforms.numFracts; + } else { + if (n < 0) n = 0; + if (n > uniforms.numFracts - 2) n = uniforms.numFracts - 2; + } + a = (a - n*lf)/lf; + float4 c = mix(uniforms.color[n], uniforms.color[n + 1], a); + return half4(c.r*renderColor.a, + c.g*renderColor.a, + c.b*renderColor.a, + renderColor.a); +} + fragment half4 aa_frag_txt( TxtShaderInOut vert [[stage_in]], texture2d renderTexture [[texture(0)]], @@ -372,6 +408,32 @@ fragment half4 frag_grad(GradShaderInOut in [[stage_in]], return half4(c); } +// LinGradFrameUniforms +fragment half4 frag_lin_grad(GradShaderInOut in [[stage_in]], + constant LinGradFrameUniforms& uniforms [[buffer(0)]]) { + float3 v = float3(in.position.x, in.position.y, 1); + float a = dot(v,uniforms.params); + float lf = 1.0/(uniforms.numFracts - 1); + + if (uniforms.cycleMethod > GradNoCycle) { + int fa = floor(a); + a = a - fa; + if (uniforms.cycleMethod == GradReflect && fa%2) { + a = 1.0 - a; + } + } + + int n = floor(a/lf); + if (uniforms.cycleMethod > GradNoCycle) { + n = ((n % uniforms.numFracts) + uniforms.numFracts) % uniforms.numFracts; + } else { + if (n < 0) n = 0; + if (n > uniforms.numFracts - 2) n = uniforms.numFracts - 2; + } + a = (a - n*lf)/lf; + float4 c = mix(uniforms.color[n], uniforms.color[n + 1], a); + return half4(c); +} vertex TxtShaderInOut vert_tp(VertexInput in [[stage_in]], constant AnchorData& anchorData [[buffer(FrameUniformBuffer)]], diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLContext.h b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLContext.h index 014b1aa0d2b..a4ab4058741 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLContext.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLContext.h @@ -217,13 +217,13 @@ pixel2:(jint) pixel2; - (void)setLinearGradientPaint:(jboolean)useMask linear:(jboolean)linear - cycleMethod:(jboolean)cycleMethod + cycleMethod:(jint)cycleMethod numStops:(jint)numStops p0:(jfloat)p0 p1:(jfloat)p1 p3:(jfloat)p3 - fractions:(void *)fractions - pixels:(void *)pixels; + fractions:(jfloat *)fractions + pixels:(jint *)pixels; - (void)setRadialGradientPaint:(jboolean)useMask linear:(jboolean)linear cycleMethod:(jboolean)cycleMethod diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLContext.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLContext.m index b3af145ad5c..bab5a4fb607 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLContext.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLContext.m @@ -336,13 +336,17 @@ - (void)setGradientPaintUseMask:(jboolean)useMask - (void)setLinearGradientPaint:(jboolean)useMask linear:(jboolean)linear - cycleMethod:(jboolean)cycleMethod + cycleMethod:(jint)cycleMethod + // 0 - NO_CYCLE + // 1 - REFLECT + // 2 - REPEAT + numStops:(jint)numStops p0:(jfloat)p0 p1:(jfloat)p1 p3:(jfloat)p3 - fractions:(void *)fractions - pixels:(void *)pixels + fractions:(jfloat*)fractions + pixels:(jint*)pixels { J2dTraceLn(J2D_TRACE_INFO, "MTLContext.setLinearGradientPaint"); [_paint setLinearGradient:useMask diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPaints.h b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPaints.h index 886f7a8c9bf..78e04f630ee 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPaints.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPaints.h @@ -64,8 +64,8 @@ p0:(jfloat)p0 p1:(jfloat)p1 p3:(jfloat)p3 - fractions:(void *)fractions - pixels:(void *)pixels; + fractions:(jfloat *)fractions + pixels:(jint *)pixels; - (void)setRadialGradient:(jboolean)useMask linear:(jboolean)linear diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPaints.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPaints.m index 5b35da19528..bce6d13fbee 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPaints.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPaints.m @@ -104,9 +104,10 @@ @implementation MTLPaint { jdouble _p0; jdouble _p1; jdouble _p3; - jboolean _cyclic; - jint _pixel1; - jint _pixel2; + jint _cyclic; + jint _pixel[GRAD_MAX_FRACTIONS]; + jfloat _fract[GRAD_MAX_FRACTIONS]; + jint _numFracts; jboolean _useMask; // texture paint @@ -133,9 +134,24 @@ - (BOOL)isEqual:(MTLPaint *)other { return _p0 == other->_p0 && _p1 == other->_p1 && _p3 == other->_p3 - && _pixel1 == other->_pixel1 - && _pixel2 == other->_pixel2; + && _pixel[0] == other->_pixel[0] + && _pixel[1] == other->_pixel[1]; } + + if (_paintState == sun_java2d_SunGraphics2D_PAINT_LIN_GRADIENT) { + if (_p0 != other->_p0 + || _p1 != other->_p1 + || _p3 != other->_p3 + || _numFracts != other->_numFracts) return NO; + + + for (int i = 0; i < _numFracts; i++) { + if (_fract[i] != other->_fract[i]) return NO; + if (_pixel[i] != other->_pixel[i]) return NO; + } + return YES; + } + if (_paintState == sun_java2d_SunGraphics2D_PAINT_ALPHACOLOR) { return _color == other->_color; } @@ -162,10 +178,23 @@ - (void)copyFrom:(MTLPaint *)other { _p0 = other->_p0; _p1 = other->_p1; _p3 = other->_p3; - _pixel1 = other->_pixel1; - _pixel2 = other->_pixel2; + _pixel[0] = other->_pixel[0]; + _pixel[1] = other->_pixel[1]; + return; + } + + if (other->_paintState == sun_java2d_SunGraphics2D_PAINT_LIN_GRADIENT) { + + _p0 = other->_p0; + _p1 = other->_p1; + _p3 = other->_p3; + _cyclic = other->_cyclic; + memcpy(_fract, other->_fract, other->_numFracts*sizeof(jfloat)); + memcpy(_pixel, other->_pixel, other->_numFracts*sizeof(jint)); + _numFracts = other->_numFracts; return; } + if (_paintState == sun_java2d_SunGraphics2D_PAINT_ALPHACOLOR) { _color = other->_color; return; @@ -190,6 +219,10 @@ - (NSString *)getDescription { return [NSString stringWithFormat:@"gradient"]; } + if (_paintState == sun_java2d_SunGraphics2D_PAINT_LIN_GRADIENT) { + return [NSString stringWithFormat:@"linear_gradient"]; + } + if (_paintState == sun_java2d_SunGraphics2D_PAINT_TEXTURE) { return [NSString stringWithFormat:@"texture_paint"]; } @@ -231,8 +264,8 @@ - (void)setGradientUseMask:(jboolean)useMask _paintState = sun_java2d_SunGraphics2D_PAINT_GRADIENT; _useMask = useMask; - _pixel1 = pixel1; - _pixel2 = pixel2; + _pixel[0] = pixel1; + _pixel[1] = pixel2; _p0 = p0; _p1 = p1; _p3 = p3; @@ -246,11 +279,20 @@ - (void)setLinearGradient:(jboolean)useMask p0:(jfloat)p0 p1:(jfloat)p1 p3:(jfloat)p3 - fractions:(void *)fractions - pixels:(void *)pixels + fractions:(jfloat*)fractions + pixels:(jint*)pixels { J2dTraceLn(J2D_TRACE_ERROR, "setLinearGradient: UNIMPLEMENTED"); - [self setColor:0]; + _paintState = sun_java2d_SunGraphics2D_PAINT_LIN_GRADIENT; + _useMask = useMask; + memcpy(_fract, fractions, numStops*sizeof(jfloat)); + memcpy(_pixel, pixels, numStops*sizeof(jint)); + _p0 = p0; + _p1 = p1; + _p3 = p3; + _cyclic = cycleMethod; + _numFracts = numStops; + } - (void)setRadialGradient:(jboolean)useMask @@ -415,15 +457,36 @@ - (void)setPipelineState:(id)encoder setTxtUniforms(encoder, 0, 0, renderOptions->interpolation, YES, [mtlc.composite getExtraAlpha], &renderOptions->srcFlags, &renderOptions->dstFlags); } else if (_paintState == sun_java2d_SunGraphics2D_PAINT_GRADIENT) { + // Gradient paint in AA mode vertShader = @"vert_txt_grad"; fragShader = @"frag_txt_grad"; struct GradFrameUniforms uf = { {_p0, _p1, _p3}, - RGBA_TO_V4(_pixel1), - RGBA_TO_V4(_pixel2), + RGBA_TO_V4(_pixel[0]), + RGBA_TO_V4(_pixel[1]), _cyclic}; [encoder setFragmentBytes:&uf length:sizeof(uf) atIndex:0]; + } else if (_paintState == sun_java2d_SunGraphics2D_PAINT_LIN_GRADIENT) { + // Linear gradient paint in AA mode + vertShader = @"vert_txt_grad"; + fragShader = @"frag_txt_lin_grad"; + + struct LinGradFrameUniforms uf = { + {_p0, _p1, _p3}, + {}, + {}, + _numFracts, + _cyclic + }; + + memcpy(uf.fract, _fract, _numFracts*sizeof(jfloat)); + for (int i = 0; i < _numFracts; i++) { + vector_float4 v = RGBA_TO_V4(_pixel[i]); + uf.color[i] = v; + } + [encoder setFragmentBytes:&uf length:sizeof(uf) atIndex:0]; + } else { vertShader = @"vert_txt"; fragShader = @"frag_txt"; @@ -451,11 +514,30 @@ - (void)setPipelineState:(id)encoder struct GradFrameUniforms uf = { {_p0, _p1, _p3}, - RGBA_TO_V4(_pixel1), - RGBA_TO_V4(_pixel2), + RGBA_TO_V4(_pixel[0]), + RGBA_TO_V4(_pixel[1]), + _cyclic + }; + [encoder setFragmentBytes:&uf length:sizeof(uf) atIndex:0]; + } else if (_paintState == sun_java2d_SunGraphics2D_PAINT_LIN_GRADIENT) { + vertShader = @"vert_grad"; + fragShader = @"frag_lin_grad"; + + struct LinGradFrameUniforms uf = { + {_p0, _p1, _p3}, + {}, + {}, + _numFracts, _cyclic }; + + memcpy(uf.fract, _fract, _numFracts*sizeof(jfloat)); + for (int i = 0; i < _numFracts; i++) { + vector_float4 v = RGBA_TO_V4(_pixel[i]); + uf.color[i] = v; + } [encoder setFragmentBytes:&uf length:sizeof(uf) atIndex:0]; + } else if (_paintState == sun_java2d_SunGraphics2D_PAINT_TEXTURE) { vertShader = @"vert_tp"; fragShader = @"frag_tp"; @@ -527,8 +609,8 @@ - (void)setXorModePipelineState:(id)encoder struct GradFrameUniforms uf = { {_p0, _p1, _p3}, - RGBA_TO_V4(_pixel1 ^ xorColor), - RGBA_TO_V4(_pixel2 ^ xorColor), + RGBA_TO_V4(_pixel[0] ^ xorColor), + RGBA_TO_V4(_pixel[1] ^ xorColor), _cyclic };