When rendering two different surfaces in the same thread, I need to call eglMakeCurrent every time to unbind the current surface to the thread and to bind the other surface to the current thread before rendering a certain surface , while the operation of unbinding a surface to a thread consumes too much time!
SourceCode:
int DisplayPicture(...)
{
if (!eglMakeCurrent(m_glesDisplay ,m_glesSurface, m_glesSurface, m_glesContext))
{
return 0;
}
glUseProgram(programObject);
glActiveTexture( GL_TEXTURE0 );
glUniform1i(m_nUniformLocation[0],0);
glBindTexture( GL_TEXTURE_2D, 0);
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);
glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE, nWidth, nHeight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, pData );
....
// Update attribute values.
glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
glEnableVertexAttribArray(ATTRIB_VERTEX);
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, 0, 0, texCoords);
glEnableVertexAttribArray(ATTRIB_TEXCOORD);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
eglSwapBuffers(m_glesDisplay, m_glesSurface);
glUseProgram(0);
return 0;
}
ps:
1. When using texture in OpenGLES, eglMakeCurrent(display, NULL, NULL, NULL) will cost a long time, why?
2. In some devices, eglMakeCurrent will return EGL_BAD_ALLOC while normal in other devices, why?
Related
I am not very good with opengl es so any beginner mistake in the code is justified. I have implemented the draw function to execute the same fragment shader with different uniform variable called blurringDirection, if I execute the horizontal blurring alone(by setting the blurringDirection to 0) it works fine, also the same for the vertical but when I try to combine them together the second overrides the first. Here is my draw() function:
fun draw(
mvpMatrix: FloatArray?,
vertexBuffer: FloatBuffer?,
firstVertex: Int,
vertexCount: Int,
coordsPerVertex: Int,
vertexStride: Int,
texMatrix: FloatArray?,
texBuffer: FloatBuffer?,
textureId: Int,
texStride: Int,
) {
//creating an intermediate texture
val intermediateTexIdArr = IntArray(1)
GLES20.glGenTextures(1, intermediateTexIdArr, 0)
glBindTexture(GL_TEXTURE_2D, intermediateTexIdArr[0])
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 640, 360, 0, GL_RGBA, GL_UNSIGNED_BYTE, null)
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)
glBindTexture(GL_TEXTURE_2D, 0)
//creating a framebuffer and attaching the newly created texture to it.
val frameBufferIdArr = IntArray(1)
GLES20.glGenFramebuffers(1, frameBufferIdArr, 0)
glBindFramebuffer(GL_FRAMEBUFFER, frameBufferIdArr[0])
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, intermediateTexIdArr[0], 0)
val status = glCheckFramebufferStatus(GL_FRAMEBUFFER)
Timber.d("KingArmstring: Framebuffer status is complete? ${status == GL_FRAMEBUFFER_COMPLETE}") //this prints true
if (status != GL_FRAMEBUFFER_COMPLETE) throw Exception("Framebuffer is not setup correctly")
//bind to the framebuffer instead of to the screen.
glBindFramebuffer(GL_FRAMEBUFFER, frameBufferIdArr[0])
glClearColor(0.0f, 0.0f, 0.0f, 1.0f)
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
glEnable(GL_DEPTH_TEST)
glDepthFunc(GL_LEQUAL)
// Select the program.
glUseProgram(programHandle)
checkGlError("glUseProgram")
// Set the texture.
glActiveTexture(GL_TEXTURE0)
glBindTexture(textureTarget, textureId) //textureId is the main id that has the original image
// Copy the model / view / projection matrix over.
glUniformMatrix4fv(mvpMatrixLoc, 1, false, mvpMatrix, 0)
checkGlError("glUniformMatrix4fv")
// Copy the texture transformation matrix over.
glUniformMatrix4fv(texMatrixLoc, 1, false, texMatrix, 0)
checkGlError("glUniformMatrix4fv")
// Enable the "aPosition" vertex attribute.
glEnableVertexAttribArray(positionLoc)
checkGlError("glEnableVertexAttribArray")
// Connect vertexBuffer to "aPosition".
glVertexAttribPointer(
positionLoc, coordsPerVertex,
GL_FLOAT, false, vertexStride, vertexBuffer
)
checkGlError("glVertexAttribPointer")
// Enable the "aTextureCoord" vertex attribute.
glEnableVertexAttribArray(textureCoordLoc)
checkGlError("glEnableVertexAttribArray")
// Connect texBuffer to "aTextureCoord".
glVertexAttribPointer(
textureCoordLoc, 2,
GL_FLOAT, false, texStride, texBuffer
)
checkGlError("glVertexAttribPointer")
if (programType == VIDEO_STREAM) {
glUniform1f(brightnessLoc, brightness)
glUniform1f(contrastLoc, contrast)
glUniform1f(saturationLoc, saturation)
glUniform1f(gammaLoc, gamma)
glUniform1f(whiteBalanceTempLoc, whiteBalanceTemp)
glUniform1f(whiteBalanceTintLoc, whiteBalanceTint)
glUniform1f(whiteBalanceEnabledLoc, whiteBalanceEnabled)
glUniform1f(hueAdjLoc, hueAdj)
glUniform1f(hueAdjEnabledLoc, hueAdjEnabled)
glUniform1f(sharpnessLoc, sharpness)
glUniform1f(imageWidthFactorLoc, imageWidthFactor)
glUniform1f(imageHeightFactorLoc, imageHeightFactor)
}
glUniform1i(blurringDirectionLoc, 0)
// Draw the rect.
glDrawArrays(GL_TRIANGLE_STRIP, firstVertex, vertexCount)//rendering to the framebuffer with the blurringDirection = 0
checkGlError("glDrawElements")
glBindFramebuffer(GL_FRAMEBUFFER, 0)
glActiveTexture(GL_TEXTURE0)
glBindTexture(GL_TEXTURE_2D, intermediateTexIdArr[0])
glUniform1i(blurringDirectionLoc, 1)
glDrawArrays(GL_TRIANGLE_STRIP, firstVertex, vertexCount)//drawing on the screen second pass with the blurringDirection = 1.
glDisableVertexAttribArray(positionLoc)
glDisableVertexAttribArray(textureCoordLoc)
GLES20.glDeleteFramebuffers(1, frameBufferIdArr, 0)
GLES20.glDeleteTextures(1, intermediateTexIdArr, 0)
}
I am trying to do multi pass rendering with framebuffer the issue is that the source is the camera so the texInput is not of type GL_TEXTURE_2D it is of type GL_TEXTURE_EXTERNAL_OES tho, if I use the function glTexImage2D it gives a black screen when I use that texture in the future after rendering to it without any errors glErros.
On the other hand if I don't use it(because it does not support GL_TEXTURE_EXTERNAL_OES) it gives me framebuffer status of NOT_COMPLETE
here is my code for creating the framebuffer and the texture that I want to associate to it.
fun prepareFBO() {
val intArray = IntArray(1)
glGenFramebuffers(1, intArray, 0)
fboId = intArray.first()
glGenTextures(1, intArray, 0)
texId = intArray.first()
glBindTexture(GL_TEXTURE_2D, texId)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,1080, 1920, 0, GL_RGBA, GL_UNSIGNED_BYTE, null)
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)
glBindFramebuffer(GL_FRAMEBUFFER, fboId)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texId, 0)
val status = glCheckFramebufferStatus(GL_FRAMEBUFFER)
Log.e(TAG, "prepareFBO: ${status == GL_FRAMEBUFFER_COMPLETE}")
glBindFramebuffer(GL_FRAMEBUFFER, 0)
glBindTexture(GL_TEXTURE_2D, 0)
}
the rest is just normal glDrawArrays and glActiveTexture that already works fine when I draw directly to the default framebuffer, if needed please let me know and I will share them.
Thanks for help!
UPDATE:
I found that I need instead of using glTexImage2d I can use eglBindTexImage instead so the final code is:
fun prepareFBO() {
val intArray = IntArray(1)
glGenFramebuffers(1, intArray, 0)
fboId = intArray.first()
glBindFramebuffer(GL_FRAMEBUFFER, fboId)
glGenTextures(1, intArray, 0)
texId = intArray.first()
glBindTexture(GL_TEXTURE_EXTERNAL_OES, texId)
checkGlError("Error 1")
eglBindTexImage(eglGetCurrentDisplay(), windowSurface!!.eglSurface, EGL_BACK_BUFFER)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_EXTERNAL_OES, texId, 0)
val status = glCheckFramebufferStatus(GL_FRAMEBUFFER)
Log.e(TAG, "prepareFBO: is status complete? => ${status == GL_FRAMEBUFFER_COMPLETE}")
}
while this looks like it makes sense, still I am getting the status of the framebuffer as not complete :/
I have generated a frame buffer object(FBO), bind it, attached a texture to its GL_COLOR_ATTACHMENT0. Then ensure that I get its status as GL_FRAMEBUFFER_COMPLETE. I have another texture(which is displaying on display), let's call it workingTexture. Now I want to render this workingTexture onto FBO, so I bind this FBO and then render workingTexture.
Then I bind default frame buffer(reserved for display) and try to render the texture attached to FBO, thinking that I will get my texture onto display, but I get black texture.
Relevant code
code to generate workingTexture...
int[] workingTexture = new int[1];
glGenTextures(1, workingTexture, 0); // generate workingTexture
glActiveTexture(GL_TEXTURE0); // attach it to TEXTURE_UNIT0
glBindTexture(GL_TEXTURE_2D, workingTexture[0]);
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_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
code to generate fbo
int[] fboName = new int[1];
int[] fboTextureName = new int[1];
final int fboTextureUnit = 1; // attach this texture to texture unit GL_TEXTURE1
glGenFramebuffers(1, fboName, 0);
int generatedTextureNameForFBO =
generateTextureForFBO(fboTextureUnit,
width, height);
fboTextureName[0] = generatedTextureNameForFBO;
glBindFramebuffer(GL_FRAMEBUFFER, fboName[0]);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, generatedTextureNameForFBO, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
// created FBO is not complete
throw new RuntimeException("FBO status INCOMPLETE 😔😔");
}
method used to generate texture attached to fbo
private int generateTextureForFBO(#IntRange(from = 0) final int textureUnit,
#IntRange(from = 1) final int width,
#IntRange(from = 1) final int height) {
int[] textureName = new int[1];
glGenTextures(1, textureName, 0);
glActiveTexture(GL_TEXTURE0 + textureUnit);
glBindTexture(GL_TEXTURE_2D, textureName[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, null);
// glBindTexture(GL_TEXTURE_2D, 0);
// 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_MIRRORED_REPEAT);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
// glBindTexture(GL_TEXTURE_2D, 0);
return textureName[0];
}
Now coming to drawing part...
#Override
public void onDrawFrame(GL10 unused) {
glClear(GL_COLOR_BUFFER_BIT);
//renderTex(mViewMatrix, 0, texProgram); // this texture is drawing on screen
glBindFramebuffer(GL_FRAMEBUFFER, fboName[0]);
renderTex(mViewMatrix, 0, texProgram); // rendering workingTexture onto FBO
glBindFramebuffer(GL_FRAMEBUFFER, 0);
renderTex(mViewMatrix, fboTextureUnit[0], texProgram); // texture appears black
}
renderTex is a simple method to render texture. It is working fine.
Also I have checked for GL_ERROR but there is no error.
My understanding of application created FBO is that every read and write glCall will happen on currently bound FBO, so is my understanding of FBO incorrect, or is there some error in my code.
Platform OpenGL|es 20 on Android
The texture which is generated in generateTextureForFBO is mipmap incomplete.
If you do not generate mipmaps (by glGenerateMipmap), then setting the GL_TEXTURE_MIN_FILTER is important. Since the default filter is GL_NEAREST_MIPMAP_LINEAR the texture would be mipmap incomplete, if you don not change the minifying function to GL_NEAREST or GL_LINEAR.
Set the texture minifying function (GL_TEXTURE_MIN_FILTER) by glTexParameter:
glBindTexture(GL_TEXTURE_2D, textureName[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, null);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
I have OpenGL ES 3.0 and I'm trying to create a texture:
case 1: glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, width, height, 0, GL_RED, GL_HALF_FLOAT, 0); break;
case 2: glTexImage2D(GL_TEXTURE_2D, 0, GL_RG16F, width, height, 0, GL_RG, GL_HALF_FLOAT, 0); break;
case 3: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_HALF_FLOAT, 0); break;
(for this code glGetError() return 0)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureHandle, 0);
But when attaching to framebuffer the glCheckFramebufferStatus(GL_FRAMEBUFFER) return 36054.
Surface CreateSurface(GLsizei width, GLsizei height, int numComponents)
{
GLuint fboHandle;
glGenFramebuffers(1, &fboHandle);
glBindFramebuffer(GL_FRAMEBUFFER, fboHandle);
GLuint textureHandle;
glGenTextures(1, &textureHandle);
glBindTexture(GL_TEXTURE_2D, textureHandle);
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);
switch (numComponents) {
case 1: glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, width, height, 0, GL_RED, GL_HALF_FLOAT, 0); break;
case 2: glTexImage2D(GL_TEXTURE_2D, 0, GL_RG16F, width, height, 0, GL_RG, GL_HALF_FLOAT, 0); break;
case 3: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_HALF_FLOAT, 0); break;
default: PezFatalError("Illegal slab format.");
}
PezCheckCondition(GL_NO_ERROR == glGetError(), "Unable to create normals texture");
GLuint colorbuffer;
glGenRenderbuffers(1, &colorbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, colorbuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureHandle, 0);
PezCheckCondition(GL_NO_ERROR == glGetError(), "Unable to attach color buffer");
PezCheckCondition(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER), "Unable to create FBO.");
Surface surface = { fboHandle, textureHandle, numComponents };
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
return surface;
}
What am I doing wrong?
Textures attached to GL_COLOR_ATTACHMENTn are required to use color-renderable format. Unfortunately, float formats are not color-renderable. For list of color-renderable formats, check Table 3.12 in http://www.khronos.org/registry/gles/specs/3.0/es_spec_3.0.2.pdf
Due to performance issues, I have had to transfer my android opengl code from Java to C. I believe I transfered all of the OpenGL code, but I now have many errors with the section of my code that draws a bitmap as a texture to the screen.
When I run the project in an emulator, the current code does not display anything and appears to have a memory leak because it slowly takes up all the memory and forces other apps to close.
Here is the code that controls this part:
In the header file:
extern unsigned char colors[1024*512*3]; // 3 bytes per pixel
In the c file:
void appRender(int width, int height, unsigned char colors)
{
unsigned int textureID;
float vertices[] =
{
0.0f, 0.0f,
512.0f, 0.0f,
0.0f, 1024.0f,
512.0f, 1024.0f
};
float texture[] =
{
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f
};
unsigned char indices[] =
{
0, 1, 3,
0, 3, 2
};
UpdateView();
//onDraw
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glOrthof(0.0f, 320.0f, 430.0f, 0.0f, 1.0f, -1.0f);
//texture stuff
glGenTextures(1,&textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//Different possible texture parameters, e.g
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 512, 1024, 0, GL_RGB ,GL_UNSIGNED_BYTE, colors);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, texture);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
Any help would be greatly appreciated.
There does not appear to be a call to glEnable(GL_TEXTURE_2D) to enable texturing in your example.
You can call glGetError() to find out if what you are doing is incorrect. This has helped me debug problems in the past.
Also you appear to be creating your texture in your appRender() method. If this is called for every frame you draw then it could be the cause of your memory leak as you are repeatedly recreating the same texture.
Typically you should only generate and define the texture once during initialization.
So the following should be done once before rendering.
glGenTextures(1,&textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//Different possible texture parameters, e.g
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 512, 1024, 0, GL_RGB ,GL_UNSIGNED_BYTE, colors);
Then when drawing you can do
glEnable(GL_TEXTURE_2D)
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindTexture(GL_TEXTURE_2D, textureID);
glVertexPointer(2, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, texture);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D)