Пример #1
0
int host1x_job_append(struct host1x_job *job, struct drm_tegra_bo *bo,
		      unsigned long offset, struct host1x_pushbuf **pbp)
{
	struct host1x_pushbuf *pb;
	size_t size;
	void *ptr;
	int err;

	if (!job || !bo || !pbp)
		return -EINVAL;

	err = drm_tegra_bo_map(bo, &ptr);
	if (err < 0)
		return err;

	size = (job->num_pushbufs + 1) * sizeof(*pb);

	pb = realloc(job->pushbufs, size);
	if (!pb)
		return -ENOMEM;

	job->pushbufs = pb;

	pb = &job->pushbufs[job->num_pushbufs++];
	memset(pb, 0, sizeof(*pb));

	pb->syncpt = job->syncpt;
	pb->bo = drm_tegra_bo_get(bo);
	pb->ptr = ptr + offset;
	pb->offset = offset;

	*pbp = pb;

	return 0;
}
Пример #2
0
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;
}