diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 99f6760e..def1a40b 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -13,6 +13,7 @@
+
diff --git a/app/build.gradle b/app/build.gradle
index 539f7fcb..31b27a54 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -95,7 +95,7 @@ android {
applicationIdSuffix '.leia'
minSdkVersion 30
dependencies {
- implementation files("../leia-cnsdk/cnsdk.aar")
+ implementation project(":leia-cnsdk")
}
}
}
diff --git a/app/src/leia/java/com/simongellis/vvb/game/LeiaSurfaceViewAdapter.kt b/app/src/leia/java/com/simongellis/vvb/game/LeiaSurfaceViewAdapter.kt
index 8c46268a..65ba9b55 100644
--- a/app/src/leia/java/com/simongellis/vvb/game/LeiaSurfaceViewAdapter.kt
+++ b/app/src/leia/java/com/simongellis/vvb/game/LeiaSurfaceViewAdapter.kt
@@ -23,7 +23,6 @@ class LeiaSurfaceViewAdapter : InterlacedSurfaceView, SurfaceViewAdapter, LeiaSD
initArgs.platform.context = context.applicationContext
initArgs.platform.activity = getActivity(context)
initArgs.enableFaceTracking = true
- initArgs.requiresFaceTrackingPermissionCheck = false
LeiaSDK.createSDK(initArgs)
}
@@ -82,7 +81,7 @@ class LeiaSurfaceViewAdapter : InterlacedSurfaceView, SurfaceViewAdapter, LeiaSD
Log.i("LeiaSurfaceViewAdapter", "setting up $textureId (error 0x${GLES20.glGetError().toString(16)})")
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId)
Log.i("LeiaSurfaceViewAdapter", "bound $textureId (error 0x${GLES20.glGetError().toString(16)})")
- GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGB, width * 2, height, 0, GLES20.GL_RGB, GLES20.GL_UNSIGNED_BYTE, null)
+ GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGB, width, height, 0, GLES20.GL_RGB, GLES20.GL_UNSIGNED_BYTE, null)
Log.i("LeiaSurfaceViewAdapter", "initialized $textureId (error 0x${GLES20.glGetError().toString(16)})")
val framebuffers = IntArray(1)
@@ -103,6 +102,7 @@ class LeiaSurfaceViewAdapter : InterlacedSurfaceView, SurfaceViewAdapter, LeiaSD
override fun didInitialize(sdk: LeiaSDK) {
Log.i("LeiaSurfaceViewAdapter", "didInitialize")
+ sdk.enableBacklight(true)
}
override fun onFaceTrackingFatalError(sdk: LeiaSDK) {
diff --git a/app/src/main/java/com/simongellis/vvb/emulator/CNSDKRenderer.kt b/app/src/main/java/com/simongellis/vvb/emulator/CNSDKRenderer.kt
new file mode 100644
index 00000000..65cadd3c
--- /dev/null
+++ b/app/src/main/java/com/simongellis/vvb/emulator/CNSDKRenderer.kt
@@ -0,0 +1,45 @@
+package com.simongellis.vvb.emulator
+
+import androidx.annotation.ColorInt
+
+class CNSDKRenderer(emulator: Emulator, settings: Settings): Renderer {
+ private var _pointer = 0L
+
+ init {
+ nativeConstructor(emulator, settings)
+ }
+
+ fun finalize() {
+ destroy()
+ }
+
+ override fun destroy() {
+ if (_pointer != 0L) {
+ nativeDestructor()
+ }
+ }
+
+ override fun onSurfaceCreated() {
+ nativeOnSurfaceCreated()
+ }
+
+ override fun onSurfaceChanged(width: Int, height: Int) {
+ nativeOnSurfaceChanged(width, height)
+ }
+
+ override fun onDrawFrame() {
+ nativeOnDrawFrame()
+ }
+
+ class Settings(
+ val screenZoom: Float,
+ val aspectRatio: Int,
+ val verticalOffset: Float,
+ @ColorInt val color: Int)
+
+ private external fun nativeConstructor(emulator: Emulator, settings: Settings)
+ private external fun nativeDestructor()
+ private external fun nativeOnSurfaceCreated()
+ private external fun nativeOnSurfaceChanged(width: Int, height: Int)
+ private external fun nativeOnDrawFrame()
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/simongellis/vvb/game/GameActivity.kt b/app/src/main/java/com/simongellis/vvb/game/GameActivity.kt
index da6015a1..bcb4356f 100644
--- a/app/src/main/java/com/simongellis/vvb/game/GameActivity.kt
+++ b/app/src/main/java/com/simongellis/vvb/game/GameActivity.kt
@@ -35,7 +35,7 @@ class GameActivity : AppCompatActivity() {
_audio = Audio(emulator, _preferences.audioSettings)
_controller = Controller(emulator)
- _view = GameView(baseContext)
+ _view = GameView(this)
requestedOrientation = _view.requestedOrientation
_view.controller = _controller
setContentView(_view)
diff --git a/app/src/main/java/com/simongellis/vvb/game/GamePreferences.kt b/app/src/main/java/com/simongellis/vvb/game/GamePreferences.kt
index 61b65303..1b25bfd6 100644
--- a/app/src/main/java/com/simongellis/vvb/game/GamePreferences.kt
+++ b/app/src/main/java/com/simongellis/vvb/game/GamePreferences.kt
@@ -74,6 +74,9 @@ class GamePreferences(context: Context) {
val stereoSettings
get() = StereoRenderer.Settings(screenZoom, aspectRatio.ordinal, verticalOffset, color)
+ val cnsdkSettings
+ get() = CNSDKRenderer.Settings(screenZoom, aspectRatio.ordinal, verticalOffset, color)
+
val leiaSettings
get() = LeiaRenderer.Settings(screenZoom, aspectRatio.ordinal, verticalOffset, color, colorBG)
@@ -83,7 +86,7 @@ class GamePreferences(context: Context) {
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
- val displayManager = LeiaSDK.getDisplayManager(context)
+ val displayManager = true//LeiaSDK.getDisplayManager(context)
var defaultMode = VideoMode.ANAGLYPH.name
var defaultScreenZoom = 100
if(displayManager !== null){
diff --git a/app/src/main/java/com/simongellis/vvb/game/GameView.kt b/app/src/main/java/com/simongellis/vvb/game/GameView.kt
index f9811342..a1cfb533 100644
--- a/app/src/main/java/com/simongellis/vvb/game/GameView.kt
+++ b/app/src/main/java/com/simongellis/vvb/game/GameView.kt
@@ -1,9 +1,9 @@
package com.simongellis.vvb.game
+import android.app.Activity
import android.content.Context
import android.content.pm.ActivityInfo
import android.graphics.Color
-import android.util.AttributeSet
import android.view.LayoutInflater
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.isVisible
@@ -19,7 +19,7 @@ import com.leia.android.lights.BacklightModeListener
import com.leia.android.lights.LeiaDisplayManager.BacklightMode.MODE_2D
import com.leia.android.lights.LeiaDisplayManager.BacklightMode.MODE_3D
-class GameView : ConstraintLayout, BacklightModeListener {
+class GameView(context: Context) : ConstraintLayout(context), BacklightModeListener {
private val _binding: GameViewBinding
private val _renderer: Renderer
private val _preferences: GamePreferences
@@ -38,12 +38,6 @@ class GameView : ConstraintLayout, BacklightModeListener {
private val _surfaceView: SurfaceViewAdapter
get() = _binding.surfaceView as SurfaceViewAdapter
- constructor(context: Context) : super(context)
- constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
- constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
- @Suppress("unused")
- constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)
-
init {
val emulator = Emulator.instance
_preferences = GamePreferences(context)
@@ -53,7 +47,7 @@ class GameView : ConstraintLayout, BacklightModeListener {
VideoMode.MONO_LEFT -> MonoRenderer(emulator, _preferences.monoSettings(Eye.LEFT))
VideoMode.MONO_RIGHT -> MonoRenderer(emulator, _preferences.monoSettings(Eye.RIGHT))
VideoMode.STEREO -> StereoRenderer(emulator, _preferences.stereoSettings)
- VideoMode.LEIA -> LeiaRenderer(emulator, _preferences.leiaSettings)
+ VideoMode.LEIA -> CNSDKRenderer(emulator, _preferences.cnsdkSettings)
}
val layoutInflater = LayoutInflater.from(context)
@@ -77,11 +71,14 @@ class GameView : ConstraintLayout, BacklightModeListener {
setBackgroundColor(Color.BLACK)
+ /*
mDisplayManager = LeiaSDK.getDisplayManager(context)
mDisplayManager?.apply {
registerBacklightModeListener(this@GameView)
checkShouldToggle3D(true)
}
+
+ */
}
fun onPause() {
@@ -124,10 +121,10 @@ class GameView : ConstraintLayout, BacklightModeListener {
}
private fun enable3D() {
- mDisplayManager?.requestBacklightMode(MODE_3D)
+ //mDisplayManager?.requestBacklightMode(MODE_3D)
}
private fun disable3D() {
- mDisplayManager?.requestBacklightMode(MODE_2D)
+ //mDisplayManager?.requestBacklightMode(MODE_2D)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/simongellis/vvb/game/PreviewActivity.kt b/app/src/main/java/com/simongellis/vvb/game/PreviewActivity.kt
index c7f203d8..75f48dd5 100644
--- a/app/src/main/java/com/simongellis/vvb/game/PreviewActivity.kt
+++ b/app/src/main/java/com/simongellis/vvb/game/PreviewActivity.kt
@@ -18,7 +18,7 @@ class PreviewActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
VvbLibrary.instance.initialize(this)
- _view = GameView(baseContext)
+ _view = GameView(this)
_preferences = GamePreferences(baseContext)
requestedOrientation = _view.requestedOrientation
setContentView(_view)
diff --git a/app/src/main/java/com/simongellis/vvb/menu/VideoMenuFragment.kt b/app/src/main/java/com/simongellis/vvb/menu/VideoMenuFragment.kt
index 78fa0da2..1f36e994 100644
--- a/app/src/main/java/com/simongellis/vvb/menu/VideoMenuFragment.kt
+++ b/app/src/main/java/com/simongellis/vvb/menu/VideoMenuFragment.kt
@@ -60,7 +60,7 @@ class VideoMenuFragment: PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.preferences_video, rootKey)
var defaultModeName = VideoMode.ANAGLYPH.name
- val leiaDisplayManager = LeiaSDK.getDisplayManager(context)
+ val leiaDisplayManager = true//LeiaSDK.getDisplayManager(context)
var defaultBGColor = ContextCompat.getColor(requireContext(), R.color.black)
var defaultScreenZoom = 100
if(leiaDisplayManager !== null){
diff --git a/leia-cnsdk/.gitignore b/leia-cnsdk/.gitignore
new file mode 100644
index 00000000..42afabfd
--- /dev/null
+++ b/leia-cnsdk/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/leia-cnsdk/build.gradle b/leia-cnsdk/build.gradle
new file mode 100644
index 00000000..810b7f62
--- /dev/null
+++ b/leia-cnsdk/build.gradle
@@ -0,0 +1,2 @@
+configurations.maybeCreate("default")
+artifacts.add("default", file('cnsdk.aar'))
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
index 6e2ceea3..0010ed6f 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,3 +1,4 @@
include ':cardboard-sdk'
+include ':leia-cnsdk'
include ':app'
rootProject.name = "Virtual Virtual Boy"
\ No newline at end of file
diff --git a/src/video/renderers.rs b/src/video/renderers.rs
index 95095f45..2a663b9b 100644
--- a/src/video/renderers.rs
+++ b/src/video/renderers.rs
@@ -1,5 +1,6 @@
mod anaglyph;
mod cardboard;
+mod cnsdk;
mod common;
mod gl;
mod leia;
@@ -9,6 +10,7 @@ mod stereo;
pub mod jni {
pub use super::anaglyph::jni::*;
pub use super::cardboard::jni::*;
+ pub use super::cnsdk::jni::*;
pub use super::leia::jni::*;
pub use super::mono::jni::*;
pub use super::stereo::jni::*;
diff --git a/src/video/renderers/cnsdk.rs b/src/video/renderers/cnsdk.rs
new file mode 100644
index 00000000..b8978e23
--- /dev/null
+++ b/src/video/renderers/cnsdk.rs
@@ -0,0 +1,218 @@
+use super::common::RenderLogic;
+use super::gl::{
+ utils::{self, VB_HEIGHT, VB_WIDTH},
+ AspectRatio, Program, Textures,
+};
+use crate::emulator::video::Eye;
+use crate::video::gl::types::{GLfloat, GLint, GLuint};
+
+use anyhow::Result;
+use cgmath::{self, vec3, Matrix4};
+
+const VERTEX_SHADER: &str = "\
+attribute vec4 a_Pos;
+attribute vec2 a_TexCoord;
+uniform mat4 u_MV;
+varying vec2 v_TexCoord;
+void main() {
+ gl_Position = u_MV * a_Pos;
+ v_TexCoord = vec2(a_TexCoord.x, 1.0 - a_TexCoord.y);
+}
+";
+
+const FRAGMENT_SHADER: &str = "\
+precision mediump float;
+varying vec2 v_TexCoord;
+uniform sampler2D u_Texture;
+uniform vec4 u_Color;
+void main() {
+ gl_FragColor = u_Color * texture2D(u_Texture, v_TexCoord).r;
+}
+";
+
+pub struct CNSDKRenderLogic {
+ program: Program,
+ textures: Textures,
+
+ position_location: GLuint,
+ tex_coord_location: GLuint,
+ modelview_location: GLint,
+ texture_location: GLint,
+ color_location: GLint,
+
+ texture_color: [GLfloat; 4],
+ aspect_ratio: AspectRatio,
+ transforms: [Matrix4; 2],
+ model_views: [[GLfloat; 16]; 2],
+}
+impl CNSDKRenderLogic {
+ pub fn new(settings: &Settings) -> Self {
+ let zoom = settings.screen_zoom;
+ let offset = -settings.vertical_offset;
+ Self {
+ program: Program::new(VERTEX_SHADER, FRAGMENT_SHADER),
+ textures: Textures::new(2, (VB_WIDTH, VB_HEIGHT)),
+
+ position_location: 0,
+ tex_coord_location: 0,
+ modelview_location: -1,
+ texture_location: -1,
+ color_location: -1,
+
+ texture_color: utils::color_as_vector(settings.color),
+ aspect_ratio: settings.aspect_ratio,
+ transforms: [
+ Matrix4::from_translation(vec3(-0.5, offset, 0.0)) * Matrix4::from_scale(zoom),
+ Matrix4::from_translation(vec3(0.5, offset, 0.0)) * Matrix4::from_scale(zoom),
+ ],
+ model_views: [utils::identity_matrix(), utils::identity_matrix()],
+ }
+ }
+}
+
+impl RenderLogic for CNSDKRenderLogic {
+ fn init(&mut self) -> Result<()> {
+ self.program.init()?;
+ self.textures.init()?;
+
+ self.position_location = self.program.get_attribute_location("a_Pos");
+ self.tex_coord_location = self.program.get_attribute_location("a_TexCoord");
+ self.modelview_location = self.program.get_uniform_location("u_MV");
+ self.texture_location = self.program.get_uniform_location("u_Texture");
+ self.color_location = self.program.get_uniform_location("u_Color");
+
+ // Set color here, because it's the same for the entire life of the program
+ self.program
+ .set_uniform_vector(self.color_location, &self.texture_color);
+
+ Ok(())
+ }
+
+ fn resize(&mut self, screen_size: (i32, i32)) -> Result<()> {
+ self.program.set_viewport(screen_size)?;
+
+ let base_mv = self
+ .aspect_ratio
+ .compute_mvp_matrix(screen_size, (VB_WIDTH * 2, VB_HEIGHT));
+ self.model_views = [
+ utils::to_matrix(base_mv * self.transforms[0]),
+ utils::to_matrix(base_mv * self.transforms[1]),
+ ];
+
+ Ok(())
+ }
+
+ fn update(&mut self, eye: Eye, buffer: &[u8]) -> Result<()> {
+ self.textures.update(eye as usize, buffer)
+ }
+
+ fn draw(&self) -> Result<()> {
+ self.program.start_render()?;
+ for i in 0..self.textures.ids.len() {
+ let texture_id = self.textures.ids[i];
+ let model_view = &self.model_views[i];
+
+ self.program
+ .set_uniform_texture(self.texture_location, texture_id);
+ self.program
+ .set_uniform_matrix(self.modelview_location, model_view);
+
+ self.program
+ .draw_square(self.position_location, self.tex_coord_location)?;
+ }
+ Ok(())
+ }
+}
+
+#[derive(Debug)]
+pub struct Settings {
+ pub screen_zoom: f32,
+ pub aspect_ratio: AspectRatio,
+ pub vertical_offset: f32,
+ pub color: (u8, u8, u8),
+}
+
+#[rustfmt::skip::macros(jni_func)]
+pub mod jni {
+ use super::{CNSDKRenderLogic, Settings};
+ use crate::emulator::jni::get_emulator;
+ use crate::jni_helpers::{JavaBinding, JavaGetResult};
+ use crate::video::renderers::common::Renderer;
+ use crate::{jni_func, EnvExtensions};
+ use anyhow::Result;
+ use jni::objects::JObject;
+ use jni::sys::jint;
+ use jni::JNIEnv;
+ use std::convert::TryInto;
+
+ type CNSDKRenderer = Renderer;
+
+ static CNSDK_BINDING: JavaBinding = JavaBinding::new();
+
+ pub fn get_settings<'a>(env: &mut JNIEnv<'a>, this: JObject<'a>) -> Result {
+ let screen_zoom = env.get_percent(&this, "screenZoom")?;
+ let aspect_ratio = env.get_int(&this, "aspectRatio")?.try_into()?;
+ let vertical_offset = env.get_percent(&this, "verticalOffset")?;
+ let color = env.get_color(&this, "color")?;
+
+ Ok(Settings {
+ screen_zoom,
+ aspect_ratio,
+ vertical_offset,
+ color,
+ })
+ }
+
+ fn get_renderer<'a>(
+ env: &'a mut JNIEnv,
+ this: JObject<'a>,
+ ) -> JavaGetResult<'a, CNSDKRenderer> {
+ CNSDK_BINDING.get_value(env, this)
+ }
+
+ jni_func!(CNSDKRenderer_nativeConstructor, constructor, JObject<'a>, JObject<'a>);
+ fn constructor<'a>(
+ env: &mut JNIEnv<'a>,
+ this: JObject<'a>,
+ emulator: JObject<'a>,
+ settings: JObject<'a>,
+ ) -> Result<()> {
+ let settings = get_settings(env, settings)?;
+ let renderer = {
+ let mut emulator = get_emulator(env, emulator)?;
+ Renderer::new(
+ emulator.claim_frame_buffer_consumers(),
+ CNSDKRenderLogic::new(&settings),
+ )
+ };
+ CNSDK_BINDING.init_value(env, this, renderer)
+ }
+
+ jni_func!(CNSDKRenderer_nativeDestructor, destructor);
+ fn destructor(env: &mut JNIEnv, this: JObject) -> Result<()> {
+ CNSDK_BINDING.drop_value(env, this)
+ }
+
+ jni_func!(CNSDKRenderer_nativeOnSurfaceCreated, on_surface_created);
+ fn on_surface_created(env: &mut JNIEnv, this: JObject) -> Result<()> {
+ let mut this = get_renderer(env, this)?;
+ this.on_surface_created()
+ }
+
+ jni_func!(CNSDKRenderer_nativeOnSurfaceChanged, on_surface_changed, jint, jint);
+ fn on_surface_changed(
+ env: &mut JNIEnv,
+ this: JObject,
+ width: jint,
+ height: jint,
+ ) -> Result<()> {
+ let mut this = get_renderer(env, this)?;
+ this.on_surface_changed(width, height)
+ }
+
+ jni_func!(CNSDKRenderer_nativeOnDrawFrame, on_draw_frame);
+ fn on_draw_frame(env: &mut JNIEnv, this: JObject) -> Result<()> {
+ let mut this = get_renderer(env, this)?;
+ this.on_draw_frame()
+ }
+}