root/drivers/gpu/drm/vc4/vc4_render_cl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rcl_u8
  2. rcl_u16
  3. rcl_u32
  4. vc4_store_before_load
  5. vc4_full_res_offset
  6. vc4_tile_coordinates
  7. emit_tile
  8. vc4_create_rcl_bo
  9. vc4_full_res_bounds_check
  10. vc4_rcl_msaa_surface_setup
  11. vc4_rcl_surface_setup
  12. vc4_rcl_render_config_surface_setup
  13. vc4_get_rcl

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

/* [<][>][^][v][top][bottom][index][help] */