Hello everyone,
I am building a UI library with the HumbleUI\Skija package, I’m successfully using it while building it out in my game at the moment, but I’m starting to hit performance limits using it with the bitmap rendering back end.
Currently I’m encoding the Skia buffer to PNG then uploading that as a texture to JME, this works but is too slow for complex UI to feel snappy.
Skija/Skia can use an OpenGL backend so I’m now trying to upgrade using this example:
apparently Skija’s DirectContext can pick up with the open GL context, thats what the documentation and examples imply?
I’ve put together the basic test case, this renders the blue cube when this line is commented out of simpleUpdate():
skia_surface = getGLSurface(app.getCamera().getWidth(), app.getCamera().getHeight());
But when that line is included, the screen is black, the blue cube does not render, however the debug stats do show the number of objects flicking from between 4/5 as you move the camera with the mouse past where the cube should be, no errors, the debug statements all print okay and the FPS stays at 60.
The test case:
import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;
import com.jme3.system.AppSettings;
import com.jme3.system.JmeContext;
import io.github.humbleui.skija.*;
import org.lwjgl.opengl.GL11;
public class GLTest extends SimpleApplication {
public static GLTest app;
public Surface skia_surface = null;
public static void main(String[] args) {
app = new GLTest();
AppSettings settings = new AppSettings(true);
//settings.disp
settings.setFullscreen(false);
settings.setWidth(600);
settings.setHeight(600);
settings.setTitle("My Awesome Game");
app.setSettings(settings);
app.start(JmeContext.Type.Display);
}
@Override
public void simpleInitApp() {
Box b = new Box(1, 1, 1);
Geometry geom = new Geometry("Box", b);
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", ColorRGBA.Blue);
geom.setMaterial(mat);
rootNode.attachChild(geom);
}
public static Surface getGLSurface(int width, int height) {
// Initialize Skija's context with JME's OpenGL context
DirectContext skija_context = DirectContext.makeGL();
//skija_context.
logStatic("DirectContext ptr: " + skija_context._ptr);
// Get the current framebuffer ID from JME
int frame_buffer_id = GL11.glGetInteger(0x8CA6);
//int frame_buffer_id = GL30.glGenFramebuffers();
logStatic("frame_buffer_id: " + frame_buffer_id);
// Create Skija's BackendRenderTarget using JME's dimensions and framebuffer
BackendRenderTarget render_target = BackendRenderTarget.makeGL(
width, height, /* samples */ 0, /* stencil */ 8, frame_buffer_id, FramebufferFormat.GR_GL_RGBA8
);
// Create a surface for drawing
Surface surface = Surface.makeFromBackendRenderTarget(
skija_context, render_target, SurfaceOrigin.BOTTOM_LEFT, SurfaceColorFormat.RGBA_8888, ColorSpace.getSRGB()
);
return surface;
}
@Override
public void simpleUpdate(float tpf) {
if (skia_surface == null) {
skia_surface = getGLSurface(app.getCamera().getWidth(), app.getCamera().getHeight());
log("skia_surface initialised");
return;
} else {
/*
Paint paint = new Paint();
//paint.setBlendMode(BlendMode.DARKEN);
paint.setMode(PaintMode.FILL);
paint.setColor(ColorRGBA.Cyan.asIntARGB());
Rect box_size = new Rect(100, 100, 200, 200);
skia_surface.getCanvas().drawRect(box_size, paint);
*/
}
}
public void log(String s) {
System.out.println("Main: " + s);
}
public static void logStatic(String s) {
System.out.println("Main[static]: ");
}
}
This outputs:
Main[static]: DirectContext ptr: 1609112682016
Main[static]: frame_buffer_id: 0
Main: skia_surface initialised
I’ve included a bit of skia rendering code in simpleUpdate() thats block commented out, but that would be a valid draw call if the skia surface was set up
I’m at the limits of my knowledge with OpenGL contexts, FrameBuffer ID’s and such, i’m fumbling around not sure if I’m on the right path at the moment… Does anyone have any idea why I get the black screen?
Or is there a better way to do this integration?
Thanks