硬件加速活动 - 如何获得OpenGL纹理大小限制?

Poi*_*ull 45 android hardware-acceleration android-3.0-honeycomb

我正在尝试在Honeycomb中启用hw加速,并在Canvas上显示一些Bitmaps.一切正常,但对于大位图(一维> 2048),我在日志中得到错误:

OpenGLRenderer:位图太大而无法上传到纹理中

我知道这是因为hw限制,并且可以通过减少最大位图大小来解决它,如果启用了hw加速(由View.isHardwareAccelerated()检查).

我的问题是:如何轻松确定硬件可用于位图绘制的最大纹理大小.2048似乎是对我的设备的限制,但它可能在不同的设备上有所不同.

编辑:我不是创建OpenGL应用程序,只是普通的应用程序,它可以利用hw加速.因此我根本不熟悉OpenGL,我只是在日志中看到OpenGL相关的错误,并期待解决它.

Rom*_*Guy 65

目前最小限制是2048px(即硬件必须支持纹理至少2048x2048.)在ICS中,我们将在Canvas类中引入一个新的API,它将为您提供以下信息:
Canvas.getMaximumBitmapWidth()Canvas.getMaximumBitmapHeight().

  • 2048x2048是GN上的最大纹理尺寸.您很可能遇到此问题,因为您的图像位于错误的密度桶中.GN是一个xhdpi设备,因此如果您的720x1200图像位于可绘制文件夹中,它将缩放100%并最终为1440x2400. (48认同)
  • @RomainGuy这两个方法只返回一个静态值Canvas.MAXMIMUM_BITMAP_SIZE,它等于`32766`.那似乎不对......? (8认同)
  • 它不能是常数,因为它取决于GPU.2048x2048是一个完全合理的假设. (4认同)
  • 该方法称为getMaximumBitmapHeight().但它不是一个静态的方法.是否有一个静态方法或常量,它给我的值,我可以用来下载或调整图像大小,而不是每次创建一个Canvas对象? (3认同)
  • 这不可能是真的!我遇到了在Galaxy Nexus上显示1236x835图像的问题!! 我的旧HTC Hero能够显示出来!并且:它只是一个静态图像!我不相信我在那里看到的东西.我怎么能绕过这个? (3认同)
  • @HenriSweers在硬件加速画布上,它返回正确的值.因此,在获取值之前,您必须使用带有`setLayerType(LAYER_TYPE_HARDWARE,null)`的真实视图.`32788`值仅适用于基于软件的画布. (3认同)
  • @TSGames有一个如何使用这两种方法的例子吗?执行(new Canvas()).getMaximumBitmap {Width,Height()}似乎在GN5上返回错误的32766. (2认同)

Pkm*_*mte 16

获得最大允许大小的另一种方法是遍历所有EGL10配置并跟踪最大尺寸.

public static int getMaxTextureSize() {
    // Safe minimum default size
    final int IMAGE_MAX_BITMAP_DIMENSION = 2048;

    // Get EGL Display
    EGL10 egl = (EGL10) EGLContext.getEGL();
    EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);

    // Initialise
    int[] version = new int[2];
    egl.eglInitialize(display, version);

    // Query total number of configurations
    int[] totalConfigurations = new int[1];
    egl.eglGetConfigs(display, null, 0, totalConfigurations);

    // Query actual list configurations
    EGLConfig[] configurationsList = new EGLConfig[totalConfigurations[0]];
    egl.eglGetConfigs(display, configurationsList, totalConfigurations[0], totalConfigurations);

    int[] textureSize = new int[1];
    int maximumTextureSize = 0;

    // Iterate through all the configurations to located the maximum texture size
    for (int i = 0; i < totalConfigurations[0]; i++) {
        // Only need to check for width since opengl textures are always squared
        egl.eglGetConfigAttrib(display, configurationsList[i], EGL10.EGL_MAX_PBUFFER_WIDTH, textureSize);

        // Keep track of the maximum texture size
        if (maximumTextureSize < textureSize[0])
            maximumTextureSize = textureSize[0];
    }

    // Release
    egl.eglTerminate(display);

    // Return largest texture size found, or default
    return Math.max(maximumTextureSize, IMAGE_MAX_BITMAP_DIMENSION);
}
Run Code Online (Sandbox Code Playgroud)

从我的测试来看,这非常可靠,并且不需要您创建实例.性能方面,我在Note 2上执行了18毫秒,在G3上只执行了4毫秒.

  • 这为您提供了最大 **PBuffer** 大小。这与获得最大纹理大小不同。它们在某些设备上可能是相同的值,但绝对不能保证。 (2认同)

Vin*_*eFR 6

如果您想要动态了解设备的纹理大小限制(因为它的更改取决于设备),您必须调用此方法:

int[] maxTextureSize = new int[1];
gl.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, maxTextureSize, 0);
Run Code Online (Sandbox Code Playgroud)

并且不要忘记,对于某些设备(例如Nexus One),纹理大小必须是2的幂!

我知道我的答案在上一次更新这个主题后很长一段时间...抱歉

  • 谢谢你的回答,它的确有效.一个注意事项:这是一个静态方法,所以你可以简单地调用`GLES10.glGetIntegerv(...)` (5认同)