/* * Copyright (C) 2022 Collabora, Ltd. * SPDX-License-Identifier: MIT */ #include "pan_afbc.h" #include "pan_afrc.h" #include "pan_format.h" #include "pan_image.h" #include "pan_layout.h" #include "pan_mod.h" #include TEST(Align, UTiledLinear) { struct { unsigned arch; enum pipe_format format; unsigned plane_idx; unsigned alignment; } cases[] = { { 6, PIPE_FORMAT_ETC2_RGB8, 0, 8 }, { 6, PIPE_FORMAT_R32G32B32_FLOAT, 0, 4 }, { 6, PIPE_FORMAT_R8G8B8A8_UNORM, 0, 1 }, { 6, PIPE_FORMAT_R5G6B5_UNORM, 0, 2 }, { 6, PIPE_FORMAT_R8_G8B8_420_UNORM, 0, 1 }, { 6, PIPE_FORMAT_R8_G8B8_420_UNORM, 1, 2 }, { 7, PIPE_FORMAT_ETC2_RGB8, 0, 64 }, { 7, PIPE_FORMAT_R32G32B32_FLOAT, 0, 64 }, { 7, PIPE_FORMAT_R8G8B8A8_UNORM, 0, 64 }, { 7, PIPE_FORMAT_R5G6B5_UNORM, 0, 64 }, { 7, PIPE_FORMAT_R8_G8B8_420_UNORM, 0, 16 }, { 7, PIPE_FORMAT_R8_G8B8_420_UNORM, 1, 16 }, { 7, PIPE_FORMAT_R10_G10B10_420_UNORM, 0, 1 }, { 7, PIPE_FORMAT_R10_G10B10_420_UNORM, 1, 1 }, }; for (unsigned i = 0; i < ARRAY_SIZE(cases); ++i) { unsigned align = pan_linear_or_tiled_row_align_req( cases[i].arch, cases[i].format, cases[i].plane_idx); EXPECT_EQ(align, cases[i].alignment); } } TEST(BlockSize, UInterleavedRegular) { enum pipe_format format[] = { PIPE_FORMAT_R32G32B32_FLOAT, PIPE_FORMAT_R8G8B8_UNORM, }; for (unsigned i = 0; i < ARRAY_SIZE(format); ++i) { struct pan_image_block_size blk = pan_u_interleaved_tile_size_el(format[i]); EXPECT_EQ(blk.width, 16); EXPECT_EQ(blk.height, 16); } } TEST(BlockSize, UInterleavedBlockCompressed) { enum pipe_format format[] = {PIPE_FORMAT_ETC2_RGB8, PIPE_FORMAT_ASTC_5x5}; for (unsigned i = 0; i < ARRAY_SIZE(format); ++i) { struct pan_image_block_size blk = pan_u_interleaved_tile_size_el(format[i]); EXPECT_EQ(blk.width, 4); EXPECT_EQ(blk.height, 4); } } TEST(BlockSize, AFBCFormatInvariant16x16) { enum pipe_format format[] = {PIPE_FORMAT_R32G32B32_FLOAT, PIPE_FORMAT_R8G8B8_UNORM}; uint64_t modifier = DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | AFBC_FORMAT_MOD_SPARSE | AFBC_FORMAT_MOD_YTR); for (unsigned i = 0; i < ARRAY_SIZE(format); ++i) { struct pan_image_block_size blk = pan_afbc_superblock_size_el(format[i], modifier); EXPECT_EQ(blk.width, 16); EXPECT_EQ(blk.height, 16); } } TEST(BlockSize, AFBCFormatInvariant32x8) { enum pipe_format format[] = {PIPE_FORMAT_R32G32B32_FLOAT, PIPE_FORMAT_R8G8B8_UNORM}; uint64_t modifier = DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 | AFBC_FORMAT_MOD_SPARSE | AFBC_FORMAT_MOD_YTR); for (unsigned i = 0; i < ARRAY_SIZE(format); ++i) { struct pan_image_block_size blk = pan_afbc_superblock_size_el(format[i], modifier); EXPECT_EQ(blk.width, 32); EXPECT_EQ(blk.height, 8); } } TEST(BlockSize, AFBCSuperblock16x16) { uint64_t modifier = DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | AFBC_FORMAT_MOD_SPARSE | AFBC_FORMAT_MOD_YTR); EXPECT_EQ(pan_afbc_superblock_size(modifier).width, 16); EXPECT_EQ(pan_afbc_superblock_width(modifier), 16); EXPECT_EQ(pan_afbc_superblock_size(modifier).height, 16); EXPECT_EQ(pan_afbc_superblock_height(modifier), 16); EXPECT_FALSE(pan_afbc_is_wide(modifier)); } TEST(BlockSize, AFBCSuperblock32x8) { uint64_t modifier = DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 | AFBC_FORMAT_MOD_SPARSE); EXPECT_EQ(pan_afbc_superblock_size(modifier).width, 32); EXPECT_EQ(pan_afbc_superblock_width(modifier), 32); EXPECT_EQ(pan_afbc_superblock_size(modifier).height, 8); EXPECT_EQ(pan_afbc_superblock_height(modifier), 8); EXPECT_TRUE(pan_afbc_is_wide(modifier)); } TEST(BlockSize, AFBCSuperblock64x4) { uint64_t modifier = DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_64x4 | AFBC_FORMAT_MOD_SPARSE); EXPECT_EQ(pan_afbc_superblock_size(modifier).width, 64); EXPECT_EQ(pan_afbc_superblock_width(modifier), 64); EXPECT_EQ(pan_afbc_superblock_size(modifier).height, 4); EXPECT_EQ(pan_afbc_superblock_height(modifier), 4); EXPECT_TRUE(pan_afbc_is_wide(modifier)); } /* Calculate Bifrost line stride, since we have reference formulas for Bifrost * stride calculations. */ static uint32_t pan_afbc_line_stride(enum pipe_format format, uint64_t modifier, uint32_t width) { return pan_afbc_stride_blocks(format, modifier, pan_afbc_row_stride(format, modifier, width)); } /* Which form of the stride we specify is hardware specific (row stride for * Valhall, line stride for Bifrost). However, the layout code is hardware * independent, so we test both row stride and line stride calculations. */ TEST(AFBCStride, Linear) { uint64_t modifiers[] = { DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | AFBC_FORMAT_MOD_SPARSE), DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 | AFBC_FORMAT_MOD_SPARSE), DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_64x4 | AFBC_FORMAT_MOD_SPARSE), }; for (unsigned m = 0; m < ARRAY_SIZE(modifiers); ++m) { uint64_t modifier = modifiers[m]; enum pipe_format format = PIPE_FORMAT_R8G8B8A8_UNORM; uint32_t sw = pan_afbc_superblock_width(modifier); uint32_t cases[] = {1, 4, 17, 39}; for (unsigned i = 0; i < ARRAY_SIZE(cases); ++i) { uint32_t width = sw * cases[i]; EXPECT_EQ(pan_afbc_row_stride(format, modifier, width), 16 * DIV_ROUND_UP(width, sw)); EXPECT_EQ(pan_afbc_line_stride(format, modifier, width), DIV_ROUND_UP(width, sw)); } } } TEST(AFBCStride, Tiled) { uint64_t modifiers[] = { DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | AFBC_FORMAT_MOD_TILED | AFBC_FORMAT_MOD_SPARSE), DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 | AFBC_FORMAT_MOD_TILED | AFBC_FORMAT_MOD_SPARSE), DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_64x4 | AFBC_FORMAT_MOD_TILED | AFBC_FORMAT_MOD_SPARSE), }; for (unsigned m = 0; m < ARRAY_SIZE(modifiers); ++m) { uint64_t modifier = modifiers[m]; enum pipe_format format = PIPE_FORMAT_R8_UNORM; uint32_t sw = pan_afbc_superblock_width(modifier); uint32_t cases[] = {1, 4, 17, 39}; for (unsigned i = 0; i < ARRAY_SIZE(cases); ++i) { uint32_t width = sw * 8 * cases[i]; EXPECT_EQ(pan_afbc_row_stride(format, modifier, width), 16 * DIV_ROUND_UP(width, (sw * 8)) * 8 * 8); EXPECT_EQ(pan_afbc_line_stride(format, modifier, width), DIV_ROUND_UP(width, sw * 8) * 8); } } } static bool layout_init(unsigned arch, const struct pan_image_props *props, unsigned plane_idx, const struct pan_image_layout_constraints *layout_constraints, struct pan_image_layout *layout) { /* Pick the first supported arch if it's zero. */ if (!arch) arch = 4; struct pan_image_plane plane = { }; struct pan_image img = { .props = *props, .mod_handler = pan_mod_get_handler(arch, props->modifier), }; img.planes[plane_idx] = &plane; if (!pan_image_layout_init(arch, &img, plane_idx, layout_constraints)) return false; *layout = plane.layout; return true; } TEST(Layout, LargeImage) { struct pan_image_props p = { .modifier = DRM_FORMAT_MOD_LINEAR, .format = PIPE_FORMAT_R8G8B8A8_UNORM, .extent_px = { .width = 65536, .height = 65536, .depth = 1, }, .nr_samples = 1, .dim = MALI_TEXTURE_DIMENSION_2D, .nr_slices = 1, }; struct pan_image_layout l = {}; ASSERT_TRUE(layout_init(0, &p, 0, NULL, &l)); } /* dEQP-GLES3.functional.texture.format.compressed.etc1_2d_pot */ TEST(Layout, ImplicitLayoutInterleavedETC2) { struct pan_image_props p = { .modifier = DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED, .format = PIPE_FORMAT_ETC2_RGB8, .extent_px = { .width = 128, .height = 128, .depth = 1, }, .nr_samples = 1, .dim = MALI_TEXTURE_DIMENSION_2D, .nr_slices = 8, }; struct pan_image_layout l = {}; unsigned offsets[9] = {0, 8192, 10240, 10752, 10880, 11008, 11136, 11264, 11392}; ASSERT_TRUE(layout_init(0, &p, 0, NULL, &l)); for (unsigned i = 0; i < 8; ++i) { unsigned size = (offsets[i + 1] - offsets[i]); EXPECT_EQ(l.slices[i].offset_B, offsets[i]); if (size == 64) EXPECT_TRUE(l.slices[i].size_B < 64); else EXPECT_EQ(l.slices[i].size_B, size); } } TEST(Layout, ImplicitLayoutInterleavedASTC5x5) { struct pan_image_props p = { .modifier = DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED, .format = PIPE_FORMAT_ASTC_5x5, .extent_px = { .width = 50, .height = 50, .depth = 1, }, .nr_samples = 1, .dim = MALI_TEXTURE_DIMENSION_2D, .nr_slices = 1, }; struct pan_image_layout l = {}; ASSERT_TRUE(layout_init(0, &p, 0, NULL, &l)); /* The image is 50x50 pixels, with 5x5 blocks. So it is a 10x10 grid of ASTC * blocks. 4x4 tiles of ASTC blocks are u-interleaved, so we have to round up * to a 12x12 grid. So we need space for 144 ASTC blocks. Each ASTC block is * 16 bytes (128-bits), so we require 2304 bytes, with a row stride of 12 * * 16 * 4 = 192 bytes. */ EXPECT_EQ(l.slices[0].offset_B, 0); EXPECT_EQ(l.slices[0].tiled_or_linear.row_stride_B, 768); EXPECT_EQ(l.slices[0].tiled_or_linear.surface_stride_B, 2304); EXPECT_EQ(l.slices[0].size_B, 2304); } TEST(Layout, ImplicitLayoutLinearASTC5x5) { struct pan_image_props p = { .modifier = DRM_FORMAT_MOD_LINEAR, .format = PIPE_FORMAT_ASTC_5x5, .extent_px = { .width = 50, .height = 50, .depth = 1, }, .nr_samples = 1, .dim = MALI_TEXTURE_DIMENSION_2D, .nr_slices = 1, }; struct pan_image_layout l = {}; ASSERT_TRUE(layout_init(0, &p, 0, NULL, &l)); /* The image is 50x50 pixels, with 5x5 blocks. So it is a 10x10 grid of ASTC * blocks. Each ASTC block is 16 bytes, so the row stride is 160 bytes, * rounded up to the cache line (192 bytes). There are 10 rows, so we have * 1920 bytes total. */ EXPECT_EQ(l.slices[0].offset_B, 0); EXPECT_EQ(l.slices[0].tiled_or_linear.row_stride_B, 192); EXPECT_EQ(l.slices[0].tiled_or_linear.surface_stride_B, 1920); EXPECT_EQ(l.slices[0].size_B, 1920); } /* dEQP-GLES3.functional.texture.format.unsized.rgba_unsigned_byte_3d_pot */ TEST(AFBCLayout, Linear3D) { uint64_t modifier = DRM_FORMAT_MOD_ARM_AFBC( AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | AFBC_FORMAT_MOD_SPARSE); struct pan_image_props p = { .modifier = modifier, .format = PIPE_FORMAT_R8G8B8A8_UNORM, .extent_px = { .width = 8, .height = 32, .depth = 16, }, .nr_samples = 1, .dim = MALI_TEXTURE_DIMENSION_3D, .nr_slices = 1, }; struct pan_image_layout l = {}; ASSERT_TRUE(layout_init(0, &p, 0, NULL, &l)); /* AFBC Surface size is the size of headers for a single surface. At superblock * size 16x16, the 8x32 layer has 1x2 superblocks, so the header size is 2 * * 16 = 32 bytes. Body offset needs to be aligned on 64 bytes on v6-. * Header/body sections of a 3D image are interleaved, so the surface stride is * is the header size, aligned to meet body offset alignment constraints, plus * the body of a single surface. * * There is only 1 superblock per row, so the row stride is the bytes per 1 * header block = 16. * * There are 16 layers of size 64 so afbc.header_size = 16 * 64 = 1024. * * Each 16x16 superblock consumes 16 * 16 * 4 = 1024 bytes. There are 2 * 1 * * 16 superblocks in the image, so body size is 32768. */ EXPECT_EQ(l.slices[0].offset_B, 0); EXPECT_EQ(l.slices[0].afbc.header.row_stride_B, 16); EXPECT_EQ(l.slices[0].afbc.header.surface_size_B, 32); EXPECT_EQ(l.slices[0].afbc.surface_stride_B, 64 + 2048); EXPECT_EQ(l.slices[0].size_B, (64 + 2048) * 16); } TEST(AFBCLayout, Tiled16x16) { uint64_t modifier = DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | AFBC_FORMAT_MOD_TILED | AFBC_FORMAT_MOD_SPARSE); struct pan_image_props p = { .modifier = modifier, .format = PIPE_FORMAT_R8G8B8A8_UNORM, .extent_px = { .width = 917, .height = 417, .depth = 1, }, .nr_samples = 1, .dim = MALI_TEXTURE_DIMENSION_2D, .nr_slices = 1, }; struct pan_image_layout l = {}; ASSERT_TRUE(layout_init(0, &p, 0, NULL, &l)); /* The image is 917x417. Superblocks are 16x16, so there are 58x27 * superblocks. Superblocks are grouped into 8x8 tiles, so there are 8x4 * tiles of superblocks. So the row stride is 16 * 8 * 8 * 8 = 8192 bytes. * There are 4 tiles vertically, so the header is 8192 * 4 = 32768 bytes. * This is already 4096-byte aligned. * * Each tile of superblock contains 128x128 pixels and each pixel is 4 bytes, * so tiles are 65536 bytes, meaning the payload is 8 * 4 * 65536 = 2097152 * bytes. * * In total, the AFBC surface is 32768 + 2097152 = 2129920 bytes. */ EXPECT_EQ(l.slices[0].offset_B, 0); EXPECT_EQ(l.slices[0].afbc.header.row_stride_B, 8192); EXPECT_EQ(l.slices[0].afbc.header.surface_size_B, 32768); EXPECT_EQ(l.slices[0].afbc.surface_stride_B, 2129920); EXPECT_EQ(l.slices[0].size_B, 2129920); } TEST(AFBCLayout, Linear16x16Minimal) { uint64_t modifier = DRM_FORMAT_MOD_ARM_AFBC( AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | AFBC_FORMAT_MOD_SPARSE); struct pan_image_props p = { .modifier = modifier, .format = PIPE_FORMAT_R8_UNORM, .extent_px = { .width = 1, .height = 1, .depth = 1, }, .nr_samples = 1, .dim = MALI_TEXTURE_DIMENSION_2D, .nr_slices = 1, }; struct pan_image_layout l = {}; ASSERT_TRUE(layout_init(0, &p, 0, NULL, &l)); /* Image is 1x1 to test for correct alignment everywhere. */ EXPECT_EQ(l.slices[0].offset_B, 0); EXPECT_EQ(l.slices[0].afbc.header.row_stride_B, 16); EXPECT_EQ(l.slices[0].afbc.header.surface_size_B, 16); EXPECT_EQ(l.slices[0].afbc.surface_stride_B, 64 + (32 * 8)); EXPECT_EQ(l.slices[0].size_B, 64 + (32 * 8)); } TEST(AFBCLayout, Linear16x16Minimalv6) { uint64_t modifier = DRM_FORMAT_MOD_ARM_AFBC( AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | AFBC_FORMAT_MOD_SPARSE); struct pan_image_props p = { .modifier = modifier, .format = PIPE_FORMAT_R8_UNORM, .extent_px = { .width = 1, .height = 1, .depth = 1, }, .nr_samples = 1, .dim = MALI_TEXTURE_DIMENSION_2D, .nr_slices = 1, }; struct pan_image_layout l = {}; ASSERT_TRUE(layout_init(6, &p, 0, NULL, &l)); /* Image is 1x1 to test for correct alignment everywhere. */ EXPECT_EQ(l.slices[0].offset_B, 0); EXPECT_EQ(l.slices[0].afbc.header.row_stride_B, 16); EXPECT_EQ(l.slices[0].afbc.header.surface_size_B, 16); EXPECT_EQ(l.slices[0].afbc.surface_stride_B, 128 + (32 * 8)); EXPECT_EQ(l.slices[0].size_B, 128 + (32 * 8)); } TEST(AFBCLayout, Tiled16x16Minimal) { uint64_t modifier = DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | AFBC_FORMAT_MOD_TILED | AFBC_FORMAT_MOD_SPARSE); struct pan_image_props p = { .modifier = modifier, .format = PIPE_FORMAT_R8_UNORM, .extent_px = { .width = 1, .height = 1, .depth = 1, }, .nr_samples = 1, .dim = MALI_TEXTURE_DIMENSION_2D, .nr_slices = 1, }; struct pan_image_layout l = {}; ASSERT_TRUE(layout_init(0, &p, 0, NULL, &l)); /* Image is 1x1 to test for correct alignment everywhere. */ EXPECT_EQ(l.slices[0].offset_B, 0); EXPECT_EQ(l.slices[0].afbc.header.row_stride_B, 16 * 8 * 8); EXPECT_EQ(l.slices[0].afbc.header.surface_size_B, 16 * 8 * 8); EXPECT_EQ(l.slices[0].afbc.surface_stride_B, 4096 + (32 * 8 * 8 * 8)); EXPECT_EQ(l.slices[0].size_B, 4096 + (32 * 8 * 8 * 8)); } static unsigned archs[] = {4, 5, 6, 7, 9, 12, 13}; #define IMAGE_WIDTH 4096 #define IMAGE_HEIGHT 512 #define IMAGE_FORMAT \ (PAN_BIND_DEPTH_STENCIL | PAN_BIND_RENDER_TARGET | PAN_BIND_SAMPLER_VIEW | \ PAN_BIND_STORAGE_IMAGE) #define EXPECT_IMPORT_SUCCESS(__arch, __iprops, __plane, __wsi_layout, \ __out_layout, __test_desc) \ do { \ bool __result = \ layout_init(__arch, __iprops, __plane, __wsi_layout, __out_layout); \ EXPECT_TRUE(__result) \ << __test_desc \ << " for format) \ << ",plane=" << __plane << ",mod=" << std::hex \ << (__iprops)->modifier << std::dec << "> rejected (arch=" << __arch \ << ")"; \ \ if (!__result) \ break; \ \ struct pan_image_plane img_plane = { \ .layout = *(__out_layout), \ }; \ struct pan_image img = { \ .props = *(__iprops), \ .mod_handler = pan_mod_get_handler(__arch, (__iprops)->modifier), \ }; \ img.planes[__plane] = &img_plane; \ unsigned __export_row_pitch_B = \ pan_image_get_wsi_row_pitch(&img, __plane, 0); \ unsigned __export_offset_B = pan_image_get_wsi_offset(&img, __plane, 0); \ EXPECT_TRUE(__export_row_pitch_B == (__wsi_layout)->wsi_row_pitch_B && \ __export_offset_B == (__wsi_layout)->offset_B) \ << " mismatch between import and export for (arch=" << __arch << ")"; \ } while (0) #define EXPECT_IMPORT_FAIL(__arch, __iprops, __plane, __wsi_layout, \ __out_layout, __test_desc) \ EXPECT_FALSE( \ layout_init(__arch, __iprops, __plane, __wsi_layout, __out_layout)) \ << __test_desc \ << " for format) \ << ",plane=" << __plane << ",mod=" << std::hex << (__iprops)->modifier \ << std::dec << "> not rejected (arch=" << __arch << ")" static bool format_can_do_mod(unsigned arch, enum pipe_format format, unsigned plane_idx, uint64_t modifier) { if (drm_is_afbc(modifier)) { return pan_afbc_format(arch, format, plane_idx) != PAN_AFBC_MODE_INVALID; } else if (drm_is_afrc(modifier)) { return arch >= 10 && pan_afrc_supports_format(format); } else if (modifier == DRM_FORMAT_MOD_ARM_INTERLEAVED_64K) { return false; } else { assert(modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED || modifier == DRM_FORMAT_MOD_LINEAR); switch (format) { case PIPE_FORMAT_R8G8B8_420_UNORM_PACKED: case PIPE_FORMAT_R10G10B10_420_UNORM_PACKED: /* Those are only supported with AFBC. */ return false; default: return true; } } } static unsigned offset_align_for_mod(unsigned arch, const struct pan_image_props *iprops, unsigned plane_idx) { uint64_t modifier = iprops->modifier; enum pipe_format format = iprops->format; if (drm_is_afbc(modifier)) { return pan_afbc_header_align(arch, modifier); } else if (drm_is_afrc(modifier)) { return pan_afrc_buffer_alignment_from_modifier(modifier); } else { assert(modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED || modifier == DRM_FORMAT_MOD_LINEAR); return pan_linear_or_tiled_row_align_req(arch, format, plane_idx); } } static unsigned row_align_for_mod(unsigned arch, const struct pan_image_props *iprops, unsigned plane_idx) { uint64_t modifier = iprops->modifier; enum pipe_format format = iprops->format; if (drm_is_afbc(modifier)) { unsigned hdr_row_align = pan_afbc_header_row_stride_align(arch, format, modifier); unsigned ntiles = hdr_row_align / AFBC_HEADER_BYTES_PER_TILE; unsigned sb_width_el = pan_afbc_superblock_width(modifier) / util_format_get_blockwidth(format); assert(pan_afbc_superblock_width(modifier) % util_format_get_blockwidth(format) == 0); return ntiles * sb_width_el * pan_format_get_plane_blocksize(format, plane_idx); } else if (drm_is_afrc(modifier)) { unsigned row_align = pan_afrc_buffer_alignment_from_modifier(modifier); struct pan_image_block_size tile_size_px = pan_afrc_tile_size(format, modifier); assert(row_align % tile_size_px.height == 0); return row_align / tile_size_px.height; } else { assert(modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED || modifier == DRM_FORMAT_MOD_LINEAR); unsigned tile_height_el = modifier == DRM_FORMAT_MOD_LINEAR ? 1 : util_format_is_compressed(format) ? 4 : 16; return DIV_ROUND_UP(offset_align_for_mod(arch, iprops, plane_idx), tile_height_el); } } static unsigned default_wsi_row_pitch(unsigned arch, const struct pan_image_props *iprops, unsigned plane_idx) { uint64_t modifier = iprops->modifier; enum pipe_format format = iprops->format; unsigned fmt_blksz_B = pan_format_get_plane_blocksize(format, plane_idx); unsigned width_px = util_format_get_plane_width(format, plane_idx, iprops->extent_px.width); assert(width_px % util_format_get_blockwidth(format) == 0); if (drm_is_afbc(modifier)) { unsigned sb_width_el = pan_afbc_superblock_width(modifier) / util_format_get_blockwidth(format); unsigned sb_height_el = pan_afbc_superblock_height(modifier) / util_format_get_blockheight(format); unsigned ntiles = DIV_ROUND_UP(width_px, pan_afbc_superblock_width(modifier)); unsigned tile_row_size_B = sb_width_el * sb_height_el * fmt_blksz_B * ntiles; assert(pan_afbc_superblock_width(modifier) % util_format_get_blockwidth(format) == 0); assert(pan_afbc_superblock_height(modifier) % util_format_get_blockheight(format) == 0); assert(tile_row_size_B % pan_afbc_superblock_height(modifier) == 0); return tile_row_size_B / pan_afbc_superblock_height(modifier); } else if (drm_is_afrc(modifier)) { struct pan_image_block_size tile_size = pan_afrc_tile_size(format, modifier); unsigned afrc_row_stride_B = pan_afrc_row_stride(format, modifier, width_px); assert(afrc_row_stride_B % tile_size.height == 0); return afrc_row_stride_B / tile_size.height; } else { assert(modifier == DRM_FORMAT_MOD_LINEAR || modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED); unsigned row_pitch_B = (width_px / util_format_get_blockwidth(format)) * fmt_blksz_B; ASSERTED struct pan_image_block_size tile_size_el = {1, 1}; if (modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) { if (util_format_is_compressed(format)) { tile_size_el.width = 4; tile_size_el.height = 4; } else { tile_size_el.width = 16; tile_size_el.height = 16; } } assert(width_px % (util_format_get_blockwidth(format) * tile_size_el.width) == 0); return row_pitch_B; } } TEST(WSI, Import) { /* We don't want to spam stderr with failure messages caused by our * EXPECT_FALSE() cases. */ os_set_option("MESA_LOG", "null", false); struct pan_image_layout layout; for (unsigned i = 0; i < ARRAY_SIZE(archs); i++) { unsigned arch = archs[i]; const struct pan_format *ftable = pan_format_table(arch); PAN_SUPPORTED_MODIFIERS(mods); for (unsigned m = 0; m < ARRAY_SIZE(mods); m++) { for (unsigned fmt = PIPE_FORMAT_NONE + 1; fmt < PIPE_FORMAT_COUNT; fmt++) { if (!(ftable[fmt].bind & IMAGE_FORMAT)) continue; struct pan_image_props iprops = { .modifier = mods[m], .format = (enum pipe_format)fmt, .extent_px = { .width = IMAGE_WIDTH, .height = IMAGE_HEIGHT, .depth = 1, }, .nr_samples = 1, .dim = MALI_TEXTURE_DIMENSION_2D, .nr_slices = 1, .array_size = 1, .crc = false, }; bool supported = true; for (unsigned p = 0; p < util_format_get_num_planes(iprops.format); p++) { if (!format_can_do_mod(arch, iprops.format, p, iprops.modifier)) { supported = false; break; } } if (!supported) continue; if (util_format_is_compressed(iprops.format)) { /* We multiply the image extent by the block extent to make sure * things are always aligned on a block. */ iprops.extent_px.width *= util_format_get_blockwidth(iprops.format); iprops.extent_px.height *= util_format_get_blockheight(iprops.format); } for (unsigned p = 0; p < util_format_get_num_planes(iprops.format); p++) { unsigned row_align_req_B = row_align_for_mod(arch, &iprops, p); unsigned offset_align_req_B = offset_align_for_mod(arch, &iprops, p); unsigned default_row_pitch_B = default_wsi_row_pitch(arch, &iprops, p); assert(default_row_pitch_B > row_align_req_B); if (row_align_req_B > 1) { struct pan_image_layout_constraints wsi_layout = { .wsi_row_pitch_B = default_row_pitch_B + 1, .strict = true, }; EXPECT_IMPORT_FAIL(arch, &iprops, p, &wsi_layout, &layout, "unaligned WSI row pitch"); } if (offset_align_req_B > 1) { struct pan_image_layout_constraints wsi_layout = { .offset_B = 1, .wsi_row_pitch_B = default_row_pitch_B, .strict = true, }; EXPECT_IMPORT_FAIL(arch, &iprops, p, &wsi_layout, &layout, "unaligned WSI offset"); } /* Exact match. */ struct pan_image_layout_constraints wsi_layout = { .wsi_row_pitch_B = default_row_pitch_B, .strict = true, }; EXPECT_IMPORT_SUCCESS(arch, &iprops, p, &wsi_layout, &layout, "tightly packed lines"); wsi_layout.wsi_row_pitch_B = default_row_pitch_B + row_align_req_B; EXPECT_IMPORT_SUCCESS(arch, &iprops, p, &wsi_layout, &layout, "lines with padding"); wsi_layout.wsi_row_pitch_B = default_row_pitch_B - row_align_req_B; EXPECT_IMPORT_FAIL(arch, &iprops, p, &wsi_layout, &layout, "partially aliased lines"); wsi_layout.wsi_row_pitch_B = default_row_pitch_B; wsi_layout.offset_B = offset_align_req_B; EXPECT_IMPORT_SUCCESS(arch, &iprops, p, &wsi_layout, &layout, "properly aligned offset"); } } } } } TEST(AFBCP, PayloadLayout) { /* Test pan_afbc_payload_layout_packed(). The test data is a dump of the * first resource packed when packing is enabled for Weston. */ unsigned arch = 7; enum pipe_format format = PIPE_FORMAT_R8G8B8A8_UNORM; uint64_t modifier = DRM_FORMAT_MOD_ARM_AFBC( AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | AFBC_FORMAT_MOD_SPARSE); uint32_t uncompressed_size = pan_afbc_payload_uncompressed_size( format, modifier); const uint32_t nr_blocks = 241; static const uint8_t headers[] = { 0x00, 0x0f, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xc0, 0x8e, 0x6c, 0xa7, 0xb1, 0x07, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x2c, 0x7b, 0x00, 0x00, 0xc0, 0xb2, 0x5d, 0xb7, 0x69, 0x9e, 0xd7, 0x71, 0x00, 0x17, 0x00, 0x00, 0xc7, 0x78, 0x00, 0x00, 0x00, 0x00, 0x40, 0xbc, 0xcf, 0x07, 0xcb, 0x1e, 0x00, 0x1b, 0x00, 0x00, 0x7e, 0x7c, 0x00, 0x00, 0x00, 0xa0, 0x3d, 0xca, 0x9b, 0x24, 0xc7, 0x97, 0x00, 0x1f, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb3, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcb, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd7, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xeb, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9b, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa3, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb3, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x5e, 0x07, 0x00, 0x00, 0x00, 0xcb, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x92, 0xe2, 0x78, 0x00, 0x00, 0xcf, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x92, 0x26, 0x76, 0x00, 0x00, 0xd3, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x72, 0x63, 0x78, 0x00, 0x00, 0xd7, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x65, 0x79, 0x00, 0x00, 0xdb, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x96, 0xe4, 0x01, 0x00, 0x00, 0xdf, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x96, 0xe4, 0x79, 0x00, 0x00, 0xe3, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x82, 0xe6, 0x78, 0x00, 0x00, 0xe7, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x96, 0x67, 0x79, 0x00, 0x00, 0xeb, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0xef, 0x01, 0x00, 0x07, 0x00, 0x00, 0x2c, 0x07, 0xaa, 0xe3, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x01, 0x00, 0xe3, 0x78, 0x69, 0x18, 0x07, 0x8e, 0xe7, 0x79, 0x00, 0x00, 0x70, 0x9e, 0x00, 0xf7, 0x01, 0x00, 0x87, 0xca, 0x1e, 0x28, 0x7f, 0x2e, 0x47, 0x73, 0x00, 0x00, 0x30, 0x1e, 0x00, 0xfb, 0x01, 0x00, 0xad, 0x3e, 0x92, 0x2e, 0x4f, 0xf1, 0x92, 0x72, 0x00, 0x00, 0x80, 0xde, 0x00, 0xff, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9b, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa3, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb3, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcb, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd7, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xeb, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9b, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa3, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x59, 0x62, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0x03, 0x00, 0xe5, 0x58, 0x9a, 0xa4, 0x58, 0x92, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x03, 0x00, 0x26, 0x76, 0x94, 0xe7, 0x58, 0x92, 0x07, 0x00, 0x00, 0x00, 0x20, 0x8a, 0x00, 0xb3, 0x03, 0x00, 0x22, 0x49, 0x96, 0xa2, 0x24, 0x82, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0x03, 0x00, 0x63, 0x59, 0x7e, 0xe4, 0x41, 0x92, 0xc7, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x03, 0x00, 0x5e, 0x78, 0x90, 0x21, 0x49, 0x96, 0x07, 0x00, 0x00, 0x00, 0x80, 0x1d, 0x00, 0xbf, 0x03, 0x00, 0x64, 0x49, 0x92, 0x65, 0x58, 0x8e, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x03, 0x00, 0xa2, 0x58, 0x9e, 0xa4, 0x08, 0x7e, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x03, 0x00, 0xa0, 0x68, 0x96, 0xa6, 0x39, 0x92, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcb, 0x03, 0x00, 0xc7, 0x38, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Manual addition. All subblocks have a size of 1 and must be converted to uncompressed. */ 0x00, 0x41, 0x10, 0x04, 0x41, 0x10, 0x04, 0x41, 0x10, 0x04, 0x41, 0x10, 0x04, 0x41, 0x10, 0x04, }; static const struct pan_afbc_payload_extent expected_layout[] = { { 240, 0 }, { 416, 240 }, { 320, 656 }, { 528, 976 }, { 16, 1504 }, { 16, 1520 }, { 16, 1536 }, { 16, 1552 }, { 16, 1568 }, { 16, 1584 }, { 16, 1600 }, { 16, 1616 }, { 16, 1632 }, { 16, 1648 }, { 16, 1664 }, { 16, 1680 }, { 16, 1696 }, { 16, 1712 }, { 16, 1728 }, { 16, 1744 }, { 16, 1760 }, { 16, 1776 }, { 16, 1792 }, { 16, 1808 }, { 16, 1824 }, { 16, 1840 }, { 16, 1856 }, { 16, 1872 }, { 16, 1888 }, { 16, 1904 }, { 16, 1920 }, { 16, 1936 }, { 16, 1952 }, { 16, 1968 }, { 16, 1984 }, { 16, 2000 }, { 16, 2016 }, { 16, 2032 }, { 16, 2048 }, { 16, 2064 }, { 16, 2080 }, { 16, 2096 }, { 16, 2112 }, { 16, 2128 }, { 16, 2144 }, { 16, 2160 }, { 16, 2176 }, { 16, 2192 }, { 16, 2208 }, { 16, 2224 }, { 16, 2240 }, { 16, 2256 }, { 16, 2272 }, { 16, 2288 }, { 16, 2304 }, { 16, 2320 }, { 16, 2336 }, { 16, 2352 }, { 16, 2368 }, { 16, 2384 }, { 16, 2400 }, { 16, 2416 }, { 16, 2432 }, { 16, 2448 }, { 16, 2464 }, { 16, 2480 }, { 16, 2496 }, { 16, 2512 }, { 16, 2528 }, { 16, 2544 }, { 16, 2560 }, { 16, 2576 }, { 16, 2592 }, { 16, 2608 }, { 16, 2624 }, { 16, 2640 }, { 16, 2656 }, { 16, 2672 }, { 16, 2688 }, { 16, 2704 }, { 16, 2720 }, { 16, 2736 }, { 16, 2752 }, { 16, 2768 }, { 16, 2784 }, { 16, 2800 }, { 16, 2816 }, { 16, 2832 }, { 16, 2848 }, { 16, 2864 }, { 16, 2880 }, { 16, 2896 }, { 16, 2912 }, { 16, 2928 }, { 16, 2944 }, { 16, 2960 }, { 16, 2976 }, { 16, 2992 }, { 16, 3008 }, { 16, 3024 }, { 16, 3040 }, { 16, 3056 }, { 16, 3072 }, { 16, 3088 }, { 16, 3104 }, { 16, 3120 }, { 16, 3136 }, { 16, 3152 }, { 16, 3168 }, { 16, 3184 }, { 80, 3200 }, { 160, 3280 }, { 160, 3440 }, { 144, 3600 }, { 128, 3744 }, { 128, 3872 }, { 176, 4000 }, { 160, 4176 }, { 176, 4336 }, { 64, 4512 }, { 240, 4576 }, { 416, 4816 }, { 320, 5232 }, { 496, 5552 }, { 16, 6048 }, { 16, 6064 }, { 16, 6080 }, { 16, 6096 }, { 16, 6112 }, { 16, 6128 }, { 16, 6144 }, { 16, 6160 }, { 16, 6176 }, { 16, 6192 }, { 16, 6208 }, { 16, 6224 }, { 16, 6240 }, { 16, 6256 }, { 16, 6272 }, { 16, 6288 }, { 16, 6304 }, { 16, 6320 }, { 16, 6336 }, { 16, 6352 }, { 16, 6368 }, { 16, 6384 }, { 16, 6400 }, { 16, 6416 }, { 16, 6432 }, { 16, 6448 }, { 16, 6464 }, { 16, 6480 }, { 16, 6496 }, { 16, 6512 }, { 16, 6528 }, { 16, 6544 }, { 16, 6560 }, { 16, 6576 }, { 16, 6592 }, { 16, 6608 }, { 16, 6624 }, { 16, 6640 }, { 16, 6656 }, { 16, 6672 }, { 16, 6688 }, { 16, 6704 }, { 16, 6720 }, { 16, 6736 }, { 16, 6752 }, { 16, 6768 }, { 16, 6784 }, { 16, 6800 }, { 16, 6816 }, { 16, 6832 }, { 16, 6848 }, { 16, 6864 }, { 16, 6880 }, { 16, 6896 }, { 16, 6912 }, { 16, 6928 }, { 16, 6944 }, { 16, 6960 }, { 16, 6976 }, { 16, 6992 }, { 16, 7008 }, { 16, 7024 }, { 16, 7040 }, { 16, 7056 }, { 16, 7072 }, { 16, 7088 }, { 16, 7104 }, { 16, 7120 }, { 16, 7136 }, { 16, 7152 }, { 16, 7168 }, { 16, 7184 }, { 16, 7200 }, { 16, 7216 }, { 16, 7232 }, { 16, 7248 }, { 16, 7264 }, { 16, 7280 }, { 16, 7296 }, { 16, 7312 }, { 16, 7328 }, { 16, 7344 }, { 16, 7360 }, { 16, 7376 }, { 16, 7392 }, { 16, 7408 }, { 16, 7424 }, { 16, 7440 }, { 16, 7456 }, { 16, 7472 }, { 16, 7488 }, { 16, 7504 }, { 16, 7520 }, { 16, 7536 }, { 16, 7552 }, { 16, 7568 }, { 16, 7584 }, { 16, 7600 }, { 16, 7616 }, { 16, 7632 }, { 16, 7648 }, { 16, 7664 }, { 16, 7680 }, { 16, 7696 }, { 16, 7712 }, { 16, 7728 }, { 112, 7744 }, { 304, 7856 }, { 336, 8160 }, { 272, 8496 }, { 288, 8768 }, { 288, 9056 }, { 304, 9344 }, { 288, 9648 }, { 304, 9936 }, { 96, 10240 }, /* Manual addition. See headers. */ { 16 * uncompressed_size, 10240 + 96 }, }; const uint32_t expected_body_size = 10240 + 96 + 16 * uncompressed_size; struct pan_afbc_payload_extent layout[nr_blocks] = { { 0, 0 }, }; uint32_t body_size = 0; body_size = pan_afbc_payload_layout_packed( arch, (struct pan_afbc_headerblock *)headers, layout, nr_blocks, format, modifier); ASSERT_EQ(body_size, expected_body_size); for (unsigned i = 0; i < nr_blocks; i++) { ASSERT_EQ(layout[i].size, expected_layout[i].size); ASSERT_EQ(layout[i].offset, expected_layout[i].offset); } }