2011-11-22 8 views
21

TextureView documentation बताता है कि इसका उपयोग OpenGL सामग्री को प्रस्तुत करने के लिए किया जा सकता है।Android Ice Cream Sandwich में TextureView के साथ GLSurfaceView को कैसे बदलें?

blog post घोषणा TextureView में, यह कहा गया है:

एक TextureView बस के रूप में आसानी से अपने आवेदन में एक ओपन दृश्य एम्बेड करने के लिए इस्तेमाल किया जा सकता। एंड्रॉइड 4.0 के रूप में, eglCreateWindowSurface() को SurfaceTexture ऑब्जेक्ट में प्रस्तुत करने के लिए उपयोग किया जा सकता है।

कौन सा मतलब है कि GLSurfaceView के बजाय TextureView उपयोग करने के लिए लगता है, एक सब EGL सेटअप खुद को क्या करना है और EGLContext और सूत्रण का प्रबंधन (के बाद से GLSurfaceView एक GLThread बनाए रखता है) करना होगा। एंड्रॉइड 4.0 एसडीके में कोई नमूना कोड प्रतीत नहीं होता है जो दर्शाता है कि कैसे "TextureView को ओपनजीएल दृश्य" एम्बेड करने के लिए आसानी से उपयोग किया जा सकता है। TextureView कैमरा पूर्वावलोकन (setPreviewTexture) और MediaPlayer (setSurface) पर अधिक स्पष्ट रूप से प्लग करने लगता है।

क्या GLSurfaceView.setEGLWindowSurfaceFactory का उपयोग कर TextureView के संयोजन के साथ GLSurfaceView का उपयोग करना संभव है ताकि इसे TextureView के भूतलटेक्चर में प्रस्तुत किया जा सके?

फिर, कुछ नमूना कोड होने पर यह अच्छा होगा।

+3

Fwiw, विभिन्न उदाहरणों ग्राफिक्स में पाया जा सकता (https://github.com/google/grafika)। अतिरिक्त पृष्ठभूमि के लिए, https://source.android.com/devices/graphics.html देखें। – fadden

+0

यह इसके बारे में एक महान चर्चा पोस्ट है: https://groups.google.com/forum/m/#!topic/android-developers/U5RXFGpAHPE –

उत्तर

1

एक मॉडरेटर नष्ट कर दिया इस जवाब तो भावी पीढ़ी के लिए इसे वापस जोड़ने:

देखें रोमेन लड़का के जवाब (नवंबर 23 वें 2011) एंड्रॉयड-देव गूगल समूह से:

http://groups.google.com/group/android-developers/browse_thread/thread/539457146a401cf1 (नजर आता: http://grokbase.com/t/gg/android-developers/11bqmgb7sw/how-to-replace-glsurfaceview-with-textureview-in-android-ice-cream-sandwich)

GLSurfaceView आपके लिए जीएल सेटअप संभालता है, जो TextureView नहीं करेगा। जब आप एक ईजीएल सतह बनाते हैं तो एक TextureView को देशी विंडो के रूप में उपयोग किया जा सकता है। यहाँ एक उदाहरण है (दिलचस्प हिस्सा करने के लिए कॉल eglCreateWindowSurface() है):

@Override 
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { 
    mRenderThread = new RenderThread(getResources(), surface); 
    mRenderThread.start(); 
} 

private static class RenderThread extends Thread { 
    private static final String LOG_TAG = "GLTextureView"; 

    static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; 
    static final int EGL_OPENGL_ES2_BIT = 4; 

    private volatile boolean mFinished; 

    private final Resources mResources; 
    private final SurfaceTexture mSurface; 

    private EGL10 mEgl; 
    private EGLDisplay mEglDisplay; 
    private EGLConfig mEglConfig; 
    private EGLContext mEglContext; 
    private EGLSurface mEglSurface; 
    private GL mGL; 

    RenderThread(Resources resources, SurfaceTexture surface) { 
     mResources = resources; 
     mSurface = surface; 
    } 

    private static final String sSimpleVS = 
      "attribute vec4 position;\n" + 
      "attribute vec2 texCoords;\n" + 
      "varying vec2 outTexCoords;\n" + 
      "\nvoid main(void) {\n" + 
      " outTexCoords = texCoords;\n" + 
      " gl_Position = position;\n" + 
      "}\n\n"; 
    private static final String sSimpleFS = 
      "precision mediump float;\n\n" + 
      "varying vec2 outTexCoords;\n" + 
      "uniform sampler2D texture;\n" + 
      "\nvoid main(void) {\n" + 
      " gl_FragColor = texture2D(texture, outTexCoords);\n" + 
      "}\n\n"; 

    private static final int FLOAT_SIZE_BYTES = 4; 
    private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES; 
    private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0; 
    private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3; 
    private final float[] mTriangleVerticesData = { 
      // X, Y, Z, U, V 
      -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 
       1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 
      -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 
       1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 
    }; 

    @Override 
    public void run() { 
     initGL(); 

     FloatBuffer triangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer(); 
     triangleVertices.put(mTriangleVerticesData).position(0); 

     int texture = loadTexture(R.drawable.large_photo); 
     int program = buildProgram(sSimpleVS, sSimpleFS); 

     int attribPosition = glGetAttribLocation(program, "position"); 
     checkGlError(); 

     int attribTexCoords = glGetAttribLocation(program, "texCoords"); 
     checkGlError(); 

     int uniformTexture = glGetUniformLocation(program, "texture"); 
     checkGlError(); 

     glBindTexture(GL_TEXTURE_2D, texture); 
     checkGlError(); 

     glUseProgram(program); 
     checkGlError(); 

     glEnableVertexAttribArray(attribPosition); 
     checkGlError(); 

     glEnableVertexAttribArray(attribTexCoords); 
     checkGlError(); 

     glUniform1i(uniformTexture, texture); 
     checkGlError(); 

     while (!mFinished) { 
      checkCurrent(); 

      glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 
      checkGlError(); 

      glClear(GL_COLOR_BUFFER_BIT); 
      checkGlError(); 

      // drawQuad 

      triangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET); 
      glVertexAttribPointer(attribPosition, 3, GL_FLOAT, false, 
        TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices); 

      triangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET); 
      glVertexAttribPointer(attribTexCoords, 3, GL_FLOAT, false, 
        TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices); 

      glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 

      if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) { 
       throw new RuntimeException("Cannot swap buffers"); 
      } 
      checkEglError(); 

      try { 
       Thread.sleep(2000); 
      } catch (InterruptedException e) { 
       // Ignore 
      } 
     } 

     finishGL(); 
    } 

    private int loadTexture(int resource) { 
     int[] textures = new int[1]; 

     glActiveTexture(GL_TEXTURE0); 
     glGenTextures(1, textures, 0); 
     checkGlError(); 

     int texture = textures[0]; 
     glBindTexture(GL_TEXTURE_2D, texture); 
     checkGlError(); 

     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 

     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 

     Bitmap bitmap = BitmapFactory.decodeResource(mResources, resource); 

     GLUtils.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap, GL_UNSIGNED_BYTE, 0); 
     checkGlError(); 

     bitmap.recycle(); 

     return texture; 
    } 

    private int buildProgram(String vertex, String fragment) { 
     int vertexShader = buildShader(vertex, GL_VERTEX_SHADER); 
     if (vertexShader == 0) return 0; 

     int fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER); 
     if (fragmentShader == 0) return 0; 

     int program = glCreateProgram(); 
     glAttachShader(program, vertexShader); 
     checkGlError(); 

     glAttachShader(program, fragmentShader); 
     checkGlError(); 

     glLinkProgram(program); 
     checkGlError(); 

     int[] status = new int[1]; 
     glGetProgramiv(program, GL_LINK_STATUS, status, 0); 
     if (status[0] != GL_TRUE) { 
      String error = glGetProgramInfoLog(program); 
      Log.d(LOG_TAG, "Error while linking program:\n" + error); 
      glDeleteShader(vertexShader); 
      glDeleteShader(fragmentShader); 
      glDeleteProgram(program); 
      return 0; 
     } 

     return program; 
    } 

    private int buildShader(String source, int type) { 
     int shader = glCreateShader(type); 

     glShaderSource(shader, source); 
     checkGlError(); 

     glCompileShader(shader); 
     checkGlError(); 

     int[] status = new int[1]; 
     glGetShaderiv(shader, GL_COMPILE_STATUS, status, 0); 
     if (status[0] != GL_TRUE) { 
      String error = glGetShaderInfoLog(shader); 
      Log.d(LOG_TAG, "Error while compiling shader:\n" + error); 
      glDeleteShader(shader); 
      return 0; 
     } 

     return shader; 
    } 

    private void checkEglError() { 
     int error = mEgl.eglGetError(); 
     if (error != EGL10.EGL_SUCCESS) { 
      Log.w(LOG_TAG, "EGL error = 0x" + Integer.toHexString(error)); 
     } 
    } 

    private void checkGlError() { 
     int error = glGetError(); 
     if (error != GL_NO_ERROR) { 
      Log.w(LOG_TAG, "GL error = 0x" + Integer.toHexString(error)); 
     } 
    } 

    private void finishGL() { 
     mEgl.eglDestroyContext(mEglDisplay, mEglContext); 
     mEgl.eglDestroySurface(mEglDisplay, mEglSurface); 
    } 

    private void checkCurrent() { 
     if (!mEglContext.equals(mEgl.eglGetCurrentContext()) || 

     !mEglSurface.equals(mEgl.eglGetCurrentSurface(EGL10.EGL_DRAW))) { 
      if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { 
       throw new RuntimeException("eglMakeCurrent failed " + GLUtils.getEGLErrorString(mEgl.eglGetError())); 
      } 
     } 
    } 

    private void initGL() { 
     mEgl = (EGL10) EGLContext.getEGL(); 

     mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); 
     if (mEglDisplay == EGL10.EGL_NO_DISPLAY) { 
      throw new RuntimeException("eglGetDisplay failed " 
        + GLUtils.getEGLErrorString(mEgl.eglGetError())); 
     } 

     int[] version = new int[2]; 
     if (!mEgl.eglInitialize(mEglDisplay, version)) { 
      throw new RuntimeException("eglInitialize failed " + 
        GLUtils.getEGLErrorString(mEgl.eglGetError())); 
     } 

     mEglConfig = chooseEglConfig(); 
     if (mEglConfig == null) { 
      throw new RuntimeException("eglConfig not initialized"); 
     } 

     mEglContext = createContext(mEgl, mEglDisplay, mEglConfig); 

     mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, mSurface, null); 

     if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) 
     { 
      int error = mEgl.eglGetError(); 
      if (error == EGL10.EGL_BAD_NATIVE_WINDOW) { 
       Log.e(LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW."); 
       return; 
      } 
      throw new RuntimeException("createWindowSurface failed " 
        + GLUtils.getEGLErrorString(error)); 
     } 

     if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { 
      throw new RuntimeException("eglMakeCurrent failed " 
        + GLUtils.getEGLErrorString(mEgl.eglGetError())); 
     } 

     mGL = mEglContext.getGL(); 
    } 


    EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) { 
     int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE }; 
     return egl.eglCreateContext(eglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list); 
    } 

    private EGLConfig chooseEglConfig() { 
     int[] configsCount = new int[1]; 
     EGLConfig[] configs = new EGLConfig[1]; 
     int[] configSpec = getConfig(); 
     if (!mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, configsCount)) { 
      throw new IllegalArgumentException("eglChooseConfig failed " + 
        GLUtils.getEGLErrorString(mEgl.eglGetError())); 
     } else if (configsCount[0] > 0) { 
      return configs[0]; 
     } 
     return null; 
    } 

    private int[] getConfig() { 
     return new int[] { 
       EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 
       EGL10.EGL_RED_SIZE, 8, 
       EGL10.EGL_GREEN_SIZE, 8, 
       EGL10.EGL_BLUE_SIZE, 8, 
       EGL10.EGL_ALPHA_SIZE, 8, 
       EGL10.EGL_DEPTH_SIZE, 0, 
       EGL10.EGL_STENCIL_SIZE, 0, 
       EGL10.EGL_NONE 
     }; 
    } 

    void finish() { 
     mFinished = true; 
    } 
} 
1

के रूप में पहले उल्लेख किया @fadden, आप यहाँ TextureView का उपयोग करने का एक अच्छा उदाहरण है: https://github.com/google/grafika/blob/master/src/com/android/grafika/TextureViewGLActivity.java

GLSurfaceView और TextureView परस्पर अनन्य हैं। मुझे एक ही समय में दोनों का उपयोग करने का मामला नहीं दिखता है।

संबंधित मुद्दे