the second seems to be fixed via
```
using AndroidUI.Utils;
using SkiaSharp;
namespace AndroidUI.Graphics
{
public class SKOverdrawCanvas2 : SKCanvasForwarder
{
class CanvasInfo
{
public SKOverdrawCanvas overdrawCanvas;
public SKCanvas canvas;
public SKBitmap bitmap;
public CanvasInfo(SKOverdrawCanvas overdrawCanvas, SKCanvas canvas, SKBitmap bitmap = null)
{
this.overdrawCanvas = overdrawCanvas;
this.canvas = canvas;
this.bitmap = bitmap;
}
}
Stack<CanvasInfo> stack_canvas = new(); // class
Stack<bool> stack_is_layer = new();
CanvasInfo top_canvas;
string shader_error_message;
SKRuntimeEffect sksl;
public string Shader_error_message => shader_error_message;
public SKOverdrawCanvas2(SKCanvas canvas)
{
stack_is_layer.Push(false);
pushCanvas(new SKOverdrawCanvas(canvas), canvas);
sksl = SKRuntimeEffect.Create(
"uniform shader src;\n" +
"uniform shader dst;\n" +
"\n" +
"half4 main() {\n" +
" float srcAlpha = sample(src).a;\n" +
" float dstAlpha = sample(dst).a;\n" +
" float alpha = srcAlpha + dstAlpha;\n" +
" return half4(0, 0, 0, alpha > 1.0 ? 1.0 : alpha);\n" +
"}\n",
out shader_error_message
);
}
void pushCanvas(SKOverdrawCanvas overdrawCanvas, SKCanvas canvas, SKBitmap bitmap = null)
{
top_canvas = new(overdrawCanvas, canvas, bitmap);
stack_canvas.Push(top_canvas);
ReleaseNativeObject();
SetNativeObject(top_canvas.overdrawCanvas, false);
}
void pushCanvas()
{
if (top_canvas.canvas.Surface.Context != null)
{
// GPU
var surface = SKSurface.Create(top_canvas.canvas.Surface.Context, false,
top_canvas.canvas.Info);
pushCanvas(new SKOverdrawCanvas(surface.Canvas), surface.Canvas);
}
else
{
// CPU
SKBitmap bitmap = new(
top_canvas.canvas.Info);
SKCanvas canvas = new(bitmap);
pushCanvas(new SKOverdrawCanvas(canvas), canvas, bitmap);
}
}
CanvasInfo popCanvas()
{
var info = stack_canvas.Pop();
top_canvas = stack_canvas.Peek();
ReleaseNativeObject();
SetNativeObject(top_canvas.overdrawCanvas, false);
return info;
}
public override void RestoreToCount(int count)
{
// safety check
if (count < 2)
{
count = 2;
}
int n = SaveCount - count;
for (int i = 0; i < n; ++i)
{
Restore();
}
}
protected override void Dispose(bool disposing)
{
RestoreToCount(1);
RestoreInternal();
// dispose temporary overdraw canvas
ReleaseNativeObject();
stack_canvas.Pop().overdrawCanvas.Dispose();
sksl.Dispose();
base.Dispose(disposing);
}
public override int Save()
{
stack_is_layer.Push(false);
return base.Save();
}
public override int SaveLayer(SKPaint paint)
{
return SaveLayer(DeviceClipBounds, paint);
}
public override int SaveLayer(SKRect limit, SKPaint paint)
{
Log.d("CLIP", "limit: " + limit);
if (paint != null && paint.NothingToDraw)
{
// no need for the layer (or any of the draws until the matching restore()
// increase internal save count
base.Save();
stack_is_layer.Push(false);
ClipRect(new SKRect(0, 0, 0, 0));
}
else
{
// increase internal save count
base.Save();
stack_is_layer.Push(true);
// push everything to stack
pushCanvas();
ClipRect(limit);
}
return SaveCount - 1;
}
public override void Restore()
{
// noop if we are at base
if (stack_is_layer.Count == 1) return;
RestoreInternal();
}
private void RestoreInternal()
{
bool is_layer = stack_is_layer.Pop();
if (!is_layer)
{
// we are restoring a save()
base.Restore();
return;
}
// we are restoring a layer
SKImage srcImage;
Flush();
bool is_gpu = top_canvas.canvas.Surface.Context != null;
var info = popCanvas();
if (is_gpu)
{
// we are restoring a GPU layer
var surface = info.canvas.Surface;
srcImage = surface.Snapshot();
// canvas is owned by surface
surface.Dispose();
}
else
{
// we are restoring a CPU layer
SKBitmap bitmap = info.bitmap;
srcImage = bitmap.AsImage();
bitmap.Dispose();
info.canvas.Dispose();
}
info = null;
using var raster = srcImage.ToRasterImage();
using var pixelsAlpha = raster.PeekPixels();
int alpha = pixelsAlpha.GetPixelSpan()[0];
Log.d("OVERDRAW 2", "src alpha: " + alpha);
using var srcShader = srcImage.ToShader();
using var dstImage = top_canvas.canvas.Surface.Snapshot();
using var dstShader = dstImage.ToShader();
SKRuntimeEffectChildren children = new(sksl) {
{ "src", srcShader },
{ "dst", dstShader }
};
using var shader = sksl.ToShader(false, new(sksl), children);
using var paint = new SKPaint();
paint.BlendMode = SKBlendMode.Src; // shader pixels only
paint.Shader = shader;
top_canvas.canvas.DrawPaint(paint);
srcImage.Dispose();
}
}
}
```