readback method
The pixels of region — the whole texture by default — as they stand
at this point in the queue: premultiplied RGBA8, row-major from the
top-left, the region's own width times four per row.
One layout, named, because the only thing anybody does with these is compare them against pixels that came from somewhere else — and two sides of a comparison that disagree about premultiplication differ on every translucent texel while looking identical on screen.
The one way to read a texture back, since 1.0. readPixels was a
second call for the same bytes that answered null where this throws; a
finished picture (a golden run, a probe, a test) and last frame's answer
while this frame goes on (an exposure meter, the id under the cursor)
are both this. Two promises make the second work:
- The copy is queued where it was asked for. A pass submitted after
this call, drawing into the same texture, does not reach the bytes:
they are the texture as the passes before this call left it. The
conformance check
a readback returns the frame beforeclears red, asks, clears blue, and gets red. - Nothing here stalls the caller for an eight-bit texture. The
hardware backends copy on the GPU and resolve the future when the
queue reports the copy done — flutter_gpu through
submit's completion callback, WebGL2 through a pixel-pack buffer and a fence — so the frame being encoded is not held up by a frame the GPU is still on. The software rasteriser has nothing to wait for and answers at once, which is the truth there.
The future therefore usually completes a frame or two later.
region is stated from the top left, in the texture's own pixels, like
every rectangle in this interface, and must lie inside the texture. One
pixel is a legitimate region and the cheapest one: the editor's pick reads
exactly that.
A whole texture in another format is converted, which is how a float target (the engine's HDR colour) is looked at: each backend draws or converts it into eight-bit RGBA on its own path, which may wait for the GPU. See readbackConverts. A region of one is refused, because a partial conversion is the place three backends would disagree.
Throws an ArgumentError for what cannot be read at all — a
deviceTransient texture, a multisampled one, a cube, a region outside
the texture, a region of a texture outside readbackFormats — because
the handle carries every one of those facts and the caller can ask before
requesting. Throws a DeviceResourceException when the device has the
texture and still cannot hand its pixels over: a format this backend has
no conversion for.
Implementation
@override
Future<ByteData> readback(TextureHandle texture, {ScreenRect? region}) {
events.add(TraceReadback(texture: _texture(texture), region: region));
return inner.readback(texture, region: region);
}