2016-09-16 62 views
1

问题。
我有一个特定的Android设备的问题。我使用本机C++库在我的应用程序中绘制东西。长期以来,我使用的解决方案在不同的设备上运行良好,直到我收到三星Galaxy S4用户(GT-I9500,Android 4.4.2,Exynos 5410)的负面反馈。我的OpenGL绘图的结果已损坏。在这种情况下,通常绘制全屏的纹理被缩小到屏幕空间的四分之一并与右上角对齐。用glClearColor绘制的背景填满整个屏幕。
我能够检查其他三个S4 - 我的应用程序中只有Exynos设备上的绘图已损坏。另外两个有Snapdragon,他们没有问题。
Android:仅在Exynos设备上的四分之一屏幕上使用OpenGL绘图

代码。
我已经简化了代码,所以我可以在这里展示它。该任务是基本的:在其上绘制红色背景和黑色全屏矩形。
下面你可以看到我的绘图方法。我传递给着色器的数据不会影响这个简化情况下的任何内容。

// Use program 
glUseProgram(_shaderProgram); 
ERROR_STATUS 
//bind quad mesh buffer 
glBindBuffer(GL_ARRAY_BUFFER, _vbo); 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo); 
ERROR_STATUS 

//set attribs 
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0); 
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *) (2 * sizeof(float))); 
glEnableVertexAttribArray(0); 
glEnableVertexAttribArray(1); 
ERROR_STATUS 

// Clear background to red 
glClear(GL_COLOR_BUFFER_BIT); 
glClearColor(1, 0, 0, 1); 

glUniform2fv(_scaleUniform, 1, _eyes[0].scale.data); 
glUniform1f(_offsetUniform, _eyes[0].offset); 
glUniform1f(_offsetYUniform, _eyes[0].offsetY); 

BindTextures(TEX); 

// Draw 
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, NULL); 
ERROR_STATUS 

glDisableVertexAttribArray(0); 
glDisableVertexAttribArray(1); 
ERROR_STATUS 


这是我的ConfigChooser(grafika是很大的帮助这里)。

private static class ConfigChooser implements GLSurfaceView.EGLConfigChooser { 

    public ConfigChooser(int r, int g, int b, int a, int depth, int stencil) { 
     mRedSize = r; 
     mGreenSize = g; 
     mBlueSize = b; 
     mAlphaSize = a; 
     mDepthSize = depth; 
     mStencilSize = stencil; 
    } 

    /* This EGL config specification is used to specify 2.0 rendering. 
    * We use a minimum size of 4 bits for red/green/blue, but will 
    * perform actual matching in chooseConfig() below. 
    */ 
    private static int EGL_OPENGL_ES2_BIT = 4; 
    private static int[] s_configAttribs2 = 
    { 
     EGL10.EGL_RED_SIZE, 4, 
     EGL10.EGL_GREEN_SIZE, 4, 
     EGL10.EGL_BLUE_SIZE, 4, 
     EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 
     EGL10.EGL_NONE 
    }; 

    public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { 

     /* Get the number of minimally matching EGL configurations 
     */ 
     int[] num_config = new int[1]; 
     egl.eglChooseConfig(display, s_configAttribs2, null, 0, num_config); 

     int numConfigs = num_config[0]; 

     if (numConfigs <= 0) { 
      throw new IllegalArgumentException("No configs match configSpec"); 
     } 

     /* Allocate then read the array of minimally matching EGL configs 
     */ 
     EGLConfig[] configs = new EGLConfig[numConfigs]; 
     egl.eglChooseConfig(display, s_configAttribs2, configs, numConfigs, num_config); 

     if (DEBUG) { 
      printConfigs(egl, display, configs); 
     } 
     /* Now return the "best" one 
     */ 
     return chooseConfig(egl, display, configs); 
    } 

    public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, 
      EGLConfig[] configs) { 
     for(EGLConfig config : configs) { 
      int d = findConfigAttrib(egl, display, config, 
        EGL10.EGL_DEPTH_SIZE, 0); 
      int s = findConfigAttrib(egl, display, config, 
        EGL10.EGL_STENCIL_SIZE, 0); 

      // We need at least mDepthSize and mStencilSize bits 
      if (d < mDepthSize || s < mStencilSize) 
       continue; 

      // We want an *exact* match for red/green/blue/alpha 
      int r = findConfigAttrib(egl, display, config, 
        EGL10.EGL_RED_SIZE, 0); 
      int g = findConfigAttrib(egl, display, config, 
         EGL10.EGL_GREEN_SIZE, 0); 
      int b = findConfigAttrib(egl, display, config, 
         EGL10.EGL_BLUE_SIZE, 0); 
      int a = findConfigAttrib(egl, display, config, 
        EGL10.EGL_ALPHA_SIZE, 0); 

      if (r == mRedSize && g == mGreenSize && b == mBlueSize && a == mAlphaSize) 
       return config; 
     } 
     return null; 
    } 

    private int findConfigAttrib(EGL10 egl, EGLDisplay display, 
      EGLConfig config, int attribute, int defaultValue) { 

     if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) { 
      return mValue[0]; 
     } 
     return defaultValue; 
    } 

    private void printConfigs(EGL10 egl, EGLDisplay display, 
     EGLConfig[] configs) { 
     int numConfigs = configs.length; 
     Log.w(TAG, String.format("%d configurations", numConfigs)); 
     for (int i = 0; i < numConfigs; i++) { 
      Log.w(TAG, String.format("Configuration %d:\n", i)); 
      printConfig(egl, display, configs[i]); 
     } 
    } 

    private void printConfig(EGL10 egl, EGLDisplay display, 
      EGLConfig config) { 
     int[] attributes = { 
       EGL10.EGL_BUFFER_SIZE, 
       EGL10.EGL_ALPHA_SIZE, 
       EGL10.EGL_BLUE_SIZE, 
       EGL10.EGL_GREEN_SIZE, 
       EGL10.EGL_RED_SIZE, 
       EGL10.EGL_DEPTH_SIZE, 
       EGL10.EGL_STENCIL_SIZE, 
       EGL10.EGL_CONFIG_CAVEAT, 
       EGL10.EGL_CONFIG_ID, 
       EGL10.EGL_LEVEL, 
       EGL10.EGL_MAX_PBUFFER_HEIGHT, 
       EGL10.EGL_MAX_PBUFFER_PIXELS, 
       EGL10.EGL_MAX_PBUFFER_WIDTH, 
       EGL10.EGL_NATIVE_RENDERABLE, 
       EGL10.EGL_NATIVE_VISUAL_ID, 
       EGL10.EGL_NATIVE_VISUAL_TYPE, 
       0x3030, // EGL10.EGL_PRESERVED_RESOURCES, 
       EGL10.EGL_SAMPLES, 
       EGL10.EGL_SAMPLE_BUFFERS, 
       EGL10.EGL_SURFACE_TYPE, 
       EGL10.EGL_TRANSPARENT_TYPE, 
       EGL10.EGL_TRANSPARENT_RED_VALUE, 
       EGL10.EGL_TRANSPARENT_GREEN_VALUE, 
       EGL10.EGL_TRANSPARENT_BLUE_VALUE, 
       0x3039, // EGL10.EGL_BIND_TO_TEXTURE_RGB, 
       0x303A, // EGL10.EGL_BIND_TO_TEXTURE_RGBA, 
       0x303B, // EGL10.EGL_MIN_SWAP_INTERVAL, 
       0x303C, // EGL10.EGL_MAX_SWAP_INTERVAL, 
       EGL10.EGL_LUMINANCE_SIZE, 
       EGL10.EGL_ALPHA_MASK_SIZE, 
       EGL10.EGL_COLOR_BUFFER_TYPE, 
       EGL10.EGL_RENDERABLE_TYPE, 
       0x3042 // EGL10.EGL_CONFORMANT 
     }; 
     String[] names = { 
       "EGL_BUFFER_SIZE", 
       "EGL_ALPHA_SIZE", 
       "EGL_BLUE_SIZE", 
       "EGL_GREEN_SIZE", 
       "EGL_RED_SIZE", 
       "EGL_DEPTH_SIZE", 
       "EGL_STENCIL_SIZE", 
       "EGL_CONFIG_CAVEAT", 
       "EGL_CONFIG_ID", 
       "EGL_LEVEL", 
       "EGL_MAX_PBUFFER_HEIGHT", 
       "EGL_MAX_PBUFFER_PIXELS", 
       "EGL_MAX_PBUFFER_WIDTH", 
       "EGL_NATIVE_RENDERABLE", 
       "EGL_NATIVE_VISUAL_ID", 
       "EGL_NATIVE_VISUAL_TYPE", 
       "EGL_PRESERVED_RESOURCES", 
       "EGL_SAMPLES", 
       "EGL_SAMPLE_BUFFERS", 
       "EGL_SURFACE_TYPE", 
       "EGL_TRANSPARENT_TYPE", 
       "EGL_TRANSPARENT_RED_VALUE", 
       "EGL_TRANSPARENT_GREEN_VALUE", 
       "EGL_TRANSPARENT_BLUE_VALUE", 
       "EGL_BIND_TO_TEXTURE_RGB", 
       "EGL_BIND_TO_TEXTURE_RGBA", 
       "EGL_MIN_SWAP_INTERVAL", 
       "EGL_MAX_SWAP_INTERVAL", 
       "EGL_LUMINANCE_SIZE", 
       "EGL_ALPHA_MASK_SIZE", 
       "EGL_COLOR_BUFFER_TYPE", 
       "EGL_RENDERABLE_TYPE", 
       "EGL_CONFORMANT" 
     }; 
     int[] value = new int[1]; 
     for (int i = 0; i < attributes.length; i++) { 
      int attribute = attributes[i]; 
      String name = names[i]; 
      if (egl.eglGetConfigAttrib(display, config, attribute, value)) { 
       Log.w(TAG, String.format(" %s: %d\n", name, value[0])); 
      } else { 
       // Log.w(TAG, String.format(" %s: failed\n", name)); 
       while (egl.eglGetError() != EGL10.EGL_SUCCESS); 
      } 
     } 
    } 

    // Subclasses can adjust these values: 
    protected int mRedSize; 
    protected int mGreenSize; 
    protected int mBlueSize; 
    protected int mAlphaSize; 
    protected int mDepthSize; 
    protected int mStencilSize; 
    private int[] mValue = new int[1]; 
} 


setEGLConfigChooser(new ConfigChooser(5, 6, 5, 0, 0, 0))附上。
上下文工厂:

private static class ContextFactory implements GLSurfaceView.EGLContextFactory { 
    private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098; 
    public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) { 
     Log.w(TAG, "creating OpenGL ES 2.0 context"); 
     checkEglError("Before eglCreateContext", egl); 
     int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE }; 
     EGLContext context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list); 
     checkEglError("After eglCreateContext", egl); 
     return context; 
    } 

    public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) { 
     egl.eglDestroyContext(display, context); 
    } 
} 

如果必要的话,我可以提供我的代码的其他部分。

结果。
虽然通常,有效的结果仅仅是黑色的屏幕(黑色,空纹理重叠红色背景),在S4的Exynos屏幕看起来像这样(在右边的箭头仅仅是系统的按钮):

enter image description here

所以这里是问题。如何解决这个问题,所以应用程序显示不同的设备相同的东西?

+0

@RawN完成。 C++标签已经被提出,这就是我选择它的原因。 –

+1

可能是许多事情,可能在代码中未显示。例如,你是否确定顶点属性真的在位置0和1? –

+0

@ReetoKoradi谢谢!那就是这个问题 - 存储属性的位置,并使用它们的固定的属性的帮助。对不起,延迟回复,直到今天我都无法检查。 –

回答

0

感谢RetoKoradi的建议,我能够修复我的代码。
问题是我在着色器中使用了固定的制服位置(0和1)。我不知道为什么这对大多数开发者来说都有效,而且有些不适合。

因此,而不是像电话:

glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0); 
glEnableVertexAttribArray(0); 

现在,我使用:

_posAttribLocation = glGetAttribLocation(_shaderProgram, "a_position"); 

存储统一的位置后着色器程序已准备就绪,并使用它,而不是固定的一个:

glVertexAttribPointer(_posAttribLocation, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0); 
glEnableVertexAttribArray(_posAttribLocation);