1 /* 2 * Copyright (C) 2014-2015 Etnaviv Project 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 * Christian Gmeiner <christian.gmeiner@gmail.com> 25 */ 26 27 #include <fcntl.h> 28 #include <stdio.h> 29 #include <string.h> 30 #include <unistd.h> 31 32 #include "xf86drm.h" 33 #include "etnaviv_drmif.h" 34 #include <drm/etnaviv_drm.h> 35 36 #include "state.xml.h" 37 #include "state_2d.xml.h" 38 #include "cmdstream.xml.h" 39 40 #include "write_bmp.h" 41 42 static inline void etna_emit_load_state(struct etna_cmd_stream *stream, 43 const uint16_t offset, const uint16_t count) 44 { 45 uint32_t v; 46 47 v = (VIV_FE_LOAD_STATE_HEADER_OP_LOAD_STATE | VIV_FE_LOAD_STATE_HEADER_OFFSET(offset) | 48 (VIV_FE_LOAD_STATE_HEADER_COUNT(count) & VIV_FE_LOAD_STATE_HEADER_COUNT__MASK)); 49 50 etna_cmd_stream_emit(stream, v); 51 } 52 53 static inline void etna_set_state(struct etna_cmd_stream *stream, uint32_t address, uint32_t value) 54 { 55 etna_cmd_stream_reserve(stream, 2); 56 etna_emit_load_state(stream, address >> 2, 1); 57 etna_cmd_stream_emit(stream, value); 58 } 59 60 static inline void etna_set_state_from_bo(struct etna_cmd_stream *stream, 61 uint32_t address, struct etna_bo *bo) 62 { 63 etna_cmd_stream_reserve(stream, 2); 64 etna_emit_load_state(stream, address >> 2, 1); 65 66 etna_cmd_stream_reloc(stream, &(struct etna_reloc){ 67 .bo = bo, 68 .flags = ETNA_RELOC_READ, 69 .offset = 0, 70 }); 71 } 72 73 static void gen_cmd_stream(struct etna_cmd_stream *stream, struct etna_bo *bmp, const int width, const int height) 74 { 75 int rec; 76 static int num_rects = 256; 77 78 etna_set_state(stream, VIVS_DE_SRC_STRIDE, 0); 79 etna_set_state(stream, VIVS_DE_SRC_ROTATION_CONFIG, 0); 80 etna_set_state(stream, VIVS_DE_SRC_CONFIG, 0); 81 etna_set_state(stream, VIVS_DE_SRC_ORIGIN, 0); 82 etna_set_state(stream, VIVS_DE_SRC_SIZE, 0); 83 etna_set_state(stream, VIVS_DE_SRC_COLOR_BG, 0); 84 etna_set_state(stream, VIVS_DE_SRC_COLOR_FG, 0); 85 etna_set_state(stream, VIVS_DE_STRETCH_FACTOR_LOW, 0); 86 etna_set_state(stream, VIVS_DE_STRETCH_FACTOR_HIGH, 0); 87 etna_set_state_from_bo(stream, VIVS_DE_DEST_ADDRESS, bmp); 88 etna_set_state(stream, VIVS_DE_DEST_STRIDE, width*4); 89 etna_set_state(stream, VIVS_DE_DEST_ROTATION_CONFIG, 0); 90 etna_set_state(stream, VIVS_DE_DEST_CONFIG, 91 VIVS_DE_DEST_CONFIG_FORMAT(DE_FORMAT_A8R8G8B8) | 92 VIVS_DE_DEST_CONFIG_COMMAND_CLEAR | 93 VIVS_DE_DEST_CONFIG_SWIZZLE(DE_SWIZZLE_ARGB) | 94 VIVS_DE_DEST_CONFIG_TILED_DISABLE | 95 VIVS_DE_DEST_CONFIG_MINOR_TILED_DISABLE 96 ); 97 etna_set_state(stream, VIVS_DE_ROP, 98 VIVS_DE_ROP_ROP_FG(0xcc) | VIVS_DE_ROP_ROP_BG(0xcc) | VIVS_DE_ROP_TYPE_ROP4); 99 etna_set_state(stream, VIVS_DE_CLIP_TOP_LEFT, 100 VIVS_DE_CLIP_TOP_LEFT_X(0) | 101 VIVS_DE_CLIP_TOP_LEFT_Y(0) 102 ); 103 etna_set_state(stream, VIVS_DE_CLIP_BOTTOM_RIGHT, 104 VIVS_DE_CLIP_BOTTOM_RIGHT_X(width) | 105 VIVS_DE_CLIP_BOTTOM_RIGHT_Y(height) 106 ); 107 etna_set_state(stream, VIVS_DE_CONFIG, 0); /* TODO */ 108 etna_set_state(stream, VIVS_DE_SRC_ORIGIN_FRACTION, 0); 109 etna_set_state(stream, VIVS_DE_ALPHA_CONTROL, 0); 110 etna_set_state(stream, VIVS_DE_ALPHA_MODES, 0); 111 etna_set_state(stream, VIVS_DE_DEST_ROTATION_HEIGHT, 0); 112 etna_set_state(stream, VIVS_DE_SRC_ROTATION_HEIGHT, 0); 113 etna_set_state(stream, VIVS_DE_ROT_ANGLE, 0); 114 115 /* Clear color PE20 */ 116 etna_set_state(stream, VIVS_DE_CLEAR_PIXEL_VALUE32, 0xff40ff40); 117 /* Clear color PE10 */ 118 etna_set_state(stream, VIVS_DE_CLEAR_BYTE_MASK, 0xff); 119 etna_set_state(stream, VIVS_DE_CLEAR_PIXEL_VALUE_LOW, 0xff40ff40); 120 etna_set_state(stream, VIVS_DE_CLEAR_PIXEL_VALUE_HIGH, 0xff40ff40); 121 122 etna_set_state(stream, VIVS_DE_DEST_COLOR_KEY, 0); 123 etna_set_state(stream, VIVS_DE_GLOBAL_SRC_COLOR, 0); 124 etna_set_state(stream, VIVS_DE_GLOBAL_DEST_COLOR, 0); 125 etna_set_state(stream, VIVS_DE_COLOR_MULTIPLY_MODES, 0); 126 etna_set_state(stream, VIVS_DE_PE_TRANSPARENCY, 0); 127 etna_set_state(stream, VIVS_DE_PE_CONTROL, 0); 128 etna_set_state(stream, VIVS_DE_PE_DITHER_LOW, 0xffffffff); 129 etna_set_state(stream, VIVS_DE_PE_DITHER_HIGH, 0xffffffff); 130 131 /* Queue DE command */ 132 etna_cmd_stream_emit(stream, 133 VIV_FE_DRAW_2D_HEADER_OP_DRAW_2D | VIV_FE_DRAW_2D_HEADER_COUNT(num_rects) /* render one rectangle */ 134 ); 135 etna_cmd_stream_emit(stream, 0x0); /* rectangles start aligned */ 136 137 for(rec=0; rec < num_rects; ++rec) { 138 int x = rec%16; 139 int y = rec/16; 140 etna_cmd_stream_emit(stream, VIV_FE_DRAW_2D_TOP_LEFT_X(x*8) | VIV_FE_DRAW_2D_TOP_LEFT_Y(y*8)); 141 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)); 142 } 143 etna_set_state(stream, 1, 0); 144 etna_set_state(stream, 1, 0); 145 etna_set_state(stream, 1, 0); 146 147 etna_set_state(stream, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_PE2D); 148 } 149 150 int etna_check_image(uint32_t *p, int width, int height) 151 { 152 int i; 153 uint32_t expected; 154 155 for (i = 0; i < width * height; i++) { 156 if (i%8 < 4 && i%(width*8) < width*4 && i%width < 8*16 && i < width*8*16) 157 expected = 0xff40ff40; 158 else 159 expected = 0x00000000; 160 161 if (p[i] != expected) { 162 fprintf(stderr, "Offset %d: expected: 0x%08x, got: 0x%08x\n", 163 i, expected, p[i]); 164 return -1; 165 } 166 } 167 168 return 0; 169 } 170 171 int main(int argc, char *argv[]) 172 { 173 const int width = 256; 174 const int height = 256; 175 const size_t bmp_size = width * height * 4; 176 177 struct etna_device *dev; 178 struct etna_gpu *gpu; 179 struct etna_pipe *pipe; 180 struct etna_bo *bmp; 181 struct etna_cmd_stream *stream; 182 183 drmVersionPtr version; 184 int fd, ret = 0; 185 uint64_t feat; 186 int core = 0; 187 188 if (argc < 2) { 189 fprintf(stderr, "Usage: %s /dev/dri/<device> [<etna.bmp>]\n", argv[0]); 190 return 1; 191 } 192 193 fd = open(argv[1], O_RDWR); 194 if (fd < 0) { 195 perror(argv[1]); 196 return 1; 197 } 198 199 version = drmGetVersion(fd); 200 if (version) { 201 printf("Version: %d.%d.%d\n", version->version_major, 202 version->version_minor, version->version_patchlevel); 203 printf(" Name: %s\n", version->name); 204 printf(" Date: %s\n", version->date); 205 printf(" Description: %s\n", version->desc); 206 drmFreeVersion(version); 207 } 208 209 dev = etna_device_new(fd); 210 if (!dev) { 211 perror("etna_device_new"); 212 ret = 2; 213 goto out; 214 } 215 216 do { 217 gpu = etna_gpu_new(dev, core); 218 if (!gpu) { 219 perror("etna_gpu_new"); 220 ret = 3; 221 goto out_device; 222 } 223 224 if (etna_gpu_get_param(gpu, ETNA_GPU_FEATURES_0, &feat)) { 225 perror("etna_gpu_get_param"); 226 ret = 4; 227 goto out_device; 228 } 229 230 if ((feat & (1 << 9)) == 0) { 231 /* GPU not 2D capable. */ 232 etna_gpu_del(gpu); 233 gpu = NULL; 234 } 235 236 core++; 237 } while (!gpu); 238 239 pipe = etna_pipe_new(gpu, ETNA_PIPE_2D); 240 if (!pipe) { 241 perror("etna_pipe_new"); 242 ret = 4; 243 goto out_gpu; 244 } 245 246 bmp = etna_bo_new(dev, bmp_size, ETNA_BO_UNCACHED); 247 if (!bmp) { 248 perror("etna_bo_new"); 249 ret = 5; 250 goto out_pipe; 251 } 252 memset(etna_bo_map(bmp), 0, bmp_size); 253 254 stream = etna_cmd_stream_new(pipe, 0x300, NULL, NULL); 255 if (!stream) { 256 perror("etna_cmd_stream_new"); 257 ret = 6; 258 goto out_bo; 259 } 260 261 /* generate command sequence */ 262 gen_cmd_stream(stream, bmp, width, height); 263 264 etna_cmd_stream_finish(stream); 265 266 if (argc > 2) 267 bmp_dump32(etna_bo_map(bmp), width, height, false, argv[2]); 268 269 if (etna_check_image(etna_bo_map(bmp), width, height)) 270 ret = 7; 271 272 etna_cmd_stream_del(stream); 273 274 out_bo: 275 etna_bo_del(bmp); 276 277 out_pipe: 278 etna_pipe_del(pipe); 279 280 out_gpu: 281 etna_gpu_del(gpu); 282 283 out_device: 284 etna_device_del(dev); 285 286 out: 287 close(fd); 288 289 return ret; 290 } 291