I try to get data from default framebuffer on Android (GLES 3.1). Andriod version 6.0. Device: Levono TAB 2 A-10.
If I use glReadPixels it works fine, but I want to avoid copying data to the CPU and bind this data to a compute shader.
Code looks like this:
glReadBuffer(GL_BACK);
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 300, 250);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 300, 250, 0);
After glCopyTexImage2D I get ERROR: 1282 (GL_INVALID_OPERATION) That from documentation means: GL_INVALID_OPERATION is generated if the currently bound framebuffer's format does not contain a superset of the components required by the base format of internalformat.
I tried different formats of texture, but without success.
Related
I'm working on displaying yuv pictures with OpenGL ES3.0 on Android. I convert yuv pixels to rgb in a fragment shader. At first, I need to pass yuv pixel data to OpenGL as a texture.
When the yuv data is 8 bit-depth, I program like below and it works:
GLenum glError;
GLuint tex_y;
glGenTextures(1, &tex_y);
glBindTexture(GL_TEXTURE_2D, tex_y);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// pix_y is y component data.
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, y_width, y_height, 0, GL_LUMINANCE,GL_UNSIGNED_BYTE, pix_y);
glGenerateMipmap(GL_TEXTURE_2D);
glError = glGetError();
if (glError != GL_NO_ERROR) {
LOGE(TAG, "y, glError: 0x%x", glError);
}
However there are some yuv formats with more depth like YUV420P10le. I don't want to lose the benefit of more depth, so I convert yuv data which has more than 8 bit depth to 16 bit by shifting data (for example: yuv420p10le, y_new = y_old << 6)。 Now I want to generate a 16 bit depth texture, but I always fail GL_INVALID_OPERATION. Below is the code to create a 16 bit texture:
// rest part is the same with 8 bit texture.
glTexImage2D(GL_TEXTURE_2D, 0, GL_R16UI, y_width, y_height, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, pix_y);
I've tried many format combinations in https://registry.khronos.org/OpenGL-Refpages/es3.0/html/glTexImage2D.xhtml, none of them succeed.
By the way, I also tested on MacOS OpenGL 3.3 and succeeded, I just need to pass data as one channel data of RGB..
// Code on MacOS OpenGL3.3. The data format depends on y depth, GL_UNSIGNED_BYTE or
// GL_UNSIGNED_SHORT. Using this config, I can access the data in RED channel of textures
// which is normalized to [0.0f, 1.0f]. However, this config doesn't work on OpenGL ES3.0
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, y_width, y_height, 0, GL_RED, dataFormat, y);
I'm using OpenGLES3.0 to do video processing.
I found that it's possible to get frames from a video by using Android MediaExtractor and MediaCodec API together with Surface texture, like below.
glGenTextures( 1, &textureId );
glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId);
glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
But there is no such API in GLES3.0.
My question is: is there a relevant API in OpenGLES3.0 to generate and use surface texture? Or is there some other APIs in Android to get all frames from a video?
I tried getFrameAtTime() in MediaMetadataRetriever and FFmpegMediaMetadataRetriever but I could only get the key frames rather than all frames, even with MediaMetadataRetriever.OPTION_CLOSEST.
It seems that 1.1 or 2.0 extensions are still available in 3.0. So to use GL_TEXTURE_EXTERNAL_OES, you only need to include the gl2ext.h.
Trying to utilize directional shadow mapping on OpenGL. Need to generate a depth texture that isn't a renderbuffer (need to be able to read from it) it future passes. Keep getting GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT (as result of glCheckFramebufferStatus) when running on Android (don't get error when running on OSX).
Here's my code:
//Shadow
//gen tex
gl_shadow_bogus_texture_active_n = 7;
glActiveTexture(GL_TEXTURE0+gl_shadow_bogus_texture_active_n);
glGenTextures(1, &gl_shadow_bogus_texture_buff_id);
glBindTexture(GL_TEXTURE_2D, gl_shadow_bogus_texture_buff_id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,tex_dim.x,tex_dim.y,0,GL_RGB,GL_UNSIGNED_BYTE,0);
//gen depth
gl_shadow_texture_active_n = 4;
glActiveTexture(GL_TEXTURE0+gl_shadow_texture_active_n);
glGenTextures(1, &gl_shadow_texture_buff_id);
glBindTexture(GL_TEXTURE_2D, gl_shadow_texture_buff_id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D,0,GL_DEPTH_COMPONENT16,1024,1024,0,GL_DEPTH_COMPONENT,GL_FLOAT,0);
glGenFramebuffers(1, &gl_shadow_framebuffer_id); //gen fb
glBindFramebuffer(GL_FRAMEBUFFER, gl_shadow_framebuffer_id); //bind fb
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gl_shadow_bogus_texture_buff_id, 0); //attach tex
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, gl_shadow_texture_buff_id, 0); //attach depth
note that the whole gl_shadow_bogus_texture_buff_id thing (the generation and binding of the color texture) is just an attempt to fill out the framebuffer, thus getting rid of the error. I don't actually care about the color data.
a further note is that the "color tex gen/bind" is not necessary on mac, and can be replaced with glDrawBuffer(GL_NONE) and glReadBuffer(GL_NONE). But I can't compile with those in for android...
You do not have a stencil attachment, which is likely why you've getting a GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT error. Although not explicitly stated in the spec, most drivers require a stencil attachment when a depth attachment is also present. However, depending on the implementation, you may run into problems, because using GL_DEPTH_COMPONENT16 with a stencil attachment may not be a supported combination (in fact, in my experience, it usually isn't). Each driver is only required to support at least one combination - unfortunately, there's no way to query exactly what the combination might be. You basically just have to guess and hope it succeeds.
The majority of Android implementations support the packed depth stencil format DEPTH24_STENCIL8_OES, and the extension implicitly supports the depth being a texture which can be sampled. You will likely have considerably more success using it (but success is not guarateed!).
In my Android 4.3 application, I would like to load a texture from a local png onto a TextureView. I do not know OpenGL and I am using the code from the GLTextureActivity hardware acceleration test. I am pasting also the loading texture part here:
private int loadTexture(int resource) {
int[] textures = new int[1];
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, textures, 0);
checkGlError();
int texture = textures[0];
glBindTexture(GL_TEXTURE_2D, texture);
checkGlError();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
Bitmap bitmap = BitmapFactory.decodeResource(mResources, resource);
GLUtils.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap, GL_UNSIGNED_BYTE, 0);
checkGlError();
bitmap.recycle();
return texture;
}
I am running the code in two devices: Nexus 7 and Galaxy Nexus phone, and I notice a huge speed difference between the two. For Nexus 7, the drawing part takes about 170 ms, although for the Galaxy Nexus it takes 459 ms. The most time consuming operation is the loading of the texture and especially the texImage2D call. I have read that there are devices with chips that are slow on texImage2D-texSubImage2D functions but how can someone tell which are those devices and how can I avoid to use those functions to achieve the same result?
Thank you in advance.
// EDIT: the glDrawArrays(GL_TRIANGLE_STRIP, 0, 4) call seems to also be significantly slower in the phone device. Why is this happening? How could I avoid it?
Are you loading textures on each frame redraw? That's just not right - you should load textures only once before main rendering loop. You won't get instant textures loading even on the fastest possible device - you load resource, decode bitmap from it and then load it to GPU. This takes some time.
I'm trying to render AV frames grabbed and converted from a MPEG4 video using Gstreamer to an Android (2.2)-opengl texture. I've pretty much exhausted google and not found an answer.
Basically, I am using Gstreamer uridecodebin to decode the frame, and then convert the frame to RGB, and then glTexSubImage2D() to create an openGL texture from it, but can't seem to get anything to work.The texture is getting colored when I get the decoded data (RGB) from Gstreamer.
I am getting the video size as 320 * 256 and my Texture size is 512 * 256 & I am using glDrawTexiOES(0,0,videowidth,videoheight), I am not getting any errors related to opengl, but the texture is blank( different color frames), though the Audio works fine.
Here is my code:Native OnDraw:
if (theGStPixelBuffer != 0) {
glBindTexture (GL_TEXTURE_2D, s_texture);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glPixelStorei( GL_UNPACK_ALIGNMENT, 2);
glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, theTexWidth,
theTexHeight, GL_RGB, GL_UNSIGNED_BYTE,
GST_BUFFER_DATA(theGStPixelBuffer));
check_gl_error("glTexSubImage2D");
theGStPixelBuffer = 0;
}
glDrawTexiOES(0, 0, 0, theTexWidth, theTexHeight);
check_gl_error("glDrawTexiOES")
I have encounter the same problem ;you can get the bitmap and use martix class to resize the bitmap.