[parisc-linux] Voodoo2 (was: Question ...)

Alan Cox alan@lxorguk.ukuu.org.uk
24 Aug 2002 15:14:52 +0100


On Sat, 2002-08-24 at 05:13, B. Douglas Hilton wrote:
> Most of the HP graphics cards used this top-secret
> "color recovery technology" which used a special
> dithering method to reduce graphics data to 8bpp,
> then the card somehow restored it to 24bpp. What

The required algorithm is on the HP web site with complete C code for
doing the dither. 

http://www.hp.com/workstations/support/documentation/manuals/user_guides/graphics/GAG11/3_XWindows11.html#HPColorRecovery

Kudos to HP's manual writers. The only bits that are not directly
covered is whether the processing is automatic or we have to bang bits
on the video board to turn on the modes



unsigned char dither_pixel_for_CR(RedValue,GreenValue,BlueValue,Xp,Yp)
  int   RedValue, GreenValue, BlueValue, Xp, Yp;
{
    static short        dither_red[2][16] = {
      {-16,  4, -1, 11,-14,  6, -3,  9,-15,  5, -2, 10,-13,  7, -4,  8},
      { 15, -5,  0,-12, 13, -7,  2,-10, 14, -6,  1,-11, 12, -8,  3,
-9}};
    static short        dither_green[2][16] = {
      { 11,-15,  7, -3,  8,-14,  4, -2, 10,-16,  6, -4,  9,-13,  5, -1},
      {-12, 14, -8,  2, -9, 13, -5,  1,-11, 15, -7,  3,-10, 12, -6, 
0}};
    static short        dither_blue[2][16] = {
      { -3,  9,-13,  7, -1, 11,-15,  5, -4,  8,-14,  6, -2, 10,-16,  4},
      {  2,-10, 12, -8,  0,-12, 14, -6,  3, -9, 13, -7,  1,-11, 15, -5}
};
    int                 red, green, blue;
    int                 x_dither_table, y_dither_table;
    unsigned char       pixel;

    /* Determine the dither table entries to use based on the pixel
address */
    x_dither_table = Xp % 16;   /* X Pixel Address MOD 16 */
    y_dither_table = Yp % 2;    /* Y Pixel Address MOD 2 */

    /* Start with the initial values as supplied by the calling routine
*/
    red   = RedValue;
    green = GreenValue;
    blue  = BlueValue;

    /* Generate the red dither value */
    red += dither_red[y_dither_table][x_dither_table];
    /* Check for overflow or underflow on red value */
    if (red > 0xff) red = 0xff;
    if (red < 0x00) red = 0x00;

    /* Generate the green dither value */
    green += dither_green[y_dither_table][x_dither_table];
    /* Check for overflow or underflow on green value */
    if (green > 0xff) green = 0xff;
    if (green < 0x00) green = 0x00;

    /* Generate the blue dither value */
    blue += (dither_blue[y_dither_table][x_dither_table]<<1);
    /* Check for overflow or underflow on blue value */
    if (blue > 0xff) blue = 0xff;
    if (blue < 0x00) blue = 0x00;

    /* Generate the pixel value by "or"ing the values together */
    pixel = ((red & 0xE0) | ((green & 0xE0) >> 3) | ((blue & 0xC0) >>
6));
    return(pixel);
}

For HCRX the code is

unsigned char dither_pixel_for_CR(RedValue,GreenValue,BlueValue,Xp,Yp)
  int           RedValue,GreenValueBlueValue,Xp,Yp;
{
    static short        dither_red[2][16] = {
      {-16,  4, -1, 11,-14,  6, -3,  9,-15,  5, -2, 10,-13,  7, -4,  8},
      { 15, -5,  0,-12, 13, -7,  2,-10, 14, -6,  1,-11, 12, -8,  3,
-9}};
    static short        dither_green[2][16] = {
      { 11,-15,  7, -3,  8,-14,  4, -2, 10,-16,  6, -4,  9,-13,  5, -1},
      {-12, 14, -8,  2, -9, 13, -5,  1,-11, 15, -7,  3,-10, 12, -6, 
0}};
    static short        dither_blue[2][16] = {
      { -3,  9,-13,  7, -1, 11,-15,  5, -4,  8,-14,  6, -2, 10,-16,  4},
      {  2,-10, 12, -8,  0,-12, 14, -6,  3, -9, 13, -7,  1,-11, 15,
-5}};
    int                 red, green, blue;
    int                 x_dither_table, y_dither_table;
    unsigned char       pixel;

    /* Determine the dither table entries to use based on the pixel
address */
    x_dither_table = Xp % 16;   /* X Pixel Address MOD 16 */
    y_dither_table = Yp % 2;    /* Y Pixel Address MOD 2 */

    /* Start with the initial values as supplied by the calling routine
*/
    red   = RedValue;
    green = GreenValue;
    blue  = BlueValue;

    /* Generate the red dither value */
    if (red >= 48) /* 48 is a constant required by this routine */
       red=red-16;
    else
       red=red/2+8;
    red += dither_red[y_dither_table][x_dither_table];
    /* Check for overflow or underflow on red value */
    if (red > 0xff) red = 0xff;
    if (red < 0x00) red = 0x00;

    /* Generate the green dither value */
    if (green >= 48) /* 48 is a constant required by this routine */
       green=green-16;
    else
       green=green/2+8;
    green += dither_green[y_dither_table][x_dither_table];
    /* Check for overflow or underflow on green value */
    if (green > 0xff) green = 0xff;
    if (green < 0x00) green = 0x00;

    /* Generate the blue dither value */
    if (blue >= 112) /* 112 is a constant required by this routine */
       blue=blue-32;
    else
       blue=blue/2+24;
    blue += (dither_blue[y_dither_table][x_dither_table]<<1);
    /* Check for overflow or underflow on blue value */
    if (blue > 0xff) blue = 0xff;
    if (blue < 0x00) blue = 0x00;

    pixel = ((red & 0xE0) | ((green & 0xE0) >> 3) | ((blue & 0xC0) >>
6));
    return(pixel);
}