有没有人遇到类似的问题,或者可以指出问题可能出现在下面的代码中?出于某种原因,屏幕截图中出现透明的“点”。并非所有帧都可能每秒都有。
我看到Adreno 530 GPU(LG G6,Google Pixel)的一些奇怪行为,其他GPU工作正常。我认为有一些线程问题,因为它在主线程上工作正常。这是交易。
我有一个原生的Android插件,它截取Unity项目的截图(OpenGLES3)。 OpenGL上下文在后台线程中从Unity复制。构造函数如下所示:
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);
}
});
}
然后当我拍摄截图时,我会调用相同的后台线程以避免阻塞main:
handler.post(new Runnable() {
@Override
public void run() {
frame.setBytes(native_readFrame(frame.getBytes()));
callback.capturedFrame(frame);
}
});
native_readFrame看起来像这样(剥离):
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;
更新 如果我在readFrame之前调用主右边的glFinish(),它就可以了。但glFinish是一个重大的操作阻止主线程10ms,这是不理想的。
答案 0 :(得分:0)
您必须确保在读取框架之前已经渲染了框架。
Opengl有一个客户端 - 服务器架构。 cpu给出了gpu draw调用,它不会阻塞cpu线程。 gpu将安排这些调用稍后执行,但如果调用glFlush(),则可以强制它们立即开始执行。另一方面,glFinish()使客户端等待除了调用glFlush()。
由于对gpu的请求可能来自不同的线程,我建议你看看如何同步它们: