<commit_before>#include <stdio.h>
#include <stddef.h>
#include <limits.h>
#include <math.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include "awesome.h"

#include <gl.h>
#include "rasterizer.h"
#include "connection.h"

#undef DEBUG_PRINT
#define COVERAGE_PRINT
#undef DUMP_ALL_COMMANDS
#undef SKIP_FPGA_WORK
#undef WARN_SKIPPED_FRAME
#define BREAK_UP_TRIANGLES

static const int32_t DISPLAY_WIDTH = XMAXSCREEN + 1;
static const int32_t DISPLAY_HEIGHT = YMAXSCREEN + 1;

static volatile uint64_t *gpu_protocol_buffer; // The fixed buffer from which the GPU reads commands

// N.B.  This is a const variable meant to be compile-time-only.
// If this variable is changed to be settable at run-time, a
// synchronization point must be added to wait on GPU and copy between
// staging to gpu buffers as necessary.
static const int double_buffer_commands = 1;
static int must_wait_on_gpu = 0;

#define MAX_PROTOCOL_QUAD_COUNT (10 * 1024 * 1024 / sizeof(uint64_t))
static volatile uint64_t staging_protocol_buffer[MAX_PROTOCOL_QUAD_COUNT]; // Optional buffer for protocol double-buffering

static volatile uint64_t *protocol_buffer; // The base of the protocol buffer to be used, either GPU or staging
static volatile uint64_t *protocol_next; // The next location to fill in the protocol buffer

static int rasterizer_start_buffer;

#ifdef COVERAGE_PRINT
static int total_bbox_area = 0;
static int total_triangle_area = 0;
static int broken_count = 0;
#endif

#ifdef BREAK_UP_TRIANGLES
static const int subtriangle_count = 31; // Sweet spot. Must be odd.
static const int max_coverage = 25; // Sweet spot.
static const int min_bbox_area = 1600; // Sweet spot.
#endif

// Compute the point "t" of the way between s0 and s1.
static void interpolate_screen_vertex(screen_vertex *s0, screen_vertex *s1,
    screen_vertex *out, double t)
{
    out->x = (uint16_t) (s0->x + ((int32_t) s1->x - s0->x)*t);
    out->y = (uint16_t) (s0->y + ((int32_t) s1->y - s0->y)*t);
    out->z = (uint32_t) (s0->z + ((int64_t) s1->z - s0->z)*t);
    out->r = (uint8_t) (s0->r + ((int16_t) s1->r - s0->r)*t);
    out->g = (uint8_t) (s0->g + ((int16_t) s1->g - s0->g)*t);
    out->b = (uint8_t) (s0->b + ((int16_t) s1->b - s0->b)*t);
    out->a = (uint8_t) (s0->a + ((int16_t) s1->a - s0->a)*t);

    // To visualize the broken-up triangles.
    if (0) {
	out->r = rand() & 0xFF;
	out->g = rand() & 0xFF;
	out->b = rand() & 0xFF;
    }
}

void gpu_finish_rasterizing()
{
#ifndef SKIP_FPGA_WORK
    // Wait until it's done rasterizing.
#ifdef DEBUG_PRINT
    printf("Waiting for FPGA to switch rasterization to the other buffer.\n");
#endif
    awesome_wait_for_end_of_rasterization();
#endif /* SKIP_FPGA_WORK */
}

void gpu_start()
{
#ifndef SKIP_FPGA_WORK
    awesome_start_rasterizing();
#endif /* SKIP_FPGA_WORK */
}

void gpu_wait()
{
#ifndef SKIP_FPGA_WORK
    // Wait until it's done rasterizing.
#ifdef DEBUG_PRINT
    printf("Waiting for FPGA to finish vsync.\n");
#endif
    awesome_wait_for_end_of_processing();
#endif /* SKIP_FPGA_WORK */
}

static float the_linewidth;
static int pattern_enabled = 0;
static int zbuffer_enabled = 0;

static int min(int a, int b)
{
    return (a < b) ? a : b;
}

static int max(int a, int b)
{
    return (a > b) ? a : b;
}

static float clamp(float v, float low, float high)
{
    return v > high ? high : (v < low ? low : v);
}

void rasterizer_clear(uint8_t r, uint8_t g, uint8_t b)
{
    awesome_clear(&protocol_next, r, g, b);
}

void rasterizer_linewidth(float w)
{
    the_linewidth = w;
}

// Packs four uint16 into a single uint64;
static uint64_t pattern16to64(uint16_t pattern[4])
{
    return
	(((uint64_t) pattern[0]) << 0) |
	(((uint64_t) pattern[1]) << 16) |
	(((uint64_t) pattern[2]) << 32) |
	(((uint64_t) pattern[3]) << 48);
}

void rasterizer_setpattern(uint16_t pattern[16])
{
    awesome_pattern(&protocol_next,
    	pattern16to64(pattern + 0),
    	pattern16to64(pattern + 4),
    	pattern16to64(pattern + 8),
    	pattern16to64(pattern + 12));
}

void rasterizer_pattern(int enable)
{
    // Store now, pass in with DRAW command and primitives
    pattern_enabled = enable;
}

static int framestats_print = 1;
static float framestats_frame_duration_sum = 0.0; 
static float framestats_cpu_duration_sum = 0.0; 
static float framestats_copy_duration_sum = 0.0; 
static float framestats_gpu_duration_sum = 0.0; 
static float framestats_raster_duration_sum = 0.0; 
static float framestats_wait_duration_sum = 0.0; 
static int framestats_duration_count = 0; 
static time_t framestats_previous_print_time;
static struct timespec framestats_previous_frame_end;
static struct timespec framestats_rasterizer_start;
static int framestats_skipped_frames = 0;

double diff_timespecs(struct timespec *t1, struct timespec *t2)		
{		
    return (t1->tv_sec - t2->tv_sec) + (t1->tv_nsec - t2->tv_nsec)/1000000000.0;
}

void rasterizer_swap()
{
    awesome_swap(&protocol_next);
    awesome_end(&protocol_next);

#ifdef COVERAGE_PRINT
    printf("%d bbox / %d triangle = %d%% (%d broken)\n",
    	total_bbox_area, total_triangle_area,
	total_triangle_area*100/total_bbox_area, broken_count);

    total_bbox_area = 0;
    total_triangle_area = 0;
    broken_count = 0;
#endif

    struct timespec now;
    clock_gettime(CLOCK_MONOTONIC, &now);

    if (framestats_print) {
	framestats_cpu_duration_sum += diff_timespecs(&now, &framestats_previous_frame_end);<commit_msg>Avoid divide by zero when displaying statistics.<commit_after>#include <stdio.h>
#include <stddef.h>
#include <limits.h>
#include <math.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include "awesome.h"

#include <gl.h>
#include "rasterizer.h"
#include "connection.h"

#undef DEBUG_PRINT
#define COVERAGE_PRINT
#undef DUMP_ALL_COMMANDS
#undef SKIP_FPGA_WORK
#undef WARN_SKIPPED_FRAME
#define BREAK_UP_TRIANGLES

static const int32_t DISPLAY_WIDTH = XMAXSCREEN + 1;
static const int32_t DISPLAY_HEIGHT = YMAXSCREEN + 1;

static volatile uint64_t *gpu_protocol_buffer; // The fixed buffer from which the GPU reads commands

// N.B.  This is a const variable meant to be compile-time-only.
// If this variable is changed to be settable at run-time, a
// synchronization point must be added to wait on GPU and copy between
// staging to gpu buffers as necessary.
static const int double_buffer_commands = 1;
static int must_wait_on_gpu = 0;

#define MAX_PROTOCOL_QUAD_COUNT (10 * 1024 * 1024 / sizeof(uint64_t))
static volatile uint64_t staging_protocol_buffer[MAX_PROTOCOL_QUAD_COUNT]; // Optional buffer for protocol double-buffering

static volatile uint64_t *protocol_buffer; // The base of the protocol buffer to be used, either GPU or staging
static volatile uint64_t *protocol_next; // The next location to fill in the protocol buffer

static int rasterizer_start_buffer;

#ifdef COVERAGE_PRINT
static int total_bbox_area = 0;
static int total_triangle_area = 0;
static int broken_count = 0;
#endif

#ifdef BREAK_UP_TRIANGLES
static const int subtriangle_count = 31; // Sweet spot. Must be odd.
static const int max_coverage = 25; // Sweet spot.
static const int min_bbox_area = 1600; // Sweet spot.
#endif

// Compute the point "t" of the way between s0 and s1.
static void interpolate_screen_vertex(screen_vertex *s0, screen_vertex *s1,
    screen_vertex *out, double t)
{
    out->x = (uint16_t) (s0->x + ((int32_t) s1->x - s0->x)*t);
    out->y = (uint16_t) (s0->y + ((int32_t) s1->y - s0->y)*t);
    out->z = (uint32_t) (s0->z + ((int64_t) s1->z - s0->z)*t);
    out->r = (uint8_t) (s0->r + ((int16_t) s1->r - s0->r)*t);
    out->g = (uint8_t) (s0->g + ((int16_t) s1->g - s0->g)*t);
    out->b = (uint8_t) (s0->b + ((int16_t) s1->b - s0->b)*t);
    out->a = (uint8_t) (s0->a + ((int16_t) s1->a - s0->a)*t);

    // To visualize the broken-up triangles.
    if (0) {
	out->r = rand() & 0xFF;
	out->g = rand() & 0xFF;
	out->b = rand() & 0xFF;
    }
}

void gpu_finish_rasterizing()
{
#ifndef SKIP_FPGA_WORK
    // Wait until it's done rasterizing.
#ifdef DEBUG_PRINT
    printf("Waiting for FPGA to switch rasterization to the other buffer.\n");
#endif
    awesome_wait_for_end_of_rasterization();
#endif /* SKIP_FPGA_WORK */
}

void gpu_start()
{
#ifndef SKIP_FPGA_WORK
    awesome_start_rasterizing();
#endif /* SKIP_FPGA_WORK */
}

void gpu_wait()
{
#ifndef SKIP_FPGA_WORK
    // Wait until it's done rasterizing.
#ifdef DEBUG_PRINT
    printf("Waiting for FPGA to finish vsync.\n");
#endif
    awesome_wait_for_end_of_processing();
#endif /* SKIP_FPGA_WORK */
}

static float the_linewidth;
static int pattern_enabled = 0;
static int zbuffer_enabled = 0;

static int min(int a, int b)
{
    return (a < b) ? a : b;
}

static int max(int a, int b)
{
    return (a > b) ? a : b;
}

static float clamp(float v, float low, float high)
{
    return v > high ? high : (v < low ? low : v);
}

void rasterizer_clear(uint8_t r, uint8_t g, uint8_t b)
{
    awesome_clear(&protocol_next, r, g, b);
}

void rasterizer_linewidth(float w)
{
    the_linewidth = w;
}

// Packs four uint16 into a single uint64;
static uint64_t pattern16to64(uint16_t pattern[4])
{
    return
	(((uint64_t) pattern[0]) << 0) |
	(((uint64_t) pattern[1]) << 16) |
	(((uint64_t) pattern[2]) << 32) |
	(((uint64_t) pattern[3]) << 48);
}

void rasterizer_setpattern(uint16_t pattern[16])
{
    awesome_pattern(&protocol_next,
    	pattern16to64(pattern + 0),
    	pattern16to64(pattern + 4),
    	pattern16to64(pattern + 8),
    	pattern16to64(pattern + 12));
}

void rasterizer_pattern(int enable)
{
    // Store now, pass in with DRAW command and primitives
    pattern_enabled = enable;
}

static int framestats_print = 1;
static float framestats_frame_duration_sum = 0.0; 
static float framestats_cpu_duration_sum = 0.0; 
static float framestats_copy_duration_sum = 0.0; 
static float framestats_gpu_duration_sum = 0.0; 
static float framestats_raster_duration_sum = 0.0; 
static float framestats_wait_duration_sum = 0.0; 
static int framestats_duration_count = 0; 
static time_t framestats_previous_print_time;
static struct timespec framestats_previous_frame_end;
static struct timespec framestats_rasterizer_start;
static int framestats_skipped_frames = 0;

double diff_timespecs(struct timespec *t1, struct timespec *t2)		
{		
    return (t1->tv_sec - t2->tv_sec) + (t1->tv_nsec - t2->tv_nsec)/1000000000.0;
}

void rasterizer_swap()
{
    awesome_swap(&protocol_next);
    awesome_end(&protocol_next);

#ifdef COVERAGE_PRINT
    if (total_bbox_area != 0) {
	printf("%d bbox / %d triangle = %d%% (%d broken)\n",
	    total_bbox_area, total_triangle_area,
	    total_triangle_area*100/total_bbox_area, broken_count);
    }

    total_bbox_area = 0;
    total_triangle_area = 0;
    broken_count = 0;
#endif

    struct timespec now;
    clock_gettime(CLOCK_MONOTONIC, &now);

    if (framestats_print) {
	framestats_cpu_duration_sum += diff_timespecs(&now, &framestats_previous_frame_end);
{'fraction_non_alphanumeric': 0.11994510521500458, 'fraction_numerical': 0.035224153705397984, 'mean_word_length': 4.23766171538093, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 95, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3422740', 'n_tokens_mistral': 4342, 'n_tokens_neox': 4099, 'n_words': 1086}