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

Fixed rendering flickering on Linux and Windows

parent 953ebd36
......@@ -4,4 +4,5 @@ build
local.properties
.DS_Store
run.sh
.idea
\ No newline at end of file
.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,99 +100,99 @@ 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"
{
if (windowsSet != NULL)
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv *env, jobject canvas)
{
LayersSet *layer = findByObject(env, canvas);
if (layer != NULL)
if (windowsSet != NULL)
{
if (layer->context == NULL)
LayersSet *layer = findByObject(env, canvas);
if (layer != NULL)
{
env->DeleteGlobalRef(layer->canvasRef);
layer->canvasRef = NULL;
windowsSet->erase(layer);
delete layer;
if (layer->context == NULL)
{
env->DeleteGlobalRef(layer->canvasRef);
layer->canvasRef = NULL;
windowsSet->erase(layer);
delete layer;
}
return;
}
return;
}
}
else
{
windowsSet = new set<LayersSet *>();
}
else
{
windowsSet = new set<LayersSet *>();
}
if (jvm == NULL)
{
env->GetJavaVM(&jvm);
}
if (jvm == NULL)
{
env->GetJavaVM(&jvm);
}
JAWT awt;
JAWT_DrawingSurface *ds = NULL;
JAWT_DrawingSurfaceInfo *dsi = NULL;
JAWT awt;
JAWT_DrawingSurface *ds = NULL;
JAWT_DrawingSurfaceInfo *dsi = NULL;
jboolean result = JNI_FALSE;
jint lock = 0;
JAWT_X11DrawingSurfaceInfo *dsi_x11;
jboolean result = JNI_FALSE;
jint lock = 0;
JAWT_X11DrawingSurfaceInfo *dsi_x11;
awt.version = (jint)JAWT_VERSION_9;
result = Skiko_GetAWT(env, &awt);
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 (result == JNI_FALSE)
{
fprintf(stderr, "JAWT_GetAWT failed! Result is JNI_FALSE\n");
return;
}
ds = awt.GetDrawingSurface(env, canvas);
lock = ds->Lock(ds);
dsi = ds->GetDrawingSurfaceInfo(ds);
dsi_x11 = (JAWT_X11DrawingSurfaceInfo *)dsi->platformInfo;
Display *display = dsi_x11->display;
Window window = dsi_x11->drawable;
if (dsi != NULL)
{
GLint att[] = {GLX_RGBA, GLX_DOUBLEBUFFER, None};
ds = awt.GetDrawingSurface(env, canvas);
lock = ds->Lock(ds);
dsi = ds->GetDrawingSurfaceInfo(ds);
dsi_x11 = (JAWT_X11DrawingSurfaceInfo *)dsi->platformInfo;
Display *display = dsi_x11->display;
Window window = dsi_x11->drawable;
if (dsi != NULL)
{
GLint att[] = {GLX_RGBA, GLX_DOUBLEBUFFER, True, None};
XVisualInfo *vi = glXChooseVisual(display, 0, att);
GLXContext context = glXCreateContext(display, vi, NULL, GL_TRUE);
XVisualInfo *vi = glXChooseVisual(display, 0, att);
GLXContext context = glXCreateContext(display, vi, NULL, GL_TRUE);
LayersSet *layer = new LayersSet();
windowsSet->insert(layer);
LayersSet *layer = new LayersSet();
windowsSet->insert(layer);
jobject canvasRef = env->NewGlobalRef(canvas);
jobject canvasRef = env->NewGlobalRef(canvas);
layer->canvasRef = canvasRef;
layer->context = context;
layer->canvasRef = canvasRef;
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)
{
LayersSet *layer = findByObject(env, canvas);
if (layer != NULL)
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_redrawLayer(JNIEnv *env, jobject canvas)
{
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)
{
LayersSet *layer = findByObject(env, canvas);
if (layer != NULL)
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_disposeLayer(JNIEnv *env, jobject canvas)
{
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"
\ No newline at end of file
......@@ -16,207 +16,246 @@ 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;
jobject windowRef;
HGLRC context;
HWND handler;
void update() {
draw();
}
void update()
{
draw();
}
void dispose() {
glLayer = NULL;
context = NULL;
}
void dispose()
{
context = NULL;
handler = NULL;
}
private:
bool isDrawing = false;
void draw() {
if (isDrawing) {
return;
}
isDrawing = true;
HDC handler = GetDC(glLayer);
wglMakeCurrent(handler, context);
if (jvm != NULL) {
JNIEnv *env;
jvm->AttachCurrentThread((void **)&env, NULL);
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);
}
wglMakeCurrent(handler, NULL);
isDrawing = false;
}
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;
}
ds = awt.GetDrawingSurface(env, windowRef);
lock = ds->Lock(ds);
dsi = ds->GetDrawingSurfaceInfo(ds);
dsi_win = (JAWT_Win32DrawingSurfaceInfo *)dsi->platformInfo;
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;
LayersSet *findByObject(JNIEnv *env, jobject object) {
for (auto &layer : *windowsSet) {
if (env->IsSameObject(object, layer->windowRef) == JNI_TRUE) {
return layer;
}
}
fprintf(stderr, "The set does not contain this window.\n");
return NULL;
set<LayersSet *> *windowsSet = NULL;
LayersSet *findByObject(JNIEnv *env, jobject object)
{
for (auto &layer : *windowsSet)
{
if (env->IsSameObject(object, layer->windowRef) == JNI_TRUE)
{
return layer;
}
}
fprintf(stderr, "The set does not contain this window.\n");
return NULL;
}
float getScaleFloatFromEnum(DEVICE_SCALE_FACTOR scaleFactor) {
switch (scaleFactor) {
case SCALE_100_PERCENT:
return 1.0f;
case SCALE_120_PERCENT:
return 1.2f;
case SCALE_125_PERCENT:
return 1.25f;
case SCALE_140_PERCENT:
return 1.4f;
case SCALE_150_PERCENT:
return 1.5f;
case SCALE_160_PERCENT:
return 1.6f;
case SCALE_175_PERCENT:
return 1.75f;
case SCALE_180_PERCENT:
return 1.8f;
case SCALE_200_PERCENT:
return 2.0f;
case SCALE_225_PERCENT:
return 2.25f;
case SCALE_250_PERCENT:
return 2.5f;
case SCALE_300_PERCENT:
return 3.0f;
case SCALE_350_PERCENT:
return 3.5f;
case SCALE_400_PERCENT:
return 4.0f;
case SCALE_450_PERCENT:
return 4.5f;
case SCALE_500_PERCENT:
return 5.0f;
case DEVICE_SCALE_FACTOR_INVALID:
return 1.0f;
float getScaleFloatFromEnum(DEVICE_SCALE_FACTOR scaleFactor)
{
switch (scaleFactor)
{
case SCALE_100_PERCENT:
return 1.0f;
case SCALE_120_PERCENT:
return 1.2f;
case SCALE_125_PERCENT:
return 1.25f;
case SCALE_140_PERCENT:
return 1.4f;
case SCALE_150_PERCENT:
return 1.5f;
case SCALE_160_PERCENT:
return 1.6f;
case SCALE_175_PERCENT:
return 1.75f;
case SCALE_180_PERCENT:
return 1.8f;
case SCALE_200_PERCENT:
return 2.0f;
case SCALE_225_PERCENT:
return 2.25f;
case SCALE_250_PERCENT:
return 2.5f;
case SCALE_300_PERCENT:
return 3.0f;
case SCALE_350_PERCENT:
return 3.5f;
case SCALE_400_PERCENT:
return 4.0f;
case SCALE_450_PERCENT:
return 4.5f;
case SCALE_500_PERCENT:
return 5.0f;
case DEVICE_SCALE_FACTOR_INVALID:
return 1.0f;
}
return 1.0f;
return 1.0f;
}
extern "C" {
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_updateLayer(JNIEnv *env, jobject window)
extern "C"
{
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) {
LayersSet *layer = findByObject(env, window);
if (layer != NULL) {
layer->update();
}
}
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->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) {
LayersSet *layer = findByObject(env, window);
if (layer != NULL) {
layer->dispose();
}
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_redrawLayer(JNIEnv *env, jobject window)
{
LayersSet *layer = findByObject(env, window);
if (layer != NULL)
{
layer->update();
}
}
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->glLayer, MONITOR_DEFAULTTOPRIMARY), &scaleFactor);
return getScaleFloatFromEnum(scaleFactor);
}
return 1.0f;
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_HardwareLayer_disposeLayer(JNIEnv *env, jobject window)
{
LayersSet *layer = findByObject(env, window);
if (layer != NULL)
{
layer->dispose();
}
}
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"
\ 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