-
-
Notifications
You must be signed in to change notification settings - Fork 79
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Postponed: Experimentally render to an Android surface #99
base: main
Are you sure you want to change the base?
Changes from all commits
7b6ca43
b550e39
707c193
5dbff6d
7378764
ad48810
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,43 @@ | ||
package com.example.demo | ||
|
||
import androidx.appcompat.app.AppCompatActivity | ||
import android.os.Bundle | ||
import android.util.Log | ||
import android.view.SurfaceHolder | ||
import android.view.SurfaceView | ||
import android.view.View | ||
import androidx.appcompat.app.AppCompatActivity | ||
import org.maplibre_rs.MapLibreRs | ||
|
||
// Currently not used. Instead the NativeActivity referenced in AndroidManifest.xml is used. | ||
|
||
class MainActivity : AppCompatActivity() { | ||
|
||
var mSurfaceView1: SurfaceView? = null | ||
var mSurfaceHolder1: SurfaceHolder? = null | ||
|
||
override fun onCreate(savedInstanceState: Bundle?) { | ||
super.onCreate(savedInstanceState) | ||
setContentView(R.layout.activity_main) | ||
MapLibreRs.android_main() | ||
|
||
mSurfaceView1 = findViewById<View>(R.id.surfaceView1) as SurfaceView | ||
mSurfaceHolder1 = mSurfaceView1!!.getHolder() | ||
|
||
mSurfaceHolder1!!.addCallback(object : SurfaceHolder.Callback { | ||
override fun surfaceCreated(p0: SurfaceHolder) { | ||
Log.v("TAG", "surfaceCreated") | ||
MapLibreRs.android_main(p0.surface) | ||
} | ||
|
||
override fun surfaceChanged(p0: SurfaceHolder, p1: Int, p2: Int, p3: Int) { | ||
Log.v( | ||
"TAG", "surfaceChanged format=" + p1 + ", width=" + p2 + ", height=" | ||
+ p3 | ||
) | ||
} | ||
|
||
override fun surfaceDestroyed(p0: SurfaceHolder) { | ||
Log.v("TAG", "surfaceDestroyed") | ||
} | ||
}) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
use jni::objects::JObject; | ||
use jni::JNIEnv; | ||
use maplibre::error::Error; | ||
use maplibre::io::scheduler::ScheduleMethod; | ||
use maplibre::io::source_client::HttpClient; | ||
use maplibre::map_schedule::InteractiveMapSchedule; | ||
use ndk::native_window::NativeWindow; | ||
use raw_window_handle::{AndroidNdkHandle, RawWindowHandle}; | ||
use std::marker::PhantomData; | ||
use std::thread::sleep; | ||
use std::time::Duration; | ||
|
||
use maplibre::window::{EventLoop, HeadedMapWindow, MapWindow, MapWindowConfig, WindowSize}; | ||
|
||
pub struct AndroidNativeWindow { | ||
window: NativeWindow, | ||
} | ||
|
||
pub struct AndroidMapWindowConfig<'a> { | ||
env: JNIEnv<'a>, | ||
surface: JObject<'a>, | ||
} | ||
|
||
unsafe impl raw_window_handle::HasRawWindowHandle for AndroidNativeWindow { | ||
fn raw_window_handle(&self) -> RawWindowHandle { | ||
let mut handle = AndroidNdkHandle::empty(); | ||
handle.a_native_window = unsafe { self.window.ptr().as_mut() as *mut _ as *mut _ }; | ||
RawWindowHandle::AndroidNdk(handle) | ||
} | ||
} | ||
Comment on lines
+24
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, let me add the bindings for this one directly on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. rust-mobile/ndk#274 Hopefully this simplifies things a bit for you, too :) |
||
|
||
impl<'a> AndroidMapWindowConfig<'a> { | ||
pub fn new(env: JNIEnv<'a>, surface: JObject<'a>) -> Self { | ||
Self { env, surface } | ||
} | ||
} | ||
|
||
impl<'a> MapWindowConfig for AndroidMapWindowConfig<'a> { | ||
type MapWindow = AndroidMapWindow<'a>; | ||
|
||
fn create(&self) -> Self::MapWindow { | ||
let window = unsafe { | ||
NativeWindow::from_surface(self.env.get_native_interface(), self.surface.into_inner()) | ||
} | ||
.unwrap(); | ||
|
||
Self::MapWindow { | ||
window: AndroidNativeWindow { window }, | ||
phantom: Default::default(), | ||
} | ||
} | ||
} | ||
|
||
pub struct AndroidMapWindow<'a> { | ||
window: AndroidNativeWindow, | ||
phantom: PhantomData<&'a u32>, | ||
} | ||
|
||
impl AndroidMapWindow<'_> { | ||
pub fn take_event_loop(&mut self) -> Option<()> { | ||
Some(()) | ||
} | ||
} | ||
|
||
impl<'a, MWC, SM, HC> EventLoop<MWC, SM, HC> for AndroidMapWindow<'a> | ||
where | ||
MWC: MapWindowConfig<MapWindow = AndroidMapWindow<'a>>, | ||
SM: ScheduleMethod, | ||
HC: HttpClient, | ||
{ | ||
fn run( | ||
mut self, | ||
mut map_schedule: InteractiveMapSchedule<MWC, SM, HC>, | ||
max_frames: Option<u64>, | ||
) { | ||
for i in 0..100 { | ||
map_schedule.update_and_redraw(); | ||
sleep(Duration::from_millis(16)) | ||
} | ||
|
||
match map_schedule.update_and_redraw() { | ||
Ok(_) => {} | ||
Err(Error::Render(e)) => { | ||
eprintln!("{}", e); | ||
} | ||
e => eprintln!("{:?}", e), | ||
}; | ||
|
||
let size = self.size(); | ||
map_schedule.resize(size.width(), size.height()); // FIXME: Resumed is also called when the app launches for the first time. Instead of first using a "fake" inner_size() in State::new we should initialize with a proper size from the beginning | ||
map_schedule.resume(&self); | ||
} | ||
} | ||
|
||
impl<'a> MapWindow for AndroidMapWindow<'a> { | ||
fn size(&self) -> WindowSize { | ||
WindowSize::new(100, 100).unwrap() | ||
} | ||
} | ||
|
||
impl<'a> HeadedMapWindow for AndroidMapWindow<'a> { | ||
type RawWindow = AndroidNativeWindow; | ||
|
||
fn inner(&self) -> &Self::RawWindow { | ||
&self.window | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CC rust-mobile/ndk#281, perhaps we should move this out of
ndk_glue
and make it generic :)Perhaps some unification with the
android_logger
crate too.