1037b3c26Smrg/* 2037b3c26Smrg * Copyright (C) 2014-2015 Etnaviv Project 3037b3c26Smrg * 4037b3c26Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5037b3c26Smrg * copy of this software and associated documentation files (the "Software"), 6037b3c26Smrg * to deal in the Software without restriction, including without limitation 7037b3c26Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8037b3c26Smrg * and/or sell copies of the Software, and to permit persons to whom the 9037b3c26Smrg * Software is furnished to do so, subject to the following conditions: 10037b3c26Smrg * 11037b3c26Smrg * The above copyright notice and this permission notice (including the next 12037b3c26Smrg * paragraph) shall be included in all copies or substantial portions of the 13037b3c26Smrg * Software. 14037b3c26Smrg * 15037b3c26Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16037b3c26Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17037b3c26Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18037b3c26Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19037b3c26Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20037b3c26Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21037b3c26Smrg * SOFTWARE. 22037b3c26Smrg * 23037b3c26Smrg * Authors: 24037b3c26Smrg * Christian Gmeiner <christian.gmeiner@gmail.com> 25037b3c26Smrg */ 26037b3c26Smrg 27037b3c26Smrg#include <fcntl.h> 28037b3c26Smrg#include <stdio.h> 29037b3c26Smrg#include <string.h> 30037b3c26Smrg#include <unistd.h> 31037b3c26Smrg 32037b3c26Smrg#include "xf86drm.h" 33037b3c26Smrg#include "etnaviv_drmif.h" 34037b3c26Smrg#include "etnaviv_drm.h" 35037b3c26Smrg 36037b3c26Smrg#include "state.xml.h" 37037b3c26Smrg#include "state_2d.xml.h" 38037b3c26Smrg#include "cmdstream.xml.h" 39037b3c26Smrg 40037b3c26Smrg#include "write_bmp.h" 41037b3c26Smrg 42037b3c26Smrgstatic inline void etna_emit_load_state(struct etna_cmd_stream *stream, 43037b3c26Smrg const uint16_t offset, const uint16_t count) 44037b3c26Smrg{ 45037b3c26Smrg uint32_t v; 46037b3c26Smrg 47037b3c26Smrg v = (VIV_FE_LOAD_STATE_HEADER_OP_LOAD_STATE | VIV_FE_LOAD_STATE_HEADER_OFFSET(offset) | 48037b3c26Smrg (VIV_FE_LOAD_STATE_HEADER_COUNT(count) & VIV_FE_LOAD_STATE_HEADER_COUNT__MASK)); 49037b3c26Smrg 50037b3c26Smrg etna_cmd_stream_emit(stream, v); 51037b3c26Smrg} 52037b3c26Smrg 53037b3c26Smrgstatic inline void etna_set_state(struct etna_cmd_stream *stream, uint32_t address, uint32_t value) 54037b3c26Smrg{ 55037b3c26Smrg etna_cmd_stream_reserve(stream, 2); 56037b3c26Smrg etna_emit_load_state(stream, address >> 2, 1); 57037b3c26Smrg etna_cmd_stream_emit(stream, value); 58037b3c26Smrg} 59037b3c26Smrg 60037b3c26Smrgstatic inline void etna_set_state_from_bo(struct etna_cmd_stream *stream, 61037b3c26Smrg uint32_t address, struct etna_bo *bo) 62037b3c26Smrg{ 63037b3c26Smrg etna_cmd_stream_reserve(stream, 2); 64037b3c26Smrg etna_emit_load_state(stream, address >> 2, 1); 65037b3c26Smrg 66037b3c26Smrg etna_cmd_stream_reloc(stream, &(struct etna_reloc){ 67037b3c26Smrg .bo = bo, 68037b3c26Smrg .flags = ETNA_RELOC_READ, 69037b3c26Smrg .offset = 0, 70037b3c26Smrg }); 71037b3c26Smrg} 72037b3c26Smrg 73037b3c26Smrgstatic void gen_cmd_stream(struct etna_cmd_stream *stream, struct etna_bo *bmp, const int width, const int height) 74037b3c26Smrg{ 75037b3c26Smrg int rec; 76037b3c26Smrg static int num_rects = 256; 77037b3c26Smrg 78037b3c26Smrg etna_set_state(stream, VIVS_DE_SRC_STRIDE, 0); 79037b3c26Smrg etna_set_state(stream, VIVS_DE_SRC_ROTATION_CONFIG, 0); 80037b3c26Smrg etna_set_state(stream, VIVS_DE_SRC_CONFIG, 0); 81037b3c26Smrg etna_set_state(stream, VIVS_DE_SRC_ORIGIN, 0); 82037b3c26Smrg etna_set_state(stream, VIVS_DE_SRC_SIZE, 0); 83037b3c26Smrg etna_set_state(stream, VIVS_DE_SRC_COLOR_BG, 0); 84037b3c26Smrg etna_set_state(stream, VIVS_DE_SRC_COLOR_FG, 0); 85037b3c26Smrg etna_set_state(stream, VIVS_DE_STRETCH_FACTOR_LOW, 0); 86037b3c26Smrg etna_set_state(stream, VIVS_DE_STRETCH_FACTOR_HIGH, 0); 87037b3c26Smrg etna_set_state_from_bo(stream, VIVS_DE_DEST_ADDRESS, bmp); 88037b3c26Smrg etna_set_state(stream, VIVS_DE_DEST_STRIDE, width*4); 89037b3c26Smrg etna_set_state(stream, VIVS_DE_DEST_ROTATION_CONFIG, 0); 90037b3c26Smrg etna_set_state(stream, VIVS_DE_DEST_CONFIG, 91037b3c26Smrg VIVS_DE_DEST_CONFIG_FORMAT(DE_FORMAT_A8R8G8B8) | 92037b3c26Smrg VIVS_DE_DEST_CONFIG_COMMAND_CLEAR | 93037b3c26Smrg VIVS_DE_DEST_CONFIG_SWIZZLE(DE_SWIZZLE_ARGB) | 94037b3c26Smrg VIVS_DE_DEST_CONFIG_TILED_DISABLE | 95037b3c26Smrg VIVS_DE_DEST_CONFIG_MINOR_TILED_DISABLE 96037b3c26Smrg ); 97037b3c26Smrg etna_set_state(stream, VIVS_DE_ROP, 98037b3c26Smrg VIVS_DE_ROP_ROP_FG(0xcc) | VIVS_DE_ROP_ROP_BG(0xcc) | VIVS_DE_ROP_TYPE_ROP4); 99037b3c26Smrg etna_set_state(stream, VIVS_DE_CLIP_TOP_LEFT, 100037b3c26Smrg VIVS_DE_CLIP_TOP_LEFT_X(0) | 101037b3c26Smrg VIVS_DE_CLIP_TOP_LEFT_Y(0) 102037b3c26Smrg ); 103037b3c26Smrg etna_set_state(stream, VIVS_DE_CLIP_BOTTOM_RIGHT, 104037b3c26Smrg VIVS_DE_CLIP_BOTTOM_RIGHT_X(width) | 105037b3c26Smrg VIVS_DE_CLIP_BOTTOM_RIGHT_Y(height) 106037b3c26Smrg ); 107037b3c26Smrg etna_set_state(stream, VIVS_DE_CONFIG, 0); /* TODO */ 108037b3c26Smrg etna_set_state(stream, VIVS_DE_SRC_ORIGIN_FRACTION, 0); 109037b3c26Smrg etna_set_state(stream, VIVS_DE_ALPHA_CONTROL, 0); 110037b3c26Smrg etna_set_state(stream, VIVS_DE_ALPHA_MODES, 0); 111037b3c26Smrg etna_set_state(stream, VIVS_DE_DEST_ROTATION_HEIGHT, 0); 112037b3c26Smrg etna_set_state(stream, VIVS_DE_SRC_ROTATION_HEIGHT, 0); 113037b3c26Smrg etna_set_state(stream, VIVS_DE_ROT_ANGLE, 0); 114037b3c26Smrg 115037b3c26Smrg /* Clear color PE20 */ 116037b3c26Smrg etna_set_state(stream, VIVS_DE_CLEAR_PIXEL_VALUE32, 0xff40ff40); 117037b3c26Smrg /* Clear color PE10 */ 118037b3c26Smrg etna_set_state(stream, VIVS_DE_CLEAR_BYTE_MASK, 0xff); 119037b3c26Smrg etna_set_state(stream, VIVS_DE_CLEAR_PIXEL_VALUE_LOW, 0xff40ff40); 120037b3c26Smrg etna_set_state(stream, VIVS_DE_CLEAR_PIXEL_VALUE_HIGH, 0xff40ff40); 121037b3c26Smrg 122037b3c26Smrg etna_set_state(stream, VIVS_DE_DEST_COLOR_KEY, 0); 123037b3c26Smrg etna_set_state(stream, VIVS_DE_GLOBAL_SRC_COLOR, 0); 124037b3c26Smrg etna_set_state(stream, VIVS_DE_GLOBAL_DEST_COLOR, 0); 125037b3c26Smrg etna_set_state(stream, VIVS_DE_COLOR_MULTIPLY_MODES, 0); 126037b3c26Smrg etna_set_state(stream, VIVS_DE_PE_TRANSPARENCY, 0); 127037b3c26Smrg etna_set_state(stream, VIVS_DE_PE_CONTROL, 0); 128037b3c26Smrg etna_set_state(stream, VIVS_DE_PE_DITHER_LOW, 0xffffffff); 129037b3c26Smrg etna_set_state(stream, VIVS_DE_PE_DITHER_HIGH, 0xffffffff); 130037b3c26Smrg 131037b3c26Smrg /* Queue DE command */ 132037b3c26Smrg etna_cmd_stream_emit(stream, 133037b3c26Smrg VIV_FE_DRAW_2D_HEADER_OP_DRAW_2D | VIV_FE_DRAW_2D_HEADER_COUNT(num_rects) /* render one rectangle */ 134037b3c26Smrg ); 135037b3c26Smrg etna_cmd_stream_emit(stream, 0x0); /* rectangles start aligned */ 136037b3c26Smrg 137037b3c26Smrg for(rec=0; rec < num_rects; ++rec) { 138037b3c26Smrg int x = rec%16; 139037b3c26Smrg int y = rec/16; 140037b3c26Smrg etna_cmd_stream_emit(stream, VIV_FE_DRAW_2D_TOP_LEFT_X(x*8) | VIV_FE_DRAW_2D_TOP_LEFT_Y(y*8)); 141037b3c26Smrg 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)); 142037b3c26Smrg } 143037b3c26Smrg etna_set_state(stream, 1, 0); 144037b3c26Smrg etna_set_state(stream, 1, 0); 145037b3c26Smrg etna_set_state(stream, 1, 0); 146037b3c26Smrg 147037b3c26Smrg etna_set_state(stream, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_PE2D); 148037b3c26Smrg} 149037b3c26Smrg 15041687f09Smrgint etna_check_image(uint32_t *p, int width, int height) 15141687f09Smrg{ 15241687f09Smrg int i; 15341687f09Smrg uint32_t expected; 15441687f09Smrg 15541687f09Smrg for (i = 0; i < width * height; i++) { 15641687f09Smrg if (i%8 < 4 && i%(width*8) < width*4 && i%width < 8*16 && i < width*8*16) 15741687f09Smrg expected = 0xff40ff40; 15841687f09Smrg else 15941687f09Smrg expected = 0x00000000; 16041687f09Smrg 16141687f09Smrg if (p[i] != expected) { 16241687f09Smrg fprintf(stderr, "Offset %d: expected: 0x%08x, got: 0x%08x\n", 16341687f09Smrg i, expected, p[i]); 16441687f09Smrg return -1; 16541687f09Smrg } 16641687f09Smrg } 16741687f09Smrg 16841687f09Smrg return 0; 16941687f09Smrg} 17041687f09Smrg 171037b3c26Smrgint main(int argc, char *argv[]) 172037b3c26Smrg{ 173037b3c26Smrg const int width = 256; 174037b3c26Smrg const int height = 256; 175037b3c26Smrg const size_t bmp_size = width * height * 4; 176037b3c26Smrg 177037b3c26Smrg struct etna_device *dev; 178037b3c26Smrg struct etna_gpu *gpu; 179037b3c26Smrg struct etna_pipe *pipe; 180037b3c26Smrg struct etna_bo *bmp; 181037b3c26Smrg struct etna_cmd_stream *stream; 182037b3c26Smrg 183037b3c26Smrg drmVersionPtr version; 184037b3c26Smrg int fd, ret = 0; 18541687f09Smrg uint64_t feat; 18641687f09Smrg int core = 0; 18741687f09Smrg 18841687f09Smrg if (argc < 2) { 18941687f09Smrg fprintf(stderr, "Usage: %s /dev/dri/<device> [<etna.bmp>]\n", argv[0]); 19041687f09Smrg return 1; 19141687f09Smrg } 192037b3c26Smrg 193037b3c26Smrg fd = open(argv[1], O_RDWR); 19441687f09Smrg if (fd < 0) { 19541687f09Smrg perror(argv[1]); 196037b3c26Smrg return 1; 19741687f09Smrg } 198037b3c26Smrg 199037b3c26Smrg version = drmGetVersion(fd); 200037b3c26Smrg if (version) { 201037b3c26Smrg printf("Version: %d.%d.%d\n", version->version_major, 202037b3c26Smrg version->version_minor, version->version_patchlevel); 203037b3c26Smrg printf(" Name: %s\n", version->name); 204037b3c26Smrg printf(" Date: %s\n", version->date); 205037b3c26Smrg printf(" Description: %s\n", version->desc); 206037b3c26Smrg drmFreeVersion(version); 207037b3c26Smrg } 208037b3c26Smrg 209037b3c26Smrg dev = etna_device_new(fd); 210037b3c26Smrg if (!dev) { 21141687f09Smrg perror("etna_device_new"); 212037b3c26Smrg ret = 2; 213037b3c26Smrg goto out; 214037b3c26Smrg } 215037b3c26Smrg 21641687f09Smrg do { 21741687f09Smrg gpu = etna_gpu_new(dev, core); 21841687f09Smrg if (!gpu) { 21941687f09Smrg perror("etna_gpu_new"); 22041687f09Smrg ret = 3; 22141687f09Smrg goto out_device; 22241687f09Smrg } 22341687f09Smrg 22441687f09Smrg if (etna_gpu_get_param(gpu, ETNA_GPU_FEATURES_0, &feat)) { 22541687f09Smrg perror("etna_gpu_get_param"); 22641687f09Smrg ret = 4; 22741687f09Smrg goto out_device; 22841687f09Smrg } 22941687f09Smrg 23041687f09Smrg if ((feat & (1 << 9)) == 0) { 23141687f09Smrg /* GPU not 2D capable. */ 23241687f09Smrg etna_gpu_del(gpu); 23341687f09Smrg gpu = NULL; 23441687f09Smrg } 23541687f09Smrg 23641687f09Smrg core++; 23741687f09Smrg } while (!gpu); 238037b3c26Smrg 239037b3c26Smrg pipe = etna_pipe_new(gpu, ETNA_PIPE_2D); 240037b3c26Smrg if (!pipe) { 24141687f09Smrg perror("etna_pipe_new"); 242037b3c26Smrg ret = 4; 243037b3c26Smrg goto out_gpu; 244037b3c26Smrg } 245037b3c26Smrg 246037b3c26Smrg bmp = etna_bo_new(dev, bmp_size, ETNA_BO_UNCACHED); 247037b3c26Smrg if (!bmp) { 24841687f09Smrg perror("etna_bo_new"); 249037b3c26Smrg ret = 5; 250037b3c26Smrg goto out_pipe; 251037b3c26Smrg } 252037b3c26Smrg memset(etna_bo_map(bmp), 0, bmp_size); 253037b3c26Smrg 254037b3c26Smrg stream = etna_cmd_stream_new(pipe, 0x300, NULL, NULL); 255037b3c26Smrg if (!stream) { 25641687f09Smrg perror("etna_cmd_stream_new"); 257037b3c26Smrg ret = 6; 258037b3c26Smrg goto out_bo; 259037b3c26Smrg } 260037b3c26Smrg 261037b3c26Smrg /* generate command sequence */ 262037b3c26Smrg gen_cmd_stream(stream, bmp, width, height); 263037b3c26Smrg 264037b3c26Smrg etna_cmd_stream_finish(stream); 265037b3c26Smrg 26641687f09Smrg if (argc > 2) 26741687f09Smrg bmp_dump32(etna_bo_map(bmp), width, height, false, argv[2]); 26841687f09Smrg 26941687f09Smrg if (etna_check_image(etna_bo_map(bmp), width, height)) 27041687f09Smrg ret = 7; 271037b3c26Smrg 272037b3c26Smrg etna_cmd_stream_del(stream); 273037b3c26Smrg 274037b3c26Smrgout_bo: 275037b3c26Smrg etna_bo_del(bmp); 276037b3c26Smrg 277037b3c26Smrgout_pipe: 278037b3c26Smrg etna_pipe_del(pipe); 279037b3c26Smrg 280037b3c26Smrgout_gpu: 281037b3c26Smrg etna_gpu_del(gpu); 282037b3c26Smrg 283037b3c26Smrgout_device: 284037b3c26Smrg etna_device_del(dev); 285037b3c26Smrg 286037b3c26Smrgout: 287037b3c26Smrg close(fd); 288037b3c26Smrg 289037b3c26Smrg return ret; 290037b3c26Smrg} 291