My device is Huawei mate30, its param is:
CPU : is 2 x Cortex-A76 Based 2.86 GHz + 2 x Cortex-A76 Based 2.09 GHz + 4 x Cortex-A55 1.86 GHz.
GPU: Mali-G76
I used glCheckError(), but it not report Error.
This is the renderer complete code:
public class FBORenderer2 implements GLSurfaceView.Renderer {
private static final String TAG = "FBORenderer2";
protected FloatBuffer mVerBuffer = ShaderUtils.floatBuffer(-1.0f, 1.0f,
-1.0f, -1.0f,
1.0f, 1.0f,
1.0f, -1.0f);
protected FloatBuffer mTexBuffer = ShaderUtils.floatBuffer(0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f);
private Bitmap mBitmap;
private ByteBuffer mBuffer;
private final int[] fFrame = new int[1];
private final int[] fRender = new int[1];
private final int[] fTexture = new int[1];
protected int mHPosition;
protected int mHCoord;
protected int mHTexture;
protected int mHMatrix;
protected int program;
private Context context;
private float[] mMatrix = {
1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1
};
private Callback mCallback;
public FBORenderer2(Context context){
this.context = context;
mMatrix = flip(mMatrix,false,true);
}
public static float[] flip(float[] m,boolean x,boolean y){
if(x||y){
Matrix.scaleM(m,0,x?-1:1,y?-1:1,1);
}
return m;
}
public void setBitmap(Bitmap bitmap){
this.mBitmap = bitmap;
}
public void setmCallback(Callback callback){
this.mCallback = callback;
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
program = ShaderUtils.createProgram(ShaderUtils.loadFromAssets("base_vertex.vert",context.getResources()),
ShaderUtils.loadFromAssets("gray_fragment.frag",context.getResources()));
GLES30.glEnable(GL_DEPTH_TEST);
mHPosition= GLES30.glGetAttribLocation(program, "vPosition");
mHCoord=GLES30.glGetAttribLocation(program,"vCoord");
mHMatrix=GLES30.glGetUniformLocation(program,"vMatrix");
mHTexture=GLES30.glGetUniformLocation(program,"vTexture");
// Texture source Texture
GLES30.glGenTextures(1, fTexture, 0);
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, fTexture[0]);
GLUtils.texImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGBA, mBitmap, 0);
// RenderBuffer
GLES30.glGenRenderbuffers(1, fRender, 0);
GLES30.glBindRenderbuffer(GLES30.GL_RENDERBUFFER, fRender[0]);
GLES30.glRenderbufferStorage(GLES30.GL_RENDERBUFFER, GLES30.GL_RGBA8, mBitmap.getWidth(), mBitmap.getHeight());
LogUtils.checkError(TAG,"glRenderbufferStorage");
// FrameBuffer
GLES30.glGenFramebuffers(1, fFrame, 0);
GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, fFrame[0]);
GLES30.glFramebufferRenderbuffer(GLES30.GL_FRAMEBUFFER, GLES30.GL_COLOR_ATTACHMENT0, GLES30.GL_RENDERBUFFER, fRender[0]);
LogUtils.checkFrameBuffer(TAG,GLES30.glCheckFramebufferStatus(GL_FRAMEBUFFER));
GLES30.glReadBuffer(GLES30.GL_COLOR_ATTACHMENT0);
mBuffer = ByteBuffer.allocate(mBitmap.getWidth() * mBitmap.getHeight() * 4);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES30.glViewport(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
}
@Override
public void onDrawFrame(GL10 gl) {
if(mBitmap != null && !mBitmap.isRecycled()){
clear();
GLES30.glBindFramebuffer(GL_FRAMEBUFFER,fFrame[0]);
GLES30.glUseProgram(program);
// set GLSL's variable value
GLES30.glUniformMatrix4fv(mHMatrix,1,false, mMatrix,0);
GLES30.glUniform1i(mHTexture,0);
GLES30.glEnableVertexAttribArray(mHPosition);
GLES30.glVertexAttribPointer(mHPosition,2, GLES30.GL_FLOAT, false, 0,mVerBuffer);
GLES30.glEnableVertexAttribArray(mHCoord);
GLES30.glVertexAttribPointer(mHCoord, 2, GLES30.GL_FLOAT, false, 0, mTexBuffer);
// bind source Texture
GLES30.glActiveTexture(GLES30.GL_TEXTURE0);
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D,fTexture[0]);
GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP,0,4);
GLES30.glDisableVertexAttribArray(mHPosition);
GLES30.glDisableVertexAttribArray(mHCoord);
GLES30.glReadBuffer(GLES30.GL_COLOR_ATTACHMENT0);
// GLES30.glFinish();
GLES30.glReadPixels(0, 0, mBitmap.getWidth(), mBitmap.getHeight(), GLES30.GL_RGBA,
GLES30.GL_UNSIGNED_BYTE, mBuffer);
LogUtils.checkError(TAG,"glReadPixels");
GLES30.glDeleteTextures(1, fTexture, 0);
GLES30.glDeleteRenderbuffers(1, fRender, 0);
GLES30.glDeleteFramebuffers(1, fFrame, 0);
if(mCallback!=null){
mCallback.onCall(mBuffer);
// in onCall(), execute: Bitmap bitmap=Bitmap.createBitmap(bmp.getWidth(),bmp.getHeight(), Bitmap.Config.ARGB_8888);
}
mBitmap.recycle();
mBuffer.clear();
}
}
private void clear(){
GLES30.glClearColor(1.0f,1.0f,1.0f,1.0f);
GLES30.glClear(GL_COLOR_BUFFER_BIT|GLES30.GL_DEPTH_BUFFER_BIT);
}
interface Callback{
void onCall(ByteBuffer data);
}
}
Then i test it on an virtual machine in Android Studio, the virtual machine’s system image is x86. it encounter the same problem.
So ,by now, i am not sure if it can use glReadPixels() to read FBO’s RenderBuffer’s color buffer for most Android device.
And after check some document and your reply, i quick use this way to pass data.
Thanks.