1.文章介绍
不甘落后,就努力充实自己。
根据自己的学习计划,最近看了看Android平台上的图片处理相关构架。发现无论是glide-transformations,还是Picasso Transformations,Fresco Processors等主流的开源项目都基于GPUImage实现图片特效的渲染。借此机会自己也记录下部分学习内容。
2.干货
一.核心类
1.GPUImage.java
Android OpenGLES核心实现类,配合GLSurfaceView和GPUImageFilter实现渲染。
/**
* 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
对GPUImage的进一步封装,实际上是一个包含了GPUImageGLSurfaceView的FrameLayout,使用时通过配合使用GPUImageFilter调整参数即可。
这里释放下程序员天赋技能(搬砖),以下是ActivityGallery.java的源码,通过GPUImageView和Filter直接实现渲染效果:
/*
* 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是用来配置OpenGLES渲染的主类,所谓VERTEX,就是顶点,FRAGMENT就是片元,这都涉及到OpenGL的渲染相关知识,多少需要了解。
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();
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;
}
上面一段代码是对OpenGL不配置任何效果,即按原始图片效果渲染图片;若需要自定义渲染效果,可以根据JAVA的继承特性扩展一个继承于GPUImageFilter的子类即可,因此在GPUImage的源码中你可以看到很多类似GPUImageAlphaBlendFilter、GPUImageBoxBlurFilter等渲染特效的子类。
4.GPUImageRenderer.java
GPUImageRenderer是接口类Renderer的实现,在OpenGLES中如何理解Renderer呢?其实Renderer是GLSurfaceView(继承于SurfaceView)定义的一个接口类,作用就是实现事件回调
public interface Renderer {
/**
* Called when the surface is created or recreated.
*
* 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.
*
* 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.
*
* 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.
*
* @param gl the GL interface. Use instanceof
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.
*
* Called after the surface is created and whenever
* the OpenGL ES surface size changes.
*
* Typically you will set your viewport here. If your camera
* is fixed then you could also set your projection matrix here:
*
* 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);
* }
*
* @param gl the GL interface. Use instanceof
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.
*
* This method is responsible for drawing the current frame.
*
* The implementation of this method typically looks like this:
*
* void onDrawFrame(GL10 gl) {
* gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
* //... other gl calls to render the scene ...
* }
*
* @param gl the GL interface. Use instanceof
to
* test if the interface supports GL11 or higher interfaces.
*/
void onDrawFrame(GL10 gl);
}
5.GPUImageNativeLibrary.java
仅仅是对YUV和ARGB数据互转进行的封装,应该是考虑C代码的效率会更高。
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
#include
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,相当与对OpenGLES的一层封装,简化了OpenGLES复杂的编程。
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是自动生成的代码,通过jni调用到OpenGLES库实现。
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已经封装好的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子类
扩展OpenGLES渲染特效的实现类,主要封装对OpenGL
的配置,以简单的GPUImageBrightnessFilter为例来说明:
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);
}
}
很好理解的渲染实现参考,仅仅是配置了片元的渲染BRIGHTNESS_FRAGMENT_SHADER是具体的配置语法,涉及到OpenGL的编程,本文不作扩展说明。
二.关于OpenGLES API的自动生成分析
首先看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
基本可以看出来是如何实现自动生成文件的了吧。
1.创建编译GL相关引用文件,比如SurfaceView 、Surface 等
echo "public interface SurfaceTexture {}" >> out/android/graphics/SurfaceTexture.java
2.自动生成GL接口类的核心逻辑实现,如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("//")) {
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/目录下的对应文件.spec描述生成规则的,比如GLES20对应的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 )
然后根据stubs/gles11/目录下对应的Header.java-if和cHeader.cpp以及common.cpp来拼凑成一个完成的类文件,jni也是同样道理.
3.根据specs/jsr239/glspec*的规则自动生成JSR239 APIs
4.生成static OpenGLES bindings
5.生成static EGL bindings
6.自动生成OpenGLES APIs,比如GLES20.java
7.创建类似Android framework的目录,准备拷贝API到该目录
8.最后是校验自动生成的文件和拷贝到Android framework的API是否一致
3.结束语
最近发生一些事情,烦恼中,没什么好说的了,就这点IT痴汉的怪脾气。