int armsoc_bo_add_fb(struct armsoc_bo *bo)
{
	int ret, depth = bo->depth;

	assert(bo->refcnt > 0);
	assert(bo->fb_id == 0);

	if (bo->bpp == 32 && bo->depth == 32 && !bo->dev->alpha_supported)
		depth = 24;

	ret = drmModeAddFB(bo->dev->fd, bo->width, bo->height, depth,
		bo->bpp, bo->pitch, bo->handle, &bo->fb_id);

	if (ret < 0 && bo->bpp == 32 && bo->depth == 32 && bo->dev->alpha_supported) {
		/* The DRM driver may not support an alpha channel but
		 * it is possible to continue by ignoring the alpha, so
		 * if an attempt to create a depth 32, bpp 32 framebuffer
		 * fails we retry with depth 24, bpp 32
		 */
		xf86DrvMsg(-1, X_WARNING,
				"depth 32 FB unsupported : falling back to depth 24\n");
		bo->dev->alpha_supported = FALSE;
		ret = drmModeAddFB(bo->dev->fd, bo->width, bo->height, 24,
				bo->bpp, bo->pitch, bo->handle, &bo->fb_id);
	}

	if (ret < 0) {
		bo->fb_id = 0;
		return ret;
	}
	return 0;
}
Beispiel #2
0
struct SDrmFbWrapper *PVRShellInitOS::DrmFbGetFromBo(struct gbm_bo *bo)
{
	struct SDrmFbWrapper *fb = (struct SDrmFbWrapper *)gbm_bo_get_user_data(bo);
	uint32_t width, height, stride, handle;
	int ret;

	if (fb)
	{
		return fb;
	}

	fb = new struct SDrmFbWrapper;
	fb->psGbmBo = bo;
	fb->i32Fd = m_i32DrmFile;

	width = gbm_bo_get_width(bo);
	height = gbm_bo_get_height(bo);
	stride = gbm_bo_get_stride(bo);
	handle = gbm_bo_get_handle(bo).u32;

	ret = drmModeAddFB(m_i32DrmFile, width, height, 24, 32, stride, handle, &fb->ui32FbId);

	if (ret) 
	{
		delete fb;
		return NULL;
	}

	gbm_bo_set_user_data(bo, fb, pfnCallbackDrmFbDestroy);
	return fb;
}
Beispiel #3
0
static struct drm_fb *drm_fb_get_from_bo(struct gbm_bo *bo)
{
   struct drm_fb *fb = (struct drm_fb*)gbm_bo_get_user_data(bo);
   if (fb)
      return fb;

   fb = (struct drm_fb*)calloc(1, sizeof(*fb));
   fb->bo = bo;

   unsigned width  = gbm_bo_get_width(bo);
   unsigned height = gbm_bo_get_height(bo);
   unsigned stride = gbm_bo_get_stride(bo);
   unsigned handle = gbm_bo_get_handle(bo).u32;

   int ret = drmModeAddFB(g_drm_fd, width, height, 24, 32, stride, handle, &fb->fb_id);
   if (ret < 0)
   {
      RARCH_ERR("[KMS/EGL]: Failed to create FB: %s\n", strerror(errno));
      free(fb);
      return NULL;
   }

   gbm_bo_set_user_data(bo, fb, drm_fb_destroy_callback);
   return fb;
}
Beispiel #4
0
NativeStateDRM::DRMFBState*
NativeStateDRM::fb_get_from_bo(gbm_bo* bo)
{
    DRMFBState* fb = reinterpret_cast<DRMFBState*>(gbm_bo_get_user_data(bo));
    if (fb) {
        return fb;
    }

    unsigned int width = gbm_bo_get_width(bo);
    unsigned int height = gbm_bo_get_height(bo);
    unsigned int stride = gbm_bo_get_stride(bo);
    unsigned int handle = gbm_bo_get_handle(bo).u32;
    unsigned int fb_id(0);
    int status = drmModeAddFB(fd_, width, height, 24, 32, stride, handle, &fb_id);
    if (status < 0) {
        Log::error("Failed to create FB: %d\n", status);
        return 0;
    }

    fb = new DRMFBState();
    fb->fd = fd_;
    fb->bo = bo;
    fb->fb_id = fb_id;

    gbm_bo_set_user_data(bo, fb, fb_destroy_callback);
    return fb;
}
Beispiel #5
0
QEglFSKmsGbmScreen::FrameBuffer *QEglFSKmsGbmScreen::framebufferForBufferObject(gbm_bo *bo)
{
    {
        FrameBuffer *fb = static_cast<FrameBuffer *>(gbm_bo_get_user_data(bo));
        if (fb)
            return fb;
    }

    uint32_t width = gbm_bo_get_width(bo);
    uint32_t height = gbm_bo_get_height(bo);
    uint32_t stride = gbm_bo_get_stride(bo);
    uint32_t handle = gbm_bo_get_handle(bo).u32;

    QScopedPointer<FrameBuffer> fb(new FrameBuffer);

    int ret = drmModeAddFB(device()->fd(), width, height, 24, 32,
                           stride, handle, &fb->fb);

    if (ret) {
        qWarning("Failed to create KMS FB!");
        return Q_NULLPTR;
    }

    gbm_bo_set_user_data(bo, fb.data(), bufferDestroyedHandler);
    return fb.take();
}
Beispiel #6
0
struct drm_fb * drm_fb_get_from_bo(struct gbm_bo *bo)
{
	struct drm_fb *fb = gbm_bo_get_user_data(bo);
	uint32_t width, height, stride, handle;
	int ret;

	if (fb)
		return fb;

	fb = calloc(1, sizeof *fb);
	fb->bo = bo;

	width = gbm_bo_get_width(bo);
	height = gbm_bo_get_height(bo);
	stride = gbm_bo_get_stride(bo);
	handle = gbm_bo_get_handle(bo).u32;

	ret = drmModeAddFB(drm.fd, width, height, 24, 32, stride, handle, &fb->fb_id);
	if (ret) {
		printf("failed to create fb: %s\n", strerror(errno));
		free(fb);
		return NULL;
	}

	gbm_bo_set_user_data(bo, fb, drm_fb_destroy_callback);

	return fb;
}
static void *
drmmode_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
{
	ScrnInfoPtr scrn = crtc->scrn;
	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
	drmmode_ptr drmmode = drmmode_crtc->drmmode;
	unsigned long rotate_pitch;
	uint32_t tiling;
	int ret;

	drmmode_crtc->rotate_bo = intel_allocate_framebuffer(scrn,
							     width, height,
							     drmmode->cpp,
							     &rotate_pitch,
							     &tiling);

	if (!drmmode_crtc->rotate_bo) {
		xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
			   "Couldn't allocate shadow memory for rotated CRTC\n");
		return NULL;
	}

	ret = drmModeAddFB(drmmode->fd, width, height, crtc->scrn->depth,
			   crtc->scrn->bitsPerPixel, rotate_pitch,
			   drmmode_crtc->rotate_bo->handle,
			   &drmmode_crtc->rotate_fb_id);
	if (ret) {
		ErrorF("failed to add rotate fb\n");
		drm_intel_bo_unreference(drmmode_crtc->rotate_bo);
		return NULL;
	}

	drmmode_crtc->rotate_pitch = rotate_pitch;
	return drmmode_crtc->rotate_bo;
}
Beispiel #8
0
static struct drm_fb *drm_fb_get_from_bo(
      gfx_ctx_drm_egl_data_t *drm,
      struct gbm_bo *bo)
{
   int ret;
   unsigned width, height, stride, handle;
   struct drm_fb *fb = (struct drm_fb*)gbm_bo_get_user_data(bo);
   if (fb)
      return fb;

   fb = (struct drm_fb*)calloc(1, sizeof(*fb));
   fb->bo = bo;

   width  = gbm_bo_get_width(bo);
   height = gbm_bo_get_height(bo);
   stride = gbm_bo_get_stride(bo);
   handle = gbm_bo_get_handle(bo).u32;

   RARCH_LOG("[KMS/EGL]: New FB: %ux%u (stride: %u).\n", width, height, stride);

   ret = drmModeAddFB(drm->g_drm_fd, width, height, 24, 32, stride, handle, &fb->fb_id);
   if (ret < 0)
   {
      RARCH_ERR("[KMS/EGL]: Failed to create FB: %s\n", strerror(errno));
      free(fb);
      return NULL;
   }

   gbm_bo_set_user_data(bo, fb, drm_fb_destroy_callback);
   return fb;
}
static int test2(void)
{
	drm_intel_bo *test_intel_bo;
	uint32_t fb_id;
	drmModeClip clip;
	int prime_fd;
	uint32_t udl_handle;
	int ret;

	test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", BO_SIZE, 4096);

	drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd);

	ret = drmPrimeFDToHandle(udl_fd, prime_fd, &udl_handle);
	if (ret)
		goto out;

	ret = drmModeAddFB(udl_fd, 640, 480, 16, 16, 640, udl_handle, &fb_id);
	if (ret)
		goto out;

	clip.x1 = 0;
	clip.y1 = 0;
	clip.x2 = 10;
	clip.y2 = 10;
	ret = drmModeDirtyFB(udl_fd, fb_id, &clip, 1);
	if (ret) {
		return ret;
	}
out:
	dumb_bo_destroy(udl_fd, udl_handle);
	drm_intel_bo_unreference(test_intel_bo);
	return ret;
}
static uint32_t
create_buffer (ply_renderer_driver_t *driver,
               unsigned long          width,
               unsigned long          height,
               unsigned long         *row_stride)
{
        ply_renderer_buffer_t *buffer;

        buffer = ply_renderer_buffer_new (driver, width, height);

        if (buffer == NULL) {
                ply_trace ("Could not allocate GEM object for frame buffer: %m");
                return 0;
        }

        if (drmModeAddFB (driver->device_fd, width, height,
                          24, 32, buffer->row_stride, buffer->handle,
                          &buffer->id) != 0) {
                ply_trace ("Could not set up GEM object as frame buffer: %m");
                ply_renderer_buffer_free (driver, buffer);
                return 0;
        }

        *row_stride = buffer->row_stride;

        buffer->added_fb = true;
        ply_hashtable_insert (driver->buffers,
                              (void *) (uintptr_t) buffer->id,
                              buffer);

        return buffer->id;
}
Beispiel #11
0
/**
 * Add textures as DRM framebuffers.
 */
static boolean
drm_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back)
{
   struct drm_surface *drmsurf = drm_surface(nsurf);
   struct drm_display *drmdpy = drmsurf->drmdpy;
   int num_framebuffers = (need_back) ? 2 : 1;
   int i, err;

   for (i = 0; i < num_framebuffers; i++) {
      struct drm_framebuffer *fb;
      enum native_attachment natt;
      struct winsys_handle whandle;
      uint block_bits;

      if (i == 0) {
         fb = &drmsurf->front_fb;
         natt = NATIVE_ATTACHMENT_FRONT_LEFT;
      }
      else {
         fb = &drmsurf->back_fb;
         natt = NATIVE_ATTACHMENT_BACK_LEFT;
      }

      if (!fb->texture) {
         /* make sure the texture has been allocated */
         resource_surface_add_resources(drmsurf->rsurf, 1 << natt);
         fb->texture =
            resource_surface_get_single_resource(drmsurf->rsurf, natt);
         if (!fb->texture)
            return FALSE;
      }

      /* already initialized */
      if (fb->buffer_id)
         continue;

      /* TODO detect the real value */
      fb->is_passive = TRUE;

      memset(&whandle, 0, sizeof(whandle));
      whandle.type = DRM_API_HANDLE_TYPE_KMS;

      if (!drmdpy->base.screen->resource_get_handle(drmdpy->base.screen,
               fb->texture, &whandle))
         return FALSE;

      block_bits = util_format_get_blocksizebits(drmsurf->color_format);
      err = drmModeAddFB(drmdpy->fd, drmsurf->width, drmsurf->height,
            block_bits, block_bits, whandle.stride, whandle.handle,
            &fb->buffer_id);
      if (err) {
         fb->buffer_id = 0;
         return FALSE;
      }
   }

   return TRUE;
}
Beispiel #12
0
ExtFramebuffer::ExtFramebuffer(Card& card, uint32_t width, uint32_t height, uint8_t depth, uint8_t bpp, uint32_t stride, uint32_t handle)
	:Framebuffer(card, width, height)
{
	uint32_t id;
	int r = drmModeAddFB(card.fd(), width, height, depth, bpp, stride, handle, &id);
	if (r)
		throw invalid_argument("fob");

	set_id(id);
}
/*
 * Add a fb object for a bo.
 */
int gralloc_drm_bo_add_fb(struct gralloc_drm_bo_t *bo)
{
	uint8_t bpp;

	if (bo->fb_id)
		return 0;

	bpp = gralloc_drm_get_bpp(bo->handle->format) * 8;

	return drmModeAddFB(bo->drm->fd,
			bo->handle->width, bo->handle->height, bpp, bpp,
			bo->handle->stride, bo->fb_handle,
			(uint32_t *) &bo->fb_id);
}
Beispiel #14
0
static void
swap(struct gbm_winsys *winsys)
{
        struct gbm_dev *dev = winsys->dev;
        struct gbm_context *context = winsys->context;
        struct gbm_bo *bo;
        uint32_t handle, stride;
        uint32_t width, height;
        uint32_t fb_id;

        eglSwapBuffers(context->edpy, context->egl_surface);

        bo = gbm_surface_lock_front_buffer(context->gbm_surface);
        width = gbm_bo_get_width(bo);
        height = gbm_bo_get_height(bo);
        stride = gbm_bo_get_stride(bo);
        handle = gbm_bo_get_handle(bo).u32;

        if (drmModeAddFB(dev->fd,
                         width, height,
                         24, /* depth */
                         32, /* bpp */
                         stride,
                         handle,
                         &fb_id)) {
                fprintf(stderr,
                        "Failed to create new back buffer handle: %m\n");
        } else {
                if (dev->saved_crtc == NULL &&
                    set_initial_crtc(dev, fb_id))
                        return;

                if (drmModePageFlip(dev->fd,
                                    dev->crtc,
                                    fb_id,
                                    DRM_MODE_PAGE_FLIP_EVENT,
                                    dev)) {
                        fprintf(stderr, "Failed to page flip: %m\n");
                        return;
                }

                dev->pending_swap = 1;

                wait_swap(dev);

                free_current_bo(context);
                context->current_bo = bo;
                context->current_fb_id = fb_id;
        }
}
int armsoc_bo_add_fb(struct armsoc_bo *bo)
{
	int ret;

	assert(bo->refcnt > 0);
	assert(bo->fb_id == 0);

	ret = drmModeAddFB(bo->dev->fd, bo->width, bo->height, bo->depth,
			bo->bpp, bo->pitch, bo->handle, &bo->fb_id);
	if (ret < 0) {
		bo->fb_id = 0;
		return ret;
	}
	return 0;
}
Beispiel #16
0
void QKmsScreen::performPageFlip()
{
    if (!m_next_bo)
        return;

    uint32_t width = gbm_bo_get_width(m_next_bo);
    uint32_t height = gbm_bo_get_height(m_next_bo);
    uint32_t stride = gbm_bo_get_stride(m_next_bo);
    uint32_t handle = gbm_bo_get_handle(m_next_bo).u32;

    uint32_t fb_id;
    int ret = drmModeAddFB(m_device->fd(), width, height, 24, 32,
                           stride, handle, &fb_id);
    if (ret) {
        qFatal("kms: Failed to create fb: fd %d, w %d, h %d, stride %d, handle %d, ret %d",
               m_device->fd(), width, height, stride, handle, ret);
    }

    if (!m_modeSet) {
        //Set the Mode of the screen.
        int ret = drmModeSetCrtc(m_device->fd(), m_crtcId, fb_id,
                0, 0, &m_connectorId, 1, &m_mode);
        if (ret)
            qFatal("failed to set mode");
        m_modeSet = true;

        // Initialize cursor

        static int hideCursor = qgetenv("QT_QPA_KMS_HIDECURSOR").toInt();
        if (!hideCursor) {
            QCursor cursor(Qt::ArrowCursor);
            m_cursor->changeCursor(&cursor, 0);
        }
    }

    int pageFlipStatus = drmModePageFlip(m_device->fd(), m_crtcId,
                                         fb_id,
                                         DRM_MODE_PAGE_FLIP_EVENT, this);
    if (pageFlipStatus)
    {
        qWarning("Pageflip status: %d", pageFlipStatus);
        gbm_surface_release_buffer(m_gbmSurface, m_next_bo);
        m_next_bo = 0;
    }
}
Beispiel #17
0
static void update_framebuffer_from_bo(
    const struct MPGLContext *ctx, struct gbm_bo *bo)
{
    struct priv *p = ctx->priv;
    p->fb.bo = bo;
    p->fb.fd = p->kms->fd;
    p->fb.width = gbm_bo_get_width(bo);
    p->fb.height = gbm_bo_get_height(bo);
    int stride = gbm_bo_get_stride(bo);
    int handle = gbm_bo_get_handle(bo).u32;

    int ret = drmModeAddFB(p->kms->fd, p->fb.width, p->fb.height,
                           24, 32, stride, handle, &p->fb.id);
    if (ret) {
        MP_ERR(ctx->vo, "Failed to create framebuffer: %s\n", mp_strerror(errno));
    }
    gbm_bo_set_user_data(bo, &p->fb, framebuffer_destroy_callback);
}
bool IntelHWComposerDrm::setupDrmFb(int disp,
                                    uint32_t fb_handler,
                                    drmModeModeInfoPtr mode)
{
    if (mDrmFd < 0) {
        ALOGE("%s: invalid drm FD\n", __func__);
        return false;
    }

    if (!mode) {
        ALOGW("%s: invalid mode !\n", __func__);
        return false;
    }

    int width = mode->hdisplay;
    int height = mode->vdisplay;
    int stride = align_to(width*4, 64);
    uint32_t fb_id = 0;

    // Drm add FB
    int ret = drmModeAddFB(mDrmFd, width, height, 24, 32,
                  stride, (uint32_t)(fb_handler), &fb_id);
    if (ret) {
        ALOGE("%s: Failed to add fb !", __func__);
        return false;
    }

    // add to local output structure
    drmModeFBPtr fbInfo = drmModeGetFB(mDrmFd, fb_id);
    if (!fbInfo) {
        ALOGE("%s: Failed to get fbInfo! ", __func__);
        return false;
    }
    setOutputFBInfo(disp, fbInfo);
    drmModeFreeFB(fbInfo);

    return true;
}
Beispiel #19
0
int main(int argc, char *argv[])
{
   EGLDisplay dpy;
   EGLContext ctx;
   EGLSurface surface;
   EGLConfig config;
   EGLint major, minor, n;
   const char *ver;
   uint32_t handle, stride;
   struct kms kms;
   int ret, fd;
   struct gbm_device *gbm;
   struct gbm_bo *bo;
   drmModeCrtcPtr saved_crtc;
   struct gbm_surface *gs;

   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);
   surface = eglCreateWindowSurface(dpy, config, gs, NULL);

   if (!eglMakeCurrent(dpy, surface, surface, ctx)) {
      fprintf(stderr, "failed to make context current\n");
      ret = -1;
      goto destroy_context;
   }

   render_stuff(kms.mode.hdisplay, kms.mode.vdisplay);

   eglSwapBuffers(dpy, surface);

   bo = gbm_surface_lock_front_buffer(gs);
   handle = gbm_bo_get_handle(bo).u32;
   stride = gbm_bo_get_stride(bo);

   printf("handle=%d, stride=%d\n", handle, stride);

   ret = drmModeAddFB(fd,
		      kms.mode.hdisplay, kms.mode.vdisplay,
		      24, 32, stride, handle, &kms.fb_id);
   if (ret) {
      fprintf(stderr, "failed to create fb\n");
      goto rm_fb;
   }

   saved_crtc = drmModeGetCrtc(fd, kms.encoder->crtc_id);
   if (saved_crtc == NULL)
      goto rm_fb;

   ret = drmModeSetCrtc(fd, kms.encoder->crtc_id, kms.fb_id, 0, 0,
			&kms.connector->connector_id, 1, &kms.mode);
   if (ret) {
      fprintf(stderr, "failed to set mode: %m\n");
      goto free_saved_crtc;
   }

   getchar();

   ret = drmModeSetCrtc(fd, saved_crtc->crtc_id, saved_crtc->buffer_id,
                        saved_crtc->x, saved_crtc->y,
                        &kms.connector->connector_id, 1, &saved_crtc->mode);
   if (ret) {
      fprintf(stderr, "failed to restore crtc: %m\n");
   }

free_saved_crtc:
   drmModeFreeCrtc(saved_crtc);
rm_fb:
   drmModeRmFB(fd, kms.fb_id);
   eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
destroy_context:
   eglDestroyContext(dpy, ctx);
egl_terminate:
   eglTerminate(dpy);
destroy_gbm_device:
   gbm_device_destroy(gbm);
close_fd:
   close(fd);

   return ret;
}
static void
_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
{
  CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
  CoglDisplayEGL *egl_display = context->display->winsys;
  CoglDisplayKMS *kms_display = egl_display->platform;
  CoglRenderer *renderer = context->display->renderer;
  CoglRendererEGL *egl_renderer = renderer->winsys;
  CoglRendererKMS *kms_renderer = egl_renderer->platform;
  CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
  CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
  uint32_t handle, stride;
  CoglFlipKMS *flip;
  GList *l;

  /* If we already have a pending swap then block until it completes */
  while (kms_onscreen->next_fb_id != 0)
    handle_drm_event (kms_renderer);

  /* First chain-up. This will call eglSwapBuffers */
  parent_vtable->onscreen_swap_buffers (onscreen);

  /* Now we need to set the CRTC to whatever is the front buffer */
  kms_onscreen->next_bo = gbm_surface_lock_front_buffer (kms_onscreen->surface);

#if (COGL_VERSION_ENCODE (COGL_GBM_MAJOR, COGL_GBM_MINOR, COGL_GBM_MICRO) >= \
     COGL_VERSION_ENCODE (8, 1, 0))
  stride = gbm_bo_get_stride (kms_onscreen->next_bo);
#else
  stride = gbm_bo_get_pitch (kms_onscreen->next_bo);
#endif
  handle = gbm_bo_get_handle (kms_onscreen->next_bo).u32;

  if (drmModeAddFB (kms_renderer->fd,
                    kms_display->width,
                    kms_display->height,
                    24, /* depth */
                    32, /* bpp */
                    stride,
                    handle,
                    &kms_onscreen->next_fb_id))
    {
      g_warning ("Failed to create new back buffer handle: %m");
      gbm_surface_release_buffer (kms_onscreen->surface,
                                  kms_onscreen->next_bo);
      kms_onscreen->next_bo = NULL;
      kms_onscreen->next_fb_id = 0;
      return;
    }

  /* If this is the first framebuffer to be presented then we now setup the
   * crtc modes... */
  if (kms_display->pending_set_crtc)
    {
      setup_crtc_modes (context->display, kms_onscreen->next_fb_id);
      kms_display->pending_set_crtc = FALSE;
    }

  flip = g_slice_new0 (CoglFlipKMS);
  flip->onscreen = onscreen;

  for (l = kms_display->outputs; l; l = l->next)
    {
      CoglOutputKMS *output = l->data;

      if (drmModePageFlip (kms_renderer->fd,
                           output->encoder->crtc_id,
                           kms_onscreen->next_fb_id,
                           DRM_MODE_PAGE_FLIP_EVENT,
                           flip))
        {
          g_warning ("Failed to flip: %m");
          continue;
        }

      flip->pending++;
    }

  if (flip->pending == 0)
    {
      drmModeRmFB (kms_renderer->fd, kms_onscreen->next_fb_id);
      gbm_surface_release_buffer (kms_onscreen->surface,
                                  kms_onscreen->next_bo);
      kms_onscreen->next_bo = NULL;
      kms_onscreen->next_fb_id = 0;
      g_slice_free (CoglFlipKMS, flip);
      flip = NULL;
    }
  else
    {
      /* Ensure the onscreen remains valid while it has any pending flips... */
      cogl_object_ref (flip->onscreen);
    }
}
static DFBResult
mesaAllocateBuffer( CoreSurfacePool       *pool,
                    void                  *pool_data,
                    void                  *pool_local,
                    CoreSurfaceBuffer     *buffer,
                    CoreSurfaceAllocation *allocation,
                    void                  *alloc_data )
{
     int                 ret;
     CoreSurface        *surface;
     MesaPoolData       *data  = pool_data;
     MesaPoolLocalData  *local = pool_local;
     MesaAllocationData *alloc = alloc_data;
     MesaData           *mesa;

     (void)data;
     (void)local;

     D_DEBUG_AT( Mesa_Surfaces, "%s( %p )\n", __FUNCTION__, buffer );

     D_MAGIC_ASSERT( pool, CoreSurfacePool );
     D_MAGIC_ASSERT( data, MesaPoolData );
     D_MAGIC_ASSERT( local, MesaPoolLocalData );
     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );

     mesa = local->mesa;
     D_ASSERT( mesa != NULL );

     surface = buffer->surface;
     D_MAGIC_ASSERT( surface, CoreSurface );

     EGLContext context = eglGetCurrentContext();

     eglMakeCurrent( mesa->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, mesa->ctx );


     GLint texture, fbo, rbo;

     glGetIntegerv( GL_TEXTURE_BINDING_2D, &texture );
     glGetIntegerv( GL_FRAMEBUFFER_BINDING, &fbo );
     glGetIntegerv( GL_RENDERBUFFER_BINDING, &rbo );

     alloc->bo = gbm_bo_create( mesa->gbm, surface->config.size.w, surface->config.size.h, GBM_BO_FORMAT_ARGB8888,
                                                                            GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING );
     alloc->handle = gbm_bo_get_handle( alloc->bo ).u32;
     alloc->pitch  = gbm_bo_get_stride( alloc->bo );

     alloc->image  = eglCreateImageKHR( mesa->dpy, NULL, EGL_NATIVE_PIXMAP_KHR, alloc->bo, NULL );

     alloc->size = alloc->pitch * surface->config.size.h;

     D_DEBUG_AT( Mesa_Surfaces, "  -> pitch %d, size %d\n", alloc->pitch, alloc->size );

     allocation->size = alloc->size;


     /*
      * Color Render Buffer
      */
     glGenRenderbuffers( 1, &alloc->color_rb );

     glBindRenderbuffer( GL_RENDERBUFFER, alloc->color_rb );

     glEGLImageTargetRenderbufferStorageOES( GL_RENDERBUFFER, alloc->image );


     /*
      * Framebuffer
      */
     glGenFramebuffers( 1, &alloc->fbo );

     glBindFramebuffer( GL_FRAMEBUFFER, alloc->fbo );

     glFramebufferRenderbuffer( GL_FRAMEBUFFER,
                                GL_COLOR_ATTACHMENT0,
                                GL_RENDERBUFFER,
                                alloc->color_rb );

     if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
          D_ERROR( "DirectFB/Mesa: Framebuffer not complete\n" );
     }


     /*
      * Texture
      */
     glGenTextures( 1, &alloc->texture );

     glBindTexture( GL_TEXTURE_2D, alloc->texture );

     glEGLImageTargetTexture2DOES( GL_TEXTURE_2D, alloc->image );


     /*
      * Restore
      */
     glBindRenderbuffer( GL_RENDERBUFFER, rbo );
     glBindFramebuffer( GL_FRAMEBUFFER, fbo );
     glBindTexture( GL_TEXTURE_2D, texture );

     eglMakeCurrent( mesa->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, context );


     /*
      * Mode Framebuffer
      */
     ret = drmModeAddFB( local->mesa->fd,
                         surface->config.size.w, surface->config.size.h,
                         24, 32, alloc->pitch, alloc->handle, &alloc->fb_id );
     if (ret) {
          D_ERROR( "DirectFB/Mesa: drmModeAddFB() failed!\n" );
//          return DFB_FAILURE;
     }


     D_MAGIC_SET( alloc, MesaAllocationData );

     return DFB_OK;
}
Beispiel #22
0
void QKmsBufferManager::setupBuffersForMode(const drmModeModeInfo &mode, int numBuffers)
{
    eglMakeCurrent(m_screen->device()->eglDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, m_screen->device()->eglContext());
    m_screen->bindFramebuffer();


    if (m_frameBufferObject) {
        clearBuffers();
    } else {
        //Setup Framebuffer Object
        glGenFramebuffers(1, &m_frameBufferObject);
        glBindFramebuffer(GL_FRAMEBUFFER, m_frameBufferObject);
    }

    //Setup shared Depth/Stencil buffer
    glGenRenderbuffers(1, &m_depthAndStencilBufferObject);
    glBindRenderbuffer(GL_RENDERBUFFER, m_depthAndStencilBufferObject);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES,
                          mode.hdisplay, mode.vdisplay);

    //Setup "numBuffer" many rendering targets
    for (int i = 0; i < numBuffers; i++) {
        QKmsFramebuffer *buffer = new QKmsFramebuffer();

        glGenRenderbuffers(1, &buffer->renderBuffer);
        glBindRenderbuffer(GL_RENDERBUFFER, buffer->renderBuffer);

        buffer->graphicsBufferObject = gbm_bo_create(m_screen->device()->gbmDevice(),
                                                     mode.hdisplay, mode.vdisplay,
                                                     GBM_BO_FORMAT_XRGB8888,
                                                     GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
        buffer->eglImage = eglCreateImageKHR(m_screen->device()->eglDisplay(), 0, EGL_NATIVE_PIXMAP_KHR,
                                             buffer->graphicsBufferObject, 0);
        glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, buffer->eglImage);

        quint32 stride = gbm_bo_get_pitch(buffer->graphicsBufferObject);
        quint32 handle = gbm_bo_get_handle(buffer->graphicsBufferObject).u32;

        int status = drmModeAddFB(m_screen->device()->fd(), mode.hdisplay, mode.vdisplay,
                                  32, 32, stride, handle, &buffer->framebufferId);
        //Todo: IF this returns true, then this is one less buffer that we use
        //Not so fatal, but not handled at the moment.
        if (status)
            qFatal("failed to add framebuffer");
        m_framebuffers.append(buffer);
    }
    //Attach the Depth and Stencil buffer
    glFramebufferRenderbuffer(GL_FRAMEBUFFER,
                              GL_DEPTH_ATTACHMENT,
                              GL_RENDERBUFFER,
                              m_depthAndStencilBufferObject);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER,
                              GL_STENCIL_ATTACHMENT,
                              GL_RENDERBUFFER,
                              m_depthAndStencilBufferObject);
    //Attach  renderbuffer as Color Attachment.
    glFramebufferRenderbuffer(GL_FRAMEBUFFER,
                              GL_COLOR_ATTACHMENT0,
                              GL_RENDERBUFFER,
                              this->renderTargetBuffer());
}
Beispiel #23
0
int main(int argc, char *argv[])
{
	uint64_t has_dumb;
	int ret, fd, opt, i;
	void *map;

	struct drm_mode_destroy_dumb dreq;
	struct drm_mode_create_dumb creq;
	struct drm_mode_map_dumb mreq;

	drmModePlaneRes *resources;
	drmModePlane *plane = NULL;

	uint32_t handle, stride, size;
	uint32_t plane_id, crtc_id;
	uint32_t width, height;
	uint32_t posx, posy;
	uint32_t fb;

	/* parse command line */

	while ((opt = getopt(argc, argv, "x:y:w:v:c:p:h")) != -1) {
		switch (opt) {
			case 'x':
				posx = atoi(optarg);
				break;
			case 'y':
				posy = atoi(optarg);
				break;
			case 'w':
				width = atoi(optarg);
				break;
			case 'v':
				height = atoi(optarg);
				break;
			case 'p':
				plane_id = atoi(optarg);
				break;
			case 'c':
				crtc_id = atoi(optarg);
				break;
			case 'h':
			default:
				printf("usage: -h] -c <connector> -e <encoder> -m <mode>\n");
				printf("\t-h: this help message\n");
				printf("\t-c <crtc>			crtc id, default is 0\n");
				printf("\t-p <plane>		plane id, default is 0\n");
				printf("\t-x <posx>			plane top left corner xpos, default is 0'\n");
				printf("\t-y <posy>			plane top left corner ypos, default is 0'\n");
				printf("\t-w <width>		plane width, default is 0'\n");
				printf("\t-v <height>		plane height, default is 0'\n");
				exit(0);
		}
	}

	/* open drm device */

	fd = open(device_name, O_RDWR | O_CLOEXEC);
	if (fd < 0) {
		perror("cannot open drm device");
		exit(-1);
	}

	drmSetMaster(fd);

    /* check dumb buffer support */

	if (drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &has_dumb) < 0) {
		perror("DRM_CAP_DUMB_BUFFER ioctl");
		ret = -EFAULT;
		goto err_close;
	}

	if (!has_dumb) {
		fprintf(stderr, "driver does not support dumb buffers\n");
		ret = -EFAULT;
		goto err_close;
	}

	/* get plane */

	resources = drmModeGetPlaneResources(fd);
	if (!resources || resources->count_planes == 0) {
		fprintf(stderr, "drmModeGetPlaneResources failed\n");
		ret = -ENODEV;
		goto err_close;
	}

	for (i = 0; i < resources->count_planes; i++) {
		drmModePlane *p = drmModeGetPlane(fd, resources->planes[i]);
		if (!p)
			continue;

		if (p->plane_id == plane_id) {
			plane = p;
			break;
		}

		drmModeFreePlane(plane);
	}

	if (!plane) {
		fprintf(stderr, "couldn't find specified plane\n");
		ret = -ENODEV;
		goto err_close;
	}

	/* create dumb buffer object */

	memset(&creq, 0, sizeof(creq));

	creq.height = height;
	creq.width = width;
	creq.bpp = 32;

	ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq);
	if (ret) {
		fprintf(stderr, "failed drmIoctl(DRM_IOCTL_MODE_CREATE_DUMB)\n");
		goto err_close;
	}

	handle = creq.handle;
	stride = creq.pitch;
	size = creq.size;

	/* create framebuffer for dumb buffer object */

	ret = drmModeAddFB(fd, width, height, 24, 32, stride, handle, &fb);
	if (ret) {
		fprintf(stderr, "cannot add drm framebuffer for dumb buffer object\n");
		goto err_destroy_dumb;
	}

	/* map dumb buffer object */

	memset(&mreq, 0, sizeof(mreq));

	mreq.handle = handle;

	ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq);
	if (ret) {
		fprintf(stderr, "failed drmIoctl(DRM_IOCTL_MODE_MAP_DUMB)\n");
		goto err_destroy_fb;
	}

	map = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mreq.offset);
	if (map == MAP_FAILED) {
		fprintf(stderr, "cannot mmap dumb buffer\n");
		goto err_destroy_fb;
	}

	/* setup new plane */

	ret = drmModeSetPlane(fd, plane_id, crtc_id, fb, 0, posx, posy,
		width, height, 0, 0, width << 16, height << 16);
	if (ret) {
		fprintf(stderr, "cannot set plane\n");
		goto err_unmap;
	}

	/* draw on the screen */
	draw_test_image((uint32_t *) map, width, height);
	getchar();

	draw_fancy_image((uint32_t *) map, width, height);
	getchar();

	drmModeSetPlane(fd, plane_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);

err_unmap:
	if (map)
		munmap(map, size);

err_destroy_fb:
	drmModeRmFB(fd, fb);

err_destroy_dumb:
	memset(&dreq, 0, sizeof(dreq));

	dreq.handle = handle;

	ret = drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
	if (ret) {
		fprintf(stderr, "cannot destroy dumb buffer\n");
	}

err_close:
	close(fd);

	return ret;
}
static Bool
nouveau_present_flip_exec(ScrnInfoPtr scrn, uint64_t event_id, int sync,
			  uint64_t target_msc, PixmapPtr pixmap, Bool vsync)
{
	ScreenPtr screen = scrn->pScreen;
	struct nouveau_pixmap *priv = NULL;
	NVPtr pNv = NVPTR(scrn);
	uint32_t next_fb;
	CARD16 stride;
	CARD32 size;
	void *token;
	int ret;

#ifdef HAVE_GLAMOR
	if (pNv->AccelMethod == GLAMOR &&
	    !(priv = nouveau_glamor_pixmap_get(pixmap))) {
		int fd = glamor_fd_from_pixmap(screen, pixmap, &stride, &size);
		if (fd < 0)
			return FALSE;

		priv = calloc(1, sizeof(*priv));
		if (!priv)
			return FALSE;

		ret = nouveau_bo_prime_handle_ref(pNv->dev, fd, &priv->bo);
		if (ret) {
			free(priv);
			return FALSE;
		}

		nouveau_glamor_pixmap_set(pixmap, priv);
	} else
#endif
	if (!priv)
		priv = nouveau_pixmap(pixmap);

	ret = drmModeAddFB(pNv->dev->fd, pixmap->drawable.width,
			   pixmap->drawable.height, pixmap->drawable.depth,
			   pixmap->drawable.bitsPerPixel, pixmap->devKind,
			   priv->bo->handle, &next_fb);
	if (ret == 0) {
		struct nouveau_present_flip *flip =
			drmmode_event_queue(scrn, event_id, sizeof(*flip),
					    nouveau_present_flip, &token);
		if (flip) {
			xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
			int last = 0, i;

			drmmode_swap(scrn, next_fb, &flip->old);
			flip->fd = pNv->dev->fd;
			flip->msc = target_msc;

			for (i = 0; i < config->num_crtc; i++) {
				if (config->crtc[i]->enabled)
					last = i;
			}

			for (i = 0; i < config->num_crtc; i++) {
				int type = vsync ? 0 : DRM_MODE_PAGE_FLIP_ASYNC;
				int crtc = drmmode_crtc(config->crtc[i]);
				void *user = NULL;

				if (!config->crtc[i]->enabled)
					continue;

				if (token && ((crtc == sync) || (i == last))) {
					type |= DRM_MODE_PAGE_FLIP_EVENT;
					user  = token;
				}

				ret = drmModePageFlip(pNv->dev->fd, crtc,
						      next_fb, type, user);
				if (ret == 0 && user) {
					token = NULL;
				}
			}

			if (token == NULL) {
				return TRUE;
			}

			drmmode_swap(scrn, flip->old, &next_fb);
			drmmode_event_abort(scrn, event_id, false);
		}

		drmModeRmFB(pNv->dev->fd, next_fb);
	}

	return FALSE;
}
static void ricochet(int tiled, int sprite_w, int sprite_h,
		     int out_w, int out_h, int dump_info)
{
	int                                 ret;
	int                                 gfx_fd;
	int                                 keep_moving;
	const int                           num_surfaces = 3;
	uint32_t                            sprite_handles[num_surfaces];
	uint32_t                            sprite_fb_id[num_surfaces];
	int                                 *sprite_x = NULL;
	int                                 *sprite_y = NULL;
	uint32_t                            sprite_stride;
	uint32_t                            sprite_size;
	uint32_t                            handles[4],
					    pitches[4],
					    offsets[4]; /* we only use [0] */
	uint32_t                            prim_width,
					    prim_height,
					    prim_handle,
					    prim_stride,
					    prim_size,
					    prim_fb_id;
	struct drm_intel_sprite_colorkey    set;
	struct connector                    curr_connector;
	drmModeRes                          *gfx_resources;
	struct termios                      orig_term,
					    curr_term;
	int                                 c_index;
	int                                 sprite_index;
	unsigned int                        *sprite_plane_id = NULL;
	uint32_t                            plane_flags = 0;
	int                                 *delta_x = NULL,
					    *delta_y = NULL;
	struct timeval                      stTimeVal;
	long long                           currTime,
	     prevFlipTime,
	     prevMoveTime,
	     deltaFlipTime,
	     deltaMoveTime,
	     SleepTime;
	char                                key;
	int				    sprite_plane_count = 0;
	int 				    i;
	// Open up I915 graphics device
	gfx_fd = drmOpen("i915", NULL);
	if (gfx_fd < 0) {
		printf("Failed to load i915 driver: %s\n", strerror(errno));
		return;
	}

	// Obtain pointer to struct containing graphics resources
	gfx_resources = drmModeGetResources(gfx_fd);
	if (!gfx_resources) {
		printf("drmModeGetResources failed: %s\n", strerror(errno));
		return;
	}

	if (dump_info != 0) {
		dump_connectors(gfx_fd, gfx_resources);
		dump_crtcs(gfx_fd, gfx_resources);
		dump_planes(gfx_fd, gfx_resources);
	}

	// Save previous terminal settings
	if (tcgetattr( 0, &orig_term) != 0) {
		printf("tcgetattr failure: %s\n",
				strerror(errno));
		return;
	}

	// Set up input to return characters immediately
	curr_term = orig_term;
	curr_term.c_lflag &= ~(ICANON | ECHO | ECHONL);
	curr_term.c_cc[VMIN] = 0;       // No minimum number of characters
	curr_term.c_cc[VTIME] = 0 ;     // Return immediately, even if
	// nothing has been entered.
	if (tcsetattr( 0, TCSANOW, &curr_term) != 0) {
		printf("tcgetattr failure: %s\n", strerror(errno));
		return;
	}

	// Cycle through all connectors and display the flying sprite
	// where there are displays attached and the hardware will support it.
	for (c_index = 0; c_index < gfx_resources->count_connectors; c_index++)  {
		curr_connector.id = gfx_resources->connectors[c_index];

		// Find the native (preferred) display mode
		connector_find_preferred_mode(gfx_fd, gfx_resources, &curr_connector);
		if (curr_connector.mode_valid == 0) {
			printf("No valid preferred mode detected\n");
			goto out;
		}

		// Determine if sprite hardware is available on pipe
		// associated with this connector.
		sprite_plane_count = connector_find_plane(gfx_fd, &curr_connector,
							  &sprite_plane_id);
		if (!sprite_plane_count) {
			printf("Failed to find sprite plane on crtc\n");
			goto out;
		}

		// Width and height of preferred mode
		prim_width = curr_connector.mode.hdisplay;
		prim_height = curr_connector.mode.vdisplay;

		// Allocate and fill memory for primary surface
		ret = prepare_primary_surface(
				gfx_fd,
				prim_width,
				prim_height,
				&prim_handle,
				&prim_stride,
				&prim_size,
				tiled);
		if (ret != 0) {
			printf("Failed to add primary fb (%dx%d): %s\n",
				prim_width, prim_height, strerror(errno));
			goto out;
		}

		// Add the primary surface framebuffer
		ret = drmModeAddFB(gfx_fd, prim_width, prim_height, 24, 32,
				   prim_stride, prim_handle, &prim_fb_id);
		gem_close(gfx_fd, prim_handle);

		if (ret != 0) {
			printf("Failed to add primary fb (%dx%d): %s\n",
					prim_width, prim_height, strerror(errno));
			goto out;
		}

		// Allocate and fill sprite surfaces
		ret = prepare_sprite_surfaces(gfx_fd, sprite_w, sprite_h, num_surfaces,
					      &sprite_handles[0],
					      &sprite_stride, &sprite_size,
					      tiled);
		if (ret != 0) {
			printf("Preparation of sprite surfaces failed %dx%d\n",
				sprite_w, sprite_h);
			goto out;
		}

		// Add the sprite framebuffers
		for (sprite_index = 0; sprite_index < num_surfaces; sprite_index++) {
			handles[0] = sprite_handles[sprite_index];
			handles[1] = handles[0];
			handles[2] = handles[0];
			handles[3] = handles[0];
			pitches[0] = sprite_stride;
			pitches[1] = sprite_stride;
			pitches[2] = sprite_stride;
			pitches[3] = sprite_stride;
			memset(offsets, 0, sizeof(offsets));

			ret = drmModeAddFB2(gfx_fd, sprite_w, sprite_h,
					    DRM_FORMAT_XRGB8888,
					    handles, pitches, offsets,
					    &sprite_fb_id[sprite_index], plane_flags);
			gem_close(gfx_fd, sprite_handles[sprite_index]);

			if (ret) {
				printf("Failed to add sprite fb (%dx%d): %s\n",
				       sprite_w, sprite_h, strerror(errno));

				sprite_index--;
				while (sprite_index >= 0) {
					drmModeRmFB(gfx_fd, sprite_fb_id[sprite_index]);
					sprite_index--;
				}
				goto out;
			}
		}

		if (dump_info != 0) {
			printf("Displayed Mode Connector struct:\n"
				"    .id = %d\n"
				"    .mode_valid = %d\n"
				"    .crtc = %d\n"
				"    .pipe = %d\n"
				"    drmModeModeInfo ...\n"
				"        .name = %s\n"
				"        .type = %d\n"
				"        .flags = %08x\n"
				"    drmModeEncoder ...\n"
				"        .encoder_id = %d\n"
				"        .encoder_type = %d (%s)\n"
				"        .crtc_id = %d\n"
				"        .possible_crtcs = %d\n"
				"        .possible_clones = %d\n"
				"    drmModeConnector ...\n"
				"        .connector_id = %d\n"
				"        .encoder_id = %d\n"
				"        .connector_type = %d (%s)\n"
				"        .connector_type_id = %d\n\n",
				curr_connector.id,
				curr_connector.mode_valid,
				curr_connector.crtc,
				curr_connector.pipe,
				curr_connector.mode.name,
				curr_connector.mode.type,
				curr_connector.mode.flags,
				curr_connector.encoder->encoder_id,
				curr_connector.encoder->encoder_type,
				kmstest_encoder_type_str(curr_connector.encoder->encoder_type),
				curr_connector.encoder->crtc_id,
				curr_connector.encoder->possible_crtcs,
				curr_connector.encoder->possible_clones,
				curr_connector.connector->connector_id,
				curr_connector.connector->encoder_id,
				curr_connector.connector->connector_type,
				kmstest_connector_type_str(curr_connector.connector->connector_type),
				curr_connector.connector->connector_type_id);

			printf("Sprite surface dimensions = %dx%d\n"
				"Sprite output dimensions = %dx%d\n"
				"Press any key to continue >\n",
				sprite_w, sprite_h, out_w, out_h);

			// Wait for a key-press
			while( read(0, &key, 1) == 0);
			// Purge unread characters
			tcflush(0, TCIFLUSH);
		}

		// Set up the primary display mode
		ret = drmModeSetCrtc(gfx_fd, curr_connector.crtc, prim_fb_id,
				     0, 0, &curr_connector.id, 1, &curr_connector.mode);
		if (ret != 0) {
			printf("Failed to set mode (%dx%d@%dHz): %s\n",
				prim_width, prim_height, curr_connector.mode.vrefresh,
				strerror(errno));
			continue;
		}

		// Set the sprite colorkey state
		for(i = 0; i < sprite_plane_count; i++) {
			set.plane_id = sprite_plane_id[i];
			set.min_value = 0;
			set.max_value = 0;
			set.flags = I915_SET_COLORKEY_NONE;
			ret = drmCommandWrite(gfx_fd, DRM_I915_SET_SPRITE_COLORKEY, &set,
					      sizeof(set));
			assert(ret == 0);
		}

		// Set up sprite output dimensions, initial position, etc.
		if (out_w > prim_width / 2)
			out_w = prim_width / 2;
		if (out_h > prim_height / 2)
			out_h = prim_height / 2;

		delta_x = (int *) malloc(sprite_plane_count * sizeof(int));
		delta_y = (int *) malloc(sprite_plane_count * sizeof(int));
		sprite_x = (int *) malloc(sprite_plane_count * sizeof(int));
		sprite_y = (int *) malloc(sprite_plane_count * sizeof(int));

		/* Initializing the coordinates (x,y) of the available sprites on the
		 * connector, equally spaced along the diagonal of the rectangle
		 * {(0,0),(prim_width/2, prim_height/2)}.
		 */
		for(i = 0; i < sprite_plane_count; i++) {
			delta_x[i] = 3;
			delta_y[i] = 4;
			sprite_x[i] = i * (prim_width / (2 * sprite_plane_count));
			sprite_y[i] = i * (prim_height / (2 * sprite_plane_count));
		}

		currTime = 0;
		prevFlipTime = 0;       // Will force immediate sprite flip
		prevMoveTime = 0;       // Will force immediate sprite move
		deltaFlipTime = 500000; // Flip sprite surface every 1/2 second
		deltaMoveTime = 100000; // Move sprite every 100 ms
		sprite_index = num_surfaces - 1;
		keep_moving = 1;

		// Bounce sprite off the walls
		while (keep_moving) {
			// Obtain system time in usec.
			if (gettimeofday( &stTimeVal, NULL ) != 0)
				printf("gettimeofday error: %s\n", strerror(errno));
			else
				currTime = ((long long)stTimeVal.tv_sec * 1000000) + stTimeVal.tv_usec;

			// Check if it's time to flip the sprite surface
			if (currTime - prevFlipTime > deltaFlipTime) {
				sprite_index = (sprite_index + 1) % num_surfaces;

				prevFlipTime = currTime;
			}

			// Move the sprite on the screen and flip
			// the surface if the index has changed
			// NB: sprite_w and sprite_h must be 16.16 fixed point, herego << 16
			for(i = 0; i < sprite_plane_count; i++) {
				if (drmModeSetPlane(gfx_fd, sprite_plane_id[i],
						    curr_connector.crtc,
						    sprite_fb_id[sprite_index],
						    plane_flags,
						    sprite_x[i], sprite_y[i],
						    out_w, out_h,
						    0, 0,
						    sprite_w << 16, sprite_h << 16))
					printf("Failed to enable sprite plane: %s\n",
						strerror(errno));
			}

			// Check if it's time to move the sprite surface
			if (currTime - prevMoveTime > deltaMoveTime)  {

				// Compute the next position for sprite
				for(i = 0; i < sprite_plane_count; i++) {
					sprite_x[i] += delta_x[i];
					sprite_y[i] += delta_y[i];
					if (sprite_x[i] < 0) {
						sprite_x[i] = 0;
						delta_x[i] = -delta_x[i];
					}
					else if (sprite_x[i] > prim_width - out_w) {
						sprite_x[i] = prim_width - out_w;
						delta_x[i] = -delta_x[i];
					}

					if (sprite_y[i] < 0) {
						sprite_y[i] = 0;
						delta_y[i] = -delta_y[i];
					}
					else if (sprite_y[i] > prim_height - out_h) {
						sprite_y[i] = prim_height - out_h;
						delta_y[i] = -delta_y[i];
					}
				}
				prevMoveTime = currTime;
			}

			// Fetch a key from input (non-blocking)
			if (read(0, &key, 1) == 1) {
				switch (key) {
				case 'q':       // Kill the program
				case 'Q':
					goto out;
					break;
				case 's':       // Slow down sprite movement;
					deltaMoveTime = (deltaMoveTime * 100) / 90;
					if (deltaMoveTime > 800000) {
						deltaMoveTime = 800000;
					}
					break;
				case 'S':       // Speed up sprite movement;
					deltaMoveTime = (deltaMoveTime * 100) / 110;
					if (deltaMoveTime < 2000) {
						deltaMoveTime = 2000;
					}
					break;
				case 'f':       // Slow down sprite flipping;
					deltaFlipTime = (deltaFlipTime * 100) / 90;
					if (deltaFlipTime > 1000000)
						deltaFlipTime = 1000000;
					break;
				case 'F':       // Speed up sprite flipping;
					deltaFlipTime = (deltaFlipTime * 100) / 110;
					if (deltaFlipTime < 20000)
						deltaFlipTime = 20000;
					break;
				case 'n':       // Next connector
				case 'N':
					keep_moving = 0;
					break;
				default:
					break;
				}

				// Purge unread characters
				tcflush(0, TCIFLUSH);
			}

			// Wait for min of flip or move deltas
			SleepTime = (deltaFlipTime < deltaMoveTime) ?
				deltaFlipTime : deltaMoveTime;
			usleep(SleepTime);
		}

		free(sprite_plane_id);
		free(sprite_x);
		free(sprite_y);
		free(delta_x);
		free(delta_y);
		sprite_plane_id = NULL;
		sprite_plane_count = 0;
		sprite_x = sprite_y = delta_x = delta_y = NULL;
	}

out:
	// Purge unread characters
	tcflush(0, TCIFLUSH);
	// Restore previous terminal settings
	if (tcsetattr( 0, TCSANOW, &orig_term) != 0) {
		printf("tcgetattr failure: %s\n", strerror(errno));
		return;
	}

	drmModeFreeResources(gfx_resources);
}
Beispiel #26
0
static gboolean
_cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
                            GError **error)
{
  CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
  CoglContext *context = framebuffer->context;
  CoglDisplay *display = context->display;
  CoglDisplayEGL *egl_display = display->winsys;
  CoglDisplayKMS *kms_display = egl_display->platform;
  CoglRenderer *renderer = display->renderer;
  CoglRendererEGL *egl_renderer = renderer->winsys;
  CoglRendererKMS *kms_renderer = egl_renderer->platform;
  CoglOnscreenEGL *egl_onscreen;
  CoglOnscreenKMS *kms_onscreen;
  int i;

  _COGL_RETURN_VAL_IF_FAIL (egl_display->egl_context, FALSE);

  onscreen->winsys = g_slice_new0 (CoglOnscreenEGL);
  egl_onscreen = onscreen->winsys;

  kms_onscreen = g_slice_new0 (CoglOnscreenKMS);
  egl_onscreen->platform = kms_onscreen;

  context->glGenRenderbuffers (2, kms_onscreen->color_rb);

  for (i = 0; i < 2; i++)
    {
      uint32_t handle, stride;

      kms_onscreen->bo[i] =
        gbm_bo_create (kms_renderer->gbm,
                       kms_display->mode.hdisplay, kms_display->mode.vdisplay,
                       GBM_BO_FORMAT_XRGB8888,
                       GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
      if (!kms_onscreen->bo[i])
        {
          g_set_error (error, COGL_WINSYS_ERROR,
                       COGL_WINSYS_ERROR_CREATE_CONTEXT,
                       "Failed to allocate buffer");
          return FALSE;
        }

      kms_onscreen->image[i] =
        _cogl_egl_create_image (context,
                                EGL_NATIVE_PIXMAP_KHR,
                                kms_onscreen->bo[i],
                                NULL);

      if (kms_onscreen->image[i] == EGL_NO_IMAGE_KHR)
        {
          g_set_error (error, COGL_WINSYS_ERROR,
                       COGL_WINSYS_ERROR_CREATE_CONTEXT,
                       "Failed to create EGL image");
          return FALSE;
        }

      context->glBindRenderbuffer (GL_RENDERBUFFER_EXT,
                                   kms_onscreen->color_rb[i]);
      context->glEGLImageTargetRenderbufferStorage (GL_RENDERBUFFER,
                                                    kms_onscreen->image[i]);
      context->glBindRenderbuffer (GL_RENDERBUFFER_EXT, 0);

      handle = gbm_bo_get_handle (kms_onscreen->bo[i]).u32;
      stride = gbm_bo_get_pitch (kms_onscreen->bo[i]);

      if (drmModeAddFB (kms_renderer->fd,
                        kms_display->mode.hdisplay,
                        kms_display->mode.vdisplay,
                        24, 32,
                        stride,
                        handle,
                        &kms_onscreen->fb_id[i]) != 0)
        {
          g_set_error (error, COGL_WINSYS_ERROR,
                       COGL_WINSYS_ERROR_CREATE_CONTEXT,
                       "Failed to create framebuffer from buffer");
          return FALSE;
        }
    }

  context->glGenFramebuffers (1, &kms_onscreen->fb);
  context->glBindFramebuffer (GL_FRAMEBUFFER_EXT, kms_onscreen->fb);

  context->glGenRenderbuffers (1, &kms_onscreen->depth_rb);
  context->glBindRenderbuffer (GL_RENDERBUFFER_EXT, kms_onscreen->depth_rb);
  context->glRenderbufferStorage (GL_RENDERBUFFER_EXT,
                                  GL_DEPTH_COMPONENT16,
                                  kms_display->mode.hdisplay,
                                  kms_display->mode.vdisplay);
  context->glBindRenderbuffer (GL_RENDERBUFFER_EXT, 0);

  context->glFramebufferRenderbuffer (GL_FRAMEBUFFER_EXT,
                                      GL_DEPTH_ATTACHMENT_EXT,
                                      GL_RENDERBUFFER_EXT,
                                      kms_onscreen->depth_rb);

  kms_onscreen->current_frame = 0;
  _cogl_winsys_onscreen_swap_buffers (onscreen);

  _cogl_framebuffer_winsys_update_size (framebuffer,
                                        kms_display->width,
                                        kms_display->height);

  return TRUE;
}
static int modeset_create_fb(int fd, struct modeset_buf *buf)
{
	struct drm_mode_create_dumb creq;
	struct drm_mode_destroy_dumb dreq;
	struct drm_mode_map_dumb mreq;
	int ret;

	/* create dumb buffer */
	memset(&creq, 0, sizeof(creq));
	creq.width = buf->width;
	creq.height = buf->height;
	creq.bpp = 32;
	ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq);
	if (ret < 0) {
		fprintf(stderr, "cannot create dumb buffer (%d): %m\n",
			errno);
		return -errno;
	}
	buf->stride = creq.pitch;
	buf->size = creq.size;
	buf->handle = creq.handle;

	/* create framebuffer object for the dumb-buffer */
	ret = drmModeAddFB(fd, buf->width, buf->height, 24, 32, buf->stride,
			   buf->handle, &buf->fb);
	if (ret) {
		fprintf(stderr, "cannot create framebuffer (%d): %m\n",
			errno);
		ret = -errno;
		goto err_destroy;
	}

	/* prepare buffer for memory mapping */
	memset(&mreq, 0, sizeof(mreq));
	mreq.handle = buf->handle;
	ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq);
	if (ret) {
		fprintf(stderr, "cannot map dumb buffer (%d): %m\n",
			errno);
		ret = -errno;
		goto err_fb;
	}

	/* perform actual memory mapping */
	buf->map = mmap(0, buf->size, PROT_READ | PROT_WRITE, MAP_SHARED,
		        fd, mreq.offset);
	if (buf->map == MAP_FAILED) {
		fprintf(stderr, "cannot mmap dumb buffer (%d): %m\n",
			errno);
		ret = -errno;
		goto err_fb;
	}

	/* clear the framebuffer to 0 */
	memset(buf->map, 0, buf->size);

	return 0;

err_fb:
	drmModeRmFB(fd, buf->fb);
err_destroy:
	memset(&dreq, 0, sizeof(dreq));
	dreq.handle = buf->handle;
	drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
	return ret;
}
Beispiel #28
0
static Bool
ms_do_pageflip(ScreenPtr screen,
               PixmapPtr new_front,
               struct ms_present_vblank_event *event,
               int ref_crtc_vblank_pipe,
               Bool async)
{
#ifndef GLAMOR_HAS_GBM
    return FALSE;
#else
    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
    modesettingPtr ms = modesettingPTR(scrn);
    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
    drmmode_bo new_front_bo;
    uint32_t flags;
    int i;
    struct ms_flipdata *flipdata;
    glamor_block_handler(screen);

    new_front_bo.gbm = glamor_gbm_bo_from_pixmap(screen, new_front);
    new_front_bo.dumb = NULL;
    if (!new_front_bo.gbm) {
        xf86DrvMsg(scrn->scrnIndex, X_ERROR,
                   "Failed to get GBM bo for flip to new front.\n");
        return FALSE;
    }

    flipdata = calloc(1, sizeof(struct ms_flipdata));
    if (!flipdata) {
        drmmode_bo_destroy(&ms->drmmode, &new_front_bo);
        xf86DrvMsg(scrn->scrnIndex, X_ERROR,
                   "Failed to allocate flipdata.\n");
        return FALSE;
    }

    flipdata->event = event;
    flipdata->screen = screen;

    /*
     * Take a local reference on flipdata.
     * if the first flip fails, the sequence abort
     * code will free the crtc flip data, and drop
     * it's reference which would cause this to be
     * freed when we still required it.
     */
    flipdata->flip_count++;

    /* Create a new handle for the back buffer */
    flipdata->old_fb_id = ms->drmmode.fb_id;
    if (drmModeAddFB(ms->fd, scrn->virtualX, scrn->virtualY,
                     scrn->depth, scrn->bitsPerPixel,
                     drmmode_bo_get_pitch(&new_front_bo),
                     drmmode_bo_get_handle(&new_front_bo), &ms->drmmode.fb_id)) {
        goto error_out;
    }

    drmmode_bo_destroy(&ms->drmmode, &new_front_bo);

    flags = DRM_MODE_PAGE_FLIP_EVENT;
    if (async)
        flags |= DRM_MODE_PAGE_FLIP_ASYNC;

    /* Queue flips on all enabled CRTCs.
     *
     * Note that if/when we get per-CRTC buffers, we'll have to update this.
     * Right now it assumes a single shared fb across all CRTCs, with the
     * kernel fixing up the offset of each CRTC as necessary.
     *
     * Also, flips queued on disabled or incorrectly configured displays
     * may never complete; this is a configuration error.
     */
    for (i = 0; i < config->num_crtc; i++) {
        xf86CrtcPtr crtc = config->crtc[i];

        if (!ms_crtc_on(crtc))
            continue;

        if (!queue_flip_on_crtc(screen, crtc, flipdata,
                                ref_crtc_vblank_pipe,
                                flags)) {
            goto error_undo;
        }
    }

    /*
     * Do we have more than our local reference,
     * if so and no errors, then drop our local
     * reference and return now.
     */
    if (flipdata->flip_count > 1) {
        flipdata->flip_count--;
        return TRUE;
    }

error_undo:

    /*
     * Have we just got the local reference?
     * free the framebuffer if so since nobody successfully
     * submitted anything
     */
    if (flipdata->flip_count == 1) {
        drmModeRmFB(ms->fd, ms->drmmode.fb_id);
        ms->drmmode.fb_id = flipdata->old_fb_id;
    }

error_out:
    xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n",
               strerror(errno));
    /* if only the local reference - free the structure,
     * else drop the local reference and return */
    if (flipdata->flip_count == 1)
        free(flipdata);
    else
        flipdata->flip_count--;

    return FALSE;
#endif /* GLAMOR_HAS_GBM */
}
Beispiel #29
0
int main(int argc, char **argv)
{
	int drmfd;
	int vtfd;
	unsigned int i, j;
	drmModeRes *res = NULL;
	drmModeEncoder *enc = NULL;
	drmModeConnector *conn = NULL;
	uint32_t fb_id, conn_id, crtc_id;
	long int vt_args;
	struct drm_mode_create_dumb fbo_create_args = {0};
	struct drm_mode_map_dumb fbo_map_args = {0};
	struct drm_mode_destroy_dumb fbo_close_args = {0};
	uint32_t gem_handle;
	uint8_t *fb_virt = NULL; /* start address of dumb fb */
	uint32_t fb_pitch;
	uint32_t fb_size;
	drmModeModeInfo curr_mode; /* store current mode infomation */

	vtfd = open("/dev/tty1", O_RDWR | O_CLOEXEC);

	/* trigger a vt switch to /dev/tty1 and wait for available */
	ioctl(vtfd, VT_ACTIVATE, 1);
	ioctl(vtfd, VT_WAITACTIVE, 1);

	ioctl(vtfd, KDGETMODE, &vt_args);
	printf("switch to %s mode on tty1\n", vt_args == KD_TEXT ? "TEXT" : "GFX");

	/* from now on, we can do pixel dance on dumb fb */
	drmfd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);

	res = drmModeGetResources(drmfd);

	for (i = 0; i < res->count_connectors; i++) {

		conn = drmModeGetConnector(drmfd, res->connectors[i]);
		conn_id = conn->connector_id;

		if (conn->connection != DRM_MODE_CONNECTED) {
			printf("conn:[%d] is offline\n", conn->connector_id);
			drmModeFreeConnector(conn);
			continue;
		}

		/* we choose max valid mode */
		memcpy(&curr_mode, &conn->modes[0], sizeof(curr_mode));
		printf("conn:[%d] is online %dx%d@%dHZ\n", conn->connector_id, curr_mode.hdisplay, curr_mode.vdisplay, curr_mode.vrefresh);

		enc = drmModeGetEncoder(drmfd, conn->encoder_id);

		crtc_id = enc->crtc_id;
		drmModeFreeEncoder(enc);

		/* create dumb fb and retrieve aperture */
		fbo_create_args.width = curr_mode.hdisplay;
		fbo_create_args.height = curr_mode.vdisplay;
		fbo_create_args.bpp = 32;

		drmIoctl(drmfd, DRM_IOCTL_MODE_CREATE_DUMB, &fbo_create_args);

		gem_handle = fbo_create_args.handle;
		fb_size = fbo_create_args.size;
		fb_pitch = fbo_create_args.pitch;

		drmModeAddFB(drmfd, curr_mode.hdisplay, curr_mode.vdisplay, 24, 32, fb_pitch, gem_handle, &fb_id);

		fbo_map_args.handle = gem_handle;
		drmIoctl(drmfd, DRM_IOCTL_MODE_MAP_DUMB, &fbo_map_args);

		fb_virt = mmap(0, fb_size, PROT_READ | PROT_WRITE, MAP_SHARED, drmfd, fbo_map_args.offset);

		drmModeFreeConnector(conn);
	}

	drmModeFreeResources(res);

	drmModeSetCrtc(drmfd, crtc_id, fb_id, 0, 0, &conn_id, 1, &curr_mode);

	for (i = 0; i < curr_mode.vdisplay; i++) {
		for (j = 0; j < curr_mode.hdisplay; j++) {
			//*((uint32_t *)(fb_virt + fb_pitch * i + j * 4)) = i * j;
			*((uint32_t *)(fb_virt + fb_pitch * i + j * 4)) = 0xFFFFFF;
		}
	}

	/* say hello */
	draw_8x8_char(10, 10, fb_virt, fb_pitch, 'h');
	draw_8x8_char(18, 10, fb_virt, fb_pitch, 'e');
	draw_8x8_char(26, 10, fb_virt, fb_pitch, 'l');
	draw_8x8_char(34, 10, fb_virt, fb_pitch, 'l');
	draw_8x8_char(42, 10, fb_virt, fb_pitch, 'o');

	draw_8x8_char(50, 10, fb_virt, fb_pitch, ' ');
	draw_8x8_char(58, 10, fb_virt, fb_pitch, 'r');
	draw_8x8_char(66, 10, fb_virt, fb_pitch, 'e');
	draw_8x8_char(74, 10, fb_virt, fb_pitch, 'd');
	draw_8x8_char(82, 10, fb_virt, fb_pitch, 'h');
	draw_8x8_char(90, 10, fb_virt, fb_pitch, 'a');
	draw_8x8_char(98, 10, fb_virt, fb_pitch, 't');
	draw_8x8_char(106, 10, fb_virt, fb_pitch, '!');

	draw_8x16_char(110, 100, fb_virt, fb_pitch, 'h');
	draw_8x16_char(118, 100, fb_virt, fb_pitch, 'e');
	draw_8x16_char(126, 100, fb_virt, fb_pitch, 'l');
	draw_8x16_char(134, 100, fb_virt, fb_pitch, 'l');
	draw_8x16_char(142, 100, fb_virt, fb_pitch, 'o');

	draw_8x16_char(150, 100, fb_virt, fb_pitch, ' ');
	draw_8x16_char(158, 100, fb_virt, fb_pitch, 'r');
	draw_8x16_char(166, 100, fb_virt, fb_pitch, 'e');
	draw_8x16_char(174, 100, fb_virt, fb_pitch, 'd');
	draw_8x16_char(182, 100, fb_virt, fb_pitch, 'h');
	draw_8x16_char(190, 100, fb_virt, fb_pitch, 'a');
	draw_8x16_char(198, 100, fb_virt, fb_pitch, 't');
	draw_8x16_char(206, 100, fb_virt, fb_pitch, '!');

	usleep(5000000);

	/* unwind anything we done */
	munmap(fb_virt, fb_size);

	drmModeRmFB(drmfd, fb_id);

	fbo_close_args.handle = gem_handle;
	drmIoctl(drmfd, DRM_IOCTL_MODE_DESTROY_DUMB, &fbo_close_args);

	close(drmfd);

	/* switch back to /dev/tty7 for convinience */
	ioctl(vtfd, VT_ACTIVATE, 7);
	ioctl(vtfd, VT_WAITACTIVE, 7);

	close(vtfd);
	return 0;
}
Beispiel #30
0
bool Drm::setDrmMode(int index, drmModeModeInfoPtr mode)
{
    DrmOutput *output = &mOutputs[index];

    int oldFbId = 0;
    int oldFbHandle = 0;
    // reuse current frame buffer if there is no resolution change
    int fbId = -1;

    drmModeModeInfo currentMode;
    memcpy(&currentMode, &output->mode, sizeof(drmModeModeInfo));

    if (isSameDrmMode(mode, &currentMode))
        return true;

    if (currentMode.hdisplay != mode->hdisplay ||
        currentMode.vdisplay != mode->vdisplay) {

        oldFbId = output->fbId;
        oldFbHandle = output->fbHandle;

        // allocate frame buffer
        int stride = 0;
#ifdef INTEL_SUPPORT_HDMI_PRIMARY
        output->fbHandle = Hwcomposer::getInstance().getBufferManager()->allocFrameBuffer(
            DEFAULT_DRM_FB_WIDTH, DEFAULT_DRM_FB_HEIGHT, &stride);
#else
        output->fbHandle = Hwcomposer::getInstance().getBufferManager()->allocFrameBuffer(
            mode->hdisplay, mode->vdisplay, &stride);
#endif
        if (output->fbHandle == 0) {
            ELOGTRACE("failed to allocate frame buffer");
            return false;
        }

        int ret = 0;
        ret = drmModeAddFB(
            mDrmFd,
#ifdef INTEL_SUPPORT_HDMI_PRIMARY
            DEFAULT_DRM_FB_WIDTH,
            DEFAULT_DRM_FB_HEIGHT,
#else
            mode->hdisplay,
            mode->vdisplay,
#endif
            DrmConfig::getFrameBufferDepth(),
            DrmConfig::getFrameBufferBpp(),
            stride,
            output->fbHandle,
            &output->fbId);
        if (ret != 0) {
            ELOGTRACE("drmModeAddFB failed, error: %d", ret);
            return false;
        }
        fbId = output->fbId;
    }

    ILOGTRACE("mode set: %dx%d@%dHz", mode->hdisplay, mode->vdisplay, mode->vrefresh);

    int ret = drmModeSetCrtc(mDrmFd, output->crtc->crtc_id, fbId, 0, 0,
                   &output->connector->connector_id, 1, mode);

    if (ret == 0) {
        //save mode
        memcpy(&output->mode, mode, sizeof(drmModeModeInfo));
    } else {
        ELOGTRACE("drmModeSetCrtc failed. error: %d", ret);
    }

    if (oldFbId) {
        drmModeRmFB(mDrmFd, oldFbId);
    }

    if (oldFbHandle) {
        Hwcomposer::getInstance().getBufferManager()->freeFrameBuffer(oldFbHandle);
    }

    return ret == 0;
}