--- /dev/null
+#include "util/u_math.h"
+#include "lp_rast_priv.h"
+#include "lp_state_fs.h"
+
+static INLINE int u_bit_scan(unsigned *mask)
+{
+ int i = ffs(*mask) - 1;
+ *mask &= ~(1 << i);
+ return i;
+}
+
+struct tile {
+ int coverage;
+ int overdraw;
+ char data[TILE_SIZE][TILE_SIZE];
+};
+
+static char get_label( int i )
+{
+ static const char *cmd_labels = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ unsigned max_label = (2*26+10);
+
+ if (i < max_label)
+ return cmd_labels[i];
+ else
+ return '?';
+}
+
+
+
+static const char *cmd_names[LP_RAST_OP_MAX] =
+{
+ "clear_color",
+ "clear_zstencil",
+ "triangle_1",
+ "triangle_2",
+ "triangle_3",
+ "triangle_4",
+ "triangle_5",
+ "triangle_6",
+ "triangle_7",
+ "triangle_8",
+ "triangle_3_16",
+ "shade_tile",
+ "shade_tile_opaque",
+ "begin_query",
+ "end_query",
+};
+
+static const char *cmd_name(unsigned cmd)
+{
+ assert(Elements(cmd_names) > cmd);
+ return cmd_names[cmd];
+}
+
+static const struct lp_fragment_shader_variant *
+get_variant( const struct cmd_block *block,
+ int k )
+{
+ if (block->cmd[k] == LP_RAST_OP_SHADE_TILE ||
+ block->cmd[k] == LP_RAST_OP_SHADE_TILE_OPAQUE)
+ return block->arg[k].shade_tile->state->variant;
+
+ if (block->cmd[k] == LP_RAST_OP_TRIANGLE_1 ||
+ block->cmd[k] == LP_RAST_OP_TRIANGLE_2 ||
+ block->cmd[k] == LP_RAST_OP_TRIANGLE_3 ||
+ block->cmd[k] == LP_RAST_OP_TRIANGLE_4 ||
+ block->cmd[k] == LP_RAST_OP_TRIANGLE_5 ||
+ block->cmd[k] == LP_RAST_OP_TRIANGLE_6 ||
+ block->cmd[k] == LP_RAST_OP_TRIANGLE_7)
+ return block->arg[k].triangle.tri->inputs.state->variant;
+
+ return NULL;
+}
+
+
+static boolean
+is_blend( const struct cmd_block *block,
+ int k )
+{
+ const struct lp_fragment_shader_variant *variant = get_variant(block, k);
+
+ if (variant)
+ return variant->key.blend.rt[0].blend_enable;
+
+ return FALSE;
+}
+
+
+
+static void
+debug_bin( const struct cmd_bin *bin )
+{
+ const struct cmd_block *head = bin->head;
+ int i, j = 0;
+
+ debug_printf("bin %d,%d:\n", bin->x, bin->y);
+
+ while (head) {
+ for (i = 0; i < head->count; i++, j++) {
+ debug_printf("%d: %s %s\n", j,
+ cmd_name(head->cmd[i]),
+ is_blend(head, i) ? "blended" : "");
+ }
+ head = head->next;
+ }
+}
+
+
+static void plot(struct tile *tile,
+ int x, int y,
+ char val,
+ boolean blend)
+{
+ if (tile->data[x][y] == ' ')
+ tile->coverage++;
+ else
+ tile->overdraw++;
+
+ tile->data[x][y] = val;
+}
+
+
+
+
+
+
+static int
+debug_shade_tile(int x, int y,
+ const union lp_rast_cmd_arg arg,
+ struct tile *tile,
+ char val)
+{
+ const struct lp_rast_shader_inputs *inputs = arg.shade_tile;
+ boolean blend = inputs->state->variant->key.blend.rt[0].blend_enable;
+ unsigned i,j;
+
+ if (inputs->disable)
+ return 0;
+
+ for (i = 0; i < TILE_SIZE; i++)
+ for (j = 0; j < TILE_SIZE; j++)
+ plot(tile, i, j, val, blend);
+
+ return TILE_SIZE * TILE_SIZE;
+}
+
+static int
+debug_clear_tile(int x, int y,
+ const union lp_rast_cmd_arg arg,
+ struct tile *tile,
+ char val)
+{
+ unsigned i,j;
+
+ for (i = 0; i < TILE_SIZE; i++)
+ for (j = 0; j < TILE_SIZE; j++)
+ plot(tile, i, j, val, FALSE);
+
+ return TILE_SIZE * TILE_SIZE;
+
+}
+
+
+static int
+debug_triangle(int tilex, int tiley,
+ const union lp_rast_cmd_arg arg,
+ struct tile *tile,
+ char val)
+{
+ const struct lp_rast_triangle *tri = arg.triangle.tri;
+ unsigned plane_mask = arg.triangle.plane_mask;
+ struct lp_rast_plane plane[8];
+ int x, y;
+ int count = 0;
+ unsigned i, nr_planes = 0;
+ boolean blend = tri->inputs.state->variant->key.blend.rt[0].blend_enable;
+
+ if (tri->inputs.disable) {
+ /* This triangle was partially binned and has been disabled */
+ return 0;
+ }
+
+ while (plane_mask) {
+ plane[nr_planes] = tri->plane[u_bit_scan(&plane_mask)];
+ plane[nr_planes].c = (plane[nr_planes].c +
+ plane[nr_planes].dcdy * tiley -
+ plane[nr_planes].dcdx * tilex);
+ nr_planes++;
+ }
+
+ for(y = 0; y < TILE_SIZE; y++)
+ {
+ for(x = 0; x < TILE_SIZE; x++)
+ {
+ for (i = 0; i < nr_planes; i++)
+ if (plane[i].c <= 0)
+ goto out;
+
+ plot(tile, x, y, val, blend);
+ count++;
+
+ out:
+ for (i = 0; i < nr_planes; i++)
+ plane[i].c -= plane[i].dcdx;
+ }
+
+ for (i = 0; i < nr_planes; i++) {
+ plane[i].c += plane[i].dcdx * TILE_SIZE;
+ plane[i].c += plane[i].dcdy;
+ }
+ }
+ return count;
+}
+
+
+
+
+
+static void
+do_debug_bin( struct tile *tile,
+ const struct cmd_bin *bin,
+ boolean print_cmds)
+{
+ unsigned k, j = 0;
+ const struct cmd_block *block;
+
+ int tx = bin->x * TILE_SIZE;
+ int ty = bin->y * TILE_SIZE;
+
+ memset(tile->data, ' ', sizeof tile->data);
+ tile->coverage = 0;
+ tile->overdraw = 0;
+
+ for (block = bin->head; block; block = block->next) {
+ for (k = 0; k < block->count; k++, j++) {
+ boolean blend = is_blend(block, k);
+ char val = get_label(j);
+ int count = 0;
+
+ if (print_cmds)
+ debug_printf("%c: %15s", val, cmd_name(block->cmd[k]));
+
+ if (block->cmd[k] == LP_RAST_OP_CLEAR_COLOR ||
+ block->cmd[k] == LP_RAST_OP_CLEAR_ZSTENCIL)
+ count = debug_clear_tile(tx, ty, block->arg[k], tile, val);
+
+ if (block->cmd[k] == LP_RAST_OP_SHADE_TILE ||
+ block->cmd[k] == LP_RAST_OP_SHADE_TILE_OPAQUE)
+ count = debug_shade_tile(tx, ty, block->arg[k], tile, val);
+
+ if (block->cmd[k] == LP_RAST_OP_TRIANGLE_1 ||
+ block->cmd[k] == LP_RAST_OP_TRIANGLE_2 ||
+ block->cmd[k] == LP_RAST_OP_TRIANGLE_3 ||
+ block->cmd[k] == LP_RAST_OP_TRIANGLE_4 ||
+ block->cmd[k] == LP_RAST_OP_TRIANGLE_5 ||
+ block->cmd[k] == LP_RAST_OP_TRIANGLE_6 ||
+ block->cmd[k] == LP_RAST_OP_TRIANGLE_7)
+ count = debug_triangle(tx, ty, block->arg[k], tile, val);
+
+ if (print_cmds) {
+ debug_printf(" % 5d", count);
+
+ if (blend)
+ debug_printf(" blended");
+
+ debug_printf("\n");
+ }
+ }
+ }
+}
+
+void
+lp_debug_bin( const struct cmd_bin *bin)
+{
+ struct tile tile;
+ int x,y;
+
+ if (bin->head) {
+ do_debug_bin(&tile, bin, TRUE);
+
+ debug_printf("------------------------------------------------------------------\n");
+ for (y = 0; y < TILE_SIZE; y++) {
+ for (x = 0; x < TILE_SIZE; x++) {
+ debug_printf("%c", tile.data[y][x]);
+ }
+ debug_printf("|\n");
+ }
+ debug_printf("------------------------------------------------------------------\n");
+
+ debug_printf("each pixel drawn avg %f times\n",
+ ((float)tile.overdraw + tile.coverage)/(float)tile.coverage);
+ }
+}
+
+
+
+
+
+
+/** Return number of bytes used for a single bin */
+static unsigned
+lp_scene_bin_size( const struct lp_scene *scene, unsigned x, unsigned y )
+{
+ struct cmd_bin *bin = lp_scene_get_bin((struct lp_scene *) scene, x, y);
+ const struct cmd_block *cmd;
+ unsigned size = 0;
+ for (cmd = bin->head; cmd; cmd = cmd->next) {
+ size += (cmd->count *
+ (sizeof(uint8_t) + sizeof(union lp_rast_cmd_arg)));
+ }
+ return size;
+}
+
+
+
+void
+lp_debug_draw_bins_by_coverage( struct lp_scene *scene )
+{
+ unsigned x, y;
+ unsigned total = 0;
+ unsigned possible = 0;
+ static unsigned long long _total;
+ static unsigned long long _possible;
+
+ for (x = 0; x < scene->tiles_x; x++)
+ debug_printf("-");
+ debug_printf("\n");
+
+ for (y = 0; y < scene->tiles_y; y++) {
+ for (x = 0; x < scene->tiles_x; x++) {
+ struct cmd_bin *bin = lp_scene_get_bin(scene, x, y);
+ const char *bits = "0123456789";
+ struct tile tile;
+
+ if (bin->head) {
+ //lp_debug_bin(bin);
+
+ do_debug_bin(&tile, bin, FALSE);
+
+ total += tile.coverage;
+ possible += 64*64;
+
+ if (tile.coverage == 64*64)
+ debug_printf("*");
+ else if (tile.coverage) {
+ int bit = tile.coverage/(64.0*64.0)*10;
+ debug_printf("%c", bits[MIN2(bit,10)]);
+ }
+ else
+ debug_printf("?");
+ }
+ else {
+ debug_printf(" ");
+ }
+ }
+ debug_printf("|\n");
+ }
+
+ for (x = 0; x < scene->tiles_x; x++)
+ debug_printf("-");
+ debug_printf("\n");
+
+ debug_printf("this tile total: %u possible %u: percentage: %f\n",
+ total,
+ possible,
+ total * 100.0 / (float)possible);
+
+ _total += total;
+ _possible += possible;
+
+ debug_printf("overall total: %llu possible %llu: percentage: %f\n",
+ _total,
+ _possible,
+ _total * 100.0 / (double)_possible);
+}
+
+
+void
+lp_debug_draw_bins_by_cmd_length( struct lp_scene *scene )
+{
+ unsigned x, y;
+
+ for (y = 0; y < scene->tiles_y; y++) {
+ for (x = 0; x < scene->tiles_x; x++) {
+ const char *bits = " ...,-~:;=o+xaw*#XAWWWWWWWWWWWWWWWW";
+ int sz = lp_scene_bin_size(scene, x, y);
+ int sz2 = util_unsigned_logbase2(sz);
+ debug_printf("%c", bits[MIN2(sz2,32)]);
+ }
+ debug_printf("\n");
+ }
+}
+
+
+void
+lp_debug_bins( struct lp_scene *scene )
+{
+ unsigned x, y;
+
+ for (y = 0; y < scene->tiles_y; y++) {
+ for (x = 0; x < scene->tiles_x; x++) {
+ struct cmd_bin *bin = lp_scene_get_bin(scene, x, y);
+ if (bin->head) {
+ debug_bin(bin);
+ }
+ }
+ }
+}