-
-
Notifications
You must be signed in to change notification settings - Fork 477
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
383 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
#![allow(dead_code)] | ||
#![allow(non_snake_case)] | ||
#![allow(non_camel_case_types)] | ||
|
||
use libc; | ||
|
||
pub type EM_BOOL = libc::c_int; | ||
pub type EM_UTF8 = libc::c_char; | ||
pub type EMSCRIPTEN_WEBGL_CONTEXT_HANDLE = libc::c_int; | ||
pub type EMSCRIPTEN_RESULT = libc::c_int; | ||
|
||
pub type em_webgl_context_callback = extern fn(libc::c_int, *const libc::c_void, *mut libc::c_void) | ||
-> EM_BOOL; | ||
|
||
#[repr(C)] | ||
pub struct EmscriptenWebGLContextAttributes { | ||
pub alpha: EM_BOOL, | ||
pub depth: EM_BOOL, | ||
pub stencil: EM_BOOL, | ||
pub antialias: EM_BOOL, | ||
pub premultipliedAlpha: EM_BOOL, | ||
pub preserveDrawingBuffer: EM_BOOL, | ||
pub preferLowPowerToHighPerformance: EM_BOOL, | ||
pub failIfMajorPerformanceCaveat: EM_BOOL, | ||
pub majorVersion: libc::c_int, | ||
pub minorVersion: libc::c_int, | ||
pub enableExtensionsByDefault: EM_BOOL, | ||
} | ||
|
||
// values for EMSCRIPTEN_RESULT | ||
pub const EMSCRIPTEN_RESULT_SUCCESS: libc::c_int = 0; | ||
pub const EMSCRIPTEN_RESULT_DEFERRED: libc::c_int = 1; | ||
pub const EMSCRIPTEN_RESULT_NOT_SUPPORTED: libc::c_int = -1; | ||
pub const EMSCRIPTEN_RESULT_FAILED_NOT_DEFERRED: libc::c_int = -2; | ||
pub const EMSCRIPTEN_RESULT_INVALID_TARGET: libc::c_int = -3; | ||
pub const EMSCRIPTEN_RESULT_UNKNOWN_TARGET: libc::c_int = -4; | ||
pub const EMSCRIPTEN_RESULT_INVALID_PARAM: libc::c_int = -5; | ||
pub const EMSCRIPTEN_RESULT_FAILED: libc::c_int = -6; | ||
pub const EMSCRIPTEN_RESULT_NO_DATA: libc::c_int = -7; | ||
|
||
extern { | ||
pub fn emscripten_webgl_init_context_attributes(attributes: *mut EmscriptenWebGLContextAttributes); | ||
pub fn emscripten_webgl_create_context(target: *const libc::c_char, | ||
attributes: *const EmscriptenWebGLContextAttributes) -> EMSCRIPTEN_WEBGL_CONTEXT_HANDLE; | ||
|
||
pub fn emscripten_webgl_make_context_current(context: EMSCRIPTEN_WEBGL_CONTEXT_HANDLE) | ||
-> EMSCRIPTEN_RESULT; | ||
|
||
pub fn emscripten_webgl_get_current_context() -> EMSCRIPTEN_WEBGL_CONTEXT_HANDLE; | ||
|
||
pub fn emscripten_webgl_destroy_context(context: EMSCRIPTEN_WEBGL_CONTEXT_HANDLE) | ||
-> EMSCRIPTEN_RESULT; | ||
|
||
pub fn emscripten_webgl_enable_extension(context: EMSCRIPTEN_WEBGL_CONTEXT_HANDLE, | ||
extension: *const libc::c_char) -> EM_BOOL; | ||
|
||
pub fn emscripten_set_webglcontextlost_callback(target: *const libc::c_char, | ||
userData: *mut libc::c_void, useCapture: EM_BOOL, callback: em_webgl_context_callback) | ||
-> EMSCRIPTEN_RESULT; | ||
pub fn emscripten_set_webglcontextrestored_callback(target: *const libc::c_char, | ||
userData: *mut libc::c_void, useCapture: EM_BOOL, callback: em_webgl_context_callback) | ||
-> EMSCRIPTEN_RESULT; | ||
|
||
pub fn emscripten_is_webgl_context_lost(target: *const libc::c_char) -> EM_BOOL; | ||
|
||
// note: this function is not documented but is used by the ports of glfw, SDL and EGL | ||
pub fn emscripten_GetProcAddress(name: *const libc::c_char) -> *const libc::c_void; | ||
|
||
|
||
pub fn emscripten_request_fullscreen(target: *const libc::c_char, | ||
deferUntilInEventHandler: EM_BOOL) -> EMSCRIPTEN_RESULT; | ||
|
||
pub fn emscripten_exit_fullscreen() -> EMSCRIPTEN_RESULT; | ||
|
||
pub fn emscripten_set_element_css_size(target: *const libc::c_char, width: libc::c_double, | ||
height: libc::c_double) -> EMSCRIPTEN_RESULT; | ||
|
||
pub fn emscripten_get_element_css_size(target: *const libc::c_char, width: *mut libc::c_double, | ||
height: *mut libc::c_double) -> EMSCRIPTEN_RESULT; | ||
|
||
pub fn emscripten_sleep(delay: libc::c_uint); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,251 @@ | ||
#![cfg(target_os = "emscripten")] | ||
|
||
use std::ffi::CString; | ||
use libc; | ||
use {Event, BuilderAttribs, CreationError, MouseCursor}; | ||
use Api; | ||
use PixelFormat; | ||
use GlContext; | ||
|
||
use std::collections::VecDeque; | ||
|
||
mod ffi; | ||
|
||
pub struct Window { | ||
context: ffi::EMSCRIPTEN_WEBGL_CONTEXT_HANDLE, | ||
} | ||
|
||
pub struct PollEventsIterator<'a> { | ||
window: &'a Window, | ||
} | ||
|
||
impl<'a> Iterator for PollEventsIterator<'a> { | ||
type Item = Event; | ||
|
||
fn next(&mut self) -> Option<Event> { | ||
None | ||
} | ||
} | ||
|
||
pub struct WaitEventsIterator<'a> { | ||
window: &'a Window, | ||
} | ||
|
||
impl<'a> Iterator for WaitEventsIterator<'a> { | ||
type Item = Event; | ||
|
||
fn next(&mut self) -> Option<Event> { | ||
None | ||
} | ||
} | ||
|
||
#[derive(Clone)] | ||
pub struct WindowProxy; | ||
|
||
impl WindowProxy { | ||
pub fn wakeup_event_loop(&self) { | ||
unimplemented!() | ||
} | ||
} | ||
|
||
pub struct MonitorID; | ||
|
||
pub fn get_available_monitors() -> VecDeque<MonitorID> { | ||
let mut list = VecDeque::new(); | ||
list.push_back(MonitorID); | ||
list | ||
} | ||
|
||
pub fn get_primary_monitor() -> MonitorID { | ||
MonitorID | ||
} | ||
|
||
impl MonitorID { | ||
pub fn get_name(&self) -> Option<String> { | ||
Some("Canvas".to_string()) | ||
} | ||
|
||
pub fn get_dimensions(&self) -> (u32, u32) { | ||
unimplemented!() | ||
} | ||
} | ||
|
||
impl Window { | ||
pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> { | ||
// getting the default values of attributes | ||
let mut attributes = unsafe { | ||
use std::mem; | ||
let mut attributes: ffi::EmscriptenWebGLContextAttributes = mem::uninitialized(); | ||
ffi::emscripten_webgl_init_context_attributes(&mut attributes); | ||
attributes | ||
}; | ||
|
||
// setting the attributes | ||
// FIXME: | ||
/*match builder.gl_version { | ||
Some((major, minor)) => { | ||
attributes.majorVersion = major as libc::c_int; | ||
attributes.minorVersion = minor as libc::c_int; | ||
}, | ||
None => () | ||
};*/ | ||
|
||
// creating the context | ||
let context = unsafe { | ||
use std::{mem, ptr}; | ||
let context = ffi::emscripten_webgl_create_context(ptr::null(), &attributes); | ||
if context <= 0 { | ||
return Err(CreationError::OsError(format!("Error while calling emscripten_webgl_create_context: {}", | ||
error_to_str(mem::transmute(context))))); | ||
} | ||
context | ||
}; | ||
|
||
// TODO: emscripten_set_webglcontextrestored_callback | ||
|
||
Ok(Window { | ||
context: context | ||
}) | ||
} | ||
|
||
pub fn is_closed(&self) -> bool { | ||
use std::ptr; | ||
unsafe { ffi::emscripten_is_webgl_context_lost(ptr::null()) != 0 } | ||
} | ||
|
||
pub fn set_title(&self, _title: &str) { | ||
} | ||
|
||
pub fn get_position(&self) -> Option<(i32, i32)> { | ||
Some((0, 0)) | ||
} | ||
|
||
pub fn set_position(&self, _: i32, _: i32) { | ||
} | ||
|
||
pub fn get_inner_size(&self) -> Option<(u32, u32)> { | ||
unsafe { | ||
use std::{mem, ptr}; | ||
let mut width = mem::uninitialized(); | ||
let mut height = mem::uninitialized(); | ||
|
||
if ffi::emscripten_get_element_css_size(ptr::null(), &mut width, &mut height) | ||
!= ffi::EMSCRIPTEN_RESULT_SUCCESS | ||
{ | ||
None | ||
} else { | ||
Some((width as u32, height as u32)) | ||
} | ||
} | ||
} | ||
|
||
pub fn get_outer_size(&self) -> Option<(u32, u32)> { | ||
self.get_inner_size() | ||
} | ||
|
||
pub fn set_inner_size(&self, width: u32, height: u32) { | ||
unsafe { | ||
use std::ptr; | ||
ffi::emscripten_set_element_css_size(ptr::null(), width as libc::c_double, height | ||
as libc::c_double); | ||
} | ||
} | ||
|
||
pub fn poll_events(&self) -> PollEventsIterator { | ||
PollEventsIterator { | ||
window: self, | ||
} | ||
} | ||
|
||
pub fn wait_events(&self) -> WaitEventsIterator { | ||
WaitEventsIterator { | ||
window: self, | ||
} | ||
} | ||
|
||
pub fn create_window_proxy(&self) -> WindowProxy { | ||
WindowProxy | ||
} | ||
|
||
pub fn show(&self) {} | ||
pub fn hide(&self) {} | ||
|
||
pub fn platform_display(&self) -> *mut libc::c_void { | ||
unimplemented!() | ||
} | ||
|
||
pub fn platform_window(&self) -> *mut libc::c_void { | ||
unimplemented!() | ||
} | ||
|
||
pub fn set_window_resize_callback(&mut self, _: Option<fn(u32, u32)>) { | ||
} | ||
|
||
pub fn set_cursor(&self, _cursor: MouseCursor) { | ||
unimplemented!() | ||
} | ||
|
||
pub fn hidpi_factor(&self) -> f32 { | ||
1.0 | ||
} | ||
} | ||
|
||
impl GlContext for Window { | ||
unsafe fn make_current(&self) { | ||
// TOOD: check if == EMSCRIPTEN_RESULT | ||
ffi::emscripten_webgl_make_context_current(self.context); | ||
} | ||
|
||
fn is_current(&self) -> bool { | ||
true // FIXME: | ||
} | ||
|
||
fn get_proc_address(&self, addr: &str) -> *const libc::c_void { | ||
let addr = CString::new(addr.as_bytes()).unwrap(); | ||
let addr = addr.as_ptr(); | ||
|
||
unsafe { | ||
ffi::emscripten_GetProcAddress(addr) as *const _ | ||
} | ||
} | ||
|
||
fn swap_buffers(&self) { | ||
unsafe { | ||
ffi::emscripten_sleep(1); // FIXME: | ||
} | ||
} | ||
|
||
fn get_api(&self) -> Api { | ||
Api::WebGl | ||
} | ||
|
||
fn get_pixel_format(&self) -> PixelFormat { | ||
unimplemented!(); | ||
} | ||
} | ||
|
||
impl Drop for Window { | ||
fn drop(&mut self) { | ||
unsafe { | ||
ffi::emscripten_exit_fullscreen(); | ||
ffi::emscripten_webgl_destroy_context(self.context); | ||
} | ||
} | ||
} | ||
|
||
fn error_to_str(code: ffi::EMSCRIPTEN_RESULT) -> &'static str { | ||
match code { | ||
ffi::EMSCRIPTEN_RESULT_SUCCESS | ffi::EMSCRIPTEN_RESULT_DEFERRED | ||
=> "Internal error in the library (success detected as failure)", | ||
|
||
ffi::EMSCRIPTEN_RESULT_NOT_SUPPORTED => "Not supported", | ||
ffi::EMSCRIPTEN_RESULT_FAILED_NOT_DEFERRED => "Failed not deferred", | ||
ffi::EMSCRIPTEN_RESULT_INVALID_TARGET => "Invalid target", | ||
ffi::EMSCRIPTEN_RESULT_UNKNOWN_TARGET => "Unknown target", | ||
ffi::EMSCRIPTEN_RESULT_INVALID_PARAM => "Invalid parameter", | ||
ffi::EMSCRIPTEN_RESULT_FAILED => "Failed", | ||
ffi::EMSCRIPTEN_RESULT_NO_DATA => "No data", | ||
|
||
_ => "Undocumented error" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
#![cfg(target_os = "emscripten")] | ||
|
||
use GlContext; | ||
|
||
pub use api::emscripten::{Window, WindowProxy, MonitorID, get_available_monitors}; | ||
pub use api::emscripten::{get_primary_monitor, WaitEventsIterator, PollEventsIterator}; | ||
|
||
#[cfg(feature = "headless")] | ||
pub struct HeadlessContext(Window); | ||
|
||
#[cfg(feature = "headless")] | ||
impl HeadlessContext { | ||
/// See the docs in the crate root file. | ||
pub fn new(builder: BuilderAttribs) -> Result<HeadlessContext, CreationError> { | ||
Window::new(builder).map(|w| HeadlessContext(w)) | ||
} | ||
} | ||
|
||
#[cfg(feature = "headless")] | ||
impl GlContext for HeadlessContext { | ||
unsafe fn make_current(&self) { | ||
self.0.make_current() | ||
} | ||
|
||
fn is_current(&self) -> bool { | ||
self.0.is_current() | ||
} | ||
|
||
fn get_proc_address(&self, addr: &str) -> *const libc::c_void { | ||
self.0.get_proc_address(addr) | ||
} | ||
|
||
fn swap_buffers(&self) { | ||
self.0.swap_buffers() | ||
} | ||
|
||
fn get_api(&self) -> Api { | ||
self.0.get_api() | ||
} | ||
|
||
fn get_pixel_format(&self) -> PixelFormat { | ||
self.0.get_pixel_format() | ||
} | ||
} | ||
|
||
#[cfg(feature = "headless")] | ||
unsafe impl Send for HeadlessContext {} | ||
#[cfg(feature = "headless")] | ||
unsafe impl Sync for HeadlessContext {} |