static struct pipe_resource * etna_resource_from_handle(struct pipe_screen *pscreen, const struct pipe_resource *tmpl, struct winsys_handle *handle, unsigned usage) { struct etna_screen *screen = etna_screen(pscreen); struct etna_resource *rsc; struct etna_resource_level *level; struct pipe_resource *prsc; struct pipe_resource *ptiled = NULL; DBG("target=%d, format=%s, %ux%ux%u, array_size=%u, last_level=%u, " "nr_samples=%u, usage=%u, bind=%x, flags=%x", tmpl->target, util_format_name(tmpl->format), tmpl->width0, tmpl->height0, tmpl->depth0, tmpl->array_size, tmpl->last_level, tmpl->nr_samples, tmpl->usage, tmpl->bind, tmpl->flags); rsc = CALLOC_STRUCT(etna_resource); if (!rsc) return NULL; level = &rsc->levels[0]; prsc = &rsc->base; *prsc = *tmpl; pipe_reference_init(&prsc->reference, 1); list_inithead(&rsc->list); prsc->screen = pscreen; rsc->bo = etna_screen_bo_from_handle(pscreen, handle, &level->stride); if (!rsc->bo) goto fail; rsc->seqno = 1; rsc->layout = modifier_to_layout(handle->modifier); rsc->halign = TEXTURE_HALIGN_FOUR; level->width = tmpl->width0; level->height = tmpl->height0; /* Determine padding of the imported resource. */ unsigned paddingX = 0, paddingY = 0; etna_layout_multiple(rsc->layout, screen->specs.pixel_pipes, VIV_FEATURE(screen, chipMinorFeatures1, TEXTURE_HALIGN), &paddingX, &paddingY, &rsc->halign); if (!screen->specs.use_blt) etna_adjust_rs_align(screen->specs.pixel_pipes, NULL, &paddingY); level->padded_width = align(level->width, paddingX); level->padded_height = align(level->height, paddingY); level->layer_stride = level->stride * util_format_get_nblocksy(prsc->format, level->padded_height); level->size = level->layer_stride; /* The DDX must give us a BO which conforms to our padding size. * The stride of the BO must be greater or equal to our padded * stride. The size of the BO must accomodate the padded height. */ if (level->stride < util_format_get_stride(tmpl->format, level->padded_width)) { BUG("BO stride %u is too small for RS engine width padding (%zu, format %s)", level->stride, util_format_get_stride(tmpl->format, level->padded_width), util_format_name(tmpl->format)); goto fail; } if (etna_bo_size(rsc->bo) < level->stride * level->padded_height) { BUG("BO size %u is too small for RS engine height padding (%u, format %s)", etna_bo_size(rsc->bo), level->stride * level->padded_height, util_format_name(tmpl->format)); goto fail; } if (rsc->layout == ETNA_LAYOUT_LINEAR) { /* * Both sampler and pixel pipes can't handle linear, create a compatible * base resource, where we can attach the imported buffer as an external * resource. */ struct pipe_resource tiled_templat = *tmpl; /* * Remove BIND_SCANOUT to avoid recursion, as etna_resource_create uses * this function to import the scanout buffer and get a tiled resource. */ tiled_templat.bind &= ~PIPE_BIND_SCANOUT; ptiled = etna_resource_create(pscreen, &tiled_templat); if (!ptiled) goto fail; etna_resource(ptiled)->external = prsc; return ptiled; } return prsc; fail: etna_resource_destroy(pscreen, prsc); if (ptiled) etna_resource_destroy(pscreen, ptiled); return NULL; }
static struct pipe_resource * etna_resource_from_handle(struct pipe_screen *pscreen, const struct pipe_resource *tmpl, struct winsys_handle *handle, unsigned usage) { struct etna_screen *screen = etna_screen(pscreen); struct etna_resource *rsc = CALLOC_STRUCT(etna_resource); struct etna_resource_level *level = &rsc->levels[0]; struct pipe_resource *prsc = &rsc->base; struct pipe_resource *ptiled = NULL; DBG("target=%d, format=%s, %ux%ux%u, array_size=%u, last_level=%u, " "nr_samples=%u, usage=%u, bind=%x, flags=%x", tmpl->target, util_format_name(tmpl->format), tmpl->width0, tmpl->height0, tmpl->depth0, tmpl->array_size, tmpl->last_level, tmpl->nr_samples, tmpl->usage, tmpl->bind, tmpl->flags); if (!rsc) return NULL; *prsc = *tmpl; pipe_reference_init(&prsc->reference, 1); list_inithead(&rsc->list); prsc->screen = pscreen; rsc->bo = etna_screen_bo_from_handle(pscreen, handle, &level->stride); if (!rsc->bo) goto fail; level->width = tmpl->width0; level->height = tmpl->height0; /* We will be using the RS to copy with this resource, so we must * ensure that it is appropriately aligned for the RS requirements. */ unsigned paddingX = ETNA_RS_WIDTH_MASK + 1; unsigned paddingY = (ETNA_RS_HEIGHT_MASK + 1) * screen->specs.pixel_pipes; level->padded_width = align(level->width, paddingX); level->padded_height = align(level->height, paddingY); /* The DDX must give us a BO which conforms to our padding size. * The stride of the BO must be greater or equal to our padded * stride. The size of the BO must accomodate the padded height. */ if (level->stride < util_format_get_stride(tmpl->format, level->padded_width)) { BUG("BO stride is too small for RS engine width padding"); goto fail; } if (etna_bo_size(rsc->bo) < level->stride * level->padded_height) { BUG("BO size is too small for RS engine height padding"); goto fail; } if (handle->type == DRM_API_HANDLE_TYPE_SHARED && tmpl->bind & PIPE_BIND_RENDER_TARGET) { /* Render targets are linear in Xorg but must be tiled * here. It would be nice if dri_drawable_get_format() * set scanout for these buffers too. */ struct etna_resource *tiled; ptiled = etna_resource_create(pscreen, tmpl); if (!ptiled) goto fail; tiled = etna_resource(ptiled); tiled->scanout = renderonly_scanout_for_prime(prsc, screen->ro); if (!tiled->scanout) goto fail; return ptiled; } return prsc; fail: etna_resource_destroy(pscreen, prsc); if (ptiled) etna_resource_destroy(pscreen, ptiled); return NULL; }