LegacyGlTexture class
Texture object of the legacy GL backend (aliased as RHI::Texture).
Keeps a LINEAR host store of level 0 in the uploaded pixel format (the same native R8/RG8/RGBA8 layout the software and PVR backends use) plus the GL texture objects the rasterizer samples. The host store is what every upload writes and what a readback answers from; the texture objects are built from it lazily, because the two differ in ways an upload should not have to care about:
- Power-of-two dimensions, where the GL insists on them. Sampling a non-power-of-two texture is a GL 2.0 feature (
GL_ARB_texture_non_power_of_twobefore that), so where it is missing each texture object is padded up and the draw path scales texel coordinates by the padded size. The padding replicates the edge texel (BuildPage()) so a bilinear tap at the last real texel does not fetch black. Where it is present (LegacyGlDevice::SupportsNonPowerOfTwo()) a page is stored at its own size and nothing is padded. - A bounded size. An image larger than what the GL can hold -
GL_MAX_TEXTURE_SIZE, capped at MaxPageDimension - is split into pages, and the draw path selects the page a primitive's texture rectangle falls into and rebases its texture coordinates onto it (see AcquirePage()). Every sprite/tile draw samples one small sub-rect of an atlas, so a primitive practically never straddles a page boundary. - Colour rather than indices. Legacy GL has no palette hardware to resolve an index with -
GL_EXT_paletted_textureis long gone from every driver and TinyGL never had it - so an indexed texture is baked through its palette row into RGBA8 first (EnsureBakedStore()), which is the same machinery the consoles use for their index+alpha content, applied to both indexed formats here. Everything else is uploaded as RGBA8 as well: one store format keeps the upload path single, and a 16-bit one would only be expanded again by the driver.
A render target is the exception to all of it: its texture object is created at the real size and GL renders into it (through a framebuffer object, or into the back buffer and back out - see LegacyGlRenderTarget), so it has no host store and nothing is ever converted or uploaded.
Mip levels above 0 and compressed formats are accepted but not stored, exactly like on the other fixed-function backends: the game never uses either.
Public types
- struct Page
- One GL-addressable piece of the texture.
Public static variables
-
static std::
uint32_t MaxTextureUnits constexpr - Number of texture units tracked by the device.
-
static std::
int32_t MaxPageDimension constexpr - The largest page this backend ever builds, per axis.
Public static functions
-
static auto Unbind(std::
uint32_t textureUnit) -> bool - Unbinds any texture from the specified texture unit.
-
static void SetUnpackAlignment(std::
int32_t alignment) - Sets the client pixel-row alignment of uploads (ignored, uploads are tightly packed).
- static auto SupportsImmutableStorage() -> bool
- static auto SupportsTextureReadback() -> bool
- static void ClearErrors()
- static auto CheckErrors() -> bool
- static void CheckFormatSupport(PixelFormat format)
-
static auto BytesPerPixel(PixelFormat format) -> std::
int32_t - Returns the number of bytes occupied by one texel of the given format (0 if unsupported).
Constructors, destructors, conversion operators
- LegacyGlTexture(TextureTarget target) explicit
- ~LegacyGlTexture()
- LegacyGlTexture(const LegacyGlTexture&) deleted
Public functions
- auto operator=(const LegacyGlTexture&) -> LegacyGlTexture& deleted
-
auto GetUniqueId() const -> std::
uint32_t - Returns a backend-neutral identifier uniquely identifying the texture (feeds material sort keys).
- auto GetTarget() const -> TextureTarget
- Returns the texture target.
-
auto GetWidth() const -> std::
int32_t - Returns the width of level 0 in texels.
-
auto GetHeight() const -> std::
int32_t - Returns the height of level 0 in texels.
- auto GetFormat() const -> PixelFormat
- Returns the pixel format of the linear host store (native, like the software backend).
- auto GetUploadFormat() const -> PixelFormat
- Returns the original upload format (R8/RG8 kept so the palette path can tell them apart).
-
auto GetStrideBytes() const -> std::
int32_t - Returns the byte distance between two consecutive rows of the linear host store.
-
auto GetPixels(std::
int32_t level = 0) const -> const std:: uint8_t* - Returns the base pointer of the linear host store (may be
nullptrbefore an upload). -
auto MutablePixels() -> std::
uint8_t* - Returns a writable base pointer of the linear host store (
nullptrbefore an upload). - auto GetWrapS() const -> SamplerWrapping
- Returns the horizontal texture-coordinate wrap mode.
- auto GetWrapT() const -> SamplerWrapping
- Returns the vertical texture-coordinate wrap mode (single stored mode).
- auto GetSwizzle() const -> const SwizzleChannel*
- Returns the four-channel sampling swizzle (identity by default; informational here).
-
auto GetMagFiltering() const -> nCine::
SamplerFilter - Returns the magnification filter.
-
auto GetMagFilter() const -> nCine::
SamplerFilter - Alias of GetMagFiltering().
- auto IsRenderTarget() const -> bool
- Returns
trueif the texture is bound as a color render target. - void SetRenderTarget(bool isRenderTarget)
- Marks the texture as (or no longer as) a color render target; becoming one allocates its surface.
-
auto GetContentVersion() const -> std::
uint32_t - Returns a globally monotonic stamp of the texel store, advanced by every allocation or upload.
- auto IsIndexed() const -> bool
- Returns
truewhen the store holds palette indices rather than colours. - auto NeedsPaletteBake() const -> bool
- Returns
truewhen the texture needs the per-palette-row CPU bake. - auto IsPaletteTexture() const -> bool
- Returns
truewhen this is the intercepted shared palette texture (its rows drive the bakes). -
auto AcquirePage(std::
int32_t texelX, std:: int32_t texelY) -> const Page* - Uploads what is missing and returns the page holding the given source texel.
-
auto GetPageCountX() const -> std::
int32_t - Number of pages the image is split into along each axis (1 x 1 for practically all content).
-
auto GetPageCountY() const -> std::
int32_t - Number of pages the image is split into along each axis.
-
auto EnsureBakedStore(const std::
uint32_t* paletteRow, std:: uint32_t paletteRowIndex, std:: uint32_t paletteGeneration, const void* palette) -> bool - Makes the texture objects hold this indexed texture baked through one palette row.
-
auto MapStreamingTexels(std::
int32_t& strideBytes) -> void* - Declined here: always returns
nullptr(the contract's streaming-texture fast path). -
auto GetRenderTargetTexture() const -> std::
uint32_t - Returns the texture object a render target draws into, or zero.
-
auto Bind(std::
uint32_t textureUnit) const -> bool - Binds the texture to the specified texture unit on the device.
- auto Bind() const -> bool
- Binds the texture to texture unit 0.
- auto Unbind() const -> bool
- Unbinds the texture from the unit it was last bound to.
-
void TexImage2D(std::
int32_t level, PixelFormat format, bool bgr, std:: int32_t width, std:: int32_t height, const void* data) - Allocates level-0 storage of the given format/size and optionally uploads its texels.
-
void TexSubImage2D(std::
int32_t level, std:: int32_t xoffset, std:: int32_t yoffset, std:: int32_t width, std:: int32_t height, PixelFormat format, bool bgr, const void* data) - Updates a rectangular subregion of level 0.
-
void TexStorage2D(std::
int32_t levels, PixelFormat format, std:: int32_t width, std:: int32_t height) - Allocates immutable level-0 storage of the given format/size (no texels yet).
-
void CompressedTexImage2D(std::
int32_t level, PixelFormat format, std:: int32_t width, std:: int32_t height, std:: int32_t imageSize, const void* data) - Compressed upload (unsupported, accepted as a no-op).
-
void CompressedTexSubImage2D(std::
int32_t level, std:: int32_t xoffset, std:: int32_t yoffset, std:: int32_t width, std:: int32_t height, PixelFormat format, std:: int32_t imageSize, const void* data) - Compressed sub-upload (unsupported, accepted as a no-op).
-
void GetTexImage(std::
int32_t level, PixelFormat format, bool bgr, void* pixels) - Reads back level-0 texels of the linear host store into client memory.
-
void SetMinFiltering(nCine::
SamplerFilter filter) - Sets the minification filter.
-
void SetMagFiltering(nCine::
SamplerFilter filter) - Sets the magnification filter.
- void SetWrap(SamplerWrapping wrap)
- Sets the wrap mode.
- void SetSwizzle(SwizzleChannel r, SwizzleChannel g, SwizzleChannel b, SwizzleChannel a)
- Sets the sampling swizzle (stored, informational - the palette path keys off the upload format instead).
-
void SetMaxLevel(std::
int32_t maxLevel) - Sets the highest defined mipmap level (ignored).
- void SetObjectLabel(StringView label)
- Sets a debug label; "Palettes" marks the shared palette texture the bakes resolve through.
Function documentation
bool nCine:: RHI:: LegacyGL:: LegacyGlTexture:: NeedsPaletteBake() const
Returns true when the texture needs the per-palette-row CPU bake.
Every indexed texture does on this backend, unlike the consoles: legacy GL has no palette hardware to resolve indices with (GL_EXT_paletted_texture is long gone and TinyGL never had it), so an indexed store is baked through its palette row into RGBA8 before it is uploaded. That is the same machinery the consoles use for their RG8 index+alpha content, applied to both indexed formats here.
const Page* nCine:: RHI:: LegacyGL:: LegacyGlTexture:: AcquirePage(std:: int32_t texelX,
std:: int32_t texelY)
Uploads what is missing and returns the page holding the given source texel.
texelX / texelY are clamped into the image, so the min corner of any texture rectangle is a valid argument. Returns nullptr when there is nothing to sample (no upload yet, an unsupported format, or an indexed texture whose bake has not been requested - see EnsureBakedStore()).
bool nCine:: RHI:: LegacyGL:: LegacyGlTexture:: EnsureBakedStore(const std:: uint32_t* paletteRow,
std:: uint32_t paletteRowIndex,
std:: uint32_t paletteGeneration,
const void* palette)
Makes the texture objects hold this indexed texture baked through one palette row.
Index resolved through paletteRow (256 RGBA8 entries); an RG8 texel's alpha comes from its own second byte, an R8 texel's from the palette entry. A small number of bakes is cached, so the common "one extra palette row" case (a sprite and its recolored twin) does not rebuild anything - each bake keeps its own texture objects, so switching between two resident ones uploads nothing and AcquirePage() simply hands out the matching set. Returns false when the bake could not be produced.
void* nCine:: RHI:: LegacyGL:: LegacyGlTexture:: MapStreamingTexels(std:: int32_t& strideBytes)
Declined here: always returns nullptr (the contract's streaming-texture fast path).
The consoles answer this with a pointer into the very memory their rasterizer samples, so content that is regenerated every frame (the cinematics) can be produced straight into it. A GL texture is a driver-owned object instead, so there is nothing to hand out and such content is uploaded like any other - which is also why the backend leaves RHI_CAP_STREAMING_TEXTURES undefined.
Variable documentation
static std:: int32_t nCine:: RHI:: LegacyGL:: LegacyGlTexture:: MaxPageDimension constexpr
The largest page this backend ever builds, per axis.
A page is actually split at what the device reports (LegacyGlDevice::GetMaxTextureDimension(), which is GL_MAX_TEXTURE_SIZE capped at LegacyGlDevice::MaxTextureDimension) - as low as 256 on a Voodoo-class card. This constant only states the ceiling the padding arithmetic is written against.