Serenity Operating System
at master 67 lines 3.5 kB view raw
1/* 2 * Copyright (c) 2022, Luke Wilde <lukew@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <LibWeb/Bindings/Intrinsics.h> 8#include <LibWeb/DOM/Document.h> 9#include <LibWeb/HTML/HTMLCanvasElement.h> 10#include <LibWeb/WebGL/WebGLContextEvent.h> 11#include <LibWeb/WebGL/WebGLRenderingContext.h> 12 13namespace Web::WebGL { 14 15// https://www.khronos.org/registry/webgl/specs/latest/1.0/#fire-a-webgl-context-event 16static void fire_webgl_context_event(HTML::HTMLCanvasElement& canvas_element, DeprecatedFlyString const& type) 17{ 18 // To fire a WebGL context event named e means that an event using the WebGLContextEvent interface, with its type attribute [DOM4] initialized to e, its cancelable attribute initialized to true, and its isTrusted attribute [DOM4] initialized to true, is to be dispatched at the given object. 19 // FIXME: Consider setting a status message. 20 auto event = WebGLContextEvent::create(canvas_element.realm(), String::from_deprecated_string(type).release_value_but_fixme_should_propagate_errors(), WebGLContextEventInit {}).release_value_but_fixme_should_propagate_errors(); 21 event->set_is_trusted(true); 22 event->set_cancelable(true); 23 canvas_element.dispatch_event(*event); 24} 25 26// https://www.khronos.org/registry/webgl/specs/latest/1.0/#fire-a-webgl-context-creation-error 27static void fire_webgl_context_creation_error(HTML::HTMLCanvasElement& canvas_element) 28{ 29 // 1. Fire a WebGL context event named "webglcontextcreationerror" at canvas, optionally with its statusMessage attribute set to a platform dependent string about the nature of the failure. 30 fire_webgl_context_event(canvas_element, "webglcontextcreationerror"sv); 31} 32 33JS::ThrowCompletionOr<JS::GCPtr<WebGLRenderingContext>> WebGLRenderingContext::create(JS::Realm& realm, HTML::HTMLCanvasElement& canvas_element, JS::Value options) 34{ 35 // We should be coming here from getContext being called on a wrapped <canvas> element. 36 auto context_attributes = TRY(convert_value_to_context_attributes_dictionary(canvas_element.vm(), options)); 37 38 bool created_bitmap = canvas_element.create_bitmap(/* minimum_width= */ 1, /* minimum_height= */ 1); 39 if (!created_bitmap) { 40 fire_webgl_context_creation_error(canvas_element); 41 return JS::GCPtr<WebGLRenderingContext> { nullptr }; 42 } 43 44 auto context_or_error = GL::create_context(*canvas_element.bitmap()); 45 if (context_or_error.is_error()) { 46 fire_webgl_context_creation_error(canvas_element); 47 return JS::GCPtr<WebGLRenderingContext> { nullptr }; 48 } 49 return MUST_OR_THROW_OOM(realm.heap().allocate<WebGLRenderingContext>(realm, realm, canvas_element, context_or_error.release_value(), context_attributes, context_attributes)); 50} 51 52WebGLRenderingContext::WebGLRenderingContext(JS::Realm& realm, HTML::HTMLCanvasElement& canvas_element, NonnullOwnPtr<GL::GLContext> context, WebGLContextAttributes context_creation_parameters, WebGLContextAttributes actual_context_parameters) 53 : WebGLRenderingContextBase(realm, canvas_element, move(context), move(context_creation_parameters), move(actual_context_parameters)) 54{ 55} 56 57WebGLRenderingContext::~WebGLRenderingContext() = default; 58 59JS::ThrowCompletionOr<void> WebGLRenderingContext::initialize(JS::Realm& realm) 60{ 61 MUST_OR_THROW_OOM(Base::initialize(realm)); 62 set_prototype(&Bindings::ensure_web_prototype<Bindings::WebGLRenderingContextPrototype>(realm, "WebGLRenderingContext")); 63 64 return {}; 65} 66 67}