postfix->shader = shader_ptr;
}
-static void
-panfrost_mali_viewport_init(struct panfrost_context *ctx,
- struct mali_viewport *mvp)
+void
+panfrost_emit_viewport(struct panfrost_batch *batch,
+ struct mali_vertex_tiler_postfix *tiler_postfix)
{
+ struct panfrost_context *ctx = batch->ctx;
const struct pipe_viewport_state *vp = &ctx->pipe_viewport;
-
- /* Clip bounds are encoded as floats. The viewport itself is encoded as
- * (somewhat) asymmetric ints. */
-
const struct pipe_scissor_state *ss = &ctx->scissor;
+ const struct pipe_rasterizer_state *rast = &ctx->rasterizer->base;
+ const struct pipe_framebuffer_state *fb = &ctx->pipe_framebuffer;
- memset(mvp, 0, sizeof(*mvp));
-
- /* By default, do no viewport clipping, i.e. clip to (-inf, inf) in
- * each direction. Clipping to the viewport in theory should work, but
- * in practice causes issues when we're not explicitly trying to
- * scissor */
-
- *mvp = (struct mali_viewport) {
- .clip_minx = -INFINITY,
- .clip_miny = -INFINITY,
- .clip_maxx = INFINITY,
- .clip_maxy = INFINITY,
- };
-
- /* Always scissor to the viewport by default. */
+ /* Derive min/max from translate/scale. Note since |x| >= 0 by
+ * definition, we have that -|x| <= |x| hence translate - |scale| <=
+ * translate + |scale|, so the ordering is correct here. */
float vp_minx = (int) (vp->translate[0] - fabsf(vp->scale[0]));
float vp_maxx = (int) (vp->translate[0] + fabsf(vp->scale[0]));
-
float vp_miny = (int) (vp->translate[1] - fabsf(vp->scale[1]));
float vp_maxy = (int) (vp->translate[1] + fabsf(vp->scale[1]));
-
float minz = (vp->translate[2] - fabsf(vp->scale[2]));
float maxz = (vp->translate[2] + fabsf(vp->scale[2]));
- /* Apply the scissor test */
+ /* Scissor to the intersection of viewport and to the scissor, clamped
+ * to the framebuffer */
- unsigned minx, miny, maxx, maxy;
+ unsigned minx = MIN2(fb->width, vp_minx);
+ unsigned maxx = MIN2(fb->width, vp_maxx);
+ unsigned miny = MIN2(fb->height, vp_miny);
+ unsigned maxy = MIN2(fb->height, vp_maxy);
- if (ss && ctx->rasterizer && ctx->rasterizer->base.scissor) {
- minx = MAX2(ss->minx, vp_minx);
- miny = MAX2(ss->miny, vp_miny);
- maxx = MIN2(ss->maxx, vp_maxx);
- maxy = MIN2(ss->maxy, vp_maxy);
- } else {
- minx = vp_minx;
- miny = vp_miny;
- maxx = vp_maxx;
- maxy = vp_maxy;
+ if (ss && rast && rast->scissor) {
+ minx = MAX2(ss->minx, minx);
+ miny = MAX2(ss->miny, miny);
+ maxx = MIN2(ss->maxx, maxx);
+ maxy = MIN2(ss->maxy, maxy);
}
- /* Hardware needs the min/max to be strictly ordered, so flip if we
- * need to. The viewport transformation in the vertex shader will
- * handle the negatives if we don't */
+ struct panfrost_transfer T = panfrost_pool_alloc(&batch->pool, MALI_VIEWPORT_LENGTH);
- if (miny > maxy) {
- unsigned temp = miny;
- miny = maxy;
- maxy = temp;
- }
+ pan_pack(T.cpu, VIEWPORT, cfg) {
+ cfg.scissor_minimum_x = minx;
+ cfg.scissor_minimum_y = miny;
+ cfg.scissor_maximum_x = maxx - 1;
+ cfg.scissor_maximum_y = maxy - 1;
- if (minx > maxx) {
- unsigned temp = minx;
- minx = maxx;
- maxx = temp;
+ cfg.minimum_z = rast->depth_clip_near ? minz : -INFINITY;
+ cfg.maximum_z = rast->depth_clip_far ? maxz : INFINITY;
}
- if (minz > maxz) {
- float temp = minz;
- minz = maxz;
- maxz = temp;
- }
-
- /* Clamp to the framebuffer size as a last check */
-
- minx = MIN2(ctx->pipe_framebuffer.width, minx);
- maxx = MIN2(ctx->pipe_framebuffer.width, maxx);
-
- miny = MIN2(ctx->pipe_framebuffer.height, miny);
- maxy = MIN2(ctx->pipe_framebuffer.height, maxy);
-
- /* Upload */
-
- mvp->viewport0[0] = minx;
- mvp->viewport1[0] = MALI_POSITIVE(maxx);
-
- mvp->viewport0[1] = miny;
- mvp->viewport1[1] = MALI_POSITIVE(maxy);
-
- bool clip_near = true;
- bool clip_far = true;
-
- if (ctx->rasterizer) {
- clip_near = ctx->rasterizer->base.depth_clip_near;
- clip_far = ctx->rasterizer->base.depth_clip_far;
- }
-
- mvp->clip_minz = clip_near ? minz : -INFINITY;
- mvp->clip_maxz = clip_far ? maxz : INFINITY;
-}
-
-void
-panfrost_emit_viewport(struct panfrost_batch *batch,
- struct mali_vertex_tiler_postfix *tiler_postfix)
-{
- struct panfrost_context *ctx = batch->ctx;
- struct mali_viewport mvp;
-
- panfrost_mali_viewport_init(batch->ctx, &mvp);
-
- /* Update the job, unless we're doing wallpapering (whose lack of
- * scissor we can ignore, since if we "miss" a tile of wallpaper, it'll
- * just... be faster :) */
-
- if (!ctx->wallpaper_batch)
- panfrost_batch_union_scissor(batch, mvp.viewport0[0],
- mvp.viewport0[1],
- mvp.viewport1[0] + 1,
- mvp.viewport1[1] + 1);
-
- tiler_postfix->viewport = panfrost_pool_upload(&batch->pool, &mvp,
- sizeof(mvp));
+ tiler_postfix->viewport = T.gpu;
+ panfrost_batch_union_scissor(batch, minx, miny, maxx, maxy);
}
static mali_ptr
} else
pandecode_msg("XXX: missing shader descriptor\n");
- if (p->viewport) {
- struct pandecode_mapped_memory *fmem = pandecode_find_mapped_gpu_mem_containing(p->viewport);
- struct mali_viewport *PANDECODE_PTR_VAR(f, fmem, p->viewport);
-
- pandecode_log("struct mali_viewport viewport_%"PRIx64"_%d%s = {\n", p->viewport, job_no, suffix);
- pandecode_indent++;
-
- pandecode_prop("clip_minx = %f", f->clip_minx);
- pandecode_prop("clip_miny = %f", f->clip_miny);
- pandecode_prop("clip_minz = %f", f->clip_minz);
- pandecode_prop("clip_maxx = %f", f->clip_maxx);
- pandecode_prop("clip_maxy = %f", f->clip_maxy);
- pandecode_prop("clip_maxz = %f", f->clip_maxz);
-
- /* Only the higher coordinates are MALI_POSITIVE scaled */
-
- pandecode_prop("viewport0 = { %d, %d }",
- f->viewport0[0], f->viewport0[1]);
-
- pandecode_prop("viewport1 = { MALI_POSITIVE(%d), MALI_POSITIVE(%d) }",
- f->viewport1[0] + 1, f->viewport1[1] + 1);
-
- pandecode_indent--;
- pandecode_log("};\n");
- }
+ if (p->viewport)
+ DUMP_ADDR("Viewport", VIEWPORT, p->viewport, 1);
unsigned max_attr_index = 0;
unsigned width = u_minify(image->width0, image->first_level);
unsigned height = u_minify(image->height0, image->first_level);
- struct mali_viewport viewport = {
- .clip_minx = -INFINITY,
- .clip_miny = -INFINITY,
- .clip_maxx = INFINITY,
- .clip_maxy = INFINITY,
- .clip_minz = 0.0,
- .clip_maxz = 1.0,
-
- .viewport0 = { 0, 0 },
- .viewport1 = { MALI_POSITIVE(width), MALI_POSITIVE(height) }
- };
+ struct panfrost_transfer viewport = panfrost_pool_alloc(pool, MALI_VIEWPORT_LENGTH);
+
+ pan_pack(viewport.cpu, VIEWPORT, cfg) {
+ cfg.scissor_maximum_x = width - 1; /* Inclusive */
+ cfg.scissor_maximum_y = height - 1;
+ }
union mali_attr varying = {
.elements = coordinates | MALI_ATTR_LINEAR,
.shader = shader_meta_t.gpu,
.varyings = panfrost_pool_upload(pool, &varying, sizeof(varying)),
.varying_meta = panfrost_pool_upload(pool, &varying_meta, sizeof(varying_meta)),
- .viewport = panfrost_pool_upload(pool, &viewport, sizeof(viewport)),
+ .viewport = viewport.gpu,
.shared_memory = fbd
}
};