1d722e3fbSopenharmony_ci/* 2d722e3fbSopenharmony_ci * Copyright (C) 2014-2015 Etnaviv Project 3d722e3fbSopenharmony_ci * 4d722e3fbSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5d722e3fbSopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6d722e3fbSopenharmony_ci * to deal in the Software without restriction, including without limitation 7d722e3fbSopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8d722e3fbSopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9d722e3fbSopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10d722e3fbSopenharmony_ci * 11d722e3fbSopenharmony_ci * The above copyright notice and this permission notice (including the next 12d722e3fbSopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13d722e3fbSopenharmony_ci * Software. 14d722e3fbSopenharmony_ci * 15d722e3fbSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16d722e3fbSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17d722e3fbSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18d722e3fbSopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19d722e3fbSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20d722e3fbSopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21d722e3fbSopenharmony_ci * SOFTWARE. 22d722e3fbSopenharmony_ci * 23d722e3fbSopenharmony_ci * Authors: 24d722e3fbSopenharmony_ci * Christian Gmeiner <christian.gmeiner@gmail.com> 25d722e3fbSopenharmony_ci */ 26d722e3fbSopenharmony_ci 27d722e3fbSopenharmony_ci#include <fcntl.h> 28d722e3fbSopenharmony_ci#include <stdio.h> 29d722e3fbSopenharmony_ci#include <string.h> 30d722e3fbSopenharmony_ci#include <unistd.h> 31d722e3fbSopenharmony_ci 32d722e3fbSopenharmony_ci#include "xf86drm.h" 33d722e3fbSopenharmony_ci#include "etnaviv_drmif.h" 34d722e3fbSopenharmony_ci#include "etnaviv_drm.h" 35d722e3fbSopenharmony_ci 36d722e3fbSopenharmony_ci#include "state.xml.h" 37d722e3fbSopenharmony_ci#include "state_2d.xml.h" 38d722e3fbSopenharmony_ci#include "cmdstream.xml.h" 39d722e3fbSopenharmony_ci 40d722e3fbSopenharmony_ci#include "write_bmp.h" 41d722e3fbSopenharmony_ci 42d722e3fbSopenharmony_cistatic inline void etna_emit_load_state(struct etna_cmd_stream *stream, 43d722e3fbSopenharmony_ci const uint16_t offset, const uint16_t count) 44d722e3fbSopenharmony_ci{ 45d722e3fbSopenharmony_ci uint32_t v; 46d722e3fbSopenharmony_ci 47d722e3fbSopenharmony_ci v = (VIV_FE_LOAD_STATE_HEADER_OP_LOAD_STATE | VIV_FE_LOAD_STATE_HEADER_OFFSET(offset) | 48d722e3fbSopenharmony_ci (VIV_FE_LOAD_STATE_HEADER_COUNT(count) & VIV_FE_LOAD_STATE_HEADER_COUNT__MASK)); 49d722e3fbSopenharmony_ci 50d722e3fbSopenharmony_ci etna_cmd_stream_emit(stream, v); 51d722e3fbSopenharmony_ci} 52d722e3fbSopenharmony_ci 53d722e3fbSopenharmony_cistatic inline void etna_set_state(struct etna_cmd_stream *stream, uint32_t address, uint32_t value) 54d722e3fbSopenharmony_ci{ 55d722e3fbSopenharmony_ci etna_cmd_stream_reserve(stream, 2); 56d722e3fbSopenharmony_ci etna_emit_load_state(stream, address >> 2, 1); 57d722e3fbSopenharmony_ci etna_cmd_stream_emit(stream, value); 58d722e3fbSopenharmony_ci} 59d722e3fbSopenharmony_ci 60d722e3fbSopenharmony_cistatic inline void etna_set_state_from_bo(struct etna_cmd_stream *stream, 61d722e3fbSopenharmony_ci uint32_t address, struct etna_bo *bo) 62d722e3fbSopenharmony_ci{ 63d722e3fbSopenharmony_ci etna_cmd_stream_reserve(stream, 2); 64d722e3fbSopenharmony_ci etna_emit_load_state(stream, address >> 2, 1); 65d722e3fbSopenharmony_ci 66d722e3fbSopenharmony_ci etna_cmd_stream_reloc(stream, &(struct etna_reloc){ 67d722e3fbSopenharmony_ci .bo = bo, 68d722e3fbSopenharmony_ci .flags = ETNA_RELOC_READ, 69d722e3fbSopenharmony_ci .offset = 0, 70d722e3fbSopenharmony_ci }); 71d722e3fbSopenharmony_ci} 72d722e3fbSopenharmony_ci 73d722e3fbSopenharmony_cistatic void gen_cmd_stream(struct etna_cmd_stream *stream, struct etna_bo *bmp, const int width, const int height) 74d722e3fbSopenharmony_ci{ 75d722e3fbSopenharmony_ci int rec; 76d722e3fbSopenharmony_ci static int num_rects = 256; 77d722e3fbSopenharmony_ci 78d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_SRC_STRIDE, 0); 79d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_SRC_ROTATION_CONFIG, 0); 80d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_SRC_CONFIG, 0); 81d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_SRC_ORIGIN, 0); 82d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_SRC_SIZE, 0); 83d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_SRC_COLOR_BG, 0); 84d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_SRC_COLOR_FG, 0); 85d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_STRETCH_FACTOR_LOW, 0); 86d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_STRETCH_FACTOR_HIGH, 0); 87d722e3fbSopenharmony_ci etna_set_state_from_bo(stream, VIVS_DE_DEST_ADDRESS, bmp); 88d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_DEST_STRIDE, width*4); 89d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_DEST_ROTATION_CONFIG, 0); 90d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_DEST_CONFIG, 91d722e3fbSopenharmony_ci VIVS_DE_DEST_CONFIG_FORMAT(DE_FORMAT_A8R8G8B8) | 92d722e3fbSopenharmony_ci VIVS_DE_DEST_CONFIG_COMMAND_CLEAR | 93d722e3fbSopenharmony_ci VIVS_DE_DEST_CONFIG_SWIZZLE(DE_SWIZZLE_ARGB) | 94d722e3fbSopenharmony_ci VIVS_DE_DEST_CONFIG_TILED_DISABLE | 95d722e3fbSopenharmony_ci VIVS_DE_DEST_CONFIG_MINOR_TILED_DISABLE 96d722e3fbSopenharmony_ci ); 97d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_ROP, 98d722e3fbSopenharmony_ci VIVS_DE_ROP_ROP_FG(0xcc) | VIVS_DE_ROP_ROP_BG(0xcc) | VIVS_DE_ROP_TYPE_ROP4); 99d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_CLIP_TOP_LEFT, 100d722e3fbSopenharmony_ci VIVS_DE_CLIP_TOP_LEFT_X(0) | 101d722e3fbSopenharmony_ci VIVS_DE_CLIP_TOP_LEFT_Y(0) 102d722e3fbSopenharmony_ci ); 103d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_CLIP_BOTTOM_RIGHT, 104d722e3fbSopenharmony_ci VIVS_DE_CLIP_BOTTOM_RIGHT_X(width) | 105d722e3fbSopenharmony_ci VIVS_DE_CLIP_BOTTOM_RIGHT_Y(height) 106d722e3fbSopenharmony_ci ); 107d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_CONFIG, 0); /* TODO */ 108d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_SRC_ORIGIN_FRACTION, 0); 109d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_ALPHA_CONTROL, 0); 110d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_ALPHA_MODES, 0); 111d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_DEST_ROTATION_HEIGHT, 0); 112d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_SRC_ROTATION_HEIGHT, 0); 113d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_ROT_ANGLE, 0); 114d722e3fbSopenharmony_ci 115d722e3fbSopenharmony_ci /* Clear color PE20 */ 116d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_CLEAR_PIXEL_VALUE32, 0xff40ff40); 117d722e3fbSopenharmony_ci /* Clear color PE10 */ 118d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_CLEAR_BYTE_MASK, 0xff); 119d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_CLEAR_PIXEL_VALUE_LOW, 0xff40ff40); 120d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_CLEAR_PIXEL_VALUE_HIGH, 0xff40ff40); 121d722e3fbSopenharmony_ci 122d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_DEST_COLOR_KEY, 0); 123d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_GLOBAL_SRC_COLOR, 0); 124d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_GLOBAL_DEST_COLOR, 0); 125d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_COLOR_MULTIPLY_MODES, 0); 126d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_PE_TRANSPARENCY, 0); 127d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_PE_CONTROL, 0); 128d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_PE_DITHER_LOW, 0xffffffff); 129d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_DE_PE_DITHER_HIGH, 0xffffffff); 130d722e3fbSopenharmony_ci 131d722e3fbSopenharmony_ci /* Queue DE command */ 132d722e3fbSopenharmony_ci etna_cmd_stream_emit(stream, 133d722e3fbSopenharmony_ci VIV_FE_DRAW_2D_HEADER_OP_DRAW_2D | VIV_FE_DRAW_2D_HEADER_COUNT(num_rects) /* render one rectangle */ 134d722e3fbSopenharmony_ci ); 135d722e3fbSopenharmony_ci etna_cmd_stream_emit(stream, 0x0); /* rectangles start aligned */ 136d722e3fbSopenharmony_ci 137d722e3fbSopenharmony_ci for(rec=0; rec < num_rects; ++rec) { 138d722e3fbSopenharmony_ci int x = rec%16; 139d722e3fbSopenharmony_ci int y = rec/16; 140d722e3fbSopenharmony_ci etna_cmd_stream_emit(stream, VIV_FE_DRAW_2D_TOP_LEFT_X(x*8) | VIV_FE_DRAW_2D_TOP_LEFT_Y(y*8)); 141d722e3fbSopenharmony_ci etna_cmd_stream_emit(stream, VIV_FE_DRAW_2D_BOTTOM_RIGHT_X(x*8+4) | VIV_FE_DRAW_2D_BOTTOM_RIGHT_Y(y*8+4)); 142d722e3fbSopenharmony_ci } 143d722e3fbSopenharmony_ci etna_set_state(stream, 1, 0); 144d722e3fbSopenharmony_ci etna_set_state(stream, 1, 0); 145d722e3fbSopenharmony_ci etna_set_state(stream, 1, 0); 146d722e3fbSopenharmony_ci 147d722e3fbSopenharmony_ci etna_set_state(stream, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_PE2D); 148d722e3fbSopenharmony_ci} 149d722e3fbSopenharmony_ci 150d722e3fbSopenharmony_ciint etna_check_image(uint32_t *p, int width, int height) 151d722e3fbSopenharmony_ci{ 152d722e3fbSopenharmony_ci int i; 153d722e3fbSopenharmony_ci uint32_t expected; 154d722e3fbSopenharmony_ci 155d722e3fbSopenharmony_ci for (i = 0; i < width * height; i++) { 156d722e3fbSopenharmony_ci if (i%8 < 4 && i%(width*8) < width*4 && i%width < 8*16 && i < width*8*16) 157d722e3fbSopenharmony_ci expected = 0xff40ff40; 158d722e3fbSopenharmony_ci else 159d722e3fbSopenharmony_ci expected = 0x00000000; 160d722e3fbSopenharmony_ci 161d722e3fbSopenharmony_ci if (p[i] != expected) { 162d722e3fbSopenharmony_ci fprintf(stderr, "Offset %d: expected: 0x%08x, got: 0x%08x\n", 163d722e3fbSopenharmony_ci i, expected, p[i]); 164d722e3fbSopenharmony_ci return -1; 165d722e3fbSopenharmony_ci } 166d722e3fbSopenharmony_ci } 167d722e3fbSopenharmony_ci 168d722e3fbSopenharmony_ci return 0; 169d722e3fbSopenharmony_ci} 170d722e3fbSopenharmony_ci 171d722e3fbSopenharmony_ciint main(int argc, char *argv[]) 172d722e3fbSopenharmony_ci{ 173d722e3fbSopenharmony_ci const int width = 256; 174d722e3fbSopenharmony_ci const int height = 256; 175d722e3fbSopenharmony_ci const size_t bmp_size = width * height * 4; 176d722e3fbSopenharmony_ci 177d722e3fbSopenharmony_ci struct etna_device *dev; 178d722e3fbSopenharmony_ci struct etna_gpu *gpu; 179d722e3fbSopenharmony_ci struct etna_pipe *pipe; 180d722e3fbSopenharmony_ci struct etna_bo *bmp; 181d722e3fbSopenharmony_ci struct etna_cmd_stream *stream; 182d722e3fbSopenharmony_ci 183d722e3fbSopenharmony_ci drmVersionPtr version; 184d722e3fbSopenharmony_ci int fd, ret = 0; 185d722e3fbSopenharmony_ci uint64_t feat; 186d722e3fbSopenharmony_ci int core = 0; 187d722e3fbSopenharmony_ci 188d722e3fbSopenharmony_ci if (argc < 2) { 189d722e3fbSopenharmony_ci fprintf(stderr, "Usage: %s /dev/dri/<device> [<etna.bmp>]\n", argv[0]); 190d722e3fbSopenharmony_ci return 1; 191d722e3fbSopenharmony_ci } 192d722e3fbSopenharmony_ci 193d722e3fbSopenharmony_ci fd = open(argv[1], O_RDWR); 194d722e3fbSopenharmony_ci if (fd < 0) { 195d722e3fbSopenharmony_ci perror(argv[1]); 196d722e3fbSopenharmony_ci return 1; 197d722e3fbSopenharmony_ci } 198d722e3fbSopenharmony_ci 199d722e3fbSopenharmony_ci version = drmGetVersion(fd); 200d722e3fbSopenharmony_ci if (version) { 201d722e3fbSopenharmony_ci printf("Version: %d.%d.%d\n", version->version_major, 202d722e3fbSopenharmony_ci version->version_minor, version->version_patchlevel); 203d722e3fbSopenharmony_ci printf(" Name: %s\n", version->name); 204d722e3fbSopenharmony_ci printf(" Date: %s\n", version->date); 205d722e3fbSopenharmony_ci printf(" Description: %s\n", version->desc); 206d722e3fbSopenharmony_ci drmFreeVersion(version); 207d722e3fbSopenharmony_ci } 208d722e3fbSopenharmony_ci 209d722e3fbSopenharmony_ci dev = etna_device_new(fd); 210d722e3fbSopenharmony_ci if (!dev) { 211d722e3fbSopenharmony_ci perror("etna_device_new"); 212d722e3fbSopenharmony_ci ret = 2; 213d722e3fbSopenharmony_ci goto out; 214d722e3fbSopenharmony_ci } 215d722e3fbSopenharmony_ci 216d722e3fbSopenharmony_ci do { 217d722e3fbSopenharmony_ci gpu = etna_gpu_new(dev, core); 218d722e3fbSopenharmony_ci if (!gpu) { 219d722e3fbSopenharmony_ci perror("etna_gpu_new"); 220d722e3fbSopenharmony_ci ret = 3; 221d722e3fbSopenharmony_ci goto out_device; 222d722e3fbSopenharmony_ci } 223d722e3fbSopenharmony_ci 224d722e3fbSopenharmony_ci if (etna_gpu_get_param(gpu, ETNA_GPU_FEATURES_0, &feat)) { 225d722e3fbSopenharmony_ci perror("etna_gpu_get_param"); 226d722e3fbSopenharmony_ci ret = 4; 227d722e3fbSopenharmony_ci goto out_device; 228d722e3fbSopenharmony_ci } 229d722e3fbSopenharmony_ci 230d722e3fbSopenharmony_ci if ((feat & (1 << 9)) == 0) { 231d722e3fbSopenharmony_ci /* GPU not 2D capable. */ 232d722e3fbSopenharmony_ci etna_gpu_del(gpu); 233d722e3fbSopenharmony_ci gpu = NULL; 234d722e3fbSopenharmony_ci } 235d722e3fbSopenharmony_ci 236d722e3fbSopenharmony_ci core++; 237d722e3fbSopenharmony_ci } while (!gpu); 238d722e3fbSopenharmony_ci 239d722e3fbSopenharmony_ci pipe = etna_pipe_new(gpu, ETNA_PIPE_2D); 240d722e3fbSopenharmony_ci if (!pipe) { 241d722e3fbSopenharmony_ci perror("etna_pipe_new"); 242d722e3fbSopenharmony_ci ret = 4; 243d722e3fbSopenharmony_ci goto out_gpu; 244d722e3fbSopenharmony_ci } 245d722e3fbSopenharmony_ci 246d722e3fbSopenharmony_ci bmp = etna_bo_new(dev, bmp_size, ETNA_BO_UNCACHED); 247d722e3fbSopenharmony_ci if (!bmp) { 248d722e3fbSopenharmony_ci perror("etna_bo_new"); 249d722e3fbSopenharmony_ci ret = 5; 250d722e3fbSopenharmony_ci goto out_pipe; 251d722e3fbSopenharmony_ci } 252d722e3fbSopenharmony_ci memset(etna_bo_map(bmp), 0, bmp_size); 253d722e3fbSopenharmony_ci 254d722e3fbSopenharmony_ci stream = etna_cmd_stream_new(pipe, 0x300, NULL, NULL); 255d722e3fbSopenharmony_ci if (!stream) { 256d722e3fbSopenharmony_ci perror("etna_cmd_stream_new"); 257d722e3fbSopenharmony_ci ret = 6; 258d722e3fbSopenharmony_ci goto out_bo; 259d722e3fbSopenharmony_ci } 260d722e3fbSopenharmony_ci 261d722e3fbSopenharmony_ci /* generate command sequence */ 262d722e3fbSopenharmony_ci gen_cmd_stream(stream, bmp, width, height); 263d722e3fbSopenharmony_ci 264d722e3fbSopenharmony_ci etna_cmd_stream_finish(stream); 265d722e3fbSopenharmony_ci 266d722e3fbSopenharmony_ci if (argc > 2) 267d722e3fbSopenharmony_ci bmp_dump32(etna_bo_map(bmp), width, height, false, argv[2]); 268d722e3fbSopenharmony_ci 269d722e3fbSopenharmony_ci if (etna_check_image(etna_bo_map(bmp), width, height)) 270d722e3fbSopenharmony_ci ret = 7; 271d722e3fbSopenharmony_ci 272d722e3fbSopenharmony_ci etna_cmd_stream_del(stream); 273d722e3fbSopenharmony_ci 274d722e3fbSopenharmony_ciout_bo: 275d722e3fbSopenharmony_ci etna_bo_del(bmp); 276d722e3fbSopenharmony_ci 277d722e3fbSopenharmony_ciout_pipe: 278d722e3fbSopenharmony_ci etna_pipe_del(pipe); 279d722e3fbSopenharmony_ci 280d722e3fbSopenharmony_ciout_gpu: 281d722e3fbSopenharmony_ci etna_gpu_del(gpu); 282d722e3fbSopenharmony_ci 283d722e3fbSopenharmony_ciout_device: 284d722e3fbSopenharmony_ci etna_device_del(dev); 285d722e3fbSopenharmony_ci 286d722e3fbSopenharmony_ciout: 287d722e3fbSopenharmony_ci close(fd); 288d722e3fbSopenharmony_ci 289d722e3fbSopenharmony_ci return ret; 290d722e3fbSopenharmony_ci} 291