Bladeren bron

LibWeb/WebGL: Implement tex(Sub)Image2D with TexImageSource

Luke Wilde 6 maanden geleden
bovenliggende
commit
fa40a1e686

+ 3 - 3
Libraries/LibWeb/WebGL/WebGL2RenderingContextOverloads.idl

@@ -22,20 +22,20 @@ interface mixin WebGL2RenderingContextOverloads {
     undefined texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, [AllowShared] ArrayBufferView? pixels);
 
     // May throw DOMException
-    [FIXME] undefined texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLenum format, GLenum type, TexImageSource source);
+    undefined texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLenum format, GLenum type, TexImageSource source);
 
     // WebGL2 entrypoints:
     [FIXME] undefined texImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, GLintptr pboOffset);
 
     // May throw DOMException
-    [FIXME] undefined texImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, TexImageSource source);
+    undefined texImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, TexImageSource source);
 
     undefined texImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, [AllowShared] ArrayBufferView srcData, unsigned long long srcOffset);
 
     [FIXME] undefined texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLintptr pboOffset);
 
     // May throw DOMException
-    [FIXME] undefined texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, TexImageSource source);
+    undefined texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, TexImageSource source);
     undefined texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, [AllowShared] ArrayBufferView srcData, unsigned long long srcOffset);
 
     [FIXME] undefined compressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, GLintptr offset);

+ 1 - 1
Libraries/LibWeb/WebGL/WebGLRenderingContextOverloads.idl

@@ -28,7 +28,7 @@ interface mixin WebGLRenderingContextOverloads {
     undefined texImage2D(GLenum target, GLint level, GLint internalformat, GLenum format, GLenum type, TexImageSource source); // May throw DOMException
 
     undefined texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, [AllowShared] ArrayBufferView? pixels);
-    [FIXME] undefined texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLenum format, GLenum type, TexImageSource source); // May throw DOMException
+    undefined texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLenum format, GLenum type, TexImageSource source); // May throw DOMException
 
     undefined uniform1fv(WebGLUniformLocation? location, Float32List v);
     undefined uniform2fv(WebGLUniformLocation? location, Float32List v);

+ 2 - 2
Libraries/LibWeb/WebIDL/OverloadResolution.cpp

@@ -210,7 +210,7 @@ JS::ThrowCompletionOr<ResolvedOverload> resolve_overload(JS::VM& vm, IDL::Effect
         //    then remove from S all other entries.
         else if (value.is_object() && is<JS::DataView>(value.as_object())
             && has_overload_with_argument_type_or_subtype_matching(overloads, i, [](IDL::Type const& type) {
-                   if (type.is_plain() && (type.name() == "DataView" || type.name() == "BufferSource"))
+                   if (type.is_plain() && (type.name() == "DataView" || type.name() == "BufferSource" || type.name() == "ArrayBufferView"))
                        return true;
                    if (type.is_object())
                        return true;
@@ -228,7 +228,7 @@ JS::ThrowCompletionOr<ResolvedOverload> resolve_overload(JS::VM& vm, IDL::Effect
         //    then remove from S all other entries.
         else if (value.is_object() && value.as_object().is_typed_array()
             && has_overload_with_argument_type_or_subtype_matching(overloads, i, [&](IDL::Type const& type) {
-                   if (type.is_plain() && (type.name() == static_cast<JS::TypedArrayBase const&>(value.as_object()).element_name() || type.name() == "BufferSource"))
+                   if (type.is_plain() && (type.name() == static_cast<JS::TypedArrayBase const&>(value.as_object()).element_name() || type.name() == "BufferSource" || type.name() == "ArrayBufferView"))
                        return true;
                    if (type.is_object())
                        return true;

+ 63 - 3
Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWebGLRenderingContext.cpp

@@ -725,7 +725,7 @@ public:
             continue;
         }
 
-        if (function.name == "texImage2D"sv && function.overload_index == 1) {
+        if (function.name == "texImage2D"sv && (function.overload_index == 1 || (webgl_version == 2 && function.overload_index == 2))) {
             // FIXME: If this function is called with an ImageData whose data attribute has been neutered,
             //        an INVALID_VALUE error is generated.
             // FIXME: If this function is called with an ImageBitmap that has been neutered, an INVALID_VALUE
@@ -761,14 +761,23 @@ public:
         return;
 
     void const* pixels_ptr = bitmap->bitmap()->begin();
+)~~~");
+
+            if (webgl_version == 2 && function.overload_index == 2) {
+                function_impl_generator.append(R"~~~(
+    glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels_ptr);
+)~~~");
+            } else {
+                function_impl_generator.append(R"~~~(
     int width = bitmap->width();
     int height = bitmap->height();
     glTexImage2D(target, level, internalformat, width, height, 0, format, type, pixels_ptr);
 )~~~");
+            }
             continue;
         }
 
-        if (webgl_version == 2 && function.name == "texImage2D"sv && function.overload_index == 2) {
+        if (webgl_version == 2 && function.name == "texImage2D"sv && function.overload_index == 3) {
             function_impl_generator.append(R"~~~(
     void const* pixels_ptr = nullptr;
     if (src_data) {
@@ -794,7 +803,58 @@ public:
             continue;
         }
 
-        if (webgl_version == 2 && function.name == "texSubImage2D"sv && function.overload_index == 1) {
+        if (function.name == "texSubImage2D" && (function.overload_index == 1 || (webgl_version == 2 && function.overload_index == 2))) {
+            // FIXME: If this function is called with an ImageData whose data attribute has been neutered,
+            //        an INVALID_VALUE error is generated.
+            // FIXME: If this function is called with an ImageBitmap that has been neutered, an INVALID_VALUE
+            //        error is generated.
+            // FIXME: If this function is called with an HTMLImageElement or HTMLVideoElement whose origin
+            //        differs from the origin of the containing Document, or with an HTMLCanvasElement,
+            //        ImageBitmap or OffscreenCanvas whose bitmap's origin-clean flag is set to false,
+            //        a SECURITY_ERR exception must be thrown. See Origin Restrictions.
+            // FIXME: If source is null then an INVALID_VALUE error is generated.
+            function_impl_generator.append(R"~~~(
+    auto bitmap = source.visit(
+        [](GC::Root<HTMLImageElement> const& source) -> RefPtr<Gfx::ImmutableBitmap> {
+            return source->immutable_bitmap();
+        },
+        [](GC::Root<HTMLCanvasElement> const& source) -> RefPtr<Gfx::ImmutableBitmap> {
+            auto surface = source->surface();
+            if (!surface)
+                return {};
+            auto bitmap = MUST(Gfx::Bitmap::create(Gfx::BitmapFormat::RGBA8888, Gfx::AlphaType::Premultiplied, surface->size()));
+            surface->read_into_bitmap(*bitmap);
+            return Gfx::ImmutableBitmap::create(*bitmap);
+        },
+        [](GC::Root<HTMLVideoElement> const& source) -> RefPtr<Gfx::ImmutableBitmap> {
+            return Gfx::ImmutableBitmap::create(*source->bitmap());
+        },
+        [](GC::Root<ImageBitmap> const& source) -> RefPtr<Gfx::ImmutableBitmap> {
+            return Gfx::ImmutableBitmap::create(*source->bitmap());
+        },
+        [](GC::Root<ImageData> const& source) -> RefPtr<Gfx::ImmutableBitmap> {
+            return Gfx::ImmutableBitmap::create(source->bitmap());
+        });
+    if (!bitmap)
+        return;
+
+    void const* pixels_ptr = bitmap->bitmap()->begin();
+)~~~");
+            if (webgl_version == 2 && function.overload_index == 2) {
+                function_impl_generator.append(R"~~~(
+    glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels_ptr);
+)~~~");
+            } else {
+                function_impl_generator.append(R"~~~(
+    int width = bitmap->width();
+    int height = bitmap->height();
+    glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels_ptr);
+)~~~");
+            }
+            continue;
+        }
+
+        if (webgl_version == 2 && function.name == "texSubImage2D"sv && function.overload_index == 3) {
             function_impl_generator.append(R"~~~(
     void const* pixels_ptr = nullptr;
     if (src_data) {