Android GPUImage

1.文章介紹

不甘落后狮辽,就努力充實(shí)自己。
根據(jù)自己的學(xué)習(xí)計(jì)劃巢寡,最近看了看Android平臺(tái)上的圖片處理相關(guān)構(gòu)架喉脖。發(fā)現(xiàn)無(wú)論是glide-transformations,還是Picasso Transformations抑月,Fresco Processors等主流的開(kāi)源項(xiàng)目都基于GPUImage實(shí)現(xiàn)圖片特效的渲染树叽。借此機(jī)會(huì)自己也記錄下部分學(xué)習(xí)內(nèi)容。

2.干貨

一.核心類

1.GPUImage.java
Android OpenGLES核心實(shí)現(xiàn)類谦絮,配合GLSurfaceView和GPUImageFilter實(shí)現(xiàn)渲染题诵。

    /**
     * Sets the GLSurfaceView which will display the preview.
     *
     * @param view the GLSurfaceView
     */
    public void setGLSurfaceView(final GLSurfaceView view) {
        mGlSurfaceView = view;
        mGlSurfaceView.setEGLContextClientVersion(2);
        mGlSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
        mGlSurfaceView.getHolder().setFormat(PixelFormat.RGBA_8888);
        mGlSurfaceView.setRenderer(mRenderer);
        mGlSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
        mGlSurfaceView.requestRender();
    }

    /**
     * Sets the filter which should be applied to the image which was (or will
     * be) set by setImage(...).
     *
     * @param filter the new filter
     */
    public void setFilter(final GPUImageFilter filter) {
        mFilter = filter;
        mRenderer.setFilter(mFilter);
        requestRender();
    }

    /**
     * Request the preview to be rendered again.
     */
    public void requestRender() {
        if (mGlSurfaceView != null) {
            mGlSurfaceView.requestRender();
        }
    }

比如渲染一張圖片:

/**
     * Sets the image on which the filter should be applied.
     *
     * @param bitmap the new image
     */
    public void setImage(final Bitmap bitmap) {
        mCurrentBitmap = bitmap;
        mRenderer.setImageBitmap(bitmap, false);
        requestRender();
    }

2.GPUImageView.java

對(duì)GPUImage的進(jìn)一步封裝,實(shí)際上是一個(gè)包含了GPUImageGLSurfaceView的FrameLayout层皱,使用時(shí)通過(guò)配合使用GPUImageFilter調(diào)整參數(shù)即可性锭。
這里釋放下程序員天賦技能(搬磚),以下是ActivityGallery.java的源碼叫胖,通過(guò)GPUImageView和Filter直接實(shí)現(xiàn)渲染效果:

/* 
 * Copyright (C) 2012 CyberAgent 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 * http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License. 
 */ 
 
package jp.co.cyberagent.android.gpuimage.sample.activity; 
 
import jp.co.cyberagent.android.gpuimage.GPUImageFilter; 
import jp.co.cyberagent.android.gpuimage.GPUImageView; 
import jp.co.cyberagent.android.gpuimage.GPUImageView.OnPictureSavedListener; 
import jp.co.cyberagent.android.gpuimage.sample.GPUImageFilterTools; 
import jp.co.cyberagent.android.gpuimage.sample.GPUImageFilterTools.FilterAdjuster; 
import jp.co.cyberagent.android.gpuimage.sample.GPUImageFilterTools.OnGpuImageFilterChosenListener; 
import jp.co.cyberagent.android.gpuimage.sample.R; 
import android.app.Activity; 
import android.content.Intent; 
import android.net.Uri; 
import android.os.Bundle; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.SeekBar; 
import android.widget.SeekBar.OnSeekBarChangeListener; 
import android.widget.Toast; 
 
public class ActivityGallery extends Activity implements OnSeekBarChangeListener, 
        OnClickListener, OnPictureSavedListener { 
 
    private static final int REQUEST_PICK_IMAGE = 1; 
    private GPUImageFilter mFilter; 
    private FilterAdjuster mFilterAdjuster; 
    private GPUImageView mGPUImageView; 
 
    @Override 
    public void onCreate(final Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_gallery); 
        ((SeekBar) findViewById(R.id.seekBar)).setOnSeekBarChangeListener(this); 
        findViewById(R.id.button_choose_filter).setOnClickListener(this); 
        findViewById(R.id.button_save).setOnClickListener(this); 
 
        mGPUImageView = (GPUImageView) findViewById(R.id.gpuimage); 
 
        Intent photoPickerIntent = new Intent(Intent.ACTION_PICK); 
        photoPickerIntent.setType("image/*"); 
        startActivityForResult(photoPickerIntent, REQUEST_PICK_IMAGE); 
    } 
 
    @Override 
    protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) { 
        switch (requestCode) { 
            case REQUEST_PICK_IMAGE: 
                if (resultCode == RESULT_OK) { 
                    handleImage(data.getData()); 
                } else { 
                    finish(); 
                } 
                break; 
 
            default: 
                super.onActivityResult(requestCode, resultCode, data); 
                break; 
        } 
    } 
 
    @Override 
    public void onClick(final View v) { 
        switch (v.getId()) { 
            case R.id.button_choose_filter: 
                GPUImageFilterTools.showDialog(this, new OnGpuImageFilterChosenListener() { 
 
                    @Override 
                    public void onGpuImageFilterChosenListener(final GPUImageFilter filter) { 
                        switchFilterTo(filter); 
                        mGPUImageView.requestRender(); 
                    } 
 
                }); 
                break; 
            case R.id.button_save: 
                saveImage(); 
                break; 
 
            default: 
                break; 
        } 
 
    } 
 
    @Override 
    public void onPictureSaved(final Uri uri) { 
        Toast.makeText(this, "Saved: " + uri.toString(), Toast.LENGTH_SHORT).show(); 
    } 
 
    private void saveImage() { 
        String fileName = System.currentTimeMillis() + ".jpg"; 
        mGPUImageView.saveToPictures("GPUImage", fileName, this); 
//        mGPUImageView.saveToPictures("GPUImage", fileName, 1600, 1600, this); 
    } 
 
    private void switchFilterTo(final GPUImageFilter filter) { 
        if (mFilter == null 
                || (filter != null && !mFilter.getClass().equals(filter.getClass()))) { 
            mFilter = filter; 
            mGPUImageView.setFilter(mFilter); 
            mFilterAdjuster = new FilterAdjuster(mFilter); 
 
            findViewById(R.id.seekBar).setVisibility( 
                    mFilterAdjuster.canAdjust() ? View.VISIBLE : View.GONE); 
        } 
    } 
 
    @Override 
    public void onProgressChanged(final SeekBar seekBar, final int progress, final boolean fromUser) { 
        if (mFilterAdjuster != null) { 
            mFilterAdjuster.adjust(progress); 
        } 
        mGPUImageView.requestRender(); 
    } 
 
    @Override 
    public void onStartTrackingTouch(final SeekBar seekBar) { 
    } 
 
    @Override 
    public void onStopTrackingTouch(final SeekBar seekBar) { 
    } 
 
    private void handleImage(final Uri selectedImage) { 
        mGPUImageView.setImage(selectedImage); 
    } 
} 

3.GPUImageFilter.java

GPUImageFilter是用來(lái)配置OpenGLES渲染的主類草冈,所謂VERTEX,就是頂點(diǎn)瓮增,F(xiàn)RAGMENT就是片元怎棱,這都涉及到OpenGL的渲染相關(guān)知識(shí),多少需要了解绷跑。

   public static final String NO_FILTER_VERTEX_SHADER = "" +
            "attribute vec4 position;\n" +
            "attribute vec4 inputTextureCoordinate;\n" +
            " \n" +
            "varying vec2 textureCoordinate;\n" +
            " \n" +
            "void main()\n" +
            "{\n" +
            "    gl_Position = position;\n" +
            "    textureCoordinate = inputTextureCoordinate.xy;\n" +
            "}";
    public static final String NO_FILTER_FRAGMENT_SHADER = "" +
            "varying highp vec2 textureCoordinate;\n" +
            " \n" +
            "uniform sampler2D inputImageTexture;\n" +
            " \n" +
            "void main()\n" +
            "{\n" +
            "     gl_FragColor = texture2D(inputImageTexture, textureCoordinate);\n" +
            "}";

    public GPUImageFilter() {
        this(NO_FILTER_VERTEX_SHADER, NO_FILTER_FRAGMENT_SHADER);
    }

    public GPUImageFilter(final String vertexShader, final String fragmentShader) {
        mRunOnDraw = new LinkedList<Runnable>();
        mVertexShader = vertexShader;
        mFragmentShader = fragmentShader;
    }

    public final void init() {
        onInit();
        mIsInitialized = true;
        onInitialized();
    }

    public void onInit() {
        mGLProgId = OpenGlUtils.loadProgram(mVertexShader, mFragmentShader);
        mGLAttribPosition = GLES20.glGetAttribLocation(mGLProgId, "position");
        mGLUniformTexture = GLES20.glGetUniformLocation(mGLProgId, "inputImageTexture");
        mGLAttribTextureCoordinate = GLES20.glGetAttribLocation(mGLProgId,
                "inputTextureCoordinate");
        mIsInitialized = true;
    }

上面一段代碼是對(duì)OpenGL不配置任何效果拳恋,即按原始圖片效果渲染圖片;若需要自定義渲染效果你踩,可以根據(jù)JAVA的繼承特性擴(kuò)展一個(gè)繼承于GPUImageFilter的子類即可诅岩,因此在GPUImage的源碼中你可以看到很多類似GPUImageAlphaBlendFilter、GPUImageBoxBlurFilter等渲染特效的子類带膜。

4.GPUImageRenderer.java

GPUImageRenderer是接口類Renderer的實(shí)現(xiàn)吩谦,在OpenGLES中如何理解Renderer呢?其實(shí)Renderer是GLSurfaceView(繼承于SurfaceView)定義的一個(gè)接口類膝藕,作用就是實(shí)現(xiàn)事件回調(diào)

    public interface Renderer { 
        /** 
         * Called when the surface is created or recreated. 
         * <p> 
         * Called when the rendering thread 
         * starts and whenever the EGL context is lost. The EGL context will typically 
         * be lost when the Android device awakes after going to sleep. 
         * <p> 
         * Since this method is called at the beginning of rendering, as well as 
         * every time the EGL context is lost, this method is a convenient place to put 
         * code to create resources that need to be created when the rendering 
         * starts, and that need to be recreated when the EGL context is lost. 
         * Textures are an example of a resource that you might want to create 
         * here. 
         * <p> 
         * Note that when the EGL context is lost, all OpenGL resources associated 
         * with that context will be automatically deleted. You do not need to call 
         * the corresponding "glDelete" methods such as glDeleteTextures to 
         * manually delete these lost resources. 
         * <p> 
         * @param gl the GL interface. Use <code>instanceof</code> to 
         * test if the interface supports GL11 or higher interfaces. 
         * @param config the EGLConfig of the created surface. Can be used 
         * to create matching pbuffers. 
         */ 
        void onSurfaceCreated(GL10 gl, EGLConfig config); 
 
        /** 
         * Called when the surface changed size. 
         * <p> 
         * Called after the surface is created and whenever 
         * the OpenGL ES surface size changes. 
         * <p> 
         * Typically you will set your viewport here. If your camera 
         * is fixed then you could also set your projection matrix here: 
         * <pre class="prettyprint"> 
         * void onSurfaceChanged(GL10 gl, int width, int height) { 
         *     gl.glViewport(0, 0, width, height); 
         *     // for a fixed camera, set the projection too 
         *     float ratio = (float) width / height; 
         *     gl.glMatrixMode(GL10.GL_PROJECTION); 
         *     gl.glLoadIdentity(); 
         *     gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10); 
         * } 
         * </pre> 
         * @param gl the GL interface. Use <code>instanceof</code> to 
         * test if the interface supports GL11 or higher interfaces. 
         * @param width 
         * @param height 
         */ 
        void onSurfaceChanged(GL10 gl, int width, int height); 
 
        /** 
         * Called to draw the current frame. 
         * <p> 
         * This method is responsible for drawing the current frame. 
         * <p> 
         * The implementation of this method typically looks like this: 
         * <pre class="prettyprint"> 
         * void onDrawFrame(GL10 gl) { 
         *     gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); 
         *     //... other gl calls to render the scene ... 
         * } 
         * </pre> 
         * @param gl the GL interface. Use <code>instanceof</code> to 
         * test if the interface supports GL11 or higher interfaces. 
         */ 
        void onDrawFrame(GL10 gl); 
    }

5.GPUImageNativeLibrary.java

僅僅是對(duì)YUV和ARGB數(shù)據(jù)互轉(zhuǎn)進(jìn)行的封裝式廷,應(yīng)該是考慮C代碼的效率會(huì)更高。

package jp.co.cyberagent.android.gpuimage;

public class GPUImageNativeLibrary {
    static {
        System.loadLibrary("gpuimage-library");
    }

    public static native void YUVtoRBGA(byte[] yuv, int width, int height, int[] out);

    public static native void YUVtoARBG(byte[] yuv, int width, int height, int[] out);
}
/*
*yuv-decoder.c
*/
#include <jni.h> 
#include <android/log.h> 
 
JNIEXPORT void JNICALL Java_jp_co_cyberagent_android_gpuimage_GPUImageNativeLibrary_YUVtoRBGA(JNIEnv * env, jobject obj, jbyteArray yuv420sp, jint width, jint height, jintArray rgbOut) 
{ 
    int             sz; 
    int             i; 
    int             j; 
    int             Y; 
    int             Cr = 0; 
    int             Cb = 0; 
    int             pixPtr = 0; 
    int             jDiv2 = 0; 
    int             R = 0; 
    int             G = 0; 
    int             B = 0; 
    int             cOff; 
    int w = width; 
    int h = height; 
    sz = w * h; 
 
    jint *rgbData = (jint*) ((*env)->GetPrimitiveArrayCritical(env, rgbOut, 0)); 
    jbyte* yuv = (jbyte*) (*env)->GetPrimitiveArrayCritical(env, yuv420sp, 0); 
 
    for(j = 0; j < h; j++) { 
             pixPtr = j * w; 
             jDiv2 = j >> 1; 
             for(i = 0; i < w; i++) { 
                     Y = yuv[pixPtr]; 
                     if(Y < 0) Y += 255; 
                     if((i & 0x1) != 1) { 
                             cOff = sz + jDiv2 * w + (i >> 1) * 2; 
                             Cb = yuv[cOff]; 
                             if(Cb < 0) Cb += 127; else Cb -= 128; 
                             Cr = yuv[cOff + 1]; 
                             if(Cr < 0) Cr += 127; else Cr -= 128; 
                     } 
                      
                     //ITU-R BT.601 conversion 
                     // 
                     //R = 1.164*(Y-16) + 2.018*(Cr-128); 
                     //G = 1.164*(Y-16) - 0.813*(Cb-128) - 0.391*(Cr-128); 
                     //B = 1.164*(Y-16) + 1.596*(Cb-128); 
                     // 
                     Y = Y + (Y >> 3) + (Y >> 5) + (Y >> 7); 
                     R = Y + (Cr << 1) + (Cr >> 6); 
                     if(R < 0) R = 0; else if(R > 255) R = 255; 
                     G = Y - Cb + (Cb >> 3) + (Cb >> 4) - (Cr >> 1) + (Cr >> 3); 
                     if(G < 0) G = 0; else if(G > 255) G = 255; 
                     B = Y + Cb + (Cb >> 1) + (Cb >> 4) + (Cb >> 5); 
                     if(B < 0) B = 0; else if(B > 255) B = 255; 
                     rgbData[pixPtr++] = 0xff000000 + (R << 16) + (G << 8) + B; 
             } 
    } 
 
    (*env)->ReleasePrimitiveArrayCritical(env, rgbOut, rgbData, 0); 
    (*env)->ReleasePrimitiveArrayCritical(env, yuv420sp, yuv, 0); 
} 
 
JNIEXPORT void JNICALL Java_jp_co_cyberagent_android_gpuimage_GPUImageNativeLibrary_YUVtoARBG(JNIEnv * env, jobject obj, jbyteArray yuv420sp, jint width, jint height, jintArray rgbOut) 
{ 
    int             sz; 
    int             i; 
    int             j; 
    int             Y; 
    int             Cr = 0; 
    int             Cb = 0; 
    int             pixPtr = 0; 
    int             jDiv2 = 0; 
    int             R = 0; 
    int             G = 0; 
    int             B = 0; 
    int             cOff; 
    int w = width; 
    int h = height; 
    sz = w * h; 
 
    jint *rgbData = (jint*) ((*env)->GetPrimitiveArrayCritical(env, rgbOut, 0)); 
    jbyte* yuv = (jbyte*) (*env)->GetPrimitiveArrayCritical(env, yuv420sp, 0); 
 
    for(j = 0; j < h; j++) { 
             pixPtr = j * w; 
             jDiv2 = j >> 1; 
             for(i = 0; i < w; i++) { 
                     Y = yuv[pixPtr]; 
                     if(Y < 0) Y += 255; 
                     if((i & 0x1) != 1) { 
                             cOff = sz + jDiv2 * w + (i >> 1) * 2; 
                             Cb = yuv[cOff]; 
                             if(Cb < 0) Cb += 127; else Cb -= 128; 
                             Cr = yuv[cOff + 1]; 
                             if(Cr < 0) Cr += 127; else Cr -= 128; 
                     } 
                      
                     //ITU-R BT.601 conversion 
                     // 
                     //R = 1.164*(Y-16) + 2.018*(Cr-128); 
                     //G = 1.164*(Y-16) - 0.813*(Cb-128) - 0.391*(Cr-128); 
                     //B = 1.164*(Y-16) + 1.596*(Cb-128); 
                     // 
                     Y = Y + (Y >> 3) + (Y >> 5) + (Y >> 7); 
                     R = Y + (Cr << 1) + (Cr >> 6); 
                     if(R < 0) R = 0; else if(R > 255) R = 255; 
                     G = Y - Cb + (Cb >> 3) + (Cb >> 4) - (Cr >> 1) + (Cr >> 3); 
                     if(G < 0) G = 0; else if(G > 255) G = 255; 
                     B = Y + Cb + (Cb >> 1) + (Cb >> 4) + (Cb >> 5); 
                     if(B < 0) B = 0; else if(B > 255) B = 255; 
                     rgbData[pixPtr++] = 0xff000000 + (B << 16) + (G << 8) + R; 
             } 
    } 
 
    (*env)->ReleasePrimitiveArrayCritical(env, rgbOut, rgbData, 0); 
    (*env)->ReleasePrimitiveArrayCritical(env, yuv420sp, yuv, 0); 
}

6.OpenGlUtils.java

直接使用Android OpenGLES API芭挽,相當(dāng)與對(duì)OpenGLES的一層封裝滑废,簡(jiǎn)化了OpenGLES復(fù)雜的編程。

   public static int loadTexture(final Bitmap img, final int usedTexId, final boolean recycle) {
        int textures[] = new int[1];
        if (usedTexId == NO_TEXTURE) {
            GLES20.glGenTextures(1, textures, 0);
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
            GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
                    GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
            GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
                    GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
            GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
                    GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
            GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
                    GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

            GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, img, 0);
        } else {
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, usedTexId);
            GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, img);
            textures[0] = usedTexId;
        }
        if (recycle) {
            img.recycle();
        }
        return textures[0];
    }

GLES20.java是自動(dòng)生成的代碼袜爪,通過(guò)jni調(diào)用到OpenGLES庫(kù)實(shí)現(xiàn)蠕趁。

package android.opengl; 
 
/**
* OpenGL ES 2.0 
*/ 
public class GLES20 { 
    ...
    native private static void _nativeClassInit(); 
    static { 
        _nativeClassInit(); 
    } 
    // C function void glActiveTexture ( GLenum texture ) 
 
    public static native void glActiveTexture( 
        int texture 
    ); 
 
    // C function void glAttachShader ( GLuint program, GLuint shader ) 
 
    public static native void glAttachShader( 
        int program, 
        int shader 
    ); 
   ...
} 

GLUtils是Android已經(jīng)封裝好的OpenGL ES工具類:

/*                                   GLUtils.java
 * Copyright (C) 2006 The Android Open Source Project 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License. 
 */ 
 
package android.opengl; 
 
import android.graphics.Bitmap; 
 
import javax.microedition.khronos.egl.EGL10; 
import javax.microedition.khronos.egl.EGL11; 
 
/** 
 * 
 * Utility class to help bridging OpenGL ES and Android APIs. 
 * 
 */ 
 
public final class GLUtils { 
 
    private GLUtils() { 
    } 
 
    /** 
     * return the internal format as defined by OpenGL ES of the supplied bitmap. 
     * @param bitmap 
     * @return the internal format of the bitmap. 
     */ 
    public static int getInternalFormat(Bitmap bitmap) { 
        if (bitmap == null) { 
            throw new NullPointerException("getInternalFormat can't be used with a null Bitmap"); 
        } 
        if (bitmap.isRecycled()) { 
            throw new IllegalArgumentException("bitmap is recycled"); 
        } 
        int result = native_getInternalFormat(bitmap); 
        if (result < 0) { 
            throw new IllegalArgumentException("Unknown internalformat"); 
        } 
        return result; 
    } 
 
    /** 
     * Return the type as defined by OpenGL ES of the supplied bitmap, if there 
     * is one. If the bitmap is stored in a compressed format, it may not have 
     * a valid OpenGL ES type. 
     * @throws IllegalArgumentException if the bitmap does not have a type. 
     * @param bitmap 
     * @return the OpenGL ES type of the bitmap. 
     */ 
    public static int getType(Bitmap bitmap) { 
        if (bitmap == null) { 
            throw new NullPointerException("getType can't be used with a null Bitmap"); 
        } 
        if (bitmap.isRecycled()) { 
            throw new IllegalArgumentException("bitmap is recycled"); 
        } 
        int result = native_getType(bitmap); 
        if (result < 0) { 
            throw new IllegalArgumentException("Unknown type"); 
        } 
        return result; 
    } 
 
    /** 
     * Calls glTexImage2D() on the current OpenGL context. If no context is 
     * current the behavior is the same as calling glTexImage2D() with  no 
     * current context, that is, eglGetError() will return the appropriate 
     * error. 
     * Unlike glTexImage2D() bitmap cannot be null and will raise an exception 
     * in that case. 
     * All other parameters are identical to those used for glTexImage2D(). 
     * 
     * NOTE: this method doesn't change GL_UNPACK_ALIGNMENT, you must make 
     * sure to set it properly according to the supplied bitmap. 
     * 
     * Whether or not bitmap can have non power of two dimensions depends on 
     * the current OpenGL context. Always check glGetError() some time 
     * after calling this method, just like when using OpenGL directly. 
     * 
     * @param target 
     * @param level 
     * @param internalformat 
     * @param bitmap 
     * @param border 
     */ 
    public static void texImage2D(int target, int level, int internalformat, 
            Bitmap bitmap, int border) { 
        if (bitmap == null) { 
            throw new NullPointerException("texImage2D can't be used with a null Bitmap"); 
        } 
        if (bitmap.isRecycled()) { 
            throw new IllegalArgumentException("bitmap is recycled"); 
        } 
        if (native_texImage2D(target, level, internalformat, bitmap, -1, border)!=0) { 
            throw new IllegalArgumentException("invalid Bitmap format"); 
        } 
    } 
 
    /** 
     * A version of texImage2D() that takes an explicit type parameter 
     * as defined by the OpenGL ES specification. The actual type and 
     * internalformat of the bitmap must be compatible with the specified 
     * type and internalformat parameters. 
     * 
     * @param target 
     * @param level 
     * @param internalformat 
     * @param bitmap 
     * @param type 
     * @param border 
     */ 
    public static void texImage2D(int target, int level, int internalformat, 
            Bitmap bitmap, int type, int border) { 
        if (bitmap == null) { 
            throw new NullPointerException("texImage2D can't be used with a null Bitmap"); 
        } 
        if (bitmap.isRecycled()) { 
            throw new IllegalArgumentException("bitmap is recycled"); 
        } 
        if (native_texImage2D(target, level, internalformat, bitmap, type, border)!=0) { 
            throw new IllegalArgumentException("invalid Bitmap format"); 
        } 
    } 
 
    /** 
     * A version of texImage2D that determines the internalFormat and type 
     * automatically. 
     * 
     * @param target 
     * @param level 
     * @param bitmap 
     * @param border 
     */ 
    public static void texImage2D(int target, int level, Bitmap bitmap, 
            int border) { 
        if (bitmap == null) { 
            throw new NullPointerException("texImage2D can't be used with a null Bitmap"); 
        } 
        if (bitmap.isRecycled()) { 
            throw new IllegalArgumentException("bitmap is recycled"); 
        } 
        if (native_texImage2D(target, level, -1, bitmap, -1, border)!=0) { 
            throw new IllegalArgumentException("invalid Bitmap format"); 
        } 
    } 
 
    /** 
     * Calls glTexSubImage2D() on the current OpenGL context. If no context is 
     * current the behavior is the same as calling glTexSubImage2D() with  no 
     * current context, that is, eglGetError() will return the appropriate 
     * error. 
     * Unlike glTexSubImage2D() bitmap cannot be null and will raise an exception 
     * in that case. 
     * All other parameters are identical to those used for glTexSubImage2D(). 
     * 
     * NOTE: this method doesn't change GL_UNPACK_ALIGNMENT, you must make 
     * sure to set it properly according to the supplied bitmap. 
     * 
     * Whether or not bitmap can have non power of two dimensions depends on 
     * the current OpenGL context. Always check glGetError() some time 
     * after calling this method, just like when using OpenGL directly. 
     * 
     * @param target 
     * @param level 
     * @param xoffset 
     * @param yoffset 
     * @param bitmap 
     */ 
    public static void texSubImage2D(int target, int level, int xoffset, int yoffset, 
            Bitmap bitmap) { 
        if (bitmap == null) { 
            throw new NullPointerException("texSubImage2D can't be used with a null Bitmap"); 
        } 
        if (bitmap.isRecycled()) { 
            throw new IllegalArgumentException("bitmap is recycled"); 
        } 
        int type = getType(bitmap); 
        if (native_texSubImage2D(target, level, xoffset, yoffset, bitmap, -1, type)!=0) { 
            throw new IllegalArgumentException("invalid Bitmap format"); 
        } 
    } 
 
    /** 
     * A version of texSubImage2D() that takes an explicit type parameter 
     * as defined by the OpenGL ES specification. 
     * 
     * @param target 
     * @param level 
     * @param xoffset 
     * @param yoffset 
     * @param bitmap 
     * @param type 
     */ 
    public static void texSubImage2D(int target, int level, int xoffset, int yoffset, 
            Bitmap bitmap, int format, int type) { 
        if (bitmap == null) { 
            throw new NullPointerException("texSubImage2D can't be used with a null Bitmap"); 
        } 
        if (bitmap.isRecycled()) { 
            throw new IllegalArgumentException("bitmap is recycled"); 
        } 
        if (native_texSubImage2D(target, level, xoffset, yoffset, bitmap, format, type)!=0) { 
            throw new IllegalArgumentException("invalid Bitmap format"); 
        } 
    } 
 
    /** 
     * Return a string for the EGL error code, or the hex representation 
     * if the error is unknown. 
     * 
     * @param error The EGL error to convert into a String. 
     * 
     * @return An error string corresponding to the EGL error code. 
     */ 
    public static String getEGLErrorString(int error) { 
        switch (error) { 
            case EGL10.EGL_SUCCESS: 
                return "EGL_SUCCESS"; 
            case EGL10.EGL_NOT_INITIALIZED: 
                return "EGL_NOT_INITIALIZED"; 
            case EGL10.EGL_BAD_ACCESS: 
                return "EGL_BAD_ACCESS"; 
            case EGL10.EGL_BAD_ALLOC: 
                return "EGL_BAD_ALLOC"; 
            case EGL10.EGL_BAD_ATTRIBUTE: 
                return "EGL_BAD_ATTRIBUTE"; 
            case EGL10.EGL_BAD_CONFIG: 
                return "EGL_BAD_CONFIG"; 
            case EGL10.EGL_BAD_CONTEXT: 
                return "EGL_BAD_CONTEXT"; 
            case EGL10.EGL_BAD_CURRENT_SURFACE: 
                return "EGL_BAD_CURRENT_SURFACE"; 
            case EGL10.EGL_BAD_DISPLAY: 
                return "EGL_BAD_DISPLAY"; 
            case EGL10.EGL_BAD_MATCH: 
                return "EGL_BAD_MATCH"; 
            case EGL10.EGL_BAD_NATIVE_PIXMAP: 
                return "EGL_BAD_NATIVE_PIXMAP"; 
            case EGL10.EGL_BAD_NATIVE_WINDOW: 
                return "EGL_BAD_NATIVE_WINDOW"; 
            case EGL10.EGL_BAD_PARAMETER: 
                return "EGL_BAD_PARAMETER"; 
            case EGL10.EGL_BAD_SURFACE: 
                return "EGL_BAD_SURFACE"; 
            case EGL11.EGL_CONTEXT_LOST: 
                return "EGL_CONTEXT_LOST"; 
            default: 
                return "0x" + Integer.toHexString(error); 
        } 
    } 
 
    /** 
     * Set OpenGL Tracing level for this application. 
     * @hide 
     */ 
    native public static void setTracingLevel(int level); 
 
    native private static int native_getInternalFormat(Bitmap bitmap); 
    native private static int native_getType(Bitmap bitmap); 
    native private static int native_texImage2D(int target, int level, int internalformat, 
            Bitmap bitmap, int type, int border); 
    native private static int native_texSubImage2D(int target, int level, int xoffset, int yoffset, 
            Bitmap bitmap, int format, int type); 
} 

7.Filter子類
擴(kuò)展OpenGLES渲染特效的實(shí)現(xiàn)類,主要封裝對(duì)OpenGL
的配置辛馆,以簡(jiǎn)單的GPUImageBrightnessFilter為例來(lái)說(shuō)明:

public class GPUImageBrightnessFilter extends GPUImageFilter {
    public static final String BRIGHTNESS_FRAGMENT_SHADER = "" +
            "varying highp vec2 textureCoordinate;\n" +
            " \n" +
            " uniform sampler2D inputImageTexture;\n" +
            " uniform lowp float brightness;\n" +
            " \n" +
            " void main()\n" +
            " {\n" +
            "     lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);\n" +
            "     \n" +
            "     gl_FragColor = vec4((textureColor.rgb + vec3(brightness)), textureColor.w);\n" +
            " }";
    private int mBrightnessLocation;
    private float mBrightness;

    public GPUImageBrightnessFilter() {
        this(0.0f);
    }

    public GPUImageBrightnessFilter(final float brightness) {
        super(NO_FILTER_VERTEX_SHADER, BRIGHTNESS_FRAGMENT_SHADER);
        mBrightness = brightness;
    }

    @Override
    public void onInit() {
        super.onInit();
        mBrightnessLocation = GLES20.glGetUniformLocation(getProgram(), "brightness");
    }

   @Override
    public void onInitialized() {
        super.onInitialized();
        setBrightness(mBrightness);
    }

    public void setBrightness(final float brightness) {
        mBrightness = brightness;
        setFloat(mBrightnessLocation, mBrightness);
    }
}

很好理解的渲染實(shí)現(xiàn)參考俺陋,僅僅是配置了片元的渲染BRIGHTNESS_FRAGMENT_SHADER是具體的配置語(yǔ)法,涉及到OpenGL的編程昙篙,本文不作擴(kuò)展說(shuō)明腊状。

二.關(guān)于OpenGLES API的自動(dòng)生成分析

首先看frameworks\native\opengl\tools\glgen下的gen

#!/bin/bash
set -u
set -e
rm -rf out generated

mkdir out

# Create dummy Java files for Android APIs that are used by the code we generate.
# This allows us to test the generated code without building the rest of Android.

mkdir -p out/javax/microedition/khronos/opengles
mkdir -p out/com/google/android/gles_jni
mkdir -p out/android/app
mkdir -p out/android/graphics
mkdir -p out/android/view
mkdir -p out/android/opengl
mkdir -p out/android/content
mkdir -p out/android/content/pm
mkdir -p out/android/os
mkdir -p out/android/util

echo "package android.graphics;" > out/android/graphics/Canvas.java
echo "public interface Canvas {}" >> out/android/graphics/Canvas.java

echo "package android.app; import android.content.pm.IPackageManager; public class AppGlobals { public static IPackageManager getPackageManager() { return null;} }" > out/android/app/AppGlobals.java
# echo "package android.content; import android.content.pm.PackageManager; public interface Context { public PackageManager getPackageManager(); }" > out/android/content/Context.java
echo "package android.content.pm; public class ApplicationInfo {public int targetSdkVersion;}" > out/android/content/pm/ApplicationInfo.java
echo "package android.content.pm; public interface IPackageManager {ApplicationInfo getApplicationInfo(java.lang.String packageName, int flags, java.lang.String userId) throws android.os.RemoteException;}" > out/android/content/pm/IPackageManager.java
echo "package android.os; public class Build {public static class VERSION_CODES { public static final int CUPCAKE = 3;};    }" > out/android/os/Build.java
echo "package android.os; public class UserHandle {public static String myUserId() { return \"\"; } }" > out/android/os/UserHandle.java
echo "package android.os; public class RemoteException extends Exception {}" > out/android/os/RemoteException.java
echo "package android.util; public class Log {public static void w(String a, String b) {} public static void e(String a, String b) {}}" > out/android/util/Log.java

echo "package android.opengl; public abstract class EGLObjectHandle { public int getHandle() { return 0; } }" > out/android/opengl/EGLObjectHandle.java


echo "package android.graphics;" > out/android/graphics/SurfaceTexture.java
echo "public interface SurfaceTexture {}" >> out/android/graphics/SurfaceTexture.java
echo "package android.view;" > out/android/view/SurfaceView.java
echo "public interface SurfaceView { SurfaceHolder getHolder(); }" >> out/android/view/SurfaceView.java
echo "package android.view;" > out/android/view/Surface.java
echo "public interface Surface {}" >> out/android/view/Surface.java
echo "package android.view;" > out/android/view/SurfaceHolder.java
echo "public interface SurfaceHolder { Surface getSurface(); }" >> out/android/view/SurfaceHolder.java

cp static/egl/*.java out/android/opengl/

GLFILE=out/javax/microedition/khronos/opengles/GL.java
cp stubs/jsr239/GLHeader.java-if $GLFILE

GLGEN_FILES="CFunc.java CType.java CodeEmitter.java EGLCodeEmitter.java GenerateEGL.java GenerateGL.java GenerateGLES.java GLESCodeEmitter.java JFunc.java JniCodeEmitter.java JType.java Jsr239CodeEmitter.java ParameterChecker.java"

pushd src > /dev/null
javac ${GLGEN_FILES}
JAVAC_RESULT=$?
if [ $JAVAC_RESULT -ne 0 ]; then
    echo "Could not compile glgen."
    exit $JAVAC_RESULT
fi
popd > /dev/null

echo "Generating JSR239-like APIs"
java -classpath src GenerateGL -c specs/jsr239/glspec-1.0 \
                                  specs/jsr239/glspec-1.0ext \
                                  specs/jsr239/glspec-1.1 \
                                  specs/jsr239/glspec-1.1ext \
                                  specs/jsr239/glspec-1.1extpack \
                                  specs/jsr239/glspec-checks
JAVA_RESULT=$?
if [ $JAVA_RESULT -ne 0 ]; then
    echo "Could not run GenerateGL."
    exit $JAVA_RESULT
fi

echo "Generating static OpenGLES bindings"
java -classpath src GenerateGLES
JAVA_RESULT=$?
if [ $JAVA_RESULT -ne 0 ]; then
    echo "Could not run GenerateGLES."
    exit $JAVA_RESULT
fi

echo "Generating static EGL bindings"
java -classpath src GenerateEGL
JAVA_RESULT=$?
if [ $JAVA_RESULT -ne 0 ]; then
    echo "Could not run GenerateEGL."
    exit $JAVA_RESULT
fi

rm src/*.class

pushd out > /dev/null
mkdir classes
javac -d classes    android/opengl/EGL14.java \
                    android/opengl/EGLExt.java \
                    com/google/android/gles_jni/GLImpl.java \
                    javax/microedition/khronos/opengles/GL10.java \
                    javax/microedition/khronos/opengles/GL10Ext.java \
                    javax/microedition/khronos/opengles/GL11.java \
                    javax/microedition/khronos/opengles/GL11Ext.java \
                    javax/microedition/khronos/opengles/GL11ExtensionPack.java \
                    android/opengl/GLES10.java \
                    android/opengl/GLES10Ext.java \
                    android/opengl/GLES11.java \
                    android/opengl/GLES11Ext.java \
                    android/opengl/GLES20.java \
                    android/opengl/GLES30.java
popd > /dev/null
JAVA_RESULT=$?
if [ $JAVA_RESULT -ne 0 ]; then
    echo "Could not compile generated classes."
    exit $JAVA_RESULT
fi

rm -rf generated
mkdir -p generated/C
cp out/com_google_android_gles_jni_GLImpl.cpp generated/C
cp -r out/com generated
cp -r out/javax generated

cp out/android_opengl_*.cpp generated/C
mkdir -p generated/android/opengl
cp -r out/android/opengl generated/android

rm -rf out
KEEP_GENERATED=0
SAID_PLEASE=0

# compareGenerated destDir generatedDir file
compareGenerated() {
    if cmp -s $1/$3 $2/$3 ; then
        echo "#    " $3 unchanged
    else
        echo "#    " $3 changed
        if [ $SAID_PLEASE == "0" ] ; then
            echo Please evaluate the following commands:
            echo
            SAID_PLEASE=1
        fi
        echo "    cp $2/$3 $1"
        echo "    (cd $1; git add $3)"
        KEEP_GENERATED=1
    fi
}

compareGenerated ../../../../base/core/jni generated/C com_google_android_gles_jni_GLImpl.cpp
compareGenerated ../../../../base/opengl/java/com/google/android/gles_jni generated/com/google/android/gles_jni GLImpl.java

for x in GL.java GL10.java GL10Ext.java GL11.java GL11Ext.java GL11ExtensionPack.java
do
    compareGenerated ../../../../base/opengl/java/javax/microedition/khronos/opengles generated/javax/microedition/khronos/opengles $x
done

for x in EGL14 EGLExt GLES10 GLES10Ext GLES11 GLES11Ext GLES20 GLES30
do
    compareGenerated ../../../../base/opengl/java/android/opengl generated/android/opengl ${x}.java
    compareGenerated ../../../../base/core/jni generated/C android_opengl_${x}.cpp
done

for x in EGLConfig EGLContext EGLDisplay EGLObjectHandle EGLSurface
do
    compareGenerated ../../../../base/opengl/java/android/opengl generated/android/opengl ${x}.java
done

if [ $KEEP_GENERATED == "0" ] ; then
    rm -rf generated
fi

基本可以看出來(lái)是如何實(shí)現(xiàn)自動(dòng)生成文件的了吧。
1.創(chuàng)建編譯GL相關(guān)引用文件苔可,比如SurfaceView 缴挖、Surface 等

echo "public interface SurfaceTexture {}" >> out/android/graphics/SurfaceTexture.java

2.自動(dòng)生成GL接口類的核心邏輯實(shí)現(xiàn),如GenerateGL.java GenerateGLES.java等

GLGEN_FILES="CFunc.java CType.java CodeEmitter.java EGLCodeEmitter.java GenerateEGL.java GenerateGL.java GenerateGLES.java GLESCodeEmitter.java JFunc.java JniCodeEmitter.java JType.java Jsr239CodeEmitter.java ParameterChecker.java"

pushd src > /dev/null
javac ${GLGEN_FILES}
/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;

public class GenerateGLES {

    static void copy(String filename, PrintStream out) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader(filename));
        String s;
        while ((s = br.readLine()) != null) {
            out.println(s);
        }
    }

    private static void emit(GLESCodeEmitter emitter,
                             BufferedReader specReader,
                             PrintStream glStream,
                             PrintStream cStream) throws Exception {
        String s = null;
        while ((s = specReader.readLine()) != null) {
            if (s.trim().startsWith("http://")) {
                continue;
            }

            CFunc cfunc = CFunc.parseCFunc(s);
            String fname = cfunc.getName();
            String stubRoot = "stubs/gles11/" + fname;
            String javaPath = stubRoot + ".java";
            File f = new File(javaPath);
            if (f.exists()) {
                System.out.println("Special-casing function " + fname);
                copy(javaPath, glStream);
                copy(stubRoot + ".cpp", cStream);

                // Register native function names
                // This should be improved to require fewer discrete files
                String filename = stubRoot + ".nativeReg";
                BufferedReader br =
                    new BufferedReader(new FileReader(filename));
                String nfunc;
                while ((nfunc = br.readLine()) != null) {
                    emitter.addNativeRegistration(nfunc);
                }
            } else {
                emitter.emitCode(cfunc, s);
            }
        }
    }

    public static void main(String[] args) throws Exception {
        int aidx = 0;
        while ((aidx < args.length) && (args[aidx].charAt(0) == '-')) {
            switch (args[aidx].charAt(1)) {
            default:
                System.err.println("Unknown flag: " + args[aidx]);
                System.exit(1);
            }

            aidx++;
        }

        BufferedReader checksReader =
            new BufferedReader(new FileReader("specs/gles11/checks.spec"));
        ParameterChecker checker = new ParameterChecker(checksReader);

        // Generate files
        for(String suffix: new String[] {"GLES10", "GLES10Ext",
                "GLES11", "GLES11Ext", "GLES20", "GLES30"})
        {
            BufferedReader spec11Reader =
                new BufferedReader(new FileReader("specs/gles11/"
                        + suffix + ".spec"));
            String gl11Filename = "android/opengl/" + suffix + ".java";
            String gl11cFilename = "android_opengl_" + suffix + ".cpp";
            PrintStream gl11Stream =
                new PrintStream(new FileOutputStream("out/" + gl11Filename));
            PrintStream gl11cStream =
                new PrintStream(new FileOutputStream("out/" + gl11cFilename));
            copy("stubs/gles11/" + suffix + "Header.java-if", gl11Stream);
            copy("stubs/gles11/" + suffix + "cHeader.cpp", gl11cStream);
            copy("stubs/gles11/common.cpp", gl11cStream);
            GLESCodeEmitter emitter = new GLESCodeEmitter(
                    "android/opengl/" + suffix,
                    checker, gl11Stream, gl11cStream);
            emit(emitter, spec11Reader, gl11Stream, gl11cStream);
            emitter.emitNativeRegistration("register_android_opengl_jni_"
                    + suffix);
            gl11Stream.println("}");
            gl11Stream.close();
            gl11cStream.close();
        }
    }
}

從上面的代碼片段:

        // Generate files
        for(String suffix: new String[] {"GLES10", "GLES10Ext",
                "GLES11", "GLES11Ext", "GLES20", "GLES30"})
        {
            BufferedReader spec11Reader =
                new BufferedReader(new FileReader("specs/gles11/"
                        + suffix + ".spec"));
            String gl11Filename = "android/opengl/" + suffix + ".java";
            String gl11cFilename = "android_opengl_" + suffix + ".cpp";
            PrintStream gl11Stream =
                new PrintStream(new FileOutputStream("out/" + gl11Filename));
            PrintStream gl11cStream =new PrintStream(new FileOutputStream("out/" + gl11cFilename));
            copy("stubs/gles11/" + suffix + "Header.java-if", gl11Stream);
            copy("stubs/gles11/" + suffix + "cHeader.cpp", gl11cStream);
            copy("stubs/gles11/common.cpp", gl11cStream);
            GLESCodeEmitter emitter = new GLESCodeEmitter(
                    "android/opengl/" + suffix,
                    checker, gl11Stream, gl11cStream);
            emit(emitter, spec11Reader, gl11Stream, gl11cStream);
            emitter.emitNativeRegistration("register_android_opengl_jni_"
                    + suffix);
            gl11Stream.println("}");
            gl11Stream.close();
            gl11cStream.close();
        }

可以看出GLES10焚辅,GLES10Ext映屋、GLES20等都是由specs/gles11/目錄下的對(duì)應(yīng)文件.spec描述生成規(guī)則的,比如GLES20對(duì)應(yīng)的GLES20.spec:

void glActiveTexture ( GLenum texture )
void glAttachShader ( GLuint program, GLuint shader )
void glBindAttribLocation ( GLuint program, GLuint index, const char *name )
void glBindBuffer ( GLenum target, GLuint buffer )
void glBindFramebuffer ( GLenum target, GLuint framebuffer )
void glBindRenderbuffer ( GLenum target, GLuint renderbuffer )
void glBindTexture ( GLenum target, GLuint texture )
void glBlendColor ( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
void glBlendEquation ( GLenum mode )
void glBlendEquationSeparate ( GLenum modeRGB, GLenum modeAlpha )
void glBlendFunc ( GLenum sfactor, GLenum dfactor )
void glBlendFuncSeparate ( GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha )
void glBufferData ( GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage )
void glBufferSubData ( GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data )
GLenum glCheckFramebufferStatus ( GLenum target )
void glClear ( GLbitfield mask )
void glClearColor ( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
void glClearDepthf ( GLclampf depth )
void glClearStencil ( GLint s )
void glColorMask ( GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha )
void glCompileShader ( GLuint shader )
void glCompressedTexImage2D ( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data )
void glCompressedTexSubImage2D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data )
void glCopyTexImage2D ( GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border )
void glCopyTexSubImage2D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height )
GLuint glCreateProgram ( void )
GLuint glCreateShader ( GLenum type )
void glCullFace ( GLenum mode )
void glDeleteBuffers ( GLsizei n, const GLuint *buffers )
void glDeleteFramebuffers ( GLsizei n, const GLuint *framebuffers )
void glDeleteProgram ( GLuint program )
void glDeleteRenderbuffers ( GLsizei n, const GLuint *renderbuffers )
void glDeleteShader ( GLuint shader )
void glDeleteTextures ( GLsizei n, const GLuint *textures )
void glDepthFunc ( GLenum func )
void glDepthMask ( GLboolean flag )
void glDepthRangef ( GLclampf zNear, GLclampf zFar )
void glDetachShader ( GLuint program, GLuint shader )
void glDisable ( GLenum cap )
void glDisableVertexAttribArray ( GLuint index )
void glDrawArrays ( GLenum mode, GLint first, GLsizei count )
void glDrawElements ( GLenum mode, GLsizei count, GLenum type, GLint offset )
void glDrawElements ( GLenum mode, GLsizei count, GLenum type, const GLvoid *indices )
void glEnable ( GLenum cap )
void glEnableVertexAttribArray ( GLuint index )
void glFinish ( void )
void glFlush ( void )
void glFramebufferRenderbuffer ( GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer )
void glFramebufferTexture2D ( GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level )
void glFrontFace ( GLenum mode )
void glGenBuffers ( GLsizei n, GLuint *buffers )
void glGenerateMipmap ( GLenum target )
void glGenFramebuffers ( GLsizei n, GLuint *framebuffers )
void glGenRenderbuffers ( GLsizei n, GLuint *renderbuffers )
void glGenTextures ( GLsizei n, GLuint *textures )
void glGetActiveAttrib ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name )
void glGetActiveUniform ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name )
void glGetAttachedShaders ( GLuint program, GLsizei maxcount, GLsizei *count, GLuint *shaders )
GLint glGetAttribLocation ( GLuint program, const char *name )
void glGetBooleanv ( GLenum pname, GLboolean *params )
void glGetBufferParameteriv ( GLenum target, GLenum pname, GLint *params )
GLenum glGetError ( void )
void glGetFloatv ( GLenum pname, GLfloat *params )
void glGetFramebufferAttachmentParameteriv ( GLenum target, GLenum attachment, GLenum pname, GLint *params )
void glGetIntegerv ( GLenum pname, GLint *params )
void glGetProgramiv ( GLuint program, GLenum pname, GLint *params )
void glGetProgramInfoLog ( GLuint program, GLsizei bufsize, GLsizei *length, char *infolog )
void glGetRenderbufferParameteriv ( GLenum target, GLenum pname, GLint *params )
void glGetShaderiv ( GLuint shader, GLenum pname, GLint *params )
void glGetShaderInfoLog ( GLuint shader, GLsizei bufsize, GLsizei *length, char *infolog )
void glGetShaderPrecisionFormat ( GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision )
void glGetShaderSource ( GLuint shader, GLsizei bufsize, GLsizei *length, char *source )
const GLubyte * glGetString ( GLenum name )
void glGetTexParameterfv ( GLenum target, GLenum pname, GLfloat *params )
void glGetTexParameteriv ( GLenum target, GLenum pname, GLint *params )
void glGetUniformfv ( GLuint program, GLint location, GLfloat *params )
void glGetUniformiv ( GLuint program, GLint location, GLint *params )
GLint glGetUniformLocation ( GLuint program, const char *name )
void glGetVertexAttribfv ( GLuint index, GLenum pname, GLfloat *params )
void glGetVertexAttribiv ( GLuint index, GLenum pname, GLint *params )
// void glGetVertexAttribPointerv ( GLuint index, GLenum pname, void **pointer )
void glHint ( GLenum target, GLenum mode )
GLboolean glIsBuffer ( GLuint buffer )
GLboolean glIsEnabled ( GLenum cap )
GLboolean glIsFramebuffer ( GLuint framebuffer )
GLboolean glIsProgram ( GLuint program )
GLboolean glIsRenderbuffer ( GLuint renderbuffer )
GLboolean glIsShader ( GLuint shader )
GLboolean glIsTexture ( GLuint texture )
void glLineWidth ( GLfloat width )
void glLinkProgram ( GLuint program )
void glPixelStorei ( GLenum pname, GLint param )
void glPolygonOffset ( GLfloat factor, GLfloat units )
void glReadPixels ( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels )
void glReleaseShaderCompiler ( void )
void glRenderbufferStorage ( GLenum target, GLenum internalformat, GLsizei width, GLsizei height )
void glSampleCoverage ( GLclampf value, GLboolean invert )
void glScissor ( GLint x, GLint y, GLsizei width, GLsizei height )
void glShaderBinary ( GLsizei n, const GLuint *shaders, GLenum binaryformat, const GLvoid *binary, GLsizei length )
void glShaderSource ( GLuint shader )
void glStencilFunc ( GLenum func, GLint ref, GLuint mask )
void glStencilFuncSeparate ( GLenum face, GLenum func, GLint ref, GLuint mask )
void glStencilMask ( GLuint mask )
void glStencilMaskSeparate ( GLenum face, GLuint mask )
void glStencilOp ( GLenum fail, GLenum zfail, GLenum zpass )
void glStencilOpSeparate ( GLenum face, GLenum fail, GLenum zfail, GLenum zpass )
void glTexImage2D ( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels )
void glTexParameterf ( GLenum target, GLenum pname, GLfloat param )
void glTexParameterfv ( GLenum target, GLenum pname, const GLfloat *params )
void glTexParameteri ( GLenum target, GLenum pname, GLint param )
void glTexParameteriv ( GLenum target, GLenum pname, const GLint *params )
void glTexSubImage2D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels )
void glUniform1f ( GLint location, GLfloat x )
void glUniform1fv ( GLint location, GLsizei count, const GLfloat *v )
void glUniform1i ( GLint location, GLint x )
void glUniform1iv ( GLint location, GLsizei count, const GLint *v )
void glUniform2f ( GLint location, GLfloat x, GLfloat y )
void glUniform2fv ( GLint location, GLsizei count, const GLfloat *v )
void glUniform2i ( GLint location, GLint x, GLint y )
void glUniform2iv ( GLint location, GLsizei count, const GLint *v )
void glUniform3f ( GLint location, GLfloat x, GLfloat y, GLfloat z )
void glUniform3fv ( GLint location, GLsizei count, const GLfloat *v )
void glUniform3i ( GLint location, GLint x, GLint y, GLint z )
void glUniform3iv ( GLint location, GLsizei count, const GLint *v )
void glUniform4f ( GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w )
void glUniform4fv ( GLint location, GLsizei count, const GLfloat *v )
void glUniform4i ( GLint location, GLint x, GLint y, GLint z, GLint w )
void glUniform4iv ( GLint location, GLsizei count, const GLint *v )
void glUniformMatrix2fv ( GLint location, GLsizei count, GLboolean transpose, const GLfloat *value )
void glUniformMatrix3fv ( GLint location, GLsizei count, GLboolean transpose, const GLfloat *value )
void glUniformMatrix4fv ( GLint location, GLsizei count, GLboolean transpose, const GLfloat *value )
void glUseProgram ( GLuint program )
void glValidateProgram ( GLuint program )
void glVertexAttrib1f ( GLuint indx, GLfloat x )
void glVertexAttrib1fv ( GLuint indx, const GLfloat *values )
void glVertexAttrib2f ( GLuint indx, GLfloat x, GLfloat y )
void glVertexAttrib2fv ( GLuint indx, const GLfloat *values )
void glVertexAttrib3f ( GLuint indx, GLfloat x, GLfloat y, GLfloat z )
void glVertexAttrib3fv ( GLuint indx, const GLfloat *values )
void glVertexAttrib4f ( GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w )
void glVertexAttrib4fv ( GLuint indx, const GLfloat *values )
void glVertexAttribPointer ( GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLint offset )
void glVertexAttribPointer ( GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *ptr )
void glViewport ( GLint x, GLint y, GLsizei width, GLsizei height )

然后根據(jù)stubs/gles11/目錄下對(duì)應(yīng)的Header.java-if和cHeader.cpp以及common.cpp來(lái)拼湊成一個(gè)完成的類文件同蜻,jni也是同樣道理.

3.根據(jù)specs/jsr239/glspec*的規(guī)則自動(dòng)生成JSR239 APIs
4.生成static OpenGLES bindings
5.生成static EGL bindings
6.自動(dòng)生成OpenGLES APIs秧荆,比如GLES20.java
7.創(chuàng)建類似Android framework的目錄,準(zhǔn)備拷貝API到該目錄
8.最后是校驗(yàn)自動(dòng)生成的文件和拷貝到Android framework的API是否一致

3.結(jié)束語(yǔ)

最近發(fā)生一些事情埃仪,煩惱中乙濒,沒(méi)什么好說(shuō)的了,就這點(diǎn)IT癡漢的怪脾氣卵蛉。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末颁股,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子傻丝,更是在濱河造成了極大的恐慌甘有,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件葡缰,死亡現(xiàn)場(chǎng)離奇詭異亏掀,居然都是意外死亡忱反,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門滤愕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)温算,“玉大人,你說(shuō)我怎么就攤上這事间影∽⒏停” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵魂贬,是天一觀的道長(zhǎng)巩割。 經(jīng)常有香客問(wèn)我,道長(zhǎng)付燥,這世上最難降的妖魔是什么宣谈? 我笑而不...
    開(kāi)封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮键科,結(jié)果婚禮上蒲祈,老公的妹妹穿的比我還像新娘。我一直安慰自己萝嘁,他們只是感情好梆掸,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布左医。 她就那樣靜靜地躺著已脓,像睡著了一般。 火紅的嫁衣襯著肌膚如雪甜害。 梳的紋絲不亂的頭發(fā)上咱枉,一...
    開(kāi)封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天卑硫,我揣著相機(jī)與錄音,去河邊找鬼蚕断。 笑死欢伏,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的亿乳。 我是一名探鬼主播硝拧,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼葛假!你這毒婦竟也來(lái)了障陶?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤聊训,失蹤者是張志新(化名)和其女友劉穎抱究,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體带斑,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鼓寺,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年勋拟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片妈候。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡敢靡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出州丹,到底是詐尸還是另有隱情,我是刑警寧澤杂彭,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布墓毒,位于F島的核電站,受9級(jí)特大地震影響亲怠,放射性物質(zhì)發(fā)生泄漏所计。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一团秽、第九天 我趴在偏房一處隱蔽的房頂上張望主胧。 院中可真熱鬧,春花似錦习勤、人聲如沸踪栋。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)夷都。三九已至,卻和暖如春予颤,著一層夾襖步出監(jiān)牢的瞬間囤官,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工蛤虐, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留党饮,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓驳庭,卻偏偏與公主長(zhǎng)得像刑顺,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子饲常,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容