#ifdef WIN32 #define WIN32_LEAN_AND_MEAN #include #endif #include #include #include #include "prof.h" #include "prof_internal.h" #pragma warning(disable:4305; disable:4244) // use factor to compute a glow amount static int get_colors(float factor, float text_color_ret[3], float glow_color_ret[3], float *glow_alpha_ret) { const float GLOW_RANGE = 0.5f; const float GLOW_ALPHA_MAX = 0.5f; float glow_alpha; int i; float hot[3] = {1, 1.0, 0.9}; float cold[3] = {0.15, 0.9, 0.15}; float glow_cold[3] = {0.5f, 0.5f, 0}; float glow_hot[3] = {1.0f, 1.0f, 0}; if (factor < 0) factor = 0; if (factor > 1) factor = 1; for (i=0; i < 3; ++i) text_color_ret[i] = cold[i] + (hot[i] - cold[i]) * factor; // Figure out whether to start up the glow as well. glow_alpha = (factor - GLOW_RANGE) / (1 - GLOW_RANGE); if (glow_alpha < 0) { *glow_alpha_ret = 0; return 0; } for (i=0; i < 3; ++i) glow_color_ret[i] = glow_cold[i] + (glow_hot[i] - glow_cold[i]) * factor; *glow_alpha_ret = glow_alpha * GLOW_ALPHA_MAX; return 1; } static void draw_rectangle(float x0, float y0, float x1, float y1) { // FACE_CULL is disabled so winding doesn't matter glVertex2f(x0, y0); glVertex2f(x1, y0); glVertex2f(x1, y1); glVertex2f(x0, y1); } typedef struct { float x0,y0; float sx,sy; } GraphLocation; static void graph_func(int id, int x0, int x1, float *values, void *data) { GraphLocation *loc = (GraphLocation *) data; int i, r,g,b; // trim out values that are under 0.2 ms to accelerate rendering while (x0 < x1 && (*values < 0.0002f)) { ++x0; ++values; } while (x1 > x0 && (values[x1-1-x0] < 0.0002f)) --x1; if (id == 0) glColor4f(1,1,1,0.5); else { if (x0 == x1) return; id = (id >> 8) + id; r = id * 37; g = id * 59; b = id * 45; #pragma warning(disable:4761) glColor3ub((r & 127) + 80, (g & 127) + 80, (b & 127) + 80); } glBegin(GL_LINE_STRIP); if (x0 == x1) { float x,y; x = loc->x0 + x0 * loc->sx; y = loc->y0 + values[0] * loc->sy; glVertex2f(x,loc->y0); glVertex2f(x, y); } for (i=0; i < x1-x0; ++i) { float x,y; x = loc->x0 + (i+x0) * loc->sx; y = loc->y0 + values[i] * loc->sy; glVertex2f(x,y); } glEnd(); } Prof_extern_C void Prof_draw_graph_gl(float sx, float sy, float x_spacing, float y_spacing) { #ifdef Prof_ENABLED Prof_Begin(iprof_draw_graph) GraphLocation loc = { sx, sy, x_spacing, y_spacing * 1000 }; Prof_graph(128, graph_func, &loc); Prof_End #endif } // float to string conversion with sprintf() was // taking up 10-20% of the Prof_draw time, so I // wrote a faster float-to-string converter static char int_to_string[100][4]; static char int_to_string_decimal[100][4]; static char int_to_string_mid_decimal[100][4]; static void int_to_string_init(void) { int i; for (i=0; i < 100; ++i) { sprintf(int_to_string[i], "%d", i); sprintf(int_to_string_decimal[i], ".%02d", i); sprintf(int_to_string_mid_decimal[i], "%d.%d", i/10, i % 10); } } static char *formats[5] = { "%.0f", "%.1f", "%.2f", "%.3f", "%.4f", }; static void float_to_string(char *buf, float num, int precision) { int x,y; switch(precision) { case 2: if (num < 0 || num >= 100) break; x = num; y = (num - x) * 100; strcpy(buf, int_to_string[x]); strcat(buf, int_to_string_decimal[y]); return; case 3: if (num < 0 || num >= 10) break; num *= 10; x = num; y = (num - x) * 100; strcpy(buf, int_to_string_mid_decimal[x]); strcat(buf, int_to_string_decimal[y]+1); return; case 4: if (num < 0 || num >= 1) break; num *= 100; x = num; y = (num - x) * 100; buf[0] = '0'; strcpy(buf+1, int_to_string_decimal[x]); strcat(buf, int_to_string_decimal[y]+1); return; } sprintf(buf, formats[precision], num); } Prof_extern_C void Prof_draw_gl(float sx, float sy, float full_width, float height, float line_spacing, int precision, void (*printText)(float x, float y, char *str), float (*textWidth)(char *str)) { #ifdef Prof_ENABLED Prof_Begin(iprof_draw) int i,j,n,o; GLuint cull, texture; float backup_sy; float field_width = textWidth("5555.55"); float name_width = full_width - field_width * 3; float plus_width = textWidth("+"); int max_records; Prof_Report *pob; if (!int_to_string[0][0]) int_to_string_init(); if (precision < 1) precision = 1; if (precision > 4) precision = 4; // disable face culling to avoid having to get winding correct texture = glIsEnabled(GL_TEXTURE_2D); cull = glIsEnabled(GL_CULL_FACE); if (cull == GL_TRUE) { glDisable(GL_CULL_FACE); } pob = Prof_create_report(); for (i=0; i < NUM_TITLE; ++i) { if (pob->title[i]) { float header_x0 = sx; float header_x1 = header_x0 + full_width; if (i == 0) glColor4f(0.1f, 0.3f, 0, 0.85); else glColor4f(0.2f, 0.1f, 0.1f, 0.85); glBegin(GL_QUADS); draw_rectangle(header_x0, sy-2, header_x1, sy-line_spacing+2); glEnd(); if (i == 0) glColor4f(0.6, 0.4, 0, 0); else glColor4f(0.8f, 0.1f, 0.1f, 0); printText(sx+2, sy, pob->title[i]); sy += 1.5*line_spacing; height -= abs(line_spacing)*1.5; } } max_records = height / abs(line_spacing); o = 0; n = pob->num_record; if (n > max_records) n = max_records; if (pob->hilight >= o + n) { o = pob->hilight - n + 1; } backup_sy = sy; // Draw the background colors for the zone data. glDisable(GL_TEXTURE_2D); glBegin(GL_QUADS); glColor4f(0,0,0,0.85); draw_rectangle(sx, sy, sx + full_width, sy - line_spacing); sy += line_spacing; for (i = 0; i < n; i++) { float y0, y1; if (i & 1) { glColor4f(0.1, 0.1f, 0.2, 0.85); } else { glColor4f(0.1f, 0.1f, 0.3, 0.85); } if (i+o == pob->hilight) glColor4f(0.3f, 0.3f, 0.1f, 0.85); y0 = sy; y1 = sy - line_spacing; draw_rectangle(sx, y0, sx + full_width, y1); sy += line_spacing; } glEnd(); sy = backup_sy; glColor4f(0.7,0.7,0.7,0); if (pob->header[0]) printText(sx+8, sy, pob->header[0]); for (j=1; j < NUM_HEADER; ++j) if (pob->header[j]) printText(sx + name_width + field_width * (j-1) + field_width/2 - textWidth(pob->header[j])/2, sy, pob->header[j]); sy += line_spacing; for (i = 0; i < n; i++) { char buf[256], *b = buf; Prof_Report_Record *r = &pob->record[i+o]; float text_color[3], glow_color[3]; float glow_alpha; float x = sx + textWidth(" ") * r->indent + plus_width/2; if (r->prefix) { buf[0] = r->prefix; ++b; } else { x += plus_width; } if (r->number) sprintf(b, "%s (%d)", r->name, r->number); else sprintf(b, "%s", r->name); if (get_colors(r->heat, text_color, glow_color, &glow_alpha)) { glColor4f(glow_color[0], glow_color[1], glow_color[2], glow_alpha); //printText(x+2, sy-1, buf); printText(x+1, sy, buf); } glColor3fv(text_color); printText(x + 1, sy, buf); for (j=0; j < NUM_VALUES; ++j) { if (r->value_flag & (1 << j)) { int pad; float_to_string(buf, r->values[j], j == 2 ? 2 : precision); pad = field_width- plus_width - textWidth(buf); if (r->indent) pad += plus_width; printText(sx + pad + name_width + field_width * j, sy, buf); } } sy += line_spacing; } Prof_free_report(pob); if (cull == GL_TRUE) glEnable(GL_CULL_FACE); if (texture == GL_TRUE) glEnable(GL_TEXTURE_2D); Prof_End #endif }