# `tecs.gfx.images`
Image identity, residency, and the commands that carry pixels to the backend.
A game names an image, hands over its pixels, and receives a small integer that
a [`Sprite`](tecs.gfx.Sprite) stores. The backend owns the texture, the view,
the sampler, and the bind group; nothing native reaches game code.
```nupp
const id = tecs.gfx.images.upload({
name = "tiles/grass",
width = 2,
height = 2,
pixels = grassRgba8,
filter = "nearest",
})
world:spawn(
tecs.ecs.Transform2D(64, 64, 0, 1, 0, 32, 32),
tecs.gfx.Tint(1, 1, 1, 1),
tecs.gfx.Sprite(id),
tecs.gfx.Renderable2D
)
```
An id is permanent and process-wide, in the same way component identity is, so
a snapshot stores the name and resolves the id again on load. Uploading a name
twice replaces the image behind that same id, and every sprite already pointing
at it draws the new pixels on the next frame.
Residency is observed rather than waited on. `upload` queues a command and
answers immediately with `"pending"`; the host drains the command, reports the
outcome, and `stateOf` then answers `"resident"` or `"failed"`. Extraction
draws a sprite whose image is not resident against the backend's opaque white
fallback, so a missing asset is a visibly untextured quad rather than a
dropped entity or a raised error.
Pixels are eight-bit RGBA with unassociated alpha, four bytes per texel, in
rows running top to bottom. That is the only accepted layout, and the command
names it so a later format costs a value rather than a command shape.
## Types
### `Address` _type_
```nupp
type Address = "clamp" | "repeat" | "mirror"
```
Selects what sampling outside the zero-to-one range returns.
These identifiers reach configuration a developer writes and are a
compatibility surface.
### `Command` _type_
```nupp
type Command = UploadImageCommand | ReleaseImageCommand | MaterialMapsCommand
```
### `Filter` _type_
```nupp
type Filter = "nearest" | "linear"
```
Selects minification and magnification filtering.
These identifiers reach configuration a developer writes and are a
compatibility surface.
### `Format` _type_
```nupp
type Format = "rgba8"
```
The pixel layout an upload carries.
This value crosses to the backend inside a command and is a compatibility
surface.
### `MaterialMaps` _type_
```nupp
type MaterialMaps = {
normalMap: integer?,
emissionMap: integer?,
ormMap: integer?
}
```
Optional companion images; omitted channels use neutral material values.
### `MaterialMapsCommand` _record_
```nupp
record MaterialMapsCommand
kind: string
serial: integer
image: integer
normalMap: integer
emissionMap: integer
ormMap: integer
end
```
One queued residency request.
#### Fields
##### `kind`
```nupp
kind: string
```
##### `serial`
```nupp
serial: integer
```
##### `image`
```nupp
image: integer
```
##### `normalMap`
```nupp
normalMap: integer
```
##### `emissionMap`
```nupp
emissionMap: integer
```
##### `ormMap`
```nupp
ormMap: integer
```
### `ReleaseImageCommand` _record_
```nupp
record ReleaseImageCommand
kind: string
serial: integer
image: integer
end
```
Asks the backend to drop one image and everything bound to it.
#### Fields
##### `kind`
```nupp
kind: string
```
Read-only. Names the command kind, which is a compatibility surface.
##### `serial`
```nupp
serial: integer
```
Read-only. Identifies the command for its completion report.
##### `image`
```nupp
image: integer
```
Read-only. Selects the process-wide image id to drop.
### `State` _type_
```nupp
type State = "unknown" | "pending" | "resident" | "failed" | "released"
```
Reports where one named image stands with the backend.
### `UploadImageCommand` _record_
```nupp
record UploadImageCommand
kind: string
serial: integer
image: integer
width: integer
height: integer
format: Format
sampler: integer
pixels: string
end
```
Asks the backend to make one image resident under an id.
#### Fields
##### `kind`
```nupp
kind: string
```
Read-only. Names the command kind, which is a compatibility surface.
##### `serial`
```nupp
serial: integer
```
Read-only. Identifies the command for its completion report.
##### `image`
```nupp
image: integer
```
Read-only. Selects the process-wide image id the texture lands under.
##### `width`
```nupp
width: integer
```
Read-only. Reports the width in texels.
##### `height`
```nupp
height: integer
```
Read-only. Reports the height in texels.
##### `format`
```nupp
format: Format
```
Read-only. Names the pixel layout.
##### `sampler`
```nupp
sampler: integer
```
Read-only. Selects one of the backend's `SAMPLER_COUNT` samplers.
##### `pixels`
```nupp
pixels: string
```
Read-only. Carries the texel bytes, which the host copies and forgets.
### `UploadOptions` _type_
```nupp
type UploadOptions = {
name: string,
width: integer,
height: integer,
pixels: string,
filter: Filter?,
address: Address?
}
```
The options `upload` accepts.
## Functions
### `complete` _function_
```nupp
function complete(image: integer, serial: integer, ok: boolean, reason: string?): nil
```
Records the backend's outcome for one drained command.
A completion that no longer matches the image's newest serial is discarded,
so a replacement queued before the previous upload completed keeps its own
state.
#### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `image` | `integer` | the process-wide image id the command named |
| `serial` | `integer` | the command serial the host applied |
| `ok` | `boolean` | whether the backend accepted the command |
| `reason` | `string?` | the non-empty host failure, required when `ok` is false |
#### Returns
| Type | Description |
| --- | --- |
| `nil` | |
#### Raises
- when a rejection carries no reason
### `drain` _function_
```nupp
function drain(): {Command}
```
Removes the queued residency commands for the host to apply.
#### Returns
| Type | Description |
| --- | --- |
| `{Command}` | the ordered command batch, which the caller owns |
### `failureOf` _function_
```nupp
function failureOf(image: integer): string?
```
Returns why the backend rejected one image.
#### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `image` | `integer` | the process-wide image id |
#### Returns
| Type | Description |
| --- | --- |
| `string?` | the host failure reason, or nil unless the state is `"failed"` |
### `id` _function_
```nupp
function id(name: string): integer
```
Returns the permanent id one image name resolves to.
Interning a name does not make it resident. A sprite may be built against
an id whose pixels arrive later, or never.
#### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `name` | `string` | the stable image name, which a snapshot stores |
#### Returns
| Type | Description |
| --- | --- |
| `integer` | the process-wide image id, which is always greater than zero |
#### Raises
- when the name is empty
### `load` _function_
```nupp
function load(path: string, name: string?): integer
```
Decodes a PNG or JPEG file and queues its RGBA pixels for upload.
#### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `path` | `string` | the image file path |
| `name` | `string?` | the stable image name; omitted uses the file path |
#### Returns
| Type | Description |
| --- | --- |
| `integer` | the image id, whose dimensions are immediately available |
#### Raises
- when the file cannot be decoded
### `nameOf` _function_
```nupp
function nameOf(image: integer): string?
```
Returns the name one image id was interned under.
#### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `image` | `integer` | the process-wide image id |
#### Returns
| Type | Description |
| --- | --- |
| `string?` | the name, or nil when no image carries that id |
### `release` _function_
```nupp
function release(name: string): boolean, string?
```
Queues one image for release.
The id survives the release, so a later `upload` under the same name makes
the same id resident again. Sprites pointing at a released image draw the
backend's fallback until then.
#### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `name` | `string` | the stable image name |
#### Returns
| Type | Description |
| --- | --- |
| `boolean` | whether a release was queued, which is false for a name nothing uploaded |
| `string?` | why nothing was queued, when unsuccessful |
### `residencyRevision` _function_
```nupp
function residencyRevision(): integer
```
Returns the revision of image residency and sampling metadata.
#### Returns
| Type | Description |
| --- | --- |
| `integer` | A monotonic count that changes when residency or sampling changes. |
### `samplerIndex` _function_
```nupp
function samplerIndex(filter: Filter?, address: Address?): integer
```
Returns the sampler index one filter and address mode select.
#### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `filter` | `Filter?` | the filtering mode, defaulting to `"nearest"` |
| `address` | `Address?` | the addressing mode, defaulting to `"clamp"` |
#### Returns
| Type | Description |
| --- | --- |
| `integer` | the sampler index, from zero to `SAMPLER_COUNT` minus one |
#### Raises
- when either mode is not one of its declared values
### `samplerOf` _function_
```nupp
function samplerOf(image: integer): integer
```
Returns the sampler index extraction writes for one image.
#### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `image` | `integer` | the process-wide image id |
#### Returns
| Type | Description |
| --- | --- |
| `integer` | the sampler index, which is nearest filtering with clamped edges for an unknown id |
### `setMaterialMaps` _function_
```nupp
function setMaterialMaps(image: integer, maps: MaterialMaps): nil
```
Associates normal, emission and packed occlusion/roughness/metallic images.
All supplied maps must have the albedo image dimensions. Applies to sprites
and TileChunks using that image; replacement pixels keep the association.
#### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `image` | `integer` | |
| `maps` | `MaterialMaps` | |
#### Returns
| Type | Description |
| --- | --- |
| `nil` | |
### `sizeOf` _function_
```nupp
function sizeOf(image: integer): integer, integer
```
Returns the texel dimensions the last accepted upload declared.
#### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `image` | `integer` | the process-wide image id |
#### Returns
| Type | Description |
| --- | --- |
| `integer` | the width and then the height in texels, both zero before an upload |
| `integer` | |
### `stateOf` _function_
```nupp
function stateOf(image: integer): State
```
Returns where one image stands with the backend.
#### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `image` | `integer` | the process-wide image id |
#### Returns
| Type | Description |
| --- | --- |
| `State` | the residency state, which is `"unknown"` for an id nothing uploaded |
### `upload` _function_
```nupp
function upload(options: UploadOptions): integer
```
Queues one image for residency and returns its permanent id.
Uploading a name that is already resident replaces its pixels behind the
same id, so every sprite pointing at it draws the new image once the host
reports the replacement complete.
#### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `options` | `UploadOptions` | the name, texel dimensions, RGBA8 pixels, and sampling modes |
#### Returns
| Type | Description |
| --- | --- |
| `integer` | the process-wide image id |
#### Raises
- when the name is empty, a dimension is not positive, a sampling mode is unknown, or the pixel length is not four bytes per texel
## Values
### `SAMPLER_COUNT` _variable_
```nupp
const SAMPLER_COUNT: integer
```
The number of distinct samplers a backend must create.
Every filter paired with every address mode, so a sampler is selected by
index and never created on demand.