• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2011-2013 Luc Verhaegen <libv@skynet.be>
3  * Copyright (c) 2017-2019 Lima Project
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, sub license,
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
13  * next paragraph) shall be included in all copies or substantial portions
14  * of the 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 NON-INFRINGEMENT. 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
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  *
24  */
25 
26 #include "util/format/u_format.h"
27 #include "util/u_debug.h"
28 #include "util/u_draw.h"
29 #include "util/half_float.h"
30 #include "util/u_helpers.h"
31 #include "util/u_inlines.h"
32 #include "util/u_pack_color.h"
33 #include "util/u_split_draw.h"
34 #include "util/u_upload_mgr.h"
35 #include "util/u_prim.h"
36 #include "util/u_vbuf.h"
37 #include "util/hash_table.h"
38 
39 #include "lima_context.h"
40 #include "lima_screen.h"
41 #include "lima_resource.h"
42 #include "lima_program.h"
43 #include "lima_bo.h"
44 #include "lima_job.h"
45 #include "lima_texture.h"
46 #include "lima_util.h"
47 #include "lima_gpu.h"
48 
49 #include "pan_minmax_cache.h"
50 
51 #include <drm-uapi/lima_drm.h>
52 
53 static void
lima_clip_scissor_to_viewport(struct lima_context * ctx)54 lima_clip_scissor_to_viewport(struct lima_context *ctx)
55 {
56    struct lima_context_framebuffer *fb = &ctx->framebuffer;
57    struct pipe_scissor_state *cscissor = &ctx->clipped_scissor;
58    int viewport_left, viewport_right, viewport_bottom, viewport_top;
59 
60    if (ctx->rasterizer && ctx->rasterizer->base.scissor) {
61       struct pipe_scissor_state *scissor = &ctx->scissor;
62       cscissor->minx = scissor->minx;
63       cscissor->maxx = scissor->maxx;
64       cscissor->miny = scissor->miny;
65       cscissor->maxy = scissor->maxy;
66    } else {
67       cscissor->minx = 0;
68       cscissor->maxx = fb->base.width;
69       cscissor->miny = 0;
70       cscissor->maxy = fb->base.height;
71    }
72 
73    viewport_left = MAX2(ctx->viewport.left, 0);
74    cscissor->minx = MAX2(cscissor->minx, viewport_left);
75    viewport_right = MIN2(MAX2(ctx->viewport.right, 0), fb->base.width);
76    cscissor->maxx = MIN2(cscissor->maxx, viewport_right);
77    if (cscissor->minx > cscissor->maxx)
78       cscissor->minx = cscissor->maxx;
79 
80    viewport_bottom = MAX2(ctx->viewport.bottom, 0);
81    cscissor->miny = MAX2(cscissor->miny, viewport_bottom);
82    viewport_top = MIN2(MAX2(ctx->viewport.top, 0), fb->base.height);
83    cscissor->maxy = MIN2(cscissor->maxy, viewport_top);
84    if (cscissor->miny > cscissor->maxy)
85       cscissor->miny = cscissor->maxy;
86 }
87 
88 static bool
lima_is_scissor_zero(struct lima_context * ctx)89 lima_is_scissor_zero(struct lima_context *ctx)
90 {
91    struct pipe_scissor_state *cscissor = &ctx->clipped_scissor;
92 
93    return cscissor->minx == cscissor->maxx || cscissor->miny == cscissor->maxy;
94 }
95 
96 static void
lima_update_job_wb(struct lima_context * ctx,unsigned buffers)97 lima_update_job_wb(struct lima_context *ctx, unsigned buffers)
98 {
99    struct lima_job *job = lima_job_get(ctx);
100    struct lima_context_framebuffer *fb = &ctx->framebuffer;
101 
102    /* add to job when the buffer is dirty and resolve is clear (not added before) */
103    if (fb->base.nr_cbufs && (buffers & PIPE_CLEAR_COLOR0) &&
104        !(job->resolve & PIPE_CLEAR_COLOR0)) {
105       struct lima_resource *res = lima_resource(fb->base.cbufs[0]->texture);
106       lima_flush_job_accessing_bo(ctx, res->bo, true);
107       _mesa_hash_table_insert(ctx->write_jobs, &res->base, job);
108       lima_job_add_bo(job, LIMA_PIPE_PP, res->bo, LIMA_SUBMIT_BO_WRITE);
109    }
110 
111    /* add to job when the buffer is dirty and resolve is clear (not added before) */
112    if (fb->base.zsbuf && (buffers & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) &&
113        !(job->resolve & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL))) {
114       struct lima_resource *res = lima_resource(fb->base.zsbuf->texture);
115       lima_flush_job_accessing_bo(ctx, res->bo, true);
116       _mesa_hash_table_insert(ctx->write_jobs, &res->base, job);
117       lima_job_add_bo(job, LIMA_PIPE_PP, res->bo, LIMA_SUBMIT_BO_WRITE);
118    }
119 
120    job->resolve |= buffers;
121 }
122 
123 static void
lima_damage_rect_union(struct pipe_scissor_state * rect,unsigned minx,unsigned maxx,unsigned miny,unsigned maxy)124 lima_damage_rect_union(struct pipe_scissor_state *rect,
125                        unsigned minx, unsigned maxx,
126                        unsigned miny, unsigned maxy)
127 {
128    rect->minx = MIN2(rect->minx, minx);
129    rect->miny = MIN2(rect->miny, miny);
130    rect->maxx = MAX2(rect->maxx, maxx);
131    rect->maxy = MAX2(rect->maxy, maxy);
132 }
133 
134 static void
lima_clear(struct pipe_context * pctx,unsigned buffers,const struct pipe_scissor_state * scissor_state,const union pipe_color_union * color,double depth,unsigned stencil)135 lima_clear(struct pipe_context *pctx, unsigned buffers, const struct pipe_scissor_state *scissor_state,
136            const union pipe_color_union *color, double depth, unsigned stencil)
137 {
138    struct lima_context *ctx = lima_context(pctx);
139    struct lima_job *job = lima_job_get(ctx);
140 
141    /* flush if this job already contains any draw, otherwise multi clear can be
142     * combined into a single job */
143    if (lima_job_has_draw_pending(job)) {
144       lima_do_job(job);
145       job = lima_job_get(ctx);
146    }
147 
148    lima_update_job_wb(ctx, buffers);
149 
150    /* no need to reload if cleared */
151    if (ctx->framebuffer.base.nr_cbufs && (buffers & PIPE_CLEAR_COLOR0)) {
152       struct lima_surface *surf = lima_surface(ctx->framebuffer.base.cbufs[0]);
153       surf->reload &= ~PIPE_CLEAR_COLOR0;
154    }
155 
156    struct lima_job_clear *clear = &job->clear;
157    clear->buffers = buffers;
158 
159    if (buffers & PIPE_CLEAR_COLOR0) {
160       clear->color_8pc =
161          ((uint32_t)float_to_ubyte(color->f[3]) << 24) |
162          ((uint32_t)float_to_ubyte(color->f[2]) << 16) |
163          ((uint32_t)float_to_ubyte(color->f[1]) << 8) |
164          float_to_ubyte(color->f[0]);
165 
166       clear->color_16pc =
167          ((uint64_t)float_to_ushort(color->f[3]) << 48) |
168          ((uint64_t)float_to_ushort(color->f[2]) << 32) |
169          ((uint64_t)float_to_ushort(color->f[1]) << 16) |
170          float_to_ushort(color->f[0]);
171    }
172 
173    struct lima_surface *zsbuf = lima_surface(ctx->framebuffer.base.zsbuf);
174 
175    if (buffers & PIPE_CLEAR_DEPTH) {
176       clear->depth = util_pack_z(PIPE_FORMAT_Z24X8_UNORM, depth);
177       if (zsbuf)
178          zsbuf->reload &= ~PIPE_CLEAR_DEPTH;
179    }
180 
181    if (buffers & PIPE_CLEAR_STENCIL) {
182       clear->stencil = stencil;
183       if (zsbuf)
184          zsbuf->reload &= ~PIPE_CLEAR_STENCIL;
185    }
186 
187    ctx->dirty |= LIMA_CONTEXT_DIRTY_CLEAR;
188 
189    lima_damage_rect_union(&job->damage_rect,
190                           0, ctx->framebuffer.base.width,
191                           0, ctx->framebuffer.base.height);
192 }
193 
194 enum lima_attrib_type {
195    LIMA_ATTRIB_FLOAT = 0x000,
196    LIMA_ATTRIB_I32   = 0x001,
197    LIMA_ATTRIB_U32   = 0x002,
198    LIMA_ATTRIB_FP16  = 0x003,
199    LIMA_ATTRIB_I16   = 0x004,
200    LIMA_ATTRIB_U16   = 0x005,
201    LIMA_ATTRIB_I8    = 0x006,
202    LIMA_ATTRIB_U8    = 0x007,
203    LIMA_ATTRIB_I8N   = 0x008,
204    LIMA_ATTRIB_U8N   = 0x009,
205    LIMA_ATTRIB_I16N  = 0x00A,
206    LIMA_ATTRIB_U16N  = 0x00B,
207    LIMA_ATTRIB_I32N  = 0x00D,
208    LIMA_ATTRIB_U32N  = 0x00E,
209    LIMA_ATTRIB_FIXED = 0x101
210 };
211 
212 static enum lima_attrib_type
lima_pipe_format_to_attrib_type(enum pipe_format format)213 lima_pipe_format_to_attrib_type(enum pipe_format format)
214 {
215    const struct util_format_description *desc = util_format_description(format);
216    int i = util_format_get_first_non_void_channel(format);
217    const struct util_format_channel_description *c = desc->channel + i;
218 
219    switch (c->type) {
220    case UTIL_FORMAT_TYPE_FLOAT:
221       if (c->size == 16)
222          return LIMA_ATTRIB_FP16;
223       else
224          return LIMA_ATTRIB_FLOAT;
225    case UTIL_FORMAT_TYPE_FIXED:
226       return LIMA_ATTRIB_FIXED;
227    case UTIL_FORMAT_TYPE_SIGNED:
228       if (c->size == 8) {
229          if (c->normalized)
230             return LIMA_ATTRIB_I8N;
231          else
232             return LIMA_ATTRIB_I8;
233       }
234       else if (c->size == 16) {
235          if (c->normalized)
236             return LIMA_ATTRIB_I16N;
237          else
238             return LIMA_ATTRIB_I16;
239       }
240       else if (c->size == 32) {
241          if (c->normalized)
242             return LIMA_ATTRIB_I32N;
243          else
244             return LIMA_ATTRIB_I32;
245       }
246       break;
247    case UTIL_FORMAT_TYPE_UNSIGNED:
248       if (c->size == 8) {
249          if (c->normalized)
250             return LIMA_ATTRIB_U8N;
251          else
252             return LIMA_ATTRIB_U8;
253       }
254       else if (c->size == 16) {
255          if (c->normalized)
256             return LIMA_ATTRIB_U16N;
257          else
258             return LIMA_ATTRIB_U16;
259       }
260       else if (c->size == 32) {
261          if (c->normalized)
262             return LIMA_ATTRIB_U32N;
263          else
264             return LIMA_ATTRIB_U32;
265       }
266       break;
267    }
268 
269    return LIMA_ATTRIB_FLOAT;
270 }
271 
272 static void
lima_pack_vs_cmd(struct lima_context * ctx,const struct pipe_draw_info * info,const struct pipe_draw_start_count_bias * draw)273 lima_pack_vs_cmd(struct lima_context *ctx, const struct pipe_draw_info *info,
274                  const struct pipe_draw_start_count_bias *draw)
275 {
276    struct lima_context_constant_buffer *ccb =
277       ctx->const_buffer + PIPE_SHADER_VERTEX;
278    struct lima_vs_compiled_shader *vs = ctx->vs;
279    struct lima_job *job = lima_job_get(ctx);
280 
281    VS_CMD_BEGIN(&job->vs_cmd_array, 24);
282 
283    if (!info->index_size) {
284       VS_CMD_ARRAYS_SEMAPHORE_BEGIN_1();
285       VS_CMD_ARRAYS_SEMAPHORE_BEGIN_2();
286    }
287    int uniform_size = MIN2(vs->state.uniform_size, ccb->size);
288 
289    int size = uniform_size + vs->state.constant_size + 32;
290    VS_CMD_UNIFORMS_ADDRESS(
291       lima_ctx_buff_va(ctx, lima_ctx_buff_gp_uniform),
292       align(size, 16));
293 
294    VS_CMD_SHADER_ADDRESS(ctx->vs->bo->va, ctx->vs->state.shader_size);
295    VS_CMD_SHADER_INFO(ctx->vs->state.prefetch, ctx->vs->state.shader_size);
296 
297    int num_outputs = ctx->vs->state.num_outputs;
298    int num_attributes = ctx->vertex_elements->num_elements;
299    VS_CMD_VARYING_ATTRIBUTE_COUNT(num_outputs, MAX2(1, num_attributes));
300 
301    VS_CMD_UNKNOWN1();
302 
303    VS_CMD_ATTRIBUTES_ADDRESS(
304       lima_ctx_buff_va(ctx, lima_ctx_buff_gp_attribute_info),
305       MAX2(1, num_attributes));
306 
307    VS_CMD_VARYINGS_ADDRESS(
308       lima_ctx_buff_va(ctx, lima_ctx_buff_gp_varying_info),
309       num_outputs);
310 
311    unsigned num = info->index_size ? (ctx->max_index - ctx->min_index + 1) : draw->count;
312    VS_CMD_DRAW(num, info->index_size);
313 
314    VS_CMD_UNKNOWN2();
315 
316    VS_CMD_ARRAYS_SEMAPHORE_END(info->index_size);
317 
318    VS_CMD_END();
319 }
320 
321 static void
lima_pack_plbu_cmd(struct lima_context * ctx,const struct pipe_draw_info * info,const struct pipe_draw_start_count_bias * draw)322 lima_pack_plbu_cmd(struct lima_context *ctx, const struct pipe_draw_info *info,
323                    const struct pipe_draw_start_count_bias *draw)
324 {
325    struct lima_vs_compiled_shader *vs = ctx->vs;
326    struct pipe_scissor_state *cscissor = &ctx->clipped_scissor;
327    struct lima_job *job = lima_job_get(ctx);
328    PLBU_CMD_BEGIN(&job->plbu_cmd_array, 32);
329 
330    PLBU_CMD_VIEWPORT_LEFT(fui(ctx->viewport.left));
331    PLBU_CMD_VIEWPORT_RIGHT(fui(ctx->viewport.right));
332    PLBU_CMD_VIEWPORT_BOTTOM(fui(ctx->viewport.bottom));
333    PLBU_CMD_VIEWPORT_TOP(fui(ctx->viewport.top));
334 
335    if (!info->index_size)
336       PLBU_CMD_ARRAYS_SEMAPHORE_BEGIN();
337 
338    int cf = ctx->rasterizer->base.cull_face;
339    int ccw = ctx->rasterizer->base.front_ccw;
340    uint32_t cull = 0;
341    bool force_point_size = false;
342 
343    if (cf != PIPE_FACE_NONE) {
344       if (cf & PIPE_FACE_FRONT)
345          cull |= ccw ? 0x00040000 : 0x00020000;
346       if (cf & PIPE_FACE_BACK)
347          cull |= ccw ? 0x00020000 : 0x00040000;
348    }
349 
350    /* Specify point size with PLBU command if shader doesn't write */
351    if (info->mode == PIPE_PRIM_POINTS && ctx->vs->state.point_size_idx == -1)
352       force_point_size = true;
353 
354    /* Specify line width with PLBU command for lines */
355    if (info->mode > PIPE_PRIM_POINTS && info->mode < PIPE_PRIM_TRIANGLES)
356       force_point_size = true;
357 
358    PLBU_CMD_PRIMITIVE_SETUP(force_point_size, cull, info->index_size);
359 
360    PLBU_CMD_RSW_VERTEX_ARRAY(
361       lima_ctx_buff_va(ctx, lima_ctx_buff_pp_plb_rsw),
362       ctx->gp_output->va);
363 
364    /* TODO
365     * - we should set it only for the first draw that enabled the scissor and for
366     *   latter draw only if scissor is dirty
367     */
368 
369    assert(cscissor->minx < cscissor->maxx && cscissor->miny < cscissor->maxy);
370    PLBU_CMD_SCISSORS(cscissor->minx, cscissor->maxx, cscissor->miny, cscissor->maxy);
371 
372    lima_damage_rect_union(&job->damage_rect, cscissor->minx, cscissor->maxx,
373                           cscissor->miny, cscissor->maxy);
374 
375    PLBU_CMD_UNKNOWN1();
376 
377    PLBU_CMD_DEPTH_RANGE_NEAR(fui(ctx->viewport.near));
378    PLBU_CMD_DEPTH_RANGE_FAR(fui(ctx->viewport.far));
379 
380    if ((info->mode == PIPE_PRIM_POINTS && ctx->vs->state.point_size_idx == -1) ||
381        ((info->mode >= PIPE_PRIM_LINES) && (info->mode < PIPE_PRIM_TRIANGLES)))
382    {
383       uint32_t v = info->mode == PIPE_PRIM_POINTS ?
384          fui(ctx->rasterizer->base.point_size) : fui(ctx->rasterizer->base.line_width);
385       PLBU_CMD_LOW_PRIM_SIZE(v);
386    }
387 
388    if (info->index_size) {
389       PLBU_CMD_INDEXED_DEST(ctx->gp_output->va);
390       if (vs->state.point_size_idx != -1)
391          PLBU_CMD_INDEXED_PT_SIZE(ctx->gp_output->va + ctx->gp_output_point_size_offt);
392 
393       PLBU_CMD_INDICES(ctx->index_res->bo->va + draw->start * info->index_size + ctx->index_offset);
394    }
395    else {
396       /* can this make the attribute info static? */
397       PLBU_CMD_DRAW_ARRAYS(info->mode, draw->start, draw->count);
398    }
399 
400    PLBU_CMD_ARRAYS_SEMAPHORE_END();
401 
402    if (info->index_size)
403       PLBU_CMD_DRAW_ELEMENTS(info->mode, ctx->min_index, draw->count);
404 
405    PLBU_CMD_END();
406 }
407 
408 static int
lima_blend_func(enum pipe_blend_func pipe)409 lima_blend_func(enum pipe_blend_func pipe)
410 {
411    switch (pipe) {
412    case PIPE_BLEND_ADD:
413       return 2;
414    case PIPE_BLEND_SUBTRACT:
415       return 0;
416    case PIPE_BLEND_REVERSE_SUBTRACT:
417       return 1;
418    case PIPE_BLEND_MIN:
419       return 4;
420    case PIPE_BLEND_MAX:
421       return 5;
422    }
423    return -1;
424 }
425 
426 static int
lima_blend_factor_has_alpha(enum pipe_blendfactor pipe)427 lima_blend_factor_has_alpha(enum pipe_blendfactor pipe)
428 {
429    /* Bit 4 is set if the blendfactor uses alpha */
430    switch (pipe) {
431    case PIPE_BLENDFACTOR_SRC_ALPHA:
432    case PIPE_BLENDFACTOR_DST_ALPHA:
433    case PIPE_BLENDFACTOR_CONST_ALPHA:
434    case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
435    case PIPE_BLENDFACTOR_INV_DST_ALPHA:
436    case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
437       return 1;
438 
439    case PIPE_BLENDFACTOR_SRC_COLOR:
440    case PIPE_BLENDFACTOR_INV_SRC_COLOR:
441    case PIPE_BLENDFACTOR_DST_COLOR:
442    case PIPE_BLENDFACTOR_INV_DST_COLOR:
443    case PIPE_BLENDFACTOR_CONST_COLOR:
444    case PIPE_BLENDFACTOR_INV_CONST_COLOR:
445    case PIPE_BLENDFACTOR_ZERO:
446    case PIPE_BLENDFACTOR_ONE:
447    case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
448       return 0;
449 
450    case PIPE_BLENDFACTOR_SRC1_COLOR:
451    case PIPE_BLENDFACTOR_SRC1_ALPHA:
452    case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
453    case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
454       return -1; /* not supported */
455    }
456    return -1;
457 }
458 
459 static int
lima_blend_factor_is_inv(enum pipe_blendfactor pipe)460 lima_blend_factor_is_inv(enum pipe_blendfactor pipe)
461 {
462    /* Bit 3 is set if the blendfactor type is inverted */
463    switch (pipe) {
464    case PIPE_BLENDFACTOR_INV_SRC_COLOR:
465    case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
466    case PIPE_BLENDFACTOR_INV_DST_COLOR:
467    case PIPE_BLENDFACTOR_INV_DST_ALPHA:
468    case PIPE_BLENDFACTOR_INV_CONST_COLOR:
469    case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
470    case PIPE_BLENDFACTOR_ONE:
471       return 1;
472 
473    case PIPE_BLENDFACTOR_SRC_COLOR:
474    case PIPE_BLENDFACTOR_SRC_ALPHA:
475    case PIPE_BLENDFACTOR_DST_COLOR:
476    case PIPE_BLENDFACTOR_DST_ALPHA:
477    case PIPE_BLENDFACTOR_CONST_COLOR:
478    case PIPE_BLENDFACTOR_CONST_ALPHA:
479    case PIPE_BLENDFACTOR_ZERO:
480    case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
481       return 0;
482 
483    case PIPE_BLENDFACTOR_SRC1_COLOR:
484    case PIPE_BLENDFACTOR_SRC1_ALPHA:
485    case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
486    case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
487       return -1; /* not supported */
488    }
489    return -1;
490 }
491 
492 static int
lima_blend_factor(enum pipe_blendfactor pipe)493 lima_blend_factor(enum pipe_blendfactor pipe)
494 {
495    /* Bits 0-2 indicate the blendfactor type */
496    switch (pipe) {
497    case PIPE_BLENDFACTOR_SRC_COLOR:
498    case PIPE_BLENDFACTOR_SRC_ALPHA:
499    case PIPE_BLENDFACTOR_INV_SRC_COLOR:
500    case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
501       return 0;
502 
503    case PIPE_BLENDFACTOR_DST_COLOR:
504    case PIPE_BLENDFACTOR_DST_ALPHA:
505    case PIPE_BLENDFACTOR_INV_DST_COLOR:
506    case PIPE_BLENDFACTOR_INV_DST_ALPHA:
507       return 1;
508 
509    case PIPE_BLENDFACTOR_CONST_COLOR:
510    case PIPE_BLENDFACTOR_CONST_ALPHA:
511    case PIPE_BLENDFACTOR_INV_CONST_COLOR:
512    case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
513       return 2;
514 
515    case PIPE_BLENDFACTOR_ZERO:
516    case PIPE_BLENDFACTOR_ONE:
517       return 3;
518 
519    case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
520       return 4;
521 
522    case PIPE_BLENDFACTOR_SRC1_COLOR:
523    case PIPE_BLENDFACTOR_SRC1_ALPHA:
524    case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
525    case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
526       return -1; /* not supported */
527    }
528    return -1;
529 }
530 
531 static int
lima_calculate_alpha_blend(enum pipe_blend_func rgb_func,enum pipe_blend_func alpha_func,enum pipe_blendfactor rgb_src_factor,enum pipe_blendfactor rgb_dst_factor,enum pipe_blendfactor alpha_src_factor,enum pipe_blendfactor alpha_dst_factor)532 lima_calculate_alpha_blend(enum pipe_blend_func rgb_func, enum pipe_blend_func alpha_func,
533                            enum pipe_blendfactor rgb_src_factor, enum pipe_blendfactor rgb_dst_factor,
534                            enum pipe_blendfactor alpha_src_factor, enum pipe_blendfactor alpha_dst_factor)
535 {
536    /* PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE has to be changed to PIPE_BLENDFACTOR_ONE
537     * if it is set for alpha_src.
538     */
539    if (alpha_src_factor == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE)
540       alpha_src_factor = PIPE_BLENDFACTOR_ONE;
541 
542    return lima_blend_func(rgb_func) |
543       (lima_blend_func(alpha_func) << 3) |
544 
545       (lima_blend_factor(rgb_src_factor) << 6) |
546       (lima_blend_factor_is_inv(rgb_src_factor) << 9) |
547       (lima_blend_factor_has_alpha(rgb_src_factor) << 10) |
548 
549       (lima_blend_factor(rgb_dst_factor) << 11) |
550       (lima_blend_factor_is_inv(rgb_dst_factor) << 14) |
551       (lima_blend_factor_has_alpha(rgb_dst_factor) << 15) |
552 
553       (lima_blend_factor(alpha_src_factor) << 16) |
554       (lima_blend_factor_is_inv(alpha_src_factor) << 19) |
555 
556       (lima_blend_factor(alpha_dst_factor) << 20) |
557       (lima_blend_factor_is_inv(alpha_dst_factor) << 23) |
558       0x0C000000; /* need to check if this is GLESv1 glAlphaFunc */
559 }
560 
561 static int
lima_stencil_op(enum pipe_stencil_op pipe)562 lima_stencil_op(enum pipe_stencil_op pipe)
563 {
564    switch (pipe) {
565    case PIPE_STENCIL_OP_KEEP:
566       return 0;
567    case PIPE_STENCIL_OP_ZERO:
568       return 2;
569    case PIPE_STENCIL_OP_REPLACE:
570       return 1;
571    case PIPE_STENCIL_OP_INCR:
572       return 6;
573    case PIPE_STENCIL_OP_DECR:
574       return 7;
575    case PIPE_STENCIL_OP_INCR_WRAP:
576       return 4;
577    case PIPE_STENCIL_OP_DECR_WRAP:
578       return 5;
579    case PIPE_STENCIL_OP_INVERT:
580       return 3;
581    }
582    return -1;
583 }
584 
585 static unsigned
lima_calculate_depth_test(struct pipe_depth_stencil_alpha_state * depth,struct pipe_rasterizer_state * rst)586 lima_calculate_depth_test(struct pipe_depth_stencil_alpha_state *depth,
587                           struct pipe_rasterizer_state *rst)
588 {
589    int offset_scale = 0, offset_units = 0;
590    enum pipe_compare_func func = (depth->depth_enabled ? depth->depth_func : PIPE_FUNC_ALWAYS);
591 
592    offset_scale = CLAMP(rst->offset_scale * 4, -128, 127);
593    if (offset_scale < 0)
594       offset_scale += 0x100;
595 
596    offset_units = CLAMP(rst->offset_units * 2, -128, 127);
597    if (offset_units < 0)
598       offset_units += 0x100;
599 
600    return (depth->depth_enabled && depth->depth_writemask) |
601       ((int)func << 1) |
602       (offset_scale << 16) |
603       (offset_units << 24);
604 }
605 
606 static void
lima_pack_render_state(struct lima_context * ctx,const struct pipe_draw_info * info)607 lima_pack_render_state(struct lima_context *ctx, const struct pipe_draw_info *info)
608 {
609    struct lima_fs_compiled_shader *fs = ctx->fs;
610    struct lima_render_state *render =
611       lima_ctx_buff_alloc(ctx, lima_ctx_buff_pp_plb_rsw,
612                           sizeof(*render));
613    bool early_z = true;
614    bool pixel_kill = true;
615 
616    /* do hw support RGBA independ blend?
617     * PIPE_CAP_INDEP_BLEND_ENABLE
618     *
619     * how to handle the no cbuf only zbuf case?
620     */
621    struct pipe_rt_blend_state *rt = ctx->blend->base.rt;
622    render->blend_color_bg = float_to_ubyte(ctx->blend_color.color[2]) |
623       (float_to_ubyte(ctx->blend_color.color[1]) << 16);
624    render->blend_color_ra = float_to_ubyte(ctx->blend_color.color[0]) |
625       (float_to_ubyte(ctx->blend_color.color[3]) << 16);
626 
627    if (rt->blend_enable) {
628       render->alpha_blend = lima_calculate_alpha_blend(rt->rgb_func, rt->alpha_func,
629          rt->rgb_src_factor, rt->rgb_dst_factor,
630          rt->alpha_src_factor, rt->alpha_dst_factor);
631    }
632    else {
633       /*
634        * Special handling for blending disabled.
635        * Binary driver is generating the same alpha_value,
636        * as when we would just enable blending, without changing/setting any blend equation/params.
637        * Normaly in this case mesa would set all rt fields (func/factor) to zero.
638        */
639       render->alpha_blend = lima_calculate_alpha_blend(PIPE_BLEND_ADD, PIPE_BLEND_ADD,
640          PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ZERO,
641          PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ZERO);
642    }
643 
644    render->alpha_blend |= (rt->colormask & PIPE_MASK_RGBA) << 28;
645 
646    struct pipe_rasterizer_state *rst = &ctx->rasterizer->base;
647    render->depth_test = lima_calculate_depth_test(&ctx->zsa->base, rst);
648 
649    if (!rst->depth_clip_near || ctx->viewport.near == 0.0f)
650       render->depth_test |= 0x10; /* don't clip depth near */
651    if (!rst->depth_clip_far || ctx->viewport.far == 1.0f)
652       render->depth_test |= 0x20; /* don't clip depth far */
653 
654    ushort far, near;
655 
656    near = float_to_ushort(ctx->viewport.near);
657    far = float_to_ushort(ctx->viewport.far);
658 
659    /* overlap with plbu? any place can remove one? */
660    render->depth_range = near | (far << 16);
661 
662    struct pipe_stencil_state *stencil = ctx->zsa->base.stencil;
663    struct pipe_stencil_ref *ref = &ctx->stencil_ref;
664 
665    if (stencil[0].enabled) { /* stencil is enabled */
666       render->stencil_front = stencil[0].func |
667          (lima_stencil_op(stencil[0].fail_op) << 3) |
668          (lima_stencil_op(stencil[0].zfail_op) << 6) |
669          (lima_stencil_op(stencil[0].zpass_op) << 9) |
670          (ref->ref_value[0] << 16) |
671          (stencil[0].valuemask << 24);
672       render->stencil_back = render->stencil_front;
673       render->stencil_test = (stencil[0].writemask & 0xff) | (stencil[0].writemask & 0xff) << 8;
674       if (stencil[1].enabled) { /* two-side is enabled */
675          render->stencil_back = stencil[1].func |
676             (lima_stencil_op(stencil[1].fail_op) << 3) |
677             (lima_stencil_op(stencil[1].zfail_op) << 6) |
678             (lima_stencil_op(stencil[1].zpass_op) << 9) |
679             (ref->ref_value[1] << 16) |
680             (stencil[1].valuemask << 24);
681          render->stencil_test = (stencil[0].writemask & 0xff) | (stencil[1].writemask & 0xff) << 8;
682       }
683       /* TODO: Find out, what (render->stecil_test & 0xff000000) is */
684    }
685    else {
686       /* Default values, when stencil is disabled:
687        * stencil[0|1].valuemask = 0xff
688        * stencil[0|1].func = PIPE_FUNC_ALWAYS
689        * stencil[0|1].writemask = 0xff
690        */
691       render->stencil_front = 0xff000007;
692       render->stencil_back = 0xff000007;
693       render->stencil_test = 0x0000ffff;
694    }
695 
696    /* need more investigation */
697    if (info->mode == PIPE_PRIM_POINTS)
698       render->multi_sample = 0x0000F000;
699    else if (info->mode < PIPE_PRIM_TRIANGLES)
700       render->multi_sample = 0x0000F400;
701    else
702       render->multi_sample = 0x0000F800;
703    if (ctx->framebuffer.base.samples)
704       render->multi_sample |= 0x68;
705 
706    /* alpha test */
707    if (ctx->zsa->base.alpha_enabled) {
708       render->multi_sample |= ctx->zsa->base.alpha_func;
709       render->stencil_test |= float_to_ubyte(ctx->zsa->base.alpha_ref_value) << 16;
710    } else {
711       /* func = PIPE_FUNC_ALWAYS */
712       render->multi_sample |= 0x7;
713    }
714 
715    render->shader_address =
716       ctx->fs->bo->va | (((uint32_t *)ctx->fs->bo->map)[0] & 0x1F);
717 
718    /* seems not needed */
719    render->uniforms_address = 0x00000000;
720 
721    render->textures_address = 0x00000000;
722 
723    render->aux0 = (ctx->vs->state.varying_stride >> 3);
724    render->aux1 = 0x00000000;
725    if (ctx->rasterizer->base.front_ccw)
726       render->aux1 = 0x00001000;
727 
728    if (ctx->blend->base.dither)
729       render->aux1 |= 0x00002000;
730 
731    if (fs->state.uses_discard ||
732        ctx->zsa->base.alpha_enabled) {
733       early_z = false;
734       pixel_kill = false;
735    }
736 
737    if (rt->blend_enable)
738       pixel_kill = false;
739 
740    if ((rt->colormask & PIPE_MASK_RGBA) != PIPE_MASK_RGBA)
741       pixel_kill = false;
742 
743    if (early_z)
744       render->aux0 |= 0x300;
745 
746    if (pixel_kill)
747       render->aux0 |= 0x1000;
748 
749    if (ctx->tex_stateobj.num_samplers) {
750       render->textures_address =
751          lima_ctx_buff_va(ctx, lima_ctx_buff_pp_tex_desc);
752       render->aux0 |= ctx->tex_stateobj.num_samplers << 14;
753       render->aux0 |= 0x20;
754    }
755 
756    if (ctx->const_buffer[PIPE_SHADER_FRAGMENT].buffer) {
757       render->uniforms_address =
758          lima_ctx_buff_va(ctx, lima_ctx_buff_pp_uniform_array);
759       uint32_t size = ctx->buffer_state[lima_ctx_buff_pp_uniform].size;
760       uint32_t bits = 0;
761       if (size >= 8) {
762          bits = util_last_bit(size >> 3) - 1;
763          bits += size & u_bit_consecutive(0, bits + 3) ? 1 : 0;
764       }
765       render->uniforms_address |= bits > 0xf ? 0xf : bits;
766 
767       render->aux0 |= 0x80;
768       render->aux1 |= 0x10000;
769    }
770 
771    if (ctx->vs->state.num_varyings) {
772       render->varying_types = 0x00000000;
773       render->varyings_address = ctx->gp_output->va +
774                                  ctx->gp_output_varyings_offt;
775       for (int i = 0, index = 0; i < ctx->vs->state.num_outputs; i++) {
776          int val;
777 
778          if (i == ctx->vs->state.gl_pos_idx ||
779              i == ctx->vs->state.point_size_idx)
780             continue;
781 
782          struct lima_varying_info *v = ctx->vs->state.varying + i;
783          if (v->component_size == 4)
784             val = v->components > 2 ? 0 : 1;
785          else
786             val = v->components > 2 ? 2 : 3;
787 
788          if (index < 10)
789             render->varying_types |= val << (3 * index);
790          else if (index == 10) {
791             render->varying_types |= val << 30;
792             render->varyings_address |= val >> 2;
793          }
794          else if (index == 11)
795             render->varyings_address |= val << 1;
796 
797          index++;
798       }
799    }
800    else {
801       render->varying_types = 0x00000000;
802       render->varyings_address = 0x00000000;
803    }
804 
805    struct lima_job *job = lima_job_get(ctx);
806 
807    lima_dump_command_stream_print(
808       job->dump, render, sizeof(*render),
809       false, "add render state at va %x\n",
810       lima_ctx_buff_va(ctx, lima_ctx_buff_pp_plb_rsw));
811 
812    lima_dump_rsw_command_stream_print(
813       job->dump, render, sizeof(*render),
814       lima_ctx_buff_va(ctx, lima_ctx_buff_pp_plb_rsw));
815 }
816 
817 static void
lima_update_gp_attribute_info(struct lima_context * ctx,const struct pipe_draw_info * info,const struct pipe_draw_start_count_bias * draw)818 lima_update_gp_attribute_info(struct lima_context *ctx, const struct pipe_draw_info *info,
819                               const struct pipe_draw_start_count_bias *draw)
820 {
821    struct lima_job *job = lima_job_get(ctx);
822    struct lima_vertex_element_state *ve = ctx->vertex_elements;
823    struct lima_context_vertex_buffer *vb = &ctx->vertex_buffers;
824 
825    uint32_t *attribute =
826       lima_ctx_buff_alloc(ctx, lima_ctx_buff_gp_attribute_info,
827                           MAX2(1, ve->num_elements) * 8);
828 
829    int n = 0;
830    for (int i = 0; i < ve->num_elements; i++) {
831       struct pipe_vertex_element *pve = ve->pipe + i;
832 
833       assert(pve->vertex_buffer_index < vb->count);
834       assert(vb->enabled_mask & (1 << pve->vertex_buffer_index));
835 
836       struct pipe_vertex_buffer *pvb = vb->vb + pve->vertex_buffer_index;
837       struct lima_resource *res = lima_resource(pvb->buffer.resource);
838 
839       lima_job_add_bo(job, LIMA_PIPE_GP, res->bo, LIMA_SUBMIT_BO_READ);
840 
841       unsigned start = info->index_size ? (ctx->min_index + draw->index_bias) : draw->start;
842       attribute[n++] = res->bo->va + pvb->buffer_offset + pve->src_offset
843          + start * pvb->stride;
844       attribute[n++] = (pvb->stride << 11) |
845          (lima_pipe_format_to_attrib_type(pve->src_format) << 2) |
846          (util_format_get_nr_components(pve->src_format) - 1);
847    }
848 
849    lima_dump_command_stream_print(
850       job->dump, attribute, n * 4, false, "update attribute info at va %x\n",
851       lima_ctx_buff_va(ctx, lima_ctx_buff_gp_attribute_info));
852 }
853 
854 static void
lima_update_gp_uniform(struct lima_context * ctx)855 lima_update_gp_uniform(struct lima_context *ctx)
856 {
857    struct lima_context_constant_buffer *ccb =
858       ctx->const_buffer + PIPE_SHADER_VERTEX;
859    struct lima_vs_compiled_shader *vs = ctx->vs;
860    int uniform_size = MIN2(vs->state.uniform_size, ccb->size);
861 
862    int size = uniform_size + vs->state.constant_size + 32;
863    void *vs_const_buff =
864       lima_ctx_buff_alloc(ctx, lima_ctx_buff_gp_uniform, size);
865 
866    if (ccb->buffer)
867       memcpy(vs_const_buff, ccb->buffer, uniform_size);
868 
869    memcpy(vs_const_buff + uniform_size,
870           ctx->viewport.transform.scale,
871           sizeof(ctx->viewport.transform.scale));
872    memcpy(vs_const_buff + uniform_size + 16,
873           ctx->viewport.transform.translate,
874           sizeof(ctx->viewport.transform.translate));
875 
876    if (vs->constant)
877       memcpy(vs_const_buff + uniform_size + 32,
878              vs->constant, vs->state.constant_size);
879 
880    struct lima_job *job = lima_job_get(ctx);
881 
882    if (lima_debug & LIMA_DEBUG_GP) {
883       float *vs_const_buff_f = vs_const_buff;
884       printf("gp uniforms:\n");
885       for (int i = 0; i < (size / sizeof(float)); i++) {
886          if ((i % 4) == 0)
887             printf("%4d:", i / 4);
888          printf(" %8.4f", vs_const_buff_f[i]);
889          if ((i % 4) == 3)
890             printf("\n");
891       }
892       printf("\n");
893    }
894 
895    lima_dump_command_stream_print(
896       job->dump, vs_const_buff, size, true,
897       "update gp uniform at va %x\n",
898       lima_ctx_buff_va(ctx, lima_ctx_buff_gp_uniform));
899 }
900 
901 static void
lima_update_pp_uniform(struct lima_context * ctx)902 lima_update_pp_uniform(struct lima_context *ctx)
903 {
904    const float *const_buff = ctx->const_buffer[PIPE_SHADER_FRAGMENT].buffer;
905    size_t const_buff_size = ctx->const_buffer[PIPE_SHADER_FRAGMENT].size / sizeof(float);
906 
907    if (!const_buff)
908       return;
909 
910    uint16_t *fp16_const_buff =
911       lima_ctx_buff_alloc(ctx, lima_ctx_buff_pp_uniform,
912                           const_buff_size * sizeof(uint16_t));
913 
914    uint32_t *array =
915       lima_ctx_buff_alloc(ctx, lima_ctx_buff_pp_uniform_array, 4);
916 
917    for (int i = 0; i < const_buff_size; i++)
918        fp16_const_buff[i] = _mesa_float_to_half(const_buff[i]);
919 
920    *array = lima_ctx_buff_va(ctx, lima_ctx_buff_pp_uniform);
921 
922    struct lima_job *job = lima_job_get(ctx);
923 
924    lima_dump_command_stream_print(
925       job->dump, fp16_const_buff, const_buff_size * 2,
926       false, "add pp uniform data at va %x\n",
927       lima_ctx_buff_va(ctx, lima_ctx_buff_pp_uniform));
928    lima_dump_command_stream_print(
929       job->dump, array, 4, false, "add pp uniform info at va %x\n",
930       lima_ctx_buff_va(ctx, lima_ctx_buff_pp_uniform_array));
931 }
932 
933 static void
lima_update_varying(struct lima_context * ctx,const struct pipe_draw_info * info,const struct pipe_draw_start_count_bias * draw)934 lima_update_varying(struct lima_context *ctx, const struct pipe_draw_info *info,
935                     const struct pipe_draw_start_count_bias *draw)
936 {
937    struct lima_job *job = lima_job_get(ctx);
938    struct lima_screen *screen = lima_screen(ctx->base.screen);
939    struct lima_vs_compiled_shader *vs = ctx->vs;
940    uint32_t gp_output_size;
941    unsigned num = info->index_size ? (ctx->max_index - ctx->min_index + 1) : draw->count;
942 
943    uint32_t *varying =
944       lima_ctx_buff_alloc(ctx, lima_ctx_buff_gp_varying_info,
945                           vs->state.num_outputs * 8);
946    int n = 0;
947 
948    int offset = 0;
949 
950    for (int i = 0; i < vs->state.num_outputs; i++) {
951       struct lima_varying_info *v = vs->state.varying + i;
952 
953       if (i == vs->state.gl_pos_idx ||
954           i == vs->state.point_size_idx)
955          continue;
956 
957       int size = v->component_size * 4;
958 
959       /* does component_size == 2 need to be 16 aligned? */
960       if (v->component_size == 4)
961          offset = align(offset, 16);
962 
963       v->offset = offset;
964       offset += size;
965    }
966 
967    vs->state.varying_stride = align(offset, 16);
968 
969    /* gl_Position is always present, allocate space for it */
970    gp_output_size = align(4 * 4 * num, 0x40);
971 
972    /* Allocate space for varyings if there're any */
973    if (vs->state.num_varyings) {
974       ctx->gp_output_varyings_offt = gp_output_size;
975       gp_output_size += align(vs->state.varying_stride * num, 0x40);
976    }
977 
978    /* Allocate space for gl_PointSize if it's there */
979    if (vs->state.point_size_idx != -1) {
980       ctx->gp_output_point_size_offt = gp_output_size;
981       gp_output_size += 4 * num;
982    }
983 
984    /* gp_output can be too large for the suballocator, so create a
985     * separate bo for it. The bo cache should prevent performance hit.
986     */
987    ctx->gp_output = lima_bo_create(screen, gp_output_size, 0);
988    assert(ctx->gp_output);
989    lima_job_add_bo(job, LIMA_PIPE_GP, ctx->gp_output, LIMA_SUBMIT_BO_WRITE);
990    lima_job_add_bo(job, LIMA_PIPE_PP, ctx->gp_output, LIMA_SUBMIT_BO_READ);
991 
992    for (int i = 0; i < vs->state.num_outputs; i++) {
993       struct lima_varying_info *v = vs->state.varying + i;
994 
995       if (i == vs->state.gl_pos_idx) {
996          /* gl_Position */
997          varying[n++] = ctx->gp_output->va;
998          varying[n++] = 0x8020;
999       } else if (i == vs->state.point_size_idx) {
1000          /* gl_PointSize */
1001          varying[n++] = ctx->gp_output->va + ctx->gp_output_point_size_offt;
1002          varying[n++] = 0x2021;
1003       } else {
1004          /* Varying */
1005          varying[n++] = ctx->gp_output->va + ctx->gp_output_varyings_offt +
1006                         v->offset;
1007          varying[n++] = (vs->state.varying_stride << 11) | (v->components - 1) |
1008             (v->component_size == 2 ? 0x0C : 0);
1009       }
1010    }
1011 
1012    lima_dump_command_stream_print(
1013       job->dump, varying, n * 4, false, "update varying info at va %x\n",
1014       lima_ctx_buff_va(ctx, lima_ctx_buff_gp_varying_info));
1015 }
1016 
1017 static void
lima_draw_vbo_update(struct pipe_context * pctx,const struct pipe_draw_info * info,const struct pipe_draw_start_count_bias * draw)1018 lima_draw_vbo_update(struct pipe_context *pctx,
1019                      const struct pipe_draw_info *info,
1020                      const struct pipe_draw_start_count_bias *draw)
1021 {
1022    struct lima_context *ctx = lima_context(pctx);
1023    struct lima_context_framebuffer *fb = &ctx->framebuffer;
1024    unsigned buffers = 0;
1025 
1026    if (fb->base.zsbuf) {
1027       if (ctx->zsa->base.depth_enabled)
1028          buffers |= PIPE_CLEAR_DEPTH;
1029       if (ctx->zsa->base.stencil[0].enabled ||
1030           ctx->zsa->base.stencil[1].enabled)
1031          buffers |= PIPE_CLEAR_STENCIL;
1032    }
1033 
1034    if (fb->base.nr_cbufs)
1035       buffers |= PIPE_CLEAR_COLOR0;
1036 
1037    lima_update_job_wb(ctx, buffers);
1038 
1039    lima_update_gp_attribute_info(ctx, info, draw);
1040 
1041    if ((ctx->dirty & LIMA_CONTEXT_DIRTY_CONST_BUFF &&
1042         ctx->const_buffer[PIPE_SHADER_VERTEX].dirty) ||
1043        ctx->dirty & LIMA_CONTEXT_DIRTY_VIEWPORT ||
1044        ctx->dirty & LIMA_CONTEXT_DIRTY_COMPILED_VS) {
1045       lima_update_gp_uniform(ctx);
1046       ctx->const_buffer[PIPE_SHADER_VERTEX].dirty = false;
1047    }
1048 
1049    lima_update_varying(ctx, info, draw);
1050 
1051    lima_pack_vs_cmd(ctx, info, draw);
1052 
1053    if (ctx->dirty & LIMA_CONTEXT_DIRTY_CONST_BUFF &&
1054        ctx->const_buffer[PIPE_SHADER_FRAGMENT].dirty) {
1055       lima_update_pp_uniform(ctx);
1056       ctx->const_buffer[PIPE_SHADER_FRAGMENT].dirty = false;
1057    }
1058 
1059    lima_update_textures(ctx);
1060 
1061    lima_pack_render_state(ctx, info);
1062    lima_pack_plbu_cmd(ctx, info, draw);
1063 
1064    if (ctx->gp_output) {
1065       lima_bo_unreference(ctx->gp_output); /* held by job */
1066       ctx->gp_output = NULL;
1067    }
1068 
1069    ctx->dirty = 0;
1070 }
1071 
1072 static void
lima_draw_vbo_indexed(struct pipe_context * pctx,const struct pipe_draw_info * info,const struct pipe_draw_start_count_bias * draw)1073 lima_draw_vbo_indexed(struct pipe_context *pctx,
1074                       const struct pipe_draw_info *info,
1075                       const struct pipe_draw_start_count_bias *draw)
1076 {
1077    struct lima_context *ctx = lima_context(pctx);
1078    struct lima_job *job = lima_job_get(ctx);
1079    struct pipe_resource *indexbuf = NULL;
1080    bool needs_indices = true;
1081 
1082    /* Mali Utgard GPU always need min/max index info for index draw,
1083     * compute it if upper layer does not do for us */
1084    if (info->index_bounds_valid) {
1085       ctx->min_index = info->min_index;
1086       ctx->max_index = info->max_index;
1087       needs_indices = false;
1088    }
1089 
1090    if (info->has_user_indices) {
1091       util_upload_index_buffer(&ctx->base, info, draw, &indexbuf, &ctx->index_offset, 0x40);
1092       ctx->index_res = lima_resource(indexbuf);
1093    }
1094    else {
1095       ctx->index_res = lima_resource(info->index.resource);
1096       ctx->index_offset = 0;
1097       needs_indices = !panfrost_minmax_cache_get(ctx->index_res->index_cache, draw->start,
1098                                                  draw->count, &ctx->min_index, &ctx->max_index);
1099    }
1100 
1101    if (needs_indices) {
1102       u_vbuf_get_minmax_index(pctx, info, draw, &ctx->min_index, &ctx->max_index);
1103       if (!info->has_user_indices)
1104          panfrost_minmax_cache_add(ctx->index_res->index_cache, draw->start, draw->count,
1105                                    ctx->min_index, ctx->max_index);
1106    }
1107 
1108    lima_job_add_bo(job, LIMA_PIPE_GP, ctx->index_res->bo, LIMA_SUBMIT_BO_READ);
1109    lima_job_add_bo(job, LIMA_PIPE_PP, ctx->index_res->bo, LIMA_SUBMIT_BO_READ);
1110    lima_draw_vbo_update(pctx, info, draw);
1111 
1112    if (indexbuf)
1113       pipe_resource_reference(&indexbuf, NULL);
1114 }
1115 
1116 static void
lima_draw_vbo_count(struct pipe_context * pctx,const struct pipe_draw_info * info,const struct pipe_draw_start_count_bias * draw)1117 lima_draw_vbo_count(struct pipe_context *pctx,
1118                     const struct pipe_draw_info *info,
1119                     const struct pipe_draw_start_count_bias *draw)
1120 {
1121    static const uint32_t max_verts = 65535;
1122 
1123    struct pipe_draw_start_count_bias local_draw = *draw;
1124    unsigned start = draw->start;
1125    unsigned count = draw->count;
1126 
1127    while (count) {
1128       unsigned this_count = count;
1129       unsigned step;
1130 
1131       u_split_draw(info, max_verts, &this_count, &step);
1132 
1133       local_draw.start = start;
1134       local_draw.count = this_count;
1135 
1136       lima_draw_vbo_update(pctx, info, &local_draw);
1137 
1138       count -= step;
1139       start += step;
1140    }
1141 }
1142 
1143 static void
lima_draw_vbo(struct pipe_context * pctx,const struct pipe_draw_info * info,unsigned drawid_offset,const struct pipe_draw_indirect_info * indirect,const struct pipe_draw_start_count_bias * draws,unsigned num_draws)1144 lima_draw_vbo(struct pipe_context *pctx,
1145               const struct pipe_draw_info *info,
1146               unsigned drawid_offset,
1147               const struct pipe_draw_indirect_info *indirect,
1148               const struct pipe_draw_start_count_bias *draws,
1149               unsigned num_draws)
1150 {
1151    if (num_draws > 1) {
1152       util_draw_multi(pctx, info, drawid_offset, indirect, draws, num_draws);
1153       return;
1154    }
1155 
1156    /* check if draw mode and vertex/index count match,
1157     * otherwise gp will hang */
1158    if (!u_trim_pipe_prim(info->mode, (unsigned*)&draws[0].count)) {
1159       debug_printf("draw mode and vertex/index count mismatch\n");
1160       return;
1161    }
1162 
1163    struct lima_context *ctx = lima_context(pctx);
1164 
1165    if (!ctx->uncomp_fs || !ctx->uncomp_vs) {
1166       debug_warn_once("no shader, skip draw\n");
1167       return;
1168    }
1169 
1170    lima_clip_scissor_to_viewport(ctx);
1171    if (lima_is_scissor_zero(ctx))
1172       return;
1173 
1174    if (!lima_update_fs_state(ctx) || !lima_update_vs_state(ctx))
1175       return;
1176 
1177    struct lima_job *job = lima_job_get(ctx);
1178    job->pp_max_stack_size = MAX2(job->pp_max_stack_size, ctx->fs->state.stack_size);
1179 
1180    lima_dump_command_stream_print(
1181       job->dump, ctx->vs->bo->map, ctx->vs->state.shader_size, false,
1182       "add vs at va %x\n", ctx->vs->bo->va);
1183    lima_dump_shader(job->dump, ctx->vs->bo->map, ctx->vs->state.shader_size, false);
1184 
1185    lima_dump_command_stream_print(
1186       job->dump, ctx->fs->bo->map, ctx->fs->state.shader_size, false,
1187       "add fs at va %x\n", ctx->fs->bo->va);
1188    lima_dump_shader(job->dump, ctx->fs->bo->map, ctx->fs->state.shader_size, true);
1189 
1190    lima_job_add_bo(job, LIMA_PIPE_GP, ctx->vs->bo, LIMA_SUBMIT_BO_READ);
1191    lima_job_add_bo(job, LIMA_PIPE_PP, ctx->fs->bo, LIMA_SUBMIT_BO_READ);
1192 
1193    if (info->index_size)
1194       lima_draw_vbo_indexed(pctx, info, &draws[0]);
1195    else
1196       lima_draw_vbo_count(pctx, info, &draws[0]);
1197 
1198    job->draws++;
1199    /* Flush job if we hit the limit of draws per job otherwise we may
1200     * hit tile heap size limit */
1201    if (job->draws > MAX_DRAWS_PER_JOB) {
1202       unsigned resolve = job->resolve;
1203       lima_do_job(job);
1204       job = lima_job_get(ctx);
1205       /* Subsequent job will need to resolve the same buffers */
1206       lima_update_job_wb(ctx, resolve);
1207    }
1208 }
1209 
1210 void
lima_draw_init(struct lima_context * ctx)1211 lima_draw_init(struct lima_context *ctx)
1212 {
1213    ctx->base.clear = lima_clear;
1214    ctx->base.draw_vbo = lima_draw_vbo;
1215 }
1216