コード例 #1
0
ファイル: drm_egl_ctx.c プロジェクト: maddox/RetroArch
static void free_drm_resources(gfx_ctx_drm_egl_data_t *drm)
{
   if (!drm)
      return;

   if (drm->g_gbm_surface)
      gbm_surface_destroy(drm->g_gbm_surface);

   if (drm->g_gbm_dev)
      gbm_device_destroy(drm->g_gbm_dev);

   if (drm->g_encoder)
      drmModeFreeEncoder(drm->g_encoder);

   if (drm->g_connector)
      drmModeFreeConnector(drm->g_connector);

   if (drm->g_resources)
      drmModeFreeResources(drm->g_resources);

   if (drm->g_orig_crtc)
      drmModeFreeCrtc(drm->g_orig_crtc);

   if (drm->g_drm_fd >= 0)
      close(drm->g_drm_fd);

   drm->g_gbm_surface = NULL;
   drm->g_gbm_dev     = NULL;
   drm->g_encoder     = NULL;
   drm->g_connector   = NULL;
   drm->g_resources   = NULL;
   drm->g_orig_crtc   = NULL;
   drm->g_drm_fd      = -1;
}
コード例 #2
0
ファイル: drm_egl_ctx.c プロジェクト: mprobinson/RetroArch
static void free_drm_resources(void)
{
   if (g_gbm_surface)
      gbm_surface_destroy(g_gbm_surface);

   if (g_gbm_dev)
      gbm_device_destroy(g_gbm_dev);

   if (g_encoder)
      drmModeFreeEncoder(g_encoder);

   if (g_connector)
      drmModeFreeConnector(g_connector);

   if (g_resources)
      drmModeFreeResources(g_resources);

   if (g_orig_crtc)
      drmModeFreeCrtc(g_orig_crtc);

   if (g_drm_fd >= 0)
      close(g_drm_fd);

   g_gbm_surface = NULL;
   g_gbm_dev     = NULL;
   g_encoder     = NULL;
   g_connector   = NULL;
   g_resources   = NULL;
   g_orig_crtc   = NULL;
   g_drm_fd      = -1;
}
コード例 #3
0
RenderingBackendGBM::Surface::~Surface()
{
    for (auto& it : m_lockedBuffers)
        m_client.destroyBuffer(it.first);

    if (m_surface)
        gbm_surface_destroy(m_surface);
}
コード例 #4
0
ファイル: GBMUtils.cpp プロジェクト: FernetMenta/xbmc
void CGBMUtils::DestroyGbm(struct gbm *gbm)
{
  if(gbm->surface)
  {
    gbm_surface_destroy(gbm->surface);
  }

  gbm->surface = nullptr;
}
コード例 #5
0
ファイル: PVRShellOS.cpp プロジェクト: jiazhy-zhiyuan/arena
/*!***********************************************************************
 @Function		OsReleaseOS
 @description	Destroys main window
*************************************************************************/
void PVRShellInit::OsReleaseOS()
{
	gbm_surface_destroy(m_psGbmSurface);
	gbm_device_destroy(m_psGbmDev);
	drmModeFreeCrtc(m_psDrmCrtc);
	drmModeFreeEncoder(m_psDrmEncoder);
	drmModeFreeConnector(m_psDrmConnector);
	drmModeFreeResources(m_psDrmResources);
	drmClose(m_i32DrmFile);
}
コード例 #6
0
ファイル: qkmsscreen.cpp プロジェクト: CodeDJ/qt5-hidpi
QKmsScreen::~QKmsScreen()
{
    delete m_cursor;
    drmModeSetCrtc(m_device->fd(), m_oldCrtc->crtc_id, m_oldCrtc->buffer_id,
                   m_oldCrtc->x, m_oldCrtc->y,
                   &m_connectorId, 1, &m_oldCrtc->mode);
    drmModeFreeCrtc(m_oldCrtc);
    if (m_eglWindowSurface != EGL_NO_SURFACE)
        eglDestroySurface(m_device->eglDisplay(), m_eglWindowSurface);
    gbm_surface_destroy(m_gbmSurface);
}
コード例 #7
0
ファイル: DRMLegacy.cpp プロジェクト: pipilavvy/xbmc
void CDRMLegacy::DestroyDrmLegacy()
{
  CDRMUtils::DestroyDrm();

  if(m_gbm->surface)
  {
    gbm_surface_destroy(m_gbm->surface);
  }

  if(m_gbm->dev)
  {
    gbm_device_destroy(m_gbm->dev);
  }
}
コード例 #8
0
ファイル: gbm_display_helpers.cpp プロジェクト: TomasMM/emir
mgg::GBMSurfaceUPtr mggh::GBMHelper::create_scanout_surface(uint32_t width, uint32_t height)
{
    auto surface_raw = gbm_surface_create(device, width, height,
                                          GBM_BO_FORMAT_XRGB8888,
                                          GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);

    auto gbm_surface_deleter = [](gbm_surface *p) { if (p) gbm_surface_destroy(p); };
    GBMSurfaceUPtr surface{surface_raw, gbm_surface_deleter};

    if (!surface)
        BOOST_THROW_EXCEPTION(std::runtime_error("Failed to create GBM scanout surface"));

    return surface;
}
コード例 #9
0
ファイル: gbm-winsys.c プロジェクト: bpeel/stereo-cube
static void
stereo_cleanup_context(struct gbm_context *context)
{
        restore_saved_crtc(context->dev);
        free_current_bo(context);
        eglMakeCurrent(context->edpy,
                       EGL_NO_SURFACE,
                       EGL_NO_SURFACE,
                       EGL_NO_CONTEXT);
        eglDestroyContext(context->edpy, context->egl_context);
        eglDestroySurface(context->edpy, context->egl_surface);
        gbm_surface_destroy(context->gbm_surface);
        eglTerminate(context->edpy);
        gbm_device_destroy(context->gbm);
        free(context);
}
コード例 #10
0
void QEglFSKmsGbmScreen::destroySurface()
{
    if (m_gbm_bo_current) {
        gbm_bo_destroy(m_gbm_bo_current);
        m_gbm_bo_current = Q_NULLPTR;
    }

    if (m_gbm_bo_next) {
        gbm_bo_destroy(m_gbm_bo_next);
        m_gbm_bo_next = Q_NULLPTR;
    }

    if (m_gbm_surface) {
        gbm_surface_destroy(m_gbm_surface);
        m_gbm_surface = Q_NULLPTR;
    }
}
コード例 #11
0
ファイル: drm_ctx.c プロジェクト: Kivutar/RetroArch
static void free_drm_resources(gfx_ctx_drm_data_t *drm)
{
   if (!drm)
      return;

   if (g_gbm_surface)
      gbm_surface_destroy(g_gbm_surface);

   if (g_gbm_dev)
      gbm_device_destroy(g_gbm_dev);

   drm_free();

   if (g_drm_fd >= 0)
      retro_fclose(drm->drm);

   g_gbm_surface      = NULL;
   g_gbm_dev          = NULL;
   g_drm_fd           = -1;
}
コード例 #12
0
static void
_cogl_winsys_egl_cleanup_context (CoglDisplay *display)
{
  CoglDisplayEGL *egl_display = display->winsys;
  CoglDisplayKMS *kms_display = egl_display->platform;
  CoglRenderer *renderer = display->renderer;
  CoglRendererEGL *egl_renderer = renderer->winsys;

  if (egl_display->dummy_surface != EGL_NO_SURFACE)
    {
      eglDestroySurface (egl_renderer->edpy, egl_display->dummy_surface);
      egl_display->dummy_surface = EGL_NO_SURFACE;
    }

  if (kms_display->dummy_gbm_surface != NULL)
    {
      gbm_surface_destroy (kms_display->dummy_gbm_surface);
      kms_display->dummy_gbm_surface = NULL;
    }
}
コード例 #13
0
ファイル: native-state-drm.cpp プロジェクト: elmarco/glmark2
void
NativeStateDRM::cleanup()
{
    // Restore CRTC state if necessary
    if (crtc_) {
        int status = drmModeSetCrtc(fd_, crtc_->crtc_id, crtc_->buffer_id,
                                    crtc_->x, crtc_->y, &connector_->connector_id,
                                    1, &crtc_->mode);
        if (status < 0) {
            Log::error("Failed to restore original CRTC: %d\n", status);
        }
        drmModeFreeCrtc(crtc_);
        crtc_ = 0;
    }
    if (surface_) {
        gbm_surface_destroy(surface_);
        surface_ = 0;
    }
    if (dev_) {
        gbm_device_destroy(dev_);
        dev_ = 0;
    }
    if (connector_) {
        drmModeFreeConnector(connector_);
        connector_ = 0;
    }
    if (encoder_) {
        drmModeFreeEncoder(encoder_);
        encoder_ = 0;
    }
    if (resources_) {
        drmModeFreeResources(resources_);
        resources_ = 0;
    }
    if (fd_ > 0) {
        drmClose(fd_);
    }
    fd_ = 0;
    mode_ = 0;
}
コード例 #14
0
ファイル: drm_egl.c プロジェクト: yoimbert/mpv
static void drm_egl_uninit(MPGLContext *ctx)
{
    struct priv *p = ctx->priv;
    crtc_release(ctx);

    if (p->vt_switcher_active)
        vt_switcher_destroy(&p->vt_switcher);

    eglMakeCurrent(p->egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    eglDestroyContext(p->egl.display, p->egl.context);
    eglDestroySurface(p->egl.display, p->egl.surface);
    gbm_surface_destroy(p->gbm.surface);
    eglTerminate(p->egl.display);
    gbm_device_destroy(p->gbm.device);
    p->egl.context = EGL_NO_CONTEXT;
    eglDestroyContext(p->egl.display, p->egl.context);

    if (p->kms) {
        kms_destroy(p->kms);
        p->kms = 0;
    }
}
コード例 #15
0
static void
_cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
{
  CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
  CoglContext *context = framebuffer->context;
  CoglRenderer *renderer = context->display->renderer;
  CoglRendererEGL *egl_renderer = renderer->winsys;
  CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
  CoglOnscreenKMS *kms_onscreen;

  /* If we never successfully allocated then there's nothing to do */
  if (egl_onscreen == NULL)
    return;

  kms_onscreen = egl_onscreen->platform;

  /* flip state takes a reference on the onscreen so there should
   * never be outstanding flips when we reach here. */
  g_return_if_fail (kms_onscreen->next_fb_id == 0);

  free_current_bo (onscreen);

  if (egl_onscreen->egl_surface != EGL_NO_SURFACE)
    {
      eglDestroySurface (egl_renderer->edpy, egl_onscreen->egl_surface);
      egl_onscreen->egl_surface = EGL_NO_SURFACE;
    }

  if (kms_onscreen->surface)
    {
      gbm_surface_destroy (kms_onscreen->surface);
      kms_onscreen->surface = NULL;
    }

  g_slice_free (CoglOnscreenKMS, kms_onscreen);
  g_slice_free (CoglOnscreenEGL, onscreen->winsys);
  onscreen->winsys = NULL;
}
コード例 #16
0
ファイル: evas_engine.c プロジェクト: FlorentRevest/EFL
static int
evgl_eng_native_window_destroy(void *data, void *native_window)
{
   Render_Engine *re = (Render_Engine *)data;

   if (!re)
     {
        ERR("Invalid Render Engine Data!");
        return 0;
     }

   if (!native_window)
     {
        ERR("Inavlid native surface.");
        return 0;
     }

   gbm_surface_destroy((struct gbm_surface *)native_window);

   native_window = NULL;

   return 1;
}
コード例 #17
0
ファイル: drm_ctx.c プロジェクト: Ezio-PS/RetroArch
static void free_drm_resources(gfx_ctx_drm_data_t *drm)
{
   if (!drm)
      return;

   /* Restore original CRTC. */
   drm_restore_crtc();

   if (g_gbm_surface)
      gbm_surface_destroy(g_gbm_surface);

   if (g_gbm_dev)
      gbm_device_destroy(g_gbm_dev);

   drm_free();

   if (drm->drm)
      if (g_drm_fd >= 0)
         filestream_close(drm->drm);

   g_gbm_surface      = NULL;
   g_gbm_dev          = NULL;
   g_drm_fd           = -1;
}
コード例 #18
0
ファイル: gbm-winsys.c プロジェクト: bpeel/stereo-cube
static struct gbm_context *
stereo_prepare_context(struct gbm_dev *dev,
                       const struct gbm_options *options)
{
        struct gbm_context *context;
        EGLint multiview_view_count = 0;

        context = xmalloc(sizeof(*context));
        context->dev = dev;

        context->gbm = gbm_create_device(dev->fd);
        if (context->gbm == NULL) {
                fprintf(stderr, "error creating GBM device\n");
                goto error;
        }

        context->edpy = eglGetDisplay((EGLNativeDisplayType) context->gbm);
        if (context->edpy == EGL_NO_DISPLAY) {
                fprintf(stderr, "error getting EGL display\n");
                goto error_gbm_device;
        }

        if (!eglInitialize(context->edpy, NULL, NULL)) {
                fprintf(stderr, "error intializing EGL display\n");
                goto error_gbm_device;
        }

        if (!extension_supported(context->edpy, MULTIVIEW_WINDOW_EXTENSION)) {
                fprintf(stderr, MULTIVIEW_WINDOW_EXTENSION " not supported\n");
                goto error_egl_display;
        }

        if (create_gbm_surface(context))
                goto error_egl_display;

        if (choose_egl_config(context))
                goto error_gbm_surface;

        if (create_egl_surface(context, options))
                goto error_gbm_surface;

        if (create_egl_context(context))
                goto error_egl_surface;

        if (!eglMakeCurrent(context->edpy,
                            context->egl_surface,
                            context->egl_surface,
                            context->egl_context)) {
                fprintf(stderr, "failed to make EGL context current\n");
                goto error_egl_context;
        }

        if ((!eglQueryContext(context->edpy,
                              context->egl_context,
                              EGL_MULTIVIEW_VIEW_COUNT_EXT,
                              &multiview_view_count) ||
             multiview_view_count < 2)) {
                fprintf(stderr,
                        "EGL created a multiview surface with only %i %s\n",
                        multiview_view_count,
                        multiview_view_count == 1 ? "view" : "views");
                goto error_unbind;
        }

        return context;

error_unbind:
        eglMakeCurrent(context->edpy,
                       EGL_NO_SURFACE, EGL_NO_SURFACE,
                       EGL_NO_CONTEXT);
error_egl_context:
        eglDestroyContext(context->edpy, context->egl_context);
error_egl_surface:
        eglDestroySurface(context->edpy, context->egl_surface);
error_gbm_surface:
        gbm_surface_destroy(context->gbm_surface);
error_egl_display:
        eglTerminate(context->edpy);
error_gbm_device:
        gbm_device_destroy(context->gbm);
error:
        free(context);
        return NULL;
}
コード例 #19
0
ファイル: drm_egl_ctx.c プロジェクト: AbelFlos/RetroArch
void gfx_ctx_destroy(void)
{
   // Make sure we acknowledge all page-flips.
   if (waiting_for_flip)
      wait_flip(true);

   if (g_egl_dpy)
   {
      if (g_egl_ctx)
      {
         eglMakeCurrent(g_egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
         eglDestroyContext(g_egl_dpy, g_egl_ctx);
      }

      if (g_egl_surf)
         eglDestroySurface(g_egl_dpy, g_egl_surf);
      eglTerminate(g_egl_dpy);
   }

   // Be as careful as possible in deinit.
   // If we screw up, the KMS tty will not restore.

   g_egl_ctx  = NULL;
   g_egl_surf = NULL;
   g_egl_dpy  = NULL;
   g_config   = 0;

   // Restore original CRTC.
   if (g_orig_crtc)
   {
      drmModeSetCrtc(g_drm_fd, g_orig_crtc->crtc_id,
            g_orig_crtc->buffer_id,
            g_orig_crtc->x,
            g_orig_crtc->y,
            &g_connector_id, 1, &g_orig_crtc->mode);

      drmModeFreeCrtc(g_orig_crtc);
   }

   if (g_gbm_surface)
      gbm_surface_destroy(g_gbm_surface);

   if (g_gbm_dev)
      gbm_device_destroy(g_gbm_dev);

   if (g_encoder)
      drmModeFreeEncoder(g_encoder);

   if (g_connector)
      drmModeFreeConnector(g_connector);

   if (g_resources)
      drmModeFreeResources(g_resources);

   g_gbm_surface = NULL;
   g_gbm_dev     = NULL;
   g_encoder     = NULL;
   g_connector   = NULL;
   g_resources   = NULL;
   g_orig_crtc   = NULL;
   g_drm_mode    = NULL;

   g_quit         = 0;
   g_crtc_id      = 0;
   g_connector_id = 0;

   g_fb_width  = 0;
   g_fb_height = 0;

   g_bo      = NULL;
   g_next_bo = NULL;

   if (g_drm_fd >= 0)
      close(g_drm_fd);
   g_drm_fd = -1;
   g_inited = false;
}
コード例 #20
0
ファイル: drm_egl_ctx.c プロジェクト: bigreen/RetroArch
void gfx_ctx_destroy(void)
{
   // Make sure we acknowledge all page-flips.
   if (waiting_for_flip)
      wait_flip(true);

   if (g_egl_dpy)
   {
      if (g_egl_ctx)
      {
         eglMakeCurrent(g_egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
         eglDestroyContext(g_egl_dpy, g_egl_ctx);
      }

      if (g_egl_surf)
         eglDestroySurface(g_egl_dpy, g_egl_surf);
      eglTerminate(g_egl_dpy);
   }

   // Be as careful as possible in deinit.
   // If we screw up, the KMS tty will not restore.

   g_egl_ctx  = NULL;
   g_egl_surf = NULL;
   g_egl_dpy  = NULL;
   g_config   = 0;

   // Restore original CRTC.
   if (g_orig_crtc)
   {
      drmModeSetCrtc(g_drm_fd, g_orig_crtc->crtc_id,
            g_orig_crtc->buffer_id,
            g_orig_crtc->x,
            g_orig_crtc->y,
            &g_connector_id, 1, &g_orig_crtc->mode);

      drmModeFreeCrtc(g_orig_crtc);
   }

   if (g_gbm_surface)
      gbm_surface_destroy(g_gbm_surface);

   if (g_gbm_dev)
      gbm_device_destroy(g_gbm_dev);

   if (g_encoder)
      drmModeFreeEncoder(g_encoder);

   if (g_connector)
      drmModeFreeConnector(g_connector);

   if (g_resources)
      drmModeFreeResources(g_resources);

   g_gbm_surface = NULL;
   g_gbm_dev     = NULL;
   g_encoder     = NULL;
   g_connector   = NULL;
   g_resources   = NULL;
   g_orig_crtc   = NULL;
   g_drm_mode    = NULL;

   g_quit         = 0;
   g_crtc_id      = 0;
   g_connector_id = 0;

   g_fb_width  = 0;
   g_fb_height = 0;

   g_bo      = NULL;
   g_next_bo = NULL;

   if (g_drm_fd >= 0)
      close(g_drm_fd);
   g_drm_fd = -1;

   unsigned frames = last_page_flip - first_page_flip;
   if (frames)
   {
      uint64_t usec = last_usec - first_usec;
      RARCH_WARN("[KMS/EGL]: Estimated monitor FPS: %.5f Hz\n", 1000000.0 * frames / usec); 
   }

   RARCH_WARN("[KMS/EGL]: Performance stats: Missed VBlanks: %u, Perfect VBlanks: %u\n", 
         missed_vblanks, hit_vblanks);

   g_inited = false;
}
コード例 #21
0
ファイル: sgxperf_egl_drm.cpp プロジェクト: prabindh/sgxperf
static void exit_gbm(void)
{
        gbm_surface_destroy(gbm.surface);
        gbm_device_destroy(gbm.dev);
        return;
}
コード例 #22
0
RenderingBackendGBM::OffscreenSurface::~OffscreenSurface()
{
    gbm_surface_destroy(m_surface);
}
コード例 #23
0
 virtual ~OffscreenContextData()
 {
     gbm_surface_destroy(surface);
 }
コード例 #24
0
void QEglFSKmsIntegration::destroyNativeWindow(EGLNativeWindowType window)
{
    gbm_surface *surface = reinterpret_cast<gbm_surface *>(window);
    gbm_surface_destroy(surface);
}
コード例 #25
0
ファイル: eglkms.c プロジェクト: siro20/XlessEGL
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;
	char *data;
	char j;
	int i;
	int once;
	once = 0;

	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.crtc_id);
	if (saved_crtc == NULL)
	{
		fprintf(stderr, "no valid graphic configuration active (VT ?)\n");
	}
	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_stride(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;
		}
		  
		/* make sure to setup crtc once (fix for broken drivers) */
		if(once == 0){
			once = 1;
			drmModeSetCrtc(fd, kms.crtc_id, next_fb_id,
				0, 0,
				&kms.connector->connector_id, 1, &kms.mode);
		}
		
		ret = drmModePageFlip(fd, kms.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:
	if(saved_crtc){
		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;
}