aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
authorAnthony Ramine <n.oxyde@gmail.com>2018-03-23 16:26:02 +0100
committerAnthony Ramine <n.oxyde@gmail.com>2018-03-23 17:32:42 +0100
commita77d35b60c5e9b01f868daff510fbb7e44ca1bbc (patch)
treeac9c0c351334236289aa44e23cefb1467a8896b3 /components/script
parent4a6453ac9ad956502ec6d39093b83820d94a409e (diff)
downloadservo-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.rs13
-rw-r--r--components/script/dom/webglrenderingcontext.rs33
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 {