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

Fixed rendering flickering on Linux and Windows

parent 953ebd36
...@@ -4,4 +4,5 @@ build ...@@ -4,4 +4,5 @@ build
local.properties local.properties
.DS_Store .DS_Store
run.sh run.sh
.idea .idea
\ No newline at end of file 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,99 +100,99 @@ LayersSet *findByObject(JNIEnv *env, jobject object) ...@@ -111,99 +100,99 @@ 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)
{ {
if (windowsSet != NULL)
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv *env, jobject canvas)
{ {
LayersSet *layer = findByObject(env, canvas); if (windowsSet != NULL)
if (layer != NULL)
{ {
if (layer->context == NULL) LayersSet *layer = findByObject(env, canvas);
if (layer != NULL)
{ {
env->DeleteGlobalRef(layer->canvasRef); if (layer->context == NULL)
layer->canvasRef = NULL; {
windowsSet->erase(layer); env->DeleteGlobalRef(layer->canvasRef);
delete layer; layer->canvasRef = NULL;
windowsSet->erase(layer);
delete layer;
}
return;
} }
return;
} }
} else
else {
{ windowsSet = new set<LayersSet *>();
windowsSet = new set<LayersSet *>(); }
}
if (jvm == NULL) if (jvm == NULL)
{ {
env->GetJavaVM(&jvm); env->GetJavaVM(&jvm);
} }
JAWT awt; JAWT awt;
JAWT_DrawingSurface *ds = NULL; JAWT_DrawingSurface *ds = NULL;
JAWT_DrawingSurfaceInfo *dsi = NULL; JAWT_DrawingSurfaceInfo *dsi = NULL;
jboolean result = JNI_FALSE; jboolean result = JNI_FALSE;
jint lock = 0; jint lock = 0;
JAWT_X11DrawingSurfaceInfo *dsi_x11; JAWT_X11DrawingSurfaceInfo *dsi_x11;
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;
} }
ds = awt.GetDrawingSurface(env, canvas); ds = awt.GetDrawingSurface(env, canvas);
lock = ds->Lock(ds); lock = ds->Lock(ds);
dsi = ds->GetDrawingSurfaceInfo(ds); dsi = ds->GetDrawingSurfaceInfo(ds);
dsi_x11 = (JAWT_X11DrawingSurfaceInfo *)dsi->platformInfo; dsi_x11 = (JAWT_X11DrawingSurfaceInfo *)dsi->platformInfo;
Display *display = dsi_x11->display; Display *display = dsi_x11->display;
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);
LayersSet *layer = new LayersSet(); LayersSet *layer = new LayersSet();
windowsSet->insert(layer); windowsSet->insert(layer);
jobject canvasRef = env->NewGlobalRef(canvas); jobject canvasRef = env->NewGlobalRef(canvas);
layer->canvasRef = canvasRef; layer->canvasRef = canvasRef;
layer->context = context; layer->context = context;
}
ds->FreeDrawingSurfaceInfo(dsi);
ds->Unlock(ds);
awt.FreeDrawingSurface(ds);
} }
ds->FreeDrawingSurfaceInfo(dsi);
ds->Unlock(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);
if (layer != NULL)
{ {
layer->update(); LayersSet *layer = findByObject(env, canvas);
if (layer != NULL)
{
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);
if (layer != NULL)
{ {
layer->dispose(); LayersSet *layer = findByObject(env, canvas);
if (layer != NULL)
{
layer->dispose();
}
} }
}
JNIEXPORT jfloat JNICALL Java_org_jetbrains_skiko_HardwareLayer_getContentScale(JNIEnv *env, jobject canvas)
{
return 1.0f;
}
JNIEXPORT jfloat JNICALL Java_org_jetbrains_skiko_HardwareLayer_getContentScale(JNIEnv *env, jobject canvas)
{
return 1.0f;
}
} // extern "C" } // extern "C"
\ No newline at end of file
...@@ -16,207 +16,246 @@ using namespace std; ...@@ -16,207 +16,246 @@ 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)
return; {
} JNIEnv *env;
jvm->GetEnv((void **)&env, JNI_VERSION_10);
isDrawing = true; JAWT awt;
HDC handler = GetDC(glLayer); JAWT_DrawingSurface *ds = NULL;
wglMakeCurrent(handler, context); JAWT_DrawingSurfaceInfo *dsi = NULL;
jboolean result = JNI_FALSE;
if (jvm != NULL) { jint lock = 0;
JNIEnv *env; JAWT_Win32DrawingSurfaceInfo *dsi_win;
jvm->AttachCurrentThread((void **)&env, NULL); awt.version = (jint)JAWT_VERSION_9;
result = Skiko_GetAWT(env, &awt);
jclass wndClass = env->GetObjectClass(windowRef); if (result == JNI_FALSE)
jmethodID drawMethod = env->GetMethodID(wndClass, "draw", "()V"); {
if (NULL == drawMethod) { fprintf(stderr, "JAWT_GetAWT failed! Result is JNI_FALSE\n");
fprintf(stderr, "The method Window.draw() not found!\n"); return;
return; }
}
env->CallVoidMethod(windowRef, drawMethod); ds = awt.GetDrawingSurface(env, windowRef);
} lock = ds->Lock(ds);
dsi = ds->GetDrawingSurfaceInfo(ds);
wglMakeCurrent(handler, NULL); dsi_win = (JAWT_Win32DrawingSurfaceInfo *)dsi->platformInfo;
isDrawing = false;
} HWND hwnd = dsi_win->hwnd;
HDC hdc = GetDC(hwnd);
if (dsi != NULL)
{
jvm->AttachCurrentThread((void **)&env, NULL);
wglMakeCurrent(hdc, context);
jclass wndClass = env->GetObjectClass(windowRef);
jmethodID drawMethod = env->GetMethodID(wndClass, "draw", "()V");
if (NULL == drawMethod)
{
fprintf(stderr, "The method Window.draw() not found!\n");
return;
}
env->CallVoidMethod(windowRef, drawMethod);
glFinish();
SwapBuffers(hdc);
}
ds->FreeDrawingSurfaceInfo(dsi);
ds->Unlock(ds);
awt.FreeDrawingSurface(ds);
}
}
}; };
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)
return layer; {
} if (env->IsSameObject(object, layer->windowRef) == JNI_TRUE)
} {
fprintf(stderr, "The set does not contain this window.\n"); return layer;
return NULL; }
}
fprintf(stderr, "The set does not contain this window.\n");
return NULL;
} }
float getScaleFloatFromEnum(DEVICE_SCALE_FACTOR scaleFactor) { float getScaleFloatFromEnum(DEVICE_SCALE_FACTOR scaleFactor)
switch (scaleFactor) { {
case SCALE_100_PERCENT: switch (scaleFactor)
return 1.0f; {
case SCALE_120_PERCENT: case SCALE_100_PERCENT:
return 1.2f; return 1.0f;
case SCALE_125_PERCENT: case SCALE_120_PERCENT:
return 1.25f; return 1.2f;
case SCALE_140_PERCENT: case SCALE_125_PERCENT:
return 1.4f; return 1.25f;
case SCALE_150_PERCENT: case SCALE_140_PERCENT:
return 1.5f; return 1.4f;
case SCALE_160_PERCENT: case SCALE_150_PERCENT:
return 1.6f; return 1.5f;
case SCALE_175_PERCENT: case SCALE_160_PERCENT:
return 1.75f; return 1.6f;
case SCALE_180_PERCENT: case SCALE_175_PERCENT:
return 1.8f; return 1.75f;
case SCALE_200_PERCENT: case SCALE_180_PERCENT:
return 2.0f; return 1.8f;
case SCALE_225_PERCENT: case SCALE_200_PERCENT:
return 2.25f; return 2.0f;
case SCALE_250_PERCENT: case SCALE_225_PERCENT:
return 2.5f; return 2.25f;
case SCALE_300_PERCENT: case SCALE_250_PERCENT:
return 3.0f; return 2.5f;
case SCALE_350_PERCENT: case SCALE_300_PERCENT:
return 3.5f; return 3.0f;
case SCALE_400_PERCENT: case SCALE_350_PERCENT:
return 4.0f; return 3.5f;
case SCALE_450_PERCENT: case SCALE_400_PERCENT:
return 4.5f; return 4.0f;
case SCALE_500_PERCENT: case SCALE_450_PERCENT:
return 5.0f; return 4.5f;
case DEVICE_SCALE_FACTOR_INVALID: case SCALE_500_PERCENT:
return 1.0f; return 5.0f;
case DEVICE_SCALE_FACTOR_INVALID:
return 1.0f;
} }
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) {
LayersSet *layer = findByObject(env, window);
if (layer != NULL) {
if (layer->glLayer == NULL && layer->context == NULL) {
env->DeleteGlobalRef(layer->windowRef);
layer->windowRef = NULL;
windowsSet->erase(layer);
delete layer;
}
return;
}
} else {
windowsSet = new set<LayersSet*>();
}
JAWT awt;
JAWT_DrawingSurface* ds = NULL;
JAWT_DrawingSurfaceInfo* dsi = NULL;
PIXELFORMATDESCRIPTOR pixFormatDscr;
HGLRC context = 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;
}
if (jvm == NULL) {
env->GetJavaVM(&jvm);
}
ds = awt.GetDrawingSurface(env, window);
lock = ds->Lock(ds);
dsi = ds->GetDrawingSurfaceInfo(ds);
// Get the platform-specific drawing info
dsi_win = (JAWT_Win32DrawingSurfaceInfo*)dsi->platformInfo;
HWND hwnd = dsi_win->hwnd;
HDC wndHandler = GetDC(hwnd);
if (dsi != NULL)
{
memset(&pixFormatDscr, 0, sizeof(PIXELFORMATDESCRIPTOR));
pixFormatDscr.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pixFormatDscr.nVersion = 1;
pixFormatDscr.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER_DONTCARE;
pixFormatDscr.iPixelType = PFD_TYPE_RGBA;
pixFormatDscr.cColorBits = 32;
int iPixelFormat = ChoosePixelFormat(wndHandler, &pixFormatDscr);
SetPixelFormat(wndHandler, iPixelFormat, &pixFormatDscr);
DescribePixelFormat(wndHandler, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pixFormatDscr);
context = wglCreateContext(wndHandler);
LayersSet* layer = new LayersSet();
windowsSet->insert(layer);
jobject windowRef = env->NewGlobalRef(window);
layer->windowRef = windowRef;
layer->glLayer = hwnd;
layer->context = context;
}
ds->FreeDrawingSurfaceInfo(dsi);
ds->Unlock(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_updateLayer(JNIEnv *env, jobject window)
LayersSet *layer = findByObject(env, window); {
if (layer != NULL) { if (windowsSet != NULL)
layer->update(); {
} LayersSet *layer = findByObject(env, window);
} if (layer != NULL)
{
if (layer->context == NULL)
{
env->DeleteGlobalRef(layer->windowRef);
layer->windowRef = NULL;
windowsSet->erase(layer);
delete layer;
}
return;
}
}
else
{
windowsSet = new set<LayersSet *>();
}
JAWT awt;
JAWT_DrawingSurface *ds = NULL;
JAWT_DrawingSurfaceInfo *dsi = NULL;
PIXELFORMATDESCRIPTOR pixFormatDscr;
HGLRC context = 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;
}
if (jvm == NULL)
{
env->GetJavaVM(&jvm);
}
ds = awt.GetDrawingSurface(env, window);
lock = ds->Lock(ds);
dsi = ds->GetDrawingSurfaceInfo(ds);
dsi_win = (JAWT_Win32DrawingSurfaceInfo *)dsi->platformInfo;
HWND hwnd = dsi_win->hwnd;
HDC wndHandler = GetDC(hwnd);
if (dsi != NULL)
{
memset(&pixFormatDscr, 0, sizeof(PIXELFORMATDESCRIPTOR));
pixFormatDscr.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pixFormatDscr.nVersion = 1;
pixFormatDscr.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pixFormatDscr.iPixelType = PFD_TYPE_RGBA;
pixFormatDscr.cColorBits = 32;
int iPixelFormat = ChoosePixelFormat(wndHandler, &pixFormatDscr);
SetPixelFormat(wndHandler, iPixelFormat, &pixFormatDscr);
DescribePixelFormat(wndHandler, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pixFormatDscr);
context = wglCreateContext(wndHandler);
LayersSet *layer = new LayersSet();
windowsSet->insert(layer);
jobject windowRef = env->NewGlobalRef(window);
layer->windowRef = windowRef;
layer->context = context;
layer->handler = hwnd;
}
ds->FreeDrawingSurfaceInfo(dsi);
ds->Unlock(ds);
awt.FreeDrawingSurface(ds);
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_disposeLayer(JNIEnv *env, jobject window) { JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_redrawLayer(JNIEnv *env, jobject window)
LayersSet *layer = findByObject(env, window); {
if (layer != NULL) { LayersSet *layer = findByObject(env, window);
layer->dispose(); if (layer != NULL)
} {
} layer->update();
}
}
JNIEXPORT jfloat JNICALL Java_org_jetbrains_skiko_HardwareLayer_getContentScale(JNIEnv *env, jobject window) { JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_disposeLayer(JNIEnv *env, jobject window)
LayersSet *layer = findByObject(env, window); {
if (layer != NULL) { LayersSet *layer = findByObject(env, window);
// get scale dpi factor of current monitor if (layer != NULL)
DEVICE_SCALE_FACTOR scaleFactor; {
GetScaleFactorForMonitor(MonitorFromWindow(layer->glLayer, MONITOR_DEFAULTTOPRIMARY), &scaleFactor); layer->dispose();
return getScaleFloatFromEnum(scaleFactor); }
} }
return 1.0f;
}
JNIEXPORT jfloat JNICALL Java_org_jetbrains_skiko_HardwareLayer_getContentScale(JNIEnv *env, jobject window)
{
LayersSet *layer = findByObject(env, window);
if (layer != NULL)
{
// get scale dpi factor of current monitor
DEVICE_SCALE_FACTOR scaleFactor;
GetScaleFactorForMonitor(MonitorFromWindow(layer->handler, MONITOR_DEFAULTTOPRIMARY), &scaleFactor);
return getScaleFloatFromEnum(scaleFactor);
}
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