3d迷宫移动:https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/A_basic_ray-caster
C:\dev\chromium104\src\third_party\blink\renderer\core\html\canvas\html_canvas_element.cc
HTMLCanvasElement::CreateLayer
HTMLCanvasElement::Paint 和 HTMLCanvasElement::PaintInternal绘制2d,用skp或者image snapshot。需要unacclerate,不用gpu加速。
snapshot = snapshot->MakeUnaccelerated();
webgl:
if (IsWebGL() && PaintsIntoCanvasBuffer())
context_->MarkLayerComposited();
HTMLCanvasElement::Snapshot可以对2d或者webgl快照出 image。
查看代码
 scoped_refptr<staticbitmapimage> HTMLCanvasElement::Snapshot(
SourceDrawingBuffer source_buffer) const {
if (size_.IsEmpty())
return nullptr;
scoped_refptr<staticbitmapimage> image_bitmap;
if (OffscreenCanvasFrame()) { // Offscreen Canvas
DCHECK(OffscreenCanvasFrame()->OriginClean());
image_bitmap = OffscreenCanvasFrame()->Bitmap();
} else if (IsWebGL()) {
if (context_->CreationAttributes().premultiplied_alpha) {
context_->PaintRenderingResultsToCanvas(source_buffer);
if (ResourceProvider())
image_bitmap = ResourceProvider()->Snapshot();
} else {
sk_sp<skdata> pixel_data =
context_->PaintRenderingResultsToDataArray(source_buffer);
if (pixel_data) {
// If the accelerated canvas is too big, there is a logic in WebGL code
// path that scales down the drawing buffer to the maximum supported
// size. Hence, we need to query the adjusted size of DrawingBuffer.
gfx::Size adjusted_size = context_->DrawingBufferSize();
if (!adjusted_size.IsEmpty()) {
SkColorInfo color_info =
GetRenderingContextSkColorInfo().makeAlphaType(
kUnpremul_SkAlphaType);
if (color_info.colorType() == kN32_SkColorType)
color_info = color_info.makeColorType(kRGBA_8888_SkColorType);
else
color_info = color_info.makeColorType(kRGBA_F16_SkColorType);
image_bitmap = StaticBitmapImage::Create(
std::move(pixel_data),
SkImageInfo::Make(
SkISize::Make(adjusted_size.width(), adjusted_size.height()),
color_info));
}
}
}
} else if (context_) {
DCHECK(IsRenderingContext2D() || IsImageBitmapRenderingContext() ||
IsWebGPU());
image_bitmap = context_->GetImage();
}
if (image_bitmap)
DCHECK(image_bitmap->SupportsDisplayCompositing());
else
image_bitmap = CreateTransparentImage(size_);
return image_bitmap;
}</skdata></staticbitmapimage></staticbitmapimage>
HTMLCanvasElement::toDataURL生成可以在html中写的
HTMLCanvasElement::toBlob 都对应有 canvas的js函数吧。
决定是否cpu or gpu 绘制canvas:
// If the canvas meets the criteria to use accelerated-GPU rendering, and
// the user signals that the canvas will not be read frequently through
// getImageData, which is a slow operation with GPU, the canvas will try to
// use accelerated-GPU rendering.
// If any of the two conditions fails, or if the creation of accelerated
// resource provider fails, the canvas will fallback to CPU rendering.
UMA_HISTOGRAM_BOOLEAN(
"Blink.Canvas.2DLayerBridge.WillReadFrequently",
context_ && context_->CreationAttributes().will_read_frequently);
if (ShouldAccelerate() && context_ &&
!context_->CreationAttributes().will_read_frequently) {
canvas2d_bridge_ = Create2DLayerBridge(RasterMode::kGPU);
}
if (!canvas2d_bridge_) {
canvas2d_bridge_ = Create2DLayerBridge(RasterMode::kCPU);
}
GetSourceImageForCanvas
通知image变化:HTMLCanvasElement::NotifyListenersCanvasChanged()
阻止不支持webgl:HTMLCanvasElement::IsWebGLBlocked()
webgl代码:src\third_party\blink\renderer\modules\webgl
canvas代码:src\third_party\blink\renderer\modules\canvas 这个目录的 README.md
C:\dev\chromium104\src\third_party\blink\renderer\core\paint\html_canvas_painter.cc
RecordForeignLayer
c:\dev\chromium104\src\third_party\blink\renderer\platform\graphics\paint\foreign_layer_display_item.cc
chrome在headless模式,是不启动gpu模式的。可以通过chrome://inspect 打开监控的无头浏览器,输入 chrome://gpu查看,全是软渲染。
- canvas 2d时:
在软渲染时,canvas的绘制指令通过cpu生成成了 layer的picture, 即skp,可以获取skp将其显示。
而在gpu绘制时,生成layer是textureLayer, 通过外部gpu绘制,这时是没有绘制指令的。无法通过skp重现。(可能是直接gpu绘制了?)
canvas webgl (canvas.getContext(“webgl”) 获得。有2d,3d api。
在canvas是获取的3d webgl上下文画笔时,会需要swiftshader软渲染。是必现生成texturelayer的。
Canvas 是 HTML5 提供的一个特性,你可以把它当做一个载体,简单的说就是一张白纸。而 Canvas 2D 相当于获取了内置的二维图形接口,也就是二维画笔。Canvas 3D 是获取基于 WebGL的图形接口,相当于三维画笔。你可以选择不同的画笔在上面作画。
OpenGL是 底层的驱动级的图形接口(是显卡有直接关系的) 类似于 DirectX. 但是这种底层的 OpenGL 是 寄生于浏览器的JavaScript无法涉及的。但是为了让 Web 拥有更强大的 图形处理能力 2010年时候WebGL被推出来。WebGL 允许工程师使用JS 去调用部分封装过的 OpenGL ES2.0 标准接口去 提供硬件级别的3D图形加速功能。
Skia 是一个开源的2D图形库。 SwiftShader是一个高性能的,基于CPU的OpenGLES和Direct3D图形APIs的实现。它的目标是为高级3D图形提供硬件独立性。
https://threejs.org/ webgl 3d 封装库
创建canvas和测试进入加速模式:
TEST_F(HTMLCanvasPainterTest, Canvas2DLayerAppearsInLayerTree) {
// Insert a <canvas> and force it into accelerated mode.
// Not using SetBodyInnerHTML() because we need to test before document
// lifecyle update.
GetDocument().body()->setInnerHTML("<canvas width="300" height="200">");
auto* element = To<htmlcanvaselement>(GetDocument().body()->firstChild());
CanvasContextCreationAttributesCore attributes;
attributes.alpha = true;
CanvasRenderingContext* context =
element->GetCanvasRenderingContext("2d", attributes);
gfx::Size size(300, 200);
std::unique_ptr<canvas2dlayerbridge> bridge = MakeCanvas2DLayerBridge(size);
element->SetResourceProviderForTesting(nullptr, std::move(bridge), size);
ASSERT_EQ(context, element->RenderingContext());
ASSERT_TRUE(context->IsComposited());
ASSERT_TRUE(element->IsAccelerated());
// Force the page to paint.
element->PreFinalizeFrame();
context->FinalizeFrame();
element->PostFinalizeFrame();
UpdateAllLifecyclePhasesForTest();
// Fetch the layer associated with the <canvas>, and check that it was
// correctly configured in the layer tree.
const cc::Layer* layer = context->CcLayer();
ASSERT_TRUE(layer);
EXPECT_TRUE(HasLayerAttached(*layer));
EXPECT_EQ(gfx::Size(300, 200), layer->bounds());
}</canvas></canvas2dlayerbridge></htmlcanvaselement></canvas></canvas>
Original: https://www.cnblogs.com/bigben0123/p/15988053.html
Author: Bigben
Title: wasm示例 js canvas 动画示例
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/551317/
转载文章受原作者版权保护。转载请注明原作者出处!