Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
S
skiko
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
liuqiang
skiko
Commits
e28b5fea
Unverified
Commit
e28b5fea
authored
Apr 01, 2022
by
Kirill Grouchnikov
Committed by
GitHub
Apr 01, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add bindings for SkImageFilters::RuntimeShader (#520)
For
https://github.com/JetBrains/skiko/issues/519
parent
82bfb2d6
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
284 additions
and
1 deletion
+284
-1
ImageFilter.kt
...o/src/commonMain/kotlin/org/jetbrains/skia/ImageFilter.kt
+45
-0
RuntimeShaderBuilder.kt
...monMain/kotlin/org/jetbrains/skia/RuntimeShaderBuilder.kt
+53
-0
ImageFilterTest.kt
...c/commonTest/kotlin/org/jetbrains/skia/ImageFilterTest.kt
+61
-1
ImageFilter.cc
skiko/src/jvmMain/cpp/common/ImageFilter.cc
+31
-0
RuntimeShaderBuilder.cc
skiko/src/jvmMain/cpp/common/RuntimeShaderBuilder.cc
+35
-0
ImageFilter.cc
skiko/src/nativeJsMain/cpp/ImageFilter.cc
+29
-0
RuntimeShaderBuilder.cc
skiko/src/nativeJsMain/cpp/RuntimeShaderBuilder.cc
+30
-0
No files found.
skiko/src/commonMain/kotlin/org/jetbrains/skia/ImageFilter.kt
View file @
e28b5fea
...
...
@@ -381,6 +381,47 @@ class ImageFilter internal constructor(ptr: NativePointer) : RefCnt(ptr) {
}
}
fun
makeRuntimeShader
(
runtimeShaderBuilder
:
RuntimeShaderBuilder
,
shaderName
:
String
,
input
:
ImageFilter
?):
ImageFilter
{
return
try
{
Stats
.
onNativeCall
()
interopScope
{
ImageFilter
(
_nMakeRuntimeShader
(
runtimeShaderBuilderPtr
=
getPtr
(
runtimeShaderBuilder
),
childShaderName
=
toInterop
(
shaderName
),
input
=
getPtr
(
input
)
)
)
}
}
finally
{
reachabilityBarrier
(
runtimeShaderBuilder
)
reachabilityBarrier
(
input
)
}
}
fun
makeRuntimeShader
(
runtimeShaderBuilder
:
RuntimeShaderBuilder
,
shaderNames
:
Array
<
String
>,
inputs
:
Array
<
ImageFilter
?
>):
ImageFilter
{
return
try
{
Stats
.
onNativeCall
()
require
(
shaderNames
.
size
==
inputs
.
size
)
interopScope
{
val
inputPtrs
=
NativePointerArray
(
inputs
.
size
)
for
(
i
in
inputs
.
indices
)
inputPtrs
[
i
]
=
getPtr
(
inputs
[
i
])
ImageFilter
(
_nMakeRuntimeShaderFromArray
(
runtimeShaderBuilderPtr
=
getPtr
(
runtimeShaderBuilder
),
childShaderNames
=
toInterop
(
shaderNames
),
inputs
=
toInterop
(
inputPtrs
),
inputLength
=
inputPtrs
.
size
)
)
}
}
finally
{
reachabilityBarrier
(
runtimeShaderBuilder
)
reachabilityBarrier
(
inputs
)
}
}
fun
makeTile
(
src
:
Rect
,
dst
:
Rect
,
input
:
ImageFilter
?):
ImageFilter
{
return
try
{
Stats
.
onNativeCall
()
...
...
@@ -753,6 +794,10 @@ private external fun _nMakeOffset(dx: Float, dy: Float, input: NativePointer, cr
private
external
fun
_nMakePaint
(
paint
:
NativePointer
,
crop
:
InteropPointer
):
NativePointer
@ExternalSymbolName
(
"org_jetbrains_skia_ImageFilter__1nMakePicture"
)
private
external
fun
_nMakePicture
(
picture
:
NativePointer
,
l
:
Float
,
t
:
Float
,
r
:
Float
,
b
:
Float
):
NativePointer
@ExternalSymbolName
(
"org_jetbrains_skia_ImageFilter__1nMakeRuntimeShader"
)
private
external
fun
_nMakeRuntimeShader
(
runtimeShaderBuilderPtr
:
NativePointer
,
childShaderName
:
InteropPointer
,
input
:
NativePointer
):
NativePointer
@ExternalSymbolName
(
"org_jetbrains_skia_ImageFilter__1nMakeRuntimeShaderFromArray"
)
private
external
fun
_nMakeRuntimeShaderFromArray
(
runtimeShaderBuilderPtr
:
NativePointer
,
childShaderNames
:
InteropPointer
,
inputs
:
InteropPointer
,
inputLength
:
Int
):
NativePointer
@ExternalSymbolName
(
"org_jetbrains_skia_ImageFilter__1nMakeTile"
)
private
external
fun
_nMakeTile
(
l0
:
Float
,
...
...
skiko/src/commonMain/kotlin/org/jetbrains/skia/RuntimeShaderBuilder.kt
0 → 100644
View file @
e28b5fea
package
org.jetbrains.skia
import
org.jetbrains.skia.impl.*
import
org.jetbrains.skia.impl.Library.Companion.staticLoad
import
org.jetbrains.skia.impl.Managed
import
org.jetbrains.skia.impl.Native.Companion.NullPointer
import
org.jetbrains.skia.impl.NativePointer
import
org.jetbrains.skia.impl.Stats
import
org.jetbrains.skia.impl.interopScope
import
org.jetbrains.skia.impl.reachabilityBarrier
class
RuntimeShaderBuilder
internal
constructor
(
ptr
:
NativePointer
)
:
Managed
(
ptr
,
_FinalizerHolder
.
PTR
)
{
companion
object
{
init
{
staticLoad
()
}
}
constructor
(
effect
:
RuntimeEffect
)
:
this
(
_nMakeFromRuntimeEffect
(
effect
.
_ptr
))
{
Stats
.
onNativeCall
()
reachabilityBarrier
(
effect
)
}
private
object
_FinalizerHolder
{
val
PTR
=
RuntimeShaderBuilder_nGetFinalizer
()
}
fun
uniform
(
name
:
String
,
value
:
Int
)
{
Stats
.
onNativeCall
()
interopScope
{
_nUniformInt
(
_ptr
,
toInterop
(
name
),
value
)
}
}
fun
uniform
(
name
:
String
,
value
:
Float
)
{
Stats
.
onNativeCall
()
interopScope
{
_nUniformFloat
(
_ptr
,
toInterop
(
name
),
value
)
}
}
}
@ExternalSymbolName
(
"org_jetbrains_skia_RuntimeShaderBuilder__1nMakeFromRuntimeEffect"
)
private
external
fun
_nMakeFromRuntimeEffect
(
effectPtr
:
NativePointer
):
NativePointer
@ExternalSymbolName
(
"org_jetbrains_skia_RuntimeShaderBuilder__1nGetFinalizer"
)
private
external
fun
RuntimeShaderBuilder_nGetFinalizer
():
NativePointer
@ExternalSymbolName
(
"org_jetbrains_skia_RuntimeShaderBuilder__1nUniformInt"
)
private
external
fun
_nUniformInt
(
builderPtr
:
NativePointer
,
uniformName
:
InteropPointer
,
uniformValue
:
Int
)
@ExternalSymbolName
(
"org_jetbrains_skia_RuntimeShaderBuilder__1nUniformFloat"
)
private
external
fun
_nUniformFloat
(
builderPtr
:
NativePointer
,
uniformName
:
InteropPointer
,
uniformValue
:
Float
)
skiko/src/commonTest/kotlin/org/jetbrains/skia/ImageFilterTest.kt
View file @
e28b5fea
...
...
@@ -3,7 +3,6 @@ package org.jetbrains.skia
import
org.jetbrains.skia.impl.use
import
org.jetbrains.skia.util.assertContentDifferent
import
org.jetbrains.skiko.tests.runTest
import
kotlin.test.Ignore
import
kotlin.test.Test
import
kotlin.test.assertEquals
...
...
@@ -224,6 +223,67 @@ class ImageFilterTest {
)
}
@Test
fun
makeRuntimeShader
()
=
imageFilterTest
{
// A simple Skia shader that bumps up the red channel of every non-transparent
// pixel to full intensity, and leaves green and blue channels unchanged.
val
redSksl
=
"""
uniform shader content;
vec4 main(vec2 coord) {
vec4 c = content.eval(coord);
return vec4(1.0 * c.a, c.g * c.a, c.b * c.a, c.a);
}
"""
val
redRuntimeEffect
=
RuntimeEffect
.
makeForShader
(
redSksl
)
val
redShaderBuilder
=
RuntimeShaderBuilder
(
redRuntimeEffect
)
ImageFilter
.
makeRuntimeShader
(
runtimeShaderBuilder
=
redShaderBuilder
,
shaderName
=
"content"
,
input
=
null
)
}
@Test
fun
makeRuntimeShaderFromArrays
()
=
imageFilterTest
{
// A Skia shader that has two children shaders - one that applies our custom shader logic
// on the underlying render node content, and another that is the built in blur. This
// shader also has a float uniform that is used to decide which one of these two children
// shaders to apply on a given pixel, based on the X coordinate.
// This test covers not only ImageFilter.makeRuntimeShader API, but also
// RuntimeShaderBuilder.uniform.
val
compositeSksl
=
"""
uniform shader content;
uniform shader blurred;
uniform float cutoff;
vec4 main(vec2 coord) {
vec4 c = content.eval(coord);
vec4 b = blurred.eval(coord);
if (coord.x > cutoff) {
return vec4(1.0 * c.a, c.g * c.a, c.b * c.a, c.a);
} else {
return b;
}
}
"""
val
compositeRuntimeEffect
=
RuntimeEffect
.
makeForShader
(
compositeSksl
)
val
compositeShaderBuilder
=
RuntimeShaderBuilder
(
compositeRuntimeEffect
)
// Pass a float uniform into our shader
compositeShaderBuilder
.
uniform
(
"cutoff"
,
10.0f
)
// And use ImageFilter.makeBlur as the second child input to our composite shader
val
blurImageFilter
=
ImageFilter
.
makeBlur
(
sigmaX
=
2.0f
,
sigmaY
=
2.0f
,
mode
=
FilterTileMode
.
DECAL
)
ImageFilter
.
makeRuntimeShader
(
runtimeShaderBuilder
=
compositeShaderBuilder
,
shaderNames
=
arrayOf
(
"content"
,
"blurred"
),
inputs
=
arrayOf
(
null
,
blurImageFilter
)
)
}
@Test
fun
makeTile
()
=
imageFilterTest
{
ImageFilter
.
makeTile
(
...
...
skiko/src/jvmMain/cpp/common/ImageFilter.cc
View file @
e28b5fea
...
...
@@ -160,6 +160,37 @@ extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_ImageFilterKt__1nMake
return
reinterpret_cast
<
jlong
>
(
ptr
);
}
extern
"C"
JNIEXPORT
jlong
JNICALL
Java_org_jetbrains_skia_ImageFilterKt__1nMakeRuntimeShader
(
JNIEnv
*
env
,
jclass
jclass
,
jlong
runtimeShaderBuilderPtr
,
jstring
childShaderName
,
jlong
inputPtr
)
{
SkRuntimeShaderBuilder
*
runtimeShaderBuilder
=
reinterpret_cast
<
SkRuntimeShaderBuilder
*>
(
static_cast
<
uintptr_t
>
(
runtimeShaderBuilderPtr
));
SkImageFilter
*
input
=
reinterpret_cast
<
SkImageFilter
*>
(
static_cast
<
uintptr_t
>
(
inputPtr
));
SkImageFilter
*
ptr
=
SkImageFilters
::
RuntimeShader
(
*
runtimeShaderBuilder
,
skString
(
env
,
childShaderName
).
c_str
(),
sk_ref_sp
(
input
)).
release
();
return
reinterpret_cast
<
jlong
>
(
ptr
);
}
extern
"C"
JNIEXPORT
jlong
JNICALL
Java_org_jetbrains_skia_ImageFilterKt__1nMakeRuntimeShaderFromArray
(
JNIEnv
*
env
,
jclass
jclass
,
jlong
runtimeShaderBuilderPtr
,
jobjectArray
childShaderNamesArr
,
jlongArray
inputPtrsArray
,
jint
_inputCount
)
{
SkRuntimeShaderBuilder
*
runtimeShaderBuilder
=
reinterpret_cast
<
SkRuntimeShaderBuilder
*>
(
static_cast
<
uintptr_t
>
(
runtimeShaderBuilderPtr
));
jsize
inputCount
=
env
->
GetArrayLength
(
inputPtrsArray
);
jlong
*
inputPtrs
=
env
->
GetLongArrayElements
(
inputPtrsArray
,
0
);
std
::
vector
<
sk_sp
<
SkImageFilter
>>
inputChildren
(
inputCount
);
for
(
int
i
=
0
;
i
<
inputCount
;
++
i
)
{
SkImageFilter
*
filter
=
reinterpret_cast
<
SkImageFilter
*>
(
static_cast
<
uintptr_t
>
(
inputPtrs
[
i
]));
inputChildren
[
i
]
=
sk_ref_sp
(
filter
);
}
env
->
ReleaseLongArrayElements
(
inputPtrsArray
,
inputPtrs
,
0
);
std
::
vector
<
SkString
>
childShaderNameStrings
=
skStringVector
(
env
,
childShaderNamesArr
);
std
::
vector
<
const
char
*>
childShaderNames
(
childShaderNameStrings
.
size
());
for
(
int
i
=
0
;
i
<
inputCount
;
++
i
)
childShaderNames
[
i
]
=
childShaderNameStrings
[
i
].
c_str
();
SkImageFilter
*
ptr
=
SkImageFilters
::
RuntimeShader
(
*
runtimeShaderBuilder
,
childShaderNames
.
data
(),
inputChildren
.
data
(),
inputCount
).
release
();
return
reinterpret_cast
<
jlong
>
(
ptr
);
}
extern
"C"
JNIEXPORT
jlong
JNICALL
Java_org_jetbrains_skia_ImageFilterKt__1nMakeTile
(
JNIEnv
*
env
,
jclass
jclass
,
jfloat
l0
,
jfloat
t0
,
jfloat
r0
,
jfloat
b0
,
jfloat
l1
,
jfloat
t1
,
jfloat
r1
,
jfloat
b1
,
jlong
inputPtr
)
{
SkImageFilter
*
input
=
reinterpret_cast
<
SkImageFilter
*>
(
static_cast
<
uintptr_t
>
(
inputPtr
));
...
...
skiko/src/jvmMain/cpp/common/RuntimeShaderBuilder.cc
0 → 100644
View file @
e28b5fea
#include <jni.h>
#include "SkRuntimeEffect.h"
#include "interop.hh"
static
void
deleteRuntimeShaderBuilder
(
SkRuntimeShaderBuilder
*
builder
)
{
delete
builder
;
}
extern
"C"
JNIEXPORT
jlong
JNICALL
Java_org_jetbrains_skia_RuntimeShaderBuilderKt_RuntimeShaderBuilder_1nGetFinalizer
(
JNIEnv
*
env
,
jclass
jclass
)
{
return
static_cast
<
jlong
>
(
reinterpret_cast
<
uintptr_t
>
(
&
deleteRuntimeShaderBuilder
));
}
extern
"C"
JNIEXPORT
jlong
JNICALL
Java_org_jetbrains_skia_RuntimeShaderBuilderKt__1nMakeFromRuntimeEffect
(
JNIEnv
*
env
,
jclass
jclass
,
jlong
effectPtr
)
{
sk_sp
<
SkRuntimeEffect
>
runtimeEffect
=
sk_ref_sp
<
SkRuntimeEffect
>
(
reinterpret_cast
<
SkRuntimeEffect
*>
(
static_cast
<
uintptr_t
>
(
effectPtr
)));
SkRuntimeShaderBuilder
*
builder
=
new
SkRuntimeShaderBuilder
(
runtimeEffect
);
return
reinterpret_cast
<
jlong
>
(
builder
);
}
extern
"C"
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skia_RuntimeShaderBuilderKt__1nUniformInt
(
JNIEnv
*
env
,
jclass
jclass
,
jlong
builderPtr
,
jstring
uniformName
,
jint
uniformValue
)
{
SkRuntimeShaderBuilder
*
runtimeShaderBuilder
=
jlongToPtr
<
SkRuntimeShaderBuilder
*>
(
builderPtr
);
runtimeShaderBuilder
->
uniform
(
skString
(
env
,
uniformName
).
c_str
())
=
uniformValue
;
}
extern
"C"
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skia_RuntimeShaderBuilderKt__1nUniformFloat
(
JNIEnv
*
env
,
jclass
jclass
,
jlong
builderPtr
,
jstring
uniformName
,
jfloat
uniformValue
)
{
SkRuntimeShaderBuilder
*
runtimeShaderBuilder
=
jlongToPtr
<
SkRuntimeShaderBuilder
*>
(
builderPtr
);
runtimeShaderBuilder
->
uniform
(
skString
(
env
,
uniformName
).
c_str
())
=
uniformValue
;
}
skiko/src/nativeJsMain/cpp/ImageFilter.cc
View file @
e28b5fea
...
...
@@ -160,6 +160,35 @@ SKIKO_EXPORT KNativePointer org_jetbrains_skia_ImageFilter__1nMakePicture
return
reinterpret_cast
<
KNativePointer
>
(
ptr
);
}
SKIKO_EXPORT
KNativePointer
org_jetbrains_skia_ImageFilter__1nMakeRuntimeShader
(
KNativePointer
runtimeShaderBuilderPtr
,
KInteropPointer
childShaderName
,
KNativePointer
inputPtr
)
{
SkRuntimeShaderBuilder
*
runtimeShaderBuilder
=
reinterpret_cast
<
SkRuntimeShaderBuilder
*>
(
runtimeShaderBuilderPtr
);
sk_sp
<
SkImageFilter
>
input
=
sk_ref_sp
<
SkImageFilter
>
(
reinterpret_cast
<
SkImageFilter
*>
(
inputPtr
));
SkImageFilter
*
ptr
=
SkImageFilters
::
RuntimeShader
(
*
runtimeShaderBuilder
,
reinterpret_cast
<
char
*>
(
childShaderName
),
input
).
release
();
return
reinterpret_cast
<
KNativePointer
>
(
ptr
);
}
SKIKO_EXPORT
KNativePointer
org_jetbrains_skia_ImageFilter__1nMakeRuntimeShaderFromArray
(
KNativePointer
runtimeShaderBuilderPtr
,
KInteropPointerArray
childShaderNamesArr
,
KNativePointerArray
inputPtrsArray
,
KInt
inputCount
)
{
SkRuntimeShaderBuilder
*
runtimeShaderBuilder
=
reinterpret_cast
<
SkRuntimeShaderBuilder
*>
(
runtimeShaderBuilderPtr
);
KNativePointer
*
inputPtrs
=
reinterpret_cast
<
KNativePointer
*>
(
inputPtrsArray
);
std
::
vector
<
sk_sp
<
SkImageFilter
>>
inputChildren
(
inputCount
);
for
(
size_t
i
=
0
;
i
<
inputCount
;
i
++
)
{
SkImageFilter
*
si
=
reinterpret_cast
<
SkImageFilter
*>
(
inputPtrs
[
i
]);
inputChildren
[
i
]
=
sk_ref_sp
(
si
);
}
std
::
vector
<
SkString
>
childShaderNameStrings
=
skStringVector
(
childShaderNamesArr
,
inputCount
);
std
::
vector
<
const
char
*>
childShaderNames
(
childShaderNameStrings
.
size
());
for
(
int
i
=
0
;
i
<
childShaderNames
.
size
();
++
i
)
childShaderNames
[
i
]
=
childShaderNameStrings
[
i
].
c_str
();
SkImageFilter
*
ptr
=
SkImageFilters
::
RuntimeShader
(
*
runtimeShaderBuilder
,
childShaderNames
.
data
(),
inputChildren
.
data
(),
inputCount
).
release
();
return
reinterpret_cast
<
KNativePointer
>
(
ptr
);
}
SKIKO_EXPORT
KNativePointer
org_jetbrains_skia_ImageFilter__1nMakeTile
(
KFloat
l0
,
KFloat
t0
,
KFloat
r0
,
KFloat
b0
,
KFloat
l1
,
KFloat
t1
,
KFloat
r1
,
KFloat
b1
,
KNativePointer
inputPtr
)
{
SkImageFilter
*
input
=
reinterpret_cast
<
SkImageFilter
*>
((
inputPtr
));
...
...
skiko/src/nativeJsMain/cpp/RuntimeShaderBuilder.cc
0 → 100644
View file @
e28b5fea
#include <iostream>
#include "SkRuntimeEffect.h"
#include "common.h"
static
void
deleteRuntimeShaderBuilder
(
SkRuntimeShaderBuilder
*
builder
)
{
delete
builder
;
}
SKIKO_EXPORT
KNativePointer
org_jetbrains_skia_RuntimeShaderBuilder__1nGetFinalizer
()
{
return
reinterpret_cast
<
KNativePointer
>
((
&
deleteRuntimeShaderBuilder
));
}
SKIKO_EXPORT
KNativePointer
org_jetbrains_skia_RuntimeShaderBuilder__1nMakeFromRuntimeEffect
(
KNativePointer
effectPtr
)
{
sk_sp
<
SkRuntimeEffect
>
runtimeEffect
=
sk_ref_sp
<
SkRuntimeEffect
>
(
reinterpret_cast
<
SkRuntimeEffect
*>
(
effectPtr
));
SkRuntimeShaderBuilder
*
builder
=
new
SkRuntimeShaderBuilder
(
runtimeEffect
);
return
reinterpret_cast
<
KNativePointer
>
(
builder
);
}
SKIKO_EXPORT
void
org_jetbrains_skia_RuntimeShaderBuilder__1nUniformInt
(
KNativePointer
builderPtr
,
KInteropPointer
uniformName
,
KInt
uniformValue
)
{
SkRuntimeShaderBuilder
*
runtimeShaderBuilder
=
reinterpret_cast
<
SkRuntimeShaderBuilder
*>
(
builderPtr
);
runtimeShaderBuilder
->
uniform
(
skString
(
uniformName
).
c_str
())
=
uniformValue
;
}
SKIKO_EXPORT
void
org_jetbrains_skia_RuntimeShaderBuilder__1nUniformFloat
(
KNativePointer
builderPtr
,
KInteropPointer
uniformName
,
KFloat
uniformValue
)
{
SkRuntimeShaderBuilder
*
runtimeShaderBuilder
=
reinterpret_cast
<
SkRuntimeShaderBuilder
*>
(
builderPtr
);
runtimeShaderBuilder
->
uniform
(
skString
(
uniformName
).
c_str
())
=
uniformValue
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment