浏览代码

preparation for the optimization of composite and rasterization

(1) create uiPicture and uiDrawCmds
/main
xingwei.zhu 5 年前
当前提交
3ecb9cf0
共有 41 个文件被更改,包括 1679 次插入1150 次删除
  1. 7
      Samples/UIWidgetSample/TextInput.unity
  2. 4
      Runtime/ui/utils/renderer/cmdbufferCanvas/command_buffer_canvas.cs
  3. 1001
      Runtime/ui/utils/renderer/cmdbufferCanvas/rendering/canvas_impl.cs
  4. 301
      Runtime/ui/utils/renderer/common/base_canvas.cs
  5. 94
      Runtime/ui/utils/renderer/common/draw_cmd.cs
  6. 276
      Runtime/ui/utils/renderer/common/picture.cs
  7. 11
      Runtime/ui/utils/renderer/canvas_clip.cs.meta
  8. 981
      Runtime/ui/utils/renderer/canvas_impl.cs
  9. 11
      Runtime/ui/utils/renderer/canvas_impl.cs.meta
  10. 11
      Runtime/ui/utils/renderer/canvas_shader.cs.meta
  11. 11
      Runtime/ui/utils/renderer/canvas_shader_utils.cs.meta
  12. 11
      Runtime/ui/utils/renderer/canvas_utils.cs.meta
  13. 11
      Runtime/ui/utils/renderer/command_buffer_canvas.cs.meta
  14. 11
      Runtime/ui/utils/renderer/generic_list.cs.meta
  15. 11
      Runtime/ui/utils/renderer/mesh_mesh.cs.meta
  16. 11
      Runtime/ui/utils/renderer/path.cs.meta
  17. 11
      Runtime/ui/utils/renderer/path_cache.cs.meta
  18. 11
      Runtime/ui/utils/renderer/path_utils.cs.meta
  19. 11
      Runtime/ui/utils/renderer/pool_items.cs.meta
  20. 11
      Runtime/ui/utils/renderer/render_cmd.cs.meta
  21. 11
      Runtime/ui/utils/renderer/render_layer.cs.meta
  22. 11
      Runtime/ui/utils/renderer/tessellation_generator.cs.meta
  23. 0
      /Runtime/ui/utils/renderer/cmdbufferCanvas/rendering/canvas_clip.cs
  24. 0
      /Runtime/ui/utils/renderer/cmdbufferCanvas/rendering/canvas_shader.cs
  25. 0
      /Runtime/ui/utils/renderer/cmdbufferCanvas/rendering/canvas_shader_utils.cs
  26. 0
      /Runtime/ui/utils/renderer/cmdbufferCanvas/rendering/canvas_utils.cs
  27. 0
      /Runtime/ui/utils/renderer/cmdbufferCanvas/command_buffer_canvas.cs
  28. 0
      /Runtime/ui/utils/renderer/allocUtils/generic_list.cs
  29. 0
      /Runtime/ui/utils/renderer/geometry/mesh_mesh.cs
  30. 0
      /Runtime/ui/utils/renderer/geometry/path/path.cs
  31. 0
      /Runtime/ui/utils/renderer/geometry/path/path_cache.cs
  32. 0
      /Runtime/ui/utils/renderer/geometry/path/path_utils.cs
  33. 0
      /Runtime/ui/utils/renderer/allocUtils/pool_items.cs
  34. 0
      /Runtime/ui/utils/renderer/cmdbufferCanvas/rendering/render_cmd.cs
  35. 0
      /Runtime/ui/utils/renderer/cmdbufferCanvas/rendering/render_layer.cs
  36. 0
      /Runtime/ui/utils/renderer/geometry/path/tessellation_generator.cs

7
Samples/UIWidgetSample/TextInput.unity


m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0.37311947, g: 0.38074, b: 0.35872698, a: 1}
m_IndirectSpecularColor: {r: 0.37311953, g: 0.38074, b: 0.35872698, a: 1}
m_UseRadianceAmbientProbe: 0
--- !u!157 &3
LightmapSettings:

width: 1
height: 1
devicePixelRatioOverride: 0
antiAliasingOverride: 4
--- !u!222 &1142533066
CanvasRenderer:
m_ObjectHideFlags: 0

width: 1
height: 1
devicePixelRatioOverride: 4
antiAliasingOverride: 4
--- !u!222 &1354314694
CanvasRenderer:
m_ObjectHideFlags: 0

m_GameObject: {fileID: 1387978526}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e9bc91696c1584e11b23dca1a9e3cde3, type: 3}
m_Script: {fileID: 11500000, guid: 9c5c86936ca864ae684720ddcd50d759, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}

width: 1
height: 1
devicePixelRatioOverride: 0
antiAliasingOverride: 4
--- !u!222 &1387978529
CanvasRenderer:
m_ObjectHideFlags: 0

4
Runtime/ui/utils/renderer/cmdbufferCanvas/command_buffer_canvas.cs


using UnityEngine;
namespace Unity.UIWidgets.ui {
public class CommandBufferCanvas : RecorderCanvas {
public class CommandBufferCanvas : uiRecorderCanvas {
: base(new PictureRecorder()) {
: base(new uiPictureRecorder()) {
this._flusher = new PictureFlusher(renderTexture, devicePixelRatio, meshPool);
}

1001
Runtime/ui/utils/renderer/cmdbufferCanvas/rendering/canvas_impl.cs
文件差异内容过多而无法显示
查看文件

301
Runtime/ui/utils/renderer/common/base_canvas.cs


using System;
using Unity.UIWidgets.flow;
using Unity.UIWidgets.foundation;
using UnityEngine;
namespace Unity.UIWidgets.ui {
public class uiRecorderCanvas : PoolItem, Canvas {
public uiRecorderCanvas(uiPictureRecorder recorder) {
this._recorder = recorder;
}
protected readonly uiPictureRecorder _recorder;
int _saveCount = 1;
public void save() {
this._saveCount++;
this._recorder.addDrawCmd(new uiDrawSave {
});
}
public void saveLayer(Rect rect, Paint paint) {
this._saveCount++;
this._recorder.addDrawCmd(new uiDrawSaveLayer {
rect = rect,
paint = new Paint(paint),
});
}
public void restore() {
this._saveCount--;
this._recorder.addDrawCmd(new uiDrawRestore {
});
}
public int getSaveCount() {
return this._saveCount;
}
public void translate(float dx, float dy) {
this._recorder.addDrawCmd(new uiDrawTranslate {
dx = dx,
dy = dy,
});
}
public void scale(float sx, float? sy = null) {
this._recorder.addDrawCmd(new uiDrawScale {
sx = sx,
sy = sy,
});
}
public void rotate(float radians, Offset offset = null) {
this._recorder.addDrawCmd(new uiDrawRotate {
radians = radians,
offset = offset,
});
}
public void skew(float sx, float sy) {
this._recorder.addDrawCmd(new uiDrawSkew {
sx = sx,
sy = sy,
});
}
public void concat(Matrix3 matrix) {
this._recorder.addDrawCmd(new uiDrawConcat {
matrix = matrix,
});
}
public Matrix3 getTotalMatrix() {
return this._recorder.getTotalMatrix();
}
public void resetMatrix() {
this._recorder.addDrawCmd(new uiDrawResetMatrix {
});
}
public void setMatrix(Matrix3 matrix) {
this._recorder.addDrawCmd(new uiDrawSetMatrix {
matrix = matrix,
});
}
public virtual float getDevicePixelRatio() {
throw new Exception("not available in recorder");
}
public void clipRect(Rect rect) {
this._recorder.addDrawCmd(new uiDrawClipRect {
rect = rect,
});
}
public void clipRRect(RRect rrect) {
this._recorder.addDrawCmd(new uiDrawClipRRect {
rrect = rrect,
});
}
public void clipPath(Path path) {
this._recorder.addDrawCmd(new uiDrawClipPath {
path = path,
});
}
public void drawLine(Offset from, Offset to, Paint paint) {
var path = new Path();
path.moveTo(from.dx, from.dy);
path.lineTo(to.dx, to.dy);
this._recorder.addDrawCmd(new uiDrawPath {
path = path,
paint = new Paint(paint),
});
}
public void drawShadow(Path path, Color color, float elevation, bool transparentOccluder) {
float dpr = Window.instance.devicePixelRatio;
PhysicalShapeLayer.drawShadow(this, path, color, elevation, transparentOccluder, dpr);
}
public void drawRect(Rect rect, Paint paint) {
if (rect.size.isEmpty) {
return;
}
var path = new Path();
path.addRect(rect);
this._recorder.addDrawCmd(new uiDrawPath {
path = path,
paint = new Paint(paint),
});
}
public void drawRRect(RRect rrect, Paint paint) {
var path = new Path();
path.addRRect(rrect);
this._recorder.addDrawCmd(new uiDrawPath {
path = path,
paint = new Paint(paint),
});
}
public void drawDRRect(RRect outer, RRect inner, Paint paint) {
var path = new Path();
path.addRRect(outer);
path.addRRect(inner);
path.winding(PathWinding.clockwise);
this._recorder.addDrawCmd(new uiDrawPath {
path = path,
paint = new Paint(paint),
});
}
public void drawOval(Rect rect, Paint paint) {
var w = rect.width / 2;
var h = rect.height / 2;
var path = new Path();
path.addEllipse(rect.left + w, rect.top + h, w, h);
this._recorder.addDrawCmd(new uiDrawPath {
path = path,
paint = new Paint(paint),
});
}
public void drawCircle(Offset c, float radius, Paint paint) {
var path = new Path();
path.addCircle(c.dx, c.dy, radius);
this._recorder.addDrawCmd(new uiDrawPath {
path = path,
paint = new Paint(paint),
});
}
public void drawArc(Rect rect, float startAngle, float sweepAngle, bool useCenter, Paint paint) {
var path = new Path();
if (useCenter) {
var center = rect.center;
path.moveTo(center.dx, center.dy);
}
bool forceMoveTo = !useCenter;
while (sweepAngle <= -Mathf.PI * 2) {
path.arcTo(rect, startAngle, -Mathf.PI, forceMoveTo);
startAngle -= Mathf.PI;
path.arcTo(rect, startAngle, -Mathf.PI, false);
startAngle -= Mathf.PI;
forceMoveTo = false;
sweepAngle += Mathf.PI * 2;
}
while (sweepAngle >= Mathf.PI * 2) {
path.arcTo(rect, startAngle, Mathf.PI, forceMoveTo);
startAngle += Mathf.PI;
path.arcTo(rect, startAngle, Mathf.PI, false);
startAngle += Mathf.PI;
forceMoveTo = false;
sweepAngle -= Mathf.PI * 2;
}
path.arcTo(rect, startAngle, sweepAngle, forceMoveTo);
if (useCenter) {
path.close();
}
this._recorder.addDrawCmd(new uiDrawPath {
path = path,
paint = new Paint(paint),
});
}
public void drawPath(Path path, Paint paint) {
this._recorder.addDrawCmd(new uiDrawPath {
path = path,
paint = new Paint(paint),
});
}
public void drawImage(Image image, Offset offset, Paint paint) {
this._recorder.addDrawCmd(new uiDrawImage {
image = image,
offset = offset,
paint = new Paint(paint),
});
}
public void drawImageRect(Image image, Rect dst, Paint paint) {
this._recorder.addDrawCmd(new uiDrawImageRect {
image = image,
dst = dst,
paint = new Paint(paint),
});
}
public void drawImageRect(Image image, Rect src, Rect dst, Paint paint) {
this._recorder.addDrawCmd(new uiDrawImageRect {
image = image,
src = src,
dst = dst,
paint = new Paint(paint),
});
}
public void drawImageNine(Image image, Rect center, Rect dst, Paint paint) {
this._recorder.addDrawCmd(new uiDrawImageNine {
image = image,
center = center,
dst = dst,
paint = new Paint(paint),
});
}
public void drawImageNine(Image image, Rect src, Rect center, Rect dst, Paint paint) {
this._recorder.addDrawCmd(new uiDrawImageNine {
image = image,
src = src,
center = center,
dst = dst,
paint = new Paint(paint),
});
}
public void drawPicture(Picture picture) {
this._recorder.addDrawCmd(new uiDrawPicture {
picture = picture,
});
}
public void drawTextBlob(TextBlob textBlob, Offset offset, Paint paint) {
this._recorder.addDrawCmd(new uiDrawTextBlob {
textBlob = textBlob,
offset = offset,
paint = new Paint(paint),
});
}
public void drawParagraph(Paragraph paragraph, Offset offset) {
D.assert(paragraph != null);
D.assert(PaintingUtils._offsetIsValid(offset));
paragraph.paint(this, offset);
}
public virtual void flush() {
throw new Exception("not available in recorder");
}
public void reset() {
this._recorder.reset();
}
}
}

94
Runtime/ui/utils/renderer/common/draw_cmd.cs


namespace Unity.UIWidgets.ui {
public abstract class uiDrawCmd {
}
public class uiDrawSave : uiDrawCmd {
}
public class uiDrawSaveLayer : uiDrawCmd {
public Rect rect;
public Paint paint;
}
public class uiDrawRestore : uiDrawCmd {
}
public class uiDrawTranslate : uiDrawCmd {
public float dx;
public float dy;
}
public class uiDrawScale : uiDrawCmd {
public float sx;
public float? sy;
}
public class uiDrawRotate : uiDrawCmd {
public float radians;
public Offset offset;
}
public class uiDrawSkew : uiDrawCmd {
public float sx;
public float sy;
}
public class uiDrawConcat : uiDrawCmd {
public Matrix3 matrix;
}
public class uiDrawResetMatrix : uiDrawCmd {
}
public class uiDrawSetMatrix : uiDrawCmd {
public Matrix3 matrix;
}
public class uiDrawClipRect : uiDrawCmd {
public Rect rect;
}
public class uiDrawClipRRect : uiDrawCmd {
public RRect rrect;
}
public class uiDrawClipPath : uiDrawCmd {
public Path path;
}
public class uiDrawPath : uiDrawCmd {
public Path path;
public Paint paint;
}
public class uiDrawImage : uiDrawCmd {
public Image image;
public Offset offset;
public Paint paint;
}
public class uiDrawImageRect : uiDrawCmd {
public Image image;
public Rect src;
public Rect dst;
public Paint paint;
}
public class uiDrawImageNine : uiDrawCmd {
public Image image;
public Rect src;
public Rect center;
public Rect dst;
public Paint paint;
}
public class uiDrawPicture : uiDrawCmd {
public Picture picture;
}
public class uiDrawTextBlob : uiDrawCmd {
public TextBlob textBlob;
public Offset offset;
public Paint paint;
}
}

276
Runtime/ui/utils/renderer/common/picture.cs


using System;
using System.Collections.Generic;
using Unity.UIWidgets.foundation;
namespace Unity.UIWidgets.ui {
public class uiPicture {
public uiPicture(List<uiDrawCmd> drawCmds, Rect paintBounds) {
this.drawCmds = drawCmds;
this.paintBounds = paintBounds;
}
public readonly List<uiDrawCmd> drawCmds;
public readonly Rect paintBounds;
}
public class uiPictureRecorder {
readonly List<uiDrawCmd> _drawCmds = new List<uiDrawCmd>();
readonly List<uiCanvasState> _states = new List<uiCanvasState>();
public uiPictureRecorder() {
this.reset();
}
uiCanvasState _getState() {
D.assert(this._states.Count > 0);
return this._states[this._states.Count - 1];
}
public Matrix3 getTotalMatrix() {
return this._getState().xform;
}
public void reset() {
this._drawCmds.Clear();
this._states.Clear();
this._states.Add(new uiCanvasState {
xform = Matrix3.I(),
scissor = null,
saveLayer = false,
layerOffset = null,
paintBounds = Rect.zero,
});
}
public uiPicture endRecording() {
if (this._states.Count > 1) {
throw new Exception("unmatched save/restore commands");
}
var state = this._getState();
return new uiPicture(new List<uiDrawCmd>(this._drawCmds), state.paintBounds);
}
public void addDrawCmd(uiDrawCmd drawCmd) {
this._drawCmds.Add(drawCmd);
switch (drawCmd) {
case uiDrawSave _:
this._states.Add(this._getState().copy());
break;
case uiDrawSaveLayer cmd: {
this._states.Add(new uiCanvasState {
xform = Matrix3.I(),
scissor = cmd.rect.shift(-cmd.rect.topLeft),
saveLayer = true,
layerOffset = cmd.rect.topLeft,
paintBounds = Rect.zero,
});
break;
}
case uiDrawRestore _: {
var stateToRestore = this._getState();
this._states.RemoveAt(this._states.Count - 1);
var state = this._getState();
if (!stateToRestore.saveLayer) {
state.paintBounds = stateToRestore.paintBounds;
} else {
var paintBounds = stateToRestore.paintBounds.shift(stateToRestore.layerOffset);
paintBounds = state.xform.mapRect(paintBounds);
this._addPaintBounds(paintBounds);
}
break;
}
case uiDrawTranslate cmd: {
var state = this._getState();
state.xform = new Matrix3(state.xform);
state.xform.preTranslate(cmd.dx, cmd.dy);
break;
}
case uiDrawScale cmd: {
var state = this._getState();
state.xform = new Matrix3(state.xform);
state.xform.preScale(cmd.sx, (cmd.sy ?? cmd.sx));
break;
}
case uiDrawRotate cmd: {
var state = this._getState();
state.xform = new Matrix3(state.xform);
if (cmd.offset == null) {
state.xform.preRotate(cmd.radians);
} else {
state.xform.preRotate(cmd.radians,
cmd.offset.dx,
cmd.offset.dy);
}
break;
}
case uiDrawSkew cmd: {
var state = this._getState();
state.xform = new Matrix3(state.xform);
state.xform.preSkew(cmd.sx, cmd.sy);
break;
}
case uiDrawConcat cmd: {
var state = this._getState();
state.xform = new Matrix3(state.xform);
state.xform.preConcat(cmd.matrix);
break;
}
case uiDrawResetMatrix _: {
var state = this._getState();
state.xform = Matrix3.I();
break;
}
case uiDrawSetMatrix cmd: {
var state = this._getState();
state.xform = new Matrix3(cmd.matrix);
break;
}
case uiDrawClipRect cmd: {
var state = this._getState();
var rect = state.xform.mapRect(cmd.rect);
state.scissor = state.scissor == null ? rect : state.scissor.intersect(rect);
break;
}
case uiDrawClipRRect cmd: {
var state = this._getState();
var rect = state.xform.mapRect(cmd.rrect.outerRect);
state.scissor = state.scissor == null ? rect : state.scissor.intersect(rect);
break;
}
case uiDrawClipPath cmd: {
var state = this._getState();
var scale = XformUtils.getScale(state.xform);
var rect = cmd.path.flatten(
scale * Window.instance.devicePixelRatio
).getFillMesh(out _).transform(state.xform).bounds;
state.scissor = state.scissor == null ? rect : state.scissor.intersect(rect);
break;
}
case uiDrawPath cmd: {
var state = this._getState();
var scale = XformUtils.getScale(state.xform);
var path = cmd.path;
var paint = cmd.paint;
var devicePixelRatio = Window.instance.devicePixelRatio;
MeshMesh mesh;
if (paint.style == PaintingStyle.fill) {
var cache = path.flatten(scale * devicePixelRatio);
mesh = cache.getFillMesh(out _).transform(state.xform);
} else {
float strokeWidth = (paint.strokeWidth * scale).clamp(0, 200.0f);
float fringeWidth = 1 / devicePixelRatio;
if (strokeWidth < fringeWidth) {
strokeWidth = fringeWidth;
}
var cache = path.flatten(scale * devicePixelRatio);
mesh = cache.getStrokeMesh(
strokeWidth / scale * 0.5f,
paint.strokeCap,
paint.strokeJoin,
paint.strokeMiterLimit).transform(state.xform);
}
if (paint.maskFilter != null && paint.maskFilter.sigma != 0) {
float sigma = scale * paint.maskFilter.sigma;
float sigma3 = 3 * sigma;
this._addPaintBounds(mesh.bounds.inflate(sigma3));
} else {
this._addPaintBounds(mesh.bounds);
}
break;
}
case uiDrawImage cmd: {
var state = this._getState();
var rect = Rect.fromLTWH(cmd.offset.dx, cmd.offset.dy,
cmd.image.width, cmd.image.height);
rect = state.xform.mapRect(rect);
this._addPaintBounds(rect);
break;
}
case uiDrawImageRect cmd: {
var state = this._getState();
var rect = state.xform.mapRect(cmd.dst);
this._addPaintBounds(rect);
break;
}
case uiDrawImageNine cmd: {
var state = this._getState();
var rect = state.xform.mapRect(cmd.dst);
this._addPaintBounds(rect);
break;
}
case uiDrawPicture cmd: {
var state = this._getState();
var rect = state.xform.mapRect(cmd.picture.paintBounds);
this._addPaintBounds(rect);
break;
}
case uiDrawTextBlob cmd: {
var state = this._getState();
var scale = XformUtils.getScale(state.xform);
var rect = cmd.textBlob.boundsInText.shift(cmd.offset);
rect = state.xform.mapRect(rect);
var paint = cmd.paint;
if (paint.maskFilter != null && paint.maskFilter.sigma != 0) {
float sigma = scale * paint.maskFilter.sigma;
float sigma3 = 3 * sigma;
this._addPaintBounds(rect.inflate(sigma3));
} else {
this._addPaintBounds(rect);
}
break;
}
default:
throw new Exception("unknown drawCmd: " + drawCmd);
}
}
void _addPaintBounds(Rect paintBounds) {
var state = this._getState();
if (state.scissor != null) {
paintBounds = paintBounds.intersect(state.scissor);
}
if (paintBounds == null || paintBounds.isEmpty) {
return;
}
if (state.paintBounds.isEmpty) {
state.paintBounds = paintBounds;
} else {
state.paintBounds = state.paintBounds.expandToInclude(paintBounds);
}
}
class uiCanvasState {
public Matrix3 xform;
public Rect scissor;
public bool saveLayer;
public Offset layerOffset;
public Rect paintBounds;
public uiCanvasState copy() {
return new uiCanvasState {
xform = this.xform,
scissor = this.scissor,
saveLayer = false,
layerOffset = null,
paintBounds = this.paintBounds,
};
}
}
}
}

11
Runtime/ui/utils/renderer/canvas_clip.cs.meta


fileFormatVersion: 2
guid: a68726f5c264a40e8a0ab3cf5c5170cb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

981
Runtime/ui/utils/renderer/canvas_impl.cs


using System;
using System.Collections.Generic;
using Unity.UIWidgets.foundation;
using UnityEngine;
using UnityEngine.Rendering;
namespace Unity.UIWidgets.ui {
public partial class PictureFlusher {
readonly RenderTexture _renderTexture;
readonly float _fringeWidth;
readonly float _devicePixelRatio;
readonly MeshPool _meshPool;
readonly List<RenderLayer> _layers = new List<RenderLayer>();
RenderLayer _currentLayer;
uiRect? _lastScissor;
public void dispose() {
if (this._currentLayer != null) {
this._clearLayer(this._currentLayer);
this._currentLayer.dispose();
this._currentLayer = null;
this._lastScissor = null;
this._layers.Clear();
}
}
public PictureFlusher(RenderTexture renderTexture, float devicePixelRatio, MeshPool meshPool) {
D.assert(renderTexture);
D.assert(devicePixelRatio > 0);
D.assert(meshPool != null);
this._renderTexture = renderTexture;
this._fringeWidth = 1.0f / devicePixelRatio;
this._devicePixelRatio = devicePixelRatio;
this._meshPool = meshPool;
}
public float getDevicePixelRatio() {
return this._devicePixelRatio;
}
void _reset() {
//clear all states
D.assert(this._layers.Count == 0 || (this._layers.Count == 1 && this._layers[0] == this._currentLayer));
if (this._currentLayer != null) {
this._clearLayer(this._currentLayer);
this._currentLayer.dispose();
this._currentLayer = null;
this._lastScissor = null;
this._layers.Clear();
}
var width = this._renderTexture.width;
var height = this._renderTexture.height;
var bounds = uiRectHelper.fromLTWH(0, 0,
width * this._fringeWidth,
height * this._fringeWidth);
RenderLayer firstLayer = RenderLayer.create(
width: width,
height: height,
layerBounds: bounds
);
this._layers.Add(firstLayer);
this._currentLayer = firstLayer;
}
void _save() {
var layer = this._currentLayer;
layer.currentState = layer.currentState.copy();
layer.states.Add(layer.currentState);
layer.clipStack.save();
}
readonly uiOffset[] _saveLayer_Points = new uiOffset[4];
void _saveLayer(uiRect bounds, Paint paint) {
D.assert(bounds.width > 0);
D.assert(bounds.height > 0);
D.assert(paint != null);
var parentLayer = this._currentLayer;
var state = parentLayer.currentState;
var textureWidth = Mathf.CeilToInt(
bounds.width * state.scale * this._devicePixelRatio);
if (textureWidth < 1) {
textureWidth = 1;
}
var textureHeight = Mathf.CeilToInt(
bounds.height * state.scale * this._devicePixelRatio);
if (textureHeight < 1) {
textureHeight = 1;
}
var layer = RenderLayer.create(
rtID: Shader.PropertyToID("_rtID_" + this._layers.Count + "_" + parentLayer.layers.Count),
width: textureWidth,
height: textureHeight,
layerBounds: bounds,
layerPaint: paint
);
parentLayer.addLayer(layer);
this._layers.Add(layer);
this._currentLayer = layer;
if (paint.backdrop != null) {
if (paint.backdrop is _BlurImageFilter) {
var filter = (_BlurImageFilter) paint.backdrop;
if (!(filter.sigmaX == 0 && filter.sigmaY == 0)) {
this._saveLayer_Points[0] = bounds.topLeft;
this._saveLayer_Points[1] = bounds.bottomLeft;
this._saveLayer_Points[2] = bounds.bottomRight;
this._saveLayer_Points[3] = bounds.topRight;
state.matrix.Value.mapPoints(this._saveLayer_Points);
var parentBounds = parentLayer.layerBounds;
for (int i = 0; i < 4; i++) {
this._saveLayer_Points[i] = new uiOffset(
(this._saveLayer_Points[i].dx - parentBounds.left) / parentBounds.width,
(this._saveLayer_Points[i].dy - parentBounds.top) / parentBounds.height
);
}
var mesh = ImageMeshGenerator.imageMesh(
null,
this._saveLayer_Points[0],
this._saveLayer_Points[1],
this._saveLayer_Points[2],
this._saveLayer_Points[3],
bounds);
var renderDraw = CanvasShader.texRT(layer, layer.layerPaint, mesh, parentLayer);
layer.draws.Add(renderDraw);
var blurLayer = this._createBlurLayer(layer, filter.sigmaX, filter.sigmaY, layer);
var blurMesh = ImageMeshGenerator.imageMesh(null, uiRectHelper.one, bounds);
layer.draws.Add(CanvasShader.texRT(layer, paint, blurMesh, blurLayer));
}
}
else if (paint.backdrop is _MatrixImageFilter) {
var filter = (_MatrixImageFilter) paint.backdrop;
if (!filter.transform.isIdentity()) {
layer.filterMode = filter.filterMode;
this._saveLayer_Points[0] = bounds.topLeft;
this._saveLayer_Points[1] = bounds.bottomLeft;
this._saveLayer_Points[2] = bounds.bottomRight;
this._saveLayer_Points[3] = bounds.topRight;
state.matrix.Value.mapPoints(this._saveLayer_Points);
var parentBounds = parentLayer.layerBounds;
for (int i = 0; i < 4; i++) {
this._saveLayer_Points[i] = new uiOffset(
(this._saveLayer_Points[i].dx - parentBounds.left) / parentBounds.width,
(this._saveLayer_Points[i].dy - parentBounds.top) / parentBounds.height
);
}
var matrix = uiMatrix3.makeTrans(-bounds.left, -bounds.top);
matrix.postConcat(uiMatrix3.fromMatrix3(filter.transform));
matrix.postTranslate(bounds.left, bounds.top);
var mesh = ImageMeshGenerator.imageMesh(
matrix,
this._saveLayer_Points[0],
this._saveLayer_Points[1],
this._saveLayer_Points[2],
this._saveLayer_Points[3],
bounds);
var renderDraw = CanvasShader.texRT(layer, layer.layerPaint, mesh, parentLayer);
layer.draws.Add(renderDraw);
}
}
}
}
void _restore() {
var layer = this._currentLayer;
D.assert(layer.states.Count > 0);
if (layer.states.Count > 1) {
layer.states[layer.states.Count - 1].dispose();
layer.states.RemoveAt(layer.states.Count - 1);
layer.currentState = layer.states[layer.states.Count - 1];
layer.clipStack.restore();
return;
}
this._layers.RemoveAt(this._layers.Count - 1);
var currentLayer = this._currentLayer = this._layers[this._layers.Count - 1];
var state = currentLayer.currentState;
var mesh = ImageMeshGenerator.imageMesh(state.matrix, uiRectHelper.one, layer.layerBounds);
if (!this._applyClip(mesh.bounds)) {
mesh.dispose();
return;
}
var renderDraw = CanvasShader.texRT(currentLayer, layer.layerPaint, mesh, layer);
currentLayer.draws.Add(renderDraw);
}
void _translate(float dx, float dy) {
var state = this._currentLayer.currentState;
var matrix = uiMatrix3.makeTrans(dx, dy);
matrix.postConcat(state.matrix.Value);
state.matrix = matrix;
}
void _scale(float sx, float? sy = null) {
var state = this._currentLayer.currentState;
var matrix = uiMatrix3.makeScale(sx, (sy ?? sx));
matrix.postConcat(state.matrix.Value);
state.matrix = matrix;
}
void _rotate(float radians, uiOffset? offset = null) {
var state = this._currentLayer.currentState;
if (offset == null) {
var matrix = uiMatrix3.makeRotate(radians);
matrix.postConcat(state.matrix.Value);
state.matrix = matrix;
}
else {
var matrix = uiMatrix3.makeRotate(radians, offset.Value.dx, offset.Value.dy);
matrix.postConcat(state.matrix.Value);
state.matrix = matrix;
}
}
void _skew(float sx, float sy) {
var state = this._currentLayer.currentState;
var matrix = uiMatrix3.makeSkew(sx, sy);
matrix.postConcat(state.matrix.Value);
state.matrix = matrix;
}
void _concat(uiMatrix3 matrix) {
var state = this._currentLayer.currentState;
matrix = new uiMatrix3(matrix);
matrix.postConcat(state.matrix.Value);
state.matrix = matrix;
}
void _resetMatrix() {
var state = this._currentLayer.currentState;
state.matrix = uiMatrix3.I();
}
void _setMatrix(uiMatrix3 matrix) {
var state = this._currentLayer.currentState;
state.matrix = new uiMatrix3(matrix);
}
void _clipRect(Rect rect) {
var path = uiPath.create();
path.addRect(rect);
this._clipPath(path);
}
void _clipRRect(RRect rrect) {
var path = uiPath.create();
path.addRRect(rrect);
this._clipPath(path);
}
void _clipPath(uiPath path) {
var layer = this._currentLayer;
var state = layer.currentState;
layer.clipStack.clipPath(path, state.matrix.Value, state.scale * this._devicePixelRatio);
path.dispose();
}
void _tryAddScissor(RenderLayer layer, uiRect? scissor) {
if (uiRectHelper.equals(scissor, this._lastScissor)) {
return;
}
layer.draws.Add(CmdScissor.create(
deviceScissor: scissor
));
this._lastScissor = scissor;
}
bool _applyClip(uiRect? queryBounds) {
if (queryBounds == null || queryBounds.Value.isEmpty) {
return false;
}
var layer = this._currentLayer;
var layerBounds = layer.layerBounds;
ReducedClip reducedClip = ReducedClip.create(layer.clipStack, layerBounds, queryBounds.Value);
if (reducedClip.isEmpty()) {
reducedClip.dispose();
return false;
}
var scissor = reducedClip.scissor;
var physicalRect = uiRectHelper.fromLTRB(0, 0, layer.width, layer.height);
if (uiRectHelper.equals(scissor,layerBounds)) {
this._tryAddScissor(layer, null);
}
else {
var deviceScissor = uiRectHelper.fromLTRB(
scissor.Value.left - layerBounds.left, layerBounds.bottom - scissor.Value.bottom,
scissor.Value.right - layerBounds.left, layerBounds.bottom - scissor.Value.top
);
deviceScissor = uiRectHelper.scale(deviceScissor, layer.width / layerBounds.width, layer.height / layerBounds.height);
deviceScissor = uiRectHelper.roundOut(deviceScissor);
deviceScissor = uiRectHelper.intersect(deviceScissor, physicalRect);
if (deviceScissor.isEmpty) {
reducedClip.dispose();
return false;
}
this._tryAddScissor(layer, deviceScissor);
}
var maskGenID = reducedClip.maskGenID();
if (this._mustRenderClip(maskGenID, reducedClip.scissor.Value)) {
if (maskGenID == ClipStack.wideOpenGenID) {
layer.ignoreClip = true;
}
else {
layer.ignoreClip = false;
// need to inflate a bit to make sure all area is cleared.
var inflatedScissor = uiRectHelper.inflate(reducedClip.scissor.Value, this._fringeWidth);
var boundsMesh = uiMeshMesh.create(inflatedScissor);
layer.draws.Add(CanvasShader.stencilClear(layer, boundsMesh));
foreach (var maskElement in reducedClip.maskElements) {
layer.draws.Add(CanvasShader.stencil0(layer, maskElement.mesh.duplicate()));
layer.draws.Add(CanvasShader.stencil1(layer, boundsMesh.duplicate()));
}
}
this._setLastClipGenId(maskGenID, reducedClip.scissor.Value);
}
reducedClip.dispose();
return true;
}
void _setLastClipGenId(uint clipGenId, uiRect clipBounds) {
var layer = this._currentLayer;
layer.lastClipGenId = clipGenId;
layer.lastClipBounds = clipBounds;
}
bool _mustRenderClip(uint clipGenId, uiRect clipBounds) {
var layer = this._currentLayer;
return layer.lastClipGenId != clipGenId || !uiRectHelper.equals(layer.lastClipBounds, clipBounds);
}
RenderLayer _createMaskLayer(RenderLayer parentLayer, uiRect maskBounds, _drawPathDrawMeshCallbackDelegate drawCallback,
Paint paint, bool convex, float alpha, Texture tex, uiRect texBound, TextBlobMesh textMesh, uiMeshMesh mesh) {
var textureWidth = Mathf.CeilToInt(maskBounds.width * this._devicePixelRatio);
if (textureWidth < 1) {
textureWidth = 1;
}
var textureHeight = Mathf.CeilToInt(maskBounds.height * this._devicePixelRatio);
if (textureHeight < 1) {
textureHeight = 1;
}
var maskLayer = RenderLayer.create(
rtID: Shader.PropertyToID("_rtID_" + this._layers.Count + "_" + parentLayer.layers.Count),
width: textureWidth,
height: textureHeight,
layerBounds: maskBounds,
filterMode: FilterMode.Bilinear,
noMSAA: true
);
parentLayer.addLayer(maskLayer);
this._layers.Add(maskLayer);
this._currentLayer = maskLayer;
var parentState = parentLayer.states[parentLayer.states.Count - 1];
var maskState = maskLayer.states[maskLayer.states.Count - 1];
maskState.matrix = parentState.matrix;
drawCallback.Invoke(Paint.shapeOnly(paint), mesh, convex, alpha, tex, texBound, textMesh);
var removed = this._layers.removeLast();
D.assert(removed == maskLayer);
this._currentLayer = this._layers[this._layers.Count - 1];
return maskLayer;
}
RenderLayer _createBlurLayer(RenderLayer maskLayer, float sigmaX, float sigmaY, RenderLayer parentLayer) {
sigmaX = BlurUtils.adjustSigma(sigmaX, out var scaleFactorX, out var radiusX);
sigmaY = BlurUtils.adjustSigma(sigmaY, out var scaleFactorY, out var radiusY);
var textureWidth = Mathf.CeilToInt((float) maskLayer.width / scaleFactorX);
if (textureWidth < 1) {
textureWidth = 1;
}
var textureHeight = Mathf.CeilToInt((float) maskLayer.height / scaleFactorY);
if (textureHeight < 1) {
textureHeight = 1;
}
var blurXLayer = RenderLayer.create(
rtID: Shader.PropertyToID("_rtID_" + this._layers.Count + "_" + parentLayer.layers.Count),
width: textureWidth,
height: textureHeight,
layerBounds: maskLayer.layerBounds,
filterMode: FilterMode.Bilinear,
noMSAA: true
);
parentLayer.addLayer(blurXLayer);
var blurYLayer = RenderLayer.create(
rtID: Shader.PropertyToID("_rtID_" + this._layers.Count + "_" + parentLayer.layers.Count),
width: textureWidth,
height: textureHeight,
layerBounds: maskLayer.layerBounds,
filterMode: FilterMode.Bilinear,
noMSAA: true
);
parentLayer.addLayer(blurYLayer);
var blurMesh = ImageMeshGenerator.imageMesh(null, uiRectHelper.one, maskLayer.layerBounds);
var kernelX = BlurUtils.get1DGaussianKernel(sigmaX, radiusX);
var kernelY = BlurUtils.get1DGaussianKernel(sigmaY, radiusY);
blurXLayer.draws.Add(CanvasShader.maskFilter(
blurXLayer, blurMesh, maskLayer,
radiusX, new Vector2(1f / textureWidth, 0), kernelX));
blurYLayer.draws.Add(CanvasShader.maskFilter(
blurYLayer, blurMesh.duplicate(), blurXLayer,
radiusY, new Vector2(0, -1f / textureHeight), kernelY));
return blurYLayer;
}
void _drawWithMaskFilter(uiRect meshBounds, Paint paint, MaskFilter maskFilter,
uiMeshMesh mesh, bool convex, float alpha, Texture tex, uiRect texBound, TextBlobMesh textMesh,
_drawPathDrawMeshCallbackDelegate drawCallback) {
var layer = this._currentLayer;
var clipBounds = layer.layerBounds;
uiRect? stackBounds;
bool iior;
layer.clipStack.getBounds(out stackBounds, out iior);
if (stackBounds != null) {
clipBounds = uiRectHelper.intersect(clipBounds,stackBounds.Value);
}
if (clipBounds.isEmpty) {
this._drawPathDrawMeshQuit(mesh);
return;
}
var state = layer.currentState;
float sigma = state.scale * maskFilter.sigma;
if (sigma <= 0) {
this._drawPathDrawMeshQuit(mesh);
return;
}
float sigma3 = 3 * sigma;
var maskBounds = uiRectHelper.inflate(meshBounds, sigma3);
maskBounds = uiRectHelper.intersect(maskBounds, uiRectHelper.inflate(clipBounds,sigma3));
if (maskBounds.isEmpty) {
this._drawPathDrawMeshQuit(mesh);
return;
}
var maskLayer = this._createMaskLayer(layer, maskBounds, drawCallback, paint, convex, alpha, tex, texBound, textMesh, mesh);
var blurLayer = this._createBlurLayer(maskLayer, sigma, sigma, layer);
var blurMesh = ImageMeshGenerator.imageMesh(null, uiRectHelper.one, maskBounds);
if (!this._applyClip(blurMesh.bounds)) {
blurMesh.dispose();
this._drawPathDrawMeshQuit(mesh);
return;
}
layer.draws.Add(CanvasShader.texRT(layer, paint, blurMesh, blurLayer));
}
delegate void _drawPathDrawMeshCallbackDelegate(Paint p, uiMeshMesh mesh, bool convex, float alpha, Texture tex, uiRect textBlobBounds, TextBlobMesh textMesh);
void _drawPathDrawMeshCallback(Paint p, uiMeshMesh mesh, bool convex, float alpha, Texture tex, uiRect textBlobBounds, TextBlobMesh textMesh) {
if (!this._applyClip(mesh.bounds)) {
mesh.dispose();
return;
}
var layer = this._currentLayer;
if (convex) {
layer.draws.Add(CanvasShader.convexFill(layer, p, mesh));
}
else {
layer.draws.Add(CanvasShader.fill0(layer, mesh));
layer.draws.Add(CanvasShader.fill1(layer, p, mesh.boundsMesh));
}
}
void _drawPathDrawMeshCallback2(Paint p, uiMeshMesh mesh, bool convex, float alpha, Texture tex, uiRect textBlobBounds, TextBlobMesh textMesh) {
if (!this._applyClip(mesh.bounds)) {
mesh.dispose();
return;
}
var layer = this._currentLayer;
layer.draws.Add(CanvasShader.stroke0(layer, p, alpha, mesh));
layer.draws.Add(CanvasShader.stroke1(layer, mesh.duplicate()));
}
void _drawTextDrawMeshCallback(Paint p, uiMeshMesh mesh, bool convex, float alpha, Texture tex, uiRect textBlobBounds, TextBlobMesh textMesh) {
if (!this._applyClip(textBlobBounds)) {
textMesh.dispose();
return;
}
var layer = this._currentLayer;
layer.draws.Add(CanvasShader.texAlpha(layer, p, textMesh, tex));
}
void _drawPathDrawMeshQuit(uiMeshMesh mesh) {
mesh.dispose();
}
void _drawPath(uiPath path, Paint paint) {
D.assert(path != null);
D.assert(paint != null);
if (paint.style == PaintingStyle.fill) {
var state = this._currentLayer.currentState;
var cache = path.flatten(state.scale * this._devicePixelRatio);
path.dispose();
bool convex;
var fillMesh = cache.getFillMesh(out convex);
var mesh = fillMesh.transform(state.matrix);
fillMesh.dispose();
cache.dispose();
if (paint.maskFilter != null && paint.maskFilter.sigma != 0) {
this._drawWithMaskFilter(mesh.bounds, paint, paint.maskFilter, mesh, convex, 0, null, uiRectHelper.zero, null, this._drawPathDrawMeshCallback);
return;
}
this._drawPathDrawMeshCallback(paint, mesh, convex, 0, null, uiRectHelper.zero, null);
}
else {
var state = this._currentLayer.currentState;
float strokeWidth = (paint.strokeWidth * state.scale).clamp(0, 200.0f);
float alpha = 1.0f;
if (strokeWidth == 0) {
strokeWidth = this._fringeWidth;
}
else if (strokeWidth < this._fringeWidth) {
// If the stroke width is less than pixel size, use alpha to emulate coverage.
// Since coverage is area, scale by alpha*alpha.
alpha = (strokeWidth / this._fringeWidth).clamp(0.0f, 1.0f);
alpha *= alpha;
strokeWidth = this._fringeWidth;
}
var cache = path.flatten(state.scale * this._devicePixelRatio);
path.dispose();
var strokenMesh = cache.getStrokeMesh(
strokeWidth / state.scale * 0.5f,
paint.strokeCap,
paint.strokeJoin,
paint.strokeMiterLimit);
var mesh = strokenMesh.transform(state.matrix);
strokenMesh.dispose();
cache.dispose();
if (paint.maskFilter != null && paint.maskFilter.sigma != 0) {
this._drawWithMaskFilter(mesh.bounds, paint, paint.maskFilter, mesh, false, alpha, null, uiRectHelper.zero, null, this._drawPathDrawMeshCallback2);
return;
}
this._drawPathDrawMeshCallback2(paint, mesh, false, alpha, null, uiRectHelper.zero, null);
}
}
void _drawImage(Image image, uiOffset offset, Paint paint) {
D.assert(image != null);
D.assert(paint != null);
this._drawImageRect(image,
null,
uiRectHelper.fromLTWH(
offset.dx, offset.dy,
image.width / this._devicePixelRatio,
image.height / this._devicePixelRatio),
paint);
}
void _drawImageRect(Image image, uiRect? src, uiRect dst, Paint paint) {
D.assert(image != null);
D.assert(paint != null);
if (src == null) {
src = uiRectHelper.one;
}
else {
src = uiRectHelper.scale(src.Value, 1f / image.width, 1f / image.height);
}
var layer = this._currentLayer;
var state = layer.currentState;
var mesh = ImageMeshGenerator.imageMesh(state.matrix, src.Value, dst);
if (!this._applyClip(mesh.bounds)) {
mesh.dispose();
return;
}
layer.draws.Add(CanvasShader.tex(layer, paint, mesh, image));
}
void _drawImageNine(Image image, uiRect? src, uiRect center, uiRect dst, Paint paint) {
D.assert(image != null);
D.assert(paint != null);
var scaleX = 1f / image.width;
var scaleY = 1f / image.height;
if (src == null) {
src = uiRectHelper.one;
}
else {
src = uiRectHelper.scale(src.Value, scaleX, scaleY);
}
center = uiRectHelper.scale(center, scaleX, scaleY);
var layer = this._currentLayer;
var state = layer.currentState;
var mesh = ImageMeshGenerator.imageNineMesh(state.matrix, src.Value, center, image.width, image.height, dst);
if (!this._applyClip(mesh.bounds)) {
mesh.dispose();
return;
}
layer.draws.Add(CanvasShader.tex(layer, paint, mesh, image));
}
void _drawPicture(Picture picture, bool needsSave = true) {
if (needsSave) {
this._save();
}
int saveCount = 0;
var drawCmds = picture.drawCmds;
foreach (var drawCmd in drawCmds) {
switch (drawCmd) {
case DrawSave _:
saveCount++;
this._save();
break;
case DrawSaveLayer cmd: {
saveCount++;
this._saveLayer(uiRectHelper.fromRect(cmd.rect), cmd.paint);
break;
}
case DrawRestore _: {
saveCount--;
if (saveCount < 0) {
throw new Exception("unmatched save/restore in picture");
}
this._restore();
break;
}
case DrawTranslate cmd: {
this._translate(cmd.dx, cmd.dy);
break;
}
case DrawScale cmd: {
this._scale(cmd.sx, cmd.sy);
break;
}
case DrawRotate cmd: {
this._rotate(cmd.radians, uiOffset.fromOffset(cmd.offset));
break;
}
case DrawSkew cmd: {
this._skew(cmd.sx, cmd.sy);
break;
}
case DrawConcat cmd: {
this._concat(uiMatrix3.fromMatrix3(cmd.matrix));
break;
}
case DrawResetMatrix _:
this._resetMatrix();
break;
case DrawSetMatrix cmd: {
this._setMatrix(uiMatrix3.fromMatrix3(cmd.matrix));
break;
}
case DrawClipRect cmd: {
this._clipRect(cmd.rect);
break;
}
case DrawClipRRect cmd: {
this._clipRRect(cmd.rrect);
break;
}
case DrawClipPath cmd: {
var uipath = uiPath.fromPath(cmd.path);
this._clipPath(uipath);
break;
}
case DrawPath cmd: {
var uipath = uiPath.fromPath(cmd.path);
this._drawPath(uipath, cmd.paint);
break;
}
case DrawImage cmd: {
this._drawImage(cmd.image, (uiOffset.fromOffset(cmd.offset)).Value, cmd.paint);
break;
}
case DrawImageRect cmd: {
this._drawImageRect(cmd.image, uiRectHelper.fromRect(cmd.src), uiRectHelper.fromRect(cmd.dst), cmd.paint);
break;
}
case DrawImageNine cmd: {
this._drawImageNine(cmd.image, uiRectHelper.fromRect(cmd.src), uiRectHelper.fromRect(cmd.center), uiRectHelper.fromRect(cmd.dst), cmd.paint);
break;
}
case DrawPicture cmd: {
this._drawPicture(cmd.picture);
break;
}
case DrawTextBlob cmd: {
this._drawTextBlob(cmd.textBlob, (uiOffset.fromOffset(cmd.offset)).Value, cmd.paint);
break;
}
default:
throw new Exception("unknown drawCmd: " + drawCmd);
}
}
if (saveCount != 0) {
throw new Exception("unmatched save/restore in picture");
}
if (needsSave) {
this._restore();
}
}
void _drawTextBlob(TextBlob textBlob, uiOffset offset, Paint paint) {
D.assert(textBlob != null);
D.assert(paint != null);
var state = this._currentLayer.currentState;
var scale = state.scale * this._devicePixelRatio;
var matrix = new uiMatrix3(state.matrix.Value);
matrix.preTranslate(offset.dx, offset.dy);
var mesh = TextBlobMesh.create(textBlob, scale, matrix);
var textBlobBounds = matrix.mapRect(uiRectHelper.fromRect(textBlob.boundsInText));
// request font texture so text mesh could be generated correctly
var style = textBlob.style;
var font = FontManager.instance.getOrCreate(style.fontFamily, style.fontWeight, style.fontStyle).font;
var fontSizeToLoad = Mathf.CeilToInt(style.UnityFontSize * scale);
var subText = textBlob.text.Substring(textBlob.textOffset, textBlob.textSize);
font.RequestCharactersInTextureSafe(subText, fontSizeToLoad, style.UnityFontStyle);
var tex = font.material.mainTexture;
if (paint.maskFilter != null && paint.maskFilter.sigma != 0) {
this._drawWithMaskFilter(textBlobBounds, paint, paint.maskFilter, null, false, 0, tex, textBlobBounds, mesh, this._drawTextDrawMeshCallback);
return;
}
this._drawTextDrawMeshCallback(paint, null, false, 0, tex, textBlobBounds, mesh);
}
public void flush(Picture picture) {
this._reset();
this._drawPicture(picture, false);
D.assert(this._layers.Count == 1);
D.assert(this._layers[0].states.Count == 1);
var layer = this._currentLayer;
using (var cmdBuf = new CommandBuffer()) {
cmdBuf.name = "CommandBufferCanvas";
this._lastRtID = -1;
this._drawLayer(layer, cmdBuf);
// this is necessary for webgl2. not sure why... just to be safe to disable the scissor.
cmdBuf.DisableScissorRect();
Graphics.ExecuteCommandBuffer(cmdBuf);
}
}
int _lastRtID;
void _setRenderTarget(CommandBuffer cmdBuf, int rtID, ref bool toClear) {
if (this._lastRtID == rtID) {
return;
}
this._lastRtID = rtID;
if (rtID == 0) {
cmdBuf.SetRenderTarget(this._renderTexture);
}
else {
cmdBuf.SetRenderTarget(rtID);
}
if (toClear) {
cmdBuf.ClearRenderTarget(true, true, UnityEngine.Color.clear);
toClear = false;
}
}
readonly float[] _drawLayer_matArray = new float[9];
void _drawLayer(RenderLayer layer, CommandBuffer cmdBuf) {
bool toClear = true;
foreach (var cmdObj in layer.draws) {
switch (cmdObj) {
case CmdLayer cmd:
var subLayer = cmd.layer;
var desc = new RenderTextureDescriptor(
subLayer.width, subLayer.height,
RenderTextureFormat.Default, 24) {
useMipMap = false,
autoGenerateMips = false,
};
if (this._renderTexture.antiAliasing != 0 && !subLayer.noMSAA) {
desc.msaaSamples = this._renderTexture.antiAliasing;
}
cmdBuf.GetTemporaryRT(subLayer.rtID, desc, subLayer.filterMode);
this._drawLayer(subLayer, cmdBuf);
break;
case CmdDraw cmd:
this._setRenderTarget(cmdBuf, layer.rtID, ref toClear);
if (cmd.layerId != null) {
if (cmd.layerId == 0) {
cmdBuf.SetGlobalTexture(CmdDraw.texId, this._renderTexture);
}
else {
cmdBuf.SetGlobalTexture(CmdDraw.texId, cmd.layerId.Value);
}
}
D.assert(cmd.meshObj == null);
cmd.meshObj = this._meshPool.getMesh();
cmd.meshObjCreated = true;
// clear triangles first in order to bypass validation in SetVertices.
cmd.meshObj.SetTriangles((int[]) null, 0, false);
uiMeshMesh mesh = cmd.mesh;
if (cmd.textMesh != null) {
mesh = cmd.textMesh.resovleMesh();
}
if (mesh == null) {
continue;
}
D.assert(mesh.vertices.Count > 0);
cmd.meshObj.SetVertices(mesh.vertices?.data);
cmd.meshObj.SetTriangles(mesh.triangles?.data, 0, false);
cmd.meshObj.SetUVs(0, mesh.uv?.data);
if (mesh.matrix == null) {
cmd.properties.SetFloatArray(CmdDraw.matId, CmdDraw.idMat3.fMat);
}
else {
var mat = mesh.matrix.Value;
this._drawLayer_matArray[0] = mat.kMScaleX;
this._drawLayer_matArray[1] = mat.kMSkewX;
this._drawLayer_matArray[2] = mat.kMTransX;
this._drawLayer_matArray[3] = mat.kMSkewY;
this._drawLayer_matArray[4] = mat.kMScaleY;
this._drawLayer_matArray[5] = mat.kMTransY;
this._drawLayer_matArray[6] = mat.kMPersp0;
this._drawLayer_matArray[7] = mat.kMPersp1;
this._drawLayer_matArray[8] = mat.kMPersp2;
cmd.properties.SetFloatArray(CmdDraw.matId, this._drawLayer_matArray);
}
cmdBuf.DrawMesh(cmd.meshObj, CmdDraw.idMat, cmd.material, 0, cmd.pass, cmd.properties.mpb);
if (cmd.layerId != null) {
cmdBuf.SetGlobalTexture(CmdDraw.texId, BuiltinRenderTextureType.None);
}
break;
case CmdScissor cmd:
this._setRenderTarget(cmdBuf, layer.rtID, ref toClear);
if (cmd.deviceScissor == null) {
cmdBuf.DisableScissorRect();
}
else {
cmdBuf.EnableScissorRect(uiRectHelper.toRect(cmd.deviceScissor.Value));
}
break;
}
}
if (toClear) {
this._setRenderTarget(cmdBuf, layer.rtID, ref toClear);
}
D.assert(!toClear);
foreach (var subLayer in layer.layers) {
cmdBuf.ReleaseTemporaryRT(subLayer.rtID);
}
}
void _clearLayer(RenderLayer layer) {
foreach (var cmdObj in layer.draws) {
switch (cmdObj) {
case CmdDraw cmd:
if (cmd.meshObjCreated) {
this._meshPool.returnMesh(cmd.meshObj);
cmd.meshObj = null;
cmd.meshObjCreated = false;
}
break;
}
cmdObj.dispose();
}
layer.draws.Clear();
foreach (var subLayer in layer.layers) {
this._clearLayer(subLayer);
subLayer.dispose();
}
layer.layers.Clear();
}
}
}

11
Runtime/ui/utils/renderer/canvas_impl.cs.meta


fileFormatVersion: 2
guid: d0406d906bb294e7790f68e3adc0655e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Runtime/ui/utils/renderer/canvas_shader.cs.meta


fileFormatVersion: 2
guid: 11e43dc1dd92e4c7a97e25b3f12a1017
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Runtime/ui/utils/renderer/canvas_shader_utils.cs.meta


fileFormatVersion: 2
guid: 9ddd3cd95755643c98042e67ba4714a3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Runtime/ui/utils/renderer/canvas_utils.cs.meta


fileFormatVersion: 2
guid: 9bc23aedd93fe480f989a21cd0128393
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Runtime/ui/utils/renderer/command_buffer_canvas.cs.meta


fileFormatVersion: 2
guid: cddbf990158e841019601291fd04d5f8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Runtime/ui/utils/renderer/generic_list.cs.meta


fileFormatVersion: 2
guid: 967dfd4c9146e4933bc96a163a73dd9c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Runtime/ui/utils/renderer/mesh_mesh.cs.meta


fileFormatVersion: 2
guid: 2e5b97cbd47ac784790290e5fa696f60
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Runtime/ui/utils/renderer/path.cs.meta


fileFormatVersion: 2
guid: 3a42c24d7ebd6429cb3147b48bf8736e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Runtime/ui/utils/renderer/path_cache.cs.meta


fileFormatVersion: 2
guid: c97372c9ed12471459d1a3ed41a3b2fe
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Runtime/ui/utils/renderer/path_utils.cs.meta


fileFormatVersion: 2
guid: 2557784b74abe7142984ee42c406a414
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Runtime/ui/utils/renderer/pool_items.cs.meta


fileFormatVersion: 2
guid: dc26305d777344a62b1f9382ec6f0ce3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Runtime/ui/utils/renderer/render_cmd.cs.meta


fileFormatVersion: 2
guid: c0cbe18d7f0874d5a9883c5a3d88f917
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Runtime/ui/utils/renderer/render_layer.cs.meta


fileFormatVersion: 2
guid: 621b1d524a6164601aa043c0411e0a19
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Runtime/ui/utils/renderer/tessellation_generator.cs.meta


fileFormatVersion: 2
guid: 4116b1938a907416199eb342667c45fe
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

/Runtime/ui/utils/renderer/canvas_clip.cs → /Runtime/ui/utils/renderer/cmdbufferCanvas/rendering/canvas_clip.cs

/Runtime/ui/utils/renderer/canvas_shader.cs → /Runtime/ui/utils/renderer/cmdbufferCanvas/rendering/canvas_shader.cs

/Runtime/ui/utils/renderer/canvas_shader_utils.cs → /Runtime/ui/utils/renderer/cmdbufferCanvas/rendering/canvas_shader_utils.cs

/Runtime/ui/utils/renderer/canvas_utils.cs → /Runtime/ui/utils/renderer/cmdbufferCanvas/rendering/canvas_utils.cs

/Runtime/ui/utils/renderer/command_buffer_canvas.cs → /Runtime/ui/utils/renderer/cmdbufferCanvas/command_buffer_canvas.cs

/Runtime/ui/utils/renderer/generic_list.cs → /Runtime/ui/utils/renderer/allocUtils/generic_list.cs

/Runtime/ui/utils/renderer/mesh_mesh.cs → /Runtime/ui/utils/renderer/geometry/mesh_mesh.cs

/Runtime/ui/utils/renderer/path.cs → /Runtime/ui/utils/renderer/geometry/path/path.cs

/Runtime/ui/utils/renderer/path_cache.cs → /Runtime/ui/utils/renderer/geometry/path/path_cache.cs

/Runtime/ui/utils/renderer/path_utils.cs → /Runtime/ui/utils/renderer/geometry/path/path_utils.cs

/Runtime/ui/utils/renderer/pool_items.cs → /Runtime/ui/utils/renderer/allocUtils/pool_items.cs

/Runtime/ui/utils/renderer/render_cmd.cs → /Runtime/ui/utils/renderer/cmdbufferCanvas/rendering/render_cmd.cs

/Runtime/ui/utils/renderer/render_layer.cs → /Runtime/ui/utils/renderer/cmdbufferCanvas/rendering/render_layer.cs

/Runtime/ui/utils/renderer/tessellation_generator.cs → /Runtime/ui/utils/renderer/geometry/path/tessellation_generator.cs

正在加载...
取消
保存