Unverified Commit ff5a1136 authored by Alen MapuH's avatar Alen MapuH Committed by GitHub

add BackendTexture and Image.adoptTextureFrom (#1030)

### New:  
(related #1019)
1. Adds bindings to GrBackendTextures::MakeGL 
2. Adds bindings to SkImages::AdoptTextureFrom
3. Adds bindings to GrBackendTextures::GLTextureParametersModdified

### Changes in build scripts:
(related #742)
1. Add file paths treating if building on Windows machine
2. Use "emcc.bat" instead of "emcc" if building on Windows machine, as
described on Emscripten website

### Use-case: 
Allows skia to draw images, rendered externally on gpu.
Compose would benefit greatly, allowing to embed VideoPlayer or Browser
without any friction or need to use Swing.
parent 9ec0e8ca
package internal.utils
import org.apache.tools.ant.taskdefs.condition.Os
import org.gradle.api.file.FileSystemLocation
import org.gradle.api.provider.Provider
import java.io.File
......@@ -86,6 +87,15 @@ internal abstract class BaseVisualStudioBuildToolsArgBuilder : AbstractArgBuilde
internal class DefaultArgBuilder() : AbstractArgBuilder() {
override fun newSelfInstance(): ArgBuilder = DefaultArgBuilder()
override fun escapePathIfNeeded(file: File): String {
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
val path = file.absolutePath
.replace("/", "\\")
.replace("\\", "\\\\")
return if (" " in path) "\"$path\"" else path
}
else return super.escapePathIfNeeded(file)
}
}
internal class VisualCppCompilerArgBuilder : BaseVisualStudioBuildToolsArgBuilder() {
......
import org.apache.tools.ant.taskdefs.condition.Os
import org.gradle.api.GradleException
import org.gradle.api.Project
import java.io.File
......@@ -50,7 +51,7 @@ fun compilerForTarget(os: OS, arch: Arch, isJvm: Boolean = false): String =
OS.Android -> "clang++"
OS.Windows -> "clang-cl.exe"
OS.MacOS, OS.IOS, OS.TVOS -> "clang++"
OS.Wasm -> "emcc"
OS.Wasm -> if (Os.isFamily(Os.FAMILY_WINDOWS)) "emcc.bat" else "emcc"
}
fun linkerForTarget(os: OS, arch: Arch, isJvm: Boolean = false): String =
......
......@@ -97,10 +97,10 @@ fun skiaPreprocessorFlags(os: OS, buildType: SkiaBuildType): Array<String> {
"-DSK_BUILD_FOR_LINUX",
"-D_GLIBCXX_USE_CXX11_ABI=0"
)
OS.Wasm -> mutableListOf<String>().apply {
add("-DSKIKO_WASM")
add("-sSUPPORT_LONGJMP=wasm")
}
OS.Wasm -> listOf(
"-DSKIKO_WASM",
"-sSUPPORT_LONGJMP=wasm"
)
OS.Android -> listOf(
"-DSK_BUILD_FOR_ANDROID"
)
......
......@@ -9,6 +9,13 @@ import org.jetbrains.skiko.loadOpenGLLibrary
class BackendRenderTarget internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHolder.PTR) {
companion object {
/**
* Creates BackendRenderTarget from GL framebuffer.
*
* @param stencilBits If wrapping in a Surface we require them to be either 0, 8 or 16.
*
* @throws RenderException if returned nullptr
*/
fun makeGL(
width: Int,
height: Int,
......@@ -37,7 +44,7 @@ class BackendRenderTarget internal constructor(ptr: NativePointer) : Managed(ptr
* @param width width of the render target in pixels
* @param height height of the render target in pixels
* @param texturePtr pointer to ID3D12Resource texture resource object; must be not zero
* @param format pixel data DXGI_FORMAT fromat of the texturePtr resource
* @param format pixel data DXGI_FORMAT format of the texturePtr resource
* @param sampleCnt samples count for texture resource
* @param levelCnt sampling quality level for texture resource
*/
......
package org.jetbrains.skia
import org.jetbrains.skia.impl.*
import org.jetbrains.skia.impl.Library.Companion.staticLoad
class BackendTexture internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHolder.PTR) {
companion object {
/**
* Creates BackendTexture from GL texture.
*
* @param width - width of the [BackendTexture] to be created
* @param height - height of the [BackendTexture] to be created
* @param isMipmapped - if the passed [textureId] has a GL mipmap, this should be true, otherwise false
* @param textureId - GL id of the texture to use
* @param textureTarget - GL enum, must be valid texture target for 2D, e.g. GL_TEXTURE_2D
* @param textureFormat - GL enum, must be valid color format, e.g. GL_RGBA or GL_BGRA_INTEGER
*
* @see glTextureParametersModified
*/
fun makeGL(
width: Int,
height: Int,
isMipmapped: Boolean,
textureId: Int,
textureTarget: Int,
textureFormat: Int
): BackendTexture {
Stats.onNativeCall()
val ptr = _nMakeGL(
width,
height,
isMipmapped,
textureId,
textureTarget,
textureFormat
)
return BackendTexture(ptr)
}
init {
staticLoad()
}
}
/**
* Call this to indicate to DirectContext that the texture parameters have been modified in the GL context externally
*/
fun glTextureParametersModified() {
return try {
Stats.onNativeCall()
_nGLTextureParametersModified(getPtr(this))
} finally {
reachabilityBarrier(this)
}
}
private object _FinalizerHolder {
val PTR = BackendTexture_nGetFinalizer()
}
}
@ExternalSymbolName("org_jetbrains_skia_BackendTexture__1nGetFinalizer")
@ModuleImport("./skiko.mjs", "org_jetbrains_skia_BackendTexture__1nGetFinalizer")
private external fun BackendTexture_nGetFinalizer(): NativePointer
@ExternalSymbolName("org_jetbrains_skia_BackendTexture__1nMakeGL")
@ModuleImport("./skiko.mjs", "org_jetbrains_skia_BackendTexture__1nMakeGL")
private external fun _nMakeGL(
width: Int,
height: Int,
isMipmapped: Boolean,
textureId: Int,
target: Int,
format: Int
): NativePointer
@ExternalSymbolName("org_jetbrains_skia_BackendTexture__1nGLTextureParametersModified")
@ModuleImport("./skiko.mjs", "org_jetbrains_skia_BackendTexture__1nGLTextureParametersModified")
private external fun _nGLTextureParametersModified(backendTexturePtr: NativePointer)
......@@ -138,6 +138,44 @@ class Image internal constructor(ptr: NativePointer) : RefCnt(ptr), IHasImageInf
return Image(ptr)
}
/**
* Creates GPU-backed SkImage from backendTexture associated with context.
*
* Skia will assume ownership of the resource and will release it when no longer needed.
* A non-null Image is returned if format of backendTexture is recognized and supported.
* Recognized formats vary by GPU backend.
*
* @param context GPU context
* @param backendTexture texture residing on GPU
* @param origin origin of backendTexture
* @param colorType color type of the resulting Image
* @return created Image
*
* @throws RuntimeException - if nullPtr is returned.
*/
fun adoptTextureFrom(
context: DirectContext,
backendTexture: BackendTexture,
origin: SurfaceOrigin,
colorType: ColorType,
): Image {
return try {
Stats.onNativeCall()
val ptr = _nAdoptTextureFrom(
getPtr(context),
getPtr(backendTexture),
origin.ordinal,
colorType.ordinal
)
if (ptr == NullPointer) throw RuntimeException("Failed to Image::makeFromTexture")
Image(ptr)
}
finally {
reachabilityBarrier(context)
reachabilityBarrier(backendTexture)
}
}
init {
staticLoad()
}
......@@ -457,3 +495,12 @@ private external fun _nReadPixelsBitmap(
@ExternalSymbolName("org_jetbrains_skia_Image__1nReadPixelsPixmap")
@ModuleImport("./skiko.mjs", "org_jetbrains_skia_Image__1nReadPixelsPixmap")
private external fun _nReadPixelsPixmap(ptr: NativePointer, pixmapPtr: NativePointer, srcX: Int, srcY: Int, cache: Boolean): Boolean
@ExternalSymbolName("org_jetbrains_skia_Image__1nAdoptTextureFrom")
@ModuleImport("./skiko.mjs", "org_jetbrains_skia_Image__1nAdoptTextureFrom")
external fun _nAdoptTextureFrom(
contextPtr: NativePointer,
backendTexture: NativePointer,
surfaceOrigin: Int,
colorType: Int
): NativePointer
#include <iostream>
#include <jni.h>
#include "ganesh/GrBackendSurface.h"
#include "SkData.h"
#include "SkImage.h"
#include <ganesh/gl/GrGLBackendSurface.h>
#include "ganesh/gl/GrGLBackendSurface.h"
#include "include/gpu/ganesh/SkImageGanesh.h"
#include "ganesh/GrDirectContext.h"
#include "ganesh/gl/GrGLDirectContext.h"
static void deleteBackendTexture(GrBackendTexture* rt) {
// std::cout << "Deleting [GrBackendTexture " << rt << "]" << std::endl;
delete rt;
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_BackendTextureKt_BackendTexture_1nGetFinalizer
(JNIEnv* env, jclass jclass) {
return static_cast<jlong>(reinterpret_cast<uintptr_t>(&deleteBackendTexture));
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_BackendTextureKt__1nMakeGL
(JNIEnv* env, jclass jclass, jint width, jint height, jboolean isMipmapped, jint textureId, jint target, jint format) {
GrGLTextureInfo textureInfo;
textureInfo.fID = static_cast<GrGLuint>(textureId);
textureInfo.fTarget = static_cast<GrGLenum>(target);
textureInfo.fFormat = static_cast<GrGLenum>(format);
GrBackendTexture obj = GrBackendTextures::MakeGL(
width,
height,
isMipmapped ? skgpu::Mipmapped::kYes : skgpu::Mipmapped::kNo,
textureInfo
);
GrBackendTexture* instance = new GrBackendTexture(obj);
return reinterpret_cast<jlong>(instance);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_BackendTextureKt__1nGLTextureParametersModified
(JNIEnv* env, jclass jclass, jlong backendTexturePtr) {
GrBackendTexture* backendTexture = reinterpret_cast<GrBackendTexture*>(static_cast<uintptr_t>(backendTexturePtr));
GrBackendTextures::GLTextureParametersModified(backendTexture);
}
......@@ -2,6 +2,11 @@
#include <jni.h>
#include "SkData.h"
#include "SkImage.h"
#include "ganesh/GrBackendSurface.h"
#include "ganesh/gl/GrGLBackendSurface.h"
#include "include/gpu/ganesh/SkImageGanesh.h"
#include "ganesh/GrDirectContext.h"
#include "ganesh/gl/GrGLDirectContext.h"
#include "SkBitmap.h"
#include "SkShader.h"
#include "SkEncodedImageFormat.h"
......@@ -158,3 +163,17 @@ extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_ImageKt__1nScalePi
auto cachingHint = cache ? SkImage::CachingHint::kAllow_CachingHint : SkImage::CachingHint::kDisallow_CachingHint;
return instance->scalePixels(*pixmap, skija::SamplingMode::unpackFrom2Ints(env, samplingOptionsVal1, samplingOptionsVal2), cachingHint);
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_ImageKt__1nAdoptTextureFrom
(JNIEnv* env, jclass jclass, jlong contextPtr, jlong backendTexturePtr, jint surfaceOrigin, jint colorType) {
GrBackendTexture* backendTexture = reinterpret_cast<GrBackendTexture*>(static_cast<uintptr_t>(backendTexturePtr));
GrDirectContext* context = reinterpret_cast<GrDirectContext*>(static_cast<uintptr_t>(contextPtr));
sk_sp<SkImage> image = SkImages::AdoptTextureFrom(
static_cast<GrRecordingContext*>(context),
*backendTexture,
static_cast<GrSurfaceOrigin>(surfaceOrigin),
static_cast<SkColorType>(colorType)
);
return reinterpret_cast<jlong>(image.release());
}
#include <iostream>
#include <stdint.h>
#include "common.h"
#include "gpu/ganesh/gl/GrGLBackendSurface.h"
#include "include/gpu/ganesh/SkImageGanesh.h"
#include "include/gpu/ganesh/gl/GrGLTypes.h"
#include "gpu/ganesh/GrBackendSurface.h"
static void deleteBackendTexture(GrBackendTexture* rt) {
delete rt;
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_BackendTexture__1nGetFinalizer() {
return reinterpret_cast<KNativePointer>(&deleteBackendTexture);
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_BackendTexture__1nMakeGL
(KInt width, KInt height, KBoolean isMipmapped, KInt textureId, KInt target, KInt format) {
GrGLTextureInfo textureInfo;
textureInfo.fID = static_cast<GrGLuint>(textureId);
textureInfo.fTarget = static_cast<GrGLenum>(target);
textureInfo.fFormat = static_cast<GrGLenum>(format);
GrBackendTexture obj = GrBackendTextures::MakeGL(
width,
height,
isMipmapped ? skgpu::Mipmapped::kYes : skgpu::Mipmapped::kNo,
textureInfo
);
GrBackendTexture* instance = new GrBackendTexture(obj);
return instance;
}
SKIKO_EXPORT void org_jetbrains_skia_BackendTexture__1nGLTextureParametersModified
(KNativePointer backendTexturePtr) {
GrBackendTexture* backendTexture = reinterpret_cast<GrBackendTexture*>(backendTexturePtr);
GrBackendTextures::GLTextureParametersModified(backendTexture);
}
\ No newline at end of file
......@@ -2,12 +2,14 @@
#include "SkData.h"
#include "SkImage.h"
#include "SkBitmap.h"
#include "ganesh/GrDirectContext.h"
#include "SkShader.h"
#include "SkEncodedImageFormat.h"
#include "encode/SkPngEncoder.h"
#include "encode/SkJpegEncoder.h"
#include "encode/SkWebpEncoder.h"
#include "common.h"
#include "include/gpu/ganesh/SkImageGanesh.h"
SKIKO_EXPORT KNativePointer org_jetbrains_skia_Image__1nMakeRaster
......@@ -154,3 +156,18 @@ SKIKO_EXPORT KBoolean org_jetbrains_skia_Image__1nScalePixels
auto cachingHint = cache ? SkImage::CachingHint::kAllow_CachingHint : SkImage::CachingHint::kDisallow_CachingHint;
return instance->scalePixels(*pixmap, skija::SamplingMode::unpackFrom2Ints(samplingOptionsVal1, samplingOptionsVal2), cachingHint);
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_Image__1nAdoptTextureFrom
(KNativePointer contextPtr, KNativePointer backendTexturePtr, KInt surfaceOrigin, KInt colorType) {
GrDirectContext* context = reinterpret_cast<GrDirectContext*>(contextPtr);
GrBackendTexture* backendTexture = reinterpret_cast<GrBackendTexture*>(backendTexturePtr);
sk_sp<SkImage> image = SkImages::AdoptTextureFrom(
static_cast<GrRecordingContext*>(context),
*backendTexture,
static_cast<GrSurfaceOrigin>(surfaceOrigin),
static_cast<SkColorType>(colorType)
);
return reinterpret_cast<KNativePointer>(image.release());
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment