File: webgl_context_factory.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (147 lines) | stat: -rw-r--r-- 5,704 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/modules/webgl/webgl_context_factory.h"

#include "base/notimplemented.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_context_creation_attributes_core.h"
#include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h"
#include "third_party/blink/renderer/modules/webgl/webgl2_rendering_context.h"
#include "third_party/blink/renderer/modules/webgl/webgl2_rendering_context_webgpu.h"
#include "third_party/blink/renderer/modules/webgl/webgl_context_event.h"
#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context.h"
#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_webgpu.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"

namespace blink {

// static
std::unique_ptr<WebGLContextFactory> WebGLContextFactory::MakeWebGL1() {
  return std::make_unique<WebGLContextFactory>(/* is_webgl2 */ false);
}

// static
std::unique_ptr<WebGLContextFactory> WebGLContextFactory::MakeWebGL2() {
  return std::make_unique<WebGLContextFactory>(/* is_webgl2 */ true);
}

WebGLContextFactory::WebGLContextFactory(bool is_webgl2)
    : is_webgl2_(is_webgl2) {}

CanvasRenderingContext* WebGLContextFactory::Create(
    CanvasRenderingContextHost* host,
    const CanvasContextCreationAttributesCore& attrs) {
  if (RuntimeEnabledFeatures::WebGLOnWebGPUEnabled()) {
    return CreateInternalWebGPU(host, attrs);
  } else {
    return CreateInternal(host, attrs);
  }
}

CanvasRenderingContext* WebGLContextFactory::CreateInternal(
    CanvasRenderingContextHost* host,
    const CanvasContextCreationAttributesCore& attrs) {
  // Create a copy of attrs so flags can be modified if needed before passing
  // into the WebGLRenderingContext constructor.
  CanvasContextCreationAttributesCore attribs = attrs;

  // The xr_compatible attribute needs to be handled before creating the context
  // because the GPU process may potentially be restarted in order to be XR
  // compatible. This scenario occurs if the GPU process is not using the GPU
  // that the VR headset is plugged into. If the GPU process is restarted, the
  // WebGraphicsContext3DProvider must be created using the new one.
  if (attribs.xr_compatible &&
      !WebGLRenderingContextBase::MakeXrCompatibleSync(host)) {
    // If xr compatibility is requested and we can't be xr compatible, return a
    // context with the flag set to false.
    attribs.xr_compatible = false;
  }

  // Create the Context3DProvider
  Platform::GraphicsInfo graphics_info;
  std::unique_ptr<WebGraphicsContext3DProvider> context_provider(
      WebGLRenderingContextBase::CreateWebGraphicsContext3DProvider(
          host, attribs, GetContextType(), &graphics_info));
  if (!context_provider) {
    // CreateWebGraphicsContext3DProvider alreade dispatches a
    // webglcontextcreationerror so we don't skip generating one here.
    return nullptr;
  }

  // Attempt to add a marker to make this context easier to find.
  gpu::gles2::GLES2Interface* gl = context_provider->ContextGL();
  std::unique_ptr<Extensions3DUtil> extensions_util =
      Extensions3DUtil::Create(gl);
  if (extensions_util->SupportsExtension("GL_EXT_debug_marker")) {
    String context_label(
        String::Format("%s-%p", GetContextName(), context_provider.get()));
    gl->PushGroupMarkerEXT(0, context_label.Ascii().c_str());
  }

  auto Initialize = [&](auto rendering_context) -> CanvasRenderingContext* {
    if (!rendering_context->GetDrawingBuffer()) {
      // We must dispose immediately so that when rendering_context is
      // garbage-collected, it will not interfere with a subsequently created
      // rendering context.
      rendering_context->Dispose();

      host->HostDispatchEvent(WebGLContextEvent::Create(
          event_type_names::kWebglcontextcreationerror,
          String::Format("Failed to create %s.", GetContextName())));
      return nullptr;
    }

    rendering_context->InitializeNewContext();
    rendering_context->RegisterContextExtensions();
    return rendering_context;
  };

  if (is_webgl2_) {
    return Initialize(MakeGarbageCollected<WebGL2RenderingContext>(
        host, std::move(context_provider), graphics_info, attribs));
  } else {
    return Initialize(MakeGarbageCollected<WebGLRenderingContext>(
        host, std::move(context_provider), graphics_info, attribs));
  }
}

CanvasRenderingContext* WebGLContextFactory::CreateInternalWebGPU(
    CanvasRenderingContextHost* host,
    const CanvasContextCreationAttributesCore& attrs) {
  if (is_webgl2_) {
    return MakeGarbageCollected<WebGL2RenderingContextWebGPU>(host, attrs);
  } else {
    return MakeGarbageCollected<WebGLRenderingContextWebGPU>(host, attrs);
  }
}

CanvasRenderingContext::CanvasRenderingAPI
WebGLContextFactory::GetRenderingAPI() const {
  if (is_webgl2_) {
    return CanvasRenderingContext::CanvasRenderingAPI::kWebgl2;
  }
  return CanvasRenderingContext::CanvasRenderingAPI::kWebgl;
}

void WebGLContextFactory::OnError(HTMLCanvasElement* canvas,
                                  const String& error) {
  canvas->DispatchEvent(*WebGLContextEvent::Create(
      event_type_names::kWebglcontextcreationerror, error));
}

const char* WebGLContextFactory::GetContextName() const {
  if (is_webgl2_) {
    return "WebGL2RenderingContext";
  }
  return "WebGLRenderingContext";
}

Platform::ContextType WebGLContextFactory::GetContextType() const {
  if (is_webgl2_) {
    return Platform::kWebGL2ContextType;
  }
  return Platform::kWebGL1ContextType;
}

}  // namespace blink