Commit 9b66885d authored by Roman Sedaikin's avatar Roman Sedaikin

Fixed rendering flickering on Linux and Windows

parent 953ebd36
...@@ -5,3 +5,4 @@ local.properties ...@@ -5,3 +5,4 @@ local.properties
.DS_Store .DS_Store
run.sh run.sh
.idea .idea
deploy.sh
\ No newline at end of file
...@@ -33,15 +33,8 @@ public: ...@@ -33,15 +33,8 @@ public:
} }
private: private:
bool isDrawing = false;
void draw() void draw()
{ {
if (isDrawing)
{
return;
}
isDrawing = true;
if (jvm != NULL) if (jvm != NULL)
{ {
JNIEnv *env; JNIEnv *env;
...@@ -83,17 +76,13 @@ private: ...@@ -83,17 +76,13 @@ private:
return; return;
} }
env->CallVoidMethod(canvasRef, drawMethod); env->CallVoidMethod(canvasRef, drawMethod);
glFinish();
glXSwapBuffers(display, window); glXSwapBuffers(display, window);
glXMakeCurrent(display, 0, 0);
jvm->DetachCurrentThread();
} }
ds->FreeDrawingSurfaceInfo(dsi); ds->FreeDrawingSurfaceInfo(dsi);
ds->Unlock(ds); ds->Unlock(ds);
awt.FreeDrawingSurface(ds); awt.FreeDrawingSurface(ds);
} }
isDrawing = false;
} }
}; };
...@@ -111,10 +100,11 @@ LayersSet *findByObject(JNIEnv *env, jobject object) ...@@ -111,10 +100,11 @@ LayersSet *findByObject(JNIEnv *env, jobject object)
return NULL; return NULL;
} }
extern "C" { extern "C"
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv *env, jobject canvas)
{ {
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv *env, jobject canvas)
{
if (windowsSet != NULL) if (windowsSet != NULL)
{ {
LayersSet *layer = findByObject(env, canvas); LayersSet *layer = findByObject(env, canvas);
...@@ -165,7 +155,7 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv ...@@ -165,7 +155,7 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv
Window window = dsi_x11->drawable; Window window = dsi_x11->drawable;
if (dsi != NULL) if (dsi != NULL)
{ {
GLint att[] = {GLX_RGBA, GLX_DOUBLEBUFFER, None}; GLint att[] = {GLX_RGBA, GLX_DOUBLEBUFFER, True, None};
XVisualInfo *vi = glXChooseVisual(display, 0, att); XVisualInfo *vi = glXChooseVisual(display, 0, att);
GLXContext context = glXCreateContext(display, vi, NULL, GL_TRUE); GLXContext context = glXCreateContext(display, vi, NULL, GL_TRUE);
...@@ -181,29 +171,28 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv ...@@ -181,29 +171,28 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv
ds->FreeDrawingSurfaceInfo(dsi); ds->FreeDrawingSurfaceInfo(dsi);
ds->Unlock(ds); ds->Unlock(ds);
awt.FreeDrawingSurface(ds); awt.FreeDrawingSurface(ds);
} }
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_redrawLayer(JNIEnv *env, jobject canvas) JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_redrawLayer(JNIEnv *env, jobject canvas)
{ {
LayersSet *layer = findByObject(env, canvas); LayersSet *layer = findByObject(env, canvas);
if (layer != NULL) if (layer != NULL)
{ {
layer->update(); layer->update();
} }
} }
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_disposeLayer(JNIEnv *env, jobject canvas) JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_disposeLayer(JNIEnv *env, jobject canvas)
{ {
LayersSet *layer = findByObject(env, canvas); LayersSet *layer = findByObject(env, canvas);
if (layer != NULL) if (layer != NULL)
{ {
layer->dispose(); layer->dispose();
} }
} }
JNIEXPORT jfloat JNICALL Java_org_jetbrains_skiko_HardwareLayer_getContentScale(JNIEnv *env, jobject canvas) JNIEXPORT jfloat JNICALL Java_org_jetbrains_skiko_HardwareLayer_getContentScale(JNIEnv *env, jobject canvas)
{ {
return 1.0f; return 1.0f;
} }
} // extern "C" } // extern "C"
\ No newline at end of file
...@@ -16,54 +16,83 @@ using namespace std; ...@@ -16,54 +16,83 @@ using namespace std;
JavaVM *jvm = NULL; JavaVM *jvm = NULL;
extern "C" jboolean Skiko_GetAWT(JNIEnv *env, JAWT *awt); extern "C" jboolean Skiko_GetAWT(JNIEnv *env, JAWT *awt);
class LayersSet { class LayersSet
{
public: public:
jobject windowRef; jobject windowRef;
HGLRC context; HGLRC context;
HWND glLayer; HWND handler;
void update() { void update()
{
draw(); draw();
} }
void dispose() { void dispose()
glLayer = NULL; {
context = NULL; context = NULL;
handler = NULL;
} }
private: private:
bool isDrawing = false; void draw()
void draw() { {
if (isDrawing) { if (jvm != NULL)
{
JNIEnv *env;
jvm->GetEnv((void **)&env, JNI_VERSION_10);
JAWT awt;
JAWT_DrawingSurface *ds = NULL;
JAWT_DrawingSurfaceInfo *dsi = NULL;
jboolean result = JNI_FALSE;
jint lock = 0;
JAWT_Win32DrawingSurfaceInfo *dsi_win;
awt.version = (jint)JAWT_VERSION_9;
result = Skiko_GetAWT(env, &awt);
if (result == JNI_FALSE)
{
fprintf(stderr, "JAWT_GetAWT failed! Result is JNI_FALSE\n");
return; return;
} }
isDrawing = true; ds = awt.GetDrawingSurface(env, windowRef);
HDC handler = GetDC(glLayer); lock = ds->Lock(ds);
wglMakeCurrent(handler, context); dsi = ds->GetDrawingSurfaceInfo(ds);
dsi_win = (JAWT_Win32DrawingSurfaceInfo *)dsi->platformInfo;
if (jvm != NULL) { HWND hwnd = dsi_win->hwnd;
JNIEnv *env; HDC hdc = GetDC(hwnd);
if (dsi != NULL)
{
jvm->AttachCurrentThread((void **)&env, NULL); jvm->AttachCurrentThread((void **)&env, NULL);
wglMakeCurrent(hdc, context);
jclass wndClass = env->GetObjectClass(windowRef); jclass wndClass = env->GetObjectClass(windowRef);
jmethodID drawMethod = env->GetMethodID(wndClass, "draw", "()V"); jmethodID drawMethod = env->GetMethodID(wndClass, "draw", "()V");
if (NULL == drawMethod) { if (NULL == drawMethod)
{
fprintf(stderr, "The method Window.draw() not found!\n"); fprintf(stderr, "The method Window.draw() not found!\n");
return; return;
} }
env->CallVoidMethod(windowRef, drawMethod); env->CallVoidMethod(windowRef, drawMethod);
glFinish();
SwapBuffers(hdc);
}
ds->FreeDrawingSurfaceInfo(dsi);
ds->Unlock(ds);
awt.FreeDrawingSurface(ds);
} }
wglMakeCurrent(handler, NULL);
isDrawing = false;
} }
}; };
set<LayersSet*> *windowsSet = NULL; set<LayersSet *> *windowsSet = NULL;
LayersSet *findByObject(JNIEnv *env, jobject object) { LayersSet *findByObject(JNIEnv *env, jobject object)
for (auto &layer : *windowsSet) { {
if (env->IsSameObject(object, layer->windowRef) == JNI_TRUE) { for (auto &layer : *windowsSet)
{
if (env->IsSameObject(object, layer->windowRef) == JNI_TRUE)
{
return layer; return layer;
} }
} }
...@@ -71,8 +100,10 @@ LayersSet *findByObject(JNIEnv *env, jobject object) { ...@@ -71,8 +100,10 @@ LayersSet *findByObject(JNIEnv *env, jobject object) {
return NULL; return NULL;
} }
float getScaleFloatFromEnum(DEVICE_SCALE_FACTOR scaleFactor) { float getScaleFloatFromEnum(DEVICE_SCALE_FACTOR scaleFactor)
switch (scaleFactor) { {
switch (scaleFactor)
{
case SCALE_100_PERCENT: case SCALE_100_PERCENT:
return 1.0f; return 1.0f;
case SCALE_120_PERCENT: case SCALE_120_PERCENT:
...@@ -111,14 +142,18 @@ float getScaleFloatFromEnum(DEVICE_SCALE_FACTOR scaleFactor) { ...@@ -111,14 +142,18 @@ float getScaleFloatFromEnum(DEVICE_SCALE_FACTOR scaleFactor) {
return 1.0f; return 1.0f;
} }
extern "C" { extern "C"
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv *env, jobject window)
{ {
if (windowsSet != NULL) {
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv *env, jobject window)
{
if (windowsSet != NULL)
{
LayersSet *layer = findByObject(env, window); LayersSet *layer = findByObject(env, window);
if (layer != NULL) { if (layer != NULL)
if (layer->glLayer == NULL && layer->context == NULL) { {
if (layer->context == NULL)
{
env->DeleteGlobalRef(layer->windowRef); env->DeleteGlobalRef(layer->windowRef);
layer->windowRef = NULL; layer->windowRef = NULL;
windowsSet->erase(layer); windowsSet->erase(layer);
...@@ -126,40 +161,40 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv ...@@ -126,40 +161,40 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv
} }
return; return;
} }
} else { }
windowsSet = new set<LayersSet*>(); else
{
windowsSet = new set<LayersSet *>();
} }
JAWT awt; JAWT awt;
JAWT_DrawingSurface* ds = NULL; JAWT_DrawingSurface *ds = NULL;
JAWT_DrawingSurfaceInfo* dsi = NULL; JAWT_DrawingSurfaceInfo *dsi = NULL;
PIXELFORMATDESCRIPTOR pixFormatDscr; PIXELFORMATDESCRIPTOR pixFormatDscr;
HGLRC context = NULL; HGLRC context = NULL;
jboolean result = JNI_FALSE; jboolean result = JNI_FALSE;
jint lock = 0; jint lock = 0;
JAWT_Win32DrawingSurfaceInfo* dsi_win; JAWT_Win32DrawingSurfaceInfo *dsi_win;
awt.version = (jint)JAWT_VERSION_9; awt.version = (jint)JAWT_VERSION_9;
result = Skiko_GetAWT(env, &awt); result = Skiko_GetAWT(env, &awt);
if (result == JNI_FALSE) { if (result == JNI_FALSE)
{
fprintf(stderr, "JAWT_GetAWT failed! Result is JNI_FALSE\n"); fprintf(stderr, "JAWT_GetAWT failed! Result is JNI_FALSE\n");
return; return;
} }
if (jvm == NULL) { if (jvm == NULL)
{
env->GetJavaVM(&jvm); env->GetJavaVM(&jvm);
} }
ds = awt.GetDrawingSurface(env, window); ds = awt.GetDrawingSurface(env, window);
lock = ds->Lock(ds); lock = ds->Lock(ds);
dsi = ds->GetDrawingSurfaceInfo(ds); dsi = ds->GetDrawingSurfaceInfo(ds);
dsi_win = (JAWT_Win32DrawingSurfaceInfo *)dsi->platformInfo;
// Get the platform-specific drawing info
dsi_win = (JAWT_Win32DrawingSurfaceInfo*)dsi->platformInfo;
HWND hwnd = dsi_win->hwnd; HWND hwnd = dsi_win->hwnd;
HDC wndHandler = GetDC(hwnd); HDC wndHandler = GetDC(hwnd);
...@@ -169,7 +204,8 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv ...@@ -169,7 +204,8 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv
memset(&pixFormatDscr, 0, sizeof(PIXELFORMATDESCRIPTOR)); memset(&pixFormatDscr, 0, sizeof(PIXELFORMATDESCRIPTOR));
pixFormatDscr.nSize = sizeof(PIXELFORMATDESCRIPTOR); pixFormatDscr.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pixFormatDscr.nVersion = 1; pixFormatDscr.nVersion = 1;
pixFormatDscr.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER_DONTCARE; pixFormatDscr.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pixFormatDscr.iPixelType = PFD_TYPE_RGBA; pixFormatDscr.iPixelType = PFD_TYPE_RGBA;
pixFormatDscr.cColorBits = 32; pixFormatDscr.cColorBits = 32;
int iPixelFormat = ChoosePixelFormat(wndHandler, &pixFormatDscr); int iPixelFormat = ChoosePixelFormat(wndHandler, &pixFormatDscr);
...@@ -177,46 +213,49 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv ...@@ -177,46 +213,49 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv
DescribePixelFormat(wndHandler, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pixFormatDscr); DescribePixelFormat(wndHandler, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pixFormatDscr);
context = wglCreateContext(wndHandler); context = wglCreateContext(wndHandler);
LayersSet* layer = new LayersSet(); LayersSet *layer = new LayersSet();
windowsSet->insert(layer); windowsSet->insert(layer);
jobject windowRef = env->NewGlobalRef(window); jobject windowRef = env->NewGlobalRef(window);
layer->windowRef = windowRef; layer->windowRef = windowRef;
layer->glLayer = hwnd;
layer->context = context; layer->context = context;
layer->handler = hwnd;
} }
ds->FreeDrawingSurfaceInfo(dsi); ds->FreeDrawingSurfaceInfo(dsi);
ds->Unlock(ds); ds->Unlock(ds);
awt.FreeDrawingSurface(ds); awt.FreeDrawingSurface(ds);
} }
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_redrawLayer(JNIEnv *env, jobject window) { JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_redrawLayer(JNIEnv *env, jobject window)
{
LayersSet *layer = findByObject(env, window); LayersSet *layer = findByObject(env, window);
if (layer != NULL) { if (layer != NULL)
{
layer->update(); layer->update();
} }
} }
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_disposeLayer(JNIEnv *env, jobject window) { JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_disposeLayer(JNIEnv *env, jobject window)
{
LayersSet *layer = findByObject(env, window); LayersSet *layer = findByObject(env, window);
if (layer != NULL) { if (layer != NULL)
{
layer->dispose(); layer->dispose();
} }
} }
JNIEXPORT jfloat JNICALL Java_org_jetbrains_skiko_HardwareLayer_getContentScale(JNIEnv *env, jobject window) { JNIEXPORT jfloat JNICALL Java_org_jetbrains_skiko_HardwareLayer_getContentScale(JNIEnv *env, jobject window)
{
LayersSet *layer = findByObject(env, window); LayersSet *layer = findByObject(env, window);
if (layer != NULL) { if (layer != NULL)
{
// get scale dpi factor of current monitor // get scale dpi factor of current monitor
DEVICE_SCALE_FACTOR scaleFactor; DEVICE_SCALE_FACTOR scaleFactor;
GetScaleFactorForMonitor(MonitorFromWindow(layer->glLayer, MONITOR_DEFAULTTOPRIMARY), &scaleFactor); GetScaleFactorForMonitor(MonitorFromWindow(layer->handler, MONITOR_DEFAULTTOPRIMARY), &scaleFactor);
return getScaleFloatFromEnum(scaleFactor); return getScaleFloatFromEnum(scaleFactor);
} }
return 1.0f; return 1.0f;
} }
} // extern "C" } // extern "C"
\ No newline at end of file
...@@ -57,15 +57,9 @@ open class SkiaLayer : HardwareLayer() { ...@@ -57,15 +57,9 @@ open class SkiaLayer : HardwareLayer() {
} }
skijaState.apply { skijaState.apply {
val gl = OpenGLApi.instance
gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f)
gl.glClear(gl.GL_COLOR_BUFFER_BIT)
canvas!!.clear(-1) canvas!!.clear(-1)
renderer?.onRender(canvas!!, width, height) renderer?.onRender(canvas!!, width, height)
context!!.flush() context!!.flush()
gl.glFinish()
} }
} }
...@@ -98,6 +92,8 @@ open class SkiaWindow : JFrame() { ...@@ -98,6 +92,8 @@ open class SkiaWindow : JFrame() {
companion object { companion object {
init { init {
Library.load("/", "skiko") Library.load("/", "skiko")
// we have to set this property to avoid render flickering.
System.setProperty("sun.awt.noerasebackground", "true")
} }
} }
......
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