overwriteTexture method

  1. @override
Future<void> overwriteTexture(
  1. TextureHandle target,
  2. ByteData rgba, {
  3. ScreenRect? region,
  4. int mipLevel = 0,
})
override

Overwrites region (the whole texture by default) of target's base level with rgba — raw RGBA8 bytes, region.width * region.height * 4 of them, row-major from the top the same way readback answers them.

readbackFormats again, and only the base level. The same two linear eight-bit layouts readback insists on, for the same reason: a caller round-tripping a region — read it, edit it, write it back — needs the two ends to agree on what the bytes mean, and a third format each backend would decode differently is exactly the mismatch readback already refuses. Refuses (throws UnsupportedError) any other target.format, including every compressed one — a block covers a 4x4 texel footprint, and a region write that lands mid-block would ask a backend to rewrite a compressed block from decoded bytes it does not carry — and refuses mipLevel other than zero, because patching one level of a chain that carries more would leave the rest silently stale, with nothing anywhere saying the picture at another level is no longer the one this level was built from.

Visible starting the next pass, the same promise overwriteGeometry makes and for the same reason: nothing here rewinds a pass already submitted against the old bytes.

Asynchronous because one backend's own write is. Three of the four can patch a region of an existing texture directly; flutter_gpu's own Texture can only overwrite a whole mip level at once, so writing a region there means reading the level back first — readback's own asynchronous half — patching it in memory, and writing the whole level back. On the other three the future completes in the same turn, the same shape loadShaders is asynchronous for.

Implementation

@override
Future<void> overwriteTexture(
  TextureHandle target,
  ByteData rgba, {
  ScreenRect? region,
  int mipLevel = 0,
}) async {
  if (!readbackFormats.contains(target.format)) {
    throw UnsupportedError(
      'overwriteTexture: TextureFormat.${target.format.name} is not one '
      'of readbackFormats — the two this call, like readback, insists on.',
    );
  }
  if (mipLevel != 0) {
    throw UnsupportedError(
      'overwriteTexture: mip level $mipLevel is refused; only the base '
      'level (0) may be overwritten.',
    );
  }
  final rect =
      region ?? ScreenRect(width: target.width, height: target.height);
  if (rect.x < 0 ||
      rect.y < 0 ||
      rect.x + rect.width > target.width ||
      rect.y + rect.height > target.height) {
    throw ArgumentError(
      'overwriteTexture: $rect does not fit inside a '
      '${target.width}x${target.height} texture',
    );
  }
  if (rgba.lengthInBytes != rect.width * rect.height * 4) {
    throw ArgumentError(
      'overwriteTexture: ${rgba.lengthInBytes} bytes does not match '
      '${rect.width}x${rect.height} RGBA8',
    );
  }
  overwrittenTextures.add((
    format: target.format,
    region: rect,
    mipLevel: mipLevel,
  ));
}