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; }
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; }