2012-07-11 20 views
6

Zostałem przypisany do utworzenia portu Java o otwartym kodzie źródłowym tego Objective C GPUImage Framework, dzięki czemu można go używać w aplikacji na Androida. Mam go odtworzyć jak najdokładniej, z wszystkimi nazwami zmiennych, nazwami funkcji itd. Jestem na początkowych etapach i próbuję połączyć GPUImageOpenGLESContext.h i GPUImageOpenGLESContext.m (Przepraszam, będę udostępniać linki, ale jako nowi użytkownicy nie mogę dodać więcej linków).Określanie limitu rozmiaru tekstury maks./min. W systemie Android OpenGLES

Mam problem z tymi metodami

+ (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; 
} 

Wydaje się, że w Objective C, można po prostu zadzwonić do tych metod w Javie, ale nie możesz. Zrobiłem trochę wyszukiwania i okazało się, że większość ludzi mówi, że używają GLSurfaceView, ale to wymagałoby działania, prawda? Byłem bardzo podekscytowany, gdy znalazłem to Get Maximum OpenGL ES 2.0 Texture Size Limit on Android, ale odpowiedź twierdzi, że kod nie zadziałałby.

Moje pytanie brzmi: jak mogę uzyskać minimalną i maksymalną teksturę w klasie, która nie jest działaniem? Korzystanie z GLSurfaceView?

Chciałbym również docenić wszelkie sugestie, jak to przelecieć. Nigdy nie przenosiłem niczego z Objective C na Javę, więc każda rada byłaby doceniona!

Jeśli byłoby pomocne, tutaj jest mój bieżący kod:

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

Po zakończeniu, daj znać tej osobie: http://stackoverflow.com/questions/11405207/gpuimage-port-for-android –

+0

Czy próbowałeś GLES20.glGetIntegerv (GLES20.GL_MAX_TEXTURE_SIZE, rozmiar, 0); ? – cleuton

Odpowiedz

1

Zdaję sobie sprawę, że jest to stary post, ale problem jest to, że nie został prawidłowo zainicjowany w EGLContext.

Zazwyczaj użytkownik chce użyć interfejsu GLSurfaceView lub TextureView, aby faktycznie uwzględnić zawartość GL w hierarchii widoku. GLSurfaceView poradzi sobie z wieloma rzeczami, jak prawidłowe tworzenie EGLContext i zarządzanie wątkiem renderowania. TextureView wymaga nieco więcej pracy ręcznej.

Gdy masz kontekst poprzez którykolwiek z tych środków można użyć:

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

Zakładając, że związany z OpenGL ES 2.0 API. Najpierw upewnij się, że poprawnie stworzyłeś EGLContext i możesz wykonywać połączenia EGL i GLES, wtedy powinieneś być w stanie zapytać o maksymalny rozmiar tekstury.

Można zobaczyć posta Romain facet o użyciu TextureView jak by Państwo GLSurfaceView zobaczyć szczegółów i niuansów o zarządzaniu własną EGLContext tutaj (https://groups.google.com/d/msg/android-developers/U5RXFGpAHPE/IqHeIeGXhr0J):

GLSurfaceView obsługuje konfigurację GL dla ciebie, co TextureView nie zrobie. Podczas tworzenia powierzchni EGL można użyć okna TextureView jako okna macierzystego. Oto przykład (ciekawe jest to wezwanie do 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; 
    } 
} 

Można mieć również poszedł trasę NDK i że będzie prawdopodobnie bardziej proste przejście z Objective C

+0

Dzięki!Niestety, nie pracuję już nad tym projektem, ale doceniam, że poświęciłeś czas na odpowiedź na to pytanie. – Synergy807

Powiązane problemy