Exemple #1
0
/**
 * This is called when we need to set up GL rendering to a new X window.
 */
static GLboolean
intelCreateBuffer(__DRIscreen * driScrnPriv,
                  __DRIdrawable * driDrawPriv,
                  const struct gl_config * mesaVis, GLboolean isPixmap)
{
   struct intel_renderbuffer *rb;
   mesa_format rgbFormat;
   struct gl_framebuffer *fb;

   if (isPixmap)
      return false;

   fb = CALLOC_STRUCT(gl_framebuffer);
   if (!fb)
      return false;

   _mesa_initialize_window_framebuffer(fb, mesaVis);

   if (mesaVis->redBits == 5)
      rgbFormat = MESA_FORMAT_B5G6R5_UNORM;
   else if (mesaVis->sRGBCapable)
      rgbFormat = MESA_FORMAT_B8G8R8A8_SRGB;
   else if (mesaVis->alphaBits == 0)
      rgbFormat = MESA_FORMAT_B8G8R8X8_UNORM;
   else
      rgbFormat = MESA_FORMAT_B8G8R8A8_UNORM;

   /* setup the hardware-based renderbuffers */
   rb = intel_create_renderbuffer(rgbFormat);
   _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &rb->Base.Base);

   if (mesaVis->doubleBufferMode) {
      rb = intel_create_renderbuffer(rgbFormat);
      _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &rb->Base.Base);
   }

   /*
    * Assert here that the gl_config has an expected depth/stencil bit
    * combination: one of d24/s8, d16/s0, d0/s0. (See intelInitScreen2(),
    * which constructs the advertised configs.)
    */
   if (mesaVis->depthBits == 24) {
      assert(mesaVis->stencilBits == 8);

      /*
       * Use combined depth/stencil. Note that the renderbuffer is
       * attached to two attachment points.
       */
      rb = intel_create_private_renderbuffer(MESA_FORMAT_Z24_UNORM_S8_UINT);
      _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &rb->Base.Base);
      _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &rb->Base.Base);
   }
   else if (mesaVis->depthBits == 16) {
      assert(mesaVis->stencilBits == 0);
      rb = intel_create_private_renderbuffer(MESA_FORMAT_Z_UNORM16);
      _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &rb->Base.Base);
   }
   else {
      assert(mesaVis->depthBits == 0);
      assert(mesaVis->stencilBits == 0);
   }

   /* now add any/all software-based renderbuffers we may need */
   _swrast_add_soft_renderbuffers(fb,
                                  false, /* never sw color */
                                  false, /* never sw depth */
                                  false, /* never sw stencil */
                                  mesaVis->accumRedBits > 0,
                                  false, /* never sw alpha */
                                  false  /* never sw aux */ );
   driDrawPriv->driverPrivate = fb;

   return true;
}
struct pipe_screen *
nv30_screen_create(struct nouveau_device *dev)
{
   struct nv30_screen *screen = CALLOC_STRUCT(nv30_screen);
   struct pipe_screen *pscreen;
   struct nouveau_pushbuf *push;
   struct nv04_fifo *fifo;
   unsigned oclass = 0;
   int ret, i;

   if (!screen)
      return NULL;

   switch (dev->chipset & 0xf0) {
   case 0x30:
      if (RANKINE_0397_CHIPSET & (1 << (dev->chipset & 0x0f)))
         oclass = NV30_3D_CLASS;
      else
      if (RANKINE_0697_CHIPSET & (1 << (dev->chipset & 0x0f)))
         oclass = NV34_3D_CLASS;
      else
      if (RANKINE_0497_CHIPSET & (1 << (dev->chipset & 0x0f)))
         oclass = NV35_3D_CLASS;
      break;
   case 0x40:
      if (CURIE_4097_CHIPSET & (1 << (dev->chipset & 0x0f)))
         oclass = NV40_3D_CLASS;
      else
      if (CURIE_4497_CHIPSET & (1 << (dev->chipset & 0x0f)))
         oclass = NV44_3D_CLASS;
      break;
   case 0x60:
      if (CURIE_4497_CHIPSET6X & (1 << (dev->chipset & 0x0f)))
         oclass = NV44_3D_CLASS;
      break;
   default:
      break;
   }

   if (!oclass) {
      NOUVEAU_ERR("unknown 3d class for 0x%02x\n", dev->chipset);
      FREE(screen);
      return NULL;
   }

   pscreen = &screen->base.base;
   pscreen->destroy = nv30_screen_destroy;
   pscreen->get_param = nv30_screen_get_param;
   pscreen->get_paramf = nv30_screen_get_paramf;
   pscreen->get_shader_param = nv30_screen_get_shader_param;
   pscreen->context_create = nv30_context_create;
   pscreen->is_format_supported = nv30_screen_is_format_supported;
   nv30_resource_screen_init(pscreen);
   nouveau_screen_init_vdec(&screen->base);

   screen->base.fence.emit = nv30_screen_fence_emit;
   screen->base.fence.update = nv30_screen_fence_update;

   ret = nouveau_screen_init(&screen->base, dev);
   if (ret)
      FAIL_SCREEN_INIT("nv30_screen_init failed: %d\n", ret);

   screen->base.vidmem_bindings |= PIPE_BIND_VERTEX_BUFFER;
   screen->base.sysmem_bindings |= PIPE_BIND_VERTEX_BUFFER;
   if (oclass == NV40_3D_CLASS) {
      screen->base.vidmem_bindings |= PIPE_BIND_INDEX_BUFFER;
      screen->base.sysmem_bindings |= PIPE_BIND_INDEX_BUFFER;
   }

   fifo = screen->base.channel->data;
   push = screen->base.pushbuf;
   push->rsvd_kick = 16;

   ret = nouveau_object_new(screen->base.channel, 0x00000000, NV01_NULL_CLASS,
                            NULL, 0, &screen->null);
   if (ret)
      FAIL_SCREEN_INIT("error allocating null object: %d\n", ret);

   /* DMA_FENCE refuses to accept DMA objects with "adjust" filled in,
    * this means that the address pointed at by the DMA object must
    * be 4KiB aligned, which means this object needs to be the first
    * one allocated on the channel.
    */
   ret = nouveau_object_new(screen->base.channel, 0xbeef1e00,
                            NOUVEAU_NOTIFIER_CLASS, &(struct nv04_notify) {
                            .length = 32 }, sizeof(struct nv04_notify),
static struct gbm_bo *
gbm_gallium_drm_bo_import(struct gbm_device *gbm,
                          uint32_t type, void *buffer, uint32_t usage)
{
   struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm);
   struct gbm_gallium_drm_bo *bo;
   struct winsys_handle whandle;
   struct pipe_resource *resource;

   switch (type) {
#if HAVE_WAYLAND_PLATFORM
   case GBM_BO_IMPORT_WL_BUFFER:
   {
      struct wl_drm_buffer *wb = (struct wl_drm_buffer *) buffer;

      resource = wb->driver_buffer;
      break;
   }
#endif

   case GBM_BO_IMPORT_EGL_IMAGE:
      if (!gdrm->lookup_egl_image)
         return NULL;

      resource = gdrm->lookup_egl_image(gdrm->lookup_egl_image_data, buffer);
      if (resource == NULL)
         return NULL;
      break;

   default:
      return NULL;
   }

   bo = CALLOC_STRUCT(gbm_gallium_drm_bo);
   if (bo == NULL)
      return NULL;

   bo->base.base.gbm = gbm;
   bo->base.base.width = resource->width0;
   bo->base.base.height = resource->height0;

   switch (resource->format) {
   case PIPE_FORMAT_B8G8R8X8_UNORM:
      bo->base.base.format = GBM_BO_FORMAT_XRGB8888;
      break;
   case PIPE_FORMAT_B8G8R8A8_UNORM:
      bo->base.base.format = GBM_BO_FORMAT_ARGB8888;
      break;
   default:
      FREE(bo);
      return NULL;
   }

   pipe_resource_reference(&bo->resource, resource);

   memset(&whandle, 0, sizeof(whandle));
   whandle.type = DRM_API_HANDLE_TYPE_KMS;
   gdrm->screen->resource_get_handle(gdrm->screen, bo->resource, &whandle);

   bo->base.base.handle.u32 = whandle.handle;
   bo->base.base.stride      = whandle.stride;

   return &bo->base.base;
}
Exemple #4
0
/**
 * Create a new XMesaContext.
 * \param v  the XMesaVisual
 * \param share_list  another XMesaContext with which to share display
 *                    lists or NULL if no sharing is wanted.
 * \return an XMesaContext or NULL if error.
 */
PUBLIC
XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list,
                                 GLuint major, GLuint minor,
                                 GLuint profileMask, GLuint contextFlags)
{
    XMesaDisplay xmdpy = xmesa_init_display(v->display);
    struct st_context_attribs attribs;
    enum st_context_error ctx_err = 0;
    XMesaContext c;

    if (!xmdpy)
        return NULL;

    /* Note: the XMesaContext contains a Mesa struct gl_context struct (inheritance) */
    c = (XMesaContext) CALLOC_STRUCT(xmesa_context);
    if (!c)
        return NULL;

    c->xm_visual = v;
    c->xm_buffer = NULL;   /* set later by XMesaMakeCurrent */
    c->xm_read_buffer = NULL;

    memset(&attribs, 0, sizeof(attribs));
    attribs.visual = v->stvis;
    attribs.major = major;
    attribs.minor = minor;
    if (contextFlags & GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
        attribs.flags |= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE;
    if (contextFlags & GLX_CONTEXT_DEBUG_BIT_ARB)
        attribs.flags |= ST_CONTEXT_FLAG_DEBUG;
    if (contextFlags & GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB)
        attribs.flags |= ST_CONTEXT_FLAG_ROBUST_ACCESS;

    /* There are no profiles before OpenGL 3.2.  The
     * GLX_ARB_create_context_profile spec says:
     *
     *     "If the requested OpenGL version is less than 3.2,
     *     GLX_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality of the
     *     context is determined solely by the requested version."
     *
     * The spec also says:
     *
     *     "The default value for GLX_CONTEXT_PROFILE_MASK_ARB is
     *     GLX_CONTEXT_CORE_PROFILE_BIT_ARB."
     */
    attribs.profile = ST_PROFILE_DEFAULT;
    if ((major > 3 || (major == 3 && minor >= 2))
            && ((profileMask & GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB) == 0))
        attribs.profile = ST_PROFILE_OPENGL_CORE;

    c->st = stapi->create_context(stapi, xmdpy->smapi, &attribs,
                                  &ctx_err, (share_list) ? share_list->st : NULL);
    if (c->st == NULL)
        goto fail;

    c->st->st_manager_private = (void *) c;

    return c;

fail:
    if (c->st)
        c->st->destroy(c->st);

    free(c);
    return NULL;
}
Exemple #5
0
struct pipe_context* r300_create_context(struct pipe_screen* screen,
                                         void *priv)
{
    struct r300_context* r300 = CALLOC_STRUCT(r300_context);
    struct r300_screen* r300screen = r300_screen(screen);
    struct radeon_winsys *rws = r300screen->rws;

    if (!r300)
        return NULL;

    r300->rws = rws;
    r300->screen = r300screen;

    r300->context.screen = screen;
    r300->context.priv = priv;

    r300->context.destroy = r300_destroy_context;

    util_slab_create(&r300->pool_transfers,
                     sizeof(struct pipe_transfer), 64,
                     UTIL_SLAB_SINGLETHREADED);

    r300->cs = rws->cs_create(rws, RING_GFX, NULL);
    if (r300->cs == NULL)
        goto fail;

    if (!r300screen->caps.has_tcl) {
        /* Create a Draw. This is used for SW TCL. */
        r300->draw = draw_create(&r300->context);
        if (r300->draw == NULL)
            goto fail;
        /* Enable our renderer. */
        draw_set_rasterize_stage(r300->draw, r300_draw_stage(r300));
        /* Disable converting points/lines to triangles. */
        draw_wide_line_threshold(r300->draw, 10000000.f);
        draw_wide_point_threshold(r300->draw, 10000000.f);
        draw_wide_point_sprites(r300->draw, FALSE);
        draw_enable_line_stipple(r300->draw, TRUE);
        draw_enable_point_sprites(r300->draw, FALSE);
    }

    if (!r300_setup_atoms(r300))
        goto fail;

    r300_init_blit_functions(r300);
    r300_init_flush_functions(r300);
    r300_init_query_functions(r300);
    r300_init_state_functions(r300);
    r300_init_resource_functions(r300);
    r300_init_render_functions(r300);
    r300_init_states(&r300->context);

    r300->context.create_video_decoder = vl_create_decoder;
    r300->context.create_video_buffer = vl_video_buffer_create;

    if (r300screen->caps.has_tcl) {
        r300->uploader = u_upload_create(&r300->context, 256 * 1024, 4,
                                         PIPE_BIND_INDEX_BUFFER);
    }

    r300->blitter = util_blitter_create(&r300->context);
    if (r300->blitter == NULL)
        goto fail;
    r300->blitter->draw_rectangle = r300_blitter_draw_rectangle;

    rws->cs_set_flush_callback(r300->cs, r300_flush_callback, r300);

    /* The KIL opcode needs the first texture unit to be enabled
     * on r3xx-r4xx. In order to calm down the CS checker, we bind this
     * dummy texture there. */
    if (!r300->screen->caps.is_r500) {
        struct pipe_resource *tex;
        struct pipe_resource rtempl = {{0}};
        struct pipe_sampler_view vtempl = {{0}};

        rtempl.target = PIPE_TEXTURE_2D;
        rtempl.format = PIPE_FORMAT_I8_UNORM;
        rtempl.usage = PIPE_USAGE_IMMUTABLE;
        rtempl.width0 = 1;
        rtempl.height0 = 1;
        rtempl.depth0 = 1;
        tex = screen->resource_create(screen, &rtempl);

        u_sampler_view_default_template(&vtempl, tex, tex->format);

        r300->texkill_sampler = (struct r300_sampler_view*)
            r300->context.create_sampler_view(&r300->context, tex, &vtempl);

        pipe_resource_reference(&tex, NULL);
    }

    if (r300screen->caps.has_tcl) {
        struct pipe_resource vb;
        memset(&vb, 0, sizeof(vb));
        vb.target = PIPE_BUFFER;
        vb.format = PIPE_FORMAT_R8_UNORM;
        vb.usage = PIPE_USAGE_STATIC;
        vb.width0 = sizeof(float) * 16;
        vb.height0 = 1;
        vb.depth0 = 1;

        r300->dummy_vb.buffer = screen->resource_create(screen, &vb);
        r300->context.set_vertex_buffers(&r300->context, 0, 1, &r300->dummy_vb);
    }

    {
        struct pipe_depth_stencil_alpha_state dsa;
        memset(&dsa, 0, sizeof(dsa));
        dsa.depth.writemask = 1;

        r300->dsa_decompress_zmask =
            r300->context.create_depth_stencil_alpha_state(&r300->context,
                                                           &dsa);
    }

    r300->hyperz_time_of_last_flush = os_time_get();

    /* Register allocator state */
    rc_init_regalloc_state(&r300->fs_regalloc_state);

    /* Print driver info. */
#ifdef DEBUG
    {
#else
    if (DBG_ON(r300, DBG_INFO)) {
#endif
        fprintf(stderr,
                "r300: DRM version: %d.%d.%d, Name: %s, ID: 0x%04x, GB: %d, Z: %d\n"
                "r300: GART size: %d MB, VRAM size: %d MB\n"
                "r300: AA compression RAM: %s, Z compression RAM: %s, HiZ RAM: %s\n",
                r300->screen->info.drm_major,
                r300->screen->info.drm_minor,
                r300->screen->info.drm_patchlevel,
                screen->get_name(screen),
                r300->screen->info.pci_id,
                r300->screen->info.r300_num_gb_pipes,
                r300->screen->info.r300_num_z_pipes,
                r300->screen->info.gart_size >> 20,
                r300->screen->info.vram_size >> 20,
                "YES", /* XXX really? */
                r300->screen->caps.zmask_ram ? "YES" : "NO",
                r300->screen->caps.hiz_ram ? "YES" : "NO");
    }

    return &r300->context;

fail:
    r300_destroy_context(&r300->context);
    return NULL;
}
Exemple #6
0
void *
fd4_zsa_state_create(struct pipe_context *pctx,
		const struct pipe_depth_stencil_alpha_state *cso)
{
	struct fd4_zsa_stateobj *so;

	so = CALLOC_STRUCT(fd4_zsa_stateobj);
	if (!so)
		return NULL;

	so->base = *cso;

	so->rb_depth_control |=
			A4XX_RB_DEPTH_CONTROL_ZFUNC(cso->depth.func); /* maps 1:1 */

	if (cso->depth.enabled)
		so->rb_depth_control |=
			A4XX_RB_DEPTH_CONTROL_Z_ENABLE |
			A4XX_RB_DEPTH_CONTROL_Z_TEST_ENABLE;

	if (cso->depth.writemask)
		so->rb_depth_control |= A4XX_RB_DEPTH_CONTROL_Z_WRITE_ENABLE;

	if (cso->stencil[0].enabled) {
		const struct pipe_stencil_state *s = &cso->stencil[0];

		so->rb_stencil_control |=
			A4XX_RB_STENCIL_CONTROL_STENCIL_READ |
			A4XX_RB_STENCIL_CONTROL_STENCIL_ENABLE |
			A4XX_RB_STENCIL_CONTROL_FUNC(s->func) | /* maps 1:1 */
			A4XX_RB_STENCIL_CONTROL_FAIL(fd_stencil_op(s->fail_op)) |
			A4XX_RB_STENCIL_CONTROL_ZPASS(fd_stencil_op(s->zpass_op)) |
			A4XX_RB_STENCIL_CONTROL_ZFAIL(fd_stencil_op(s->zfail_op));
		so->rb_stencil_control2 |=
			A4XX_RB_STENCIL_CONTROL2_STENCIL_BUFFER;
		so->rb_stencilrefmask |=
			0xff000000 | /* ??? */
			A4XX_RB_STENCILREFMASK_STENCILWRITEMASK(s->writemask) |
			A4XX_RB_STENCILREFMASK_STENCILMASK(s->valuemask);

		if (cso->stencil[1].enabled) {
			const struct pipe_stencil_state *bs = &cso->stencil[1];

			so->rb_stencil_control |=
				A4XX_RB_STENCIL_CONTROL_STENCIL_ENABLE_BF |
				A4XX_RB_STENCIL_CONTROL_FUNC_BF(bs->func) | /* maps 1:1 */
				A4XX_RB_STENCIL_CONTROL_FAIL_BF(fd_stencil_op(bs->fail_op)) |
				A4XX_RB_STENCIL_CONTROL_ZPASS_BF(fd_stencil_op(bs->zpass_op)) |
				A4XX_RB_STENCIL_CONTROL_ZFAIL_BF(fd_stencil_op(bs->zfail_op));
			so->rb_stencilrefmask_bf |=
				0xff000000 | /* ??? */
				A4XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK(bs->writemask) |
				A4XX_RB_STENCILREFMASK_BF_STENCILMASK(bs->valuemask);
		}
	}

	if (cso->alpha.enabled) {
		uint32_t ref = cso->alpha.ref_value * 255.0;
		so->gras_alpha_control =
			A4XX_GRAS_ALPHA_CONTROL_ALPHA_TEST_ENABLE;
		so->rb_alpha_control =
			A4XX_RB_ALPHA_CONTROL_ALPHA_TEST |
			A4XX_RB_ALPHA_CONTROL_ALPHA_REF(ref) |
			A4XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC(cso->alpha.func);
		so->rb_depth_control |=
			A4XX_RB_DEPTH_CONTROL_EARLY_Z_DISABLE;
	}

	return so;
}
/* XXX: Still implementing this as if it was a screen function, but
 * can now modify it to queue transfers on the context.
 */
static struct pipe_transfer *
svga_texture_get_transfer(struct pipe_context *pipe,
                          struct pipe_resource *texture,
                          unsigned level,
                          unsigned usage,
                          const struct pipe_box *box)
{
   struct svga_context *svga = svga_context(pipe);
   struct svga_screen *ss = svga_screen(pipe->screen);
   struct svga_winsys_screen *sws = ss->sws;
   struct svga_transfer *st;
   unsigned nblocksx = util_format_get_nblocksx(texture->format, box->width);
   unsigned nblocksy = util_format_get_nblocksy(texture->format, box->height);

   /* We can't map texture storage directly */
   if (usage & PIPE_TRANSFER_MAP_DIRECTLY)
      return NULL;

   assert(box->depth == 1);
   st = CALLOC_STRUCT(svga_transfer);
   if (!st)
      return NULL;

   pipe_resource_reference(&st->base.resource, texture);
   st->base.level = level;
   st->base.usage = usage;
   st->base.box = *box;
   st->base.stride = nblocksx*util_format_get_blocksize(texture->format);
   st->base.layer_stride = 0;

   st->hw_nblocksy = nblocksy;

   st->hwbuf = svga_winsys_buffer_create(svga,
                                         1, 
                                         0,
                                         st->hw_nblocksy*st->base.stride);
   while(!st->hwbuf && (st->hw_nblocksy /= 2)) {
      st->hwbuf = svga_winsys_buffer_create(svga,
                                            1, 
                                            0,
                                            st->hw_nblocksy*st->base.stride);
   }

   if(!st->hwbuf)
      goto no_hwbuf;

   if(st->hw_nblocksy < nblocksy) {
      /* We couldn't allocate a hardware buffer big enough for the transfer, 
       * so allocate regular malloc memory instead */
      if (0) {
         debug_printf("%s: failed to allocate %u KB of DMA, "
                      "splitting into %u x %u KB DMA transfers\n",
                      __FUNCTION__,
                      (nblocksy*st->base.stride + 1023)/1024,
                      (nblocksy + st->hw_nblocksy - 1)/st->hw_nblocksy,
                      (st->hw_nblocksy*st->base.stride + 1023)/1024);
      }

      st->swbuf = MALLOC(nblocksy*st->base.stride);
      if(!st->swbuf)
         goto no_swbuf;
   }

   if (usage & PIPE_TRANSFER_READ) {
      SVGA3dSurfaceDMAFlags flags;
      memset(&flags, 0, sizeof flags);
      svga_transfer_dma(svga, st, SVGA3D_READ_HOST_VRAM, flags);
   }

   return &st->base;

no_swbuf:
   sws->buffer_destroy(sws, st->hwbuf);
no_hwbuf:
   FREE(st);
   return NULL;
}
Exemple #8
0
/* Allocate 2D texture or render target resource
 */
static struct pipe_resource * etna_screen_resource_create(struct pipe_screen *screen,
                                         const struct pipe_resource *templat)
{
    struct etna_screen *priv = etna_screen(screen);
    assert(templat);
    unsigned element_size = util_format_get_blocksize(templat->format);
    if(!element_size)
        return NULL;

    /* Check input */
    if(templat->target == PIPE_TEXTURE_CUBE)
    {
        assert(templat->array_size == 6);
    } else if (templat->target == PIPE_BUFFER)
    {
        assert(templat->format == PIPE_FORMAT_R8_UNORM); /* bytes; want TYPELESS or similar */
        assert(templat->array_size == 1);
        assert(templat->height0 == 1);
        assert(templat->depth0 == 1);
        assert(templat->array_size == 1);
        assert(templat->last_level == 0);
    } else
    {
        assert(templat->array_size == 1);
    }
    assert(templat->width0 != 0);
    assert(templat->height0 != 0);
    assert(templat->depth0 != 0);
    assert(templat->array_size != 0);

    /* Figure out what tiling to use -- for now, assume that textures cannot be supertiled, and cannot be linear.
     * There is a feature flag SUPERTILED_TEXTURE (not supported on any known hw) that may allow this, as well
     * as LINEAR_TEXTURE_SUPPORT (supported on gc880 and gc2000 at least), but not sure how it works.
     * Buffers always have LINEAR layout.
     */
    unsigned layout = ETNA_LAYOUT_LINEAR;
    if(templat->target != PIPE_BUFFER)
    {
        if(!(templat->bind & PIPE_BIND_SAMPLER_VIEW) && priv->specs.can_supertile &&
                !DBG_ENABLED(ETNA_DBG_NO_SUPERTILE))
            layout = ETNA_LAYOUT_SUPER_TILED;
        else
            layout = ETNA_LAYOUT_TILED;
    }
    /* XXX multi tiled formats */

    /* Determine scaling for antialiasing, allow override using debug flag */
    int nr_samples = templat->nr_samples;
    if((templat->bind & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL)) &&
       !(templat->bind & PIPE_BIND_SAMPLER_VIEW))
    {
        if(DBG_ENABLED(ETNA_DBG_MSAA_2X))
            nr_samples = 2;
        if(DBG_ENABLED(ETNA_DBG_MSAA_4X))
            nr_samples = 4;
    }
    int msaa_xscale = 1, msaa_yscale = 1;
    if(!translate_samples_to_xyscale(nr_samples, &msaa_xscale, &msaa_yscale, NULL))
    {
        /* Number of samples not supported */
        assert(0);
    }

    /* Determine needed padding (alignment of height/width) */
    unsigned paddingX = 0, paddingY = 0;
    unsigned halign = TEXTURE_HALIGN_FOUR;
    etna_layout_multiple(layout,
            priv->dev->chip.pixel_pipes,
            (templat->bind & PIPE_BIND_SAMPLER_VIEW) && !VIV_FEATURE(priv->dev, chipMinorFeatures1, TEXTURE_HALIGN),
            &paddingX, &paddingY, &halign);
    assert(paddingX && paddingY);

    /* determine mipmap levels */
    struct etna_resource *resource = CALLOC_STRUCT(etna_resource);
    int max_mip_level = templat->last_level;
    if(unlikely(max_mip_level >= ETNA_NUM_LOD)) /* max LOD supported by hw */
        max_mip_level = ETNA_NUM_LOD - 1;

    /* take care about DXTx formats, which have a divSize of non-1x1
     * also: lower mipmaps are still 4x4 due to tiling. In as sense, compressed formats are already tiled.
     * XXX UYVY formats?
     */
    unsigned divSizeX = util_format_get_blockwidth(templat->format);
    unsigned divSizeY = util_format_get_blockheight(templat->format);
    unsigned ix = 0;
    unsigned x = templat->width0, y = templat->height0;
    unsigned offset = 0;
    while(true)
    {
        struct etna_resource_level *mip = &resource->levels[ix];
        mip->width = x;
        mip->height = y;
        mip->padded_width = align(x * msaa_xscale, paddingX);
        mip->padded_height = align(y * msaa_yscale, paddingY);
        mip->stride = align(mip->padded_width, divSizeX)/divSizeX * element_size;
        mip->offset = offset;
        mip->layer_stride = align(mip->padded_width, divSizeX)/divSizeX *
                      align(mip->padded_height, divSizeY)/divSizeY * element_size;
        mip->size = templat->array_size * mip->layer_stride;
        offset += align(mip->size, ETNA_PE_ALIGNMENT); /* align mipmaps to 64 bytes to be able to render to them */
        if(ix == max_mip_level || (x == 1 && y == 1))
            break; // stop at last level
        x = MAX2(x >> 1, 1);
        y = MAX2(y >> 1, 1);
        ix += 1;
    }

    /* Determine memory size, and whether to create a tile status */
    size_t rt_size = offset;

    /* determine memory type */
    enum viv_surf_type memtype = VIV_SURF_UNKNOWN;
    if(templat->bind & PIPE_BIND_SAMPLER_VIEW)
        memtype = VIV_SURF_TEXTURE;
    else if(templat->bind & PIPE_BIND_RENDER_TARGET)
        memtype = VIV_SURF_RENDER_TARGET;
    else if(templat->bind & PIPE_BIND_DEPTH_STENCIL)
        memtype = VIV_SURF_DEPTH;
    else if(templat->bind & PIPE_BIND_INDEX_BUFFER)
        memtype = VIV_SURF_INDEX;
    else if(templat->bind & PIPE_BIND_VERTEX_BUFFER)
        memtype = VIV_SURF_VERTEX;

    DBG_F(ETNA_DBG_RESOURCE_MSGS, "%p: Allocate surface of %ix%i (padded to %ix%i) of format %s (%i bpe %ix%i), size %08zx flags %08x, memtype %i",
            resource,
            templat->width0, templat->height0, resource->levels[0].padded_width, resource->levels[0].padded_height, util_format_name(templat->format),
            element_size, divSizeX, divSizeY, rt_size, templat->bind, memtype);

    struct etna_vidmem *rt = 0;
    if(unlikely(etna_vidmem_alloc_linear(priv->dev, &rt, rt_size, memtype, VIV_POOL_DEFAULT, true) != ETNA_OK))
    {
        BUG("Problem allocating video memory for resource");
        return NULL;
    }

    resource->base = *templat;
    resource->base.last_level = ix; /* real last mipmap level */
    resource->base.screen = screen;
    resource->base.nr_samples = nr_samples;
    resource->layout = layout;
    resource->halign = halign;
    resource->surface = rt;
    resource->ts = 0; /* TS is only created when first bound to surface */
    pipe_reference_init(&resource->base.reference, 1);

    if(DBG_ENABLED(ETNA_DBG_ZERO))
    {
        memset(resource->surface->logical, 0, rt_size);
    }

    for(unsigned ix=0; ix<=resource->base.last_level; ++ix)
    {
        struct etna_resource_level *mip = &resource->levels[ix];
        mip->address = resource->surface->address + mip->offset;
        mip->logical = resource->surface->logical + mip->offset;
        DBG_F(ETNA_DBG_RESOURCE_MSGS, "  %08x level %i: %ix%i (%i) stride=%i layer_stride=%i",
                (int)mip->address, ix, (int)mip->width, (int)mip->height, (int)mip->size,
                (int)mip->stride, (int)mip->layer_stride);
    }

    return &resource->base;
}
struct svga_sampler_view *
svga_get_tex_sampler_view(struct pipe_context *pipe,
			  struct pipe_resource *pt,
                          unsigned min_lod, unsigned max_lod)
{
   struct svga_context *svga = svga_context(pipe);
   struct svga_screen *ss = svga_screen(pipe->screen);
   struct svga_texture *tex = svga_texture(pt);
   struct svga_sampler_view *sv = NULL;
   SVGA3dSurface1Flags flags = SVGA3D_SURFACE_HINT_TEXTURE;
   SVGA3dSurfaceFormat format = svga_translate_format(ss, pt->format,
                                                      PIPE_BIND_SAMPLER_VIEW);
   boolean view = TRUE;

   assert(pt);
   assert(min_lod <= max_lod);
   assert(max_lod <= pt->last_level);
   assert(!svga_have_vgpu10(svga));

   /* Is a view needed */
   {
      /*
       * Can't control max lod. For first level views and when we only
       * look at one level we disable mip filtering to achive the same
       * results as a view.
       */
      if (min_lod == 0 && max_lod >= pt->last_level)
         view = FALSE;

      if (ss->debug.no_sampler_view)
         view = FALSE;

      if (ss->debug.force_sampler_view)
         view = TRUE;
   }

   /* First try the cache */
   if (view) {
      mtx_lock(&ss->tex_mutex);
      if (tex->cached_view &&
          tex->cached_view->min_lod == min_lod &&
          tex->cached_view->max_lod == max_lod) {
         svga_sampler_view_reference(&sv, tex->cached_view);
         mtx_unlock(&ss->tex_mutex);
         SVGA_DBG(DEBUG_VIEWS, "svga: Sampler view: reuse %p, %u %u, last %u\n",
                              pt, min_lod, max_lod, pt->last_level);
         svga_validate_sampler_view(svga_context(pipe), sv);
         return sv;
      }
      mtx_unlock(&ss->tex_mutex);
   }

   sv = CALLOC_STRUCT(svga_sampler_view);
   if (!sv)
      return NULL;

   pipe_reference_init(&sv->reference, 1);

   /* Note: we're not refcounting the texture resource here to avoid
    * a circular dependency.
    */
   sv->texture = pt;

   sv->min_lod = min_lod;
   sv->max_lod = max_lod;

   /* No view needed just use the whole texture */
   if (!view) {
      SVGA_DBG(DEBUG_VIEWS,
               "svga: Sampler view: no %p, mips %u..%u, nr %u, size (%ux%ux%u), last %u\n",
               pt, min_lod, max_lod,
               max_lod - min_lod + 1,
               pt->width0,
               pt->height0,
               pt->depth0,
               pt->last_level);
      sv->key.cachable = 0;
      sv->handle = tex->handle;
      debug_reference(&sv->reference,
                      (debug_reference_descriptor)svga_debug_describe_sampler_view, 0);
      return sv;
   }

   SVGA_DBG(DEBUG_VIEWS,
            "svga: Sampler view: yes %p, mips %u..%u, nr %u, size (%ux%ux%u), last %u\n",
            pt, min_lod, max_lod,
            max_lod - min_lod + 1,
            pt->width0,
            pt->height0,
            pt->depth0,
            pt->last_level);

   sv->age = tex->age;
   sv->handle = svga_texture_view_surface(svga, tex,
                                          PIPE_BIND_SAMPLER_VIEW,
                                          flags, format,
                                          min_lod,
                                          max_lod - min_lod + 1,
                                          -1, 1, -1, FALSE,
                                          &sv->key);

   if (!sv->handle) {
      sv->key.cachable = 0;
      sv->handle = tex->handle;
      debug_reference(&sv->reference,
                      (debug_reference_descriptor)
                      svga_debug_describe_sampler_view, 0);
      return sv;
   }

   mtx_lock(&ss->tex_mutex);
   svga_sampler_view_reference(&tex->cached_view, sv);
   mtx_unlock(&ss->tex_mutex);

   debug_reference(&sv->reference,
                   (debug_reference_descriptor)
                   svga_debug_describe_sampler_view, 0);

   return sv;
}
Exemple #10
0
struct pipe_query *r600_create_batch_query(struct pipe_context *ctx,
					   unsigned num_queries,
					   unsigned *query_types)
{
	struct r600_common_context *rctx = (struct r600_common_context *)ctx;
	struct r600_common_screen *screen = rctx->screen;
	struct r600_perfcounters *pc = screen->perfcounters;
	struct r600_perfcounter_block *block;
	struct r600_pc_group *group;
	struct r600_query_pc *query;
	unsigned base_gid, sub_gid, sub_index;
	unsigned i, j;

	if (!pc)
		return NULL;

	query = CALLOC_STRUCT(r600_query_pc);
	if (!query)
		return NULL;

	query->b.b.ops = &batch_query_ops;
	query->b.ops = &batch_query_hw_ops;

	query->num_counters = num_queries;

	/* Collect selectors per group */
	for (i = 0; i < num_queries; ++i) {
		unsigned sub_gid;

		if (query_types[i] < R600_QUERY_FIRST_PERFCOUNTER)
			goto error;

		block = lookup_counter(pc, query_types[i] - R600_QUERY_FIRST_PERFCOUNTER,
				       &base_gid, &sub_index);
		if (!block)
			goto error;

		sub_gid = sub_index / block->num_selectors;
		sub_index = sub_index % block->num_selectors;

		group = get_group_state(screen, query, block, sub_gid);
		if (!group)
			goto error;

		if (group->num_counters >= block->num_counters) {
			fprintf(stderr,
				"perfcounter group %s: too many selected\n",
				block->basename);
			goto error;
		}
		group->selectors[group->num_counters] = sub_index;
		++group->num_counters;
	}

	/* Compute result bases and CS size per group */
	query->b.num_cs_dw_begin = pc->num_start_cs_dwords;
	query->b.num_cs_dw_end = pc->num_stop_cs_dwords;

	query->b.num_cs_dw_begin += pc->num_instance_cs_dwords; /* conservative */
	query->b.num_cs_dw_end += pc->num_instance_cs_dwords;

	i = 0;
	for (group = query->groups; group; group = group->next) {
		struct r600_perfcounter_block *block = group->block;
		unsigned select_dw, read_dw;
		unsigned instances = 1;

		if ((block->flags & R600_PC_BLOCK_SE) && group->se < 0)
			instances = rctx->screen->info.max_se;
		if (group->instance < 0)
			instances *= block->num_instances;

		group->result_base = i;
		query->b.result_size += sizeof(uint64_t) * instances * group->num_counters;
		i += instances * group->num_counters;

		pc->get_size(block, group->num_counters, group->selectors,
			     &select_dw, &read_dw);
		query->b.num_cs_dw_begin += select_dw;
		query->b.num_cs_dw_end += instances * read_dw;
		query->b.num_cs_dw_begin += pc->num_instance_cs_dwords; /* conservative */
		query->b.num_cs_dw_end += instances * pc->num_instance_cs_dwords;
	}

	if (query->shaders) {
		if (query->shaders == R600_PC_SHADERS_WINDOWING)
			query->shaders = 0xffffffff;
		query->b.num_cs_dw_begin += pc->num_shaders_cs_dwords;
	}

	/* Map user-supplied query array to result indices */
	query->counters = CALLOC(num_queries, sizeof(*query->counters));
	for (i = 0; i < num_queries; ++i) {
		struct r600_pc_counter *counter = &query->counters[i];
		struct r600_perfcounter_block *block;

		block = lookup_counter(pc, query_types[i] - R600_QUERY_FIRST_PERFCOUNTER,
				       &base_gid, &sub_index);

		sub_gid = sub_index / block->num_selectors;
		sub_index = sub_index % block->num_selectors;

		group = get_group_state(screen, query, block, sub_gid);
		assert(group != NULL);

		for (j = 0; j < group->num_counters; ++j) {
			if (group->selectors[j] == sub_index)
				break;
		}

		counter->base = group->result_base + j;
		counter->stride = group->num_counters;

		counter->qwords = 1;
		if ((block->flags & R600_PC_BLOCK_SE) && group->se < 0)
			counter->qwords = screen->info.max_se;
		if (group->instance < 0)
			counter->qwords *= block->num_instances;
	}

	if (!r600_query_hw_init(rctx, &query->b))
		goto error;

	return (struct pipe_query *)query;

error:
	r600_pc_query_destroy(rctx, &query->b.b);
	return NULL;
}
Exemple #11
0
uint32
vmw_ioctl_gb_surface_create(struct vmw_winsys_screen *vws,
			    SVGA3dSurfaceFlags flags,
			    SVGA3dSurfaceFormat format,
                            unsigned usage,
			    SVGA3dSize size,
			    uint32_t numFaces,
			    uint32_t numMipLevels,
                            uint32_t buffer_handle,
			    struct vmw_region **p_region)
{
   union drm_vmw_gb_surface_create_arg s_arg;
   struct drm_vmw_gb_surface_create_req *req = &s_arg.req;
   struct drm_vmw_gb_surface_create_rep *rep = &s_arg.rep;
   struct vmw_region *region = NULL;
   int ret;

   vmw_printf("%s flags %d format %d\n", __FUNCTION__, flags, format);

   if (p_region) {
      region = CALLOC_STRUCT(vmw_region);
      if (!region)
         return SVGA3D_INVALID_ID;
   }

   memset(&s_arg, 0, sizeof(s_arg));
   if (flags & SVGA3D_SURFACE_HINT_SCANOUT) {
      req->svga3d_flags = (uint32_t) (flags & ~SVGA3D_SURFACE_HINT_SCANOUT);
      req->drm_surface_flags = drm_vmw_surface_flag_scanout;
   } else {
      req->svga3d_flags = (uint32_t) flags;
   }
   req->format = (uint32_t) format;
   if (usage & SVGA_SURFACE_USAGE_SHARED)
      req->drm_surface_flags |= drm_vmw_surface_flag_shareable;
   req->drm_surface_flags |= drm_vmw_surface_flag_create_buffer; 

   assert(numFaces * numMipLevels < DRM_VMW_MAX_SURFACE_FACES*
	  DRM_VMW_MAX_MIP_LEVELS);
   req->base_size.width = size.width;
   req->base_size.height = size.height;
   req->base_size.depth = size.depth;
   req->mip_levels = numMipLevels;
   req->multisample_count = 0;
   req->autogen_filter = SVGA3D_TEX_FILTER_NONE;
   if (buffer_handle)
      req->buffer_handle = buffer_handle;
   else
      req->buffer_handle = SVGA3D_INVALID_ID;

   ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_GB_SURFACE_CREATE,
			     &s_arg, sizeof(s_arg));

   if (ret)
      goto out_fail_create;

   if (p_region) {
      region->handle = rep->buffer_handle;
      region->map_handle = rep->buffer_map_handle;
      region->drm_fd = vws->ioctl.drm_fd;
      region->size = rep->backup_size;
      *p_region = region;
   }

   vmw_printf("Surface id is %d\n", rep->sid);
   return rep->handle;

out_fail_create:
   if (region)
      FREE(region);
   return SVGA3D_INVALID_ID;
}
Exemple #12
0
static struct r600_pc_group *get_group_state(struct r600_common_screen *screen,
					     struct r600_query_pc *query,
					     struct r600_perfcounter_block *block,
					     unsigned sub_gid)
{
	struct r600_pc_group *group = query->groups;

	while (group) {
		if (group->block == block && group->sub_gid == sub_gid)
			return group;
		group = group->next;
	}

	group = CALLOC_STRUCT(r600_pc_group);
	if (!group)
		return NULL;

	group->block = block;
	group->sub_gid = sub_gid;

	if (block->flags & R600_PC_BLOCK_SHADER) {
		unsigned sub_gids = block->num_instances;
		unsigned shader_id;
		unsigned shaders;
		unsigned query_shaders;

		if (block->flags & R600_PC_BLOCK_SE_GROUPS)
			sub_gids = sub_gids * screen->info.max_se;
		shader_id = sub_gid / sub_gids;
		sub_gid = sub_gid % sub_gids;

		shaders = screen->perfcounters->shader_type_bits[shader_id];

		query_shaders = query->shaders & ~R600_PC_SHADERS_WINDOWING;
		if (query_shaders && query_shaders != shaders) {
			fprintf(stderr, "r600_perfcounter: incompatible shader groups\n");
			FREE(group);
			return NULL;
		}
		query->shaders = shaders;
	}

	if (block->flags & R600_PC_BLOCK_SHADER_WINDOWED && !query->shaders) {
		// A non-zero value in query->shaders ensures that the shader
		// masking is reset unless the user explicitly requests one.
		query->shaders = R600_PC_SHADERS_WINDOWING;
	}

	if (block->flags & R600_PC_BLOCK_SE_GROUPS) {
		group->se = sub_gid / block->num_instances;
		sub_gid = sub_gid % block->num_instances;
	} else {
		group->se = -1;
	}

	if (block->flags & R600_PC_BLOCK_INSTANCE_GROUPS) {
		group->instance = sub_gid;
	} else {
		group->instance = -1;
	}

	group->next = query->groups;
	query->groups = group;

	return group;
}
Exemple #13
0
/**
 * Allocate a new swrast_texture_image (a subclass of gl_texture_image).
 * Called via ctx->Driver.NewTextureImage().
 */
struct gl_texture_image *
_swrast_new_texture_image( struct gl_context *ctx )
{
   (void) ctx;
   return (struct gl_texture_image *) CALLOC_STRUCT(swrast_texture_image);
}
Exemple #14
0
void *
fd5_zsa_state_create(struct pipe_context *pctx,
		const struct pipe_depth_stencil_alpha_state *cso)
{
	struct fd5_zsa_stateobj *so;

	so = CALLOC_STRUCT(fd5_zsa_stateobj);
	if (!so)
		return NULL;

	so->base = *cso;

	switch (cso->depth.func) {
	case PIPE_FUNC_LESS:
	case PIPE_FUNC_LEQUAL:
		so->gras_lrz_cntl = A5XX_GRAS_LRZ_CNTL_ENABLE;
		break;

	case PIPE_FUNC_GREATER:
	case PIPE_FUNC_GEQUAL:
		so->gras_lrz_cntl = A5XX_GRAS_LRZ_CNTL_ENABLE | A5XX_GRAS_LRZ_CNTL_GREATER;
		break;

	default:
		/* LRZ not enabled */
		so->gras_lrz_cntl = 0;
		break;
	}

	if (!(cso->stencil->enabled || cso->alpha.enabled || !cso->depth.writemask))
		so->lrz_write = true;

	so->rb_depth_cntl |=
		A5XX_RB_DEPTH_CNTL_ZFUNC(cso->depth.func); /* maps 1:1 */

	if (cso->depth.enabled)
		so->rb_depth_cntl |=
			A5XX_RB_DEPTH_CNTL_Z_ENABLE |
			A5XX_RB_DEPTH_CNTL_Z_TEST_ENABLE;

	if (cso->depth.writemask)
		so->rb_depth_cntl |= A5XX_RB_DEPTH_CNTL_Z_WRITE_ENABLE;

	if (cso->stencil[0].enabled) {
		const struct pipe_stencil_state *s = &cso->stencil[0];

		so->rb_stencil_control |=
			A5XX_RB_STENCIL_CONTROL_STENCIL_READ |
			A5XX_RB_STENCIL_CONTROL_STENCIL_ENABLE |
			A5XX_RB_STENCIL_CONTROL_FUNC(s->func) | /* maps 1:1 */
			A5XX_RB_STENCIL_CONTROL_FAIL(fd_stencil_op(s->fail_op)) |
			A5XX_RB_STENCIL_CONTROL_ZPASS(fd_stencil_op(s->zpass_op)) |
			A5XX_RB_STENCIL_CONTROL_ZFAIL(fd_stencil_op(s->zfail_op));
		so->rb_stencilrefmask |=
			A5XX_RB_STENCILREFMASK_STENCILWRITEMASK(s->writemask) |
			A5XX_RB_STENCILREFMASK_STENCILMASK(s->valuemask);

		if (cso->stencil[1].enabled) {
			const struct pipe_stencil_state *bs = &cso->stencil[1];

			so->rb_stencil_control |=
				A5XX_RB_STENCIL_CONTROL_STENCIL_ENABLE_BF |
				A5XX_RB_STENCIL_CONTROL_FUNC_BF(bs->func) | /* maps 1:1 */
				A5XX_RB_STENCIL_CONTROL_FAIL_BF(fd_stencil_op(bs->fail_op)) |
				A5XX_RB_STENCIL_CONTROL_ZPASS_BF(fd_stencil_op(bs->zpass_op)) |
				A5XX_RB_STENCIL_CONTROL_ZFAIL_BF(fd_stencil_op(bs->zfail_op));
			so->rb_stencilrefmask_bf |=
				A5XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK(bs->writemask) |
				A5XX_RB_STENCILREFMASK_BF_STENCILMASK(bs->valuemask);
		}
	}

	if (cso->alpha.enabled) {
		uint32_t ref = cso->alpha.ref_value * 255.0;
		so->rb_alpha_control =
			A5XX_RB_ALPHA_CONTROL_ALPHA_TEST |
			A5XX_RB_ALPHA_CONTROL_ALPHA_REF(ref) |
			A5XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC(cso->alpha.func);
//		so->rb_depth_control |=
//			A5XX_RB_DEPTH_CONTROL_EARLY_Z_DISABLE;
	}

	return so;
}
Exemple #15
0
/**
 * Translate a geometry program to create a new variant.
 */
static struct st_gp_variant *
st_translate_geometry_program(struct st_context *st,
                              struct st_geometry_program *stgp,
                              const struct st_gp_variant_key *key)
{
   GLuint inputMapping[GEOM_ATTRIB_MAX];
   GLuint outputMapping[GEOM_RESULT_MAX];
   struct pipe_context *pipe = st->pipe;
   GLuint attr;
   GLbitfield64 inputsRead;
   GLuint vslot = 0;
   GLuint num_generic = 0;

   uint gs_num_inputs = 0;
   uint gs_builtin_inputs = 0;
   uint gs_array_offset = 0;

   ubyte gs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
   ubyte gs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
   uint gs_num_outputs = 0;

   GLint i;
   GLuint maxSlot = 0;
   struct ureg_program *ureg;

   struct st_gp_variant *gpv;

   gpv = CALLOC_STRUCT(st_gp_variant);
   if (!gpv)
      return NULL;

   _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_OUTPUT);
   _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_VARYING);

   ureg = ureg_create( TGSI_PROCESSOR_GEOMETRY );
   if (ureg == NULL) {
      free(gpv);
      return NULL;
   }

   /* which vertex output goes to the first geometry input */
   vslot = 0;

   memset(inputMapping, 0, sizeof(inputMapping));
   memset(outputMapping, 0, sizeof(outputMapping));

   /*
    * Convert Mesa program inputs to TGSI input register semantics.
    */
   inputsRead = stgp->Base.Base.InputsRead;
   for (attr = 0; attr < GEOM_ATTRIB_MAX; attr++) {
      if ((inputsRead & BITFIELD64_BIT(attr)) != 0) {
         const GLuint slot = gs_num_inputs;

         gs_num_inputs++;

         inputMapping[attr] = slot;

         stgp->input_map[slot + gs_array_offset] = vslot - gs_builtin_inputs;
         stgp->input_to_index[attr] = vslot;
         stgp->index_to_input[vslot] = attr;
         ++vslot;

         if (attr != GEOM_ATTRIB_PRIMITIVE_ID) {
            gs_array_offset += 2;
         } else
            ++gs_builtin_inputs;

#if 0
         debug_printf("input map at %d = %d\n",
                      slot + gs_array_offset, stgp->input_map[slot + gs_array_offset]);
#endif

         switch (attr) {
         case GEOM_ATTRIB_PRIMITIVE_ID:
            stgp->input_semantic_name[slot] = TGSI_SEMANTIC_PRIMID;
            stgp->input_semantic_index[slot] = 0;
            break;
         case GEOM_ATTRIB_POSITION:
            stgp->input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
            stgp->input_semantic_index[slot] = 0;
            break;
         case GEOM_ATTRIB_COLOR0:
            stgp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
            stgp->input_semantic_index[slot] = 0;
            break;
         case GEOM_ATTRIB_COLOR1:
            stgp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
            stgp->input_semantic_index[slot] = 1;
            break;
         case GEOM_ATTRIB_FOG_FRAG_COORD:
            stgp->input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
            stgp->input_semantic_index[slot] = 0;
            break;
         case GEOM_ATTRIB_TEX_COORD:
            stgp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
            stgp->input_semantic_index[slot] = num_generic++;
            break;
         case GEOM_ATTRIB_VAR0:
            /* fall-through */
         default:
            stgp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
            stgp->input_semantic_index[slot] = num_generic++;
         }
      }
   }

   /* initialize output semantics to defaults */
   for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) {
      gs_output_semantic_name[i] = TGSI_SEMANTIC_GENERIC;
      gs_output_semantic_index[i] = 0;
   }

   num_generic = 0;
   /*
    * Determine number of outputs, the (default) output register
    * mapping and the semantic information for each output.
    */
   for (attr = 0; attr < GEOM_RESULT_MAX; attr++) {
      if (stgp->Base.Base.OutputsWritten & BITFIELD64_BIT(attr)) {
         GLuint slot;

         slot = gs_num_outputs;
         gs_num_outputs++;
         outputMapping[attr] = slot;

         switch (attr) {
         case GEOM_RESULT_POS:
            assert(slot == 0);
            gs_output_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
            gs_output_semantic_index[slot] = 0;
            break;
         case GEOM_RESULT_COL0:
            gs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
            gs_output_semantic_index[slot] = 0;
            break;
         case GEOM_RESULT_COL1:
            gs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
            gs_output_semantic_index[slot] = 1;
            break;
         case GEOM_RESULT_SCOL0:
            gs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
            gs_output_semantic_index[slot] = 0;
            break;
         case GEOM_RESULT_SCOL1:
            gs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
            gs_output_semantic_index[slot] = 1;
            break;
         case GEOM_RESULT_FOGC:
            gs_output_semantic_name[slot] = TGSI_SEMANTIC_FOG;
            gs_output_semantic_index[slot] = 0;
            break;
         case GEOM_RESULT_PSIZ:
            gs_output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
            gs_output_semantic_index[slot] = 0;
            break;
         case GEOM_RESULT_TEX0:
         case GEOM_RESULT_TEX1:
         case GEOM_RESULT_TEX2:
         case GEOM_RESULT_TEX3:
         case GEOM_RESULT_TEX4:
         case GEOM_RESULT_TEX5:
         case GEOM_RESULT_TEX6:
         case GEOM_RESULT_TEX7:
            /* fall-through */
         case GEOM_RESULT_VAR0:
            /* fall-through */
         default:
            assert(slot < Elements(gs_output_semantic_name));
            /* use default semantic info */
            gs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
            gs_output_semantic_index[slot] = num_generic++;
         }
      }
   }

   assert(gs_output_semantic_name[0] == TGSI_SEMANTIC_POSITION);

   /* find max output slot referenced to compute gs_num_outputs */
   for (attr = 0; attr < GEOM_RESULT_MAX; attr++) {
      if (outputMapping[attr] != ~0 && outputMapping[attr] > maxSlot)
         maxSlot = outputMapping[attr];
   }
   gs_num_outputs = maxSlot + 1;

#if 0 /* debug */
   {
      GLuint i;
      printf("outputMapping? %d\n", outputMapping ? 1 : 0);
      if (outputMapping) {
         printf("attr -> slot\n");
         for (i = 0; i < 16;  i++) {
            printf(" %2d       %3d\n", i, outputMapping[i]);
         }
      }
      printf("slot    sem_name  sem_index\n");
      for (i = 0; i < gs_num_outputs; i++) {
         printf(" %2d         %d         %d\n",
                i,
                gs_output_semantic_name[i],
                gs_output_semantic_index[i]);
      }
   }
#endif

   /* free old shader state, if any */
   if (stgp->tgsi.tokens) {
      st_free_tokens(stgp->tgsi.tokens);
      stgp->tgsi.tokens = NULL;
   }

   ureg_property_gs_input_prim(ureg, stgp->Base.InputType);
   ureg_property_gs_output_prim(ureg, stgp->Base.OutputType);
   ureg_property_gs_max_vertices(ureg, stgp->Base.VerticesOut);

   st_translate_mesa_program(st->ctx,
                             TGSI_PROCESSOR_GEOMETRY,
                             ureg,
                             &stgp->Base.Base,
                             /* inputs */
                             gs_num_inputs,
                             inputMapping,
                             stgp->input_semantic_name,
                             stgp->input_semantic_index,
                             NULL,
                             /* outputs */
                             gs_num_outputs,
                             outputMapping,
                             gs_output_semantic_name,
                             gs_output_semantic_index,
                             FALSE,
                             FALSE);

   stgp->num_inputs = gs_num_inputs;
   stgp->tgsi.tokens = ureg_get_tokens( ureg, NULL );
   ureg_destroy( ureg );

   if (stgp->glsl_to_tgsi) {
      st_translate_stream_output_info(stgp->glsl_to_tgsi,
                                      outputMapping,
                                      &stgp->tgsi.stream_output);
   }

   /* fill in new variant */
   gpv->driver_shader = pipe->create_gs_state(pipe, &stgp->tgsi);
   gpv->key = *key;

   if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) {
      _mesa_print_program(&stgp->Base.Base);
      debug_printf("\n");
   }

   if (ST_DEBUG & DEBUG_TGSI) {
      tgsi_dump(stgp->tgsi.tokens, 0);
      debug_printf("\n");
   }

   return gpv;
}
Exemple #16
0
struct nouveau_screen *
nv30_screen_create(struct nouveau_device *dev)
{
   struct nv30_screen *screen;
   struct pipe_screen *pscreen;
   struct nouveau_pushbuf *push;
   struct nv04_fifo *fifo;
   unsigned oclass = 0;
   int ret, i;

   switch (dev->chipset & 0xf0) {
   case 0x30:
      if (RANKINE_0397_CHIPSET & (1 << (dev->chipset & 0x0f)))
         oclass = NV30_3D_CLASS;
      else
      if (RANKINE_0697_CHIPSET & (1 << (dev->chipset & 0x0f)))
         oclass = NV34_3D_CLASS;
      else
      if (RANKINE_0497_CHIPSET & (1 << (dev->chipset & 0x0f)))
         oclass = NV35_3D_CLASS;
      break;
   case 0x40:
      if (CURIE_4097_CHIPSET & (1 << (dev->chipset & 0x0f)))
         oclass = NV40_3D_CLASS;
      else
      if (CURIE_4497_CHIPSET & (1 << (dev->chipset & 0x0f)))
         oclass = NV44_3D_CLASS;
      break;
   case 0x60:
      if (CURIE_4497_CHIPSET6X & (1 << (dev->chipset & 0x0f)))
         oclass = NV44_3D_CLASS;
      break;
   default:
      break;
   }

   if (!oclass) {
      NOUVEAU_ERR("unknown 3d class for 0x%02x\n", dev->chipset);
      return NULL;
   }

   screen = CALLOC_STRUCT(nv30_screen);
   if (!screen)
      return NULL;

   pscreen = &screen->base.base;
   pscreen->destroy = nv30_screen_destroy;

   /*
    * Some modern apps try to use msaa without keeping in mind the
    * restrictions on videomem of older cards. Resulting in dmesg saying:
    * [ 1197.850642] nouveau E[soffice.bin[3785]] fail ttm_validate
    * [ 1197.850648] nouveau E[soffice.bin[3785]] validating bo list
    * [ 1197.850654] nouveau E[soffice.bin[3785]] validate: -12
    *
    * Because we are running out of video memory, after which the program
    * using the msaa visual freezes, and eventually the entire system freezes.
    *
    * To work around this we do not allow msaa visauls by default and allow
    * the user to override this via NV30_MAX_MSAA.
    */
   screen->max_sample_count = debug_get_num_option("NV30_MAX_MSAA", 0);
   if (screen->max_sample_count > 4)
      screen->max_sample_count = 4;

   pscreen->get_param = nv30_screen_get_param;
   pscreen->get_paramf = nv30_screen_get_paramf;
   pscreen->get_shader_param = nv30_screen_get_shader_param;
   pscreen->context_create = nv30_context_create;
   pscreen->is_format_supported = nv30_screen_is_format_supported;
   nv30_resource_screen_init(pscreen);
   nouveau_screen_init_vdec(&screen->base);

   screen->base.fence.emit = nv30_screen_fence_emit;
   screen->base.fence.update = nv30_screen_fence_update;

   ret = nouveau_screen_init(&screen->base, dev);
   if (ret)
      FAIL_SCREEN_INIT("nv30_screen_init failed: %d\n", ret);

   screen->base.vidmem_bindings |= PIPE_BIND_VERTEX_BUFFER;
   screen->base.sysmem_bindings |= PIPE_BIND_VERTEX_BUFFER;
   if (oclass == NV40_3D_CLASS) {
      screen->base.vidmem_bindings |= PIPE_BIND_INDEX_BUFFER;
      screen->base.sysmem_bindings |= PIPE_BIND_INDEX_BUFFER;
   }

   fifo = screen->base.channel->data;
   push = screen->base.pushbuf;
   push->rsvd_kick = 16;

   ret = nouveau_object_new(screen->base.channel, 0x00000000, NV01_NULL_CLASS,
                            NULL, 0, &screen->null);
   if (ret)
      FAIL_SCREEN_INIT("error allocating null object: %d\n", ret);

   /* DMA_FENCE refuses to accept DMA objects with "adjust" filled in,
    * this means that the address pointed at by the DMA object must
    * be 4KiB aligned, which means this object needs to be the first
    * one allocated on the channel.
    */
   ret = nouveau_object_new(screen->base.channel, 0xbeef1e00,
                            NOUVEAU_NOTIFIER_CLASS, &(struct nv04_notify) {
                            .length = 32 }, sizeof(struct nv04_notify),
Exemple #17
0
/**
 * Create a new pipe_screen object
 * Note: we're not presently subclassing pipe_screen (no llvmpipe_screen).
 */
struct pipe_screen *
llvmpipe_create_screen(struct sw_winsys *winsys)
{
   struct llvmpipe_screen *screen;

   util_cpu_detect();

#ifdef DEBUG
   LP_DEBUG = debug_get_flags_option("LP_DEBUG", lp_debug_flags, 0 );
#endif

   LP_PERF = debug_get_flags_option("LP_PERF", lp_perf_flags, 0 );

   screen = CALLOC_STRUCT(llvmpipe_screen);
   if (!screen)
      return NULL;

   if (!lp_jit_screen_init(screen)) {
      FREE(screen);
      return NULL;
   }

   screen->winsys = winsys;

   screen->base.destroy = llvmpipe_destroy_screen;

   screen->base.get_name = llvmpipe_get_name;
   screen->base.get_vendor = llvmpipe_get_vendor;
   screen->base.get_device_vendor = llvmpipe_get_vendor; // TODO should be the CPU vendor
   screen->base.get_param = llvmpipe_get_param;
   screen->base.get_shader_param = llvmpipe_get_shader_param;
   screen->base.get_paramf = llvmpipe_get_paramf;
   screen->base.is_format_supported = llvmpipe_is_format_supported;

   screen->base.context_create = llvmpipe_create_context;
   screen->base.flush_frontbuffer = llvmpipe_flush_frontbuffer;
   screen->base.fence_reference = llvmpipe_fence_reference;
   screen->base.fence_finish = llvmpipe_fence_finish;

   screen->base.get_timestamp = llvmpipe_get_timestamp;

   llvmpipe_init_screen_resource_funcs(&screen->base);

   screen->num_threads = util_cpu_caps.nr_cpus > 1 ? util_cpu_caps.nr_cpus : 0;
#ifdef PIPE_SUBSYSTEM_EMBEDDED
   screen->num_threads = 0;
#endif
   screen->num_threads = debug_get_num_option("LP_NUM_THREADS", screen->num_threads);
   screen->num_threads = MIN2(screen->num_threads, LP_MAX_THREADS);

   screen->rast = lp_rast_create(screen->num_threads);
   if (!screen->rast) {
      lp_jit_screen_cleanup(screen);
      FREE(screen);
      return NULL;
   }
   pipe_mutex_init(screen->rast_mutex);

   util_format_s3tc_init();

   return &screen->base;
}
Exemple #18
0
/**
 * Create a framebuffer from a manager interface.
 */
static struct st_framebuffer *
st_framebuffer_create(struct st_context *st,
                      struct st_framebuffer_iface *stfbi)
{
   struct st_framebuffer *stfb;
   struct gl_config mode;
   gl_buffer_index idx;

   if (!stfbi)
      return NULL;

   stfb = CALLOC_STRUCT(st_framebuffer);
   if (!stfb)
      return NULL;

   st_visual_to_context_mode(stfbi->visual, &mode);

   /*
    * For desktop GL, sRGB framebuffer write is controlled by both the
    * capability of the framebuffer and GL_FRAMEBUFFER_SRGB.  We should
    * advertise the capability when the pipe driver (and core Mesa) supports
    * it so that applications can enable sRGB write when they want to.
    *
    * This is not to be confused with GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB.  When
    * the attribute is GLX_TRUE, it tells the st manager to pick a color
    * format such that util_format_srgb(visual->color_format) can be supported
    * by the pipe driver.  We still need to advertise the capability here.
    *
    * For GLES, however, sRGB framebuffer write is controlled only by the
    * capability of the framebuffer.  There is GL_EXT_sRGB_write_control to
    * give applications the control back, but sRGB write is still enabled by
    * default.  To avoid unexpected results, we should not advertise the
    * capability.  This could change when we add support for
    * EGL_KHR_gl_colorspace.
    */
   if (_mesa_is_desktop_gl(st->ctx)) {
      struct pipe_screen *screen = st->pipe->screen;
      const enum pipe_format srgb_format =
         util_format_srgb(stfbi->visual->color_format);

      if (srgb_format != PIPE_FORMAT_NONE &&
          st_pipe_format_to_mesa_format(srgb_format) != MESA_FORMAT_NONE &&
          screen->is_format_supported(screen, srgb_format,
                                      PIPE_TEXTURE_2D, stfbi->visual->samples,
                                      PIPE_BIND_RENDER_TARGET))
         mode.sRGBCapable = GL_TRUE;
   }

   _mesa_initialize_window_framebuffer(&stfb->Base, &mode);

   stfb->iface = stfbi;
   stfb->iface_stamp = p_atomic_read(&stfbi->stamp) - 1;

   /* add the color buffer */
   idx = stfb->Base._ColorDrawBufferIndexes[0];
   if (!st_framebuffer_add_renderbuffer(stfb, idx)) {
      free(stfb);
      return NULL;
   }

   st_framebuffer_add_renderbuffer(stfb, BUFFER_DEPTH);
   st_framebuffer_add_renderbuffer(stfb, BUFFER_ACCUM);

   stfb->stamp = 0;
   st_framebuffer_update_attachments(stfb);

   return stfb;
}
   svga_texture_destroy,	      /* resource_destroy */
   svga_texture_get_transfer,	      /* get_transfer */
   svga_texture_transfer_destroy,     /* transfer_destroy */
   svga_texture_transfer_map,	      /* transfer_map */
   u_default_transfer_flush_region,   /* transfer_flush_region */
   svga_texture_transfer_unmap,	      /* transfer_unmap */
   u_default_transfer_inline_write    /* transfer_inline_write */
};


struct pipe_resource *
svga_texture_create(struct pipe_screen *screen,
                    const struct pipe_resource *template)
{
   struct svga_screen *svgascreen = svga_screen(screen);
   struct svga_texture *tex = CALLOC_STRUCT(svga_texture);

   if (!tex)
      goto error1;

   tex->b.b = *template;
   tex->b.vtbl = &svga_texture_vtbl;
   pipe_reference_init(&tex->b.b.reference, 1);
   tex->b.b.screen = screen;

   assert(template->last_level < SVGA_MAX_TEXTURE_LEVELS);
   if(template->last_level >= SVGA_MAX_TEXTURE_LEVELS)
      goto error2;
   
   tex->key.flags = 0;
   tex->key.size.width = template->width0;
Exemple #20
0
struct blitter_context *util_blitter_create(struct pipe_context *pipe)
{
   struct blitter_context_priv *ctx;
   struct pipe_blend_state blend;
   struct pipe_depth_stencil_alpha_state dsa;
   struct pipe_rasterizer_state rs_state;
   struct pipe_sampler_state sampler_state;
   struct pipe_vertex_element velem[2];
   unsigned i;

   ctx = CALLOC_STRUCT(blitter_context_priv);
   if (!ctx)
      return NULL;

   ctx->base.pipe = pipe;
   ctx->base.draw_rectangle = blitter_draw_rectangle;

   /* init state objects for them to be considered invalid */
   ctx->base.saved_blend_state = INVALID_PTR;
   ctx->base.saved_dsa_state = INVALID_PTR;
   ctx->base.saved_rs_state = INVALID_PTR;
   ctx->base.saved_fs = INVALID_PTR;
   ctx->base.saved_vs = INVALID_PTR;
   ctx->base.saved_gs = INVALID_PTR;
   ctx->base.saved_velem_state = INVALID_PTR;
   ctx->base.saved_fb_state.nr_cbufs = ~0;
   ctx->base.saved_num_sampler_views = ~0;
   ctx->base.saved_num_sampler_states = ~0;
   ctx->base.saved_num_vertex_buffers = ~0;
   ctx->base.saved_num_so_targets = ~0;

   ctx->has_geometry_shader =
      pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_GEOMETRY,
                                     PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0;
   ctx->vertex_has_integers =
      pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_VERTEX,
                                     PIPE_SHADER_CAP_INTEGERS);
   ctx->has_stream_out =
      pipe->screen->get_param(pipe->screen,
                              PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) != 0;

   /* blend state objects */
   memset(&blend, 0, sizeof(blend));
   ctx->blend_keep_color = pipe->create_blend_state(pipe, &blend);

   blend.rt[0].colormask = PIPE_MASK_RGBA;
   ctx->blend_write_color = pipe->create_blend_state(pipe, &blend);

   /* depth stencil alpha state objects */
   memset(&dsa, 0, sizeof(dsa));
   ctx->dsa_keep_depth_stencil =
      pipe->create_depth_stencil_alpha_state(pipe, &dsa);

   dsa.depth.enabled = 1;
   dsa.depth.writemask = 1;
   dsa.depth.func = PIPE_FUNC_ALWAYS;
   ctx->dsa_write_depth_keep_stencil =
      pipe->create_depth_stencil_alpha_state(pipe, &dsa);

   dsa.stencil[0].enabled = 1;
   dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
   dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
   dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
   dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
   dsa.stencil[0].valuemask = 0xff;
   dsa.stencil[0].writemask = 0xff;
   ctx->dsa_write_depth_stencil =
      pipe->create_depth_stencil_alpha_state(pipe, &dsa);

   dsa.depth.enabled = 0;
   dsa.depth.writemask = 0;
   ctx->dsa_keep_depth_write_stencil =
      pipe->create_depth_stencil_alpha_state(pipe, &dsa);

   /* sampler state */
   memset(&sampler_state, 0, sizeof(sampler_state));
   sampler_state.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
   sampler_state.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
   sampler_state.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
   sampler_state.normalized_coords = 1;
   ctx->sampler_state = pipe->create_sampler_state(pipe, &sampler_state);

   /* rasterizer state */
   memset(&rs_state, 0, sizeof(rs_state));
   rs_state.cull_face = PIPE_FACE_NONE;
   rs_state.gl_rasterization_rules = 1;
   rs_state.flatshade = 1;
   rs_state.depth_clip = 1;
   ctx->rs_state = pipe->create_rasterizer_state(pipe, &rs_state);

   if (ctx->has_stream_out) {
      rs_state.rasterizer_discard = 1;
      ctx->rs_discard_state = pipe->create_rasterizer_state(pipe, &rs_state);
   }

   /* vertex elements states */
   memset(&velem[0], 0, sizeof(velem[0]) * 2);
   for (i = 0; i < 2; i++) {
      velem[i].src_offset = i * 4 * sizeof(float);
      velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
   }
   ctx->velem_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]);

   if (ctx->vertex_has_integers) {
      memset(&velem[0], 0, sizeof(velem[0]) * 2);
      velem[0].src_offset = 0;
      velem[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
      velem[1].src_offset = 4 * sizeof(float);
      velem[1].src_format = PIPE_FORMAT_R32G32B32A32_SINT;
      ctx->velem_sint_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]);

      memset(&velem[0], 0, sizeof(velem[0]) * 2);
      velem[0].src_offset = 0;
      velem[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
      velem[1].src_offset = 4 * sizeof(float);
      velem[1].src_format = PIPE_FORMAT_R32G32B32A32_UINT;
      ctx->velem_uint_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]);
   }

   if (ctx->has_stream_out) {
      velem[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
      ctx->velem_state_readbuf = pipe->create_vertex_elements_state(pipe, 1, &velem[0]);
   }

   /* fragment shaders are created on-demand */

   /* vertex shaders */
   {
      const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
                                      TGSI_SEMANTIC_GENERIC };
      const uint semantic_indices[] = { 0, 0 };
      ctx->vs =
         util_make_vertex_passthrough_shader(pipe, 2, semantic_names,
                                             semantic_indices);
   }
   if (ctx->has_stream_out) {
      struct pipe_stream_output_info so;
      const uint semantic_names[] = { TGSI_SEMANTIC_POSITION };
      const uint semantic_indices[] = { 0 };

      memset(&so, 0, sizeof(so));
      so.num_outputs = 1;
      so.output[0].register_mask = TGSI_WRITEMASK_XYZW;
      so.stride = 4;

      ctx->vs_pos_only =
         util_make_vertex_passthrough_shader_with_so(pipe, 1, semantic_names,
                                                     semantic_indices, &so);
   }

   /* set invariant vertex coordinates */
   for (i = 0; i < 4; i++)
      ctx->vertices[i][0][3] = 1; /*v.w*/

   /* create the vertex buffer */
   ctx->vbuf = pipe_user_buffer_create(ctx->base.pipe->screen,
                                       ctx->vertices,
                                       sizeof(ctx->vertices),
                                       PIPE_BIND_VERTEX_BUFFER);

   return &ctx->base;
}
Exemple #21
0
static void *si_texture_transfer_map(struct pipe_context *ctx,
				     struct pipe_resource *texture,
				     unsigned level,
				     unsigned usage,
				     const struct pipe_box *box,
				     struct pipe_transfer **ptransfer)
{
	struct r600_context *rctx = (struct r600_context *)ctx;
	struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture;
	struct pipe_resource resource;
	struct r600_transfer *trans;
	int r;
	boolean use_staging_texture = FALSE;
	struct radeon_winsys_cs_handle *buf;
	enum pipe_format format = texture->format;
	unsigned offset = 0;
	char *map;

	/* We cannot map a tiled texture directly because the data is
	 * in a different order, therefore we do detiling using a blit.
	 *
	 * Also, use a temporary in GTT memory for read transfers, as
	 * the CPU is much happier reading out of cached system memory
	 * than uncached VRAM.
	 */
	if (rtex->surface.level[level].mode != RADEON_SURF_MODE_LINEAR_ALIGNED &&
	    rtex->surface.level[level].mode != RADEON_SURF_MODE_LINEAR)
		use_staging_texture = TRUE;

	/* XXX: Use a staging texture for uploads if the underlying BO
	 * is busy.  No interface for checking that currently? so do
	 * it eagerly whenever the transfer doesn't require a readback
	 * and might block.
	 */
	if ((usage & PIPE_TRANSFER_WRITE) &&
			!(usage & (PIPE_TRANSFER_READ |
					PIPE_TRANSFER_DONTBLOCK |
					PIPE_TRANSFER_UNSYNCHRONIZED)))
		use_staging_texture = TRUE;

	if (!permit_hardware_blit(ctx->screen, texture) ||
		(texture->flags & R600_RESOURCE_FLAG_TRANSFER))
		use_staging_texture = FALSE;

	if (use_staging_texture && (usage & PIPE_TRANSFER_MAP_DIRECTLY))
		return NULL;

	trans = CALLOC_STRUCT(r600_transfer);
	if (trans == NULL)
		return NULL;
	pipe_resource_reference(&trans->transfer.resource, texture);
	trans->transfer.level = level;
	trans->transfer.usage = usage;
	trans->transfer.box = *box;
	if (rtex->depth) {
		/* XXX: only readback the rectangle which is being mapped?
		*/
		/* XXX: when discard is true, no need to read back from depth texture
		*/
		r = r600_texture_depth_flush(ctx, texture, FALSE);
		if (r < 0) {
			R600_ERR("failed to create temporary texture to hold untiled copy\n");
			pipe_resource_reference(&trans->transfer.resource, NULL);
			FREE(trans);
			return NULL;
		}
		trans->transfer.stride = rtex->flushed_depth_texture->surface.level[level].pitch_bytes;
		trans->offset = r600_texture_get_offset(rtex->flushed_depth_texture, level, box->z);
	} else if (use_staging_texture) {
		resource.target = PIPE_TEXTURE_2D;
		resource.format = texture->format;
		resource.width0 = box->width;
		resource.height0 = box->height;
		resource.depth0 = 1;
		resource.array_size = 1;
		resource.last_level = 0;
		resource.nr_samples = 0;
		resource.usage = PIPE_USAGE_STAGING;
		resource.bind = 0;
		resource.flags = R600_RESOURCE_FLAG_TRANSFER;
		/* For texture reading, the temporary (detiled) texture is used as
		 * a render target when blitting from a tiled texture. */
		if (usage & PIPE_TRANSFER_READ) {
			resource.bind |= PIPE_BIND_RENDER_TARGET;
		}
		/* For texture writing, the temporary texture is used as a sampler
		 * when blitting into a tiled texture. */
		if (usage & PIPE_TRANSFER_WRITE) {
			resource.bind |= PIPE_BIND_SAMPLER_VIEW;
		}
		/* Create the temporary texture. */
		trans->staging_texture = ctx->screen->resource_create(ctx->screen, &resource);
		if (trans->staging_texture == NULL) {
			R600_ERR("failed to create temporary texture to hold untiled copy\n");
			pipe_resource_reference(&trans->transfer.resource, NULL);
			FREE(trans);
			return NULL;
		}

		trans->transfer.stride = ((struct r600_resource_texture *)trans->staging_texture)
					->surface.level[0].pitch_bytes;
		if (usage & PIPE_TRANSFER_READ) {
			r600_copy_to_staging_texture(ctx, trans);
			/* Always referenced in the blit. */
			radeonsi_flush(ctx, NULL, 0);
		}
	} else {
		trans->transfer.stride = rtex->surface.level[level].pitch_bytes;
		trans->transfer.layer_stride = rtex->surface.level[level].slice_size;
		trans->offset = r600_texture_get_offset(rtex, level, box->z);
	}

	if (trans->staging_texture) {
		buf = si_resource(trans->staging_texture)->cs_buf;
	} else {
		struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture;

		if (rtex->flushed_depth_texture)
			buf = rtex->flushed_depth_texture->resource.cs_buf;
		else
			buf = si_resource(texture)->cs_buf;

		offset = trans->offset +
			box->y / util_format_get_blockheight(format) * trans->transfer.stride +
			box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
	}

	if (!(map = rctx->ws->buffer_map(buf, rctx->cs, usage))) {
		pipe_resource_reference(&trans->staging_texture, NULL);
		pipe_resource_reference(&trans->transfer.resource, NULL);
		FREE(trans);
		return NULL;
	}

	*ptransfer = &trans->transfer;
	return map + offset;
}
Exemple #22
0
struct pipe_screen *
nv50_screen_create(struct nouveau_device *dev)
{
   struct nv50_screen *screen;
   struct pipe_screen *pscreen;
   struct nouveau_object *chan;
   uint64_t value;
   uint32_t tesla_class;
   unsigned stack_size;
   int ret;

   screen = CALLOC_STRUCT(nv50_screen);
   if (!screen)
      return NULL;
   pscreen = &screen->base.base;

   ret = nouveau_screen_init(&screen->base, dev);
   if (ret) {
      NOUVEAU_ERR("nouveau_screen_init failed: %d\n", ret);
      goto fail;
   }

   /* TODO: Prevent FIFO prefetch before transfer of index buffers and
    *  admit them to VRAM.
    */
   screen->base.vidmem_bindings |= PIPE_BIND_CONSTANT_BUFFER |
      PIPE_BIND_VERTEX_BUFFER;
   screen->base.sysmem_bindings |=
      PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER;

   screen->base.pushbuf->user_priv = screen;
   screen->base.pushbuf->rsvd_kick = 5;

   chan = screen->base.channel;

   pscreen->destroy = nv50_screen_destroy;
   pscreen->context_create = nv50_create;
   pscreen->is_format_supported = nv50_screen_is_format_supported;
   pscreen->get_param = nv50_screen_get_param;
   pscreen->get_shader_param = nv50_screen_get_shader_param;
   pscreen->get_paramf = nv50_screen_get_paramf;

   nv50_screen_init_resource_functions(pscreen);

   if (screen->base.device->chipset < 0x84 ||
       debug_get_bool_option("NOUVEAU_PMPEG", FALSE)) {
      /* PMPEG */
      nouveau_screen_init_vdec(&screen->base);
   } else if (screen->base.device->chipset < 0x98 ||
              screen->base.device->chipset == 0xa0) {
      /* VP2 */
      screen->base.base.get_video_param = nv84_screen_get_video_param;
      screen->base.base.is_video_format_supported = nv84_screen_video_supported;
   } else {
      /* VP3/4 */
      screen->base.base.get_video_param = nouveau_vp3_screen_get_video_param;
      screen->base.base.is_video_format_supported = nouveau_vp3_screen_video_supported;
   }

   ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, 4096,
                        NULL, &screen->fence.bo);
   if (ret) {
      NOUVEAU_ERR("Failed to allocate fence bo: %d\n", ret);
      goto fail;
   }

   nouveau_bo_map(screen->fence.bo, 0, NULL);
   screen->fence.map = screen->fence.bo->map;
   screen->base.fence.emit = nv50_screen_fence_emit;
   screen->base.fence.update = nv50_screen_fence_update;

   ret = nouveau_object_new(chan, 0xbeef0301, NOUVEAU_NOTIFIER_CLASS,
                            &(struct nv04_notify){ .length = 32 },
                            sizeof(struct nv04_notify), &screen->sync);
Exemple #23
0
struct pipe_context *svga_context_create( struct pipe_screen *screen,
					  void *priv )
{
   struct svga_screen *svgascreen = svga_screen(screen);
   struct svga_context *svga = NULL;
   enum pipe_error ret;

   svga = CALLOC_STRUCT(svga_context);
   if (svga == NULL)
      goto no_svga;

   svga->pipe.screen = screen;
   svga->pipe.priv = priv;
   svga->pipe.destroy = svga_destroy;
   svga->pipe.clear = svga_clear;

   svga->swc = svgascreen->sws->context_create(svgascreen->sws);
   if(!svga->swc)
      goto no_swc;

   svga_init_resource_functions(svga);
   svga_init_blend_functions(svga);
   svga_init_blit_functions(svga);
   svga_init_depth_stencil_functions(svga);
   svga_init_draw_functions(svga);
   svga_init_flush_functions(svga);
   svga_init_misc_functions(svga);
   svga_init_rasterizer_functions(svga);
   svga_init_sampler_functions(svga);
   svga_init_fs_functions(svga);
   svga_init_vs_functions(svga);
   svga_init_vertex_functions(svga);
   svga_init_constbuffer_functions(svga);
   svga_init_query_functions(svga);
   svga_init_surface_functions(svga);


   /* debug */
   svga->debug.no_swtnl = debug_get_option_no_swtnl();
   svga->debug.force_swtnl = debug_get_option_force_swtnl();
   svga->debug.use_min_mipmap = debug_get_option_use_min_mipmap();
   svga->debug.disable_shader = debug_get_option_disable_shader();
   svga->debug.no_line_width = debug_get_option_no_line_width();
   svga->debug.force_hw_line_stipple = debug_get_option_force_hw_line_stipple();

   svga->fs_bm = util_bitmask_create();
   if (svga->fs_bm == NULL)
      goto no_fs_bm;

   svga->vs_bm = util_bitmask_create();
   if (svga->vs_bm == NULL)
      goto no_vs_bm;

   svga->hwtnl = svga_hwtnl_create(svga);
   if (svga->hwtnl == NULL)
      goto no_hwtnl;

   if (!svga_init_swtnl(svga))
      goto no_swtnl;

   ret = svga_emit_initial_state( svga );
   if (ret != PIPE_OK)
      goto no_state;
   
   /* Avoid shortcircuiting state with initial value of zero.
    */
   memset(&svga->state.hw_clear, 0xcd, sizeof(svga->state.hw_clear));
   memset(&svga->state.hw_clear.framebuffer, 0x0, 
          sizeof(svga->state.hw_clear.framebuffer));

   memset(&svga->state.hw_draw, 0xcd, sizeof(svga->state.hw_draw));
   memset(&svga->state.hw_draw.views, 0x0, sizeof(svga->state.hw_draw.views));
   svga->state.hw_draw.num_views = 0;

   svga->dirty = ~0;

   LIST_INITHEAD(&svga->dirty_buffers);

   return &svga->pipe;

no_state:
   svga_destroy_swtnl(svga);
no_swtnl:
   svga_hwtnl_destroy( svga->hwtnl );
no_hwtnl:
   util_bitmask_destroy( svga->vs_bm );
no_vs_bm:
   util_bitmask_destroy( svga->fs_bm );
no_fs_bm:
   svga->swc->destroy(svga->swc);
no_swc:
   FREE(svga);
no_svga:
   return NULL;
}
Exemple #24
0
/**
 * Create a new stw_framebuffer object which corresponds to the given
 * HDC/window.  If successful, we return the new stw_framebuffer object
 * with its mutex locked.
 */
struct stw_framebuffer *
stw_framebuffer_create(HDC hdc, int iPixelFormat)
{
   HWND hWnd;
   struct stw_framebuffer *fb;
   const struct stw_pixelformat_info *pfi;

   /* We only support drawing to a window. */
   hWnd = WindowFromDC( hdc );
   if (!hWnd)
      return NULL;

   fb = CALLOC_STRUCT( stw_framebuffer );
   if (fb == NULL)
      return NULL;

   fb->hWnd = hWnd;
   fb->iPixelFormat = iPixelFormat;

   /*
    * We often need a displayable pixel format to make GDI happy. Set it
    * here (always 1, i.e., out first pixel format) where appropriate.
    */
   fb->iDisplayablePixelFormat = iPixelFormat <= stw_dev->pixelformat_count
      ? iPixelFormat : 1;

   fb->pfi = pfi = stw_pixelformat_get_info( iPixelFormat );
   fb->stfb = stw_st_create_framebuffer( fb );
   if (!fb->stfb) {
      FREE( fb );
      return NULL;
   }

   fb->refcnt = 1;

   /*
    * Windows can be sometimes have zero width and or height, but we ensure
    * a non-zero framebuffer size at all times.
    */

   fb->must_resize = TRUE;
   fb->width  = 1;
   fb->height = 1;
   fb->client_rect.left   = 0;
   fb->client_rect.top    = 0;
   fb->client_rect.right  = fb->client_rect.left + fb->width;
   fb->client_rect.bottom = fb->client_rect.top  + fb->height;

   stw_framebuffer_get_size(fb);

   InitializeCriticalSection(&fb->mutex);

   /* This is the only case where we lock the stw_framebuffer::mutex before
    * stw_dev::fb_mutex, since no other thread can know about this framebuffer
    * and we must prevent any other thread from destroying it before we return.
    */
   stw_framebuffer_lock(fb);

   stw_lock_framebuffers(stw_dev);
   fb->next = stw_dev->fb_head;
   stw_dev->fb_head = fb;
   stw_unlock_framebuffers(stw_dev);

   return fb;
}
Exemple #25
0
/*
 * Create a new X/Mesa visual.
 * Input:  display - X11 display
 *         visinfo - an XVisualInfo pointer
 *         rgb_flag - GL_TRUE = RGB mode,
 *                    GL_FALSE = color index mode
 *         alpha_flag - alpha buffer requested?
 *         db_flag - GL_TRUE = double-buffered,
 *                   GL_FALSE = single buffered
 *         stereo_flag - stereo visual?
 *         ximage_flag - GL_TRUE = use an XImage for back buffer,
 *                       GL_FALSE = use an off-screen pixmap for back buffer
 *         depth_size - requested bits/depth values, or zero
 *         stencil_size - requested bits/stencil values, or zero
 *         accum_red_size - requested bits/red accum values, or zero
 *         accum_green_size - requested bits/green accum values, or zero
 *         accum_blue_size - requested bits/blue accum values, or zero
 *         accum_alpha_size - requested bits/alpha accum values, or zero
 *         num_samples - number of samples/pixel if multisampling, or zero
 *         level - visual level, usually 0
 *         visualCaveat - ala the GLX extension, usually GLX_NONE
 * Return;  a new XMesaVisual or 0 if error.
 */
PUBLIC
XMesaVisual XMesaCreateVisual( Display *display,
                               XVisualInfo * visinfo,
                               GLboolean rgb_flag,
                               GLboolean alpha_flag,
                               GLboolean db_flag,
                               GLboolean stereo_flag,
                               GLboolean ximage_flag,
                               GLint depth_size,
                               GLint stencil_size,
                               GLint accum_red_size,
                               GLint accum_green_size,
                               GLint accum_blue_size,
                               GLint accum_alpha_size,
                               GLint num_samples,
                               GLint level,
                               GLint visualCaveat )
{
   XMesaDisplay xmdpy = xmesa_init_display(display);
   XMesaVisual v;
   GLint red_bits, green_bits, blue_bits, alpha_bits;

   if (!xmdpy)
      return NULL;

   /* For debugging only */
   if (_mesa_getenv("MESA_XSYNC")) {
      /* This makes debugging X easier.
       * In your debugger, set a breakpoint on _XError to stop when an
       * X protocol error is generated.
       */
      XSynchronize( display, 1 );
   }

   v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual);
   if (!v) {
      return NULL;
   }

   v->display = display;

   /* Save a copy of the XVisualInfo struct because the user may Xfree()
    * the struct but we may need some of the information contained in it
    * at a later time.
    */
   v->visinfo = (XVisualInfo *) MALLOC(sizeof(*visinfo));
   if (!v->visinfo) {
      free(v);
      return NULL;
   }
   memcpy(v->visinfo, visinfo, sizeof(*visinfo));

   v->ximage_flag = ximage_flag;

   v->mesa_visual.redMask = visinfo->red_mask;
   v->mesa_visual.greenMask = visinfo->green_mask;
   v->mesa_visual.blueMask = visinfo->blue_mask;
   v->mesa_visual.visualID = visinfo->visualid;
   v->mesa_visual.screen = visinfo->screen;

#if !(defined(__cplusplus) || defined(c_plusplus))
   v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->class);
#else
   v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->c_class);
#endif

   v->mesa_visual.visualRating = visualCaveat;

   if (alpha_flag)
      v->mesa_visual.alphaBits = 8;

   (void) initialize_visual_and_buffer( v, NULL, rgb_flag, 0, 0 );

   {
      const int xclass = v->mesa_visual.visualType;
      if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) {
         red_bits   = _mesa_bitcount(GET_REDMASK(v));
         green_bits = _mesa_bitcount(GET_GREENMASK(v));
         blue_bits  = _mesa_bitcount(GET_BLUEMASK(v));
      }
      else {
         /* this is an approximation */
         int depth;
         depth = v->visinfo->depth;
         red_bits = depth / 3;
         depth -= red_bits;
         green_bits = depth / 2;
         depth -= green_bits;
         blue_bits = depth;
         alpha_bits = 0;
         assert( red_bits + green_bits + blue_bits == v->visinfo->depth );
      }
      alpha_bits = v->mesa_visual.alphaBits;
   }

   /* initialize visual */
   {
      __GLcontextModes *vis = &v->mesa_visual;

      vis->rgbMode          = GL_TRUE;
      vis->doubleBufferMode = db_flag;
      vis->stereoMode       = stereo_flag;

      vis->redBits          = red_bits;
      vis->greenBits        = green_bits;
      vis->blueBits         = blue_bits;
      vis->alphaBits        = alpha_bits;
      vis->rgbBits          = red_bits + green_bits + blue_bits;

      vis->indexBits      = 0;
      vis->depthBits      = depth_size;
      vis->stencilBits    = stencil_size;

      vis->accumRedBits   = accum_red_size;
      vis->accumGreenBits = accum_green_size;
      vis->accumBlueBits  = accum_blue_size;
      vis->accumAlphaBits = accum_alpha_size;

      vis->haveAccumBuffer   = accum_red_size > 0;
      vis->haveDepthBuffer   = depth_size > 0;
      vis->haveStencilBuffer = stencil_size > 0;

      vis->numAuxBuffers = 0;
      vis->level = 0;
      vis->pixmapMode = 0;
      vis->sampleBuffers = 0;
      vis->samples = 0;
   }

   v->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK;
   if (db_flag)
      v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
   if (stereo_flag) {
      v->stvis.buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
      if (db_flag)
         v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK;
   }

   v->stvis.color_format = choose_pixel_format(v);
   if (v->stvis.color_format == PIPE_FORMAT_NONE) {
      FREE(v->visinfo);
      FREE(v);
      return NULL;
   }

   v->stvis.depth_stencil_format =
      choose_depth_stencil_format(xmdpy, depth_size, stencil_size);

   v->stvis.accum_format = (accum_red_size +
         accum_green_size + accum_blue_size + accum_alpha_size) ?
      PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE;

   v->stvis.samples = num_samples;
   v->stvis.render_buffer = ST_ATTACHMENT_INVALID;

   /* XXX minor hack */
   v->mesa_visual.level = level;
   return v;
}
Exemple #26
0
/**
 * Translate a vertex program to create a new variant.
 */
static struct st_vp_variant *
st_translate_vertex_program(struct st_context *st,
                            struct st_vertex_program *stvp,
                            const struct st_vp_variant_key *key)
{
   struct st_vp_variant *vpv = CALLOC_STRUCT(st_vp_variant);
   struct pipe_context *pipe = st->pipe;
   struct ureg_program *ureg;
   enum pipe_error error;
   unsigned num_outputs;

   st_prepare_vertex_program(st->ctx, stvp);

   if (!stvp->glsl_to_tgsi)
   {
      _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_OUTPUT);
      _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_VARYING);
   }

   ureg = ureg_create( TGSI_PROCESSOR_VERTEX );
   if (ureg == NULL) {
      free(vpv);
      return NULL;
   }

   vpv->key = *key;

   vpv->num_inputs = stvp->num_inputs;
   num_outputs = stvp->num_outputs;
   if (key->passthrough_edgeflags) {
      vpv->num_inputs++;
      num_outputs++;
   }

   if (ST_DEBUG & DEBUG_MESA) {
      _mesa_print_program(&stvp->Base.Base);
      _mesa_print_program_parameters(st->ctx, &stvp->Base.Base);
      debug_printf("\n");
   }

   if (stvp->glsl_to_tgsi)
      error = st_translate_program(st->ctx,
                                   TGSI_PROCESSOR_VERTEX,
                                   ureg,
                                   stvp->glsl_to_tgsi,
                                   &stvp->Base.Base,
                                   /* inputs */
                                   stvp->num_inputs,
                                   stvp->input_to_index,
                                   NULL, /* input semantic name */
                                   NULL, /* input semantic index */
                                   NULL, /* interp mode */
                                   NULL, /* is centroid */
                                   /* outputs */
                                   stvp->num_outputs,
                                   stvp->result_to_output,
                                   stvp->output_semantic_name,
                                   stvp->output_semantic_index,
                                   key->passthrough_edgeflags,
                                   key->clamp_color);
   else
      error = st_translate_mesa_program(st->ctx,
                                        TGSI_PROCESSOR_VERTEX,
                                        ureg,
                                        &stvp->Base.Base,
                                        /* inputs */
                                        vpv->num_inputs,
                                        stvp->input_to_index,
                                        NULL, /* input semantic name */
                                        NULL, /* input semantic index */
                                        NULL,
                                        /* outputs */
                                        num_outputs,
                                        stvp->result_to_output,
                                        stvp->output_semantic_name,
                                        stvp->output_semantic_index,
                                        key->passthrough_edgeflags,
                                        key->clamp_color);

   if (error)
      goto fail;

   vpv->tgsi.tokens = ureg_get_tokens( ureg, NULL );
   if (!vpv->tgsi.tokens)
      goto fail;

   ureg_destroy( ureg );

   if (stvp->glsl_to_tgsi) {
      st_translate_stream_output_info(stvp->glsl_to_tgsi,
                                      stvp->result_to_output,
                                      &vpv->tgsi.stream_output);
   }

   vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->tgsi);

   if (ST_DEBUG & DEBUG_TGSI) {
      tgsi_dump( vpv->tgsi.tokens, 0 );
      debug_printf("\n");
   }

   return vpv;

fail:
   debug_printf("%s: failed to translate Mesa program:\n", __FUNCTION__);
   _mesa_print_program(&stvp->Base.Base);
   debug_assert(0);

   ureg_destroy( ureg );
   return NULL;
}
Exemple #27
0
struct pipe_context *
nvc0_create(struct pipe_screen *pscreen, void *priv)
{
   struct nvc0_screen *screen = nvc0_screen(pscreen);
   struct nvc0_context *nvc0;
   struct pipe_context *pipe;
   int ret;
   uint32_t flags;

   nvc0 = CALLOC_STRUCT(nvc0_context);
   if (!nvc0)
      return NULL;
   pipe = &nvc0->base.pipe;

   if (!nvc0_blitctx_create(nvc0))
      goto out_err;

   nvc0->base.pushbuf = screen->base.pushbuf;

   ret = nouveau_bufctx_new(screen->base.client, NVC0_BIND_COUNT,
                            &nvc0->bufctx_3d);
   if (!ret)
      nouveau_bufctx_new(screen->base.client, 2, &nvc0->bufctx);
   if (ret)
      goto out_err;

   nvc0->screen = screen;
   nvc0->base.screen = &screen->base;

   pipe->screen = pscreen;
   pipe->priv = priv;

   pipe->destroy = nvc0_destroy;

   pipe->draw_vbo = nvc0_draw_vbo;
   pipe->clear = nvc0_clear;

   pipe->flush = nvc0_flush;
   pipe->texture_barrier = nvc0_texture_barrier;

   if (!screen->cur_ctx) {
      screen->cur_ctx = nvc0;
      nouveau_pushbuf_bufctx(screen->base.pushbuf, nvc0->bufctx);
   }
   screen->base.pushbuf->kick_notify = nvc0_default_kick_notify;

   nvc0_init_query_functions(nvc0);
   nvc0_init_surface_functions(nvc0);
   nvc0_init_state_functions(nvc0);
   nvc0_init_transfer_functions(nvc0);
   nvc0_init_resource_functions(pipe);

#ifdef NVC0_WITH_DRAW_MODULE
   /* no software fallbacks implemented */
   nvc0->draw = draw_create(pipe);
   assert(nvc0->draw);
   draw_set_rasterize_stage(nvc0->draw, nvc0_draw_render_stage(nvc0));
#endif

   nouveau_context_init_vdec(&nvc0->base);

   /* shader builtin library is per-screen, but we need a context for m2mf */
   nvc0_program_library_upload(nvc0);

   /* add permanently resident buffers to bufctxts */

   flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD;

   BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->text);
   BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->uniform_bo);
   BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->txc);
   BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->poly_cache);

   flags = NOUVEAU_BO_GART | NOUVEAU_BO_WR;

   BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->fence.bo);
   BCTX_REFN_bo(nvc0->bufctx, FENCE, flags, screen->fence.bo);

   nvc0->base.scratch.bo_size = 2 << 20;

   memset(nvc0->tex_handles, ~0, sizeof(nvc0->tex_handles));

   return pipe;

out_err:
   if (nvc0) {
      if (nvc0->bufctx_3d)
         nouveau_bufctx_del(&nvc0->bufctx_3d);
      if (nvc0->bufctx)
         nouveau_bufctx_del(&nvc0->bufctx);
      if (nvc0->blit)
         FREE(nvc0->blit);
      FREE(nvc0);
   }
   return NULL;
}
Exemple #28
0
/**
 * Translate a Mesa fragment shader into a TGSI shader using extra info in
 * the key.
 * \return  new fragment program variant
 */
static struct st_fp_variant *
st_translate_fragment_program(struct st_context *st,
                              struct st_fragment_program *stfp,
                              const struct st_fp_variant_key *key)
{
   struct pipe_context *pipe = st->pipe;
   struct st_fp_variant *variant = CALLOC_STRUCT(st_fp_variant);
   GLboolean deleteFP = GL_FALSE;

   GLuint outputMapping[FRAG_RESULT_MAX];
   GLuint inputMapping[FRAG_ATTRIB_MAX];
   GLuint interpMode[PIPE_MAX_SHADER_INPUTS];  /* XXX size? */
   GLuint attr;
   GLbitfield64 inputsRead;
   struct ureg_program *ureg;

   GLboolean write_all = GL_FALSE;

   ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS];
   ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS];
   GLboolean is_centroid[PIPE_MAX_SHADER_INPUTS];
   uint fs_num_inputs = 0;

   ubyte fs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
   ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
   uint fs_num_outputs = 0;

   if (!variant)
      return NULL;

   assert(!(key->bitmap && key->drawpixels));

   if (key->bitmap) {
      /* glBitmap drawing */
      struct gl_fragment_program *fp; /* we free this temp program below */

      st_make_bitmap_fragment_program(st, &stfp->Base,
                                      &fp, &variant->bitmap_sampler);

      variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters);
      stfp = st_fragment_program(fp);
      deleteFP = GL_TRUE;
   }
   else if (key->drawpixels) {
      /* glDrawPixels drawing */
      struct gl_fragment_program *fp; /* we free this temp program below */

      if (key->drawpixels_z || key->drawpixels_stencil) {
         fp = st_make_drawpix_z_stencil_program(st, key->drawpixels_z,
                                                key->drawpixels_stencil);
      }
      else {
         /* RGBA */
         st_make_drawpix_fragment_program(st, &stfp->Base, &fp);
         variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters);
         deleteFP = GL_TRUE;
      }
      stfp = st_fragment_program(fp);
   }

   if (!stfp->glsl_to_tgsi)
      _mesa_remove_output_reads(&stfp->Base.Base, PROGRAM_OUTPUT);

   /*
    * Convert Mesa program inputs to TGSI input register semantics.
    */
   inputsRead = stfp->Base.Base.InputsRead;
   for (attr = 0; attr < FRAG_ATTRIB_MAX; attr++) {
      if ((inputsRead & BITFIELD64_BIT(attr)) != 0) {
         const GLuint slot = fs_num_inputs++;

         inputMapping[attr] = slot;
         is_centroid[slot] = (stfp->Base.IsCentroid & BITFIELD64_BIT(attr)) != 0;

         switch (attr) {
         case FRAG_ATTRIB_WPOS:
            input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
            input_semantic_index[slot] = 0;
            interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
            break;
         case FRAG_ATTRIB_COL0:
            input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
            input_semantic_index[slot] = 0;
            interpMode[slot] = st_translate_interp(stfp->Base.InterpQualifier[attr],
                                                   TRUE);
            break;
         case FRAG_ATTRIB_COL1:
            input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
            input_semantic_index[slot] = 1;
            interpMode[slot] = st_translate_interp(stfp->Base.InterpQualifier[attr],
                                                   TRUE);
            break;
         case FRAG_ATTRIB_FOGC:
            input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
            input_semantic_index[slot] = 0;
            interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
            break;
         case FRAG_ATTRIB_FACE:
            input_semantic_name[slot] = TGSI_SEMANTIC_FACE;
            input_semantic_index[slot] = 0;
            interpMode[slot] = TGSI_INTERPOLATE_CONSTANT;
            break;
         case FRAG_ATTRIB_CLIP_DIST0:
            input_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST;
            input_semantic_index[slot] = 0;
            interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
            break;
         case FRAG_ATTRIB_CLIP_DIST1:
            input_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST;
            input_semantic_index[slot] = 1;
            interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
            break;
            /* In most cases, there is nothing special about these
             * inputs, so adopt a convention to use the generic
             * semantic name and the mesa FRAG_ATTRIB_ number as the
             * index.
             *
             * All that is required is that the vertex shader labels
             * its own outputs similarly, and that the vertex shader
             * generates at least every output required by the
             * fragment shader plus fixed-function hardware (such as
             * BFC).
             *
             * There is no requirement that semantic indexes start at
             * zero or be restricted to a particular range -- nobody
             * should be building tables based on semantic index.
             */
         case FRAG_ATTRIB_PNTC:
         case FRAG_ATTRIB_TEX0:
         case FRAG_ATTRIB_TEX1:
         case FRAG_ATTRIB_TEX2:
         case FRAG_ATTRIB_TEX3:
         case FRAG_ATTRIB_TEX4:
         case FRAG_ATTRIB_TEX5:
         case FRAG_ATTRIB_TEX6:
         case FRAG_ATTRIB_TEX7:
         case FRAG_ATTRIB_VAR0:
         default:
            /* Actually, let's try and zero-base this just for
             * readability of the generated TGSI.
             */
            assert(attr >= FRAG_ATTRIB_TEX0);
            input_semantic_index[slot] = (attr - FRAG_ATTRIB_TEX0);
            input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
            if (attr == FRAG_ATTRIB_PNTC)
               interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
            else
               interpMode[slot] = st_translate_interp(stfp->Base.InterpQualifier[attr],
                                                      FALSE);
            break;
         }
      }
      else {
         inputMapping[attr] = -1;
      }
   }

   /*
    * Semantics and mapping for outputs
    */
   {
      uint numColors = 0;
      GLbitfield64 outputsWritten = stfp->Base.Base.OutputsWritten;

      /* if z is written, emit that first */
      if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) {
         fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_POSITION;
         fs_output_semantic_index[fs_num_outputs] = 0;
         outputMapping[FRAG_RESULT_DEPTH] = fs_num_outputs;
         fs_num_outputs++;
         outputsWritten &= ~(1 << FRAG_RESULT_DEPTH);
      }

      if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_STENCIL)) {
         fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_STENCIL;
         fs_output_semantic_index[fs_num_outputs] = 0;
         outputMapping[FRAG_RESULT_STENCIL] = fs_num_outputs;
         fs_num_outputs++;
         outputsWritten &= ~(1 << FRAG_RESULT_STENCIL);
      }

      /* handle remaining outputs (color) */
      for (attr = 0; attr < FRAG_RESULT_MAX; attr++) {
         if (outputsWritten & BITFIELD64_BIT(attr)) {
            switch (attr) {
            case FRAG_RESULT_DEPTH:
            case FRAG_RESULT_STENCIL:
               /* handled above */
               assert(0);
               break;
            case FRAG_RESULT_COLOR:
               write_all = GL_TRUE; /* fallthrough */
            default:
               assert(attr == FRAG_RESULT_COLOR ||
                      (FRAG_RESULT_DATA0 <= attr && attr < FRAG_RESULT_MAX));
               fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_COLOR;
               fs_output_semantic_index[fs_num_outputs] = numColors;
               outputMapping[attr] = fs_num_outputs;
               numColors++;
               break;
            }

            fs_num_outputs++;
         }
      }
   }

   ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
   if (ureg == NULL) {
      free(variant);
      return NULL;
   }

   if (ST_DEBUG & DEBUG_MESA) {
      _mesa_print_program(&stfp->Base.Base);
      _mesa_print_program_parameters(st->ctx, &stfp->Base.Base);
      debug_printf("\n");
   }
   if (write_all == GL_TRUE)
      ureg_property_fs_color0_writes_all_cbufs(ureg, 1);

   if (stfp->Base.FragDepthLayout != FRAG_DEPTH_LAYOUT_NONE) {
      switch (stfp->Base.FragDepthLayout) {
      case FRAG_DEPTH_LAYOUT_ANY:
         ureg_property_fs_depth_layout(ureg, TGSI_FS_DEPTH_LAYOUT_ANY);
         break;
      case FRAG_DEPTH_LAYOUT_GREATER:
         ureg_property_fs_depth_layout(ureg, TGSI_FS_DEPTH_LAYOUT_GREATER);
         break;
      case FRAG_DEPTH_LAYOUT_LESS:
         ureg_property_fs_depth_layout(ureg, TGSI_FS_DEPTH_LAYOUT_LESS);
         break;
      case FRAG_DEPTH_LAYOUT_UNCHANGED:
         ureg_property_fs_depth_layout(ureg, TGSI_FS_DEPTH_LAYOUT_UNCHANGED);
         break;
      default:
         assert(0);
      }
   }

   if (stfp->glsl_to_tgsi)
      st_translate_program(st->ctx,
                           TGSI_PROCESSOR_FRAGMENT,
                           ureg,
                           stfp->glsl_to_tgsi,
                           &stfp->Base.Base,
                           /* inputs */
                           fs_num_inputs,
                           inputMapping,
                           input_semantic_name,
                           input_semantic_index,
                           interpMode,
                           is_centroid,
                           /* outputs */
                           fs_num_outputs,
                           outputMapping,
                           fs_output_semantic_name,
                           fs_output_semantic_index, FALSE,
                           key->clamp_color );
   else
      st_translate_mesa_program(st->ctx,
                                TGSI_PROCESSOR_FRAGMENT,
                                ureg,
                                &stfp->Base.Base,
                                /* inputs */
                                fs_num_inputs,
                                inputMapping,
                                input_semantic_name,
                                input_semantic_index,
                                interpMode,
                                /* outputs */
                                fs_num_outputs,
                                outputMapping,
                                fs_output_semantic_name,
                                fs_output_semantic_index, FALSE,
                                key->clamp_color);

   variant->tgsi.tokens = ureg_get_tokens( ureg, NULL );
   ureg_destroy( ureg );

   /* fill in variant */
   variant->driver_shader = pipe->create_fs_state(pipe, &variant->tgsi);
   variant->key = *key;

   if (ST_DEBUG & DEBUG_TGSI) {
      tgsi_dump( variant->tgsi.tokens, 0/*TGSI_DUMP_VERBOSE*/ );
      debug_printf("\n");
   }

   if (deleteFP) {
      /* Free the temporary program made above */
      struct gl_fragment_program *fp = &stfp->Base;
      _mesa_reference_fragprog(st->ctx, &fp, NULL);
   }

   return variant;
}
static void *
svga_texture_transfer_map(struct pipe_context *pipe,
                          struct pipe_resource *texture,
                          unsigned level,
                          unsigned usage,
                          const struct pipe_box *box,
                          struct pipe_transfer **ptransfer)
{
   struct svga_context *svga = svga_context(pipe);
   struct svga_screen *ss = svga_screen(pipe->screen);
   struct svga_winsys_screen *sws = ss->sws;
   struct svga_texture *tex = svga_texture(texture);
   struct svga_transfer *st;
   unsigned nblocksx, nblocksy;
   boolean use_direct_map = svga_have_gb_objects(svga) &&
      !svga_have_gb_dma(svga);
   unsigned d;
   void *returnVal;
   int64_t begin = os_time_get();

   /* We can't map texture storage directly unless we have GB objects */
   if (usage & PIPE_TRANSFER_MAP_DIRECTLY) {
      if (svga_have_gb_objects(svga))
         use_direct_map = TRUE;
      else
         return NULL;
   }

   st = CALLOC_STRUCT(svga_transfer);
   if (!st)
      return NULL;

   {
      unsigned w, h;
      if (use_direct_map) {
         /* we'll directly access the guest-backed surface */
         w = u_minify(texture->width0, level);
         h = u_minify(texture->height0, level);
         d = u_minify(texture->depth0, level);
      }
      else {
         /* we'll put the data into a tightly packed buffer */
         w = box->width;
         h = box->height;
         d = box->depth;
      }
      nblocksx = util_format_get_nblocksx(texture->format, w);
      nblocksy = util_format_get_nblocksy(texture->format, h);
   }

   pipe_resource_reference(&st->base.resource, texture);

   st->base.level = level;
   st->base.usage = usage;
   st->base.box = *box;
   st->base.stride = nblocksx*util_format_get_blocksize(texture->format);
   st->base.layer_stride = st->base.stride * nblocksy;

   switch (tex->b.b.target) {
   case PIPE_TEXTURE_CUBE:
   case PIPE_TEXTURE_2D_ARRAY:
   case PIPE_TEXTURE_1D_ARRAY:
      st->slice = st->base.box.z;
      st->base.box.z = 0;   /* so we don't apply double offsets below */
      break;
   default:
      st->slice = 0;
      break;
   }

   if (usage & PIPE_TRANSFER_WRITE) {
      /* record texture upload for HUD */
      svga->hud.num_bytes_uploaded +=
         nblocksx * nblocksy * d * util_format_get_blocksize(texture->format);
   }

   if (!use_direct_map) {
      /* Use a DMA buffer */
      st->hw_nblocksy = nblocksy;

      st->hwbuf = svga_winsys_buffer_create(svga, 1, 0,
                                   st->hw_nblocksy * st->base.stride * d);
      while(!st->hwbuf && (st->hw_nblocksy /= 2)) {
         st->hwbuf = svga_winsys_buffer_create(svga, 1, 0,
                                   st->hw_nblocksy * st->base.stride * d);
      }

      if (!st->hwbuf) {
         FREE(st);
         return NULL;
      }

      if (st->hw_nblocksy < nblocksy) {
         /* We couldn't allocate a hardware buffer big enough for the transfer,
          * so allocate regular malloc memory instead */
         if (0) {
            debug_printf("%s: failed to allocate %u KB of DMA, "
                         "splitting into %u x %u KB DMA transfers\n",
                         __FUNCTION__,
                         (nblocksy*st->base.stride + 1023)/1024,
                         (nblocksy + st->hw_nblocksy - 1)/st->hw_nblocksy,
                         (st->hw_nblocksy*st->base.stride + 1023)/1024);
         }

         st->swbuf = MALLOC(nblocksy * st->base.stride * d);
         if (!st->swbuf) {
            sws->buffer_destroy(sws, st->hwbuf);
            FREE(st);
            return NULL;
         }
      }

      if (usage & PIPE_TRANSFER_READ) {
         SVGA3dSurfaceDMAFlags flags;
         memset(&flags, 0, sizeof flags);
         svga_transfer_dma(svga, st, SVGA3D_READ_HOST_VRAM, flags);
      }
   } else {
      struct pipe_transfer *transfer = &st->base;
      struct svga_winsys_surface *surf = tex->handle;

      if (!surf) {
         FREE(st);
         return NULL;
      }

      /* If this is the first time mapping to the surface in this
       * command buffer, clear the dirty masks of this surface.
       */
      if (sws->surface_is_flushed(sws, surf)) {
         svga_clear_texture_dirty(tex);
      }

      if (need_tex_readback(transfer)) {
	 enum pipe_error ret;

         svga_surfaces_flush(svga);

         if (svga_have_vgpu10(svga)) {
            ret = readback_image_vgpu10(svga, surf, st->slice, transfer->level,
                                        tex->b.b.last_level + 1);
         } else {
            ret = readback_image_vgpu9(svga, surf, st->slice, transfer->level);
         }

         svga->hud.num_readbacks++;

         assert(ret == PIPE_OK);
         (void) ret;

	 svga_context_flush(svga, NULL);

         /*
          * Note: if PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE were specified
          * we could potentially clear the flag for all faces/layers/mips.
          */
         svga_clear_texture_rendered_to(tex, st->slice, transfer->level);
      }
      else {
	 assert(transfer->usage & PIPE_TRANSFER_WRITE);
	 if ((transfer->usage & PIPE_TRANSFER_UNSYNCHRONIZED) == 0) {
            if (svga_is_texture_dirty(tex, st->slice, transfer->level)) {
               /*
                * do a surface flush if the subresource has been modified
                * in this command buffer.
                */
               svga_surfaces_flush(svga);
               if (!sws->surface_is_flushed(sws, surf)) {
                  svga->hud.surface_write_flushes++;
                  svga_context_flush(svga, NULL);
               }
            }
	 }
      }
      if (transfer->usage & PIPE_TRANSFER_WRITE) {
         /* mark this texture level as dirty */
         svga_set_texture_dirty(tex, st->slice, transfer->level);
      }
   }

   st->use_direct_map = use_direct_map;

   *ptransfer = &st->base;

   /*
    * Begin mapping code
    */
   if (st->swbuf) {
      returnVal = st->swbuf;
   }
   else if (!st->use_direct_map) {
      returnVal = sws->buffer_map(sws, st->hwbuf, usage);
   }
   else {
      SVGA3dSize baseLevelSize;
      struct svga_texture *tex = svga_texture(texture);
      struct svga_winsys_surface *surf = tex->handle;
      uint8_t *map;
      boolean retry;
      unsigned offset, mip_width, mip_height;
      unsigned xoffset = st->base.box.x;
      unsigned yoffset = st->base.box.y;
      unsigned zoffset = st->base.box.z;

      map = svga->swc->surface_map(svga->swc, surf, usage, &retry);
      if (map == NULL && retry) {
         /*
          * At this point, the svga_surfaces_flush() should already have
          * called in svga_texture_get_transfer().
          */
         svga_context_flush(svga, NULL);
         map = svga->swc->surface_map(svga->swc, surf, usage, &retry);
      }

      /*
       * Make sure we return NULL if the map fails
       */
      if (!map) {
         FREE(st);
         return map;
      }

      /**
       * Compute the offset to the specific texture slice in the buffer.
       */
      baseLevelSize.width = tex->b.b.width0;
      baseLevelSize.height = tex->b.b.height0;
      baseLevelSize.depth = tex->b.b.depth0;

      offset = svga3dsurface_get_image_offset(tex->key.format, baseLevelSize,
                                              tex->b.b.last_level + 1, /* numMips */
                                              st->slice, level);
      if (level > 0) {
         assert(offset > 0);
      }

      mip_width = u_minify(tex->b.b.width0, level);
      mip_height = u_minify(tex->b.b.height0, level);

      offset += svga3dsurface_get_pixel_offset(tex->key.format,
                                               mip_width, mip_height,
                                               xoffset, yoffset, zoffset);
      returnVal = (void *) (map + offset);
   }

   svga->hud.map_buffer_time += (os_time_get() - begin);
   svga->hud.num_resources_mapped++;

   return returnVal;
}
Exemple #30
0
static struct pb_buffer *
pb_cache_manager_create_buffer(struct pb_manager *_mgr, 
                               pb_size size,
                               const struct pb_desc *desc)
{
   struct pb_cache_manager *mgr = pb_cache_manager(_mgr);
   struct pb_cache_buffer *buf;
   struct pb_cache_buffer *curr_buf;
   struct list_head *curr, *next;
   struct util_time now;
   
   pipe_mutex_lock(mgr->mutex);

   buf = NULL;
   curr = mgr->delayed.next;
   next = curr->next;
   
   /* search in the expired buffers, freeing them in the process */
   util_time_get(&now);
   while(curr != &mgr->delayed) {
      curr_buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
      if(!buf && pb_cache_is_buffer_compat(curr_buf, size, desc))
	 buf = curr_buf;
      else if(util_time_timeout(&curr_buf->start, &curr_buf->end, &now))
	 _pb_cache_buffer_destroy(curr_buf);
      else
         /* This buffer (and all hereafter) are still hot in cache */
         break;
      curr = next; 
      next = curr->next;
   }

   /* keep searching in the hot buffers */
   if(!buf) {
      while(curr != &mgr->delayed) {
         curr_buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
         if(pb_cache_is_buffer_compat(curr_buf, size, desc)) {
            buf = curr_buf;
            break;
         }
         /* no need to check the timeout here */
         curr = next;
         next = curr->next;
      }
   }
   
   if(buf) {
      LIST_DEL(&buf->head);
      pipe_mutex_unlock(mgr->mutex);
      /* Increase refcount */
      pb_reference((struct pb_buffer**)&buf, &buf->base);
      return &buf->base;
   }
   
   pipe_mutex_unlock(mgr->mutex);

   buf = CALLOC_STRUCT(pb_cache_buffer);
   if(!buf)
      return NULL;
   
   buf->buffer = mgr->provider->create_buffer(mgr->provider, size, desc);
   if(!buf->buffer) {
      FREE(buf);
      return NULL;
   }
   
   assert(pipe_is_referenced(&buf->buffer->base.reference));
   assert(pb_check_alignment(desc->alignment, buf->buffer->base.alignment));
   assert(pb_check_usage(desc->usage, buf->buffer->base.usage));
   assert(buf->buffer->base.size >= size);
   
   pipe_reference_init(&buf->base.base.reference, 1);
   buf->base.base.alignment = buf->buffer->base.alignment;
   buf->base.base.usage = buf->buffer->base.usage;
   buf->base.base.size = buf->buffer->base.size;
   
   buf->base.vtbl = &pb_cache_buffer_vtbl;
   buf->mgr = mgr;
   
   return &buf->base;
}