Skip to content

Commit acadd8d

Browse files
authored
webgl backend supports now non-srgb framebuffer (#3070)
1 parent 81dc1e2 commit acadd8d

File tree

5 files changed

+71
-40
lines changed

5 files changed

+71
-40
lines changed

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,13 @@ Bottom level categories:
4949

5050
### Added/New Features
5151

52-
Add the `"wgsl"` feature, to enable WGSL shaders in `wgpu-core` and `wgpu`. Enabled by default in `wgpu`. By @daxpedda in [#2890](https://github.com/gfx-rs/wgpu/pull/2890).
52+
#### General
53+
54+
- Add the `"wgsl"` feature, to enable WGSL shaders in `wgpu-core` and `wgpu`. Enabled by default in `wgpu`. By @daxpedda in [#2890](https://github.com/gfx-rs/wgpu/pull/2890).
55+
56+
#### GLES
57+
58+
- Surfaces support now `TextureFormat::Rgba8Unorm` and (non-web only) `TextureFormat::Bgra8Unorm`
5359

5460
### Bug Fixes
5561

wgpu-hal/src/gles/adapter.rs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -786,27 +786,27 @@ impl crate::Adapter<super::Api> for super::Adapter {
786786
&self,
787787
surface: &super::Surface,
788788
) -> Option<crate::SurfaceCapabilities> {
789-
let mut formats = if surface.supports_srgb() {
790-
vec![
791-
wgt::TextureFormat::Rgba8UnormSrgb,
792-
#[cfg(not(target_arch = "wasm32"))]
793-
wgt::TextureFormat::Bgra8UnormSrgb,
794-
]
795-
} else {
796-
vec![
789+
if surface.presentable {
790+
let mut formats = vec![
797791
wgt::TextureFormat::Rgba8Unorm,
798792
#[cfg(not(target_arch = "wasm32"))]
799793
wgt::TextureFormat::Bgra8Unorm,
800-
]
801-
};
802-
if self
803-
.shared
804-
.private_caps
805-
.contains(super::PrivateCapabilities::COLOR_BUFFER_HALF_FLOAT)
806-
{
807-
formats.push(wgt::TextureFormat::Rgba16Float)
808-
}
809-
if surface.presentable {
794+
];
795+
if surface.supports_srgb() {
796+
formats.extend(&[
797+
wgt::TextureFormat::Rgba8UnormSrgb,
798+
#[cfg(not(target_arch = "wasm32"))]
799+
wgt::TextureFormat::Bgra8UnormSrgb,
800+
])
801+
}
802+
if self
803+
.shared
804+
.private_caps
805+
.contains(super::PrivateCapabilities::COLOR_BUFFER_HALF_FLOAT)
806+
{
807+
formats.push(wgt::TextureFormat::Rgba16Float)
808+
}
809+
810810
Some(crate::SurfaceCapabilities {
811811
formats,
812812
present_modes: vec![wgt::PresentMode::Fifo], //TODO

wgpu-hal/src/gles/web.rs

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ impl Instance {
4343

4444
Ok(Surface {
4545
webgl2_context,
46-
present_program: None,
46+
srgb_present_program: None,
4747
swapchain: None,
4848
texture: None,
4949
presentable: true,
@@ -64,7 +64,7 @@ impl Instance {
6464

6565
Ok(Surface {
6666
webgl2_context,
67-
present_program: None,
67+
srgb_present_program: None,
6868
swapchain: None,
6969
texture: None,
7070
presentable: true,
@@ -144,7 +144,7 @@ pub struct Surface {
144144
pub(super) swapchain: Option<Swapchain>,
145145
texture: Option<glow::Texture>,
146146
pub(super) presentable: bool,
147-
present_program: Option<glow::Program>,
147+
srgb_present_program: Option<glow::Program>,
148148
}
149149

150150
// SAFE: Because web doesn't have threads ( yet )
@@ -166,35 +166,59 @@ impl Surface {
166166
_suf_texture: super::Texture,
167167
gl: &glow::Context,
168168
) -> Result<(), crate::SurfaceError> {
169-
gl.bind_framebuffer(glow::DRAW_FRAMEBUFFER, None);
170-
gl.bind_sampler(0, None);
171-
gl.active_texture(glow::TEXTURE0);
172-
gl.bind_texture(glow::TEXTURE_2D, self.texture);
173-
gl.use_program(self.present_program);
174-
gl.disable(glow::DEPTH_TEST);
175-
gl.disable(glow::STENCIL_TEST);
176-
gl.disable(glow::SCISSOR_TEST);
177-
gl.disable(glow::BLEND);
178-
gl.disable(glow::CULL_FACE);
179-
gl.draw_buffers(&[glow::BACK]);
180-
gl.draw_arrays(glow::TRIANGLES, 0, 3);
169+
let swapchain = self.swapchain.as_ref().ok_or(crate::SurfaceError::Other(
170+
"need to configure surface before presenting",
171+
))?;
172+
173+
if swapchain.format.describe().srgb {
174+
gl.bind_framebuffer(glow::DRAW_FRAMEBUFFER, None);
175+
gl.bind_sampler(0, None);
176+
gl.active_texture(glow::TEXTURE0);
177+
gl.bind_texture(glow::TEXTURE_2D, self.texture);
178+
gl.use_program(self.srgb_present_program);
179+
gl.disable(glow::DEPTH_TEST);
180+
gl.disable(glow::STENCIL_TEST);
181+
gl.disable(glow::SCISSOR_TEST);
182+
gl.disable(glow::BLEND);
183+
gl.disable(glow::CULL_FACE);
184+
gl.draw_buffers(&[glow::BACK]);
185+
gl.draw_arrays(glow::TRIANGLES, 0, 3);
186+
} else {
187+
gl.bind_framebuffer(glow::READ_FRAMEBUFFER, Some(swapchain.framebuffer));
188+
gl.bind_framebuffer(glow::DRAW_FRAMEBUFFER, None);
189+
// Note the Y-flipping here. GL's presentation is not flipped,
190+
// but main rendering is. Therefore, we Y-flip the output positions
191+
// in the shader, and also this blit.
192+
gl.blit_framebuffer(
193+
0,
194+
swapchain.extent.height as i32,
195+
swapchain.extent.width as i32,
196+
0,
197+
0,
198+
0,
199+
swapchain.extent.width as i32,
200+
swapchain.extent.height as i32,
201+
glow::COLOR_BUFFER_BIT,
202+
glow::NEAREST,
203+
);
204+
}
181205

182206
Ok(())
183207
}
184208

185-
unsafe fn create_present_program(gl: &glow::Context) -> glow::Program {
209+
unsafe fn create_srgb_present_program(gl: &glow::Context) -> glow::Program {
186210
let program = gl
187211
.create_program()
188212
.expect("Could not create shader program");
189213
let vertex = gl
190214
.create_shader(glow::VERTEX_SHADER)
191215
.expect("Could not create shader");
192-
gl.shader_source(vertex, include_str!("./shaders/present.vert"));
216+
gl.shader_source(vertex, include_str!("./shaders/srgb_present.vert"));
193217
gl.compile_shader(vertex);
194218
let fragment = gl
195219
.create_shader(glow::FRAGMENT_SHADER)
196220
.expect("Could not create shader");
197-
gl.shader_source(fragment, include_str!("./shaders/present.frag"));
221+
gl.shader_source(fragment, include_str!("./shaders/srgb_present.frag"));
198222
gl.compile_shader(fragment);
199223
gl.attach_shader(program, vertex);
200224
gl.attach_shader(program, fragment);
@@ -207,7 +231,8 @@ impl Surface {
207231
}
208232

209233
pub fn supports_srgb(&self) -> bool {
210-
true // WebGL only supports sRGB
234+
// present.frag takes care of handling srgb conversion
235+
true
211236
}
212237
}
213238

@@ -224,8 +249,8 @@ impl crate::Surface<super::Api> for Surface {
224249
gl.delete_framebuffer(swapchain.framebuffer);
225250
}
226251

227-
if self.present_program.is_none() {
228-
self.present_program = Some(Self::create_present_program(gl));
252+
if self.srgb_present_program.is_none() && config.format.describe().srgb {
253+
self.srgb_present_program = Some(Self::create_srgb_present_program(gl));
229254
}
230255

231256
if let Some(texture) = self.texture.take() {

0 commit comments

Comments
 (0)