Android:Adreno 530 GPU上的glReadPixels图像不完整
有没有人经历过类似的事情,或者可以指出问题可能出现在下面的代码中?由于某种原因,屏幕截图中会出现透明的“点”。并不是每一帧,也许每一秒 我看到Adreno530GPU(LG G6,谷歌像素)有一些奇怪的行为,其他GPU工作正常。我认为存在一些线程问题,因为它在主线程上运行良好。事情是这样的 我有一个原生的Android插件,它拍摄了Unity项目(OpenGLES3)的屏幕截图。OpenGL上下文是在后台线程中从Unity复制的。构造函数如下所示:Android:Adreno 530 GPU上的glReadPixels图像不完整,android,multithreading,unity3d,opengl-es,glreadpixels,Android,Multithreading,Unity3d,Opengl Es,Glreadpixels,有没有人经历过类似的事情,或者可以指出问题可能出现在下面的代码中?由于某种原因,屏幕截图中会出现透明的“点”。并不是每一帧,也许每一秒 我看到Adreno530GPU(LG G6,谷歌像素)有一些奇怪的行为,其他GPU工作正常。我认为存在一些线程问题,因为它在主线程上运行良好。事情是这样的 我有一个原生的Android插件,它拍摄了Unity项目(OpenGLES3)的屏幕截图。OpenGL上下文是在后台线程中从Unity复制的。构造函数如下所示: this.handlerThread
this.handlerThread = new HandlerThread("UnityScreenCapture");
this.handlerThread.start();
this.handler = new Handler(handlerThread.getLooper());
final EGLContext currentContext = EGL14.eglGetCurrentContext();
final EGLDisplay currentDisplay = EGL14.eglGetCurrentDisplay();
final int[] eglContextClientVersion = new int[1];
eglQueryContext(currentDisplay,
currentContext,
EGL14.EGL_CONTEXT_CLIENT_VERSION,
eglContextClientVersion,
0
);
this.handler.post(new Runnable() {
@Override
public void run() {
final EGLDisplay eglDisplay = eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
final int[] version = new int[2];
eglInitialize(eglDisplay, version, 0, version, 1);
int[] configAttributes = {EGL14.EGL_COLOR_BUFFER_TYPE,
EGL14.EGL_RGB_BUFFER,
EGL14.EGL_LEVEL,
0,
EGL14.EGL_RENDERABLE_TYPE,
EGL14.EGL_OPENGL_ES2_BIT,
EGL14.EGL_SURFACE_TYPE,
EGL14.EGL_PBUFFER_BIT,
EGL14.EGL_NONE};
final EGLConfig[] eglConfigs = new EGLConfig[1];
final int[] numConfig = new int[1];
eglChooseConfig(eglDisplay, configAttributes, 0, eglConfigs, 0, 1, numConfig, 0);
final EGLConfig eglConfig = eglConfigs[0];
int[] surfaceAttributes = {EGL14.EGL_WIDTH, 1, EGL14.EGL_HEIGHT, 1, EGL14.EGL_NONE};
EGLSurface eglSurface = eglCreatePbufferSurface(eglDisplay,
eglConfig,
surfaceAttributes,
0
);
int[] contextAttributes = {EGL14.EGL_CONTEXT_CLIENT_VERSION,
eglContextClientVersion[0],
EGL14.EGL_NONE};
final EGLContext eglContext = eglCreateContext(eglDisplay,
eglConfig,
currentContext,
contextAttributes,
0
);
eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
}
});
}
然后,当我拍摄屏幕截图时,我调用相同的背景线程以避免阻塞主线程:
handler.post(new Runnable() {
@Override
public void run() {
frame.setBytes(native_readFrame(frame.getBytes()));
callback.capturedFrame(frame);
}
});
本机_readFrame如下所示(精简):
更新
如果我在readFrame之前调用main右侧的glFinish(),它就会工作。但是glFinish是一个沉重的操作,它会将主线程阻塞10毫秒,这并不理想。在读取帧之前,必须确保帧已经渲染 Opengl具有客户机-服务器体系结构。cpu发出gpu draw调用,该调用不会阻塞cpu线程。gpu将安排这些调用稍后执行,但如果调用glFlush(),则可以强制它们立即开始执行。另一方面,glFinish()除了调用glFlush()之外,还使客户端等待 由于对gpu的请求可能来自不同的线程,我建议您看看如何同步它们:
mcluint texture = capture_context->texture;
if (capture_context->framebuffer == 0) {
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
mcluint framebuffer;
// Generate framebuffer
glGenFramebuffers(1, &framebuffer);
// Bind texture to framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
capture_context->framebuffer = framebuffer;
}
int width = capture_context->width;
int height = capture_context->height;
rect_t crop = capture_context->crop;
glBindTexture(GL_TEXTURE_2D, texture);
glBindFramebuffer(GL_FRAMEBUFFER, capture_context->framebuffer);
mclbyte *pixels = NULL;
if (dst != NULL) {
pixels = *dst;
} else {
pixels = (mclbyte *) malloc(crop.width * crop.height * sizeof(mclbyte) * 4);
}
glReadPixels(crop.x, crop.y, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
pixels);
if (length != NULL) {
*length = crop.width * crop.height * sizeof(mclbyte) * 4;
}
return pixels;