On Fri, Apr 13, 2012 at 7:36 AM, Mandeep Singh Baines <mandeep.bai...@gmail.com> wrote: > Guarantee that the back buffer is validated by calling flush before > assigning the back buffer to current. >
Attached is an app which reproduces the bug. > Signed-off-by: Mandeep Singh Baines <m...@chromium.org> > Cc: Ander Conselvan de Oliveira <ander.conselvan.de.olive...@intel.com> > Cc: Benjamin Franzke <benjaminfran...@googlemail.com> > Cc: Kristian Hogsberg <k...@bitplanet.net> > Cc: David Reveman <reve...@chromium.org> > Cc: Stephane Marchesin <marc...@chromium.org> > --- > src/egl/drivers/dri2/platform_drm.c | 3 ++- > 1 files changed, 2 insertions(+), 1 deletions(-) > > diff --git a/src/egl/drivers/dri2/platform_drm.c > b/src/egl/drivers/dri2/platform_drm.c > index 18ecd17..7b4529d 100644 > --- a/src/egl/drivers/dri2/platform_drm.c > +++ b/src/egl/drivers/dri2/platform_drm.c > @@ -325,6 +325,8 @@ dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, > _EGLSurface *draw) > struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); > struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); > > + (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); > + > if (dri2_surf->base.Type == EGL_WINDOW_BIT) { > if (dri2_surf->current) > _eglError(EGL_BAD_SURFACE, "dri2_swap_buffers"); > @@ -332,7 +334,6 @@ dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, > _EGLSurface *draw) > dri2_surf->back = NULL; > } > > - (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); > (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable); > > return EGL_TRUE; > -- > 1.7.3.4 >
/* * Copyright © 2011 Kristian Høgsberg * Copyright © 2011 Benjamin Franzke * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that copyright * notice and this permission notice appear in supporting documentation, and * that the name of the copyright holders not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. The copyright holders make no representations * about the suitability of this software for any purpose. It is provided "as * is" without express or implied warranty. * * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ #include <stdio.h> #include <stdlib.h> #define EGL_EGLEXT_PROTOTYPES #define GL_GLEXT_PROTOTYPES #include <gbm.h> #include <GL/gl.h> #include <EGL/egl.h> #include <EGL/eglext.h> #include <drm.h> #include <xf86drm.h> #include <xf86drmMode.h> #include <fcntl.h> #include <signal.h> #include <unistd.h> #include <string.h> #include <time.h> #ifdef GL_OES_EGL_image static PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES_func; #endif struct kms { drmModeConnector *connector; drmModeEncoder *encoder; drmModeModeInfo mode; }; GLfloat x = 1.0; GLfloat y = 1.0; GLfloat xstep = 1.0f; GLfloat ystep = 1.0f; GLfloat rsize = 50; int quit = 0; static EGLBoolean setup_kms(int fd, struct kms *kms) { drmModeRes *resources; drmModeConnector *connector; drmModeEncoder *encoder; int i; resources = drmModeGetResources(fd); if (!resources) { fprintf(stderr, "drmModeGetResources failed\n"); return EGL_FALSE; } for (i = 0; i < resources->count_connectors; i++) { connector = drmModeGetConnector(fd, resources->connectors[i]); if (connector == NULL) continue; if (connector->connection == DRM_MODE_CONNECTED && connector->count_modes > 0) break; drmModeFreeConnector(connector); } if (i == resources->count_connectors) { fprintf(stderr, "No currently active connector found.\n"); return EGL_FALSE; } for (i = 0; i < resources->count_encoders; i++) { encoder = drmModeGetEncoder(fd, resources->encoders[i]); if (encoder == NULL) continue; if (encoder->encoder_id == connector->encoder_id) break; drmModeFreeEncoder(encoder); } kms->connector = connector; kms->encoder = encoder; kms->mode = connector->modes[0]; return EGL_TRUE; } static void render_stuff(int width, int height) { glViewport(0, 0, (GLint) width, (GLint) height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, width, 0, height, 1.0, -1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0f, 0.0f, 0.0f); glRectf(x, y, x + rsize, y + rsize); if (x <= 0 || x >= width - rsize) xstep *= -1; if (y <= 0 || y >= height - rsize) ystep *= -1; x += xstep; y += ystep; } static const char device_name[] = "/dev/dri/card0"; static const EGLint attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, 1, EGL_GREEN_SIZE, 1, EGL_BLUE_SIZE, 1, EGL_ALPHA_SIZE, 0, EGL_DEPTH_SIZE, 1, EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, EGL_NONE }; void quit_handler(int signum) { quit = 1; printf("Quitting!\n"); } uint32_t current_fb_id, next_fb_id; struct gbm_bo *current_bo, *next_bo; struct gbm_surface *gs; struct kms kms; static void page_flip_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data) { if (current_fb_id) drmModeRmFB(fd, current_fb_id); current_fb_id = next_fb_id; next_fb_id = 0; if (current_bo) gbm_surface_release_buffer(gs, current_bo); current_bo = next_bo; next_bo = NULL; } int main(int argc, char *argv[]) { EGLDisplay dpy; EGLContext ctx; EGLConfig config; EGLSurface surface; EGLint major, minor, n; const char *ver; uint32_t handle, stride; int ret, fd, frames = 0; struct gbm_device *gbm; drmModeCrtcPtr saved_crtc; time_t start, end; signal (SIGINT, quit_handler); fd = open(device_name, O_RDWR); if (fd < 0) { /* Probably permissions error */ fprintf(stderr, "couldn't open %s, skipping\n", device_name); return -1; } gbm = gbm_create_device(fd); if (gbm == NULL) { fprintf(stderr, "couldn't create gbm device\n"); ret = -1; goto close_fd; } dpy = eglGetDisplay(gbm); if (dpy == EGL_NO_DISPLAY) { fprintf(stderr, "eglGetDisplay() failed\n"); ret = -1; goto destroy_gbm_device; } if (!eglInitialize(dpy, &major, &minor)) { printf("eglInitialize() failed\n"); ret = -1; goto egl_terminate; } ver = eglQueryString(dpy, EGL_VERSION); printf("EGL_VERSION = %s\n", ver); if (!setup_kms(fd, &kms)) { ret = -1; goto egl_terminate; } eglBindAPI(EGL_OPENGL_API); if (!eglChooseConfig(dpy, attribs, &config, 1, &n) || n != 1) { fprintf(stderr, "failed to choose argb config\n"); goto egl_terminate; } ctx = eglCreateContext(dpy, config, EGL_NO_CONTEXT, NULL); if (ctx == NULL) { fprintf(stderr, "failed to create context\n"); ret = -1; goto egl_terminate; } gs = gbm_surface_create(gbm, kms.mode.hdisplay, kms.mode.vdisplay, GBM_BO_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); if (gs == NULL) { fprintf(stderr, "unable to create gbm surface\n"); ret = -1; goto egl_terminate; } surface = eglCreateWindowSurface(dpy, config, gs, NULL); if (surface == EGL_NO_SURFACE) { fprintf(stderr, "failed to create surface\n"); ret = -1; goto destroy_gbm_surface; } if (!eglMakeCurrent(dpy, surface, surface, ctx)) { fprintf(stderr, "failed to make context current\n"); ret = -1; goto destroy_surface; } saved_crtc = drmModeGetCrtc(fd, kms.encoder->crtc_id); if (saved_crtc == NULL) goto destroy_context; time(&start); do { drmEventContext evctx; fd_set rfds; render_stuff(kms.mode.hdisplay, kms.mode.vdisplay); eglSwapBuffers(dpy, surface); if (!gbm_surface_has_free_buffers(gs)) { fprintf(stderr, "out of free buffers\n"); goto out; } next_bo = gbm_surface_lock_front_buffer(gs); if (!next_bo) { fprintf(stderr, "failed to lock front buffer: %m\n"); goto out; } handle = gbm_bo_get_handle(next_bo).u32; stride = gbm_bo_get_pitch(next_bo); ret = drmModeAddFB(fd, kms.mode.hdisplay, kms.mode.vdisplay, 24, 32, stride, handle, &next_fb_id); if (ret) { fprintf(stderr, "failed to create fb\n"); goto out; } ret = drmModePageFlip(fd, kms.encoder->crtc_id, next_fb_id, DRM_MODE_PAGE_FLIP_EVENT, 0); if (ret) { fprintf(stderr, "failed to page flip: %m\n"); goto out; } FD_ZERO(&rfds); FD_SET(fd, &rfds); while (select(fd + 1, &rfds, NULL, NULL, NULL) == -1) NULL; memset(&evctx, 0, sizeof evctx); evctx.version = DRM_EVENT_CONTEXT_VERSION; evctx.page_flip_handler = page_flip_handler; drmHandleEvent(fd, &evctx); frames++; } while (!quit); time(&end); printf("Frames per second: %.2lf\n", frames / difftime(end, start)); out: drmModeSetCrtc(fd, saved_crtc->crtc_id, saved_crtc->buffer_id, saved_crtc->x, saved_crtc->y, &kms.connector->connector_id, 1, &saved_crtc->mode); drmModeFreeCrtc(saved_crtc); if (current_fb_id) drmModeRmFB(fd, current_fb_id); if (next_fb_id) drmModeRmFB(fd, next_fb_id); eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); destroy_context: eglDestroyContext(dpy, ctx); destroy_surface: eglDestroySurface(dpy, surface); destroy_gbm_surface: gbm_surface_destroy(gs); egl_terminate: eglTerminate(dpy); destroy_gbm_device: gbm_device_destroy(gbm); close_fd: close(fd); return ret; }
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev