Java 在后台线程中初始化OpenGL上下文
因此,我在解决android的屏幕外渲染问题时遇到了一些困难,并且找不到解决方案。请记住,我在所有与OpenGL相关的事情上都是新手,所以如果我做出任何错误的陈述,我会提前道歉 这个android进程的目标是在用户看不到的情况下在后台线程中将内容渲染到位图上(从而进行屏幕外渲染)。我用来渲染这些东西的库要求我在使用工具渲染方法之前手动设置OpenGL上下文。初始化OpenGL上下文并将其绑定到线程后,我需要将位图加载到OpenGL纹理(由GLES20.glGenTextures(..)创建)。不过,我无法详细了解图书馆的情况 问题是:我不知道如果不使用GLSurfaceView,如何在android中设置OpenGL上下文,对它的每次搜索都会将我重定向到基于这个SurfaceView的某种解决方案。所以我需要一个起点来找出如何在后台线程中有效地调用GLES20 我所知道的是,我需要使用EGL14提供的方法来设置它:Java 在后台线程中初始化OpenGL上下文,java,android,opengl-es,rendering,Java,Android,Opengl Es,Rendering,因此,我在解决android的屏幕外渲染问题时遇到了一些困难,并且找不到解决方案。请记住,我在所有与OpenGL相关的事情上都是新手,所以如果我做出任何错误的陈述,我会提前道歉 这个android进程的目标是在用户看不到的情况下在后台线程中将内容渲染到位图上(从而进行屏幕外渲染)。我用来渲染这些东西的库要求我在使用工具渲染方法之前手动设置OpenGL上下文。初始化OpenGL上下文并将其绑定到线程后,我需要将位图加载到OpenGL纹理(由GLES20.glGenTextures(..)创建)。不
eglCreateContext(...);
eglMakeCurrent(...);
eglInitialize(...);
但是因为文档是不存在的,我很难弄清楚要使用什么参数,甚至是使用它们的组合/顺序
非常感谢您的帮助
编辑:只是澄清一下,我并不反对基于GLSURFACHEVIEW的解决方案,但据我所知,它们都需要出现在屏幕上,这是我绝对不能做到的
编辑2: 因此,在进一步挖掘之后,我偶然发现了一些看起来相当不错的东西:
mEgl = (EGL10) EGLContext.getEGL();
mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
if (mEglDisplay == EGL10.EGL_NO_DISPLAY)
throw new RuntimeException("Error: eglGetDisplay() Failed "
+ GLUtils.getEGLErrorString(mEgl.eglGetError()));
int[] version = new int[2];
if (!mEgl.eglInitialize(mEglDisplay, version))
throw new RuntimeException("Error: eglInitialize() Failed "
+ GLUtils.getEGLErrorString(mEgl.eglGetError()));
maEGLconfigs = new EGLConfig[1];
int[] configsCount = new int[1];
int[] configSpec = new int[]
{
EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL10.EGL_RED_SIZE, 8,
EGL10.EGL_GREEN_SIZE, 8,
EGL10.EGL_BLUE_SIZE, 8,
EGL10.EGL_ALPHA_SIZE, 8,
EGL10.EGL_DEPTH_SIZE, 0,
EGL10.EGL_STENCIL_SIZE, 0,
EGL10.EGL_NONE
};
if ((!mEgl.eglChooseConfig(mEglDisplay, configSpec, maEGLconfigs, 1, configsCount)) || (configsCount[0] == 0))
throw new IllegalArgumentException("Error: eglChooseConfig() Failed "
+ GLUtils.getEGLErrorString(mEgl.eglGetError()));
if (maEGLconfigs[0] == null)
throw new RuntimeException("Error: eglConfig() not Initialized");
int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE};
mEglContext = mEgl.eglCreateContext(mEglDisplay, maEGLconfigs[0], EGL10.EGL_NO_CONTEXT, attrib_list);
下一个电话是:
final int[] textureHandle = {0};
GLES20.glGenTextures(1, textureHandle, 0);
但是textureHandle[0]仍然是0。此外,它还会将错误打印到控制台:
E/libEGL: call to OpenGL ES API with no current context
因此,如果我们忽略这个问题,即代码使用旧的EGL10方法,它仍然不能正常工作。我这里缺少什么?下面的函数设置与OpenGL ES 1.x兼容的渲染上下文。您可以修改创建上下文函数的attrib列表,以创建与OpenGL ES 2.x兼容的渲染上下文
void initializeEGL() {
//get access to the EGL object, so that we can
//initialize EGL
mEGL = (EGL10) EGLContext.getEGL();
//initialize display
mDisplay = mEGL.eglGetDisplay(EGL11.EGL_DEFAULT_DISPLAY);
if(mDisplay == EGL11.EGL_NO_DISPLAY)
{
Log.e("SimpleGLView", "Unable to get access to Native Display");
}
int[] version = new int[2];
boolean success = mEGL.eglInitialize(mDisplay, version);
if(!success) {
int error = mEGL.eglGetError();
switch(error) {
case EGL11.EGL_NOT_INITIALIZED:
Log.e("SimpleGLView", "Unable to initialize the EGL sub-system");
break;
case EGL11.EGL_BAD_DISPLAY:
Log.e("SimpleGLView", "Display not valid");
break;
}
return;
}
int[] mConfigSpec = { EGL11.EGL_RED_SIZE, 8,
EGL11.EGL_GREEN_SIZE, 8,
EGL11.EGL_BLUE_SIZE, 8,
EGL11.EGL_DEPTH_SIZE, 16,
EGL11.EGL_STENCIL_SIZE, 8,
EGL11.EGL_NONE };
EGLConfig[] configs = new EGLConfig[1];
int[] num_config = new int[1];
success = mEGL.eglChooseConfig(mDisplay, mConfigSpec, configs, 1, num_config);
if(success) {
Log.i("SimpleGLView", "Successfully acquired a surface configuration");
return;
}
mConfig = configs[0];
mSurface = mEGL.eglCreateWindowSurface(mDisplay,mConfig, holder, null);
if(mSurface == EGL11.EGL_NO_SURFACE) {
Log.e("SimpleGLView", "Unable to create surface");
int error = mEGL.eglGetError();
switch(error) {
case EGL11.EGL_BAD_CONFIG:
Log.e("SimpleGLView", "Invalid configuration selected");
break;
case EGL11.EGL_BAD_NATIVE_WINDOW:
Log.e("SimpleGLView", "Bad native window used");
break;
case EGL11.EGL_BAD_ALLOC:
Log.e("SimpleGLView", "Not enough resources to create a surface");
break;
}
return;
}
mContext = mEGL.eglCreateContext(mDisplay, mConfig, EGL11.EGL_NO_CONTEXT, null);
if(mContext == null) {
Log.i("SimpleGLView", "Create Context failed");
return;
}
success = mEGL.eglMakeCurrent(mDisplay, mSurface, mSurface, mContext);
if(success) {
Log.i("SimpleGLView", "Made current");
}
}
我不确定是否应该在EGL14这样的类中创建上下文。上下文通常由一个属性生成,该属性指示要使用的版本。之后,使用相应的API。你能从另一个问题egl.eglCreateContext中检查一下吗。缺少对eglCreateSurface和eglMakeCurrent()函数的调用。在创建渲染上下文之前,必须先创建一个曲面,然后在创建渲染上下文之后,必须将其设置为当前的。@MaticOblak我不确定我是否理解您的意思。在我的例子的最底层,我完全按照你说的去做(至少从你提供的链接来看我是这样认为的)。啊,我现在明白了,你在没有编辑的情况下写了关于原始帖子的文章。是的,你说得对。我只是使用示例EGL14.egl….()来说明该方法属于哪个类。我不是有意暗示,它们是静态的方法。我将编辑我的问题以避免误解。代码第35行开始的代码片段对我来说有点奇怪。如果我成功选择了配置,为什么要调用return?这样做不会为线程创建有效的上下文,因为mEGL.eglMakeCurrent(…)不会被调用,或者我在这里遗漏了什么吗?不管怎样,我找到了一种方法使它能够满足我的目的,你的代码帮了我很多忙,谢谢!我会接受你的答案,并在我完成并满意后尽快发布我编辑的答案。你是对的,不需要返回。不知道那是怎么进来的:)。感谢您纠正错误。小更新:很遗憾,我无法升级到EGL20,因为我必须使用的库显然不支持它。好吧,它起作用了,就是这样。再次感谢:)