WebGLRenderingContext.cpp 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. /*
  2. * Copyright (c) 2022, Luke Wilde <lukew@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibWeb/Bindings/Intrinsics.h>
  7. #include <LibWeb/DOM/Document.h>
  8. #include <LibWeb/HTML/HTMLCanvasElement.h>
  9. #include <LibWeb/WebGL/WebGLContextEvent.h>
  10. #include <LibWeb/WebGL/WebGLRenderingContext.h>
  11. namespace Web::WebGL {
  12. // https://www.khronos.org/registry/webgl/specs/latest/1.0/#fire-a-webgl-context-event
  13. static void fire_webgl_context_event(HTML::HTMLCanvasElement& canvas_element, DeprecatedFlyString const& type)
  14. {
  15. // 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.
  16. // FIXME: Consider setting a status message.
  17. 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();
  18. event->set_is_trusted(true);
  19. event->set_cancelable(true);
  20. canvas_element.dispatch_event(*event);
  21. }
  22. // https://www.khronos.org/registry/webgl/specs/latest/1.0/#fire-a-webgl-context-creation-error
  23. static void fire_webgl_context_creation_error(HTML::HTMLCanvasElement& canvas_element)
  24. {
  25. // 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.
  26. fire_webgl_context_event(canvas_element, "webglcontextcreationerror"sv);
  27. }
  28. JS::ThrowCompletionOr<JS::GCPtr<WebGLRenderingContext>> WebGLRenderingContext::create(JS::Realm& realm, HTML::HTMLCanvasElement& canvas_element, JS::Value options)
  29. {
  30. // We should be coming here from getContext being called on a wrapped <canvas> element.
  31. auto context_attributes = TRY(convert_value_to_context_attributes_dictionary(canvas_element.vm(), options));
  32. bool created_bitmap = canvas_element.create_bitmap(/* minimum_width= */ 1, /* minimum_height= */ 1);
  33. if (!created_bitmap) {
  34. fire_webgl_context_creation_error(canvas_element);
  35. return JS::GCPtr<WebGLRenderingContext> { nullptr };
  36. }
  37. auto context_or_error = GL::create_context(*canvas_element.bitmap());
  38. if (context_or_error.is_error()) {
  39. fire_webgl_context_creation_error(canvas_element);
  40. return JS::GCPtr<WebGLRenderingContext> { nullptr };
  41. }
  42. return MUST_OR_THROW_OOM(realm.heap().allocate<WebGLRenderingContext>(realm, realm, canvas_element, context_or_error.release_value(), context_attributes, context_attributes));
  43. }
  44. WebGLRenderingContext::WebGLRenderingContext(JS::Realm& realm, HTML::HTMLCanvasElement& canvas_element, NonnullOwnPtr<GL::GLContext> context, WebGLContextAttributes context_creation_parameters, WebGLContextAttributes actual_context_parameters)
  45. : WebGLRenderingContextBase(realm, canvas_element, move(context), move(context_creation_parameters), move(actual_context_parameters))
  46. {
  47. }
  48. WebGLRenderingContext::~WebGLRenderingContext() = default;
  49. JS::ThrowCompletionOr<void> WebGLRenderingContext::initialize(JS::Realm& realm)
  50. {
  51. MUST_OR_THROW_OOM(Base::initialize(realm));
  52. set_prototype(&Bindings::ensure_web_prototype<Bindings::WebGLRenderingContextPrototype>(realm, "WebGLRenderingContext"));
  53. return {};
  54. }
  55. }