2016-09-16 60 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);