panfrost: Move viewport desc emission out of panfrost_emit_for_draw()
[mesa.git] / src / gallium / drivers / panfrost / pan_cmdstream.c
1 /*
2 * Copyright (C) 2018 Alyssa Rosenzweig
3 * Copyright (C) 2020 Collabora Ltd.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25 #include "pan_allocate.h"
26 #include "pan_cmdstream.h"
27 #include "pan_context.h"
28 #include "pan_job.h"
29
30 static void
31 panfrost_mali_viewport_init(struct panfrost_context *ctx,
32 struct mali_viewport *mvp)
33 {
34 const struct pipe_viewport_state *vp = &ctx->pipe_viewport;
35
36 /* Clip bounds are encoded as floats. The viewport itself is encoded as
37 * (somewhat) asymmetric ints. */
38
39 const struct pipe_scissor_state *ss = &ctx->scissor;
40
41 memset(mvp, 0, sizeof(*mvp));
42
43 /* By default, do no viewport clipping, i.e. clip to (-inf, inf) in
44 * each direction. Clipping to the viewport in theory should work, but
45 * in practice causes issues when we're not explicitly trying to
46 * scissor */
47
48 *mvp = (struct mali_viewport) {
49 .clip_minx = -INFINITY,
50 .clip_miny = -INFINITY,
51 .clip_maxx = INFINITY,
52 .clip_maxy = INFINITY,
53 };
54
55 /* Always scissor to the viewport by default. */
56 float vp_minx = (int) (vp->translate[0] - fabsf(vp->scale[0]));
57 float vp_maxx = (int) (vp->translate[0] + fabsf(vp->scale[0]));
58
59 float vp_miny = (int) (vp->translate[1] - fabsf(vp->scale[1]));
60 float vp_maxy = (int) (vp->translate[1] + fabsf(vp->scale[1]));
61
62 float minz = (vp->translate[2] - fabsf(vp->scale[2]));
63 float maxz = (vp->translate[2] + fabsf(vp->scale[2]));
64
65 /* Apply the scissor test */
66
67 unsigned minx, miny, maxx, maxy;
68
69 if (ss && ctx->rasterizer && ctx->rasterizer->base.scissor) {
70 minx = MAX2(ss->minx, vp_minx);
71 miny = MAX2(ss->miny, vp_miny);
72 maxx = MIN2(ss->maxx, vp_maxx);
73 maxy = MIN2(ss->maxy, vp_maxy);
74 } else {
75 minx = vp_minx;
76 miny = vp_miny;
77 maxx = vp_maxx;
78 maxy = vp_maxy;
79 }
80
81 /* Hardware needs the min/max to be strictly ordered, so flip if we
82 * need to. The viewport transformation in the vertex shader will
83 * handle the negatives if we don't */
84
85 if (miny > maxy) {
86 unsigned temp = miny;
87 miny = maxy;
88 maxy = temp;
89 }
90
91 if (minx > maxx) {
92 unsigned temp = minx;
93 minx = maxx;
94 maxx = temp;
95 }
96
97 if (minz > maxz) {
98 float temp = minz;
99 minz = maxz;
100 maxz = temp;
101 }
102
103 /* Clamp to the framebuffer size as a last check */
104
105 minx = MIN2(ctx->pipe_framebuffer.width, minx);
106 maxx = MIN2(ctx->pipe_framebuffer.width, maxx);
107
108 miny = MIN2(ctx->pipe_framebuffer.height, miny);
109 maxy = MIN2(ctx->pipe_framebuffer.height, maxy);
110
111 /* Upload */
112
113 mvp->viewport0[0] = minx;
114 mvp->viewport1[0] = MALI_POSITIVE(maxx);
115
116 mvp->viewport0[1] = miny;
117 mvp->viewport1[1] = MALI_POSITIVE(maxy);
118
119 mvp->clip_minz = minz;
120 mvp->clip_maxz = maxz;
121 }
122
123 void
124 panfrost_emit_viewport(struct panfrost_batch *batch,
125 struct midgard_payload_vertex_tiler *tp)
126 {
127 struct panfrost_context *ctx = batch->ctx;
128 struct mali_viewport mvp;
129
130 panfrost_mali_viewport_init(batch->ctx, &mvp);
131
132 /* Update the job, unless we're doing wallpapering (whose lack of
133 * scissor we can ignore, since if we "miss" a tile of wallpaper, it'll
134 * just... be faster :) */
135
136 if (!ctx->wallpaper_batch)
137 panfrost_batch_union_scissor(batch, mvp.viewport0[0],
138 mvp.viewport0[1],
139 mvp.viewport1[0] + 1,
140 mvp.viewport1[1] + 1);
141
142 tp->postfix.viewport = panfrost_upload_transient(batch, &mvp,
143 sizeof(mvp));
144 }