Skip to content

Commit 2c7538a

Browse files
committed
new platform/out: JNI on Linux!
1 parent 17605f8 commit 2c7538a

File tree

8 files changed

+285
-0
lines changed

8 files changed

+285
-0
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,8 @@ sled.wasm.map
4646

4747
# nix default result symlink (from nix-build)
4848
/result
49+
50+
# JNI build files
51+
src/os/JniSled.class
52+
src/os/sh_tty_sled_JniSled.h
53+
/sled.jar

GNUmakefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ include Makefiles/card10.GNUmakefile
171171
include Makefiles/esp32.GNUmakefile
172172
include Makefiles/ndless.GNUmakefile
173173
include Makefiles/emscripten.GNUmakefile
174+
include Makefiles/unix_jni.GNUmakefile
174175

175176
# --- All/Cleaning begins here ---
176177

Makefiles/sledconf.unix_jni

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Example sledconf for building sled as a JNI library
2+
3+
# Build with `make sled.jar`
4+
5+
PROJECT := sled
6+
7+
DEBUG := 0
8+
9+
# I've only validated it to work in static form. Dynamic will need extra handling/work in unix_jni.GNUmakefile
10+
STATIC := 1
11+
PLATFORM := unix_jni
12+
13+
# Avoid touching CFLAGS too much.
14+
15+
DEFAULT_OUTMOD := jnibuf
16+
DEFAULT_MODULEDIR := "./modules"
17+
MODULES := $(MODULES_DEFAULT) out_$(DEFAULT_OUTMOD)
18+
19+
# TODO these are useless now. Set them in src/os/JniSled.java instead.
20+
#MATRIX_X := 256
21+
#MATRIX_Y := 256

Makefiles/unix_jni.GNUmakefile

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
ifeq ($(PLATFORM),unix_jni)
2+
3+
ifeq (,${JAVA_HOME})
4+
#$(error Please set JAVA_HOME)
5+
JAVA_HOME := /usr/lib/jvm/java-17-openjdk
6+
endif
7+
8+
STATIC := 1
9+
10+
CFLAGS += -fPIC
11+
12+
CFLAGS += -I${JAVA_HOME}/include/
13+
CFLAGS += -I${JAVA_HOME}/include/linux
14+
15+
16+
src/os/sh_tty_sled_JniSled.h src/os/JniSled.class: src/os/JniSled.java
17+
javac -h src/os $^
18+
19+
sh/tty/sled/JniSled.class: src/os/JniSled.class
20+
mkdir -p $(shell dirname $@)
21+
cp $^ $@
22+
23+
JNI_PROJECT := sled
24+
25+
#OBJECTS += sh_tty_sled_JniSled.h
26+
27+
#PROJECT := $(JNI_PROJECT).jar
28+
29+
lib$(PROJECT).so: $(OBJECTS) $(ML_OBJECTS)
30+
$(CC) -shared $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) $(shell cat $(PLATFORM_LIBS) $(MODULES_STATIC_LIBS) 2>/dev/null || true)
31+
32+
$(PROJECT).jar: lib$(PROJECT).so sh/tty/sled/JniSled.class
33+
zip $@ $^
34+
endif

src/modules/out_jnibuf.c

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
// Dummy output.
2+
//
3+
// Copyright (c) 2021, fridtjof <fridtjof@das-labor.org>
4+
//
5+
// Permission to use, copy, modify, and/or distribute this software for any
6+
// purpose with or without fee is hereby granted, provided that the above
7+
// copyright notice and this permission notice appear in all copies.
8+
//
9+
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10+
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11+
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12+
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13+
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14+
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15+
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16+
17+
#include "../os/sh_tty_sled_JniSled.h"
18+
19+
#include <types.h>
20+
#include <timers.h>
21+
#include <assert.h>
22+
#include <string.h>
23+
#include <stdlib.h>
24+
#include "stdio.h"
25+
26+
#define PPOS(x, y) (x + (y * matx))
27+
28+
static size_t JNI_BUFFER_SIZE;
29+
static jintArray buffers[2];
30+
static jint* working_buffer;
31+
static jint* currentBufferPtr;
32+
static int currentBuffer = -1;
33+
#define NEXTBUFFER ((currentBuffer + 1) % 2)
34+
35+
extern JNIEnv *pJniEnv;
36+
#define JniEnv (*pJniEnv)
37+
extern jobject jo_jni_sled;
38+
39+
static jclass jc_jni_sled;
40+
static jmethodID jm_setCurrentBuffer;
41+
static jfieldID jf_matx;
42+
static jfieldID jf_maty;
43+
44+
static int matx;
45+
static int maty;
46+
47+
void ignoreException() {
48+
if (JniEnv->ExceptionCheck(pJniEnv)) {
49+
// this doesn't actually output anything??
50+
JniEnv->ExceptionDescribe(pJniEnv);
51+
JniEnv->ExceptionClear(pJniEnv);
52+
}
53+
}
54+
55+
void swapBuffers() {
56+
currentBuffer = NEXTBUFFER;
57+
JniEnv->CallVoidMethodA(pJniEnv, jo_jni_sled, jm_setCurrentBuffer, (jvalue *) &buffers[currentBuffer]);
58+
59+
// warnings constantly show up with -Xcheck:jni, I have no idea why
60+
ignoreException();
61+
}
62+
63+
inline unsigned int rgb2uint(RGB color) {
64+
return (color.blue << 0) | (color.green << 8) | (color.red << 16) | (color.alpha << 24);
65+
}
66+
67+
inline RGB uint2rgb(unsigned int color) {
68+
RGB col;
69+
col.blue = (color << 0) & 0xFF;
70+
col.green = (color << 8) & 0xFF;
71+
col.red = (color << 16) & 0xFF;
72+
col.alpha = (color << 24) & 0xFF;
73+
74+
return col;
75+
}
76+
77+
int init(void) {
78+
jc_jni_sled = JniEnv->GetObjectClass(pJniEnv, jo_jni_sled);
79+
80+
// determine sizes
81+
jf_matx = JniEnv->GetStaticFieldID(pJniEnv, jc_jni_sled, "MATRIX_X", "I");
82+
jf_maty = JniEnv->GetStaticFieldID(pJniEnv, jc_jni_sled, "MATRIX_Y", "I");
83+
matx = JniEnv->GetStaticIntField(pJniEnv, jc_jni_sled, jf_matx);
84+
maty = JniEnv->GetStaticIntField(pJniEnv, jc_jni_sled, jf_maty);
85+
JNI_BUFFER_SIZE = matx * maty * sizeof(jint);
86+
87+
// allocate output buffers
88+
working_buffer = malloc(JNI_BUFFER_SIZE);
89+
buffers[0] = JniEnv->NewIntArray(pJniEnv, matx * maty);
90+
buffers[1] = JniEnv->NewIntArray(pJniEnv, matx * maty);
91+
92+
// get ready for rendering
93+
jm_setCurrentBuffer = JniEnv->GetMethodID(pJniEnv, jc_jni_sled, "setCurrentBuffer", "([I)V");
94+
swapBuffers();
95+
96+
return 0;
97+
}
98+
99+
int getx(int _modno) {
100+
return matx;
101+
}
102+
int gety(int _modno) {
103+
return maty;
104+
}
105+
106+
inline void bounds_check(int x, int y) {
107+
assert(x >= 0);
108+
assert(y >= 0);
109+
assert(x < matx);
110+
assert(y < maty);
111+
}
112+
113+
int set(int _modno, int x, int y, RGB color) {
114+
bounds_check(x, y);
115+
working_buffer[PPOS(x, y)] = rgb2uint(color);
116+
return 0;
117+
}
118+
119+
RGB get(int _modno, int x, int y) {
120+
bounds_check(x, y);
121+
return uint2rgb((unsigned int) working_buffer[PPOS(x, y)]);
122+
}
123+
124+
int clear(int _modno) {
125+
memset(working_buffer, 0, JNI_BUFFER_SIZE);
126+
return 0;
127+
}
128+
129+
int render(void) {
130+
// prepare for working on the next frame
131+
currentBufferPtr = JniEnv->GetIntArrayElements(pJniEnv, buffers[NEXTBUFFER], 0 /*ptr bool*/);
132+
memcpy(currentBufferPtr, working_buffer, JNI_BUFFER_SIZE);
133+
JniEnv->ReleaseIntArrayElements(pJniEnv, buffers[NEXTBUFFER], currentBufferPtr, 0);
134+
swapBuffers();
135+
// notify? prob not needed i think?
136+
return 0;
137+
}
138+
139+
oscore_time wait_until(int _modno, oscore_time desired_usec) {
140+
// Hey, we can just delegate work to someone else. Yay!
141+
#ifdef CIMODE
142+
return desired_usec;
143+
#else
144+
return timers_wait_until_core(desired_usec);
145+
#endif
146+
}
147+
148+
void wait_until_break(int _modno) {
149+
#ifndef CIMODE
150+
timers_wait_until_break_core();
151+
#endif
152+
}
153+
154+
void deinit(int _modno) {
155+
// TODO actually do stuff here. Sled and/or jvm won't exit properly.
156+
// maybe this needs some more fiddling in the os_ module too?
157+
}

src/os/JniSled.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package sh.tty.sled;
2+
3+
import java.awt.image.BufferedImage;
4+
import java.awt.image.DataBufferInt;
5+
6+
public class JniSled implements Runnable {
7+
static {
8+
System.loadLibrary("sled");
9+
}
10+
11+
// only set these before starting the thread!!!
12+
public static int MATRIX_X = 256;
13+
public static int MATRIX_Y = 256;
14+
15+
private int[] currentBuf;
16+
17+
public native void main();
18+
19+
@Override
20+
public void run() {
21+
main();
22+
}
23+
24+
// TODO: maybe make this trigger a callback optionally?
25+
// could use that to let the user immediately render,
26+
// "pushing" instead of polling
27+
// this would let us have a variable frame rate dictated by sled.
28+
public void setCurrentBuffer(int[] buf) {
29+
currentBuf = buf;
30+
}
31+
32+
public int[] getCurrentBuffer() {
33+
return currentBuf;
34+
}
35+
}

src/os/os_unix_jni.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// os_unix_jni
2+
// you're going to hate this
3+
//
4+
// Copyright (c) 2021, fridtjof <fridtjof@das-labor.org>
5+
//
6+
// Permission to use, copy, modify, and/or distribute this software for any
7+
// purpose with or without fee is hereby granted, provided that the above
8+
// copyright notice and this permission notice appear in all copies.
9+
//
10+
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11+
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12+
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13+
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14+
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15+
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16+
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17+
18+
#include "os_unix.c"
19+
20+
#include "sh_tty_sled_JniSled.h"
21+
22+
JNIEnv *pJniEnv;
23+
jobject jo_jni_sled;
24+
25+
JNIEXPORT void JNICALL Java_sh_tty_sled_JniSled_main(JNIEnv * env, jobject obj) {
26+
pJniEnv = env;
27+
jo_jni_sled = obj;
28+
29+
char * args[] = {"sled"};
30+
sled_main(1,args);
31+
}

src/os/os_unix_jni.libs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-lpthread

0 commit comments

Comments
 (0)