17ec681f3Smrg/*
27ec681f3Smrg * Copyright 2010 Red Hat Inc.
37ec681f3Smrg * Copyright © 2014-2017 Broadcom
47ec681f3Smrg * Copyright (C) 2019-2020 Collabora, Ltd.
57ec681f3Smrg * Copyright 2006 VMware, Inc.
67ec681f3Smrg *
77ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
87ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
97ec681f3Smrg * to deal in the Software without restriction, including without limitation
107ec681f3Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub
117ec681f3Smrg * license, and/or sell copies of the Software, and to permit persons to whom
127ec681f3Smrg * the Software is furnished to do so, subject to the following conditions:
137ec681f3Smrg *
147ec681f3Smrg * The above copyright notice and this permission notice (including the next
157ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
167ec681f3Smrg * Software.
177ec681f3Smrg *
187ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
197ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
207ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
217ec681f3Smrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
227ec681f3Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
237ec681f3Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
247ec681f3Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE.
257ec681f3Smrg */
267ec681f3Smrg#include <stdio.h>
277ec681f3Smrg#include <errno.h>
287ec681f3Smrg#include "pipe/p_defines.h"
297ec681f3Smrg#include "pipe/p_state.h"
307ec681f3Smrg#include "pipe/p_context.h"
317ec681f3Smrg#include "pipe/p_screen.h"
327ec681f3Smrg#include "util/u_memory.h"
337ec681f3Smrg#include "util/u_screen.h"
347ec681f3Smrg#include "util/u_inlines.h"
357ec681f3Smrg#include "util/format/u_format.h"
367ec681f3Smrg#include "util/u_upload_mgr.h"
377ec681f3Smrg#include "util/half_float.h"
387ec681f3Smrg#include "frontend/winsys_handle.h"
397ec681f3Smrg#include "frontend/sw_winsys.h"
407ec681f3Smrg#include "gallium/auxiliary/util/u_transfer.h"
417ec681f3Smrg#include "gallium/auxiliary/util/u_surface.h"
427ec681f3Smrg#include "gallium/auxiliary/util/u_framebuffer.h"
437ec681f3Smrg#include "agx_public.h"
447ec681f3Smrg#include "agx_state.h"
457ec681f3Smrg#include "magic.h"
467ec681f3Smrg#include "asahi/compiler/agx_compile.h"
477ec681f3Smrg#include "asahi/lib/decode.h"
487ec681f3Smrg#include "asahi/lib/tiling.h"
497ec681f3Smrg#include "asahi/lib/agx_formats.h"
507ec681f3Smrg
517ec681f3Smrgstatic const struct debug_named_value agx_debug_options[] = {
527ec681f3Smrg   {"trace",     AGX_DBG_TRACE,    "Trace the command stream"},
537ec681f3Smrg   {"deqp",      AGX_DBG_DEQP,     "Hacks for dEQP"},
547ec681f3Smrg   {"no16",      AGX_DBG_NO16,     "Disable 16-bit support"},
557ec681f3Smrg   DEBUG_NAMED_VALUE_END
567ec681f3Smrg};
577ec681f3Smrg
587ec681f3Smrgvoid agx_init_state_functions(struct pipe_context *ctx);
597ec681f3Smrg
607ec681f3Smrgstatic struct pipe_query *
617ec681f3Smrgagx_create_query(struct pipe_context *ctx, unsigned query_type, unsigned index)
627ec681f3Smrg{
637ec681f3Smrg   struct agx_query *query = CALLOC_STRUCT(agx_query);
647ec681f3Smrg
657ec681f3Smrg   return (struct pipe_query *)query;
667ec681f3Smrg}
677ec681f3Smrg
687ec681f3Smrgstatic void
697ec681f3Smrgagx_destroy_query(struct pipe_context *ctx, struct pipe_query *query)
707ec681f3Smrg{
717ec681f3Smrg   FREE(query);
727ec681f3Smrg}
737ec681f3Smrg
747ec681f3Smrgstatic bool
757ec681f3Smrgagx_begin_query(struct pipe_context *ctx, struct pipe_query *query)
767ec681f3Smrg{
777ec681f3Smrg   return true;
787ec681f3Smrg}
797ec681f3Smrg
807ec681f3Smrgstatic bool
817ec681f3Smrgagx_end_query(struct pipe_context *ctx, struct pipe_query *query)
827ec681f3Smrg{
837ec681f3Smrg   return true;
847ec681f3Smrg}
857ec681f3Smrg
867ec681f3Smrgstatic bool
877ec681f3Smrgagx_get_query_result(struct pipe_context *ctx,
887ec681f3Smrg                     struct pipe_query *query,
897ec681f3Smrg                     bool wait,
907ec681f3Smrg                     union pipe_query_result *vresult)
917ec681f3Smrg{
927ec681f3Smrg   uint64_t *result = (uint64_t*)vresult;
937ec681f3Smrg
947ec681f3Smrg   *result = 0;
957ec681f3Smrg   return true;
967ec681f3Smrg}
977ec681f3Smrg
987ec681f3Smrgstatic void
997ec681f3Smrgagx_set_active_query_state(struct pipe_context *pipe, bool enable)
1007ec681f3Smrg{
1017ec681f3Smrg}
1027ec681f3Smrg
1037ec681f3Smrg
1047ec681f3Smrg/*
1057ec681f3Smrg * resource
1067ec681f3Smrg */
1077ec681f3Smrg
1087ec681f3Smrgstatic struct pipe_resource *
1097ec681f3Smrgagx_resource_from_handle(struct pipe_screen *pscreen,
1107ec681f3Smrg                         const struct pipe_resource *templat,
1117ec681f3Smrg                         struct winsys_handle *whandle,
1127ec681f3Smrg                         unsigned usage)
1137ec681f3Smrg{
1147ec681f3Smrg   unreachable("Imports todo");
1157ec681f3Smrg}
1167ec681f3Smrg
1177ec681f3Smrgstatic bool
1187ec681f3Smrgagx_resource_get_handle(struct pipe_screen *pscreen,
1197ec681f3Smrg                        struct pipe_context *ctx,
1207ec681f3Smrg                        struct pipe_resource *pt,
1217ec681f3Smrg                        struct winsys_handle *handle,
1227ec681f3Smrg                        unsigned usage)
1237ec681f3Smrg{
1247ec681f3Smrg   unreachable("Handles todo");
1257ec681f3Smrg}
1267ec681f3Smrg
1277ec681f3Smrgstatic inline bool
1287ec681f3Smrgagx_is_2d(const struct agx_resource *pres)
1297ec681f3Smrg{
1307ec681f3Smrg   switch (pres->base.target) {
1317ec681f3Smrg   case PIPE_TEXTURE_2D:
1327ec681f3Smrg   case PIPE_TEXTURE_RECT:
1337ec681f3Smrg   case PIPE_TEXTURE_CUBE:
1347ec681f3Smrg      return true;
1357ec681f3Smrg   default:
1367ec681f3Smrg      return false;
1377ec681f3Smrg   }
1387ec681f3Smrg}
1397ec681f3Smrg
1407ec681f3Smrgstatic bool
1417ec681f3Smrgagx_must_tile(const struct agx_resource *pres)
1427ec681f3Smrg{
1437ec681f3Smrg   switch (pres->base.target) {
1447ec681f3Smrg   case PIPE_TEXTURE_CUBE:
1457ec681f3Smrg   case PIPE_TEXTURE_3D:
1467ec681f3Smrg      /* We don't know how to do linear for these */
1477ec681f3Smrg      return true;
1487ec681f3Smrg   default:
1497ec681f3Smrg      break;
1507ec681f3Smrg   }
1517ec681f3Smrg
1527ec681f3Smrg   return false;
1537ec681f3Smrg}
1547ec681f3Smrg
1557ec681f3Smrgstatic bool
1567ec681f3Smrgagx_should_tile(const struct agx_resource *pres)
1577ec681f3Smrg{
1587ec681f3Smrg   const unsigned valid_binding =
1597ec681f3Smrg      PIPE_BIND_DEPTH_STENCIL |
1607ec681f3Smrg      PIPE_BIND_RENDER_TARGET |
1617ec681f3Smrg      PIPE_BIND_BLENDABLE |
1627ec681f3Smrg      PIPE_BIND_SAMPLER_VIEW |
1637ec681f3Smrg      PIPE_BIND_DISPLAY_TARGET |
1647ec681f3Smrg      PIPE_BIND_SCANOUT |
1657ec681f3Smrg      PIPE_BIND_SHARED;
1667ec681f3Smrg
1677ec681f3Smrg   unsigned bpp = util_format_get_blocksizebits(pres->base.format);
1687ec681f3Smrg
1697ec681f3Smrg   bool can_tile = agx_is_2d(pres)
1707ec681f3Smrg      && (bpp == 32)
1717ec681f3Smrg      && ((pres->base.bind & ~valid_binding) == 0);
1727ec681f3Smrg
1737ec681f3Smrg   bool should_tile = (pres->base.usage != PIPE_USAGE_STREAM);
1747ec681f3Smrg   bool must_tile = agx_must_tile(pres);
1757ec681f3Smrg
1767ec681f3Smrg   assert(!(must_tile && !can_tile));
1777ec681f3Smrg   return must_tile || (can_tile && should_tile);
1787ec681f3Smrg}
1797ec681f3Smrg
1807ec681f3Smrgstatic struct pipe_resource *
1817ec681f3Smrgagx_resource_create(struct pipe_screen *screen,
1827ec681f3Smrg                    const struct pipe_resource *templ)
1837ec681f3Smrg{
1847ec681f3Smrg   struct agx_device *dev = agx_device(screen);
1857ec681f3Smrg   struct agx_resource *nresource;
1867ec681f3Smrg
1877ec681f3Smrg   nresource = CALLOC_STRUCT(agx_resource);
1887ec681f3Smrg   if (!nresource)
1897ec681f3Smrg      return NULL;
1907ec681f3Smrg
1917ec681f3Smrg   nresource->base = *templ;
1927ec681f3Smrg   nresource->base.screen = screen;
1937ec681f3Smrg
1947ec681f3Smrg   nresource->modifier = agx_should_tile(nresource) ?
1957ec681f3Smrg      DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER : DRM_FORMAT_MOD_LINEAR;
1967ec681f3Smrg
1977ec681f3Smrg   unsigned offset = 0;
1987ec681f3Smrg
1997ec681f3Smrg   for (unsigned l = 0; l <= templ->last_level; ++l) {
2007ec681f3Smrg      unsigned width = u_minify(templ->width0, l);
2017ec681f3Smrg      unsigned height = u_minify(templ->height0, l);
2027ec681f3Smrg
2037ec681f3Smrg      if (nresource->modifier == DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER) {
2047ec681f3Smrg         width = ALIGN_POT(width, 64);
2057ec681f3Smrg         height = ALIGN_POT(height, 64);
2067ec681f3Smrg      }
2077ec681f3Smrg
2087ec681f3Smrg      nresource->slices[l].line_stride =
2097ec681f3Smrg         util_format_get_stride(templ->format, width);
2107ec681f3Smrg
2117ec681f3Smrg      nresource->slices[l].offset = offset;
2127ec681f3Smrg      offset += ALIGN_POT(nresource->slices[l].line_stride * height, 0x80);
2137ec681f3Smrg   }
2147ec681f3Smrg
2157ec681f3Smrg   /* Arrays and cubemaps have the entire miptree duplicated */
2167ec681f3Smrg   nresource->array_stride = ALIGN_POT(offset, 64);
2177ec681f3Smrg   unsigned size = ALIGN_POT(nresource->array_stride * templ->array_size, 4096);
2187ec681f3Smrg
2197ec681f3Smrg   pipe_reference_init(&nresource->base.reference, 1);
2207ec681f3Smrg
2217ec681f3Smrg   struct sw_winsys *winsys = ((struct agx_screen *) screen)->winsys;
2227ec681f3Smrg
2237ec681f3Smrg   if (templ->bind & (PIPE_BIND_DISPLAY_TARGET |
2247ec681f3Smrg                      PIPE_BIND_SCANOUT |
2257ec681f3Smrg                      PIPE_BIND_SHARED)) {
2267ec681f3Smrg      unsigned width0 = templ->width0, height0 = templ->height0;
2277ec681f3Smrg
2287ec681f3Smrg      if (nresource->modifier == DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER) {
2297ec681f3Smrg         width0 = ALIGN_POT(width0, 64);
2307ec681f3Smrg         height0 = ALIGN_POT(height0, 64);
2317ec681f3Smrg      }
2327ec681f3Smrg
2337ec681f3Smrg      nresource->dt = winsys->displaytarget_create(winsys,
2347ec681f3Smrg                      templ->bind,
2357ec681f3Smrg                      templ->format,
2367ec681f3Smrg                      width0,
2377ec681f3Smrg                      height0,
2387ec681f3Smrg                      64,
2397ec681f3Smrg                      NULL /*map_front_private*/,
2407ec681f3Smrg                      &nresource->dt_stride);
2417ec681f3Smrg
2427ec681f3Smrg      nresource->slices[0].line_stride = nresource->dt_stride;
2437ec681f3Smrg      assert((nresource->dt_stride & 0xF) == 0);
2447ec681f3Smrg
2457ec681f3Smrg      offset = nresource->slices[0].line_stride * ALIGN_POT(templ->height0, 64);
2467ec681f3Smrg
2477ec681f3Smrg      if (nresource->dt == NULL) {
2487ec681f3Smrg         FREE(nresource);
2497ec681f3Smrg         return NULL;
2507ec681f3Smrg      }
2517ec681f3Smrg   }
2527ec681f3Smrg
2537ec681f3Smrg   nresource->bo = agx_bo_create(dev, size, AGX_MEMORY_TYPE_FRAMEBUFFER);
2547ec681f3Smrg
2557ec681f3Smrg   if (!nresource->bo) {
2567ec681f3Smrg      FREE(nresource);
2577ec681f3Smrg      return NULL;
2587ec681f3Smrg   }
2597ec681f3Smrg
2607ec681f3Smrg   return &nresource->base;
2617ec681f3Smrg}
2627ec681f3Smrg
2637ec681f3Smrgstatic uint8_t *
2647ec681f3Smrgagx_rsrc_offset(struct agx_resource *rsrc, unsigned level, unsigned z)
2657ec681f3Smrg{
2667ec681f3Smrg   struct agx_bo *bo = rsrc->bo;
2677ec681f3Smrg   uint8_t *map = ((uint8_t *) bo->ptr.cpu) + rsrc->slices[level].offset;
2687ec681f3Smrg   map += z * rsrc->array_stride;
2697ec681f3Smrg
2707ec681f3Smrg   return map;
2717ec681f3Smrg}
2727ec681f3Smrg
2737ec681f3Smrgstatic void
2747ec681f3Smrgagx_resource_destroy(struct pipe_screen *screen,
2757ec681f3Smrg                     struct pipe_resource *prsrc)
2767ec681f3Smrg{
2777ec681f3Smrg   struct agx_resource *rsrc = (struct agx_resource *)prsrc;
2787ec681f3Smrg
2797ec681f3Smrg   if (rsrc->dt) {
2807ec681f3Smrg      /* display target */
2817ec681f3Smrg      struct agx_screen *agx_screen = (struct agx_screen*)screen;
2827ec681f3Smrg      struct sw_winsys *winsys = agx_screen->winsys;
2837ec681f3Smrg      winsys->displaytarget_destroy(winsys, rsrc->dt);
2847ec681f3Smrg   }
2857ec681f3Smrg
2867ec681f3Smrg   agx_bo_unreference(rsrc->bo);
2877ec681f3Smrg   FREE(rsrc);
2887ec681f3Smrg}
2897ec681f3Smrg
2907ec681f3Smrg
2917ec681f3Smrg/*
2927ec681f3Smrg * transfer
2937ec681f3Smrg */
2947ec681f3Smrg
2957ec681f3Smrgstatic void
2967ec681f3Smrgagx_transfer_flush_region(struct pipe_context *pipe,
2977ec681f3Smrg                          struct pipe_transfer *transfer,
2987ec681f3Smrg                          const struct pipe_box *box)
2997ec681f3Smrg{
3007ec681f3Smrg}
3017ec681f3Smrg
3027ec681f3Smrgstatic void *
3037ec681f3Smrgagx_transfer_map(struct pipe_context *pctx,
3047ec681f3Smrg                 struct pipe_resource *resource,
3057ec681f3Smrg                 unsigned level,
3067ec681f3Smrg                 unsigned usage,  /* a combination of PIPE_MAP_x */
3077ec681f3Smrg                 const struct pipe_box *box,
3087ec681f3Smrg                 struct pipe_transfer **out_transfer)
3097ec681f3Smrg{
3107ec681f3Smrg   struct agx_context *ctx = agx_context(pctx);
3117ec681f3Smrg   struct agx_resource *rsrc = agx_resource(resource);
3127ec681f3Smrg   unsigned bytes_per_pixel = util_format_get_blocksize(resource->format);
3137ec681f3Smrg
3147ec681f3Smrg   /* Can't map tiled/compressed directly */
3157ec681f3Smrg   if ((usage & PIPE_MAP_DIRECTLY) && rsrc->modifier != DRM_FORMAT_MOD_LINEAR)
3167ec681f3Smrg      return NULL;
3177ec681f3Smrg
3187ec681f3Smrg   if (ctx->batch->cbufs[0] && resource == ctx->batch->cbufs[0]->texture)
3197ec681f3Smrg      pctx->flush(pctx, NULL, 0);
3207ec681f3Smrg   if (ctx->batch->zsbuf && resource == ctx->batch->zsbuf->texture)
3217ec681f3Smrg      pctx->flush(pctx, NULL, 0);
3227ec681f3Smrg
3237ec681f3Smrg   struct agx_transfer *transfer = CALLOC_STRUCT(agx_transfer);
3247ec681f3Smrg   transfer->base.level = level;
3257ec681f3Smrg   transfer->base.usage = usage;
3267ec681f3Smrg   transfer->base.box = *box;
3277ec681f3Smrg
3287ec681f3Smrg   pipe_resource_reference(&transfer->base.resource, resource);
3297ec681f3Smrg   *out_transfer = &transfer->base;
3307ec681f3Smrg
3317ec681f3Smrg   if (rsrc->modifier == DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER) {
3327ec681f3Smrg      transfer->base.stride = box->width * bytes_per_pixel;
3337ec681f3Smrg      transfer->base.layer_stride = transfer->base.stride * box->height;
3347ec681f3Smrg      transfer->map = calloc(transfer->base.layer_stride, box->depth);
3357ec681f3Smrg      assert(box->depth == 1);
3367ec681f3Smrg
3377ec681f3Smrg      if ((usage & PIPE_MAP_READ) && BITSET_TEST(rsrc->data_valid, level)) {
3387ec681f3Smrg         for (unsigned z = 0; z < box->depth; ++z) {
3397ec681f3Smrg            uint8_t *map = agx_rsrc_offset(rsrc, level, box->z + z);
3407ec681f3Smrg
3417ec681f3Smrg            agx_detile(map, transfer->map,
3427ec681f3Smrg               u_minify(resource->width0, level), bytes_per_pixel * 8,
3437ec681f3Smrg               transfer->base.stride / bytes_per_pixel,
3447ec681f3Smrg               box->x, box->y, box->x + box->width, box->y + box->height);
3457ec681f3Smrg         }
3467ec681f3Smrg      }
3477ec681f3Smrg
3487ec681f3Smrg      return transfer->map;
3497ec681f3Smrg   } else {
3507ec681f3Smrg      assert (rsrc->modifier == DRM_FORMAT_MOD_LINEAR);
3517ec681f3Smrg
3527ec681f3Smrg      transfer->base.stride = rsrc->slices[level].line_stride;
3537ec681f3Smrg      transfer->base.layer_stride = rsrc->array_stride;
3547ec681f3Smrg
3557ec681f3Smrg      /* Be conservative for direct writes */
3567ec681f3Smrg
3577ec681f3Smrg      if ((usage & PIPE_MAP_WRITE) && (usage & PIPE_MAP_DIRECTLY))
3587ec681f3Smrg         BITSET_SET(rsrc->data_valid, level);
3597ec681f3Smrg
3607ec681f3Smrg      return agx_rsrc_offset(rsrc, level, box->z)
3617ec681f3Smrg             + transfer->base.box.y * rsrc->slices[level].line_stride
3627ec681f3Smrg             + transfer->base.box.x * bytes_per_pixel;
3637ec681f3Smrg   }
3647ec681f3Smrg}
3657ec681f3Smrg
3667ec681f3Smrgstatic void
3677ec681f3Smrgagx_transfer_unmap(struct pipe_context *pctx,
3687ec681f3Smrg                   struct pipe_transfer *transfer)
3697ec681f3Smrg{
3707ec681f3Smrg   /* Gallium expects writeback here, so we tile */
3717ec681f3Smrg
3727ec681f3Smrg   struct agx_transfer *trans = agx_transfer(transfer);
3737ec681f3Smrg   struct pipe_resource *prsrc = transfer->resource;
3747ec681f3Smrg   struct agx_resource *rsrc = (struct agx_resource *) prsrc;
3757ec681f3Smrg   unsigned bytes_per_pixel = util_format_get_blocksize(prsrc->format);
3767ec681f3Smrg
3777ec681f3Smrg   if (transfer->usage & PIPE_MAP_WRITE)
3787ec681f3Smrg      BITSET_SET(rsrc->data_valid, transfer->level);
3797ec681f3Smrg
3807ec681f3Smrg   /* Tiling will occur in software from a staging cpu buffer */
3817ec681f3Smrg   if ((transfer->usage & PIPE_MAP_WRITE) &&
3827ec681f3Smrg         rsrc->modifier == DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER) {
3837ec681f3Smrg      assert(trans->map != NULL);
3847ec681f3Smrg
3857ec681f3Smrg      for (unsigned z = 0; z < transfer->box.depth; ++z) {
3867ec681f3Smrg         uint8_t *map = agx_rsrc_offset(rsrc, transfer->level,
3877ec681f3Smrg               transfer->box.z + z);
3887ec681f3Smrg
3897ec681f3Smrg         agx_tile(map, trans->map,
3907ec681f3Smrg            u_minify(transfer->resource->width0, transfer->level),
3917ec681f3Smrg            bytes_per_pixel * 8,
3927ec681f3Smrg            transfer->stride / bytes_per_pixel,
3937ec681f3Smrg            transfer->box.x, transfer->box.y,
3947ec681f3Smrg            transfer->box.x + transfer->box.width,
3957ec681f3Smrg            transfer->box.y + transfer->box.height);
3967ec681f3Smrg      }
3977ec681f3Smrg   }
3987ec681f3Smrg
3997ec681f3Smrg   /* Free the transfer */
4007ec681f3Smrg   free(trans->map);
4017ec681f3Smrg   pipe_resource_reference(&transfer->resource, NULL);
4027ec681f3Smrg   FREE(transfer);
4037ec681f3Smrg}
4047ec681f3Smrg
4057ec681f3Smrg/*
4067ec681f3Smrg * clear/copy
4077ec681f3Smrg */
4087ec681f3Smrgstatic void
4097ec681f3Smrgagx_clear(struct pipe_context *pctx, unsigned buffers, const struct pipe_scissor_state *scissor_state,
4107ec681f3Smrg          const union pipe_color_union *color, double depth, unsigned stencil)
4117ec681f3Smrg{
4127ec681f3Smrg   struct agx_context *ctx = agx_context(pctx);
4137ec681f3Smrg   ctx->batch->clear |= buffers;
4147ec681f3Smrg   memcpy(ctx->batch->clear_color, color->f, sizeof(color->f));
4157ec681f3Smrg}
4167ec681f3Smrg
4177ec681f3Smrg
4187ec681f3Smrgstatic void
4197ec681f3Smrgagx_flush_resource(struct pipe_context *ctx,
4207ec681f3Smrg                   struct pipe_resource *resource)
4217ec681f3Smrg{
4227ec681f3Smrg}
4237ec681f3Smrg
4247ec681f3Smrg/*
4257ec681f3Smrg * context
4267ec681f3Smrg */
4277ec681f3Smrgstatic void
4287ec681f3Smrgagx_flush(struct pipe_context *pctx,
4297ec681f3Smrg          struct pipe_fence_handle **fence,
4307ec681f3Smrg          unsigned flags)
4317ec681f3Smrg{
4327ec681f3Smrg   struct agx_context *ctx = agx_context(pctx);
4337ec681f3Smrg
4347ec681f3Smrg   if (fence)
4357ec681f3Smrg      *fence = NULL;
4367ec681f3Smrg
4377ec681f3Smrg   /* TODO */
4387ec681f3Smrg   if (!ctx->batch->cbufs[0])
4397ec681f3Smrg      return;
4407ec681f3Smrg
4417ec681f3Smrg   /* Nothing to do */
4427ec681f3Smrg   if (!(ctx->batch->draw | ctx->batch->clear))
4437ec681f3Smrg      return;
4447ec681f3Smrg
4457ec681f3Smrg   /* Finalize the encoder */
4467ec681f3Smrg   uint8_t stop[5 + 64] = { 0x00, 0x00, 0x00, 0xc0, 0x00 };
4477ec681f3Smrg   memcpy(ctx->batch->encoder_current, stop, sizeof(stop));
4487ec681f3Smrg
4497ec681f3Smrg   /* Emit the commandbuffer */
4507ec681f3Smrg   uint64_t pipeline_clear = 0;
4517ec681f3Smrg   bool clear_pipeline_textures = false;
4527ec681f3Smrg
4537ec681f3Smrg   struct agx_device *dev = agx_device(pctx->screen);
4547ec681f3Smrg
4557ec681f3Smrg   if (ctx->batch->clear & PIPE_CLEAR_COLOR0) {
4567ec681f3Smrg      uint16_t clear_colour[4] = {
4577ec681f3Smrg         _mesa_float_to_half(ctx->batch->clear_color[0]),
4587ec681f3Smrg         _mesa_float_to_half(ctx->batch->clear_color[1]),
4597ec681f3Smrg         _mesa_float_to_half(ctx->batch->clear_color[2]),
4607ec681f3Smrg         _mesa_float_to_half(ctx->batch->clear_color[3])
4617ec681f3Smrg      };
4627ec681f3Smrg
4637ec681f3Smrg
4647ec681f3Smrg      pipeline_clear = agx_build_clear_pipeline(ctx,
4657ec681f3Smrg                               dev->internal.clear,
4667ec681f3Smrg                               agx_pool_upload(&ctx->batch->pool, clear_colour, sizeof(clear_colour)));
4677ec681f3Smrg   } else {
4687ec681f3Smrg      enum pipe_format fmt = ctx->batch->cbufs[0]->format;
4697ec681f3Smrg      enum agx_format internal = agx_pixel_format[fmt].internal;
4707ec681f3Smrg      uint32_t shader = dev->reload.format[internal];
4717ec681f3Smrg
4727ec681f3Smrg      pipeline_clear = agx_build_reload_pipeline(ctx, shader,
4737ec681f3Smrg                               ctx->batch->cbufs[0]);
4747ec681f3Smrg
4757ec681f3Smrg      clear_pipeline_textures = true;
4767ec681f3Smrg   }
4777ec681f3Smrg
4787ec681f3Smrg   uint64_t pipeline_store =
4797ec681f3Smrg      agx_build_store_pipeline(ctx,
4807ec681f3Smrg                               dev->internal.store,
4817ec681f3Smrg                               agx_pool_upload(&ctx->batch->pool, ctx->render_target[0], sizeof(ctx->render_target)));
4827ec681f3Smrg
4837ec681f3Smrg   /* Pipelines must 64 aligned */
4847ec681f3Smrg   struct agx_ptr pipeline_null =
4857ec681f3Smrg      agx_pool_alloc_aligned(&ctx->batch->pipeline_pool, 64, 64);
4867ec681f3Smrg   memset(pipeline_null.cpu, 0, 64);
4877ec681f3Smrg
4887ec681f3Smrg   struct agx_resource *rt0 = agx_resource(ctx->batch->cbufs[0]->texture);
4897ec681f3Smrg   BITSET_SET(rt0->data_valid, 0);
4907ec681f3Smrg
4917ec681f3Smrg   struct agx_resource *zbuf = ctx->batch->zsbuf ?
4927ec681f3Smrg      agx_resource(ctx->batch->zsbuf->texture) : NULL;
4937ec681f3Smrg
4947ec681f3Smrg   if (zbuf)
4957ec681f3Smrg      BITSET_SET(zbuf->data_valid, 0);
4967ec681f3Smrg
4977ec681f3Smrg   /* BO list for a given batch consists of:
4987ec681f3Smrg    *  - BOs for the batch's framebuffer surfaces
4997ec681f3Smrg    *  - BOs for the batch's pools
5007ec681f3Smrg    *  - BOs for the encoder
5017ec681f3Smrg    *  - BO for internal shaders
5027ec681f3Smrg    *  - BOs added to the batch explicitly
5037ec681f3Smrg    */
5047ec681f3Smrg   struct agx_batch *batch = ctx->batch;
5057ec681f3Smrg
5067ec681f3Smrg   agx_batch_add_bo(batch, batch->encoder);
5077ec681f3Smrg   agx_batch_add_bo(batch, batch->scissor.bo);
5087ec681f3Smrg   agx_batch_add_bo(batch, dev->internal.bo);
5097ec681f3Smrg   agx_batch_add_bo(batch, dev->reload.bo);
5107ec681f3Smrg
5117ec681f3Smrg   for (unsigned i = 0; i < batch->nr_cbufs; ++i) {
5127ec681f3Smrg      struct pipe_surface *surf = batch->cbufs[i];
5137ec681f3Smrg      assert(surf != NULL && surf->texture != NULL);
5147ec681f3Smrg      struct agx_resource *rsrc = agx_resource(surf->texture);
5157ec681f3Smrg      agx_batch_add_bo(batch, rsrc->bo);
5167ec681f3Smrg   }
5177ec681f3Smrg
5187ec681f3Smrg   if (batch->zsbuf) {
5197ec681f3Smrg      struct pipe_surface *surf = batch->zsbuf;
5207ec681f3Smrg      struct agx_resource *rsrc = agx_resource(surf->texture);
5217ec681f3Smrg      agx_batch_add_bo(batch, rsrc->bo);
5227ec681f3Smrg   }
5237ec681f3Smrg
5247ec681f3Smrg   unsigned handle_count =
5257ec681f3Smrg      BITSET_COUNT(batch->bo_list) +
5267ec681f3Smrg      agx_pool_num_bos(&batch->pool) +
5277ec681f3Smrg      agx_pool_num_bos(&batch->pipeline_pool);
5287ec681f3Smrg
5297ec681f3Smrg   uint32_t *handles = calloc(sizeof(uint32_t), handle_count);
5307ec681f3Smrg   unsigned handle = 0, handle_i = 0;
5317ec681f3Smrg
5327ec681f3Smrg   BITSET_FOREACH_SET(handle, batch->bo_list, sizeof(batch->bo_list) * 8) {
5337ec681f3Smrg      handles[handle_i++] = handle;
5347ec681f3Smrg   }
5357ec681f3Smrg
5367ec681f3Smrg   agx_pool_get_bo_handles(&batch->pool, handles + handle_i);
5377ec681f3Smrg   handle_i += agx_pool_num_bos(&batch->pool);
5387ec681f3Smrg
5397ec681f3Smrg   agx_pool_get_bo_handles(&batch->pipeline_pool, handles + handle_i);
5407ec681f3Smrg   handle_i += agx_pool_num_bos(&batch->pipeline_pool);
5417ec681f3Smrg
5427ec681f3Smrg   /* Size calculation should've been exact */
5437ec681f3Smrg   assert(handle_i == handle_count);
5447ec681f3Smrg
5457ec681f3Smrg   unsigned cmdbuf_id = agx_get_global_id(dev);
5467ec681f3Smrg   unsigned encoder_id = agx_get_global_id(dev);
5477ec681f3Smrg
5487ec681f3Smrg   unsigned cmdbuf_size = demo_cmdbuf(dev->cmdbuf.ptr.cpu,
5497ec681f3Smrg               dev->cmdbuf.size,
5507ec681f3Smrg               &ctx->batch->pool,
5517ec681f3Smrg               ctx->batch->encoder->ptr.gpu,
5527ec681f3Smrg               encoder_id,
5537ec681f3Smrg               ctx->batch->scissor.bo->ptr.gpu,
5547ec681f3Smrg               ctx->batch->width,
5557ec681f3Smrg               ctx->batch->height,
5567ec681f3Smrg               pipeline_null.gpu,
5577ec681f3Smrg               pipeline_clear,
5587ec681f3Smrg               pipeline_store,
5597ec681f3Smrg               rt0->bo->ptr.gpu,
5607ec681f3Smrg               clear_pipeline_textures);
5617ec681f3Smrg
5627ec681f3Smrg   /* Generate the mapping table from the BO list */
5637ec681f3Smrg   demo_mem_map(dev->memmap.ptr.cpu, dev->memmap.size, handles, handle_count,
5647ec681f3Smrg                cmdbuf_id, encoder_id, cmdbuf_size);
5657ec681f3Smrg
5667ec681f3Smrg   free(handles);
5677ec681f3Smrg
5687ec681f3Smrg   agx_submit_cmdbuf(dev, dev->cmdbuf.handle, dev->memmap.handle, dev->queue.id);
5697ec681f3Smrg
5707ec681f3Smrg   agx_wait_queue(dev->queue);
5717ec681f3Smrg
5727ec681f3Smrg   if (dev->debug & AGX_DBG_TRACE) {
5737ec681f3Smrg      agxdecode_cmdstream(dev->cmdbuf.handle, dev->memmap.handle, true);
5747ec681f3Smrg      agxdecode_next_frame();
5757ec681f3Smrg   }
5767ec681f3Smrg
5777ec681f3Smrg   memset(batch->bo_list, 0, sizeof(batch->bo_list));
5787ec681f3Smrg   agx_pool_cleanup(&ctx->batch->pool);
5797ec681f3Smrg   agx_pool_cleanup(&ctx->batch->pipeline_pool);
5807ec681f3Smrg   agx_pool_init(&ctx->batch->pool, dev, AGX_MEMORY_TYPE_FRAMEBUFFER, true);
5817ec681f3Smrg   agx_pool_init(&ctx->batch->pipeline_pool, dev, AGX_MEMORY_TYPE_CMDBUF_32, true);
5827ec681f3Smrg   ctx->batch->clear = 0;
5837ec681f3Smrg   ctx->batch->draw = 0;
5847ec681f3Smrg   ctx->batch->encoder_current = ctx->batch->encoder->ptr.cpu;
5857ec681f3Smrg   ctx->batch->scissor.count = 0;
5867ec681f3Smrg   ctx->dirty = ~0;
5877ec681f3Smrg}
5887ec681f3Smrg
5897ec681f3Smrgstatic void
5907ec681f3Smrgagx_destroy_context(struct pipe_context *pctx)
5917ec681f3Smrg{
5927ec681f3Smrg   struct agx_context *ctx = agx_context(pctx);
5937ec681f3Smrg
5947ec681f3Smrg   if (pctx->stream_uploader)
5957ec681f3Smrg      u_upload_destroy(pctx->stream_uploader);
5967ec681f3Smrg
5977ec681f3Smrg   if (ctx->blitter)
5987ec681f3Smrg      util_blitter_destroy(ctx->blitter);
5997ec681f3Smrg
6007ec681f3Smrg   util_unreference_framebuffer_state(&ctx->framebuffer);
6017ec681f3Smrg
6027ec681f3Smrg   FREE(ctx);
6037ec681f3Smrg}
6047ec681f3Smrg
6057ec681f3Smrgstatic void
6067ec681f3Smrgagx_invalidate_resource(struct pipe_context *ctx,
6077ec681f3Smrg                        struct pipe_resource *resource)
6087ec681f3Smrg{
6097ec681f3Smrg}
6107ec681f3Smrg
6117ec681f3Smrgstatic struct pipe_context *
6127ec681f3Smrgagx_create_context(struct pipe_screen *screen,
6137ec681f3Smrg                   void *priv, unsigned flags)
6147ec681f3Smrg{
6157ec681f3Smrg   struct agx_context *ctx = CALLOC_STRUCT(agx_context);
6167ec681f3Smrg   struct pipe_context *pctx = &ctx->base;
6177ec681f3Smrg
6187ec681f3Smrg   if (!ctx)
6197ec681f3Smrg      return NULL;
6207ec681f3Smrg
6217ec681f3Smrg   pctx->screen = screen;
6227ec681f3Smrg   pctx->priv = priv;
6237ec681f3Smrg
6247ec681f3Smrg   ctx->batch = CALLOC_STRUCT(agx_batch);
6257ec681f3Smrg   agx_pool_init(&ctx->batch->pool,
6267ec681f3Smrg                 agx_device(screen), AGX_MEMORY_TYPE_FRAMEBUFFER, true);
6277ec681f3Smrg   agx_pool_init(&ctx->batch->pipeline_pool,
6287ec681f3Smrg                 agx_device(screen), AGX_MEMORY_TYPE_SHADER, true);
6297ec681f3Smrg   ctx->batch->encoder = agx_bo_create(agx_device(screen), 0x80000, AGX_MEMORY_TYPE_FRAMEBUFFER);
6307ec681f3Smrg   ctx->batch->encoder_current = ctx->batch->encoder->ptr.cpu;
6317ec681f3Smrg   ctx->batch->scissor.bo = agx_bo_create(agx_device(screen), 0x80000, AGX_MEMORY_TYPE_FRAMEBUFFER);
6327ec681f3Smrg
6337ec681f3Smrg   /* Upload fixed shaders (TODO: compile them?) */
6347ec681f3Smrg
6357ec681f3Smrg   pctx->stream_uploader = u_upload_create_default(pctx);
6367ec681f3Smrg   if (!pctx->stream_uploader) {
6377ec681f3Smrg      FREE(pctx);
6387ec681f3Smrg      return NULL;
6397ec681f3Smrg   }
6407ec681f3Smrg   pctx->const_uploader = pctx->stream_uploader;
6417ec681f3Smrg
6427ec681f3Smrg   pctx->destroy = agx_destroy_context;
6437ec681f3Smrg   pctx->flush = agx_flush;
6447ec681f3Smrg   pctx->clear = agx_clear;
6457ec681f3Smrg   pctx->resource_copy_region = util_resource_copy_region;
6467ec681f3Smrg   pctx->blit = agx_blit;
6477ec681f3Smrg   pctx->flush_resource = agx_flush_resource;
6487ec681f3Smrg   pctx->create_query = agx_create_query;
6497ec681f3Smrg   pctx->destroy_query = agx_destroy_query;
6507ec681f3Smrg   pctx->begin_query = agx_begin_query;
6517ec681f3Smrg   pctx->end_query = agx_end_query;
6527ec681f3Smrg   pctx->get_query_result = agx_get_query_result;
6537ec681f3Smrg   pctx->set_active_query_state = agx_set_active_query_state;
6547ec681f3Smrg   pctx->buffer_map = agx_transfer_map;
6557ec681f3Smrg   pctx->texture_map = agx_transfer_map;
6567ec681f3Smrg   pctx->transfer_flush_region = agx_transfer_flush_region;
6577ec681f3Smrg   pctx->buffer_unmap = agx_transfer_unmap;
6587ec681f3Smrg   pctx->texture_unmap = agx_transfer_unmap;
6597ec681f3Smrg   pctx->buffer_subdata = u_default_buffer_subdata;
6607ec681f3Smrg   pctx->texture_subdata = u_default_texture_subdata;
6617ec681f3Smrg   pctx->invalidate_resource = agx_invalidate_resource;
6627ec681f3Smrg   agx_init_state_functions(pctx);
6637ec681f3Smrg
6647ec681f3Smrg
6657ec681f3Smrg   ctx->blitter = util_blitter_create(pctx);
6667ec681f3Smrg
6677ec681f3Smrg   return pctx;
6687ec681f3Smrg}
6697ec681f3Smrg
6707ec681f3Smrgstatic void
6717ec681f3Smrgagx_flush_frontbuffer(struct pipe_screen *_screen,
6727ec681f3Smrg                      struct pipe_context *pctx,
6737ec681f3Smrg                      struct pipe_resource *prsrc,
6747ec681f3Smrg                      unsigned level, unsigned layer,
6757ec681f3Smrg                      void *context_private, struct pipe_box *box)
6767ec681f3Smrg{
6777ec681f3Smrg   struct agx_resource *rsrc = (struct agx_resource *) prsrc;
6787ec681f3Smrg   struct agx_screen *agx_screen = (struct agx_screen*)_screen;
6797ec681f3Smrg   struct sw_winsys *winsys = agx_screen->winsys;
6807ec681f3Smrg
6817ec681f3Smrg   /* Dump the framebuffer */
6827ec681f3Smrg   assert (rsrc->dt);
6837ec681f3Smrg   void *map = winsys->displaytarget_map(winsys, rsrc->dt, PIPE_USAGE_DEFAULT);
6847ec681f3Smrg   assert(map != NULL);
6857ec681f3Smrg
6867ec681f3Smrg   if (rsrc->modifier == DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER) {
6877ec681f3Smrg      agx_detile(rsrc->bo->ptr.cpu, map,
6887ec681f3Smrg                 rsrc->base.width0, 32, rsrc->dt_stride / 4,
6897ec681f3Smrg                 0, 0, rsrc->base.width0, rsrc->base.height0);
6907ec681f3Smrg   } else {
6917ec681f3Smrg      memcpy(map, rsrc->bo->ptr.cpu, rsrc->dt_stride * rsrc->base.height0);
6927ec681f3Smrg   }
6937ec681f3Smrg
6947ec681f3Smrg   winsys->displaytarget_display(winsys, rsrc->dt, context_private, box);
6957ec681f3Smrg}
6967ec681f3Smrg
6977ec681f3Smrgstatic const char *
6987ec681f3Smrgagx_get_vendor(struct pipe_screen* pscreen)
6997ec681f3Smrg{
7007ec681f3Smrg   return "Asahi";
7017ec681f3Smrg}
7027ec681f3Smrg
7037ec681f3Smrgstatic const char *
7047ec681f3Smrgagx_get_device_vendor(struct pipe_screen* pscreen)
7057ec681f3Smrg{
7067ec681f3Smrg   return "Apple";
7077ec681f3Smrg}
7087ec681f3Smrg
7097ec681f3Smrgstatic const char *
7107ec681f3Smrgagx_get_name(struct pipe_screen* pscreen)
7117ec681f3Smrg{
7127ec681f3Smrg   return "Apple M1 (G13G B0)";
7137ec681f3Smrg}
7147ec681f3Smrg
7157ec681f3Smrgstatic int
7167ec681f3Smrgagx_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
7177ec681f3Smrg{
7187ec681f3Smrg   bool is_deqp = agx_device(pscreen)->debug & AGX_DBG_DEQP;
7197ec681f3Smrg
7207ec681f3Smrg   switch (param) {
7217ec681f3Smrg   case PIPE_CAP_NPOT_TEXTURES:
7227ec681f3Smrg   case PIPE_CAP_MIXED_COLOR_DEPTH_BITS:
7237ec681f3Smrg   case PIPE_CAP_FRAGMENT_SHADER_TEXTURE_LOD:
7247ec681f3Smrg   case PIPE_CAP_VERTEX_SHADER_SATURATE:
7257ec681f3Smrg   case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
7267ec681f3Smrg   case PIPE_CAP_DEPTH_CLIP_DISABLE:
7277ec681f3Smrg   case PIPE_CAP_MIXED_COLORBUFFER_FORMATS:
7287ec681f3Smrg   case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES:
7297ec681f3Smrg   case PIPE_CAP_FRAGMENT_SHADER_DERIVATIVES:
7307ec681f3Smrg   case PIPE_CAP_FRAMEBUFFER_NO_ATTACHMENT:
7317ec681f3Smrg   case PIPE_CAP_CLIP_HALFZ:
7327ec681f3Smrg      return 1;
7337ec681f3Smrg
7347ec681f3Smrg   case PIPE_CAP_MAX_RENDER_TARGETS:
7357ec681f3Smrg      return 1;
7367ec681f3Smrg
7377ec681f3Smrg   case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
7387ec681f3Smrg      return 0;
7397ec681f3Smrg
7407ec681f3Smrg   case PIPE_CAP_OCCLUSION_QUERY:
7417ec681f3Smrg   case PIPE_CAP_PRIMITIVE_RESTART:
7427ec681f3Smrg   case PIPE_CAP_PRIMITIVE_RESTART_FIXED_INDEX:
7437ec681f3Smrg      return true;
7447ec681f3Smrg
7457ec681f3Smrg   case PIPE_CAP_SAMPLER_VIEW_TARGET:
7467ec681f3Smrg   case PIPE_CAP_TEXTURE_SWIZZLE:
7477ec681f3Smrg   case PIPE_CAP_BLEND_EQUATION_SEPARATE:
7487ec681f3Smrg   case PIPE_CAP_INDEP_BLEND_ENABLE:
7497ec681f3Smrg   case PIPE_CAP_INDEP_BLEND_FUNC:
7507ec681f3Smrg   case PIPE_CAP_ACCELERATED:
7517ec681f3Smrg   case PIPE_CAP_UMA:
7527ec681f3Smrg   case PIPE_CAP_TEXTURE_FLOAT_LINEAR:
7537ec681f3Smrg   case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR:
7547ec681f3Smrg   case PIPE_CAP_TGSI_ARRAY_COMPONENTS:
7557ec681f3Smrg   case PIPE_CAP_CS_DERIVED_SYSTEM_VALUES_SUPPORTED:
7567ec681f3Smrg   case PIPE_CAP_PACKED_UNIFORMS:
7577ec681f3Smrg      return 1;
7587ec681f3Smrg
7597ec681f3Smrg   case PIPE_CAP_TGSI_INSTANCEID:
7607ec681f3Smrg   case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR:
7617ec681f3Smrg   case PIPE_CAP_TEXTURE_MULTISAMPLE:
7627ec681f3Smrg   case PIPE_CAP_SURFACE_SAMPLE_COUNT:
7637ec681f3Smrg      return is_deqp;
7647ec681f3Smrg
7657ec681f3Smrg   case PIPE_CAP_COPY_BETWEEN_COMPRESSED_AND_PLAIN_FORMATS:
7667ec681f3Smrg      return 0;
7677ec681f3Smrg
7687ec681f3Smrg   case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS:
7697ec681f3Smrg      return is_deqp ? PIPE_MAX_SO_BUFFERS : 0;
7707ec681f3Smrg
7717ec681f3Smrg   case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS:
7727ec681f3Smrg   case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS:
7737ec681f3Smrg      return is_deqp ? PIPE_MAX_SO_OUTPUTS : 0;
7747ec681f3Smrg
7757ec681f3Smrg   case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
7767ec681f3Smrg   case PIPE_CAP_STREAM_OUTPUT_INTERLEAVE_BUFFERS:
7777ec681f3Smrg      return is_deqp ? 1 : 0;
7787ec681f3Smrg
7797ec681f3Smrg   case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
7807ec681f3Smrg      return is_deqp ? 256 : 0;
7817ec681f3Smrg
7827ec681f3Smrg   case PIPE_CAP_GLSL_FEATURE_LEVEL:
7837ec681f3Smrg   case PIPE_CAP_GLSL_FEATURE_LEVEL_COMPATIBILITY:
7847ec681f3Smrg      return 130;
7857ec681f3Smrg   case PIPE_CAP_ESSL_FEATURE_LEVEL:
7867ec681f3Smrg      return 120;
7877ec681f3Smrg
7887ec681f3Smrg   case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
7897ec681f3Smrg      return 16;
7907ec681f3Smrg
7917ec681f3Smrg   case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE:
7927ec681f3Smrg      return 65536;
7937ec681f3Smrg
7947ec681f3Smrg   case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
7957ec681f3Smrg      return 64;
7967ec681f3Smrg
7977ec681f3Smrg   case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
7987ec681f3Smrg      return 1;
7997ec681f3Smrg
8007ec681f3Smrg   case PIPE_CAP_MAX_TEXTURE_2D_SIZE:
8017ec681f3Smrg      return 16384;
8027ec681f3Smrg   case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
8037ec681f3Smrg   case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
8047ec681f3Smrg      return 13;
8057ec681f3Smrg
8067ec681f3Smrg   case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
8077ec681f3Smrg      return 0;
8087ec681f3Smrg
8097ec681f3Smrg   case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
8107ec681f3Smrg   case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
8117ec681f3Smrg   case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
8127ec681f3Smrg   case PIPE_CAP_TGSI_TEXCOORD:
8137ec681f3Smrg   case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL:
8147ec681f3Smrg   case PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL:
8157ec681f3Smrg   case PIPE_CAP_SEAMLESS_CUBE_MAP:
8167ec681f3Smrg   case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
8177ec681f3Smrg      return true;
8187ec681f3Smrg   case PIPE_CAP_TGSI_FS_POINT_IS_SYSVAL:
8197ec681f3Smrg      return false;
8207ec681f3Smrg
8217ec681f3Smrg   case PIPE_CAP_MAX_VERTEX_ELEMENT_SRC_OFFSET:
8227ec681f3Smrg      return 0xffff;
8237ec681f3Smrg
8247ec681f3Smrg   case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:
8257ec681f3Smrg      return 0;
8267ec681f3Smrg
8277ec681f3Smrg   case PIPE_CAP_ENDIANNESS:
8287ec681f3Smrg      return PIPE_ENDIAN_LITTLE;
8297ec681f3Smrg
8307ec681f3Smrg   case PIPE_CAP_VIDEO_MEMORY: {
8317ec681f3Smrg      uint64_t system_memory;
8327ec681f3Smrg
8337ec681f3Smrg      if (!os_get_total_physical_memory(&system_memory))
8347ec681f3Smrg         return 0;
8357ec681f3Smrg
8367ec681f3Smrg      return (int)(system_memory >> 20);
8377ec681f3Smrg   }
8387ec681f3Smrg
8397ec681f3Smrg   case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT:
8407ec681f3Smrg      return 4;
8417ec681f3Smrg
8427ec681f3Smrg   case PIPE_CAP_MAX_VARYINGS:
8437ec681f3Smrg      return 16;
8447ec681f3Smrg
8457ec681f3Smrg   case PIPE_CAP_FLATSHADE:
8467ec681f3Smrg   case PIPE_CAP_TWO_SIDED_COLOR:
8477ec681f3Smrg   case PIPE_CAP_ALPHA_TEST:
8487ec681f3Smrg   case PIPE_CAP_CLIP_PLANES:
8497ec681f3Smrg   case PIPE_CAP_NIR_IMAGES_AS_DEREF:
8507ec681f3Smrg      return 0;
8517ec681f3Smrg
8527ec681f3Smrg   case PIPE_CAP_SHAREABLE_SHADERS:
8537ec681f3Smrg      return 1;
8547ec681f3Smrg
8557ec681f3Smrg   default:
8567ec681f3Smrg      return u_pipe_screen_get_param_defaults(pscreen, param);
8577ec681f3Smrg   }
8587ec681f3Smrg}
8597ec681f3Smrg
8607ec681f3Smrgstatic float
8617ec681f3Smrgagx_get_paramf(struct pipe_screen* pscreen,
8627ec681f3Smrg               enum pipe_capf param)
8637ec681f3Smrg{
8647ec681f3Smrg   switch (param) {
8657ec681f3Smrg   case PIPE_CAPF_MAX_LINE_WIDTH:
8667ec681f3Smrg   case PIPE_CAPF_MAX_LINE_WIDTH_AA:
8677ec681f3Smrg      return 16.0; /* Off-by-one fixed point 4:4 encoding */
8687ec681f3Smrg
8697ec681f3Smrg   case PIPE_CAPF_MAX_POINT_WIDTH:
8707ec681f3Smrg   case PIPE_CAPF_MAX_POINT_WIDTH_AA:
8717ec681f3Smrg      return 511.95f;
8727ec681f3Smrg
8737ec681f3Smrg   case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY:
8747ec681f3Smrg      return 16.0;
8757ec681f3Smrg
8767ec681f3Smrg   case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS:
8777ec681f3Smrg      return 16.0; /* arbitrary */
8787ec681f3Smrg
8797ec681f3Smrg   case PIPE_CAPF_MIN_CONSERVATIVE_RASTER_DILATE:
8807ec681f3Smrg   case PIPE_CAPF_MAX_CONSERVATIVE_RASTER_DILATE:
8817ec681f3Smrg   case PIPE_CAPF_CONSERVATIVE_RASTER_DILATE_GRANULARITY:
8827ec681f3Smrg      return 0.0f;
8837ec681f3Smrg
8847ec681f3Smrg   default:
8857ec681f3Smrg      debug_printf("Unexpected PIPE_CAPF %d query\n", param);
8867ec681f3Smrg      return 0.0;
8877ec681f3Smrg   }
8887ec681f3Smrg}
8897ec681f3Smrg
8907ec681f3Smrgstatic int
8917ec681f3Smrgagx_get_shader_param(struct pipe_screen* pscreen,
8927ec681f3Smrg                     enum pipe_shader_type shader,
8937ec681f3Smrg                     enum pipe_shader_cap param)
8947ec681f3Smrg{
8957ec681f3Smrg   bool is_deqp = agx_device(pscreen)->debug & AGX_DBG_DEQP;
8967ec681f3Smrg   bool is_no16 = agx_device(pscreen)->debug & AGX_DBG_NO16;
8977ec681f3Smrg
8987ec681f3Smrg   if (shader != PIPE_SHADER_VERTEX &&
8997ec681f3Smrg       shader != PIPE_SHADER_FRAGMENT)
9007ec681f3Smrg      return 0;
9017ec681f3Smrg
9027ec681f3Smrg   /* this is probably not totally correct.. but it's a start: */
9037ec681f3Smrg   switch (param) {
9047ec681f3Smrg   case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
9057ec681f3Smrg   case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
9067ec681f3Smrg   case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
9077ec681f3Smrg   case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:
9087ec681f3Smrg      return 16384;
9097ec681f3Smrg
9107ec681f3Smrg   case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:
9117ec681f3Smrg      return 1024;
9127ec681f3Smrg
9137ec681f3Smrg   case PIPE_SHADER_CAP_MAX_INPUTS:
9147ec681f3Smrg      return 16;
9157ec681f3Smrg
9167ec681f3Smrg   case PIPE_SHADER_CAP_MAX_OUTPUTS:
9177ec681f3Smrg      return shader == PIPE_SHADER_FRAGMENT ? 4 : 16;
9187ec681f3Smrg
9197ec681f3Smrg   case PIPE_SHADER_CAP_MAX_TEMPS:
9207ec681f3Smrg      return 256; /* GL_MAX_PROGRAM_TEMPORARIES_ARB */
9217ec681f3Smrg
9227ec681f3Smrg   case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE:
9237ec681f3Smrg      return 16 * 1024 * sizeof(float);
9247ec681f3Smrg
9257ec681f3Smrg   case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
9267ec681f3Smrg      return 16;
9277ec681f3Smrg
9287ec681f3Smrg   case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:
9297ec681f3Smrg      return 0;
9307ec681f3Smrg
9317ec681f3Smrg   case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
9327ec681f3Smrg   case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:
9337ec681f3Smrg   case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:
9347ec681f3Smrg   case PIPE_SHADER_CAP_SUBROUTINES:
9357ec681f3Smrg   case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED:
9367ec681f3Smrg      return 0;
9377ec681f3Smrg
9387ec681f3Smrg   case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:
9397ec681f3Smrg      return is_deqp;
9407ec681f3Smrg
9417ec681f3Smrg   case PIPE_SHADER_CAP_INTEGERS:
9427ec681f3Smrg      return true;
9437ec681f3Smrg
9447ec681f3Smrg   case PIPE_SHADER_CAP_FP16:
9457ec681f3Smrg   case PIPE_SHADER_CAP_GLSL_16BIT_CONSTS:
9467ec681f3Smrg   case PIPE_SHADER_CAP_FP16_DERIVATIVES:
9477ec681f3Smrg   case PIPE_SHADER_CAP_FP16_CONST_BUFFERS:
9487ec681f3Smrg   case PIPE_SHADER_CAP_INT16:
9497ec681f3Smrg      return !is_no16;
9507ec681f3Smrg
9517ec681f3Smrg   case PIPE_SHADER_CAP_INT64_ATOMICS:
9527ec681f3Smrg   case PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED:
9537ec681f3Smrg   case PIPE_SHADER_CAP_TGSI_DFRACEXP_DLDEXP_SUPPORTED:
9547ec681f3Smrg   case PIPE_SHADER_CAP_TGSI_LDEXP_SUPPORTED:
9557ec681f3Smrg   case PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED:
9567ec681f3Smrg   case PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE:
9577ec681f3Smrg      return 0;
9587ec681f3Smrg
9597ec681f3Smrg   case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
9607ec681f3Smrg   case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS:
9617ec681f3Smrg      return 16; /* XXX: How many? */
9627ec681f3Smrg
9637ec681f3Smrg   case PIPE_SHADER_CAP_PREFERRED_IR:
9647ec681f3Smrg      return PIPE_SHADER_IR_NIR;
9657ec681f3Smrg
9667ec681f3Smrg   case PIPE_SHADER_CAP_SUPPORTED_IRS:
9677ec681f3Smrg      return (1 << PIPE_SHADER_IR_NIR) | (1 << PIPE_SHADER_IR_NIR_SERIALIZED);
9687ec681f3Smrg
9697ec681f3Smrg   case PIPE_SHADER_CAP_MAX_UNROLL_ITERATIONS_HINT:
9707ec681f3Smrg      return 32;
9717ec681f3Smrg
9727ec681f3Smrg   case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS:
9737ec681f3Smrg   case PIPE_SHADER_CAP_MAX_SHADER_IMAGES:
9747ec681f3Smrg   case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTERS:
9757ec681f3Smrg   case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTER_BUFFERS:
9767ec681f3Smrg   case PIPE_SHADER_CAP_TGSI_SKIP_MERGE_REGISTERS:
9777ec681f3Smrg   case PIPE_SHADER_CAP_LOWER_IF_THRESHOLD:
9787ec681f3Smrg      return 0;
9797ec681f3Smrg
9807ec681f3Smrg   default:
9817ec681f3Smrg      /* Other params are unknown */
9827ec681f3Smrg      return 0;
9837ec681f3Smrg   }
9847ec681f3Smrg
9857ec681f3Smrg   return 0;
9867ec681f3Smrg}
9877ec681f3Smrg
9887ec681f3Smrgstatic int
9897ec681f3Smrgagx_get_compute_param(struct pipe_screen *pscreen,
9907ec681f3Smrg                      enum pipe_shader_ir ir_type,
9917ec681f3Smrg                      enum pipe_compute_cap param,
9927ec681f3Smrg                      void *ret)
9937ec681f3Smrg{
9947ec681f3Smrg   return 0;
9957ec681f3Smrg}
9967ec681f3Smrg
9977ec681f3Smrgstatic bool
9987ec681f3Smrgagx_is_format_supported(struct pipe_screen* pscreen,
9997ec681f3Smrg                        enum pipe_format format,
10007ec681f3Smrg                        enum pipe_texture_target target,
10017ec681f3Smrg                        unsigned sample_count,
10027ec681f3Smrg                        unsigned storage_sample_count,
10037ec681f3Smrg                        unsigned usage)
10047ec681f3Smrg{
10057ec681f3Smrg   const struct util_format_description *format_desc;
10067ec681f3Smrg
10077ec681f3Smrg   assert(target == PIPE_BUFFER ||
10087ec681f3Smrg          target == PIPE_TEXTURE_1D ||
10097ec681f3Smrg          target == PIPE_TEXTURE_1D_ARRAY ||
10107ec681f3Smrg          target == PIPE_TEXTURE_2D ||
10117ec681f3Smrg          target == PIPE_TEXTURE_2D_ARRAY ||
10127ec681f3Smrg          target == PIPE_TEXTURE_RECT ||
10137ec681f3Smrg          target == PIPE_TEXTURE_3D ||
10147ec681f3Smrg          target == PIPE_TEXTURE_CUBE ||
10157ec681f3Smrg          target == PIPE_TEXTURE_CUBE_ARRAY);
10167ec681f3Smrg
10177ec681f3Smrg   format_desc = util_format_description(format);
10187ec681f3Smrg
10197ec681f3Smrg   if (!format_desc)
10207ec681f3Smrg      return false;
10217ec681f3Smrg
10227ec681f3Smrg   if (sample_count > 1)
10237ec681f3Smrg      return false;
10247ec681f3Smrg
10257ec681f3Smrg   if (MAX2(sample_count, 1) != MAX2(storage_sample_count, 1))
10267ec681f3Smrg      return false;
10277ec681f3Smrg
10287ec681f3Smrg   if (usage & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW)) {
10297ec681f3Smrg      struct agx_pixel_format_entry ent = agx_pixel_format[format];
10307ec681f3Smrg
10317ec681f3Smrg      if (!agx_is_valid_pixel_format(format))
10327ec681f3Smrg         return false;
10337ec681f3Smrg
10347ec681f3Smrg      if ((usage & PIPE_BIND_RENDER_TARGET) && !ent.renderable)
10357ec681f3Smrg         return false;
10367ec681f3Smrg   }
10377ec681f3Smrg
10387ec681f3Smrg   /* TODO: formats */
10397ec681f3Smrg   if (usage & PIPE_BIND_VERTEX_BUFFER) {
10407ec681f3Smrg      switch (format) {
10417ec681f3Smrg      case PIPE_FORMAT_R16_FLOAT:
10427ec681f3Smrg      case PIPE_FORMAT_R16G16_FLOAT:
10437ec681f3Smrg      case PIPE_FORMAT_R16G16B16_FLOAT:
10447ec681f3Smrg      case PIPE_FORMAT_R16G16B16A16_FLOAT:
10457ec681f3Smrg      case PIPE_FORMAT_R32_FLOAT:
10467ec681f3Smrg      case PIPE_FORMAT_R32G32_FLOAT:
10477ec681f3Smrg      case PIPE_FORMAT_R32G32B32_FLOAT:
10487ec681f3Smrg      case PIPE_FORMAT_R32G32B32A32_FLOAT:
10497ec681f3Smrg         return true;
10507ec681f3Smrg      default:
10517ec681f3Smrg         return false;
10527ec681f3Smrg      }
10537ec681f3Smrg   }
10547ec681f3Smrg
10557ec681f3Smrg   /* TODO */
10567ec681f3Smrg   return true;
10577ec681f3Smrg}
10587ec681f3Smrg
10597ec681f3Smrgstatic uint64_t
10607ec681f3Smrgagx_get_timestamp(struct pipe_screen *pscreen)
10617ec681f3Smrg{
10627ec681f3Smrg   return 0;
10637ec681f3Smrg}
10647ec681f3Smrg
10657ec681f3Smrgstatic void
10667ec681f3Smrgagx_destroy_screen(struct pipe_screen *screen)
10677ec681f3Smrg{
10687ec681f3Smrg   agx_close_device(agx_device(screen));
10697ec681f3Smrg   ralloc_free(screen);
10707ec681f3Smrg}
10717ec681f3Smrg
10727ec681f3Smrgstatic void
10737ec681f3Smrgagx_fence_reference(struct pipe_screen *screen,
10747ec681f3Smrg                    struct pipe_fence_handle **ptr,
10757ec681f3Smrg                    struct pipe_fence_handle *fence)
10767ec681f3Smrg{
10777ec681f3Smrg}
10787ec681f3Smrg
10797ec681f3Smrgstatic bool
10807ec681f3Smrgagx_fence_finish(struct pipe_screen *screen,
10817ec681f3Smrg                 struct pipe_context *ctx,
10827ec681f3Smrg                 struct pipe_fence_handle *fence,
10837ec681f3Smrg                 uint64_t timeout)
10847ec681f3Smrg{
10857ec681f3Smrg   return true;
10867ec681f3Smrg}
10877ec681f3Smrg
10887ec681f3Smrgstatic const void *
10897ec681f3Smrgagx_get_compiler_options(struct pipe_screen *pscreen,
10907ec681f3Smrg                         enum pipe_shader_ir ir,
10917ec681f3Smrg                         enum pipe_shader_type shader)
10927ec681f3Smrg{
10937ec681f3Smrg   return &agx_nir_options;
10947ec681f3Smrg}
10957ec681f3Smrg
10967ec681f3Smrgstruct pipe_screen *
10977ec681f3Smrgagx_screen_create(struct sw_winsys *winsys)
10987ec681f3Smrg{
10997ec681f3Smrg   struct agx_screen *agx_screen;
11007ec681f3Smrg   struct pipe_screen *screen;
11017ec681f3Smrg
11027ec681f3Smrg   agx_screen = rzalloc(NULL, struct agx_screen);
11037ec681f3Smrg   if (!agx_screen)
11047ec681f3Smrg      return NULL;
11057ec681f3Smrg
11067ec681f3Smrg   screen = &agx_screen->pscreen;
11077ec681f3Smrg   agx_screen->winsys = winsys;
11087ec681f3Smrg
11097ec681f3Smrg   /* Set debug before opening */
11107ec681f3Smrg   agx_screen->dev.debug =
11117ec681f3Smrg      debug_get_flags_option("ASAHI_MESA_DEBUG", agx_debug_options, 0);
11127ec681f3Smrg
11137ec681f3Smrg   /* Try to open an AGX device */
11147ec681f3Smrg   if (!agx_open_device(screen, &agx_screen->dev)) {
11157ec681f3Smrg      ralloc_free(agx_screen);
11167ec681f3Smrg      return NULL;
11177ec681f3Smrg   }
11187ec681f3Smrg
11197ec681f3Smrg   screen->destroy = agx_destroy_screen;
11207ec681f3Smrg   screen->get_name = agx_get_name;
11217ec681f3Smrg   screen->get_vendor = agx_get_vendor;
11227ec681f3Smrg   screen->get_device_vendor = agx_get_device_vendor;
11237ec681f3Smrg   screen->get_param = agx_get_param;
11247ec681f3Smrg   screen->get_shader_param = agx_get_shader_param;
11257ec681f3Smrg   screen->get_compute_param = agx_get_compute_param;
11267ec681f3Smrg   screen->get_paramf = agx_get_paramf;
11277ec681f3Smrg   screen->is_format_supported = agx_is_format_supported;
11287ec681f3Smrg   screen->context_create = agx_create_context;
11297ec681f3Smrg   screen->resource_create = agx_resource_create;
11307ec681f3Smrg   screen->resource_from_handle = agx_resource_from_handle;
11317ec681f3Smrg   screen->resource_get_handle = agx_resource_get_handle;
11327ec681f3Smrg   screen->resource_destroy = agx_resource_destroy;
11337ec681f3Smrg   screen->flush_frontbuffer = agx_flush_frontbuffer;
11347ec681f3Smrg   screen->get_timestamp = agx_get_timestamp;
11357ec681f3Smrg   screen->fence_reference = agx_fence_reference;
11367ec681f3Smrg   screen->fence_finish = agx_fence_finish;
11377ec681f3Smrg   screen->get_compiler_options = agx_get_compiler_options;
11387ec681f3Smrg
11397ec681f3Smrg   agx_internal_shaders(&agx_screen->dev);
11407ec681f3Smrg
11417ec681f3Smrg   return screen;
11427ec681f3Smrg}
1143