From 9c8908907ad47ffcf95affa397edda8b6bec37cf Mon Sep 17 00:00:00 2001 From: robin Date: Mon, 23 Nov 2015 23:01:40 -0500 Subject: [PATCH 01/77] mavenize --- JavaFrameBuffer/.classpath | 32 ++++++++++++++ JavaFrameBuffer/.gitignore | 3 ++ JavaFrameBuffer/.project | 23 ++++++++++ .../.settings/org.eclipse.jdt.core.prefs | 1 + JavaFrameBuffer/pom.xml | 44 +++++++++++++++++++ .../org/tw/pi/framebuffer/FrameBuffer.java | 16 ++++--- .../tw/pi/framebuffer/TestFrameBuffer.java | 0 7 files changed, 112 insertions(+), 7 deletions(-) create mode 100644 JavaFrameBuffer/.classpath create mode 100644 JavaFrameBuffer/.gitignore create mode 100644 JavaFrameBuffer/.project create mode 100644 JavaFrameBuffer/pom.xml rename JavaFrameBuffer/src/{main => test}/java/org/tw/pi/framebuffer/TestFrameBuffer.java (100%) diff --git a/JavaFrameBuffer/.classpath b/JavaFrameBuffer/.classpath new file mode 100644 index 0000000..fc6d660 --- /dev/null +++ b/JavaFrameBuffer/.classpath @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/JavaFrameBuffer/.gitignore b/JavaFrameBuffer/.gitignore new file mode 100644 index 0000000..755cdc3 --- /dev/null +++ b/JavaFrameBuffer/.gitignore @@ -0,0 +1,3 @@ +/bin/ +/target/ +/.settings/ diff --git a/JavaFrameBuffer/.project b/JavaFrameBuffer/.project new file mode 100644 index 0000000..8c183f3 --- /dev/null +++ b/JavaFrameBuffer/.project @@ -0,0 +1,23 @@ + + + framebuffer + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.m2e.core.maven2Nature + org.eclipse.jdt.core.javanature + + diff --git a/JavaFrameBuffer/.settings/org.eclipse.jdt.core.prefs b/JavaFrameBuffer/.settings/org.eclipse.jdt.core.prefs index 0f8f6c5..6effb62 100755 --- a/JavaFrameBuffer/.settings/org.eclipse.jdt.core.prefs +++ b/JavaFrameBuffer/.settings/org.eclipse.jdt.core.prefs @@ -8,5 +8,6 @@ org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning org.eclipse.jdt.core.compiler.source=1.7 org.eclipse.objectteams.otdt.compiler.option.pure_java=enabled diff --git a/JavaFrameBuffer/pom.xml b/JavaFrameBuffer/pom.xml new file mode 100644 index 0000000..36e31d0 --- /dev/null +++ b/JavaFrameBuffer/pom.xml @@ -0,0 +1,44 @@ + + 4.0.0 + org.tw.pi + framebuffer + 0.0.1-SNAPSHOT + + nar + + + + org.scijava + native-lib-loader + 2.1.2 + + + + + + + maven-compiler-plugin + 3.3 + + 1.7 + 1.7 + + + + com.github.maven-nar + nar-maven-plugin + 3.2.3 + true + + + + jni + org.tw.pi + + + + + + + \ No newline at end of file diff --git a/JavaFrameBuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java b/JavaFrameBuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java index 5ccfd13..b436a18 100755 --- a/JavaFrameBuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java +++ b/JavaFrameBuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java @@ -18,6 +18,8 @@ import javax.swing.JPanel; +import org.tw.pi.NarSystem; + /** * This class is the Java front end for a simple to use FrameBuffer driver. @@ -62,15 +64,15 @@ public class FrameBuffer { // ----------------------------------------------------------------------------------------------------------------- - private native long openDevice(String device); - private native void closeDevice(long di); - private native int getDeviceWidth(long di); - private native int getDeviceHeight(long di); - private native int getDeviceBitsPerPixel(long di); - private native boolean updateDeviceBuffer(long di,int[] buffer); + private static native long openDevice(String device); + private static native void closeDevice(long di); + private static native int getDeviceWidth(long di); + private static native int getDeviceHeight(long di); + private static native int getDeviceBitsPerPixel(long di); + private static native boolean updateDeviceBuffer(long di,int[] buffer); static { - System.loadLibrary("FrameBufferJNI"); // FrameBufferJNI.dll (Windows) or FrameBufferJNI.so (Unixes) + NarSystem.loadLibrary(); } // ----------------------------------------------------------------------------------------------------------------- diff --git a/JavaFrameBuffer/src/main/java/org/tw/pi/framebuffer/TestFrameBuffer.java b/JavaFrameBuffer/src/test/java/org/tw/pi/framebuffer/TestFrameBuffer.java similarity index 100% rename from JavaFrameBuffer/src/main/java/org/tw/pi/framebuffer/TestFrameBuffer.java rename to JavaFrameBuffer/src/test/java/org/tw/pi/framebuffer/TestFrameBuffer.java From 420d524dcd9dfa2969fa98b8cd31ec325600f2b6 Mon Sep 17 00:00:00 2001 From: robin Date: Mon, 23 Nov 2015 23:03:46 -0500 Subject: [PATCH 02/77] remove .settings file --- .../.settings/org.eclipse.jdt.core.prefs | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100755 JavaFrameBuffer/.settings/org.eclipse.jdt.core.prefs diff --git a/JavaFrameBuffer/.settings/org.eclipse.jdt.core.prefs b/JavaFrameBuffer/.settings/org.eclipse.jdt.core.prefs deleted file mode 100755 index 6effb62..0000000 --- a/JavaFrameBuffer/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,13 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.7 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.source=1.7 -org.eclipse.objectteams.otdt.compiler.option.pure_java=enabled From 5a6430b85ec89fae69c1982481306f5425afae9f Mon Sep 17 00:00:00 2001 From: robin Date: Mon, 23 Nov 2015 23:09:16 -0500 Subject: [PATCH 03/77] Move shell scripts, remove precompiled binaries --- JavaFrameBuffer/libFrameBufferJNI.jnilib | Bin 9332 -> 0 bytes JavaFrameBuffer/libFrameBufferJNI.so | Bin 8011 -> 0 bytes .../{ => src/main/sh}/compileLinux.sh | 0 JavaFrameBuffer/{ => src/main/sh}/compileMac.sh | 0 JavaFrameBuffer/{ => src/test/sh}/run.sh | 0 5 files changed, 0 insertions(+), 0 deletions(-) delete mode 100755 JavaFrameBuffer/libFrameBufferJNI.jnilib delete mode 100755 JavaFrameBuffer/libFrameBufferJNI.so rename JavaFrameBuffer/{ => src/main/sh}/compileLinux.sh (100%) rename JavaFrameBuffer/{ => src/main/sh}/compileMac.sh (100%) rename JavaFrameBuffer/{ => src/test/sh}/run.sh (100%) diff --git a/JavaFrameBuffer/libFrameBufferJNI.jnilib b/JavaFrameBuffer/libFrameBufferJNI.jnilib deleted file mode 100755 index 3345cc7bb45cfc1c663d623f402445aa82771dd0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9332 zcmeHNYiv|S6rSxvwx!Z-tgr%xi&9gRlr7;=G$!4an!B)Ip{>+Foo>5#+co>*?!C}L zFpDccuGi{D{b5YhYWzWrB2gs77t|7pfdqtzCK_oF>6ZG6F@_LjJ!kIRvfYZ5#Q5u; zbmp9I9%p90nd#2X?8z%XU7bdVEuRo_3xpXEoP~t!CJwL&xdTFF9wC%AH?%ghq=}JH z>{=Sf;FEwG<`Xk1RiqvTEkknsrKTI{XP_+<#07?F#04ag4JnN)YDauLDc7GL2Lj?U z6hUm`HYz*!hhs)D{LyYH6q96zCyw_;?ynsSgCOQzH4-NEuQRU5!AO^pJBh#FxxZ(4 zzKJ=U=o=C#RU_Mi5kCz^0#Sx1_AgOt)ND5tF)@de6s1x(4amN*WMt*?H_ZJxc}>K) zMy@BgPHKQ)N>{m?-C3o~^>H1I>jeFpzA24_XuLPv5e?CpB45{^=?<5vSr=Qy`Lv_K zh0?BQ*0P)A&%qs;br9$JD>j{hrZnXHxBfY~zgk`gakf7kFJJ1c1o9?Apw#PGx29p0 z$J}EA%O-pq62h^ zxX=;|-t3?m#x#%`fsh#JJ)rl1#x;*^^vpN9b_5*kg9dR-jS#X0=K@1Ef7$tH_dxyI zauWg1fq?Ctc=ge6@rD({AH3e*f9S&d!wVqI0f7{OR|xl-7}G#XAecO0Uv0K`fH50c ztj6WVFm4P@y>UefSJhSdd&il$2g;(~Mn0~E9Jd2Txeo&7BgTGNVliMbU@>4ZU@`Dt zGSDJwKe#u#A8|J~iOC-w9__40%N%k+6X_xNJQKA+aj3o$TLdj|%|4I-vkykl>@Xt^ zv2%wTBkAXuzx>3`b40lviWx<`+WAbX5lV@Aexhcv z>Jr2GW z%i_RDUb={tsjn2Zuf^mM$0qk?_hW9_HW*-1RXXn}tVD49O^u>b zC>Y5dcIc<5$DNQQqz^%ozQdk=4a?jdCD6WoQ`=zayj4bfdR+;kgxS7c=g7h36EK^f z7Gs8-9_^%8+j-2Red*Eu^ymc(yxP@Fsuc*-2G{CprI9oOsnw@5sbAqdBx(((+U-+%+-`CqM1%z|Zzw z7s+Kf0$m-rl%G65ujsdc=5Qk^L`)ve^CXWJh{=J1%yIRTvF6>U)n%-qCp@CwfDK&p zZ+EYpp%l5b8AfHJ;$f_KVQh}57mgvndJW9--C)5KFNG$+86TIZtH(sWEgDn1##UDfL?YlD!%H5QyXak+< z#)%odn8{?i@t8aMEn0KYI*k_YhS6haEl2B9v|wh*=zg>|p!F77?P&Fb)ga4J`F??& zi#yo4ScpbKy@DF?OR^9OM%11~f*O|uzZwqr3Vvy8uu~E$8KO&;xO$c@buAQv5jaKq z{6a;%m>5|V{+D zBik6v@3Uy*zAk}p$8(Ku$ob$TFJ>dQejw|M)8_1jd`{`b;4|4q(*C)6>%k?nVm$<%xdn?;wz+%8+z+%8+z+%8+z+%8+z+%8+ zz+%8+z+&KkWT0%mvlW{wtEKn^4i_MDjI7_{NY%pQn4dke(++rdhDY&48tzV**ivMR z6KZsZqH&1;5C8;X@Z7Bg5LP0TC6?s^JM0UEqMevigGh~peKAC}fUeaN0mb8;z6kTt zh)9wBDwYJX(bc}KJ{py~sIra5g2v;uaeYIx?p!EYL<*uYDYA-P+mJ5SNe)6?lETd` zYRvCbBm)_*qvQ?v8ANIp+^?kISvG%T(64lp7i^*w?CMs?OSZb85^t2`#$b;WBCkN% z#B3~!Q9nleX2YG$tVCYSVZJI8a^<@cxC$hA4Kv}^1@CuCAti+mmLPa_g;>BFE)WF* zVh6`>b4)n?o@4WO6EmSKmUr>|^Siy+|pFuorn71({eLgGI^sD&#lv$X ss@1X<{#2{{!#>FRSHSo9`0h6LwYj6sy=?AcbN`wkYRyyPK$Iu)Euu^nukN-MUCU%OczqBtcwQ)L{+^!I!3-EgyD z8+$S*=bU@aJ@@O}k9YRR4NZ+cpHD~#h#EmDS1Lp;X!TSf{6b8s6`Gg?UA36u=%qdB z<5OImL}8O~^iJ6mC^$}Dj{VE7-)Vg|>$6j(Gb)8?X-&zU48KLCZY;GLKe)P6u8IoaU9W?;(%B)}tg?76&*N)gI4z zzXEtUkoDLu_4JQvuiGTFpH>BZM;@ItbOUv4%c=W(?dfF=Z+`Mp;i-);pSbs$;q#Ba z_tpa&s$bmp>6EuWSiS1hnfkWgmZgKObC*8$@f&BSoPQ_!>V~sB`y2M(y$UWaf^x5O z0dItZSX)8>qmq54%(?t0IwpZ*ep?Ell;2nMT#sKA>30{&4;0Btb)iA`WRdF8OspHt-7Mfy;YtiwKn0OXWU zLnMA)RG+aU*JB#iZzFCkv6)`ww{g-Gp#q0U*_`3l$lsz_Qu*x(QU-z z$#(e8Sm|g_3QR1MY`^U`J(FoS5*>o3B9?5o;v&^!Wkh$kk(y{T?eS#B^xEl2n`o>j z!Rk)A=r+4ErZrJtou=h_x;GZJy1sF(Rc5TS>zg;WEM{ez&2)3D&x}vB&7M@$u)JZr z^DR13=~%+*5E(0Krqd!GYikc@lHtWdH(_gF(%Ui_cg+fjHMAYFu3L;iE-MMVJ zzA$|27+1@fBlyStNjcz^Quh6iKfkaMkMdld9*ZHO1L7vcF3Tz$*)JABCLBb3^Q?T) zqeC8j#iK_(`kF_Nc{C2MtjD{LbikwUVt-Tag5Hk{=NRNl9N5Q6aVfk-io;vxB+4_LSWAT*^=L& z@XZRpO5y7ieu=_I6uw5`HHEKI_>jVvD!fqmbDv-6+X(oI$X>fb+iM3R+jIWNjt_-c zU$}O3zVE%!(T{g+anG++&~xm5ZF{Z`_Cou+V=u(I0_LJB0==w@&?uV?n}FE+;qOOB z&s2l=Y1sn(3+;%_xqA(MyMU`OWxGKKfDz%gA;k7vjnl?}+D2)W(gu8#E*hPmr?2Wq zahIchGklHI&-+L;XY(V+)(mSRTkyAL^ZU^Uk$c(}L)k(}D4Rd4Z5tMmY+lr5^TDA< zP6i{73Yj_I${A z|CDW;8p1?8~%l-f5dYymsu-(V6~Gw(uawCYlRD_(2$#i4bgjdu<)%LD-)Q z?X~w~yoP6oEl_qE^V|yAkNFYsk;6K(-f@)QjdGt?egft6(O8`=l)^_deKa=@W4o0d zfbCky0nhez*p_bEW0$A)*jnoztnp@hXQ{}Qr#9Q6*3IZsHs1*QLqpJETpUvg*I;Oy z%{gd=zlEMYm>YD)Uk+ffg#3n9oiR9+0#+C8sn^_53Ci}m1C?zSq0`L;`ko4 z7r1TYIcFOB6{*B}b=DK>%$Q(V z-=ZCM^}w^XXwBxi_SAak1`wmqob(}ned4}6 z_SjXy(B#Szu|EF=<|SQs_LPhzwz2WZ4#Xw6o5XNJ(e_<1fMevm)l+ms7NCRe^7em2#wJv{8I%U)F?*5%KlpBDOg+-V2j zKv)}|Gu+n=>2xxEyN0JoB57%SjA+WEMvFR+n6Ne{gP?BdGB2ToPJ7VEICagamg#A4 zH#3=zo_M@JTqYdmlOmg5BONo^;^ug>Inlm3 z(Ye~3sMeNBY1*7Pn10J-w?v~6i^Hvz)cAM`i)c@Gcfan`5X!3zgGpIkbitu!dQz!m z+A`s^Cu3?07Hikj7oiJ_9|RI`O*?lrt}*8wi|}^dpZo^ny~^)2#If^j#`~4u7nF(T zfdBq#GJ&x%nO@d^I|n`~=QNLD}aK(0!1<1Z5i&1%3xhs6qq(FG?Szd~d8=zWjErW`)@n zGZI>DcyV~qyaly4r&F;7H@TvykHFM0jkcKZ-3WHlVo_33>YMB<^G^#__$qzV1695m zzM1}O0@c22{d0XHoayhjj5bg!?b0sEVTH|bXQC(E))R|I=f$GJk-Cgbmk3Au6R7D@ zEA47}&2$FwI8M-^OPg`pyG$x>iLmp*5Vp)d@XlvLIGuDJnPIcb{UC5{bR(TM`du5z z-`@_GaA$PK+R;=JF5Ieko{DgLvb)<%psaq~ny_J6=~!D2LYz}LAz&;bM4T8p4oaL2 zl)#uI;BDo^BV&y*N_-0_^`t~@&d(7)v||htyF4ApSe!2b&lsZ}W1AQOGUgfA^u>2= z9gs3q&R*bt;2w~`xFztt!Z@aiF-&X(Pd@~f6Yl{s?#VOui3}pPOJCAH3ZC1UcHBe6 zK1EME?xk*^wBw#5N;{5E+Vz5`e>CTu3H-k0`5-~I`v3~0o!m!9r4cCYh#P^@E(c%4 z0qMlE0TB-?cKik=!gLH|m93r~*O_-RF~kNupdG~lk8)nNPH|ECK+)LzJqsRcXYF|A zF{gGZyM3^^(zD}PIPf)gFTjTFGZvVe8T=Z%-$Bngrk#_cgWU*tt}lUo;P{7t(jU*z zt>{Dx$|TT^_(!0$>@GEqzrc=u*)DStxgtCIARGgdXUq|3H_K(6|I`tgQ-ZIQ zQ;2{5kPr)`04n|QjAxq?7QyZ#DS%2lQm&bVjb7rA`@aszF`=px%c{SPFnC=lkp5tL z5%BCF1iV(yxgun@Wu66ufY)R0c~^F4lzZEi-PPhAc4e30UUg+`G644^A>c(c_ns@e z7qQGC$($bdldE@cx7?WQ?nId*3OE@_cMrJs2qFOEoe*#$*1gMJnKOsjeZnEob5-0p zC1nngAn(b5ldXk6#0eqb+}!S+=gM3hH;!Cc-q=nt?0LgqfPkoSW?YVkCkv-i%6`Zd zkk5PLrJhS6=Z7x~%5wb7$WpEtvv>6t&IA{(7}tX!a)7g-kU3Ky#>@7&UtFkk{K@wb z+n*1Glx6=~++~BNTr}W6_YwQy!;6LfwD9535rPSOQ;ewlNTGWEa+V6p^=HSI_L$o7J ztz^c@c&}tCz3So9m0VCUzTDqaE|k@JKX|AmoQsJrvif6+ m?oFbydJ}bXiC-t&UuDMi>k>aLxxYj?y--ajxQ@y%PX7Ug)8>x= diff --git a/JavaFrameBuffer/compileLinux.sh b/JavaFrameBuffer/src/main/sh/compileLinux.sh similarity index 100% rename from JavaFrameBuffer/compileLinux.sh rename to JavaFrameBuffer/src/main/sh/compileLinux.sh diff --git a/JavaFrameBuffer/compileMac.sh b/JavaFrameBuffer/src/main/sh/compileMac.sh similarity index 100% rename from JavaFrameBuffer/compileMac.sh rename to JavaFrameBuffer/src/main/sh/compileMac.sh diff --git a/JavaFrameBuffer/run.sh b/JavaFrameBuffer/src/test/sh/run.sh similarity index 100% rename from JavaFrameBuffer/run.sh rename to JavaFrameBuffer/src/test/sh/run.sh From 518f9175b5cd4f02c5fdee5b05189e1e867d4470 Mon Sep 17 00:00:00 2001 From: robin Date: Mon, 23 Nov 2015 23:12:11 -0500 Subject: [PATCH 04/77] Accept fbdev as an argument to test --- .../src/test/java/org/tw/pi/framebuffer/TestFrameBuffer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/JavaFrameBuffer/src/test/java/org/tw/pi/framebuffer/TestFrameBuffer.java b/JavaFrameBuffer/src/test/java/org/tw/pi/framebuffer/TestFrameBuffer.java index 9a8f1f8..2fed83d 100755 --- a/JavaFrameBuffer/src/test/java/org/tw/pi/framebuffer/TestFrameBuffer.java +++ b/JavaFrameBuffer/src/test/java/org/tw/pi/framebuffer/TestFrameBuffer.java @@ -138,12 +138,12 @@ public void run() { // ----------------------------------------------------------------------------------------------------------------- public static void main(String[] args) { + final String fbdev = args.length > 0 ? args[0] : "dummy_200x300"; SwingUtilities.invokeLater(new Runnable() { @Override public void run() { -// TestFrameBuffer mt = new TestFrameBuffer("/dev/fb1"); - TestFrameBuffer mt = new TestFrameBuffer("dummy_200x330"); + TestFrameBuffer mt = new TestFrameBuffer(fbdev); if (true) { JFrame f = new JFrame("Frame Buffer Test"); From b45d3e37a11aedeed012c82ae419e5ee8fe1d35b Mon Sep 17 00:00:00 2001 From: robin Date: Mon, 23 Nov 2015 23:25:58 -0500 Subject: [PATCH 05/77] API changes, involving removal of test case --- .../org/tw/pi/framebuffer/FrameBuffer.java | 179 +++++------------- .../tw/pi/framebuffer/TestFrameBuffer.java | 162 ---------------- 2 files changed, 43 insertions(+), 298 deletions(-) delete mode 100755 JavaFrameBuffer/src/test/java/org/tw/pi/framebuffer/TestFrameBuffer.java diff --git a/JavaFrameBuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java b/JavaFrameBuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java index b436a18..d3ee9a1 100755 --- a/JavaFrameBuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java +++ b/JavaFrameBuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java @@ -9,14 +9,9 @@ package org.tw.pi.framebuffer; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.awt.image.DataBufferInt; - -import javax.swing.JPanel; +import java.io.Closeable; import org.tw.pi.NarSystem; @@ -48,7 +43,7 @@ *

* If you get the wrong colors, try the CONFIG_FB_ST7735_RGB_ORDER_REVERSED option ! */ -public class FrameBuffer { +public class FrameBuffer implements Closeable { private static final int FPS = 60; // Max. update rate @@ -77,26 +72,12 @@ public class FrameBuffer { // ----------------------------------------------------------------------------------------------------------------- - /** - * Open the named frame buffer device and starts the automatic update thread between the internal - * BufferedImage and the device. - * - * @param deviceName e.g. /dev/fb1 or dummy_320x200 - */ - public FrameBuffer(String deviceName) { - this(deviceName,true); - } - - // ----------------------------------------------------------------------------------------------------------------- - /** * Open the named frame buffer device. * * @param deviceName e.g. /dev/fb1 or dummy_320x200 - * @param autoUpdate if true, starts the automatic update thread between the internal - * BufferedImage and the device. */ - public FrameBuffer(String deviceName, boolean autoUpdate) { + public FrameBuffer(String deviceName) { this.deviceName = deviceName; @@ -108,131 +89,41 @@ public FrameBuffer(String deviceName, boolean autoUpdate) { this.width = getDeviceWidth(deviceInfo); this.height = getDeviceHeight(deviceInfo); - - System.err.println("Open with "+deviceName+" ("+deviceInfo+")"); - System.err.println(" width "+getDeviceWidth(deviceInfo)); - System.err.println(" height "+getDeviceHeight(deviceInfo)); - System.err.println(" bpp "+getDeviceBitsPerPixel(deviceInfo)); + this.bits = getDeviceBitsPerPixel(deviceInfo); // We always use ARGB image type. img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); imgBuffer = ((DataBufferInt) img.getRaster().getDataBuffer()).getBankData()[0]; - - if (autoUpdate) new UpdateThread().start(); } // ----------------------------------------------------------------------------------------------------------------- - private ScreenPanel screenPanel; - - /** - * Returns a ScreenPanel (JPanel) which represents the actual frame buffer device. - * - * @return ScreenPanel... - */ - public ScreenPanel getScreenPanel() { - synchronized (deviceName) { - if (screenPanel != null) throw new IllegalStateException("Only one screen panel supported"); - - screenPanel = new ScreenPanel(); - - return screenPanel; - } - } - // ----------------------------------------------------------------------------------------------------------------- - /** - * Internal helper class for displaying the current frame buffer image via a JPanel. - */ - @SuppressWarnings("serial") - public class ScreenPanel extends JPanel { - - private int scale = 1; - - public ScreenPanel() { - setPreferredSize(new Dimension(FrameBuffer.this.width,FrameBuffer.this.height)); - } - - @Override - protected void paintComponent(Graphics g) { - super.paintComponent(g); - - int w = this.getWidth(); - int h = this.getHeight(); - int wi = img.getWidth() * scale; - int hi = img.getHeight() * scale; - - Graphics2D g2 = (Graphics2D) g; - g2.translate(w / 2 - wi / 2, h / 2 - hi / 2); - g2.scale(scale,scale); - - g.setColor(Color.BLACK); - g.fillRect(0,0,img.getWidth(), img.getHeight() ); - g.drawImage(img, 0, 0, null); - } - - public void setScale(int scale) { - this.scale = scale; - repaint(); - } - } + // ----------------------------------------------------------------------------------------------------------------- - /** - * Internal helper class for refreshing the frame buffer display and/or JPanel. - */ - private class UpdateThread extends Thread { - - UpdateThread() { - setDaemon(true); - setName("FB "+deviceName+ " update"); - } - - @Override - public void run() { - final int SLEEP_TIME = 1000 / FPS; - - while (deviceInfo != 0) { - - if (updateScreen()) { - if (screenPanel != null) { - screenPanel.repaint(); - } - } - - try { - sleep(SLEEP_TIME); - } catch (InterruptedException e) { - break; - } - - } // while - - } - - } // class UpdateThread - // ----------------------------------------------------------------------------------------------------------------- - + /** - * Returns the BufferedImage for drawing. Anything your draw here is synchronized to the frame buffer. - * - * @return BufferedImage of type ARGB. + * Update the screen. + * + * @return true if the BufferedImage was changed since the last call. */ - public BufferedImage getScreen() { - return img; + public synchronized boolean write() { + if (deviceInfo == 0) return false; + return updateDeviceBuffer(deviceInfo,imgBuffer); } - - // ----------------------------------------------------------------------------------------------------------------- - /** * Close the device. */ - public void close() { - synchronized (deviceName) { + public synchronized void close() { + if(deviceInfo == 0) + return; + try { closeDevice(deviceInfo); + } finally { deviceInfo = 0; img = null; imgBuffer = null; @@ -241,18 +132,34 @@ public void close() { // ----------------------------------------------------------------------------------------------------------------- + + + // ----------------------------------------------------------------------------------------------------------------- + + // ----------------------------------------------------------------------------------------------------------------- + /** - * Update the screen if no automatic sync is used (see constructor autoUpdate flag). - * This method is normally called by the autoUpdate thread. - * - * @return true if the BufferedImage was changed since the last call. + * Returns the BufferedImage for drawing. Anything your draw here is synchronized to the frame buffer. + * + * @return BufferedImage of type ARGB. */ - public boolean updateScreen() { - synchronized (deviceName) { - if (deviceInfo == 0) return false; - return updateDeviceBuffer(deviceInfo,imgBuffer); - } + public BufferedImage getBufferedImage() { + return img; + } + public String getDeviceName() { + return deviceName; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public int getBits() { + return bits; } - } // of class diff --git a/JavaFrameBuffer/src/test/java/org/tw/pi/framebuffer/TestFrameBuffer.java b/JavaFrameBuffer/src/test/java/org/tw/pi/framebuffer/TestFrameBuffer.java deleted file mode 100755 index 2fed83d..0000000 --- a/JavaFrameBuffer/src/test/java/org/tw/pi/framebuffer/TestFrameBuffer.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * This file is the JNI Java part of a Raspberry Pi FrameBuffer project. - * - * Created 2013 by Thomas Welsch (ttww@gmx.de). - * - * Do whatever you want to do with it :-) - * - **/ -package org.tw.pi.framebuffer; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Font; -import java.awt.GradientPaint; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.geom.AffineTransform; -import java.awt.image.BufferedImage; -import java.util.Random; - -import javax.swing.JFrame; -import javax.swing.SwingUtilities; - - -/** - * Simple test file class for demonstrate the FrameBuffer class. - */ -public class TestFrameBuffer { - - private FrameBuffer fb; - - // ----------------------------------------------------------------------------------------------------------------- - - public TestFrameBuffer(String deviceName) { - fb = new FrameBuffer(deviceName); - } - - // ----------------------------------------------------------------------------------------------------------------- - - private void startTests() { - - new Thread("Test") { - @Override - public void run() { - BufferedImage img = fb.getScreen(); - - int w = img.getWidth(); - int h = img.getHeight(); - - Graphics2D g = img.createGraphics(); - - // RenderingHints.VALUE_ANTIALIAS_ON must before rotate ! - // Rotated font drawing behaves strange without that.... - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - - g.setColor(Color.LIGHT_GRAY); - g.fillRect(0, 0, w, h); - - g.setColor(Color.WHITE); - g.drawString("Hello world !", 22, 45); - - int y = 17; - g.setColor(Color.RED); - g.fillRect(0, y, 20,20); - y += 21; - - g.setColor(Color.GREEN); - g.fillRect(0, y, 20,20); - y += 21; - - g.setColor(Color.BLUE); - g.fillRect(0, y, 20,20); - y += 21; - - AffineTransform st = g.getTransform(); - g.translate(w/2, h/2+5); - - AffineTransform stt = g.getTransform(); - - for (int i=0; i<360; i += 4) { - - g.rotate(Math.toRadians(i)); - - g.setColor(Color.WHITE); - g.drawString("Nice !!!", 0,0); - - try { - sleep(150); - } catch (InterruptedException e) { - return; - } - - g.setColor(Color.LIGHT_GRAY); - g.drawString("Nice !!!", 0,0); - - g.setTransform(stt); -// g.rotate(Math.toRadians(-i)); - } - g.setTransform(st); - - - g.setFont(new Font("Serif", Font.BOLD, 30)); - Color c1 = new Color(0, 0, 0, 0); - Color c2 = new Color(0, 0, 0, 100); - GradientPaint gradient = new GradientPaint(10, 8, c1, 10, 40, c2, true); - - g.setColor(Color.GREEN); - g.fillRect(0, 0, w, h); - g.setColor(Color.BLACK); - g.setPaint(gradient); - g.fillRoundRect(100, 100, 200, 50, 25, 25); - g.setPaint(Color.BLACK); - g.drawRoundRect(100, 100, 200, 50, 25, 25); - g.drawString("Hello World!", 118, 135); - - try { - sleep(2000); - } catch (InterruptedException e) { - return; - } - - - Random r = new Random(); - - while (true) { - int x1 = r.nextInt(w); - int x2 = r.nextInt(w); - int y1 = r.nextInt(h); - int y2 = r.nextInt(h); - - g.setColor(new Color(r.nextInt(255),r.nextInt(255),r.nextInt(255))); - g.drawLine(x1, y1, x2, y2); - } - } - }.start(); - } - - // ----------------------------------------------------------------------------------------------------------------- - - public static void main(String[] args) { - final String fbdev = args.length > 0 ? args[0] : "dummy_200x300"; - - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - TestFrameBuffer mt = new TestFrameBuffer(fbdev); - - if (true) { - JFrame f = new JFrame("Frame Buffer Test"); - f.setSize(400, 400); - f.setLocation(300,200); - f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - f.getContentPane().add(BorderLayout.CENTER, mt.fb.getScreenPanel()); - f.setVisible(true); - } - - mt.startTests(); - } - }); - } - -} // of TestFrameBuffer From 9a8977f0bba085f090f20e0d8cc5fbbd3be2f5fd Mon Sep 17 00:00:00 2001 From: robin Date: Mon, 23 Nov 2015 23:31:04 -0500 Subject: [PATCH 06/77] Specify encodings --- JavaFrameBuffer/pom.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/JavaFrameBuffer/pom.xml b/JavaFrameBuffer/pom.xml index 36e31d0..057eeb6 100644 --- a/JavaFrameBuffer/pom.xml +++ b/JavaFrameBuffer/pom.xml @@ -23,6 +23,15 @@ 1.7 1.7 + UTF-8 + + + + org.apache.maven.plugins + maven-resources-plugin + 2.7 + + UTF-8 From 87b73956f850ff3b36d6923e691a4a4fe55f4e79 Mon Sep 17 00:00:00 2001 From: robin Date: Mon, 23 Nov 2015 23:32:27 -0500 Subject: [PATCH 07/77] Change declared version --- JavaFrameBuffer/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JavaFrameBuffer/pom.xml b/JavaFrameBuffer/pom.xml index 057eeb6..73c6192 100644 --- a/JavaFrameBuffer/pom.xml +++ b/JavaFrameBuffer/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.tw.pi framebuffer - 0.0.1-SNAPSHOT + 0.0.1-esialb-SNAPSHOT nar From 9cddb64fa3b0f1289995afe3c8c98b1fe880a9ee Mon Sep 17 00:00:00 2001 From: robin Date: Mon, 23 Nov 2015 23:36:20 -0500 Subject: [PATCH 08/77] Simple test that tries to load the native lib --- JavaFrameBuffer/pom.xml | 6 ++++++ .../java/org/tw/pi/framebuffer/FrameBufferTest.java | 10 ++++++++++ 2 files changed, 16 insertions(+) create mode 100644 JavaFrameBuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java diff --git a/JavaFrameBuffer/pom.xml b/JavaFrameBuffer/pom.xml index 73c6192..685e1fa 100644 --- a/JavaFrameBuffer/pom.xml +++ b/JavaFrameBuffer/pom.xml @@ -13,6 +13,12 @@ native-lib-loader 2.1.2 + + junit + junit + 4.12 + test + diff --git a/JavaFrameBuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/JavaFrameBuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java new file mode 100644 index 0000000..dab5f32 --- /dev/null +++ b/JavaFrameBuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -0,0 +1,10 @@ +package org.tw.pi.framebuffer; + +import org.junit.Test; + +public class FrameBufferTest { + @Test + public void testLoad() throws Exception { + Class.forName(FrameBuffer.class.getName()); + } +} From 8b2a7484c018444edfddb383aed015054a6ddedd Mon Sep 17 00:00:00 2001 From: robin Date: Mon, 23 Nov 2015 23:39:45 -0500 Subject: [PATCH 09/77] Remove generated JNI header --- JavaFrameBuffer/src/main/c/FrameBuffer.c | 2 +- .../c/org_tw_pi_framebuffer_FrameBuffer.h | 63 ------------------- 2 files changed, 1 insertion(+), 64 deletions(-) delete mode 100755 JavaFrameBuffer/src/main/c/org_tw_pi_framebuffer_FrameBuffer.h diff --git a/JavaFrameBuffer/src/main/c/FrameBuffer.c b/JavaFrameBuffer/src/main/c/FrameBuffer.c index d9be549..4048bbd 100755 --- a/JavaFrameBuffer/src/main/c/FrameBuffer.c +++ b/JavaFrameBuffer/src/main/c/FrameBuffer.c @@ -25,7 +25,7 @@ #include -#include "org_tw_pi_framebuffer_FrameBuffer.h" +#include // --------------------------------------------------------------------------------------------------------------------- // Handle structur from Java: diff --git a/JavaFrameBuffer/src/main/c/org_tw_pi_framebuffer_FrameBuffer.h b/JavaFrameBuffer/src/main/c/org_tw_pi_framebuffer_FrameBuffer.h deleted file mode 100755 index 903e132..0000000 --- a/JavaFrameBuffer/src/main/c/org_tw_pi_framebuffer_FrameBuffer.h +++ /dev/null @@ -1,63 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class org_tw_pi_framebuffer_FrameBuffer */ - -#ifndef _Included_org_tw_pi_framebuffer_FrameBuffer -#define _Included_org_tw_pi_framebuffer_FrameBuffer -#ifdef __cplusplus -extern "C" { -#endif -#undef org_tw_pi_framebuffer_FrameBuffer_FPS -#define org_tw_pi_framebuffer_FrameBuffer_FPS 50L -/* - * Class: org_tw_pi_framebuffer_FrameBuffer - * Method: openDevice - * Signature: (Ljava/lang/String;)J - */ -JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_openDevice - (JNIEnv *, jobject, jstring); - -/* - * Class: org_tw_pi_framebuffer_FrameBuffer - * Method: closeDevice - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_closeDevice - (JNIEnv *, jobject, jlong); - -/* - * Class: org_tw_pi_framebuffer_FrameBuffer - * Method: getDeviceWidth - * Signature: (J)I - */ -JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_getDeviceWidth - (JNIEnv *, jobject, jlong); - -/* - * Class: org_tw_pi_framebuffer_FrameBuffer - * Method: getDeviceHeight - * Signature: (J)I - */ -JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_getDeviceHeight - (JNIEnv *, jobject, jlong); - -/* - * Class: org_tw_pi_framebuffer_FrameBuffer - * Method: getDeviceBitsPerPixel - * Signature: (J)I - */ -JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_getDeviceBitsPerPixel - (JNIEnv *, jobject, jlong); - -/* - * Class: org_tw_pi_framebuffer_FrameBuffer - * Method: updateDeviceBuffer - * Signature: (J[I)Z - */ -JNIEXPORT jboolean JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_updateDeviceBuffer - (JNIEnv *, jobject, jlong, jintArray); - -#ifdef __cplusplus -} -#endif -#endif From 4399b19a69bb063399a840e200d437a1c0bef81b Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 00:19:48 -0500 Subject: [PATCH 10/77] read/write framebuffer support --- JavaFrameBuffer/src/main/c/FrameBuffer.c | 204 +++++++++--------- .../org/tw/pi/framebuffer/FrameBuffer.java | 20 +- 2 files changed, 124 insertions(+), 100 deletions(-) diff --git a/JavaFrameBuffer/src/main/c/FrameBuffer.c b/JavaFrameBuffer/src/main/c/FrameBuffer.c index 4048bbd..a45b8d0 100755 --- a/JavaFrameBuffer/src/main/c/FrameBuffer.c +++ b/JavaFrameBuffer/src/main/c/FrameBuffer.c @@ -10,7 +10,7 @@ * * For testing purpose a dummy device is supported (via the devicename "dummy_160x128" instead of "/dev/fb1"). * -**/ + **/ #include #include @@ -19,17 +19,14 @@ #include #ifdef __linux - #include - #include +#include +#include #endif #include #include -// --------------------------------------------------------------------------------------------------------------------- -// Handle structur from Java: -// --------------------------------------------------------------------------------------------------------------------- struct deviceInfo { char *deviceName; // Device-Name from Java ("/dev/fb1" or "dummy_240x180")... int fbfd; // File descriptor, 0 for dummy devices @@ -42,12 +39,16 @@ struct deviceInfo { char *fbp; // MemoryMapped buffer - unsigned int *currentScreen; // Last screen + unsigned int *dummy; // Last screen }; -// --------------------------------------------------------------------------------------------------------------------- -// long openDevice(String device); -// --------------------------------------------------------------------------------------------------------------------- +// http://stackoverflow.com/questions/4770985/how-to-check-if-a-string-starts-with-another-string-in-c +static int starts_with(const char *pre, const char *str) { + size_t lenpre = strlen(pre); + size_t lenstr = strlen(str); + return lenstr < lenpre ? 0 : strncmp(pre, str, lenpre) == 0; +} + JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_openDevice( JNIEnv *env, jobject obj, jstring device) { @@ -64,10 +65,10 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_openDevice( (*env)->ReleaseStringUTFChars(env, device, s); // Open the file for reading and writing - if (*di->deviceName == '/') { + if (!starts_with("dummy_", di->deviceName)) { #ifndef __linux - printf("Error: Framebuffer only under linux, use dummy device (dummy_220x440) instead %s\n",di->deviceName); + // printf("Error: Framebuffer only under linux, use dummy device (dummy_220x440) instead %s\n",di->deviceName); return (1); #else @@ -76,32 +77,29 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_openDevice( di->fbfd = open(di->deviceName, O_RDWR); if (!di->fbfd) { - printf("Error: cannot open framebuffer device. %s\n", - di->deviceName); + // printf("Error: cannot open framebuffer device. %s\n", di->deviceName); return (1); } - printf("The framebuffer device %s was opened successfully.\n", - di->deviceName); + // printf("The framebuffer device %s was opened successfully.\n", di->deviceName); // Get fixed screen information if (ioctl(di->fbfd, FBIOGET_FSCREENINFO, &finfo)) { - printf("Error reading fixed information.\n"); + // printf("Error reading fixed information.\n"); return (2); } // Get variable screen information if (ioctl(di->fbfd, FBIOGET_VSCREENINFO, &vinfo)) { - printf("Error reading variable information.\n"); + // printf("Error reading variable information.\n"); return (3); } di->width = vinfo.xres; di->height = vinfo.yres; di->bpp = vinfo.bits_per_pixel; - di->currentScreen = malloc(vinfo.xres * vinfo.yres * sizeof(int)); + di->dummy = NULL; - printf("%dx%d, %d bpp %ld bytes\n", vinfo.xres, vinfo.yres, - vinfo.bits_per_pixel, (long) finfo.smem_len); + // printf("%dx%d, %d bpp %ld bytes\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel, (long) finfo.smem_len); // map framebuffer to user memory di->screensize = finfo.smem_len; @@ -110,7 +108,7 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_openDevice( MAP_SHARED, di->fbfd, 0); if ((int) di->fbp == -1) { - printf("Failed to mmap.\n"); + // printf("Failed to mmap.\n"); return (4); } #endif @@ -118,21 +116,19 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_openDevice( // Parse dummy_123x343 sscanf(di->deviceName, "dummy_%dx%d", &di->width, &di->height); di->bpp = 0; - di->currentScreen = malloc(di->width * di->height * sizeof(int)); + di->dummy = malloc(di->width * di->height * sizeof(int)); } return (jlong) (intptr_t) di; } -// --------------------------------------------------------------------------------------------------------------------- -// void closeDevice(long di); -// --------------------------------------------------------------------------------------------------------------------- JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_closeDevice( JNIEnv *env, jobject obj, jlong jdi) { struct deviceInfo *di = (struct deviceInfo *) (intptr_t) jdi; free(di->deviceName); - free(di->currentScreen); + if(di->dummy) + free(di->dummy); if (di->fbfd != 0) { munmap(di->fbp, di->screensize); @@ -142,9 +138,6 @@ JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_closeDevice( memset(di, 0, sizeof(*di)); // :-) } -// --------------------------------------------------------------------------------------------------------------------- -// int getDeviceWidth(long di); -// --------------------------------------------------------------------------------------------------------------------- JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_getDeviceWidth( JNIEnv *env, jobject obj, jlong jdi) { @@ -153,9 +146,6 @@ JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_getDeviceWidth( return di->width; } -// --------------------------------------------------------------------------------------------------------------------- -// int getDeviceHeight(long di); -// --------------------------------------------------------------------------------------------------------------------- JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_getDeviceHeight( JNIEnv *env, jobject obj, jlong jdi) { @@ -164,9 +154,6 @@ JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_getDeviceHeight( return di->height; } -// --------------------------------------------------------------------------------------------------------------------- -// int getDeviceBitsPerPixel(long di); -// --------------------------------------------------------------------------------------------------------------------- JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_getDeviceBitsPerPixel( JNIEnv *env, jobject obj, jlong jdi) { @@ -175,42 +162,49 @@ JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_getDeviceBitsPerPi return di->bpp; } -// --------------------------------------------------------------------------------------------------------------------- -// boolean updateDeviceBuffer(long di,int[] buffer); -// --------------------------------------------------------------------------------------------------------------------- -JNIEXPORT jboolean JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_updateDeviceBuffer( +static unsigned short to_16bit(unsigned int rgb) { + unsigned char r = (rgb >> 16) & 0x0ff; + unsigned char g = (rgb >> 8) & 0x0ff; + unsigned char b = (rgb) & 0x0ff; + + return ((r / 8) << 11) + ((g / 4) << 5) + (b / 8); +} + +static unsigned int from_16bit(unsigned short rgb) { + unsigned int r = 0xff & ((rgb >> 11) << 3); + unsigned int g = 0xff & ((rgb >> 5) << 2); + unsigned int b = 0xff & (rgb << 2); + + return (r << 16) + (g << 8) + b; +} + +JNIEXPORT jboolean JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_writeDeviceBuffer( JNIEnv *env, jobject obj, jlong jdi, jintArray buf) { struct deviceInfo *di = (struct deviceInfo *) (intptr_t) jdi; int i; jsize len = (*env)->GetArrayLength(env, buf); - unsigned int *current = di->currentScreen; + unsigned int *dummy = di->dummy; int updated = 0; -// See http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/functions.html -#define USE_CRITICAL // Avoid copy, but blocks gc.... -#ifdef USE_CRITICAL jint *body = (*env)->GetPrimitiveArrayCritical(env, buf, 0); -#else - jboolean isCopy; - jint *body = (*env)->GetIntArrayElements(env, buf, &isCopy); -#endif + unsigned short *p = (unsigned short *) di->fbp; switch (di->bpp) { - case 0: { + case 0: // Dummy Device for (i = 0; i < len; i++) { - unsigned int u = body[i]; + unsigned int rgb = body[i]; - if (current[i] == u) + if (dummy[i] == rgb) continue; + updated = 1; - current[i] = u; + dummy[i] = rgb; } - } - break; - case 16: { + break; + case 16: // Comment from: // http://raspberrycompote.blogspot.de/2013/03/low-level-graphics-on-raspberry-pi-part_8.html // @@ -219,60 +213,78 @@ JNIEXPORT jboolean JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_updateDeviceBu // The green has 6 bits, so can be in the range 0-63, divide by 4, and multiply by 32 or shift // 5 bits left. Finally the blue has 5 bits and is stored at the last bits, so no need to move. - unsigned short *p = (unsigned short *) di->fbp; - for (i = 0; i < len; i++) { - unsigned int u = body[i]; + unsigned int rgb = body[i]; + unsigned int now = from_16bit(p[i]); + + if (rgb == now) continue; + + updated = 1; + + p[i] = to_16bit(rgb); + } + break; + + default: + // do nothing + break; + } + + (*env)->ReleasePrimitiveArrayCritical(env, buf, body, 0); + + return updated; +} + +JNIEXPORT jboolean JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_readDeviceBuffer( + JNIEnv *env, jobject obj, jlong jdi, jintArray buf) { + + struct deviceInfo *di = (struct deviceInfo *) (intptr_t) jdi; + int i; + jsize len = (*env)->GetArrayLength(env, buf); + unsigned int *dummy = di->dummy; + int updated = 0; - if (current[i] == u) continue; + jint *body = (*env)->GetPrimitiveArrayCritical(env, buf, 0); + unsigned short *p = (unsigned short *) di->fbp; + + switch (di->bpp) { + case 0: + // Dummy Device + for (i = 0; i < len; i++) { + unsigned int rgb = dummy[i]; + + if (body[i] == rgb) + continue; updated = 1; - current[i] = u; + body[i] = rgb; + } + break; + case 16: + // Comment from: + // http://raspberrycompote.blogspot.de/2013/03/low-level-graphics-on-raspberry-pi-part_8.html + // + // The red value has 5 bits, so can be in the range 0-31, therefore divide the original 0-255 + // value by 8. It is stored in the first 5 bits, so multiply by 2048 or shift 11 bits left. + // The green has 6 bits, so can be in the range 0-63, divide by 4, and multiply by 32 or shift + // 5 bits left. Finally the blue has 5 bits and is stored at the last bits, so no need to move. - unsigned char r = (u >> 16) & 0x0ff; - unsigned char g = (u >> 8) & 0x0ff; - unsigned char b = (u) & 0x0ff; + for (i = 0; i < len; i++) { + unsigned int rgb = from_16bit(p[i]); - //printf("%5d: %#x %3d %3d %3d %3d\n",i,u,a,r,g,b); - u = ((r / 8) << 11) + ((g / 4) << 5) + (b / 8); + if (body[i] == rgb) continue; - p[i] = u; + updated = 1; + body[i] = rgb; } - } break; - /* - case 24: - { - // untested... - for (i=0; i>16) & 0x0ff; - unsigned char g = (u >> 8) & 0x0ff; - unsigned char b = (u) & 0x0ff; - - unsigned char *p = ((unsigned char *) di->fbp) + i + i + i; - *p++ = r; - *p++ = g; - *p = b; - } - } - break; - */ + default: - fprintf(stderr, "FrameBuffer depth %d not supported, use 16 !\n", - di->bpp); + // do nothing + break; } -#ifdef USE_CRITICAL (*env)->ReleasePrimitiveArrayCritical(env, buf, body, 0); -#else - if (isCopy) (*env)->ReleaseIntArrayElements(env, buf, body, 0); -#endif return updated; } - diff --git a/JavaFrameBuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java b/JavaFrameBuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java index d3ee9a1..4e0f353 100755 --- a/JavaFrameBuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java +++ b/JavaFrameBuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java @@ -64,7 +64,8 @@ public class FrameBuffer implements Closeable { private static native int getDeviceWidth(long di); private static native int getDeviceHeight(long di); private static native int getDeviceBitsPerPixel(long di); - private static native boolean updateDeviceBuffer(long di,int[] buffer); + private static native boolean writeDeviceBuffer(long di,int[] buffer); + private static native boolean readDeviceBuffer(long di,int[] buffer); static { NarSystem.loadLibrary(); @@ -107,14 +108,25 @@ public FrameBuffer(String deviceName) { // ----------------------------------------------------------------------------------------------------------------- /** - * Update the screen. + * Update the screen from the BufferedImage. * - * @return true if the BufferedImage was changed since the last call. + * @return true if the screen was modified. */ public synchronized boolean write() { if (deviceInfo == 0) return false; - return updateDeviceBuffer(deviceInfo,imgBuffer); + return writeDeviceBuffer(deviceInfo,imgBuffer); } + + /** + * Update the BufferedImage from the screen. + * + * @return true if the BufferedImage was modified. + */ + public synchronized boolean read() { + if (deviceInfo == 0) return false; + return readDeviceBuffer(deviceInfo,imgBuffer); + } + /** * Close the device. */ From 8998b93e3dc5c0ec8d9f95bc8b58e7a9d07cad70 Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 00:26:12 -0500 Subject: [PATCH 11/77] flashy screeny thing for test --- .../tw/pi/framebuffer/FrameBufferTest.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/JavaFrameBuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/JavaFrameBuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index dab5f32..c5422c6 100644 --- a/JavaFrameBuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/JavaFrameBuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -1,5 +1,9 @@ package org.tw.pi.framebuffer; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.image.BufferedImage; + import org.junit.Test; public class FrameBufferTest { @@ -7,4 +11,25 @@ public class FrameBufferTest { public void testLoad() throws Exception { Class.forName(FrameBuffer.class.getName()); } + + public static void main(String[] args) throws Exception { + FrameBuffer fb = new FrameBuffer(args[0]); + BufferedImage buf = fb.getBufferedImage(); + BufferedImage saved = new BufferedImage(buf.getWidth(), buf.getHeight(), buf.getType()); + fb.read(); + saved.getGraphics().drawImage(buf, 0, 0, null); + try { + for(Color c = Color.WHITE; !c.equals(Color.BLACK); c = c.darker()) { + Graphics g = buf.getGraphics(); + g.setColor(c); + g.fillRect(0, 0, buf.getWidth(), buf.getHeight()); + fb.write(); + Thread.sleep(100); + } + buf.getGraphics().drawImage(saved, 0, 0, null); + fb.write(); + } finally { + fb.close(); + } + } } From a522d22004c1ed822b13edf26704043d2b44fdf7 Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 00:30:18 -0500 Subject: [PATCH 12/77] Create shaded jar --- JavaFrameBuffer/pom.xml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/JavaFrameBuffer/pom.xml b/JavaFrameBuffer/pom.xml index 685e1fa..db60674 100644 --- a/JavaFrameBuffer/pom.xml +++ b/JavaFrameBuffer/pom.xml @@ -40,6 +40,21 @@ UTF-8 + + org.apache.maven.plugins + maven-shade-plugin + 2.4.2 + + + package + shade + + false + true + + + + com.github.maven-nar nar-maven-plugin From 4cda5157b31a4fba95fa6ba14315566fda30cff8 Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 00:35:23 -0500 Subject: [PATCH 13/77] It works, don't need the shading to test it anymore. --- JavaFrameBuffer/pom.xml | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/JavaFrameBuffer/pom.xml b/JavaFrameBuffer/pom.xml index db60674..685e1fa 100644 --- a/JavaFrameBuffer/pom.xml +++ b/JavaFrameBuffer/pom.xml @@ -40,21 +40,6 @@ UTF-8 - - org.apache.maven.plugins - maven-shade-plugin - 2.4.2 - - - package - shade - - false - true - - - - com.github.maven-nar nar-maven-plugin From 6f62be5ca60cf55a2a7d276684099175a8bfbbea Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 00:36:13 -0500 Subject: [PATCH 14/77] Make private c functions inline --- JavaFrameBuffer/src/main/c/FrameBuffer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/JavaFrameBuffer/src/main/c/FrameBuffer.c b/JavaFrameBuffer/src/main/c/FrameBuffer.c index a45b8d0..d5b92f5 100755 --- a/JavaFrameBuffer/src/main/c/FrameBuffer.c +++ b/JavaFrameBuffer/src/main/c/FrameBuffer.c @@ -162,7 +162,7 @@ JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_getDeviceBitsPerPi return di->bpp; } -static unsigned short to_16bit(unsigned int rgb) { +static inline unsigned short to_16bit(unsigned int rgb) { unsigned char r = (rgb >> 16) & 0x0ff; unsigned char g = (rgb >> 8) & 0x0ff; unsigned char b = (rgb) & 0x0ff; @@ -170,7 +170,7 @@ static unsigned short to_16bit(unsigned int rgb) { return ((r / 8) << 11) + ((g / 4) << 5) + (b / 8); } -static unsigned int from_16bit(unsigned short rgb) { +static inline unsigned int from_16bit(unsigned short rgb) { unsigned int r = 0xff & ((rgb >> 11) << 3); unsigned int g = 0xff & ((rgb >> 5) << 2); unsigned int b = 0xff & (rgb << 2); From d2aff76fbffc875578a8bee9cc48d8d0e3a7cfe7 Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 00:44:44 -0500 Subject: [PATCH 15/77] rename directory --- {JavaFrameBuffer => framebuffer}/.classpath | 0 {JavaFrameBuffer => framebuffer}/.gitignore | 0 {JavaFrameBuffer => framebuffer}/.project | 0 {JavaFrameBuffer => framebuffer}/pom.xml | 0 {JavaFrameBuffer => framebuffer}/src/main/c/FrameBuffer.c | 0 .../src/main/java/org/tw/pi/framebuffer/FrameBuffer.java | 0 {JavaFrameBuffer => framebuffer}/src/main/sh/compileLinux.sh | 0 {JavaFrameBuffer => framebuffer}/src/main/sh/compileMac.sh | 0 .../src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java | 0 {JavaFrameBuffer => framebuffer}/src/test/sh/run.sh | 0 10 files changed, 0 insertions(+), 0 deletions(-) rename {JavaFrameBuffer => framebuffer}/.classpath (100%) rename {JavaFrameBuffer => framebuffer}/.gitignore (100%) rename {JavaFrameBuffer => framebuffer}/.project (100%) rename {JavaFrameBuffer => framebuffer}/pom.xml (100%) rename {JavaFrameBuffer => framebuffer}/src/main/c/FrameBuffer.c (100%) rename {JavaFrameBuffer => framebuffer}/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java (100%) rename {JavaFrameBuffer => framebuffer}/src/main/sh/compileLinux.sh (100%) rename {JavaFrameBuffer => framebuffer}/src/main/sh/compileMac.sh (100%) rename {JavaFrameBuffer => framebuffer}/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java (100%) rename {JavaFrameBuffer => framebuffer}/src/test/sh/run.sh (100%) diff --git a/JavaFrameBuffer/.classpath b/framebuffer/.classpath similarity index 100% rename from JavaFrameBuffer/.classpath rename to framebuffer/.classpath diff --git a/JavaFrameBuffer/.gitignore b/framebuffer/.gitignore similarity index 100% rename from JavaFrameBuffer/.gitignore rename to framebuffer/.gitignore diff --git a/JavaFrameBuffer/.project b/framebuffer/.project similarity index 100% rename from JavaFrameBuffer/.project rename to framebuffer/.project diff --git a/JavaFrameBuffer/pom.xml b/framebuffer/pom.xml similarity index 100% rename from JavaFrameBuffer/pom.xml rename to framebuffer/pom.xml diff --git a/JavaFrameBuffer/src/main/c/FrameBuffer.c b/framebuffer/src/main/c/FrameBuffer.c similarity index 100% rename from JavaFrameBuffer/src/main/c/FrameBuffer.c rename to framebuffer/src/main/c/FrameBuffer.c diff --git a/JavaFrameBuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java similarity index 100% rename from JavaFrameBuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java rename to framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java diff --git a/JavaFrameBuffer/src/main/sh/compileLinux.sh b/framebuffer/src/main/sh/compileLinux.sh similarity index 100% rename from JavaFrameBuffer/src/main/sh/compileLinux.sh rename to framebuffer/src/main/sh/compileLinux.sh diff --git a/JavaFrameBuffer/src/main/sh/compileMac.sh b/framebuffer/src/main/sh/compileMac.sh similarity index 100% rename from JavaFrameBuffer/src/main/sh/compileMac.sh rename to framebuffer/src/main/sh/compileMac.sh diff --git a/JavaFrameBuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java similarity index 100% rename from JavaFrameBuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java rename to framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java diff --git a/JavaFrameBuffer/src/test/sh/run.sh b/framebuffer/src/test/sh/run.sh similarity index 100% rename from JavaFrameBuffer/src/test/sh/run.sh rename to framebuffer/src/test/sh/run.sh From d87a1999b78a61c291dd4697545035514db24e21 Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 00:52:28 -0500 Subject: [PATCH 16/77] parent pom, shaded version --- framebuffer-parent/.gitignore | 2 ++ framebuffer-parent/.project | 17 +++++++++++++++ framebuffer-parent/pom.xml | 11 ++++++++++ framebuffer-shaded/.classpath | 36 ++++++++++++++++++++++++++++++++ framebuffer-shaded/.gitignore | 3 +++ framebuffer-shaded/.project | 23 +++++++++++++++++++++ framebuffer-shaded/pom.xml | 39 +++++++++++++++++++++++++++++++++++ framebuffer/pom.xml | 8 +++++-- 8 files changed, 137 insertions(+), 2 deletions(-) create mode 100644 framebuffer-parent/.gitignore create mode 100644 framebuffer-parent/.project create mode 100644 framebuffer-parent/pom.xml create mode 100644 framebuffer-shaded/.classpath create mode 100644 framebuffer-shaded/.gitignore create mode 100644 framebuffer-shaded/.project create mode 100644 framebuffer-shaded/pom.xml diff --git a/framebuffer-parent/.gitignore b/framebuffer-parent/.gitignore new file mode 100644 index 0000000..d4111ff --- /dev/null +++ b/framebuffer-parent/.gitignore @@ -0,0 +1,2 @@ +/.settings/ +/target/ diff --git a/framebuffer-parent/.project b/framebuffer-parent/.project new file mode 100644 index 0000000..2d51b9c --- /dev/null +++ b/framebuffer-parent/.project @@ -0,0 +1,17 @@ + + + framebuffer-parent + + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.m2e.core.maven2Nature + + diff --git a/framebuffer-parent/pom.xml b/framebuffer-parent/pom.xml new file mode 100644 index 0000000..5b12c50 --- /dev/null +++ b/framebuffer-parent/pom.xml @@ -0,0 +1,11 @@ + + 4.0.0 + org.tw.pi + framebuffer-parent + 0.0.1-esialb-SNAPSHOT + pom + + ../framebuffer + ../framebuffer-shaded + + \ No newline at end of file diff --git a/framebuffer-shaded/.classpath b/framebuffer-shaded/.classpath new file mode 100644 index 0000000..9fc2de7 --- /dev/null +++ b/framebuffer-shaded/.classpath @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/framebuffer-shaded/.gitignore b/framebuffer-shaded/.gitignore new file mode 100644 index 0000000..5d665db --- /dev/null +++ b/framebuffer-shaded/.gitignore @@ -0,0 +1,3 @@ +/target/ +/.settings/ +/dependency-reduced-pom.xml diff --git a/framebuffer-shaded/.project b/framebuffer-shaded/.project new file mode 100644 index 0000000..72c8cb0 --- /dev/null +++ b/framebuffer-shaded/.project @@ -0,0 +1,23 @@ + + + framebuffer-shaded + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/framebuffer-shaded/pom.xml b/framebuffer-shaded/pom.xml new file mode 100644 index 0000000..d35b0cf --- /dev/null +++ b/framebuffer-shaded/pom.xml @@ -0,0 +1,39 @@ + + 4.0.0 + framebuffer-shaded + + org.tw.pi + framebuffer-parent + 0.0.1-esialb-SNAPSHOT + ../framebuffer-parent + + + + org.tw.pi + framebuffer + 0.0.1-esialb-SNAPSHOT + nar + + + + + + org.apache.maven.plugins + maven-shade-plugin + 2.4.2 + + + shade + package + + true + false + true + + + + + + + \ No newline at end of file diff --git a/framebuffer/pom.xml b/framebuffer/pom.xml index 685e1fa..0932d1d 100644 --- a/framebuffer/pom.xml +++ b/framebuffer/pom.xml @@ -1,9 +1,7 @@ 4.0.0 - org.tw.pi framebuffer - 0.0.1-esialb-SNAPSHOT nar @@ -56,4 +54,10 @@ + + org.tw.pi + framebuffer-parent + 0.0.1-esialb-SNAPSHOT + ../framebuffer-parent + \ No newline at end of file From 3962ae86c0ab5f73157896ea6ffae42a86b39dc5 Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 00:56:39 -0500 Subject: [PATCH 17/77] Don't do the whole "modified check" thing --- framebuffer/src/main/c/FrameBuffer.c | 29 ++------------- .../org/tw/pi/framebuffer/FrameBuffer.java | 36 +++++++++---------- 2 files changed, 20 insertions(+), 45 deletions(-) diff --git a/framebuffer/src/main/c/FrameBuffer.c b/framebuffer/src/main/c/FrameBuffer.c index d5b92f5..f8e5c68 100755 --- a/framebuffer/src/main/c/FrameBuffer.c +++ b/framebuffer/src/main/c/FrameBuffer.c @@ -178,14 +178,13 @@ static inline unsigned int from_16bit(unsigned short rgb) { return (r << 16) + (g << 8) + b; } -JNIEXPORT jboolean JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_writeDeviceBuffer( +JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_writeDeviceBuffer( JNIEnv *env, jobject obj, jlong jdi, jintArray buf) { struct deviceInfo *di = (struct deviceInfo *) (intptr_t) jdi; int i; jsize len = (*env)->GetArrayLength(env, buf); unsigned int *dummy = di->dummy; - int updated = 0; jint *body = (*env)->GetPrimitiveArrayCritical(env, buf, 0); @@ -196,11 +195,6 @@ JNIEXPORT jboolean JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_writeDeviceBuf // Dummy Device for (i = 0; i < len; i++) { unsigned int rgb = body[i]; - - if (dummy[i] == rgb) - continue; - - updated = 1; dummy[i] = rgb; } break; @@ -215,12 +209,6 @@ JNIEXPORT jboolean JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_writeDeviceBuf for (i = 0; i < len; i++) { unsigned int rgb = body[i]; - unsigned int now = from_16bit(p[i]); - - if (rgb == now) continue; - - updated = 1; - p[i] = to_16bit(rgb); } break; @@ -231,18 +219,15 @@ JNIEXPORT jboolean JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_writeDeviceBuf } (*env)->ReleasePrimitiveArrayCritical(env, buf, body, 0); - - return updated; } -JNIEXPORT jboolean JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_readDeviceBuffer( +JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_readDeviceBuffer( JNIEnv *env, jobject obj, jlong jdi, jintArray buf) { struct deviceInfo *di = (struct deviceInfo *) (intptr_t) jdi; int i; jsize len = (*env)->GetArrayLength(env, buf); unsigned int *dummy = di->dummy; - int updated = 0; jint *body = (*env)->GetPrimitiveArrayCritical(env, buf, 0); @@ -253,10 +238,6 @@ JNIEXPORT jboolean JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_readDeviceBuff // Dummy Device for (i = 0; i < len; i++) { unsigned int rgb = dummy[i]; - - if (body[i] == rgb) - continue; - updated = 1; body[i] = rgb; } break; @@ -271,10 +252,6 @@ JNIEXPORT jboolean JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_readDeviceBuff for (i = 0; i < len; i++) { unsigned int rgb = from_16bit(p[i]); - - if (body[i] == rgb) continue; - - updated = 1; body[i] = rgb; } break; @@ -285,6 +262,4 @@ JNIEXPORT jboolean JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_readDeviceBuff } (*env)->ReleasePrimitiveArrayCritical(env, buf, body, 0); - - return updated; } diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java index 4e0f353..811c96c 100755 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java @@ -64,8 +64,8 @@ public class FrameBuffer implements Closeable { private static native int getDeviceWidth(long di); private static native int getDeviceHeight(long di); private static native int getDeviceBitsPerPixel(long di); - private static native boolean writeDeviceBuffer(long di,int[] buffer); - private static native boolean readDeviceBuffer(long di,int[] buffer); + private static native void writeDeviceBuffer(long di,int[] buffer); + private static native void readDeviceBuffer(long di,int[] buffer); static { NarSystem.loadLibrary(); @@ -101,32 +101,32 @@ public FrameBuffer(String deviceName) { // ----------------------------------------------------------------------------------------------------------------- - + // ----------------------------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------------------------- - + /** * Update the screen from the BufferedImage. * * @return true if the screen was modified. */ - public synchronized boolean write() { - if (deviceInfo == 0) return false; - return writeDeviceBuffer(deviceInfo,imgBuffer); + public synchronized void write() { + if (deviceInfo == 0) return; + writeDeviceBuffer(deviceInfo,imgBuffer); } - + /** * Update the BufferedImage from the screen. * * @return true if the BufferedImage was modified. */ - public synchronized boolean read() { - if (deviceInfo == 0) return false; - return readDeviceBuffer(deviceInfo,imgBuffer); + public synchronized void read() { + if (deviceInfo == 0) return; + readDeviceBuffer(deviceInfo,imgBuffer); } - + /** * Close the device. */ @@ -144,12 +144,12 @@ public synchronized void close() { // ----------------------------------------------------------------------------------------------------------------- - + // ----------------------------------------------------------------------------------------------------------------- - + // ----------------------------------------------------------------------------------------------------------------- - + /** * Returns the BufferedImage for drawing. Anything your draw here is synchronized to the frame buffer. * @@ -161,15 +161,15 @@ public BufferedImage getBufferedImage() { public String getDeviceName() { return deviceName; } - + public int getWidth() { return width; } - + public int getHeight() { return height; } - + public int getBits() { return bits; } From 4e6c5a6c8141377b52d63166f12cdee488132298 Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 01:02:16 -0500 Subject: [PATCH 18/77] newly opened framebuffers are all empty, so no point in trying to read --- framebuffer/src/main/c/FrameBuffer.c | 44 +------------------ .../org/tw/pi/framebuffer/FrameBuffer.java | 11 ----- .../tw/pi/framebuffer/FrameBufferTest.java | 5 --- 3 files changed, 1 insertion(+), 59 deletions(-) diff --git a/framebuffer/src/main/c/FrameBuffer.c b/framebuffer/src/main/c/FrameBuffer.c index f8e5c68..ca2c3ed 100755 --- a/framebuffer/src/main/c/FrameBuffer.c +++ b/framebuffer/src/main/c/FrameBuffer.c @@ -178,7 +178,7 @@ static inline unsigned int from_16bit(unsigned short rgb) { return (r << 16) + (g << 8) + b; } -JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_writeDeviceBuffer( +JNIEXPORT jvoid JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_writeDeviceBuffer( JNIEnv *env, jobject obj, jlong jdi, jintArray buf) { struct deviceInfo *di = (struct deviceInfo *) (intptr_t) jdi; @@ -221,45 +221,3 @@ JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_writeDeviceBuffer( (*env)->ReleasePrimitiveArrayCritical(env, buf, body, 0); } -JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_readDeviceBuffer( - JNIEnv *env, jobject obj, jlong jdi, jintArray buf) { - - struct deviceInfo *di = (struct deviceInfo *) (intptr_t) jdi; - int i; - jsize len = (*env)->GetArrayLength(env, buf); - unsigned int *dummy = di->dummy; - - - jint *body = (*env)->GetPrimitiveArrayCritical(env, buf, 0); - unsigned short *p = (unsigned short *) di->fbp; - - switch (di->bpp) { - case 0: - // Dummy Device - for (i = 0; i < len; i++) { - unsigned int rgb = dummy[i]; - body[i] = rgb; - } - break; - case 16: - // Comment from: - // http://raspberrycompote.blogspot.de/2013/03/low-level-graphics-on-raspberry-pi-part_8.html - // - // The red value has 5 bits, so can be in the range 0-31, therefore divide the original 0-255 - // value by 8. It is stored in the first 5 bits, so multiply by 2048 or shift 11 bits left. - // The green has 6 bits, so can be in the range 0-63, divide by 4, and multiply by 32 or shift - // 5 bits left. Finally the blue has 5 bits and is stored at the last bits, so no need to move. - - for (i = 0; i < len; i++) { - unsigned int rgb = from_16bit(p[i]); - body[i] = rgb; - } - break; - - default: - // do nothing - break; - } - - (*env)->ReleasePrimitiveArrayCritical(env, buf, body, 0); -} diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java index 811c96c..ea7a4c2 100755 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java @@ -65,7 +65,6 @@ public class FrameBuffer implements Closeable { private static native int getDeviceHeight(long di); private static native int getDeviceBitsPerPixel(long di); private static native void writeDeviceBuffer(long di,int[] buffer); - private static native void readDeviceBuffer(long di,int[] buffer); static { NarSystem.loadLibrary(); @@ -117,16 +116,6 @@ public synchronized void write() { writeDeviceBuffer(deviceInfo,imgBuffer); } - /** - * Update the BufferedImage from the screen. - * - * @return true if the BufferedImage was modified. - */ - public synchronized void read() { - if (deviceInfo == 0) return; - readDeviceBuffer(deviceInfo,imgBuffer); - } - /** * Close the device. */ diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index c5422c6..2f847a7 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -15,9 +15,6 @@ public void testLoad() throws Exception { public static void main(String[] args) throws Exception { FrameBuffer fb = new FrameBuffer(args[0]); BufferedImage buf = fb.getBufferedImage(); - BufferedImage saved = new BufferedImage(buf.getWidth(), buf.getHeight(), buf.getType()); - fb.read(); - saved.getGraphics().drawImage(buf, 0, 0, null); try { for(Color c = Color.WHITE; !c.equals(Color.BLACK); c = c.darker()) { Graphics g = buf.getGraphics(); @@ -26,8 +23,6 @@ public static void main(String[] args) throws Exception { fb.write(); Thread.sleep(100); } - buf.getGraphics().drawImage(saved, 0, 0, null); - fb.write(); } finally { fb.close(); } From 9845214bca1610eb1c30b8aa95730555b57925da Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 01:02:16 -0500 Subject: [PATCH 19/77] newly opened framebuffers are all empty, so no point in trying to read Conflicts: framebuffer/src/main/c/FrameBuffer.c framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java --- framebuffer/src/main/c/FrameBuffer.c | 53 ------------------- .../org/tw/pi/framebuffer/FrameBuffer.java | 10 ---- .../tw/pi/framebuffer/FrameBufferTest.java | 5 -- 3 files changed, 68 deletions(-) diff --git a/framebuffer/src/main/c/FrameBuffer.c b/framebuffer/src/main/c/FrameBuffer.c index d5b92f5..5d5528b 100755 --- a/framebuffer/src/main/c/FrameBuffer.c +++ b/framebuffer/src/main/c/FrameBuffer.c @@ -235,56 +235,3 @@ JNIEXPORT jboolean JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_writeDeviceBuf return updated; } -JNIEXPORT jboolean JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_readDeviceBuffer( - JNIEnv *env, jobject obj, jlong jdi, jintArray buf) { - - struct deviceInfo *di = (struct deviceInfo *) (intptr_t) jdi; - int i; - jsize len = (*env)->GetArrayLength(env, buf); - unsigned int *dummy = di->dummy; - int updated = 0; - - - jint *body = (*env)->GetPrimitiveArrayCritical(env, buf, 0); - unsigned short *p = (unsigned short *) di->fbp; - - switch (di->bpp) { - case 0: - // Dummy Device - for (i = 0; i < len; i++) { - unsigned int rgb = dummy[i]; - - if (body[i] == rgb) - continue; - updated = 1; - body[i] = rgb; - } - break; - case 16: - // Comment from: - // http://raspberrycompote.blogspot.de/2013/03/low-level-graphics-on-raspberry-pi-part_8.html - // - // The red value has 5 bits, so can be in the range 0-31, therefore divide the original 0-255 - // value by 8. It is stored in the first 5 bits, so multiply by 2048 or shift 11 bits left. - // The green has 6 bits, so can be in the range 0-63, divide by 4, and multiply by 32 or shift - // 5 bits left. Finally the blue has 5 bits and is stored at the last bits, so no need to move. - - for (i = 0; i < len; i++) { - unsigned int rgb = from_16bit(p[i]); - - if (body[i] == rgb) continue; - - updated = 1; - body[i] = rgb; - } - break; - - default: - // do nothing - break; - } - - (*env)->ReleasePrimitiveArrayCritical(env, buf, body, 0); - - return updated; -} diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java index 4e0f353..bacc9e6 100755 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java @@ -65,7 +65,6 @@ public class FrameBuffer implements Closeable { private static native int getDeviceHeight(long di); private static native int getDeviceBitsPerPixel(long di); private static native boolean writeDeviceBuffer(long di,int[] buffer); - private static native boolean readDeviceBuffer(long di,int[] buffer); static { NarSystem.loadLibrary(); @@ -117,15 +116,6 @@ public synchronized boolean write() { return writeDeviceBuffer(deviceInfo,imgBuffer); } - /** - * Update the BufferedImage from the screen. - * - * @return true if the BufferedImage was modified. - */ - public synchronized boolean read() { - if (deviceInfo == 0) return false; - return readDeviceBuffer(deviceInfo,imgBuffer); - } /** * Close the device. diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index c5422c6..2f847a7 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -15,9 +15,6 @@ public void testLoad() throws Exception { public static void main(String[] args) throws Exception { FrameBuffer fb = new FrameBuffer(args[0]); BufferedImage buf = fb.getBufferedImage(); - BufferedImage saved = new BufferedImage(buf.getWidth(), buf.getHeight(), buf.getType()); - fb.read(); - saved.getGraphics().drawImage(buf, 0, 0, null); try { for(Color c = Color.WHITE; !c.equals(Color.BLACK); c = c.darker()) { Graphics g = buf.getGraphics(); @@ -26,8 +23,6 @@ public static void main(String[] args) throws Exception { fb.write(); Thread.sleep(100); } - buf.getGraphics().drawImage(saved, 0, 0, null); - fb.write(); } finally { fb.close(); } From 7bc0b443d95281f8df82c729bfbd9af5063c68e7 Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 01:08:18 -0500 Subject: [PATCH 20/77] Keep the previous buffer to minimize writes --- framebuffer/src/main/c/FrameBuffer.c | 29 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/framebuffer/src/main/c/FrameBuffer.c b/framebuffer/src/main/c/FrameBuffer.c index 5d5528b..cfed810 100755 --- a/framebuffer/src/main/c/FrameBuffer.c +++ b/framebuffer/src/main/c/FrameBuffer.c @@ -8,7 +8,7 @@ * This code transfers an Java BufferedImage ARGB data array to a FrameBuffer device * (e.g. SPI-Displays like http://www.sainsmart.com/blog/ada/). * - * For testing purpose a dummy device is supported (via the devicename "dummy_160x128" instead of "/dev/fb1"). + * For testing purpose a previous device is supported (via the devicename "dummy_160x128" instead of "/dev/fb1"). * **/ @@ -29,17 +29,17 @@ struct deviceInfo { char *deviceName; // Device-Name from Java ("/dev/fb1" or "dummy_240x180")... - int fbfd; // File descriptor, 0 for dummy devices + int fbfd; // File descriptor, 0 for previous devices int width; int height; - int bpp; // BitsPerPixel, 0 for dummy devices + int bpp; // BitsPerPixel, 0 for previous devices long int screensize; // Buffer size in bytes char *fbp; // MemoryMapped buffer - unsigned int *dummy; // Last screen + unsigned int *previous; // Last screen }; // http://stackoverflow.com/questions/4770985/how-to-check-if-a-string-starts-with-another-string-in-c @@ -68,7 +68,7 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_openDevice( if (!starts_with("dummy_", di->deviceName)) { #ifndef __linux - // printf("Error: Framebuffer only under linux, use dummy device (dummy_220x440) instead %s\n",di->deviceName); + // printf("Error: Framebuffer only under linux, use previous device (dummy_220x440) instead %s\n",di->deviceName); return (1); #else @@ -97,7 +97,7 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_openDevice( di->width = vinfo.xres; di->height = vinfo.yres; di->bpp = vinfo.bits_per_pixel; - di->dummy = NULL; + di->previous = malloc(di->width * di->height * sizeof(int)); // printf("%dx%d, %d bpp %ld bytes\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel, (long) finfo.smem_len); @@ -116,7 +116,7 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_openDevice( // Parse dummy_123x343 sscanf(di->deviceName, "dummy_%dx%d", &di->width, &di->height); di->bpp = 0; - di->dummy = malloc(di->width * di->height * sizeof(int)); + di->previous = malloc(di->width * di->height * sizeof(int)); } return (jlong) (intptr_t) di; } @@ -127,8 +127,7 @@ JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_closeDevice( struct deviceInfo *di = (struct deviceInfo *) (intptr_t) jdi; free(di->deviceName); - if(di->dummy) - free(di->dummy); + free(di->previous); if (di->fbfd != 0) { munmap(di->fbp, di->screensize); @@ -184,7 +183,7 @@ JNIEXPORT jboolean JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_writeDeviceBuf struct deviceInfo *di = (struct deviceInfo *) (intptr_t) jdi; int i; jsize len = (*env)->GetArrayLength(env, buf); - unsigned int *dummy = di->dummy; + unsigned int *previous = di->previous; int updated = 0; @@ -197,11 +196,11 @@ JNIEXPORT jboolean JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_writeDeviceBuf for (i = 0; i < len; i++) { unsigned int rgb = body[i]; - if (dummy[i] == rgb) + if (previous[i] == rgb) continue; updated = 1; - dummy[i] = rgb; + previous[i] = rgb; } break; case 16: @@ -215,12 +214,12 @@ JNIEXPORT jboolean JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_writeDeviceBuf for (i = 0; i < len; i++) { unsigned int rgb = body[i]; - unsigned int now = from_16bit(p[i]); - if (rgb == now) continue; + if (previous[i] == rgb) + continue; updated = 1; - + previous[i] = rgb; p[i] = to_16bit(rgb); } break; From 20ca17d0e47d83088c4e28286f2f6c72882dadfb Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 01:12:23 -0500 Subject: [PATCH 21/77] Prettier test? --- .../java/org/tw/pi/framebuffer/FrameBufferTest.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index 2f847a7..15b1301 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -16,12 +16,17 @@ public static void main(String[] args) throws Exception { FrameBuffer fb = new FrameBuffer(args[0]); BufferedImage buf = fb.getBufferedImage(); try { - for(Color c = Color.WHITE; !c.equals(Color.BLACK); c = c.darker()) { - Graphics g = buf.getGraphics(); + Graphics g = buf.getGraphics(); + Color c = Color.WHITE; + for(int i = 0; i < Math.min(fb.getWidth(), fb.getHeight()) / 2; i++) { g.setColor(c); - g.fillRect(0, 0, buf.getWidth(), buf.getHeight()); + g.drawRect(i, i, fb.getWidth() - 2*i, fb.getHeight() - 2*i); fb.write(); Thread.sleep(100); + if(Color.BLACK.equals(c)) + c = Color.WHITE; + else + c = c.darker(); } } finally { fb.close(); From 5c7e8a7eab8c8f8051877d79b605b80d7f1dcf6f Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 01:15:53 -0500 Subject: [PATCH 22/77] more colory? --- .../test/java/org/tw/pi/framebuffer/FrameBufferTest.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index 15b1301..12d647c 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -17,16 +17,11 @@ public static void main(String[] args) throws Exception { BufferedImage buf = fb.getBufferedImage(); try { Graphics g = buf.getGraphics(); - Color c = Color.WHITE; for(int i = 0; i < Math.min(fb.getWidth(), fb.getHeight()) / 2; i++) { - g.setColor(c); + g.setColor(new Color((int)(0xFFFFFF * Math.random()))); g.drawRect(i, i, fb.getWidth() - 2*i, fb.getHeight() - 2*i); fb.write(); Thread.sleep(100); - if(Color.BLACK.equals(c)) - c = Color.WHITE; - else - c = c.darker(); } } finally { fb.close(); From dc5b916586220a94320c944d9969c73f38eb633e Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 01:20:22 -0500 Subject: [PATCH 23/77] Don't sleep --- .../src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index 12d647c..b7246e4 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -21,7 +21,6 @@ public static void main(String[] args) throws Exception { g.setColor(new Color((int)(0xFFFFFF * Math.random()))); g.drawRect(i, i, fb.getWidth() - 2*i, fb.getHeight() - 2*i); fb.write(); - Thread.sleep(100); } } finally { fb.close(); From 6d0f1225adb85e606c1e7cb6d8abd86b77811117 Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 18:43:18 -0500 Subject: [PATCH 24/77] rastery stuff --- framebuffer/src/main/c/FrameBuffer.c | 156 ++++++------------ .../org/tw/pi/framebuffer/FrameBuffer.java | 132 ++------------- .../pi/framebuffer/FrameBufferDataBuffer.java | 60 +++++++ .../tw/pi/framebuffer/FrameBufferImage.java | 33 ++++ .../tw/pi/framebuffer/FrameBufferRaster.java | 36 ++++ .../tw/pi/framebuffer/FrameBufferTest.java | 6 +- 6 files changed, 188 insertions(+), 235 deletions(-) create mode 100644 framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferDataBuffer.java create mode 100644 framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java create mode 100644 framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java diff --git a/framebuffer/src/main/c/FrameBuffer.c b/framebuffer/src/main/c/FrameBuffer.c index cfed810..783effd 100755 --- a/framebuffer/src/main/c/FrameBuffer.c +++ b/framebuffer/src/main/c/FrameBuffer.c @@ -18,10 +18,8 @@ #include #include -#ifdef __linux #include #include -#endif #include @@ -42,13 +40,6 @@ struct deviceInfo { unsigned int *previous; // Last screen }; -// http://stackoverflow.com/questions/4770985/how-to-check-if-a-string-starts-with-another-string-in-c -static int starts_with(const char *pre, const char *str) { - size_t lenpre = strlen(pre); - size_t lenstr = strlen(str); - return lenstr < lenpre ? 0 : strncmp(pre, str, lenpre) == 0; -} - JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_openDevice( JNIEnv *env, jobject obj, jstring device) { @@ -65,59 +56,46 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_openDevice( (*env)->ReleaseStringUTFChars(env, device, s); // Open the file for reading and writing - if (!starts_with("dummy_", di->deviceName)) { + struct fb_var_screeninfo vinfo; + struct fb_fix_screeninfo finfo; -#ifndef __linux - // printf("Error: Framebuffer only under linux, use previous device (dummy_220x440) instead %s\n",di->deviceName); + di->fbfd = open(di->deviceName, O_RDWR); + if (!di->fbfd) { + // printf("Error: cannot open framebuffer device. %s\n", di->deviceName); return (1); -#else - - struct fb_var_screeninfo vinfo; - struct fb_fix_screeninfo finfo; - - di->fbfd = open(di->deviceName, O_RDWR); - if (!di->fbfd) { - // printf("Error: cannot open framebuffer device. %s\n", di->deviceName); - return (1); - } - // printf("The framebuffer device %s was opened successfully.\n", di->deviceName); - - // Get fixed screen information - if (ioctl(di->fbfd, FBIOGET_FSCREENINFO, &finfo)) { - // printf("Error reading fixed information.\n"); - return (2); - } - - // Get variable screen information - if (ioctl(di->fbfd, FBIOGET_VSCREENINFO, &vinfo)) { - // printf("Error reading variable information.\n"); - return (3); - } - - di->width = vinfo.xres; - di->height = vinfo.yres; - di->bpp = vinfo.bits_per_pixel; - di->previous = malloc(di->width * di->height * sizeof(int)); - - // printf("%dx%d, %d bpp %ld bytes\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel, (long) finfo.smem_len); - - // map framebuffer to user memory - di->screensize = finfo.smem_len; - - di->fbp = (char*) mmap(0, di->screensize, PROT_READ | PROT_WRITE, - MAP_SHARED, di->fbfd, 0); - - if ((int) di->fbp == -1) { - // printf("Failed to mmap.\n"); - return (4); - } -#endif - } else { - // Parse dummy_123x343 - sscanf(di->deviceName, "dummy_%dx%d", &di->width, &di->height); - di->bpp = 0; - di->previous = malloc(di->width * di->height * sizeof(int)); } + // printf("The framebuffer device %s was opened successfully.\n", di->deviceName); + + // Get fixed screen information + if (ioctl(di->fbfd, FBIOGET_FSCREENINFO, &finfo)) { + // printf("Error reading fixed information.\n"); + return (2); + } + + // Get variable screen information + if (ioctl(di->fbfd, FBIOGET_VSCREENINFO, &vinfo)) { + // printf("Error reading variable information.\n"); + return (3); + } + + di->width = vinfo.xres; + di->height = vinfo.yres; + di->bpp = vinfo.bits_per_pixel; + di->previous = malloc(di->width * di->height * sizeof(int)); + + // printf("%dx%d, %d bpp %ld bytes\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel, (long) finfo.smem_len); + + // map framebuffer to user memory + di->screensize = finfo.smem_len; + + di->fbp = (char*) mmap(0, di->screensize, PROT_READ | PROT_WRITE, + MAP_SHARED, di->fbfd, 0); + + if ((int) di->fbp == -1) { + // printf("Failed to mmap.\n"); + return (4); + } + return (jlong) (intptr_t) di; } @@ -177,60 +155,18 @@ static inline unsigned int from_16bit(unsigned short rgb) { return (r << 16) + (g << 8) + b; } -JNIEXPORT jboolean JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_writeDeviceBuffer( - JNIEnv *env, jobject obj, jlong jdi, jintArray buf) { - +JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_writeRGB +(JNIEnv *env, jclass clazz, jlong ptr, jint idx, jint rgb) { struct deviceInfo *di = (struct deviceInfo *) (intptr_t) jdi; - int i; - jsize len = (*env)->GetArrayLength(env, buf); - unsigned int *previous = di->previous; - int updated = 0; - - - jint *body = (*env)->GetPrimitiveArrayCritical(env, buf, 0); unsigned short *p = (unsigned short *) di->fbp; - switch (di->bpp) { - case 0: - // Dummy Device - for (i = 0; i < len; i++) { - unsigned int rgb = body[i]; - - if (previous[i] == rgb) - continue; - - updated = 1; - previous[i] = rgb; - } - break; - case 16: - // Comment from: - // http://raspberrycompote.blogspot.de/2013/03/low-level-graphics-on-raspberry-pi-part_8.html - // - // The red value has 5 bits, so can be in the range 0-31, therefore divide the original 0-255 - // value by 8. It is stored in the first 5 bits, so multiply by 2048 or shift 11 bits left. - // The green has 6 bits, so can be in the range 0-63, divide by 4, and multiply by 32 or shift - // 5 bits left. Finally the blue has 5 bits and is stored at the last bits, so no need to move. - - for (i = 0; i < len; i++) { - unsigned int rgb = body[i]; - - if (previous[i] == rgb) - continue; - - updated = 1; - previous[i] = rgb; - p[i] = to_16bit(rgb); - } - break; - - default: - // do nothing - break; - } + p[idx] = to_16bit(rgb); +} - (*env)->ReleasePrimitiveArrayCritical(env, buf, body, 0); +JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_readRGB +(JNIEnv *env, jclass clazz, jlong ptr, jint idx) { + struct deviceInfo *di = (struct deviceInfo *) (intptr_t) jdi; + unsigned short *p = (unsigned short *) di->fbp; - return updated; + return from_16bit(p[idx]); } - diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java index bacc9e6..f0937ed 100755 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java @@ -9,10 +9,6 @@ package org.tw.pi.framebuffer; -import java.awt.image.BufferedImage; -import java.awt.image.DataBufferInt; -import java.io.Closeable; - import org.tw.pi.NarSystem; @@ -43,125 +39,19 @@ *

* If you get the wrong colors, try the CONFIG_FB_ST7735_RGB_ORDER_REVERSED option ! */ -public class FrameBuffer implements Closeable { - - private static final int FPS = 60; // Max. update rate - - private String deviceName; - - private long deviceInfo; // Private data from JNI C - - private int width,height; - private int bits; - - private BufferedImage img; - private int[] imgBuffer; - - // ----------------------------------------------------------------------------------------------------------------- - - private static native long openDevice(String device); - private static native void closeDevice(long di); - private static native int getDeviceWidth(long di); - private static native int getDeviceHeight(long di); - private static native int getDeviceBitsPerPixel(long di); - private static native boolean writeDeviceBuffer(long di,int[] buffer); +public abstract class FrameBuffer { + public static native long openDevice(String device); + public static native void closeDevice(long di); + public static native int getDeviceWidth(long di); + public static native int getDeviceHeight(long di); + public static native int getDeviceBitsPerPixel(long di); + public static native void writeRGB(long di, int idx, int rgb); + public static native int readRGB(long di, int idx); + static { NarSystem.loadLibrary(); } - // ----------------------------------------------------------------------------------------------------------------- - - /** - * Open the named frame buffer device. - * - * @param deviceName e.g. /dev/fb1 or dummy_320x200 - */ - public FrameBuffer(String deviceName) { - - this.deviceName = deviceName; - - deviceInfo = openDevice(deviceName); - - if (deviceInfo < 10) { - throw new IllegalArgumentException("Init. for frame buffer "+deviceName+" failed with error code "+deviceInfo); - } - - this.width = getDeviceWidth(deviceInfo); - this.height = getDeviceHeight(deviceInfo); - this.bits = getDeviceBitsPerPixel(deviceInfo); - - // We always use ARGB image type. - img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); - imgBuffer = ((DataBufferInt) img.getRaster().getDataBuffer()).getBankData()[0]; - } - - // ----------------------------------------------------------------------------------------------------------------- - - // ----------------------------------------------------------------------------------------------------------------- - - - - // ----------------------------------------------------------------------------------------------------------------- - - // ----------------------------------------------------------------------------------------------------------------- - - /** - * Update the screen from the BufferedImage. - * - * @return true if the screen was modified. - */ - public synchronized boolean write() { - if (deviceInfo == 0) return false; - return writeDeviceBuffer(deviceInfo,imgBuffer); - } - - - /** - * Close the device. - */ - public synchronized void close() { - if(deviceInfo == 0) - return; - try { - closeDevice(deviceInfo); - } finally { - deviceInfo = 0; - img = null; - imgBuffer = null; - } - } - - // ----------------------------------------------------------------------------------------------------------------- - - - - // ----------------------------------------------------------------------------------------------------------------- - - // ----------------------------------------------------------------------------------------------------------------- - - /** - * Returns the BufferedImage for drawing. Anything your draw here is synchronized to the frame buffer. - * - * @return BufferedImage of type ARGB. - */ - public BufferedImage getBufferedImage() { - return img; - } - public String getDeviceName() { - return deviceName; - } - - public int getWidth() { - return width; - } - - public int getHeight() { - return height; - } - - public int getBits() { - return bits; - } - -} // of class + private FrameBuffer() {} +} diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferDataBuffer.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferDataBuffer.java new file mode 100644 index 0000000..78771c7 --- /dev/null +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferDataBuffer.java @@ -0,0 +1,60 @@ +package org.tw.pi.framebuffer; + +import java.awt.image.DataBuffer; + +public class FrameBufferDataBuffer extends DataBuffer { + + private static long open(String fbdev) { + long ptr = FrameBuffer.openDevice(fbdev); + + if (ptr < 10) { + throw new IllegalArgumentException("Init. for frame buffer " + fbdev + " failed with error code " + ptr); + } + + return ptr; + } + + private long ptr; + + public FrameBufferDataBuffer(String fbdev) { + this(open(fbdev)); + } + + private FrameBufferDataBuffer(long ptr) { + super(TYPE_INT, FrameBuffer.getDeviceWidth(ptr) * FrameBuffer.getDeviceHeight(ptr)); + this.ptr = ptr; + } + + @Override + public int getElem(int bank, int i) { + if(ptr == 0) + throw new IllegalStateException(); + return FrameBuffer.readRGB(ptr, i); + } + + @Override + public void setElem(int bank, int i, int val) { + if(ptr == 0) + throw new IllegalStateException(); + FrameBuffer.writeRGB(ptr, i, val); + } + + public void close() { + if(ptr != 0) { + FrameBuffer.closeDevice(ptr); + ptr = 0; + } + } + + public int getWidth() { + if(ptr == 0) + throw new IllegalStateException(); + return FrameBuffer.getDeviceWidth(ptr); + } + + public int getHeight() { + if(ptr == 0) + throw new IllegalStateException(); + return FrameBuffer.getDeviceHeight(ptr); + } +} diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java new file mode 100644 index 0000000..d9ca2c9 --- /dev/null +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java @@ -0,0 +1,33 @@ +package org.tw.pi.framebuffer; + +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.DirectColorModel; +import java.awt.image.WritableRaster; + +public class FrameBufferImage extends BufferedImage { + private static ColorModel createColorModel() { + return new DirectColorModel(24, + 0x00ff0000, // Red + 0x0000ff00, // Green + 0x000000ff, // Blue + 0x0 // Alpha + ); + } + + private static WritableRaster createWritableRaster(FrameBufferDataBuffer dataBuffer) { + return new FrameBufferRaster(dataBuffer); + } + + public FrameBufferImage(String fbdev) { + this(new FrameBufferDataBuffer(fbdev)); + } + + public FrameBufferImage(FrameBufferDataBuffer dataBuffer) { + super(createColorModel(), createWritableRaster(dataBuffer), true, null); + } + + public void close() { + ((FrameBufferRaster) getData()).close(); + } +} diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java new file mode 100644 index 0000000..077bb6b --- /dev/null +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java @@ -0,0 +1,36 @@ +package org.tw.pi.framebuffer; + +import java.awt.Point; +import java.awt.image.DataBuffer; +import java.awt.image.SampleModel; +import java.awt.image.SinglePixelPackedSampleModel; +import java.awt.image.WritableRaster; + +public class FrameBufferRaster extends WritableRaster { + + private static SampleModel createSampleModel(FrameBufferDataBuffer dataBuffer) { + return new SinglePixelPackedSampleModel( + DataBuffer.TYPE_INT, + dataBuffer.getWidth(), + dataBuffer.getHeight(), + new int[] { + 0x00ff0000, // Red + 0x0000ff00, // Green + 0x000000ff, // Blue + 0x00000000 // alpha + }); + } + + public FrameBufferRaster(String fbdev) { + this(new FrameBufferDataBuffer(fbdev)); + } + + public FrameBufferRaster(FrameBufferDataBuffer dataBuffer) { + super(createSampleModel(dataBuffer), dataBuffer, new Point(0, 0)); + } + + public void close() { + ((FrameBufferDataBuffer) dataBuffer).close(); + } + +} diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index b7246e4..559a54a 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -13,14 +13,12 @@ public void testLoad() throws Exception { } public static void main(String[] args) throws Exception { - FrameBuffer fb = new FrameBuffer(args[0]); - BufferedImage buf = fb.getBufferedImage(); + FrameBufferImage fb = new FrameBufferImage(args[0]); try { - Graphics g = buf.getGraphics(); + Graphics g = fb.getGraphics(); for(int i = 0; i < Math.min(fb.getWidth(), fb.getHeight()) / 2; i++) { g.setColor(new Color((int)(0xFFFFFF * Math.random()))); g.drawRect(i, i, fb.getWidth() - 2*i, fb.getHeight() - 2*i); - fb.write(); } } finally { fb.close(); From 4e77165089ec04696ef56fde8fea62137e74bc51 Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 18:46:12 -0500 Subject: [PATCH 25/77] fix varname --- framebuffer/src/main/c/FrameBuffer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framebuffer/src/main/c/FrameBuffer.c b/framebuffer/src/main/c/FrameBuffer.c index 783effd..21e1249 100755 --- a/framebuffer/src/main/c/FrameBuffer.c +++ b/framebuffer/src/main/c/FrameBuffer.c @@ -157,7 +157,7 @@ static inline unsigned int from_16bit(unsigned short rgb) { JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_writeRGB (JNIEnv *env, jclass clazz, jlong ptr, jint idx, jint rgb) { - struct deviceInfo *di = (struct deviceInfo *) (intptr_t) jdi; + struct deviceInfo *di = (struct deviceInfo *) (intptr_t) ptr; unsigned short *p = (unsigned short *) di->fbp; p[idx] = to_16bit(rgb); @@ -165,7 +165,7 @@ JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_writeRGB JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_readRGB (JNIEnv *env, jclass clazz, jlong ptr, jint idx) { - struct deviceInfo *di = (struct deviceInfo *) (intptr_t) jdi; + struct deviceInfo *di = (struct deviceInfo *) (intptr_t) ptr; unsigned short *p = (unsigned short *) di->fbp; return from_16bit(p[idx]); From d82736747b41c305f4ca9bf911009cf2434708ca Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 18:49:14 -0500 Subject: [PATCH 26/77] fix sample model? --- .../main/java/org/tw/pi/framebuffer/FrameBufferRaster.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java index 077bb6b..d9164fe 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java @@ -14,10 +14,7 @@ private static SampleModel createSampleModel(FrameBufferDataBuffer dataBuffer) { dataBuffer.getWidth(), dataBuffer.getHeight(), new int[] { - 0x00ff0000, // Red - 0x0000ff00, // Green - 0x000000ff, // Blue - 0x00000000 // alpha + 0x00ffffff }); } From 0c796687d17f23f1bd971e3356d691680d899fca Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 18:56:49 -0500 Subject: [PATCH 27/77] Fix sampling compatibility --- .../java/org/tw/pi/framebuffer/FrameBufferImage.java | 4 ++-- .../org/tw/pi/framebuffer/FrameBufferRaster.java | 12 +++++++----- .../org/tw/pi/framebuffer/FrameBufferImageTest.java | 11 +++++++++++ 3 files changed, 20 insertions(+), 7 deletions(-) create mode 100644 framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java index d9ca2c9..39bcb4a 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java @@ -6,7 +6,7 @@ import java.awt.image.WritableRaster; public class FrameBufferImage extends BufferedImage { - private static ColorModel createColorModel() { + static ColorModel createColorModel() { return new DirectColorModel(24, 0x00ff0000, // Red 0x0000ff00, // Green @@ -15,7 +15,7 @@ private static ColorModel createColorModel() { ); } - private static WritableRaster createWritableRaster(FrameBufferDataBuffer dataBuffer) { + static WritableRaster createWritableRaster(FrameBufferDataBuffer dataBuffer) { return new FrameBufferRaster(dataBuffer); } diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java index d9164fe..dfe3bef 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java @@ -8,13 +8,15 @@ public class FrameBufferRaster extends WritableRaster { - private static SampleModel createSampleModel(FrameBufferDataBuffer dataBuffer) { + static SampleModel createSampleModel(int w, int h) { return new SinglePixelPackedSampleModel( DataBuffer.TYPE_INT, - dataBuffer.getWidth(), - dataBuffer.getHeight(), + w, + h, new int[] { - 0x00ffffff + 0x00ff0000, + 0x0000ff00, + 0x000000ff, }); } @@ -23,7 +25,7 @@ public FrameBufferRaster(String fbdev) { } public FrameBufferRaster(FrameBufferDataBuffer dataBuffer) { - super(createSampleModel(dataBuffer), dataBuffer, new Point(0, 0)); + super(createSampleModel(dataBuffer.getWidth(), dataBuffer.getHeight()), dataBuffer, new Point(0, 0)); } public void close() { diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java new file mode 100644 index 0000000..bde15e8 --- /dev/null +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java @@ -0,0 +1,11 @@ +package org.tw.pi.framebuffer; + +import org.junit.Assert; +import org.junit.Test; + +public class FrameBufferImageTest { + @Test + public void testCompatibility() { + Assert.assertTrue(FrameBufferImage.createColorModel().isCompatibleSampleModel(FrameBufferRaster.createSampleModel(1, 1))); + } +} From 0e3b0054d61e2f6ee1f6f2e3819056e320ee19d6 Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 18:58:15 -0500 Subject: [PATCH 28/77] Make FrameBuffer JNI class package-private --- .../java/org/tw/pi/framebuffer/FrameBuffer.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java index f0937ed..69580e6 100755 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java @@ -39,15 +39,15 @@ *

* If you get the wrong colors, try the CONFIG_FB_ST7735_RGB_ORDER_REVERSED option ! */ -public abstract class FrameBuffer { +abstract class FrameBuffer { - public static native long openDevice(String device); - public static native void closeDevice(long di); - public static native int getDeviceWidth(long di); - public static native int getDeviceHeight(long di); - public static native int getDeviceBitsPerPixel(long di); - public static native void writeRGB(long di, int idx, int rgb); - public static native int readRGB(long di, int idx); + static native long openDevice(String device); + static native void closeDevice(long di); + static native int getDeviceWidth(long di); + static native int getDeviceHeight(long di); + static native int getDeviceBitsPerPixel(long di); + static native void writeRGB(long di, int idx, int rgb); + static native int readRGB(long di, int idx); static { NarSystem.loadLibrary(); From 3f6b46ed5fd1920a591ce5a15922ffb9fc977a47 Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 19:07:22 -0500 Subject: [PATCH 29/77] working? --- .../tw/pi/framebuffer/FrameBufferDataBuffer.java | 15 ++++++++++++--- .../tw/pi/framebuffer/FrameBufferImageTest.java | 1 + 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferDataBuffer.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferDataBuffer.java index 78771c7..55c2fe7 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferDataBuffer.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferDataBuffer.java @@ -20,8 +20,8 @@ public FrameBufferDataBuffer(String fbdev) { this(open(fbdev)); } - private FrameBufferDataBuffer(long ptr) { - super(TYPE_INT, FrameBuffer.getDeviceWidth(ptr) * FrameBuffer.getDeviceHeight(ptr)); + FrameBufferDataBuffer(long ptr) { + super(TYPE_INT, ptr == -1 ? 1 : FrameBuffer.getDeviceWidth(ptr) * FrameBuffer.getDeviceHeight(ptr)); this.ptr = ptr; } @@ -29,6 +29,8 @@ private FrameBufferDataBuffer(long ptr) { public int getElem(int bank, int i) { if(ptr == 0) throw new IllegalStateException(); + if(ptr == -1) + return 0; return FrameBuffer.readRGB(ptr, i); } @@ -36,12 +38,15 @@ public int getElem(int bank, int i) { public void setElem(int bank, int i, int val) { if(ptr == 0) throw new IllegalStateException(); + if(ptr == -1) + return; FrameBuffer.writeRGB(ptr, i, val); } public void close() { if(ptr != 0) { - FrameBuffer.closeDevice(ptr); + if(ptr != -1) + FrameBuffer.closeDevice(ptr); ptr = 0; } } @@ -49,12 +54,16 @@ public void close() { public int getWidth() { if(ptr == 0) throw new IllegalStateException(); + if(ptr == -1) + return 1; return FrameBuffer.getDeviceWidth(ptr); } public int getHeight() { if(ptr == 0) throw new IllegalStateException(); + if(ptr == -1) + return 1; return FrameBuffer.getDeviceHeight(ptr); } } diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java index bde15e8..1877a73 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java @@ -7,5 +7,6 @@ public class FrameBufferImageTest { @Test public void testCompatibility() { Assert.assertTrue(FrameBufferImage.createColorModel().isCompatibleSampleModel(FrameBufferRaster.createSampleModel(1, 1))); + Assert.assertTrue(FrameBufferImage.createColorModel().isCompatibleRaster(new FrameBufferRaster(new FrameBufferDataBuffer(-1)))); } } From 639ad30d523b27a05cd0b17642c461c7f17d17dc Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 19:12:48 -0500 Subject: [PATCH 30/77] fixes --- .../pi/framebuffer/FrameBufferDataBuffer.java | 29 ++++++++++--------- .../tw/pi/framebuffer/FrameBufferImage.java | 5 +++- .../pi/framebuffer/FrameBufferImageTest.java | 2 +- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferDataBuffer.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferDataBuffer.java index 55c2fe7..27cf712 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferDataBuffer.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferDataBuffer.java @@ -4,7 +4,7 @@ public class FrameBufferDataBuffer extends DataBuffer { - private static long open(String fbdev) { + static long open(String fbdev) { long ptr = FrameBuffer.openDevice(fbdev); if (ptr < 10) { @@ -15,14 +15,25 @@ private static long open(String fbdev) { } private long ptr; + private int w; + private int h; public FrameBufferDataBuffer(String fbdev) { this(open(fbdev)); } - FrameBufferDataBuffer(long ptr) { - super(TYPE_INT, ptr == -1 ? 1 : FrameBuffer.getDeviceWidth(ptr) * FrameBuffer.getDeviceHeight(ptr)); + public FrameBufferDataBuffer(int w, int h) { + super(TYPE_INT, w * h); + this.ptr = -1; + this.w = w; + this.h = h; + } + + private FrameBufferDataBuffer(long ptr) { + super(TYPE_INT, FrameBuffer.getDeviceWidth(ptr) * FrameBuffer.getDeviceHeight(ptr)); this.ptr = ptr; + this.w = FrameBuffer.getDeviceWidth(ptr); + this.h = FrameBuffer.getDeviceHeight(ptr); } @Override @@ -52,18 +63,10 @@ public void close() { } public int getWidth() { - if(ptr == 0) - throw new IllegalStateException(); - if(ptr == -1) - return 1; - return FrameBuffer.getDeviceWidth(ptr); + return w; } public int getHeight() { - if(ptr == 0) - throw new IllegalStateException(); - if(ptr == -1) - return 1; - return FrameBuffer.getDeviceHeight(ptr); + return h; } } diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java index 39bcb4a..b716e27 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java @@ -19,15 +19,18 @@ static WritableRaster createWritableRaster(FrameBufferDataBuffer dataBuffer) { return new FrameBufferRaster(dataBuffer); } + private FrameBufferDataBuffer dataBuffer; + public FrameBufferImage(String fbdev) { this(new FrameBufferDataBuffer(fbdev)); } public FrameBufferImage(FrameBufferDataBuffer dataBuffer) { super(createColorModel(), createWritableRaster(dataBuffer), true, null); + this.dataBuffer = dataBuffer; } public void close() { - ((FrameBufferRaster) getData()).close(); + dataBuffer.close(); } } diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java index 1877a73..c2cd7c1 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java @@ -7,6 +7,6 @@ public class FrameBufferImageTest { @Test public void testCompatibility() { Assert.assertTrue(FrameBufferImage.createColorModel().isCompatibleSampleModel(FrameBufferRaster.createSampleModel(1, 1))); - Assert.assertTrue(FrameBufferImage.createColorModel().isCompatibleRaster(new FrameBufferRaster(new FrameBufferDataBuffer(-1)))); + Assert.assertTrue(FrameBufferImage.createColorModel().isCompatibleRaster(new FrameBufferRaster(new FrameBufferDataBuffer(1,1)))); } } From c030dd4a78461a78b4b72cc0f7995ac3fb90a2ca Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 19:18:51 -0500 Subject: [PATCH 31/77] Relocate scijava's nativelib --- framebuffer-shaded/pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/framebuffer-shaded/pom.xml b/framebuffer-shaded/pom.xml index d35b0cf..63db5bd 100644 --- a/framebuffer-shaded/pom.xml +++ b/framebuffer-shaded/pom.xml @@ -30,6 +30,12 @@ true false true + + + org.scijava.nativelib + org.tw.pi.framebuffer.org.scijava.nativelib + + From 1b4442147d8a640e53726cf68ea1c0bded39891e Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 19:24:45 -0500 Subject: [PATCH 32/77] Compile on non-linux, default to 320x240 fake buffer if not linux --- framebuffer/src/main/c/FrameBuffer.c | 7 +++++++ .../pi/framebuffer/FrameBufferDataBuffer.java | 20 ++++++++++++------- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/framebuffer/src/main/c/FrameBuffer.c b/framebuffer/src/main/c/FrameBuffer.c index 21e1249..0c1180e 100755 --- a/framebuffer/src/main/c/FrameBuffer.c +++ b/framebuffer/src/main/c/FrameBuffer.c @@ -18,8 +18,10 @@ #include #include +#ifdef __linux #include #include +#endif #include @@ -47,6 +49,10 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_openDevice( struct deviceInfo *di; +#ifndef __linux + return -1; +#else + di = malloc(sizeof(*di)); memset(di, 0, sizeof(*di)); @@ -97,6 +103,7 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_openDevice( } return (jlong) (intptr_t) di; +#endif } JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_closeDevice( diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferDataBuffer.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferDataBuffer.java index 27cf712..52414a8 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferDataBuffer.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferDataBuffer.java @@ -18,22 +18,27 @@ static long open(String fbdev) { private int w; private int h; + private int[] buf; + public FrameBufferDataBuffer(String fbdev) { this(open(fbdev)); } public FrameBufferDataBuffer(int w, int h) { super(TYPE_INT, w * h); - this.ptr = -1; + ptr = -1; this.w = w; this.h = h; + buf = new int[w * h]; } private FrameBufferDataBuffer(long ptr) { - super(TYPE_INT, FrameBuffer.getDeviceWidth(ptr) * FrameBuffer.getDeviceHeight(ptr)); + super(TYPE_INT, ptr == -1 ? 320*240 : FrameBuffer.getDeviceWidth(ptr) * FrameBuffer.getDeviceHeight(ptr)); this.ptr = ptr; - this.w = FrameBuffer.getDeviceWidth(ptr); - this.h = FrameBuffer.getDeviceHeight(ptr); + w = ptr == -1 ? 320 : FrameBuffer.getDeviceWidth(ptr); + h = ptr == -1 ? 240 : FrameBuffer.getDeviceHeight(ptr); + if(ptr == -1) + this.buf = new int[w * h]; } @Override @@ -41,7 +46,7 @@ public int getElem(int bank, int i) { if(ptr == 0) throw new IllegalStateException(); if(ptr == -1) - return 0; + return buf[i]; return FrameBuffer.readRGB(ptr, i); } @@ -50,8 +55,9 @@ public void setElem(int bank, int i, int val) { if(ptr == 0) throw new IllegalStateException(); if(ptr == -1) - return; - FrameBuffer.writeRGB(ptr, i, val); + buf[i] = val; + else + FrameBuffer.writeRGB(ptr, i, val); } public void close() { From 9996e00c42ab6b43511858ca549a5d648b06a1da Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 20:46:47 -0500 Subject: [PATCH 33/77] too much, mostly refactoring --- framebuffer/src/main/c/FrameBuffer.c | 84 +++++++----- .../org/tw/pi/framebuffer/FrameBuffer.java | 126 ++++++++++++------ .../pi/framebuffer/FrameBufferDataBuffer.java | 100 ++++++++------ .../tw/pi/framebuffer/FrameBufferImage.java | 30 ++--- .../tw/pi/framebuffer/FrameBufferRaster.java | 27 +--- .../pi/framebuffer/FrameBufferImageTest.java | 13 +- .../tw/pi/framebuffer/FrameBufferTest.java | 2 - 7 files changed, 223 insertions(+), 159 deletions(-) diff --git a/framebuffer/src/main/c/FrameBuffer.c b/framebuffer/src/main/c/FrameBuffer.c index 0c1180e..5ea62f7 100755 --- a/framebuffer/src/main/c/FrameBuffer.c +++ b/framebuffer/src/main/c/FrameBuffer.c @@ -27,6 +27,8 @@ #include +#include "org_tw_pi_framebuffer_FrameBuffer.h" + struct deviceInfo { char *deviceName; // Device-Name from Java ("/dev/fb1" or "dummy_240x180")... int fbfd; // File descriptor, 0 for previous devices @@ -38,8 +40,6 @@ struct deviceInfo { long int screensize; // Buffer size in bytes char *fbp; // MemoryMapped buffer - - unsigned int *previous; // Last screen }; JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_openDevice( @@ -50,7 +50,7 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_openDevice( struct deviceInfo *di; #ifndef __linux - return -1; + return org_tw_pi_framebuffer_FrameBuffer_DUMMY; #else di = malloc(sizeof(*di)); @@ -68,26 +68,36 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_openDevice( di->fbfd = open(di->deviceName, O_RDWR); if (!di->fbfd) { // printf("Error: cannot open framebuffer device. %s\n", di->deviceName); - return (1); + free(di->deviceName); + return org_tw_pi_framebuffer_FrameBuffer_ERR_OPEN; } // printf("The framebuffer device %s was opened successfully.\n", di->deviceName); // Get fixed screen information if (ioctl(di->fbfd, FBIOGET_FSCREENINFO, &finfo)) { // printf("Error reading fixed information.\n"); - return (2); + close(di->fbfd); + free(di->deviceName); + return org_tw_pi_framebuffer_FrameBuffer_ERR_FIXED; } // Get variable screen information if (ioctl(di->fbfd, FBIOGET_VSCREENINFO, &vinfo)) { // printf("Error reading variable information.\n"); - return (3); + close(di->fbfd); + free(di->deviceName); + return org_tw_pi_framebuffer_FrameBuffer_ERR_VARIABLE; } di->width = vinfo.xres; di->height = vinfo.yres; di->bpp = vinfo.bits_per_pixel; - di->previous = malloc(di->width * di->height * sizeof(int)); + + if(di->bpp != 16 && di->bpp != 24) { + close(di->fbfd); + free(di->deviceName); + return org_tw_pi_framebuffer_FrameBuffer_ERR_BITS; + } // printf("%dx%d, %d bpp %ld bytes\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel, (long) finfo.smem_len); @@ -99,7 +109,9 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_openDevice( if ((int) di->fbp == -1) { // printf("Failed to mmap.\n"); - return (4); + close(di->fbfd); + free(di->deviceName); + return org_tw_pi_framebuffer_FrameBuffer_ERR_MMAP; } return (jlong) (intptr_t) di; @@ -112,7 +124,6 @@ JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_closeDevice( struct deviceInfo *di = (struct deviceInfo *) (intptr_t) jdi; free(di->deviceName); - free(di->previous); if (di->fbfd != 0) { munmap(di->fbp, di->screensize); @@ -146,34 +157,45 @@ JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_getDeviceBitsPerPi return di->bpp; } -static inline unsigned short to_16bit(unsigned int rgb) { - unsigned char r = (rgb >> 16) & 0x0ff; - unsigned char g = (rgb >> 8) & 0x0ff; - unsigned char b = (rgb) & 0x0ff; - - return ((r / 8) << 11) + ((g / 4) << 5) + (b / 8); -} - -static inline unsigned int from_16bit(unsigned short rgb) { - unsigned int r = 0xff & ((rgb >> 11) << 3); - unsigned int g = 0xff & ((rgb >> 5) << 2); - unsigned int b = 0xff & (rgb << 2); - - return (r << 16) + (g << 8) + b; -} - JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_writeRGB (JNIEnv *env, jclass clazz, jlong ptr, jint idx, jint rgb) { struct deviceInfo *di = (struct deviceInfo *) (intptr_t) ptr; - unsigned short *p = (unsigned short *) di->fbp; - - p[idx] = to_16bit(rgb); + if(di->bpp == 16) { + unsigned short *p = (unsigned short *) di->fbp; + unsigned char r = (rgb >> 16) & 0x0ff; + unsigned char g = (rgb >> 8) & 0x0ff; + unsigned char b = (rgb) & 0x0ff; + + p[idx] = ((r / 8) << 11) + ((g / 4) << 5) + (b / 8); + } else if(di->bpp == 24) { + unsigned char *p = (unsigned char *) di->fbp; + unsigned char r = (unsigned char)(0xFF & (rgb >> 16)); + unsigned char g = (unsigned char)(0xFF & (rgb >> 8)); + unsigned char b = (unsigned char)(0xFF & rgb); + + p[3*idx] = r; + p[3*idx + 1] = g; + p[3*idx + 2] = b; + } } JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_readRGB (JNIEnv *env, jclass clazz, jlong ptr, jint idx) { struct deviceInfo *di = (struct deviceInfo *) (intptr_t) ptr; - unsigned short *p = (unsigned short *) di->fbp; - - return from_16bit(p[idx]); + if(di->bpp == 16) { + unsigned short *p = (unsigned short *) di->fbp; + unsigned int r = 0xff & ((rgb >> 11) << 3); + unsigned int g = 0xff & ((rgb >> 5) << 2); + unsigned int b = 0xff & (rgb << 2); + + return (r << 16) + (g << 8) + b; + } else if(di->bpp == 24) { + unsigned char *p = (unsigned char *) di->fbp; + unsigned int r = p[3*idx]; + unsigned int g = p[3*idx + 1]; + unsigned int b = p[3*idx + 2]; + + return (r << 16) + (g << 8) + b; + } else + return -1; } diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java index 69580e6..1c40dfe 100755 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java @@ -9,49 +9,99 @@ package org.tw.pi.framebuffer; +import java.awt.image.ColorModel; +import java.awt.image.DataBuffer; +import java.awt.image.DirectColorModel; +import java.awt.image.SampleModel; +import java.awt.image.SinglePixelPackedSampleModel; + import org.tw.pi.NarSystem; +public abstract class FrameBuffer { + public static final long DUMMY = -1; + static final long ERR_OPEN = 1; + static final long ERR_FIXED = 2; + static final long ERR_VARIABLE = 3; + static final long ERR_BITS = 4; + static final long ERR_MMAP = 5; + + static native long openDevice(String fbdev); + static native void closeDevice(long ptr); + + static native int getDeviceWidth(long ptr); + static native int getDeviceHeight(long ptr); + static native int getDeviceBitsPerPixel(long ptr); + + static native void writeRGB(long ptr, int idx, int rgb); + static native int readRGB(long ptr, int idx); -/** - * This class is the Java front end for a simple to use FrameBuffer driver. - * Simple draw in the BufferedImage and all changes are transfered to the FrameBuffer device.

- * For testing purpose a dummy device is supported (via the devicename "dummy_160x128" instead of "/dev/fb1"). - * It's used to drive small bit mapped screens connected via SPI, see - * http://www.sainsmart.com/blog/ada/ - *

- *

- * My Linux kernel config for SPI display was: - *

- * CONFIG_FB_ST7735=y
- * CONFIG_FB_ST7735_PANEL_TYPE_RED_TAB=y
- * CONFIG_FB_ST7735_RGB_ORDER_REVERSED=y
- * CONFIG_FB_ST7735_MAP=y
- * CONFIG_FB_ST7735_MAP_RST_GPIO=25
- * CONFIG_FB_ST7735_MAP_DC_GPIO=24
- * CONFIG_FB_ST7735_MAP_SPI_BUS_NUM=0
- * CONFIG_FB_ST7735_MAP_SPI_BUS_CS=0
- * CONFIG_FB_ST7735_MAP_SPI_BUS_SPEED=16000000
- * CONFIG_FB_ST7735_MAP_SPI_BUS_MODE=0
- * 
- * CONFIG_FB_ST7735_MAP_SPI_BUS_SPEED gives faster updates :-) - *

- * If you get the wrong colors, try the CONFIG_FB_ST7735_RGB_ORDER_REVERSED option ! - */ -abstract class FrameBuffer { - - static native long openDevice(String device); - static native void closeDevice(long di); - static native int getDeviceWidth(long di); - static native int getDeviceHeight(long di); - static native int getDeviceBitsPerPixel(long di); - static native void writeRGB(long di, int idx, int rgb); - static native int readRGB(long di, int idx); - static { NarSystem.loadLibrary(); } + + public static long open(String fbdev) { + long ptr = FrameBuffer.openDevice(fbdev); + + if(ptr == FrameBuffer.DUMMY) + return FrameBuffer.DUMMY; + if(ptr == FrameBuffer.ERR_OPEN) + throw new RuntimeException("Unable to open framebuffer device: " + fbdev); + if(ptr == FrameBuffer.ERR_FIXED) + throw new RuntimeException("Error reading fixed screen info for: " + fbdev); + if(ptr == FrameBuffer.ERR_VARIABLE) + throw new RuntimeException("Error reading variable screen info for: " + fbdev); + if(ptr == FrameBuffer.ERR_BITS) + throw new RuntimeException("Invalid color depth (" + FrameBuffer.getDeviceBitsPerPixel(ptr) + "), 16 and 24 supported, for: " + fbdev); + if(ptr == FrameBuffer.ERR_MMAP) + throw new RuntimeException("Unable to mmap for: " + fbdev); + + return ptr; + } + + public static ColorModel createColorModel(int bpp) { + if(bpp == 16) { + return new DirectColorModel(16, + 0x00f80000, // Red + 0x0000fc00, // Green + 0x000000f8, // Blue + 0x0 // Alpha + ); + } else if(bpp == 24) { + return new DirectColorModel(24, + 0x00ff0000, // Red + 0x0000ff00, // Green + 0x000000ff, // Blue + 0x0 // Alpha + ); + } else + throw new IllegalArgumentException("Invalid framebuffer color depth:" + bpp); + } - private FrameBuffer() {} + public static SampleModel createSampleModel(int bpp, int w, int h) { + if(bpp == 16) { + return new SinglePixelPackedSampleModel( + DataBuffer.TYPE_INT, + w, + h, + new int[] { + 0x00f80000, // Red + 0x0000fc00, // Green + 0x000000f8, // Blue + }); + } else if(bpp == 24) { + return new SinglePixelPackedSampleModel( + DataBuffer.TYPE_INT, + w, + h, + new int[] { + 0x00ff0000, // Red + 0x0000ff00, // Green + 0x000000ff, // Blue + }); + } else + throw new IllegalArgumentException("Invalid framebuffer color depth:" + bpp); + } + + private FrameBuffer() { + } } diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferDataBuffer.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferDataBuffer.java index 52414a8..8c96f4b 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferDataBuffer.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferDataBuffer.java @@ -3,76 +3,98 @@ import java.awt.image.DataBuffer; public class FrameBufferDataBuffer extends DataBuffer { + private static final int DEFAULT_DUMMY_WIDTH = 320; + private static final int DEFAULT_DUMMY_HEIGHT = 240; + private static final int DEFAULT_COLOR_DEPTH = 24; - static long open(String fbdev) { - long ptr = FrameBuffer.openDevice(fbdev); + private final long ptr; + private final int w; + private final int h; + private final int bpp; - if (ptr < 10) { - throw new IllegalArgumentException("Init. for frame buffer " + fbdev + " failed with error code " + ptr); - } - - return ptr; - } - - private long ptr; - private int w; - private int h; + private final int[] dummy; - private int[] buf; + private boolean closed; + + public FrameBufferDataBuffer() { + this(FrameBuffer.DUMMY); + } public FrameBufferDataBuffer(String fbdev) { - this(open(fbdev)); + this(FrameBuffer.open(fbdev)); } - + + public FrameBufferDataBuffer(int w, int h, int bpp) { + this(FrameBuffer.DUMMY, w, h, bpp); + } + public FrameBufferDataBuffer(int w, int h) { - super(TYPE_INT, w * h); - ptr = -1; - this.w = w; - this.h = h; - buf = new int[w * h]; + this(FrameBuffer.DUMMY, w, h, DEFAULT_COLOR_DEPTH); } - + private FrameBufferDataBuffer(long ptr) { - super(TYPE_INT, ptr == -1 ? 320*240 : FrameBuffer.getDeviceWidth(ptr) * FrameBuffer.getDeviceHeight(ptr)); + this( + ptr, + (ptr == FrameBuffer.DUMMY ? DEFAULT_DUMMY_WIDTH : FrameBuffer.getDeviceWidth(ptr)), + (ptr == FrameBuffer.DUMMY ? DEFAULT_DUMMY_HEIGHT : FrameBuffer.getDeviceHeight(ptr)), + (ptr == FrameBuffer.DUMMY ? DEFAULT_COLOR_DEPTH : FrameBuffer.getDeviceBitsPerPixel(ptr))); + } + + private FrameBufferDataBuffer(long ptr, int w, int h, int bpp) { + super(TYPE_INT, w * h); this.ptr = ptr; - w = ptr == -1 ? 320 : FrameBuffer.getDeviceWidth(ptr); - h = ptr == -1 ? 240 : FrameBuffer.getDeviceHeight(ptr); - if(ptr == -1) - this.buf = new int[w * h]; + this.w = w; + this.h = h; + if(ptr == FrameBuffer.DUMMY) { + this.bpp = bpp; + this.dummy = new int[w * h]; + } else { + this.bpp = FrameBuffer.getDeviceBitsPerPixel(ptr); + this.dummy = null; + } + this.closed = false; } - + @Override public int getElem(int bank, int i) { - if(ptr == 0) + if(closed) throw new IllegalStateException(); - if(ptr == -1) - return buf[i]; - return FrameBuffer.readRGB(ptr, i); + int val; + if(ptr == FrameBuffer.DUMMY) + val = dummy[i]; + else + val = FrameBuffer.readRGB(ptr, i); + return val & 0x00FFFFFF; } @Override public void setElem(int bank, int i, int val) { - if(ptr == 0) + val = val & 0x00FFFFFF; + if(closed) throw new IllegalStateException(); - if(ptr == -1) - buf[i] = val; + if(ptr == FrameBuffer.DUMMY) + dummy[i] = val; else FrameBuffer.writeRGB(ptr, i, val); } - + public void close() { - if(ptr != 0) { - if(ptr != -1) + if(!closed) { + if(ptr != FrameBuffer.DUMMY) FrameBuffer.closeDevice(ptr); - ptr = 0; + closed = true; } } public int getWidth() { return w; } - + public int getHeight() { return h; } + + public int getColorDepth() { + return bpp; + } } diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java index b716e27..c39015e 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java @@ -1,36 +1,24 @@ package org.tw.pi.framebuffer; import java.awt.image.BufferedImage; -import java.awt.image.ColorModel; -import java.awt.image.DirectColorModel; -import java.awt.image.WritableRaster; public class FrameBufferImage extends BufferedImage { - static ColorModel createColorModel() { - return new DirectColorModel(24, - 0x00ff0000, // Red - 0x0000ff00, // Green - 0x000000ff, // Blue - 0x0 // Alpha - ); - } - - static WritableRaster createWritableRaster(FrameBufferDataBuffer dataBuffer) { - return new FrameBufferRaster(dataBuffer); - } - - private FrameBufferDataBuffer dataBuffer; + private FrameBufferDataBuffer fb; public FrameBufferImage(String fbdev) { this(new FrameBufferDataBuffer(fbdev)); } - public FrameBufferImage(FrameBufferDataBuffer dataBuffer) { - super(createColorModel(), createWritableRaster(dataBuffer), true, null); - this.dataBuffer = dataBuffer; + public FrameBufferImage(FrameBufferDataBuffer fb) { + super(FrameBuffer.createColorModel(fb.getColorDepth()), new FrameBufferRaster(fb), true, null); + this.fb = fb; } public void close() { - dataBuffer.close(); + fb.close(); + } + + public FrameBufferDataBuffer getFrameBuffer() { + return fb; } } diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java index dfe3bef..3f9bd67 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java @@ -1,35 +1,12 @@ package org.tw.pi.framebuffer; import java.awt.Point; -import java.awt.image.DataBuffer; -import java.awt.image.SampleModel; -import java.awt.image.SinglePixelPackedSampleModel; import java.awt.image.WritableRaster; public class FrameBufferRaster extends WritableRaster { - static SampleModel createSampleModel(int w, int h) { - return new SinglePixelPackedSampleModel( - DataBuffer.TYPE_INT, - w, - h, - new int[] { - 0x00ff0000, - 0x0000ff00, - 0x000000ff, - }); - } - - public FrameBufferRaster(String fbdev) { - this(new FrameBufferDataBuffer(fbdev)); - } - - public FrameBufferRaster(FrameBufferDataBuffer dataBuffer) { - super(createSampleModel(dataBuffer.getWidth(), dataBuffer.getHeight()), dataBuffer, new Point(0, 0)); - } - - public void close() { - ((FrameBufferDataBuffer) dataBuffer).close(); + public FrameBufferRaster(FrameBufferDataBuffer fb) { + super(FrameBuffer.createSampleModel(fb.getColorDepth(), fb.getWidth(), fb.getHeight()), fb, new Point(0, 0)); } } diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java index c2cd7c1..1f66994 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java @@ -4,9 +4,16 @@ import org.junit.Test; public class FrameBufferImageTest { + @Test - public void testCompatibility() { - Assert.assertTrue(FrameBufferImage.createColorModel().isCompatibleSampleModel(FrameBufferRaster.createSampleModel(1, 1))); - Assert.assertTrue(FrameBufferImage.createColorModel().isCompatibleRaster(new FrameBufferRaster(new FrameBufferDataBuffer(1,1)))); + public void testCompatibility16bpp() { + Assert.assertTrue(FrameBuffer.createColorModel(16).isCompatibleSampleModel(FrameBuffer.createSampleModel(16, 1, 1))); + Assert.assertTrue(FrameBuffer.createColorModel(16).isCompatibleRaster(new FrameBufferRaster(new FrameBufferDataBuffer(1,1)))); + } + + @Test + public void testCompatibility24bpp() { + Assert.assertTrue(FrameBuffer.createColorModel(24).isCompatibleSampleModel(FrameBuffer.createSampleModel(24, 1, 1))); + Assert.assertTrue(FrameBuffer.createColorModel(24).isCompatibleRaster(new FrameBufferRaster(new FrameBufferDataBuffer(1,1)))); } } diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index 559a54a..2ae9a70 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -2,8 +2,6 @@ import java.awt.Color; import java.awt.Graphics; -import java.awt.image.BufferedImage; - import org.junit.Test; public class FrameBufferTest { From 3680de97601f40baaf88a4d792c493d9ddf7a976 Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 20:51:52 -0500 Subject: [PATCH 34/77] Rename some stuff --- .../main/c/{FrameBuffer.c => FrameBuffers.c} | 28 +-- .../org/tw/pi/framebuffer/FrameBuffer.java | 167 +++++++++--------- .../pi/framebuffer/FrameBufferDataBuffer.java | 100 ----------- .../tw/pi/framebuffer/FrameBufferImage.java | 10 +- .../tw/pi/framebuffer/FrameBufferRaster.java | 4 +- .../org/tw/pi/framebuffer/FrameBuffers.java | 107 +++++++++++ .../pi/framebuffer/FrameBufferImageTest.java | 8 +- .../tw/pi/framebuffer/FrameBufferTest.java | 2 +- 8 files changed, 213 insertions(+), 213 deletions(-) rename framebuffer/src/main/c/{FrameBuffer.c => FrameBuffers.c} (83%) mode change 100755 => 100644 framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java delete mode 100644 framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferDataBuffer.java create mode 100755 framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java diff --git a/framebuffer/src/main/c/FrameBuffer.c b/framebuffer/src/main/c/FrameBuffers.c similarity index 83% rename from framebuffer/src/main/c/FrameBuffer.c rename to framebuffer/src/main/c/FrameBuffers.c index 5ea62f7..6d74a76 100755 --- a/framebuffer/src/main/c/FrameBuffer.c +++ b/framebuffer/src/main/c/FrameBuffers.c @@ -27,7 +27,7 @@ #include -#include "org_tw_pi_framebuffer_FrameBuffer.h" +#include "org_tw_pi_framebuffer_FrameBuffers.h" struct deviceInfo { char *deviceName; // Device-Name from Java ("/dev/fb1" or "dummy_240x180")... @@ -42,7 +42,7 @@ struct deviceInfo { char *fbp; // MemoryMapped buffer }; -JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_openDevice( +JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_openDevice( JNIEnv *env, jobject obj, jstring device) { jboolean isCopy; @@ -50,7 +50,7 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_openDevice( struct deviceInfo *di; #ifndef __linux - return org_tw_pi_framebuffer_FrameBuffer_DUMMY; + return org_tw_pi_framebuffer_FrameBuffers_DUMMY; #else di = malloc(sizeof(*di)); @@ -69,7 +69,7 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_openDevice( if (!di->fbfd) { // printf("Error: cannot open framebuffer device. %s\n", di->deviceName); free(di->deviceName); - return org_tw_pi_framebuffer_FrameBuffer_ERR_OPEN; + return org_tw_pi_framebuffer_FrameBuffers_ERR_OPEN; } // printf("The framebuffer device %s was opened successfully.\n", di->deviceName); @@ -78,7 +78,7 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_openDevice( // printf("Error reading fixed information.\n"); close(di->fbfd); free(di->deviceName); - return org_tw_pi_framebuffer_FrameBuffer_ERR_FIXED; + return org_tw_pi_framebuffer_FrameBuffers_ERR_FIXED; } // Get variable screen information @@ -86,7 +86,7 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_openDevice( // printf("Error reading variable information.\n"); close(di->fbfd); free(di->deviceName); - return org_tw_pi_framebuffer_FrameBuffer_ERR_VARIABLE; + return org_tw_pi_framebuffer_FrameBuffers_ERR_VARIABLE; } di->width = vinfo.xres; @@ -96,7 +96,7 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_openDevice( if(di->bpp != 16 && di->bpp != 24) { close(di->fbfd); free(di->deviceName); - return org_tw_pi_framebuffer_FrameBuffer_ERR_BITS; + return org_tw_pi_framebuffer_FrameBuffers_ERR_BITS; } // printf("%dx%d, %d bpp %ld bytes\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel, (long) finfo.smem_len); @@ -111,14 +111,14 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_openDevice( // printf("Failed to mmap.\n"); close(di->fbfd); free(di->deviceName); - return org_tw_pi_framebuffer_FrameBuffer_ERR_MMAP; + return org_tw_pi_framebuffer_FrameBuffers_ERR_MMAP; } return (jlong) (intptr_t) di; #endif } -JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_closeDevice( +JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_closeDevice( JNIEnv *env, jobject obj, jlong jdi) { struct deviceInfo *di = (struct deviceInfo *) (intptr_t) jdi; @@ -133,7 +133,7 @@ JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_closeDevice( memset(di, 0, sizeof(*di)); // :-) } -JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_getDeviceWidth( +JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_getDeviceWidth( JNIEnv *env, jobject obj, jlong jdi) { struct deviceInfo *di = (struct deviceInfo *) (intptr_t) jdi; @@ -141,7 +141,7 @@ JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_getDeviceWidth( return di->width; } -JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_getDeviceHeight( +JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_getDeviceHeight( JNIEnv *env, jobject obj, jlong jdi) { struct deviceInfo *di = (struct deviceInfo *) (intptr_t) jdi; @@ -149,7 +149,7 @@ JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_getDeviceHeight( return di->height; } -JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_getDeviceBitsPerPixel( +JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_getDeviceBitsPerPixel( JNIEnv *env, jobject obj, jlong jdi) { struct deviceInfo *di = (struct deviceInfo *) (intptr_t) jdi; @@ -157,7 +157,7 @@ JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_getDeviceBitsPerPi return di->bpp; } -JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_writeRGB +JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_writeRGB (JNIEnv *env, jclass clazz, jlong ptr, jint idx, jint rgb) { struct deviceInfo *di = (struct deviceInfo *) (intptr_t) ptr; if(di->bpp == 16) { @@ -179,7 +179,7 @@ JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_writeRGB } } -JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffer_readRGB +JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_readRGB (JNIEnv *env, jclass clazz, jlong ptr, jint idx) { struct deviceInfo *di = (struct deviceInfo *) (intptr_t) ptr; if(di->bpp == 16) { diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java old mode 100755 new mode 100644 index 1c40dfe..477893b --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java @@ -1,107 +1,100 @@ -/* - * This file is the JNI Java part of a Raspberry Pi FrameBuffer project. - * - * Created 2013 by Thomas Welsch (ttww@gmx.de). - * - * Do whatever you want to do with it :-) - * - **/ - package org.tw.pi.framebuffer; -import java.awt.image.ColorModel; import java.awt.image.DataBuffer; -import java.awt.image.DirectColorModel; -import java.awt.image.SampleModel; -import java.awt.image.SinglePixelPackedSampleModel; -import org.tw.pi.NarSystem; +public class FrameBuffer extends DataBuffer { + private static final int DEFAULT_DUMMY_WIDTH = 320; + private static final int DEFAULT_DUMMY_HEIGHT = 240; + private static final int DEFAULT_COLOR_DEPTH = 24; + + private final long ptr; + private final int w; + private final int h; + private final int bpp; + + private final int[] dummy; + + private boolean closed; -public abstract class FrameBuffer { - public static final long DUMMY = -1; - static final long ERR_OPEN = 1; - static final long ERR_FIXED = 2; - static final long ERR_VARIABLE = 3; - static final long ERR_BITS = 4; - static final long ERR_MMAP = 5; + public FrameBuffer() { + this(FrameBuffers.DUMMY); + } + + public FrameBuffer(String fbdev) { + this(FrameBuffers.open(fbdev)); + } - static native long openDevice(String fbdev); - static native void closeDevice(long ptr); + public FrameBuffer(int w, int h, int bpp) { + this(FrameBuffers.DUMMY, w, h, bpp); + } - static native int getDeviceWidth(long ptr); - static native int getDeviceHeight(long ptr); - static native int getDeviceBitsPerPixel(long ptr); + public FrameBuffer(int w, int h) { + this(FrameBuffers.DUMMY, w, h, DEFAULT_COLOR_DEPTH); + } - static native void writeRGB(long ptr, int idx, int rgb); - static native int readRGB(long ptr, int idx); + private FrameBuffer(long ptr) { + this( + ptr, + (ptr == FrameBuffers.DUMMY ? DEFAULT_DUMMY_WIDTH : FrameBuffers.getDeviceWidth(ptr)), + (ptr == FrameBuffers.DUMMY ? DEFAULT_DUMMY_HEIGHT : FrameBuffers.getDeviceHeight(ptr)), + (ptr == FrameBuffers.DUMMY ? DEFAULT_COLOR_DEPTH : FrameBuffers.getDeviceBitsPerPixel(ptr))); + } - static { - NarSystem.loadLibrary(); + private FrameBuffer(long ptr, int w, int h, int bpp) { + super(TYPE_INT, w * h); + this.ptr = ptr; + this.w = w; + this.h = h; + if(ptr == FrameBuffers.DUMMY) { + this.bpp = bpp; + this.dummy = new int[w * h]; + } else { + this.bpp = FrameBuffers.getDeviceBitsPerPixel(ptr); + this.dummy = null; + } + this.closed = false; } - - public static long open(String fbdev) { - long ptr = FrameBuffer.openDevice(fbdev); - if(ptr == FrameBuffer.DUMMY) - return FrameBuffer.DUMMY; - if(ptr == FrameBuffer.ERR_OPEN) - throw new RuntimeException("Unable to open framebuffer device: " + fbdev); - if(ptr == FrameBuffer.ERR_FIXED) - throw new RuntimeException("Error reading fixed screen info for: " + fbdev); - if(ptr == FrameBuffer.ERR_VARIABLE) - throw new RuntimeException("Error reading variable screen info for: " + fbdev); - if(ptr == FrameBuffer.ERR_BITS) - throw new RuntimeException("Invalid color depth (" + FrameBuffer.getDeviceBitsPerPixel(ptr) + "), 16 and 24 supported, for: " + fbdev); - if(ptr == FrameBuffer.ERR_MMAP) - throw new RuntimeException("Unable to mmap for: " + fbdev); + @Override + public int getElem(int bank, int i) { + if(closed) + throw new IllegalStateException(); + int val; + if(ptr == FrameBuffers.DUMMY) + val = dummy[i]; + else + val = FrameBuffers.readRGB(ptr, i); + return val & 0x00FFFFFF; + } - return ptr; + @Override + public void setElem(int bank, int i, int val) { + val = val & 0x00FFFFFF; + if(closed) + throw new IllegalStateException(); + if(ptr == FrameBuffers.DUMMY) + dummy[i] = val; + else + FrameBuffers.writeRGB(ptr, i, val); } - public static ColorModel createColorModel(int bpp) { - if(bpp == 16) { - return new DirectColorModel(16, - 0x00f80000, // Red - 0x0000fc00, // Green - 0x000000f8, // Blue - 0x0 // Alpha - ); - } else if(bpp == 24) { - return new DirectColorModel(24, - 0x00ff0000, // Red - 0x0000ff00, // Green - 0x000000ff, // Blue - 0x0 // Alpha - ); - } else - throw new IllegalArgumentException("Invalid framebuffer color depth:" + bpp); + public void close() { + if(!closed) { + if(ptr != FrameBuffers.DUMMY) + FrameBuffers.closeDevice(ptr); + closed = true; + } } - public static SampleModel createSampleModel(int bpp, int w, int h) { - if(bpp == 16) { - return new SinglePixelPackedSampleModel( - DataBuffer.TYPE_INT, - w, - h, - new int[] { - 0x00f80000, // Red - 0x0000fc00, // Green - 0x000000f8, // Blue - }); - } else if(bpp == 24) { - return new SinglePixelPackedSampleModel( - DataBuffer.TYPE_INT, - w, - h, - new int[] { - 0x00ff0000, // Red - 0x0000ff00, // Green - 0x000000ff, // Blue - }); - } else - throw new IllegalArgumentException("Invalid framebuffer color depth:" + bpp); + public int getWidth() { + return w; } - private FrameBuffer() { + public int getHeight() { + return h; + } + + public int getColorDepth() { + return bpp; } } diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferDataBuffer.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferDataBuffer.java deleted file mode 100644 index 8c96f4b..0000000 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferDataBuffer.java +++ /dev/null @@ -1,100 +0,0 @@ -package org.tw.pi.framebuffer; - -import java.awt.image.DataBuffer; - -public class FrameBufferDataBuffer extends DataBuffer { - private static final int DEFAULT_DUMMY_WIDTH = 320; - private static final int DEFAULT_DUMMY_HEIGHT = 240; - private static final int DEFAULT_COLOR_DEPTH = 24; - - private final long ptr; - private final int w; - private final int h; - private final int bpp; - - private final int[] dummy; - - private boolean closed; - - public FrameBufferDataBuffer() { - this(FrameBuffer.DUMMY); - } - - public FrameBufferDataBuffer(String fbdev) { - this(FrameBuffer.open(fbdev)); - } - - public FrameBufferDataBuffer(int w, int h, int bpp) { - this(FrameBuffer.DUMMY, w, h, bpp); - } - - public FrameBufferDataBuffer(int w, int h) { - this(FrameBuffer.DUMMY, w, h, DEFAULT_COLOR_DEPTH); - } - - private FrameBufferDataBuffer(long ptr) { - this( - ptr, - (ptr == FrameBuffer.DUMMY ? DEFAULT_DUMMY_WIDTH : FrameBuffer.getDeviceWidth(ptr)), - (ptr == FrameBuffer.DUMMY ? DEFAULT_DUMMY_HEIGHT : FrameBuffer.getDeviceHeight(ptr)), - (ptr == FrameBuffer.DUMMY ? DEFAULT_COLOR_DEPTH : FrameBuffer.getDeviceBitsPerPixel(ptr))); - } - - private FrameBufferDataBuffer(long ptr, int w, int h, int bpp) { - super(TYPE_INT, w * h); - this.ptr = ptr; - this.w = w; - this.h = h; - if(ptr == FrameBuffer.DUMMY) { - this.bpp = bpp; - this.dummy = new int[w * h]; - } else { - this.bpp = FrameBuffer.getDeviceBitsPerPixel(ptr); - this.dummy = null; - } - this.closed = false; - } - - @Override - public int getElem(int bank, int i) { - if(closed) - throw new IllegalStateException(); - int val; - if(ptr == FrameBuffer.DUMMY) - val = dummy[i]; - else - val = FrameBuffer.readRGB(ptr, i); - return val & 0x00FFFFFF; - } - - @Override - public void setElem(int bank, int i, int val) { - val = val & 0x00FFFFFF; - if(closed) - throw new IllegalStateException(); - if(ptr == FrameBuffer.DUMMY) - dummy[i] = val; - else - FrameBuffer.writeRGB(ptr, i, val); - } - - public void close() { - if(!closed) { - if(ptr != FrameBuffer.DUMMY) - FrameBuffer.closeDevice(ptr); - closed = true; - } - } - - public int getWidth() { - return w; - } - - public int getHeight() { - return h; - } - - public int getColorDepth() { - return bpp; - } -} diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java index c39015e..6b15934 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java @@ -3,14 +3,14 @@ import java.awt.image.BufferedImage; public class FrameBufferImage extends BufferedImage { - private FrameBufferDataBuffer fb; + private FrameBuffer fb; public FrameBufferImage(String fbdev) { - this(new FrameBufferDataBuffer(fbdev)); + this(new FrameBuffer(fbdev)); } - public FrameBufferImage(FrameBufferDataBuffer fb) { - super(FrameBuffer.createColorModel(fb.getColorDepth()), new FrameBufferRaster(fb), true, null); + public FrameBufferImage(FrameBuffer fb) { + super(FrameBuffers.createColorModel(fb.getColorDepth()), new FrameBufferRaster(fb), true, null); this.fb = fb; } @@ -18,7 +18,7 @@ public void close() { fb.close(); } - public FrameBufferDataBuffer getFrameBuffer() { + public FrameBuffer getFrameBuffer() { return fb; } } diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java index 3f9bd67..55c0595 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java @@ -5,8 +5,8 @@ public class FrameBufferRaster extends WritableRaster { - public FrameBufferRaster(FrameBufferDataBuffer fb) { - super(FrameBuffer.createSampleModel(fb.getColorDepth(), fb.getWidth(), fb.getHeight()), fb, new Point(0, 0)); + public FrameBufferRaster(FrameBuffer fb) { + super(FrameBuffers.createSampleModel(fb.getColorDepth(), fb.getWidth(), fb.getHeight()), fb, new Point(0, 0)); } } diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java new file mode 100755 index 0000000..d51450a --- /dev/null +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java @@ -0,0 +1,107 @@ +/* + * This file is the JNI Java part of a Raspberry Pi FrameBuffer project. + * + * Created 2013 by Thomas Welsch (ttww@gmx.de). + * + * Do whatever you want to do with it :-) + * + **/ + +package org.tw.pi.framebuffer; + +import java.awt.image.ColorModel; +import java.awt.image.DataBuffer; +import java.awt.image.DirectColorModel; +import java.awt.image.SampleModel; +import java.awt.image.SinglePixelPackedSampleModel; + +import org.tw.pi.NarSystem; + +public abstract class FrameBuffers { + public static final long DUMMY = -1; + public static final long ERR_OPEN = 1; + public static final long ERR_FIXED = 2; + public static final long ERR_VARIABLE = 3; + public static final long ERR_BITS = 4; + public static final long ERR_MMAP = 5; + + public static native long openDevice(String fbdev); + public static native void closeDevice(long ptr); + + public static native int getDeviceWidth(long ptr); + public static native int getDeviceHeight(long ptr); + public static native int getDeviceBitsPerPixel(long ptr); + + public static native void writeRGB(long ptr, int idx, int rgb); + public static native int readRGB(long ptr, int idx); + + static { + NarSystem.loadLibrary(); + } + + public static long open(String fbdev) { + long ptr = FrameBuffers.openDevice(fbdev); + + if(ptr == FrameBuffers.DUMMY) + return FrameBuffers.DUMMY; + if(ptr == FrameBuffers.ERR_OPEN) + throw new RuntimeException("Unable to open framebuffer device: " + fbdev); + if(ptr == FrameBuffers.ERR_FIXED) + throw new RuntimeException("Error reading fixed screen info for: " + fbdev); + if(ptr == FrameBuffers.ERR_VARIABLE) + throw new RuntimeException("Error reading variable screen info for: " + fbdev); + if(ptr == FrameBuffers.ERR_BITS) + throw new RuntimeException("Invalid color depth (" + FrameBuffers.getDeviceBitsPerPixel(ptr) + "), 16 and 24 supported, for: " + fbdev); + if(ptr == FrameBuffers.ERR_MMAP) + throw new RuntimeException("Unable to mmap for: " + fbdev); + + return ptr; + } + + public static ColorModel createColorModel(int bpp) { + if(bpp == 16) { + return new DirectColorModel(16, + 0x00f80000, // Red + 0x0000fc00, // Green + 0x000000f8, // Blue + 0x0 // Alpha + ); + } else if(bpp == 24) { + return new DirectColorModel(24, + 0x00ff0000, // Red + 0x0000ff00, // Green + 0x000000ff, // Blue + 0x0 // Alpha + ); + } else + throw new IllegalArgumentException("Invalid framebuffer color depth:" + bpp); + } + + public static SampleModel createSampleModel(int bpp, int w, int h) { + if(bpp == 16) { + return new SinglePixelPackedSampleModel( + DataBuffer.TYPE_INT, + w, + h, + new int[] { + 0x00f80000, // Red + 0x0000fc00, // Green + 0x000000f8, // Blue + }); + } else if(bpp == 24) { + return new SinglePixelPackedSampleModel( + DataBuffer.TYPE_INT, + w, + h, + new int[] { + 0x00ff0000, // Red + 0x0000ff00, // Green + 0x000000ff, // Blue + }); + } else + throw new IllegalArgumentException("Invalid framebuffer color depth:" + bpp); + } + + private FrameBuffers() { + } +} diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java index 1f66994..a4b594a 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java @@ -7,13 +7,13 @@ public class FrameBufferImageTest { @Test public void testCompatibility16bpp() { - Assert.assertTrue(FrameBuffer.createColorModel(16).isCompatibleSampleModel(FrameBuffer.createSampleModel(16, 1, 1))); - Assert.assertTrue(FrameBuffer.createColorModel(16).isCompatibleRaster(new FrameBufferRaster(new FrameBufferDataBuffer(1,1)))); + Assert.assertTrue(FrameBuffers.createColorModel(16).isCompatibleSampleModel(FrameBuffers.createSampleModel(16, 1, 1))); + Assert.assertTrue(FrameBuffers.createColorModel(16).isCompatibleRaster(new FrameBufferRaster(new FrameBuffer(1,1)))); } @Test public void testCompatibility24bpp() { - Assert.assertTrue(FrameBuffer.createColorModel(24).isCompatibleSampleModel(FrameBuffer.createSampleModel(24, 1, 1))); - Assert.assertTrue(FrameBuffer.createColorModel(24).isCompatibleRaster(new FrameBufferRaster(new FrameBufferDataBuffer(1,1)))); + Assert.assertTrue(FrameBuffers.createColorModel(24).isCompatibleSampleModel(FrameBuffers.createSampleModel(24, 1, 1))); + Assert.assertTrue(FrameBuffers.createColorModel(24).isCompatibleRaster(new FrameBufferRaster(new FrameBuffer(1,1)))); } } diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index 2ae9a70..8d5381c 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -7,7 +7,7 @@ public class FrameBufferTest { @Test public void testLoad() throws Exception { - Class.forName(FrameBuffer.class.getName()); + Class.forName(FrameBuffers.class.getName()); } public static void main(String[] args) throws Exception { From 65b3f9386c66a83356b62d296513a4323dbe45f8 Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 22:03:09 -0500 Subject: [PATCH 35/77] lots of refactoring and factories and such --- framebuffer/src/main/c/FrameBuffers.c | 73 ++--- .../org/tw/pi/framebuffer/FrameBuffer.java | 11 +- .../tw/pi/framebuffer/FrameBufferImage.java | 23 +- .../tw/pi/framebuffer/FrameBufferRaster.java | 19 +- .../org/tw/pi/framebuffer/FrameBuffers.java | 272 +++++++++++++++--- .../pi/framebuffer/FrameBufferImageTest.java | 8 +- .../tw/pi/framebuffer/FrameBufferTest.java | 5 +- 7 files changed, 318 insertions(+), 93 deletions(-) diff --git a/framebuffer/src/main/c/FrameBuffers.c b/framebuffer/src/main/c/FrameBuffers.c index 6d74a76..77c5431 100755 --- a/framebuffer/src/main/c/FrameBuffers.c +++ b/framebuffer/src/main/c/FrameBuffers.c @@ -93,7 +93,7 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_openDevice( di->height = vinfo.yres; di->bpp = vinfo.bits_per_pixel; - if(di->bpp != 16 && di->bpp != 24) { + if(di->bpp != 8 && di->bpp != 16 && di->bpp != 24) { close(di->fbfd); free(di->deviceName); return org_tw_pi_framebuffer_FrameBuffers_ERR_BITS; @@ -160,42 +160,51 @@ JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_getDeviceBitsPerP JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_writeRGB (JNIEnv *env, jclass clazz, jlong ptr, jint idx, jint rgb) { struct deviceInfo *di = (struct deviceInfo *) (intptr_t) ptr; - if(di->bpp == 16) { - unsigned short *p = (unsigned short *) di->fbp; - unsigned char r = (rgb >> 16) & 0x0ff; - unsigned char g = (rgb >> 8) & 0x0ff; - unsigned char b = (rgb) & 0x0ff; - - p[idx] = ((r / 8) << 11) + ((g / 4) << 5) + (b / 8); - } else if(di->bpp == 24) { - unsigned char *p = (unsigned char *) di->fbp; - unsigned char r = (unsigned char)(0xFF & (rgb >> 16)); - unsigned char g = (unsigned char)(0xFF & (rgb >> 8)); - unsigned char b = (unsigned char)(0xFF & rgb); - - p[3*idx] = r; - p[3*idx + 1] = g; - p[3*idx + 2] = b; + unsigned char *p = (unsigned char *) di->fbp; + unsigned int width; + + if(di->bpp == 8) + width = 1; + else if(di->bpp == 16) + width = 2; + else if(di->bpp == 24) + width = 3; + else + return; + + p += (width * idx); + p += (width - 1); + while(width > 0) { + *p = (unsigned char)(0xFF & rgb); + rgb = rgb >> 8; + width--; + p--; } } JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_readRGB (JNIEnv *env, jclass clazz, jlong ptr, jint idx) { struct deviceInfo *di = (struct deviceInfo *) (intptr_t) ptr; - if(di->bpp == 16) { - unsigned short *p = (unsigned short *) di->fbp; - unsigned int r = 0xff & ((rgb >> 11) << 3); - unsigned int g = 0xff & ((rgb >> 5) << 2); - unsigned int b = 0xff & (rgb << 2); - - return (r << 16) + (g << 8) + b; - } else if(di->bpp == 24) { - unsigned char *p = (unsigned char *) di->fbp; - unsigned int r = p[3*idx]; - unsigned int g = p[3*idx + 1]; - unsigned int b = p[3*idx + 2]; - - return (r << 16) + (g << 8) + b; - } else + unsigned char *p = (unsigned char *) di->fbp; + unsigned int width; + + if(di->bpp == 8) + width = 1; + else if(di->bpp == 16) + width = 2; + else if(di->bpp == 24) + width = 3; + else return -1; + + unsigned int rgb = 0; + + p += (width * idx); + while(width > 0) { + rgb = (rgb << 8) + *p; + width--; + p++; + } + + return rgb; } diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java index 477893b..2eb95d2 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java @@ -3,9 +3,9 @@ import java.awt.image.DataBuffer; public class FrameBuffer extends DataBuffer { - private static final int DEFAULT_DUMMY_WIDTH = 320; - private static final int DEFAULT_DUMMY_HEIGHT = 240; - private static final int DEFAULT_COLOR_DEPTH = 24; + public static final int DEFAULT_DUMMY_WIDTH = 320; + public static final int DEFAULT_DUMMY_HEIGHT = 240; + public static final int DEFAULT_COLOR_DEPTH = 24; private final long ptr; private final int w; @@ -41,15 +41,14 @@ private FrameBuffer(long ptr) { } private FrameBuffer(long ptr, int w, int h, int bpp) { - super(TYPE_INT, w * h); + super(DataBuffer.TYPE_INT, w * h); this.ptr = ptr; this.w = w; this.h = h; + this.bpp = bpp; if(ptr == FrameBuffers.DUMMY) { - this.bpp = bpp; this.dummy = new int[w * h]; } else { - this.bpp = FrameBuffers.getDeviceBitsPerPixel(ptr); this.dummy = null; } this.closed = false; diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java index 6b15934..8fd3e86 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java @@ -1,6 +1,9 @@ package org.tw.pi.framebuffer; import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; + +import org.tw.pi.framebuffer.FrameBuffers.ColorEndian; public class FrameBufferImage extends BufferedImage { private FrameBuffer fb; @@ -9,9 +12,25 @@ public FrameBufferImage(String fbdev) { this(new FrameBuffer(fbdev)); } + public FrameBufferImage(String fbdev, ColorEndian ce) { + this(new FrameBuffer(fbdev), ce); + } + public FrameBufferImage(FrameBuffer fb) { - super(FrameBuffers.createColorModel(fb.getColorDepth()), new FrameBufferRaster(fb), true, null); - this.fb = fb; + this(fb, ColorEndian.RGB); + } + + public FrameBufferImage(FrameBuffer fb, ColorEndian ce) { + this( + new FrameBufferRaster( + fb, + ce.createSampleModel(fb.getWidth(), fb.getHeight(), fb.getColorDepth())), + ce.createColorModel(fb.getColorDepth())); + } + + public FrameBufferImage(FrameBufferRaster raster, ColorModel colorModel) { + super(colorModel, raster, true, null); + fb = raster.getFrameBuffer(); } public void close() { diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java index 55c0595..a06d028 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java @@ -1,12 +1,29 @@ package org.tw.pi.framebuffer; import java.awt.Point; +import java.awt.image.SampleModel; import java.awt.image.WritableRaster; +import org.tw.pi.framebuffer.FrameBuffers.ColorEndian; + public class FrameBufferRaster extends WritableRaster { + private FrameBuffer fb; + public FrameBufferRaster(FrameBuffer fb) { - super(FrameBuffers.createSampleModel(fb.getColorDepth(), fb.getWidth(), fb.getHeight()), fb, new Point(0, 0)); + this(fb, ColorEndian.RGB); + } + + public FrameBufferRaster(FrameBuffer fb, ColorEndian ce) { + this(fb, ce.createSampleModel(fb.getWidth(), fb.getHeight(), fb.getColorDepth())); } + public FrameBufferRaster(FrameBuffer fb, SampleModel sampleModel) { + super(sampleModel, fb, new Point(0,0)); + this.fb = fb; + } + + public FrameBuffer getFrameBuffer() { + return fb; + } } diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java index d51450a..5b06d9b 100755 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java @@ -9,6 +9,7 @@ package org.tw.pi.framebuffer; +import java.awt.color.ColorSpace; import java.awt.image.ColorModel; import java.awt.image.DataBuffer; import java.awt.image.DirectColorModel; @@ -25,6 +26,227 @@ public abstract class FrameBuffers { public static final long ERR_BITS = 4; public static final long ERR_MMAP = 5; + public static enum ColorEndian { + RGB { + @Override + public ColorModel createColorModel(int bpp) { + return createColorModelRGB(bpp); + } + + @Override + public SampleModel createSampleModel(int w, int h, int bpp) { + return createSampleModelRGB(w, h, bpp); + } + }, + BGR { + @Override + public ColorModel createColorModel(int bpp) { + return createColorModelBGR(bpp); + } + + @Override + public SampleModel createSampleModel(int w, int h, int bpp) { + return createSampleModelBGR(w, h, bpp); + } + }, + ; + + public abstract ColorModel createColorModel(int bpp); + public abstract SampleModel createSampleModel(int w, int h, int bpp); + } + + public static ColorModel createColorModelRGB8() { + return new DirectColorModel( + ColorSpace.getInstance(ColorSpace.CS_sRGB), + 16, + 0x000000e0, + 0x0000001c, + 0x00000003, + 0x0, + false, + DataBuffer.TYPE_INT); + } + + public static ColorModel createColorModelRGB16() { + return new DirectColorModel( + ColorSpace.getInstance(ColorSpace.CS_sRGB), + 16, + 0x0000f800, + 0x000007e0, + 0x0000001f, + 0x0, + false, + DataBuffer.TYPE_INT); + } + + public static ColorModel createColorModelRGB24() { + return new DirectColorModel( + ColorSpace.getInstance(ColorSpace.CS_sRGB), + 24, + 0x00ff0000, + 0x0000ff00, + 0x000000ff, + 0x0, + false, + DataBuffer.TYPE_INT); + } + + public static ColorModel createColorModelBGR8() { + return new DirectColorModel( + ColorSpace.getInstance(ColorSpace.CS_sRGB), + 16, + 0x00000003, + 0x0000001c, + 0x000000e0, + 0x0, + false, + DataBuffer.TYPE_INT); + } + + public static ColorModel createColorModelBGR16() { + return new DirectColorModel( + ColorSpace.getInstance(ColorSpace.CS_sRGB), + 16, + 0x0000001f, + 0x000007e0, + 0x0000f800, + 0x0, + false, + DataBuffer.TYPE_INT); + } + + public static ColorModel createColorModelBGR24() { + return new DirectColorModel( + ColorSpace.getInstance(ColorSpace.CS_sRGB), + 24, + 0x000000ff, + 0x0000ff00, + 0x00ff0000, + 0x0, + false, + DataBuffer.TYPE_INT); + } + + public static ColorModel createColorModelRGB(int bpp) { + switch(bpp) { + case 8: + return createColorModelRGB8(); + case 16: + return createColorModelRGB16(); + case 24: + return createColorModelRGB24(); + } + throw new IllegalArgumentException("Invalid RGB color depth:" + bpp); + } + + public static ColorModel createColorModelBGR(int bpp) { + switch(bpp) { + case 8: + return createColorModelBGR8(); + case 16: + return createColorModelBGR16(); + case 24: + return createColorModelBGR24(); + } + throw new IllegalArgumentException("Invalid BGR color depth:" + bpp); + } + + public static final SampleModel createSampleModelRGB8(int w, int h) { + return new SinglePixelPackedSampleModel( + DataBuffer.TYPE_INT, + w, + h, + new int[] { + 0x000000e0, + 0x0000001c, + 0x00000003, + }); + } + + public static final SampleModel createSampleModelRGB16(int w, int h) { + return new SinglePixelPackedSampleModel( + DataBuffer.TYPE_INT, + w, + h, + new int[] { + 0x0000f800, + 0x000007e0, + 0x0000001f, + }); + } + + public static final SampleModel createSampleModelRGB24(int w, int h) { + return new SinglePixelPackedSampleModel( + DataBuffer.TYPE_INT, + w, + h, + new int[] { + 0x00ff0000, + 0x0000ff00, + 0x000000ff, + }); + } + + public static final SampleModel createSampleModelBGR8(int w, int h) { + return new SinglePixelPackedSampleModel( + DataBuffer.TYPE_INT, + w, + h, + new int[] { + 0x00000003, + 0x0000001c, + 0x000000e0, + }); + } + + public static final SampleModel createSampleModelBGR16(int w, int h) { + return new SinglePixelPackedSampleModel( + DataBuffer.TYPE_INT, + w, + h, + new int[] { + 0x0000001f, + 0x000007e0, + 0x0000f800, + }); + } + + public static final SampleModel createSampleModelBGR24(int w, int h) { + return new SinglePixelPackedSampleModel( + DataBuffer.TYPE_INT, + w, + h, + new int[] { + 0x000000ff, + 0x0000ff00, + 0x00ff0000, + }); + } + + public static SampleModel createSampleModelRGB(int w, int h, int bpp) { + switch(bpp) { + case 8: + return createSampleModelRGB8(w, h); + case 16: + return createSampleModelRGB16(w, h); + case 24: + return createSampleModelRGB24(w, h); + } + throw new IllegalArgumentException("Invalid RGB color depth:" + bpp); + } + + public static SampleModel createSampleModelBGR(int w, int h, int bpp) { + switch(bpp) { + case 8: + return createSampleModelBGR8(w, h); + case 16: + return createSampleModelBGR16(w, h); + case 24: + return createSampleModelBGR24(w, h); + } + throw new IllegalArgumentException("Invalid BGR color depth:" + bpp); + } + public static native long openDevice(String fbdev); public static native void closeDevice(long ptr); @@ -35,10 +257,6 @@ public abstract class FrameBuffers { public static native void writeRGB(long ptr, int idx, int rgb); public static native int readRGB(long ptr, int idx); - static { - NarSystem.loadLibrary(); - } - public static long open(String fbdev) { long ptr = FrameBuffers.openDevice(fbdev); @@ -58,50 +276,10 @@ public static long open(String fbdev) { return ptr; } - public static ColorModel createColorModel(int bpp) { - if(bpp == 16) { - return new DirectColorModel(16, - 0x00f80000, // Red - 0x0000fc00, // Green - 0x000000f8, // Blue - 0x0 // Alpha - ); - } else if(bpp == 24) { - return new DirectColorModel(24, - 0x00ff0000, // Red - 0x0000ff00, // Green - 0x000000ff, // Blue - 0x0 // Alpha - ); - } else - throw new IllegalArgumentException("Invalid framebuffer color depth:" + bpp); - } - - public static SampleModel createSampleModel(int bpp, int w, int h) { - if(bpp == 16) { - return new SinglePixelPackedSampleModel( - DataBuffer.TYPE_INT, - w, - h, - new int[] { - 0x00f80000, // Red - 0x0000fc00, // Green - 0x000000f8, // Blue - }); - } else if(bpp == 24) { - return new SinglePixelPackedSampleModel( - DataBuffer.TYPE_INT, - w, - h, - new int[] { - 0x00ff0000, // Red - 0x0000ff00, // Green - 0x000000ff, // Blue - }); - } else - throw new IllegalArgumentException("Invalid framebuffer color depth:" + bpp); + private FrameBuffers() { } - private FrameBuffers() { + static { + NarSystem.loadLibrary(); } } diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java index a4b594a..e6fb07f 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java @@ -7,13 +7,13 @@ public class FrameBufferImageTest { @Test public void testCompatibility16bpp() { - Assert.assertTrue(FrameBuffers.createColorModel(16).isCompatibleSampleModel(FrameBuffers.createSampleModel(16, 1, 1))); - Assert.assertTrue(FrameBuffers.createColorModel(16).isCompatibleRaster(new FrameBufferRaster(new FrameBuffer(1,1)))); + Assert.assertTrue(FrameBuffers.createColorModelRGB(16).isCompatibleSampleModel(FrameBuffers.createSampleModelRGB(1, 1, 16))); + Assert.assertTrue(FrameBuffers.createColorModelRGB(16).isCompatibleRaster(new FrameBufferRaster(new FrameBuffer(1, 1, 16)))); } @Test public void testCompatibility24bpp() { - Assert.assertTrue(FrameBuffers.createColorModel(24).isCompatibleSampleModel(FrameBuffers.createSampleModel(24, 1, 1))); - Assert.assertTrue(FrameBuffers.createColorModel(24).isCompatibleRaster(new FrameBufferRaster(new FrameBuffer(1,1)))); + Assert.assertTrue(FrameBuffers.createColorModelRGB(24).isCompatibleSampleModel(FrameBuffers.createSampleModelRGB(1, 1, 24))); + Assert.assertTrue(FrameBuffers.createColorModelRGB(24).isCompatibleRaster(new FrameBufferRaster(new FrameBuffer(1, 1, 24)))); } } diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index 8d5381c..9bb4227 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -14,9 +14,12 @@ public static void main(String[] args) throws Exception { FrameBufferImage fb = new FrameBufferImage(args[0]); try { Graphics g = fb.getGraphics(); + int m = 7; for(int i = 0; i < Math.min(fb.getWidth(), fb.getHeight()) / 2; i++) { - g.setColor(new Color((int)(0xFFFFFF * Math.random()))); + g.setColor(new Color(m)); g.drawRect(i, i, fb.getWidth() - 2*i, fb.getHeight() - 2*i); + m <<= 1; + m |= (m >>> 24); } } finally { fb.close(); From d8fb97c7a447db4685572d2c082a444c84d8478e Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 22:29:42 -0500 Subject: [PATCH 36/77] more refactoring improvements --- .../tw/pi/framebuffer/FrameBufferImage.java | 8 +- .../tw/pi/framebuffer/FrameBufferRaster.java | 4 +- .../org/tw/pi/framebuffer/FrameBuffers.java | 235 ++++-------------- .../pi/framebuffer/FrameBufferImageTest.java | 17 +- .../tw/pi/framebuffer/FrameBufferTest.java | 2 +- 5 files changed, 70 insertions(+), 196 deletions(-) diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java index 8fd3e86..bbb81c7 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java @@ -12,15 +12,15 @@ public FrameBufferImage(String fbdev) { this(new FrameBuffer(fbdev)); } - public FrameBufferImage(String fbdev, ColorEndian ce) { - this(new FrameBuffer(fbdev), ce); + public FrameBufferImage(ColorEndian ce, String fbdev) { + this(ce, new FrameBuffer(fbdev)); } public FrameBufferImage(FrameBuffer fb) { - this(fb, ColorEndian.RGB); + this(ColorEndian.RGB, fb); } - public FrameBufferImage(FrameBuffer fb, ColorEndian ce) { + public FrameBufferImage(ColorEndian ce, FrameBuffer fb) { this( new FrameBufferRaster( fb, diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java index a06d028..e5260e8 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java @@ -11,10 +11,10 @@ public class FrameBufferRaster extends WritableRaster { private FrameBuffer fb; public FrameBufferRaster(FrameBuffer fb) { - this(fb, ColorEndian.RGB); + this(ColorEndian.RGB, fb); } - public FrameBufferRaster(FrameBuffer fb, ColorEndian ce) { + public FrameBufferRaster(ColorEndian ce, FrameBuffer fb) { this(fb, ce.createSampleModel(fb.getWidth(), fb.getHeight(), fb.getColorDepth())); } diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java index 5b06d9b..8329da9 100755 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java @@ -27,225 +27,90 @@ public abstract class FrameBuffers { public static final long ERR_MMAP = 5; public static enum ColorEndian { - RGB { - @Override - public ColorModel createColorModel(int bpp) { - return createColorModelRGB(bpp); - } - - @Override - public SampleModel createSampleModel(int w, int h, int bpp) { - return createSampleModelRGB(w, h, bpp); - } - }, - BGR { - @Override - public ColorModel createColorModel(int bpp) { - return createColorModelBGR(bpp); - } - - @Override - public SampleModel createSampleModel(int w, int h, int bpp) { - return createSampleModelBGR(w, h, bpp); - } - }, - ; - - public abstract ColorModel createColorModel(int bpp); - public abstract SampleModel createSampleModel(int w, int h, int bpp); - } - - public static ColorModel createColorModelRGB8() { - return new DirectColorModel( - ColorSpace.getInstance(ColorSpace.CS_sRGB), - 16, + RGB(new int[]{ 0x000000e0, 0x0000001c, 0x00000003, - 0x0, - false, - DataBuffer.TYPE_INT); - } - - public static ColorModel createColorModelRGB16() { - return new DirectColorModel( - ColorSpace.getInstance(ColorSpace.CS_sRGB), - 16, + }, new int[]{ 0x0000f800, 0x000007e0, 0x0000001f, - 0x0, - false, - DataBuffer.TYPE_INT); - } - - public static ColorModel createColorModelRGB24() { - return new DirectColorModel( - ColorSpace.getInstance(ColorSpace.CS_sRGB), - 24, + }, new int[] { 0x00ff0000, 0x0000ff00, 0x000000ff, - 0x0, - false, - DataBuffer.TYPE_INT); - } - - public static ColorModel createColorModelBGR8() { - return new DirectColorModel( - ColorSpace.getInstance(ColorSpace.CS_sRGB), - 16, + }), + BGR(new int[]{ 0x00000003, 0x0000001c, 0x000000e0, - 0x0, - false, - DataBuffer.TYPE_INT); - } - - public static ColorModel createColorModelBGR16() { - return new DirectColorModel( - ColorSpace.getInstance(ColorSpace.CS_sRGB), - 16, + }, new int[]{ 0x0000001f, 0x000007e0, 0x0000f800, - 0x0, - false, - DataBuffer.TYPE_INT); - } - - public static ColorModel createColorModelBGR24() { - return new DirectColorModel( - ColorSpace.getInstance(ColorSpace.CS_sRGB), - 24, + }, new int[] { 0x000000ff, 0x0000ff00, 0x00ff0000, - 0x0, - false, - DataBuffer.TYPE_INT); - } - - public static ColorModel createColorModelRGB(int bpp) { - switch(bpp) { - case 8: - return createColorModelRGB8(); - case 16: - return createColorModelRGB16(); - case 24: - return createColorModelRGB24(); - } - throw new IllegalArgumentException("Invalid RGB color depth:" + bpp); - } + }), + ; - public static ColorModel createColorModelBGR(int bpp) { - switch(bpp) { - case 8: - return createColorModelBGR8(); - case 16: - return createColorModelBGR16(); - case 24: - return createColorModelBGR24(); + public static final int RED = 0; + public static final int GREEN = 1; + public static final int BLUE = 2; + + private int[] mask8; + private int[] mask16; + private int[] mask24; + + private ColorEndian(int[] mask8, int[] mask16, int[] mask24) { + this.mask8 = mask8; + this.mask16 = mask16; + this.mask24 = mask24; + } + + public int mask(int bpp, int color) { + switch(bpp) { + case 8: return mask8[color]; + case 16: return mask16[color]; + case 24: return mask24[color]; + } + throw new IllegalArgumentException("Invalid color depth for " + this + ": " + bpp); } - throw new IllegalArgumentException("Invalid BGR color depth:" + bpp); - } - - public static final SampleModel createSampleModelRGB8(int w, int h) { - return new SinglePixelPackedSampleModel( - DataBuffer.TYPE_INT, - w, - h, - new int[] { - 0x000000e0, - 0x0000001c, - 0x00000003, - }); - } - - public static final SampleModel createSampleModelRGB16(int w, int h) { - return new SinglePixelPackedSampleModel( - DataBuffer.TYPE_INT, - w, - h, - new int[] { - 0x0000f800, - 0x000007e0, - 0x0000001f, - }); - } - public static final SampleModel createSampleModelRGB24(int w, int h) { - return new SinglePixelPackedSampleModel( - DataBuffer.TYPE_INT, - w, - h, - new int[] { - 0x00ff0000, - 0x0000ff00, - 0x000000ff, - }); + public ColorModel createColorModel(int bpp) { + return FrameBuffers.createColorModel(this, bpp); + } + public SampleModel createSampleModel(int w, int h, int bpp) { + return FrameBuffers.createSampleModel(this, w, h, bpp); + } } - public static final SampleModel createSampleModelBGR8(int w, int h) { - return new SinglePixelPackedSampleModel( - DataBuffer.TYPE_INT, - w, - h, - new int[] { - 0x00000003, - 0x0000001c, - 0x000000e0, - }); + public static ColorModel createColorModel(ColorEndian ce, int bpp) { + return new DirectColorModel( + ColorSpace.getInstance(ColorSpace.CS_sRGB), + bpp, + ce.mask(bpp, ColorEndian.RED), + ce.mask(bpp, ColorEndian.GREEN), + ce.mask(bpp, ColorEndian.BLUE), + 0x0, + false, + DataBuffer.TYPE_INT); } - public static final SampleModel createSampleModelBGR16(int w, int h) { - return new SinglePixelPackedSampleModel( - DataBuffer.TYPE_INT, - w, - h, - new int[] { - 0x0000001f, - 0x000007e0, - 0x0000f800, - }); - } - public static final SampleModel createSampleModelBGR24(int w, int h) { + public static SampleModel createSampleModel(ColorEndian ce, int w, int h, int bpp) { return new SinglePixelPackedSampleModel( DataBuffer.TYPE_INT, w, h, new int[] { - 0x000000ff, - 0x0000ff00, - 0x00ff0000, + ce.mask(bpp, ColorEndian.RED), + ce.mask(bpp, ColorEndian.GREEN), + ce.mask(bpp, ColorEndian.BLUE), }); } - public static SampleModel createSampleModelRGB(int w, int h, int bpp) { - switch(bpp) { - case 8: - return createSampleModelRGB8(w, h); - case 16: - return createSampleModelRGB16(w, h); - case 24: - return createSampleModelRGB24(w, h); - } - throw new IllegalArgumentException("Invalid RGB color depth:" + bpp); - } - - public static SampleModel createSampleModelBGR(int w, int h, int bpp) { - switch(bpp) { - case 8: - return createSampleModelBGR8(w, h); - case 16: - return createSampleModelBGR16(w, h); - case 24: - return createSampleModelBGR24(w, h); - } - throw new IllegalArgumentException("Invalid BGR color depth:" + bpp); - } public static native long openDevice(String fbdev); public static native void closeDevice(long ptr); diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java index e6fb07f..4284857 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java @@ -2,18 +2,27 @@ import org.junit.Assert; import org.junit.Test; +import org.tw.pi.framebuffer.FrameBuffers.ColorEndian; public class FrameBufferImageTest { @Test public void testCompatibility16bpp() { - Assert.assertTrue(FrameBuffers.createColorModelRGB(16).isCompatibleSampleModel(FrameBuffers.createSampleModelRGB(1, 1, 16))); - Assert.assertTrue(FrameBuffers.createColorModelRGB(16).isCompatibleRaster(new FrameBufferRaster(new FrameBuffer(1, 1, 16)))); + ColorEndian ce = ColorEndian.RGB; + Assert.assertTrue(FrameBuffers.createColorModel(ce, 16).isCompatibleSampleModel(FrameBuffers.createSampleModel(ce, 1, 1, 16))); + Assert.assertTrue(FrameBuffers.createColorModel(ce, 16).isCompatibleRaster(new FrameBufferRaster(ce, new FrameBuffer(1, 1, 16)))); + ce = ColorEndian.BGR; + Assert.assertTrue(FrameBuffers.createColorModel(ce, 16).isCompatibleSampleModel(FrameBuffers.createSampleModel(ce, 1, 1, 16))); + Assert.assertTrue(FrameBuffers.createColorModel(ce, 16).isCompatibleRaster(new FrameBufferRaster(ce, new FrameBuffer(1, 1, 16)))); } @Test public void testCompatibility24bpp() { - Assert.assertTrue(FrameBuffers.createColorModelRGB(24).isCompatibleSampleModel(FrameBuffers.createSampleModelRGB(1, 1, 24))); - Assert.assertTrue(FrameBuffers.createColorModelRGB(24).isCompatibleRaster(new FrameBufferRaster(new FrameBuffer(1, 1, 24)))); + ColorEndian ce = ColorEndian.RGB; + Assert.assertTrue(FrameBuffers.createColorModel(ce, 24).isCompatibleSampleModel(FrameBuffers.createSampleModel(ce, 1, 1, 24))); + Assert.assertTrue(FrameBuffers.createColorModel(ce, 24).isCompatibleRaster(new FrameBufferRaster(ce, new FrameBuffer(1, 1, 24)))); + ce = ColorEndian.BGR; + Assert.assertTrue(FrameBuffers.createColorModel(ce, 24).isCompatibleSampleModel(FrameBuffers.createSampleModel(ce, 1, 1, 24))); + Assert.assertTrue(FrameBuffers.createColorModel(ce, 24).isCompatibleRaster(new FrameBufferRaster(ce, new FrameBuffer(1, 1, 24)))); } } diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index 9bb4227..5423e8b 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -14,7 +14,7 @@ public static void main(String[] args) throws Exception { FrameBufferImage fb = new FrameBufferImage(args[0]); try { Graphics g = fb.getGraphics(); - int m = 7; + int m = 0xff; for(int i = 0; i < Math.min(fb.getWidth(), fb.getHeight()) / 2; i++) { g.setColor(new Color(m)); g.drawRect(i, i, fb.getWidth() - 2*i, fb.getHeight() - 2*i); From a6d39302c7df4f149568b77122fce0e8b850afc8 Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 22:38:18 -0500 Subject: [PATCH 37/77] Reduce visibility, rename, native methods --- framebuffer/src/main/c/FrameBuffers.c | 14 ++--- .../org/tw/pi/framebuffer/FrameBuffer.java | 14 ++--- .../org/tw/pi/framebuffer/FrameBuffers.java | 58 +++++++++---------- 3 files changed, 43 insertions(+), 43 deletions(-) diff --git a/framebuffer/src/main/c/FrameBuffers.c b/framebuffer/src/main/c/FrameBuffers.c index 77c5431..757a667 100755 --- a/framebuffer/src/main/c/FrameBuffers.c +++ b/framebuffer/src/main/c/FrameBuffers.c @@ -42,7 +42,7 @@ struct deviceInfo { char *fbp; // MemoryMapped buffer }; -JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_openDevice( +JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_openDevice0( JNIEnv *env, jobject obj, jstring device) { jboolean isCopy; @@ -118,7 +118,7 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_openDevice( #endif } -JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_closeDevice( +JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_closeDevice0( JNIEnv *env, jobject obj, jlong jdi) { struct deviceInfo *di = (struct deviceInfo *) (intptr_t) jdi; @@ -133,7 +133,7 @@ JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_closeDevice( memset(di, 0, sizeof(*di)); // :-) } -JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_getDeviceWidth( +JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_getDeviceWidth0( JNIEnv *env, jobject obj, jlong jdi) { struct deviceInfo *di = (struct deviceInfo *) (intptr_t) jdi; @@ -141,7 +141,7 @@ JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_getDeviceWidth( return di->width; } -JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_getDeviceHeight( +JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_getDeviceHeight0( JNIEnv *env, jobject obj, jlong jdi) { struct deviceInfo *di = (struct deviceInfo *) (intptr_t) jdi; @@ -149,7 +149,7 @@ JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_getDeviceHeight( return di->height; } -JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_getDeviceBitsPerPixel( +JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_getDeviceBitsPerPixel0( JNIEnv *env, jobject obj, jlong jdi) { struct deviceInfo *di = (struct deviceInfo *) (intptr_t) jdi; @@ -157,7 +157,7 @@ JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_getDeviceBitsPerP return di->bpp; } -JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_writeRGB +JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_writeRGB0 (JNIEnv *env, jclass clazz, jlong ptr, jint idx, jint rgb) { struct deviceInfo *di = (struct deviceInfo *) (intptr_t) ptr; unsigned char *p = (unsigned char *) di->fbp; @@ -182,7 +182,7 @@ JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_writeRGB } } -JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_readRGB +JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_readRGB0 (JNIEnv *env, jclass clazz, jlong ptr, jint idx) { struct deviceInfo *di = (struct deviceInfo *) (intptr_t) ptr; unsigned char *p = (unsigned char *) di->fbp; diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java index 2eb95d2..0b7cb99 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java @@ -21,7 +21,7 @@ public FrameBuffer() { } public FrameBuffer(String fbdev) { - this(FrameBuffers.open(fbdev)); + this(FrameBuffers.openDevice(fbdev)); } public FrameBuffer(int w, int h, int bpp) { @@ -35,9 +35,9 @@ public FrameBuffer(int w, int h) { private FrameBuffer(long ptr) { this( ptr, - (ptr == FrameBuffers.DUMMY ? DEFAULT_DUMMY_WIDTH : FrameBuffers.getDeviceWidth(ptr)), - (ptr == FrameBuffers.DUMMY ? DEFAULT_DUMMY_HEIGHT : FrameBuffers.getDeviceHeight(ptr)), - (ptr == FrameBuffers.DUMMY ? DEFAULT_COLOR_DEPTH : FrameBuffers.getDeviceBitsPerPixel(ptr))); + (ptr == FrameBuffers.DUMMY ? DEFAULT_DUMMY_WIDTH : FrameBuffers.getDeviceWidth0(ptr)), + (ptr == FrameBuffers.DUMMY ? DEFAULT_DUMMY_HEIGHT : FrameBuffers.getDeviceHeight0(ptr)), + (ptr == FrameBuffers.DUMMY ? DEFAULT_COLOR_DEPTH : FrameBuffers.getDeviceBitsPerPixel0(ptr))); } private FrameBuffer(long ptr, int w, int h, int bpp) { @@ -62,7 +62,7 @@ public int getElem(int bank, int i) { if(ptr == FrameBuffers.DUMMY) val = dummy[i]; else - val = FrameBuffers.readRGB(ptr, i); + val = FrameBuffers.readRGB0(ptr, i); return val & 0x00FFFFFF; } @@ -74,13 +74,13 @@ public void setElem(int bank, int i, int val) { if(ptr == FrameBuffers.DUMMY) dummy[i] = val; else - FrameBuffers.writeRGB(ptr, i, val); + FrameBuffers.writeRGB0(ptr, i, val); } public void close() { if(!closed) { if(ptr != FrameBuffers.DUMMY) - FrameBuffers.closeDevice(ptr); + FrameBuffers.closeDevice0(ptr); closed = true; } } diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java index 8329da9..f2959a4 100755 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java @@ -19,12 +19,12 @@ import org.tw.pi.NarSystem; public abstract class FrameBuffers { - public static final long DUMMY = -1; - public static final long ERR_OPEN = 1; - public static final long ERR_FIXED = 2; - public static final long ERR_VARIABLE = 3; - public static final long ERR_BITS = 4; - public static final long ERR_MMAP = 5; + static final long DUMMY = -1; + static final long ERR_OPEN = 1; + static final long ERR_FIXED = 2; + static final long ERR_VARIABLE = 3; + static final long ERR_BITS = 4; + static final long ERR_MMAP = 5; public static enum ColorEndian { RGB(new int[]{ @@ -55,9 +55,9 @@ public static enum ColorEndian { }), ; - public static final int RED = 0; - public static final int GREEN = 1; - public static final int BLUE = 2; + public static final int RED_COMPONENT = 0; + public static final int GREEN_COMPONENT = 1; + public static final int BLUE_COMPONENT = 2; private int[] mask8; private int[] mask16; @@ -69,11 +69,11 @@ private ColorEndian(int[] mask8, int[] mask16, int[] mask24) { this.mask24 = mask24; } - public int mask(int bpp, int color) { + public int getComponentMask(int bpp, int component) { switch(bpp) { - case 8: return mask8[color]; - case 16: return mask16[color]; - case 24: return mask24[color]; + case 8: return mask8[component]; + case 16: return mask16[component]; + case 24: return mask24[component]; } throw new IllegalArgumentException("Invalid color depth for " + this + ": " + bpp); } @@ -90,9 +90,9 @@ public static ColorModel createColorModel(ColorEndian ce, int bpp) { return new DirectColorModel( ColorSpace.getInstance(ColorSpace.CS_sRGB), bpp, - ce.mask(bpp, ColorEndian.RED), - ce.mask(bpp, ColorEndian.GREEN), - ce.mask(bpp, ColorEndian.BLUE), + ce.getComponentMask(bpp, ColorEndian.RED_COMPONENT), + ce.getComponentMask(bpp, ColorEndian.GREEN_COMPONENT), + ce.getComponentMask(bpp, ColorEndian.BLUE_COMPONENT), 0x0, false, DataBuffer.TYPE_INT); @@ -105,25 +105,25 @@ public static SampleModel createSampleModel(ColorEndian ce, int w, int h, int bp w, h, new int[] { - ce.mask(bpp, ColorEndian.RED), - ce.mask(bpp, ColorEndian.GREEN), - ce.mask(bpp, ColorEndian.BLUE), + ce.getComponentMask(bpp, ColorEndian.RED_COMPONENT), + ce.getComponentMask(bpp, ColorEndian.GREEN_COMPONENT), + ce.getComponentMask(bpp, ColorEndian.BLUE_COMPONENT), }); } - public static native long openDevice(String fbdev); - public static native void closeDevice(long ptr); + static native long openDevice0(String fbdev); + static native void closeDevice0(long ptr); - public static native int getDeviceWidth(long ptr); - public static native int getDeviceHeight(long ptr); - public static native int getDeviceBitsPerPixel(long ptr); + static native int getDeviceWidth0(long ptr); + static native int getDeviceHeight0(long ptr); + static native int getDeviceBitsPerPixel0(long ptr); - public static native void writeRGB(long ptr, int idx, int rgb); - public static native int readRGB(long ptr, int idx); + static native void writeRGB0(long ptr, int idx, int rgb); + static native int readRGB0(long ptr, int idx); - public static long open(String fbdev) { - long ptr = FrameBuffers.openDevice(fbdev); + static long openDevice(String fbdev) { + long ptr = FrameBuffers.openDevice0(fbdev); if(ptr == FrameBuffers.DUMMY) return FrameBuffers.DUMMY; @@ -134,7 +134,7 @@ public static long open(String fbdev) { if(ptr == FrameBuffers.ERR_VARIABLE) throw new RuntimeException("Error reading variable screen info for: " + fbdev); if(ptr == FrameBuffers.ERR_BITS) - throw new RuntimeException("Invalid color depth (" + FrameBuffers.getDeviceBitsPerPixel(ptr) + "), 16 and 24 supported, for: " + fbdev); + throw new RuntimeException("Invalid color depth (" + FrameBuffers.getDeviceBitsPerPixel0(ptr) + "), 16 and 24 supported, for: " + fbdev); if(ptr == FrameBuffers.ERR_MMAP) throw new RuntimeException("Unable to mmap for: " + fbdev); From bd913555970653ed4097ff782af6d20212f5bfa1 Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 22:41:12 -0500 Subject: [PATCH 38/77] rename classes --- ...ameBufferImage.java => FrameBufferedImage.java} | 14 +++++++------- ...eBufferRaster.java => FrameBufferedRaster.java} | 8 ++++---- .../java/org/tw/pi/framebuffer/FrameBuffers.java | 7 +++++++ .../org/tw/pi/framebuffer/FrameBufferTest.java | 2 +- ...rImageTest.java => FrameBufferedImageTest.java} | 10 +++++----- 5 files changed, 24 insertions(+), 17 deletions(-) rename framebuffer/src/main/java/org/tw/pi/framebuffer/{FrameBufferImage.java => FrameBufferedImage.java} (62%) rename framebuffer/src/main/java/org/tw/pi/framebuffer/{FrameBufferRaster.java => FrameBufferedRaster.java} (65%) rename framebuffer/src/test/java/org/tw/pi/framebuffer/{FrameBufferImageTest.java => FrameBufferedImageTest.java} (77%) diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedImage.java similarity index 62% rename from framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java rename to framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedImage.java index bbb81c7..7d7feb9 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferImage.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedImage.java @@ -5,30 +5,30 @@ import org.tw.pi.framebuffer.FrameBuffers.ColorEndian; -public class FrameBufferImage extends BufferedImage { +public class FrameBufferedImage extends BufferedImage { private FrameBuffer fb; - public FrameBufferImage(String fbdev) { + public FrameBufferedImage(String fbdev) { this(new FrameBuffer(fbdev)); } - public FrameBufferImage(ColorEndian ce, String fbdev) { + public FrameBufferedImage(ColorEndian ce, String fbdev) { this(ce, new FrameBuffer(fbdev)); } - public FrameBufferImage(FrameBuffer fb) { + public FrameBufferedImage(FrameBuffer fb) { this(ColorEndian.RGB, fb); } - public FrameBufferImage(ColorEndian ce, FrameBuffer fb) { + public FrameBufferedImage(ColorEndian ce, FrameBuffer fb) { this( - new FrameBufferRaster( + new FrameBufferedRaster( fb, ce.createSampleModel(fb.getWidth(), fb.getHeight(), fb.getColorDepth())), ce.createColorModel(fb.getColorDepth())); } - public FrameBufferImage(FrameBufferRaster raster, ColorModel colorModel) { + public FrameBufferedImage(FrameBufferedRaster raster, ColorModel colorModel) { super(colorModel, raster, true, null); fb = raster.getFrameBuffer(); } diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedRaster.java similarity index 65% rename from framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java rename to framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedRaster.java index e5260e8..44159fe 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferRaster.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedRaster.java @@ -6,19 +6,19 @@ import org.tw.pi.framebuffer.FrameBuffers.ColorEndian; -public class FrameBufferRaster extends WritableRaster { +public class FrameBufferedRaster extends WritableRaster { private FrameBuffer fb; - public FrameBufferRaster(FrameBuffer fb) { + public FrameBufferedRaster(FrameBuffer fb) { this(ColorEndian.RGB, fb); } - public FrameBufferRaster(ColorEndian ce, FrameBuffer fb) { + public FrameBufferedRaster(ColorEndian ce, FrameBuffer fb) { this(fb, ce.createSampleModel(fb.getWidth(), fb.getHeight(), fb.getColorDepth())); } - public FrameBufferRaster(FrameBuffer fb, SampleModel sampleModel) { + public FrameBufferedRaster(FrameBuffer fb, SampleModel sampleModel) { super(sampleModel, fb, new Point(0,0)); this.fb = fb; } diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java index f2959a4..d30007c 100755 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java @@ -110,7 +110,14 @@ public static SampleModel createSampleModel(ColorEndian ce, int w, int h, int bp ce.getComponentMask(bpp, ColorEndian.BLUE_COMPONENT), }); } + + public static FrameBufferedImage openImage(String fbdev) { + return new FrameBufferedImage(fbdev); + } + public static FrameBufferedImage openImage(ColorEndian ce, String fbdev) { + return new FrameBufferedImage(ce, fbdev); + } static native long openDevice0(String fbdev); static native void closeDevice0(long ptr); diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index 5423e8b..e56345e 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -11,7 +11,7 @@ public void testLoad() throws Exception { } public static void main(String[] args) throws Exception { - FrameBufferImage fb = new FrameBufferImage(args[0]); + FrameBufferedImage fb = new FrameBufferedImage(args[0]); try { Graphics g = fb.getGraphics(); int m = 0xff; diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferedImageTest.java similarity index 77% rename from framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java rename to framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferedImageTest.java index 4284857..abbff89 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferImageTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferedImageTest.java @@ -4,25 +4,25 @@ import org.junit.Test; import org.tw.pi.framebuffer.FrameBuffers.ColorEndian; -public class FrameBufferImageTest { +public class FrameBufferedImageTest { @Test public void testCompatibility16bpp() { ColorEndian ce = ColorEndian.RGB; Assert.assertTrue(FrameBuffers.createColorModel(ce, 16).isCompatibleSampleModel(FrameBuffers.createSampleModel(ce, 1, 1, 16))); - Assert.assertTrue(FrameBuffers.createColorModel(ce, 16).isCompatibleRaster(new FrameBufferRaster(ce, new FrameBuffer(1, 1, 16)))); + Assert.assertTrue(FrameBuffers.createColorModel(ce, 16).isCompatibleRaster(new FrameBufferedRaster(ce, new FrameBuffer(1, 1, 16)))); ce = ColorEndian.BGR; Assert.assertTrue(FrameBuffers.createColorModel(ce, 16).isCompatibleSampleModel(FrameBuffers.createSampleModel(ce, 1, 1, 16))); - Assert.assertTrue(FrameBuffers.createColorModel(ce, 16).isCompatibleRaster(new FrameBufferRaster(ce, new FrameBuffer(1, 1, 16)))); + Assert.assertTrue(FrameBuffers.createColorModel(ce, 16).isCompatibleRaster(new FrameBufferedRaster(ce, new FrameBuffer(1, 1, 16)))); } @Test public void testCompatibility24bpp() { ColorEndian ce = ColorEndian.RGB; Assert.assertTrue(FrameBuffers.createColorModel(ce, 24).isCompatibleSampleModel(FrameBuffers.createSampleModel(ce, 1, 1, 24))); - Assert.assertTrue(FrameBuffers.createColorModel(ce, 24).isCompatibleRaster(new FrameBufferRaster(ce, new FrameBuffer(1, 1, 24)))); + Assert.assertTrue(FrameBuffers.createColorModel(ce, 24).isCompatibleRaster(new FrameBufferedRaster(ce, new FrameBuffer(1, 1, 24)))); ce = ColorEndian.BGR; Assert.assertTrue(FrameBuffers.createColorModel(ce, 24).isCompatibleSampleModel(FrameBuffers.createSampleModel(ce, 1, 1, 24))); - Assert.assertTrue(FrameBuffers.createColorModel(ce, 24).isCompatibleRaster(new FrameBufferRaster(ce, new FrameBuffer(1, 1, 24)))); + Assert.assertTrue(FrameBuffers.createColorModel(ce, 24).isCompatibleRaster(new FrameBufferedRaster(ce, new FrameBuffer(1, 1, 24)))); } } From 4eb0a7678ab825187932a8316f66660e57c3b5f8 Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 22:51:50 -0500 Subject: [PATCH 39/77] Mostly done refactoring, about time to start documenting --- .../org/tw/pi/framebuffer/FrameBuffer.java | 3 +- .../tw/pi/framebuffer/FrameBufferedImage.java | 3 +- .../pi/framebuffer/FrameBufferedRaster.java | 8 +- .../org/tw/pi/framebuffer/FrameBuffers.java | 80 ++++++++----------- .../framebuffer/FrameBufferedImageTest.java | 28 +++++-- 5 files changed, 63 insertions(+), 59 deletions(-) diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java index 0b7cb99..47f9277 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java @@ -1,8 +1,9 @@ package org.tw.pi.framebuffer; import java.awt.image.DataBuffer; +import java.io.Closeable; -public class FrameBuffer extends DataBuffer { +public class FrameBuffer extends DataBuffer implements Closeable { public static final int DEFAULT_DUMMY_WIDTH = 320; public static final int DEFAULT_DUMMY_HEIGHT = 240; public static final int DEFAULT_COLOR_DEPTH = 24; diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedImage.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedImage.java index 7d7feb9..2e2295a 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedImage.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedImage.java @@ -2,10 +2,11 @@ import java.awt.image.BufferedImage; import java.awt.image.ColorModel; +import java.io.Closeable; import org.tw.pi.framebuffer.FrameBuffers.ColorEndian; -public class FrameBufferedImage extends BufferedImage { +public class FrameBufferedImage extends BufferedImage implements Closeable { private FrameBuffer fb; public FrameBufferedImage(String fbdev) { diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedRaster.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedRaster.java index 44159fe..350b6ee 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedRaster.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedRaster.java @@ -3,10 +3,11 @@ import java.awt.Point; import java.awt.image.SampleModel; import java.awt.image.WritableRaster; +import java.io.Closeable; import org.tw.pi.framebuffer.FrameBuffers.ColorEndian; -public class FrameBufferedRaster extends WritableRaster { +public class FrameBufferedRaster extends WritableRaster implements Closeable { private FrameBuffer fb; @@ -26,4 +27,9 @@ public FrameBufferedRaster(FrameBuffer fb, SampleModel sampleModel) { public FrameBuffer getFrameBuffer() { return fb; } + + @Override + public void close() { + fb.close(); + } } diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java index d30007c..f8f0c2e 100755 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java @@ -1,15 +1,8 @@ -/* - * This file is the JNI Java part of a Raspberry Pi FrameBuffer project. - * - * Created 2013 by Thomas Welsch (ttww@gmx.de). - * - * Do whatever you want to do with it :-) - * - **/ package org.tw.pi.framebuffer; import java.awt.color.ColorSpace; +import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.DataBuffer; import java.awt.image.DirectColorModel; @@ -19,12 +12,13 @@ import org.tw.pi.NarSystem; public abstract class FrameBuffers { - static final long DUMMY = -1; - static final long ERR_OPEN = 1; - static final long ERR_FIXED = 2; - static final long ERR_VARIABLE = 3; - static final long ERR_BITS = 4; - static final long ERR_MMAP = 5; + public static BufferedImage open(String fbdev) { + return open(ColorEndian.RGB, fbdev); + } + + public static BufferedImage open(ColorEndian ce, String fbdev) { + return new FrameBufferedImage(fbdev); + } public static enum ColorEndian { RGB(new int[]{ @@ -79,45 +73,35 @@ public int getComponentMask(int bpp, int component) { } public ColorModel createColorModel(int bpp) { - return FrameBuffers.createColorModel(this, bpp); + return new DirectColorModel( + ColorSpace.getInstance(ColorSpace.CS_sRGB), + bpp, + getComponentMask(bpp, ColorEndian.RED_COMPONENT), + getComponentMask(bpp, ColorEndian.GREEN_COMPONENT), + getComponentMask(bpp, ColorEndian.BLUE_COMPONENT), + 0x0, + false, + DataBuffer.TYPE_INT); } public SampleModel createSampleModel(int w, int h, int bpp) { - return FrameBuffers.createSampleModel(this, w, h, bpp); + return new SinglePixelPackedSampleModel( + DataBuffer.TYPE_INT, + w, + h, + new int[] { + getComponentMask(bpp, ColorEndian.RED_COMPONENT), + getComponentMask(bpp, ColorEndian.GREEN_COMPONENT), + getComponentMask(bpp, ColorEndian.BLUE_COMPONENT), + }); } } - public static ColorModel createColorModel(ColorEndian ce, int bpp) { - return new DirectColorModel( - ColorSpace.getInstance(ColorSpace.CS_sRGB), - bpp, - ce.getComponentMask(bpp, ColorEndian.RED_COMPONENT), - ce.getComponentMask(bpp, ColorEndian.GREEN_COMPONENT), - ce.getComponentMask(bpp, ColorEndian.BLUE_COMPONENT), - 0x0, - false, - DataBuffer.TYPE_INT); - } - - - public static SampleModel createSampleModel(ColorEndian ce, int w, int h, int bpp) { - return new SinglePixelPackedSampleModel( - DataBuffer.TYPE_INT, - w, - h, - new int[] { - ce.getComponentMask(bpp, ColorEndian.RED_COMPONENT), - ce.getComponentMask(bpp, ColorEndian.GREEN_COMPONENT), - ce.getComponentMask(bpp, ColorEndian.BLUE_COMPONENT), - }); - } - - public static FrameBufferedImage openImage(String fbdev) { - return new FrameBufferedImage(fbdev); - } - - public static FrameBufferedImage openImage(ColorEndian ce, String fbdev) { - return new FrameBufferedImage(ce, fbdev); - } + static final long DUMMY = -1; + static final long ERR_OPEN = 1; + static final long ERR_FIXED = 2; + static final long ERR_VARIABLE = 3; + static final long ERR_BITS = 4; + static final long ERR_MMAP = 5; static native long openDevice0(String fbdev); static native void closeDevice0(long ptr); diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferedImageTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferedImageTest.java index abbff89..762756b 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferedImageTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferedImageTest.java @@ -8,21 +8,33 @@ public class FrameBufferedImageTest { @Test public void testCompatibility16bpp() { + FrameBufferedRaster r = null; + FrameBuffer fb = null; ColorEndian ce = ColorEndian.RGB; - Assert.assertTrue(FrameBuffers.createColorModel(ce, 16).isCompatibleSampleModel(FrameBuffers.createSampleModel(ce, 1, 1, 16))); - Assert.assertTrue(FrameBuffers.createColorModel(ce, 16).isCompatibleRaster(new FrameBufferedRaster(ce, new FrameBuffer(1, 1, 16)))); + Assert.assertTrue(ce.createColorModel(16).isCompatibleSampleModel(ce.createSampleModel(1, 1, 16))); + Assert.assertTrue(ce.createColorModel(16).isCompatibleRaster(r = new FrameBufferedRaster(fb = new FrameBuffer(1, 1, 16)))); + r.close(); + fb.close(); ce = ColorEndian.BGR; - Assert.assertTrue(FrameBuffers.createColorModel(ce, 16).isCompatibleSampleModel(FrameBuffers.createSampleModel(ce, 1, 1, 16))); - Assert.assertTrue(FrameBuffers.createColorModel(ce, 16).isCompatibleRaster(new FrameBufferedRaster(ce, new FrameBuffer(1, 1, 16)))); + Assert.assertTrue(ce.createColorModel(16).isCompatibleSampleModel(ce.createSampleModel(1, 1, 16))); + Assert.assertTrue(ce.createColorModel(16).isCompatibleRaster(r = new FrameBufferedRaster(fb = new FrameBuffer(1, 1, 16)))); + r.close(); + fb.close(); } @Test public void testCompatibility24bpp() { + FrameBufferedRaster r = null; + FrameBuffer fb = null; ColorEndian ce = ColorEndian.RGB; - Assert.assertTrue(FrameBuffers.createColorModel(ce, 24).isCompatibleSampleModel(FrameBuffers.createSampleModel(ce, 1, 1, 24))); - Assert.assertTrue(FrameBuffers.createColorModel(ce, 24).isCompatibleRaster(new FrameBufferedRaster(ce, new FrameBuffer(1, 1, 24)))); + Assert.assertTrue(ce.createColorModel(24).isCompatibleSampleModel(ce.createSampleModel(1, 1, 24))); + Assert.assertTrue(ce.createColorModel(24).isCompatibleRaster(r = new FrameBufferedRaster(fb = new FrameBuffer(1, 1, 24)))); + r.close(); + fb.close(); ce = ColorEndian.BGR; - Assert.assertTrue(FrameBuffers.createColorModel(ce, 24).isCompatibleSampleModel(FrameBuffers.createSampleModel(ce, 1, 1, 24))); - Assert.assertTrue(FrameBuffers.createColorModel(ce, 24).isCompatibleRaster(new FrameBufferedRaster(ce, new FrameBuffer(1, 1, 24)))); + Assert.assertTrue(ce.createColorModel(24).isCompatibleSampleModel(ce.createSampleModel(1, 1, 24))); + Assert.assertTrue(ce.createColorModel(24).isCompatibleRaster(r = new FrameBufferedRaster(fb = new FrameBuffer(1, 1, 24)))); + r.close(); + fb.close(); } } From 44d807b9a2d39ac782905685b29153ff3490535e Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 22:54:01 -0500 Subject: [PATCH 40/77] fix tests --- .../org/tw/pi/framebuffer/FrameBufferedImageTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferedImageTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferedImageTest.java index 762756b..ad2fb6a 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferedImageTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferedImageTest.java @@ -12,12 +12,12 @@ public void testCompatibility16bpp() { FrameBuffer fb = null; ColorEndian ce = ColorEndian.RGB; Assert.assertTrue(ce.createColorModel(16).isCompatibleSampleModel(ce.createSampleModel(1, 1, 16))); - Assert.assertTrue(ce.createColorModel(16).isCompatibleRaster(r = new FrameBufferedRaster(fb = new FrameBuffer(1, 1, 16)))); + Assert.assertTrue(ce.createColorModel(16).isCompatibleRaster(r = new FrameBufferedRaster(ce, fb = new FrameBuffer(1, 1, 16)))); r.close(); fb.close(); ce = ColorEndian.BGR; Assert.assertTrue(ce.createColorModel(16).isCompatibleSampleModel(ce.createSampleModel(1, 1, 16))); - Assert.assertTrue(ce.createColorModel(16).isCompatibleRaster(r = new FrameBufferedRaster(fb = new FrameBuffer(1, 1, 16)))); + Assert.assertTrue(ce.createColorModel(16).isCompatibleRaster(r = new FrameBufferedRaster(ce, fb = new FrameBuffer(1, 1, 16)))); r.close(); fb.close(); } @@ -28,12 +28,12 @@ public void testCompatibility24bpp() { FrameBuffer fb = null; ColorEndian ce = ColorEndian.RGB; Assert.assertTrue(ce.createColorModel(24).isCompatibleSampleModel(ce.createSampleModel(1, 1, 24))); - Assert.assertTrue(ce.createColorModel(24).isCompatibleRaster(r = new FrameBufferedRaster(fb = new FrameBuffer(1, 1, 24)))); + Assert.assertTrue(ce.createColorModel(24).isCompatibleRaster(r = new FrameBufferedRaster(ce, fb = new FrameBuffer(1, 1, 24)))); r.close(); fb.close(); ce = ColorEndian.BGR; Assert.assertTrue(ce.createColorModel(24).isCompatibleSampleModel(ce.createSampleModel(1, 1, 24))); - Assert.assertTrue(ce.createColorModel(24).isCompatibleRaster(r = new FrameBufferedRaster(fb = new FrameBuffer(1, 1, 24)))); + Assert.assertTrue(ce.createColorModel(24).isCompatibleRaster(r = new FrameBufferedRaster(ce, fb = new FrameBuffer(1, 1, 24)))); r.close(); fb.close(); } From ba88d2640935664a1cdc972ccd59dc29a3f8e16e Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 22:56:45 -0500 Subject: [PATCH 41/77] Move ColorEndian enum to its own file --- .../org/tw/pi/framebuffer/ColorEndian.java | 84 +++++++++++++++++++ .../tw/pi/framebuffer/FrameBufferedImage.java | 2 - .../pi/framebuffer/FrameBufferedRaster.java | 2 - .../org/tw/pi/framebuffer/FrameBuffers.java | 82 ------------------ .../framebuffer/FrameBufferedImageTest.java | 1 - 5 files changed, 84 insertions(+), 87 deletions(-) create mode 100644 framebuffer/src/main/java/org/tw/pi/framebuffer/ColorEndian.java diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/ColorEndian.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/ColorEndian.java new file mode 100644 index 0000000..ec60355 --- /dev/null +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/ColorEndian.java @@ -0,0 +1,84 @@ +package org.tw.pi.framebuffer; + +import java.awt.color.ColorSpace; +import java.awt.image.ColorModel; +import java.awt.image.DataBuffer; +import java.awt.image.DirectColorModel; +import java.awt.image.SampleModel; +import java.awt.image.SinglePixelPackedSampleModel; + +public enum ColorEndian { + RGB(new int[]{ + 0x000000e0, + 0x0000001c, + 0x00000003, + }, new int[]{ + 0x0000f800, + 0x000007e0, + 0x0000001f, + }, new int[] { + 0x00ff0000, + 0x0000ff00, + 0x000000ff, + }), + BGR(new int[]{ + 0x00000003, + 0x0000001c, + 0x000000e0, + }, new int[]{ + 0x0000001f, + 0x000007e0, + 0x0000f800, + }, new int[] { + 0x000000ff, + 0x0000ff00, + 0x00ff0000, + }), + ; + + public static final int RED_COMPONENT = 0; + public static final int GREEN_COMPONENT = 1; + public static final int BLUE_COMPONENT = 2; + + private int[] mask8; + private int[] mask16; + private int[] mask24; + + private ColorEndian(int[] mask8, int[] mask16, int[] mask24) { + this.mask8 = mask8; + this.mask16 = mask16; + this.mask24 = mask24; + } + + public int getComponentMask(int bpp, int component) { + switch(bpp) { + case 8: return mask8[component]; + case 16: return mask16[component]; + case 24: return mask24[component]; + } + throw new IllegalArgumentException("Invalid color depth for " + this + ": " + bpp); + } + + public ColorModel createColorModel(int bpp) { + return new DirectColorModel( + ColorSpace.getInstance(ColorSpace.CS_sRGB), + bpp, + getComponentMask(bpp, ColorEndian.RED_COMPONENT), + getComponentMask(bpp, ColorEndian.GREEN_COMPONENT), + getComponentMask(bpp, ColorEndian.BLUE_COMPONENT), + 0x0, + false, + DataBuffer.TYPE_INT); + } + public SampleModel createSampleModel(int w, int h, int bpp) { + return new SinglePixelPackedSampleModel( + DataBuffer.TYPE_INT, + w, + h, + new int[] { + getComponentMask(bpp, ColorEndian.RED_COMPONENT), + getComponentMask(bpp, ColorEndian.GREEN_COMPONENT), + getComponentMask(bpp, ColorEndian.BLUE_COMPONENT), + }); + } +} \ No newline at end of file diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedImage.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedImage.java index 2e2295a..1a40ead 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedImage.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedImage.java @@ -4,8 +4,6 @@ import java.awt.image.ColorModel; import java.io.Closeable; -import org.tw.pi.framebuffer.FrameBuffers.ColorEndian; - public class FrameBufferedImage extends BufferedImage implements Closeable { private FrameBuffer fb; diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedRaster.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedRaster.java index 350b6ee..fb63a63 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedRaster.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedRaster.java @@ -5,8 +5,6 @@ import java.awt.image.WritableRaster; import java.io.Closeable; -import org.tw.pi.framebuffer.FrameBuffers.ColorEndian; - public class FrameBufferedRaster extends WritableRaster implements Closeable { private FrameBuffer fb; diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java index f8f0c2e..ea06c17 100755 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java @@ -1,13 +1,7 @@ package org.tw.pi.framebuffer; -import java.awt.color.ColorSpace; import java.awt.image.BufferedImage; -import java.awt.image.ColorModel; -import java.awt.image.DataBuffer; -import java.awt.image.DirectColorModel; -import java.awt.image.SampleModel; -import java.awt.image.SinglePixelPackedSampleModel; import org.tw.pi.NarSystem; @@ -20,82 +14,6 @@ public static BufferedImage open(ColorEndian ce, String fbdev) { return new FrameBufferedImage(fbdev); } - public static enum ColorEndian { - RGB(new int[]{ - 0x000000e0, - 0x0000001c, - 0x00000003, - }, new int[]{ - 0x0000f800, - 0x000007e0, - 0x0000001f, - }, new int[] { - 0x00ff0000, - 0x0000ff00, - 0x000000ff, - }), - BGR(new int[]{ - 0x00000003, - 0x0000001c, - 0x000000e0, - }, new int[]{ - 0x0000001f, - 0x000007e0, - 0x0000f800, - }, new int[] { - 0x000000ff, - 0x0000ff00, - 0x00ff0000, - }), - ; - - public static final int RED_COMPONENT = 0; - public static final int GREEN_COMPONENT = 1; - public static final int BLUE_COMPONENT = 2; - - private int[] mask8; - private int[] mask16; - private int[] mask24; - - private ColorEndian(int[] mask8, int[] mask16, int[] mask24) { - this.mask8 = mask8; - this.mask16 = mask16; - this.mask24 = mask24; - } - - public int getComponentMask(int bpp, int component) { - switch(bpp) { - case 8: return mask8[component]; - case 16: return mask16[component]; - case 24: return mask24[component]; - } - throw new IllegalArgumentException("Invalid color depth for " + this + ": " + bpp); - } - - public ColorModel createColorModel(int bpp) { - return new DirectColorModel( - ColorSpace.getInstance(ColorSpace.CS_sRGB), - bpp, - getComponentMask(bpp, ColorEndian.RED_COMPONENT), - getComponentMask(bpp, ColorEndian.GREEN_COMPONENT), - getComponentMask(bpp, ColorEndian.BLUE_COMPONENT), - 0x0, - false, - DataBuffer.TYPE_INT); - } - public SampleModel createSampleModel(int w, int h, int bpp) { - return new SinglePixelPackedSampleModel( - DataBuffer.TYPE_INT, - w, - h, - new int[] { - getComponentMask(bpp, ColorEndian.RED_COMPONENT), - getComponentMask(bpp, ColorEndian.GREEN_COMPONENT), - getComponentMask(bpp, ColorEndian.BLUE_COMPONENT), - }); - } - } - static final long DUMMY = -1; static final long ERR_OPEN = 1; static final long ERR_FIXED = 2; diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferedImageTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferedImageTest.java index ad2fb6a..487ff20 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferedImageTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferedImageTest.java @@ -2,7 +2,6 @@ import org.junit.Assert; import org.junit.Test; -import org.tw.pi.framebuffer.FrameBuffers.ColorEndian; public class FrameBufferedImageTest { From 80525fc4fb8f5a3d3e971848a58ea8a1896246c7 Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 22:57:57 -0500 Subject: [PATCH 42/77] tweak exception --- .../src/main/java/org/tw/pi/framebuffer/FrameBuffers.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java index ea06c17..8ceb5c8 100755 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java @@ -43,7 +43,7 @@ static long openDevice(String fbdev) { if(ptr == FrameBuffers.ERR_VARIABLE) throw new RuntimeException("Error reading variable screen info for: " + fbdev); if(ptr == FrameBuffers.ERR_BITS) - throw new RuntimeException("Invalid color depth (" + FrameBuffers.getDeviceBitsPerPixel0(ptr) + "), 16 and 24 supported, for: " + fbdev); + throw new RuntimeException("Invalid color depth (" + FrameBuffers.getDeviceBitsPerPixel0(ptr) + "); 8, 16, and 24 supported; for: " + fbdev); if(ptr == FrameBuffers.ERR_MMAP) throw new RuntimeException("Unable to mmap for: " + fbdev); From 64d2ccfd920e18da2d2bc1cd6551587f65b8bebc Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 23:00:29 -0500 Subject: [PATCH 43/77] Throw IOException instead of RuntimeException for bad fbdev --- .../java/org/tw/pi/framebuffer/FrameBuffer.java | 3 ++- .../tw/pi/framebuffer/FrameBufferedImage.java | 5 +++-- .../org/tw/pi/framebuffer/FrameBuffers.java | 17 +++++++++-------- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java index 47f9277..adf3e54 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java @@ -2,6 +2,7 @@ import java.awt.image.DataBuffer; import java.io.Closeable; +import java.io.IOException; public class FrameBuffer extends DataBuffer implements Closeable { public static final int DEFAULT_DUMMY_WIDTH = 320; @@ -21,7 +22,7 @@ public FrameBuffer() { this(FrameBuffers.DUMMY); } - public FrameBuffer(String fbdev) { + public FrameBuffer(String fbdev) throws IOException { this(FrameBuffers.openDevice(fbdev)); } diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedImage.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedImage.java index 1a40ead..01f688a 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedImage.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedImage.java @@ -3,15 +3,16 @@ import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.io.Closeable; +import java.io.IOException; public class FrameBufferedImage extends BufferedImage implements Closeable { private FrameBuffer fb; - public FrameBufferedImage(String fbdev) { + public FrameBufferedImage(String fbdev) throws IOException { this(new FrameBuffer(fbdev)); } - public FrameBufferedImage(ColorEndian ce, String fbdev) { + public FrameBufferedImage(ColorEndian ce, String fbdev) throws IOException { this(ce, new FrameBuffer(fbdev)); } diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java index 8ceb5c8..a6bee3d 100755 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java @@ -2,15 +2,16 @@ package org.tw.pi.framebuffer; import java.awt.image.BufferedImage; +import java.io.IOException; import org.tw.pi.NarSystem; public abstract class FrameBuffers { - public static BufferedImage open(String fbdev) { + public static BufferedImage open(String fbdev) throws IOException { return open(ColorEndian.RGB, fbdev); } - public static BufferedImage open(ColorEndian ce, String fbdev) { + public static BufferedImage open(ColorEndian ce, String fbdev) throws IOException { return new FrameBufferedImage(fbdev); } @@ -31,21 +32,21 @@ public static BufferedImage open(ColorEndian ce, String fbdev) { static native void writeRGB0(long ptr, int idx, int rgb); static native int readRGB0(long ptr, int idx); - static long openDevice(String fbdev) { + static long openDevice(String fbdev) throws IOException { long ptr = FrameBuffers.openDevice0(fbdev); if(ptr == FrameBuffers.DUMMY) return FrameBuffers.DUMMY; if(ptr == FrameBuffers.ERR_OPEN) - throw new RuntimeException("Unable to open framebuffer device: " + fbdev); + throw new IOException("Unable to open framebuffer device: " + fbdev); if(ptr == FrameBuffers.ERR_FIXED) - throw new RuntimeException("Error reading fixed screen info for: " + fbdev); + throw new IOException("Error reading fixed screen info for: " + fbdev); if(ptr == FrameBuffers.ERR_VARIABLE) - throw new RuntimeException("Error reading variable screen info for: " + fbdev); + throw new IOException("Error reading variable screen info for: " + fbdev); if(ptr == FrameBuffers.ERR_BITS) - throw new RuntimeException("Invalid color depth (" + FrameBuffers.getDeviceBitsPerPixel0(ptr) + "); 8, 16, and 24 supported; for: " + fbdev); + throw new IOException("Invalid color depth (" + FrameBuffers.getDeviceBitsPerPixel0(ptr) + "); 8, 16, and 24 supported; for: " + fbdev); if(ptr == FrameBuffers.ERR_MMAP) - throw new RuntimeException("Unable to mmap for: " + fbdev); + throw new IOException("Unable to mmap for: " + fbdev); return ptr; } From aae8f0d83ebbdd05deb6fb132710da8481809bbb Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 23:11:29 -0500 Subject: [PATCH 44/77] Strip some obsolete comments, rename struct --- framebuffer/src/main/c/FrameBuffers.c | 51 ++++++++------------------- 1 file changed, 15 insertions(+), 36 deletions(-) diff --git a/framebuffer/src/main/c/FrameBuffers.c b/framebuffer/src/main/c/FrameBuffers.c index 757a667..f26182f 100755 --- a/framebuffer/src/main/c/FrameBuffers.c +++ b/framebuffer/src/main/c/FrameBuffers.c @@ -1,16 +1,3 @@ -/* - * This file is the JNI C part of a Raspberry Pi FrameBuffer project. - * - * Created 2013 by Thomas Welsch (ttww@gmx.de). - * - * Do whatever you want to do with it :-) - * - * This code transfers an Java BufferedImage ARGB data array to a FrameBuffer device - * (e.g. SPI-Displays like http://www.sainsmart.com/blog/ada/). - * - * For testing purpose a previous device is supported (via the devicename "dummy_160x128" instead of "/dev/fb1"). - * - **/ #include #include @@ -29,17 +16,17 @@ #include "org_tw_pi_framebuffer_FrameBuffers.h" -struct deviceInfo { - char *deviceName; // Device-Name from Java ("/dev/fb1" or "dummy_240x180")... - int fbfd; // File descriptor, 0 for previous devices +static struct FrameBufferData { + char *deviceName; + int fbfd; int width; int height; - int bpp; // BitsPerPixel, 0 for previous devices + int bpp; - long int screensize; // Buffer size in bytes + long int screensize; - char *fbp; // MemoryMapped buffer + char *fbp; }; JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_openDevice0( @@ -47,7 +34,7 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_openDevice0( jboolean isCopy; - struct deviceInfo *di; + struct FrameBufferData *di; #ifndef __linux return org_tw_pi_framebuffer_FrameBuffers_DUMMY; @@ -67,15 +54,12 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_openDevice0( di->fbfd = open(di->deviceName, O_RDWR); if (!di->fbfd) { - // printf("Error: cannot open framebuffer device. %s\n", di->deviceName); free(di->deviceName); return org_tw_pi_framebuffer_FrameBuffers_ERR_OPEN; } - // printf("The framebuffer device %s was opened successfully.\n", di->deviceName); // Get fixed screen information if (ioctl(di->fbfd, FBIOGET_FSCREENINFO, &finfo)) { - // printf("Error reading fixed information.\n"); close(di->fbfd); free(di->deviceName); return org_tw_pi_framebuffer_FrameBuffers_ERR_FIXED; @@ -83,7 +67,6 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_openDevice0( // Get variable screen information if (ioctl(di->fbfd, FBIOGET_VSCREENINFO, &vinfo)) { - // printf("Error reading variable information.\n"); close(di->fbfd); free(di->deviceName); return org_tw_pi_framebuffer_FrameBuffers_ERR_VARIABLE; @@ -99,16 +82,12 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_openDevice0( return org_tw_pi_framebuffer_FrameBuffers_ERR_BITS; } - // printf("%dx%d, %d bpp %ld bytes\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel, (long) finfo.smem_len); - // map framebuffer to user memory di->screensize = finfo.smem_len; - di->fbp = (char*) mmap(0, di->screensize, PROT_READ | PROT_WRITE, - MAP_SHARED, di->fbfd, 0); + di->fbp = (char*) mmap(0, di->screensize, PROT_READ | PROT_WRITE, MAP_SHARED, di->fbfd, 0); if ((int) di->fbp == -1) { - // printf("Failed to mmap.\n"); close(di->fbfd); free(di->deviceName); return org_tw_pi_framebuffer_FrameBuffers_ERR_MMAP; @@ -121,7 +100,7 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_openDevice0( JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_closeDevice0( JNIEnv *env, jobject obj, jlong jdi) { - struct deviceInfo *di = (struct deviceInfo *) (intptr_t) jdi; + struct FrameBufferData *di = (struct FrameBufferData *) (intptr_t) jdi; free(di->deviceName); @@ -130,13 +109,13 @@ JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_closeDevice0( close(di->fbfd); } - memset(di, 0, sizeof(*di)); // :-) + memset(di, 0, sizeof(*di)); } JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_getDeviceWidth0( JNIEnv *env, jobject obj, jlong jdi) { - struct deviceInfo *di = (struct deviceInfo *) (intptr_t) jdi; + struct FrameBufferData *di = (struct FrameBufferData *) (intptr_t) jdi; return di->width; } @@ -144,7 +123,7 @@ JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_getDeviceWidth0( JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_getDeviceHeight0( JNIEnv *env, jobject obj, jlong jdi) { - struct deviceInfo *di = (struct deviceInfo *) (intptr_t) jdi; + struct FrameBufferData *di = (struct FrameBufferData *) (intptr_t) jdi; return di->height; } @@ -152,14 +131,14 @@ JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_getDeviceHeight0( JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_getDeviceBitsPerPixel0( JNIEnv *env, jobject obj, jlong jdi) { - struct deviceInfo *di = (struct deviceInfo *) (intptr_t) jdi; + struct FrameBufferData *di = (struct FrameBufferData *) (intptr_t) jdi; return di->bpp; } JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_writeRGB0 (JNIEnv *env, jclass clazz, jlong ptr, jint idx, jint rgb) { - struct deviceInfo *di = (struct deviceInfo *) (intptr_t) ptr; + struct FrameBufferData *di = (struct FrameBufferData *) (intptr_t) ptr; unsigned char *p = (unsigned char *) di->fbp; unsigned int width; @@ -184,7 +163,7 @@ JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_writeRGB0 JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_readRGB0 (JNIEnv *env, jclass clazz, jlong ptr, jint idx) { - struct deviceInfo *di = (struct deviceInfo *) (intptr_t) ptr; + struct FrameBufferData *di = (struct FrameBufferData *) (intptr_t) ptr; unsigned char *p = (unsigned char *) di->fbp; unsigned int width; From afa73e40bed5ebab3dd39f8105b9e6899abeeeee Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 23:30:15 -0500 Subject: [PATCH 45/77] Make instance vars final --- .../src/main/java/org/tw/pi/framebuffer/FrameBufferedImage.java | 2 +- .../main/java/org/tw/pi/framebuffer/FrameBufferedRaster.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedImage.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedImage.java index 01f688a..441e30b 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedImage.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedImage.java @@ -6,7 +6,7 @@ import java.io.IOException; public class FrameBufferedImage extends BufferedImage implements Closeable { - private FrameBuffer fb; + final private FrameBuffer fb; public FrameBufferedImage(String fbdev) throws IOException { this(new FrameBuffer(fbdev)); diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedRaster.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedRaster.java index fb63a63..fd33fdc 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedRaster.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedRaster.java @@ -7,7 +7,7 @@ public class FrameBufferedRaster extends WritableRaster implements Closeable { - private FrameBuffer fb; + final private FrameBuffer fb; public FrameBufferedRaster(FrameBuffer fb) { this(ColorEndian.RGB, fb); From 44a2065e46e6d3b359005311b59719b6e1b24294 Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Nov 2015 23:33:24 -0500 Subject: [PATCH 46/77] Promote to 0.1.0-SNAPSHOT --- framebuffer-parent/pom.xml | 2 +- framebuffer-shaded/pom.xml | 4 ++-- framebuffer/pom.xml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/framebuffer-parent/pom.xml b/framebuffer-parent/pom.xml index 5b12c50..1dd318f 100644 --- a/framebuffer-parent/pom.xml +++ b/framebuffer-parent/pom.xml @@ -2,7 +2,7 @@ 4.0.0 org.tw.pi framebuffer-parent - 0.0.1-esialb-SNAPSHOT + 0.1.0-SNAPSHOT pom ../framebuffer diff --git a/framebuffer-shaded/pom.xml b/framebuffer-shaded/pom.xml index 63db5bd..9b7fd72 100644 --- a/framebuffer-shaded/pom.xml +++ b/framebuffer-shaded/pom.xml @@ -5,14 +5,14 @@ org.tw.pi framebuffer-parent - 0.0.1-esialb-SNAPSHOT + 0.1.0-SNAPSHOT ../framebuffer-parent org.tw.pi framebuffer - 0.0.1-esialb-SNAPSHOT + 0.1.0-SNAPSHOT nar diff --git a/framebuffer/pom.xml b/framebuffer/pom.xml index 0932d1d..883dbdf 100644 --- a/framebuffer/pom.xml +++ b/framebuffer/pom.xml @@ -57,7 +57,7 @@ org.tw.pi framebuffer-parent - 0.0.1-esialb-SNAPSHOT + 0.1.0-SNAPSHOT ../framebuffer-parent \ No newline at end of file From 9037d5582338ea2d196cbe4ebbbfee9163643991 Mon Sep 17 00:00:00 2001 From: robin Date: Wed, 25 Nov 2015 06:07:56 -0500 Subject: [PATCH 47/77] Extensive javadoc --- framebuffer/src/main/c/FrameBuffers.c | 47 ++++++- .../org/tw/pi/framebuffer/ColorEndian.java | 63 +++++++++- .../org/tw/pi/framebuffer/FrameBuffer.java | 115 +++++++++++++++++- .../tw/pi/framebuffer/FrameBufferedImage.java | 47 ++++++- .../pi/framebuffer/FrameBufferedRaster.java | 31 ++++- .../org/tw/pi/framebuffer/FrameBuffers.java | 115 +++++++++++++++++- .../org/tw/pi/framebuffer/package-info.java | 14 +++ 7 files changed, 416 insertions(+), 16 deletions(-) create mode 100644 framebuffer/src/main/java/org/tw/pi/framebuffer/package-info.java diff --git a/framebuffer/src/main/c/FrameBuffers.c b/framebuffer/src/main/c/FrameBuffers.c index f26182f..33072be 100755 --- a/framebuffer/src/main/c/FrameBuffers.c +++ b/framebuffer/src/main/c/FrameBuffers.c @@ -16,19 +16,45 @@ #include "org_tw_pi_framebuffer_FrameBuffers.h" +/* + * struct to keep track of an open linux framebuffer + */ static struct FrameBufferData { + /* + * The path to the framebuffer, such as /dev/fb1 + */ char *deviceName; + + /* + * file descriptor for the framebuffer + */ int fbfd; + /* + * Width of the framebuffer + */ int width; + /* + * Height of the framebuffer + */ int height; + /* + * Color depth of the framebuffer + */ int bpp; + /* + * Size of the memory-mapped framebuffer device + */ long int screensize; char *fbp; }; +/* + * Open a linux framebuffer, returning a pointer to struct FrameBufferData, + * or an error code defined in FrameBuffers.java + */ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_openDevice0( JNIEnv *env, jobject obj, jstring device) { @@ -37,7 +63,8 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_openDevice0( struct FrameBufferData *di; #ifndef __linux - return org_tw_pi_framebuffer_FrameBuffers_DUMMY; + // not supported on not linux + return org_tw_pi_framebuffer_FrameBuffers_ERR_NOT_SUPPORTED; #else di = malloc(sizeof(*di)); @@ -97,6 +124,9 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_openDevice0( #endif } +/* + * Close a framebuffer tracked by a pointer to struct FrameBufferData + */ JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_closeDevice0( JNIEnv *env, jobject obj, jlong jdi) { @@ -112,6 +142,9 @@ JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_closeDevice0( memset(di, 0, sizeof(*di)); } +/* + * Return the tracked framebuffer width by a pointer to struct FrameBufferData + */ JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_getDeviceWidth0( JNIEnv *env, jobject obj, jlong jdi) { @@ -120,6 +153,9 @@ JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_getDeviceWidth0( return di->width; } +/* + * Return the tracked framebuffer height by a pointer to struct FrameBufferData + */ JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_getDeviceHeight0( JNIEnv *env, jobject obj, jlong jdi) { @@ -128,6 +164,9 @@ JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_getDeviceHeight0( return di->height; } +/* + * Return the tracked framebuffer color depth by a pointer to struct FrameBufferData + */ JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_getDeviceBitsPerPixel0( JNIEnv *env, jobject obj, jlong jdi) { @@ -136,6 +175,9 @@ JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_getDeviceBitsPerP return di->bpp; } +/* + * Write a pixel to a framebuffer + */ JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_writeRGB0 (JNIEnv *env, jclass clazz, jlong ptr, jint idx, jint rgb) { struct FrameBufferData *di = (struct FrameBufferData *) (intptr_t) ptr; @@ -161,6 +203,9 @@ JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_writeRGB0 } } +/* + * Read a pixel from a framebuffer + */ JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_readRGB0 (JNIEnv *env, jclass clazz, jlong ptr, jint idx) { struct FrameBufferData *di = (struct FrameBufferData *) (intptr_t) ptr; diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/ColorEndian.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/ColorEndian.java index ec60355..bc334a0 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/ColorEndian.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/ColorEndian.java @@ -7,7 +7,17 @@ import java.awt.image.SampleModel; import java.awt.image.SinglePixelPackedSampleModel; +/** + * Utility enum useful as an argument to select between RGB and BGR framebuffers.

+ * + * Not sure if BGR framebuffers exist, but oh well. + * @author Robin Kirkman + * + */ public enum ColorEndian { + /** + * Color is represented as R, G, B, in ascending address order + */ RGB(new int[]{ 0x000000e0, 0x0000001c, @@ -21,6 +31,9 @@ public enum ColorEndian { 0x0000ff00, 0x000000ff, }), + /** + * Color is represented as B, G, R, in ascending address order + */ BGR(new int[]{ 0x00000003, 0x0000001c, @@ -36,12 +49,30 @@ public enum ColorEndian { }), ; - public static final int RED_COMPONENT = 0; - public static final int GREEN_COMPONENT = 1; - public static final int BLUE_COMPONENT = 2; + /** + * The red component offset in a bitmask array + */ + private static final int RED_COMPONENT = 0; + /** + * The green component offset in a bitmask array + */ + private static final int GREEN_COMPONENT = 1; + /** + * The blue component offset in a bitmask array + */ + private static final int BLUE_COMPONENT = 2; + /** + * 8-bit color bitmasks for red, green, blue + */ private int[] mask8; + /** + * 16-bit color bitmasks for red, green, blue + */ private int[] mask16; + /** + * 24-bit color bitmasks for red, green, blue + */ private int[] mask24; private ColorEndian(int[] mask8, int[] mask16, int[] mask24) { @@ -50,7 +81,16 @@ private ColorEndian(int[] mask8, int[] mask16, int[] mask24) { this.mask24 = mask24; } - public int getComponentMask(int bpp, int component) { + /** + * Get the bitmask for a component at a particular color depth + * @param bpp The color depth: {@code 8}, {@code 16}, or {@code 24} + * @param component The color component offset + * @return The bitmask for that color at that color depth + * @see #RED_COMPONENT + * @see #GREEN_COMPONENT + * @see #BLUE_COMPONENT + */ + private int getComponentMask(int bpp, int component) { switch(bpp) { case 8: return mask8[component]; case 16: return mask16[component]; @@ -59,6 +99,12 @@ public int getComponentMask(int bpp, int component) { throw new IllegalArgumentException("Invalid color depth for " + this + ": " + bpp); } + /** + * Create and return a new {@link ColorModel} appropriate for use in a {@link FrameBufferedImage} + * at the argument color depth + * @param bpp The color depth: {@code 8}, {@code 16}, or {@code 24} + * @return A new {@link ColorModel} + */ public ColorModel createColorModel(int bpp) { return new DirectColorModel( ColorSpace.getInstance(ColorSpace.CS_sRGB), @@ -70,6 +116,15 @@ public ColorModel createColorModel(int bpp) { false, DataBuffer.TYPE_INT); } + + /** + * Create and return a new {@link SampleModel} appropriate for use in a {@link FrameBufferedImage} + * with the argument width, height, and color depth + * @param w The width + * @param h The height + * @param bpp The color depth: {@code 8}, {@code 16}, or {@code 24} + * @return A new {@link SampleModel} + */ public SampleModel createSampleModel(int w, int h, int bpp) { return new SinglePixelPackedSampleModel( DataBuffer.TYPE_INT, diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java index adf3e54..a1759bd 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffer.java @@ -4,36 +4,102 @@ import java.io.Closeable; import java.io.IOException; +/** + * {@link DataBuffer} for use in a {@link FrameBufferedImage} that is usually + * backed by a linux framebuffer device. May also be instantiated using a + * "dummy" framebuffer, just an array of ints. + * @author Robin Kirkman + * + */ public class FrameBuffer extends DataBuffer implements Closeable { + /** + * Default width of a dummy framebuffer + */ public static final int DEFAULT_DUMMY_WIDTH = 320; + /** + * Default height of a dummy framebuffer + */ public static final int DEFAULT_DUMMY_HEIGHT = 240; + /** + * Default color depth of a dummy framebuffer + */ public static final int DEFAULT_COLOR_DEPTH = 24; + /** + * Pointer to a {@code struct FrameBufferData} from the JNI layer. + */ private final long ptr; + /** + * Width of the frame buffer + */ private final int w; + /** + * Height of the frame buffer + */ private final int h; + /** + * Color depth of the frame buffer + */ private final int bpp; + /** + * {@code int} array used to hold data for a dummy buffer. is {@code null} if + * this {@link FrameBuffer} is backed by an actual framebuffer device. + */ private final int[] dummy; + /** + * Has this {@link FrameBuffer} been closed? + * @see #close() + */ private boolean closed; + /** + * Create a new dummy {@link FrameBuffer} with the default width, height, and color depth. + * @see #DEFAULT_DUMMY_WIDTH + * @see #DEFAULT_DUMMY_HEIGHT + * @see #DEFAULT_COLOR_DEPTH + */ public FrameBuffer() { this(FrameBuffers.DUMMY); } + /** + * Open a framebuffer with the argument device path, such as {@code "/dev/fb1"}. + * @param fbdev The path to the framebuffer device + * @throws IOException If the framebuffer could not be opened, such as on a non-linux system, + * or if the current user lacks sufficient privileges. + */ public FrameBuffer(String fbdev) throws IOException { this(FrameBuffers.openDevice(fbdev)); } + /** + * Create a new dummy {@link FrameBuffer} with the specified width, height, and color depth. + * @param w The width + * @param h The height + * @param bpp The color depth: {@code 8}, {@code 16}, or {@code 24} + */ public FrameBuffer(int w, int h, int bpp) { this(FrameBuffers.DUMMY, w, h, bpp); } + /** + * Create a new dummy {@link FrameBuffer} with the specified width and height, and + * a default color depth. + * @param w The width + * @param h The height + * @see #DEFAULT_COLOR_DEPTH + */ public FrameBuffer(int w, int h) { this(FrameBuffers.DUMMY, w, h, DEFAULT_COLOR_DEPTH); } + /** + * Create a {@link FrameBuffer} by wrapping a {@code struct FrameBufferData*} returned + * by {@link FrameBuffers#openDevice0(String)} + * @param ptr The pointer from the JNI, or {@link FrameBuffers#DUMMY} for a default dummy {@link FrameBuffer} + */ private FrameBuffer(long ptr) { this( ptr, @@ -42,8 +108,19 @@ private FrameBuffer(long ptr) { (ptr == FrameBuffers.DUMMY ? DEFAULT_COLOR_DEPTH : FrameBuffers.getDeviceBitsPerPixel0(ptr))); } + /** + * Create a {@link FrameBuffer} wrapping a {@code struct FrameBufferData*} returned + * by {@link FrameBuffers#openDevice0(String)}, with supplied width, height, and + * color depth. + * @param ptr The pointer from the JNI, or {@link FrameBuffers#DUMMY} for a dummy {@link FrameBuffer} + * @param w The width + * @param h The height + * @param bpp The color depth: {@code 8}, {@code 16}, or {@code 24} + */ private FrameBuffer(long ptr, int w, int h, int bpp) { super(DataBuffer.TYPE_INT, w * h); + if(!FrameBuffers.isValidColorDepth(bpp)) + throw new IllegalArgumentException("Illegal color depth: " + bpp); this.ptr = ptr; this.w = w; this.h = h; @@ -56,29 +133,47 @@ private FrameBuffer(long ptr, int w, int h, int bpp) { this.closed = false; } + /* + * (non-Javadoc) + * @see java.awt.image.DataBuffer#getElem(int, int) + * + * Return an int taken from the framebuffer device, or the dummy array for a dummy FrameBuffer + */ @Override public int getElem(int bank, int i) { - if(closed) + if(closed) // cannot get if closed throw new IllegalStateException(); int val; if(ptr == FrameBuffers.DUMMY) val = dummy[i]; else val = FrameBuffers.readRGB0(ptr, i); - return val & 0x00FFFFFF; + return val & 0x00FFFFFF; // ensure 24bit unsigned int } + /* + * (non-Javadoc) + * @see java.awt.image.DataBuffer#setElem(int, int, int) + * + * Set an int in the framebuffer device, or the dummy array for a dummy FrameBuffer + */ @Override public void setElem(int bank, int i, int val) { - val = val & 0x00FFFFFF; - if(closed) + if(closed) // cannot set if closed throw new IllegalStateException(); + val = val & 0x00FFFFFF; // ensure 24bit unsigned int if(ptr == FrameBuffers.DUMMY) dummy[i] = val; else FrameBuffers.writeRGB0(ptr, i, val); } + /** + * Close this {@link FrameBuffer}, releasing any JNI resources (such as file + * handles or memory maps) for a non-dummy {@link FrameBuffer}.

+ * + * Subsequent calls to {@link #close()} have no effect. + */ public void close() { if(!closed) { if(ptr != FrameBuffers.DUMMY) @@ -87,14 +182,26 @@ public void close() { } } + /** + * Returns the width of this {@link FrameBuffer} + * @return The width in pixels + */ public int getWidth() { return w; } + /** + * Returns the height of this {@link FrameBuffer} + * @return The height in pixels + */ public int getHeight() { return h; } + /** + * Returns the color depth of this {@link FrameBuffer} + * @return The color depth, in bits + */ public int getColorDepth() { return bpp; } diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedImage.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedImage.java index 441e30b..bc0b8c7 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedImage.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedImage.java @@ -5,30 +5,65 @@ import java.io.Closeable; import java.io.IOException; +/** + * {@link BufferedImage} whose data is backed by a {@link FrameBuffer}, itself + * either a dummy or backed by a linux framebuffer device. + * @author Robin Kirkman + * + */ public class FrameBufferedImage extends BufferedImage implements Closeable { + /** + * The {@link FrameBuffer} backing this {@link FrameBufferedImage} + */ final private FrameBuffer fb; + /** + * Create a new {@link FrameBufferedImage} by opening a linux framebuffer device + * @param fbdev The path to the framebuffer, such as {@code "/dev/fb1"} + * @throws IOException If the framebuffer could not be opened + */ public FrameBufferedImage(String fbdev) throws IOException { this(new FrameBuffer(fbdev)); } + /** + * Create a new {@link FrameBufferedImage} by opening a linux framebuffer device + * with a specified color endian-ness + * @param ce The color endian-ness: {@link ColorEndian#RGB} or {@link ColorEndian#BGR} + * @param fbdev The path to the framebuffer, such as {@code "/dev/fb1"} + * @throws IOException If the framebuffer could not be opened + */ public FrameBufferedImage(ColorEndian ce, String fbdev) throws IOException { this(ce, new FrameBuffer(fbdev)); } + /** + * Create a new {@link FrameBufferedImage} by wrapping an existing {@link FrameBuffer} + * @param fb The {@link FrameBuffer} to wrap + */ public FrameBufferedImage(FrameBuffer fb) { this(ColorEndian.RGB, fb); } + /** + * Create a new {@link FrameBufferedImage} by wrapping an existing {@link FrameBuffer} with a + * specified color endian-ness + * @param ce The color endian-ness: {@link ColorEndian#RGB} or {@link ColorEndian#BGR} + * @param fb The {@link FrameBuffer} to wrap + */ public FrameBufferedImage(ColorEndian ce, FrameBuffer fb) { this( - new FrameBufferedRaster( - fb, - ce.createSampleModel(fb.getWidth(), fb.getHeight(), fb.getColorDepth())), + new FrameBufferedRaster(ce, fb), ce.createColorModel(fb.getColorDepth())); } - public FrameBufferedImage(FrameBufferedRaster raster, ColorModel colorModel) { + /** + * Create a new {@link FrameBufferedImage} wrapping a {@link FrameBufferedRaster} + * and a {@link ColorModel} returned by {@link ColorEndian#createColorModel(int)} + * @param raster The {@link FrameBufferedRaster} to wrap + * @param colorModel The {@link ColorModel} to use + */ + private FrameBufferedImage(FrameBufferedRaster raster, ColorModel colorModel) { super(colorModel, raster, true, null); fb = raster.getFrameBuffer(); } @@ -37,6 +72,10 @@ public void close() { fb.close(); } + /** + * Returns the {@link FrameBuffer} backing this {@link FrameBufferedImage} + * @return + */ public FrameBuffer getFrameBuffer() { return fb; } diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedRaster.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedRaster.java index fd33fdc..cc094a8 100644 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedRaster.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBufferedRaster.java @@ -1,27 +1,56 @@ package org.tw.pi.framebuffer; import java.awt.Point; +import java.awt.image.DataBuffer; import java.awt.image.SampleModel; import java.awt.image.WritableRaster; import java.io.Closeable; +/** + * {@link WritableRaster} that uses a {@link FrameBuffer} as its {@link DataBuffer}. + * @author Robin Kirkman + * + */ public class FrameBufferedRaster extends WritableRaster implements Closeable { + /** + * The {@link FrameBuffer} backing this {@link FrameBufferedRaster} + */ final private FrameBuffer fb; + /** + * Create a new {@link FrameBufferedRaster} using RGB color endian-ness + * @param fb The {@link FrameBuffer} to use + * @see ColorEndian#RGB + */ public FrameBufferedRaster(FrameBuffer fb) { this(ColorEndian.RGB, fb); } + /** + * Create a new {@link FrameBufferedRaster} + * @param ce The {@link ColorEndian} to use: {@link ColorEndian#RGB} or {@link ColorEndian#BGR} + * @param fb The {@link FrameBuffer} to use + */ public FrameBufferedRaster(ColorEndian ce, FrameBuffer fb) { this(fb, ce.createSampleModel(fb.getWidth(), fb.getHeight(), fb.getColorDepth())); } - public FrameBufferedRaster(FrameBuffer fb, SampleModel sampleModel) { + /** + * Create a new {@link FrameBufferedRaster} using a {@link FrameBuffer} and + * a {@link SampleModel} returned by {@link ColorEndian#createSampleModel(int, int, int)} + * @param fb The {@link FrameBuffer} to use + * @param sampleModel The {@link SampleModel} to use + */ + private FrameBufferedRaster(FrameBuffer fb, SampleModel sampleModel) { super(sampleModel, fb, new Point(0,0)); this.fb = fb; } + /** + * Returns the {@link FrameBuffer} used by this {@link FrameBufferedRaster} + * @return The {@link FrameBuffer} + */ public FrameBuffer getFrameBuffer() { return fb; } diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java index a6bee3d..81a75df 100755 --- a/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/FrameBuffers.java @@ -6,37 +6,135 @@ import org.tw.pi.NarSystem; +/** + * Utilities and JNI used by {@link FrameBuffer}.

+ * + * Also has utility methods {@link #open(String)} and {@link #open(ColorEndian, String)} to + * return a new {@link BufferedImage} backed by a linux framebuffer. + * @author Robin Kirkman + * + */ public abstract class FrameBuffers { + /** + * Open a linux framebuffer device and return a new {@link BufferedImage} backed by it, + * using RGB color endian-ness + * @param fbdev The path to the framebuffer, such as {@code "/dev/fb1"} + * @return A new {@link BufferedImage} backed by the framebuffer + * @throws IOException If the linux framebuffer could not be opened + * @see ColorEndian#RGB + * @see FrameBufferedImage + */ public static BufferedImage open(String fbdev) throws IOException { return open(ColorEndian.RGB, fbdev); } + /** + * Open a linux framebuffer device and return a new {@link BufferedImage} backed by it, + * using a specified color endian-ness and framebuffer path + * @param ce The color endianness: {@link ColorEndian#RGB} or {@link ColorEndian#BGR} + * @param fbdev The path the the framebuffer, such as {@code "/dev/fb1"} + * @return A new {@link BufferedImage} backed by the framebuffer + * @throws IOException If the linux framebuffer could not be opened + * @see FrameBufferedImage + */ public static BufferedImage open(ColorEndian ce, String fbdev) throws IOException { return new FrameBufferedImage(fbdev); } + /** + * magic JNI struct pointer value to indicate a dummy {@link FrameBuffer} + */ static final long DUMMY = -1; + /** + * Returned by {@link #openDevice0(String)} on non-linux systems + */ + static final long ERR_NOT_SUPPORTED = 0; + /** + * Returned by {@link #openDevice0(String)} if the framebuffer could not be opened + */ static final long ERR_OPEN = 1; + /** + * Returned by {@link #openDevice0(String)} if the "fixed" framebuffer data could not be read + */ static final long ERR_FIXED = 2; + /** + * Returned by {@link #openDevice0(String)} if the "variable" framebuffer data could not be read + */ static final long ERR_VARIABLE = 3; + /** + * Returned by {@link #openDevice0(String)} if the framebuffer's color depth is not 8, 16, or 24 + */ static final long ERR_BITS = 4; + /** + * Returned by {@link #openDevice0(String)} if the framebuffer could not be memory mapped + */ static final long ERR_MMAP = 5; + /** + * Open a framebuffer by path and return a pointer of type {@code struct FrameBufferData*} + * @param fbdev The path to the framebuffer, such as {@code "/dev/fb1"} + * @return A JNI pointer, or one of the listed error codes. + * @see #ERR_NOT_SUPPORTED + * @see #ERR_OPEN + * @see #ERR_FIXED + * @see #ERR_VARIABLE + * @see #ERR_BITS + * @see #ERR_MMAP + */ static native long openDevice0(String fbdev); + + /** + * Close a framebuffer referenced by a pointer of type {@code struct FrameBufferData*}. + * Will probably crash the JVM if the pointer is invalid. + * @param ptr A valid JNI pointer returned by {@link #openDevice0(String)} + */ static native void closeDevice0(long ptr); + /** + * Returns the width of a framebuffer + * @param ptr A valid JNI pointer returned by {@link #openDevice0(String)} + * @return The width in pixels + */ static native int getDeviceWidth0(long ptr); + /** + * Returns the height of a framebuffer + * @param ptr A valid JNI pointer returned by {@link #openDevice0(String)} + * @return The height in pixels + */ static native int getDeviceHeight0(long ptr); + /** + * Returns the color depth of a framebuffer + * @param ptr A valid JNI pointer returned by {@link #openDevice0(String)} + * @return The native framebuffer's color depth + */ static native int getDeviceBitsPerPixel0(long ptr); + /** + * Write a pixel to a native framebuffer + * @param ptr A valid JNI pointer returned by {@link #openDevice0(String)} + * @param idx The pixel number; {@code idx == y * width + x} + * @param rgb The int representation of the new pixel color + */ static native void writeRGB0(long ptr, int idx, int rgb); + /** + * Read a pixel from a native framebuffer + * @param ptr A valid JNI pointer returned by {@link #openDevice0(String)} + * @param idx The pixel number; {@code idx == y * width + x} + * @return The int representation of the specified pixel color + */ static native int readRGB0(long ptr, int idx); + /** + * Try to open a linux framebuffer by path, throwing {@link IOException} if unable. + * @param fbdev The path to the framebuffer, such as {@code "/dev/fb1"} + * @return A valid JNI pointer returned by {@link #openDevice0(String)} + * @throws IOException If the framebuffer could not be opened + */ static long openDevice(String fbdev) throws IOException { long ptr = FrameBuffers.openDevice0(fbdev); - if(ptr == FrameBuffers.DUMMY) - return FrameBuffers.DUMMY; + if(ptr == FrameBuffers.ERR_NOT_SUPPORTED) + throw new IOException("Linux framebuffers are not supported on this computer"); if(ptr == FrameBuffers.ERR_OPEN) throw new IOException("Unable to open framebuffer device: " + fbdev); if(ptr == FrameBuffers.ERR_FIXED) @@ -50,11 +148,24 @@ static long openDevice(String fbdev) throws IOException { return ptr; } + + /** + * Return whether the argument is a valid color depth ({@code 8}, {@code 16}, or {@code 24}) + * @param bpp The color depth to test + * @return {@code true} if the color depth is valid, e.g. is one of {@code 8}, {@code 16}, or {@code 24} + */ + static boolean isValidColorDepth(int bpp) { + return bpp == 8 || bpp == 16 || bpp == 24; + } + /* + * Can't instantiate this class + */ private FrameBuffers() { } static { + // load the JNI NarSystem.loadLibrary(); } } diff --git a/framebuffer/src/main/java/org/tw/pi/framebuffer/package-info.java b/framebuffer/src/main/java/org/tw/pi/framebuffer/package-info.java new file mode 100644 index 0000000..78451d8 --- /dev/null +++ b/framebuffer/src/main/java/org/tw/pi/framebuffer/package-info.java @@ -0,0 +1,14 @@ +package org.tw.pi.framebuffer; +/** + * Java classes for accessing a linux framebuffer device as a {@link java.awt.image.BufferedImage}.

+ * + * The framebuffer is updated immediately when the {@link java.awt.image.BufferedImage} is changed + * by using a custom {@link java.awt.image.DataBuffer} subclass, {@link org.tw.pi.framebuffer.FrameBuffer}, + * which uses a JNI-accessed framebuffer device as its backing store.

+ * + * This package makes use of the Java AWT image classes, so anything a {@link java.awt.image.BufferedImage} + * can do can be done with a framebuffer device. + * + * @author Robin Kirkman + */ + From fc9b035046c0f5edc5aa7a015d49520e5e52866d Mon Sep 17 00:00:00 2001 From: robin Date: Wed, 25 Nov 2015 06:12:17 -0500 Subject: [PATCH 48/77] README.md --- README.md | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index fb21c99..fd465a9 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,8 @@ -JavaFrameBuffer -=============== +# org.tw.pi:framebuffer:0.1.0-SNAPSHOT -Acces to Linux frame buffer devices from Java. E.g. for driving LCD SPI displays on the Raspberry Pi +Access to Linux frame buffer devices from Java. E.g. for driving LCD SPI displays on the Raspberry Pi -See the run.sh script for setting up the LD_LIBRARY path for the JNI part and the example test class. - -I didn't make a jar for on file, so you have to copy the Java file and the JNI to your Java project. - -If someone can compile the Windows JNI parts, please send me the script and the library, I will add it :-) - -"Do what ever you want to do with it" licence... - -Ciao, - Thomas +Originally based off code from [ttww/JavaFrameBuffer](https://github.com/ttww/JavaFrameBuffer). +Modified to build with Apache Maven, then API rewritten to provide direct-write access +to linux framebuffers as java.awt.image.BuffferedImage + \ No newline at end of file From d4cf52fb54e15b21a02f9506b9f0ff2c9ab42d18 Mon Sep 17 00:00:00 2001 From: robin Date: Sat, 28 Nov 2015 20:12:33 -0500 Subject: [PATCH 49/77] Move compiler/resources config into parent pom --- framebuffer-parent/pom.xml | 46 +++++++++++++++++++++++++++-------- framebuffer-shaded/.classpath | 2 +- framebuffer/pom.xml | 17 ------------- 3 files changed, 37 insertions(+), 28 deletions(-) diff --git a/framebuffer-parent/pom.xml b/framebuffer-parent/pom.xml index 1dd318f..d0eae37 100644 --- a/framebuffer-parent/pom.xml +++ b/framebuffer-parent/pom.xml @@ -1,11 +1,37 @@ - - 4.0.0 - org.tw.pi - framebuffer-parent - 0.1.0-SNAPSHOT - pom - - ../framebuffer - ../framebuffer-shaded - + + 4.0.0 + org.tw.pi + framebuffer-parent + 0.1.0-SNAPSHOT + pom + + ../framebuffer + ../framebuffer-shaded + + + + + + + maven-compiler-plugin + 3.3 + + 1.7 + 1.7 + UTF-8 + + + + org.apache.maven.plugins + maven-resources-plugin + 2.7 + + UTF-8 + + + + + + \ No newline at end of file diff --git a/framebuffer-shaded/.classpath b/framebuffer-shaded/.classpath index 9fc2de7..e43402f 100644 --- a/framebuffer-shaded/.classpath +++ b/framebuffer-shaded/.classpath @@ -22,7 +22,7 @@ - + diff --git a/framebuffer/pom.xml b/framebuffer/pom.xml index 883dbdf..1f4b92d 100644 --- a/framebuffer/pom.xml +++ b/framebuffer/pom.xml @@ -21,23 +21,6 @@ - - maven-compiler-plugin - 3.3 - - 1.7 - 1.7 - UTF-8 - - - - org.apache.maven.plugins - maven-resources-plugin - 2.7 - - UTF-8 - - com.github.maven-nar nar-maven-plugin From 8348a29fa6c55ead4315ff84fd1da6c77f2bbecc Mon Sep 17 00:00:00 2001 From: robin Date: Sun, 29 Nov 2015 17:05:42 -0500 Subject: [PATCH 50/77] clocky test --- .../tw/pi/framebuffer/FrameBufferTest.java | 46 ++++++++++++++++--- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index e56345e..5f2ad78 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -1,7 +1,12 @@ package org.tw.pi.framebuffer; import java.awt.Color; +import java.awt.Dimension; import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Point; +import java.util.Calendar; + import org.junit.Test; public class FrameBufferTest { @@ -10,16 +15,43 @@ public void testLoad() throws Exception { Class.forName(FrameBuffers.class.getName()); } + private static Point project(Point center, int value, int max, int length) { + double radians = (value / (double) max) * (2 * Math.PI); + Point p = new Point(center.x, center.y); + p.x += length * Math.cos(radians); + p.y += length * Math.sin(radians); + return p; + } + public static void main(String[] args) throws Exception { FrameBufferedImage fb = new FrameBufferedImage(args[0]); try { - Graphics g = fb.getGraphics(); - int m = 0xff; - for(int i = 0; i < Math.min(fb.getWidth(), fb.getHeight()) / 2; i++) { - g.setColor(new Color(m)); - g.drawRect(i, i, fb.getWidth() - 2*i, fb.getHeight() - 2*i); - m <<= 1; - m |= (m >>> 24); + Graphics2D g = (Graphics2D) fb.getGraphics(); + Dimension dim = new Dimension(fb.getWidth(), fb.getHeight()); + Point center = new Point(dim.width / 2, dim.height / 2); + int radius = Math.min(dim.width, dim.height) / 2; + Calendar c = Calendar.getInstance(); + while(true) { + g.setColor(Color.BLACK); + g.fillRect(0, 0, dim.width, dim.height); + g.setColor(Color.WHITE); + g.drawOval(center.x - radius, center.y - radius, radius * 2, radius * 2); + + c.setTimeInMillis(System.currentTimeMillis()); + int hour = c.get(Calendar.HOUR); + int minute = c.get(Calendar.MINUTE); + int second = c.get(Calendar.SECOND); + + Point p = project(center, hour, 12, radius * 2 / 3); + g.drawLine(center.x, center.y, p.x, p.y); + + p = project(center, minute, 60, radius * 3 / 4); + g.drawLine(center.x, center.y, p.x, p.y); + + p = project(center, second, 60, radius * 5 / 6); + g.drawLine(center.x, center.y, p.x, p.y); + + Thread.sleep(500); } } finally { fb.close(); From 2159d4c8d9491e6e38c8a7678bd88e6a7b8a1937 Mon Sep 17 00:00:00 2001 From: robin Date: Sun, 29 Nov 2015 17:08:48 -0500 Subject: [PATCH 51/77] less repainty --- .../tw/pi/framebuffer/FrameBufferTest.java | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index 5f2ad78..7b3bcdc 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -31,18 +31,20 @@ public static void main(String[] args) throws Exception { Point center = new Point(dim.width / 2, dim.height / 2); int radius = Math.min(dim.width, dim.height) / 2; Calendar c = Calendar.getInstance(); + g.setColor(Color.BLACK); + g.fillRect(0, 0, dim.width, dim.height); + g.setColor(Color.WHITE); + g.drawOval(center.x - radius, center.y - radius, radius * 2, radius * 2); while(true) { - g.setColor(Color.BLACK); - g.fillRect(0, 0, dim.width, dim.height); - g.setColor(Color.WHITE); - g.drawOval(center.x - radius, center.y - radius, radius * 2, radius * 2); - c.setTimeInMillis(System.currentTimeMillis()); int hour = c.get(Calendar.HOUR); int minute = c.get(Calendar.MINUTE); int second = c.get(Calendar.SECOND); + + Point p; - Point p = project(center, hour, 12, radius * 2 / 3); + g.setColor(Color.WHITE); + p = project(center, hour, 12, radius * 2 / 3); g.drawLine(center.x, center.y, p.x, p.y); p = project(center, minute, 60, radius * 3 / 4); @@ -52,6 +54,17 @@ public static void main(String[] args) throws Exception { g.drawLine(center.x, center.y, p.x, p.y); Thread.sleep(500); + + g.setColor(Color.BLACK); + p = project(center, hour, 12, radius * 2 / 3); + g.drawLine(center.x, center.y, p.x, p.y); + + p = project(center, minute, 60, radius * 3 / 4); + g.drawLine(center.x, center.y, p.x, p.y); + + p = project(center, second, 60, radius * 5 / 6); + g.drawLine(center.x, center.y, p.x, p.y); + } } finally { fb.close(); From 9a1ce8a9fce5fd720093161cc1aa0d27d0b84690 Mon Sep 17 00:00:00 2001 From: robin Date: Sun, 29 Nov 2015 17:09:17 -0500 Subject: [PATCH 52/77] Reduce radius --- .../src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index 7b3bcdc..c3780f4 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -29,7 +29,7 @@ public static void main(String[] args) throws Exception { Graphics2D g = (Graphics2D) fb.getGraphics(); Dimension dim = new Dimension(fb.getWidth(), fb.getHeight()); Point center = new Point(dim.width / 2, dim.height / 2); - int radius = Math.min(dim.width, dim.height) / 2; + int radius = Math.min(dim.width, dim.height) / 2 - 1; Calendar c = Calendar.getInstance(); g.setColor(Color.BLACK); g.fillRect(0, 0, dim.width, dim.height); From 84fa02aec0cbb89306ee1df31871aaa0e6f55a84 Mon Sep 17 00:00:00 2001 From: robin Date: Sun, 29 Nov 2015 17:12:33 -0500 Subject: [PATCH 53/77] Fix --- .../src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index c3780f4..57d0c60 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -16,7 +16,7 @@ public void testLoad() throws Exception { } private static Point project(Point center, int value, int max, int length) { - double radians = (value / (double) max) * (2 * Math.PI); + double radians = Math.PI / 2 - (value / (double) max) * (2 * Math.PI); Point p = new Point(center.x, center.y); p.x += length * Math.cos(radians); p.y += length * Math.sin(radians); From 63e747f42419b3d6d893f89249f6290d4f8c6d2f Mon Sep 17 00:00:00 2001 From: robin Date: Sun, 29 Nov 2015 17:13:09 -0500 Subject: [PATCH 54/77] invert sign --- .../src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index 57d0c60..8980422 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -19,7 +19,7 @@ private static Point project(Point center, int value, int max, int length) { double radians = Math.PI / 2 - (value / (double) max) * (2 * Math.PI); Point p = new Point(center.x, center.y); p.x += length * Math.cos(radians); - p.y += length * Math.sin(radians); + p.y -= length * Math.sin(radians); return p; } From 95a7e7527e8df8964b2cc67ce3de6dfdc34b4065 Mon Sep 17 00:00:00 2001 From: robin Date: Sun, 29 Nov 2015 17:15:11 -0500 Subject: [PATCH 55/77] Clock face --- .../test/java/org/tw/pi/framebuffer/FrameBufferTest.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index 8980422..27c66aa 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -35,6 +35,13 @@ public static void main(String[] args) throws Exception { g.fillRect(0, 0, dim.width, dim.height); g.setColor(Color.WHITE); g.drawOval(center.x - radius, center.y - radius, radius * 2, radius * 2); + + for(int i = 0; i < 12; i++) { + Point p1 = project(center, i, 12, radius * 8 / 9); + Point p2 = project(center, i, 12, radius); + g.drawLine(p1.x, p1.y, p2.x, p2.y); + } + while(true) { c.setTimeInMillis(System.currentTimeMillis()); int hour = c.get(Calendar.HOUR); From 3786a8b78cbff0c628bc69ec0d6fe99822b53e8a Mon Sep 17 00:00:00 2001 From: robin Date: Sun, 29 Nov 2015 17:18:27 -0500 Subject: [PATCH 56/77] clock tweaks --- .../org/tw/pi/framebuffer/FrameBufferTest.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index 27c66aa..cee9937 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -38,7 +38,7 @@ public static void main(String[] args) throws Exception { for(int i = 0; i < 12; i++) { Point p1 = project(center, i, 12, radius * 8 / 9); - Point p2 = project(center, i, 12, radius); + Point p2 = project(center, i, 12, radius * 9 / 10); g.drawLine(p1.x, p1.y, p2.x, p2.y); } @@ -51,25 +51,25 @@ public static void main(String[] args) throws Exception { Point p; g.setColor(Color.WHITE); - p = project(center, hour, 12, radius * 2 / 3); + p = project(center, hour, 12, radius * 1 / 2); g.drawLine(center.x, center.y, p.x, p.y); - p = project(center, minute, 60, radius * 3 / 4); + p = project(center, minute, 60, radius * 2 / 3); g.drawLine(center.x, center.y, p.x, p.y); - p = project(center, second, 60, radius * 5 / 6); + p = project(center, second, 60, radius * 3 / 4); g.drawLine(center.x, center.y, p.x, p.y); Thread.sleep(500); g.setColor(Color.BLACK); - p = project(center, hour, 12, radius * 2 / 3); + p = project(center, hour, 12, radius * 1 / 2); g.drawLine(center.x, center.y, p.x, p.y); - p = project(center, minute, 60, radius * 3 / 4); + p = project(center, minute, 60, radius * 2 / 3); g.drawLine(center.x, center.y, p.x, p.y); - p = project(center, second, 60, radius * 5 / 6); + p = project(center, second, 60, radius * 3 / 4); g.drawLine(center.x, center.y, p.x, p.y); } From f642d4140fb2a8a7ec5aa246e2c4ea68389e189f Mon Sep 17 00:00:00 2001 From: robin Date: Sun, 29 Nov 2015 17:20:31 -0500 Subject: [PATCH 57/77] longer notches --- .../src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index cee9937..a05e500 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -38,7 +38,7 @@ public static void main(String[] args) throws Exception { for(int i = 0; i < 12; i++) { Point p1 = project(center, i, 12, radius * 8 / 9); - Point p2 = project(center, i, 12, radius * 9 / 10); + Point p2 = project(center, i, 12, radius * 19 / 20); g.drawLine(p1.x, p1.y, p2.x, p2.y); } From 51a07025469ebcd3177057167db5b5d42df8a050 Mon Sep 17 00:00:00 2001 From: robin Date: Sun, 29 Nov 2015 17:34:40 -0500 Subject: [PATCH 58/77] show numbers too --- .../tw/pi/framebuffer/FrameBufferTest.java | 40 ++++++++++++++++++- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index a05e500..39706d4 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -2,9 +2,12 @@ import java.awt.Color; import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; +import java.awt.font.LineMetrics; import java.util.Calendar; import org.junit.Test; @@ -23,16 +26,25 @@ private static Point project(Point center, int value, int max, int length) { return p; } + private static Dimension bounds(FontMetrics fm, String s) { + Dimension d = new Dimension(); + d.height += fm.getHeight(); + d.width += fm.stringWidth(s); + return d; + } + public static void main(String[] args) throws Exception { FrameBufferedImage fb = new FrameBufferedImage(args[0]); try { Graphics2D g = (Graphics2D) fb.getGraphics(); Dimension dim = new Dimension(fb.getWidth(), fb.getHeight()); + g.setColor(Color.BLACK); + g.fillRect(0, 0, dim.width, dim.height); + Point center = new Point(dim.width / 2, dim.height / 2); int radius = Math.min(dim.width, dim.height) / 2 - 1; + Calendar c = Calendar.getInstance(); - g.setColor(Color.BLACK); - g.fillRect(0, 0, dim.width, dim.height); g.setColor(Color.WHITE); g.drawOval(center.x - radius, center.y - radius, radius * 2, radius * 2); @@ -42,35 +54,59 @@ public static void main(String[] args) throws Exception { g.drawLine(p1.x, p1.y, p2.x, p2.y); } + g.setFont(new Font("Monospace", Font.BOLD, 6)); + FontMetrics fm = g.getFontMetrics(); + while(true) { c.setTimeInMillis(System.currentTimeMillis()); int hour = c.get(Calendar.HOUR); int minute = c.get(Calendar.MINUTE); int second = c.get(Calendar.SECOND); + if(hour == 0) + hour = 12; + Point p; + Dimension d; g.setColor(Color.WHITE); + p = project(center, hour, 12, radius * 1 / 2); g.drawLine(center.x, center.y, p.x, p.y); + d = bounds(fm, String.valueOf(hour)); + g.drawString(String.valueOf(hour), p.x - d.width / 2, p.y + d.height / 2); + p = project(center, minute, 60, radius * 2 / 3); g.drawLine(center.x, center.y, p.x, p.y); + d = bounds(fm, String.valueOf(minute)); + g.drawString(String.valueOf(minute), p.x - d.width / 2, p.y + d.height / 2); p = project(center, second, 60, radius * 3 / 4); g.drawLine(center.x, center.y, p.x, p.y); + d = bounds(fm, String.valueOf(second)); + g.drawString(String.valueOf(second), p.x - d.width / 2, p.y + d.height / 2); + Thread.sleep(500); g.setColor(Color.BLACK); + p = project(center, hour, 12, radius * 1 / 2); g.drawLine(center.x, center.y, p.x, p.y); + d = bounds(fm, String.valueOf(hour)); + g.drawString(String.valueOf(hour), p.x - d.width / 2, p.y + d.height / 2); + p = project(center, minute, 60, radius * 2 / 3); g.drawLine(center.x, center.y, p.x, p.y); + d = bounds(fm, String.valueOf(minute)); + g.drawString(String.valueOf(minute), p.x - d.width / 2, p.y + d.height / 2); p = project(center, second, 60, radius * 3 / 4); g.drawLine(center.x, center.y, p.x, p.y); + d = bounds(fm, String.valueOf(second)); + g.drawString(String.valueOf(second), p.x - d.width / 2, p.y + d.height / 2); } } finally { From ccd7d142b2cf262ab0a0342b0fff8680e8ad4e36 Mon Sep 17 00:00:00 2001 From: robin Date: Sun, 29 Nov 2015 17:37:34 -0500 Subject: [PATCH 59/77] bigger text, shorter arms --- .../java/org/tw/pi/framebuffer/FrameBufferTest.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index 39706d4..19a40bc 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -54,7 +54,7 @@ public static void main(String[] args) throws Exception { g.drawLine(p1.x, p1.y, p2.x, p2.y); } - g.setFont(new Font("Monospace", Font.BOLD, 6)); + g.setFont(new Font("Monospace", Font.BOLD, 12)); FontMetrics fm = g.getFontMetrics(); while(true) { @@ -71,20 +71,23 @@ public static void main(String[] args) throws Exception { g.setColor(Color.WHITE); - p = project(center, hour, 12, radius * 1 / 2); + p = project(center, hour, 12, radius * 1 / 2 - 12); g.drawLine(center.x, center.y, p.x, p.y); d = bounds(fm, String.valueOf(hour)); + p = project(center, hour, 12, radius * 1 / 2); g.drawString(String.valueOf(hour), p.x - d.width / 2, p.y + d.height / 2); - p = project(center, minute, 60, radius * 2 / 3); + p = project(center, minute, 60, radius * 2 / 3 - 12); g.drawLine(center.x, center.y, p.x, p.y); d = bounds(fm, String.valueOf(minute)); + p = project(center, minute, 60, radius * 2 / 3); g.drawString(String.valueOf(minute), p.x - d.width / 2, p.y + d.height / 2); - p = project(center, second, 60, radius * 3 / 4); + p = project(center, second, 60, radius * 3 / 4 - 12); g.drawLine(center.x, center.y, p.x, p.y); d = bounds(fm, String.valueOf(second)); + p = project(center, second, 60, radius * 3 / 4); g.drawString(String.valueOf(second), p.x - d.width / 2, p.y + d.height / 2); From d907729b321cf41056cae4b4845250518cbcfaf9 Mon Sep 17 00:00:00 2001 From: robin Date: Sun, 29 Nov 2015 18:18:01 -0500 Subject: [PATCH 60/77] Proper undrawing --- .../test/java/org/tw/pi/framebuffer/FrameBufferTest.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index 19a40bc..e8fa199 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -95,20 +95,23 @@ public static void main(String[] args) throws Exception { g.setColor(Color.BLACK); - p = project(center, hour, 12, radius * 1 / 2); + p = project(center, hour, 12, radius * 1 / 2 - 12); g.drawLine(center.x, center.y, p.x, p.y); d = bounds(fm, String.valueOf(hour)); + p = project(center, hour, 12, radius * 1 / 2); g.drawString(String.valueOf(hour), p.x - d.width / 2, p.y + d.height / 2); - p = project(center, minute, 60, radius * 2 / 3); + p = project(center, minute, 60, radius * 2 / 3 - 12); g.drawLine(center.x, center.y, p.x, p.y); d = bounds(fm, String.valueOf(minute)); + p = project(center, minute, 60, radius * 2 / 3); g.drawString(String.valueOf(minute), p.x - d.width / 2, p.y + d.height / 2); - p = project(center, second, 60, radius * 3 / 4); + p = project(center, second, 60, radius * 3 / 4 - 12); g.drawLine(center.x, center.y, p.x, p.y); d = bounds(fm, String.valueOf(second)); + p = project(center, second, 60, radius * 3 / 4); g.drawString(String.valueOf(second), p.x - d.width / 2, p.y + d.height / 2); } From 6cc824757ff84cab71d1007d7ca9867267ea94ab Mon Sep 17 00:00:00 2001 From: robin Date: Sun, 29 Nov 2015 18:20:13 -0500 Subject: [PATCH 61/77] Tweak fonts --- .../src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index e8fa199..d2b352a 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -28,7 +28,7 @@ private static Point project(Point center, int value, int max, int length) { private static Dimension bounds(FontMetrics fm, String s) { Dimension d = new Dimension(); - d.height += fm.getHeight(); + d.height += fm.getAscent(); d.width += fm.stringWidth(s); return d; } From 7d268f2223e9fd791a63b645d25cca6871b628c6 Mon Sep 17 00:00:00 2001 From: robin Date: Sun, 29 Nov 2015 18:23:07 -0500 Subject: [PATCH 62/77] Less sleep time --- .../src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index d2b352a..b83662a 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -91,7 +91,7 @@ public static void main(String[] args) throws Exception { g.drawString(String.valueOf(second), p.x - d.width / 2, p.y + d.height / 2); - Thread.sleep(500); + Thread.sleep(125); g.setColor(Color.BLACK); From 9412662a174f7447d292db7f6dd585b67d4a7cbe Mon Sep 17 00:00:00 2001 From: robin Date: Sun, 29 Nov 2015 18:28:36 -0500 Subject: [PATCH 63/77] gray clock face --- .../test/java/org/tw/pi/framebuffer/FrameBufferTest.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index b83662a..3d954b6 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -45,6 +45,10 @@ public static void main(String[] args) throws Exception { int radius = Math.min(dim.width, dim.height) / 2 - 1; Calendar c = Calendar.getInstance(); + + g.setColor(Color.GRAY); + g.fillOval(center.x - radius, center.y - radius, radius * 2, radius * 2); + g.setColor(Color.WHITE); g.drawOval(center.x - radius, center.y - radius, radius * 2, radius * 2); @@ -93,7 +97,7 @@ public static void main(String[] args) throws Exception { Thread.sleep(125); - g.setColor(Color.BLACK); + g.setColor(Color.GRAY); p = project(center, hour, 12, radius * 1 / 2 - 12); g.drawLine(center.x, center.y, p.x, p.y); From 0ac05b4b4b2c28460ecb4bf60bc9324f7290cfbe Mon Sep 17 00:00:00 2001 From: robin Date: Sun, 29 Nov 2015 18:30:10 -0500 Subject: [PATCH 64/77] light gray --- .../src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index 3d954b6..1fc85e5 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -46,7 +46,7 @@ public static void main(String[] args) throws Exception { Calendar c = Calendar.getInstance(); - g.setColor(Color.GRAY); + g.setColor(Color.LIGHT_GRAY); g.fillOval(center.x - radius, center.y - radius, radius * 2, radius * 2); g.setColor(Color.WHITE); @@ -97,7 +97,7 @@ public static void main(String[] args) throws Exception { Thread.sleep(125); - g.setColor(Color.GRAY); + g.setColor(Color.LIGHT_GRAY); p = project(center, hour, 12, radius * 1 / 2 - 12); g.drawLine(center.x, center.y, p.x, p.y); From 87bbb0b7f06f78b61bf2f1dd50d022d6d140e2bd Mon Sep 17 00:00:00 2001 From: robin Date: Sun, 29 Nov 2015 18:31:38 -0500 Subject: [PATCH 65/77] grayer? --- .../src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index 1fc85e5..e64caf8 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -46,7 +46,7 @@ public static void main(String[] args) throws Exception { Calendar c = Calendar.getInstance(); - g.setColor(Color.LIGHT_GRAY); + g.setColor(Color.GRAY.brighter()); g.fillOval(center.x - radius, center.y - radius, radius * 2, radius * 2); g.setColor(Color.WHITE); @@ -97,7 +97,7 @@ public static void main(String[] args) throws Exception { Thread.sleep(125); - g.setColor(Color.LIGHT_GRAY); + g.setColor(Color.GRAY.brighter()); p = project(center, hour, 12, radius * 1 / 2 - 12); g.drawLine(center.x, center.y, p.x, p.y); From cc19c261958456235db667b6d86ec52fd734013a Mon Sep 17 00:00:00 2001 From: robin Date: Sun, 29 Nov 2015 18:33:34 -0500 Subject: [PATCH 66/77] blue face --- .../src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index e64caf8..deeaa02 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -46,7 +46,7 @@ public static void main(String[] args) throws Exception { Calendar c = Calendar.getInstance(); - g.setColor(Color.GRAY.brighter()); + g.setColor(Color.BLUE); g.fillOval(center.x - radius, center.y - radius, radius * 2, radius * 2); g.setColor(Color.WHITE); @@ -97,7 +97,7 @@ public static void main(String[] args) throws Exception { Thread.sleep(125); - g.setColor(Color.GRAY.brighter()); + g.setColor(Color.BLUE); p = project(center, hour, 12, radius * 1 / 2 - 12); g.drawLine(center.x, center.y, p.x, p.y); From f128dfa5e6bdbc1cb833556cee5bf2d224b06101 Mon Sep 17 00:00:00 2001 From: robin Date: Sun, 29 Nov 2015 18:37:24 -0500 Subject: [PATCH 67/77] maybe fix endian --- framebuffer/src/main/c/FrameBuffers.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/framebuffer/src/main/c/FrameBuffers.c b/framebuffer/src/main/c/FrameBuffers.c index 33072be..dc4e26d 100755 --- a/framebuffer/src/main/c/FrameBuffers.c +++ b/framebuffer/src/main/c/FrameBuffers.c @@ -194,12 +194,11 @@ JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_writeRGB0 return; p += (width * idx); - p += (width - 1); while(width > 0) { *p = (unsigned char)(0xFF & rgb); rgb = rgb >> 8; width--; - p--; + p++; } } @@ -224,10 +223,11 @@ JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_readRGB0 unsigned int rgb = 0; p += (width * idx); + p += width - 1; while(width > 0) { rgb = (rgb << 8) + *p; width--; - p++; + p--; } return rgb; From 775da060782467f3fcd56feac1011f1d9edce1ca Mon Sep 17 00:00:00 2001 From: robin Date: Sun, 29 Nov 2015 18:57:15 -0500 Subject: [PATCH 68/77] Smoother second hand --- .../test/java/org/tw/pi/framebuffer/FrameBufferTest.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index deeaa02..ad02bbd 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -66,6 +66,7 @@ public static void main(String[] args) throws Exception { int hour = c.get(Calendar.HOUR); int minute = c.get(Calendar.MINUTE); int second = c.get(Calendar.SECOND); + int ms = c.get(Calendar.MILLISECOND); if(hour == 0) hour = 12; @@ -88,10 +89,10 @@ public static void main(String[] args) throws Exception { p = project(center, minute, 60, radius * 2 / 3); g.drawString(String.valueOf(minute), p.x - d.width / 2, p.y + d.height / 2); - p = project(center, second, 60, radius * 3 / 4 - 12); + p = project(center, second * 1000 + ms, 60000, radius * 3 / 4 - 12); g.drawLine(center.x, center.y, p.x, p.y); d = bounds(fm, String.valueOf(second)); - p = project(center, second, 60, radius * 3 / 4); + p = project(center, second * 1000 + ms, 60000, radius * 3 / 4); g.drawString(String.valueOf(second), p.x - d.width / 2, p.y + d.height / 2); @@ -112,10 +113,10 @@ public static void main(String[] args) throws Exception { p = project(center, minute, 60, radius * 2 / 3); g.drawString(String.valueOf(minute), p.x - d.width / 2, p.y + d.height / 2); - p = project(center, second, 60, radius * 3 / 4 - 12); + p = project(center, second * 1000 + ms, 60000, radius * 3 / 4 - 12); g.drawLine(center.x, center.y, p.x, p.y); d = bounds(fm, String.valueOf(second)); - p = project(center, second, 60, radius * 3 / 4); + p = project(center, second * 1000 + ms, 60000, radius * 3 / 4); g.drawString(String.valueOf(second), p.x - d.width / 2, p.y + d.height / 2); } From b6b4aa8f14a0751254a069cfb04a71bfb1444d51 Mon Sep 17 00:00:00 2001 From: robin Date: Sun, 29 Nov 2015 19:00:09 -0500 Subject: [PATCH 69/77] antialias --- .../src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index ad02bbd..91feeb8 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -7,6 +7,7 @@ import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; +import java.awt.RenderingHints; import java.awt.font.LineMetrics; import java.util.Calendar; @@ -37,6 +38,9 @@ public static void main(String[] args) throws Exception { FrameBufferedImage fb = new FrameBufferedImage(args[0]); try { Graphics2D g = (Graphics2D) fb.getGraphics(); + + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + Dimension dim = new Dimension(fb.getWidth(), fb.getHeight()); g.setColor(Color.BLACK); g.fillRect(0, 0, dim.width, dim.height); From bd1b74446561b832e06b2eb92aac451667b31479 Mon Sep 17 00:00:00 2001 From: robin Date: Sun, 29 Nov 2015 19:01:32 -0500 Subject: [PATCH 70/77] Revert "antialias" This reverts commit b6b4aa8f14a0751254a069cfb04a71bfb1444d51. --- .../src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index 91feeb8..ad02bbd 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -7,7 +7,6 @@ import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; -import java.awt.RenderingHints; import java.awt.font.LineMetrics; import java.util.Calendar; @@ -38,9 +37,6 @@ public static void main(String[] args) throws Exception { FrameBufferedImage fb = new FrameBufferedImage(args[0]); try { Graphics2D g = (Graphics2D) fb.getGraphics(); - - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - Dimension dim = new Dimension(fb.getWidth(), fb.getHeight()); g.setColor(Color.BLACK); g.fillRect(0, 0, dim.width, dim.height); From abbb2060bda67e1ccf2430e15764f0eb23076b13 Mon Sep 17 00:00:00 2001 From: robin Date: Sun, 29 Nov 2015 19:07:45 -0500 Subject: [PATCH 71/77] change color --- .../src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index ad02bbd..62bd0c7 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -46,7 +46,7 @@ public static void main(String[] args) throws Exception { Calendar c = Calendar.getInstance(); - g.setColor(Color.BLUE); + g.setColor(new Color(0, 32, 32)); g.fillOval(center.x - radius, center.y - radius, radius * 2, radius * 2); g.setColor(Color.WHITE); @@ -98,7 +98,7 @@ public static void main(String[] args) throws Exception { Thread.sleep(125); - g.setColor(Color.BLUE); + g.setColor(new Color(0, 32, 32)); p = project(center, hour, 12, radius * 1 / 2 - 12); g.drawLine(center.x, center.y, p.x, p.y); From 25e950582e63cf5dd4e0025044bdca239409f8a4 Mon Sep 17 00:00:00 2001 From: robin Date: Sun, 29 Nov 2015 19:09:10 -0500 Subject: [PATCH 72/77] Face --- .../src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index 62bd0c7..8626719 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -46,7 +46,7 @@ public static void main(String[] args) throws Exception { Calendar c = Calendar.getInstance(); - g.setColor(new Color(0, 32, 32)); + g.setColor(new Color(0, 64, 64)); g.fillOval(center.x - radius, center.y - radius, radius * 2, radius * 2); g.setColor(Color.WHITE); @@ -98,7 +98,7 @@ public static void main(String[] args) throws Exception { Thread.sleep(125); - g.setColor(new Color(0, 32, 32)); + g.setColor(new Color(0, 64, 64)); p = project(center, hour, 12, radius * 1 / 2 - 12); g.drawLine(center.x, center.y, p.x, p.y); From 3074f5f3df7c704c9a373a15a713c4970bae64bd Mon Sep 17 00:00:00 2001 From: robin Date: Sun, 29 Nov 2015 19:21:07 -0500 Subject: [PATCH 73/77] partial minutes, partial hours --- .../tw/pi/framebuffer/FrameBufferTest.java | 47 ++++++++++--------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index 8626719..0652590 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -18,7 +18,7 @@ public void testLoad() throws Exception { Class.forName(FrameBuffers.class.getName()); } - private static Point project(Point center, int value, int max, int length) { + private static Point project(Point center, double value, double max, int length) { double radians = Math.PI / 2 - (value / (double) max) * (2 * Math.PI); Point p = new Point(center.x, center.y); p.x += length * Math.cos(radians); @@ -63,13 +63,14 @@ public static void main(String[] args) throws Exception { while(true) { c.setTimeInMillis(System.currentTimeMillis()); - int hour = c.get(Calendar.HOUR); - int minute = c.get(Calendar.MINUTE); - int second = c.get(Calendar.SECOND); - int ms = c.get(Calendar.MILLISECOND); - if(hour == 0) - hour = 12; + double ms = c.get(Calendar.MILLISECOND); + double second = c.get(Calendar.SECOND) + ms / 1000; + double minute = c.get(Calendar.MINUTE) + second / 60; + double hour = c.get(Calendar.HOUR) + minute / 60; + + if(((int) hour) == 0) + hour += 12; Point p; Dimension d; @@ -78,22 +79,22 @@ public static void main(String[] args) throws Exception { p = project(center, hour, 12, radius * 1 / 2 - 12); g.drawLine(center.x, center.y, p.x, p.y); - d = bounds(fm, String.valueOf(hour)); + d = bounds(fm, String.valueOf((int) hour)); p = project(center, hour, 12, radius * 1 / 2); - g.drawString(String.valueOf(hour), p.x - d.width / 2, p.y + d.height / 2); + g.drawString(String.valueOf((int) hour), p.x - d.width / 2, p.y + d.height / 2); p = project(center, minute, 60, radius * 2 / 3 - 12); g.drawLine(center.x, center.y, p.x, p.y); - d = bounds(fm, String.valueOf(minute)); + d = bounds(fm, String.valueOf((int) minute)); p = project(center, minute, 60, radius * 2 / 3); - g.drawString(String.valueOf(minute), p.x - d.width / 2, p.y + d.height / 2); + g.drawString(String.valueOf((int) minute), p.x - d.width / 2, p.y + d.height / 2); - p = project(center, second * 1000 + ms, 60000, radius * 3 / 4 - 12); + p = project(center, second, 60, radius * 3 / 4 - 12); g.drawLine(center.x, center.y, p.x, p.y); - d = bounds(fm, String.valueOf(second)); - p = project(center, second * 1000 + ms, 60000, radius * 3 / 4); - g.drawString(String.valueOf(second), p.x - d.width / 2, p.y + d.height / 2); + d = bounds(fm, String.valueOf((int) second)); + p = project(center, second, 60, radius * 3 / 4); + g.drawString(String.valueOf((int) second), p.x - d.width / 2, p.y + d.height / 2); Thread.sleep(125); @@ -102,22 +103,22 @@ public static void main(String[] args) throws Exception { p = project(center, hour, 12, radius * 1 / 2 - 12); g.drawLine(center.x, center.y, p.x, p.y); - d = bounds(fm, String.valueOf(hour)); + d = bounds(fm, String.valueOf((int) hour)); p = project(center, hour, 12, radius * 1 / 2); - g.drawString(String.valueOf(hour), p.x - d.width / 2, p.y + d.height / 2); + g.drawString(String.valueOf((int) hour), p.x - d.width / 2, p.y + d.height / 2); p = project(center, minute, 60, radius * 2 / 3 - 12); g.drawLine(center.x, center.y, p.x, p.y); - d = bounds(fm, String.valueOf(minute)); + d = bounds(fm, String.valueOf((int) minute)); p = project(center, minute, 60, radius * 2 / 3); - g.drawString(String.valueOf(minute), p.x - d.width / 2, p.y + d.height / 2); + g.drawString(String.valueOf((int) minute), p.x - d.width / 2, p.y + d.height / 2); - p = project(center, second * 1000 + ms, 60000, radius * 3 / 4 - 12); + p = project(center, second, 60, radius * 3 / 4 - 12); g.drawLine(center.x, center.y, p.x, p.y); - d = bounds(fm, String.valueOf(second)); - p = project(center, second * 1000 + ms, 60000, radius * 3 / 4); - g.drawString(String.valueOf(second), p.x - d.width / 2, p.y + d.height / 2); + d = bounds(fm, String.valueOf((int) second)); + p = project(center, second, 60, radius * 3 / 4); + g.drawString(String.valueOf((int) second), p.x - d.width / 2, p.y + d.height / 2); } } finally { From b605c27b55c95904d07b342adc236d68f8972f65 Mon Sep 17 00:00:00 2001 From: robin Date: Sun, 29 Nov 2015 19:22:05 -0500 Subject: [PATCH 74/77] red --- .../src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index 0652590..0c23832 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -46,7 +46,7 @@ public static void main(String[] args) throws Exception { Calendar c = Calendar.getInstance(); - g.setColor(new Color(0, 64, 64)); + g.setColor(Color.RED); g.fillOval(center.x - radius, center.y - radius, radius * 2, radius * 2); g.setColor(Color.WHITE); @@ -99,7 +99,7 @@ public static void main(String[] args) throws Exception { Thread.sleep(125); - g.setColor(new Color(0, 64, 64)); + g.setColor(Color.RED); p = project(center, hour, 12, radius * 1 / 2 - 12); g.drawLine(center.x, center.y, p.x, p.y); From c1ea9f020a7b6737d08e3820a7c2ec3a3df6a6a6 Mon Sep 17 00:00:00 2001 From: robin Date: Sun, 29 Nov 2015 19:24:24 -0500 Subject: [PATCH 75/77] Wider stroke --- .../src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index 0c23832..ad29bd6 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -1,5 +1,6 @@ package org.tw.pi.framebuffer; +import java.awt.BasicStroke; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; @@ -42,7 +43,9 @@ public static void main(String[] args) throws Exception { g.fillRect(0, 0, dim.width, dim.height); Point center = new Point(dim.width / 2, dim.height / 2); - int radius = Math.min(dim.width, dim.height) / 2 - 1; + int radius = Math.min(dim.width, dim.height) / 2 - 3; + + g.setStroke(new BasicStroke(2f)); Calendar c = Calendar.getInstance(); From fadae33f99544087d16e29cf1e49a18e17775de0 Mon Sep 17 00:00:00 2001 From: robin Date: Sun, 29 Nov 2015 19:26:23 -0500 Subject: [PATCH 76/77] purple --- .../src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java index ad29bd6..d76df20 100644 --- a/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java +++ b/framebuffer/src/test/java/org/tw/pi/framebuffer/FrameBufferTest.java @@ -49,7 +49,7 @@ public static void main(String[] args) throws Exception { Calendar c = Calendar.getInstance(); - g.setColor(Color.RED); + g.setColor(Color.MAGENTA); g.fillOval(center.x - radius, center.y - radius, radius * 2, radius * 2); g.setColor(Color.WHITE); @@ -102,7 +102,7 @@ public static void main(String[] args) throws Exception { Thread.sleep(125); - g.setColor(Color.RED); + g.setColor(Color.MAGENTA); p = project(center, hour, 12, radius * 1 / 2 - 12); g.drawLine(center.x, center.y, p.x, p.y); From 5e44650e4ff136ee7eb6e2220db8f45101268513 Mon Sep 17 00:00:00 2001 From: robin Date: Fri, 11 Dec 2015 21:35:17 -0500 Subject: [PATCH 77/77] Keep a cache of the framebuffer and only write to the fb itself if the written value differs from the cache. Only read from the cache. --- framebuffer/src/main/c/FrameBuffers.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/framebuffer/src/main/c/FrameBuffers.c b/framebuffer/src/main/c/FrameBuffers.c index dc4e26d..8f1c93d 100755 --- a/framebuffer/src/main/c/FrameBuffers.c +++ b/framebuffer/src/main/c/FrameBuffers.c @@ -49,6 +49,8 @@ static struct FrameBufferData { long int screensize; char *fbp; + + char *cache; }; /* @@ -114,7 +116,7 @@ JNIEXPORT jlong JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_openDevice0( di->fbp = (char*) mmap(0, di->screensize, PROT_READ | PROT_WRITE, MAP_SHARED, di->fbfd, 0); - if ((int) di->fbp == -1) { + if (((int) di->fbp == -1) || ((di->cache = malloc(di->screensize)) == NULL)) { close(di->fbfd); free(di->deviceName); return org_tw_pi_framebuffer_FrameBuffers_ERR_MMAP; @@ -133,11 +135,10 @@ JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_closeDevice0( struct FrameBufferData *di = (struct FrameBufferData *) (intptr_t) jdi; free(di->deviceName); + free(di->cache); - if (di->fbfd != 0) { - munmap(di->fbp, di->screensize); - close(di->fbfd); - } + munmap(di->fbp, di->screensize); + close(di->fbfd); memset(di, 0, sizeof(*di)); } @@ -182,6 +183,7 @@ JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_writeRGB0 (JNIEnv *env, jclass clazz, jlong ptr, jint idx, jint rgb) { struct FrameBufferData *di = (struct FrameBufferData *) (intptr_t) ptr; unsigned char *p = (unsigned char *) di->fbp; + unsigned char *q = (unsigned char *) di->cache; unsigned int width; if(di->bpp == 8) @@ -194,11 +196,14 @@ JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_writeRGB0 return; p += (width * idx); + q += (width * idx); while(width > 0) { - *p = (unsigned char)(0xFF & rgb); + if(*q != (unsigned char)(0xFF & rgb)) + *q = *p = (unsigned char)(0xFF & rgb); rgb = rgb >> 8; width--; p++; + q++; } } @@ -208,7 +213,7 @@ JNIEXPORT void JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_writeRGB0 JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_readRGB0 (JNIEnv *env, jclass clazz, jlong ptr, jint idx) { struct FrameBufferData *di = (struct FrameBufferData *) (intptr_t) ptr; - unsigned char *p = (unsigned char *) di->fbp; + unsigned char *q = (unsigned char *) di->cache; unsigned int width; if(di->bpp == 8) @@ -222,12 +227,12 @@ JNIEXPORT jint JNICALL Java_org_tw_pi_framebuffer_FrameBuffers_readRGB0 unsigned int rgb = 0; - p += (width * idx); - p += width - 1; + q += (width * idx); + q += width - 1; while(width > 0) { - rgb = (rgb << 8) + *p; + rgb = (rgb << 8) + *q; width--; - p--; + q--; } return rgb;