Ejemplo n.º 1
0
unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format,
                                   const unsigned char *swizzle_view,
                                   boolean dxtc_swizzle)
{
    unsigned i;
    unsigned char swizzle[4];
    unsigned result = 0;
    const uint32_t swizzle_shift[4] = {
        R300_TX_FORMAT_R_SHIFT,
        R300_TX_FORMAT_G_SHIFT,
        R300_TX_FORMAT_B_SHIFT,
        R300_TX_FORMAT_A_SHIFT
    };
    uint32_t swizzle_bit[4] = {
        dxtc_swizzle ? R300_TX_FORMAT_Z : R300_TX_FORMAT_X,
        R300_TX_FORMAT_Y,
        dxtc_swizzle ? R300_TX_FORMAT_X : R300_TX_FORMAT_Z,
        R300_TX_FORMAT_W
    };

    if (swizzle_view) {
        /* Combine two sets of swizzles. */
        util_format_compose_swizzles(swizzle_format, swizzle_view, swizzle);
    } else {
        memcpy(swizzle, swizzle_format, 4);
    }

    /* Get swizzle. */
    for (i = 0; i < 4; i++) {
        switch (swizzle[i]) {
            case UTIL_FORMAT_SWIZZLE_Y:
                result |= swizzle_bit[1] << swizzle_shift[i];
                break;
            case UTIL_FORMAT_SWIZZLE_Z:
                result |= swizzle_bit[2] << swizzle_shift[i];
                break;
            case UTIL_FORMAT_SWIZZLE_W:
                result |= swizzle_bit[3] << swizzle_shift[i];
                break;
            case UTIL_FORMAT_SWIZZLE_0:
                result |= R300_TX_FORMAT_ZERO << swizzle_shift[i];
                break;
            case UTIL_FORMAT_SWIZZLE_1:
                result |= R300_TX_FORMAT_ONE << swizzle_shift[i];
                break;
            default: /* UTIL_FORMAT_SWIZZLE_X */
                result |= swizzle_bit[0] << swizzle_shift[i];
        }
    }
    return result;
}
Ejemplo n.º 2
0
uint32_t
fd4_tex_swiz(enum pipe_format format, unsigned swizzle_r, unsigned swizzle_g,
		unsigned swizzle_b, unsigned swizzle_a)
{
	const struct util_format_description *desc =
			util_format_description(format);
	unsigned char swiz[4] = {
			swizzle_r, swizzle_g, swizzle_b, swizzle_a,
	}, rswiz[4];

	util_format_compose_swizzles(desc->swizzle, swiz, rswiz);

	return A4XX_TEX_CONST_0_SWIZ_X(tex_swiz(rswiz[0])) |
			A4XX_TEX_CONST_0_SWIZ_Y(tex_swiz(rswiz[1])) |
			A4XX_TEX_CONST_0_SWIZ_Z(tex_swiz(rswiz[2])) |
			A4XX_TEX_CONST_0_SWIZ_W(tex_swiz(rswiz[3]));
}
static void *
vc5_vertex_state_create(struct pipe_context *pctx, unsigned num_elements,
                        const struct pipe_vertex_element *elements)
{
        struct vc5_context *vc5 = vc5_context(pctx);
        struct vc5_vertex_stateobj *so = CALLOC_STRUCT(vc5_vertex_stateobj);

        if (!so)
                return NULL;

        memcpy(so->pipe, elements, sizeof(*elements) * num_elements);
        so->num_elements = num_elements;

        for (int i = 0; i < so->num_elements; i++) {
                const struct pipe_vertex_element *elem = &elements[i];
                const struct util_format_description *desc =
                        util_format_description(elem->src_format);
                uint32_t r_size = desc->channel[0].size;

                struct V3D33_GL_SHADER_STATE_ATTRIBUTE_RECORD attr_unpacked = {
                        /* vec_size == 0 means 4 */
                        .vec_size = desc->nr_channels & 3,
                        .signed_int_type = (desc->channel[0].type ==
                                            UTIL_FORMAT_TYPE_SIGNED),

                        .normalized_int_type = desc->channel[0].normalized,
                        .read_as_int_uint = desc->channel[0].pure_integer,
                        .instance_divisor = elem->instance_divisor,
                };

                switch (desc->channel[0].type) {
                case UTIL_FORMAT_TYPE_FLOAT:
                        if (r_size == 32) {
                                attr_unpacked.type = ATTRIBUTE_FLOAT;
                        } else {
                                assert(r_size == 16);
                                attr_unpacked.type = ATTRIBUTE_HALF_FLOAT;
                        }
                        break;

                case UTIL_FORMAT_TYPE_SIGNED:
                case UTIL_FORMAT_TYPE_UNSIGNED:
                        switch (r_size) {
                        case 32:
                                attr_unpacked.type = ATTRIBUTE_INT;
                                break;
                        case 16:
                                attr_unpacked.type = ATTRIBUTE_SHORT;
                                break;
                        case 10:
                                attr_unpacked.type = ATTRIBUTE_INT2_10_10_10;
                                break;
                        case 8:
                                attr_unpacked.type = ATTRIBUTE_BYTE;
                                break;
                        default:
                                fprintf(stderr,
                                        "format %s unsupported\n",
                                        desc->name);
                                attr_unpacked.type = ATTRIBUTE_BYTE;
                                abort();
                        }
                        break;

                default:
                        fprintf(stderr,
                                "format %s unsupported\n",
                                desc->name);
                        abort();
                }

                const uint32_t size =
                        cl_packet_length(GL_SHADER_STATE_ATTRIBUTE_RECORD);
                V3D33_GL_SHADER_STATE_ATTRIBUTE_RECORD_pack(NULL,
                                                            (uint8_t *)&so->attrs[i * size],
                                                            &attr_unpacked);
        }

        /* Set up the default attribute values in case any of the vertex
         * elements use them.
         */
        so->default_attribute_values = vc5_bo_alloc(vc5->screen,
                                                    VC5_MAX_ATTRIBUTES *
                                                    4 * sizeof(float),
                                                    "default attributes");
        uint32_t *attrs = vc5_bo_map(so->default_attribute_values);
        for (int i = 0; i < VC5_MAX_ATTRIBUTES; i++) {
                attrs[i * 4 + 0] = 0;
                attrs[i * 4 + 1] = 0;
                attrs[i * 4 + 2] = 0;
                if (i < so->num_elements &&
                    util_format_is_pure_integer(so->pipe[i].src_format)) {
                        attrs[i * 4 + 3] = 1;
                } else {
                        attrs[i * 4 + 3] = fui(1.0);
                }
        }

        return so;
}

static void
vc5_vertex_state_bind(struct pipe_context *pctx, void *hwcso)
{
        struct vc5_context *vc5 = vc5_context(pctx);
        vc5->vtx = hwcso;
        vc5->dirty |= VC5_DIRTY_VTXSTATE;
}

static void
vc5_set_constant_buffer(struct pipe_context *pctx, uint shader, uint index,
                        const struct pipe_constant_buffer *cb)
{
        struct vc5_context *vc5 = vc5_context(pctx);
        struct vc5_constbuf_stateobj *so = &vc5->constbuf[shader];

        util_copy_constant_buffer(&so->cb[index], cb);

        /* Note that the state tracker can unbind constant buffers by
         * passing NULL here.
         */
        if (unlikely(!cb)) {
                so->enabled_mask &= ~(1 << index);
                so->dirty_mask &= ~(1 << index);
                return;
        }

        so->enabled_mask |= 1 << index;
        so->dirty_mask |= 1 << index;
        vc5->dirty |= VC5_DIRTY_CONSTBUF;
}

static void
vc5_set_framebuffer_state(struct pipe_context *pctx,
                          const struct pipe_framebuffer_state *framebuffer)
{
        struct vc5_context *vc5 = vc5_context(pctx);
        struct pipe_framebuffer_state *cso = &vc5->framebuffer;
        unsigned i;

        vc5->job = NULL;

        for (i = 0; i < framebuffer->nr_cbufs; i++)
                pipe_surface_reference(&cso->cbufs[i], framebuffer->cbufs[i]);
        for (; i < vc5->framebuffer.nr_cbufs; i++)
                pipe_surface_reference(&cso->cbufs[i], NULL);

        cso->nr_cbufs = framebuffer->nr_cbufs;

        pipe_surface_reference(&cso->zsbuf, framebuffer->zsbuf);

        cso->width = framebuffer->width;
        cso->height = framebuffer->height;

        vc5->dirty |= VC5_DIRTY_FRAMEBUFFER;
}

static struct vc5_texture_stateobj *
vc5_get_stage_tex(struct vc5_context *vc5, enum pipe_shader_type shader)
{
        switch (shader) {
        case PIPE_SHADER_FRAGMENT:
                vc5->dirty |= VC5_DIRTY_FRAGTEX;
                return &vc5->fragtex;
                break;
        case PIPE_SHADER_VERTEX:
                vc5->dirty |= VC5_DIRTY_VERTTEX;
                return &vc5->verttex;
                break;
        default:
                fprintf(stderr, "Unknown shader target %d\n", shader);
                abort();
        }
}

static uint32_t translate_wrap(uint32_t pipe_wrap, bool using_nearest)
{
        switch (pipe_wrap) {
        case PIPE_TEX_WRAP_REPEAT:
                return 0;
        case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
                return 1;
        case PIPE_TEX_WRAP_MIRROR_REPEAT:
                return 2;
        case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
                return 3;
        case PIPE_TEX_WRAP_CLAMP:
                return (using_nearest ? 1 : 3);
        default:
                unreachable("Unknown wrap mode");
        }
}


static void *
vc5_create_sampler_state(struct pipe_context *pctx,
                         const struct pipe_sampler_state *cso)
{
        struct vc5_sampler_state *so = CALLOC_STRUCT(vc5_sampler_state);

        if (!so)
                return NULL;

        memcpy(so, cso, sizeof(*cso));

        bool either_nearest =
                (cso->mag_img_filter == PIPE_TEX_MIPFILTER_NEAREST ||
                 cso->min_img_filter == PIPE_TEX_MIPFILTER_NEAREST);

        struct V3D33_TEXTURE_UNIFORM_PARAMETER_0_CFG_MODE1 p0_unpacked = {
                .s_wrap_mode = translate_wrap(cso->wrap_s, either_nearest),
                .t_wrap_mode = translate_wrap(cso->wrap_t, either_nearest),
                .r_wrap_mode = translate_wrap(cso->wrap_r, either_nearest),
        };
        V3D33_TEXTURE_UNIFORM_PARAMETER_0_CFG_MODE1_pack(NULL,
                                                         (uint8_t *)&so->p0,
                                                         &p0_unpacked);

        struct V3D33_TEXTURE_SHADER_STATE state_unpacked = {
                cl_packet_header(TEXTURE_SHADER_STATE),

                .min_level_of_detail = MAX2(cso->min_lod, 0.0),
                .depth_compare_function = cso->compare_func,
                .fixed_bias = cso->lod_bias,
        };
        STATIC_ASSERT(ARRAY_SIZE(so->texture_shader_state) ==
                      cl_packet_length(TEXTURE_SHADER_STATE));
        cl_packet_pack(TEXTURE_SHADER_STATE)(NULL, so->texture_shader_state,
                                             &state_unpacked);

        return so;
}

static void
vc5_sampler_states_bind(struct pipe_context *pctx,
                        enum pipe_shader_type shader, unsigned start,
                        unsigned nr, void **hwcso)
{
        struct vc5_context *vc5 = vc5_context(pctx);
        struct vc5_texture_stateobj *stage_tex = vc5_get_stage_tex(vc5, shader);

        assert(start == 0);
        unsigned i;
        unsigned new_nr = 0;

        for (i = 0; i < nr; i++) {
                if (hwcso[i])
                        new_nr = i + 1;
                stage_tex->samplers[i] = hwcso[i];
        }

        for (; i < stage_tex->num_samplers; i++) {
                stage_tex->samplers[i] = NULL;
        }

        stage_tex->num_samplers = new_nr;
}

static uint32_t
translate_swizzle(unsigned char pipe_swizzle)
{
        switch (pipe_swizzle) {
        case PIPE_SWIZZLE_0:
                return 0;
        case PIPE_SWIZZLE_1:
                return 1;
        case PIPE_SWIZZLE_X:
        case PIPE_SWIZZLE_Y:
        case PIPE_SWIZZLE_Z:
        case PIPE_SWIZZLE_W:
                return 2 + pipe_swizzle;
        default:
                unreachable("unknown swizzle");
        }
}

static struct pipe_sampler_view *
vc5_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc,
                        const struct pipe_sampler_view *cso)
{
        struct vc5_sampler_view *so = CALLOC_STRUCT(vc5_sampler_view);
        struct vc5_resource *rsc = vc5_resource(prsc);

        if (!so)
                return NULL;

        so->base = *cso;

        pipe_reference(NULL, &prsc->reference);

        struct V3D33_TEXTURE_UNIFORM_PARAMETER_1_CFG_MODE1 unpacked = {
        };

        unpacked.return_word_0_of_texture_data = true;
        if (vc5_get_tex_return_size(cso->format) == 16) {
                unpacked.return_word_1_of_texture_data = true;
        } else {
                int chans = vc5_get_tex_return_channels(cso->format);

                if (chans > 1)
                        unpacked.return_word_1_of_texture_data = true;
                if (chans > 2)
                        unpacked.return_word_2_of_texture_data = true;
                if (chans > 3)
                        unpacked.return_word_3_of_texture_data = true;
        }

        V3D33_TEXTURE_UNIFORM_PARAMETER_1_CFG_MODE1_pack(NULL,
                                                         (uint8_t *)&so->p1,
                                                         &unpacked);

        /* Compute the sampler view's swizzle up front. This will be plugged
         * into either the sampler (for 16-bit returns) or the shader's
         * texture key (for 32)
         */
        uint8_t view_swizzle[4] = {
                cso->swizzle_r,
                cso->swizzle_g,
                cso->swizzle_b,
                cso->swizzle_a
        };
        const uint8_t *fmt_swizzle = vc5_get_format_swizzle(so->base.format);
        util_format_compose_swizzles(fmt_swizzle, view_swizzle, so->swizzle);

        so->base.texture = prsc;
        so->base.reference.count = 1;
        so->base.context = pctx;

        struct V3D33_TEXTURE_SHADER_STATE state_unpacked = {
                cl_packet_header(TEXTURE_SHADER_STATE),

                .image_width = prsc->width0,
                .image_height = prsc->height0,
                .image_depth = prsc->depth0,

                .texture_type = rsc->tex_format,
                .srgb = util_format_is_srgb(cso->format),

                .base_level = cso->u.tex.first_level,
                .array_stride_64_byte_aligned = rsc->cube_map_stride / 64,
        };

        /* Note: Contrary to the docs, the swizzle still applies even
         * if the return size is 32.  It's just that you probably want
         * to swizzle in the shader, because you need the Y/Z/W
         * channels to be defined.
         */
        if (vc5_get_tex_return_size(cso->format) != 32) {
                state_unpacked.swizzle_r = translate_swizzle(so->swizzle[0]);
                state_unpacked.swizzle_g = translate_swizzle(so->swizzle[1]);
                state_unpacked.swizzle_b = translate_swizzle(so->swizzle[2]);
                state_unpacked.swizzle_a = translate_swizzle(so->swizzle[3]);
        } else {
                state_unpacked.swizzle_r = translate_swizzle(PIPE_SWIZZLE_X);
                state_unpacked.swizzle_g = translate_swizzle(PIPE_SWIZZLE_Y);
                state_unpacked.swizzle_b = translate_swizzle(PIPE_SWIZZLE_Z);
                state_unpacked.swizzle_a = translate_swizzle(PIPE_SWIZZLE_W);
        }

        /* XXX: While we need to use this flag to enable tiled
         * resource sharing (even a small shared buffer should be UIF,
         * not UBLINEAR or raster), this is also at the moment
         * patching up the fact that our resource layout's decisions
         * about XOR don't quite match the HW's.
         */
        switch (rsc->slices[0].tiling) {
        case VC5_TILING_UIF_NO_XOR:
        case VC5_TILING_UIF_XOR:
                state_unpacked.level_0_is_strictly_uif = true;
                state_unpacked.level_0_xor_enable = false;
                break;
        default:
                break;
        }

        STATIC_ASSERT(ARRAY_SIZE(so->texture_shader_state) ==
                      cl_packet_length(TEXTURE_SHADER_STATE));
        cl_packet_pack(TEXTURE_SHADER_STATE)(NULL, so->texture_shader_state,
                                             &state_unpacked);

        return &so->base;
}

static void
vc5_sampler_view_destroy(struct pipe_context *pctx,
                         struct pipe_sampler_view *view)
{
        pipe_resource_reference(&view->texture, NULL);
        free(view);
}

static void
vc5_set_sampler_views(struct pipe_context *pctx,
                      enum pipe_shader_type shader,
                      unsigned start, unsigned nr,
                      struct pipe_sampler_view **views)
{
        struct vc5_context *vc5 = vc5_context(pctx);
        struct vc5_texture_stateobj *stage_tex = vc5_get_stage_tex(vc5, shader);
        unsigned i;
        unsigned new_nr = 0;

        assert(start == 0);

        for (i = 0; i < nr; i++) {
                if (views[i])
                        new_nr = i + 1;
                pipe_sampler_view_reference(&stage_tex->textures[i], views[i]);
        }

        for (; i < stage_tex->num_textures; i++) {
                pipe_sampler_view_reference(&stage_tex->textures[i], NULL);
        }

        stage_tex->num_textures = new_nr;
}

static struct pipe_stream_output_target *
vc5_create_stream_output_target(struct pipe_context *pctx,
                                struct pipe_resource *prsc,
                                unsigned buffer_offset,
                                unsigned buffer_size)
{
        struct pipe_stream_output_target *target;

        target = CALLOC_STRUCT(pipe_stream_output_target);
        if (!target)
                return NULL;

        pipe_reference_init(&target->reference, 1);
        pipe_resource_reference(&target->buffer, prsc);

        target->context = pctx;
        target->buffer_offset = buffer_offset;
        target->buffer_size = buffer_size;

        return target;
}

static void
vc5_stream_output_target_destroy(struct pipe_context *pctx,
                                 struct pipe_stream_output_target *target)
{
        pipe_resource_reference(&target->buffer, NULL);
        free(target);
}
Ejemplo n.º 4
0
static void get_external_state(
    struct r300_context* r300,
    struct r300_fragment_program_external_state* state)
{
    struct r300_textures_state *texstate = r300->textures_state.state;
    struct r300_rs_state *rs = r300->rs_state.state;
    unsigned i;

    state->frag_clamp = rs ? rs->rs.clamp_fragment_color : 0;

    for (i = 0; i < texstate->sampler_state_count; i++) {
        struct r300_sampler_state *s = texstate->sampler_states[i];
        struct r300_sampler_view *v = texstate->sampler_views[i];
        struct r300_resource *t;

        if (!s || !v) {
            continue;
        }

        t = r300_resource(v->base.texture);

        if (s->state.compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
            state->unit[i].compare_mode_enabled = 1;

            /* Fortunately, no need to translate this. */
            state->unit[i].texture_compare_func = s->state.compare_func;
        }

        state->unit[i].non_normalized_coords = !s->state.normalized_coords;
        state->unit[i].convert_unorm_to_snorm =
                v->base.format == PIPE_FORMAT_RGTC1_SNORM ||
                v->base.format == PIPE_FORMAT_LATC1_SNORM;

        /* Pass texture swizzling to the compiler, some lowering passes need it. */
        if (v->base.format == PIPE_FORMAT_RGTC1_SNORM ||
            v->base.format == PIPE_FORMAT_LATC1_SNORM) {
            unsigned char swizzle[4];

            util_format_compose_swizzles(
                            util_format_description(v->base.format)->swizzle,
                            v->swizzle,
                            swizzle);

            state->unit[i].texture_swizzle =
                    RC_MAKE_SWIZZLE(swizzle[0], swizzle[1],
                                    swizzle[2], swizzle[3]);
        } else if (state->unit[i].compare_mode_enabled) {
            state->unit[i].texture_swizzle =
                RC_MAKE_SWIZZLE(v->swizzle[0], v->swizzle[1],
                                v->swizzle[2], v->swizzle[3]);
        }

        /* XXX this should probably take into account STR, not just S. */
        if (t->tex.is_npot) {
            switch (s->state.wrap_s) {
            case PIPE_TEX_WRAP_REPEAT:
                state->unit[i].wrap_mode = RC_WRAP_REPEAT;
                break;

            case PIPE_TEX_WRAP_MIRROR_REPEAT:
                state->unit[i].wrap_mode = RC_WRAP_MIRRORED_REPEAT;
                break;

            case PIPE_TEX_WRAP_MIRROR_CLAMP:
            case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
            case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
                state->unit[i].wrap_mode = RC_WRAP_MIRRORED_CLAMP;
                break;

            default:
                state->unit[i].wrap_mode = RC_WRAP_NONE;
            }

            if (t->b.b.b.target == PIPE_TEXTURE_3D)
                state->unit[i].clamp_and_scale_before_fetch = TRUE;
        }
    }
}