int etna_set_pipe(struct etna_ctx *ctx, enum etna_pipe pipe) { int status; if(ctx == NULL) return ETNA_INVALID_ADDR; if((status = etna_reserve(ctx, 2)) != ETNA_OK) return status; ETNA_EMIT_LOAD_STATE(ctx, VIVS_GL_FLUSH_CACHE>>2, 1, 0); switch(pipe) { case ETNA_PIPE_2D: ETNA_EMIT(ctx, VIVS_GL_FLUSH_CACHE_PE2D); break; case ETNA_PIPE_3D: ETNA_EMIT(ctx, VIVS_GL_FLUSH_CACHE_DEPTH | VIVS_GL_FLUSH_CACHE_COLOR); break; default: return ETNA_INVALID_VALUE; } etna_stall(ctx, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); if((status = etna_reserve(ctx, 2)) != ETNA_OK) return status; ETNA_EMIT_LOAD_STATE(ctx, VIVS_GL_PIPE_SELECT>>2, 1, 0); ETNA_EMIT(ctx, pipe); #ifdef GCABI_HAS_CONTEXT if(ctx->cur_buf != ETNA_CTX_BUFFER) { GCCTX(ctx)->currentPipe = pipe; } #endif return ETNA_OK; }
int etna_set_pipe(etna_ctx *ctx, etna_pipe pipe) { int status; if(ctx == NULL) return ETNA_INVALID_ADDR; if((status = etna_reserve(ctx, 2)) != ETNA_OK) return status; ETNA_EMIT_LOAD_STATE(ctx, VIVS_GL_FLUSH_CACHE, 1, 0); switch(pipe) { case ETNA_PIPE_2D: ETNA_EMIT(ctx, VIVS_GL_FLUSH_CACHE_PE2D); break; case ETNA_PIPE_3D: ETNA_EMIT(ctx, VIVS_GL_FLUSH_CACHE_DEPTH | VIVS_GL_FLUSH_CACHE_COLOR); break; default: return ETNA_INVALID_VALUE; } etna_stall(ctx, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); if((status = etna_reserve(ctx, 2)) != ETNA_OK) return status; ETNA_EMIT_LOAD_STATE(ctx, VIVS_GL_PIPE_SELECT, 1, 0); ETNA_EMIT(ctx, pipe); ctx->ctx.currentPipe = pipe; return ETNA_OK; }
int etna_semaphore(struct etna_ctx *ctx, uint32_t from, uint32_t to) { int status; if(ctx == NULL) return ETNA_INVALID_ADDR; if((status = etna_reserve(ctx, 2)) != ETNA_OK) return status; ETNA_EMIT_LOAD_STATE(ctx, VIVS_GL_SEMAPHORE_TOKEN>>2, 1, 0); ETNA_EMIT(ctx, VIVS_GL_SEMAPHORE_TOKEN_FROM(from) | VIVS_GL_SEMAPHORE_TOKEN_TO(to)); return ETNA_OK; }
int etna_stall(struct etna_ctx *ctx, uint32_t from, uint32_t to) { int status; if(ctx == NULL) return ETNA_INVALID_ADDR; if((status = etna_reserve(ctx, 4)) != ETNA_OK) return status; ETNA_EMIT_LOAD_STATE(ctx, VIVS_GL_SEMAPHORE_TOKEN>>2, 1, 0); ETNA_EMIT(ctx, VIVS_GL_SEMAPHORE_TOKEN_FROM(from) | VIVS_GL_SEMAPHORE_TOKEN_TO(to)); if(from == SYNC_RECIPIENT_FE) { /* if the frontend is to be stalled, queue a STALL frontend command */ ETNA_EMIT_STALL(ctx, from, to); } else { /* otherwise, load the STALL token state */ ETNA_EMIT_LOAD_STATE(ctx, VIVS_GL_STALL_TOKEN>>2, 1, 0); ETNA_EMIT(ctx, VIVS_GL_STALL_TOKEN_FROM(from) | VIVS_GL_STALL_TOKEN_TO(to)); } return ETNA_OK; }
int main(int argc, char **argv) { int rv; int width = 256; int height = 256; int padded_width = etna_align_up(width, 8); int padded_height = etna_align_up(height, 1); printf("padded_width %i padded_height %i\n", padded_width, padded_height); struct viv_conn *conn = 0; rv = viv_open(VIV_HW_2D, &conn); if(rv!=0) { fprintf(stderr, "Error opening device\n"); exit(1); } printf("Succesfully opened device\n"); struct etna_vidmem *bmp = 0; /* bitmap */ struct etna_vidmem *src = 0; /* source */ size_t bmp_size = width * height * 4; size_t src_size = width * height * 4; if(etna_vidmem_alloc_linear(conn, &bmp, bmp_size, VIV_SURF_BITMAP, VIV_POOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(conn, &src, src_size, VIV_SURF_BITMAP, VIV_POOL_DEFAULT, true)!=ETNA_OK) { fprintf(stderr, "Error allocating video memory\n"); exit(1); } struct etna_ctx *ctx = 0; if(etna_create(conn, &ctx) != ETNA_OK) { printf("Unable to create context\n"); exit(1); } /* switch to 2D pipe */ etna_set_pipe(ctx, ETNA_PIPE_2D); /* pre-clear surface. Could use the 2D engine for this, * but we're lazy. */ for(int i=0; i<bmp_size/4; ++i) ((uint32_t*)bmp->logical)[i] = 0xff000000; /* Make pattern */ for(int y=0; y<8; ++y) { for(int x=0; x<8; ++x) { uint8_t a = 0xff; uint8_t r = x*32; uint8_t g = y*32; uint8_t b = 0x12; ((uint32_t*)src->logical)[y*8+x] = ((uint32_t)a << 24)|((uint32_t)b<<16)|((uint32_t)g<<8)|(uint32_t)r; } } for(int frame=0; frame<1; ++frame) { printf("*** FRAME %i ****\n", frame); etna_set_state(ctx, VIVS_DE_SRC_ADDRESS, 0); etna_set_state(ctx, VIVS_DE_SRC_STRIDE, width*4); etna_set_state(ctx, VIVS_DE_SRC_ROTATION_CONFIG, 0); etna_set_state(ctx, VIVS_DE_SRC_CONFIG, VIVS_DE_SRC_CONFIG_UNK16 | VIVS_DE_SRC_CONFIG_SOURCE_FORMAT(DE_FORMAT_MONOCHROME) | VIVS_DE_SRC_CONFIG_LOCATION_MEMORY | VIVS_DE_SRC_CONFIG_PACK_PACKED8 | VIVS_DE_SRC_CONFIG_PE10_SOURCE_FORMAT(DE_FORMAT_MONOCHROME)); etna_set_state(ctx, VIVS_DE_SRC_ORIGIN, 0); etna_set_state(ctx, VIVS_DE_SRC_SIZE, 0); etna_set_state(ctx, VIVS_DE_SRC_COLOR_BG, 0xff44ff44); etna_set_state(ctx, VIVS_DE_SRC_COLOR_FG, 0xff44ff44); etna_set_state(ctx, VIVS_DE_STRETCH_FACTOR_LOW, 0); etna_set_state(ctx, VIVS_DE_STRETCH_FACTOR_HIGH, 0); etna_set_state(ctx, VIVS_DE_DEST_ADDRESS, bmp->address); etna_set_state(ctx, VIVS_DE_DEST_STRIDE, width*4); etna_set_state(ctx, VIVS_DE_DEST_ROTATION_CONFIG, 0); etna_set_state(ctx, VIVS_DE_DEST_CONFIG, VIVS_DE_DEST_CONFIG_FORMAT(DE_FORMAT_A8R8G8B8) | VIVS_DE_DEST_CONFIG_COMMAND_LINE | VIVS_DE_DEST_CONFIG_SWIZZLE(DE_SWIZZLE_ARGB) | VIVS_DE_DEST_CONFIG_TILED_DISABLE | VIVS_DE_DEST_CONFIG_MINOR_TILED_DISABLE ); etna_set_state(ctx, VIVS_DE_ROP, VIVS_DE_ROP_ROP_FG(0xf0) | VIVS_DE_ROP_ROP_BG(0xf0) | VIVS_DE_ROP_TYPE_ROP4); etna_set_state(ctx, VIVS_DE_CLIP_TOP_LEFT, VIVS_DE_CLIP_TOP_LEFT_X(0) | VIVS_DE_CLIP_TOP_LEFT_Y(0) ); etna_set_state(ctx, VIVS_DE_CLIP_BOTTOM_RIGHT, VIVS_DE_CLIP_BOTTOM_RIGHT_X(width) | VIVS_DE_CLIP_BOTTOM_RIGHT_Y(height) ); etna_set_state(ctx, VIVS_DE_CONFIG, 0); /* TODO */ etna_set_state(ctx, VIVS_DE_SRC_ORIGIN_FRACTION, 0); etna_set_state(ctx, VIVS_DE_ALPHA_CONTROL, 0); etna_set_state(ctx, VIVS_DE_ALPHA_MODES, 0); etna_set_state(ctx, VIVS_DE_DEST_ROTATION_HEIGHT, 0); etna_set_state(ctx, VIVS_DE_SRC_ROTATION_HEIGHT, 0); etna_set_state(ctx, VIVS_DE_ROT_ANGLE, 0); etna_set_state(ctx, VIVS_DE_PATTERN_ADDRESS, src->address); etna_set_state(ctx, VIVS_DE_PATTERN_CONFIG, VIVS_DE_PATTERN_CONFIG_FORMAT(DE_FORMAT_A8R8G8B8) | VIVS_DE_PATTERN_CONFIG_TYPE_PATTERN); etna_set_state(ctx, VIVS_DE_PATTERN_MASK_LOW, 0xffffffff); etna_set_state(ctx, VIVS_DE_PATTERN_MASK_HIGH, 0xffffffff); etna_set_state(ctx, VIVS_DE_DEST_COLOR_KEY, 0); etna_set_state(ctx, VIVS_DE_GLOBAL_SRC_COLOR, 0); etna_set_state(ctx, VIVS_DE_GLOBAL_DEST_COLOR, 0); etna_set_state(ctx, VIVS_DE_COLOR_MULTIPLY_MODES, 0); etna_set_state(ctx, VIVS_DE_PE_TRANSPARENCY, 0); etna_set_state(ctx, VIVS_DE_PE_CONTROL, 0); etna_set_state(ctx, VIVS_DE_PE_DITHER_LOW, 0xffffffff); etna_set_state(ctx, VIVS_DE_PE_DITHER_HIGH, 0xffffffff); #define NUM_RECTS (2) /* Queue DE command */ etna_reserve(ctx, 256*2 + 2); (ctx)->buf[(ctx)->offset++] = VIV_FE_DRAW_2D_HEADER_OP_DRAW_2D | VIV_FE_DRAW_2D_HEADER_COUNT(NUM_RECTS); (ctx)->offset++; /* rectangles start aligned */ (ctx)->buf[(ctx)->offset++] = VIV_FE_DRAW_2D_TOP_LEFT_X(0) | VIV_FE_DRAW_2D_TOP_LEFT_Y(0); (ctx)->buf[(ctx)->offset++] = VIV_FE_DRAW_2D_BOTTOM_RIGHT_X(width) | VIV_FE_DRAW_2D_BOTTOM_RIGHT_Y(height); (ctx)->buf[(ctx)->offset++] = VIV_FE_DRAW_2D_TOP_LEFT_X(width) | VIV_FE_DRAW_2D_TOP_LEFT_Y(0); (ctx)->buf[(ctx)->offset++] = VIV_FE_DRAW_2D_BOTTOM_RIGHT_X(0) | VIV_FE_DRAW_2D_BOTTOM_RIGHT_Y(height); etna_set_state(ctx, 1, 0); etna_set_state(ctx, 1, 0); etna_set_state(ctx, 1, 0); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_PE2D); etna_finish(ctx); } bmp_dump32(bmp->logical, width, height, false, "/tmp/fb.bmp"); printf("Dump complete\n"); /* Unlock video memory */ if(etna_vidmem_unlock(conn, bmp) != 0) { fprintf(stderr, "Cannot unlock vidmem\n"); exit(1); } etna_free(ctx); viv_close(conn); return 0; }
int main(int argc, char **argv) { int rv; int width = 256; int height = 256; size_t dst_stride = etna_align_up(width, 8) * 4; struct viv_conn *conn = 0; rv = viv_open(VIV_HW_2D, &conn); if(rv!=0) { fprintf(stderr, "Error opening device\n"); exit(1); } printf("Succesfully opened device\n"); /* Read test image */ int src_width, src_height, src_stride; uint32_t *src_data = 0; if(!read_png("amethyst256.png", 8*4, &src_stride, &src_width, &src_height, &src_data)) { printf("Unable to read amethyst256.png in current directory\n"); exit(1); } struct etna_vidmem *bmp = 0; /* bitmap */ struct etna_vidmem *src = 0; /* source */ size_t bmp_size = dst_stride * height; size_t src_size = src_stride * src_height; if(etna_vidmem_alloc_linear(conn, &bmp, bmp_size, VIV_SURF_BITMAP, VIV_POOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(conn, &src, src_size, VIV_SURF_BITMAP, VIV_POOL_DEFAULT, true)!=ETNA_OK) { fprintf(stderr, "Error allocating video memory\n"); exit(1); } struct etna_ctx *ctx = 0; if(etna_create(conn, &ctx) != ETNA_OK) { printf("Unable to create context\n"); exit(1); } /* switch to 2D pipe */ etna_set_pipe(ctx, ETNA_PIPE_2D); /* pre-clear surface. Could use the 2D engine for this, * but we're lazy. */ for(int i=0; i<bmp_size/4; ++i) ((uint32_t*)bmp->logical)[i] = 0xff000000; memcpy(src->logical, src_data, src_height * src_stride); for(int frame=0; frame<1; ++frame) { printf("*** FRAME %i ****\n", frame); etna_set_state(ctx, VIVS_DE_SRC_ADDRESS, src->address); etna_set_state(ctx, VIVS_DE_SRC_STRIDE, src_stride); etna_set_state(ctx, VIVS_DE_SRC_ROTATION_CONFIG, VIVS_DE_SRC_ROTATION_CONFIG_WIDTH(src_width) | VIVS_DE_SRC_ROTATION_CONFIG_ROTATION_ENABLE); etna_set_state(ctx, VIVS_DE_SRC_ROTATION_HEIGHT, VIVS_DE_SRC_ROTATION_HEIGHT_HEIGHT(src_height)); etna_set_state(ctx, VIVS_DE_SRC_CONFIG, VIVS_DE_SRC_CONFIG_SOURCE_FORMAT(DE_FORMAT_A8R8G8B8) | VIVS_DE_SRC_CONFIG_LOCATION_MEMORY | VIVS_DE_SRC_CONFIG_PE10_SOURCE_FORMAT(DE_FORMAT_A8R8G8B8)); etna_set_state(ctx, VIVS_DE_SRC_ORIGIN, VIVS_DE_SRC_ORIGIN_X(28) | VIVS_DE_SRC_ORIGIN_Y(28)); etna_set_state(ctx, VIVS_DE_SRC_SIZE, VIVS_DE_SRC_SIZE_X(width) | VIVS_DE_SRC_SIZE_Y(height) ); // source size is ignored etna_set_state(ctx, VIVS_DE_SRC_COLOR_BG, 0xff303030); etna_set_state(ctx, VIVS_DE_SRC_COLOR_FG, 0xff12ff56); etna_set_state(ctx, VIVS_DE_STRETCH_FACTOR_LOW, 0); etna_set_state(ctx, VIVS_DE_STRETCH_FACTOR_HIGH, 0); etna_set_state(ctx, VIVS_DE_DEST_ADDRESS, bmp->address); etna_set_state(ctx, VIVS_DE_DEST_STRIDE, dst_stride); etna_set_state(ctx, VIVS_DE_DEST_ROTATION_CONFIG, VIVS_DE_DEST_ROTATION_CONFIG_WIDTH(width) | VIVS_DE_DEST_ROTATION_CONFIG_ROTATION_DISABLE); etna_set_state(ctx, VIVS_DE_DEST_ROTATION_HEIGHT, VIVS_DE_DEST_ROTATION_HEIGHT_HEIGHT(height)); etna_set_state(ctx, VIVS_DE_DEST_CONFIG, VIVS_DE_DEST_CONFIG_FORMAT(DE_FORMAT_A8R8G8B8) | VIVS_DE_DEST_CONFIG_COMMAND_BIT_BLT | VIVS_DE_DEST_CONFIG_SWIZZLE(DE_SWIZZLE_ARGB) | VIVS_DE_DEST_CONFIG_TILED_DISABLE | VIVS_DE_DEST_CONFIG_MINOR_TILED_DISABLE ); etna_set_state(ctx, VIVS_DE_ROP, VIVS_DE_ROP_ROP_FG(0xcc) | VIVS_DE_ROP_ROP_BG(0xcc) | VIVS_DE_ROP_TYPE_ROP4); etna_set_state(ctx, VIVS_DE_CLIP_TOP_LEFT, VIVS_DE_CLIP_TOP_LEFT_X(0) | VIVS_DE_CLIP_TOP_LEFT_Y(0) ); etna_set_state(ctx, VIVS_DE_CLIP_BOTTOM_RIGHT, VIVS_DE_CLIP_BOTTOM_RIGHT_X(width) | VIVS_DE_CLIP_BOTTOM_RIGHT_Y(height) ); etna_set_state(ctx, VIVS_DE_CONFIG, VIVS_DE_CONFIG_MIRROR_BLT_ENABLE_OFF | VIVS_DE_CONFIG_MIRROR_BLT_MODE_NORMAL ); etna_set_state(ctx, VIVS_DE_SRC_ORIGIN_FRACTION, 0); etna_set_state(ctx, VIVS_DE_ALPHA_CONTROL, 0); etna_set_state(ctx, VIVS_DE_ALPHA_MODES, 0); etna_set_state(ctx, VIVS_DE_ROT_ANGLE, 0); /* Clear color PE20 */ etna_set_state(ctx, VIVS_DE_CLEAR_PIXEL_VALUE32, 0xff40ff40); /* Clear color PE10 */ etna_set_state(ctx, VIVS_DE_CLEAR_BYTE_MASK, 0xff); etna_set_state(ctx, VIVS_DE_CLEAR_PIXEL_VALUE_LOW, 0xff40ff40); etna_set_state(ctx, VIVS_DE_CLEAR_PIXEL_VALUE_HIGH, 0xff40ff40); etna_set_state(ctx, VIVS_DE_DEST_COLOR_KEY, 0); etna_set_state(ctx, VIVS_DE_GLOBAL_SRC_COLOR, 0); etna_set_state(ctx, VIVS_DE_GLOBAL_DEST_COLOR, 0); etna_set_state(ctx, VIVS_DE_COLOR_MULTIPLY_MODES, 0); etna_set_state(ctx, VIVS_DE_PE_TRANSPARENCY, 0); etna_set_state(ctx, VIVS_DE_PE_CONTROL, 0); etna_set_state(ctx, VIVS_DE_PE_DITHER_LOW, 0xffffffff); etna_set_state(ctx, VIVS_DE_PE_DITHER_HIGH, 0xffffffff); #define NUM_RECTS (1) /* Queue DE command */ etna_reserve(ctx, 256*2 + 2); (ctx)->buf[(ctx)->offset++] = VIV_FE_DRAW_2D_HEADER_OP_DRAW_2D | VIV_FE_DRAW_2D_HEADER_COUNT(NUM_RECTS) | VIV_FE_DRAW_2D_HEADER_DATA_COUNT(0); (ctx)->offset++; /* rectangles start aligned */ for(int rec=0; rec<NUM_RECTS; ++rec) { int tgt_width = 200; int tgt_height = 200; int x1 = 28; int y1 = 28; (ctx)->buf[(ctx)->offset++] = VIV_FE_DRAW_2D_TOP_LEFT_X(x1) | VIV_FE_DRAW_2D_TOP_LEFT_Y(y1); (ctx)->buf[(ctx)->offset++] = VIV_FE_DRAW_2D_BOTTOM_RIGHT_X(x1 + tgt_width) | VIV_FE_DRAW_2D_BOTTOM_RIGHT_Y(y1 + tgt_height); } etna_set_state(ctx, 1, 0); etna_set_state(ctx, 1, 0); etna_set_state(ctx, 1, 0); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_PE2D); etna_finish(ctx); } bmp_dump32_noflip(bmp->logical, width, height, true, "/tmp/fb.bmp"); printf("Dump complete\n"); /* Unlock video memory */ if(etna_vidmem_unlock(conn, NULL, bmp) != 0) { fprintf(stderr, "Cannot unlock vidmem\n"); exit(1); } etna_free(ctx); viv_close(conn); return 0; }