Skip to content
Permalink
Browse files

8252386: Lanai: Implement RadialGradientPaint in shader

  • Loading branch information
Alexey Ushakov committed Sep 3, 2020
1 parent d3bbb05 commit db306e2f0938b67d07cc79a074fc578effea2e88
@@ -346,6 +346,27 @@ void setPaint(Graphics2D g2d, int id) {
}
}

static class RadGrad3OvalRotParticleRenderer extends FlatOvalRotParticleRenderer {


RadGrad3OvalRotParticleRenderer(int n, float r) {
super(n, r);
}

@Override
void setPaint(Graphics2D g2d, int id) {
Point2D start = new Point2D.Double();
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]};
RadialGradientPaint p =
new RadialGradientPaint(start, r, dist, cls);
g2d.setPaint(p);
}
}

static class FlatBoxParticleRenderer extends FlatParticleRenderer {


@@ -639,6 +660,7 @@ private boolean isAlmostEqual(Color c1, Color c2) {
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 radGrad3OvalRotRenderer = new RadGrad3OvalRotParticleRenderer(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);
@@ -725,6 +747,14 @@ public void testLinGrad3OvalRotBubblesAA() throws Exception {
(new PerfMeter("LinGrad3RotatedOvalAA")).exec(createPR(linGrad3OvalRotRenderer).configure(AA)).report();
}

public void testRadGrad3OvalRotBubbles() throws Exception {
(new PerfMeter("RadGrad3RotatedOval")).exec(createPR(radGrad3OvalRotRenderer)).report();
}

public void testRadGrad3OvalRotBubblesAA() throws Exception {
(new PerfMeter("RadGrad3RotatedOvalAA")).exec(createPR(radGrad3OvalRotRenderer).configure(AA)).report();
}

public void testLinGradOvalRotBubbles() throws Exception {
(new PerfMeter("LinGradRotatedOval")).exec(createPR(linGradOvalRotRenderer)).report();
}
@@ -193,9 +193,5 @@ boolean isPaintValid(SunGraphics2D sg2d) {

private static class RadialGradient extends MultiGradient {
private RadialGradient() {}
@Override
boolean isPaintValid(SunGraphics2D sg2d) {
return false;
}
}
}
@@ -71,6 +71,16 @@ struct LinGradFrameUniforms {
int cycleMethod;
};

struct RadGradFrameUniforms {
float fract[GRAD_MAX_FRACTIONS];
vector_float4 color[GRAD_MAX_FRACTIONS];
int numFracts;
int cycleMethod;
vector_float3 m0;
vector_float3 m1;
vector_float3 precalc;
};

struct Vertex {
float position[2];
};
@@ -257,6 +257,47 @@ fragment half4 frag_txt_lin_grad(GradShaderInOut in [[stage_in]],
renderColor.a);
}

fragment half4 frag_txt_rad_grad(GradShaderInOut in [[stage_in]],
constant RadGradFrameUniforms& uniforms [[buffer(0)]],
texture2d<float, access::sample> renderTexture [[texture(0)]])
{
constexpr sampler textureSampler (address::repeat, mag_filter::nearest,
min_filter::nearest);

float4 renderColor = renderTexture.sample(textureSampler, in.texCoords);

float3 fragCoord = float3(in.position.x+0.5, in.position.y-0.5, 1);
float x = dot(fragCoord, uniforms.m0);
float y = dot(fragCoord, uniforms.m1);
float xfx = x - uniforms.precalc.x;
float a = (uniforms.precalc.x*xfx + sqrt(xfx*xfx + y*y*uniforms.precalc.y))*uniforms.precalc.z;

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<float, access::sample> renderTexture [[texture(0)]],
@@ -435,6 +476,37 @@ fragment half4 frag_lin_grad(GradShaderInOut in [[stage_in]],
return half4(c);
}

fragment half4 frag_rad_grad(GradShaderInOut in [[stage_in]],
constant RadGradFrameUniforms& uniforms [[buffer(0)]]) {
float3 fragCoord = float3(in.position.x+0.5, in.position.y-0.5, 1);
float x = dot(fragCoord, uniforms.m0);
float y = dot(fragCoord, uniforms.m1);
float xfx = x - uniforms.precalc.x;
float a = (uniforms.precalc.x*xfx + sqrt(xfx*xfx + y*y*uniforms.precalc.y))*uniforms.precalc.z;

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)]],
constant TransformMatrix& transform [[buffer(MatrixBuffer)]])
@@ -69,7 +69,7 @@

- (void)setRadialGradient:(jboolean)useMask
linear:(jboolean)linear
cycleMethod:(jboolean)cycleMethod
cycleMethod:(jint)cycleMethod
numStops:(jint)numStops
m00:(jfloat)m00
m01:(jfloat)m01
@@ -100,16 +100,27 @@ @implementation MTLPaint {
// color-mode
jint _color;

// lin-grad-mode
// grad-mode
jdouble _p0;
jdouble _p1;
jdouble _p3;
jint _cyclic;
jboolean _useMask;
jint _pixel[GRAD_MAX_FRACTIONS];
jfloat _fract[GRAD_MAX_FRACTIONS];
jint _numFracts;
jboolean _useMask;

// lin-grad-mode
jint _numFracts;
jboolean _linear;

// rad-grad-mode
jfloat _m00;
jfloat _m01;
jfloat _m02;
jfloat _m10;
jfloat _m11;
jfloat _m12;
jfloat _focusX;
// texture paint
id<MTLTexture> _paintTexture;
struct AnchorData _anchor;
@@ -152,6 +163,24 @@ - (BOOL)isEqual:(MTLPaint *)other {
return YES;
}

if (_paintState == sun_java2d_SunGraphics2D_PAINT_RAD_GRADIENT) {
if (_m00 != other->_m00
|| _m01 != other->_m01
|| _m02 != other->_m02
|| _m10 != other->_m10
|| _m11 != other->_m11
|| _m12 != other->_m12
|| _focusX != other->_focusX
|| _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;
}
@@ -195,6 +224,22 @@ - (void)copyFrom:(MTLPaint *)other {
return;
}

if (other->_paintState == sun_java2d_SunGraphics2D_PAINT_RAD_GRADIENT) {

_m00 = other->_m00;
_m01 = other->_m01;
_m02 = other->_m02;
_m10 = other->_m10;
_m11 = other->_m11;
_m12 = other->_m12;
_focusX = other->_focusX;
_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;
@@ -223,6 +268,10 @@ - (NSString *)getDescription {
return [NSString stringWithFormat:@"linear_gradient"];
}

if (_paintState == sun_java2d_SunGraphics2D_PAINT_RAD_GRADIENT) {
return [NSString stringWithFormat:@"radial_gradient"];
}

if (_paintState == sun_java2d_SunGraphics2D_PAINT_TEXTURE) {
return [NSString stringWithFormat:@"texture_paint"];
}
@@ -254,14 +303,6 @@ - (void)setGradientUseMask:(jboolean)useMask
pixel1:(jint)pixel1
pixel2:(jint)pixel2
{
//TODO Resolve gradient distribution problem
//TODO Implement useMask
//TODO Implement cyclic
//fprintf(stderr,
// "MTLPaints_SetGradientPaint useMask=%d cyclic=%d "
// "p0=%f p1=%f p3=%f pix1=%d pix2=%d\n", useMask, cyclic,
// p0, p1, p3, pixel1, pixel2);

_paintState = sun_java2d_SunGraphics2D_PAINT_GRADIENT;
_useMask = useMask;
_pixel[0] = pixel1;
@@ -282,22 +323,21 @@ - (void)setLinearGradient:(jboolean)useMask
fractions:(jfloat*)fractions
pixels:(jint*)pixels
{
J2dTraceLn(J2D_TRACE_ERROR, "setLinearGradient: UNIMPLEMENTED");
_paintState = sun_java2d_SunGraphics2D_PAINT_LIN_GRADIENT;
_useMask = useMask;
_linear = linear; // TODO: to be implemented
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
linear:(jboolean)linear
cycleMethod:(jboolean)cycleMethod
cycleMethod:(jint)cycleMethod
numStops:(jint)numStops
m00:(jfloat)m00
m01:(jfloat)m01
@@ -309,8 +349,19 @@ - (void)setRadialGradient:(jboolean)useMask
fractions:(void *)fractions
pixels:(void *)pixels
{
J2dTraceLn(J2D_TRACE_ERROR, "setRadialGradient: UNIMPLEMENTED");
[self setColor:0];
_paintState = sun_java2d_SunGraphics2D_PAINT_RAD_GRADIENT;
_useMask = useMask;
_cyclic = cycleMethod;
_numFracts = numStops;
memcpy(_fract, fractions, numStops * sizeof(jfloat));
memcpy(_pixel, pixels, numStops * sizeof(jint));
_m00 = m00;
_m01 = m01;
_m02 = m02;
_m10 = m10;
_m11 = m11;
_m12 = m12;
_focusX = focusX;
}

- (void)setTexture:(jboolean)useMask
@@ -486,7 +537,30 @@ - (void)setPipelineState:(id<MTLRenderCommandEncoder>)encoder
uf.color[i] = v;
}
[encoder setFragmentBytes:&uf length:sizeof(uf) atIndex:0];
} else if (_paintState == sun_java2d_SunGraphics2D_PAINT_RAD_GRADIENT) {
vertShader = @"vert_txt_grad";
fragShader = @"frag_txt_rad_grad";

struct RadGradFrameUniforms uf = {
{},
{},
_numFracts,
_cyclic,
{_m00, _m01, _m02},
{_m10, _m11, _m12},
{}
};

uf.precalc[0] = _focusX;
uf.precalc[1] = 1.0 - (_focusX * _focusX);
uf.precalc[2] = 1.0 / uf.precalc[1];

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";
@@ -538,6 +612,31 @@ - (void)setPipelineState:(id<MTLRenderCommandEncoder>)encoder
}
[encoder setFragmentBytes:&uf length:sizeof(uf) atIndex:0];

} else if (_paintState == sun_java2d_SunGraphics2D_PAINT_RAD_GRADIENT) {
vertShader = @"vert_grad";
fragShader = @"frag_rad_grad";

struct RadGradFrameUniforms uf = {
{},
{},
_numFracts,
_cyclic,
{_m00, _m01, _m02},
{_m10, _m11, _m12},
{}
};

uf.precalc[0] = _focusX;
uf.precalc[1] = 1.0 - (_focusX * _focusX);
uf.precalc[2] = 1.0 / uf.precalc[1];

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";

0 comments on commit db306e2

Please sign in to comment.