aboutsummaryrefslogtreecommitdiffstats
path: root/components/compositing/gl.rs
diff options
context:
space:
mode:
authorCristian Brinza <cristianb@gmail.com>2024-08-03 23:04:26 +0300
committerGitHub <noreply@github.com>2024-08-03 20:04:26 +0000
commit7c2c383bb1fb15dfeea1e0f33af2e42b407af4e1 (patch)
treeae26b2a6512b5cd142f7bfd12f92c3dbac3d60fa /components/compositing/gl.rs
parentbb176514c64b50011ee0be5cfb10f0cbce48cd93 (diff)
downloadservo-7c2c383bb1fb15dfeea1e0f33af2e42b407af4e1.tar.gz
servo-7c2c383bb1fb15dfeea1e0f33af2e42b407af4e1.zip
Fix save to image on Windows (#32914)
* Read pixels in same format (gl::RGBA) as the texture Signed-off-by: crbrz <cristianb@gmail.com> * Add read pixels test Signed-off-by: crbrz <cristianb@gmail.com> * Use patched surfman Signed-off-by: crbrz <cristianb@gmail.com> * Update surfman to 0.9.5 Signed-off-by: crbrz <cristianb@gmail.com> --------- Signed-off-by: crbrz <cristianb@gmail.com>
Diffstat (limited to 'components/compositing/gl.rs')
-rw-r--r--components/compositing/gl.rs70
1 files changed, 64 insertions, 6 deletions
diff --git a/components/compositing/gl.rs b/components/compositing/gl.rs
index e5bd588b298..8587c61d7a0 100644
--- a/components/compositing/gl.rs
+++ b/components/compositing/gl.rs
@@ -5,8 +5,8 @@
use std::rc::Rc;
use gleam::gl::{self, Gl};
-use image::RgbImage;
-use log::trace;
+use image::RgbaImage;
+use log::{trace, warn};
use servo_geometry::FramebufferUintLength;
pub struct RenderTargetInfo {
@@ -105,7 +105,7 @@ impl RenderTargetInfo {
y: i32,
width: FramebufferUintLength,
height: FramebufferUintLength,
- ) -> RgbImage {
+ ) -> RgbaImage {
let width = width.get() as usize;
let height = height.get() as usize;
// For some reason, OSMesa fails to render on the 3rd
@@ -121,13 +121,17 @@ impl RenderTargetInfo {
y,
width as gl::GLsizei,
height as gl::GLsizei,
- gl::RGB,
+ gl::RGBA,
gl::UNSIGNED_BYTE,
);
+ let gl_error = self.gl.get_error();
+ if gl_error != gl::NO_ERROR {
+ warn!("GL error code 0x{gl_error:x} set after read_pixels");
+ }
// flip image vertically (texture is upside down)
let orig_pixels = pixels.clone();
- let stride = width * 3;
+ let stride = width * 4;
for y in 0..height {
let dst_start = y * stride;
let src_start = (height - y - 1) * stride;
@@ -135,7 +139,7 @@ impl RenderTargetInfo {
pixels[dst_start..dst_start + stride].clone_from_slice(&src_slice[..stride]);
}
- RgbImage::from_raw(width as u32, height as u32, pixels).expect("Flipping image failed!")
+ RgbaImage::from_raw(width as u32, height as u32, pixels).expect("Flipping image failed!")
}
}
@@ -148,3 +152,57 @@ impl Drop for RenderTargetInfo {
self.gl.delete_framebuffers(&self.framebuffer_ids);
}
}
+
+#[cfg(test)]
+mod test {
+ use gleam::gl;
+ use image::Rgba;
+ use servo_geometry::FramebufferUintLength;
+ use surfman::{Connection, ContextAttributeFlags, ContextAttributes, Error, GLApi, GLVersion};
+
+ use super::RenderTargetInfo;
+
+ #[test]
+ #[allow(unsafe_code)]
+ fn test_read_pixels() -> Result<(), Error> {
+ let connection = Connection::new()?;
+ let adapter = connection.create_software_adapter()?;
+ let mut device = connection.create_device(&adapter)?;
+ let context_descriptor = device.create_context_descriptor(&ContextAttributes {
+ version: GLVersion::new(3, 0),
+ flags: ContextAttributeFlags::empty(),
+ })?;
+ let mut context = device.create_context(&context_descriptor, None)?;
+
+ let gl = match connection.gl_api() {
+ GLApi::GL => unsafe { gl::GlFns::load_with(|s| device.get_proc_address(&context, s)) },
+ GLApi::GLES => unsafe {
+ gl::GlesFns::load_with(|s| device.get_proc_address(&context, s))
+ },
+ };
+
+ device.make_context_current(&context)?;
+
+ {
+ const WIDTH: FramebufferUintLength = FramebufferUintLength::new(16);
+ const HEIGHT: FramebufferUintLength = FramebufferUintLength::new(16);
+ let render_target = RenderTargetInfo::new(gl, WIDTH, HEIGHT);
+ render_target.bind();
+ render_target
+ .gl
+ .clear_color(12.0 / 255.0, 34.0 / 255.0, 56.0 / 255.0, 78.0 / 255.0);
+ render_target.gl.clear(gl::COLOR_BUFFER_BIT);
+
+ let img = render_target.read_back_from_gpu(0, 0, WIDTH, HEIGHT);
+ assert_eq!(img.width(), WIDTH.get());
+ assert_eq!(img.height(), HEIGHT.get());
+
+ let expected_pixel: Rgba<u8> = Rgba([12, 34, 56, 78]);
+ assert!(img.pixels().all(|&p| p == expected_pixel));
+ }
+
+ device.destroy_context(&mut context)?;
+
+ Ok(())
+ }
+}