bool etna_screen_resource_alloc_ts(struct pipe_screen *screen, struct etna_resource *resource) { struct etna_screen *priv = etna_screen(screen); size_t rt_ts_size; assert(!resource->ts); /* TS only for level 0 -- XXX is this formula correct? */ rt_ts_size = align(resource->levels[0].size*priv->specs.bits_per_tile/0x80, 0x100); if(rt_ts_size == 0) return true; DBG_F(ETNA_DBG_RESOURCE_MSGS, "%p: Allocating tile status of size %zi", resource, rt_ts_size); struct etna_vidmem *rt_ts = 0; if(unlikely(etna_vidmem_alloc_linear(priv->dev, &rt_ts, rt_ts_size, VIV_SURF_TILE_STATUS, VIV_POOL_DEFAULT, true)!=ETNA_OK)) { BUG("Problem allocating tile status for resource"); return false; } resource->ts = rt_ts; resource->levels[0].ts_address = resource->ts->address; resource->levels[0].ts_size = resource->ts->size; /* It is important to initialize the TS, as random pattern * can result in crashes. Do this on the CPU as this only happens once * per surface anyway and it's a small area, so it may not be worth * queuing this to the GPU. */ memset(rt_ts->logical, priv->specs.ts_clear_value, rt_ts_size); return true; }
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, height; int width_s, height_s; int padded_width, padded_height; int backbuffer = 0; int supersample_x = 2; // 1 or 2 int supersample_y = 2; // 1 or 2 int extra_ps_inputs = 0; fb_info fb; rv = fb_open(0, &fb); if(rv!=0) { exit(1); } width = fb.fb_var.xres; height = fb.fb_var.yres; width_s = width * supersample_x; height_s = height * supersample_y; padded_width = etna_align_up(width_s, 64); padded_height = etna_align_up(height_s, 64); extra_ps_inputs = (supersample_x > 1 || supersample_y > 1); // in case of supersample, there is an extra input to PS printf("padded_width %i padded_height %i\n", padded_width, padded_height); rv = viv_open(); if(rv!=0) { fprintf(stderr, "Error opening device\n"); exit(1); } printf("Succesfully opened device\n"); etna_vidmem *rt = 0; /* main render target */ etna_vidmem *rt_ts = 0; /* tile status for main render target */ etna_vidmem *z = 0; /* depth for main render target */ etna_vidmem *z_ts = 0; /* depth ts for main render target */ etna_vidmem *vtx = 0; /* vertex buffer */ etna_vidmem *idx = 0; /* index buffer */ etna_vidmem *aux_rt = 0; /* auxilary render target */ etna_vidmem *aux_rt_ts = 0; /* tile status for auxilary render target */ etna_vidmem *tex = 0; /* texture */ etna_vidmem *bmp = 0; /* bitmap */ /* TODO: anti aliasing (doubles width/height) */ size_t rt_size = padded_width * padded_height * 4; size_t rt_ts_size = etna_align_up((padded_width * padded_height * 4)/0x100, 0x100); size_t z_size = padded_width * padded_height * 2; size_t z_ts_size = etna_align_up((padded_width * padded_height * 2)/0x100, 0x100); size_t bmp_size = width * height * 4; if(etna_vidmem_alloc_linear(&rt, rt_size, gcvSURF_RENDER_TARGET, gcvPOOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(&rt_ts, rt_ts_size, gcvSURF_TILE_STATUS, gcvPOOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(&z, z_size, gcvSURF_DEPTH, gcvPOOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(&z_ts, z_ts_size, gcvSURF_TILE_STATUS, gcvPOOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(&vtx, VERTEX_BUFFER_SIZE, gcvSURF_VERTEX, gcvPOOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(&idx, INDEX_BUFFER_SIZE, gcvSURF_INDEX, gcvPOOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(&aux_rt, 0x4000, gcvSURF_RENDER_TARGET, gcvPOOL_SYSTEM, true)!=ETNA_OK || etna_vidmem_alloc_linear(&aux_rt_ts, 0x100, gcvSURF_TILE_STATUS, gcvPOOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(&tex, 0x100000, gcvSURF_TEXTURE, gcvPOOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(&bmp, bmp_size, gcvSURF_BITMAP, gcvPOOL_DEFAULT, true)!=ETNA_OK ) { fprintf(stderr, "Error allocating video memory\n"); exit(1); } /* Phew, now we got all the memory we need. * Write interleaved attribute vertex stream. * Unlike the GL example we only do this once, not every time glDrawArrays is called, the same would be accomplished * from GL by using a vertex buffer object. */ memset(vtx->logical, 0, 0x5ef80); #ifndef INDEXED printf("Interleaving vertices...\n"); float *vertices_array = companion_vertices_array(); float *texture_coordinates_array = companion_texture_coordinates_array(); float *normals_array = companion_normals_array(); assert(COMPANION_ARRAY_COUNT*(3+3+2)*sizeof(float) < VERTEX_BUFFER_SIZE); for(int vert=0; vert<COMPANION_ARRAY_COUNT; ++vert) { int dest_idx = vert * (3 + 3 + 2); for(int comp=0; comp<3; ++comp) ((float*)vtx->logical)[dest_idx+comp+0] = vertices_array[vert*3 + comp]; /* 0 */ for(int comp=0; comp<3; ++comp) ((float*)vtx->logical)[dest_idx+comp+3] = normals_array[vert*3 + comp]; /* 1 */ for(int comp=0; comp<2; ++comp) ((float*)vtx->logical)[dest_idx+comp+6] = texture_coordinates_array[vert*2 + comp]; /* 2 */ } #else printf("Interleaving vertices and copying index buffer...\n"); assert(COMPANION_VERTEX_COUNT*(3+3+2)*sizeof(float) < VERTEX_BUFFER_SIZE); for(int vert=0; vert<COMPANION_VERTEX_COUNT; ++vert) { int dest_idx = vert * (3 + 3 + 2); for(int comp=0; comp<3; ++comp) ((float*)vtx->logical)[dest_idx+comp+0] = companion_vertices[vert][comp]; /* 0 */ for(int comp=0; comp<3; ++comp) ((float*)vtx->logical)[dest_idx+comp+3] = companion_normals[vert][comp]; /* 1 */ for(int comp=0; comp<2; ++comp) ((float*)vtx->logical)[dest_idx+comp+6] = companion_texture_coordinates[vert][comp]; /* 2 */ } assert(COMPANION_TRIANGLE_COUNT*3*sizeof(unsigned short) < INDEX_BUFFER_SIZE); memcpy(idx->logical, &companion_triangles[0][0], COMPANION_TRIANGLE_COUNT*3*sizeof(unsigned short)); #endif /* Fill in texture (convert from RGB linear to tiled) */ #define TILE_WIDTH (4) #define TILE_HEIGHT (4) #define TILE_WORDS (TILE_WIDTH*TILE_HEIGHT) unsigned ytiles = COMPANION_TEXTURE_HEIGHT / TILE_HEIGHT; unsigned xtiles = COMPANION_TEXTURE_WIDTH / TILE_WIDTH; unsigned dst_stride = xtiles * TILE_WORDS; for(unsigned ty=0; ty<ytiles; ++ty) { for(unsigned tx=0; tx<xtiles; ++tx) { unsigned ofs = ty * dst_stride + tx * TILE_WORDS; for(unsigned y=0; y<TILE_HEIGHT; ++y) { for(unsigned x=0; x<TILE_WIDTH; ++x) { unsigned srcy = ty*TILE_HEIGHT + y; unsigned srcx = tx*TILE_WIDTH + x; unsigned src_ofs = (srcy*COMPANION_TEXTURE_WIDTH+srcx)*3; unsigned r,g,b,a; #ifndef TEST_PATTERN /* actual texture */ r = ((uint8_t*)companion_texture)[src_ofs+0]; g = ((uint8_t*)companion_texture)[src_ofs+1]; b = ((uint8_t*)companion_texture)[src_ofs+2]; #else /* test pattern */ r = srcx; g = srcy; b = 0; #endif a = 255; ((uint32_t*)tex->logical)[ofs] = ((a&0xFF) << 24) | ((b&0xFF) << 16) | ((g&0xFF) << 8) | (r&0xFF); ofs += 1; } } } } etna_ctx *ctx = 0; if(etna_create(&ctx) != ETNA_OK) { printf("Unable to create context\n"); exit(1); } for(int frame=0; frame<1000; ++frame) { printf("*** FRAME %i ****\n", frame); /* XXX part of this can be put outside the loop, but until we have usable context management * this is safest. */ etna_set_state(ctx, VIVS_GL_VERTEX_ELEMENT_CONFIG, 0x1); etna_set_state(ctx, VIVS_RA_CONTROL, 0x1); etna_set_state(ctx, VIVS_PA_W_CLIP_LIMIT, 0x34000001); etna_set_state(ctx, VIVS_PA_SYSTEM_MODE, 0x11); etna_set_state(ctx, VIVS_PA_CONFIG, ETNA_MASKED_BIT(VIVS_PA_CONFIG_UNK22, 0)); etna_set_state(ctx, VIVS_SE_CONFIG, 0x0); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR); etna_set_state(ctx, VIVS_PE_ALPHA_CONFIG, ETNA_MASKED_BIT(VIVS_PE_ALPHA_CONFIG_BLEND_ENABLE_COLOR, 0) & ETNA_MASKED_BIT(VIVS_PE_ALPHA_CONFIG_BLEND_ENABLE_ALPHA, 0) & ETNA_MASKED(VIVS_PE_ALPHA_CONFIG_SRC_FUNC_COLOR, BLEND_FUNC_ONE) & ETNA_MASKED(VIVS_PE_ALPHA_CONFIG_SRC_FUNC_ALPHA, BLEND_FUNC_ONE) & ETNA_MASKED(VIVS_PE_ALPHA_CONFIG_DST_FUNC_COLOR, BLEND_FUNC_ZERO) & ETNA_MASKED(VIVS_PE_ALPHA_CONFIG_DST_FUNC_ALPHA, BLEND_FUNC_ZERO) & ETNA_MASKED(VIVS_PE_ALPHA_CONFIG_EQ_COLOR, BLEND_EQ_ADD) & ETNA_MASKED(VIVS_PE_ALPHA_CONFIG_EQ_ALPHA, BLEND_EQ_ADD)); etna_set_state(ctx, VIVS_PE_ALPHA_BLEND_COLOR, VIVS_PE_ALPHA_BLEND_COLOR_B(0) | VIVS_PE_ALPHA_BLEND_COLOR_G(0) | VIVS_PE_ALPHA_BLEND_COLOR_R(0) | VIVS_PE_ALPHA_BLEND_COLOR_A(0)); etna_set_state(ctx, VIVS_PE_ALPHA_OP, ETNA_MASKED_BIT(VIVS_PE_ALPHA_OP_ALPHA_TEST, 0)); etna_set_state(ctx, VIVS_PA_CONFIG, ETNA_MASKED_INL(VIVS_PA_CONFIG_CULL_FACE_MODE, CCW)); etna_set_state(ctx, VIVS_PE_STENCIL_CONFIG, ETNA_MASKED(VIVS_PE_STENCIL_CONFIG_REF_FRONT, 0) & ETNA_MASKED(VIVS_PE_STENCIL_CONFIG_MASK_FRONT, 0xff) & ETNA_MASKED(VIVS_PE_STENCIL_CONFIG_WRITE_MASK, 0xff) & ETNA_MASKED_INL(VIVS_PE_STENCIL_CONFIG_MODE, DISABLED)); etna_set_state(ctx, VIVS_PE_STENCIL_OP, ETNA_MASKED(VIVS_PE_STENCIL_OP_FUNC_FRONT, COMPARE_FUNC_ALWAYS) & ETNA_MASKED(VIVS_PE_STENCIL_OP_FUNC_BACK, COMPARE_FUNC_ALWAYS) & ETNA_MASKED(VIVS_PE_STENCIL_OP_FAIL_FRONT, STENCIL_OP_KEEP) & ETNA_MASKED(VIVS_PE_STENCIL_OP_FAIL_BACK, STENCIL_OP_KEEP) & ETNA_MASKED(VIVS_PE_STENCIL_OP_DEPTH_FAIL_FRONT, STENCIL_OP_KEEP) & ETNA_MASKED(VIVS_PE_STENCIL_OP_DEPTH_FAIL_BACK, STENCIL_OP_KEEP) & ETNA_MASKED(VIVS_PE_STENCIL_OP_PASS_FRONT, STENCIL_OP_KEEP) & ETNA_MASKED(VIVS_PE_STENCIL_OP_PASS_BACK, STENCIL_OP_KEEP)); etna_set_state(ctx, VIVS_SE_DEPTH_SCALE, 0x0); etna_set_state(ctx, VIVS_SE_DEPTH_BIAS, 0x0); etna_set_state(ctx, VIVS_PA_CONFIG, ETNA_MASKED_INL(VIVS_PA_CONFIG_FILL_MODE, SOLID) & ETNA_MASKED_INL(VIVS_PA_CONFIG_SHADE_MODEL, SMOOTH)); etna_set_state(ctx, VIVS_PE_COLOR_FORMAT, ETNA_MASKED_BIT(VIVS_PE_COLOR_FORMAT_PARTIAL, 0) & ETNA_MASKED(VIVS_PE_COLOR_FORMAT_COMPONENTS, 0xf) & ETNA_MASKED(VIVS_PE_COLOR_FORMAT_FORMAT, RS_FORMAT_X8R8G8B8) & ETNA_MASKED_BIT(VIVS_PE_COLOR_FORMAT_SUPER_TILED, 1)); etna_set_state(ctx, VIVS_PE_COLOR_ADDR, rt->address); etna_set_state(ctx, VIVS_PE_COLOR_STRIDE, padded_width * 4); uint32_t ts_msaa_config; if(supersample_x == 2 && supersample_y == 2) { // 4X MSAA etna_set_state(ctx, VIVS_GL_MULTI_SAMPLE_CONFIG, ETNA_MASKED_INL(VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES, 4X) & ETNA_MASKED(VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES, 0xf) & ETNA_MASKED(VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12, 0x0) & ETNA_MASKED(VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16, 0x0) ); etna_set_state(ctx, VIVS_RA_MULTISAMPLE_UNK00E04, 0x0); etna_set_state(ctx, VIVS_RA_MULTISAMPLE_UNK00E10(2), 0xaaa22a22); etna_set_state(ctx, VIVS_RA_CENTROID_TABLE(8), 0x262a2288); etna_set_state(ctx, VIVS_RA_CENTROID_TABLE(9), 0x886688a2); etna_set_state(ctx, VIVS_RA_CENTROID_TABLE(10), 0x888866aa); etna_set_state(ctx, VIVS_RA_CENTROID_TABLE(11), 0x668888a6); etna_set_state(ctx, VIVS_RA_MULTISAMPLE_UNK00E10(1), 0xe6ae622a); etna_set_state(ctx, VIVS_RA_CENTROID_TABLE(4), 0x46622a88); etna_set_state(ctx, VIVS_RA_CENTROID_TABLE(5), 0x888888ae); etna_set_state(ctx, VIVS_RA_CENTROID_TABLE(6), 0x888888e6); etna_set_state(ctx, VIVS_RA_CENTROID_TABLE(7), 0x888888ca); etna_set_state(ctx, VIVS_RA_MULTISAMPLE_UNK00E10(0), 0xeaa26e26); etna_set_state(ctx, VIVS_RA_CENTROID_TABLE(0), 0x4a6e2688); etna_set_state(ctx, VIVS_RA_CENTROID_TABLE(1), 0x888888a2); etna_set_state(ctx, VIVS_RA_CENTROID_TABLE(2), 0x888888ea); etna_set_state(ctx, VIVS_RA_CENTROID_TABLE(3), 0x888888c6); ts_msaa_config = VIVS_TS_MEM_CONFIG_MSAA | VIVS_TS_MEM_CONFIG_MSAA_FORMAT_A8R8G8B8; } else if(supersample_x == 2 && supersample_y == 1) { // 2X MSAA etna_set_state(ctx, VIVS_GL_MULTI_SAMPLE_CONFIG, ETNA_MASKED_INL(VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES, 2X) & ETNA_MASKED(VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES, 0xf) & ETNA_MASKED(VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12, 0x0) & ETNA_MASKED(VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16, 0x0) ); etna_set_state(ctx, VIVS_RA_MULTISAMPLE_UNK00E04, 0x0); etna_set_state(ctx, VIVS_RA_MULTISAMPLE_UNK00E10(0), 0xaa22); etna_set_state(ctx, VIVS_RA_CENTROID_TABLE(0), 0x66aa2288); etna_set_state(ctx, VIVS_RA_CENTROID_TABLE(1), 0x88558800); etna_set_state(ctx, VIVS_RA_CENTROID_TABLE(2), 0x88881100); etna_set_state(ctx, VIVS_RA_CENTROID_TABLE(3), 0x33888800); ts_msaa_config = VIVS_TS_MEM_CONFIG_MSAA | VIVS_TS_MEM_CONFIG_MSAA_FORMAT_A8R8G8B8; } else { // No multisampling etna_set_state(ctx, VIVS_GL_MULTI_SAMPLE_CONFIG, ETNA_MASKED_INL(VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES, NONE) & ETNA_MASKED(VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES, 0xf) & ETNA_MASKED(VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12, 0x0) & ETNA_MASKED(VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16, 0x0) ); ts_msaa_config = 0; } etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR); etna_set_state(ctx, VIVS_TS_COLOR_CLEAR_VALUE, 0); etna_set_state(ctx, VIVS_TS_COLOR_STATUS_BASE, rt_ts->address); etna_set_state(ctx, VIVS_TS_COLOR_SURFACE_BASE, rt->address); etna_set_state(ctx, VIVS_PE_DEPTH_CONFIG, ETNA_MASKED_BIT(VIVS_PE_DEPTH_CONFIG_WRITE_ENABLE, 0) & ETNA_MASKED_INL(VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT, D16) & ETNA_MASKED_BIT(VIVS_PE_DEPTH_CONFIG_SUPER_TILED, 1) & ETNA_MASKED_BIT(VIVS_PE_DEPTH_CONFIG_EARLY_Z, 1)); etna_set_state(ctx, VIVS_PE_DEPTH_ADDR, z->address); etna_set_state(ctx, VIVS_PE_DEPTH_STRIDE, padded_width * 2); etna_set_state(ctx, VIVS_PE_HDEPTH_CONTROL, VIVS_PE_HDEPTH_CONTROL_FORMAT_DISABLED); etna_set_state_f32(ctx, VIVS_PE_DEPTH_NORMALIZE, 65535.0); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_DEPTH); etna_set_state(ctx, VIVS_TS_DEPTH_CLEAR_VALUE, 0xffffffff); etna_set_state(ctx, VIVS_TS_DEPTH_STATUS_BASE, z_ts->address); etna_set_state(ctx, VIVS_TS_DEPTH_SURFACE_BASE, z->address); etna_set_state(ctx, VIVS_TS_MEM_CONFIG, VIVS_TS_MEM_CONFIG_DEPTH_FAST_CLEAR | VIVS_TS_MEM_CONFIG_COLOR_FAST_CLEAR | VIVS_TS_MEM_CONFIG_DEPTH_16BPP | VIVS_TS_MEM_CONFIG_DEPTH_COMPRESSION | ts_msaa_config); #ifdef EXTRA_DELAYS /* Warm up RS on aux render target (is this needed?) */ etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); etna_warm_up_rs(ctx, aux_rt->address, aux_rt_ts->address); etna_set_state(ctx, VIVS_TS_COLOR_STATUS_BASE, rt_ts_physical); etna_set_state(ctx, VIVS_TS_COLOR_SURFACE_BASE, rt_physical); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); etna_warm_up_rs(ctx, aux_rt_physical, aux_rt_ts_physical); etna_set_state(ctx, VIVS_TS_COLOR_STATUS_BASE, rt_ts_physical); etna_set_state(ctx, VIVS_TS_COLOR_SURFACE_BASE, rt_physical); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); etna_warm_up_rs(ctx, aux_rt_physical, aux_rt_ts_physical); etna_set_state(ctx, VIVS_TS_COLOR_STATUS_BASE, rt_ts_physical); etna_set_state(ctx, VIVS_TS_COLOR_SURFACE_BASE, rt_physical); #endif /* sync rasterizer to pixel engine after changes to PE config */ etna_stall(ctx, SYNC_RECIPIENT_RA, SYNC_RECIPIENT_PE); /* Set up the resolve to clear tile status for main render target and depth * Regard the TS as an image of width 16 with 4 bytes per pixel (64 bytes per row) * */ etna_set_state(ctx, VIVS_RS_CONFIG, VIVS_RS_CONFIG_SOURCE_FORMAT(RS_FORMAT_A8R8G8B8) | VIVS_RS_CONFIG_DEST_FORMAT(RS_FORMAT_A8R8G8B8) ); etna_set_state_multi(ctx, VIVS_RS_DITHER(0), 2, (uint32_t[]){0xffffffff, 0xffffffff}); etna_set_state(ctx, VIVS_RS_FILL_VALUE(0), 0x55555555); etna_set_state(ctx, VIVS_RS_CLEAR_CONTROL, VIVS_RS_CLEAR_CONTROL_MODE_ENABLED1 | (0xffff << VIVS_RS_CLEAR_CONTROL_BITS__SHIFT)); etna_set_state(ctx, VIVS_RS_EXTRA_CONFIG, 0); /* clear color ts */ etna_set_state(ctx, VIVS_RS_DEST_ADDR, rt_ts->address); etna_set_state(ctx, VIVS_RS_DEST_STRIDE, 0x40); etna_set_state(ctx, VIVS_RS_WINDOW_SIZE, ((rt_ts_size/0x40) << VIVS_RS_WINDOW_SIZE_HEIGHT__SHIFT) | (16 << VIVS_RS_WINDOW_SIZE_WIDTH__SHIFT)); etna_set_state(ctx, VIVS_RS_KICKER, 0xbeebbeeb); /* clear depth ts */ etna_set_state(ctx, VIVS_RS_DEST_ADDR, z_ts->address); etna_set_state(ctx, VIVS_RS_DEST_STRIDE, 0x40); etna_set_state(ctx, VIVS_RS_WINDOW_SIZE, ((z_ts_size/0x40) << VIVS_RS_WINDOW_SIZE_HEIGHT__SHIFT) | (16 << VIVS_RS_WINDOW_SIZE_WIDTH__SHIFT)); etna_set_state(ctx, VIVS_RS_KICKER, 0xbeebbeeb); /** Done */ etna_set_state(ctx, VIVS_TS_COLOR_CLEAR_VALUE, 0xff7f7f7f); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR); etna_set_state(ctx, VIVS_TS_COLOR_STATUS_BASE, rt_ts->address); etna_set_state(ctx, VIVS_TS_COLOR_SURFACE_BASE, rt->address); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); /* depth setup */ etna_set_state(ctx, VIVS_PE_DEPTH_CONFIG, ETNA_MASKED_BIT(VIVS_PE_DEPTH_CONFIG_WRITE_ENABLE, 1) & ETNA_MASKED(VIVS_PE_DEPTH_CONFIG_DEPTH_FUNC, COMPARE_FUNC_LESS) & ETNA_MASKED_INL(VIVS_PE_DEPTH_CONFIG_DEPTH_MODE, Z) & ETNA_MASKED_BIT(VIVS_PE_DEPTH_CONFIG_ONLY_DEPTH, 0)); etna_set_state_f32(ctx, VIVS_PE_DEPTH_NEAR, 0.0); etna_set_state_f32(ctx, VIVS_PE_DEPTH_FAR, 1.0); etna_set_state_f32(ctx, VIVS_PE_DEPTH_NORMALIZE, 65535.0); /* set up primitive assembly and setup engine */ etna_set_state_f32(ctx, VIVS_PA_VIEWPORT_OFFSET_Z, 0.0); etna_set_state_f32(ctx, VIVS_PA_VIEWPORT_SCALE_Z, 1.0); etna_set_state_fixp(ctx, VIVS_PA_VIEWPORT_OFFSET_X, width << 15); etna_set_state_fixp(ctx, VIVS_PA_VIEWPORT_OFFSET_Y, height << 15); etna_set_state_fixp(ctx, VIVS_PA_VIEWPORT_SCALE_X, width << 15); etna_set_state_fixp(ctx, VIVS_PA_VIEWPORT_SCALE_Y, height << 15); etna_set_state_fixp(ctx, VIVS_SE_SCISSOR_LEFT, 0); etna_set_state_fixp(ctx, VIVS_SE_SCISSOR_TOP, 0); etna_set_state_fixp(ctx, VIVS_SE_SCISSOR_RIGHT, (width << 16) | 5); etna_set_state_fixp(ctx, VIVS_SE_SCISSOR_BOTTOM, (height << 16) | 5); /* set up texture unit */ etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_TEXTURE); etna_set_state(ctx, VIVS_TE_SAMPLER_SIZE(0), VIVS_TE_SAMPLER_SIZE_WIDTH(512)|VIVS_TE_SAMPLER_SIZE_HEIGHT(512)); etna_set_state(ctx, VIVS_TE_SAMPLER_LOG_SIZE(0), VIVS_TE_SAMPLER_LOG_SIZE_WIDTH(9<<5) | VIVS_TE_SAMPLER_LOG_SIZE_HEIGHT(9<<5)); etna_set_state(ctx, VIVS_TE_SAMPLER_LOD_ADDR(0,0), tex->address); etna_set_state(ctx, VIVS_TE_SAMPLER_CONFIG0(0), VIVS_TE_SAMPLER_CONFIG0_TYPE(TEXTURE_TYPE_2D)| VIVS_TE_SAMPLER_CONFIG0_UWRAP(TEXTURE_WRAPMODE_CLAMP_TO_EDGE)| VIVS_TE_SAMPLER_CONFIG0_VWRAP(TEXTURE_WRAPMODE_CLAMP_TO_EDGE)| VIVS_TE_SAMPLER_CONFIG0_MIN(TEXTURE_FILTER_LINEAR)| VIVS_TE_SAMPLER_CONFIG0_MIP(TEXTURE_FILTER_NONE)| VIVS_TE_SAMPLER_CONFIG0_MAG(TEXTURE_FILTER_LINEAR)| VIVS_TE_SAMPLER_CONFIG0_FORMAT(TEXTURE_FORMAT_X8R8G8B8)); etna_set_state(ctx, VIVS_TE_SAMPLER_LOD_CONFIG(0), 0x00000000); /* TE.SAMPLER[0].LOD_CONFIG := 0x0 */ /* shader setup */ etna_set_state(ctx, VIVS_VS_END_PC, vs_size/16); etna_set_state_multi(ctx, VIVS_VS_INPUT_COUNT, 3, (uint32_t[]){ /* VIVS_VS_INPUT_COUNT */ VIVS_VS_INPUT_COUNT_UNK8(1) | VIVS_VS_INPUT_COUNT_COUNT(3), /* VIVS_VS_TEMP_REGISTER_CONTROL */ VIVS_VS_TEMP_REGISTER_CONTROL_NUM_TEMPS(6), /* VIVS_VS_OUTPUT(0) */ 0x10004}); etna_set_state(ctx, VIVS_VS_START_PC, 0x0); etna_set_state_f32(ctx, VIVS_VS_UNIFORMS(45), 0.5); /* u11.y */ etna_set_state_f32(ctx, VIVS_VS_UNIFORMS(44), 1.0); /* u11.x */ etna_set_state_f32(ctx, VIVS_VS_UNIFORMS(27), 0.0); /* u6.w */ etna_set_state_f32(ctx, VIVS_VS_UNIFORMS(23), 20.0); /* u5.w */ etna_set_state_f32(ctx, VIVS_VS_UNIFORMS(19), 2.0); /* u4.w */ /* Now load the shader itself */ etna_set_state_multi(ctx, VIVS_VS_INST_MEM(0), vs_size/4, vs); etna_set_state(ctx, VIVS_RA_CONTROL, 0x3); etna_set_state_f32(ctx, VIVS_PS_UNIFORMS(0), 1.0); /* u0.x */ etna_set_state_multi(ctx, VIVS_PS_END_PC, 2, (uint32_t[]){ /* VIVS_PS_END_PC */ ps_size/16, /* VIVS_PS_OUTPUT_REG */ 0x1}); etna_set_state(ctx, VIVS_PS_START_PC, 0x0); etna_set_state(ctx, VIVS_PA_ATTRIBUTE_ELEMENT_COUNT, 0x200); etna_set_state(ctx, VIVS_PA_SHADER_ATTRIBUTES(0), 0x200); etna_set_state(ctx, VIVS_PA_SHADER_ATTRIBUTES(1), 0x200); etna_set_state(ctx, VIVS_GL_VARYING_NUM_COMPONENTS, VIVS_GL_VARYING_NUM_COMPONENTS_VAR0(4)| /* position */ VIVS_GL_VARYING_NUM_COMPONENTS_VAR1(2) /* texture coordinate */ ); etna_set_state_multi(ctx, VIVS_GL_VARYING_COMPONENT_USE(0), 2, (uint32_t[]){ VIVS_GL_VARYING_COMPONENT_USE_COMP0(VARYING_COMPONENT_USE_USED) | VIVS_GL_VARYING_COMPONENT_USE_COMP1(VARYING_COMPONENT_USE_USED) | VIVS_GL_VARYING_COMPONENT_USE_COMP2(VARYING_COMPONENT_USE_USED) | VIVS_GL_VARYING_COMPONENT_USE_COMP3(VARYING_COMPONENT_USE_USED) | VIVS_GL_VARYING_COMPONENT_USE_COMP4(VARYING_COMPONENT_USE_USED) | VIVS_GL_VARYING_COMPONENT_USE_COMP5(VARYING_COMPONENT_USE_USED) , 0 }); etna_set_state_multi(ctx, VIVS_PS_INST_MEM(0), ps_size/4, ps); etna_set_state(ctx, VIVS_PS_INPUT_COUNT, VIVS_PS_INPUT_COUNT_UNK8(31)| VIVS_PS_INPUT_COUNT_COUNT(3 + extra_ps_inputs)); etna_set_state(ctx, VIVS_PS_TEMP_REGISTER_CONTROL, VIVS_PS_TEMP_REGISTER_CONTROL_NUM_TEMPS(3 + extra_ps_inputs)); etna_set_state(ctx, VIVS_PS_CONTROL, VIVS_PS_CONTROL_UNK1); etna_set_state(ctx, VIVS_GL_VARYING_TOTAL_COMPONENTS, VIVS_GL_VARYING_TOTAL_COMPONENTS_NUM(6)); /* 4+2=6 total varying components */ etna_set_state(ctx, VIVS_VS_LOAD_BALANCING, 0xf3f0542); /* depends on number of inputs/outputs/varyings? XXX how exactly */ etna_set_state(ctx, VIVS_VS_OUTPUT_COUNT, 3); etna_set_state(ctx, VIVS_PA_CONFIG, ETNA_MASKED_BIT(VIVS_PA_CONFIG_POINT_SIZE_ENABLE, 0)); /* Compute transform matrices in the same way as cube egl demo */ ESMatrix modelview; esMatrixLoadIdentity(&modelview); esTranslate(&modelview, 0.0f, 0.0f, -9.0f); esRotate(&modelview, 45.0f, 1.0f, 0.0f, 0.0f); esRotate(&modelview, 45.0f, 0.0f, 1.0f, 0.0f); esRotate(&modelview, frame*0.5f, 0.0f, 0.0f, 1.0f); esScale(&modelview, 0.475f, 0.475f, 0.475f); GLfloat aspect = (GLfloat)(height) / (GLfloat)(width); ESMatrix projection; esMatrixLoadIdentity(&projection); esFrustum(&projection, -2.8f, +2.8f, -2.8f * aspect, +2.8f * aspect, 6.0f, 10.0f); ESMatrix modelviewprojection; esMatrixLoadIdentity(&modelviewprojection); esMatrixMultiply(&modelviewprojection, &modelview, &projection); ESMatrix inverse, normal; /* compute inverse transpose normal transformation matrix */ esMatrixInverse3x3(&inverse, &modelview); esMatrixTranspose(&normal, &inverse); etna_set_state_multi(ctx, VIVS_VS_UNIFORMS(0), 16, (uint32_t*)&modelviewprojection.m[0][0]); etna_set_state_multi(ctx, VIVS_VS_UNIFORMS(16), 3, (uint32_t*)&normal.m[0][0]); /* u4.xyz */ etna_set_state_multi(ctx, VIVS_VS_UNIFORMS(20), 3, (uint32_t*)&normal.m[1][0]); /* u5.xyz */ etna_set_state_multi(ctx, VIVS_VS_UNIFORMS(24), 3, (uint32_t*)&normal.m[2][0]); /* u6.xyz */ etna_set_state_multi(ctx, VIVS_VS_UNIFORMS(28), 16, (uint32_t*)&modelview.m[0][0]); #ifdef INDEXED etna_set_state(ctx, VIVS_FE_INDEX_STREAM_BASE_ADDR, idx->address); etna_set_state(ctx, VIVS_FE_INDEX_STREAM_CONTROL, VIVS_FE_INDEX_STREAM_CONTROL_TYPE_UNSIGNED_SHORT); #endif etna_set_state(ctx, VIVS_FE_VERTEX_STREAM_BASE_ADDR, vtx->address); etna_set_state(ctx, VIVS_FE_VERTEX_STREAM_CONTROL, VIVS_FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE((3 + 3 + 2)*4)); etna_set_state(ctx, VIVS_FE_VERTEX_ELEMENT_CONFIG(0), VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_FLOAT | (ENDIAN_MODE_NO_SWAP << VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN__SHIFT) | VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM(0) | VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM_3 | VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_OFF | VIVS_FE_VERTEX_ELEMENT_CONFIG_START(0x0) | VIVS_FE_VERTEX_ELEMENT_CONFIG_END(0xc)); etna_set_state(ctx, VIVS_FE_VERTEX_ELEMENT_CONFIG(1), VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_FLOAT | (ENDIAN_MODE_NO_SWAP << VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN__SHIFT) | VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM(0) | VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM_3 | VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_OFF | VIVS_FE_VERTEX_ELEMENT_CONFIG_START(0xc) | VIVS_FE_VERTEX_ELEMENT_CONFIG_END(0x18)); etna_set_state(ctx, VIVS_FE_VERTEX_ELEMENT_CONFIG(2), VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_FLOAT | (ENDIAN_MODE_NO_SWAP << VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN__SHIFT) | VIVS_FE_VERTEX_ELEMENT_CONFIG_NONCONSECUTIVE | VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM(0) | VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM_2 | VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_OFF | VIVS_FE_VERTEX_ELEMENT_CONFIG_START(0x18) | VIVS_FE_VERTEX_ELEMENT_CONFIG_END(0x20)); etna_set_state(ctx, VIVS_VS_INPUT(0), 0x20100); etna_set_state(ctx, VIVS_PA_CONFIG, ETNA_MASKED_BIT(VIVS_PA_CONFIG_POINT_SPRITE_ENABLE, 0)); #ifdef INDEXED etna_draw_indexed_primitives(ctx, PRIMITIVE_TYPE_TRIANGLES, 0, COMPANION_TRIANGLE_COUNT, 0); #else etna_draw_primitives(ctx, PRIMITIVE_TYPE_TRIANGLES, 0, COMPANION_TRIANGLE_COUNT); #endif etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); #ifdef EXTRA_DELAYS etna_flush(ctx); #endif etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); etna_set_state(ctx, VIVS_RS_CONFIG, VIVS_RS_CONFIG_SOURCE_FORMAT(RS_FORMAT_A8R8G8B8) | VIVS_RS_CONFIG_SOURCE_TILED | VIVS_RS_CONFIG_DEST_FORMAT(RS_FORMAT_A8R8G8B8) | VIVS_RS_CONFIG_DEST_TILED); etna_set_state(ctx, VIVS_RS_SOURCE_STRIDE, (padded_width * 4 * 4) | VIVS_RS_SOURCE_STRIDE_TILING); etna_set_state(ctx, VIVS_RS_DEST_STRIDE, (padded_width * 4 * 4) | VIVS_RS_DEST_STRIDE_TILING); etna_set_state(ctx, VIVS_RS_DITHER(0), 0xffffffff); etna_set_state(ctx, VIVS_RS_DITHER(1), 0xffffffff); etna_set_state(ctx, VIVS_RS_CLEAR_CONTROL, VIVS_RS_CLEAR_CONTROL_MODE_DISABLED); etna_set_state(ctx, VIVS_RS_EXTRA_CONFIG, 0); etna_set_state(ctx, VIVS_RS_SOURCE_ADDR, rt->address); etna_set_state(ctx, VIVS_RS_DEST_ADDR, rt->address); etna_set_state(ctx, VIVS_RS_WINDOW_SIZE, VIVS_RS_WINDOW_SIZE_HEIGHT(padded_height) | VIVS_RS_WINDOW_SIZE_WIDTH(padded_width)); etna_set_state(ctx, VIVS_RS_KICKER, 0xbeebbeeb); #ifdef EXTRA_DELAYS etna_flush(ctx); etna_warm_up_rs(ctx, aux_rt->address, aux_rt_ts->address); #endif etna_set_state(ctx, VIVS_TS_COLOR_STATUS_BASE, rt_ts->address); etna_set_state(ctx, VIVS_TS_COLOR_SURFACE_BASE, rt->address); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR); etna_set_state(ctx, VIVS_TS_MEM_CONFIG, VIVS_TS_MEM_CONFIG_DEPTH_FAST_CLEAR | VIVS_TS_MEM_CONFIG_DEPTH_16BPP | VIVS_TS_MEM_CONFIG_DEPTH_COMPRESSION); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR); /* Wait for pixel engine to finish */ #ifdef EXTRA_DELAYS etna_finish(ctx); #else etna_stall(ctx, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); #endif /* Copy result to framebuffer */ etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); etna_set_state(ctx, VIVS_RS_CONFIG, VIVS_RS_CONFIG_SOURCE_FORMAT(RS_FORMAT_A8R8G8B8) | VIVS_RS_CONFIG_SOURCE_TILED | ((supersample_x>1)?VIVS_RS_CONFIG_DOWNSAMPLE_X:0) | ((supersample_y>1)?VIVS_RS_CONFIG_DOWNSAMPLE_Y:0) | VIVS_RS_CONFIG_DEST_FORMAT(RS_FORMAT_A8R8G8B8) | VIVS_RS_CONFIG_SWAP_RB); etna_set_state(ctx, VIVS_RS_SOURCE_STRIDE, (padded_width * 4 * 4) | VIVS_RS_SOURCE_STRIDE_TILING); etna_set_state(ctx, VIVS_RS_DEST_STRIDE, fb.fb_fix.line_length); etna_set_state(ctx, VIVS_RS_DITHER(0), 0xffffffff); etna_set_state(ctx, VIVS_RS_DITHER(1), 0xffffffff); etna_set_state(ctx, VIVS_RS_CLEAR_CONTROL, VIVS_RS_CLEAR_CONTROL_MODE_DISABLED); etna_set_state(ctx, VIVS_RS_EXTRA_CONFIG, 0); etna_set_state(ctx, VIVS_RS_SOURCE_ADDR, rt->address); etna_set_state(ctx, VIVS_RS_DEST_ADDR, fb.physical[backbuffer]); etna_set_state(ctx, VIVS_RS_WINDOW_SIZE, VIVS_RS_WINDOW_SIZE_HEIGHT(height * supersample_y) | VIVS_RS_WINDOW_SIZE_WIDTH(width * supersample_x)); etna_set_state(ctx, VIVS_RS_KICKER, 0xbeebbeeb); etna_finish(ctx); /* switch buffers */ fb_set_buffer(&fb, backbuffer); backbuffer = 1-backbuffer; } etna_free(ctx); viv_close(); return 0; }
int main(int argc, char **argv) { int rv; int width = 256; int height = 256; int padded_width = etna_align_up(width, 64); int padded_height = etna_align_up(height, 64); printf("padded_width %i padded_height %i\n", padded_width, padded_height); struct viv_conn *conn = 0; rv = viv_open(VIV_HW_3D, &conn); if(rv!=0) { fprintf(stderr, "Error opening device\n"); exit(1); } printf("Succesfully opened device\n"); struct etna_vidmem *rt = 0; /* main render target */ struct etna_vidmem *rt_ts = 0; /* tile status for main render target */ struct etna_vidmem *z = 0; /* depth for main render target */ struct etna_vidmem *z_ts = 0; /* depth ts for main render target */ struct etna_vidmem *vtx = 0; /* vertex buffer */ struct etna_vidmem *aux_rt = 0; /* auxilary render target */ struct etna_vidmem *aux_rt_ts = 0; /* tile status for auxilary render target */ struct etna_vidmem *bmp = 0; /* bitmap */ size_t rt_size = padded_width * padded_height * 4; size_t rt_ts_size = etna_align_up((padded_width * padded_height * 4)/0x100, 0x100); size_t z_size = padded_width * padded_height * 2; size_t z_ts_size = etna_align_up((padded_width * padded_height * 2)/0x100, 0x100); size_t bmp_size = width * height * 4; if(etna_vidmem_alloc_linear(conn, &rt, rt_size, VIV_SURF_RENDER_TARGET, VIV_POOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(conn, &rt_ts, rt_ts_size, VIV_SURF_TILE_STATUS, VIV_POOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(conn, &z, z_size, VIV_SURF_DEPTH, VIV_POOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(conn, &z_ts, z_ts_size, VIV_SURF_TILE_STATUS, VIV_POOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(conn, &vtx, VERTEX_BUFFER_SIZE, VIV_SURF_VERTEX, VIV_POOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(conn, &aux_rt, 0x4000, VIV_SURF_RENDER_TARGET, VIV_POOL_SYSTEM, true)!=ETNA_OK || etna_vidmem_alloc_linear(conn, &aux_rt_ts, 0x100, VIV_SURF_TILE_STATUS, VIV_POOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(conn, &bmp, bmp_size, VIV_SURF_BITMAP, VIV_POOL_DEFAULT, true)!=ETNA_OK ) { fprintf(stderr, "Error allocating video memory\n"); exit(1); } /* Phew, now we got all the memory we need. * Write interleaved attribute vertex stream. * Unlike the GL example we only do this once, not every time glDrawArrays is called, the same would be accomplished * from GL by using a vertex buffer object. */ for(int vert=0; vert<NUM_VERTICES; ++vert) { int dest_idx = vert * (3 + 2); for(int comp=0; comp<3; ++comp) ((float*)vtx->logical)[dest_idx+comp+0] = vVertices[vert*3 + comp]; /* 0 */ for(int comp=0; comp<2; ++comp) ((float*)vtx->logical)[dest_idx+comp+3] = vTexCoords[vert*2 + comp]; /* 1 */ } struct etna_ctx *ctx = 0; if(etna_create(conn, &ctx) != ETNA_OK) { printf("Unable to create context\n"); exit(1); } /* Now load the shader itself */ uint32_t vs[] = { 0x02001001, 0x2a800800, 0x00000000, 0x003fc008, 0x02001003, 0x2a800800, 0x00000040, 0x00000002, }; uint32_t vs_size = sizeof(vs); uint32_t *ps; uint32_t ps_size; if(argc < 2) { perror("provide shader on command line"); exit(1); } int fd = open(argv[1], O_RDONLY); if(fd == -1) { perror("opening shader"); exit(1); } ps_size = lseek(fd, 0, SEEK_END); ps = malloc(ps_size); lseek(fd, 0, SEEK_SET); if(ps_size == 0 || ps_size>8192 || read(fd, ps, ps_size) != ps_size) { perror("empty or unreadable shader"); exit(1); } close(fd); /* XXX how important is the ordering? I suppose we could group states (except the flushes, kickers, semaphores etc) * and simply submit them at once. Especially for consecutive states and masked stated this could be a big win * in DMA command buffer size. */ /* Build first command buffer */ etna_set_state(ctx, VIVS_GL_VERTEX_ELEMENT_CONFIG, 0x1); etna_set_state(ctx, VIVS_RA_CONTROL, 0x1); etna_set_state(ctx, VIVS_PA_W_CLIP_LIMIT, 0x34000001); etna_set_state(ctx, VIVS_PA_SYSTEM_MODE, 0x11); etna_set_state(ctx, VIVS_PA_CONFIG, ETNA_MASKED_BIT(VIVS_PA_CONFIG_UNK22, 0)); etna_set_state(ctx, VIVS_SE_CONFIG, 0x0); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR); /* Set up pixel engine */ etna_set_state(ctx, VIVS_PE_COLOR_FORMAT, ETNA_MASKED_BIT(VIVS_PE_COLOR_FORMAT_OVERWRITE, 0)); etna_set_state(ctx, VIVS_PE_ALPHA_CONFIG, ETNA_MASKED_BIT(VIVS_PE_ALPHA_CONFIG_BLEND_ENABLE_COLOR, 0) & ETNA_MASKED_BIT(VIVS_PE_ALPHA_CONFIG_BLEND_SEPARATE_ALPHA, 0) & ETNA_MASKED(VIVS_PE_ALPHA_CONFIG_SRC_FUNC_COLOR, BLEND_FUNC_ONE) & ETNA_MASKED(VIVS_PE_ALPHA_CONFIG_SRC_FUNC_ALPHA, BLEND_FUNC_ONE) & ETNA_MASKED(VIVS_PE_ALPHA_CONFIG_DST_FUNC_COLOR, BLEND_FUNC_ZERO) & ETNA_MASKED(VIVS_PE_ALPHA_CONFIG_DST_FUNC_ALPHA, BLEND_FUNC_ZERO) & ETNA_MASKED(VIVS_PE_ALPHA_CONFIG_EQ_COLOR, BLEND_EQ_ADD) & ETNA_MASKED(VIVS_PE_ALPHA_CONFIG_EQ_ALPHA, BLEND_EQ_ADD)); etna_set_state(ctx, VIVS_PE_ALPHA_BLEND_COLOR, VIVS_PE_ALPHA_BLEND_COLOR_B(0) | VIVS_PE_ALPHA_BLEND_COLOR_G(0) | VIVS_PE_ALPHA_BLEND_COLOR_R(0) | VIVS_PE_ALPHA_BLEND_COLOR_A(0)); etna_set_state(ctx, VIVS_PE_ALPHA_OP, ETNA_MASKED_BIT(VIVS_PE_ALPHA_OP_ALPHA_TEST, 0)); etna_set_state(ctx, VIVS_PA_CONFIG, ETNA_MASKED_INL(VIVS_PA_CONFIG_CULL_FACE_MODE, OFF)); etna_set_state(ctx, VIVS_PE_DEPTH_CONFIG, ETNA_MASKED_BIT(VIVS_PE_DEPTH_CONFIG_WRITE_ENABLE, 0)); etna_set_state(ctx, VIVS_PE_STENCIL_CONFIG, ETNA_MASKED(VIVS_PE_STENCIL_CONFIG_REF_FRONT, 0) & ETNA_MASKED(VIVS_PE_STENCIL_CONFIG_MASK_FRONT, 0xff) & ETNA_MASKED(VIVS_PE_STENCIL_CONFIG_WRITE_MASK, 0xff)); etna_set_state(ctx, VIVS_PE_STENCIL_OP, ETNA_MASKED(VIVS_PE_STENCIL_OP_FUNC_FRONT, COMPARE_FUNC_ALWAYS) & ETNA_MASKED(VIVS_PE_STENCIL_OP_FUNC_BACK, COMPARE_FUNC_ALWAYS) & ETNA_MASKED(VIVS_PE_STENCIL_OP_FAIL_FRONT, STENCIL_OP_KEEP) & ETNA_MASKED(VIVS_PE_STENCIL_OP_FAIL_BACK, STENCIL_OP_KEEP) & ETNA_MASKED(VIVS_PE_STENCIL_OP_DEPTH_FAIL_FRONT, STENCIL_OP_KEEP) & ETNA_MASKED(VIVS_PE_STENCIL_OP_DEPTH_FAIL_BACK, STENCIL_OP_KEEP) & ETNA_MASKED(VIVS_PE_STENCIL_OP_PASS_FRONT, STENCIL_OP_KEEP) & ETNA_MASKED(VIVS_PE_STENCIL_OP_PASS_BACK, STENCIL_OP_KEEP)); etna_set_state(ctx, VIVS_PE_DEPTH_CONFIG, ETNA_MASKED_BIT(VIVS_PE_DEPTH_CONFIG_EARLY_Z, 0)); etna_set_state(ctx, VIVS_PE_COLOR_FORMAT, ETNA_MASKED(VIVS_PE_COLOR_FORMAT_COMPONENTS, 0xf)); etna_set_state(ctx, VIVS_SE_DEPTH_SCALE, 0x0); etna_set_state(ctx, VIVS_SE_DEPTH_BIAS, 0x0); etna_set_state(ctx, VIVS_PA_CONFIG, ETNA_MASKED_INL(VIVS_PA_CONFIG_FILL_MODE, SOLID)); etna_set_state(ctx, VIVS_PA_CONFIG, ETNA_MASKED_INL(VIVS_PA_CONFIG_SHADE_MODEL, SMOOTH)); /* Set up render target */ etna_set_state(ctx, VIVS_PE_COLOR_FORMAT, ETNA_MASKED(VIVS_PE_COLOR_FORMAT_FORMAT, RS_FORMAT_A8R8G8B8) & ETNA_MASKED_BIT(VIVS_PE_COLOR_FORMAT_SUPER_TILED, 1)); for(int frame=0; frame<1; ++frame) { printf("*** FRAME %i ****\n", frame); etna_set_state(ctx, VIVS_PE_COLOR_ADDR, rt->address); /* ADDR_A */ etna_set_state(ctx, VIVS_PE_COLOR_STRIDE, padded_width * 4); etna_set_state(ctx, VIVS_GL_MULTI_SAMPLE_CONFIG, ETNA_MASKED_INL(VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES, NONE) & ETNA_MASKED(VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES, 0xf) & ETNA_MASKED(VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12, 0x0) & ETNA_MASKED(VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16, 0x0) ); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR); etna_set_state(ctx, VIVS_PE_COLOR_FORMAT, ETNA_MASKED_BIT(VIVS_PE_COLOR_FORMAT_OVERWRITE, 1)); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR); etna_set_state(ctx, VIVS_TS_COLOR_CLEAR_VALUE, 0); etna_set_state(ctx, VIVS_TS_COLOR_STATUS_BASE, rt_ts->address); /* ADDR_B */ etna_set_state(ctx, VIVS_TS_COLOR_SURFACE_BASE, rt->address); /* ADDR_A */ etna_set_state(ctx, VIVS_TS_MEM_CONFIG, VIVS_TS_MEM_CONFIG_COLOR_FAST_CLEAR); /* ADDR_A */ etna_set_state(ctx, VIVS_PE_DEPTH_CONFIG, ETNA_MASKED_INL(VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT, D16) & ETNA_MASKED_BIT(VIVS_PE_DEPTH_CONFIG_SUPER_TILED, 1) ); etna_set_state(ctx, VIVS_PE_DEPTH_ADDR, z->address); /* ADDR_C */ etna_set_state(ctx, VIVS_PE_DEPTH_STRIDE, padded_width * 2); etna_set_state(ctx, VIVS_PE_STENCIL_CONFIG, ETNA_MASKED_INL(VIVS_PE_STENCIL_CONFIG_MODE, DISABLED)); etna_set_state(ctx, VIVS_PE_HDEPTH_CONTROL, VIVS_PE_HDEPTH_CONTROL_FORMAT_DISABLED); etna_set_state_f32(ctx, VIVS_PE_DEPTH_NORMALIZE, 65535.0); etna_set_state(ctx, VIVS_PE_DEPTH_CONFIG, ETNA_MASKED_BIT(VIVS_PE_DEPTH_CONFIG_EARLY_Z, 0)); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_DEPTH); etna_set_state(ctx, VIVS_TS_DEPTH_CLEAR_VALUE, 0xffffffff); etna_set_state(ctx, VIVS_TS_DEPTH_STATUS_BASE, z_ts->address); /* ADDR_D */ etna_set_state(ctx, VIVS_TS_DEPTH_SURFACE_BASE, z->address); /* ADDR_C */ etna_set_state(ctx, VIVS_TS_MEM_CONFIG, VIVS_TS_MEM_CONFIG_DEPTH_FAST_CLEAR | VIVS_TS_MEM_CONFIG_COLOR_FAST_CLEAR | VIVS_TS_MEM_CONFIG_DEPTH_16BPP | VIVS_TS_MEM_CONFIG_DEPTH_COMPRESSION); etna_set_state(ctx, VIVS_PE_DEPTH_CONFIG, ETNA_MASKED_BIT(VIVS_PE_DEPTH_CONFIG_EARLY_Z, 1)); /* flip-flopping once again */ /* Warm up RS on aux render target */ etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); etna_warm_up_rs(ctx, aux_rt->address, aux_rt_ts->address); /* Phew, now that's one hell of a setup; the serious rendering starts now */ etna_set_state(ctx, VIVS_TS_COLOR_STATUS_BASE, rt_ts->address); /* ADDR_B */ etna_set_state(ctx, VIVS_TS_COLOR_SURFACE_BASE, rt->address); /* ADDR_A */ /* ... or so we thought */ etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); etna_warm_up_rs(ctx, aux_rt->address, aux_rt_ts->address); /* maybe now? */ etna_set_state(ctx, VIVS_TS_COLOR_STATUS_BASE, rt_ts->address); /* ADDR_B */ etna_set_state(ctx, VIVS_TS_COLOR_SURFACE_BASE, rt->address); /* ADDR_A */ etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); /* nope, not really... */ etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); etna_warm_up_rs(ctx, aux_rt->address, aux_rt_ts->address); etna_set_state(ctx, VIVS_TS_COLOR_STATUS_BASE, rt_ts->address); /* ADDR_B */ etna_set_state(ctx, VIVS_TS_COLOR_SURFACE_BASE, rt->address); /* ADDR_A */ etna_stall(ctx, SYNC_RECIPIENT_RA, SYNC_RECIPIENT_PE); /* Set up the resolve to clear tile status for main render target * What the blob does is regard the TS as an image of width N, height 4, with 4 bytes per pixel * Looks like the height always stays the same. I don't think it matters as long as the entire memory are is covered. * XXX need to clear the depth ts too. * */ etna_set_state(ctx, VIVS_RS_CONFIG, VIVS_RS_CONFIG_SOURCE_FORMAT(RS_FORMAT_A8R8G8B8) | VIVS_RS_CONFIG_DEST_FORMAT(RS_FORMAT_A8R8G8B8) ); etna_set_state_multi(ctx, VIVS_RS_DITHER(0), 2, (uint32_t[]){0xffffffff, 0xffffffff}); etna_set_state(ctx, VIVS_RS_DEST_ADDR, rt_ts->address); /* ADDR_B */ etna_set_state(ctx, VIVS_RS_DEST_STRIDE, 0x100); /* 0x100 iso 0x40! seems it uses a width of 256 if width divisible by 256, XXX need to figure out these rules */ etna_set_state(ctx, VIVS_RS_WINDOW_SIZE, VIVS_RS_WINDOW_SIZE_HEIGHT(rt_ts_size/0x100) | VIVS_RS_WINDOW_SIZE_WIDTH(64)); etna_set_state(ctx, VIVS_RS_FILL_VALUE(0), 0x55555555); etna_set_state(ctx, VIVS_RS_CLEAR_CONTROL, VIVS_RS_CLEAR_CONTROL_MODE_ENABLED1 | VIVS_RS_CLEAR_CONTROL_BITS(0xffff)); etna_set_state(ctx, VIVS_RS_EXTRA_CONFIG, 0); /* no AA, no endian switch */ etna_set_state(ctx, VIVS_RS_KICKER, 0xbeebbeeb); etna_set_state(ctx, VIVS_TS_COLOR_CLEAR_VALUE, 0xff7f7f7f); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR); etna_set_state(ctx, VIVS_TS_COLOR_CLEAR_VALUE, 0xff7f7f7f); etna_set_state(ctx, VIVS_TS_COLOR_STATUS_BASE, rt_ts->address); /* ADDR_B */ etna_set_state(ctx, VIVS_TS_COLOR_SURFACE_BASE, rt->address); /* ADDR_A */ etna_set_state(ctx, VIVS_TS_MEM_CONFIG, VIVS_TS_MEM_CONFIG_DEPTH_FAST_CLEAR | VIVS_TS_MEM_CONFIG_COLOR_FAST_CLEAR | VIVS_TS_MEM_CONFIG_DEPTH_16BPP | VIVS_TS_MEM_CONFIG_DEPTH_COMPRESSION); //etna_set_state(ctx, VIVS_PA_CONFIG, ETNA_MASKED_INL(VIVS_PA_CONFIG_CULL_FACE_MODE, CCW)); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); etna_set_state(ctx, VIVS_PE_DEPTH_CONFIG, ETNA_MASKED_BIT(VIVS_PE_DEPTH_CONFIG_WRITE_ENABLE, 0)); etna_set_state(ctx, VIVS_PE_DEPTH_CONFIG, ETNA_MASKED_INL(VIVS_PE_DEPTH_CONFIG_DEPTH_MODE, NONE)); etna_set_state(ctx, VIVS_PE_DEPTH_CONFIG, ETNA_MASKED_BIT(VIVS_PE_DEPTH_CONFIG_WRITE_ENABLE, 0)); etna_set_state(ctx, VIVS_PE_DEPTH_CONFIG, ETNA_MASKED(VIVS_PE_DEPTH_CONFIG_DEPTH_FUNC, COMPARE_FUNC_ALWAYS)); etna_set_state(ctx, VIVS_PE_DEPTH_CONFIG, ETNA_MASKED_INL(VIVS_PE_DEPTH_CONFIG_DEPTH_MODE, Z)); etna_set_state_f32(ctx, VIVS_PE_DEPTH_NEAR, 0.0); etna_set_state_f32(ctx, VIVS_PE_DEPTH_FAR, 1.0); etna_set_state_f32(ctx, VIVS_PE_DEPTH_NORMALIZE, 65535.0); /* set up primitive assembly */ etna_set_state_f32(ctx, VIVS_PA_VIEWPORT_OFFSET_Z, 0.0); etna_set_state_f32(ctx, VIVS_PA_VIEWPORT_SCALE_Z, 1.0); etna_set_state(ctx, VIVS_PE_DEPTH_CONFIG, ETNA_MASKED_BIT(VIVS_PE_DEPTH_CONFIG_ONLY_DEPTH, 0)); etna_set_state_fixp(ctx, VIVS_PA_VIEWPORT_OFFSET_X, width << 15); etna_set_state_fixp(ctx, VIVS_PA_VIEWPORT_OFFSET_Y, height << 15); etna_set_state_fixp(ctx, VIVS_PA_VIEWPORT_SCALE_X, width << 15); etna_set_state_fixp(ctx, VIVS_PA_VIEWPORT_SCALE_Y, height << 15); etna_set_state_fixp(ctx, VIVS_SE_SCISSOR_LEFT, 0); etna_set_state_fixp(ctx, VIVS_SE_SCISSOR_TOP, 0); etna_set_state_fixp(ctx, VIVS_SE_SCISSOR_RIGHT, (width << 16) | 5); etna_set_state_fixp(ctx, VIVS_SE_SCISSOR_BOTTOM, (height << 16) | 5); /* shader setup */ etna_set_state(ctx, VIVS_VS_END_PC, vs_size/16); etna_set_state_multi(ctx, VIVS_VS_INPUT_COUNT, 3, (uint32_t[]){ /* VIVS_VS_INPUT_COUNT */ (1<<8) | 2, /* VIVS_VS_TEMP_REGISTER_CONTROL */ VIVS_VS_TEMP_REGISTER_CONTROL_NUM_TEMPS(2), /* VIVS_VS_OUTPUT(0) */ 0x100}); etna_set_state(ctx, VIVS_VS_START_PC, 0x0); etna_set_state_f32(ctx, VIVS_VS_UNIFORMS(0), 0.5); /* u0.x */ etna_set_state_multi(ctx, VIVS_VS_INST_MEM(0), vs_size/4, vs); etna_set_state(ctx, VIVS_RA_CONTROL, 0x3); /* huh, this is 1 for the cubes */ etna_set_state_multi(ctx, VIVS_PS_END_PC, 2, (uint32_t[]){ /* VIVS_PS_END_PC */ ps_size/16, /* VIVS_PS_OUTPUT_REG */ 0x1}); etna_set_state(ctx, VIVS_PS_START_PC, 0x0); etna_set_state(ctx, VIVS_PA_SHADER_ATTRIBUTES(0), 0x200); etna_set_state(ctx, VIVS_GL_VARYING_NUM_COMPONENTS, /* one varying, with two components */ VIVS_GL_VARYING_NUM_COMPONENTS_VAR0(2) ); etna_set_state_multi(ctx, VIVS_GL_VARYING_COMPONENT_USE(0), 2, (uint32_t[]){ /* one varying, with four components */ VIVS_GL_VARYING_COMPONENT_USE_COMP0(VARYING_COMPONENT_USE_USED) | VIVS_GL_VARYING_COMPONENT_USE_COMP1(VARYING_COMPONENT_USE_USED) | VIVS_GL_VARYING_COMPONENT_USE_COMP2(VARYING_COMPONENT_USE_UNUSED) | VIVS_GL_VARYING_COMPONENT_USE_COMP3(VARYING_COMPONENT_USE_UNUSED) , 0 }); etna_set_state_f32(ctx, VIVS_PS_UNIFORMS(0), 0.0); /* u0.x */ etna_set_state_f32(ctx, VIVS_PS_UNIFORMS(1), 1.0); /* u0.y */ etna_set_state_f32(ctx, VIVS_PS_UNIFORMS(2), 0.5); /* u0.z */ etna_set_state_f32(ctx, VIVS_PS_UNIFORMS(3), 2.0); /* u0.w */ etna_set_state_f32(ctx, VIVS_PS_UNIFORMS(4), 1/256.0); /* u1.x */ etna_set_state_f32(ctx, VIVS_PS_UNIFORMS(5), 16.0); /* u1.y */ etna_set_state_f32(ctx, VIVS_PS_UNIFORMS(6), 10.0); /* u1.z */ etna_set_state_f32(ctx, VIVS_PS_UNIFORMS(8), frame); /* u2.x */ etna_set_state_multi(ctx, VIVS_PS_INST_MEM(0), ps_size/4, ps); etna_set_state(ctx, VIVS_PS_INPUT_COUNT, (31<<8)|2); etna_set_state(ctx, VIVS_PS_TEMP_REGISTER_CONTROL, VIVS_PS_TEMP_REGISTER_CONTROL_NUM_TEMPS(4)); etna_set_state(ctx, VIVS_PS_CONTROL, VIVS_PS_CONTROL_UNK1 ); etna_set_state(ctx, VIVS_PA_ATTRIBUTE_ELEMENT_COUNT, 0x100); etna_set_state(ctx, VIVS_GL_VARYING_TOTAL_COMPONENTS, /* one varying, with two components, must be changed together with GL_VARYING_NUM_COMPONENTS */ VIVS_GL_VARYING_TOTAL_COMPONENTS_NUM(2) ); etna_set_state(ctx, VIVS_VS_LOAD_BALANCING, 0xf3f0582); etna_set_state(ctx, VIVS_VS_OUTPUT_COUNT, 2); etna_set_state(ctx, VIVS_PA_CONFIG, ETNA_MASKED_BIT(VIVS_PA_CONFIG_POINT_SIZE_ENABLE, 0)); etna_set_state(ctx, VIVS_FE_VERTEX_STREAM_BASE_ADDR, vtx->address); /* ADDR_E */ etna_set_state(ctx, VIVS_FE_VERTEX_STREAM_CONTROL, VIVS_FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE(0x14)); etna_set_state(ctx, VIVS_FE_VERTEX_ELEMENT_CONFIG(0), VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_FLOAT | VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN(ENDIAN_MODE_NO_SWAP) | VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM(0) | VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM(3) | VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_OFF | VIVS_FE_VERTEX_ELEMENT_CONFIG_START(0x0) | VIVS_FE_VERTEX_ELEMENT_CONFIG_END(0xc)); etna_set_state(ctx, VIVS_FE_VERTEX_ELEMENT_CONFIG(1), VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_FLOAT | VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN(ENDIAN_MODE_NO_SWAP) | VIVS_FE_VERTEX_ELEMENT_CONFIG_NONCONSECUTIVE | VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM(0) | VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM(2) | VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_OFF | VIVS_FE_VERTEX_ELEMENT_CONFIG_START(0xc) | VIVS_FE_VERTEX_ELEMENT_CONFIG_END(0x14)); etna_set_state(ctx, VIVS_VS_INPUT(0), 0x00100); /* 0x20000 in etna_cube */ etna_set_state(ctx, VIVS_PA_CONFIG, ETNA_MASKED_BIT(VIVS_PA_CONFIG_POINT_SPRITE_ENABLE, 0)); etna_draw_primitives(ctx, PRIMITIVE_TYPE_TRIANGLE_STRIP, 0, 2); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); /* Submit first command buffer */ etna_flush(ctx); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); etna_set_state(ctx, VIVS_RS_CONFIG, VIVS_RS_CONFIG_SOURCE_FORMAT(RS_FORMAT_A8R8G8B8) | VIVS_RS_CONFIG_SOURCE_TILED | VIVS_RS_CONFIG_DEST_FORMAT(RS_FORMAT_A8R8G8B8) | VIVS_RS_CONFIG_DEST_TILED); etna_set_state(ctx, VIVS_RS_SOURCE_STRIDE, (padded_width * 4 * 4) | VIVS_RS_SOURCE_STRIDE_TILING); etna_set_state(ctx, VIVS_RS_DEST_STRIDE, (padded_width * 4 * 4) | VIVS_RS_DEST_STRIDE_TILING); etna_set_state(ctx, VIVS_RS_DITHER(0), 0xffffffff); etna_set_state(ctx, VIVS_RS_DITHER(1), 0xffffffff); etna_set_state(ctx, VIVS_RS_CLEAR_CONTROL, VIVS_RS_CLEAR_CONTROL_MODE_DISABLED); etna_set_state(ctx, VIVS_RS_EXTRA_CONFIG, 0); /* no AA, no endian switch */ etna_set_state(ctx, VIVS_RS_SOURCE_ADDR, rt->address); /* ADDR_A */ etna_set_state(ctx, VIVS_RS_DEST_ADDR, rt->address); /* ADDR_A */ etna_set_state(ctx, VIVS_RS_WINDOW_SIZE, VIVS_RS_WINDOW_SIZE_HEIGHT(padded_height) | VIVS_RS_WINDOW_SIZE_WIDTH(padded_width)); etna_set_state(ctx, VIVS_RS_KICKER, 0xbeebbeeb); /* Submit second command buffer */ etna_flush(ctx); etna_warm_up_rs(ctx, aux_rt->address, aux_rt_ts->address); etna_set_state(ctx, VIVS_TS_COLOR_STATUS_BASE, rt_ts->address); /* ADDR_B */ etna_set_state(ctx, VIVS_TS_COLOR_SURFACE_BASE, rt->address); /* ADDR_A */ etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR); etna_set_state(ctx, VIVS_TS_MEM_CONFIG, VIVS_TS_MEM_CONFIG_DEPTH_FAST_CLEAR | VIVS_TS_MEM_CONFIG_DEPTH_16BPP | VIVS_TS_MEM_CONFIG_DEPTH_COMPRESSION); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR); etna_set_state(ctx, VIVS_PE_COLOR_FORMAT, ETNA_MASKED_BIT(VIVS_PE_COLOR_FORMAT_OVERWRITE, 0)); /* Submit third command buffer, wait for pixel engine to finish */ etna_finish(ctx); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); etna_set_state(ctx, VIVS_RS_CONFIG, VIVS_RS_CONFIG_SOURCE_FORMAT(RS_FORMAT_A8R8G8B8) | VIVS_RS_CONFIG_SOURCE_TILED | VIVS_RS_CONFIG_DEST_FORMAT(RS_FORMAT_A8R8G8B8) /*| VIVS_RS_CONFIG_SWAP_RB*/); etna_set_state(ctx, VIVS_RS_SOURCE_STRIDE, (padded_width * 4 * 4) | VIVS_RS_SOURCE_STRIDE_TILING); etna_set_state(ctx, VIVS_RS_DEST_STRIDE, width * 4); etna_set_state(ctx, VIVS_RS_DITHER(0), 0xffffffff); etna_set_state(ctx, VIVS_RS_DITHER(1), 0xffffffff); etna_set_state(ctx, VIVS_RS_CLEAR_CONTROL, VIVS_RS_CLEAR_CONTROL_MODE_DISABLED); etna_set_state(ctx, VIVS_RS_EXTRA_CONFIG, 0); /* no AA, no endian switch */ etna_set_state(ctx, VIVS_RS_SOURCE_ADDR, rt->address); /* ADDR_A */ etna_set_state(ctx, VIVS_RS_DEST_ADDR, bmp->address); /* ADDR_J */ etna_set_state(ctx, VIVS_RS_WINDOW_SIZE, VIVS_RS_WINDOW_SIZE_HEIGHT(height) | VIVS_RS_WINDOW_SIZE_WIDTH(width)); etna_set_state(ctx, VIVS_RS_KICKER, 0xbeebbeeb); etna_finish(ctx); } if(argc>2) { printf("Dumping image to %s\n", argv[2]); bmp_dump32(bmp->logical, width, height, true, argv[2]); } /* 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; int padded_width, padded_height; int backbuffer = 0; struct fb_info fb; rv = fb_open(0, &fb); if(rv!=0) { exit(1); } width = fb.fb_var.xres; height = fb.fb_var.yres; padded_width = etna_align_up(width, 64); padded_height = etna_align_up(height, 64); printf("padded_width %i padded_height %i\n", padded_width, padded_height); struct viv_conn *conn = 0; rv = viv_open(VIV_HW_3D, &conn); if(rv!=0) { fprintf(stderr, "Error opening device\n"); exit(1); } printf("Succesfully opened device\n"); struct etna_vidmem *rt = 0; /* main render target */ struct etna_vidmem *rt_ts = 0; /* tile status for main render target */ struct etna_vidmem *z = 0; /* depth for main render target */ struct etna_vidmem *z_ts = 0; /* depth ts for main render target */ struct etna_vidmem *aux_rt = 0; /* auxilary render target */ struct etna_vidmem *aux_rt_ts = 0; /* tile status for auxilary render target */ size_t rt_size = padded_width * padded_height * 4; size_t rt_ts_size = etna_align_up((padded_width * padded_height * 4)/0x100, 0x100); size_t z_size = padded_width * padded_height * 2; size_t z_ts_size = etna_align_up((padded_width * padded_height * 2)/0x100, 0x100); if(etna_vidmem_alloc_linear(conn, &rt, rt_size, gcvSURF_RENDER_TARGET, gcvPOOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(conn, &rt_ts, rt_ts_size, gcvSURF_TILE_STATUS, gcvPOOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(conn, &z, z_size, gcvSURF_DEPTH, gcvPOOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(conn, &z_ts, z_ts_size, gcvSURF_TILE_STATUS, gcvPOOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(conn, &aux_rt, 0x4000, gcvSURF_RENDER_TARGET, gcvPOOL_SYSTEM, true)!=ETNA_OK || etna_vidmem_alloc_linear(conn, &aux_rt_ts, 0x100, gcvSURF_TILE_STATUS, gcvPOOL_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); } memset(rt_ts->logical, 0x55, rt_ts->size); // Pattern: cleared //memset(rt_ts->logical, 0xAA, rt_ts->size); // Pattern: weird pattern fill //memset(rt_ts->logical, 0x00, rt_ts->size); // Pattern: filled in (nothing to do) //memset(rt_ts->logical, 0xFF, rt_ts->size); // Pattern: weird pattern fill uint32_t pixelfmt = RS_FORMAT_X8R8G8B8; bool supertiled = true; bool tiled = true; uint32_t stride = 0; if(tiled) { stride = (padded_width * 4 * 4) | (supertiled?VIVS_RS_DEST_STRIDE_TILING:0); } else { stride = (padded_width * 4) | (supertiled?VIVS_RS_DEST_STRIDE_TILING:0); } for(int frame=0; frame<1; ++frame) { if(frame%50 == 0) printf("*** FRAME %i ****\n", frame); /* XXX part of this can be put outside the loop, but until we have usable context management * this is safest. */ etna_set_state(ctx, VIVS_GL_VERTEX_ELEMENT_CONFIG, 0x1); etna_set_state(ctx, VIVS_RA_CONTROL, 0x1); etna_set_state(ctx, VIVS_PA_W_CLIP_LIMIT, 0x34000001); etna_set_state(ctx, VIVS_PA_SYSTEM_MODE, 0x11); etna_set_state(ctx, VIVS_PA_CONFIG, ETNA_MASKED_BIT(VIVS_PA_CONFIG_UNK22, 0)); etna_set_state(ctx, VIVS_SE_CONFIG, 0x0); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR); /* Does this affect the RS? It appears not. */ etna_set_state(ctx, VIVS_GL_MULTI_SAMPLE_CONFIG, ETNA_MASKED_INL(VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES, 4X) & ETNA_MASKED(VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES, 0xf) & ETNA_MASKED(VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12, 0x0) & ETNA_MASKED(VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16, 0x0) ); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); /* Set up resolve to self */ etna_set_state(ctx, VIVS_TS_COLOR_CLEAR_VALUE, 0xff7f7f7f); etna_set_state(ctx, VIVS_TS_COLOR_STATUS_BASE, rt_ts->address); /* ADDR_B */ etna_set_state(ctx, VIVS_TS_COLOR_SURFACE_BASE, rt->address); /* ADDR_A */ #if 0 /* don't care about depth, for now */ etna_set_state(ctx, VIVS_TS_DEPTH_CLEAR_VALUE, 0xffffffff); etna_set_state(ctx, VIVS_TS_DEPTH_STATUS_BASE, z_ts->address); /* ADDR_D */ etna_set_state(ctx, VIVS_TS_DEPTH_SURFACE_BASE, z->address); /* ADDR_C */ #endif etna_set_state(ctx, VIVS_TS_MEM_CONFIG, VIVS_TS_MEM_CONFIG_COLOR_FAST_CLEAR /*VIVS_TS_MEM_CONFIG_DEPTH_FAST_CLEAR | VIVS_TS_MEM_CONFIG_DEPTH_16BPP | VIVS_TS_MEM_CONFIG_DEPTH_COMPRESSION*/); etna_set_state(ctx, VIVS_RS_CONFIG, VIVS_RS_CONFIG_SOURCE_FORMAT(pixelfmt) | (tiled?VIVS_RS_CONFIG_SOURCE_TILED:0) | VIVS_RS_CONFIG_DEST_FORMAT(pixelfmt) | (tiled?VIVS_RS_CONFIG_DEST_TILED:0)); etna_set_state(ctx, VIVS_RS_SOURCE_STRIDE, stride); etna_set_state(ctx, VIVS_RS_DEST_STRIDE, stride); etna_set_state(ctx, VIVS_RS_DITHER(0), 0xffffffff); etna_set_state(ctx, VIVS_RS_DITHER(1), 0xffffffff); etna_set_state(ctx, VIVS_RS_CLEAR_CONTROL, VIVS_RS_CLEAR_CONTROL_MODE_DISABLED); etna_set_state(ctx, VIVS_RS_EXTRA_CONFIG, 0); /* no AA, no endian switch */ etna_set_state(ctx, VIVS_RS_SOURCE_ADDR, rt->address); /* ADDR_A */ etna_set_state(ctx, VIVS_RS_DEST_ADDR, rt->address); /* ADDR_A */ etna_set_state(ctx, VIVS_RS_WINDOW_SIZE, VIVS_RS_WINDOW_SIZE_HEIGHT(padded_height) | VIVS_RS_WINDOW_SIZE_WIDTH(padded_width)); etna_set_state(ctx, VIVS_RS_KICKER, 0xbeebbeeb); etna_set_state(ctx, VIVS_TS_FLUSH_CACHE, VIVS_TS_FLUSH_CACHE_FLUSH | VIVS_GL_FLUSH_CACHE_COLOR); /* Clear part using normal (not fast) clear */ etna_set_state(ctx, VIVS_TS_MEM_CONFIG, 0); etna_set_state_multi(ctx, VIVS_RS_DITHER(0), 2, (uint32_t[]){0xffffffff, 0xffffffff}); etna_set_state(ctx, VIVS_RS_WINDOW_SIZE, VIVS_RS_WINDOW_SIZE_HEIGHT(0x100) | VIVS_RS_WINDOW_SIZE_WIDTH(0x100)); etna_set_state(ctx, VIVS_RS_FILL_VALUE(0), 0xffff0000); etna_set_state(ctx, VIVS_RS_FILL_VALUE(1), 0xff00ff00); etna_set_state(ctx, VIVS_RS_FILL_VALUE(2), 0xff0000ff); etna_set_state(ctx, VIVS_RS_FILL_VALUE(3), 0xffff00ff); etna_set_state(ctx, VIVS_RS_SOURCE_ADDR, 0); /* fill disregards source anyway */ etna_set_state(ctx, VIVS_RS_DEST_ADDR, rt->address + 64*64*4); /* Offset one entire 64*64 tile. Interesting things happen if only a partial tile is offset. */ /* Pure FILL_VALUE(0) */ //etna_set_state(ctx, VIVS_RS_CLEAR_CONTROL, VIVS_RS_CLEAR_CONTROL_MODE_ENABLED1 | VIVS_RS_CLEAR_CONTROL_BITS(0xffff)); /* Vertical line pattern */ etna_set_state(ctx, VIVS_RS_CLEAR_CONTROL, VIVS_RS_CLEAR_CONTROL_MODE_ENABLED4 | VIVS_RS_CLEAR_CONTROL_BITS(0xffff)); /* Same as ENABLED2 */ //etna_set_state(ctx, VIVS_RS_CLEAR_CONTROL, VIVS_RS_CLEAR_CONTROL_MODE_ENABLED4_2 | VIVS_RS_CLEAR_CONTROL_BITS(0xffff)); etna_set_state(ctx, VIVS_RS_EXTRA_CONFIG, 0); etna_set_state(ctx, VIVS_RS_KICKER, 0xbeebbeeb); etna_finish(ctx); #if 0 /* manually fill, to figure out tiling pattern */ for(int x=0; x<16384/4; ++x) { int a = (x & 0x3F) << 2; int b = ((x >> 3) & 0x3F) << 2; int c = ((x >> 6) & 0x3F) << 2; ((uint32_t*)(rt->logical + 16384*6))[x] = (a & 0xFF) | ((b & 0xFF) << 8) | ((c & 0xFF) << 16); printf("%08x\n", (a & 0xFF) | ((b & 0xFF) << 8) | ((c & 0xFF) << 16)); } #endif /* Copy image to screen */ etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); etna_set_state(ctx, VIVS_TS_MEM_CONFIG, 0); etna_set_state(ctx, VIVS_RS_CONFIG, VIVS_RS_CONFIG_SOURCE_FORMAT(pixelfmt) | (tiled?VIVS_RS_CONFIG_SOURCE_TILED:0) | VIVS_RS_CONFIG_DEST_FORMAT(RS_FORMAT_X8R8G8B8) | VIVS_RS_CONFIG_SWAP_RB); etna_set_state(ctx, VIVS_RS_SOURCE_STRIDE, stride); etna_set_state(ctx, VIVS_RS_DEST_STRIDE, fb.fb_fix.line_length); etna_set_state(ctx, VIVS_RS_DITHER(0), 0xffffffff); etna_set_state(ctx, VIVS_RS_DITHER(1), 0xffffffff); etna_set_state(ctx, VIVS_RS_CLEAR_CONTROL, VIVS_RS_CLEAR_CONTROL_MODE_DISABLED); etna_set_state(ctx, VIVS_RS_EXTRA_CONFIG, 0); /* no AA, no endian switch */ etna_set_state(ctx, VIVS_RS_SOURCE_ADDR, rt->address); /* ADDR_A */ etna_set_state(ctx, VIVS_RS_DEST_ADDR, fb.physical[backbuffer]); /* ADDR_J */ etna_set_state(ctx, VIVS_RS_WINDOW_SIZE, VIVS_RS_WINDOW_SIZE_HEIGHT(height) | VIVS_RS_WINDOW_SIZE_WIDTH(width)); etna_set_state(ctx, VIVS_RS_KICKER, 0xbeebbeeb); etna_finish(ctx); /* switch buffers */ fb_set_buffer(&fb, backbuffer); backbuffer = 1-backbuffer; } #ifdef DUMP bmp_dump32(fb.logical[1-backbuffer], width, height, false, "/mnt/sdcard/fb.bmp"); printf("Dump complete\n"); #endif etna_free(ctx); viv_close(conn); return 0; }
int main(int argc, char **argv) { int rv; int width = 256; int height = 256; int padded_width = etna_align_up(width, 64); int padded_height = etna_align_up(height, 64); printf("padded_width %i padded_height %i\n", padded_width, padded_height); rv = viv_open(); if(rv!=0) { fprintf(stderr, "Error opening device\n"); exit(1); } printf("Succesfully opened device\n"); bool supertiled = VIV_FEATURE(chipMinorFeatures0,SUPER_TILED); unsigned bits_per_tile = VIV_FEATURE(chipMinorFeatures0,2BITPERTILE)?2:4; printf("Supertile: %i, bits per tile: %i\n", supertiled, bits_per_tile); etna_vidmem *rt = 0; /* main render target */ etna_vidmem *rt_ts = 0; /* tile status for main render target */ etna_vidmem *z = 0; /* depth for main render target */ etna_vidmem *z_ts = 0; /* depth ts for main render target */ etna_vidmem *vtx = 0; /* vertex buffer */ etna_vidmem *aux_rt = 0; /* auxilary render target */ etna_vidmem *aux_rt_ts = 0; /* tile status for auxilary render target */ etna_vidmem *bmp = 0; /* bitmap */ size_t rt_size = padded_width * padded_height * 4; size_t rt_ts_size = etna_align_up((padded_width * padded_height * 4)*bits_per_tile/0x80, 0x100); size_t z_size = padded_width * padded_height * 2; size_t z_ts_size = etna_align_up((padded_width * padded_height * 2)*bits_per_tile/0x80, 0x100); size_t bmp_size = width * height * 4; if(etna_vidmem_alloc_linear(&rt, rt_size, gcvSURF_RENDER_TARGET, gcvPOOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(&rt_ts, rt_ts_size, gcvSURF_TILE_STATUS, gcvPOOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(&z, z_size, gcvSURF_DEPTH, gcvPOOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(&z_ts, z_ts_size, gcvSURF_TILE_STATUS, gcvPOOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(&vtx, VERTEX_BUFFER_SIZE, gcvSURF_VERTEX, gcvPOOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(&aux_rt, 0x4000, gcvSURF_RENDER_TARGET, gcvPOOL_SYSTEM, true)!=ETNA_OK || etna_vidmem_alloc_linear(&aux_rt_ts, 0x80*bits_per_tile, gcvSURF_TILE_STATUS, gcvPOOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(&bmp, bmp_size, gcvSURF_BITMAP, gcvPOOL_DEFAULT, true)!=ETNA_OK ) { fprintf(stderr, "Error allocating video memory\n"); exit(1); } /* Phew, now we got all the memory we need. * Write interleaved attribute vertex stream. * Unlike the GL example we only do this once, not every time glDrawArrays is called, the same would be accomplished * from GL by using a vertex buffer object. */ for(int vert=0; vert<NUM_VERTICES; ++vert) { int src_idx = vert * COMPONENTS_PER_VERTEX; int dest_idx = vert * COMPONENTS_PER_VERTEX * 3; for(int comp=0; comp<COMPONENTS_PER_VERTEX; ++comp) { ((float*)vtx->logical)[dest_idx+comp+0] = vVertices[src_idx + comp]; /* 0 */ ((float*)vtx->logical)[dest_idx+comp+3] = vNormals[src_idx + comp]; /* 1 */ ((float*)vtx->logical)[dest_idx+comp+6] = vColors[src_idx + comp]; /* 2 */ } } etna_ctx *ctx = 0; if(etna_create(&ctx) != ETNA_OK) { printf("Unable to create context\n"); exit(1); } /* XXX how important is the ordering? I suppose we could group states (except the flushes, kickers, semaphores etc) * and simply submit them at once. Especially for consecutive states and masked stated this could be a big win * in DMA command buffer size. */ for(int frame=0; frame<1; ++frame) { printf("*** FRAME %i ****\n", frame); /* XXX part of this can be put outside the loop, but until we have usable context management * this is safest. */ etna_set_state(ctx, VIVS_GL_VERTEX_ELEMENT_CONFIG, 0x1); etna_set_state(ctx, VIVS_RA_CONTROL, 0x1); etna_set_state(ctx, VIVS_PA_W_CLIP_LIMIT, 0x34000001); etna_set_state(ctx, VIVS_PA_SYSTEM_MODE, 0x11); etna_set_state(ctx, VIVS_PA_CONFIG, ETNA_MASKED_BIT(VIVS_PA_CONFIG_UNK22, 0)); etna_set_state(ctx, VIVS_SE_CONFIG, 0x0); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR); etna_set_state(ctx, VIVS_PE_COLOR_FORMAT, ETNA_MASKED_BIT(VIVS_PE_COLOR_FORMAT_PARTIAL, 0)); etna_set_state(ctx, VIVS_PE_ALPHA_CONFIG, ETNA_MASKED_BIT(VIVS_PE_ALPHA_CONFIG_BLEND_ENABLE_COLOR, 0) & ETNA_MASKED_BIT(VIVS_PE_ALPHA_CONFIG_BLEND_ENABLE_ALPHA, 0) & ETNA_MASKED(VIVS_PE_ALPHA_CONFIG_SRC_FUNC_COLOR, BLEND_FUNC_ONE) & ETNA_MASKED(VIVS_PE_ALPHA_CONFIG_SRC_FUNC_ALPHA, BLEND_FUNC_ONE) & ETNA_MASKED(VIVS_PE_ALPHA_CONFIG_DST_FUNC_COLOR, BLEND_FUNC_ZERO) & ETNA_MASKED(VIVS_PE_ALPHA_CONFIG_DST_FUNC_ALPHA, BLEND_FUNC_ZERO) & ETNA_MASKED(VIVS_PE_ALPHA_CONFIG_EQ_COLOR, BLEND_EQ_ADD) & ETNA_MASKED(VIVS_PE_ALPHA_CONFIG_EQ_ALPHA, BLEND_EQ_ADD)); etna_set_state(ctx, VIVS_PE_ALPHA_BLEND_COLOR, VIVS_PE_ALPHA_BLEND_COLOR_B(0) | VIVS_PE_ALPHA_BLEND_COLOR_G(0) | VIVS_PE_ALPHA_BLEND_COLOR_R(0) | VIVS_PE_ALPHA_BLEND_COLOR_A(0)); etna_set_state(ctx, VIVS_PE_ALPHA_OP, ETNA_MASKED_BIT(VIVS_PE_ALPHA_OP_ALPHA_TEST, 0)); etna_set_state(ctx, VIVS_PA_CONFIG, ETNA_MASKED_INL(VIVS_PA_CONFIG_CULL_FACE_MODE, OFF)); etna_set_state(ctx, VIVS_PE_DEPTH_CONFIG, ETNA_MASKED_BIT(VIVS_PE_DEPTH_CONFIG_WRITE_ENABLE, 0)); etna_set_state(ctx, VIVS_PE_STENCIL_CONFIG, ETNA_MASKED(VIVS_PE_STENCIL_CONFIG_REF_FRONT, 0) & ETNA_MASKED(VIVS_PE_STENCIL_CONFIG_MASK_FRONT, 0xff) & ETNA_MASKED(VIVS_PE_STENCIL_CONFIG_WRITE_MASK, 0xff) & ETNA_MASKED_INL(VIVS_PE_STENCIL_CONFIG_MODE, DISABLED)); etna_set_state(ctx, VIVS_PE_STENCIL_OP, ETNA_MASKED(VIVS_PE_STENCIL_OP_FUNC_FRONT, COMPARE_FUNC_ALWAYS) & ETNA_MASKED(VIVS_PE_STENCIL_OP_FUNC_BACK, COMPARE_FUNC_ALWAYS) & ETNA_MASKED(VIVS_PE_STENCIL_OP_FAIL_FRONT, STENCIL_OP_KEEP) & ETNA_MASKED(VIVS_PE_STENCIL_OP_FAIL_BACK, STENCIL_OP_KEEP) & ETNA_MASKED(VIVS_PE_STENCIL_OP_DEPTH_FAIL_FRONT, STENCIL_OP_KEEP) & ETNA_MASKED(VIVS_PE_STENCIL_OP_DEPTH_FAIL_BACK, STENCIL_OP_KEEP) & ETNA_MASKED(VIVS_PE_STENCIL_OP_PASS_FRONT, STENCIL_OP_KEEP) & ETNA_MASKED(VIVS_PE_STENCIL_OP_PASS_BACK, STENCIL_OP_KEEP)); etna_set_state(ctx, VIVS_PE_COLOR_FORMAT, ETNA_MASKED(VIVS_PE_COLOR_FORMAT_COMPONENTS, 0xf)); etna_set_state(ctx, VIVS_PE_DEPTH_CONFIG, ETNA_MASKED_BIT(VIVS_PE_DEPTH_CONFIG_EARLY_Z, 0)); etna_set_state(ctx, VIVS_SE_DEPTH_SCALE, 0x0); etna_set_state(ctx, VIVS_SE_DEPTH_BIAS, 0x0); etna_set_state(ctx, VIVS_PA_CONFIG, ETNA_MASKED_INL(VIVS_PA_CONFIG_FILL_MODE, SOLID)); etna_set_state(ctx, VIVS_PA_CONFIG, ETNA_MASKED_INL(VIVS_PA_CONFIG_SHADE_MODEL, SMOOTH)); etna_set_state(ctx, VIVS_PE_COLOR_FORMAT, ETNA_MASKED(VIVS_PE_COLOR_FORMAT_FORMAT, RS_FORMAT_X8R8G8B8) & ETNA_MASKED_BIT(VIVS_PE_COLOR_FORMAT_SUPER_TILED, supertiled)); etna_set_state(ctx, VIVS_PE_COLOR_ADDR, rt->address); /* ADDR_A */ etna_set_state(ctx, VIVS_PE_COLOR_STRIDE, padded_width * 4); etna_set_state(ctx, VIVS_GL_MULTI_SAMPLE_CONFIG, ETNA_MASKED_INL(VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES, NONE) & ETNA_MASKED(VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES, 0xf) & ETNA_MASKED(VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12, 0x0) & ETNA_MASKED(VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16, 0x0) ); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR); etna_set_state(ctx, VIVS_PE_COLOR_FORMAT, ETNA_MASKED_BIT(VIVS_PE_COLOR_FORMAT_PARTIAL, 1)); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR); etna_set_state(ctx, VIVS_TS_COLOR_CLEAR_VALUE, 0); etna_set_state(ctx, VIVS_TS_COLOR_STATUS_BASE, rt_ts->address); /* ADDR_B */ etna_set_state(ctx, VIVS_TS_COLOR_SURFACE_BASE, rt->address); /* ADDR_A */ etna_set_state(ctx, VIVS_TS_MEM_CONFIG, VIVS_TS_MEM_CONFIG_COLOR_FAST_CLEAR); etna_set_state(ctx, VIVS_PE_DEPTH_CONFIG, ETNA_MASKED_INL(VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT, D16) & ETNA_MASKED_BIT(VIVS_PE_DEPTH_CONFIG_SUPER_TILED, supertiled) ); etna_set_state(ctx, VIVS_PE_DEPTH_ADDR, z->address); /* ADDR_C */ etna_set_state(ctx, VIVS_PE_DEPTH_STRIDE, padded_width * 2); etna_set_state(ctx, VIVS_PE_HDEPTH_CONTROL, VIVS_PE_HDEPTH_CONTROL_FORMAT_DISABLED); etna_set_state_f32(ctx, VIVS_PE_DEPTH_NORMALIZE, 65535.0); etna_set_state(ctx, VIVS_PE_DEPTH_CONFIG, ETNA_MASKED_BIT(VIVS_PE_DEPTH_CONFIG_EARLY_Z, 0)); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_DEPTH); etna_set_state(ctx, VIVS_TS_DEPTH_CLEAR_VALUE, 0xffffffff); etna_set_state(ctx, VIVS_TS_DEPTH_STATUS_BASE, z_ts->address); /* ADDR_D */ etna_set_state(ctx, VIVS_TS_DEPTH_SURFACE_BASE, z->address); /* ADDR_C */ etna_set_state(ctx, VIVS_TS_MEM_CONFIG, VIVS_TS_MEM_CONFIG_DEPTH_FAST_CLEAR | VIVS_TS_MEM_CONFIG_COLOR_FAST_CLEAR | VIVS_TS_MEM_CONFIG_DEPTH_16BPP | VIVS_TS_MEM_CONFIG_DEPTH_COMPRESSION); etna_set_state(ctx, VIVS_PE_DEPTH_CONFIG, ETNA_MASKED_BIT(VIVS_PE_DEPTH_CONFIG_EARLY_Z, 1)); /* flip-flopping once again */ /* Warm up RS on aux render target */ etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); etna_warm_up_rs(ctx, aux_rt->address, aux_rt_ts->address); etna_set_state(ctx, VIVS_TS_COLOR_STATUS_BASE, rt_ts->address); /* ADDR_B */ etna_set_state(ctx, VIVS_TS_COLOR_SURFACE_BASE, rt->address); /* ADDR_A */ etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); etna_warm_up_rs(ctx, aux_rt->address, aux_rt_ts->address); etna_set_state(ctx, VIVS_TS_COLOR_STATUS_BASE, rt_ts->address); /* ADDR_B */ etna_set_state(ctx, VIVS_TS_COLOR_SURFACE_BASE, rt->address); /* ADDR_A */ etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); etna_warm_up_rs(ctx, aux_rt->address, aux_rt_ts->address); etna_set_state(ctx, VIVS_TS_COLOR_STATUS_BASE, rt_ts->address); /* ADDR_B */ etna_set_state(ctx, VIVS_TS_COLOR_SURFACE_BASE, rt->address); /* ADDR_A */ etna_stall(ctx, SYNC_RECIPIENT_RA, SYNC_RECIPIENT_PE); /* Set up the resolve to clear tile status for main render target * Regard the TS as an image of width 16 with 4 bytes per pixel (64 bytes per row) * XXX need to clear the depth ts too. * */ etna_set_state(ctx, VIVS_RS_CONFIG, (RS_FORMAT_X8R8G8B8 << VIVS_RS_CONFIG_SOURCE_FORMAT__SHIFT) | (RS_FORMAT_X8R8G8B8 << VIVS_RS_CONFIG_DEST_FORMAT__SHIFT) ); etna_set_state_multi(ctx, VIVS_RS_DITHER(0), 2, (uint32_t[]) { 0xffffffff, 0xffffffff }); etna_set_state(ctx, VIVS_RS_DEST_ADDR, rt_ts->address); /* ADDR_B */ etna_set_state(ctx, VIVS_RS_DEST_STRIDE, 0x40); etna_set_state(ctx, VIVS_RS_WINDOW_SIZE, ((rt_ts_size/0x40) << VIVS_RS_WINDOW_SIZE_HEIGHT__SHIFT) | (16 << VIVS_RS_WINDOW_SIZE_WIDTH__SHIFT)); etna_set_state(ctx, VIVS_RS_FILL_VALUE(0), (bits_per_tile==4)?0x11111111:0x55555555); etna_set_state(ctx, VIVS_RS_CLEAR_CONTROL, VIVS_RS_CLEAR_CONTROL_MODE_ENABLED1 | (0xffff << VIVS_RS_CLEAR_CONTROL_BITS__SHIFT)); etna_set_state(ctx, VIVS_RS_EXTRA_CONFIG, 0); /* no AA, no endian switch */ etna_set_state(ctx, VIVS_RS_KICKER, 0xbeebbeeb); /** Done */ etna_set_state(ctx, VIVS_TS_COLOR_CLEAR_VALUE, 0xff7f7f7f); etna_set_state(ctx, VIVS_TS_COLOR_STATUS_BASE, rt_ts->address); /* ADDR_B */ etna_set_state(ctx, VIVS_TS_COLOR_SURFACE_BASE, rt->address); /* ADDR_A */ etna_set_state(ctx, VIVS_TS_MEM_CONFIG, VIVS_TS_MEM_CONFIG_DEPTH_FAST_CLEAR | VIVS_TS_MEM_CONFIG_COLOR_FAST_CLEAR | VIVS_TS_MEM_CONFIG_DEPTH_16BPP | VIVS_TS_MEM_CONFIG_DEPTH_COMPRESSION); etna_set_state(ctx, VIVS_PA_CONFIG, ETNA_MASKED_INL(VIVS_PA_CONFIG_CULL_FACE_MODE, CCW)); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); etna_set_state(ctx, VIVS_PE_DEPTH_CONFIG, ETNA_MASKED_BIT(VIVS_PE_DEPTH_CONFIG_WRITE_ENABLE, 0)); etna_set_state(ctx, VIVS_PE_DEPTH_CONFIG, ETNA_MASKED_INL(VIVS_PE_DEPTH_CONFIG_DEPTH_MODE, NONE)); etna_set_state(ctx, VIVS_PE_DEPTH_CONFIG, ETNA_MASKED_BIT(VIVS_PE_DEPTH_CONFIG_WRITE_ENABLE, 0)); etna_set_state(ctx, VIVS_PE_DEPTH_CONFIG, ETNA_MASKED(VIVS_PE_DEPTH_CONFIG_DEPTH_FUNC, COMPARE_FUNC_ALWAYS)); etna_set_state(ctx, VIVS_PE_DEPTH_CONFIG, ETNA_MASKED_INL(VIVS_PE_DEPTH_CONFIG_DEPTH_MODE, Z)); etna_set_state_f32(ctx, VIVS_PE_DEPTH_NEAR, 0.0); etna_set_state_f32(ctx, VIVS_PE_DEPTH_FAR, 1.0); etna_set_state_f32(ctx, VIVS_PE_DEPTH_NORMALIZE, 65535.0); /* set up primitive assembly */ etna_set_state_f32(ctx, VIVS_PA_VIEWPORT_OFFSET_Z, 0.0); etna_set_state_f32(ctx, VIVS_PA_VIEWPORT_SCALE_Z, 1.0); etna_set_state(ctx, VIVS_PE_DEPTH_CONFIG, ETNA_MASKED_BIT(VIVS_PE_DEPTH_CONFIG_ONLY_DEPTH, 0)); etna_set_state_fixp(ctx, VIVS_PA_VIEWPORT_OFFSET_X, width << 15); etna_set_state_fixp(ctx, VIVS_PA_VIEWPORT_OFFSET_Y, height << 15); etna_set_state_fixp(ctx, VIVS_PA_VIEWPORT_SCALE_X, width << 15); etna_set_state_fixp(ctx, VIVS_PA_VIEWPORT_SCALE_Y, height << 15); etna_set_state_fixp(ctx, VIVS_SE_SCISSOR_LEFT, 0); etna_set_state_fixp(ctx, VIVS_SE_SCISSOR_TOP, 0); etna_set_state_fixp(ctx, VIVS_SE_SCISSOR_RIGHT, (width << 16) | 5); etna_set_state_fixp(ctx, VIVS_SE_SCISSOR_BOTTOM, (height << 16) | 5); /* shader setup */ etna_set_state(ctx, VIVS_VS_END_PC, vs_size/16); etna_set_state_multi(ctx, VIVS_VS_INPUT_COUNT, 3, (uint32_t[]) { /* VIVS_VS_INPUT_COUNT */ (1<<8) | 3, /* VIVS_VS_TEMP_REGISTER_CONTROL */ 6 << VIVS_VS_TEMP_REGISTER_CONTROL_NUM_TEMPS__SHIFT, /* VIVS_VS_OUTPUT(0) */ 4 }); etna_set_state(ctx, VIVS_VS_START_PC, 0x0); etna_set_state_f32(ctx, VIVS_VS_UNIFORMS(45), 0.5); /* u11.y */ etna_set_state_f32(ctx, VIVS_VS_UNIFORMS(44), 1.0); /* u11.x */ etna_set_state_f32(ctx, VIVS_VS_UNIFORMS(27), 0.0); /* u6.w */ etna_set_state_f32(ctx, VIVS_VS_UNIFORMS(23), 20.0); /* u5.w */ etna_set_state_f32(ctx, VIVS_VS_UNIFORMS(19), 2.0); /* u4.w */ /* Now load the shader itself */ etna_set_state_multi(ctx, VIVS_VS_INST_MEM(0), vs_size/4, vs); etna_set_state(ctx, VIVS_RA_CONTROL, 0x1); etna_set_state_multi(ctx, VIVS_PS_END_PC, 2, (uint32_t[]) { /* VIVS_PS_END_PC */ ps_size/16, /* VIVS_PS_OUTPUT_REG */ 0x1 }); etna_set_state(ctx, VIVS_PS_START_PC, 0x0); etna_set_state(ctx, VIVS_PA_SHADER_ATTRIBUTES(0), 0x200); etna_set_state(ctx, VIVS_GL_VARYING_NUM_COMPONENTS, /* one varying, with four components */ (4 << VIVS_GL_VARYING_NUM_COMPONENTS_VAR0__SHIFT) ); etna_set_state_multi(ctx, VIVS_GL_VARYING_COMPONENT_USE(0), 2, (uint32_t[]) { /* one varying, with four components */ (VARYING_COMPONENT_USE_USED << VIVS_GL_VARYING_COMPONENT_USE_COMP0__SHIFT) | (VARYING_COMPONENT_USE_USED << VIVS_GL_VARYING_COMPONENT_USE_COMP1__SHIFT) | (VARYING_COMPONENT_USE_USED << VIVS_GL_VARYING_COMPONENT_USE_COMP2__SHIFT) | (VARYING_COMPONENT_USE_USED << VIVS_GL_VARYING_COMPONENT_USE_COMP3__SHIFT) , 0 }); etna_set_state_multi(ctx, VIVS_PS_INST_MEM(0), ps_size/4, ps); etna_set_state(ctx, VIVS_PS_INPUT_COUNT, (31<<8)|2); etna_set_state(ctx, VIVS_PS_TEMP_REGISTER_CONTROL, (2 << VIVS_PS_TEMP_REGISTER_CONTROL_NUM_TEMPS__SHIFT)); etna_set_state(ctx, VIVS_PS_CONTROL, VIVS_PS_CONTROL_UNK1 ); etna_set_state(ctx, VIVS_PA_ATTRIBUTE_ELEMENT_COUNT, 0x100); etna_set_state(ctx, VIVS_GL_VARYING_TOTAL_COMPONENTS, /* one varying, with four components */ VIVS_GL_VARYING_TOTAL_COMPONENTS_NUM(4) ); etna_set_state(ctx, VIVS_VS_LOAD_BALANCING, 0xf3f0582); etna_set_state(ctx, VIVS_VS_OUTPUT_COUNT, 2); etna_set_state(ctx, VIVS_PA_CONFIG, ETNA_MASKED_BIT(VIVS_PA_CONFIG_POINT_SIZE_ENABLE, 0)); /* Compute transform matrices in the same way as cube egl demo */ ESMatrix modelview; esMatrixLoadIdentity(&modelview); esTranslate(&modelview, 0.0f, 0.0f, -8.0f); esRotate(&modelview, 45.0f, 1.0f, 0.0f, 0.0f); esRotate(&modelview, 45.0f, 0.0f, 1.0f, 0.0f); esRotate(&modelview, frame*0.5f, 0.0f, 0.0f, 1.0f); GLfloat aspect = (GLfloat)(height) / (GLfloat)(width); ESMatrix projection; esMatrixLoadIdentity(&projection); esFrustum(&projection, -2.8f, +2.8f, -2.8f * aspect, +2.8f * aspect, 6.0f, 10.0f); ESMatrix modelviewprojection; esMatrixLoadIdentity(&modelviewprojection); esMatrixMultiply(&modelviewprojection, &modelview, &projection); ESMatrix inverse, normal; /* compute inverse transpose normal transformation matrix */ esMatrixInverse3x3(&inverse, &modelview); esMatrixTranspose(&normal, &inverse); etna_set_state_multi(ctx, VIVS_VS_UNIFORMS(0), 16, (uint32_t*)&modelviewprojection.m[0][0]); etna_set_state_multi(ctx, VIVS_VS_UNIFORMS(16), 3, (uint32_t*)&normal.m[0][0]); /* u4.xyz */ etna_set_state_multi(ctx, VIVS_VS_UNIFORMS(20), 3, (uint32_t*)&normal.m[1][0]); /* u5.xyz */ etna_set_state_multi(ctx, VIVS_VS_UNIFORMS(24), 3, (uint32_t*)&normal.m[2][0]); /* u6.xyz */ etna_set_state_multi(ctx, VIVS_VS_UNIFORMS(28), 16, (uint32_t*)&modelview.m[0][0]); etna_set_state(ctx, VIVS_FE_VERTEX_STREAM_BASE_ADDR, vtx->address); /* ADDR_E */ etna_set_state(ctx, VIVS_FE_VERTEX_STREAM_CONTROL, 0x24 << VIVS_FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE__SHIFT); etna_set_state(ctx, VIVS_FE_VERTEX_ELEMENT_CONFIG(0), VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_FLOAT | (ENDIAN_MODE_NO_SWAP << VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN__SHIFT) | (0 << VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM__SHIFT) | (3 <<VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM__SHIFT) | VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_OFF | (0x0 << VIVS_FE_VERTEX_ELEMENT_CONFIG_START__SHIFT) | (0xc << VIVS_FE_VERTEX_ELEMENT_CONFIG_END__SHIFT)); etna_set_state(ctx, VIVS_FE_VERTEX_ELEMENT_CONFIG(1), VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_FLOAT | (ENDIAN_MODE_NO_SWAP << VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN__SHIFT) | (0 << VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM__SHIFT) | (3 <<VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM__SHIFT) | VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_OFF | (0xc << VIVS_FE_VERTEX_ELEMENT_CONFIG_START__SHIFT) | (0x18 << VIVS_FE_VERTEX_ELEMENT_CONFIG_END__SHIFT)); etna_set_state(ctx, VIVS_FE_VERTEX_ELEMENT_CONFIG(2), VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_FLOAT | (ENDIAN_MODE_NO_SWAP << VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN__SHIFT) | VIVS_FE_VERTEX_ELEMENT_CONFIG_NONCONSECUTIVE | (0 << VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM__SHIFT) | (3 <<VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM__SHIFT) | VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_OFF | (0x18 << VIVS_FE_VERTEX_ELEMENT_CONFIG_START__SHIFT) | (0x24 << VIVS_FE_VERTEX_ELEMENT_CONFIG_END__SHIFT)); etna_set_state(ctx, VIVS_VS_INPUT(0), 0x20100); etna_set_state(ctx, VIVS_PA_CONFIG, ETNA_MASKED_BIT(VIVS_PA_CONFIG_POINT_SPRITE_ENABLE, 0)); for(int prim=0; prim<6; ++prim) { etna_draw_primitives(ctx, PRIMITIVE_TYPE_TRIANGLE_STRIP, prim*4, 2); } etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); etna_flush(ctx); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); etna_set_state(ctx, VIVS_RS_CONFIG, VIVS_RS_CONFIG_SOURCE_FORMAT(RS_FORMAT_X8R8G8B8) | VIVS_RS_CONFIG_SOURCE_TILED | VIVS_RS_CONFIG_DEST_FORMAT(RS_FORMAT_X8R8G8B8) | VIVS_RS_CONFIG_DEST_TILED); etna_set_state(ctx, VIVS_RS_SOURCE_STRIDE, (padded_width * 4 * 4) | (supertiled?VIVS_RS_SOURCE_STRIDE_TILING:0)); etna_set_state(ctx, VIVS_RS_DEST_STRIDE, (padded_width * 4 * 4) | (supertiled?VIVS_RS_DEST_STRIDE_TILING:0)); etna_set_state(ctx, VIVS_RS_DITHER(0), 0xffffffff); etna_set_state(ctx, VIVS_RS_DITHER(1), 0xffffffff); etna_set_state(ctx, VIVS_RS_CLEAR_CONTROL, VIVS_RS_CLEAR_CONTROL_MODE_DISABLED); etna_set_state(ctx, VIVS_RS_EXTRA_CONFIG, 0); /* no AA, no endian switch */ etna_set_state(ctx, VIVS_RS_SOURCE_ADDR, rt->address); /* ADDR_A */ etna_set_state(ctx, VIVS_RS_DEST_ADDR, rt->address); /* ADDR_A */ etna_set_state(ctx, VIVS_RS_WINDOW_SIZE, VIVS_RS_WINDOW_SIZE_HEIGHT(padded_height) | VIVS_RS_WINDOW_SIZE_WIDTH(padded_width)); etna_set_state(ctx, VIVS_RS_KICKER, 0xbeebbeeb); /* Submit second command buffer */ etna_flush(ctx); etna_warm_up_rs(ctx, aux_rt->address, aux_rt_ts->address); etna_set_state(ctx, VIVS_TS_COLOR_STATUS_BASE, rt_ts->address); /* ADDR_B */ etna_set_state(ctx, VIVS_TS_COLOR_SURFACE_BASE, rt->address); /* ADDR_A */ etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR); etna_set_state(ctx, VIVS_TS_MEM_CONFIG, VIVS_TS_MEM_CONFIG_DEPTH_FAST_CLEAR | VIVS_TS_MEM_CONFIG_DEPTH_16BPP | VIVS_TS_MEM_CONFIG_DEPTH_COMPRESSION); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR); etna_set_state(ctx, VIVS_PE_COLOR_FORMAT, ETNA_MASKED_BIT(VIVS_PE_COLOR_FORMAT_PARTIAL, 0)); /* Submit third command buffer, wait for pixel engine to finish */ etna_finish(ctx); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); etna_set_state(ctx, VIVS_RS_CONFIG, VIVS_RS_CONFIG_SOURCE_FORMAT(RS_FORMAT_X8R8G8B8) | VIVS_RS_CONFIG_SOURCE_TILED | VIVS_RS_CONFIG_DEST_FORMAT(RS_FORMAT_X8R8G8B8) /*| VIVS_RS_CONFIG_SWAP_RB*/); etna_set_state(ctx, VIVS_RS_SOURCE_STRIDE, (padded_width * 4 * 4) | (supertiled?VIVS_RS_SOURCE_STRIDE_TILING:0)); etna_set_state(ctx, VIVS_RS_DEST_STRIDE, width * 4); etna_set_state(ctx, VIVS_RS_DITHER(0), 0xffffffff); etna_set_state(ctx, VIVS_RS_DITHER(1), 0xffffffff); etna_set_state(ctx, VIVS_RS_CLEAR_CONTROL, VIVS_RS_CLEAR_CONTROL_MODE_DISABLED); etna_set_state(ctx, VIVS_RS_EXTRA_CONFIG, 0); /* no AA, no endian switch */ etna_set_state(ctx, VIVS_RS_SOURCE_ADDR, rt->address); etna_set_state(ctx, VIVS_RS_DEST_ADDR, bmp->address); etna_set_state(ctx, VIVS_RS_WINDOW_SIZE, VIVS_RS_WINDOW_SIZE_HEIGHT(height) | VIVS_RS_WINDOW_SIZE_WIDTH(width)); etna_set_state(ctx, VIVS_RS_KICKER, 0xbeebbeeb); etna_finish(ctx); } bmp_dump32(bmp->logical, width, height, false, "/tmp/fb.bmp"); printf("Dump complete\n"); /* Unlock video memory */ if(etna_vidmem_unlock(bmp) != 0) { fprintf(stderr, "Cannot unlock vidmem\n"); exit(1); } etna_free(ctx); viv_close(); 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; }
/* Allocate 2D texture or render target resource */ static struct pipe_resource * etna_screen_resource_create(struct pipe_screen *screen, const struct pipe_resource *templat) { struct etna_screen *priv = etna_screen(screen); assert(templat); unsigned element_size = util_format_get_blocksize(templat->format); if(!element_size) return NULL; /* Check input */ if(templat->target == PIPE_TEXTURE_CUBE) { assert(templat->array_size == 6); } else if (templat->target == PIPE_BUFFER) { assert(templat->format == PIPE_FORMAT_R8_UNORM); /* bytes; want TYPELESS or similar */ assert(templat->array_size == 1); assert(templat->height0 == 1); assert(templat->depth0 == 1); assert(templat->array_size == 1); assert(templat->last_level == 0); } else { assert(templat->array_size == 1); } assert(templat->width0 != 0); assert(templat->height0 != 0); assert(templat->depth0 != 0); assert(templat->array_size != 0); /* Figure out what tiling to use -- for now, assume that textures cannot be supertiled, and cannot be linear. * There is a feature flag SUPERTILED_TEXTURE (not supported on any known hw) that may allow this, as well * as LINEAR_TEXTURE_SUPPORT (supported on gc880 and gc2000 at least), but not sure how it works. * Buffers always have LINEAR layout. */ unsigned layout = ETNA_LAYOUT_LINEAR; if(templat->target != PIPE_BUFFER) { if(!(templat->bind & PIPE_BIND_SAMPLER_VIEW) && priv->specs.can_supertile && !DBG_ENABLED(ETNA_DBG_NO_SUPERTILE)) layout = ETNA_LAYOUT_SUPER_TILED; else layout = ETNA_LAYOUT_TILED; } /* XXX multi tiled formats */ /* Determine scaling for antialiasing, allow override using debug flag */ int nr_samples = templat->nr_samples; if((templat->bind & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL)) && !(templat->bind & PIPE_BIND_SAMPLER_VIEW)) { if(DBG_ENABLED(ETNA_DBG_MSAA_2X)) nr_samples = 2; if(DBG_ENABLED(ETNA_DBG_MSAA_4X)) nr_samples = 4; } int msaa_xscale = 1, msaa_yscale = 1; if(!translate_samples_to_xyscale(nr_samples, &msaa_xscale, &msaa_yscale, NULL)) { /* Number of samples not supported */ assert(0); } /* Determine needed padding (alignment of height/width) */ unsigned paddingX = 0, paddingY = 0; unsigned halign = TEXTURE_HALIGN_FOUR; etna_layout_multiple(layout, priv->dev->chip.pixel_pipes, (templat->bind & PIPE_BIND_SAMPLER_VIEW) && !VIV_FEATURE(priv->dev, chipMinorFeatures1, TEXTURE_HALIGN), &paddingX, &paddingY, &halign); assert(paddingX && paddingY); /* determine mipmap levels */ struct etna_resource *resource = CALLOC_STRUCT(etna_resource); int max_mip_level = templat->last_level; if(unlikely(max_mip_level >= ETNA_NUM_LOD)) /* max LOD supported by hw */ max_mip_level = ETNA_NUM_LOD - 1; /* take care about DXTx formats, which have a divSize of non-1x1 * also: lower mipmaps are still 4x4 due to tiling. In as sense, compressed formats are already tiled. * XXX UYVY formats? */ unsigned divSizeX = util_format_get_blockwidth(templat->format); unsigned divSizeY = util_format_get_blockheight(templat->format); unsigned ix = 0; unsigned x = templat->width0, y = templat->height0; unsigned offset = 0; while(true) { struct etna_resource_level *mip = &resource->levels[ix]; mip->width = x; mip->height = y; mip->padded_width = align(x * msaa_xscale, paddingX); mip->padded_height = align(y * msaa_yscale, paddingY); mip->stride = align(mip->padded_width, divSizeX)/divSizeX * element_size; mip->offset = offset; mip->layer_stride = align(mip->padded_width, divSizeX)/divSizeX * align(mip->padded_height, divSizeY)/divSizeY * element_size; mip->size = templat->array_size * mip->layer_stride; offset += align(mip->size, ETNA_PE_ALIGNMENT); /* align mipmaps to 64 bytes to be able to render to them */ if(ix == max_mip_level || (x == 1 && y == 1)) break; // stop at last level x = MAX2(x >> 1, 1); y = MAX2(y >> 1, 1); ix += 1; } /* Determine memory size, and whether to create a tile status */ size_t rt_size = offset; /* determine memory type */ enum viv_surf_type memtype = VIV_SURF_UNKNOWN; if(templat->bind & PIPE_BIND_SAMPLER_VIEW) memtype = VIV_SURF_TEXTURE; else if(templat->bind & PIPE_BIND_RENDER_TARGET) memtype = VIV_SURF_RENDER_TARGET; else if(templat->bind & PIPE_BIND_DEPTH_STENCIL) memtype = VIV_SURF_DEPTH; else if(templat->bind & PIPE_BIND_INDEX_BUFFER) memtype = VIV_SURF_INDEX; else if(templat->bind & PIPE_BIND_VERTEX_BUFFER) memtype = VIV_SURF_VERTEX; DBG_F(ETNA_DBG_RESOURCE_MSGS, "%p: Allocate surface of %ix%i (padded to %ix%i) of format %s (%i bpe %ix%i), size %08zx flags %08x, memtype %i", resource, templat->width0, templat->height0, resource->levels[0].padded_width, resource->levels[0].padded_height, util_format_name(templat->format), element_size, divSizeX, divSizeY, rt_size, templat->bind, memtype); struct etna_vidmem *rt = 0; if(unlikely(etna_vidmem_alloc_linear(priv->dev, &rt, rt_size, memtype, VIV_POOL_DEFAULT, true) != ETNA_OK)) { BUG("Problem allocating video memory for resource"); return NULL; } resource->base = *templat; resource->base.last_level = ix; /* real last mipmap level */ resource->base.screen = screen; resource->base.nr_samples = nr_samples; resource->layout = layout; resource->halign = halign; resource->surface = rt; resource->ts = 0; /* TS is only created when first bound to surface */ pipe_reference_init(&resource->base.reference, 1); if(DBG_ENABLED(ETNA_DBG_ZERO)) { memset(resource->surface->logical, 0, rt_size); } for(unsigned ix=0; ix<=resource->base.last_level; ++ix) { struct etna_resource_level *mip = &resource->levels[ix]; mip->address = resource->surface->address + mip->offset; mip->logical = resource->surface->logical + mip->offset; DBG_F(ETNA_DBG_RESOURCE_MSGS, " %08x level %i: %ix%i (%i) stride=%i layer_stride=%i", (int)mip->address, ix, (int)mip->width, (int)mip->height, (int)mip->size, (int)mip->stride, (int)mip->layer_stride); } return &resource->base; }
int main(int argc, char **argv) { int rv; int width = 256; int height = 256; int padded_width, padded_height; fb_info fb; rv = fb_open(0, &fb); if(rv!=0) { exit(1); } width = fb.fb_var.xres; height = fb.fb_var.yres; padded_width = etna_align_up(width, 64); padded_height = etna_align_up(height, 64); printf("padded_width %i padded_height %i\n", padded_width, padded_height); rv = viv_open(); if(rv!=0) { fprintf(stderr, "Error opening device\n"); exit(1); } printf("Succesfully opened device\n"); etna_ctx *ctx = 0; if(etna_create(&ctx) != ETNA_OK) { printf("Unable to create context\n"); exit(1); } /* Initialize buffers synchronization structure */ etna_bswap_buffers *buffers = 0; if(etna_bswap_create(ctx, &buffers, (int (*)(void *, int))&fb_set_buffer, NULL, &fb) < 0) { fprintf(stderr, "Error creating buffer swapper\n"); exit(1); } /* Allocate video memory */ etna_vidmem *rt = 0; /* main render target */ etna_vidmem *rt_ts = 0; /* tile status for main render target */ etna_vidmem *z = 0; /* depth for main render target */ etna_vidmem *z_ts = 0; /* depth ts for main render target */ etna_vidmem *vtx = 0; /* vertex buffer */ etna_vidmem *aux_rt = 0; /* auxilary render target */ etna_vidmem *aux_rt_ts = 0; /* tile status for auxilary render target */ etna_vidmem *tex = 0; /* texture */ size_t rt_size = padded_width * padded_height * 4; size_t rt_ts_size = etna_align_up((padded_width * padded_height * 4)/0x100, 0x100); size_t z_size = padded_width * padded_height * 2; size_t z_ts_size = etna_align_up((padded_width * padded_height * 2)/0x100, 0x100); dds_texture *dds = 0; if(argc<2 || !dds_load(argv[1], &dds)) { printf("Error loading texture\n"); exit(1); } if(etna_vidmem_alloc_linear(&rt, rt_size, gcvSURF_RENDER_TARGET, gcvPOOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(&rt_ts, rt_ts_size, gcvSURF_TILE_STATUS, gcvPOOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(&z, z_size, gcvSURF_DEPTH, gcvPOOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(&z_ts, z_ts_size, gcvSURF_TILE_STATUS, gcvPOOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(&vtx, VERTEX_BUFFER_SIZE, gcvSURF_VERTEX, gcvPOOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(&aux_rt, 0x4000, gcvSURF_RENDER_TARGET, gcvPOOL_SYSTEM, true)!=ETNA_OK || etna_vidmem_alloc_linear(&aux_rt_ts, 0x100, gcvSURF_TILE_STATUS, gcvPOOL_DEFAULT, true)!=ETNA_OK || etna_vidmem_alloc_linear(&tex, dds->size, gcvSURF_TEXTURE, gcvPOOL_DEFAULT, true)!=ETNA_OK ) { fprintf(stderr, "Error allocating video memory\n"); exit(1); } uint32_t tex_format = 0; uint32_t tex_base_width = dds->slices[0][0].width; uint32_t tex_base_height = dds->slices[0][0].height; uint32_t tex_base_log_width = (int)(logf(tex_base_width) * RCPLOG2 * 32.0f + 0.5f); uint32_t tex_base_log_height = (int)(logf(tex_base_height) * RCPLOG2 * 32.0f + 0.5f); printf("Loading compressed texture (format %i, %ix%i) log_width=%i log_height=%i\n", dds->fmt, tex_base_width, tex_base_height, tex_base_log_width, tex_base_log_height); if(dds->fmt == FMT_X8R8G8B8 || dds->fmt == FMT_A8R8G8B8) { for(int ix=0; ix<dds->num_mipmaps; ++ix) { printf("%08x: Tiling mipmap %i (%ix%i)\n", dds->slices[0][ix].offset, ix, dds->slices[0][ix].width, dds->slices[0][ix].height); etna_texture_tile((void*)((size_t)tex->logical + dds->slices[0][ix].offset), dds->slices[0][ix].data, dds->slices[0][ix].width, dds->slices[0][ix].height, dds->slices[0][ix].stride, 4); } tex_format = TEXTURE_FORMAT_X8R8G8B8; } else if(dds->fmt == FMT_DXT1 || dds->fmt == FMT_DXT3 || dds->fmt == FMT_DXT5 || dds->fmt == FMT_ETC1) { printf("Uploading compressed texture\n"); memcpy(tex->logical, dds->data, dds->size); switch(dds->fmt) { case FMT_DXT1: tex_format = TEXTURE_FORMAT_DXT1; break; case FMT_DXT3: tex_format = TEXTURE_FORMAT_DXT2_DXT3; break; case FMT_DXT5: tex_format = TEXTURE_FORMAT_DXT4_DXT5; break; case FMT_ETC1: tex_format = TEXTURE_FORMAT_ETC1; break; } } else { printf("Unknown texture format\n"); exit(1); } /* Phew, now we got all the memory we need. * Write interleaved attribute vertex stream. * Unlike the GL example we only do this once, not every time glDrawArrays is called, the same would be accomplished * from GL by using a vertex buffer object. */ for(int vert=0; vert<NUM_VERTICES; ++vert) { int dest_idx = vert * (3 + 3 + 2); for(int comp=0; comp<3; ++comp) ((float*)vtx->logical)[dest_idx+comp+0] = vVertices[vert*3 + comp]; /* 0 */ for(int comp=0; comp<3; ++comp) ((float*)vtx->logical)[dest_idx+comp+3] = vNormals[vert*3 + comp]; /* 1 */ for(int comp=0; comp<2; ++comp) ((float*)vtx->logical)[dest_idx+comp+6] = vTexCoords[vert*2 + comp]; /* 2 */ } for(int frame=0; frame<1000; ++frame) { if(frame%50 == 0) printf("*** FRAME %i ****\n", frame); /* Compute transform matrices in the same way as cube egl demo */ ESMatrix modelview, projection, modelviewprojection; ESMatrix inverse, normal; esMatrixLoadIdentity(&modelview); esTranslate(&modelview, 0.0f, 0.0f, -8.0f); esRotate(&modelview, 45.0f, 1.0f, 0.0f, 0.0f); esRotate(&modelview, 45.0f, 0.0f, 1.0f, 0.0f); esRotate(&modelview, frame*0.5f, 0.0f, 0.0f, 1.0f); GLfloat aspect = (GLfloat)(height) / (GLfloat)(width); esMatrixLoadIdentity(&projection); esFrustum(&projection, -2.8f, +2.8f, -2.8f * aspect, +2.8f * aspect, 6.0f, 10.0f); esMatrixLoadIdentity(&modelviewprojection); esMatrixMultiply(&modelviewprojection, &modelview, &projection); esMatrixInverse3x3(&inverse, &modelview); esMatrixTranspose(&normal, &inverse); /* XXX part of this can be put outside the loop, but until we have usable context management * this is safest. */ etna_set_state(ctx, VIVS_RA_CONTROL, 0x3); etna_set_state(ctx, VIVS_GL_MULTI_SAMPLE_CONFIG, VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_NONE | VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES(0xf) /*| VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12 | VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16 */ ); etna_set_state(ctx, VIVS_GL_VERTEX_ELEMENT_CONFIG, 0x1); etna_set_state(ctx, VIVS_GL_VARYING_NUM_COMPONENTS, VIVS_GL_VARYING_NUM_COMPONENTS_VAR0(4)| /* position */ VIVS_GL_VARYING_NUM_COMPONENTS_VAR1(2) /* texture coordinate */ ); etna_set_state(ctx, VIVS_GL_VARYING_TOTAL_COMPONENTS, VIVS_GL_VARYING_TOTAL_COMPONENTS_NUM(4 + 2) ); etna_set_state_multi(ctx, VIVS_GL_VARYING_COMPONENT_USE(0), 2, (uint32_t[]){ VIVS_GL_VARYING_COMPONENT_USE_COMP0(VARYING_COMPONENT_USE_USED) | VIVS_GL_VARYING_COMPONENT_USE_COMP1(VARYING_COMPONENT_USE_USED) | VIVS_GL_VARYING_COMPONENT_USE_COMP2(VARYING_COMPONENT_USE_USED) | VIVS_GL_VARYING_COMPONENT_USE_COMP3(VARYING_COMPONENT_USE_USED) | VIVS_GL_VARYING_COMPONENT_USE_COMP4(VARYING_COMPONENT_USE_USED) | VIVS_GL_VARYING_COMPONENT_USE_COMP5(VARYING_COMPONENT_USE_USED) , 0 }); etna_set_state(ctx, VIVS_PA_W_CLIP_LIMIT, 0x34000001); etna_set_state(ctx, VIVS_PA_SYSTEM_MODE, 0x11); etna_set_state(ctx, VIVS_PA_CONFIG, /* VIVS_PA_CONFIG_UNK22 | */ VIVS_PA_CONFIG_CULL_FACE_MODE_CCW | VIVS_PA_CONFIG_FILL_MODE_SOLID | VIVS_PA_CONFIG_SHADE_MODEL_SMOOTH /* | VIVS_PA_CONFIG_POINT_SIZE_ENABLE | VIVS_PA_CONFIG_POINT_SPRITE_ENABLE*/); etna_set_state_f32(ctx, VIVS_PA_VIEWPORT_OFFSET_Z, 0.0); etna_set_state_f32(ctx, VIVS_PA_VIEWPORT_SCALE_Z, 1.0); etna_set_state_fixp(ctx, VIVS_PA_VIEWPORT_OFFSET_X, width << 15); etna_set_state_fixp(ctx, VIVS_PA_VIEWPORT_OFFSET_Y, height << 15); etna_set_state_fixp(ctx, VIVS_PA_VIEWPORT_SCALE_X, width << 15); etna_set_state_fixp(ctx, VIVS_PA_VIEWPORT_SCALE_Y, height << 15); etna_set_state(ctx, VIVS_PA_ATTRIBUTE_ELEMENT_COUNT, 0x200); etna_set_state(ctx, VIVS_PA_SHADER_ATTRIBUTES(0), 0x200); etna_set_state(ctx, VIVS_PA_SHADER_ATTRIBUTES(1), 0x200); etna_set_state(ctx, VIVS_SE_CONFIG, 0x0); etna_set_state(ctx, VIVS_SE_DEPTH_SCALE, 0x0); etna_set_state(ctx, VIVS_SE_DEPTH_BIAS, 0x0); etna_set_state_fixp(ctx, VIVS_SE_SCISSOR_LEFT, 0); etna_set_state_fixp(ctx, VIVS_SE_SCISSOR_TOP, 0); etna_set_state_fixp(ctx, VIVS_SE_SCISSOR_RIGHT, (width << 16) | 5); etna_set_state_fixp(ctx, VIVS_SE_SCISSOR_BOTTOM, (height << 16) | 5); etna_set_state(ctx, VIVS_PE_ALPHA_CONFIG, /* VIVS_PE_ALPHA_CONFIG_BLEND_ENABLE_COLOR | */ /* VIVS_PE_ALPHA_CONFIG_BLEND_ENABLE_ALPHA | */ VIVS_PE_ALPHA_CONFIG_SRC_FUNC_COLOR(BLEND_FUNC_ONE) | VIVS_PE_ALPHA_CONFIG_SRC_FUNC_ALPHA(BLEND_FUNC_ONE) | VIVS_PE_ALPHA_CONFIG_DST_FUNC_COLOR(BLEND_FUNC_ZERO) | VIVS_PE_ALPHA_CONFIG_DST_FUNC_ALPHA(BLEND_FUNC_ZERO) | VIVS_PE_ALPHA_CONFIG_EQ_COLOR(BLEND_EQ_ADD) | VIVS_PE_ALPHA_CONFIG_EQ_ALPHA(BLEND_EQ_ADD)); etna_set_state(ctx, VIVS_PE_ALPHA_BLEND_COLOR, VIVS_PE_ALPHA_BLEND_COLOR_B(0) | VIVS_PE_ALPHA_BLEND_COLOR_G(0) | VIVS_PE_ALPHA_BLEND_COLOR_R(0) | VIVS_PE_ALPHA_BLEND_COLOR_A(0)); etna_set_state(ctx, VIVS_PE_ALPHA_OP, /* VIVS_PE_ALPHA_OP_ALPHA_TEST */ 0); etna_set_state(ctx, VIVS_PE_STENCIL_CONFIG, VIVS_PE_STENCIL_CONFIG_REF_FRONT(0) | VIVS_PE_STENCIL_CONFIG_MASK_FRONT(0xff) | VIVS_PE_STENCIL_CONFIG_WRITE_MASK(0xff) | VIVS_PE_STENCIL_CONFIG_MODE_DISABLED); etna_set_state(ctx, VIVS_PE_STENCIL_OP, VIVS_PE_STENCIL_OP_FUNC_FRONT(COMPARE_FUNC_ALWAYS) | VIVS_PE_STENCIL_OP_FUNC_BACK(COMPARE_FUNC_ALWAYS) | VIVS_PE_STENCIL_OP_FAIL_FRONT(STENCIL_OP_KEEP) | VIVS_PE_STENCIL_OP_FAIL_BACK(STENCIL_OP_KEEP) | VIVS_PE_STENCIL_OP_DEPTH_FAIL_FRONT(STENCIL_OP_KEEP) | VIVS_PE_STENCIL_OP_DEPTH_FAIL_BACK(STENCIL_OP_KEEP) | VIVS_PE_STENCIL_OP_PASS_FRONT(STENCIL_OP_KEEP) | VIVS_PE_STENCIL_OP_PASS_BACK(STENCIL_OP_KEEP)); etna_set_state(ctx, VIVS_PE_COLOR_FORMAT, VIVS_PE_COLOR_FORMAT_COMPONENTS(0xf) | VIVS_PE_COLOR_FORMAT_FORMAT(RS_FORMAT_X8R8G8B8) | VIVS_PE_COLOR_FORMAT_SUPER_TILED | VIVS_PE_COLOR_FORMAT_OVERWRITE); etna_set_state(ctx, VIVS_PE_DEPTH_CONFIG, VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT_D16 | VIVS_PE_DEPTH_CONFIG_SUPER_TILED | VIVS_PE_DEPTH_CONFIG_EARLY_Z | /* VIVS_PE_DEPTH_CONFIG_WRITE_ENABLE | */ VIVS_PE_DEPTH_CONFIG_DEPTH_FUNC(COMPARE_FUNC_ALWAYS) | VIVS_PE_DEPTH_CONFIG_DEPTH_MODE_Z /* VIVS_PE_DEPTH_CONFIG_ONLY_DEPTH */ ); etna_set_state(ctx, VIVS_PE_DEPTH_ADDR, z->address); etna_set_state(ctx, VIVS_PE_DEPTH_STRIDE, padded_width * 2); etna_set_state(ctx, VIVS_PE_HDEPTH_CONTROL, VIVS_PE_HDEPTH_CONTROL_FORMAT_DISABLED); etna_set_state_f32(ctx, VIVS_PE_DEPTH_NORMALIZE, 65535.0); etna_set_state(ctx, VIVS_PE_COLOR_ADDR, rt->address); etna_set_state(ctx, VIVS_PE_COLOR_STRIDE, padded_width * 4); etna_set_state_f32(ctx, VIVS_PE_DEPTH_NEAR, 0.0); etna_set_state_f32(ctx, VIVS_PE_DEPTH_FAR, 1.0); etna_set_state_f32(ctx, VIVS_PE_DEPTH_NORMALIZE, 65535.0); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); etna_set_state(ctx, VIVS_RS_FLUSH_CACHE, VIVS_RS_FLUSH_CACHE_FLUSH); etna_stall(ctx, SYNC_RECIPIENT_RA, SYNC_RECIPIENT_PE); /* Set up the resolve to clear tile status for main render target * Regard the TS plane as an image of width 16 with 4 bytes per pixel (64 bytes per row) * XXX need to clear the depth ts too? we don't really use depth buffer in this sample * */ etna_set_state(ctx, VIVS_TS_MEM_CONFIG, 0); etna_set_state(ctx, VIVS_RS_CONFIG, VIVS_RS_CONFIG_SOURCE_FORMAT(RS_FORMAT_X8R8G8B8) | VIVS_RS_CONFIG_DEST_FORMAT(RS_FORMAT_X8R8G8B8) ); etna_set_state_multi(ctx, VIVS_RS_DITHER(0), 2, (uint32_t[]){0xffffffff, 0xffffffff}); etna_set_state(ctx, VIVS_RS_DEST_ADDR, rt_ts->address); /* ADDR_B */ etna_set_state(ctx, VIVS_RS_DEST_STRIDE, 0x40); etna_set_state(ctx, VIVS_RS_WINDOW_SIZE, ((rt_ts_size/0x40) << VIVS_RS_WINDOW_SIZE_HEIGHT__SHIFT) | (16 << VIVS_RS_WINDOW_SIZE_WIDTH__SHIFT)); etna_set_state(ctx, VIVS_RS_FILL_VALUE(0), 0x55555555); etna_set_state(ctx, VIVS_RS_CLEAR_CONTROL, VIVS_RS_CLEAR_CONTROL_MODE_ENABLED1 | (0xffff << VIVS_RS_CLEAR_CONTROL_BITS__SHIFT)); etna_set_state(ctx, VIVS_RS_EXTRA_CONFIG, 0); etna_set_state(ctx, VIVS_RS_KICKER, 0xbeebbeeb); /** Done */ /* Now set up TS */ etna_set_state(ctx, VIVS_TS_MEM_CONFIG, VIVS_TS_MEM_CONFIG_DEPTH_FAST_CLEAR | VIVS_TS_MEM_CONFIG_COLOR_FAST_CLEAR | VIVS_TS_MEM_CONFIG_DEPTH_16BPP | VIVS_TS_MEM_CONFIG_DEPTH_COMPRESSION); etna_set_state(ctx, VIVS_TS_DEPTH_CLEAR_VALUE, 0xffffffff); etna_set_state(ctx, VIVS_TS_DEPTH_STATUS_BASE, z_ts->address); etna_set_state(ctx, VIVS_TS_DEPTH_SURFACE_BASE, z->address); etna_set_state(ctx, VIVS_TS_COLOR_CLEAR_VALUE, 0xff303030); etna_set_state(ctx, VIVS_TS_COLOR_STATUS_BASE, rt_ts->address); etna_set_state(ctx, VIVS_TS_COLOR_SURFACE_BASE, rt->address); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); /* set up texture unit */ etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_TEXTURE); etna_set_state(ctx, VIVS_TE_SAMPLER_SIZE(0), VIVS_TE_SAMPLER_SIZE_WIDTH(tex_base_width)| VIVS_TE_SAMPLER_SIZE_HEIGHT(tex_base_height)); etna_set_state(ctx, VIVS_TE_SAMPLER_LOG_SIZE(0), VIVS_TE_SAMPLER_LOG_SIZE_WIDTH(tex_base_log_width) | VIVS_TE_SAMPLER_LOG_SIZE_HEIGHT(tex_base_log_height)); for(int ix=0; ix<dds->num_mipmaps; ++ix) { etna_set_state(ctx, VIVS_TE_SAMPLER_LOD_ADDR(0,ix), tex->address + dds->slices[0][ix].offset); } etna_set_state(ctx, VIVS_TE_SAMPLER_CONFIG0(0), VIVS_TE_SAMPLER_CONFIG0_TYPE(TEXTURE_TYPE_2D)| VIVS_TE_SAMPLER_CONFIG0_UWRAP(TEXTURE_WRAPMODE_CLAMP_TO_EDGE)| VIVS_TE_SAMPLER_CONFIG0_VWRAP(TEXTURE_WRAPMODE_CLAMP_TO_EDGE)| VIVS_TE_SAMPLER_CONFIG0_MIN(TEXTURE_FILTER_LINEAR)| VIVS_TE_SAMPLER_CONFIG0_MIP(TEXTURE_FILTER_LINEAR)| VIVS_TE_SAMPLER_CONFIG0_MAG(TEXTURE_FILTER_LINEAR)| VIVS_TE_SAMPLER_CONFIG0_FORMAT(tex_format)); etna_set_state(ctx, VIVS_TE_SAMPLER_LOD_CONFIG(0), VIVS_TE_SAMPLER_LOD_CONFIG_MAX((dds->num_mipmaps - 1)<<5) | VIVS_TE_SAMPLER_LOD_CONFIG_MIN(0)); //etna_set_state(ctx, VIVS_TE_SAMPLER_UNK2100(0), 0); //etna_set_state(ctx, VIVS_TE_SAMPLER_UNK2140(0), 0); /* shader setup */ etna_set_state(ctx, VIVS_VS_START_PC, 0x0); etna_set_state(ctx, VIVS_VS_END_PC, vs_size/16); etna_set_state_multi(ctx, VIVS_VS_INPUT_COUNT, 3, (uint32_t[]){ /* VIVS_VS_INPUT_COUNT */ VIVS_VS_INPUT_COUNT_UNK8(1) | VIVS_VS_INPUT_COUNT_COUNT(3), /* VIVS_VS_TEMP_REGISTER_CONTROL */ VIVS_VS_TEMP_REGISTER_CONTROL_NUM_TEMPS(6), /* VIVS_VS_OUTPUT(0) */ VIVS_VS_OUTPUT_O0(4) | VIVS_VS_OUTPUT_O1(0) | VIVS_VS_OUTPUT_O2(1)}); etna_set_state_multi(ctx, VIVS_VS_INST_MEM(0), vs_size/4, vs); etna_set_state(ctx, VIVS_VS_OUTPUT_COUNT, 3); etna_set_state(ctx, VIVS_VS_LOAD_BALANCING, 0xf3f0542); /* depends on number of inputs/outputs/varyings? XXX how exactly */ etna_set_state_multi(ctx, VIVS_VS_UNIFORMS(0), 16, (uint32_t*)&modelviewprojection.m[0][0]); etna_set_state_multi(ctx, VIVS_VS_UNIFORMS(16), 3, (uint32_t*)&normal.m[0][0]); /* u4.xyz */ etna_set_state_multi(ctx, VIVS_VS_UNIFORMS(20), 3, (uint32_t*)&normal.m[1][0]); /* u5.xyz */ etna_set_state_multi(ctx, VIVS_VS_UNIFORMS(24), 3, (uint32_t*)&normal.m[2][0]); /* u6.xyz */ etna_set_state_multi(ctx, VIVS_VS_UNIFORMS(28), 16, (uint32_t*)&modelview.m[0][0]); etna_set_state_f32(ctx, VIVS_VS_UNIFORMS(19), 2.0); /* u4.w */ etna_set_state_f32(ctx, VIVS_VS_UNIFORMS(23), 20.0); /* u5.w */ etna_set_state_f32(ctx, VIVS_VS_UNIFORMS(27), 0.0); /* u6.w */ etna_set_state_f32(ctx, VIVS_VS_UNIFORMS(45), 0.5); /* u11.y */ etna_set_state_f32(ctx, VIVS_VS_UNIFORMS(44), 1.0); /* u11.x */ etna_set_state(ctx, VIVS_VS_INPUT(0), VIVS_VS_INPUT_I0(0) | VIVS_VS_INPUT_I1(1) | VIVS_VS_INPUT_I2(2)); etna_set_state(ctx, VIVS_PS_START_PC, 0x0); etna_set_state_multi(ctx, VIVS_PS_END_PC, 2, (uint32_t[]){ /* VIVS_PS_END_PC */ ps_size/16, /* VIVS_PS_OUTPUT_REG */ 0x1}); etna_set_state_multi(ctx, VIVS_PS_INST_MEM(0), ps_size/4, ps); etna_set_state(ctx, VIVS_PS_INPUT_COUNT, VIVS_PS_INPUT_COUNT_UNK8(31) | VIVS_PS_INPUT_COUNT_COUNT(3)); etna_set_state(ctx, VIVS_PS_TEMP_REGISTER_CONTROL, VIVS_PS_TEMP_REGISTER_CONTROL_NUM_TEMPS(3)); etna_set_state(ctx, VIVS_PS_CONTROL, VIVS_PS_CONTROL_UNK1); etna_set_state_f32(ctx, VIVS_PS_UNIFORMS(0), 1.0); /* u0.x */ etna_set_state(ctx, VIVS_FE_VERTEX_STREAM_BASE_ADDR, vtx->address); /* ADDR_E */ etna_set_state(ctx, VIVS_FE_VERTEX_STREAM_CONTROL, VIVS_FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE((3 + 3 + 2)*4)); etna_set_state(ctx, VIVS_FE_VERTEX_ELEMENT_CONFIG(0), VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_FLOAT | (ENDIAN_MODE_NO_SWAP << VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN__SHIFT) | VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM(0) | VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM(3) | VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_OFF | VIVS_FE_VERTEX_ELEMENT_CONFIG_START(0x0) | VIVS_FE_VERTEX_ELEMENT_CONFIG_END(0xc)); etna_set_state(ctx, VIVS_FE_VERTEX_ELEMENT_CONFIG(1), VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_FLOAT | (ENDIAN_MODE_NO_SWAP << VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN__SHIFT) | VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM(0) | VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM(3) | VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_OFF | VIVS_FE_VERTEX_ELEMENT_CONFIG_START(0xc) | VIVS_FE_VERTEX_ELEMENT_CONFIG_END(0x18)); etna_set_state(ctx, VIVS_FE_VERTEX_ELEMENT_CONFIG(2), VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_FLOAT | (ENDIAN_MODE_NO_SWAP << VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN__SHIFT) | VIVS_FE_VERTEX_ELEMENT_CONFIG_NONCONSECUTIVE | VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM(0) | VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM(2) | VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_OFF | VIVS_FE_VERTEX_ELEMENT_CONFIG_START(0x18) | VIVS_FE_VERTEX_ELEMENT_CONFIG_END(0x20)); for(int prim=0; prim<6; ++prim) { etna_draw_primitives(ctx, PRIMITIVE_TYPE_TRIANGLE_STRIP, prim*4, 2); } #if 0 /* resolve to self */ etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); etna_set_state(ctx, VIVS_RS_CONFIG, VIVS_RS_CONFIG_SOURCE_FORMAT(RS_FORMAT_X8R8G8B8) | VIVS_RS_CONFIG_SOURCE_TILED | VIVS_RS_CONFIG_DEST_FORMAT(RS_FORMAT_X8R8G8B8) | VIVS_RS_CONFIG_DEST_TILED); etna_set_state(ctx, VIVS_RS_SOURCE_STRIDE, (padded_width * 4 * 4) | VIVS_RS_SOURCE_STRIDE_TILING); etna_set_state(ctx, VIVS_RS_DEST_STRIDE, (padded_width * 4 * 4) | VIVS_RS_DEST_STRIDE_TILING); etna_set_state(ctx, VIVS_RS_DITHER(0), 0xffffffff); etna_set_state(ctx, VIVS_RS_DITHER(1), 0xffffffff); etna_set_state(ctx, VIVS_RS_CLEAR_CONTROL, VIVS_RS_CLEAR_CONTROL_MODE_DISABLED); etna_set_state(ctx, VIVS_RS_EXTRA_CONFIG, 0); /* no AA, no endian switch */ etna_set_state(ctx, VIVS_RS_SOURCE_ADDR, rt->address); /* ADDR_A */ etna_set_state(ctx, VIVS_RS_DEST_ADDR, rt->address); /* ADDR_A */ etna_set_state(ctx, VIVS_RS_WINDOW_SIZE, VIVS_RS_WINDOW_SIZE_HEIGHT(padded_height) | VIVS_RS_WINDOW_SIZE_WIDTH(padded_width)); etna_set_state(ctx, VIVS_RS_KICKER, 0xbeebbeeb); etna_set_state(ctx, VIVS_RS_FLUSH_CACHE, VIVS_RS_FLUSH_CACHE_FLUSH); etna_set_state(ctx, VIVS_TS_COLOR_STATUS_BASE, rt_ts->address); /* ADDR_B */ etna_set_state(ctx, VIVS_TS_COLOR_SURFACE_BASE, rt->address); /* ADDR_A */ etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR); etna_set_state(ctx, VIVS_TS_MEM_CONFIG, VIVS_TS_MEM_CONFIG_DEPTH_FAST_CLEAR | VIVS_TS_MEM_CONFIG_DEPTH_16BPP | VIVS_TS_MEM_CONFIG_DEPTH_COMPRESSION); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR); #endif etna_stall(ctx, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); /* copy to screen */ etna_bswap_wait_available(buffers); etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); etna_set_state(ctx, VIVS_RS_CONFIG, VIVS_RS_CONFIG_SOURCE_FORMAT(RS_FORMAT_X8R8G8B8) | VIVS_RS_CONFIG_SOURCE_TILED | VIVS_RS_CONFIG_DEST_FORMAT(RS_FORMAT_X8R8G8B8) | VIVS_RS_CONFIG_SWAP_RB); etna_set_state(ctx, VIVS_RS_SOURCE_STRIDE, (padded_width * 4 * 4) | VIVS_RS_SOURCE_STRIDE_TILING); etna_set_state(ctx, VIVS_RS_DEST_STRIDE, fb.fb_fix.line_length); etna_set_state(ctx, VIVS_RS_DITHER(0), 0xffffffff); etna_set_state(ctx, VIVS_RS_DITHER(1), 0xffffffff); etna_set_state(ctx, VIVS_RS_CLEAR_CONTROL, VIVS_RS_CLEAR_CONTROL_MODE_DISABLED); etna_set_state(ctx, VIVS_RS_EXTRA_CONFIG, 0); /* no AA, no endian switch */ etna_set_state(ctx, VIVS_RS_SOURCE_ADDR, rt->address); /* ADDR_A */ etna_set_state(ctx, VIVS_RS_DEST_ADDR, fb.physical[buffers->backbuffer]); /* ADDR_J */ etna_set_state(ctx, VIVS_RS_WINDOW_SIZE, VIVS_RS_WINDOW_SIZE_HEIGHT(height) | VIVS_RS_WINDOW_SIZE_WIDTH(width)); etna_set_state(ctx, VIVS_RS_KICKER, 0xbeebbeeb); etna_flush(ctx); etna_bswap_queue_swap(buffers); } #ifdef DUMP bmp_dump32(fb.logical[1-backbuffer], width, height, false, "/mnt/sdcard/fb.bmp"); printf("Dump complete\n"); #endif etna_bswap_free(buffers); etna_free(ctx); viv_close(); return 0; }