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
.DS_Store
run.sh
.idea
deploy.sh
\ No newline at end of file
......@@ -33,15 +33,8 @@ public:
}
private:
bool isDrawing = false;
void draw()
{
if (isDrawing)
{
return;
}
isDrawing = true;
if (jvm != NULL)
{
JNIEnv *env;
......@@ -83,17 +76,13 @@ private:
return;
}
env->CallVoidMethod(canvasRef, drawMethod);
glFinish();
glXSwapBuffers(display, window);
glXMakeCurrent(display, 0, 0);
jvm->DetachCurrentThread();
}
ds->FreeDrawingSurfaceInfo(dsi);
ds->Unlock(ds);
awt.FreeDrawingSurface(ds);
}
isDrawing = false;
}
};
......@@ -111,10 +100,11 @@ LayersSet *findByObject(JNIEnv *env, jobject object)
return NULL;
}
extern "C" {
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv *env, jobject canvas)
extern "C"
{
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv *env, jobject canvas)
{
if (windowsSet != NULL)
{
LayersSet *layer = findByObject(env, canvas);
......@@ -165,7 +155,7 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv
Window window = dsi_x11->drawable;
if (dsi != NULL)
{
GLint att[] = {GLX_RGBA, GLX_DOUBLEBUFFER, None};
GLint att[] = {GLX_RGBA, GLX_DOUBLEBUFFER, True, None};
XVisualInfo *vi = glXChooseVisual(display, 0, att);
GLXContext context = glXCreateContext(display, vi, NULL, GL_TRUE);
......@@ -181,29 +171,28 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv
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();
}
}
}
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();
}
}
}
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;
}
}
} // extern "C"
\ No newline at end of file
......@@ -16,54 +16,83 @@ using namespace std;
JavaVM *jvm = NULL;
extern "C" jboolean Skiko_GetAWT(JNIEnv *env, JAWT *awt);
class LayersSet {
class LayersSet
{
public:
jobject windowRef;
HGLRC context;
HWND glLayer;
HWND handler;
void update() {
void update()
{
draw();
}
void dispose() {
glLayer = NULL;
void dispose()
{
context = NULL;
handler = NULL;
}
private:
bool isDrawing = false;
void draw() {
if (isDrawing) {
void draw()
{
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;
}
isDrawing = true;
HDC handler = GetDC(glLayer);
wglMakeCurrent(handler, context);
ds = awt.GetDrawingSurface(env, windowRef);
lock = ds->Lock(ds);
dsi = ds->GetDrawingSurfaceInfo(ds);
dsi_win = (JAWT_Win32DrawingSurfaceInfo *)dsi->platformInfo;
if (jvm != NULL) {
JNIEnv *env;
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) {
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);
}
wglMakeCurrent(handler, NULL);
isDrawing = false;
}
};
set<LayersSet*> *windowsSet = NULL;
LayersSet *findByObject(JNIEnv *env, jobject object) {
for (auto &layer : *windowsSet) {
if (env->IsSameObject(object, layer->windowRef) == JNI_TRUE) {
set<LayersSet *> *windowsSet = NULL;
LayersSet *findByObject(JNIEnv *env, jobject object)
{
for (auto &layer : *windowsSet)
{
if (env->IsSameObject(object, layer->windowRef) == JNI_TRUE)
{
return layer;
}
}
......@@ -71,8 +100,10 @@ LayersSet *findByObject(JNIEnv *env, jobject object) {
return NULL;
}
float getScaleFloatFromEnum(DEVICE_SCALE_FACTOR scaleFactor) {
switch (scaleFactor) {
float getScaleFloatFromEnum(DEVICE_SCALE_FACTOR scaleFactor)
{
switch (scaleFactor)
{
case SCALE_100_PERCENT:
return 1.0f;
case SCALE_120_PERCENT:
......@@ -111,14 +142,18 @@ float getScaleFloatFromEnum(DEVICE_SCALE_FACTOR scaleFactor) {
return 1.0f;
}
extern "C" {
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv *env, jobject window)
extern "C"
{
if (windowsSet != NULL) {
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) {
if (layer != NULL)
{
if (layer->context == NULL)
{
env->DeleteGlobalRef(layer->windowRef);
layer->windowRef = NULL;
windowsSet->erase(layer);
......@@ -126,40 +161,40 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv
}
return;
}
} else {
windowsSet = new set<LayersSet*>();
}
else
{
windowsSet = new set<LayersSet *>();
}
JAWT awt;
JAWT_DrawingSurface* ds = NULL;
JAWT_DrawingSurfaceInfo* dsi = NULL;
JAWT_DrawingSurface *ds = NULL;
JAWT_DrawingSurfaceInfo *dsi = NULL;
PIXELFORMATDESCRIPTOR pixFormatDscr;
HGLRC context = NULL;
jboolean result = JNI_FALSE;
jint lock = 0;
JAWT_Win32DrawingSurfaceInfo* dsi_win;
JAWT_Win32DrawingSurfaceInfo *dsi_win;
awt.version = (jint)JAWT_VERSION_9;
result = Skiko_GetAWT(env, &awt);
if (result == JNI_FALSE) {
if (result == JNI_FALSE)
{
fprintf(stderr, "JAWT_GetAWT failed! Result is JNI_FALSE\n");
return;
}
if (jvm == NULL) {
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;
dsi_win = (JAWT_Win32DrawingSurfaceInfo *)dsi->platformInfo;
HWND hwnd = dsi_win->hwnd;
HDC wndHandler = GetDC(hwnd);
......@@ -169,7 +204,8 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv
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.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pixFormatDscr.iPixelType = PFD_TYPE_RGBA;
pixFormatDscr.cColorBits = 32;
int iPixelFormat = ChoosePixelFormat(wndHandler, &pixFormatDscr);
......@@ -177,46 +213,49 @@ JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv
DescribePixelFormat(wndHandler, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pixFormatDscr);
context = wglCreateContext(wndHandler);
LayersSet* layer = new LayersSet();
LayersSet *layer = new LayersSet();
windowsSet->insert(layer);
jobject windowRef = env->NewGlobalRef(window);
layer->windowRef = windowRef;
layer->glLayer = hwnd;
layer->context = context;
layer->handler = hwnd;
}
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_redrawLayer(JNIEnv *env, jobject window)
{
LayersSet *layer = findByObject(env, window);
if (layer != NULL) {
if (layer != NULL)
{
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);
if (layer != NULL) {
if (layer != NULL)
{
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);
if (layer != NULL) {
if (layer != NULL)
{
// get scale dpi factor of current monitor
DEVICE_SCALE_FACTOR scaleFactor;
GetScaleFactorForMonitor(MonitorFromWindow(layer->glLayer, MONITOR_DEFAULTTOPRIMARY), &scaleFactor);
GetScaleFactorForMonitor(MonitorFromWindow(layer->handler, MONITOR_DEFAULTTOPRIMARY), &scaleFactor);
return getScaleFloatFromEnum(scaleFactor);
}
return 1.0f;
}
}
} // extern "C"
\ No newline at end of file
......@@ -57,15 +57,9 @@ open class SkiaLayer : HardwareLayer() {
}
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)
renderer?.onRender(canvas!!, width, height)
context!!.flush()
gl.glFinish()
}
}
......@@ -98,6 +92,8 @@ open class SkiaWindow : JFrame() {
companion object {
init {
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