| /* |
| * Copyright (C) 2014-2015 Etnaviv Project |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| * and/or sell copies of the Software, and to permit persons to whom the |
| * Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice (including the next |
| * paragraph) shall be included in all copies or substantial portions of the |
| * Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| * SOFTWARE. |
| * |
| * Authors: |
| * Christian Gmeiner <christian.gmeiner@gmail.com> |
| */ |
| |
| #ifdef HAVE_CONFIG_H |
| # include "config.h" |
| #endif |
| |
| #include <fcntl.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <unistd.h> |
| |
| #include "xf86drm.h" |
| #include "etnaviv_drmif.h" |
| #include "etnaviv_drm.h" |
| |
| #include "state.xml.h" |
| #include "state_2d.xml.h" |
| #include "cmdstream.xml.h" |
| |
| #include "write_bmp.h" |
| |
| static inline void etna_emit_load_state(struct etna_cmd_stream *stream, |
| const uint16_t offset, const uint16_t count) |
| { |
| uint32_t v; |
| |
| v = (VIV_FE_LOAD_STATE_HEADER_OP_LOAD_STATE | VIV_FE_LOAD_STATE_HEADER_OFFSET(offset) | |
| (VIV_FE_LOAD_STATE_HEADER_COUNT(count) & VIV_FE_LOAD_STATE_HEADER_COUNT__MASK)); |
| |
| etna_cmd_stream_emit(stream, v); |
| } |
| |
| static inline void etna_set_state(struct etna_cmd_stream *stream, uint32_t address, uint32_t value) |
| { |
| etna_cmd_stream_reserve(stream, 2); |
| etna_emit_load_state(stream, address >> 2, 1); |
| etna_cmd_stream_emit(stream, value); |
| } |
| |
| static inline void etna_set_state_from_bo(struct etna_cmd_stream *stream, |
| uint32_t address, struct etna_bo *bo) |
| { |
| etna_cmd_stream_reserve(stream, 2); |
| etna_emit_load_state(stream, address >> 2, 1); |
| |
| etna_cmd_stream_reloc(stream, &(struct etna_reloc){ |
| .bo = bo, |
| .flags = ETNA_RELOC_READ, |
| .offset = 0, |
| }); |
| } |
| |
| static void gen_cmd_stream(struct etna_cmd_stream *stream, struct etna_bo *bmp, const int width, const int height) |
| { |
| int rec; |
| static int num_rects = 256; |
| |
| etna_set_state(stream, VIVS_DE_SRC_STRIDE, 0); |
| etna_set_state(stream, VIVS_DE_SRC_ROTATION_CONFIG, 0); |
| etna_set_state(stream, VIVS_DE_SRC_CONFIG, 0); |
| etna_set_state(stream, VIVS_DE_SRC_ORIGIN, 0); |
| etna_set_state(stream, VIVS_DE_SRC_SIZE, 0); |
| etna_set_state(stream, VIVS_DE_SRC_COLOR_BG, 0); |
| etna_set_state(stream, VIVS_DE_SRC_COLOR_FG, 0); |
| etna_set_state(stream, VIVS_DE_STRETCH_FACTOR_LOW, 0); |
| etna_set_state(stream, VIVS_DE_STRETCH_FACTOR_HIGH, 0); |
| etna_set_state_from_bo(stream, VIVS_DE_DEST_ADDRESS, bmp); |
| etna_set_state(stream, VIVS_DE_DEST_STRIDE, width*4); |
| etna_set_state(stream, VIVS_DE_DEST_ROTATION_CONFIG, 0); |
| etna_set_state(stream, VIVS_DE_DEST_CONFIG, |
| VIVS_DE_DEST_CONFIG_FORMAT(DE_FORMAT_A8R8G8B8) | |
| VIVS_DE_DEST_CONFIG_COMMAND_CLEAR | |
| VIVS_DE_DEST_CONFIG_SWIZZLE(DE_SWIZZLE_ARGB) | |
| VIVS_DE_DEST_CONFIG_TILED_DISABLE | |
| VIVS_DE_DEST_CONFIG_MINOR_TILED_DISABLE |
| ); |
| etna_set_state(stream, VIVS_DE_ROP, |
| VIVS_DE_ROP_ROP_FG(0xcc) | VIVS_DE_ROP_ROP_BG(0xcc) | VIVS_DE_ROP_TYPE_ROP4); |
| etna_set_state(stream, VIVS_DE_CLIP_TOP_LEFT, |
| VIVS_DE_CLIP_TOP_LEFT_X(0) | |
| VIVS_DE_CLIP_TOP_LEFT_Y(0) |
| ); |
| etna_set_state(stream, VIVS_DE_CLIP_BOTTOM_RIGHT, |
| VIVS_DE_CLIP_BOTTOM_RIGHT_X(width) | |
| VIVS_DE_CLIP_BOTTOM_RIGHT_Y(height) |
| ); |
| etna_set_state(stream, VIVS_DE_CONFIG, 0); /* TODO */ |
| etna_set_state(stream, VIVS_DE_SRC_ORIGIN_FRACTION, 0); |
| etna_set_state(stream, VIVS_DE_ALPHA_CONTROL, 0); |
| etna_set_state(stream, VIVS_DE_ALPHA_MODES, 0); |
| etna_set_state(stream, VIVS_DE_DEST_ROTATION_HEIGHT, 0); |
| etna_set_state(stream, VIVS_DE_SRC_ROTATION_HEIGHT, 0); |
| etna_set_state(stream, VIVS_DE_ROT_ANGLE, 0); |
| |
| /* Clear color PE20 */ |
| etna_set_state(stream, VIVS_DE_CLEAR_PIXEL_VALUE32, 0xff40ff40); |
| /* Clear color PE10 */ |
| etna_set_state(stream, VIVS_DE_CLEAR_BYTE_MASK, 0xff); |
| etna_set_state(stream, VIVS_DE_CLEAR_PIXEL_VALUE_LOW, 0xff40ff40); |
| etna_set_state(stream, VIVS_DE_CLEAR_PIXEL_VALUE_HIGH, 0xff40ff40); |
| |
| etna_set_state(stream, VIVS_DE_DEST_COLOR_KEY, 0); |
| etna_set_state(stream, VIVS_DE_GLOBAL_SRC_COLOR, 0); |
| etna_set_state(stream, VIVS_DE_GLOBAL_DEST_COLOR, 0); |
| etna_set_state(stream, VIVS_DE_COLOR_MULTIPLY_MODES, 0); |
| etna_set_state(stream, VIVS_DE_PE_TRANSPARENCY, 0); |
| etna_set_state(stream, VIVS_DE_PE_CONTROL, 0); |
| etna_set_state(stream, VIVS_DE_PE_DITHER_LOW, 0xffffffff); |
| etna_set_state(stream, VIVS_DE_PE_DITHER_HIGH, 0xffffffff); |
| |
| /* Queue DE command */ |
| etna_cmd_stream_emit(stream, |
| VIV_FE_DRAW_2D_HEADER_OP_DRAW_2D | VIV_FE_DRAW_2D_HEADER_COUNT(num_rects) /* render one rectangle */ |
| ); |
| etna_cmd_stream_emit(stream, 0x0); /* rectangles start aligned */ |
| |
| for(rec=0; rec < num_rects; ++rec) { |
| int x = rec%16; |
| int y = rec/16; |
| etna_cmd_stream_emit(stream, VIV_FE_DRAW_2D_TOP_LEFT_X(x*8) | VIV_FE_DRAW_2D_TOP_LEFT_Y(y*8)); |
| 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)); |
| } |
| etna_set_state(stream, 1, 0); |
| etna_set_state(stream, 1, 0); |
| etna_set_state(stream, 1, 0); |
| |
| etna_set_state(stream, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_PE2D); |
| } |
| |
| int main(int argc, char *argv[]) |
| { |
| const int width = 256; |
| const int height = 256; |
| const size_t bmp_size = width * height * 4; |
| |
| struct etna_device *dev; |
| struct etna_gpu *gpu; |
| struct etna_pipe *pipe; |
| struct etna_bo *bmp; |
| struct etna_cmd_stream *stream; |
| |
| drmVersionPtr version; |
| int fd, ret = 0; |
| |
| fd = open(argv[1], O_RDWR); |
| if (fd < 0) |
| return 1; |
| |
| version = drmGetVersion(fd); |
| if (version) { |
| printf("Version: %d.%d.%d\n", version->version_major, |
| version->version_minor, version->version_patchlevel); |
| printf(" Name: %s\n", version->name); |
| printf(" Date: %s\n", version->date); |
| printf(" Description: %s\n", version->desc); |
| drmFreeVersion(version); |
| } |
| |
| dev = etna_device_new(fd); |
| if (!dev) { |
| ret = 2; |
| goto out; |
| } |
| |
| /* TODO: we assume that core 0 is a 2D capable one */ |
| gpu = etna_gpu_new(dev, 0); |
| if (!gpu) { |
| ret = 3; |
| goto out_device; |
| } |
| |
| pipe = etna_pipe_new(gpu, ETNA_PIPE_2D); |
| if (!pipe) { |
| ret = 4; |
| goto out_gpu; |
| } |
| |
| bmp = etna_bo_new(dev, bmp_size, ETNA_BO_UNCACHED); |
| if (!bmp) { |
| ret = 5; |
| goto out_pipe; |
| } |
| memset(etna_bo_map(bmp), 0, bmp_size); |
| |
| stream = etna_cmd_stream_new(pipe, 0x300, NULL, NULL); |
| if (!stream) { |
| ret = 6; |
| goto out_bo; |
| } |
| |
| /* generate command sequence */ |
| gen_cmd_stream(stream, bmp, width, height); |
| |
| etna_cmd_stream_finish(stream); |
| |
| bmp_dump32(etna_bo_map(bmp), width, height, false, "/tmp/etna.bmp"); |
| |
| etna_cmd_stream_del(stream); |
| |
| out_bo: |
| etna_bo_del(bmp); |
| |
| out_pipe: |
| etna_pipe_del(pipe); |
| |
| out_gpu: |
| etna_gpu_del(gpu); |
| |
| out_device: |
| etna_device_del(dev); |
| |
| out: |
| close(fd); |
| |
| return ret; |
| } |