Ejemplo n.º 1
0
/* Flush a depth stencil buffer. */
void r300_flush_depth_stencil(struct pipe_context *pipe,
                              struct pipe_resource *dst,
                              unsigned level,
                              unsigned layer)
{
    struct r300_context *r300 = r300_context(pipe);
    struct pipe_surface *dstsurf, surf_tmpl;
    struct r300_texture *tex = r300_texture(dst);

    if (!tex->zmask_mem[level])
        return;
    if (!tex->zmask_in_use[level])
        return;

    surf_tmpl.format = dst->format;
    surf_tmpl.usage = PIPE_BIND_DEPTH_STENCIL;
    surf_tmpl.u.tex.level = level;
    surf_tmpl.u.tex.first_layer = layer;
    surf_tmpl.u.tex.last_layer = layer;
    dstsurf = pipe->create_surface(pipe, dst, &surf_tmpl);

    r300->z_decomp_rd = TRUE;
    r300_blitter_begin(r300, R300_CLEAR_SURFACE);
    util_blitter_flush_depth_stencil(r300->blitter, dstsurf);
    r300_blitter_end(r300);
    r300->z_decomp_rd = FALSE;

    tex->zmask_in_use[level] = FALSE;
}
Ejemplo n.º 2
0
void* r300_texture_transfer_map(struct pipe_context *ctx,
				struct pipe_transfer *transfer)
{
    struct r300_context *r300 = r300_context(ctx);
    struct r300_winsys_screen *rws = (struct r300_winsys_screen *)ctx->winsys;
    struct r300_transfer *r300transfer = r300_transfer(transfer);
    struct r300_texture *tex = r300_texture(transfer->resource);
    char *map;
    enum pipe_format format = tex->desc.b.b.format;

    if (r300transfer->linear_texture) {
        /* The detiled texture is of the same size as the region being mapped
         * (no offset needed). */
        return rws->buffer_map(rws,
                               r300transfer->linear_texture->buffer,
                               r300->cs,
                               transfer->usage);
    } else {
        /* Tiling is disabled. */
        map = rws->buffer_map(rws, tex->buffer, r300->cs,
                              transfer->usage);

        if (!map) {
            return NULL;
        }

        return map + r300_transfer(transfer)->offset +
            transfer->box.y / util_format_get_blockheight(format) * transfer->stride +
            transfer->box.x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
    }
}
Ejemplo n.º 3
0
void r300_texture_transfer_unmap(struct pipe_context *ctx,
				 struct pipe_transfer *transfer)
{
    struct r300_winsys_screen *rws = (struct r300_winsys_screen *)ctx->winsys;
    struct r300_transfer *r300transfer = r300_transfer(transfer);
    struct r300_texture *tex = r300_texture(transfer->resource);

    if (r300transfer->linear_texture) {
        rws->buffer_unmap(rws, r300transfer->linear_texture->buffer);
    } else {
        rws->buffer_unmap(rws, tex->buffer);
    }
}
Ejemplo n.º 4
0
void r300_texture_reinterpret_format(struct pipe_screen *screen,
                                     struct pipe_resource *tex,
                                     enum pipe_format new_format)
{
    struct r300_screen *r300screen = r300_screen(screen);

    SCREEN_DBG(r300screen, DBG_TEX,
        "r300: texture_reinterpret_format: %s -> %s\n",
        util_format_short_name(tex->format),
        util_format_short_name(new_format));

    tex->format = new_format;

    r300_texture_setup_fb_state(r300_screen(screen), r300_texture(tex));
}
Ejemplo n.º 5
0
/* Not required to implement u_resource_vtbl, consider moving to another file:
 */
struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen,
                                          struct pipe_resource* texture,
					  unsigned face,
					  unsigned level,
					  unsigned zslice,
					  unsigned flags)
{
    struct r300_texture* tex = r300_texture(texture);
    struct r300_surface* surface = CALLOC_STRUCT(r300_surface);

    if (surface) {
        uint32_t offset, tile_height;

        pipe_reference_init(&surface->base.reference, 1);
        pipe_resource_reference(&surface->base.texture, texture);
        surface->base.format = texture->format;
        surface->base.width = u_minify(texture->width0, level);
        surface->base.height = u_minify(texture->height0, level);
        surface->base.usage = flags;
        surface->base.zslice = zslice;
        surface->base.face = face;
        surface->base.level = level;

        surface->buffer = tex->buffer;

        /* Prefer VRAM if there are multiple domains to choose from. */
        surface->domain = tex->domain;
        if (surface->domain & R300_DOMAIN_VRAM)
            surface->domain &= ~R300_DOMAIN_GTT;

        surface->offset = r300_texture_get_offset(&tex->desc,
                                                  level, zslice, face);
        surface->pitch = tex->fb_state.pitch[level];
        surface->format = tex->fb_state.format;

        /* Parameters for the CBZB clear. */
        surface->cbzb_allowed = tex->desc.cbzb_allowed[level];
        surface->cbzb_width = align(surface->base.width, 64);

        /* Height must be aligned to the size of a tile. */
        tile_height = r300_get_pixel_alignment(tex->desc.b.b.format,
                                               tex->desc.b.b.nr_samples,
                                               tex->desc.microtile,
                                               tex->desc.macrotile[level],
                                               DIM_HEIGHT, 0);

        surface->cbzb_height = align((surface->base.height + 1) / 2,
                                     tile_height);

        /* Offset must be aligned to 2K and must point at the beginning
         * of a scanline. */
        offset = surface->offset +
                 tex->desc.stride_in_bytes[level] * surface->cbzb_height;
        surface->cbzb_midpoint_offset = offset & ~2047;

        surface->cbzb_pitch = surface->pitch & 0x1ffffc;

        if (util_format_get_blocksizebits(surface->base.format) == 32)
            surface->cbzb_format = R300_DEPTHFORMAT_24BIT_INT_Z_8BIT_STENCIL;
        else
            surface->cbzb_format = R300_DEPTHFORMAT_16BIT_INT_Z;

        SCREEN_DBG(r300_screen(screen), DBG_CBZB,
                   "CBZB Allowed: %s, Dim: %ix%i, Misalignment: %i, Micro: %s, Macro: %s\n",
                   surface->cbzb_allowed ? "YES" : " NO",
                   surface->cbzb_width, surface->cbzb_height,
                   offset & 2047,
                   tex->desc.microtile ? "YES" : " NO",
                   tex->desc.macrotile[level] ? "YES" : " NO");
    }

    return &surface->base;
}
Ejemplo n.º 6
0
/* Clear currently bound buffers. */
static void r300_clear(struct pipe_context* pipe,
                       unsigned buffers,
                       const float* rgba,
                       double depth,
                       unsigned stencil)
{
    /* My notes about fastfill:
     *
     * 1) Only the zbuffer is cleared.
     *
     * 2) The zbuffer must be micro-tiled and whole microtiles must be
     *    written. If microtiling is disabled, it locks up.
     *
     * 3) There is Z Mask RAM which contains a compressed zbuffer and
     *    it interacts with fastfill. We should figure out how to use it
     *    to get more performance.
     *    This is what we know about the Z Mask:
     *
     *       Each dword of the Z Mask contains compression information
     *       for 16 4x4 pixel blocks, that is 2 bits for each block.
     *       On chips with 2 Z pipes, every other dword maps to a different
     *       pipe.
     *
     * 4) ZB_DEPTHCLEARVALUE is used to clear the zbuffer and the Z Mask must
     *    be equal to 0. (clear the Z Mask RAM with zeros)
     *
     * 5) For 16-bit zbuffer, compression causes a hung with one or
     *    two samples and should not be used.
     *
     * 6) FORCE_COMPRESSED_STENCIL_VALUE should be enabled for stencil clears
     *    to avoid needless decompression.
     *
     * 7) Fastfill must not be used if reading of compressed Z data is disabled
     *    and writing of compressed Z data is enabled (RD/WR_COMP_ENABLE),
     *    i.e. it cannot be used to compress the zbuffer.
     *
     * 8) ZB_CB_CLEAR does not interact with fastfill in any way.
     *
     * - Marek
     */

    struct r300_context* r300 = r300_context(pipe);
    struct pipe_framebuffer_state *fb =
        (struct pipe_framebuffer_state*)r300->fb_state.state;
    struct r300_hyperz_state *hyperz =
        (struct r300_hyperz_state*)r300->hyperz_state.state;
    struct r300_texture *zstex =
            fb->zsbuf ? r300_texture(fb->zsbuf->texture) : NULL;
    uint32_t width = fb->width;
    uint32_t height = fb->height;
    boolean can_hyperz = r300->rws->get_value(r300->rws, R300_CAN_HYPERZ);
    uint32_t hyperz_dcv = hyperz->zb_depthclearvalue;

    /* Enable fast Z clear.
     * The zbuffer must be in micro-tiled mode, otherwise it locks up. */
    if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && can_hyperz) {
        hyperz_dcv = hyperz->zb_depthclearvalue =
            r300_depth_clear_value(fb->zsbuf->format, depth, stencil);

        r300_mark_fb_state_dirty(r300, R300_CHANGED_ZCLEAR_FLAG);
        if (zstex->zmask_mem[fb->zsbuf->u.tex.level]) {
            r300_mark_atom_dirty(r300, &r300->zmask_clear);
            buffers &= ~PIPE_CLEAR_DEPTHSTENCIL;
        }
        if (zstex->hiz_mem[fb->zsbuf->u.tex.level])
            r300_mark_atom_dirty(r300, &r300->hiz_clear);
    }

    /* Enable CBZB clear. */
    if (r300_cbzb_clear_allowed(r300, buffers)) {
        struct r300_surface *surf = r300_surface(fb->cbufs[0]);

        hyperz->zb_depthclearvalue =
                r300_depth_clear_cb_value(surf->base.format, rgba);

        width = surf->cbzb_width;
        height = surf->cbzb_height;

        r300->cbzb_clear = TRUE;
        r300_mark_fb_state_dirty(r300, R300_CHANGED_CBZB_FLAG);
    }

    /* Clear. */
    if (buffers) {
        /* Clear using the blitter. */
        r300_blitter_begin(r300, R300_CLEAR);
        util_blitter_clear(r300->blitter,
                           width,
                           height,
                           fb->nr_cbufs,
                           buffers, rgba, depth, stencil);
        r300_blitter_end(r300);
    } else if (r300->zmask_clear.dirty) {
        /* Just clear zmask and hiz now, this does not use a standard draw
         * procedure. */
        unsigned dwords;

        /* Calculate zmask_clear and hiz_clear atom sizes. */
        r300_update_hyperz_state(r300);
        dwords = r300->zmask_clear.size +
                 (r300->hiz_clear.dirty ? r300->hiz_clear.size : 0) +
                 r300_get_num_cs_end_dwords(r300);

        /* Reserve CS space. */
        if (dwords > (R300_MAX_CMDBUF_DWORDS - r300->cs->cdw)) {
            r300->context.flush(&r300->context, 0, NULL);
        }

        /* Emit clear packets. */
        r300_emit_zmask_clear(r300, r300->zmask_clear.size,
                              r300->zmask_clear.state);
        r300->zmask_clear.dirty = FALSE;
        if (r300->hiz_clear.dirty) {
            r300_emit_hiz_clear(r300, r300->hiz_clear.size,
                                r300->hiz_clear.state);
            r300->hiz_clear.dirty = FALSE;
        }
    } else {
        assert(0);
    }

    /* Disable CBZB clear. */
    if (r300->cbzb_clear) {
        r300->cbzb_clear = FALSE;
        hyperz->zb_depthclearvalue = hyperz_dcv;
        r300_mark_fb_state_dirty(r300, R300_CHANGED_CBZB_FLAG);
    }

    /* Enable fastfill and/or hiz.
     *
     * If we cleared zmask/hiz, it's in use now. The Hyper-Z state update
     * looks if zmask/hiz is in use and enables fastfill accordingly. */
    if (zstex &&
        (zstex->zmask_in_use[fb->zsbuf->u.tex.level] ||
         zstex->hiz_in_use[fb->zsbuf->u.tex.level])) {
        r300_mark_atom_dirty(r300, &r300->hyperz_state);
    }
}
Ejemplo n.º 7
0
struct pipe_transfer*
r300_texture_get_transfer(struct pipe_context *ctx,
			  struct pipe_resource *texture,
			  struct pipe_subresource sr,
			  unsigned usage,
			  const struct pipe_box *box)
{
    struct r300_context *r300 = r300_context(ctx);
    struct r300_texture *tex = r300_texture(texture);
    struct r300_transfer *trans;
    struct pipe_resource base;
    boolean referenced_cs, referenced_hw, blittable;

    referenced_cs =
        r300->rws->cs_is_buffer_referenced(r300->cs,
                                           tex->buffer, R300_REF_CS);
    if (referenced_cs) {
        referenced_hw = TRUE;
    } else {
        referenced_hw =
            r300->rws->cs_is_buffer_referenced(r300->cs,
                                               tex->buffer, R300_REF_HW);
    }

    blittable = ctx->screen->is_format_supported(
            ctx->screen, texture->format, texture->target, 0,
            PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET, 0);

    trans = CALLOC_STRUCT(r300_transfer);
    if (trans) {
        /* Initialize the transfer object. */
        pipe_resource_reference(&trans->transfer.resource, texture);
        trans->transfer.sr = sr;
        trans->transfer.usage = usage;
        trans->transfer.box = *box;

        /* If the texture is tiled, we must create a temporary detiled texture
         * for this transfer.
         * Also make write transfers pipelined. */
        if (tex->desc.microtile || tex->desc.macrotile[sr.level] ||
            ((referenced_hw & !(usage & PIPE_TRANSFER_READ)) && blittable)) {
            base.target = PIPE_TEXTURE_2D;
            base.format = texture->format;
            base.width0 = box->width;
            base.height0 = box->height;
            base.depth0 = 0;
            base.last_level = 0;
            base.nr_samples = 0;
            base.usage = PIPE_USAGE_DYNAMIC;
            base.bind = 0;
	    base.flags = R300_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) {
                base.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) {
                base.bind |= PIPE_BIND_SAMPLER_VIEW;
            }

            /* Create the temporary texture. */
            trans->linear_texture = r300_texture(
               ctx->screen->resource_create(ctx->screen,
                                            &base));

            if (!trans->linear_texture) {
                /* Oh crap, the thing can't create the texture.
                 * Let's flush and try again. */
                ctx->flush(ctx, 0, NULL);

                trans->linear_texture = r300_texture(
                   ctx->screen->resource_create(ctx->screen,
                                                &base));

                if (!trans->linear_texture) {
                    /* For linear textures, it's safe to fallback to
                     * an unpipelined transfer. */
                    if (!tex->desc.microtile && !tex->desc.macrotile[sr.level]) {
                        goto unpipelined;
                    }

                    /* Otherwise, go to hell. */
                    fprintf(stderr,
                        "r300: Failed to create a transfer object, praise.\n");
                    FREE(trans);
                    return NULL;
                }
            }

            assert(!trans->linear_texture->desc.microtile &&
                   !trans->linear_texture->desc.macrotile[0]);

            /* Set the stride.
	     *
	     * Even though we are using an internal texture for this,
	     * the transfer sr, box and usage parameters still reflect
	     * the arguments received to get_transfer.  We just do the
	     * right thing internally.
	     */
            trans->transfer.stride =
                    trans->linear_texture->desc.stride_in_bytes[0];

            if (usage & PIPE_TRANSFER_READ) {
                /* We cannot map a tiled texture directly because the data is
                 * in a different order, therefore we do detiling using a blit. */
                r300_copy_from_tiled_texture(ctx, trans);

                /* Always referenced in the blit. */
                ctx->flush(ctx, 0, NULL);
            }
            return &trans->transfer;
        }

    unpipelined:
        /* Unpipelined transfer. */
        trans->transfer.stride = tex->desc.stride_in_bytes[sr.level];
        trans->offset = r300_texture_get_offset(&tex->desc,
                                                sr.level, box->z, sr.face);

        if (referenced_cs)
            ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL);
        return &trans->transfer;
    }
    return NULL;
}