2
* Copyright (c) 2011-2013 Luc Verhaegen <libv@skynet.be>
3
* Copyright (c) 2017-2019 Lima Project
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:
12
* The above copyright notice and this permission notice (including the
13
* next paragraph) shall be included in all copies or substantial portions
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.
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"
39
#include "lima_context.h"
40
#include "lima_screen.h"
41
#include "lima_resource.h"
42
#include "lima_program.h"
45
#include "lima_texture.h"
46
#include "lima_util.h"
49
#include "pan_minmax_cache.h"
51
#include <drm-uapi/lima_drm.h>
54
lima_clip_scissor_to_viewport(struct lima_context *ctx)
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;
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;
68
cscissor->maxx = fb->base.width;
70
cscissor->maxy = fb->base.height;
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;
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;
89
lima_extend_viewport(struct lima_context *ctx, const struct pipe_draw_info *info)
91
/* restore the original values */
92
ctx->ext_viewport.left = ctx->viewport.left;
93
ctx->ext_viewport.right = ctx->viewport.right;
94
ctx->ext_viewport.bottom = ctx->viewport.bottom;
95
ctx->ext_viewport.top = ctx->viewport.top;
97
if (info->mode != PIPE_PRIM_LINES)
100
if (!ctx->rasterizer)
103
float line_width = ctx->rasterizer->base.line_width;
105
if (line_width == 1.0f)
108
ctx->ext_viewport.left = ctx->viewport.left - line_width / 2;
109
ctx->ext_viewport.right = ctx->viewport.right + line_width / 2;
110
ctx->ext_viewport.bottom = ctx->viewport.bottom - line_width / 2;
111
ctx->ext_viewport.top = ctx->viewport.top + line_width / 2;
115
lima_is_scissor_zero(struct lima_context *ctx)
117
struct pipe_scissor_state *cscissor = &ctx->clipped_scissor;
119
return cscissor->minx == cscissor->maxx || cscissor->miny == cscissor->maxy;
123
lima_update_job_wb(struct lima_context *ctx, unsigned buffers)
125
struct lima_job *job = lima_job_get(ctx);
126
struct lima_context_framebuffer *fb = &ctx->framebuffer;
128
/* add to job when the buffer is dirty and resolve is clear (not added before) */
129
if (fb->base.nr_cbufs && (buffers & PIPE_CLEAR_COLOR0) &&
130
!(job->resolve & PIPE_CLEAR_COLOR0)) {
131
struct lima_resource *res = lima_resource(fb->base.cbufs[0]->texture);
132
lima_flush_job_accessing_bo(ctx, res->bo, true);
133
_mesa_hash_table_insert(ctx->write_jobs, &res->base, job);
134
lima_job_add_bo(job, LIMA_PIPE_PP, res->bo, LIMA_SUBMIT_BO_WRITE);
137
/* add to job when the buffer is dirty and resolve is clear (not added before) */
138
if (fb->base.zsbuf && (buffers & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) &&
139
!(job->resolve & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL))) {
140
struct lima_resource *res = lima_resource(fb->base.zsbuf->texture);
141
lima_flush_job_accessing_bo(ctx, res->bo, true);
142
_mesa_hash_table_insert(ctx->write_jobs, &res->base, job);
143
lima_job_add_bo(job, LIMA_PIPE_PP, res->bo, LIMA_SUBMIT_BO_WRITE);
146
job->resolve |= buffers;
150
lima_damage_rect_union(struct pipe_scissor_state *rect,
151
unsigned minx, unsigned maxx,
152
unsigned miny, unsigned maxy)
154
rect->minx = MIN2(rect->minx, minx);
155
rect->miny = MIN2(rect->miny, miny);
156
rect->maxx = MAX2(rect->maxx, maxx);
157
rect->maxy = MAX2(rect->maxy, maxy);
161
lima_clear(struct pipe_context *pctx, unsigned buffers, const struct pipe_scissor_state *scissor_state,
162
const union pipe_color_union *color, double depth, unsigned stencil)
164
struct lima_context *ctx = lima_context(pctx);
165
struct lima_job *job = lima_job_get(ctx);
167
/* flush if this job already contains any draw, otherwise multi clear can be
168
* combined into a single job */
169
if (lima_job_has_draw_pending(job)) {
171
job = lima_job_get(ctx);
174
lima_update_job_wb(ctx, buffers);
176
/* no need to reload if cleared */
177
if (ctx->framebuffer.base.nr_cbufs && (buffers & PIPE_CLEAR_COLOR0)) {
178
struct lima_surface *surf = lima_surface(ctx->framebuffer.base.cbufs[0]);
179
surf->reload &= ~PIPE_CLEAR_COLOR0;
182
struct lima_job_clear *clear = &job->clear;
183
clear->buffers = buffers;
185
if (buffers & PIPE_CLEAR_COLOR0) {
187
((uint32_t)float_to_ubyte(color->f[3]) << 24) |
188
((uint32_t)float_to_ubyte(color->f[2]) << 16) |
189
((uint32_t)float_to_ubyte(color->f[1]) << 8) |
190
float_to_ubyte(color->f[0]);
193
((uint64_t)float_to_ushort(color->f[3]) << 48) |
194
((uint64_t)float_to_ushort(color->f[2]) << 32) |
195
((uint64_t)float_to_ushort(color->f[1]) << 16) |
196
float_to_ushort(color->f[0]);
199
struct lima_surface *zsbuf = lima_surface(ctx->framebuffer.base.zsbuf);
201
if (buffers & PIPE_CLEAR_DEPTH) {
202
clear->depth = util_pack_z(PIPE_FORMAT_Z24X8_UNORM, depth);
204
zsbuf->reload &= ~PIPE_CLEAR_DEPTH;
207
if (buffers & PIPE_CLEAR_STENCIL) {
208
clear->stencil = stencil;
210
zsbuf->reload &= ~PIPE_CLEAR_STENCIL;
213
ctx->dirty |= LIMA_CONTEXT_DIRTY_CLEAR;
215
lima_damage_rect_union(&job->damage_rect,
216
0, ctx->framebuffer.base.width,
217
0, ctx->framebuffer.base.height);
220
enum lima_attrib_type {
221
LIMA_ATTRIB_FLOAT = 0x000,
222
LIMA_ATTRIB_I32 = 0x001,
223
LIMA_ATTRIB_U32 = 0x002,
224
LIMA_ATTRIB_FP16 = 0x003,
225
LIMA_ATTRIB_I16 = 0x004,
226
LIMA_ATTRIB_U16 = 0x005,
227
LIMA_ATTRIB_I8 = 0x006,
228
LIMA_ATTRIB_U8 = 0x007,
229
LIMA_ATTRIB_I8N = 0x008,
230
LIMA_ATTRIB_U8N = 0x009,
231
LIMA_ATTRIB_I16N = 0x00A,
232
LIMA_ATTRIB_U16N = 0x00B,
233
LIMA_ATTRIB_I32N = 0x00D,
234
LIMA_ATTRIB_U32N = 0x00E,
235
LIMA_ATTRIB_FIXED = 0x101
238
static enum lima_attrib_type
239
lima_pipe_format_to_attrib_type(enum pipe_format format)
241
const struct util_format_description *desc = util_format_description(format);
242
int i = util_format_get_first_non_void_channel(format);
243
const struct util_format_channel_description *c = desc->channel + i;
246
case UTIL_FORMAT_TYPE_FLOAT:
248
return LIMA_ATTRIB_FP16;
250
return LIMA_ATTRIB_FLOAT;
251
case UTIL_FORMAT_TYPE_FIXED:
252
return LIMA_ATTRIB_FIXED;
253
case UTIL_FORMAT_TYPE_SIGNED:
256
return LIMA_ATTRIB_I8N;
258
return LIMA_ATTRIB_I8;
260
else if (c->size == 16) {
262
return LIMA_ATTRIB_I16N;
264
return LIMA_ATTRIB_I16;
266
else if (c->size == 32) {
268
return LIMA_ATTRIB_I32N;
270
return LIMA_ATTRIB_I32;
273
case UTIL_FORMAT_TYPE_UNSIGNED:
276
return LIMA_ATTRIB_U8N;
278
return LIMA_ATTRIB_U8;
280
else if (c->size == 16) {
282
return LIMA_ATTRIB_U16N;
284
return LIMA_ATTRIB_U16;
286
else if (c->size == 32) {
288
return LIMA_ATTRIB_U32N;
290
return LIMA_ATTRIB_U32;
295
return LIMA_ATTRIB_FLOAT;
299
lima_pack_vs_cmd(struct lima_context *ctx, const struct pipe_draw_info *info,
300
const struct pipe_draw_start_count_bias *draw)
302
struct lima_context_constant_buffer *ccb =
303
ctx->const_buffer + PIPE_SHADER_VERTEX;
304
struct lima_vs_compiled_shader *vs = ctx->vs;
305
struct lima_job *job = lima_job_get(ctx);
307
VS_CMD_BEGIN(&job->vs_cmd_array, 24);
309
if (!info->index_size) {
310
VS_CMD_ARRAYS_SEMAPHORE_BEGIN_1();
311
VS_CMD_ARRAYS_SEMAPHORE_BEGIN_2();
313
int uniform_size = MIN2(vs->state.uniform_size, ccb->size);
315
int size = uniform_size + vs->state.constant_size + 32;
316
VS_CMD_UNIFORMS_ADDRESS(
317
lima_ctx_buff_va(ctx, lima_ctx_buff_gp_uniform),
320
VS_CMD_SHADER_ADDRESS(ctx->vs->bo->va, ctx->vs->state.shader_size);
321
VS_CMD_SHADER_INFO(ctx->vs->state.prefetch, ctx->vs->state.shader_size);
323
int num_outputs = ctx->vs->state.num_outputs;
324
int num_attributes = ctx->vertex_elements->num_elements;
325
VS_CMD_VARYING_ATTRIBUTE_COUNT(num_outputs, MAX2(1, num_attributes));
329
VS_CMD_ATTRIBUTES_ADDRESS(
330
lima_ctx_buff_va(ctx, lima_ctx_buff_gp_attribute_info),
331
MAX2(1, num_attributes));
333
VS_CMD_VARYINGS_ADDRESS(
334
lima_ctx_buff_va(ctx, lima_ctx_buff_gp_varying_info),
337
unsigned num = info->index_size ? (ctx->max_index - ctx->min_index + 1) : draw->count;
338
VS_CMD_DRAW(num, info->index_size);
342
VS_CMD_ARRAYS_SEMAPHORE_END(info->index_size);
348
lima_pack_plbu_cmd(struct lima_context *ctx, const struct pipe_draw_info *info,
349
const struct pipe_draw_start_count_bias *draw)
351
struct lima_vs_compiled_shader *vs = ctx->vs;
352
struct pipe_scissor_state *cscissor = &ctx->clipped_scissor;
353
struct lima_job *job = lima_job_get(ctx);
354
PLBU_CMD_BEGIN(&job->plbu_cmd_array, 32);
356
PLBU_CMD_VIEWPORT_LEFT(fui(ctx->ext_viewport.left));
357
PLBU_CMD_VIEWPORT_RIGHT(fui(ctx->ext_viewport.right));
358
PLBU_CMD_VIEWPORT_BOTTOM(fui(ctx->ext_viewport.bottom));
359
PLBU_CMD_VIEWPORT_TOP(fui(ctx->ext_viewport.top));
361
if (!info->index_size)
362
PLBU_CMD_ARRAYS_SEMAPHORE_BEGIN();
364
int cf = ctx->rasterizer->base.cull_face;
365
int ccw = ctx->rasterizer->base.front_ccw;
367
bool force_point_size = false;
369
if (cf != PIPE_FACE_NONE) {
370
if (cf & PIPE_FACE_FRONT)
371
cull |= ccw ? 0x00040000 : 0x00020000;
372
if (cf & PIPE_FACE_BACK)
373
cull |= ccw ? 0x00020000 : 0x00040000;
376
/* Specify point size with PLBU command if shader doesn't write */
377
if (info->mode == PIPE_PRIM_POINTS && ctx->vs->state.point_size_idx == -1)
378
force_point_size = true;
380
/* Specify line width with PLBU command for lines */
381
if (info->mode > PIPE_PRIM_POINTS && info->mode < PIPE_PRIM_TRIANGLES)
382
force_point_size = true;
384
PLBU_CMD_PRIMITIVE_SETUP(force_point_size, cull, info->index_size);
386
PLBU_CMD_RSW_VERTEX_ARRAY(
387
lima_ctx_buff_va(ctx, lima_ctx_buff_pp_plb_rsw),
391
* - we should set it only for the first draw that enabled the scissor and for
392
* latter draw only if scissor is dirty
395
assert(cscissor->minx < cscissor->maxx && cscissor->miny < cscissor->maxy);
396
PLBU_CMD_SCISSORS(cscissor->minx, cscissor->maxx, cscissor->miny, cscissor->maxy);
398
lima_damage_rect_union(&job->damage_rect, cscissor->minx, cscissor->maxx,
399
cscissor->miny, cscissor->maxy);
403
PLBU_CMD_DEPTH_RANGE_NEAR(fui(ctx->viewport.near));
404
PLBU_CMD_DEPTH_RANGE_FAR(fui(ctx->viewport.far));
406
if ((info->mode == PIPE_PRIM_POINTS && ctx->vs->state.point_size_idx == -1) ||
407
((info->mode >= PIPE_PRIM_LINES) && (info->mode < PIPE_PRIM_TRIANGLES)))
409
uint32_t v = info->mode == PIPE_PRIM_POINTS ?
410
fui(ctx->rasterizer->base.point_size) : fui(ctx->rasterizer->base.line_width);
411
PLBU_CMD_LOW_PRIM_SIZE(v);
414
if (info->index_size) {
415
PLBU_CMD_INDEXED_DEST(ctx->gp_output->va);
416
if (vs->state.point_size_idx != -1)
417
PLBU_CMD_INDEXED_PT_SIZE(ctx->gp_output->va + ctx->gp_output_point_size_offt);
419
PLBU_CMD_INDICES(ctx->index_res->bo->va + draw->start * info->index_size + ctx->index_offset);
422
/* can this make the attribute info static? */
423
PLBU_CMD_DRAW_ARRAYS(info->mode, draw->start, draw->count);
426
PLBU_CMD_ARRAYS_SEMAPHORE_END();
428
if (info->index_size)
429
PLBU_CMD_DRAW_ELEMENTS(info->mode, ctx->min_index, draw->count);
435
lima_blend_func(enum pipe_blend_func pipe)
440
case PIPE_BLEND_SUBTRACT:
442
case PIPE_BLEND_REVERSE_SUBTRACT:
453
lima_blend_factor(enum pipe_blendfactor pipe)
455
/* Bits 0-2 indicate the blendfactor type,
456
* Bit 3 is set if blendfactor is inverted
457
* Bit 4 is set if blendfactor has alpha */
459
case PIPE_BLENDFACTOR_SRC_COLOR:
460
return 0 << 4 | 0 << 3 | 0;
461
case PIPE_BLENDFACTOR_SRC_ALPHA:
462
return 1 << 4 | 0 << 3 | 0;
463
case PIPE_BLENDFACTOR_INV_SRC_COLOR:
464
return 0 << 4 | 1 << 3 | 0;
465
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
466
return 1 << 4 | 1 << 3 | 0;
468
case PIPE_BLENDFACTOR_DST_COLOR:
469
return 0 << 4 | 0 << 3 | 1;
470
case PIPE_BLENDFACTOR_DST_ALPHA:
471
return 1 << 4 | 0 << 3 | 1;
472
case PIPE_BLENDFACTOR_INV_DST_COLOR:
473
return 0 << 4 | 1 << 3 | 1;
474
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
475
return 1 << 4 | 1 << 3 | 1;
477
case PIPE_BLENDFACTOR_CONST_COLOR:
478
return 0 << 4 | 0 << 3 | 2;
479
case PIPE_BLENDFACTOR_CONST_ALPHA:
480
return 1 << 4 | 0 << 3 | 2;
481
case PIPE_BLENDFACTOR_INV_CONST_COLOR:
482
return 0 << 4 | 1 << 3 | 2;
483
case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
484
return 1 << 4 | 1 << 3 | 2;
486
case PIPE_BLENDFACTOR_ZERO:
487
return 0 << 4 | 0 << 3 | 3;
488
case PIPE_BLENDFACTOR_ONE:
489
return 0 << 4 | 1 << 3 | 3;
491
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
492
return 0 << 4 | 0 << 3 | 4;
494
case PIPE_BLENDFACTOR_SRC1_COLOR:
495
return 0 << 4 | 0 << 3 | 5;
496
case PIPE_BLENDFACTOR_SRC1_ALPHA:
497
return 1 << 4 | 0 << 3 | 5;
498
case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
499
return 0 << 4 | 1 << 3 | 5;
500
case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
501
return 1 << 4 | 1 << 3 | 5;
507
lima_calculate_alpha_blend(enum pipe_blend_func rgb_func, enum pipe_blend_func alpha_func,
508
enum pipe_blendfactor rgb_src_factor, enum pipe_blendfactor rgb_dst_factor,
509
enum pipe_blendfactor alpha_src_factor, enum pipe_blendfactor alpha_dst_factor)
511
/* PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE has to be changed to PIPE_BLENDFACTOR_ONE
512
* if it is set for alpha_src or alpha_dst.
514
if (alpha_src_factor == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE)
515
alpha_src_factor = PIPE_BLENDFACTOR_ONE;
517
if (alpha_dst_factor == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE)
518
alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
520
/* MIN and MAX ops actually do OP(As * S + Ad * D, Ad), so
521
* we need to set S to 1 and D to 0 to get correct result */
522
if (alpha_func == PIPE_BLEND_MIN ||
523
alpha_func == PIPE_BLEND_MAX) {
524
alpha_src_factor = PIPE_BLENDFACTOR_ONE;
525
alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
528
/* MIN and MAX ops actually do OP(Cs * S + Cd * D, Cd), so
529
* we need to set S to 1 and D to 0 to get correct result */
530
if (rgb_func == PIPE_BLEND_MIN ||
531
rgb_func == PIPE_BLEND_MAX) {
532
rgb_src_factor = PIPE_BLENDFACTOR_ONE;
533
rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
536
return lima_blend_func(rgb_func) |
537
(lima_blend_func(alpha_func) << 3) |
538
(lima_blend_factor(rgb_src_factor) << 6) |
539
(lima_blend_factor(rgb_dst_factor) << 11) |
540
/* alpha_src and alpha_dst are 4 bit, so need to mask 5th bit */
541
((lima_blend_factor(alpha_src_factor) & 0xf) << 16) |
542
((lima_blend_factor(alpha_dst_factor) & 0xf) << 20) |
543
0x0C000000; /* need to check if this is GLESv1 glAlphaFunc */
547
lima_stencil_op(enum pipe_stencil_op pipe)
550
case PIPE_STENCIL_OP_KEEP:
552
case PIPE_STENCIL_OP_ZERO:
554
case PIPE_STENCIL_OP_REPLACE:
556
case PIPE_STENCIL_OP_INCR:
558
case PIPE_STENCIL_OP_DECR:
560
case PIPE_STENCIL_OP_INCR_WRAP:
562
case PIPE_STENCIL_OP_DECR_WRAP:
564
case PIPE_STENCIL_OP_INVERT:
571
lima_calculate_depth_test(struct pipe_depth_stencil_alpha_state *depth,
572
struct pipe_rasterizer_state *rst)
574
int offset_scale = 0, offset_units = 0;
575
enum pipe_compare_func func = (depth->depth_enabled ? depth->depth_func : PIPE_FUNC_ALWAYS);
577
offset_scale = CLAMP(rst->offset_scale * 4, -128, 127);
578
if (offset_scale < 0)
579
offset_scale += 0x100;
581
offset_units = CLAMP(rst->offset_units * 2, -128, 127);
582
if (offset_units < 0)
583
offset_units += 0x100;
585
return (depth->depth_enabled && depth->depth_writemask) |
587
(offset_scale << 16) |
588
(offset_units << 24);
592
lima_pack_render_state(struct lima_context *ctx, const struct pipe_draw_info *info)
594
struct lima_fs_compiled_shader *fs = ctx->fs;
595
struct lima_render_state *render =
596
lima_ctx_buff_alloc(ctx, lima_ctx_buff_pp_plb_rsw,
599
bool pixel_kill = true;
601
/* do hw support RGBA independ blend?
602
* PIPE_CAP_INDEP_BLEND_ENABLE
604
* how to handle the no cbuf only zbuf case?
606
struct pipe_rt_blend_state *rt = ctx->blend->base.rt;
607
render->blend_color_bg = float_to_ubyte(ctx->blend_color.color[2]) |
608
(float_to_ubyte(ctx->blend_color.color[1]) << 16);
609
render->blend_color_ra = float_to_ubyte(ctx->blend_color.color[0]) |
610
(float_to_ubyte(ctx->blend_color.color[3]) << 16);
612
if (rt->blend_enable) {
613
render->alpha_blend = lima_calculate_alpha_blend(rt->rgb_func, rt->alpha_func,
614
rt->rgb_src_factor, rt->rgb_dst_factor,
615
rt->alpha_src_factor, rt->alpha_dst_factor);
619
* Special handling for blending disabled.
620
* Binary driver is generating the same alpha_value,
621
* as when we would just enable blending, without changing/setting any blend equation/params.
622
* Normaly in this case mesa would set all rt fields (func/factor) to zero.
624
render->alpha_blend = lima_calculate_alpha_blend(PIPE_BLEND_ADD, PIPE_BLEND_ADD,
625
PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ZERO,
626
PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ZERO);
629
render->alpha_blend |= (rt->colormask & PIPE_MASK_RGBA) << 28;
631
struct pipe_rasterizer_state *rst = &ctx->rasterizer->base;
632
render->depth_test = lima_calculate_depth_test(&ctx->zsa->base, rst);
634
if (!rst->depth_clip_near || ctx->viewport.near == 0.0f)
635
render->depth_test |= 0x10; /* don't clip depth near */
636
if (!rst->depth_clip_far || ctx->viewport.far == 1.0f)
637
render->depth_test |= 0x20; /* don't clip depth far */
639
if (fs->state.frag_depth_reg != -1) {
640
render->depth_test |= (fs->state.frag_depth_reg << 6);
641
/* Shader writes depth */
642
render->depth_test |= 0x801;
647
near = float_to_ushort(ctx->viewport.near);
648
far = float_to_ushort(ctx->viewport.far);
650
/* overlap with plbu? any place can remove one? */
651
render->depth_range = near | (far << 16);
653
struct pipe_stencil_state *stencil = ctx->zsa->base.stencil;
654
struct pipe_stencil_ref *ref = &ctx->stencil_ref;
656
if (stencil[0].enabled) { /* stencil is enabled */
657
render->stencil_front = stencil[0].func |
658
(lima_stencil_op(stencil[0].fail_op) << 3) |
659
(lima_stencil_op(stencil[0].zfail_op) << 6) |
660
(lima_stencil_op(stencil[0].zpass_op) << 9) |
661
(ref->ref_value[0] << 16) |
662
(stencil[0].valuemask << 24);
663
render->stencil_back = render->stencil_front;
664
render->stencil_test = (stencil[0].writemask & 0xff) | (stencil[0].writemask & 0xff) << 8;
665
if (stencil[1].enabled) { /* two-side is enabled */
666
render->stencil_back = stencil[1].func |
667
(lima_stencil_op(stencil[1].fail_op) << 3) |
668
(lima_stencil_op(stencil[1].zfail_op) << 6) |
669
(lima_stencil_op(stencil[1].zpass_op) << 9) |
670
(ref->ref_value[1] << 16) |
671
(stencil[1].valuemask << 24);
672
render->stencil_test = (stencil[0].writemask & 0xff) | (stencil[1].writemask & 0xff) << 8;
674
/* TODO: Find out, what (render->stecil_test & 0xff000000) is */
677
/* Default values, when stencil is disabled:
678
* stencil[0|1].valuemask = 0xff
679
* stencil[0|1].func = PIPE_FUNC_ALWAYS
680
* stencil[0|1].writemask = 0xff
682
render->stencil_front = 0xff000007;
683
render->stencil_back = 0xff000007;
684
render->stencil_test = 0x0000ffff;
687
/* need more investigation */
688
if (info->mode == PIPE_PRIM_POINTS)
689
render->multi_sample = 0x0000F000;
690
else if (info->mode < PIPE_PRIM_TRIANGLES)
691
render->multi_sample = 0x0000F400;
693
render->multi_sample = 0x0000F800;
694
if (ctx->framebuffer.base.samples)
695
render->multi_sample |= 0x68;
697
/* Set gl_FragColor register, need to specify it 4 times */
698
render->multi_sample |= (fs->state.frag_color0_reg << 28) |
699
(fs->state.frag_color0_reg << 24) |
700
(fs->state.frag_color0_reg << 20) |
701
(fs->state.frag_color0_reg << 16);
704
if (ctx->zsa->base.alpha_enabled) {
705
render->multi_sample |= ctx->zsa->base.alpha_func;
706
render->stencil_test |= float_to_ubyte(ctx->zsa->base.alpha_ref_value) << 16;
708
/* func = PIPE_FUNC_ALWAYS */
709
render->multi_sample |= 0x7;
712
render->shader_address =
713
ctx->fs->bo->va | (((uint32_t *)ctx->fs->bo->map)[0] & 0x1F);
715
/* seems not needed */
716
render->uniforms_address = 0x00000000;
718
render->textures_address = 0x00000000;
720
render->aux0 = (ctx->vs->state.varying_stride >> 3);
721
render->aux1 = 0x00000000;
722
if (ctx->rasterizer->base.front_ccw)
723
render->aux1 = 0x00001000;
725
if (ctx->blend->base.dither)
726
render->aux1 |= 0x00002000;
728
if (fs->state.uses_discard ||
729
ctx->zsa->base.alpha_enabled ||
730
fs->state.frag_depth_reg != -1) {
735
if (rt->blend_enable)
738
if ((rt->colormask & PIPE_MASK_RGBA) != PIPE_MASK_RGBA)
742
render->aux0 |= 0x300;
745
render->aux0 |= 0x1000;
747
if (ctx->tex_stateobj.num_samplers) {
748
render->textures_address =
749
lima_ctx_buff_va(ctx, lima_ctx_buff_pp_tex_desc);
750
render->aux0 |= ctx->tex_stateobj.num_samplers << 14;
751
render->aux0 |= 0x20;
754
if (ctx->const_buffer[PIPE_SHADER_FRAGMENT].buffer) {
755
render->uniforms_address =
756
lima_ctx_buff_va(ctx, lima_ctx_buff_pp_uniform_array);
757
uint32_t size = ctx->buffer_state[lima_ctx_buff_pp_uniform].size;
760
bits = util_last_bit(size >> 3) - 1;
761
bits += size & u_bit_consecutive(0, bits + 3) ? 1 : 0;
763
render->uniforms_address |= bits > 0xf ? 0xf : bits;
765
render->aux0 |= 0x80;
766
render->aux1 |= 0x10000;
769
/* Set secondary output color */
770
if (fs->state.frag_color1_reg != -1)
771
render->aux0 |= (fs->state.frag_color1_reg << 28);
773
if (ctx->vs->state.num_varyings) {
774
render->varying_types = 0x00000000;
775
render->varyings_address = ctx->gp_output->va +
776
ctx->gp_output_varyings_offt;
777
for (int i = 0, index = 0; i < ctx->vs->state.num_outputs; i++) {
780
if (i == ctx->vs->state.gl_pos_idx ||
781
i == ctx->vs->state.point_size_idx)
784
struct lima_varying_info *v = ctx->vs->state.varying + i;
785
if (v->component_size == 4)
786
val = v->components > 2 ? 0 : 1;
788
val = v->components > 2 ? 2 : 3;
791
render->varying_types |= val << (3 * index);
792
else if (index == 10) {
793
render->varying_types |= val << 30;
794
render->varyings_address |= val >> 2;
796
else if (index == 11)
797
render->varyings_address |= val << 1;
803
render->varying_types = 0x00000000;
804
render->varyings_address = 0x00000000;
807
struct lima_job *job = lima_job_get(ctx);
809
lima_dump_command_stream_print(
810
job->dump, render, sizeof(*render),
811
false, "add render state at va %x\n",
812
lima_ctx_buff_va(ctx, lima_ctx_buff_pp_plb_rsw));
814
lima_dump_rsw_command_stream_print(
815
job->dump, render, sizeof(*render),
816
lima_ctx_buff_va(ctx, lima_ctx_buff_pp_plb_rsw));
820
lima_update_gp_attribute_info(struct lima_context *ctx, const struct pipe_draw_info *info,
821
const struct pipe_draw_start_count_bias *draw)
823
struct lima_job *job = lima_job_get(ctx);
824
struct lima_vertex_element_state *ve = ctx->vertex_elements;
825
struct lima_context_vertex_buffer *vb = &ctx->vertex_buffers;
827
uint32_t *attribute =
828
lima_ctx_buff_alloc(ctx, lima_ctx_buff_gp_attribute_info,
829
MAX2(1, ve->num_elements) * 8);
832
for (int i = 0; i < ve->num_elements; i++) {
833
struct pipe_vertex_element *pve = ve->pipe + i;
835
assert(pve->vertex_buffer_index < vb->count);
836
assert(vb->enabled_mask & (1 << pve->vertex_buffer_index));
838
struct pipe_vertex_buffer *pvb = vb->vb + pve->vertex_buffer_index;
839
struct lima_resource *res = lima_resource(pvb->buffer.resource);
841
lima_job_add_bo(job, LIMA_PIPE_GP, res->bo, LIMA_SUBMIT_BO_READ);
843
unsigned start = info->index_size ? (ctx->min_index + draw->index_bias) : draw->start;
844
attribute[n++] = res->bo->va + pvb->buffer_offset + pve->src_offset
845
+ start * pvb->stride;
846
attribute[n++] = (pvb->stride << 11) |
847
(lima_pipe_format_to_attrib_type(pve->src_format) << 2) |
848
(util_format_get_nr_components(pve->src_format) - 1);
851
lima_dump_command_stream_print(
852
job->dump, attribute, n * 4, false, "update attribute info at va %x\n",
853
lima_ctx_buff_va(ctx, lima_ctx_buff_gp_attribute_info));
857
lima_update_gp_uniform(struct lima_context *ctx)
859
struct lima_context_constant_buffer *ccb =
860
ctx->const_buffer + PIPE_SHADER_VERTEX;
861
struct lima_vs_compiled_shader *vs = ctx->vs;
862
int uniform_size = MIN2(vs->state.uniform_size, ccb->size);
864
int size = uniform_size + vs->state.constant_size + 32;
865
void *vs_const_buff =
866
lima_ctx_buff_alloc(ctx, lima_ctx_buff_gp_uniform, size);
869
memcpy(vs_const_buff, ccb->buffer, uniform_size);
871
memcpy(vs_const_buff + uniform_size,
872
ctx->viewport.transform.scale,
873
sizeof(ctx->viewport.transform.scale));
874
memcpy(vs_const_buff + uniform_size + 16,
875
ctx->viewport.transform.translate,
876
sizeof(ctx->viewport.transform.translate));
879
memcpy(vs_const_buff + uniform_size + 32,
880
vs->constant, vs->state.constant_size);
882
struct lima_job *job = lima_job_get(ctx);
884
if (lima_debug & LIMA_DEBUG_GP) {
885
float *vs_const_buff_f = vs_const_buff;
886
printf("gp uniforms:\n");
887
for (int i = 0; i < (size / sizeof(float)); i++) {
889
printf("%4d:", i / 4);
890
printf(" %8.4f", vs_const_buff_f[i]);
897
lima_dump_command_stream_print(
898
job->dump, vs_const_buff, size, true,
899
"update gp uniform at va %x\n",
900
lima_ctx_buff_va(ctx, lima_ctx_buff_gp_uniform));
904
lima_update_pp_uniform(struct lima_context *ctx)
906
const float *const_buff = ctx->const_buffer[PIPE_SHADER_FRAGMENT].buffer;
907
size_t const_buff_size = ctx->const_buffer[PIPE_SHADER_FRAGMENT].size / sizeof(float);
912
uint16_t *fp16_const_buff =
913
lima_ctx_buff_alloc(ctx, lima_ctx_buff_pp_uniform,
914
const_buff_size * sizeof(uint16_t));
917
lima_ctx_buff_alloc(ctx, lima_ctx_buff_pp_uniform_array, 4);
919
for (int i = 0; i < const_buff_size; i++)
920
fp16_const_buff[i] = _mesa_float_to_half(const_buff[i]);
922
*array = lima_ctx_buff_va(ctx, lima_ctx_buff_pp_uniform);
924
struct lima_job *job = lima_job_get(ctx);
926
lima_dump_command_stream_print(
927
job->dump, fp16_const_buff, const_buff_size * 2,
928
false, "add pp uniform data at va %x\n",
929
lima_ctx_buff_va(ctx, lima_ctx_buff_pp_uniform));
930
lima_dump_command_stream_print(
931
job->dump, array, 4, false, "add pp uniform info at va %x\n",
932
lima_ctx_buff_va(ctx, lima_ctx_buff_pp_uniform_array));
936
lima_update_varying(struct lima_context *ctx, const struct pipe_draw_info *info,
937
const struct pipe_draw_start_count_bias *draw)
939
struct lima_job *job = lima_job_get(ctx);
940
struct lima_screen *screen = lima_screen(ctx->base.screen);
941
struct lima_vs_compiled_shader *vs = ctx->vs;
942
uint32_t gp_output_size;
943
unsigned num = info->index_size ? (ctx->max_index - ctx->min_index + 1) : draw->count;
946
lima_ctx_buff_alloc(ctx, lima_ctx_buff_gp_varying_info,
947
vs->state.num_outputs * 8);
952
for (int i = 0; i < vs->state.num_outputs; i++) {
953
struct lima_varying_info *v = vs->state.varying + i;
955
if (i == vs->state.gl_pos_idx ||
956
i == vs->state.point_size_idx)
959
int size = v->component_size * 4;
961
/* does component_size == 2 need to be 16 aligned? */
962
if (v->component_size == 4)
963
offset = align(offset, 16);
969
vs->state.varying_stride = align(offset, 16);
971
/* gl_Position is always present, allocate space for it */
972
gp_output_size = align(4 * 4 * num, 0x40);
974
/* Allocate space for varyings if there're any */
975
if (vs->state.num_varyings) {
976
ctx->gp_output_varyings_offt = gp_output_size;
977
gp_output_size += align(vs->state.varying_stride * num, 0x40);
980
/* Allocate space for gl_PointSize if it's there */
981
if (vs->state.point_size_idx != -1) {
982
ctx->gp_output_point_size_offt = gp_output_size;
983
gp_output_size += 4 * num;
986
/* gp_output can be too large for the suballocator, so create a
987
* separate bo for it. The bo cache should prevent performance hit.
989
ctx->gp_output = lima_bo_create(screen, gp_output_size, 0);
990
assert(ctx->gp_output);
991
lima_job_add_bo(job, LIMA_PIPE_GP, ctx->gp_output, LIMA_SUBMIT_BO_WRITE);
992
lima_job_add_bo(job, LIMA_PIPE_PP, ctx->gp_output, LIMA_SUBMIT_BO_READ);
994
for (int i = 0; i < vs->state.num_outputs; i++) {
995
struct lima_varying_info *v = vs->state.varying + i;
997
if (i == vs->state.gl_pos_idx) {
999
varying[n++] = ctx->gp_output->va;
1000
varying[n++] = 0x8020;
1001
} else if (i == vs->state.point_size_idx) {
1003
varying[n++] = ctx->gp_output->va + ctx->gp_output_point_size_offt;
1004
varying[n++] = 0x2021;
1007
varying[n++] = ctx->gp_output->va + ctx->gp_output_varyings_offt +
1009
varying[n++] = (vs->state.varying_stride << 11) | (v->components - 1) |
1010
(v->component_size == 2 ? 0x0C : 0);
1014
lima_dump_command_stream_print(
1015
job->dump, varying, n * 4, false, "update varying info at va %x\n",
1016
lima_ctx_buff_va(ctx, lima_ctx_buff_gp_varying_info));
1020
lima_draw_vbo_update(struct pipe_context *pctx,
1021
const struct pipe_draw_info *info,
1022
const struct pipe_draw_start_count_bias *draw)
1024
struct lima_context *ctx = lima_context(pctx);
1025
struct lima_context_framebuffer *fb = &ctx->framebuffer;
1026
unsigned buffers = 0;
1028
if (fb->base.zsbuf) {
1029
if (ctx->zsa->base.depth_enabled)
1030
buffers |= PIPE_CLEAR_DEPTH;
1031
if (ctx->zsa->base.stencil[0].enabled ||
1032
ctx->zsa->base.stencil[1].enabled)
1033
buffers |= PIPE_CLEAR_STENCIL;
1036
if (fb->base.nr_cbufs)
1037
buffers |= PIPE_CLEAR_COLOR0;
1039
lima_update_job_wb(ctx, buffers);
1041
lima_update_gp_attribute_info(ctx, info, draw);
1043
if ((ctx->dirty & LIMA_CONTEXT_DIRTY_CONST_BUFF &&
1044
ctx->const_buffer[PIPE_SHADER_VERTEX].dirty) ||
1045
ctx->dirty & LIMA_CONTEXT_DIRTY_VIEWPORT ||
1046
ctx->dirty & LIMA_CONTEXT_DIRTY_COMPILED_VS) {
1047
lima_update_gp_uniform(ctx);
1048
ctx->const_buffer[PIPE_SHADER_VERTEX].dirty = false;
1051
lima_update_varying(ctx, info, draw);
1053
lima_pack_vs_cmd(ctx, info, draw);
1055
if (ctx->dirty & LIMA_CONTEXT_DIRTY_CONST_BUFF &&
1056
ctx->const_buffer[PIPE_SHADER_FRAGMENT].dirty) {
1057
lima_update_pp_uniform(ctx);
1058
ctx->const_buffer[PIPE_SHADER_FRAGMENT].dirty = false;
1061
lima_update_textures(ctx);
1063
lima_pack_render_state(ctx, info);
1064
lima_pack_plbu_cmd(ctx, info, draw);
1066
if (ctx->gp_output) {
1067
lima_bo_unreference(ctx->gp_output); /* held by job */
1068
ctx->gp_output = NULL;
1075
lima_draw_vbo_indexed(struct pipe_context *pctx,
1076
const struct pipe_draw_info *info,
1077
const struct pipe_draw_start_count_bias *draw)
1079
struct lima_context *ctx = lima_context(pctx);
1080
struct lima_job *job = lima_job_get(ctx);
1081
struct pipe_resource *indexbuf = NULL;
1082
bool needs_indices = true;
1084
/* Mali Utgard GPU always need min/max index info for index draw,
1085
* compute it if upper layer does not do for us */
1086
if (info->index_bounds_valid) {
1087
ctx->min_index = info->min_index;
1088
ctx->max_index = info->max_index;
1089
needs_indices = false;
1092
if (info->has_user_indices) {
1093
util_upload_index_buffer(&ctx->base, info, draw, &indexbuf, &ctx->index_offset, 0x40);
1094
ctx->index_res = lima_resource(indexbuf);
1097
ctx->index_res = lima_resource(info->index.resource);
1098
ctx->index_offset = 0;
1099
needs_indices = !panfrost_minmax_cache_get(ctx->index_res->index_cache, draw->start,
1100
draw->count, &ctx->min_index, &ctx->max_index);
1103
if (needs_indices) {
1104
u_vbuf_get_minmax_index(pctx, info, draw, &ctx->min_index, &ctx->max_index);
1105
if (!info->has_user_indices)
1106
panfrost_minmax_cache_add(ctx->index_res->index_cache, draw->start, draw->count,
1107
ctx->min_index, ctx->max_index);
1110
lima_job_add_bo(job, LIMA_PIPE_GP, ctx->index_res->bo, LIMA_SUBMIT_BO_READ);
1111
lima_job_add_bo(job, LIMA_PIPE_PP, ctx->index_res->bo, LIMA_SUBMIT_BO_READ);
1112
lima_draw_vbo_update(pctx, info, draw);
1115
pipe_resource_reference(&indexbuf, NULL);
1119
lima_draw_vbo_count(struct pipe_context *pctx,
1120
const struct pipe_draw_info *info,
1121
const struct pipe_draw_start_count_bias *draw)
1123
static const uint32_t max_verts = 65535;
1125
struct pipe_draw_start_count_bias local_draw = *draw;
1126
unsigned start = draw->start;
1127
unsigned count = draw->count;
1130
unsigned this_count = count;
1133
u_split_draw(info, max_verts, &this_count, &step);
1135
local_draw.start = start;
1136
local_draw.count = this_count;
1138
lima_draw_vbo_update(pctx, info, &local_draw);
1146
lima_draw_vbo(struct pipe_context *pctx,
1147
const struct pipe_draw_info *info,
1148
unsigned drawid_offset,
1149
const struct pipe_draw_indirect_info *indirect,
1150
const struct pipe_draw_start_count_bias *draws,
1153
if (num_draws > 1) {
1154
util_draw_multi(pctx, info, drawid_offset, indirect, draws, num_draws);
1158
/* check if draw mode and vertex/index count match,
1159
* otherwise gp will hang */
1160
if (!u_trim_pipe_prim(info->mode, (unsigned*)&draws[0].count)) {
1161
debug_printf("draw mode and vertex/index count mismatch\n");
1165
struct lima_context *ctx = lima_context(pctx);
1167
if (!ctx->uncomp_fs || !ctx->uncomp_vs) {
1168
debug_warn_once("no shader, skip draw\n");
1172
lima_clip_scissor_to_viewport(ctx);
1173
if (lima_is_scissor_zero(ctx))
1176
/* extend the viewport in case of line draws with a line_width > 1.0f,
1177
* otherwise use the original values */
1178
lima_extend_viewport(ctx, info);
1180
if (!lima_update_fs_state(ctx) || !lima_update_vs_state(ctx))
1183
struct lima_job *job = lima_job_get(ctx);
1184
job->pp_max_stack_size = MAX2(job->pp_max_stack_size, ctx->fs->state.stack_size);
1186
lima_dump_command_stream_print(
1187
job->dump, ctx->vs->bo->map, ctx->vs->state.shader_size, false,
1188
"add vs at va %x\n", ctx->vs->bo->va);
1189
lima_dump_shader(job->dump, ctx->vs->bo->map, ctx->vs->state.shader_size, false);
1191
lima_dump_command_stream_print(
1192
job->dump, ctx->fs->bo->map, ctx->fs->state.shader_size, false,
1193
"add fs at va %x\n", ctx->fs->bo->va);
1194
lima_dump_shader(job->dump, ctx->fs->bo->map, ctx->fs->state.shader_size, true);
1196
lima_job_add_bo(job, LIMA_PIPE_GP, ctx->vs->bo, LIMA_SUBMIT_BO_READ);
1197
lima_job_add_bo(job, LIMA_PIPE_PP, ctx->fs->bo, LIMA_SUBMIT_BO_READ);
1199
if (info->index_size)
1200
lima_draw_vbo_indexed(pctx, info, &draws[0]);
1202
lima_draw_vbo_count(pctx, info, &draws[0]);
1205
/* Flush job if we hit the limit of draws per job otherwise we may
1206
* hit tile heap size limit */
1207
if (job->draws > MAX_DRAWS_PER_JOB) {
1208
unsigned resolve = job->resolve;
1210
/* Subsequent job will need to resolve the same buffers */
1211
lima_update_job_wb(ctx, resolve);
1216
lima_draw_init(struct lima_context *ctx)
1218
ctx->base.clear = lima_clear;
1219
ctx->base.draw_vbo = lima_draw_vbo;