Esempio n. 1
12
void DumbFramebuffer::Create()
{
	int r;

	const FormatInfo& format_info = format_info_array.at(m_format);

	m_num_planes = format_info.num_planes;

	for (int i = 0; i < format_info.num_planes; ++i) {
		const FormatPlaneInfo& pi = format_info.planes[i];
		FramebufferPlane& plane = m_planes[i];

		/* create dumb buffer */
		struct drm_mode_create_dumb creq = drm_mode_create_dumb();
		creq.width = width() / pi.xsub;
		creq.height = height() / pi.ysub;
		creq.bpp = pi.bitspp;
		r = drmIoctl(card().fd(), DRM_IOCTL_MODE_CREATE_DUMB, &creq);
		if (r)
			throw std::invalid_argument("foo");

		plane.handle = creq.handle;
		plane.stride = creq.pitch;
		plane.size = creq.height * creq.pitch;

		/*
		printf("buf %d: %dx%d, bitspp %d, stride %d, size %d\n",
			i, creq.width, creq.height, pi->bitspp, plane->stride, plane->size);
		*/

		/* prepare buffer for memory mapping */
		struct drm_mode_map_dumb mreq = drm_mode_map_dumb();
		mreq.handle = plane.handle;
		r = drmIoctl(card().fd(), DRM_IOCTL_MODE_MAP_DUMB, &mreq);
		if (r)
			throw std::invalid_argument("foo");

		/* perform actual memory mapping */
		m_planes[i].map = (uint8_t *)mmap(0, plane.size, PROT_READ | PROT_WRITE, MAP_SHARED,
						  card().fd(), mreq.offset);
		if (plane.map == MAP_FAILED)
			throw std::invalid_argument("foo");

		/* clear the framebuffer to 0 */
		memset(plane.map, 0, plane.size);
	}

	/* create framebuffer object for the dumb-buffer */
	uint32_t bo_handles[4] = { m_planes[0].handle, m_planes[1].handle };
	uint32_t pitches[4] = { m_planes[0].stride, m_planes[1].stride };
	uint32_t offsets[4] = { 0 };
	uint32_t id;
	r = drmModeAddFB2(card().fd(), width(), height(), (uint32_t)format(),
			  bo_handles, pitches, offsets, &id, 0);
	if (r)
		throw std::invalid_argument("foo");

	set_id(id);
}
Esempio n. 2
0
ExtFramebuffer::ExtFramebuffer(Card& card, uint32_t width, uint32_t height, PixelFormat format,
			       uint32_t handles[], uint32_t pitches[], uint32_t offsets[])
	: Framebuffer(card, width, height)
{
	uint32_t id;
	int r = drmModeAddFB2(card.fd(), width, height, (uint32_t)format, handles, pitches, offsets, &id, 0);
	if (r)
		throw std::invalid_argument(string("Failed to create ExtFramebuffer: ") + strerror(r));

	set_id(id);
}
Esempio n. 3
0
int NvImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) {
  memset(bo, 0, sizeof(hwc_drm_bo_t));
  NvBuffer_t *buf = GrallocGetNvBuffer(handle);
  if (buf) {
    atomic_fetch_add(&buf->ref, 1);
    *bo = buf->bo;
    return 0;
  }

  buf = new NvBuffer_t();
  if (!buf) {
    ALOGE("Failed to allocate new NvBuffer_t");
    return -ENOMEM;
  }
  buf->bo.priv = buf;
  buf->importer = this;

  // We initialize the reference count to 2 since NvGralloc is still using this
  // buffer (will be cleared in the NvGrallocRelease), and the other
  // reference is for HWC (this ImportBuffer call).
  atomic_init(&buf->ref, 2);

  int ret = gralloc_->perform(gralloc_, GRALLOC_MODULE_PERFORM_DRM_IMPORT,
                              drm_->fd(), handle, &buf->bo);
  if (ret) {
    ALOGE("GRALLOC_MODULE_PERFORM_DRM_IMPORT failed %d", ret);
    delete buf;
    return ret;
  }

  ret = drmModeAddFB2(drm_->fd(), buf->bo.width, buf->bo.height, buf->bo.format,
                      buf->bo.gem_handles, buf->bo.pitches, buf->bo.offsets,
                      &buf->bo.fb_id, 0);
  if (ret) {
    ALOGE("Failed to add fb %d", ret);
    ReleaseBufferImpl(&buf->bo);
    delete buf;
    return ret;
  }

  ret = GrallocSetNvBuffer(handle, buf);
  if (ret) {
    /* This will happen is persist.tegra.gpu_mapping_cache is 0/off,
     * or if NV gralloc runs out of "priv slots" (currently 3 per buffer,
     * only one of which should be used by drm_hwcomposer). */
    ALOGE("Failed to register free callback for imported buffer %d", ret);
    ReleaseBufferImpl(&buf->bo);
    delete buf;
    return ret;
  }
  *bo = buf->bo;
  return 0;
}
Esempio n. 4
0
/**
 * igt_create_fb_with_bo_size:
 * @fd: open i915 drm file descriptor
 * @width: width of the framebuffer in pixel
 * @height: height of the framebuffer in pixel
 * @format: drm fourcc pixel format code
 * @tiling: tiling layout of the framebuffer (as framebuffer modifier)
 * @fb: pointer to an #igt_fb structure
 * @bo_size: size of the backing bo (0 for minimum needed size)
 *
 * This function allocates a gem buffer object suitable to back a framebuffer
 * with the requested properties and then wraps it up in a drm framebuffer
 * object of the requested size. All metadata is stored in @fb.
 *
 * The backing storage of the framebuffer is filled with all zeros, i.e. black
 * for rgb pixel formats.
 *
 * Returns:
 * The kms id of the created framebuffer.
 */
unsigned int
igt_create_fb_with_bo_size(int fd, int width, int height,
			   uint32_t format, uint64_t tiling,
			   struct igt_fb *fb, unsigned bo_size)
{
	uint32_t fb_id;
	int bpp;

	memset(fb, 0, sizeof(*fb));

	bpp = igt_drm_format_to_bpp(format);

	igt_debug("%s(width=%d, height=%d, format=0x%x [bpp=%d], tiling=0x%"PRIx64", size=%d)\n",
		  __func__, width, height, format, bpp, tiling, bo_size);
	do_or_die(create_bo_for_fb(fd, width, height, bpp, tiling, bo_size,
				   &fb->gem_handle, &fb->size, &fb->stride));

	igt_debug("%s(handle=%d, pitch=%d)\n",
		  __func__, fb->gem_handle, fb->stride);

	if (tiling != LOCAL_DRM_FORMAT_MOD_NONE &&
	    tiling != LOCAL_I915_FORMAT_MOD_X_TILED) {
		do_or_die(__kms_addfb(fd, fb->gem_handle, width, height,
				      fb->stride, format, tiling,
				      LOCAL_DRM_MODE_FB_MODIFIERS, &fb_id));
	} else {
		uint32_t handles[4];
		uint32_t pitches[4];
		uint32_t offsets[4];

		memset(handles, 0, sizeof(handles));
		memset(pitches, 0, sizeof(pitches));
		memset(offsets, 0, sizeof(offsets));

		handles[0] = fb->gem_handle;
		pitches[0] = fb->stride;

		do_or_die(drmModeAddFB2(fd, width, height, format,
					handles, pitches, offsets,
					&fb_id, 0));
	}

	fb->width = width;
	fb->height = height;
	fb->tiling = tiling;
	fb->drm_format = format;
	fb->fb_id = fb_id;

	return fb_id;
}
Esempio n. 5
0
drm_fb * CDRMUtils::DrmFbGetFromBo(struct gbm_bo *bo)
{
  {
    struct drm_fb *fb = static_cast<drm_fb *>(gbm_bo_get_user_data(bo));
    if(fb)
    {
      return fb;
    }
  }

  struct drm_fb *fb = new drm_fb;
  fb->bo = bo;

  uint32_t width,
           height,
           handles[4] = {0},
           strides[4] = {0},
           offsets[4] = {0};

  width = gbm_bo_get_width(bo);
  height = gbm_bo_get_height(bo);

  handles[0] = gbm_bo_get_handle(bo).u32;
  strides[0] = gbm_bo_get_stride(bo);
  memset(offsets, 0, 16);

  auto ret = drmModeAddFB2(m_fd,
                           width,
                           height,
                           m_primary_plane->format,
                           handles,
                           strides,
                           offsets,
                           &fb->fb_id,
                           0);

  if(ret)
  {
    delete (fb);
    CLog::Log(LOGDEBUG, "CDRMUtils::%s - failed to add framebuffer", __FUNCTION__);
    return nullptr;
  }

  gbm_bo_set_user_data(bo, fb, DrmFbDestroyCallback);

  return fb;
}
drm_overlay_fb * drm_clone_fb(int drm_fd, drm_overlay_fb *fb)
{
    uint32_t fb_id = HANDLE_INVALID;
    drm_overlay_fb *clone;
    uint32_t bo_handles[4];
    uint32_t pitches[4];
    uint32_t offsets[4];
    int err;

    clone = malloc(sizeof(*clone));
    if (!clone)
        return NULL;

    memcpy(clone, fb, sizeof(*fb));

    bo_handles[0] = clone->bo_y_id;
    bo_handles[1] = clone->bo_cb_id;
    bo_handles[2] = clone->bo_cr_id;
    bo_handles[3] = 0;

    pitches[0] = clone->pitch_y;
    pitches[1] = clone->pitch_cb;
    pitches[2] = clone->pitch_cr;
    pitches[3] = 0;

    offsets[0] = clone->offset_y;
    offsets[1] = clone->offset_cb;
    offsets[2] = clone->offset_cr;
    offsets[3] = 0;

    err = drmModeAddFB2(drm_fd, clone->width, clone->height, clone->format,
                        bo_handles, pitches, offsets, &fb_id, 0);
    if (err) {
        ErrorMsg("Failed to create DRM framebuffer: %s\n", strerror(-err));
        free(clone);
        return NULL;
    }

    clone->fb_id = fb_id;

    drm_tegra_bo_ref(clone->bo);
    drm_tegra_bo_ref(clone->bo_cb);
    drm_tegra_bo_ref(clone->bo_cr);

    return clone;
}
Esempio n. 7
0
int add_fb_sp_bo(struct sp_bo *bo, uint32_t format)
{
	int ret;
	uint32_t handles[4], pitches[4], offsets[4];

	handles[0] = bo->handle;
	pitches[0] = bo->pitch;
	offsets[0] = 0;

	ret = drmModeAddFB2(bo->dev->fd, bo->width, bo->height,
			format, handles, pitches, offsets,
			&bo->fb_id, bo->flags);
	if (ret) {
		printf("failed to create fb ret=%d\n", ret);
		return ret;
	}
	return 0;
}
Esempio n. 8
0
uint32_t DisplayOzone::Buffer::getDRMFB()
{
    if (!mHasDRMFB)
    {
        int fd              = gbm_device_get_fd(mDisplay->mGBM);
        uint32_t handles[4] = {gbm_bo_get_handle(mBO).u32};
        uint32_t pitches[4] = {gbm_bo_get_stride(mBO)};
        uint32_t offsets[4] = {0};
        if (drmModeAddFB2(fd, mWidth, mHeight, mDRMFormatFB, handles, pitches, offsets, &mDRMFB, 0))
        {
            std::cerr << "drmModeAddFB2 failed" << std::endl;
        }
        else
        {
            mHasDRMFB = true;
        }
    }

    return mDRMFB;
}
Esempio n. 9
0
void OmapFramebuffer::Create()
{
	const PixelFormatInfo& format_info = get_pixel_format_info(m_format);

	m_num_planes = format_info.num_planes;

	for (int i = 0; i < format_info.num_planes; ++i) {
		const PixelFormatPlaneInfo& pi = format_info.planes[i];
		FramebufferPlane& plane = m_planes[i];

		uint32_t flags = OMAP_BO_SCANOUT | OMAP_BO_WC;

		uint32_t size = width() * height() * pi.bitspp / 8;

		struct omap_bo* bo =  omap_bo_new(m_omap_card.dev(), size, flags);
		if (!bo)
			throw invalid_argument(string("omap_bo_new failed: ") + strerror(errno));

		uint32_t stride = width() * pi.bitspp / 8;

		plane.omap_bo = bo;
		plane.handle = omap_bo_handle(bo);
		plane.stride = stride;
		plane.size = omap_bo_size(bo);
		plane.offset = 0;
		plane.map = 0;
		plane.prime_fd = -1;
	}

	/* create framebuffer object for the dumb-buffer */
	uint32_t bo_handles[4] = { m_planes[0].handle, m_planes[1].handle };
	uint32_t pitches[4] = { m_planes[0].stride, m_planes[1].stride };
	uint32_t offsets[4] = { m_planes[0].offset, m_planes[1].offset };
	uint32_t id;
	int r = drmModeAddFB2(card().fd(), width(), height(), (uint32_t)format(),
			  bo_handles, pitches, offsets, &id, 0);
	if (r)
		throw invalid_argument(string("drmModeAddFB2 failed: ") + strerror(errno));

	set_id(id);
}
static int fb_alloc_buffer(struct private_module_t *module,
			   struct private_buffer_t *buffer,
			   const drmModeModeInfo *mode)
{
	unsigned int bo_attrs[] = {
		KMS_WIDTH, mode->hdisplay,
		KMS_HEIGHT, mode->vdisplay,
		KMS_BO_TYPE, KMS_BO_TYPE_SCANOUT_X8R8G8B8,
		KMS_TERMINATE_PROP_LIST,
	};
	uint32_t handles[4] = { 0 };
	uint32_t pitches[4] = { 0 };
	uint32_t offsets[4] = { 0 };
	int err;

	err = kms_bo_create(module->kms, bo_attrs, &buffer->bo);
	if (err < 0)
		goto done;

	err = kms_bo_map(buffer->bo, &buffer->vaddr);
	if (err < 0)
		goto done;

	kms_bo_get_prop(buffer->bo, KMS_HANDLE, &buffer->handle);

	handles[0] = buffer->handle;
	pitches[0] = mode->hdisplay * 2;
	err = drmModeAddFB2(module->fd, mode->hdisplay, mode->vdisplay,
			    FB_FORMAT, handles, pitches, offsets, &buffer->fb,
			    0);

done:
	if (err < 0)
		fb_free_buffer(module, buffer);

	return err;
}
Esempio n. 11
0
ExtFramebuffer::ExtFramebuffer(Card& card, uint32_t width, uint32_t height, PixelFormat format,
			       int fds[4], uint32_t pitches[4], uint32_t offsets[4])
	: Framebuffer(card, width, height)
{
	int r;

	const PixelFormatInfo& format_info = get_pixel_format_info(format);

	uint32_t handles[4] = { 0 };

	for (int i = 0; i < format_info.num_planes; ++i) {
		r = drmPrimeFDToHandle(card.fd(), fds[i], &handles[i]);
		if (r)
			throw invalid_argument(string("drmPrimeFDToHandle: ") + strerror(errno));
	}

	uint32_t id;
	r = drmModeAddFB2(card.fd(), width, height, (uint32_t)format,
			  handles, pitches, offsets, &id, 0);
	if (r)
		throw invalid_argument(string("drmModeAddFB2 failed: ") + strerror(errno));

	set_id(id);
}
Esempio n. 12
0
int main(int argc, char **argv)
{
	struct exynos_device *dev;
	struct exynos_bo *bo, *src;
	struct connector con;
	unsigned int fb_id;
	uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0};
	drmModeRes *resources;
	int ret, fd, c;

	memset(&con, 0, sizeof(struct connector));

	if (argc != 3) {
		usage(argv[0]);
		return -EINVAL;
	}

	while ((c = getopt(argc, argv, optstr)) != -1) {
		switch (c) {
		case 's':
			con.crtc = -1;
			if (sscanf(optarg, "%d:0x%64s",
						&con.id,
						con.mode_str) != 2 &&
					sscanf(optarg, "%d@%d:%64s",
						&con.id,
						&con.crtc,
						con.mode_str) != 3)
				usage(argv[0]);
			break;
		default:
			usage(argv[0]);
			return -EINVAL;
		}
	}

	fd = drmOpen(DRM_MODULE_NAME, NULL);
	if (fd < 0) {
		fprintf(stderr, "failed to open.\n");
		return fd;
	}

	dev = exynos_device_create(fd);
	if (!dev) {
		drmClose(dev->fd);
		return -EFAULT;
	}

	resources = drmModeGetResources(dev->fd);
	if (!resources) {
		fprintf(stderr, "drmModeGetResources failed: %s\n",
				strerror(errno));
		ret = -EFAULT;
		goto err_drm_close;
	}

	connector_find_mode(dev->fd, &con, resources);
	drmModeFreeResources(resources);

	if (!con.mode) {
		fprintf(stderr, "failed to find usable connector\n");
		ret = -EFAULT;
		goto err_drm_close;
	}

	screen_width = con.mode->hdisplay;
	screen_height = con.mode->vdisplay;

	if (screen_width == 0 || screen_height == 0) {
		fprintf(stderr, "failed to find sane resolution on connector\n");
		ret = -EFAULT;
		goto err_drm_close;
	}

	printf("screen width = %d, screen height = %d\n", screen_width,
			screen_height);

	bo = exynos_create_buffer(dev, screen_width * screen_height * 4, 0);
	if (!bo) {
		ret = -EFAULT;
		goto err_drm_close;
	}

	handles[0] = bo->handle;
	pitches[0] = screen_width * 4;
	offsets[0] = 0;

	ret = drmModeAddFB2(dev->fd, screen_width, screen_height,
				DRM_FORMAT_RGBA8888, handles,
				pitches, offsets, &fb_id, 0);
	if (ret < 0)
		goto err_destroy_buffer;

	con.plane_zpos = -1;

	memset(bo->vaddr, 0xff, screen_width * screen_height * 4);

	ret = drm_set_crtc(dev, &con, fb_id);
	if (ret < 0)
		goto err_rm_fb;

	ret = test_case.solid_fill(dev, bo);
	if (ret < 0) {
		fprintf(stderr, "failed to solid fill operation.\n");
		goto err_rm_fb;
	}

	wait_for_user_input(0);

	src = exynos_create_buffer(dev, screen_width * screen_height * 4, 0);
	if (!src) {
		ret = -EFAULT;
		goto err_rm_fb;
	}

	ret = test_case.copy(dev, src, bo, G2D_IMGBUF_GEM);
	if (ret < 0) {
		fprintf(stderr, "failed to test copy operation.\n");
		goto err_free_src;
	}

	wait_for_user_input(0);

	ret = test_case.copy_with_scale(dev, src, bo, G2D_IMGBUF_GEM);
	if (ret < 0) {
		fprintf(stderr, "failed to test copy and scale operation.\n");
		goto err_free_src;
	}

	wait_for_user_input(0);

	ret = test_case.checkerboard(dev, src, bo, G2D_IMGBUF_GEM);
	if (ret < 0) {
		fprintf(stderr, "failed to issue checkerboard test.\n");
		goto err_free_src;
	}

	wait_for_user_input(1);

	/*
	 * The blend test uses the userptr functionality of exynos-drm, which
	 * is currently not safe to use. If the kernel hasn't been build with
	 * exynos-iommu support, then the blend test is going to produce (kernel)
	 * memory corruption, eventually leading to a system crash.
	 *
	 * Disable the test for now, until the kernel code has been sanitized.
	 */
#if 0
	ret  = test_case.blend(dev, src, bo, G2D_IMGBUF_USERPTR);
	if (ret < 0)
		fprintf(stderr, "failed to test blend operation.\n");

	getchar();
#endif

err_free_src:
	if (src)
		exynos_destroy_buffer(src);

err_rm_fb:
	drmModeRmFB(dev->fd, fb_id);

err_destroy_buffer:
	exynos_destroy_buffer(bo);

err_drm_close:
	drmClose(dev->fd);
	exynos_device_destroy(dev);

	return 0;
}
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);
}
static drm_overlay_fb * drm_create_fb_internal(struct drm_tegra *drm,
                                               int drm_fd,
                                               uint32_t drm_format,
                                               uint32_t width, uint32_t height,
                                               uint32_t *bo_handles,
                                               uint32_t *pitches,
                                               uint32_t *offsets,
                                               Bool dont_map)
{
    struct drm_tegra_bo *bo    = NULL;
    struct drm_tegra_bo *bo_cb = NULL;
    struct drm_tegra_bo *bo_cr = NULL;
    drm_overlay_fb *fb         = NULL;
    uint32_t fb_id             = HANDLE_INVALID;
    Bool from_handle;
    int err;

    if (width == 0 || height == 0)
        return NULL;

    if (!pitches) {
        pitches = alloca(sizeof(uint32_t) * 4);

        pitches[0] = fb_pitch_aligned(drm_format, width);
        pitches[1] = fb_pitch_c_aligned(drm_format, width);
        pitches[2] = fb_pitch_c_aligned(drm_format, width);
        pitches[3] = 0;
    }

    if (!offsets) {
        offsets = alloca(sizeof(uint32_t) * 4);

        offsets[0] = 0;
        offsets[1] = 0;
        offsets[2] = 0;
        offsets[3] = 0;
    }

    from_handle = !!(bo_handles);

    if (from_handle) {
        err = drm_tegra_bo_wrap(&bo, drm, bo_handles[0], 0,
                                pitches[0] * height);
        if (err)
            goto error_cleanup;

        drm_tegra_bo_forbid_caching(bo);

        if (format_planar(drm_format)) {
            err = drm_tegra_bo_wrap(&bo_cb, drm, bo_handles[1], 0,
                                    pitches[1] * height / 2);
            if (err)
                goto error_cleanup;

            drm_tegra_bo_forbid_caching(bo_cb);

            err = drm_tegra_bo_wrap(&bo_cr, drm, bo_handles[2], 0,
                                    pitches[2] * height / 2);
            if (err)
                goto error_cleanup;

            drm_tegra_bo_forbid_caching(bo_cr);
        }

        goto create_framebuffer;
    }

    bo_handles = alloca(sizeof(uint32_t) * 4);

    bo_handles[1] = HANDLE_INVALID;
    bo_handles[2] = HANDLE_INVALID;
    bo_handles[3] = HANDLE_INVALID;

    /* Allocate PLANE[0] */
    err = drm_tegra_bo_new(&bo, drm, 0, offsets[0] +
                           fb_size_aligned(drm_format, width, height));
    if (err)
        goto error_cleanup;

    drm_tegra_bo_get_handle(bo, &bo_handles[0]);

    if (!format_planar(drm_format))
        goto create_framebuffer;

    /* Allocate PLANE[1] */
    err = drm_tegra_bo_new(&bo_cb, drm, 0, offsets[1] +
                           fb_size_c_aligned(drm_format, width, height));
    if (err)
        goto error_cleanup;

    drm_tegra_bo_get_handle(bo_cb, &bo_handles[1]);

    /* Allocate PLANE[2] */
    err = drm_tegra_bo_new(&bo_cr, drm, 0, offsets[2] +
                           fb_size_c_aligned(drm_format, width, height));
    if (err)
        goto error_cleanup;

    drm_tegra_bo_get_handle(bo_cr, &bo_handles[2]);

create_framebuffer:
    err = drmModeAddFB2(drm_fd, width, height, drm_format,
                        bo_handles, pitches, offsets, &fb_id, 0);
    if (err) {
        ErrorMsg("Failed to create DRM framebuffer: %s\n", strerror(-err));
        goto error_cleanup;
    }

    fb = calloc(1, sizeof(*fb));
    if (!fb)
        goto error_cleanup;

    fb->fb_id           = fb_id;
    fb->format          = drm_format;
    fb->width           = width;
    fb->height          = height;
    fb->width_c         = fb_width_c(drm_format, width);
    fb->height_c        = fb_height_c(drm_format, height);
    fb->bpp             = fb_bpp(drm_format);
    fb->bpp_c           = fb_bpp_c(drm_format);
    fb->bo_y_id         = bo_handles[0];
    fb->bo_cb_id        = bo_handles[1];
    fb->bo_cr_id        = bo_handles[2];
    fb->bo_y            = bo;
    fb->bo_cb           = bo_cb;
    fb->bo_cr           = bo_cr;
    fb->pitch_y         = pitches[0];
    fb->pitch_cb        = pitches[1];
    fb->pitch_cr        = pitches[2];
    fb->offset_y        = offsets[0];
    fb->offset_cb       = offsets[1];
    fb->offset_cr       = offsets[2];

    fb->width_pad       = (fb_pitch_aligned(drm_format, width) -
                            fb_pitch(drm_format, width)) *
                                fb_height_aligned(drm_format, height);

    fb->height_pad      = (fb_height_aligned(drm_format, height) - height) *
                            fb_pitch_aligned(drm_format, width);

    fb->height_offset   = (fb_height_aligned(drm_format, height) - height) *
                            fb->bpp / 8;

    fb->width_c_pad     = (fb_pitch_c_aligned(drm_format, width) -
                            fb_pitch_c(drm_format, width)) *
                                fb_height_c_aligned(drm_format, height);

    fb->height_c_pad    = (fb_height_c_aligned(drm_format, height) - fb->height_c) *
                            fb_pitch_c_aligned(drm_format, width);

    fb->height_c_offset = (fb_height_c_aligned(drm_format, height) - fb->height_c) *
                            fb->bpp_c / 8;

    if (dont_map)
        return fb;

    err = drm_tegra_bo_map(fb->bo_y, (void **)&fb->bo_y_mmap);
    if (err)
        goto error_cleanup;

    fb->bo_y_mmap += fb->offset_y;

    if (!format_planar(drm_format))
        return fb;

    err = drm_tegra_bo_map(fb->bo_cb, (void **)&fb->bo_cb_mmap);
    if (err)
        goto error_cleanup;

    err = drm_tegra_bo_map(fb->bo_cr, (void **)&fb->bo_cr_mmap);
    if (err)
        goto error_cleanup;

    fb->bo_cb_mmap += fb->offset_cb;
    fb->bo_cr_mmap += fb->offset_cr;

    return fb;

error_cleanup:
    if (from_handle)
        return NULL;

    if (fb_id != HANDLE_INVALID)
        drmModeRmFB(drm_fd, fb_id);

    drm_tegra_bo_unref(bo);
    drm_tegra_bo_unref(bo_cb);
    drm_tegra_bo_unref(bo_cr);

    free(fb);

    return NULL;
}
Esempio n. 15
0
  bool CreateFramebuffer(int width, int height, Framebuffer& framebuffer) {
    framebuffer.bo = gbm_bo_create(gbm_, width, height, GBM_FORMAT_XRGB8888,
                                   GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
    if (!framebuffer.bo) {
      fprintf(stderr, "failed to create a gbm buffer.\n");
      return false;
    }

    framebuffer.fd = gbm_bo_get_fd(framebuffer.bo);
    if (framebuffer.fd < 0) {
      fprintf(stderr, "failed to get fb for bo: %d", framebuffer.fd);
      return false;
    }

    uint32_t handle = gbm_bo_get_handle(framebuffer.bo).u32;
    uint32_t stride = gbm_bo_get_stride(framebuffer.bo);
    uint32_t offset = 0;
    drmModeAddFB2(drm_->GetFD(), width, height, GBM_FORMAT_XRGB8888, &handle,
                  &stride, &offset, &framebuffer.fb_id, 0);
    if (!framebuffer.fb_id) {
      fprintf(stderr, "failed to create framebuffer from buffer object.\n");
      return false;
    }

    const EGLint khr_image_attrs[] = {EGL_DMA_BUF_PLANE0_FD_EXT,
                                      framebuffer.fd,
                                      EGL_WIDTH,
                                      width,
                                      EGL_HEIGHT,
                                      height,
                                      EGL_LINUX_DRM_FOURCC_EXT,
                                      GBM_FORMAT_XRGB8888,
                                      EGL_DMA_BUF_PLANE0_PITCH_EXT,
                                      static_cast<const int>(stride),
                                      EGL_DMA_BUF_PLANE0_OFFSET_EXT,
                                      static_cast<const int>(offset),
                                      EGL_NONE};

    framebuffer.image =
        egl_.CreateImageKHR(egl_.display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT,
                            nullptr /* no client buffer */, khr_image_attrs);
    if (framebuffer.image == EGL_NO_IMAGE_KHR) {
      fprintf(stderr, "failed to make image from buffer object: %s\n",
              EglGetError());
      return false;
    }

    glGenTextures(1, &framebuffer.gl_tex);
    glBindTexture(GL_TEXTURE_2D, framebuffer.gl_tex);
    egl_.EGLImageTargetTexture2DOES(GL_TEXTURE_2D, framebuffer.image);
    glBindTexture(GL_TEXTURE_2D, 0);

    glGenFramebuffers(1, &framebuffer.gl_fb);
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.gl_fb);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
                           framebuffer.gl_tex, 0);

    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
      fprintf(stderr,
              "failed framebuffer check for created target buffer: %x\n",
              glCheckFramebufferStatus(GL_FRAMEBUFFER));
      glDeleteFramebuffers(1, &framebuffer.gl_fb);
      glDeleteTextures(1, &framebuffer.gl_tex);
      return false;
    }

    return true;
  }
Esempio n. 16
0
static int exynos_alloc(struct hook_data *data) {
  struct exynos_device *device;
  struct exynos_bo *bo;
  struct exynos_page *pages;
  struct drm_prime_handle req = { 0 };
  unsigned i;

  const unsigned flags = 0;

  device = exynos_device_create(data->drm_fd);
  if (device == NULL) {
    fprintf(stderr, "[exynos_init] error: failed to create device from fd\n");
    return -1;
  }

  pages = calloc(data->num_pages, sizeof(struct exynos_page));
  if (pages == NULL) {
    fprintf(stderr, "[exynos_init] error: failed to allocate pages\n");
    goto fail_alloc;
  }

  for (i = 0; i < data->num_pages; ++i) {
    bo = exynos_bo_create(device, data->size, flags);
    if (bo == NULL) {
      fprintf(stderr, "[exynos_init] error: failed to create buffer object\n");
      goto fail;
    }

    req.handle = bo->handle;

    if (drmIoctl(data->drm_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &req) < 0) {
      fprintf(stderr, "[exynos_init] error: failed to get fd from bo\n");
      exynos_bo_destroy(bo);
      goto fail;
    }

    /* Don't map the BO, since we don't access it through userspace. */

    pages[i].bo = bo;
    pages[i].fd = req.fd;
    pages[i].base = data;

    pages[i].used = false;
    pages[i].clear = true;
  }

  if (vconf.use_screen == 1) {
    const uint32_t pixel_format = (data->bpp == 2) ? DRM_FORMAT_RGB565 : DRM_FORMAT_XRGB8888;
    uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0};

    pitches[0] = data->pitch;
    offsets[0] = 0;

    for (i = 0; i < data->num_pages; ++i) {
      handles[0] = pages[i].bo->handle;

      if (drmModeAddFB2(data->drm_fd, data->width, data->height,
                        pixel_format, handles, pitches, offsets,
                        &pages[i].buf_id, flags)) {
        fprintf(stderr, "[exynos_init] error: failed to add bo %u to fb\n", i);
        goto fail;
      }
    }
  }

  if (vconf.use_screen == 1) {
    /* Setup CRTC: display the last allocated page. */
    if (drmModeSetCrtc(data->drm_fd, data->drm->crtc_id, pages[data->num_pages - 1].buf_id,
                       0, 0, &data->drm->connector_id, 1, data->drm->mode)) {
      fprintf(stderr, "[exynos_init] error: drmModeSetCrtc failed\n");
      goto fail;
    }
  }

  data->pages = pages;
  data->device = device;

  return 0;

fail:
  clean_up_pages(pages, data->num_pages);

fail_alloc:
  exynos_device_destroy(device);

  return -1;
}