コード例 #1
0
ファイル: etna.c プロジェクト: alexzhang007/etna_viv
/* Clear GPU context, to rebuild it for next flush */
static int gpu_context_clear(struct etna_ctx *ctx)
{
    /* If context was used, queue free it and allocate new buffer to prevent
     * overwriting it while being used by the GPU.  Otherwise we can just
     * re-use it.
     */
    int rv;
#ifdef DEBUG
    fprintf(stderr, "gpu_context_clear (context %i)\n", (int)GCCTX(ctx)->id);
#endif
    if(GCCTX(ctx)->inUse != NULL &&
       *GCCTX(ctx)->inUse)
    {
#ifdef DEBUG
        fprintf(stderr, "gpu_context_clear: context was in use, deferred freeing and reallocating it\n");
#endif
        if((rv = etna_bo_del(ctx->conn, ctx->ctx_bo, ctx->queue)) != ETNA_OK)
        {
            return rv;
        }
        if((ctx->ctx_bo = etna_bo_new(ctx->conn, COMMAND_BUFFER_SIZE, DRM_ETNA_GEM_TYPE_CMD)) == NULL)
        {
            return ETNA_OUT_OF_MEMORY;
        }
    }
    /* Leave space at beginning of buffer for PIPE switch */
    GCCTX(ctx)->bufferSize = BEGIN_COMMIT_CLEARANCE;
    GCCTX(ctx)->logical = etna_bo_map(ctx->ctx_bo);
#ifdef GCABI_CONTEXT_HAS_PHYSICAL
    GCCTX(ctx)->bytes = etna_bo_size(ctx->ctx_bo); /* actual size of buffer */
    GCCTX(ctx)->physical = HANDLE_TO_VIV(etna_bo_gpu_address(ctx->ctx_bo));
#endif
    /* When context is empty, initial pipe should default to entry pipe so that
     * no pipe switch is needed within the context and the kernel does the
     * right thing.
     */
    GCCTX(ctx)->initialPipe = GCCTX(ctx)->entryPipe;
    return ETNA_OK;
}
コード例 #2
0
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;
}
コード例 #3
0
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;
}