PDA

View Full Version : GL: format, internal format, pixel format - my slightly stale research



Chebmaster
24-01-2018, 05:18 PM
When learning OpenGL I always struggled with these values: which combinations are valid? This information is hard to find. So I made my engine try and output and finally found combinations that work (see code at the bottom). Interestingly, GL and GLES have it differently:

The values are: <my engine's enum> / <internal format> / <format> / <type>
-- in the relative order you pass them to glTexImage2d(), which is
glTexImage2D (GL_TEXTURE_2D, 0, <internal format>, 32, 32, 0, <format>, <type>, @buffer);

Desktop GL:
You tell it which internal format it should use and pass it image in what pixel format you have (usually 8 bits).
The driver does the work of converting the image to the internal format.

Trying texture formats...
OK: texformat_L8 / GL_LUMINANCE8 / GL_LUMINANCE / GL_UNSIGNED_BYTE
OK: texformat_A8 / GL_ALPHA8 / GL_ALPHA / GL_UNSIGNED_BYTE
OK: texformat_LA8 / GL_LUMINANCE8_ALPHA8 / GL_LUMINANCE_ALPHA / GL_UNSIGNED_BYTE
OK: texformat_L16 / GL_LUMINANCE16 / GL_LUMINANCE / GL_UNSIGNED_SHORT
OK: texformat_LA16 / GL_LUMINANCE16_ALPHA16 / GL_LUMINANCE_ALPHA / GL_UNSIGNED_SHORT
OK: texformat_R3G3B2 / GL_R3_G3_B2 / GL_RGB / GL_UNSIGNED_BYTE_3_3_2
OK: texformat_R3G3B2 / GL_R3_G3_B2 / GL_RGB / GL_UNSIGNED_BYTE
OK: texformat_R5G6B5 / GL_RGB5 / GL_RGB / GL_UNSIGNED_SHORT_5_6_5
OK: texformat_R5G6B5 / GL_RGB5 / GL_RGB / GL_UNSIGNED_BYTE
OK: texformat_R5G5B5A1 / GL_RGB5 / GL_RGBA / GL_UNSIGNED_SHORT_1_5_5_5_REV
OK: texformat_R5G5B5A1 / GL_RGB5 / GL_RGBA / GL_UNSIGNED_SHORT_5_5_5_1
OK: texformat_R5G5B5A1 / GL_RGB5 / GL_RGBA / GL_UNSIGNED_BYTE
OK: texformat_RGBA4 / GL_RGBA4 / GL_RGBA / GL_UNSIGNED_SHORT_4_4_4_4_REV
OK: texformat_RGBA4 / GL_RGBA4 / GL_RGBA / GL_UNSIGNED_SHORT_4_4_4_4
OK: texformat_RGBA4 / GL_RGBA4 / GL_RGBA / GL_UNSIGNED_BYTE
OK: texformat_RGB8 / GL_RGB8 / GL_RGB / GL_UNSIGNED_BYTE
OK: texformat_RGBA8 / GL_RGBA8 / GL_RGBA / GL_UNSIGNED_BYTE
OK: texformat_RGB16 / GL_RGB16 / GL_RGB / GL_UNSIGNED_SHORT
OK: texformat_RGBA16 / GL_RGBA16 / GL_RGBA / GL_UNSIGNED_SHORT
OK: texformat_R32F / GL_LUMINANCE32F / format 1903h / GL_FLOAT
OK: texformat_RGBA32F / GL_RGBA32F / GL_RGBA / GL_FLOAT
OK: texformat_R16F / GL_LUMINANCE16F / format 1903h / GL_HALF_FLOAT
OK: texformat_RGBA16F / GL_RGBA16F / GL_RGBA / GL_HALF_FLOAT
OK: texformat_DXT1 / GL_COMPRESSED_RGB_S3TC_DXT1_EXT / GL_RGB / GL_UNSIGNED_BYTE
OK: texformat_DXT1RGBA / GL_COMPRESSED_RGBA_S3TC_DXT1_EXT / GL_RGBA / GL_UNSIGNED_BYTE
OK: texformat_DXT3 / GL_COMPRESSED_RGBA_S3TC_DXT3_EXT / GL_RGBA / GL_UNSIGNED_BYTE
OK: texformat_DXT5 / GL_COMPRESSED_RGBA_S3TC_DXT5_EXT / GL_RGBA / GL_UNSIGNED_BYTE

GLES2 on ANGLE (Google's Direct3d wrapper):
You must convert the image to the desired pixel format. You do not tell the driver which internal format it should use -- it devises that from your image's pixel format Thankfully I use Vampyre Imaging library.


Trying texture formats...
OK: texformat_L8 / GL_LUMINANCE / GL_LUMINANCE / GL_UNSIGNED_BYTE
OK: texformat_LA8 / GL_LUMINANCE_ALPHA / GL_LUMINANCE_ALPHA / GL_UNSIGNED_BYTE
OK: texformat_RGB8 / GL_RGB / GL_RGB / GL_UNSIGNED_BYTE
OK: texformat_RGBA8 / GL_RGBA / GL_RGBA / GL_UNSIGNED_BYTE
texformat_R3G3B2 / GL_RGB / GL_RGB / GL_UNSIGNED_BYTE_3_3_2: failed, GL_INVALID_ENUM.
OK: texformat_R5G6B5 / GL_RGB / GL_RGB / GL_UNSIGNED_SHORT_5_6_5
texformat_R5G5B5A1 / GL_RGBA / GL_RGBA / GL_UNSIGNED_SHORT_1_5_5_5_REV: failed, GL_INVALID_ENUM.
OK: texformat_R5G5B5A1 / GL_RGBA / GL_RGBA / GL_UNSIGNED_SHORT_5_5_5_1
texformat_RGBA4 / GL_RGBA / GL_RGBA / GL_UNSIGNED_SHORT_4_4_4_4_REV: failed, GL_INVALID_ENUM.
OK: texformat_RGBA4 / GL_RGBA / GL_RGBA / GL_UNSIGNED_SHORT_4_4_4_4
OK: texformat_R16F / GL_LUMINANCE / GL_LUMINANCE / GL_HALF_FLOAT_OES
OK: texformat_RGBA16F / GL_RGBA / GL_RGBA / GL_HALF_FLOAT_OES
texformat_RGB16 / GL_RGB / GL_RGB / GL_UNSIGNED_SHORT: failed, GL_INVALID_OPERATION.
texformat_RGBA16 / GL_RGBA / GL_RGBA / GL_UNSIGNED_SHORT: failed, GL_INVALID_OPERATION.
OK: texformat_R32F / GL_LUMINANCE / GL_LUMINANCE / GL_FLOAT
OK: texformat_RGBA32F / GL_RGBA / GL_RGBA / GL_FLOAT

GLES2 on Physical raspberry Pi 2:
The same thing just with less formats working.

Trying texture formats...
OK: texformat_L8 / GL_LUMINANCE / GL_LUMINANCE / GL_UNSIGNED_BYTE
OK: texformat_LA8 / GL_LUMINANCE_ALPHA / GL_LUMINANCE_ALPHA / GL_UNSIGNED_BYTE
OK: texformat_RGB8 / GL_RGB / GL_RGB / GL_UNSIGNED_BYTE
OK: texformat_RGBA8 / GL_RGBA / GL_RGBA / GL_UNSIGNED_BYTE
texformat_R3G3B2 / GL_RGB / GL_RGB / GL_UNSIGNED_BYTE_3_3_2: failed, GL_INVALID_OPERATION.
OK: texformat_R5G6B5 / GL_RGB / GL_RGB / GL_UNSIGNED_SHORT_5_6_5
texformat_R5G5B5A1 / GL_RGBA / GL_RGBA / GL_UNSIGNED_SHORT_1_5_5_5_REV: failed, GL_INVALID_OPERATION.
OK: texformat_R5G5B5A1 / GL_RGBA / GL_RGBA / GL_UNSIGNED_SHORT_5_5_5_1
texformat_RGBA4 / GL_RGBA / GL_RGBA / GL_UNSIGNED_SHORT_4_4_4_4_REV: failed, GL_INVALID_OPERATION.
OK: texformat_RGBA4 / GL_RGBA / GL_RGBA / GL_UNSIGNED_SHORT_4_4_4_4
texformat_R16F / GL_LUMINANCE / GL_LUMINANCE / GL_HALF_FLOAT_OES: failed, GL_INVALID_OPERATION.
texformat_RGBA16F / GL_RGBA / GL_RGBA / GL_HALF_FLOAT_OES: failed, GL_INVALID_OPERATION.
texformat_RGB16 / GL_RGB / GL_RGB / GL_UNSIGNED_SHORT: failed, GL_INVALID_OPERATION.
texformat_RGBA16 / GL_RGBA / GL_RGBA / GL_UNSIGNED_SHORT: failed, GL_INVALID_OPERATION.
texformat_R32F / GL_LUMINANCE / GL_LUMINANCE / GL_FLOAT: failed, GL_INVALID_OPERATION.
texformat_RGBA32F / GL_RGBA / GL_RGBA / GL_FLOAT: failed, GL_INVALID_OPERATION.

Chebmaster
24-01-2018, 05:20 PM
class procedure TGAPI.AnalyzeAndRegisterQuirks;
var
t: TGAPITextureFormat;
v: TImageFormat;
function TryGLTexFormat(mfmt: TGAPITextureFormat; gfmt, gtype: GLenum;
gact: GLint; vf: TImageFormat): boolean;
var
i: TImageFormat;
t: GLuint;
e: GLenum;
buf: pointer;
begin
try
case Mother^.GAPI.Mode of
{$ifndef glesonly}
gapi_GL21,
{$endif glesonly}
gapi_GLES2: begin
ImageFormatForTextureFormat[mfmt]:= ifUnknown; //aka zero

try
GetMem(buf, 16 * 32 * 32);//Self.NumTexelsToBytes(mfmt, 32 * 32));
GlGenTextures(1, @t);
glBindTexture(GL_TEXTURE_2D, t);
glTexImage2D (GL_TEXTURE_2D, 0, gact, 32, 32, 0, gfmt, gtype, buf);
e:= glGetError();
glDeleteTextures(1, @t);
finally
FreeMem(buf);
buf:= nil;
glGetError();
end;

if e = GL_NO_ERROR then begin
if Mother^.Debug.Verbose then AddLog(
' OK: %0 / %1 / %2 / %3',
[GetEnumName(typeinfo(TGAPITextureFormat), ord(mfmt)),
GlTextureFormatToString(gact),
GlTextureFormatToString(gfmt),
GlTextureFormatToString(gtype)
]);
with Mother^.GAPI.TexFormats^[mfmt] do begin
general:= gfmt;
_type:= gtype;
actual:= gact;
end;
TGAPI.ImageFormatForTextureFormat[mfmt]:= vf;
Result:= true;
end
else begin
if Mother^.Debug.Verbose then AddLog(
' %0 / %1 / %2 / %3: failed, %4.',
[GetEnumName(typeinfo(TGAPITextureFormat), ord(mfmt)),
GlTextureFormatToString(gact),
GlTextureFormatToString(gfmt),
GlTextureFormatToString(gtype),
GlErrorCodeToString(e)
]);
FillChar(Mother^.GAPI.TexFormats^[mfmt], sizeof(TMotherTexFormatDesc), 0);
Result:= false;
end;
end;
else
DieUnsupportedGLMode;
end;
except
Die(RuEn(
'Сбой при испытании сочетания текстурных форматов %0 / %1 / %2 / %3',
'Crashed trying texture formats combo %0 / %1 / %2 / %3'
), [GetEnumName(typeinfo(TGAPITextureFormat), ord(mfmt)),
GlTextureFormatToString(gact),
GlTextureFormatToString(gfmt),
GlTextureFormatToString(gtype)
]
);
end;
end;

function TryRenderbufferFormat(mfmt: TGAPITextureFormat; gfmt: GLenum): boolean;
var
t: GLuint;
e: GLenum;
begin
try
case Mother^.GAPI.Mode of
{$ifndef glesonly}
gapi_GL21,
{$endif glesonly}
gapi_GLES2: begin
glGenRenderbuffers(1, @t);
glBindRenderbuffer(GL_RENDERBUFFER_EXT, t);
glRenderbufferStorage(GL_RENDERBUFFER_EXT, gfmt, 32, 32);
e:= glGetError();
glDeleteRenderbuffers(1, @t);
glGetError();

if e = GL_NO_ERROR then begin
if Mother^.Debug.Verbose then AddLog(
' OK: %0 / %1',
[GetEnumName(typeinfo(TGAPITextureFormat), ord(mfmt)),
GlTextureFormatToString(gfmt)
]);
Mother^.GAPI.RenderBufferFormats^[mfmt]:= gfmt;
Result:= true;
end
else begin
if Mother^.Debug.Verbose then AddLog(
' %0 / %1: failed, %2.',
[GetEnumName(typeinfo(TGAPITextureFormat), ord(mfmt)),
GlTextureFormatToString(gfmt),
GlErrorCodeToString(e)
]);
Mother^.GAPI.RenderBufferFormats^[mfmt]:= 0;
Result:= false;
end;
end;
else
DieUnsupportedGLMode;
end;
except
Die(RuEn(
'Сбой при испытании формата буфера отрисовки %0 / %1',
'Crashed trying render buffer format %0 / %1'
), [GetEnumName(typeinfo(TGAPITextureFormat), ord(mfmt)),
GlTextureFormatToString(gfmt)
]
);
end;
end;

begin
Config.GetSet(@Mother^.GAPI.Quirks, typeInfo(TGAPIQuirksEnum), 'videocard', 'quirks');
Config.GetSet(@Mother^.GAPI.QuirksTested, typeInfo(TGAPIQuirksEnum), 'videocard', 'tested_quirks');

try
case Mother^.GAPI.Mode of
{$ifndef glesonly}
gapi_GL21: begin
Assert(sizeof(TGAPITextureFormatSet) = 4, 'The size of TGAPITextureFormatSet is not 4 but ' + IntToStr(sizeof(TGAPITextureFormatSet)));

GetMem(Mother^.GAPI.TexFormats, 32 * sizeof(TMotherTexFormatDesc));
FillChar(Mother^.GAPI.TexFormats^, 32 * sizeof(TMotherTexFormatDesc), 0);

GetMem(Mother^.GAPI.RenderbufferFormats, 32 * sizeof(ptruint));
FillChar(Mother^.GAPI.RenderbufferFormats^, 32 * sizeof(ptruint), 0);

if Mother^.Debug.Verbose then AddLog(' Trying texture formats...');
TryGLTexFormat(texformat_RGB8, GL_RGB, GL_UNSIGNED_BYTE, GL_RGB8, ifR8G8B8);
TryGLTexFormat(texformat_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA8, ifA8R8G8B8);

TryGLTexFormat(texformat_L8, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_LUMINANCE8, ifGray8);
TryGLTexFormat(texformat_A8, GL_ALPHA, GL_UNSIGNED_BYTE, GL_ALPHA8, ifGray8);
TryGLTexFormat(texformat_LA8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_LUMINANCE8_ALPHA8, ifA8Gray8);
TryGLTexFormat(texformat_L16, GL_LUMINANCE, GL_UNSIGNED_SHORT, GL_LUMINANCE16, ifGray16);
TryGLTexFormat(texformat_LA16, GL_LUMINANCE_ALPHA, GL_UNSIGNED_SHORT, GL_LUMINANCE16_ALPHA16, ifA16Gray16);

if not TryGLTexFormat(texformat_R5G6B5, GL_RGB, GL_UNSIGNED_BYTE, GL_RGB5, ifA8R8G8B8)
then TryGLTexFormat(texformat_R5G6B5, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_RGB5, ifR5G6B5);

if not TryGLTexFormat(texformat_R5G5B5A1, GL_RGBA, GL_UNSIGNED_BYTE, GL_RGB5, ifA8R8G8B8)
then TryGLTexFormat(texformat_R5G5B5A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_RGB5, ifA1R5G5B5);

if not TryGLTexFormat(texformat_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA4, ifA8R8G8B8)
then TryGLTexFormat(texformat_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_RGBA4, ifA4R4G4B4);


TryGLTexFormat(texformat_RGB16, GL_RGB, GL_UNSIGNED_SHORT, GL_RGB16, ifR16G16B16);
TryGLTexFormat(texformat_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, GL_RGBA16, ifA16R16G16B16);
TryGLTexFormat(texformat_R32F, GL_RED, GL_FLOAT, GL_LUMINANCE32F_ARB, ifR32F);
TryGLTexFormat(texformat_RGBA32F, GL_RGBA, GL_FLOAT, GL_RGBA32F_ARB, ifA32R32G32B32F);
TryGLTexFormat(texformat_R16F, GL_RED, GL_HALF_FLOAT_ARB, GL_LUMINANCE16F_ARB, ifR16F);
TryGLTexFormat(texformat_RGBA16F, GL_RGBA, GL_HALF_FLOAT_ARB, GL_RGBA16F_ARB, ifA16R16G16B16F);

// DDS format is NOT supported because it is patented.
// If the driver allows uploading RGBA8 to DXT, this becomes the driver
// manufacturer's problem.
// So while using DXT is supported, saving / loading of it is NOT.
// (even as Vampyre Imaging has DDS support, including mipmaps)
TryGLTexFormat(texformat_DXT1, GL_RGB, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, ifR8G8B8);
TryGLTexFormat(texformat_DXT1RGBA, GL_RGBA, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, ifA8R8G8B8);
TryGLTexFormat(texformat_DXT3, GL_RGBA, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, ifA8R8G8B8);
TryGLTexFormat(texformat_DXT5, GL_RGBA, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, ifA8R8G8B8);

if not TryGLTexFormat(texformat_Depth, GL_DEPTH_COMPONENT, GL_FLOAT, GL_DEPTH_COMPONENT, ifR32F)
then TryGLTexFormat(texformat_Depth, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, ifGray32);
if not TryGLTexFormat(texformat_Depth16, GL_DEPTH_COMPONENT, GL_HALF_FLOAT_ARB, GL_DEPTH_COMPONENT, ifR16F)
then TryGLTexFormat(texformat_Depth16, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, ifR16F);

for t in TGAPITextureFormat do begin
v:= TGAPI.ImageFormatForTextureFormat[t];
if v <> ifUnknown
then TGAPI.TextureFormatsPerImageFormat[byte(v)]+= [t]; //add the enum to the set
end;

if Mother^.Debug.Verbose then AddLog(' Trying render buffer formats...');
TryRenderbufferFormat(texformat_RGBA4, GL_RGBA4);
TryRenderbufferFormat(texformat_R5G6B5, GL_RGB565);
TryRenderbufferFormat(texformat_R5G5B5A1, GL_RGB5_A1);

TryRenderbufferFormat(texformat_RGBA8, GL_RGBA8);
TryRenderbufferFormat(texformat_RGB8, GL_RGB8);
TryRenderbufferFormat(texformat_RGB16, GL_RGB16);
TryRenderbufferFormat(texformat_RGBA16, GL_RGBA16);
TryRenderbufferFormat(texformat_R16F, GL_LUMINANCE16F_ARB);
TryRenderbufferFormat(texformat_R32F, GL_LUMINANCE32F_ARB);
TryRenderbufferFormat(texformat_RGBA16F, GL_RGBA16F_ARB);
TryRenderbufferFormat(texformat_RGBA32F, GL_RGBA32F_ARB);
TryRenderbufferFormat(texformat_L8, GL_LUMINANCE8);
{

TryRenderbufferFormat();
TryRenderbufferFormat();
TryRenderbufferFormat();
TryRenderbufferFormat();
TryRenderbufferFormat();
}
if not TryRenderbufferFormat(texformat_Depth, GL_DEPTH_COMPONENT32)
then TryRenderbufferFormat(texformat_Depth, GL_DEPTH_COMPONENT24);
TryRenderbufferFormat(texformat_Depth16, GL_DEPTH_COMPONENT16);



if Mother^.GAPI.Mode in [gapi_GL21]
then TestOpenGlQuirkNo2;

CheckGLError(false);
end;
{$endif glesonly}
gapi_GLES2: begin
Assert(sizeof(TGAPITextureFormatSet) = 4, 'The size of TGAPITextureFormatSet is not 4 but ' + IntToStr(sizeof(TGAPITextureFormatSet)));

GetMem(Mother^.GAPI.TexFormats, 32 * sizeof(TMotherTexFormatDesc));
FillChar(Mother^.GAPI.TexFormats^, 32 * sizeof(TMotherTexFormatDesc), 0);

GetMem(Mother^.GAPI.RenderbufferFormats, 32 * sizeof(ptruint));
FillChar(Mother^.GAPI.RenderbufferFormats^, 32 * sizeof(ptruint), 0);


if Mother^.Debug.Verbose then AddLog(' Trying texture formats...');

TryGLTexFormat(texformat_RGB8, GL_RGB, GL_UNSIGNED_BYTE, GL_RGB, ifR8G8B8);
TryGLTexFormat(texformat_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA, ifA8R8G8B8);

TryGLTexFormat(texformat_L8, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_LUMINANCE, ifGray8);
TryGLTexFormat(texformat_LA8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_LUMINANCE_ALPHA, ifA8Gray8);
TryGLTexFormat(texformat_L16, GL_LUMINANCE, GL_UNSIGNED_SHORT, GL_LUMINANCE, ifGray16);
TryGLTexFormat(texformat_LA16, GL_LUMINANCE_ALPHA, GL_UNSIGNED_SHORT, GL_LUMINANCE_ALPHA, ifA16Gray16);

TryGLTexFormat(texformat_R5G6B5, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_RGB, ifR5G6B5);
TryGLTexFormat(texformat_R5G5B5A1, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_RGBA, ifA1R5G5B5);
TryGLTexFormat(texformat_R5G5B5A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_RGBA, ifA1R5G5B5);
TryGLTexFormat(texformat_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV, GL_RGBA, ifA4R4G4B4);
TryGLTexFormat(texformat_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_RGBA, ifA4R4G4B4);

TryGLTexFormat(texformat_R16F, GL_LUMINANCE, GL_HALF_FLOAT_OES, GL_LUMINANCE, ifR16F);
TryGLTexFormat(texformat_RGBA16F, GL_RGBA, GL_HALF_FLOAT_OES, GL_RGBA, ifA16R16G16B16F);

TryGLTexFormat(texformat_RGB16, GL_RGB, GL_UNSIGNED_SHORT, GL_RGB, ifR16G16B16);
TryGLTexFormat(texformat_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, GL_RGBA, ifA16R16G16B16);

// Well, ANGLE supports this. On top of Direct3d9...
TryGLTexFormat(texformat_R32F, GL_LUMINANCE, GL_FLOAT, GL_LUMINANCE, ifR32F);
TryGLTexFormat(texformat_RGBA32F, GL_RGBA, GL_FLOAT, GL_RGBA, ifA32R32G32B32F);


//These do *not* work in ANGLE:
if not TryGLTexFormat(texformat_Depth, GL_DEPTH_COMPONENT, GL_FLOAT, GL_DEPTH_COMPONENT, ifR32F)
then TryGLTexFormat(texformat_Depth, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT32_OES, GL_DEPTH_COMPONENT, ifR32F);
if not TryGLTexFormat(texformat_Depth16, GL_DEPTH_COMPONENT, GL_HALF_FLOAT_OES, GL_DEPTH_COMPONENT, ifR16F)
then TryGLTexFormat(texformat_Depth16, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, ifR16F);

for t in TGAPITextureFormat do begin
v:= TGAPI.ImageFormatForTextureFormat[t];
if v <> ifUnknown
then TGAPI.TextureFormatsPerImageFormat[byte(v)]+= [t]; //add the enum to the set
end;

if Mother^.Debug.Verbose then AddLog(' Trying render buffer formats...');
TryRenderbufferFormat(texformat_RGBA4, GL_RGBA4);
TryRenderbufferFormat(texformat_R5G6B5, GL_RGB565);
TryRenderbufferFormat(texformat_R5G5B5A1, GL_RGB5_A1);


TryRenderbufferFormat(texformat_RGBA8, GL_RGBA8);
TryRenderbufferFormat(texformat_RGB8, GL_RGB8);
TryRenderbufferFormat(texformat_RGB16, GL_RGB16);
TryRenderbufferFormat(texformat_RGBA16, GL_RGBA16);
TryRenderbufferFormat(texformat_R16F, GL_LUMINANCE16F_ARB);
TryRenderbufferFormat(texformat_R32F, GL_LUMINANCE32F_ARB);
TryRenderbufferFormat(texformat_RGBA16F, GL_RGBA16F_ARB);
TryRenderbufferFormat(texformat_RGBA32F, GL_RGBA32F_ARB);
TryRenderbufferFormat(texformat_L8, GL_LUMINANCE8);


if not TryRenderbufferFormat(texformat_Depth, GL_DEPTH_COMPONENT24_OES) //this one never works
then if not TryRenderbufferFormat(texformat_Depth, GL_DEPTH_COMPONENT32_OES)
then TryRenderbufferFormat(texformat_Depth, GL_DEPTH24_STENCIL8_OES);
TryRenderbufferFormat(texformat_Depth16, GL_DEPTH_COMPONENT16);

if Mother^.GAPI.Mode in [gapi_GL21]
then TestOpenGlQuirkNo2;
end;
else
DieUnsupportedGLMode;
end;

if Self.SupportedTexFormat(texformat_RGBA8) <> texformat_RGBA8
then Die(RuEn(
'Что-то не то с видеодрайвером, нет поддержки текстурного формата RGBA8!',
'There is something wrong with the video driver, no support for the RGBA8 texture format!'))

except
Die(RuEn(
'Сбой при анализе особенностей %0',
'Crashed trying to analyze %0 quirks'
), [self.Name(rc_Accusative)]);
end;

end;

Chebmaster
24-01-2018, 05:44 PM
Now, when I want to load image into texture I call these helpers, the calling code is identical across GL and GLES:


format:= TGAPI.SupportedTexFormat(texformat_DXT5, texformat_LA8,
texformat_RGBA4, texformat_RGBA8);

file_name:= UnmangleFilename('{$INSDIR}modules/chentrah/img/consolefont.png');
if not FileExists(file_name)
then Die(MI_ERROR_FILE_NOT_FOUND, [file_name]);
p:= LoadPicAs(PFileNameChar(file_name), [format]);
CheckForGuardedException;
glGenTextures(1, @f_texture);
glBindTexture(GL_TEXTURE_2D, f_texture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
TGAPI.TexImage2d(p, format);
DeletePic(p);

where:

function LoadPicAs (FileName: PFileNameChar;
ValidFormats: TGAPITextureFormatSet): pointer; cdecl;
var
n: TFileNameString;
w: UnicodeString;
i: PImageData;
s: TFileStream = nil;
p: pointer = nil;
size: longint;
begin
if Mother^.Image.CorrectThreadId <> GetCurrentThreadId()
then Die(MI_ERROR_PROGRAMMER_NO_BAKA, ['Imaging API called from a wrong thread']);
try
n:= UnmangleFileName(FileName);
w:= FileNameToUnicode(n);
i:=GetMem(SizeOf(TImageData));
VyCheckFileNameLoad(w);
if not FileExists(n)
then Die(MI_ERROR_FILE_NOT_FOUND, [n]);
{ Whoops... vampyre is not unicode, have to load the file by ourselves! }
try
try
s:= TFileStream.Create(n, fmOpenRead);
size:= s.Size;
p:= GetMem(size);
s.ReadBuffer(p^, size);
if not LoadImageFromMemory(p, size, i^) //Vampyre call
then begin
FreeMem(i);
i:= nil;
Die(FailedToDecodeMessage() ,[]);
end;
finally
s.Free;
FreeMem(p);
end;

ClearDyingEvents(GetExceptionState());
//Vampyre often litters the dying events log with screened exceptions that
// my SEH still dutifully logs.

except
Die(
'Не удалось прочитать "%0".'#10#13' Скорее всего, файл повреждён.',
'Cannot read file "%0".'#10#13' It''s probaly corrupt.', [w]);
end;
if Assigned(i) then ConvertImageIfNecessary (i, ValidFormats);
Result:= i;
except
ProcessGuardedException();
end;
end;


procedure ConvertImageIfNecessary(var i: PImageData; ValidFormats: TGAPITextureFormatSet);
var
gf: TGapiTextureFormat;
vy , nvy: TImageFormat;
unnecessary: boolean;
begin
nvy:= ifUnknown;
unnecessary:= false;
for gf in ValidFormats do begin
vy:= TGAPI.ImageFormatForTextureFormat[gf];
if vy = i^.Format then begin
unnecessary:= true;
break;
end;
if nvy = ifUnknown then nvy:= vy;
if unnecessary then break; // Why oh why there is no such thing as break 2 :(
end;

if unnecessary then begin
if Mother^.Debug.Verbose then AddLog (
' There is no need to convert image as %0 already matches [%1]',
[VyFormatName(i^.Format) ,
SetToString(dword((@ValidFormats)^), typeinfo(TGAPITextureFormatSet))]);
end
else begin
if nvy = ifUnknown then Die(RuEn(
'Невозможно привести изображение к набору абстрактных текстурных форматов [%0], т.к. ему не сопоставлен ни один формат изображения Vampyre Imaging',
'Unable to convert image to the abstract texture formats set [%0] because it has no Vampyre Imaging image formats associated with it'
), [SetToString(dword((@ValidFormats)^), typeinfo(TGAPITextureFormatSet))]);
if Mother^.Debug.Verbose then AddLog (
' Converting image from %0 to %1 to match [%2]',
[ VyFormatName(i^.Format),// GetEnumName(typeinfo(TImageFormat), ord(i^.Format)),
// cl_mother_api_imaging.inc(399,21) Error: No type info available for this type
// ****.

VyFormatname(nvy), //GetEnumName(typeinfo(TImageFormat), ord(nvy)), //cl_mother_api_imaging.inc(403,42) Error: No type info available for this type
SetToString(dword((@ValidFormats)^), typeinfo(TGAPITextureFormatSet))]);
ConvertImage(i^, nvy);
end;
end;


class function TGAPI.SupportedTexFormat(f1: TGAPITextureFormat;
f2: TGAPITextureFormat = texformat_NONE;
f3: TGAPITextureFormat = texformat_NONE;
f4: TGAPITextureFormat = texformat_NONE;
f5: TGAPITextureFormat = texformat_NONE
): TGAPITextureFormat;
begin
with Mother^.GAPI do begin
if TexFormats^[f1].actual <> 0 then Exit(f1);
if TexFormats^[f2].actual <> 0 then Exit(f2);
if TexFormats^[f3].actual <> 0 then Exit(f3);
if TexFormats^[f4].actual <> 0 then Exit(f4);
if TexFormats^[f5].actual <> 0 then Exit(f5);
end;
Result:= texformat_NONE;
end;


/ Will evoke Die if image format is not in ImageFormatsPerTextureFormat
// for the given texture format.
// Pass nil to i to load uninitialized image.
// The caller is responsible for all sanity checks (if NPOT supported, etc.)
class function TGAPI.TexImage2d(
image: pointer;
format: TGAPITextureFormat;
level: GLuint = 0;
width: GLuint = 0; // 0 = get from image
height: GLuint = 0; // 0 = get from image
CreateTextureObject: boolean = false
): GLuint; //no return value unless CreateTextureObject is true
var
sset: TGAPITextureFormatSet;
e: GLenum;
begin
try
sset:= Mother^.Image.GetFmt(image);
// CheckForGuardedException;

if not (format in sset)
then
{$ifdef cgekernel}
ConvertImageIfNecessary (image, [format]);
{$else}
// CANNOT convert on the fly.
// Because converting should be a threaded task in a different thread.
Die(RuEn(
'Попытка загрузить в текстуру %0 изображение, совместимое с [%1]',
'Attempt to upload image compatible with [%1] into texture %0'),
[GetEnumName(typeinfo(TGAPITextureFormat), ord(format)),
mo_cge.SetToString(pdword(@sset)^, typeinfo(TGAPITextureFormatSet))]);
{$endif}
case Mother^.GAPI.Mode of
{$ifndef glesonly}
gapi_GL21,
{$endif}
gapi_GLES2 : begin
if CreateTextureObject then begin
glGenTextures(1, @Result);
glBindTexture(GL_TEXTURE_2D, Result);
CheckGLError;
end;
with Mother^.Image
do with Mother^.GAPI.TexFormats^[format]
do glTexImage2D (GL_TEXTURE_2D, level, actual,
GetWidth(image), GetHeight(image), 0, general, _type,
GetPixels(image));
e:= glGetError();
if e <> GL_NO_ERROR
then with Mother^.GAPI.TexFormats^[format]
do Die('%0 with %1 / %2 / %3 / %4', [
GlErrorCodeToString(e),
GetEnumName(typeinfo(TGAPITextureFormat), ord(format)),
GlTextureFormatToString(actual),
GlTextureFormatToString(general),
GlTextureFormatToString(_type)
]);
end;
else
DieUnsupportedGLMode;
end;
except
Die(RuEn(
'Сбой при закачке текстуры в видеодрайвер',
'Failed to upload texture image'));
end;
end;

LP
24-01-2018, 09:10 PM
This web page (https://www.khronos.org/opengl/wiki/Image_Format#Required_formats) pretty much explains what formats are always supported ("Required Formats" section).

For others, you can use glGetInternalFormat (https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetInternalformat.xhtml) to check for a particular internal format at run-time, which might be hardware-dependent.

To find our overall support for some specific compressed formats there's a nice database site (which also has very useful information regarding OpenGL extensions):
http://opengl.gpuinfo.org

Edit: Raspberry PI doesn't support OpenGL ES 3, nor https://www.khronos.org/registry/OpenGL/extensions/OES/OES_texture_float.txt (OES_texture_float), which would explain your results regarding floating-point formats. For OpenGL ES, there is also ARB_internalformat_query2 (https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_internalformat_query2.txt), although RPi doesn't seem to support it either (https://gist.github.com/jvcleave/8657864), so you are pretty much limited to almost minimal OpenGL ES 2.0 spec (https://www.khronos.org/registry/OpenGL/specs/es/2.0/es_cm_spec_2.0.pdf) (see Table 3.1 - Texture Image Formats and Types, on page 20).

Chebmaster
25-01-2018, 04:05 PM
Thank you for the links! When I try serach for GLES 2 documentation most websites force-feed me GLES 3 documentation in the form of "this link is obsolete, go that-a-ways" or auto-redirects.

..I'm going to feel the pain, ain't I...? With Raspberry...? No reading from depth, only one color attachment, maximum color depth is RGBA8...