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