~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/gallium/drivers/lima/lima_draw.c

  • Committer: mmach
  • Date: 2022-09-22 19:56:13 UTC
  • Revision ID: netbit73@gmail.com-20220922195613-wtik9mmy20tmor0i
2022-09-22 21:17:09

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (c) 2011-2013 Luc Verhaegen <libv@skynet.be>
3
 
 * Copyright (c) 2017-2019 Lima Project
4
 
 *
5
 
 * Permission is hereby granted, free of charge, to any person obtaining a
6
 
 * copy of this software and associated documentation files (the "Software"),
7
 
 * to deal in the Software without restriction, including without limitation
8
 
 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9
 
 * and/or sell copies of the Software, and to permit persons to whom the
10
 
 * Software is furnished to do so, subject to the following conditions:
11
 
 *
12
 
 * The above copyright notice and this permission notice (including the
13
 
 * next paragraph) shall be included in all copies or substantial portions
14
 
 * of the Software.
15
 
 *
16
 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19
 
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
 
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
 
 * DEALINGS IN THE SOFTWARE.
23
 
 *
24
 
 */
25
 
 
26
 
#include "util/format/u_format.h"
27
 
#include "util/u_debug.h"
28
 
#include "util/u_draw.h"
29
 
#include "util/half_float.h"
30
 
#include "util/u_helpers.h"
31
 
#include "util/u_inlines.h"
32
 
#include "util/u_pack_color.h"
33
 
#include "util/u_split_draw.h"
34
 
#include "util/u_upload_mgr.h"
35
 
#include "util/u_prim.h"
36
 
#include "util/u_vbuf.h"
37
 
#include "util/hash_table.h"
38
 
 
39
 
#include "lima_context.h"
40
 
#include "lima_screen.h"
41
 
#include "lima_resource.h"
42
 
#include "lima_program.h"
43
 
#include "lima_bo.h"
44
 
#include "lima_job.h"
45
 
#include "lima_texture.h"
46
 
#include "lima_util.h"
47
 
#include "lima_gpu.h"
48
 
 
49
 
#include "pan_minmax_cache.h"
50
 
 
51
 
#include <drm-uapi/lima_drm.h>
52
 
 
53
 
static void
54
 
lima_clip_scissor_to_viewport(struct lima_context *ctx)
55
 
{
56
 
   struct lima_context_framebuffer *fb = &ctx->framebuffer;
57
 
   struct pipe_scissor_state *cscissor = &ctx->clipped_scissor;
58
 
   int viewport_left, viewport_right, viewport_bottom, viewport_top;
59
 
 
60
 
   if (ctx->rasterizer && ctx->rasterizer->base.scissor) {
61
 
      struct pipe_scissor_state *scissor = &ctx->scissor;
62
 
      cscissor->minx = scissor->minx;
63
 
      cscissor->maxx = scissor->maxx;
64
 
      cscissor->miny = scissor->miny;
65
 
      cscissor->maxy = scissor->maxy;
66
 
   } else {
67
 
      cscissor->minx = 0;
68
 
      cscissor->maxx = fb->base.width;
69
 
      cscissor->miny = 0;
70
 
      cscissor->maxy = fb->base.height;
71
 
   }
72
 
 
73
 
   viewport_left = MAX2(ctx->viewport.left, 0);
74
 
   cscissor->minx = MAX2(cscissor->minx, viewport_left);
75
 
   viewport_right = MIN2(MAX2(ctx->viewport.right, 0), fb->base.width);
76
 
   cscissor->maxx = MIN2(cscissor->maxx, viewport_right);
77
 
   if (cscissor->minx > cscissor->maxx)
78
 
      cscissor->minx = cscissor->maxx;
79
 
 
80
 
   viewport_bottom = MAX2(ctx->viewport.bottom, 0);
81
 
   cscissor->miny = MAX2(cscissor->miny, viewport_bottom);
82
 
   viewport_top = MIN2(MAX2(ctx->viewport.top, 0), fb->base.height);
83
 
   cscissor->maxy = MIN2(cscissor->maxy, viewport_top);
84
 
   if (cscissor->miny > cscissor->maxy)
85
 
      cscissor->miny = cscissor->maxy;
86
 
}
87
 
 
88
 
static void
89
 
lima_extend_viewport(struct lima_context *ctx, const struct pipe_draw_info *info)
90
 
{
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;
96
 
 
97
 
   if (info->mode != PIPE_PRIM_LINES)
98
 
      return;
99
 
 
100
 
   if (!ctx->rasterizer)
101
 
      return;
102
 
 
103
 
   float line_width = ctx->rasterizer->base.line_width;
104
 
 
105
 
   if (line_width == 1.0f)
106
 
      return;
107
 
 
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;
112
 
}
113
 
 
114
 
static bool
115
 
lima_is_scissor_zero(struct lima_context *ctx)
116
 
{
117
 
   struct pipe_scissor_state *cscissor = &ctx->clipped_scissor;
118
 
 
119
 
   return cscissor->minx == cscissor->maxx || cscissor->miny == cscissor->maxy;
120
 
}
121
 
 
122
 
static void
123
 
lima_update_job_wb(struct lima_context *ctx, unsigned buffers)
124
 
{
125
 
   struct lima_job *job = lima_job_get(ctx);
126
 
   struct lima_context_framebuffer *fb = &ctx->framebuffer;
127
 
 
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);
135
 
   }
136
 
 
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);
144
 
   }
145
 
 
146
 
   job->resolve |= buffers;
147
 
}
148
 
 
149
 
static void
150
 
lima_damage_rect_union(struct pipe_scissor_state *rect,
151
 
                       unsigned minx, unsigned maxx,
152
 
                       unsigned miny, unsigned maxy)
153
 
{
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);
158
 
}
159
 
 
160
 
static void
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)
163
 
{
164
 
   struct lima_context *ctx = lima_context(pctx);
165
 
   struct lima_job *job = lima_job_get(ctx);
166
 
 
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)) {
170
 
      lima_do_job(job);
171
 
      job = lima_job_get(ctx);
172
 
   }
173
 
 
174
 
   lima_update_job_wb(ctx, buffers);
175
 
 
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;
180
 
   }
181
 
 
182
 
   struct lima_job_clear *clear = &job->clear;
183
 
   clear->buffers = buffers;
184
 
 
185
 
   if (buffers & PIPE_CLEAR_COLOR0) {
186
 
      clear->color_8pc =
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]);
191
 
 
192
 
      clear->color_16pc =
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]);
197
 
   }
198
 
 
199
 
   struct lima_surface *zsbuf = lima_surface(ctx->framebuffer.base.zsbuf);
200
 
 
201
 
   if (buffers & PIPE_CLEAR_DEPTH) {
202
 
      clear->depth = util_pack_z(PIPE_FORMAT_Z24X8_UNORM, depth);
203
 
      if (zsbuf)
204
 
         zsbuf->reload &= ~PIPE_CLEAR_DEPTH;
205
 
   }
206
 
 
207
 
   if (buffers & PIPE_CLEAR_STENCIL) {
208
 
      clear->stencil = stencil;
209
 
      if (zsbuf)
210
 
         zsbuf->reload &= ~PIPE_CLEAR_STENCIL;
211
 
   }
212
 
 
213
 
   ctx->dirty |= LIMA_CONTEXT_DIRTY_CLEAR;
214
 
 
215
 
   lima_damage_rect_union(&job->damage_rect,
216
 
                          0, ctx->framebuffer.base.width,
217
 
                          0, ctx->framebuffer.base.height);
218
 
}
219
 
 
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
236
 
};
237
 
 
238
 
static enum lima_attrib_type
239
 
lima_pipe_format_to_attrib_type(enum pipe_format format)
240
 
{
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;
244
 
 
245
 
   switch (c->type) {
246
 
   case UTIL_FORMAT_TYPE_FLOAT:
247
 
      if (c->size == 16)
248
 
         return LIMA_ATTRIB_FP16;
249
 
      else
250
 
         return LIMA_ATTRIB_FLOAT;
251
 
   case UTIL_FORMAT_TYPE_FIXED:
252
 
      return LIMA_ATTRIB_FIXED;
253
 
   case UTIL_FORMAT_TYPE_SIGNED:
254
 
      if (c->size == 8) {
255
 
         if (c->normalized)
256
 
            return LIMA_ATTRIB_I8N;
257
 
         else
258
 
            return LIMA_ATTRIB_I8;
259
 
      }
260
 
      else if (c->size == 16) {
261
 
         if (c->normalized)
262
 
            return LIMA_ATTRIB_I16N;
263
 
         else
264
 
            return LIMA_ATTRIB_I16;
265
 
      }
266
 
      else if (c->size == 32) {
267
 
         if (c->normalized)
268
 
            return LIMA_ATTRIB_I32N;
269
 
         else
270
 
            return LIMA_ATTRIB_I32;
271
 
      }
272
 
      break;
273
 
   case UTIL_FORMAT_TYPE_UNSIGNED:
274
 
      if (c->size == 8) {
275
 
         if (c->normalized)
276
 
            return LIMA_ATTRIB_U8N;
277
 
         else
278
 
            return LIMA_ATTRIB_U8;
279
 
      }
280
 
      else if (c->size == 16) {
281
 
         if (c->normalized)
282
 
            return LIMA_ATTRIB_U16N;
283
 
         else
284
 
            return LIMA_ATTRIB_U16;
285
 
      }
286
 
      else if (c->size == 32) {
287
 
         if (c->normalized)
288
 
            return LIMA_ATTRIB_U32N;
289
 
         else
290
 
            return LIMA_ATTRIB_U32;
291
 
      }
292
 
      break;
293
 
   }
294
 
 
295
 
   return LIMA_ATTRIB_FLOAT;
296
 
}
297
 
 
298
 
static void
299
 
lima_pack_vs_cmd(struct lima_context *ctx, const struct pipe_draw_info *info,
300
 
                 const struct pipe_draw_start_count_bias *draw)
301
 
{
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);
306
 
 
307
 
   VS_CMD_BEGIN(&job->vs_cmd_array, 24);
308
 
 
309
 
   if (!info->index_size) {
310
 
      VS_CMD_ARRAYS_SEMAPHORE_BEGIN_1();
311
 
      VS_CMD_ARRAYS_SEMAPHORE_BEGIN_2();
312
 
   }
313
 
   int uniform_size = MIN2(vs->state.uniform_size, ccb->size);
314
 
 
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),
318
 
      align(size, 16));
319
 
 
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);
322
 
 
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));
326
 
 
327
 
   VS_CMD_UNKNOWN1();
328
 
 
329
 
   VS_CMD_ATTRIBUTES_ADDRESS(
330
 
      lima_ctx_buff_va(ctx, lima_ctx_buff_gp_attribute_info),
331
 
      MAX2(1, num_attributes));
332
 
 
333
 
   VS_CMD_VARYINGS_ADDRESS(
334
 
      lima_ctx_buff_va(ctx, lima_ctx_buff_gp_varying_info),
335
 
      num_outputs);
336
 
 
337
 
   unsigned num = info->index_size ? (ctx->max_index - ctx->min_index + 1) : draw->count;
338
 
   VS_CMD_DRAW(num, info->index_size);
339
 
 
340
 
   VS_CMD_UNKNOWN2();
341
 
 
342
 
   VS_CMD_ARRAYS_SEMAPHORE_END(info->index_size);
343
 
 
344
 
   VS_CMD_END();
345
 
}
346
 
 
347
 
static void
348
 
lima_pack_plbu_cmd(struct lima_context *ctx, const struct pipe_draw_info *info,
349
 
                   const struct pipe_draw_start_count_bias *draw)
350
 
{
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);
355
 
 
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));
360
 
 
361
 
   if (!info->index_size)
362
 
      PLBU_CMD_ARRAYS_SEMAPHORE_BEGIN();
363
 
 
364
 
   int cf = ctx->rasterizer->base.cull_face;
365
 
   int ccw = ctx->rasterizer->base.front_ccw;
366
 
   uint32_t cull = 0;
367
 
   bool force_point_size = false;
368
 
 
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;
374
 
   }
375
 
 
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;
379
 
 
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;
383
 
 
384
 
   PLBU_CMD_PRIMITIVE_SETUP(force_point_size, cull, info->index_size);
385
 
 
386
 
   PLBU_CMD_RSW_VERTEX_ARRAY(
387
 
      lima_ctx_buff_va(ctx, lima_ctx_buff_pp_plb_rsw),
388
 
      ctx->gp_output->va);
389
 
 
390
 
   /* TODO
391
 
    * - we should set it only for the first draw that enabled the scissor and for
392
 
    *   latter draw only if scissor is dirty
393
 
    */
394
 
 
395
 
   assert(cscissor->minx < cscissor->maxx && cscissor->miny < cscissor->maxy);
396
 
   PLBU_CMD_SCISSORS(cscissor->minx, cscissor->maxx, cscissor->miny, cscissor->maxy);
397
 
 
398
 
   lima_damage_rect_union(&job->damage_rect, cscissor->minx, cscissor->maxx,
399
 
                          cscissor->miny, cscissor->maxy);
400
 
 
401
 
   PLBU_CMD_UNKNOWN1();
402
 
 
403
 
   PLBU_CMD_DEPTH_RANGE_NEAR(fui(ctx->viewport.near));
404
 
   PLBU_CMD_DEPTH_RANGE_FAR(fui(ctx->viewport.far));
405
 
 
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)))
408
 
   {
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);
412
 
   }
413
 
 
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);
418
 
 
419
 
      PLBU_CMD_INDICES(ctx->index_res->bo->va + draw->start * info->index_size + ctx->index_offset);
420
 
   }
421
 
   else {
422
 
      /* can this make the attribute info static? */
423
 
      PLBU_CMD_DRAW_ARRAYS(info->mode, draw->start, draw->count);
424
 
   }
425
 
 
426
 
   PLBU_CMD_ARRAYS_SEMAPHORE_END();
427
 
 
428
 
   if (info->index_size)
429
 
      PLBU_CMD_DRAW_ELEMENTS(info->mode, ctx->min_index, draw->count);
430
 
 
431
 
   PLBU_CMD_END();
432
 
}
433
 
 
434
 
static int
435
 
lima_blend_func(enum pipe_blend_func pipe)
436
 
{
437
 
   switch (pipe) {
438
 
   case PIPE_BLEND_ADD:
439
 
      return 2;
440
 
   case PIPE_BLEND_SUBTRACT:
441
 
      return 0;
442
 
   case PIPE_BLEND_REVERSE_SUBTRACT:
443
 
      return 1;
444
 
   case PIPE_BLEND_MIN:
445
 
      return 4;
446
 
   case PIPE_BLEND_MAX:
447
 
      return 5;
448
 
   }
449
 
   return -1;
450
 
}
451
 
 
452
 
static int
453
 
lima_blend_factor(enum pipe_blendfactor pipe)
454
 
{
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 */
458
 
   switch (pipe) {
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;
467
 
 
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;
476
 
 
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;
485
 
 
486
 
   case PIPE_BLENDFACTOR_ZERO:
487
 
      return 0 << 4 | 0 << 3 | 3;
488
 
   case PIPE_BLENDFACTOR_ONE:
489
 
      return 0 << 4 | 1 << 3 | 3;
490
 
 
491
 
   case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
492
 
      return 0 << 4 | 0 << 3 | 4;
493
 
 
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;
502
 
   }
503
 
   return -1;
504
 
}
505
 
 
506
 
static int
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)
510
 
{
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.
513
 
    */
514
 
   if (alpha_src_factor == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE)
515
 
      alpha_src_factor = PIPE_BLENDFACTOR_ONE;
516
 
 
517
 
   if (alpha_dst_factor == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE)
518
 
      alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
519
 
 
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;
526
 
   }
527
 
 
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;
534
 
   }
535
 
 
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 */
544
 
}
545
 
 
546
 
static int
547
 
lima_stencil_op(enum pipe_stencil_op pipe)
548
 
{
549
 
   switch (pipe) {
550
 
   case PIPE_STENCIL_OP_KEEP:
551
 
      return 0;
552
 
   case PIPE_STENCIL_OP_ZERO:
553
 
      return 2;
554
 
   case PIPE_STENCIL_OP_REPLACE:
555
 
      return 1;
556
 
   case PIPE_STENCIL_OP_INCR:
557
 
      return 6;
558
 
   case PIPE_STENCIL_OP_DECR:
559
 
      return 7;
560
 
   case PIPE_STENCIL_OP_INCR_WRAP:
561
 
      return 4;
562
 
   case PIPE_STENCIL_OP_DECR_WRAP:
563
 
      return 5;
564
 
   case PIPE_STENCIL_OP_INVERT:
565
 
      return 3;
566
 
   }
567
 
   return -1;
568
 
}
569
 
 
570
 
static unsigned
571
 
lima_calculate_depth_test(struct pipe_depth_stencil_alpha_state *depth,
572
 
                          struct pipe_rasterizer_state *rst)
573
 
{
574
 
   int offset_scale = 0, offset_units = 0;
575
 
   enum pipe_compare_func func = (depth->depth_enabled ? depth->depth_func : PIPE_FUNC_ALWAYS);
576
 
 
577
 
   offset_scale = CLAMP(rst->offset_scale * 4, -128, 127);
578
 
   if (offset_scale < 0)
579
 
      offset_scale += 0x100;
580
 
 
581
 
   offset_units = CLAMP(rst->offset_units * 2, -128, 127);
582
 
   if (offset_units < 0)
583
 
      offset_units += 0x100;
584
 
 
585
 
   return (depth->depth_enabled && depth->depth_writemask) |
586
 
      ((int)func << 1) |
587
 
      (offset_scale << 16) |
588
 
      (offset_units << 24);
589
 
}
590
 
 
591
 
static void
592
 
lima_pack_render_state(struct lima_context *ctx, const struct pipe_draw_info *info)
593
 
{
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,
597
 
                          sizeof(*render));
598
 
   bool early_z = true;
599
 
   bool pixel_kill = true;
600
 
 
601
 
   /* do hw support RGBA independ blend?
602
 
    * PIPE_CAP_INDEP_BLEND_ENABLE
603
 
    *
604
 
    * how to handle the no cbuf only zbuf case?
605
 
    */
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);
611
 
 
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);
616
 
   }
617
 
   else {
618
 
      /*
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.
623
 
       */
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);
627
 
   }
628
 
 
629
 
   render->alpha_blend |= (rt->colormask & PIPE_MASK_RGBA) << 28;
630
 
 
631
 
   struct pipe_rasterizer_state *rst = &ctx->rasterizer->base;
632
 
   render->depth_test = lima_calculate_depth_test(&ctx->zsa->base, rst);
633
 
 
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 */
638
 
 
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;
643
 
   }
644
 
 
645
 
   ushort far, near;
646
 
 
647
 
   near = float_to_ushort(ctx->viewport.near);
648
 
   far = float_to_ushort(ctx->viewport.far);
649
 
 
650
 
   /* overlap with plbu? any place can remove one? */
651
 
   render->depth_range = near | (far << 16);
652
 
 
653
 
   struct pipe_stencil_state *stencil = ctx->zsa->base.stencil;
654
 
   struct pipe_stencil_ref *ref = &ctx->stencil_ref;
655
 
 
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;
673
 
      }
674
 
      /* TODO: Find out, what (render->stecil_test & 0xff000000) is */
675
 
   }
676
 
   else {
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
681
 
       */
682
 
      render->stencil_front = 0xff000007;
683
 
      render->stencil_back = 0xff000007;
684
 
      render->stencil_test = 0x0000ffff;
685
 
   }
686
 
 
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;
692
 
   else
693
 
      render->multi_sample = 0x0000F800;
694
 
   if (ctx->framebuffer.base.samples)
695
 
      render->multi_sample |= 0x68;
696
 
 
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);
702
 
 
703
 
   /* alpha test */
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;
707
 
   } else {
708
 
      /* func = PIPE_FUNC_ALWAYS */
709
 
      render->multi_sample |= 0x7;
710
 
   }
711
 
 
712
 
   render->shader_address =
713
 
      ctx->fs->bo->va | (((uint32_t *)ctx->fs->bo->map)[0] & 0x1F);
714
 
 
715
 
   /* seems not needed */
716
 
   render->uniforms_address = 0x00000000;
717
 
 
718
 
   render->textures_address = 0x00000000;
719
 
 
720
 
   render->aux0 = (ctx->vs->state.varying_stride >> 3);
721
 
   render->aux1 = 0x00000000;
722
 
   if (ctx->rasterizer->base.front_ccw)
723
 
      render->aux1 = 0x00001000;
724
 
 
725
 
   if (ctx->blend->base.dither)
726
 
      render->aux1 |= 0x00002000;
727
 
 
728
 
   if (fs->state.uses_discard ||
729
 
       ctx->zsa->base.alpha_enabled ||
730
 
       fs->state.frag_depth_reg != -1) {
731
 
      early_z = false;
732
 
      pixel_kill = false;
733
 
   }
734
 
 
735
 
   if (rt->blend_enable)
736
 
      pixel_kill = false;
737
 
 
738
 
   if ((rt->colormask & PIPE_MASK_RGBA) != PIPE_MASK_RGBA)
739
 
      pixel_kill = false;
740
 
 
741
 
   if (early_z)
742
 
      render->aux0 |= 0x300;
743
 
 
744
 
   if (pixel_kill)
745
 
      render->aux0 |= 0x1000;
746
 
 
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;
752
 
   }
753
 
 
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;
758
 
      uint32_t bits = 0;
759
 
      if (size >= 8) {
760
 
         bits = util_last_bit(size >> 3) - 1;
761
 
         bits += size & u_bit_consecutive(0, bits + 3) ? 1 : 0;
762
 
      }
763
 
      render->uniforms_address |= bits > 0xf ? 0xf : bits;
764
 
 
765
 
      render->aux0 |= 0x80;
766
 
      render->aux1 |= 0x10000;
767
 
   }
768
 
 
769
 
   /* Set secondary output color */
770
 
   if (fs->state.frag_color1_reg != -1)
771
 
      render->aux0 |= (fs->state.frag_color1_reg << 28);
772
 
 
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++) {
778
 
         int val;
779
 
 
780
 
         if (i == ctx->vs->state.gl_pos_idx ||
781
 
             i == ctx->vs->state.point_size_idx)
782
 
            continue;
783
 
 
784
 
         struct lima_varying_info *v = ctx->vs->state.varying + i;
785
 
         if (v->component_size == 4)
786
 
            val = v->components > 2 ? 0 : 1;
787
 
         else
788
 
            val = v->components > 2 ? 2 : 3;
789
 
 
790
 
         if (index < 10)
791
 
            render->varying_types |= val << (3 * index);
792
 
         else if (index == 10) {
793
 
            render->varying_types |= val << 30;
794
 
            render->varyings_address |= val >> 2;
795
 
         }
796
 
         else if (index == 11)
797
 
            render->varyings_address |= val << 1;
798
 
 
799
 
         index++;
800
 
      }
801
 
   }
802
 
   else {
803
 
      render->varying_types = 0x00000000;
804
 
      render->varyings_address = 0x00000000;
805
 
   }
806
 
 
807
 
   struct lima_job *job = lima_job_get(ctx);
808
 
 
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));
813
 
 
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));
817
 
}
818
 
 
819
 
static void
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)
822
 
{
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;
826
 
 
827
 
   uint32_t *attribute =
828
 
      lima_ctx_buff_alloc(ctx, lima_ctx_buff_gp_attribute_info,
829
 
                          MAX2(1, ve->num_elements) * 8);
830
 
 
831
 
   int n = 0;
832
 
   for (int i = 0; i < ve->num_elements; i++) {
833
 
      struct pipe_vertex_element *pve = ve->pipe + i;
834
 
 
835
 
      assert(pve->vertex_buffer_index < vb->count);
836
 
      assert(vb->enabled_mask & (1 << pve->vertex_buffer_index));
837
 
 
838
 
      struct pipe_vertex_buffer *pvb = vb->vb + pve->vertex_buffer_index;
839
 
      struct lima_resource *res = lima_resource(pvb->buffer.resource);
840
 
 
841
 
      lima_job_add_bo(job, LIMA_PIPE_GP, res->bo, LIMA_SUBMIT_BO_READ);
842
 
 
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);
849
 
   }
850
 
 
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));
854
 
}
855
 
 
856
 
static void
857
 
lima_update_gp_uniform(struct lima_context *ctx)
858
 
{
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);
863
 
 
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);
867
 
 
868
 
   if (ccb->buffer)
869
 
      memcpy(vs_const_buff, ccb->buffer, uniform_size);
870
 
 
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));
877
 
 
878
 
   if (vs->constant)
879
 
      memcpy(vs_const_buff + uniform_size + 32,
880
 
             vs->constant, vs->state.constant_size);
881
 
 
882
 
   struct lima_job *job = lima_job_get(ctx);
883
 
 
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++) {
888
 
         if ((i % 4) == 0)
889
 
            printf("%4d:", i / 4);
890
 
         printf(" %8.4f", vs_const_buff_f[i]);
891
 
         if ((i % 4) == 3)
892
 
            printf("\n");
893
 
      }
894
 
      printf("\n");
895
 
   }
896
 
 
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));
901
 
}
902
 
 
903
 
static void
904
 
lima_update_pp_uniform(struct lima_context *ctx)
905
 
{
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);
908
 
 
909
 
   if (!const_buff)
910
 
      return;
911
 
 
912
 
   uint16_t *fp16_const_buff =
913
 
      lima_ctx_buff_alloc(ctx, lima_ctx_buff_pp_uniform,
914
 
                          const_buff_size * sizeof(uint16_t));
915
 
 
916
 
   uint32_t *array =
917
 
      lima_ctx_buff_alloc(ctx, lima_ctx_buff_pp_uniform_array, 4);
918
 
 
919
 
   for (int i = 0; i < const_buff_size; i++)
920
 
       fp16_const_buff[i] = _mesa_float_to_half(const_buff[i]);
921
 
 
922
 
   *array = lima_ctx_buff_va(ctx, lima_ctx_buff_pp_uniform);
923
 
 
924
 
   struct lima_job *job = lima_job_get(ctx);
925
 
 
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));
933
 
}
934
 
 
935
 
static void
936
 
lima_update_varying(struct lima_context *ctx, const struct pipe_draw_info *info,
937
 
                    const struct pipe_draw_start_count_bias *draw)
938
 
{
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;
944
 
 
945
 
   uint32_t *varying =
946
 
      lima_ctx_buff_alloc(ctx, lima_ctx_buff_gp_varying_info,
947
 
                          vs->state.num_outputs * 8);
948
 
   int n = 0;
949
 
 
950
 
   int offset = 0;
951
 
 
952
 
   for (int i = 0; i < vs->state.num_outputs; i++) {
953
 
      struct lima_varying_info *v = vs->state.varying + i;
954
 
 
955
 
      if (i == vs->state.gl_pos_idx ||
956
 
          i == vs->state.point_size_idx)
957
 
         continue;
958
 
 
959
 
      int size = v->component_size * 4;
960
 
 
961
 
      /* does component_size == 2 need to be 16 aligned? */
962
 
      if (v->component_size == 4)
963
 
         offset = align(offset, 16);
964
 
 
965
 
      v->offset = offset;
966
 
      offset += size;
967
 
   }
968
 
 
969
 
   vs->state.varying_stride = align(offset, 16);
970
 
 
971
 
   /* gl_Position is always present, allocate space for it */
972
 
   gp_output_size = align(4 * 4 * num, 0x40);
973
 
 
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);
978
 
   }
979
 
 
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;
984
 
   }
985
 
 
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.
988
 
    */
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);
993
 
 
994
 
   for (int i = 0; i < vs->state.num_outputs; i++) {
995
 
      struct lima_varying_info *v = vs->state.varying + i;
996
 
 
997
 
      if (i == vs->state.gl_pos_idx) {
998
 
         /* gl_Position */
999
 
         varying[n++] = ctx->gp_output->va;
1000
 
         varying[n++] = 0x8020;
1001
 
      } else if (i == vs->state.point_size_idx) {
1002
 
         /* gl_PointSize */
1003
 
         varying[n++] = ctx->gp_output->va + ctx->gp_output_point_size_offt;
1004
 
         varying[n++] = 0x2021;
1005
 
      } else {
1006
 
         /* Varying */
1007
 
         varying[n++] = ctx->gp_output->va + ctx->gp_output_varyings_offt +
1008
 
                        v->offset;
1009
 
         varying[n++] = (vs->state.varying_stride << 11) | (v->components - 1) |
1010
 
            (v->component_size == 2 ? 0x0C : 0);
1011
 
      }
1012
 
   }
1013
 
 
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));
1017
 
}
1018
 
 
1019
 
static void
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)
1023
 
{
1024
 
   struct lima_context *ctx = lima_context(pctx);
1025
 
   struct lima_context_framebuffer *fb = &ctx->framebuffer;
1026
 
   unsigned buffers = 0;
1027
 
 
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;
1034
 
   }
1035
 
 
1036
 
   if (fb->base.nr_cbufs)
1037
 
      buffers |= PIPE_CLEAR_COLOR0;
1038
 
 
1039
 
   lima_update_job_wb(ctx, buffers);
1040
 
 
1041
 
   lima_update_gp_attribute_info(ctx, info, draw);
1042
 
 
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;
1049
 
   }
1050
 
 
1051
 
   lima_update_varying(ctx, info, draw);
1052
 
 
1053
 
   lima_pack_vs_cmd(ctx, info, draw);
1054
 
 
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;
1059
 
   }
1060
 
 
1061
 
   lima_update_textures(ctx);
1062
 
 
1063
 
   lima_pack_render_state(ctx, info);
1064
 
   lima_pack_plbu_cmd(ctx, info, draw);
1065
 
 
1066
 
   if (ctx->gp_output) {
1067
 
      lima_bo_unreference(ctx->gp_output); /* held by job */
1068
 
      ctx->gp_output = NULL;
1069
 
   }
1070
 
 
1071
 
   ctx->dirty = 0;
1072
 
}
1073
 
 
1074
 
static void
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)
1078
 
{
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;
1083
 
 
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;
1090
 
   }
1091
 
 
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);
1095
 
   }
1096
 
   else {
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);
1101
 
   }
1102
 
 
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);
1108
 
   }
1109
 
 
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);
1113
 
 
1114
 
   if (indexbuf)
1115
 
      pipe_resource_reference(&indexbuf, NULL);
1116
 
}
1117
 
 
1118
 
static void
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)
1122
 
{
1123
 
   static const uint32_t max_verts = 65535;
1124
 
 
1125
 
   struct pipe_draw_start_count_bias local_draw = *draw;
1126
 
   unsigned start = draw->start;
1127
 
   unsigned count = draw->count;
1128
 
 
1129
 
   while (count) {
1130
 
      unsigned this_count = count;
1131
 
      unsigned step;
1132
 
 
1133
 
      u_split_draw(info, max_verts, &this_count, &step);
1134
 
 
1135
 
      local_draw.start = start;
1136
 
      local_draw.count = this_count;
1137
 
 
1138
 
      lima_draw_vbo_update(pctx, info, &local_draw);
1139
 
 
1140
 
      count -= step;
1141
 
      start += step;
1142
 
   }
1143
 
}
1144
 
 
1145
 
static void
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,
1151
 
              unsigned num_draws)
1152
 
{
1153
 
   if (num_draws > 1) {
1154
 
      util_draw_multi(pctx, info, drawid_offset, indirect, draws, num_draws);
1155
 
      return;
1156
 
   }
1157
 
 
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");
1162
 
      return;
1163
 
   }
1164
 
 
1165
 
   struct lima_context *ctx = lima_context(pctx);
1166
 
 
1167
 
   if (!ctx->uncomp_fs || !ctx->uncomp_vs) {
1168
 
      debug_warn_once("no shader, skip draw\n");
1169
 
      return;
1170
 
   }
1171
 
 
1172
 
   lima_clip_scissor_to_viewport(ctx);
1173
 
   if (lima_is_scissor_zero(ctx))
1174
 
      return;
1175
 
 
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);
1179
 
 
1180
 
   if (!lima_update_fs_state(ctx) || !lima_update_vs_state(ctx))
1181
 
      return;
1182
 
 
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);
1185
 
 
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);
1190
 
 
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);
1195
 
 
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);
1198
 
 
1199
 
   if (info->index_size)
1200
 
      lima_draw_vbo_indexed(pctx, info, &draws[0]);
1201
 
   else
1202
 
      lima_draw_vbo_count(pctx, info, &draws[0]);
1203
 
 
1204
 
   job->draws++;
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;
1209
 
      lima_do_job(job);
1210
 
      /* Subsequent job will need to resolve the same buffers */
1211
 
      lima_update_job_wb(ctx, resolve);
1212
 
   }
1213
 
}
1214
 
 
1215
 
void
1216
 
lima_draw_init(struct lima_context *ctx)
1217
 
{
1218
 
   ctx->base.clear = lima_clear;
1219
 
   ctx->base.draw_vbo = lima_draw_vbo;
1220
 
}