2012-07-11 157 views
6

我已被分配创建此Objective C GPUImage Framework的开放源代码Java端口,以便它可以在Android应用程序中使用。我会尽可能地重新创建它,所有变量名称,函数名称等都是一样的。我在开始阶段,我试图端口GPUImageOpenGLESContext.h和GPUImageOpenGLESContext.m(对不起,会提供链接,但作为一个新用户,我不能再添加任何链接)。确定Android OpenGLES中的最大/最小纹理大小限制

我在使用这些方法

+ (GLint)maximumTextureSizeForThisDevice; 
{ 
    GLint maxTextureSize; 
    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); 
    return maxTextureSize; 
} 

+ (GLint)maximumTextureUnitsForThisDevice; 
{ 
    GLint maxTextureUnits; 
    glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits); 
    return maxTextureUnits; 
} 

难度似乎在Objective C,你可以只是简单的调用这些方法,但在Java中,你不能。我做了一些搜索,发现大多数人都说使用GLSurfaceView,但那需要一个活动,是否正确?当我发现这个Get Maximum OpenGL ES 2.0 Texture Size Limit on Android时,我非常兴奋,但是回应声称代码不起作用。

所以,我的问题是,我怎样才能得到一个不是活动的类中的最小和最大纹理?使用GLSurfaceView?

我也很感激任何关于如何移植的建议。我从来没有将任何东西从Objective C移植到Java,所以任何建议都将不胜感激!

如果这将是有帮助的,这是我当前的代码:

public class GPUImageOpenGLESContext 
{ 
    private static GPUImageOpenGLESContext instance = null; 

    EGLContext context; 

    protected GPUImageOpenGLESContext() 
    { 
     // This is a protected empty method 
     // that exists only to prevent 
     // this singleton object from 
     // multiple instantiation 

     return; 
    } 

    public enum GPUImageRotationMode { 
      kGPUImageNoRotation, kGPUImageRotateLeft, kGPUImageRotateRight, kGPUImageFlipVertical, 
      kGPUImageFlipHorizontal, kGPUImageRotateRightFlipVertical, kGPUImageRotate180 
    } 

    public GPUImageRotationMode GPUImageRotationSwapsWidthAndHeight(GPUImageRotationMode rotation) 
    { 
     // TODO: Implement GPUImageRotationSwapsWidthAndHeight macro as method 
     //rotation = ((rotation) == kGPUImageRotateLeft || (rotation) == kGPUImageRotateRight || (rotation) == kGPUImageRotateRightFlipVertical) 
     return rotation; 
    } 

    public static GPUImageOpenGLESContext sharedImageProcessingOpenGLESContext() 
    { 
     if (instance == null) 
     { 
      instance = new GPUImageOpenGLESContext(); 
     } 
     return instance; 
    } 

    public static void useImageProcessingContext() 
    { 
     EGLContext imageProcessingContext = GPUImageOpenGLESContext.sharedImageProcessingOpenGLESContext().context; 
     if (EGLContext.getEGL() != imageProcessingContext) 
     { 
      // In Objective C, this call would be here: 
      // [EAGLContext setCurrentContext:imageProcessingContext] 

      // Cannot figure out how to handle this. For now, throws an exception. 
      throw new RuntimeException("useImageProcessingContext not equal to EGLContext"); 
     } 

     return; 
    } 

    public static int maximumTextureSizeForThisDevice() 
    { 
     int[] maxTextureSize = new int[1]; 

     // TODO: See if you can use gl. without an activity 
     //GL10 gl = new GL10(); 
     //EGL gl = EGLContext.getEGL(); 

     //gl.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, maxTextureSize, 0); 

     return maxTextureSize[0]; 
    } 

    public static int maximumTextureUnitsForThisDevice() 
    { 
     // TODO: Implement maximumTextureUnitsForThisDevice(); 
     return -1; 
    } 

    public static CGSize sizeThatFitsWithinATextureForSize(CGSize inputSize) 
    { 
     int maxTextureSize = maximumTextureSizeForThisDevice(); 

     if ((inputSize.width < maxTextureSize) && (inputSize.height < maxTextureSize)) 
     { 
      return inputSize; 
     } 

     CGSize adjustedSize = new CGSize(); 
     if (inputSize.width > inputSize.height) 
     { 
      adjustedSize.width = (float)maxTextureSize; 
      adjustedSize.height = ((float)maxTextureSize/inputSize.width) * inputSize.height; 
     } 
     else 
     { 
      adjustedSize.height = (float)maxTextureSize; 
      adjustedSize.width = ((float)maxTextureSize/inputSize.height) * inputSize.width; 
     } 

     return adjustedSize; 
    } 

    public EGLContext getContext() 
    { 
     if (context == null) 
     { 
      // TODO: Implement getContext() 
     } 
    } 

    public interface GPUImageInput 
    { 
     public void newFrameReadyAtTime(Time frameTime); 
     public void setInputTextureAtIndex(int newInputTexture, int textureIndex); 
     public int nextAvailableTextureIndex(); 
     public void setInputSizeAtIndex(CGSize newSize, int textureIndex); 
     public void setInputRotationAtIndex(GPUImageRotationMode newInputRotation, int textureIndex); 
     public CGSize maximumOutputSize(); 
     public void endProcessing(); 
     public boolean shouldIgnoreUpdatesToThisTarget(); 
    } 
} 
+0

当你完成后,请确保你让这个人知道它:http://stackoverflow.com/questions/11405207/gpuimage-port-for-android – 2012-07-12 21:56:02

+0

你试过GLES20.glGetIntegerv(GLES20.GL_MAX_TEXTURE_SIZE,尺寸, 0); ? – cleuton 2013-02-01 17:43:12

回答

1

我意识到这是一个老的文章,但你的问题是你没有正确初始化EGLContext。

通常,您希望使用GLSurfaceView或TextureView将GL内容实际包含在View层次结构中。 GLSurfaceView将为您处理很多事情,比如正确创建EGLContext和管理渲染线程。 TextureView需要更多的手工工作。

一旦你有通过任一这些装置的情况下,可以使用:

GLES20.glGetIntegerv(GLES20.GL_MAX_TEXTURE_SIZE, size, 0); 

假设你已经结合了OpenGL ES 2.0 API。首先确保你已经正确创建了EGLContext并且可以执行EGL和GLES调用,那么你应该能够查询最大纹理尺寸。

你可以看到罗曼盖伊的关于使用TextureView后,你会一个GLSurfaceView到这里看到管理自己的EGLContext(https://groups.google.com/d/msg/android-developers/U5RXFGpAHPE/IqHeIeGXhr0J)的细节问题细节:

GLSurfaceView处理GL设置为你,这TextureView不行。 当您创建EGL 表面时,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; 
    } 
} 

你可以有也去了NDK的路线和很可能会从目标C.

更直接过渡
+0

谢谢!不幸的是,我不再从事这个项目,但我感谢您花时间回答这个问题。 – Synergy807 2013-08-20 20:26:11

相关问题