HumbleUI / Skija

Java bindings for Skia
Apache License 2.0
514 stars 34 forks source link

Native Code Error when trying to use RadialGradientShader #24

Open smokracek opened 2 years ago

smokracek commented 2 years ago

Hi there, I'm trying to make use of Skija with Clojure, as a way to learn both. Maybe also SKSL shaders as well (although I can't figure out how to make a shader from SKSL yet). Anyways, Java crashed when running this Clojure code:

(ns shaders.core
  (:require
    [clojure.main :as cl-main]
    [nrepl.server :as nrepl])
  (:import
    (io.github.humbleui.skija BackendRenderTarget Canvas ColorSpace
                              DirectContext FramebufferFormat Surface
                              SurfaceColorFormat SurfaceOrigin Paint Shader)
    (org.lwjgl.glfw Callbacks GLFW GLFWErrorCallback)
    (org.lwjgl.opengl GL GL11)
    (org.lwjgl.system MemoryUtil)))

(set! *warn-on-reflection* true)

(defn color [^long l]
  (.intValue (Long/valueOf l)))

(def *rect-color (atom (color 0xFFCC3333)))

(defn draw [^Canvas canvas]
  (let [paint (doto (Paint.) (.setShader (Shader/makeRadialGradient
                                           320.0
                                           240.0
                                           50.0
                                           [0xffffff 0x923423])))]
    (.drawPaint paint)))

(defn display-scale [window]
  (let [x (make-array Float/TYPE 1)
        y (make-array Float/TYPE 1)]
    (GLFW/glfwGetWindowContentScale window x y)
    [(first x) (first y)]))

(defn -main [& args]
  (.set (GLFWErrorCallback/createPrint System/err))
  (GLFW/glfwInit)
  (GLFW/glfwWindowHint GLFW/GLFW_VISIBLE GLFW/GLFW_FALSE)
  (GLFW/glfwWindowHint GLFW/GLFW_RESIZABLE GLFW/GLFW_TRUE)
  (let [width 640
        height 480
        window (GLFW/glfwCreateWindow width height "Messing with Skija" MemoryUtil/NULL MemoryUtil/NULL)]
    (GLFW/glfwMakeContextCurrent window)
    (GLFW/glfwSwapInterval 1)
    (GLFW/glfwShowWindow window)
    (GL/createCapabilities)

    (doto (Thread. #(cl-main/main))
      (.start))

    (nrepl/start-server :port 7888)
    (println "nREPL server started at locahost:7888")

    (let [context (DirectContext/makeGL)
          fb-id   (GL11/glGetInteger 0x8CA6)
          [scale-x scale-y] (display-scale window)
          target  (BackendRenderTarget/makeGL (* scale-x width) (* scale-y height) 0 8 fb-id FramebufferFormat/GR_GL_RGBA8)
          surface (Surface/makeFromBackendRenderTarget context target SurfaceOrigin/BOTTOM_LEFT SurfaceColorFormat/RGBA_8888 (ColorSpace/getSRGB))
          canvas  (.getCanvas surface)]
      (.scale canvas scale-x scale-y)
      (loop []
        (when (not (GLFW/glfwWindowShouldClose window))
          (.clear canvas (color 0xFFFFFFFF))
          (let [layer (.save canvas)]
            (draw canvas)
            (.restoreToCount canvas layer))
          (.flush context)
          (GLFW/glfwSwapBuffers window)
          (GLFW/glfwPollEvents)
          (recur)))

      (Callbacks/glfwFreeCallbacks window)
      (GLFW/glfwHideWindow window)
      (GLFW/glfwDestroyWindow window)
      (GLFW/glfwPollEvents)

      (.close surface)
      (.close target)
      (.close context)

      (GLFW/glfwTerminate)
      (.free (GLFW/glfwSetErrorCallback nil))
      (nrepl/stop-server 7888)
      (shutdown-agents)
      )))

(comment
  (reset! shaders.core/*rect-color (shaders.core/color 0xFF33CC33)))

This was the terminal error message:

lein run           
Reflection warning, shaders/core.clj:21:42 - call to static method makeRadialGradient on io.github.humbleui.skija.Shader can't be resolved (argument types: double, double, double, clojure.lang.APersistentVector).
Reflection warning, shaders/core.clj:26:5 - reference to field drawPaint on io.github.humbleui.skija.Paint can't be resolved.
Reflection warning, shaders/core.clj:31:5 - call to static method glfwGetWindowContentScale on org.lwjgl.glfw.GLFW can't be resolved (argument types: unknown, unknown, unknown).
Clojure 1.11.1
nREPL server started at locahost:7888
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "clojure.lang.IFn.invoke(Object)" because the return value of "clojure.lang.Var.get()" is null
        at clojure.pprint$write_out.invokeStatic(pprint_base.clj:194)
        at clojure.pprint$pprint$fn__10392.invoke(pprint_base.clj:249)
        at clojure.pprint$pprint.invokeStatic(pprint_base.clj:248)
        at clojure.pprint$pprint.invoke(pprint_base.clj:241)
        at clojure.pprint$pprint.invokeStatic(pprint_base.clj:245)
        at clojure.pprint$pprint.invoke(pprint_base.clj:241)
        at clojure.lang.Var.invoke(Var.java:384)
        at clojure.main$report_error$fn__9280$fn__9281.invoke(main.clj:603)
        at clojure.main$report_error$fn__9280.invoke(main.clj:602)
        at clojure.main$report_error.invokeStatic(main.clj:601)
        at clojure.main$main.invokeStatic(main.clj:666)
        at clojure.main$main.doInvoke(main.clj:616)
        at clojure.lang.RestFn.applyTo(RestFn.java:137)
        at clojure.lang.Var.applyTo(Var.java:705)
        at clojure.main.main(main.java:40)
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007ffa222a1770, pid=30010, tid=51459
#
# JRE version: OpenJDK Runtime Environment Homebrew (18.0.2) (build 18.0.2+0)
# Java VM: OpenJDK 64-Bit Server VM Homebrew (18.0.2+0, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, bsd-amd64)
# Problematic frame:
# C  [libGL.dylib+0x5770]  glBindFramebuffer+0x11
#

And this was the MacOS error report..

Hopefully someone can be of some help. Maybe there's something painfully obvious I'm missing.

tonsky commented 2 years ago

Take a look at reflection warnings, they might give you a hint.

E.g. try (int-array [0xffffff 0x923423]) instead of [0xffffff 0x923423]? Also try (.drawPaint canvas paint) instead of (.drawPaint paint)