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