Bug 85869 - Offscreen rendering to pixmap EGLSurface is odd
Summary: Offscreen rendering to pixmap EGLSurface is odd
Status: NEW
Alias: None
Product: Mesa
Classification: Unclassified
Component: EGL (show other bugs)
Version: unspecified
Hardware: x86-64 (AMD64) Linux (All)
: medium normal
Assignee: mesa-dev
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-11-04 17:33 UTC by Rinat
Modified: 2014-11-05 12:34 UTC (History)
2 users (show)

See Also:
i915 platform:
i915 features:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
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


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.