Results 1 to 5 of 5

Thread: GL: format, internal format, pixel format - my slightly stale research

  1. #1

    Lightbulb GL: format, internal format, pixel format - my slightly stale research

    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.
    Code:
      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.
    Code:
      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.
    Code:
      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.

  2. #2
    Code:
    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;

  3. #3
    Now, when I want to load image into texture I call these helpers, the calling code is identical across GL and GLES:

    Code:
             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:
    Code:
    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;
    Code:
    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;
    Code:
    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;
    Code:
    / 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;

  4. #4
    This web page pretty much explains what formats are always supported ("Required Formats" section).

    For others, you can use glGetInternalFormat 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, which would explain your results regarding floating-point formats. For OpenGL ES, there is also ARB_internalformat_query2, although RPi doesn't seem to support it either, so you are pretty much limited to almost minimal OpenGL ES 2.0 spec (see Table 3.1 - Texture Image Formats and Types, on page 20).
    Last edited by LP; 24-01-2018 at 09:24 PM.

  5. #5
    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...

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •