File:  [WindowsNT SDKs] / ntddk / src / video / displays / vga256 / screen.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 18:31:12 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: ntddk-nov-1993, HEAD
Microsoft Windows NT Build 511 (DDK SDK) 11-01-1993

/******************************Module*Header*******************************\
* Module Name: screen.c
*
* Initializes the GDIINFO and DEVINFO structures for DrvEnablePDEV.
*
* Copyright (c) 1992 Microsoft Corporation
\**************************************************************************/

#include "driver.h"

#define SYSTM_LOGFONT {16,7,0,0,700,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,  \
                       CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,VARIABLE_PITCH | \
                       FF_DONTCARE,L"System"}
#define HELVE_LOGFONT {12,9,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,  \
                       CLIP_STROKE_PRECIS,PROOF_QUALITY,VARIABLE_PITCH | \
                       FF_DONTCARE,L"MS Sans Serif"}
#define COURI_LOGFONT {12,9,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,  \
                       CLIP_STROKE_PRECIS,PROOF_QUALITY,FIXED_PITCH |    \
                       FF_DONTCARE, L"Courier"}

// This is the basic devinfo for a default driver.  This is used as a base and customized based
// on information passed back from the miniport driver.

const DEVINFO gDevInfoFrameBuffer = {
    (GCAPS_OPAQUERECT    | // Graphics capabilities
     GCAPS_PALMANAGED    |
     GCAPS_ALTERNATEFILL |
     GCAPS_WINDINGFILL   |
     GCAPS_MONO_DITHER   |
     GCAPS_COLOR_DITHER  |
     GCAPS_TRAPPAINT),

     // Should also implement GCAPS_HORIZSTRIKE so that the underlines
     // aren't drawn using DrvBitBlt

    SYSTM_LOGFONT,      // Default font description
    HELVE_LOGFONT,      // ANSI variable font description
    COURI_LOGFONT,      // ANSI fixed font description
    0,                  // Count of device fonts
    BMF_8BPP,           // Preferred DIB format
    8,                  // Width of color dither
    8,                  // Height of color dither
    0                   // Default palette to use for this device
};

/******************************Public*Routine******************************\
* bInitSURF
*
* Enables the surface.  Maps the frame buffer into memory.
*
\**************************************************************************/

BOOL bInitSURF(PPDEV ppdev, BOOL bFirst)
{
    VIDEO_MEMORY             VideoMemory;
    VIDEO_MEMORY_INFORMATION VideoMemoryInfo;
    DWORD                    ReturnedDataLength;

    // Set the mode.

    if (!DeviceIoControl(ppdev->hDriver,
                         IOCTL_VIDEO_SET_CURRENT_MODE,
                         (LPVOID) &ppdev->ulMode,  // input buffer
                         sizeof(DWORD),
                         NULL,
                         0,
                         &ReturnedDataLength,
                         NULL))
    {
        RIP("Failed SET_CURRENT_MODE");
        return(FALSE);
    }

    if (bFirst)
    {
        // Get the linear memory address range.

        VideoMemory.RequestedVirtualAddress = NULL;

        if (!DeviceIoControl(ppdev->hDriver,
                             IOCTL_VIDEO_MAP_VIDEO_MEMORY,
                             (PVOID) &VideoMemory, // input buffer
                             sizeof (VIDEO_MEMORY),
                             (PVOID) &VideoMemoryInfo, // output buffer
                             sizeof (VideoMemoryInfo),
                             &ReturnedDataLength,
                             NULL))
        {
            RIP("Failed MAP_VIDEO_MEMORY");
            return(FALSE);
        }
    }

    // Record the Frame Buffer Linear Address.

    if (bFirst)
    {
        ppdev->pjScreen =  (PBYTE) VideoMemoryInfo.FrameBufferBase;
    }

    // Set the various write mode values, so we don't have to read before write
    // later on

    vSetWriteModes(&ppdev->ulrm0_wmX);

    // Initialize the VGA registers to their default states, so that we
    // can be sure of drawing properly even when the miniport didn't
    // happen to set them the way we like them:

    vInitRegs(ppdev);

    // Since we just did a mode-set, we'll be in non-planar mode.  And make
    // sure we reset the bank manager (otherwise, after a switch from full-
    // screen, we may think we've got one bank mapped in, when in fact there's
    // a different one mapped in, and bad things would happen...).

    ppdev->flBank &= ~BANK_PLANAR;

    ppdev->rcl1WindowClip.bottom    = -1;
    ppdev->rcl2WindowClip[0].bottom = -1;
    ppdev->rcl2WindowClip[1].bottom = -1;

    ppdev->rcl1PlanarClip.bottom    = -1;
    ppdev->rcl2PlanarClip[0].bottom = -1;
    ppdev->rcl2PlanarClip[1].bottom = -1;

    return(TRUE);
}

/******************************Public*Routine******************************\
* vDisableSURF
*
* Disable the surface. Un-Maps the frame in memory.
*
\**************************************************************************/

VOID vDisableSURF(PPDEV ppdev)
{
    DWORD returnedDataLength;
    VIDEO_MEMORY videoMemory;

    videoMemory.RequestedVirtualAddress = (PVOID) ppdev->pjScreen;

    if (!DeviceIoControl(ppdev->hDriver,
                        IOCTL_VIDEO_UNMAP_VIDEO_MEMORY,
                        (LPVOID) &videoMemory,
                        sizeof(VIDEO_MEMORY),
                        NULL,
                        0,
                        &returnedDataLength,
                        NULL))
    {
        RIP("Failed UNMAP_VIDEO_MEMORY");
    }
}

/******************************Public*Routine******************************\
* bInitPDEV
*
* Determine the mode we should be in based on the DEVMODE passed in.
* Query mini-port to get information needed to fill in the DevInfo and the
* GdiInfo .
*
\**************************************************************************/

BOOL bInitPDEV(
PPDEV ppdev,
DEVMODEW *pDevMode)
{
    GDIINFO *pGdiInfo;
    ULONG cModes;
    PVIDEO_MODE_INFORMATION pVideoBuffer, pVideoModeSelected, pVideoTemp;
    VIDEO_COLOR_CAPABILITIES colorCapabilities;
    ULONG ulTemp;
    BOOL bSelectDefault;
    ULONG cbModeSize;

    pGdiInfo = ppdev->pGdiInfo;

    //
    // calls the miniport to get mode information.
    //

    cModes = getAvailableModes(ppdev->hDriver, &pVideoBuffer, &cbModeSize);

    if (cModes == 0)
    {
        DISPDBG((0, "vga256.dll: no available modes\n"));
        return(FALSE);
    }

    //
    // Determine if we are looking for a default mode.
    //

    if ( ((pDevMode->dmPelsWidth) ||
          (pDevMode->dmPelsHeight) ||
          (pDevMode->dmBitsPerPel) ||
          (pDevMode->dmDisplayFlags) ||
          (pDevMode->dmDisplayFrequency)) == 0)
    {
        bSelectDefault = TRUE;
    }
    else
    {
        bSelectDefault = FALSE;
    }

    //
    // Now see if the requested mode has a match in that table.
    //

    pVideoModeSelected = NULL;
    pVideoTemp = pVideoBuffer;

    while (cModes--)
    {
        if (pVideoTemp->Length != 0)
        {
            if (bSelectDefault ||
                ((pVideoTemp->VisScreenWidth  == pDevMode->dmPelsWidth) &&
                 (pVideoTemp->VisScreenHeight == pDevMode->dmPelsHeight) &&
                 (pVideoTemp->BitsPerPlane *
                    pVideoTemp->NumberOfPlanes  == pDevMode->dmBitsPerPel) &&
                 ((pVideoTemp->Frequency  == pDevMode->dmDisplayFrequency) ||
                    (pDevMode->dmDisplayFrequency == 0)) &&
                 (((pVideoTemp->AttributeFlags &
                            VIDEO_MODE_INTERLACED) ? 1:0) ==
                    ((pDevMode->dmDisplayFlags & DM_INTERLACED) ? 1:0)) ) )

            {
                pVideoModeSelected = pVideoTemp;
                DISPDBG((2, "vga256: Found a match\n")) ;
                break;
            }
        }

        pVideoTemp = (PVIDEO_MODE_INFORMATION)
            (((PUCHAR)pVideoTemp) + cbModeSize);
    }

    //
    // If no mode has been found, return an error
    //

    if (pVideoModeSelected == NULL)
    {
        DISPDBG((0, "vga256.dll: no valid modes\n"));
        LocalFree(pVideoBuffer);
        return(FALSE);
    }

    //
    // Fill in the GDIINFO data structure with the information returned from
    // the kernel driver.
    //

    ppdev->ulMode = pVideoModeSelected->ModeIndex;
    ppdev->cxScreen = pVideoModeSelected->VisScreenWidth;
    ppdev->cyScreen = pVideoModeSelected->VisScreenHeight;
    ppdev->ulBitCount = pVideoModeSelected->BitsPerPlane *
                        pVideoModeSelected->NumberOfPlanes;
    ppdev->lDeltaScreen = pVideoModeSelected->ScreenStride;

    ppdev->flRed = pVideoModeSelected->RedMask;
    ppdev->flGreen = pVideoModeSelected->GreenMask;
    ppdev->flBlue = pVideoModeSelected->BlueMask;

    if (!(pVideoModeSelected->AttributeFlags & VIDEO_MODE_NO_OFF_SCREEN))
    {
        ppdev->fl |= DRIVER_USE_OFFSCREEN;
    }

    pGdiInfo->ulVersion    = 0x1000;    // Our driver is version 1.000
    pGdiInfo->ulTechnology = DT_RASDISPLAY;
    pGdiInfo->ulHorzSize   = pVideoModeSelected->XMillimeter;
    pGdiInfo->ulVertSize   = pVideoModeSelected->YMillimeter;

    pGdiInfo->ulHorzRes    = ppdev->cxScreen;
    pGdiInfo->ulVertRes    = ppdev->cyScreen;
    pGdiInfo->cBitsPixel   = pVideoModeSelected->BitsPerPlane;
    pGdiInfo->cPlanes      = pVideoModeSelected->NumberOfPlanes;

    pGdiInfo->ulLogPixelsX = 96;
    pGdiInfo->ulLogPixelsY = 96;

    pGdiInfo->flTextCaps   = TC_RA_ABLE | TC_SCROLLBLT;
    pGdiInfo->flRaster     = 0;         // DDI reservers flRaster

    pGdiInfo->ulDACRed     = pVideoModeSelected->NumberRedBits;
    pGdiInfo->ulDACGreen   = pVideoModeSelected->NumberGreenBits;
    pGdiInfo->ulDACBlue    = pVideoModeSelected->NumberBlueBits;

    pGdiInfo->ulAspectX    = 0x24;      // One-to-one aspect ratio
    pGdiInfo->ulAspectY    = 0x24;
    pGdiInfo->ulAspectXY   = 0x33;

    pGdiInfo->xStyleStep   = 1;         // A style unit is 3 pels
    pGdiInfo->yStyleStep   = 1;
    pGdiInfo->denStyleStep = 3;

    pGdiInfo->ptlPhysOffset.x = 0;
    pGdiInfo->ptlPhysOffset.y = 0;
    pGdiInfo->szlPhysSize.cx  = 0;
    pGdiInfo->szlPhysSize.cy  = 0;

    // RGB and CMY color info.

    // try to get it from the miniport.
    // if the miniport doesn ot support this feature, use defaults.

    if (!DeviceIoControl(ppdev->hDriver,
                         IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES,
                         NULL,
                         0,
                         &colorCapabilities,
                         sizeof(VIDEO_COLOR_CAPABILITIES),
                         &ulTemp,
                         NULL))
    {
        DISPDBG((1, "vga256 DISP getcolorCapabilities failed \n"));

        pGdiInfo->ciDevice.Red.x = 6700;
        pGdiInfo->ciDevice.Red.y = 3300;
        pGdiInfo->ciDevice.Red.Y = 0;
        pGdiInfo->ciDevice.Green.x = 2100;
        pGdiInfo->ciDevice.Green.y = 7100;
        pGdiInfo->ciDevice.Green.Y = 0;
        pGdiInfo->ciDevice.Blue.x = 1400;
        pGdiInfo->ciDevice.Blue.y = 800;
        pGdiInfo->ciDevice.Blue.Y = 0;
        pGdiInfo->ciDevice.AlignmentWhite.x = 3127;
        pGdiInfo->ciDevice.AlignmentWhite.y = 3290;
        pGdiInfo->ciDevice.AlignmentWhite.Y = 0;

        pGdiInfo->ciDevice.RedGamma = 20000;
        pGdiInfo->ciDevice.GreenGamma = 20000;
        pGdiInfo->ciDevice.BlueGamma = 20000;

    }
    else
    {

        pGdiInfo->ciDevice.Red.x = colorCapabilities.RedChromaticity_x;
        pGdiInfo->ciDevice.Red.y = colorCapabilities.RedChromaticity_y;
        pGdiInfo->ciDevice.Red.Y = 0;
        pGdiInfo->ciDevice.Green.x = colorCapabilities.GreenChromaticity_x;
        pGdiInfo->ciDevice.Green.y = colorCapabilities.GreenChromaticity_y;
        pGdiInfo->ciDevice.Green.Y = 0;
        pGdiInfo->ciDevice.Blue.x = colorCapabilities.BlueChromaticity_x;
        pGdiInfo->ciDevice.Blue.y = colorCapabilities.BlueChromaticity_y;
        pGdiInfo->ciDevice.Blue.Y = 0;
        pGdiInfo->ciDevice.AlignmentWhite.x = colorCapabilities.WhiteChromaticity_x;
        pGdiInfo->ciDevice.AlignmentWhite.y = colorCapabilities.WhiteChromaticity_y;
        pGdiInfo->ciDevice.AlignmentWhite.Y = colorCapabilities.WhiteChromaticity_Y;

        // if we have a color device store the three color gamma values,
        // otherwise store the unique gamma value in all three.

        if (colorCapabilities.AttributeFlags & VIDEO_DEVICE_COLOR)
        {
            pGdiInfo->ciDevice.RedGamma = colorCapabilities.RedGamma;
            pGdiInfo->ciDevice.GreenGamma = colorCapabilities.GreenGamma;
            pGdiInfo->ciDevice.BlueGamma = colorCapabilities.BlueGamma;
        }
        else
        {
            pGdiInfo->ciDevice.RedGamma = colorCapabilities.WhiteGamma;
            pGdiInfo->ciDevice.GreenGamma = colorCapabilities.WhiteGamma;
            pGdiInfo->ciDevice.BlueGamma = colorCapabilities.WhiteGamma;
        }

    };

    pGdiInfo->ciDevice.Cyan.x = 0;
    pGdiInfo->ciDevice.Cyan.y = 0;
    pGdiInfo->ciDevice.Cyan.Y = 0;
    pGdiInfo->ciDevice.Magenta.x = 0;
    pGdiInfo->ciDevice.Magenta.y = 0;
    pGdiInfo->ciDevice.Magenta.Y = 0;
    pGdiInfo->ciDevice.Yellow.x = 0;
    pGdiInfo->ciDevice.Yellow.y = 0;
    pGdiInfo->ciDevice.Yellow.Y = 0;

    // No dye correction for raster displays.

    pGdiInfo->ciDevice.MagentaInCyanDye = 0;
    pGdiInfo->ciDevice.YellowInCyanDye = 0;
    pGdiInfo->ciDevice.CyanInMagentaDye = 0;
    pGdiInfo->ciDevice.YellowInMagentaDye = 0;
    pGdiInfo->ciDevice.CyanInYellowDye = 0;
    pGdiInfo->ciDevice.MagentaInYellowDye = 0;

    // Fill in the rest of the devinfo and GdiInfo structures.

    pGdiInfo->ulNumColors = 20;
    pGdiInfo->ulNumPalReg = 1 << ppdev->ulBitCount;

    pGdiInfo->ulDevicePelsDPI  = 0;   // For printers only
    pGdiInfo->ulPrimaryOrder   = PRIMARY_ORDER_CBA;
    pGdiInfo->ulHTPatternSize  = HT_PATSIZE_4x4_M;
    pGdiInfo->ulHTOutputFormat = HT_FORMAT_8BPP;
    pGdiInfo->flHTFlags        = HT_FLAG_ADDITIVE_PRIMS;

    // Fill in the basic devinfo structure

    *(ppdev->pDevInfo) = gDevInfoFrameBuffer;

    LocalFree(pVideoBuffer);

    return(TRUE);
}

/******************************Public*Routine******************************\
* VOID vInitBrushCache(ppdev)
*
* Initializes various brush cache structures.  Must be done after bank
* initialization.
*
\**************************************************************************/

VOID vInitBrushCache(PPDEV ppdev)
{
    LONG cCacheBrushesPerScan = ppdev->lNextScan / BRUSH_SIZE;
    LONG cCacheScans          = ppdev->cTotalScans - ppdev->cyScreen;
    LONG cCacheEntries;
    LONG i;
    LONG j;
    BRUSHCACHEENTRY* pbce;
    BRUSHCACHEENTRY* pbceEnd;

    cCacheEntries = min(cCacheScans*cCacheBrushesPerScan, BRUSH_MAX_CACHE_SIZE);

    if (cCacheEntries <= 0)
    {
        goto InitFailed;
    }

    ppdev->pbceCache = (BRUSHCACHEENTRY*) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT,
                       cCacheEntries * sizeof(BRUSHCACHEENTRY));
    if (ppdev->pbceCache == NULL)
    {
        goto InitFailed;
    }

    // We successfully managed to allocate all our data structures for looking
    // after off-screen memory, so set the flag saying that we can use it
    // (note that if ppdev->fl's DRIVER_USE_OFFSCREEN hasn't been set, the
    // memory cannot be used for long-term storage):

    ppdev->fl |= DRIVER_HAS_OFFSCREEN;

    ppdev->iCache     = 0;          // 0 is a reserved index
    ppdev->iCacheLast = cCacheEntries - 1;

    // Initialize our cache entry array:

    pbce    = &ppdev->pbceCache[0];
    pbceEnd = &ppdev->pbceCache[cCacheEntries];

    for (i = ppdev->cyScreen; i < ppdev->cTotalScans; i++)
    {
        for (j = 0; j < cCacheBrushesPerScan; j++)
        {
            // Bitmap offset is in planar format, where every byte is one
            // quadpixel:

            pbce->yCache  = i;
            pbce->ulCache = (i * ppdev->lNextScan + j * BRUSH_SIZE) / 4;

            // This verification pointer doesn't actually have to be
            // initialized, but we do so for debugging purposes:

            pbce->prbVerifyRealization = NULL;

            pbce++;
            if (pbce >= pbceEnd)
                return;
        }
    }

    RIP("Shouldn't get here");

InitFailed:
    ppdev->fl &= ~(DRIVER_USE_OFFSCREEN | DRIVER_HAS_OFFSCREEN);
    return;
}

/******************************Public*Routine******************************\
* VOID vResetBrushCache(ppdev)
*
* Blows away the brush cache entries -- this is useful when switching
* out of full-screen mode, where anyone could have written over the video
* memory where we cache our brushes.
*
\**************************************************************************/

VOID vResetBrushCache(PPDEV ppdev)
{
    BRUSHCACHEENTRY* pbce;
    LONG             i;

    // Make sure we actually have a brush cache before we try to reset it:

    if (ppdev->fl & DRIVER_HAS_OFFSCREEN)
    {
        pbce = &ppdev->pbceCache[0];
        for (i = ppdev->iCacheLast; i >= 0; i--)
        {
            pbce->prbVerifyRealization = NULL;
            pbce++;
        }
    }
}

/******************************Public*Routine******************************\
* VOID vDisableBrushCache(ppdev)
*
* Frees various brush cache structures.
*
\**************************************************************************/

VOID vDisableBrushCache(PPDEV ppdev)
{
    if (ppdev->pbceCache != NULL)
    {
        LocalFree(ppdev->pbceCache);
    }
}

/******************************Public*Routine******************************\
* getAvailableModes
*
* Calls the miniport to get the list of modes supported by the kernel driver,
* and returns the list of modes supported by the diplay driver among those
*
* returns the number of entries in the videomode buffer.
* 0 means no modes are supported by the miniport or that an error occured.
*
* NOTE: the buffer must be freed up by the caller.
*
\**************************************************************************/

DWORD getAvailableModes(
HANDLE hDriver,
PVIDEO_MODE_INFORMATION *modeInformation,
DWORD *cbModeSize)
{
    ULONG ulTemp;
    VIDEO_NUM_MODES modes;
    PVIDEO_MODE_INFORMATION pVideoTemp;

    //
    // Get the number of modes supported by the mini-port
    //

    if (!DeviceIoControl(hDriver,
            IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES,
            NULL,
            0,
            &modes,
            sizeof(VIDEO_NUM_MODES),
            &ulTemp,
            NULL))
    {
        DISPDBG((0, "vga256 getAvailableModes failed VIDEO_QUERY_NUM_AVAIL_MODES\n"));
        return(0);
    }

    *cbModeSize = modes.ModeInformationLength;

    //
    // Allocate the buffer for the mini-port to write the modes in.
    //

    *modeInformation = (PVIDEO_MODE_INFORMATION)
                        LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT,
                                   modes.NumModes *
                                   modes.ModeInformationLength);

    if (*modeInformation == (PVIDEO_MODE_INFORMATION) NULL)
    {
        DISPDBG((0, "vga256 getAvailableModes failed LocalAlloc\n"));

        return 0;
    }

    //
    // Ask the mini-port to fill in the available modes.
    //

    if (!DeviceIoControl(hDriver,
            IOCTL_VIDEO_QUERY_AVAIL_MODES,
            NULL,
            0,
            *modeInformation,
            modes.NumModes * modes.ModeInformationLength,
            &ulTemp,
            NULL))
    {

        DISPDBG((0, "vga256 getAvailableModes failed VIDEO_QUERY_AVAIL_MODES\n"));

        LocalFree(*modeInformation);
        *modeInformation = (PVIDEO_MODE_INFORMATION) NULL;

        return(0);
    }

    //
    // Now see which of these modes are supported by the display driver.
    // As an internal mechanism, set the length to 0 for the modes we
    // DO NOT support.
    //

    ulTemp = modes.NumModes;
    pVideoTemp = *modeInformation;

    //
    // Mode is rejected if it is not one plane, or not graphics, or is not
    // one of 8 bits per pel (that is all the vga 256 currently supports)
    //

    while (ulTemp--)
    {
        if ((pVideoTemp->NumberOfPlanes != 1 ) ||
            !(pVideoTemp->AttributeFlags & VIDEO_MODE_GRAPHICS) ||
            (pVideoTemp->BitsPerPlane != 8))
        {
            pVideoTemp->Length = 0;
        }

        pVideoTemp = (PVIDEO_MODE_INFORMATION)
            (((PUCHAR)pVideoTemp) + modes.ModeInformationLength);
    }

    return modes.NumModes;

}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.