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 (at) 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 "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 main(int argc, char *argv[]) 151 { 152 const int width = 256; 153 const int height = 256; 154 const size_t bmp_size = width * height * 4; 155 156 struct etna_device *dev; 157 struct etna_gpu *gpu; 158 struct etna_pipe *pipe; 159 struct etna_bo *bmp; 160 struct etna_cmd_stream *stream; 161 162 drmVersionPtr version; 163 int fd, ret = 0; 164 165 fd = open(argv[1], O_RDWR); 166 if (fd < 0) 167 return 1; 168 169 version = drmGetVersion(fd); 170 if (version) { 171 printf("Version: %d.%d.%d\n", version->version_major, 172 version->version_minor, version->version_patchlevel); 173 printf(" Name: %s\n", version->name); 174 printf(" Date: %s\n", version->date); 175 printf(" Description: %s\n", version->desc); 176 drmFreeVersion(version); 177 } 178 179 dev = etna_device_new(fd); 180 if (!dev) { 181 ret = 2; 182 goto out; 183 } 184 185 /* TODO: we assume that core 0 is a 2D capable one */ 186 gpu = etna_gpu_new(dev, 0); 187 if (!gpu) { 188 ret = 3; 189 goto out_device; 190 } 191 192 pipe = etna_pipe_new(gpu, ETNA_PIPE_2D); 193 if (!pipe) { 194 ret = 4; 195 goto out_gpu; 196 } 197 198 bmp = etna_bo_new(dev, bmp_size, ETNA_BO_UNCACHED); 199 if (!bmp) { 200 ret = 5; 201 goto out_pipe; 202 } 203 memset(etna_bo_map(bmp), 0, bmp_size); 204 205 stream = etna_cmd_stream_new(pipe, 0x300, NULL, NULL); 206 if (!stream) { 207 ret = 6; 208 goto out_bo; 209 } 210 211 /* generate command sequence */ 212 gen_cmd_stream(stream, bmp, width, height); 213 214 etna_cmd_stream_finish(stream); 215 216 bmp_dump32(etna_bo_map(bmp), width, height, false, "/tmp/etna.bmp"); 217 218 etna_cmd_stream_del(stream); 219 220 out_bo: 221 etna_bo_del(bmp); 222 223 out_pipe: 224 etna_pipe_del(pipe); 225 226 out_gpu: 227 etna_gpu_del(gpu); 228 229 out_device: 230 etna_device_del(dev); 231 232 out: 233 close(fd); 234 235 return ret; 236 } 237