DrKLO/Telegram · error · FrameProcessingException

Could not store the LUT as a texture.

Error message

Could not store the LUT as a texture.

What it means

SingleColorLut.toGlTextureProcessor wraps any GlUtil.GlException thrown by storeLutAsTexture(lut) into FrameProcessingException('Could not store the LUT as a texture.'). storeLutAsTexture creates an OpenGL 2D texture and uploads the LUT bitmap via GLUtils.texImage2D; a GL error during creation or upload surfaces here.

Source

Thrown at TMessagesProj/src/main/java/com/google/android/exoplayer2/effect/SingleColorLut.java:157

  @Override
  public int getLength(long presentationTimeUs) {
    return lut.getWidth();
  }

  @Override
  public void release() throws GlUtil.GlException {
    GlUtil.deleteTexture(lutTextureId);
  }

  @Override
  public SingleFrameGlTextureProcessor toGlTextureProcessor(Context context, boolean useHdr)
      throws FrameProcessingException {
    checkState(!useHdr, "HDR is currently not supported.");

    try {
      lutTextureId = storeLutAsTexture(lut);
    } catch (GlUtil.GlException e) {
      throw new FrameProcessingException("Could not store the LUT as a texture.", e);
    }

    return new ColorLutProcessor(context, /* colorLut= */ this, useHdr);
  }

  private static int storeLutAsTexture(Bitmap bitmap) throws GlUtil.GlException {
    int lutTextureId =
        GlUtil.createTexture(
            bitmap.getWidth(), bitmap.getHeight(), /* useHighPrecisionColorComponents= */ false);
    GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, /* level= */ 0, bitmap, /* border= */ 0);
    GlUtil.checkGlError();
    return lutTextureId;
  }
}

View on GitHub (pinned to 45ab8f4308)

Solutions

  1. Ensure toGlTextureProcessor runs on the GL/effects thread with a valid current EGL context.
  2. Pass a valid, non-recycled ARGB bitmap of reasonable dimensions as the LUT.
  3. Catch FrameProcessingException around the effects pipeline and surface a user-facing fallback rather than crashing.

Example fix

// before
lut.toGlTextureProcessor(ctx, false); // called off the GL thread

// after
glThread.invoke(() -> lut.toGlTextureProcessor(ctx, false)); // run on the GL thread
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure LUT bitmap is valid and a GL context is current before calling
if (lutBitmap != null && !lutBitmap.isRecycled() && GlUtil.hasValidContext()) {
  lut.toGlTextureProcessor(ctx, /* useHdr= */ false);
}

Try / catch

try { lut.toGlTextureProcessor(ctx, false); }
catch (FrameProcessingException e) { /* skip LUT effect, surface error to user */ }

Prevention

When it happens

Trigger: Calling toGlTextureProcessor(context, useHdr) — note it first asserts useHdr is false — when GlUtil.createTexture or GLUtils.texImage2D/GlUtil.checkGlError() raises a GlException (e.g. no current GL context, texture allocation failure, unsupported bitmap format).

Common situations: Invoking the LUT pipeline off the GL thread / without a bound EGL context; a recycled or non-ARGB_8888 LUT bitmap; GPU out of memory for the LUT dimensions; GL state left in an error state by a prior operation.

Related errors


AI-assisted analysis of DrKLO/Telegram@45ab8f4308 (2026-08-14). Data as JSON: /api/errors/e1fec713b8c129f1. Report an issue: GitHub.