Skip to content

Commit 3e7061d

Browse files
Lubrsiawesomekling
authored andcommitted
LibWeb/WebGL: Respect UNPACK_FLIP_Y_WEBGL pixel storage parameter
When this is true, we have to vertically flip TexImageSource provided images before uploading them. Fixes several graphical glitches on Google Maps. Fixes globe being upside down on Shopify's homepage. Likely fixes more websites.
1 parent 008699c commit 3e7061d

File tree

4 files changed

+45
-3
lines changed

4 files changed

+45
-3
lines changed

Libraries/LibWeb/WebGL/WebGL2RenderingContextImpl.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2849,6 +2849,8 @@ JS::Value WebGL2RenderingContextImpl::get_parameter(WebIDL::UnsignedLong pname)
28492849
glGetBooleanvRobustANGLE(GL_TRANSFORM_FEEDBACK_PAUSED, 1, nullptr, &result);
28502850
return JS::Value(result == GL_TRUE);
28512851
}
2852+
case UNPACK_FLIP_Y_WEBGL:
2853+
return JS::Value(m_unpack_flip_y);
28522854
default:
28532855
dbgln("Unknown WebGL parameter name: {:x}", pname);
28542856
set_error(GL_INVALID_ENUM);
@@ -3145,6 +3147,13 @@ void WebGL2RenderingContextImpl::link_program(GC::Root<WebGLProgram> program)
31453147
void WebGL2RenderingContextImpl::pixel_storei(WebIDL::UnsignedLong pname, WebIDL::Long param)
31463148
{
31473149
m_context->make_current();
3150+
3151+
switch (pname) {
3152+
case UNPACK_FLIP_Y_WEBGL:
3153+
m_unpack_flip_y = param != GL_FALSE;
3154+
return;
3155+
}
3156+
31483157
glPixelStorei(pname, param);
31493158
}
31503159

Libraries/LibWeb/WebGL/WebGLRenderingContextBase.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ extern "C" {
1212
#include <GLES2/gl2ext_angle.h>
1313
}
1414

15+
#include <LibGfx/SkiaUtils.h>
1516
#include <LibWeb/HTML/HTMLCanvasElement.h>
1617
#include <LibWeb/HTML/HTMLImageElement.h>
1718
#include <LibWeb/HTML/HTMLVideoElement.h>
@@ -20,10 +21,12 @@ extern "C" {
2021
#include <LibWeb/WebGL/OpenGLContext.h>
2122
#include <LibWeb/WebGL/WebGLRenderingContextBase.h>
2223

24+
#include <core/SkCanvas.h>
2325
#include <core/SkColorSpace.h>
2426
#include <core/SkColorType.h>
2527
#include <core/SkImage.h>
2628
#include <core/SkPixmap.h>
29+
#include <core/SkSurface.h>
2730

2831
namespace Web::WebGL {
2932

@@ -178,8 +181,20 @@ Optional<WebGLRenderingContextBase::ConvertedTexture> WebGLRenderingContextBase:
178181
// FIXME: Respect unpackColorSpace
179182
auto color_space = SkColorSpace::MakeSRGB();
180183
auto image_info = SkImageInfo::Make(width, height, skia_format, SkAlphaType::kPremul_SkAlphaType, color_space);
181-
SkPixmap const pixmap(image_info, buffer.data(), buffer_pitch.value());
182-
bitmap->sk_image()->readPixels(pixmap, 0, 0);
184+
auto surface = SkSurfaces::WrapPixels(image_info, buffer.data(), buffer_pitch.value());
185+
auto surface_canvas = surface->getCanvas();
186+
auto dst_rect = Gfx::to_skia_rect(Gfx::Rect { 0, 0, width, height });
187+
188+
// The first pixel transferred from the source to the WebGL implementation corresponds to the upper left corner of
189+
// the source. This behavior is modified by the UNPACK_FLIP_Y_WEBGL pixel storage parameter, except for ImageBitmap
190+
// arguments, as described in the abovementioned section.
191+
if (m_unpack_flip_y && !source.has<GC::Root<HTML::ImageBitmap>>()) {
192+
surface_canvas->translate(0, dst_rect.height());
193+
surface_canvas->scale(1, -1);
194+
}
195+
196+
surface_canvas->drawImageRect(bitmap->sk_image(), dst_rect, Gfx::to_skia_sampling_options(Gfx::ScalingMode::NearestNeighbor));
197+
183198
return ConvertedTexture {
184199
.buffer = move(buffer),
185200
.width = width,

Libraries/LibWeb/WebGL/WebGLRenderingContextBase.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
namespace Web::WebGL {
1616

17+
static constexpr int UNPACK_FLIP_Y_WEBGL = 0x9240;
18+
1719
// NOTE: This is the Variant created by the IDL wrapper generator, and needs to be updated accordingly.
1820
using TexImageSource = Variant<GC::Root<HTML::ImageBitmap>, GC::Root<HTML::ImageData>, GC::Root<HTML::HTMLImageElement>, GC::Root<HTML::HTMLCanvasElement>, GC::Root<HTML::OffscreenCanvas>, GC::Root<HTML::HTMLVideoElement>>;
1921

@@ -107,7 +109,14 @@ class WebGLRenderingContextBase {
107109
int width { 0 };
108110
int height { 0 };
109111
};
110-
static Optional<ConvertedTexture> read_and_pixel_convert_texture_image_source(TexImageSource const& source, WebIDL::UnsignedLong format, WebIDL::UnsignedLong type, Optional<int> destination_width = OptionalNone {}, Optional<int> destination_height = OptionalNone {});
112+
Optional<ConvertedTexture> read_and_pixel_convert_texture_image_source(TexImageSource const& source, WebIDL::UnsignedLong format, WebIDL::UnsignedLong type, Optional<int> destination_width = OptionalNone {}, Optional<int> destination_height = OptionalNone {});
113+
114+
protected:
115+
// UNPACK_FLIP_Y_WEBGL of type boolean
116+
// If set, then during any subsequent calls to texImage2D or texSubImage2D, the source data is flipped along
117+
// the vertical axis, so that conceptually the last row is the first one transferred. The initial value is false.
118+
// Any non-zero value is interpreted as true.
119+
bool m_unpack_flip_y { false };
111120
};
112121

113122
}

Libraries/LibWeb/WebGL/WebGLRenderingContextImpl.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1501,6 +1501,8 @@ JS::Value WebGLRenderingContextImpl::get_parameter(WebIDL::UnsignedLong pname)
15011501
set_error(GL_INVALID_ENUM);
15021502
return JS::js_null();
15031503
}
1504+
case UNPACK_FLIP_Y_WEBGL:
1505+
return JS::Value(m_unpack_flip_y);
15041506
default:
15051507
dbgln("Unknown WebGL parameter name: {:x}", pname);
15061508
set_error(GL_INVALID_ENUM);
@@ -1793,6 +1795,13 @@ void WebGLRenderingContextImpl::link_program(GC::Root<WebGLProgram> program)
17931795
void WebGLRenderingContextImpl::pixel_storei(WebIDL::UnsignedLong pname, WebIDL::Long param)
17941796
{
17951797
m_context->make_current();
1798+
1799+
switch (pname) {
1800+
case UNPACK_FLIP_Y_WEBGL:
1801+
m_unpack_flip_y = param != GL_FALSE;
1802+
return;
1803+
}
1804+
17961805
glPixelStorei(pname, param);
17971806
}
17981807

0 commit comments

Comments
 (0)