diff options
author | Anthony Ramine <n.oxyde@gmail.com> | 2018-03-23 16:26:02 +0100 |
---|---|---|
committer | Anthony Ramine <n.oxyde@gmail.com> | 2018-03-23 17:32:42 +0100 |
commit | a77d35b60c5e9b01f868daff510fbb7e44ca1bbc (patch) | |
tree | ac9c0c351334236289aa44e23cefb1467a8896b3 /components/script | |
parent | 4a6453ac9ad956502ec6d39093b83820d94a409e (diff) | |
download | servo-a77d35b60c5e9b01f868daff510fbb7e44ca1bbc.tar.gz servo-a77d35b60c5e9b01f868daff510fbb7e44ca1bbc.zip |
Implement HTMLCanvasElement.toDataURL for WebGL canvas (fixes #19147)
Diffstat (limited to 'components/script')
-rw-r--r-- | components/script/dom/htmlcanvaselement.rs | 13 | ||||
-rw-r--r-- | components/script/dom/webglrenderingcontext.rs | 33 |
2 files changed, 45 insertions, 1 deletions
diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs index c866664cbcf..b1bea124a7b 100644 --- a/components/script/dom/htmlcanvaselement.rs +++ b/components/script/dom/htmlcanvaselement.rs @@ -345,11 +345,22 @@ impl HTMLCanvasElementMethods for HTMLCanvasElement { Finite::wrap(self.Height() as f64))?; image_data.get_data_array() } + Some(CanvasContext::WebGL(ref context)) => { + match context.get_image_data(self.Width(), self.Height()) { + Some(data) => data, + None => return Ok("data:,".into()), + } + } + Some(CanvasContext::WebGL2(ref context)) => { + match context.base_context().get_image_data(self.Width(), self.Height()) { + Some(data) => data, + None => return Ok("data:,".into()), + } + } None => { // Each pixel is fully-transparent black. vec![0; (self.Width() * self.Height() * 4) as usize] } - _ => return Err(Error::NotSupported) // WebGL }; // Only handle image/png for now. diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 37d117a93fd..8d3801c36e3 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -56,6 +56,7 @@ use offscreen_gl_context::{GLContextAttributes, GLLimits}; use script_layout_interface::HTMLCanvasDataSource; use servo_config::prefs::PREFS; use std::cell::{Cell, Ref}; +use std::cmp; use std::iter::FromIterator; use std::ptr::NonNull; use webrender_api; @@ -1157,6 +1158,38 @@ impl WebGLRenderingContext { } } } + + // Used by HTMLCanvasElement.toDataURL + // + // This emits errors quite liberally, but the spec says that this operation + // can fail and that it is UB what happens in that case. + // + // https://www.khronos.org/registry/webgl/specs/latest/1.0/#2.2 + pub fn get_image_data(&self, mut width: u32, mut height: u32) -> Option<Vec<u8>> { + if !self.validate_framebuffer_complete() { + return None; + } + + if let Some((fb_width, fb_height)) = self.get_current_framebuffer_size() { + width = cmp::min(width, fb_width as u32); + height = cmp::min(height, fb_height as u32); + } else { + self.webgl_error(InvalidOperation); + return None; + } + + let (sender, receiver) = webgl_channel().unwrap(); + self.send_command(WebGLCommand::ReadPixels( + 0, + 0, + width as i32, + height as i32, + constants::RGBA, + constants::UNSIGNED_BYTE, + sender, + )); + Some(receiver.recv().unwrap()) + } } impl Drop for WebGLRenderingContext { |