Skip to content
Permalink
Browse files

8233309: implement image rendering options

  • Loading branch information
Artem Bochkarev
Artem Bochkarev committed Apr 9, 2020
1 parent 8d90ece commit 5cae755f2117d0adc242c9d92ee8b8d6a44a1998
@@ -65,9 +65,15 @@ struct TxtVertex {
float txtpos[2];
};

#define INTERPOLATION_NEAREST_NEIGHBOR 0
#define INTERPOLATION_BILINEAR 1
// NOTE: Metal samplers doesn't supports bicubic interpolation
// see table 2.7 from https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf
// (probably we need to implement separate fragment shader with bicubic interpolation)

struct TxtFrameUniforms {
vector_float4 color;
int mode;
int mode; // NOTE: consider to use bit fields
int isSrcOpaque;
int isDstOpaque;
float extraAlpha;
@@ -129,17 +129,20 @@ fragment unsigned int frag_stencil(StencilShaderInOut in [[stage_in]]) {
return in.color;
}

// NOTE:
// 1. consider to make shaders without IF-conditions
// 2. we can pass interpolation mode via uniforms and select corresponding sampler in shader
// but it can cause performance problems (something like getTextureSampler(hint) will be invoked
// for every pixel)

fragment half4 frag_txt(
TxtShaderInOut vert [[stage_in]],
texture2d<float, access::sample> renderTexture [[texture(0)]],
constant TxtFrameUniforms& uniforms [[buffer(1)]]
)
{
constexpr sampler textureSampler (mag_filter::linear,
min_filter::linear);
constant TxtFrameUniforms& uniforms [[buffer(1)]],
sampler textureSampler [[sampler(0)]]
) {
float4 pixelColor = renderTexture.sample(textureSampler, vert.texCoords);
float srcA = uniforms.isSrcOpaque ? 1 : pixelColor.a;
// TODO: consider to make shaders without IF-conditions
if (uniforms.mode) {
float4 c = mix(pixelColor, uniforms.color, srcA);
return half4(c.r, c.g, c.b , c.a);
@@ -152,12 +155,9 @@ fragment half4 frag_txt(

fragment half4 frag_txt_tp(TxtShaderInOut vert [[stage_in]],
texture2d<float, access::sample> renderTexture [[texture(0)]],
texture2d<float, access::sample> paintTexture [[texture(1)]])
{
constexpr sampler textureSampler (address::repeat,
mag_filter::nearest,
min_filter::nearest);

texture2d<float, access::sample> paintTexture [[texture(1)]],
sampler textureSampler [[sampler(0)]]
) {
float4 renderColor = renderTexture.sample(textureSampler, vert.texCoords);
float4 paintColor = paintTexture.sample(textureSampler, vert.tpCoords);
return half4(paintColor.r*renderColor.a,
@@ -187,10 +187,9 @@ fragment half4 frag_txt_grad(GradShaderInOut in [[stage_in]],
fragment half4 aa_frag_txt(
TxtShaderInOut vert [[stage_in]],
texture2d<float, access::sample> renderTexture [[texture(0)]],
constant TxtFrameUniforms& uniforms [[buffer(1)]]
)
{
constexpr sampler textureSampler (mag_filter::linear, min_filter::linear);
constant TxtFrameUniforms& uniforms [[buffer(1)]],
sampler textureSampler [[sampler(0)]]
) {
float4 pixelColor = renderTexture.sample(textureSampler, vert.texCoords);
return half4(pixelColor.r, pixelColor.g, pixelColor.b, pixelColor.a);
}
@@ -40,20 +40,27 @@
- (id<MTLRenderCommandEncoder> _Nonnull)getTextureEncoder:(const BMTLSDOps * _Nonnull)dstOps
isSrcOpaque:(bool)isSrcOpaque;

- (id<MTLRenderCommandEncoder> _Nonnull) getTextureEncoder:(id<MTLTexture> _Nonnull)dest
isSrcOpaque:(bool)isSrcOpaque
isDstOpaque:(bool)isDstOpaque;

- (id<MTLRenderCommandEncoder> _Nonnull)getTextureEncoder:(id<MTLTexture> _Nonnull)dest
isSrcOpaque:(bool)isSrcOpaque
isDstOpaque:(bool)isDstOpaque;
isDstOpaque:(bool)isDstOpaque
interpolation:(int)interpolation;

- (id<MTLRenderCommandEncoder> _Nonnull)getTextureEncoder:(id<MTLTexture> _Nonnull)dest
isSrcOpaque:(bool)isSrcOpaque
isDstOpaque:(bool)isDstOpaque
interpolation:(int)interpolation
isAA:(jboolean)isAA;

// Base method to obtain any MTLRenderCommandEncoder
- (id<MTLRenderCommandEncoder> _Nonnull)
getEncoder:(id<MTLTexture> _Nonnull)dest
isOpaque:(jboolean)isOpaque
isTexture:(jboolean)isTexture
interpolation:(int)interpolation
isAA:(jboolean)isAA
srcFlags:(const SurfaceRasterFlags *_Nullable)srcFlags;

@@ -40,6 +40,8 @@ @implementation EncoderStates {
id<MTLTexture> _destination;
SurfaceRasterFlags _dstFlags;

jboolean _isAA;

//
// Cached 'mutable' states of encoder
//
@@ -53,7 +55,7 @@ @implementation EncoderStates {

// If true, indicates that encoder is used for texture drawing (user must do [encoder setFragmentTexture:] before drawing)
jboolean _isTexture;
jboolean _isAA;
int _interpolationMode;

// Clip rect or stencil
MTLClip * _clip;
@@ -102,6 +104,7 @@ - (void)updateEncoder:(id<MTLRenderCommandEncoder>)encoder
paint:(MTLPaint *)paint
composite:(MTLComposite *)composite
isTexture:(jboolean)isTexture
interpolation:(int)interpolation
isAA:(jboolean)isAA
srcFlags:(const SurfaceRasterFlags * _Nullable)srcFlags
clip:(MTLClip *)clip
@@ -129,6 +132,7 @@ - (void)updateEncoder:(id<MTLRenderCommandEncoder>)encoder
composite:composite
isStencilUsed:[clip isShape]
isTexture:isTexture
interpolation:interpolation
isAA:isAA
srcFlags:srcFlags
forceUpdate:forceUpdate];
@@ -146,6 +150,7 @@ - (void)updatePipelineState:(id<MTLRenderCommandEncoder>)encoder
composite:(MTLComposite *)composite
isStencilUsed:(jboolean)isStencilUsed
isTexture:(jboolean)isTexture
interpolation:(int)interpolation
isAA:(jboolean)isAA
srcFlags:(const SurfaceRasterFlags * _Nullable)srcFlags
forceUpdate:(jboolean)forceUpdate
@@ -156,14 +161,15 @@ - (void)updatePipelineState:(id<MTLRenderCommandEncoder>)encoder
if (!forceUpdate
&& [_paint isEqual:paint]
&& [_composite isEqual:composite]
&& _isTexture == isTexture
&& (_isTexture == isTexture && (!isTexture || _interpolationMode == interpolation)) // interpolation is used only in texture mode
&& _isAA == isAA
&& _srcFlags.isOpaque == srcFlags->isOpaque && _srcFlags.isPremultiplied == srcFlags->isPremultiplied)
return;

[_paint copyFrom:paint];
[_composite copyFrom:composite];
_isTexture = isTexture;
_interpolationMode = interpolation;
_isAA = isAA;
_srcFlags = *srcFlags;

@@ -172,6 +178,7 @@ - (void)updatePipelineState:(id<MTLRenderCommandEncoder>)encoder
composite:_composite
isStencilUsed:isStencilUsed
isTexture:_isTexture
interpolation:interpolation
srcFlags:&_srcFlags
dstFlags:&_dstFlags
pipelineStateStorage:_pipelineStateStorage];
@@ -180,6 +187,7 @@ - (void)updatePipelineState:(id<MTLRenderCommandEncoder>)encoder
composite:_composite
isStencilUsed:isStencilUsed
isTexture:_isTexture
interpolation:interpolation
isAA:isAA
srcFlags:&_srcFlags
dstFlags:&_dstFlags
@@ -267,6 +275,7 @@ - (void)setContext:(MTLContex * _Nonnull)mtlc {
return [self getEncoder:dstTxt
isOpaque:dstOps->isOpaque
isTexture:JNI_FALSE
interpolation:INTERPOLATION_NEAREST_NEIGHBOR
isAA:JNI_TRUE
srcFlags:NULL];
}
@@ -277,40 +286,59 @@ - (void)setContext:(MTLContex * _Nonnull)mtlc {
return [self getEncoder:dest
isOpaque:isOpaque
isTexture:JNI_FALSE
interpolation:INTERPOLATION_NEAREST_NEIGHBOR
isAA:JNI_FALSE
srcFlags:NULL];
}

- (id<MTLRenderCommandEncoder> _Nonnull) getTextureEncoder:(const BMTLSDOps * _Nonnull)dstOps
isSrcOpaque:(bool)isSrcOpaque
{
return [self getTextureEncoder:dstOps->pTexture isSrcOpaque:isSrcOpaque isDstOpaque:dstOps->isOpaque];
return [self getTextureEncoder:dstOps->pTexture
isSrcOpaque:isSrcOpaque
isDstOpaque:dstOps->isOpaque
interpolation:INTERPOLATION_NEAREST_NEIGHBOR];
}

- (id<MTLRenderCommandEncoder> _Nonnull) getTextureEncoder:(id<MTLTexture> _Nonnull)dest
isSrcOpaque:(bool)isSrcOpaque
isDstOpaque:(bool)isDstOpaque
{
return [self getTextureEncoder:dest
isSrcOpaque:isSrcOpaque
isDstOpaque:isDstOpaque
interpolation:INTERPOLATION_NEAREST_NEIGHBOR
isAA:JNI_FALSE];
}

- (id<MTLRenderCommandEncoder> _Nonnull) getTextureEncoder:(id<MTLTexture> _Nonnull)dest
isSrcOpaque:(bool)isSrcOpaque
isDstOpaque:(bool)isDstOpaque
interpolation:(int)interpolation
isAA:(jboolean)isAA
{
SurfaceRasterFlags srcFlags = { isSrcOpaque, JNI_TRUE };
return [self getEncoder:dest
isOpaque:isDstOpaque
isTexture:JNI_TRUE
interpolation:interpolation
isAA:isAA
srcFlags:&srcFlags];
}

- (id<MTLRenderCommandEncoder> _Nonnull) getTextureEncoder:(id<MTLTexture> _Nonnull)dest
isSrcOpaque:(bool)isSrcOpaque
isDstOpaque:(bool)isDstOpaque
interpolation:(int)interpolation
{
return [self getTextureEncoder:dest isSrcOpaque:isSrcOpaque isDstOpaque:isDstOpaque isAA:JNI_FALSE];
return [self getTextureEncoder:dest isSrcOpaque:isSrcOpaque isDstOpaque:isDstOpaque interpolation:interpolation isAA:JNI_FALSE];
}

- (id<MTLRenderCommandEncoder> _Nonnull)
getEncoder:(id<MTLTexture> _Nonnull)dest
isOpaque:(jboolean)isOpaque
isTexture:(jboolean)isTexture
interpolation:(int)interpolation
isAA:(jboolean)isAA
srcFlags:(const SurfaceRasterFlags *_Nullable)srcFlags {
//
@@ -409,6 +437,7 @@ - (void)setContext:(MTLContex * _Nonnull)mtlc {
paint:_mtlc.paint
composite:_mtlc.composite
isTexture:isTexture
interpolation:interpolation
isAA:isAA
srcFlags:srcFlags
clip:_mtlc.clip
@@ -436,6 +465,7 @@ - (void) endEncoder {
_encoder = [self getTextureEncoder:_destination
isSrcOpaque:JNI_FALSE
isDstOpaque:JNI_TRUE
interpolation:INTERPOLATION_NEAREST_NEIGHBOR
isAA:JNI_TRUE];

struct TxtVertex quadTxVerticesBuffer[] = {
@@ -71,7 +71,7 @@ void MTLBlitTex2Tex(MTLContext *mtlc, id<MTLTexture> src, id<MTLTexture> dest);

void drawTex2Tex(MTLContext *mtlc,
id<MTLTexture> src, id<MTLTexture> dst,
jboolean isSrcOpaque, jboolean isDstOpaque,
jboolean isSrcOpaque, jboolean isDstOpaque, jint hint,
jint sx1, jint sy1, jint sx2, jint sy2,
jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2);

@@ -142,7 +142,7 @@ void fillTxQuad(

void drawTex2Tex(MTLContext *mtlc,
id<MTLTexture> src, id<MTLTexture> dst,
jboolean isSrcOpaque, jboolean isDstOpaque,
jboolean isSrcOpaque, jboolean isDstOpaque, jint hint,
jint sx1, jint sy1, jint sx2, jint sy2,
jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2)
{
@@ -155,7 +155,9 @@ void drawTex2Tex(MTLContext *mtlc,

id<MTLRenderCommandEncoder> encoder = [mtlc.encoderManager getTextureEncoder:dst
isSrcOpaque:isSrcOpaque
isDstOpaque:isDstOpaque];
isDstOpaque:isDstOpaque
interpolation:hint
];

struct TxtVertex quadTxVerticesBuffer[6];
fillTxQuad(quadTxVerticesBuffer, sx1, sy1, sx2, sy2, src.width, src.height, dx1, dy1, dx2, dy2, dst.width, dst.height);
@@ -249,7 +251,7 @@ void drawTex2Tex(MTLContext *mtlc,
static void
MTLBlitSwToTextureViaPooledTexture(
MTLContext *mtlc, SurfaceDataRasInfo *srcInfo, BMTLSDOps * bmtlsdOps,
MTLRasterFormatInfo * rfi, jboolean useBlitEncoder,
MTLRasterFormatInfo * rfi, jboolean useBlitEncoder, jint hint,
jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2)
{
const int sw = srcInfo->bounds.x2 - srcInfo->bounds.x1;
@@ -279,7 +281,7 @@ void drawTex2Tex(MTLContext *mtlc,
destinationOrigin:MTLOriginMake(dx1, dy1, 0)];
[blitEncoder endEncoding];
} else {
drawTex2Tex(mtlc, swizzledTexture != nil ? swizzledTexture : texBuff, dest, !rfi->hasAlpha, bmtlsdOps->isOpaque,
drawTex2Tex(mtlc, swizzledTexture != nil ? swizzledTexture : texBuff, dest, !rfi->hasAlpha, bmtlsdOps->isOpaque, hint,
0, 0, sw, sh, dx1, dy1, dx2, dy2);
}

@@ -485,7 +487,7 @@ jboolean clipDestCoords(
#ifdef TRACE_ISOBLIT
J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_TRUE," [via sampling]");
#endif //TRACE_ISOBLIT
drawTex2Tex(mtlc, srcTex, dstTex, srcOps->isOpaque, dstOps->isOpaque, sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);
drawTex2Tex(mtlc, srcTex, dstTex, srcOps->isOpaque, dstOps->isOpaque, hint, sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);
}

/**
@@ -613,13 +615,13 @@ jboolean clipDestCoords(
#ifdef TRACE_BLIT
J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_TRUE," [via pooled + blit]");
#endif //TRACE_BLIT
MTLBlitSwToTextureViaPooledTexture(mtlc, &srcInfo, dstOps, &rfi, true, dx1, dy1, dx2, dy2);
MTLBlitSwToTextureViaPooledTexture(mtlc, &srcInfo, dstOps, &rfi, true, hint, dx1, dy1, dx2, dy2);
}
} else { // !useReplaceRegion
#ifdef TRACE_BLIT
J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_TRUE," [via pooled texture]");
#endif //TRACE_BLIT
MTLBlitSwToTextureViaPooledTexture(mtlc, &srcInfo, dstOps, &rfi, false, dx1, dy1, dx2, dy2);
MTLBlitSwToTextureViaPooledTexture(mtlc, &srcInfo, dstOps, &rfi, false, hint, dx1, dy1, dx2, dy2);
}
}
SurfaceData_InvokeRelease(env, srcOps, &srcInfo);
@@ -99,6 +99,8 @@ @implementation MTLContext {
commandQueue, vertexBuffer,
texturePool;

extern void initSamplers(id<MTLDevice> device);

- (id)initWithDevice:(id<MTLDevice>)d shadersLib:(NSString*)shadersLib {
self = [super init];
if (self) {
@@ -131,6 +133,8 @@ - (id)initWithDevice:(id<MTLDevice>)d shadersLib:(NSString*)shadersLib {

// Create command queue
commandQueue = [device newCommandQueue];

initSamplers(device);
}
return self;
}
@@ -98,6 +98,7 @@
composite:(MTLComposite *)composite
isStencilUsed:(jboolean)isStencilUsed
isTexture:(jboolean)isTexture
interpolation:(int)interpolation
srcFlags:(const SurfaceRasterFlags *)srcFlags
dstFlags:(const SurfaceRasterFlags *)dstFlags
pipelineStateStorage:(MTLPipelineStatesStorage *)pipelineStateStorage;
@@ -106,6 +107,7 @@
composite:(MTLComposite *)composite
isStencilUsed:(jboolean)isStencilUsed
isTexture:(jboolean)isTexture
interpolation:(int)interpolation
srcFlags:(const SurfaceRasterFlags *)srcFlags
dstFlags:(const SurfaceRasterFlags *)dstFlags
pipelineStateStorage:(MTLPipelineStatesStorage *)pipelineStateStorage;

0 comments on commit 5cae755

Please sign in to comment.
You can’t perform that action at this time.