2012-07-11 34 views
6

Tôi đã được gán để tạo cổng Java nguồn mở của Objective C GPUImage Framework này để có thể sử dụng trong ứng dụng Android. Tôi sẽ tái tạo nó một cách chặt chẽ nhất có thể, với tất cả các tên biến, tên hàm, v.v. giống nhau. Tôi đang ở giai đoạn đầu và tôi đang cố gắng kết nối GPUImageOpenGLESContext.h và GPUImageOpenGLESContext.m (Xin lỗi, sẽ cung cấp liên kết, nhưng với tư cách là người dùng mới, tôi không thể thêm bất kỳ liên kết nào khác).Xác định giới hạn kích thước họa tiết tối đa/tối trong Android OpenGLES

Tôi đang gặp khó khăn với những phương pháp

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

Dường như trong Objective C, bạn có thể chỉ đơn giản là gọi những phương pháp nhưng trong Java bạn không thể. Tôi đã thực hiện một số tìm kiếm và thấy rằng hầu hết mọi người đã nói để sử dụng GLSurfaceView, nhưng điều đó sẽ yêu cầu một hoạt động, đúng không? Tôi đã rất vui mừng khi tôi tìm thấy điều này Get Maximum OpenGL ES 2.0 Texture Size Limit on Android, nhưng phản ứng cho rằng mã sẽ không hoạt động.

Vì vậy, câu hỏi của tôi là, làm cách nào để có được kết cấu tối thiểu và tối đa trong một lớp không phải là hoạt động? Sử dụng GLSurfaceView?

Tôi cũng đánh giá cao bất kỳ đề xuất nào về cách thực hiện điều này. Tôi chưa bao giờ chuyển bất cứ thứ gì từ Objective C sang Java, vì vậy mọi lời khuyên sẽ được đánh giá cao!

Nếu nó sẽ là hữu ích, đây là mã hiện tại của tôi:

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

Khi bạn hoàn tất, hãy đảm bảo rằng bạn cho người này biết về điều đó: http://stackoverflow.com/questions/11405207/gpuimage-port-for-android –

+0

Bạn đã thử GLES20.glGetIntegerv (GLES20.GL_MAX_TEXTURE_SIZE, kích thước, 0); ? – cleuton

Trả lời

1

Tôi nhận ra đây là một bài cũ nhưng vấn đề của bạn là bạn đã không đúng cách khởi tạo các EGLContext.

Thông thường, bạn muốn sử dụng GLSurfaceView hoặc TextureView để thực sự bao gồm nội dung GL của bạn trong hệ thống phân cấp Xem. GLSurfaceView sẽ xử lý rất nhiều thứ cho bạn như tạo đúng EGLContext và quản lý một chuỗi kết xuất. TextureView yêu cầu công việc thủ công hơn một chút.

Một khi bạn có một bối cảnh thông qua một trong những phương tiện, bạn có thể sử dụng:

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

Giả sử bạn đã bị ràng buộc 2.0 API OpenGL ES. Trước tiên hãy chắc chắn rằng bạn đã tạo đúng EGLContext của mình và có thể thực hiện các cuộc gọi EGL và GLES, sau đó bạn sẽ có thể truy vấn kích thước họa tiết tối đa.

Bạn có thể xem bài Romain Guy về việc sử dụng một TextureView như bạn sẽ một GLSurfaceView để xem chi tiết để về quản lý EGLContext riêng của mình tại đây (https://groups.google.com/d/msg/android-developers/U5RXFGpAHPE/IqHeIeGXhr0J):

GLSurfaceView xử lý GL thiết lập cho bạn, mà TextureView sẽ không làm. Một TextureView có thể được sử dụng làm cửa sổ gốc khi bạn tạo một bề mặt EGL . Dưới đây là một ví dụ (phần thú vị là cuộc gọi đến 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; 
    } 
} 

Bạn có thể có cũng đã đi con đường NDK và rằng nhiều khả năng sẽ là một quá trình chuyển đổi đơn giản hơn từ Objective C.

+0

Xin cảm ơn!Thật không may, tôi không còn làm việc trong dự án này nữa, nhưng tôi đánh giá cao việc bạn dành thời gian trả lời câu hỏi. – Synergy807

Các vấn đề liên quan