WebGLRenderingContext.cpp 3.3 KB

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