diff --git a/src/add-ons/accelerants/common/compute_display_timing.cpp b/src/add-ons/accelerants/common/compute_display_timing.cpp index 23e69fcb1c..60f42ad7d8 100644 --- a/src/add-ons/accelerants/common/compute_display_timing.cpp +++ b/src/add-ons/accelerants/common/compute_display_timing.cpp @@ -69,8 +69,6 @@ * These mode timings can then be formatted as an XFree86 modeline * or a mode description for use by fbset(8). * - * - * * NOTES: * * The GTF allows for computation of "margins" (the visible border @@ -85,8 +83,6 @@ * I've implemented the computations but not enabled them, yet. * I should probably enable and test this at some point. * - * - * * TODO: * * o Add support for interlaced modes. @@ -118,21 +114,22 @@ #endif -#define MARGIN_PERCENT 1.8 // % of active vertical image -#define CELL_GRAN 8.0 // assumed character cell granularity -#define MIN_PORCH 1 // minimum front porch -#define V_SYNC_RQD 3 // width of vsync in lines -#define H_SYNC_PERCENT 8.0 // width of hsync as % of total line -#define MIN_VSYNC_PLUS_BP 550.0 // min time of vsync + back porch (microsec) +#define MARGIN_PERCENT 1.8 // % of active vertical image +#define CELL_GRANULARITY 8.0 + // assumed character cell granularity +#define MIN_PORCH 1 // minimum front porch +#define V_SYNC_WIDTH 3 // width of vsync in lines +#define H_SYNC_PERCENT 8.0 // width of hsync as % of total line +#define MIN_VSYNC_PLUS_BACK_PORCH 550.0 // time in microsec + +// C' and M' are part of the Blanking Duty Cycle computation + #define M 600.0 // blanking formula gradient #define C 40.0 // blanking formula offset #define K 128.0 // blanking formula scaling factor #define J 20.0 // blanking formula scaling factor - -// C' and M' are part of the Blanking Duty Cycle computation - -#define C_PRIME (((C - J) * K/256.0) + J) -#define M_PRIME (K/256.0 * M) +#define C_PRIME (((C - J) * K / 256.0) + J) +#define M_PRIME (K / 256.0 * M) /*! As defined by the GTF Timing Standard, compute the Stage 1 Parameters @@ -147,42 +144,14 @@ compute_display_timing(uint32 width, uint32 height, float refresh, || refresh < 25 || refresh > 1000) return B_BAD_VALUE; - int margins = 0; - - float h_pixels_rnd; - float v_lines_rnd; - float v_field_rate_rqd; - float top_margin; - float bottom_margin; - float interlace; - float h_period_est; - float vsync_plus_bp; - float v_back_porch; - float total_v_lines; - float v_field_rate_est; - float h_period; - float v_field_rate; - float v_frame_rate; - float left_margin; - float right_margin; - float total_active_pixels; - float ideal_duty_cycle; - float h_blank; - float total_pixels; - float pixel_freq; - float h_freq; - - float h_sync; - float h_front_porch; - float v_odd_front_porch_lines; + bool margins = false; // 1. In order to give correct results, the number of horizontal // pixels requested is first processed to ensure that it is divisible // by the character size, by rounding it to the nearest character // cell boundary: // [H PIXELS RND] = ((ROUND([H PIXELS]/[CELL GRAN RND],0))*[CELLGRAN RND]) - h_pixels_rnd = rint((float)width / CELL_GRAN) * CELL_GRAN; - TRACE("[H PIXELS RND] %g\n", h_pixels_rnd); + width = (uint32)(rint(width / CELL_GRANULARITY) * CELL_GRANULARITY); // 2. If interlace is requested, the number of vertical lines assumed // by the calculation must be halved, as the computation calculates @@ -190,133 +159,99 @@ compute_display_timing(uint32 width, uint32 height, float refresh, // number of lines is rounded to the nearest integer. // [V LINES RND] = IF([INT RQD?]="y", ROUND([V LINES]/2,0), // ROUND([V LINES],0)) - v_lines_rnd = interlaced - ? (double)height / 2.0 : (double)height; - TRACE("[V LINES RND] %g\n", v_lines_rnd); + float verticalLines = interlaced ? (double)height / 2.0 : (double)height; // 3. Find the frame rate required: // [V FIELD RATE RQD] = IF([INT RQD?]="y", [I/P FREQ RQD]*2, // [I/P FREQ RQD]) - v_field_rate_rqd = interlaced ? refresh * 2.0 : refresh; - TRACE("[V FIELD RATE RQD] %g\n", v_field_rate_rqd); + float verticalFieldRate = interlaced ? refresh * 2.0 : refresh; // 4. Find number of lines in Top margin: // [TOP MARGIN (LINES)] = IF([MARGINS RQD?]="Y", // ROUND(([MARGIN%]/100*[V LINES RND]),0), 0) - top_margin = margins ? rint(MARGIN_PERCENT / 100.0 * v_lines_rnd) : 0.0; - TRACE("[TOP MARGIN (LINES)] %g\n", top_margin); + float topMargin = margins ? rint(MARGIN_PERCENT / 100.0 * verticalLines) + : 0.0; // 5. Find number of lines in Bottom margin: // [BOT MARGIN (LINES)] = IF([MARGINS RQD?]="Y", // ROUND(([MARGIN%]/100*[V LINES RND]),0), 0) - bottom_margin = margins ? rint(MARGIN_PERCENT/100.0 * v_lines_rnd) : 0.0; - TRACE("[BOT MARGIN (LINES)] %g\n", bottom_margin); + float bottomMargin = margins ? rint(MARGIN_PERCENT / 100.0 * verticalLines) + : 0.0; // 6. If interlace is required, then set variable [INTERLACE]=0.5: // [INTERLACE]=(IF([INT RQD?]="y",0.5,0)) - interlace = interlaced ? 0.5 : 0.0; - TRACE("[INTERLACE] %g\n", interlace); + float interlace = interlaced ? 0.5 : 0.0; // 7. Estimate the Horizontal period // [H PERIOD EST] = ((1/[V FIELD RATE RQD]) - [MIN VSYNC+BP]/1000000) // / ([V LINES RND] + (2*[TOP MARGIN (LINES)]) // + [MIN PORCH RND]+[INTERLACE]) * 1000000 - h_period_est = (((1.0 / v_field_rate_rqd) - (MIN_VSYNC_PLUS_BP / 1000000.0)) - / (v_lines_rnd + (2 * top_margin) + MIN_PORCH + interlace) * 1000000.0); - TRACE("[H PERIOD EST] %g\n", h_period_est); + float horizontalPeriodEstimate = (1.0 / verticalFieldRate + - MIN_VSYNC_PLUS_BACK_PORCH / 1000000.0) + / (verticalLines + (2 * topMargin) + MIN_PORCH + interlace) * 1000000.0; // 8. Find the number of lines in V sync + back porch: // [V SYNC+BP] = ROUND(([MIN VSYNC+BP]/[H PERIOD EST]),0) - vsync_plus_bp = rint(MIN_VSYNC_PLUS_BP/h_period_est); - TRACE("[V SYNC+BP] %g\n", vsync_plus_bp); - - // 9. Find the number of lines in V back porch alone: - // [V BACK PORCH] = [V SYNC+BP] - [V SYNC RND] - // XXX is "[V SYNC RND]" a typo? should be [V SYNC RQD]? - v_back_porch = vsync_plus_bp - V_SYNC_RQD; - TRACE("[V BACK PORCH] %g\n", v_back_porch); + float verticalSyncPlusBackPorch = rint(MIN_VSYNC_PLUS_BACK_PORCH + / horizontalPeriodEstimate); // 10. Find the total number of lines in Vertical field period: // [TOTAL V LINES] = [V LINES RND] + [TOP MARGIN (LINES)] // + [BOT MARGIN (LINES)] + [V SYNC+BP] + [INTERLACE] + [MIN PORCH RND] - total_v_lines = v_lines_rnd + top_margin + bottom_margin + vsync_plus_bp + - interlace + MIN_PORCH; - TRACE("[TOTAL V LINES] %g\n", total_v_lines); + float totalVerticalLines = verticalLines + topMargin + bottomMargin + + verticalSyncPlusBackPorch + interlace + MIN_PORCH; // 11. Estimate the Vertical field frequency: // [V FIELD RATE EST] = 1 / [H PERIOD EST] / [TOTAL V LINES] * 1000000 - v_field_rate_est = 1.0 / h_period_est / total_v_lines * 1000000.0; - TRACE("[V FIELD RATE EST] %g\n", v_field_rate_est); + float verticalFieldRateEstimate = 1.0 / horizontalPeriodEstimate + / totalVerticalLines * 1000000.0; // 12. Find the actual horizontal period: // [H PERIOD] = [H PERIOD EST] / ([V FIELD RATE RQD] / [V FIELD RATE EST]) - h_period = h_period_est / (v_field_rate_rqd / v_field_rate_est); - TRACE("[H PERIOD] %g\n", h_period); - - // 13. Find the actual Vertical field frequency: - // [V FIELD RATE] = 1 / [H PERIOD] / [TOTAL V LINES] * 1000000 - v_field_rate = 1.0 / h_period / total_v_lines * 1000000.0; - TRACE("[V FIELD RATE] %g\n", v_field_rate); - - // 14. Find the Vertical frame frequency: - // [V FRAME RATE] = (IF([INT RQD?]="y", [V FIELD RATE]/2, [V FIELD RATE])) - v_frame_rate = interlaced ? v_field_rate / 2.0 : v_field_rate; - TRACE("[V FRAME RATE] %g\n", v_frame_rate); + float horizontalPeriod = horizontalPeriodEstimate + / (verticalFieldRate / verticalFieldRateEstimate); // 15. Find number of pixels in left margin: // [LEFT MARGIN (PIXELS)] = (IF( [MARGINS RQD?]="Y", // (ROUND( ([H PIXELS RND] * [MARGIN%] / 100 / // [CELL GRAN RND]),0)) * [CELL GRAN RND], 0)) - left_margin = margins - ? rint(h_pixels_rnd * MARGIN_PERCENT / 100.0 / CELL_GRAN) * CELL_GRAN - : 0.0; - TRACE("[LEFT MARGIN (PIXELS)] %g\n", left_margin); + float leftMargin = margins ? rint(width * MARGIN_PERCENT / 100.0 + / CELL_GRANULARITY) * CELL_GRANULARITY : 0.0; // 16. Find number of pixels in right margin: // [RIGHT MARGIN (PIXELS)] = (IF( [MARGINS RQD?]="Y", // (ROUND( ([H PIXELS RND] * [MARGIN%] / 100 / // [CELL GRAN RND]),0)) * [CELL GRAN RND], 0)) - right_margin = margins - ? rint(h_pixels_rnd * MARGIN_PERCENT / 100.0 / CELL_GRAN) * CELL_GRAN - : 0.0; - TRACE("[RIGHT MARGIN (PIXELS)] %g\n", right_margin); + float rightMargin = margins ? rint(width * MARGIN_PERCENT / 100.0 + / CELL_GRANULARITY) * CELL_GRANULARITY : 0.0; // 17. Find total number of active pixels in image and left and right // margins: // [TOTAL ACTIVE PIXELS] = [H PIXELS RND] + [LEFT MARGIN (PIXELS)] // + [RIGHT MARGIN (PIXELS)] - total_active_pixels = h_pixels_rnd + left_margin + right_margin; - TRACE("[TOTAL ACTIVE PIXELS] %g\n", total_active_pixels); + float totalActivePixels = width + leftMargin + rightMargin; // 18. Find the ideal blanking duty cycle from the blanking duty cycle // equation: // [IDEAL DUTY CYCLE] = [C'] - ([M']*[H PERIOD]/1000) - ideal_duty_cycle = C_PRIME - (M_PRIME * h_period / 1000.0); - TRACE("[IDEAL DUTY CYCLE] %g\n", ideal_duty_cycle); + float idealDutyCycle = C_PRIME - (M_PRIME * horizontalPeriod / 1000.0); // 19. Find the number of pixels in the blanking time to the nearest // double character cell: // [H BLANK (PIXELS)] = (ROUND(([TOTAL ACTIVE PIXELS] // * [IDEAL DUTY CYCLE] / (100-[IDEAL DUTY CYCLE]) // / (2*[CELL GRAN RND])), 0)) * (2*[CELL GRAN RND]) - h_blank = rint(total_active_pixels * ideal_duty_cycle - / (100.0 - ideal_duty_cycle) / (2.0 * CELL_GRAN)) * (2.0 * CELL_GRAN); - TRACE("[H BLANK (PIXELS)] %g\n", h_blank); + float horizontalBlank = rint(totalActivePixels * idealDutyCycle + / (100.0 - idealDutyCycle) / (2.0 * CELL_GRANULARITY)) + * (2.0 * CELL_GRANULARITY); // 20. Find total number of pixels: // [TOTAL PIXELS] = [TOTAL ACTIVE PIXELS] + [H BLANK (PIXELS)] - total_pixels = total_active_pixels + h_blank; - TRACE("[TOTAL PIXELS] %g\n", total_pixels); + float totalPixels = totalActivePixels + horizontalBlank; // 21. Find pixel clock frequency: // [PIXEL FREQ] = [TOTAL PIXELS] / [H PERIOD] - pixel_freq = total_pixels / h_period; - TRACE("[PIXEL FREQ] %g\n", pixel_freq); - - // 22. Find horizontal frequency: - // [H FREQ] = 1000 / [H PERIOD] - h_freq = 1000.0 / h_period; - TRACE("[H FREQ] %g\n", h_freq); + float pixelFrequency = totalPixels / horizontalPeriod; // Stage 1 computations are now complete; I should really pass // the results to another function and do the Stage 2 @@ -326,31 +261,30 @@ compute_display_timing(uint32 width, uint32 height, float refresh, // 17. Find the number of pixels in the horizontal sync period: // [H SYNC (PIXELS)] =(ROUND(([H SYNC%] / 100 * [TOTAL PIXELS] // / [CELL GRAN RND]),0))*[CELL GRAN RND] - h_sync = rint(H_SYNC_PERCENT/100.0 * total_pixels / CELL_GRAN) * CELL_GRAN; - TRACE("[H SYNC (PIXELS)] %g\n", h_sync); + float horizontalSync = rint(H_SYNC_PERCENT / 100.0 * totalPixels + / CELL_GRANULARITY) * CELL_GRANULARITY; // 18. Find the number of pixels in the horizontal front porch period: // [H FRONT PORCH (PIXELS)] = ([H BLANK (PIXELS)]/2)-[H SYNC (PIXELS)] - h_front_porch = (h_blank / 2.0) - h_sync; - TRACE("[H FRONT PORCH (PIXELS)] %g\n", h_front_porch); + float horizontalFrontPorch = (horizontalBlank / 2.0) - horizontalSync; // 36. Find the number of lines in the odd front porch period: // [V ODD FRONT PORCH(LINES)]=([MIN PORCH RND]+[INTERLACE]) - v_odd_front_porch_lines = MIN_PORCH + interlace; - TRACE("[V ODD FRONT PORCH(LINES)] %g\n", v_odd_front_porch_lines); + float verticalOddFrontPorchLines = MIN_PORCH + interlace; // finally, pack the results in the mode struct - timing->pixel_clock = uint32(pixel_freq * 1000); - timing->h_display = (uint16)h_pixels_rnd; - timing->h_sync_start = (uint16)(h_pixels_rnd + h_front_porch); - timing->h_sync_end = (uint16)(h_pixels_rnd + h_front_porch + h_sync); - timing->h_total = (uint16)total_pixels; - timing->v_display = (uint16)v_lines_rnd; - timing->v_sync_start = (uint16)(v_lines_rnd + v_odd_front_porch_lines); - timing->v_sync_end = (uint16)(v_lines_rnd + v_odd_front_porch_lines - + V_SYNC_RQD); - timing->v_total = (uint16)total_v_lines; + timing->pixel_clock = uint32(pixelFrequency * 1000); + timing->h_display = (uint16)width; + timing->h_sync_start = (uint16)(width + horizontalFrontPorch); + timing->h_sync_end + = (uint16)(width + horizontalFrontPorch + horizontalSync); + timing->h_total = (uint16)totalPixels; + timing->v_display = (uint16)verticalLines; + timing->v_sync_start = (uint16)(verticalLines + verticalOddFrontPorchLines); + timing->v_sync_end + = (uint16)(verticalLines + verticalOddFrontPorchLines + V_SYNC_WIDTH); + timing->v_total = (uint16)totalVerticalLines; timing->flags = B_POSITIVE_HSYNC | B_POSITIVE_VSYNC | (interlace ? B_TIMING_INTERLACED : 0);