WebGLRenderingContext.cpp 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  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/EventNames.h>
  10. #include <LibWeb/WebGL/WebGLContextEvent.h>
  11. #include <LibWeb/WebGL/WebGLRenderingContext.h>
  12. namespace Web::WebGL {
  13. JS_DEFINE_ALLOCATOR(WebGLRenderingContext);
  14. // https://www.khronos.org/registry/webgl/specs/latest/1.0/#fire-a-webgl-context-event
  15. static void fire_webgl_context_event(HTML::HTMLCanvasElement& canvas_element, FlyString const& type)
  16. {
  17. // 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.
  18. // FIXME: Consider setting a status message.
  19. auto event = WebGLContextEvent::create(canvas_element.realm(), type, WebGLContextEventInit {});
  20. event->set_is_trusted(true);
  21. event->set_cancelable(true);
  22. canvas_element.dispatch_event(*event);
  23. }
  24. // https://www.khronos.org/registry/webgl/specs/latest/1.0/#fire-a-webgl-context-creation-error
  25. static void fire_webgl_context_creation_error(HTML::HTMLCanvasElement& canvas_element)
  26. {
  27. // 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.
  28. fire_webgl_context_event(canvas_element, EventNames::webglcontextcreationerror);
  29. }
  30. JS::ThrowCompletionOr<JS::GCPtr<WebGLRenderingContext>> WebGLRenderingContext::create(JS::Realm& realm, HTML::HTMLCanvasElement& canvas_element, JS::Value options)
  31. {
  32. // We should be coming here from getContext being called on a wrapped <canvas> element.
  33. auto context_attributes = TRY(convert_value_to_context_attributes_dictionary(canvas_element.vm(), options));
  34. bool created_bitmap = canvas_element.create_bitmap(/* minimum_width= */ 1, /* minimum_height= */ 1);
  35. if (!created_bitmap) {
  36. fire_webgl_context_creation_error(canvas_element);
  37. return JS::GCPtr<WebGLRenderingContext> { nullptr };
  38. }
  39. VERIFY(canvas_element.bitmap());
  40. auto context = OpenGLContext::create(*canvas_element.bitmap());
  41. if (!context) {
  42. fire_webgl_context_creation_error(canvas_element);
  43. return JS::GCPtr<WebGLRenderingContext> { nullptr };
  44. }
  45. return realm.heap().allocate<WebGLRenderingContext>(realm, realm, canvas_element, context.release_nonnull(), context_attributes, context_attributes);
  46. }
  47. WebGLRenderingContext::WebGLRenderingContext(JS::Realm& realm, HTML::HTMLCanvasElement& canvas_element, NonnullOwnPtr<OpenGLContext> context, WebGLContextAttributes context_creation_parameters, WebGLContextAttributes actual_context_parameters)
  48. : WebGLRenderingContextBase(realm, canvas_element, move(context), move(context_creation_parameters), move(actual_context_parameters))
  49. {
  50. }
  51. WebGLRenderingContext::~WebGLRenderingContext() = default;
  52. void WebGLRenderingContext::initialize(JS::Realm& realm)
  53. {
  54. Base::initialize(realm);
  55. WEB_SET_PROTOTYPE_FOR_INTERFACE(WebGLRenderingContext);
  56. }
  57. }