+
+#if !CONFIG_EMBEDDED
+
+// redraw progress meter between pixels x1, x2, position at x3
+static void
+vc_draw_progress_meter(unsigned int flags, int x1, int x2, int x3)
+{
+ const unsigned char * data;
+ int x, w;
+ int ox, oy;
+ int endCapPos;
+ int onoff;
+ // 1 rounded fill, 0 square end
+ int style = (0 == (2 & vc_progress_withmeter));
+
+ ox = ((vinfo.v_width - (kProgressBarWidth * vc_uiscale)) / 2);
+ oy = vinfo.v_height - (vinfo.v_height / 3) - ((kProgressBarHeight * vc_uiscale) / 2);
+
+ if (kDataBack == flags)
+ {
+ // restore back bits
+ vc_blit_rect(ox + x1, oy, x1,
+ x2, (kProgressBarHeight * vc_uiscale), 0, (kProgressBarWidth * vc_uiscale),
+ NULL, vc_progressmeter_backbuffer, flags);
+ return;
+ }
+
+ for (x = x1; x < x2; x += w)
+ {
+ onoff = (x < x3);
+ endCapPos = ((style && onoff) ? x3 : (kProgressBarWidth * vc_uiscale));
+ if (x < (kProgressBarCapWidth * vc_uiscale))
+ {
+ if (x2 < (kProgressBarCapWidth * vc_uiscale))
+ w = x2 - x;
+ else
+ w = (kProgressBarCapWidth * vc_uiscale) - x;
+ data = progressmeter_leftcap[vc_uiscale >= 2][onoff];
+ data += x;
+ vc_blit_rect(ox + x, oy, x, w,
+ (kProgressBarHeight * vc_uiscale),
+ (kProgressBarCapWidth * vc_uiscale),
+ (kProgressBarWidth * vc_uiscale),
+ data, vc_progressmeter_backbuffer, flags);
+ }
+ else if (x < (endCapPos - (kProgressBarCapWidth * vc_uiscale)))
+ {
+ if (x2 < (endCapPos - (kProgressBarCapWidth * vc_uiscale)))
+ w = x2 - x;
+ else
+ w = (endCapPos - (kProgressBarCapWidth * vc_uiscale)) - x;
+ data = progressmeter_middle[vc_uiscale >= 2][onoff];
+ vc_blit_rect(ox + x, oy, x, w,
+ (kProgressBarHeight * vc_uiscale),
+ 1,
+ (kProgressBarWidth * vc_uiscale),
+ data, vc_progressmeter_backbuffer, flags);
+ }
+ else
+ {
+ w = endCapPos - x;
+ data = progressmeter_rightcap[vc_uiscale >= 2][onoff];
+ data += x - (endCapPos - (kProgressBarCapWidth * vc_uiscale));
+ vc_blit_rect(ox + x, oy, x, w,
+ (kProgressBarHeight * vc_uiscale),
+ (kProgressBarCapWidth * vc_uiscale),
+ (kProgressBarWidth * vc_uiscale),
+ data, vc_progressmeter_backbuffer, flags);
+ }
+ }
+}
+
+extern void IORecordProgressBackbuffer(void * buffer, size_t size, uint32_t theme);
+
+static void
+internal_enable_progressmeter(int new_value)
+{
+ spl_t s;
+ void * new_buffer;
+ boolean_t stashBackbuffer;
+
+ stashBackbuffer = FALSE;
+ new_buffer = NULL;
+ if (new_value)
+ {
+ new_buffer = kalloc((kProgressBarWidth * vc_uiscale)
+ * (kProgressBarHeight * vc_uiscale) * sizeof(int));
+ }
+
+ s = splhigh();
+ simple_lock(&vc_progress_lock);
+
+ if (kProgressMeterUser == new_value)
+ {
+ if (gc_enabled || !gc_acquired || !gc_graphics_boot
+ || (kProgressMeterKernel == vc_progressmeter_enable)) new_value = vc_progressmeter_enable;
+ }
+
+ if (new_value != vc_progressmeter_enable)
+ {
+ if (new_value)
+ {
+ if (kProgressMeterOff == vc_progressmeter_enable)
+ {
+ vc_progressmeter_backbuffer = new_buffer;
+ vc_draw_progress_meter(kDataAlpha | kSave, 0, (kProgressBarWidth * vc_uiscale), 0);
+ new_buffer = NULL;
+ vc_progressmeter_drawn = 0;
+ }
+ vc_progressmeter_enable = new_value;
+ }
+ else if (vc_progressmeter_backbuffer)
+ {
+ if (kProgressMeterUser == vc_progressmeter_enable)
+ {
+ vc_draw_progress_meter(kDataBack, 0, (kProgressBarWidth * vc_uiscale), vc_progressmeter_drawn);
+ }
+ else stashBackbuffer = TRUE;
+ new_buffer = vc_progressmeter_backbuffer;
+ vc_progressmeter_backbuffer = NULL;
+ vc_progressmeter_enable = FALSE;
+ }
+ }
+
+ simple_unlock(&vc_progress_lock);
+ splx(s);
+
+ if (new_buffer)
+ {
+ if (stashBackbuffer) IORecordProgressBackbuffer(new_buffer,
+ (kProgressBarWidth * vc_uiscale)
+ * (kProgressBarHeight * vc_uiscale)
+ * sizeof(int),
+ vc_progress_white);
+ kfree(new_buffer, (kProgressBarWidth * vc_uiscale)
+ * (kProgressBarHeight * vc_uiscale) * sizeof(int));
+ }
+}
+
+static void
+internal_set_progressmeter(int new_value)
+{
+ int x1, x3;
+ int capRedraw;
+ // 1 rounded fill, 0 square end
+ int style = (0 == (2 & vc_progress_withmeter));
+
+ if ((new_value < 0) || (new_value > kProgressMeterMax)) return;
+
+ if (vc_progressmeter_enable)
+ {
+ vc_progressmeter_value = new_value;
+
+ capRedraw = (style ? (kProgressBarCapWidth * vc_uiscale) : 0);
+ x3 = (((kProgressBarWidth * vc_uiscale) - 2 * capRedraw) * vc_progressmeter_value) / kProgressMeterMax;
+ x3 += (2 * capRedraw);
+
+ if (x3 > vc_progressmeter_drawn)
+ {
+ x1 = capRedraw;
+ if (x1 > vc_progressmeter_drawn) x1 = vc_progressmeter_drawn;
+ vc_draw_progress_meter(kDataAlpha, vc_progressmeter_drawn - x1, x3, x3);
+ }
+ else
+ {
+ vc_draw_progress_meter(kDataAlpha, x3 - capRedraw, vc_progressmeter_drawn, x3);
+ }
+ vc_progressmeter_drawn = x3;
+ }
+}
+
+void
+vc_enable_progressmeter(int new_value)
+{
+ if (kProgressMeterKernel == vc_progressmeter_enable)
+ {
+ vc_progressmeter_hold = new_value;
+ }
+ else
+ {
+ internal_enable_progressmeter(new_value ? kProgressMeterUser : kProgressMeterOff);
+ }
+}
+
+void
+vc_set_progressmeter(int new_value)
+{
+ spl_t s;
+
+ s = splhigh();
+ simple_lock(&vc_progress_lock);
+
+ if (vc_progressmeter_enable && (kProgressMeterKernel != vc_progressmeter_enable))
+ {
+ internal_set_progressmeter((new_value * kProgressMeterMax) / 100);
+ }
+
+ simple_unlock(&vc_progress_lock);
+ splx(s);
+}
+
+#endif /* !CONFIG_EMBEDDED */
+
+
+