Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/vc4/kernel/vc4_render_cl.c
4574 views
1
/*
2
* Copyright © 2014-2015 Broadcom
3
*
4
* Permission is hereby granted, free of charge, to any person obtaining a
5
* copy of this software and associated documentation files (the "Software"),
6
* to deal in the Software without restriction, including without limitation
7
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
* and/or sell copies of the Software, and to permit persons to whom the
9
* Software is furnished to do so, subject to the following conditions:
10
*
11
* The above copyright notice and this permission notice (including the next
12
* paragraph) shall be included in all copies or substantial portions of the
13
* Software.
14
*
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
* IN THE SOFTWARE.
22
*/
23
24
/**
25
* DOC: Render command list generation
26
*
27
* In the VC4 driver, render command list generation is performed by the
28
* kernel instead of userspace. We do this because validating a
29
* user-submitted command list is hard to get right and has high CPU overhead,
30
* while the number of valid configurations for render command lists is
31
* actually fairly low.
32
*/
33
34
#include "vc4_drv.h"
35
#include "vc4_packet.h"
36
37
struct vc4_rcl_setup {
38
struct drm_gem_cma_object *color_read;
39
struct drm_gem_cma_object *color_write;
40
struct drm_gem_cma_object *zs_read;
41
struct drm_gem_cma_object *zs_write;
42
struct drm_gem_cma_object *msaa_color_write;
43
struct drm_gem_cma_object *msaa_zs_write;
44
45
struct drm_gem_cma_object *rcl;
46
u32 next_offset;
47
};
48
49
static inline void rcl_u8(struct vc4_rcl_setup *setup, u8 val)
50
{
51
*(u8 *)(setup->rcl->vaddr + setup->next_offset) = val;
52
setup->next_offset += 1;
53
}
54
55
static inline void rcl_u16(struct vc4_rcl_setup *setup, u16 val)
56
{
57
*(u16 *)(setup->rcl->vaddr + setup->next_offset) = val;
58
setup->next_offset += 2;
59
}
60
61
static inline void rcl_u32(struct vc4_rcl_setup *setup, u32 val)
62
{
63
*(u32 *)(setup->rcl->vaddr + setup->next_offset) = val;
64
setup->next_offset += 4;
65
}
66
67
/*
68
* Emits a no-op STORE_TILE_BUFFER_GENERAL.
69
*
70
* If we emit a PACKET_TILE_COORDINATES, it must be followed by a store of
71
* some sort before another load is triggered.
72
*/
73
static void vc4_store_before_load(struct vc4_rcl_setup *setup)
74
{
75
rcl_u8(setup, VC4_PACKET_STORE_TILE_BUFFER_GENERAL);
76
rcl_u16(setup,
77
VC4_SET_FIELD(VC4_LOADSTORE_TILE_BUFFER_NONE,
78
VC4_LOADSTORE_TILE_BUFFER_BUFFER) |
79
VC4_STORE_TILE_BUFFER_DISABLE_COLOR_CLEAR |
80
VC4_STORE_TILE_BUFFER_DISABLE_ZS_CLEAR |
81
VC4_STORE_TILE_BUFFER_DISABLE_VG_MASK_CLEAR);
82
rcl_u32(setup, 0); /* no address, since we're in None mode */
83
}
84
85
/*
86
* Calculates the physical address of the start of a tile in a RCL surface.
87
*
88
* Unlike the other load/store packets,
89
* VC4_PACKET_LOAD/STORE_FULL_RES_TILE_BUFFER don't look at the tile
90
* coordinates packet, and instead just store to the address given.
91
*/
92
static uint32_t vc4_full_res_offset(struct vc4_exec_info *exec,
93
struct drm_gem_cma_object *bo,
94
struct drm_vc4_submit_rcl_surface *surf,
95
uint8_t x, uint8_t y)
96
{
97
return bo->paddr + surf->offset + VC4_TILE_BUFFER_SIZE *
98
(DIV_ROUND_UP(exec->args->width, exec->tile_width) * y + x);
99
}
100
101
/*
102
* Emits a PACKET_TILE_COORDINATES if one isn't already pending.
103
*
104
* The tile coordinates packet triggers a pending load if there is one, are
105
* used for clipping during rendering, and determine where loads/stores happen
106
* relative to their base address.
107
*/
108
static void vc4_tile_coordinates(struct vc4_rcl_setup *setup,
109
uint32_t x, uint32_t y)
110
{
111
rcl_u8(setup, VC4_PACKET_TILE_COORDINATES);
112
rcl_u8(setup, x);
113
rcl_u8(setup, y);
114
}
115
116
static void emit_tile(struct vc4_exec_info *exec,
117
struct vc4_rcl_setup *setup,
118
uint8_t x, uint8_t y, bool first, bool last)
119
{
120
struct drm_vc4_submit_cl *args = exec->args;
121
bool has_bin = args->bin_cl_size != 0;
122
123
/* Note that the load doesn't actually occur until the
124
* tile coords packet is processed, and only one load
125
* may be outstanding at a time.
126
*/
127
if (setup->color_read) {
128
if (args->color_read.flags &
129
VC4_SUBMIT_RCL_SURFACE_READ_IS_FULL_RES) {
130
rcl_u8(setup, VC4_PACKET_LOAD_FULL_RES_TILE_BUFFER);
131
rcl_u32(setup,
132
vc4_full_res_offset(exec, setup->color_read,
133
&args->color_read, x, y) |
134
VC4_LOADSTORE_FULL_RES_DISABLE_ZS);
135
} else {
136
rcl_u8(setup, VC4_PACKET_LOAD_TILE_BUFFER_GENERAL);
137
rcl_u16(setup, args->color_read.bits);
138
rcl_u32(setup, setup->color_read->paddr +
139
args->color_read.offset);
140
}
141
}
142
143
if (setup->zs_read) {
144
if (setup->color_read) {
145
/* Exec previous load. */
146
vc4_tile_coordinates(setup, x, y);
147
vc4_store_before_load(setup);
148
}
149
150
if (args->zs_read.flags &
151
VC4_SUBMIT_RCL_SURFACE_READ_IS_FULL_RES) {
152
rcl_u8(setup, VC4_PACKET_LOAD_FULL_RES_TILE_BUFFER);
153
rcl_u32(setup,
154
vc4_full_res_offset(exec, setup->zs_read,
155
&args->zs_read, x, y) |
156
VC4_LOADSTORE_FULL_RES_DISABLE_COLOR);
157
} else {
158
rcl_u8(setup, VC4_PACKET_LOAD_TILE_BUFFER_GENERAL);
159
rcl_u16(setup, args->zs_read.bits);
160
rcl_u32(setup, setup->zs_read->paddr +
161
args->zs_read.offset);
162
}
163
}
164
165
/* Clipping depends on tile coordinates having been
166
* emitted, so we always need one here.
167
*/
168
vc4_tile_coordinates(setup, x, y);
169
170
/* Wait for the binner before jumping to the first
171
* tile's lists.
172
*/
173
if (first && has_bin)
174
rcl_u8(setup, VC4_PACKET_WAIT_ON_SEMAPHORE);
175
176
if (has_bin) {
177
rcl_u8(setup, VC4_PACKET_BRANCH_TO_SUB_LIST);
178
rcl_u32(setup, (exec->tile_bo->paddr +
179
exec->tile_alloc_offset +
180
(y * exec->bin_tiles_x + x) * 32));
181
}
182
183
if (setup->msaa_color_write) {
184
bool last_tile_write = (!setup->msaa_zs_write &&
185
!setup->zs_write &&
186
!setup->color_write);
187
uint32_t bits = VC4_LOADSTORE_FULL_RES_DISABLE_ZS;
188
189
if (!last_tile_write)
190
bits |= VC4_LOADSTORE_FULL_RES_DISABLE_CLEAR_ALL;
191
else if (last)
192
bits |= VC4_LOADSTORE_FULL_RES_EOF;
193
rcl_u8(setup, VC4_PACKET_STORE_FULL_RES_TILE_BUFFER);
194
rcl_u32(setup,
195
vc4_full_res_offset(exec, setup->msaa_color_write,
196
&args->msaa_color_write, x, y) |
197
bits);
198
}
199
200
if (setup->msaa_zs_write) {
201
bool last_tile_write = (!setup->zs_write &&
202
!setup->color_write);
203
uint32_t bits = VC4_LOADSTORE_FULL_RES_DISABLE_COLOR;
204
205
if (setup->msaa_color_write)
206
vc4_tile_coordinates(setup, x, y);
207
if (!last_tile_write)
208
bits |= VC4_LOADSTORE_FULL_RES_DISABLE_CLEAR_ALL;
209
else if (last)
210
bits |= VC4_LOADSTORE_FULL_RES_EOF;
211
rcl_u8(setup, VC4_PACKET_STORE_FULL_RES_TILE_BUFFER);
212
rcl_u32(setup,
213
vc4_full_res_offset(exec, setup->msaa_zs_write,
214
&args->msaa_zs_write, x, y) |
215
bits);
216
}
217
218
if (setup->zs_write) {
219
bool last_tile_write = !setup->color_write;
220
221
if (setup->msaa_color_write || setup->msaa_zs_write)
222
vc4_tile_coordinates(setup, x, y);
223
224
rcl_u8(setup, VC4_PACKET_STORE_TILE_BUFFER_GENERAL);
225
rcl_u16(setup, args->zs_write.bits |
226
(last_tile_write ?
227
0 : VC4_STORE_TILE_BUFFER_DISABLE_COLOR_CLEAR));
228
rcl_u32(setup,
229
(setup->zs_write->paddr + args->zs_write.offset) |
230
((last && last_tile_write) ?
231
VC4_LOADSTORE_TILE_BUFFER_EOF : 0));
232
}
233
234
if (setup->color_write) {
235
if (setup->msaa_color_write || setup->msaa_zs_write ||
236
setup->zs_write) {
237
vc4_tile_coordinates(setup, x, y);
238
}
239
240
if (last)
241
rcl_u8(setup, VC4_PACKET_STORE_MS_TILE_BUFFER_AND_EOF);
242
else
243
rcl_u8(setup, VC4_PACKET_STORE_MS_TILE_BUFFER);
244
}
245
}
246
247
static int vc4_create_rcl_bo(struct drm_device *dev, struct vc4_exec_info *exec,
248
struct vc4_rcl_setup *setup)
249
{
250
struct drm_vc4_submit_cl *args = exec->args;
251
bool has_bin = args->bin_cl_size != 0;
252
uint8_t min_x_tile = args->min_x_tile;
253
uint8_t min_y_tile = args->min_y_tile;
254
uint8_t max_x_tile = args->max_x_tile;
255
uint8_t max_y_tile = args->max_y_tile;
256
uint8_t xtiles = max_x_tile - min_x_tile + 1;
257
uint8_t ytiles = max_y_tile - min_y_tile + 1;
258
uint8_t xi, yi;
259
uint32_t size, loop_body_size;
260
bool positive_x = true;
261
bool positive_y = true;
262
263
if (args->flags & VC4_SUBMIT_CL_FIXED_RCL_ORDER) {
264
if (!(args->flags & VC4_SUBMIT_CL_RCL_ORDER_INCREASING_X))
265
positive_x = false;
266
if (!(args->flags & VC4_SUBMIT_CL_RCL_ORDER_INCREASING_Y))
267
positive_y = false;
268
}
269
270
size = VC4_PACKET_TILE_RENDERING_MODE_CONFIG_SIZE;
271
loop_body_size = VC4_PACKET_TILE_COORDINATES_SIZE;
272
273
if (args->flags & VC4_SUBMIT_CL_USE_CLEAR_COLOR) {
274
size += VC4_PACKET_CLEAR_COLORS_SIZE +
275
VC4_PACKET_TILE_COORDINATES_SIZE +
276
VC4_PACKET_STORE_TILE_BUFFER_GENERAL_SIZE;
277
}
278
279
if (setup->color_read) {
280
if (args->color_read.flags &
281
VC4_SUBMIT_RCL_SURFACE_READ_IS_FULL_RES) {
282
loop_body_size += VC4_PACKET_LOAD_FULL_RES_TILE_BUFFER_SIZE;
283
} else {
284
loop_body_size += VC4_PACKET_LOAD_TILE_BUFFER_GENERAL_SIZE;
285
}
286
}
287
if (setup->zs_read) {
288
if (setup->color_read) {
289
loop_body_size += VC4_PACKET_TILE_COORDINATES_SIZE;
290
loop_body_size += VC4_PACKET_STORE_TILE_BUFFER_GENERAL_SIZE;
291
}
292
293
if (args->zs_read.flags &
294
VC4_SUBMIT_RCL_SURFACE_READ_IS_FULL_RES) {
295
loop_body_size += VC4_PACKET_LOAD_FULL_RES_TILE_BUFFER_SIZE;
296
} else {
297
loop_body_size += VC4_PACKET_LOAD_TILE_BUFFER_GENERAL_SIZE;
298
}
299
}
300
301
if (has_bin) {
302
size += VC4_PACKET_WAIT_ON_SEMAPHORE_SIZE;
303
loop_body_size += VC4_PACKET_BRANCH_TO_SUB_LIST_SIZE;
304
}
305
306
if (setup->msaa_color_write)
307
loop_body_size += VC4_PACKET_STORE_FULL_RES_TILE_BUFFER_SIZE;
308
if (setup->msaa_zs_write)
309
loop_body_size += VC4_PACKET_STORE_FULL_RES_TILE_BUFFER_SIZE;
310
311
if (setup->zs_write)
312
loop_body_size += VC4_PACKET_STORE_TILE_BUFFER_GENERAL_SIZE;
313
if (setup->color_write)
314
loop_body_size += VC4_PACKET_STORE_MS_TILE_BUFFER_SIZE;
315
316
/* We need a VC4_PACKET_TILE_COORDINATES in between each store. */
317
loop_body_size += VC4_PACKET_TILE_COORDINATES_SIZE *
318
((setup->msaa_color_write != NULL) +
319
(setup->msaa_zs_write != NULL) +
320
(setup->color_write != NULL) +
321
(setup->zs_write != NULL) - 1);
322
323
size += xtiles * ytiles * loop_body_size;
324
325
setup->rcl = drm_gem_cma_create(dev, size);
326
if (!setup->rcl)
327
return -ENOMEM;
328
list_addtail(&to_vc4_bo(&setup->rcl->base)->unref_head,
329
&exec->unref_list);
330
331
rcl_u8(setup, VC4_PACKET_TILE_RENDERING_MODE_CONFIG);
332
rcl_u32(setup,
333
(setup->color_write ? (setup->color_write->paddr +
334
args->color_write.offset) :
335
0));
336
rcl_u16(setup, args->width);
337
rcl_u16(setup, args->height);
338
rcl_u16(setup, args->color_write.bits);
339
340
/* The tile buffer gets cleared when the previous tile is stored. If
341
* the clear values changed between frames, then the tile buffer has
342
* stale clear values in it, so we have to do a store in None mode (no
343
* writes) so that we trigger the tile buffer clear.
344
*/
345
if (args->flags & VC4_SUBMIT_CL_USE_CLEAR_COLOR) {
346
rcl_u8(setup, VC4_PACKET_CLEAR_COLORS);
347
rcl_u32(setup, args->clear_color[0]);
348
rcl_u32(setup, args->clear_color[1]);
349
rcl_u32(setup, args->clear_z);
350
rcl_u8(setup, args->clear_s);
351
352
vc4_tile_coordinates(setup, 0, 0);
353
354
rcl_u8(setup, VC4_PACKET_STORE_TILE_BUFFER_GENERAL);
355
rcl_u16(setup, VC4_LOADSTORE_TILE_BUFFER_NONE);
356
rcl_u32(setup, 0); /* no address, since we're in None mode */
357
}
358
359
for (yi = 0; yi < ytiles; yi++) {
360
int y = positive_y ? min_y_tile + yi : max_y_tile - yi;
361
for (xi = 0; xi < xtiles; xi++) {
362
int x = positive_x ? min_x_tile + xi : max_x_tile - xi;
363
bool first = (xi == 0 && yi == 0);
364
bool last = (xi == xtiles - 1 && yi == ytiles - 1);
365
366
emit_tile(exec, setup, x, y, first, last);
367
}
368
}
369
370
BUG_ON(setup->next_offset != size);
371
exec->ct1ca = setup->rcl->paddr;
372
exec->ct1ea = setup->rcl->paddr + setup->next_offset;
373
374
return 0;
375
}
376
377
static int vc4_full_res_bounds_check(struct vc4_exec_info *exec,
378
struct drm_gem_cma_object *obj,
379
struct drm_vc4_submit_rcl_surface *surf)
380
{
381
struct drm_vc4_submit_cl *args = exec->args;
382
u32 render_tiles_stride = DIV_ROUND_UP(exec->args->width,
383
exec->tile_width);
384
385
if (surf->offset > obj->base.size) {
386
DRM_ERROR("surface offset %d > BO size %zd\n",
387
surf->offset, obj->base.size);
388
return -EINVAL;
389
}
390
391
if ((obj->base.size - surf->offset) / VC4_TILE_BUFFER_SIZE <
392
render_tiles_stride * args->max_y_tile + args->max_x_tile) {
393
DRM_ERROR("MSAA tile %d, %d out of bounds "
394
"(bo size %zd, offset %d).\n",
395
args->max_x_tile, args->max_y_tile,
396
obj->base.size,
397
surf->offset);
398
return -EINVAL;
399
}
400
401
return 0;
402
}
403
404
static int vc4_rcl_msaa_surface_setup(struct vc4_exec_info *exec,
405
struct drm_gem_cma_object **obj,
406
struct drm_vc4_submit_rcl_surface *surf)
407
{
408
if (surf->flags != 0 || surf->bits != 0) {
409
DRM_ERROR("MSAA surface had nonzero flags/bits\n");
410
return -EINVAL;
411
}
412
413
if (surf->hindex == ~0)
414
return 0;
415
416
*obj = vc4_use_bo(exec, surf->hindex);
417
if (!*obj)
418
return -EINVAL;
419
420
if (surf->offset & 0xf) {
421
DRM_ERROR("MSAA write must be 16b aligned.\n");
422
return -EINVAL;
423
}
424
425
return vc4_full_res_bounds_check(exec, *obj, surf);
426
}
427
428
static int vc4_rcl_surface_setup(struct vc4_exec_info *exec,
429
struct drm_gem_cma_object **obj,
430
struct drm_vc4_submit_rcl_surface *surf)
431
{
432
uint8_t tiling = VC4_GET_FIELD(surf->bits,
433
VC4_LOADSTORE_TILE_BUFFER_TILING);
434
uint8_t buffer = VC4_GET_FIELD(surf->bits,
435
VC4_LOADSTORE_TILE_BUFFER_BUFFER);
436
uint8_t format = VC4_GET_FIELD(surf->bits,
437
VC4_LOADSTORE_TILE_BUFFER_FORMAT);
438
int cpp;
439
int ret;
440
441
if (surf->flags & ~VC4_SUBMIT_RCL_SURFACE_READ_IS_FULL_RES) {
442
DRM_ERROR("Extra flags set\n");
443
return -EINVAL;
444
}
445
446
if (surf->hindex == ~0)
447
return 0;
448
449
*obj = vc4_use_bo(exec, surf->hindex);
450
if (!*obj)
451
return -EINVAL;
452
453
if (surf->flags & VC4_SUBMIT_RCL_SURFACE_READ_IS_FULL_RES) {
454
if (surf == &exec->args->zs_write) {
455
DRM_ERROR("general zs write may not be a full-res.\n");
456
return -EINVAL;
457
}
458
459
if (surf->bits != 0) {
460
DRM_ERROR("load/store general bits set with "
461
"full res load/store.\n");
462
return -EINVAL;
463
}
464
465
ret = vc4_full_res_bounds_check(exec, *obj, surf);
466
if (!ret)
467
return ret;
468
469
return 0;
470
}
471
472
if (surf->bits & ~(VC4_LOADSTORE_TILE_BUFFER_TILING_MASK |
473
VC4_LOADSTORE_TILE_BUFFER_BUFFER_MASK |
474
VC4_LOADSTORE_TILE_BUFFER_FORMAT_MASK)) {
475
DRM_ERROR("Unknown bits in load/store: 0x%04x\n",
476
surf->bits);
477
return -EINVAL;
478
}
479
480
if (tiling > VC4_TILING_FORMAT_LT) {
481
DRM_ERROR("Bad tiling format\n");
482
return -EINVAL;
483
}
484
485
if (buffer == VC4_LOADSTORE_TILE_BUFFER_ZS) {
486
if (format != 0) {
487
DRM_ERROR("No color format should be set for ZS\n");
488
return -EINVAL;
489
}
490
cpp = 4;
491
} else if (buffer == VC4_LOADSTORE_TILE_BUFFER_COLOR) {
492
switch (format) {
493
case VC4_LOADSTORE_TILE_BUFFER_BGR565:
494
case VC4_LOADSTORE_TILE_BUFFER_BGR565_DITHER:
495
cpp = 2;
496
break;
497
case VC4_LOADSTORE_TILE_BUFFER_RGBA8888:
498
cpp = 4;
499
break;
500
default:
501
DRM_ERROR("Bad tile buffer format\n");
502
return -EINVAL;
503
}
504
} else {
505
DRM_ERROR("Bad load/store buffer %d.\n", buffer);
506
return -EINVAL;
507
}
508
509
if (surf->offset & 0xf) {
510
DRM_ERROR("load/store buffer must be 16b aligned.\n");
511
return -EINVAL;
512
}
513
514
if (!vc4_check_tex_size(exec, *obj, surf->offset, tiling,
515
exec->args->width, exec->args->height, cpp)) {
516
return -EINVAL;
517
}
518
519
return 0;
520
}
521
522
static int
523
vc4_rcl_render_config_surface_setup(struct vc4_exec_info *exec,
524
struct vc4_rcl_setup *setup,
525
struct drm_gem_cma_object **obj,
526
struct drm_vc4_submit_rcl_surface *surf)
527
{
528
uint8_t tiling = VC4_GET_FIELD(surf->bits,
529
VC4_RENDER_CONFIG_MEMORY_FORMAT);
530
uint8_t format = VC4_GET_FIELD(surf->bits,
531
VC4_RENDER_CONFIG_FORMAT);
532
int cpp;
533
534
if (surf->flags != 0) {
535
DRM_ERROR("No flags supported on render config.\n");
536
return -EINVAL;
537
}
538
539
if (surf->bits & ~(VC4_RENDER_CONFIG_MEMORY_FORMAT_MASK |
540
VC4_RENDER_CONFIG_FORMAT_MASK |
541
VC4_RENDER_CONFIG_MS_MODE_4X |
542
VC4_RENDER_CONFIG_DECIMATE_MODE_4X)) {
543
DRM_ERROR("Unknown bits in render config: 0x%04x\n",
544
surf->bits);
545
return -EINVAL;
546
}
547
548
if (surf->hindex == ~0)
549
return 0;
550
551
*obj = vc4_use_bo(exec, surf->hindex);
552
if (!*obj)
553
return -EINVAL;
554
555
if (tiling > VC4_TILING_FORMAT_LT) {
556
DRM_ERROR("Bad tiling format\n");
557
return -EINVAL;
558
}
559
560
switch (format) {
561
case VC4_RENDER_CONFIG_FORMAT_BGR565_DITHERED:
562
case VC4_RENDER_CONFIG_FORMAT_BGR565:
563
cpp = 2;
564
break;
565
case VC4_RENDER_CONFIG_FORMAT_RGBA8888:
566
cpp = 4;
567
break;
568
default:
569
DRM_ERROR("Bad tile buffer format\n");
570
return -EINVAL;
571
}
572
573
if (!vc4_check_tex_size(exec, *obj, surf->offset, tiling,
574
exec->args->width, exec->args->height, cpp)) {
575
return -EINVAL;
576
}
577
578
return 0;
579
}
580
581
int vc4_get_rcl(struct drm_device *dev, struct vc4_exec_info *exec)
582
{
583
struct vc4_rcl_setup setup = {0};
584
struct drm_vc4_submit_cl *args = exec->args;
585
bool has_bin = args->bin_cl_size != 0;
586
int ret;
587
588
if (args->min_x_tile > args->max_x_tile ||
589
args->min_y_tile > args->max_y_tile) {
590
DRM_ERROR("Bad render tile set (%d,%d)-(%d,%d)\n",
591
args->min_x_tile, args->min_y_tile,
592
args->max_x_tile, args->max_y_tile);
593
return -EINVAL;
594
}
595
596
if (has_bin &&
597
(args->max_x_tile > exec->bin_tiles_x ||
598
args->max_y_tile > exec->bin_tiles_y)) {
599
DRM_ERROR("Render tiles (%d,%d) outside of bin config "
600
"(%d,%d)\n",
601
args->max_x_tile, args->max_y_tile,
602
exec->bin_tiles_x, exec->bin_tiles_y);
603
return -EINVAL;
604
}
605
606
ret = vc4_rcl_render_config_surface_setup(exec, &setup,
607
&setup.color_write,
608
&args->color_write);
609
if (ret)
610
return ret;
611
612
ret = vc4_rcl_surface_setup(exec, &setup.color_read, &args->color_read);
613
if (ret)
614
return ret;
615
616
ret = vc4_rcl_surface_setup(exec, &setup.zs_read, &args->zs_read);
617
if (ret)
618
return ret;
619
620
ret = vc4_rcl_surface_setup(exec, &setup.zs_write, &args->zs_write);
621
if (ret)
622
return ret;
623
624
ret = vc4_rcl_msaa_surface_setup(exec, &setup.msaa_color_write,
625
&args->msaa_color_write);
626
if (ret)
627
return ret;
628
629
ret = vc4_rcl_msaa_surface_setup(exec, &setup.msaa_zs_write,
630
&args->msaa_zs_write);
631
if (ret)
632
return ret;
633
634
/* We shouldn't even have the job submitted to us if there's no
635
* surface to write out.
636
*/
637
if (!setup.color_write && !setup.zs_write &&
638
!setup.msaa_color_write && !setup.msaa_zs_write) {
639
DRM_ERROR("RCL requires color or Z/S write\n");
640
return -EINVAL;
641
}
642
643
return vc4_create_rcl_bo(dev, exec, &setup);
644
}
645
646