Bug 85869

Summary: Offscreen rendering to pixmap EGLSurface is odd
Product: Mesa Reporter: Rinat <ibragimovrinat>
Component: EGLAssignee: mesa-dev
Status: RESOLVED MOVED QA Contact:
Severity: normal    
Priority: medium CC: ibragimovrinat, lemody
Version: unspecified   
Hardware: x86-64 (AMD64)   
OS: Linux (All)   
Whiteboard:
i915 platform: i915 features:

Description Rinat 2014-11-04 17:33:41 UTC
When I render to a EGLSurface bound to an offscreen pixmap, then copy pixmap content to a window using XCopyArea, behaviour is odd.

Sample program below calls glClear() twice. First time it should make all pixmap red, second time — green. But when I run it on the integrated Intel adapter, it renders only red box. It seems all drawing commands after first glClear() are ignored.

My research have stopped at fb->_NumColorDrawBuffers becoming 0 in _mesa_drawbuffers(). Probably that was the immediate reason second glClear() was ignored.

#include <X11/Xlib.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>


Window      wnd;
Window      root_wnd;
Display    *dpy;
Pixmap      pixmap;
EGLDisplay  egl_dpy;
EGLContext  glc;
EGLSurface  egl_surf;


void
handle_graphics_expose(XEvent *ev)
{
    EGLBoolean ret;

    ret = eglMakeCurrent(egl_dpy, egl_surf, egl_surf, glc);
    if (!ret) {
        printf("eglMakeCurrent failed\n");
        exit(1);
    }
    printf("eglMakeCurrent ok\n");

    glClearColor(1, 0, 0, 1);
    glClear(GL_COLOR_BUFFER_BIT);

    glClearColor(0, 1, 0, 1);
    glClear(GL_COLOR_BUFFER_BIT);

    glFinish();
    eglWaitGL();

    XCopyArea(dpy, pixmap, wnd, DefaultGC(dpy, 0),
              0, 0, 400, 300, 10, 10);
    XSync(dpy, False);
}

int
main(void)
{
    dpy = XOpenDisplay(NULL);
    root_wnd = DefaultRootWindow(dpy);
    wnd = XCreateSimpleWindow(dpy, root_wnd, 0, 0, 400+20, 300+20, 0, 0, 0xa0a0f0);

    printf("root_wnd = %p\n", (void *)root_wnd);

    XSelectInput(dpy, wnd, ExposureMask);
    XMapWindow(dpy, wnd);
    XSync(dpy, False);
    printf("wnd = %p\n", (void *)wnd);

    egl_dpy = eglGetDisplay(dpy);
    eglInitialize(egl_dpy, NULL, NULL);

    int nconfigs = -1;
    EGLConfig egl_config;
    EGLint cfg_attrs[] = { EGL_ALPHA_SIZE, 0,
                           EGL_BLUE_SIZE, 8,
                           EGL_GREEN_SIZE, 8,
                           EGL_RED_SIZE, 8,
                           EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
                           EGL_SURFACE_TYPE, EGL_PIXMAP_BIT,
                           EGL_NONE };
    eglChooseConfig(egl_dpy, cfg_attrs, &egl_config, 1, &nconfigs);

    printf("nconfigs = %d\n", nconfigs);
    printf("egl_config = %p\n", egl_config);

    EGLint ctx_attrs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
    glc = eglCreateContext(egl_dpy, egl_config, EGL_NO_CONTEXT, ctx_attrs);
    if (glc == EGL_NO_CONTEXT) {
        printf("eglCreateContext returned EGL_NO_CONTEXT\n");
        exit(1);
    }
    printf("context ok\n");

    pixmap = XCreatePixmap(dpy, wnd, 400, 300, DefaultDepth(dpy, 0));
    egl_surf = eglCreatePixmapSurface(egl_dpy, egl_config, pixmap, NULL);
    if (egl_surf == EGL_NO_SURFACE) {
        printf("eglCreatePixmapSurface returned EGL_NO_SURFACE\n");
        exit(1);
    }
    printf("pixmap and surface ok\n");

    // message loop
    while (1) {
        XEvent ev;
        XNextEvent(dpy, &ev);
        switch (ev.type) {
        case GraphicsExpose:
        case Expose:
            handle_graphics_expose(&ev);
            break;
        default:
            // do nothing
            break;
        }
    }

    eglTerminate(egl_dpy);
    XFreePixmap(dpy, pixmap);
    XDestroyWindow(dpy, wnd);
    XCloseDisplay(dpy);
    return 0;
}
Comment 1 Tapani Pälli 2014-11-05 10:42:06 UTC
test seems to work with Mesa 10.2 but fails with >= 10.3
Comment 2 Tapani Pälli 2014-11-05 12:34:13 UTC
bisected to:
---- 8< ----
commit 8f55174fbdc27076f310c4dfb1f87072588b8b0b
Author: Kristian Høgsberg <krh@bitplanet.net>
Date:   Fri Aug 15 23:19:52 2014 -0700

    meta: Make MESA_META_DRAW_BUFFERS restore properly
    
    A meta begin/end pair with MESA_META_DRAW_BUFFERS will change visible GL
    state.  We recreate the draw buffer enums from the buffer bitfield, which
    changes GL_BACK to GL_BACK_LEFT (and GL_FRONT to GL_FRONT_LEFT).
    
    This commit modifes the save/restore logic to instead copy the buffer enums
    from the gl_framebuffer and then set them on restore using
    _mesa_drawbuffers().
    
    It's not clear how this breaks the benchmark in 82796, but fixing meta to not
    leak the state change fixes the regression.
    
    No piglit regressions.
    
    Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
    Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=82796
    Signed-off-by: Kristian Høgsberg <krh@bitplanet.net>
    Cc: mesa-stable@lists.freedesktop.org
Comment 3 GitLab Migration User 2019-09-18 18:07:17 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/mesa/mesa/issues/154.

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.