Commit c70deacf authored by Roman Sedaikin's avatar Roman Sedaikin

First Angle rendering prototype.

parent 3a80b7a1
...@@ -219,8 +219,6 @@ tasks.withType(CppCompile::class.java).configureEach { ...@@ -219,8 +219,6 @@ tasks.withType(CppCompile::class.java).configureEach {
"-I$skiaDir/third_party/externals/harfbuzz/src", "-I$skiaDir/third_party/externals/harfbuzz/src",
"-I$skiaDir/third_party/icu", "-I$skiaDir/third_party/icu",
"-I$skiaDir/third_party/externals/icu/source/common", "-I$skiaDir/third_party/externals/icu/source/common",
// "-lEGL",
// "-lGLESv2",
"-DSK_ALLOW_STATIC_GLOBAL_INITIALIZERS=1", "-DSK_ALLOW_STATIC_GLOBAL_INITIALIZERS=1",
"-DSK_FORCE_DISTANCE_FIELD_TEXT=0", "-DSK_FORCE_DISTANCE_FIELD_TEXT=0",
"-DSK_GAMMA_APPLY_TO_A8", "-DSK_GAMMA_APPLY_TO_A8",
......
...@@ -9,27 +9,45 @@ ...@@ -9,27 +9,45 @@
#include <EGL/eglext.h> #include <EGL/eglext.h>
#include "gl/GrGLAssembleInterface.h" #include "gl/GrGLAssembleInterface.h"
#include "gl/GrGLDefines.h" #include "gl/GrGLDefines.h"
#include <GL/gl.h>
class AngleDevice class AngleDevice
{ {
public: public:
HWND window;
HDC device; HDC device;
EGLDisplay display = EGL_NO_DISPLAY; EGLDisplay display = EGL_NO_DISPLAY;
EGLContext context = EGL_NO_CONTEXT; EGLContext context = EGL_NO_CONTEXT;
EGLSurface surface = EGL_NO_SURFACE; EGLSurface surface = EGL_NO_SURFACE;
sk_sp<const GrGLInterface> backendContext;
~AngleDevice() ~AngleDevice()
{ {
backendContext.reset(nullptr);
eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (EGL_NO_CONTEXT != context)
{
eglDestroyContext(display, context);
}
if (EGL_NO_SURFACE != surface)
{
eglDestroySurface(display, surface);
}
if (EGL_NO_DISPLAY != display)
{
eglTerminate(display);
}
} }
}; };
extern "C" extern "C"
{ {
EGLDisplay getAngleEGLDisplay(HDC hdc) { EGLDisplay getAngleEGLDisplay(HDC hdc)
{
PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT; PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT;
eglGetPlatformDisplayEXT = (PFNEGLGETPLATFORMDISPLAYEXTPROC)GetProcAddress(GetModuleHandle(NULL), "eglGetPlatformDisplayEXT"); eglGetPlatformDisplayEXT = (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT");
// We expect ANGLE to support this extension // We expect ANGLE to support this extension
if (!eglGetPlatformDisplayEXT) { if (!eglGetPlatformDisplayEXT)
{
return EGL_NO_DISPLAY; return EGL_NO_DISPLAY;
} }
// We currently only support D3D11 ANGLE. // We currently only support D3D11 ANGLE.
...@@ -42,43 +60,127 @@ extern "C" ...@@ -42,43 +60,127 @@ extern "C"
JNIEnv *env, jobject redrawer, jlong windowHandle) JNIEnv *env, jobject redrawer, jlong windowHandle)
{ {
AngleDevice *angleDevice = new AngleDevice(); AngleDevice *angleDevice = new AngleDevice();
angleDevice->device = GetDC((HWND) windowHandle); angleDevice->window = (HWND)windowHandle;
angleDevice->device = GetDC(angleDevice->window);
angleDevice->display = getAngleEGLDisplay(angleDevice->device); angleDevice->display = getAngleEGLDisplay(angleDevice->device);
if (EGL_NO_DISPLAY == angleDevice->display) { if (EGL_NO_DISPLAY == angleDevice->display)
{
fprintf(stderr, "Could not get display!\n");
return 0;
}
EGLint majorVersion;
EGLint minorVersion;
if (!eglInitialize(angleDevice->display, &majorVersion, &minorVersion))
{
fprintf(stderr, "Could not initialize display!\n");
return 0; return 0;
} }
EGLint numConfigs;
const int sampleBuffers = 1;
const EGLint configAttribs[] = {EGL_RENDERABLE_TYPE,
// We currently only support ES3.
EGL_OPENGL_ES3_BIT,
EGL_RED_SIZE,
8,
EGL_GREEN_SIZE,
8,
EGL_BLUE_SIZE,
8,
EGL_ALPHA_SIZE,
8,
EGL_SAMPLE_BUFFERS,
sampleBuffers,
EGL_SAMPLES,
0,
EGL_NONE};
EGLConfig surfaceConfig;
if (!eglChooseConfig(angleDevice->display, configAttribs, &surfaceConfig, 1, &numConfigs))
{
fprintf(stderr, "Could not create choose config!\n");
return 0;
}
// We currently only support ES3.
const EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
angleDevice->context = eglCreateContext(angleDevice->display, surfaceConfig, nullptr, contextAttribs);
if (EGL_NO_CONTEXT == angleDevice->context)
{
fprintf(stderr, "Could not create context!\n");
return 0;
}
angleDevice->surface = eglCreateWindowSurface(angleDevice->display, surfaceConfig, angleDevice->window, nullptr);
if (EGL_NO_SURFACE == angleDevice->surface)
{
fprintf(stderr, "Could not create surface!\n");
return 0;
}
if (!eglMakeCurrent(angleDevice->display, angleDevice->surface, angleDevice->surface, angleDevice->context))
{
fprintf(stderr, "Could not make contxt current!\n");
return 0;
}
sk_sp<const GrGLInterface> interface(GrGLMakeAssembledInterface(
nullptr,
[](void *ctx, const char name[]) -> GrGLFuncPtr { return eglGetProcAddress(name); }));
angleDevice->backendContext = interface;
return toJavaPointer(angleDevice); return toJavaPointer(angleDevice);
} }
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_AngleRedrawer_makeAngleContext( JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_AngleRedrawer_makeAngleContext(
JNIEnv* env, jobject redrawer, jlong devicePtr) JNIEnv *env, jobject redrawer, jlong devicePtr)
{ {
return 0; AngleDevice *angleDevice = fromJavaPointer<AngleDevice *>(devicePtr);
sk_sp<const GrGLInterface> backendContext = angleDevice->backendContext;
return toJavaPointer(GrDirectContext::MakeGL(backendContext).release());
} }
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_AngleRedrawer_makeAngleRenderTarget( JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_AngleRedrawer_makeAngleRenderTarget(
JNIEnv * env, jobject redrawer, jlong devicePtr, jint width, jint height) JNIEnv *env, jobject redrawer, jlong devicePtr, jint width, jint height)
{ {
return 0; AngleDevice *angleDevice = fromJavaPointer<AngleDevice *>(devicePtr);
eglMakeCurrent(angleDevice->display, angleDevice->surface, angleDevice->surface, angleDevice->context);
angleDevice->backendContext->fFunctions.fViewport(0, 0, width, height);
GrGLint buffer;
angleDevice->backendContext->fFunctions.fGetIntegerv(GR_GL_FRAMEBUFFER_BINDING, &buffer);
GrGLFramebufferInfo info;
info.fFBOID = buffer;
info.fFormat = GR_GL_RGBA8;
GrBackendRenderTarget *renderTarget = new GrBackendRenderTarget(width,
height,
0,
8,
info);
return toJavaPointer(renderTarget);
} }
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_AngleRedrawer_resizeBuffers( JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_AngleRedrawer_resizeBuffers(
JNIEnv *env, jobject redrawer, jlong devicePtr, jint width, jint height) JNIEnv *env, jobject redrawer, jlong devicePtr, jint width, jint height)
{ {
} }
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_AngleRedrawer_finishFrame( JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_AngleRedrawer_finishFrame(
JNIEnv *env, jobject redrawer, jlong devicePtr, jlong contextPtr, jlong surfacePtr, jboolean isVsyncEnabled) JNIEnv *env, jobject redrawer, jlong devicePtr, jboolean isVsyncEnabled)
{ {
AngleDevice *angleDevice = fromJavaPointer<AngleDevice *>(devicePtr);
eglMakeCurrent(angleDevice->display, angleDevice->surface, angleDevice->surface, angleDevice->context);
eglSwapInterval(angleDevice->display, (int)isVsyncEnabled); // wait for vsync
if (!eglSwapBuffers(angleDevice->display, angleDevice->surface))
{
fprintf(stderr, "Could not complete eglSwapBuffers.\n");
}
} }
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_AngleRedrawer_disposeDevice( JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_AngleRedrawer_disposeDevice(
JNIEnv *env, jobject redrawer, jlong devicePtr) JNIEnv *env, jobject redrawer, jlong devicePtr)
{ {
AngleDevice *angleDevice = fromJavaPointer<AngleDevice*>(devicePtr); AngleDevice *angleDevice = fromJavaPointer<AngleDevice *>(devicePtr);
delete angleDevice; delete angleDevice;
} }
} // end extern C } // end extern C
......
...@@ -25,7 +25,7 @@ internal class AngleContextHandler(layer: SkiaLayer) : ContextHandler(layer) { ...@@ -25,7 +25,7 @@ internal class AngleContextHandler(layer: SkiaLayer) : ContextHandler(layer) {
if (device == 0L) { if (device == 0L) {
throw Exception("Failed to create Angle device.") throw Exception("Failed to create Angle device.")
} }
context = angleRedrawer.makeContext(device) context = angleRedrawer.makeContext()
} }
} catch (e: Exception) { } catch (e: Exception) {
println("${e.message}\nFailed to create Skia Angle context!") println("${e.message}\nFailed to create Skia Angle context!")
...@@ -41,12 +41,12 @@ internal class AngleContextHandler(layer: SkiaLayer) : ContextHandler(layer) { ...@@ -41,12 +41,12 @@ internal class AngleContextHandler(layer: SkiaLayer) : ContextHandler(layer) {
val w = (layer.width * scale).toInt().coerceAtLeast(0) val w = (layer.width * scale).toInt().coerceAtLeast(0)
val h = (layer.height * scale).toInt().coerceAtLeast(0) val h = (layer.height * scale).toInt().coerceAtLeast(0)
renderTarget = angleRedrawer.makeRenderTarget(device, w, h) renderTarget = angleRedrawer.makeRenderTarget(w, h)
surface = Surface.makeFromBackendRenderTarget( surface = Surface.makeFromBackendRenderTarget(
context!!, context!!,
renderTarget!!, renderTarget!!,
SurfaceOrigin.TOP_LEFT, SurfaceOrigin.BOTTOM_LEFT,
SurfaceColorFormat.RGBA_8888, SurfaceColorFormat.RGBA_8888,
ColorSpace.getSRGB() ColorSpace.getSRGB()
) )
...@@ -56,19 +56,6 @@ internal class AngleContextHandler(layer: SkiaLayer) : ContextHandler(layer) { ...@@ -56,19 +56,6 @@ internal class AngleContextHandler(layer: SkiaLayer) : ContextHandler(layer) {
override fun flush() { override fun flush() {
super.flush() super.flush()
try { angleRedrawer.finishFrame()
angleRedrawer.finishFrame(
device,
Native.getPtr(context!!),
Native.getPtr(surface!!)
)
} finally {
Reference.reachabilityFence(context!!)
Reference.reachabilityFence(surface!!)
}
}
override fun destroyContext() {
destroyContext(Native.getPtr(context!!))
} }
} }
...@@ -46,27 +46,25 @@ internal class AngleRedrawer( ...@@ -46,27 +46,25 @@ internal class AngleRedrawer(
layer.draw() layer.draw()
} }
fun makeContext(device: Long) = DirectContext( fun createDevice(): Long {
device = createAngleDevice(layer.windowHandle)
return device
}
fun makeContext() = DirectContext(
makeAngleContext(device) makeAngleContext(device)
) )
fun makeRenderTarget(device: Long, width: Int, height: Int) = BackendRenderTarget( fun makeRenderTarget(width: Int, height: Int) = BackendRenderTarget(
makeAngleRenderTarget(device, width, height) makeAngleRenderTarget(device, width, height)
) )
fun createDevice(): Long { fun finishFrame() = finishFrame(device, properties.isVsyncEnabled)
device = createAngleDevice(layer.windowHandle)
return device
}
fun finishFrame(device: Long, context: Long, surface: Long) {
finishFrame(device, context, surface, properties.isVsyncEnabled)
}
external fun createAngleDevice(windowHandle: Long): Long external fun createAngleDevice(windowHandle: Long): Long
external fun makeAngleContext(device: Long): Long external fun makeAngleContext(device: Long): Long
external fun makeAngleRenderTarget(device: Long, width: Int, height: Int): Long external fun makeAngleRenderTarget(device: Long, width: Int, height: Int): Long
external fun resizeBuffers(device: Long, width: Int, height: Int) external fun resizeBuffers(device: Long, width: Int, height: Int)
external fun finishFrame(device: Long, context: Long, surface: Long, isVsyncEnabled: Boolean) external fun finishFrame(device: Long, isVsyncEnabled: Boolean)
external fun disposeDevice(device: Long) external fun disposeDevice(device: Long)
} }
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