ANDROID “call to opengl es api with no current context”错误的解决

1,背景:android pad项目中使用到google实景(panorama)的项目,该项目中应用到opengl的一些底层,该问题就是opengl底层出现问题时的表现。

2,症状:在项目中有两个activity(a,b,b为实景,通过a来启动),如果a,b在AndroidManifest.xml均关闭硬件加速( android:hardwareAccelerated="false")则实景可用,但a开硬件加速,b关闭硬件加速的话,则b中的实景不可用,表现为只展示图片,不能随着角度滚动展示。

3,问题的解释:

 (1)question:   am new to both openGL and android development so please forgive me if my question is very trivial.

I am trying to build a simple little app that takes input from the user in three EditTexts representing a 0 - 100% value for each component of a RGB color to be displayed in a GLSurfaceView.

The catch is that I need this to use openGL ES 2.0 and I need to pass the data into the shading program using a uniform value so that once I get it working I can move on to what I am really trying to accomplish.

Upon running what I have written I can get the GLSurfaceView to correctly display the first solid color, but whenever I change any of the values and make calls to rebuild the uniform slot in the shading program I get this error in the LogCat:

ERROR/libEGL(14316): call to OpenGL ES API with no current context (logged once per thread)

and of course the GLSurfaceView remains the initial color.

I've been searching all over for a solution to this problem and as best I can tell I might need to be setting up an EGLContext somewhere before setting my renderer. However, I don't see anything in the API demos about this, and the only information I can find online was written before GLSurfaceView was even available.

Do I need to set up an EGLContext still or have I missed something else? 

Additional info that may help:

-used an XML file to set up the UI (and as far as I can tell doing it in code doesn't help)

-having the same trouble when I try to load in a new texture from the sd card in a seperate program. I can get the first texture to work fine, but when using the same method to load the second I get the same error and nothing changes.

answer: You're not calling it from the OpenGL thread. If a different thread is trying to do something with OpenGL, queue that up and call it during your OpenGL thread instead.

 

(2)

这里使用到了线程局部存储机制,这是一个什么东东呢?

概念:线程局部存储(Thread Local Storage,TLS)用来将数据与一个正在执行的指定线程关联起来。

进程中的全局变量与函数内定义的静态(static)变量,是各个线程都可以访问的共享变量。在一个线程修改的内存内容,对所有线程都生效。这是一个优点也是一个缺点。说它是优点,线程的数据交换变得非常快捷。说它是缺点,一个线程死掉了,其它线程也性命不保; 多个线程访问共享数据,需要昂贵的同步开销,也容易造成同步相关的BUG。

如果需要在一个线程内部的各个函数调用都能访问、但其它线程不能访问的变量(被称为static memory local to a thread 线程局部静态变量),就需要新的机制来实现。这就是TLS。

功能:它主要是为了避免多个线程同时访存同一全局变量或者静态变量时所导致的冲突,尤其是多个线程同时需要修改这一变量时。为了解决这个问题,我们可以通过TLS机制,为每一个使用该全局变量的线程都提供一个变量值的副本,每一个线程均可以独立地改变自己的副本,而不会和其它线程的副本冲突。从线程的角度看,就好像每一个线程都完全拥有该变量。而从全局变量的角度上来看,就好像一个全局变量被克隆成了多份副本,而每一份副本都可以被一个线程独立地改变。

 

好了,介绍完毕,下面介绍系统中代码如何体现的:

由于OpenGL是一个其于上下文Context 环境开发的,所以每个线程需要保存自已的运行环境,如果没有的话则会报错:

"call to OpenGL ES API with no current context logged once per thread"

4,解决办法:

在com.android.panoramagl.iphone.EAGLContext文件中修改红色位置,然后重新jar在项目中引用。

public static boolean setCurrentContext(EAGLContext context)
{
try
{
EGL10 egl = (EGL10)EGLContext.getEGL();
if(context == null)
egl.eglMakeCurrent(currentContext == null ? egl.eglGetCurrentDisplay() : currentContext.getDisplay(), EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
else //if(currentContext != context)
{
egl.eglMakeCurrent(context.getDisplay(), context.getSurface(), context.getSurface(), context.getContext());
currentContext = context;
}
return true;
}
catch(Exception ex)
{
Log.e("setCurrentContext", "Error can't setCurrentContext:" + ex.getMessage());
}
return false;
}

5.另一种解决方式:

在Android项目中,开启设备的硬件加速的话,可能会解决这个问题。但具体的原因我研究完底层的调用后写出

具体做法:

在Android Mainfest 的applicaiton节点下添加

<application android:hardwareAccelerated="true">

### 关于 OpenGL 的初始化和使用 #### 什么是 OpenGLOpenGL 是一种跨平台的图形处理库,用于实现二维和三维矢量图形的硬件加速渲染。通过调用其 API 函数,开发者可以在多种平台上开发高性能的图形应用程序。 --- #### 如何初始化 OpenGL? ##### Windows 平台下的 OpenGL 初始化 在 Windows 下,可以通过以下方式完成 OpenGL 的初始化: 1. **加载必要的头文件** 需要引入 `GL/gl.h` 和其他相关头文件来访问 OpenGL 功能。 2. **创建窗口上下文** 使用 WinAPI 创建一个窗口,并设置像素格式以支持 OpenGL 渲染[^1]。 3. **启用 OpenGL 上下文** 调用 `wglCreateContext()` 来创建 OpenGL 上下文,并将其激活以便后续操作。 以下是基于 C++ 的简单代码示例: ```cpp #include <windows.h> #include <GL/gl.h> // 定义全局变量 HDC hDC; HGLRC hRC; void initOpenGL(HWND hwnd) { PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; int pixelFormat = ChoosePixelFormat(hDC, &pfd); SetPixelFormat(hDC, pixelFormat, &pfd); hRC = wglCreateContext(hDC); // 创建 OpenGL 上下文 wglMakeCurrent(hDC, hRC); // 激活上下文 } ``` 4. **清理资源** 当不再需要 OpenGL 上下文时,应释放相关资源以避免内存泄漏。 ```cpp void cleanup() { if (hRC) { wglDeleteContext(hRC); hRC = NULL; } } ``` --- ##### Android 平台上 Native 工程中的 OpenGL 初始化 对于 Android 应用程序,在原生层(C/C++)中初始化 OpenGL ES 可能涉及以下几个步骤[^3]: 1. **配置 EGL 显示环境** 使用 EGL 提供的功能来管理 OpenGL ES 的显示表面、上下文以及同步机制。 2. **绑定到现有 WindowSurface** 将创建好的 EGLSurface 对象与当前活动窗口关联起来。 下面是一个简单的伪代码片段展示如何执行这些任务: ```c++ EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(display, nullptr, nullptr); EGLConfig config; int numConfigs; eglChooseConfig(display, attribList, &config, 1, &numConfigs); EGLSurface surface = eglCreateWindowSurface(display, config, native_window, attributes); EGLContext context = eglCreateContext(display, config, NULL, contextAttribs); if (!eglMakeCurrent(display, surface, surface, context)) { LOGE("Failed to make current"); } // 开始绘图... ``` --- #### 基本的 OpenGL 图形渲染流程 一旦成功完成了上述初始化过程,则可以按照如下顺序来进行基本的图形绘制工作流: 1. 设置视口(Viewport),定义屏幕区域大小; 2. 加载着色器(shader programs),编写顶点/片元着色器源码并编译链接成可执行形式; 3. 构建几何数据结构(VBO/VAO etc.)存储模型信息; 4. 执行实际的draw call命令提交给GPU进行最终呈现; 例如一段典型的三角形绘制逻辑可能看起来像这样: ```cpp GLuint programID = LoadShaders("SimpleVertexShader.vertexshader", "SimpleFragmentShader.fragmentshader"); glUseProgram(programID); GLfloat vertices[] = {-0.5f,-0.5f,0.f , 0.5f,-0.5f,0.f , 0.f,0.5f,0.f}; GLuint vertexbuffer; glGenBuffers(1,&vertexbuffer); glBindBuffer(GL_ARRAY_BUFFER,vertexbuffer); glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,(void*)0 ); glDrawArrays(GL_TRIANGLES,0,3); ``` 以上就是有关于怎样利用OpenGL来做初步设定还有基础图像输出的一个概括说明. ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值