Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android:Adreno 530 GPU上的glReadPixels图像不完整_Android_Multithreading_Unity3d_Opengl Es_Glreadpixels - Fatal编程技术网

Android:Adreno 530 GPU上的glReadPixels图像不完整

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

有没有人经历过类似的事情,或者可以指出问题可能出现在下面的代码中?由于某种原因,屏幕截图中会出现透明的“点”。并不是每一帧,也许每一秒

我看到Adreno530GPU(LG G6,谷歌像素)有一些奇怪的行为,其他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);
        }
    });
}
然后,当我拍摄屏幕截图时,我调用相同的背景线程以避免阻塞主线程:

    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;