On Tue, Apr 10, 2012 at 4:02 PM, Kristian Høgsberg <k...@bitplanet.net> wrote:
> On Tue, Apr 10, 2012 at 6:30 PM, Mandeep Baines
> <mandeep.bai...@gmail.com> wrote:
>> Attached is the test case I've been using.
>
> Nice, I've been meaning to update eglkms.c to also demonstrate
> pageflipping.  Do you mind if I commit your version?
>

Attached is a cleaned up version with proper error handling.

> Kristian
>
>> On Tue, Apr 10, 2012 at 3:26 PM,  <mandeep.bai...@gmail.com> wrote:
>>> From: Mandeep Singh Baines <m...@chromium.org>
>>>
>>> Keep a reference to any newly allocated aux buffers to avoid
>>> re-allocating for every st_framebuffer_validate() (i.e. leaking).
>>>
>>> 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 |    9 ++++-----
>>>  1 files changed, 4 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/src/egl/drivers/dri2/platform_drm.c 
>>> b/src/egl/drivers/dri2/platform_drm.c
>>> index 18ecd17..54067ff 100644
>>> --- a/src/egl/drivers/dri2/platform_drm.c
>>> +++ b/src/egl/drivers/dri2/platform_drm.c
>>> @@ -220,16 +220,15 @@ get_aux_bo(struct dri2_egl_surface *dri2_surf,
>>>  {
>>>    struct dri2_egl_display *dri2_dpy =
>>>       dri2_egl_display(dri2_surf->base.Resource.Display);
>>> -   __DRIbuffer *b;
>>> +   __DRIbuffer *b = dri2_surf->dri_buffers[attachment];
>>>
>>> -   b = NULL;
>>> -   if (dri2_surf->dri_buffers[attachment])
>>> -      b = dri2_surf->dri_buffers[attachment];
>>> -   if (b == NULL)
>>> +   if (b == NULL) {
>>>       b = dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen,
>>>                                         attachment, format,
>>>                                         dri2_surf->base.Width,
>>>                                         dri2_surf->base.Height);
>>> +      dri2_surf->dri_buffers[attachment] = b;
>>> +   }
>>>    if (b == NULL)
>>>       return -1;
>>>
>>> --
>>> 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");

      next_bo = gbm_surface_lock_front_buffer(gs);
      if (!next_bo)
         fprintf(stderr, "failed to lock front buffer: %m\n");
      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

Reply via email to