Problems in bitblt (in x11drv)

David Albrecht davidca at writeme.com
Tue Jun 7 22:16:38 CDT 2005


I'm new to wine and relatively new to windows programming being mostly
a unix hack.  Just for yucks I thought I'd get a relatively simple app
emu48 to work.  Turns out emu48 is not so simple (multi-threaded,
etc.).  First task towards functionality is to get the boot up display
to look right and a BitBlt didn't seem to be functioning correctly.

Much investigation later it turns out that in the file dib.c:

    /* if the source bitmap is 8bpp or less, we're supposed to use the
     * DC's palette for color conversion (not the DIB color table) */

is NOT true at least not for my case where the DC containing the
bitmap has one palette and the colormap for the bitmap is not the
same.  If I disable the hPalette tests as I did below and always use
the DIB colormap it boots up with the correct display
otherwise the color mapping  doesn't match the DIB bits and I get
garbage.


    if (dib.dsBm.bmBitsPixel <= 8) {
      HPALETTE hPalette = GetCurrentObject( physDevSrc->hdc, OBJ_PAL
);
      if (/*!hPalette || (hPalette ==
GetStockObject(DEFAULT_PALETTE))*/1) {
    /* HACK: no palette has been set in the source DC,
     * use the DIB colormap instead - this is necessary in some
     * cases since we need to do depth conversion in some places
     * where real Windows can just copy data straight over */
    colorMap = physBitmap->colorMap;
    nColorMap = physBitmap->nColorMap;

      } else {
    colorMap = X11DRV_DIB_BuildColorMap( physDevSrc, (WORD)-1,
                         dib.dsBm.bmBitsPixel,
                         (BITMAPINFO*)&dib.dsBmih,
                         &nColorMap );
    if (colorMap) aColorMap = TRUE;
      }
    }

Not knowing the full ramifications of this code I thought I'd pass
this along so that someone more familiar with it can reassess
it.

The DC and bitmap are created thusly:

#if defined GRAYSCALE
    #define NOCOLORS    8
#else
    #define NOCOLORS    2
#endif

static struct
{
    BITMAPINFOHEADER Lcd_bmih;
    RGBQUAD bmiColors[NOCOLORS];
} bmiLcd =
{
    {0x28,0/*x*/,0/*y*/,1,8,BI_RGB,0,0,0,NOCOLORS,0}
};
VOID CreateLcdBitmap(VOID)
{
    // create LCD bitmap
    _ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4);
    bmiLcd.Lcd_bmih.biWidth = LCD_ROW * nLcdDoubled;
    bmiLcd.Lcd_bmih.biHeight = -64 * nLcdDoubled;
    _ASSERT(hLcdDC == NULL);
    hLcdDC = CreateCompatibleDC(hWindowDC);
    _ASSERT(hLcdDC != NULL);
    hLcdBitmap = CreateDIBSection(hLcdDC, 
(BITMAPINFO*)&bmiLcd,DIB_RGB_COLORS, (LPVOID*)&pbyLcd, NULL, 0);
    _ASSERT(hLcdBitmap != NULL);
    hOldLcdBitmap = SelectObject(hLcdDC, hLcdBitmap);
    _ASSERT(hPalette != NULL);
    SelectPalette(hLcdDC, hPalette, FALSE);    // set palette for LCD DC
    RealizePalette(hLcdDC);                    // realize palette
    BuildPattern();                            // build Nibble -> DIB 
mask pattern
    UpdateContrast(Chipset.contrast);
    return;
}
Note that update contrast doe a SetDIBColorTable:
VOID UpdateContrast(BYTE byContrast)
{
#if defined GRAYSCALE
    INT  i;

    RGBQUAD c = *(RGBQUAD*)&dwKMLColor[byContrast];       // pixel on  color
    RGBQUAD b = *(RGBQUAD*)&dwKMLColor[byContrast+32]; // pixel off color
    if ((Chipset.IORam[BITOFFSET] & DON) == 0 || I == *(DWORD*)&b)
        b = *(RGBQUAD*)&dwKMLColor[0];

    // fill color palette of bitmap
    for (i = 0; i < ARRAYSIZEOF(bmiLcd.bmiColors); ++i)
    {
        const INT nCAdj[] = { 0, 1, 1, 2, 1, 2, 2, 3 };

        _ASSERT(i < ARRAYSIZEOF(bmiLcd.bmiColors));
        _ASSERT(i < ARRAYSIZEOF(nCAdj));
        bmiLcd.bmiColors[i] = b;
        bmiLcd.bmiColors[i].rgbRed   += (((INT) c.rgbRed   - (INT) 
b.rgbRed)   * nCAdj[i] / 3);
        bmiLcd.bmiColors[i].rgbGreen += (((INT) c.rgbGreen - (INT) 
b.rgbGreen) * nCAdj[i] / 3);
        bmiLcd.bmiColors[i].rgbBlue  += (((INT) c.rgbBlue  - (INT) 
b.rgbBlue)  * nCAdj[i] / 3);
    }
#else
    bmiLcd.bmiColors[1] = *(RGBQUAD*)&dwKMLColor[byContrast];    // 
pixel on  color
    bmiLcd.bmiColors[0] = *(RGBQUAD*)&dwKMLColor[byContrast+32]; // 
pixel off color
    if ((Chipset.IORam[BITOFFSET] & DON) == 0 || I == 
*(DWORD*)&bmiLcd.bmiColors[0])
        bmiLcd.bmiColors[0] = *(RGBQUAD*)&dwKMLColor[0];
#endif

    // update palette information
    _ASSERT(hLcdDC);
    
SetDIBColorTable(hLcdDC,0,ARRAYSIZEOF(bmiLcd.bmiColors),bmiLcd.bmiColors);
    return;
}

The BitBlt:
        BitBlt(hWindowDC, nLcdX, nLcdY, 131*nLcdDoubled, nLines*nLcdDoubled,
               hLcdDC, Chipset.boffset*nLcdDoubled, 0, SRCCOPY);

As emu48 still doesn't work I'll probably have more things I find in
likely much different areas later.

Dave



More information about the wine-devel mailing list