wasm的 surface.makeSurface
webgl时 有个最大的宽高 - Bigben - 博客园 (cnblogs.com)
wasm的 surface.makeSurface js中:
CanvasKit.Surface.prototype.makeSurface = function(imageInfo) { CanvasKit.setCurrentContext(this._context); var s = this._makeSurface(imageInfo); s._context = this._context; return s; };
c++中
.function("_makeSurface", optional_override([](SkSurface& self, SimpleImageInfo sii)->sk_sp<SkSurface> { return self.makeSurface(toSkImageInfo(sii)); }), allow_raw_pointers()) SkImageInfo toSkImageInfo(const SimpleImageInfo& sii) { return SkImageInfo::Make(sii.width, sii.height, sii.colorType, sii.alphaType, sii.colorSpace ? sii.colorSpace : SkColorSpace::MakeSRGB()); }
实现类中:
sk_sp<SkSurface> SkSurface::makeSurface(const SkImageInfo& info) { return asSB(this)->onNewSurface(info); }
最终到gpu中:
sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrRecordingContext* rContext, const SkSurfaceCharacterization& c, SkBudgeted budgeted) { if (!rContext || !c.isValid()) { return nullptr; } if (c.usesGLFBO0()) { // If we are making the surface we will never use FBO0. return nullptr; } if (c.vulkanSecondaryCBCompatible()) { return nullptr; } auto device = rContext->priv().createDevice(budgeted, c.imageInfo(), SkBackingFit::kExact, c.sampleCount(), GrMipmapped(c.isMipMapped()), c.isProtected(), c.origin(), c.surfaceProps(), skgpu::BaseDevice::InitContents::kClear); if (!device) { return nullptr; } sk_sp<SkSurface> result = sk_make_sp<SkSurface_Gpu>(std::move(device)); #ifdef SK_DEBUG if (result) { SkASSERT(result->isCompatible(c)); } #endif return result; }
目前surface的创建方式:优先gpu,没用就用软渲染:
<script type="text/javascript" charset="utf-8" async> 1,去下载wasm var CanvasKit = null; var cdn = 'https://storage.googleapis.com/skia-cdn/misc/'; const ckLoaded = CanvasKitInit({locateFile: (file) => '/build/'+file}); async function initWebGpu(CK) { if (navigator.gpu && CK.webgpu) { const adapter = await navigator.gpu.requestAdapter(); const device = await adapter.requestDevice(); var gpu = CK.MakeGPUDeviceContext(device); if (!gpu) { console.error('Failed to initialize WebGPU device context'); } return gpu; } return null; } const ready = async function() { let CK = await ckLoaded; let gpu = await initWebGpu(CK); return [CK, gpu]; }(); // Examples which only require canvaskit //这里是开始ready函数成功,then:initData就是上面的return返回的 return [CK, gpu] ready.then((initData) => { const [CK, gpu] = initData; CanvasKit = CK; // 开始使用创建: const surface = MakeCanvasSurface(CanvasKit, gpu, 'ink'); } // Helper function to create an optional WebGPU canvas surface, if WebGPU is supported. Falls back // to CanvasKit.MakeCanvasSurface for SW/WebGL otherwise. function MakeCanvasSurface(CanvasKit, gpu, canvasId) { if (gpu) { const canvasContext = CanvasKit.MakeGPUCanvasContext( gpu, document.getElementById(canvasId)); if (!canvasContext) { console.error('Failed to configure WebGPU canvas context'); return; } const surface = CanvasKit.MakeGPUCanvasSurface(canvasContext); if (!surface) { console.error('Failed to initialize current swapchain Surface'); } return surface; } return CanvasKit.MakeCanvasSurface(canvasId); }
canvaskit tile perf示例:https://stackblitz.com/edit/vitejs-vite-g6sht4?file=canvaskit.ts,canvas2d.ts
google帖子(draw image性能):https://groups.google.com/g/skia-discuss/c/CXF1misjJrc
import { TileSize, TileColumns, TileRows, TileSizeScaled, CombinedCanvasHeight, CombinedCanvasWidth, } from './config'; import CanvasKitInit from 'canvaskit-wasm'; // @ts-ignore import CanvasKitPath from 'canvaskit-wasm/bin/canvaskit.wasm?url'; async function main() { const CanvasKit = await CanvasKitInit({ locateFile: () => CanvasKitPath }); const targetCanvas = document.createElement('canvas'); targetCanvas.width = CombinedCanvasWidth; targetCanvas.height = CombinedCanvasHeight; document.body.appendChild(targetCanvas); console.time('init'); const glContextHandle = CanvasKit.GetWebGLContext(targetCanvas); const grDirectContext = CanvasKit.MakeWebGLContext(glContextHandle)!; const CombinedSurface = CanvasKit.MakeOnScreenGLSurface( grDirectContext, CombinedCanvasWidth, CombinedCanvasHeight, CanvasKit.ColorSpace.SRGB )!; console.timeEnd('init'); console.time('render tiles'); const renderTarget = CanvasKit.MakeRenderTarget( grDirectContext, TileSize, TileSize )!; const paint = new CanvasKit.Paint(); paint.setColor([0, 255, 0, 255]); paint.setAntiAlias(true); const canvas = renderTarget.getCanvas(); const tiles = new Array(TileColumns * TileRows).fill(0).map(() => { canvas.clear(CanvasKit.TRANSPARENT); canvas.drawRect(CanvasKit.XYWHRect(0, 0, 100, 100), paint); canvas.drawRect(CanvasKit.XYWHRect(100, 100, 100, 100), paint); return renderTarget.makeImageSnapshot(); }); console.timeEnd('render tiles'); console.time('combine tiles'); const combinedCanvas = CombinedSurface.getCanvas()!; tiles.forEach((c, index) => { const row = Math.floor(index / TileRows); const column = index % TileColumns; combinedCanvas.drawImageRectCubic( c, CanvasKit.XYWHRect(0, 0, TileSize, TileSize), CanvasKit.XYWHRect( row * TileSizeScaled, column * TileSizeScaled, TileSizeScaled, TileSizeScaled ), 1, 1 ); }); CombinedSurface.flush(); console.timeEnd('combine tiles'); // keep the references, prevent gc // blocks.forEach((b) => b.delete()); } main();
有关gpu的surface,skimage转换的api们:
这些方法在 CanvasKit API 中用于处理与后端纹理和渲染目标相关的操作。它们主要用于高级图形编程,特别是在处理纹理和渲染目标时。这些方法允许你与底层图形 API(如 OpenGL 或 Vulkan)进行交互,以实现更高效和定制化的图形渲染。以下是这些方法的详细作用和区别:
MakeFromBackendTexture
- 作用: 从后端纹理创建一个 SkImage 对象。
- 用途: 用于将已有的 GPU 纹理资源包装成 SkImage 对象,以便在 CanvasKit 中使用。
- 典型场景: 你已经有一个由 OpenGL 或 Vulkan 创建的纹理,并希望在 CanvasKit 中对其进行绘制或处理。
javascript
const skImage = CanvasKit.MakeFromBackendTexture(
context,
backendTexture,
origin,
colorType,
alphaType,
colorSpace
);
MakeFromBackendRenderTarget
- 作用: 从后端渲染目标创建一个 SkSurface 对象。
- 用途: 用于将已有的 GPU 渲染目标资源包装成 SkSurface 对象,以便在 CanvasKit 中进行绘制操作。
- 典型场景: 你有一个由 OpenGL 或 Vulkan 创建的渲染目标,并希望在 CanvasKit 中对其进行绘制。
javascript
const skSurface = CanvasKit.MakeFromBackendRenderTarget(
context,
backendRenderTarget,
origin,
colorType,
colorSpace,
props
);
MakeRenderTarget
- 作用: 创建一个新的 SkSurface 对象,作为渲染目标。
- 用途: 用于创建一个新的渲染目标,以便在 CanvasKit 中进行绘制操作。
- 典型场景: 你需要一个新的渲染目标用于离屏渲染或其他图形操作。
const skSurface = CanvasKit.MakeRenderTarget(
context, // GrDirectContext, 表示 GPU 上下文。
width, // int, 渲染目标的宽度。
height, // int, 渲染目标的高度。
colorType, // SkColorType, 颜色类型。
alphaType, // SkAlphaType, Alpha 类型。
colorSpace, // SkColorSpace, 颜色空间。
sampleCount, // int, 抗锯齿采样数(可选)。
surfaceProps // SkSurfaceProps, 表面属性(可选)。
);
width, // int, 渲染目标的宽度。
height, // int, 渲染目标的高度。
colorType, // SkColorType, 颜色类型。
alphaType, // SkAlphaType, Alpha 类型。
colorSpace, // SkColorSpace, 颜色空间。
sampleCount, // int, 抗锯齿采样数(可选)。
surfaceProps // SkSurfaceProps, 表面属性(可选)。
);
getBackendTexture
- 作用: 获取 SkImage 对象的后端纹理信息。
- 用途: 用于访问 SkImage 对象所使用的底层 GPU 纹理信息。
- 典型场景: 你需要获取 SkImage 对象的底层纹理以进行进一步的 GPU 操作。
javascript
const backendTexture = skImage.getBackendTexture();
getBackendRenderTarget
- 作用: 获取 SkSurface 对象的后端渲染目标信息。
- 用途: 用于访问 SkSurface 对象所使用的底层 GPU 渲染目标信息。
- 典型场景: 你需要获取 SkSurface 对象的底层渲染目标以进行进一步的 GPU 操作。
javascript
const backendRenderTarget = skSurface.getBackendRenderTarget();
replaceBackendTexture
- 作用: 用新的后端纹理替换 SkImage 对象当前使用的纹理。
- 用途: 用于动态替换 SkImage 对象的底层 GPU 纹理。
- 典型场景: 你需要在运行时替换 SkImage 对象的纹理资源。
javascript
skImage.replaceBackendTexture(newBackendTexture);
flush
- 作用: 将所有挂起的绘制命令提交给 GPU。
- 用途: 用于确保所有的绘制命令都已被处理并提交给 GPU。
- 典型场景: 你需要在某个时刻确保所有的绘制操作都已完成,例如在渲染结束或在切换纹理之前。
javascript
skSurface.flush();
总结
这些方法提供了与底层图形 API 的直接交互能力,允许你在 CanvasKit 中高效地管理和操作纹理和渲染目标。它们的区别在于各自操作的对象(纹理或渲染目标)以及具体的用途(创建、获取信息、替换等)。了解它们的作用有助于你在进行高级图形编程时充分利用 CanvasKit 的功能。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?