wg_engine: Viewport support

[issues 1479: Viewport](#1479)

Supports viewport settings and rectangular clip path.
Scissors cliping used as a way to clip viewport
This commit is contained in:
Sergii Liebodkin 2024-07-10 15:44:43 +00:00 committed by Hermet Park
parent d6d4839f1a
commit 3223f17f9c
5 changed files with 16 additions and 4 deletions

View file

@ -86,6 +86,7 @@ struct WgRenderSettings
struct WgRenderDataPaint struct WgRenderDataPaint
{ {
WgBindGroupPaint bindGroupPaint{}; WgBindGroupPaint bindGroupPaint{};
RenderRegion viewport{};
float opacity{}; float opacity{};
virtual ~WgRenderDataPaint() {}; virtual ~WgRenderDataPaint() {};

View file

@ -30,6 +30,7 @@
{ {
release(context); release(context);
// store target storage size // store target storage size
this->samples = samples;
width = w * samples; width = w * samples;
height = h * samples; height = h * samples;
workgroupsCountX = (width + WG_COMPUTE_WORKGROUP_SIZE_X - 1) / WG_COMPUTE_WORKGROUP_SIZE_X; // workgroup size x == 8 workgroupsCountX = (width + WG_COMPUTE_WORKGROUP_SIZE_X - 1) / WG_COMPUTE_WORKGROUP_SIZE_X; // workgroup size x == 8
@ -100,6 +101,8 @@ void WgRenderStorage::renderPicture(WgContext& context, WgRenderDataPicture* ren
assert(renderData); assert(renderData);
assert(mRenderPassEncoder); assert(mRenderPassEncoder);
uint8_t blend = (uint8_t)blendType; uint8_t blend = (uint8_t)blendType;
auto& vp = renderData->viewport;
wgpuRenderPassEncoderSetScissorRect(mRenderPassEncoder, vp.x * samples, vp.y * samples, vp.w * samples, vp.h * samples);
wgpuRenderPassEncoderSetStencilReference(mRenderPassEncoder, 0); wgpuRenderPassEncoderSetStencilReference(mRenderPassEncoder, 0);
mPipelines->image[blend].use(mRenderPassEncoder, mBindGroupCanvas, renderData->bindGroupPaint, renderData->bindGroupPicture); mPipelines->image[blend].use(mRenderPassEncoder, mBindGroupCanvas, renderData->bindGroupPaint, renderData->bindGroupPicture);
renderData->meshData.drawImage(context, mRenderPassEncoder); renderData->meshData.drawImage(context, mRenderPassEncoder);
@ -112,7 +115,8 @@ void WgRenderStorage::drawShape(WgContext& context, WgRenderDataShape* renderDat
assert(mRenderPassEncoder); assert(mRenderPassEncoder);
assert(renderData->meshGroupShapes.meshes.count == renderData->meshGroupShapesBBox.meshes.count); assert(renderData->meshGroupShapes.meshes.count == renderData->meshGroupShapesBBox.meshes.count);
if (renderData->renderSettingsShape.skip) return; if (renderData->renderSettingsShape.skip) return;
// draw shape geometry auto& vp = renderData->viewport;
wgpuRenderPassEncoderSetScissorRect(mRenderPassEncoder, vp.x * samples, vp.y * samples, vp.w * samples, vp.h * samples);
wgpuRenderPassEncoderSetStencilReference(mRenderPassEncoder, 0); wgpuRenderPassEncoderSetStencilReference(mRenderPassEncoder, 0);
// setup fill rule // setup fill rule
if (renderData->fillRule == FillRule::Winding) if (renderData->fillRule == FillRule::Winding)
@ -141,6 +145,8 @@ void WgRenderStorage::drawStroke(WgContext& context, WgRenderDataShape* renderDa
assert(mRenderPassEncoder); assert(mRenderPassEncoder);
assert(renderData->meshGroupStrokes.meshes.count == renderData->meshGroupStrokesBBox.meshes.count); assert(renderData->meshGroupStrokes.meshes.count == renderData->meshGroupStrokesBBox.meshes.count);
if (renderData->renderSettingsStroke.skip) return; if (renderData->renderSettingsStroke.skip) return;
auto& vp = renderData->viewport;
wgpuRenderPassEncoderSetScissorRect(mRenderPassEncoder, vp.x * samples, vp.y * samples, vp.w * samples, vp.h * samples);
// draw stroke geometry // draw stroke geometry
uint8_t blend = (uint8_t)blendType; uint8_t blend = (uint8_t)blendType;
// draw strokes to stencil (first pass) // draw strokes to stencil (first pass)

View file

@ -38,6 +38,7 @@ public:
WGPUTextureView texViewStencil{}; WGPUTextureView texViewStencil{};
WgBindGroupTextureStorageRgba bindGroupTexStorageRgba; WgBindGroupTextureStorageRgba bindGroupTexStorageRgba;
WgBindGroupTextureStorageBgra bindGroupTexStorageBgra; WgBindGroupTextureStorageBgra bindGroupTexStorageBgra;
uint32_t samples{};
uint32_t width{}; uint32_t width{};
uint32_t height{}; uint32_t height{};
uint32_t workgroupsCountX{}; uint32_t workgroupsCountX{};

View file

@ -113,6 +113,7 @@ RenderData WgRenderer::prepare(const RenderShape& rshape, RenderData data, const
} }
// setup fill settings // setup fill settings
renderDataShape->viewport = mViewport;
renderDataShape->opacity = opacity; renderDataShape->opacity = opacity;
renderDataShape->renderSettingsShape.update(mContext, rshape.fill, rshape.color, flags); renderDataShape->renderSettingsShape.update(mContext, rshape.fill, rshape.color, flags);
if (rshape.stroke) if (rshape.stroke)
@ -136,6 +137,7 @@ RenderData WgRenderer::prepare(Surface* surface, const RenderMesh* mesh, RenderD
renderDataPicture = new WgRenderDataPicture(); renderDataPicture = new WgRenderDataPicture();
// update paint settings // update paint settings
renderDataPicture->viewport = mViewport;
renderDataPicture->opacity = opacity; renderDataPicture->opacity = opacity;
if (flags & (RenderUpdateFlag::Transform | RenderUpdateFlag::Blend)) { if (flags & (RenderUpdateFlag::Transform | RenderUpdateFlag::Blend)) {
WgShaderTypeMat4x4f modelMat(transform); WgShaderTypeMat4x4f modelMat(transform);
@ -261,17 +263,18 @@ RenderRegion WgRenderer::region(TVG_UNUSED RenderData data)
RenderRegion WgRenderer::viewport() { RenderRegion WgRenderer::viewport() {
return { 0, 0, INT32_MAX, INT32_MAX }; return mViewport;
} }
bool WgRenderer::viewport(TVG_UNUSED const RenderRegion& vp) bool WgRenderer::viewport(const RenderRegion& vp)
{ {
mViewport = vp;
return true; return true;
} }
bool WgRenderer::blend(TVG_UNUSED BlendMethod method) bool WgRenderer::blend(BlendMethod method)
{ {
mBlendMethod = method; mBlendMethod = method;
return false; return false;

View file

@ -80,6 +80,7 @@ private:
WgContext mContext; WgContext mContext;
WgPipelines mPipelines; WgPipelines mPipelines;
Surface mTargetSurface; Surface mTargetSurface;
RenderRegion mViewport{};
BlendMethod mBlendMethod{}; // current blend method BlendMethod mBlendMethod{}; // current blend method