1/* 2 * Copyright (C) 2019 Collabora, Ltd. 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 FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 * 23 * Authors: 24 * Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> 25 */ 26 27#include "pan_texture.h" 28 29/* Arm FrameBuffer Compression (AFBC) is a lossless compression scheme natively 30 * implemented in Mali GPUs (as well as many display controllers paired with 31 * Mali GPUs, etc). Where possible, Panfrost prefers to use AFBC for both 32 * rendering and texturing. In most cases, this is a performance-win due to a 33 * dramatic reduction in memory bandwidth and cache locality compared to a 34 * linear resources. 35 * 36 * AFBC divides the framebuffer into 16x16 tiles (other sizes possible, TODO: 37 * do we need to support this?). So, the width and height each must be aligned 38 * up to 16 pixels. This is inherently good for performance; note that for a 4 39 * byte-per-pixel format like RGBA8888, that means that rows are 16*4=64 byte 40 * aligned, which is the cache-line size. 41 * 42 * For each AFBC-compressed resource, there is a single contiguous 43 * (CPU/GPU-shared) buffer. This buffer itself is divided into two parts: 44 * header and body, placed immediately after each other. 45 * 46 * The AFBC header contains 16 bytes of metadata per tile. 47 * 48 * The AFBC body is the same size as the original linear resource (padded to 49 * the nearest tile). Although the body comes immediately after the header, it 50 * must also be cache-line aligned, so there can sometimes be a bit of padding 51 * between the header and body. 52 * 53 * As an example, a 64x64 RGBA framebuffer contains 64/16 = 4 tiles horizontally and 54 * 4 tiles vertically. There are 4*4=16 tiles in total, each containing 16 55 * bytes of metadata, so there is a 16*16=256 byte header. 64x64 is already 56 * tile aligned, so the body is 64*64 * 4 bytes per pixel = 16384 bytes of 57 * body. 58 * 59 * From userspace, Panfrost needs to be able to calculate these sizes. It 60 * explicitly does not and can not know the format of the data contained within 61 * this header and body. The GPU has native support for AFBC encode/decode. For 62 * an internal FBO or a framebuffer used for scanout with an AFBC-compatible 63 * winsys/display-controller, the buffer is maintained AFBC throughout flight, 64 * and the driver never needs to know the internal data. For edge cases where 65 * the driver really does need to read/write from the AFBC resource, we 66 * generate a linear staging buffer and use the GPU to blit AFBC<--->linear. 67 */ 68 69/* AFBC supports compressing a few canonical formats. Additional formats are 70 * available by using a canonical internal format. Given a PIPE format, find 71 * the canonical AFBC internal format if it exists, or NONE if the format 72 * cannot be compressed. */ 73 74enum pipe_format 75panfrost_afbc_format(unsigned arch, enum pipe_format format) 76{ 77 /* Don't allow swizzled formats on v7 */ 78 switch (format) { 79 case PIPE_FORMAT_B8G8R8A8_UNORM: 80 case PIPE_FORMAT_B8G8R8X8_UNORM: 81 case PIPE_FORMAT_A8R8G8B8_UNORM: 82 case PIPE_FORMAT_X8R8G8B8_UNORM: 83 case PIPE_FORMAT_X8B8G8R8_UNORM: 84 case PIPE_FORMAT_A8B8G8R8_UNORM: 85 case PIPE_FORMAT_B8G8R8_UNORM: 86 case PIPE_FORMAT_B5G6R5_UNORM: 87 if (arch >= 7) 88 return PIPE_FORMAT_NONE; 89 90 break; 91 default: 92 break; 93 } 94 95 switch (format) { 96 case PIPE_FORMAT_Z16_UNORM: 97 return PIPE_FORMAT_R8G8_UNORM; 98 99 case PIPE_FORMAT_R8G8B8_UNORM: 100 case PIPE_FORMAT_B8G8R8_UNORM: 101 return PIPE_FORMAT_R8G8B8_UNORM; 102 103 case PIPE_FORMAT_R8G8B8A8_UNORM: 104 case PIPE_FORMAT_R8G8B8X8_UNORM: 105 case PIPE_FORMAT_Z24_UNORM_S8_UINT: 106 case PIPE_FORMAT_Z24X8_UNORM: 107 case PIPE_FORMAT_X24S8_UINT: 108 case PIPE_FORMAT_B8G8R8A8_UNORM: 109 case PIPE_FORMAT_B8G8R8X8_UNORM: 110 case PIPE_FORMAT_A8R8G8B8_UNORM: 111 case PIPE_FORMAT_X8R8G8B8_UNORM: 112 case PIPE_FORMAT_X8B8G8R8_UNORM: 113 case PIPE_FORMAT_A8B8G8R8_UNORM: 114 return PIPE_FORMAT_R8G8B8A8_UNORM; 115 116 case PIPE_FORMAT_R5G6B5_UNORM: 117 case PIPE_FORMAT_B5G6R5_UNORM: 118 return PIPE_FORMAT_R5G6B5_UNORM; 119 120 /* TODO: More AFBC formats */ 121 default: 122 return PIPE_FORMAT_NONE; 123 } 124} 125 126/* A format may be compressed as AFBC if it has an AFBC internal format */ 127 128bool 129panfrost_format_supports_afbc(const struct panfrost_device *dev, enum pipe_format format) 130{ 131 return panfrost_afbc_format(dev->arch, format) != PIPE_FORMAT_NONE; 132} 133 134/* The lossless colour transform (AFBC_FORMAT_MOD_YTR) requires RGB. */ 135 136bool 137panfrost_afbc_can_ytr(enum pipe_format format) 138{ 139 const struct util_format_description *desc = 140 util_format_description(format); 141 142 /* YTR is only defined for RGB(A) */ 143 if (desc->nr_channels != 3 && desc->nr_channels != 4) 144 return false; 145 146 /* The fourth channel if it exists doesn't matter */ 147 return desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB; 148} 149 150/* 151 * Check if the device supports AFBC with tiled headers (and hence also solid 152 * colour blocks). 153 */ 154bool 155panfrost_afbc_can_tile(const struct panfrost_device *dev) 156{ 157 return (dev->arch >= 7); 158} 159