From d195fb1f61fd00ac0d2b2409eaef2be1a881154c Mon Sep 17 00:00:00 2001 From: Martin Fouilleul Date: Mon, 27 Feb 2023 14:24:59 +0100 Subject: [PATCH] [canvas, mtl backend] Compute each layer with pre-multiplied alpha, starting from transparent color. Composite them to surface with premultiplied alpha too. --- src/mtl_canvas.m | 12 +++--------- src/mtl_shader.metal | 2 ++ src/mtl_surface.m | 11 ----------- 3 files changed, 5 insertions(+), 20 deletions(-) diff --git a/src/mtl_canvas.m b/src/mtl_canvas.m index 117fcd7..261b272 100644 --- a/src/mtl_canvas.m +++ b/src/mtl_canvas.m @@ -467,11 +467,6 @@ mg_canvas_backend* mg_mtl_canvas_create(mg_surface surface) //----------------------------------------------------------- backend->tileCounters = [metalSurface->device newBufferWithLength: RENDERER_MAX_TILES*sizeof(uint) options: MTLResourceStorageModePrivate]; - id commandBuffer = [metalSurface->commandQueue commandBuffer]; - id blitEncoder = [commandBuffer blitCommandEncoder]; - [blitEncoder fillBuffer: backend->tileCounters range: NSMakeRange(0, RENDERER_MAX_TILES*sizeof(uint)) value: 0]; - [blitEncoder endEncoding]; - //----------------------------------------------------------- //NOTE(martin): load the library //----------------------------------------------------------- @@ -539,12 +534,11 @@ mg_canvas_backend* mg_mtl_canvas_create(mg_surface surface) pipelineStateDescriptor.colorAttachments[0].pixelFormat = metalSurface->mtlLayer.pixelFormat; pipelineStateDescriptor.colorAttachments[0].blendingEnabled = YES; pipelineStateDescriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd; - pipelineStateDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha; + pipelineStateDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorOne; pipelineStateDescriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha; - pipelineStateDescriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd; - pipelineStateDescriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorZero; - pipelineStateDescriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOne; + pipelineStateDescriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne; + pipelineStateDescriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha; // create render pipeline backend->renderPipeline = [metalSurface->device newRenderPipelineStateWithDescriptor: pipelineStateDescriptor error:&err]; diff --git a/src/mtl_shader.metal b/src/mtl_shader.metal index 5de0ed6..965beb9 100644 --- a/src/mtl_shader.metal +++ b/src/mtl_shader.metal @@ -266,6 +266,7 @@ kernel void RenderKernel(texture2d outTexture [[texture(0) int shapeIndex = v0->shapeIndex; float4 color = shapeBuffer[shapeIndex].color; + color.rgb *= color.a; const device float* uvTransform2x3 = shapeBuffer[shapeIndex].uvTransform; matrix_float3x3 uvTransform = {{uvTransform2x3[0], uvTransform2x3[3], 0}, @@ -298,6 +299,7 @@ kernel void RenderKernel(texture2d outTexture [[texture(0) { constexpr sampler smp(mip_filter::nearest, mag_filter::linear, min_filter::linear); texColor = texAtlas.sample(smp, uv); + texColor.rgb *= texColor.a; } //TODO(martin): this is a quick and dirty fix for solid polygons where we use // cubic = (1, 1, 1, 1) on all vertices, which can cause small errors to diff --git a/src/mtl_surface.m b/src/mtl_surface.m index 63ef781..8e299f5 100644 --- a/src/mtl_surface.m +++ b/src/mtl_surface.m @@ -99,17 +99,6 @@ void mg_mtl_surface_prepare(mg_surface_data* interface) { mg_mtl_surface* surface = (mg_mtl_surface*)interface; mg_mtl_surface_acquire_drawable_and_command_buffer(surface); - - @autoreleasepool - { - MTLRenderPassDescriptor* renderPassDescriptor = [MTLRenderPassDescriptor renderPassDescriptor]; - renderPassDescriptor.colorAttachments[0].texture = surface->drawable.texture; - renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear; - renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(0.0,0.0,0.0,0.0); - - id renderEncoder = [surface->commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor]; - [renderEncoder endEncoding]; - } } void mg_mtl_surface_present(mg_surface_data* interface)