home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection 1998 Fall: Game Toolkit / Disc.iso / SDKs / PCI Driver Development Kit / • Samples / Driver Samples / Video samples / GDX 950717 / GDX / GraphicsCoreControl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-20  |  30.2 KB  |  876 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        GraphicsCoreControl.c
  3.  
  4.     Contains:    GDX Control Calls
  5.  
  6.     Written by:    Sean Williams, Kevin Williams
  7.  
  8.     Copyright:    © 1994-1995 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <2>     7/17/95    SW        For GraphicsHAL SetSync(), syncBitFieldValid is now input only.
  13.          <1>     4/15/95    SW        First Checked In
  14.  
  15. */
  16.  
  17. #include "GraphicsCoreControl.h"
  18. #include "GraphicsCoreStatus.h"
  19. #include "GraphicsCorePriv.h"
  20. #include "GraphicsPriv.h"
  21. #include "GraphicsCoreUtils.h"
  22. #include "GraphicsHAL.h"
  23. #include "GraphicsOSS.h"
  24.  
  25. #include <DriverServices.h>                // for PoolAllocate/Deallocate
  26.  
  27.  
  28.  
  29. //=====================================================================================================
  30. //
  31. // GraphicsCoreSetMode()
  32. //    This is an antiquated control call that is only included for backward compatibility.  This routine
  33. //    lets you change the pixel depth and/or the current graphics page BUT ONLY for the current
  34. //    DisplayModeID.
  35. //
  36. //    The control call GraphicsCoreSwitchMode() is the newer, enhanced version of this and is used by
  37. //    software that supports 'on-the-fly' resolution switching.
  38. //
  39. //    For this routine, the relevant fields indicated by 'VDPageInfo' are:
  40. //            ->    csMode            desired depth mode
  41. //            ->    csPage            desired display page
  42. //            <-    csBaseAddr        base address of frame buffer
  43. //
  44. //=====================================================================================================
  45. GDXErr GraphicsCoreSetMode(VDPageInfo *pageInfo)
  46. {
  47.     GraphicsCoreData *coreData = GraphicsCoreGetCoreData();
  48.     GDXErr err = kGDXErrUnknownError;                                    // Assume failure
  49.  
  50.     Boolean directColor;
  51.     char *baseAddress;
  52.  
  53.  
  54.     Boolean modePossible = false;
  55.     
  56.     DepthMode depthMode = (DepthMode) pageInfo->csMode;
  57.     SInt16 page = pageInfo->csPage;
  58.  
  59.     
  60.     // Make sure that the requested depth mode and page are valid
  61.     err = GraphicsHALModePossible(coreData->displayModeID, depthMode, page, &modePossible);
  62.     if (!modePossible || err)
  63.     {
  64.         err = kGDXErrRequestedModeNotPossible;
  65.         goto ErrorExit;
  66.     }
  67.  
  68.     // Set the CLUT to 50% gray.  This is done because 50% gray looks the same at all pixel depths,
  69.     // so no funny screen artifacts will be seen during mode switching.
  70.     
  71.     err = GraphicsHALGrayCLUT(coreData->gammaTable);
  72.     if (err)
  73.         goto ErrorExit;
  74.         
  75.     err = GraphicsHALProgramHardware(coreData->displayModeID, depthMode, page, &directColor,
  76.             &baseAddress);
  77.     if (err)
  78.         goto ErrorExit;
  79.             
  80.     // Request has been successfully completed, so update the coreData to relfect the current state.
  81.     
  82.     coreData->depthMode = depthMode;
  83.     coreData->currentPage = page;
  84.     coreData->baseAddress = baseAddress;
  85.     coreData->directColor = directColor;
  86.     
  87.     // Return the new base address in pageInfo->csBaseAddr
  88.     pageInfo->csBaseAddr = (Ptr) baseAddress;
  89.     
  90.     // Map the relative bit depth (DepthMode) to abosolute bit depth
  91.     err = GraphicsHALMapDepthModeToBPP(coreData->depthMode, &coreData->bitsPerPixel);
  92.     
  93.     if (err)
  94.         goto ErrorExit;
  95.     
  96.     err = kGDXErrNoError;                                                // Everything okay
  97.         
  98. ErrorExit:
  99.  
  100.     return err;
  101. }
  102.  
  103.  
  104.  
  105. //=====================================================================================================
  106. //
  107. // GraphicsCoreSetEntries()
  108. //    This should change the contents of the graphics hardware's CLUT for indexed devices.  If the
  109. //    graphics hardware is in a direct color mode, the call should never be received, but if it is, then
  110. //    an error should be returned.
  111. //
  112. //=====================================================================================================
  113. GDXErr GraphicsCoreSetEntries(const VDSetEntryRecord *setEntry)
  114. {
  115.     GraphicsCoreData *coreData  = GraphicsCoreGetCoreData() ;
  116.     GDXErr err = kGDXErrUnknownError;                                    // Assume failure
  117.     
  118.     // Make sure we are on an indexed device and not a direct device.
  119.     if (coreData->directColor)
  120.     {
  121.         err = kGDXErrInvalidForIndexedDevice;
  122.         goto ErrorExit;
  123.     }
  124.         
  125.     err = GraphicsUtilSetEntries(setEntry, coreData->gammaTable, coreData->depthMode,
  126.             coreData->bitsPerPixel, coreData->luminanceMapping, coreData->directColor);
  127.         
  128. ErrorExit:
  129.  
  130.     return err;
  131. }
  132.  
  133.  
  134.  
  135. //=====================================================================================================
  136. //
  137. // GraphicsCoreSetGamma()
  138. //    For a detailed description of gamma tables and how they are used in in the GDX Model, please see
  139. //    "Designing PCI Card and Drivers", Chapter 11.
  140. //
  141. //=====================================================================================================
  142. GDXErr GraphicsCoreSetGamma(const VDGammaRecord *gamma)
  143. {
  144.     GraphicsCoreData *coreData = GraphicsCoreGetCoreData();
  145.     GDXErr err = kGDXErrUnknownError;                                // Assume failure
  146.     
  147.     GammaTbl *clientGamma = (GammaTbl *) gamma->csGTable;
  148.     GammaTbl *gammaTable = coreData->gammaTable;
  149.     
  150.  
  151.     // If the client passed in NULL as the gamma table pointer, that indicates that we should build
  152.     // a linear ramp. Otherwise, the client has supplied a gamma table, and we should make a copy of
  153.     // it and make it our current one.
  154.     
  155.     if (NULL == clientGamma)
  156.     {    
  157.         // Client  passed in NULL, so just build a linear ramp. The size of a linear ramp is:
  158.         //
  159.         //    linearRampSize  = sizeof(GammaTbl)        -- fixed size header
  160.         //        + 0                            -- 0 == gFormulaSize
  161.         //        + 1 * 256 * 1                -- (# of channels) * (entries/channel) * (bytes/entry)
  162.         //        - 2                            -- accounts for gFormulaData[0] is last element of GammaTbl 
  163.         //
  164.         
  165.         ByteCount linearRampSize = sizeof(GammaTbl) + 0 + (1 * 256 * 1) - 2;    
  166.         UInt8 *correctionData;
  167.         UInt32 i;
  168.                 
  169.         // Only allocate new gamma table if existing gamma table is smaller than required.
  170.         if (linearRampSize > coreData->maxGammaTableSize) 
  171.         {
  172.             coreData->maxGammaTableSize = 0;
  173.  
  174.             if (NULL != coreData->gammaTable)                    // Deallocate previous gamma table
  175.             {
  176.                 PoolDeallocate(coreData->gammaTable);
  177.                 coreData->gammaTable = NULL;
  178.             }
  179.             
  180.             coreData->gammaTable = PoolAllocateResident(linearRampSize, true);
  181.             if (NULL == coreData->gammaTable)
  182.             {
  183.                 err = kGDXErrUnableToAllocateGammaTable;
  184.                 goto ErrorExit;
  185.             }
  186.         
  187.             coreData->maxGammaTableSize = linearRampSize;
  188.             
  189.         }
  190.         
  191.         gammaTable = coreData->gammaTable;    // Dereference for clarity
  192.         
  193.         gammaTable->gVersion = 0;            // A version 0 style of the GammaTbl structure
  194.         gammaTable->gType = 0;                // Frame buffer hardware invariant
  195.         gammaTable->gFormulaSize = 0;        // No formula data, just correction data
  196.         gammaTable->gChanCnt = 1;            // Apply same correction to Red, Green, & Blue
  197.         gammaTable->gDataCnt = 256;            // gDataCnt == 2^^gDataWidth
  198.         gammaTable->gDataWidth = 8;            // 8 bits of significant data per entry
  199.         
  200.         // Find the starting address of the correction data.  This can be computed by starting at
  201.         // the address of gFormula[0] and adding the gFormulaSize.
  202.         correctionData = (UInt8 *) ( (unsigned long) &gammaTable->gFormulaData[0]
  203.                 + gammaTable->gFormulaSize);
  204.                 
  205.         // Build the linear ramp.  Normally, for a linear ramp, the 'correction data == index'
  206.         // However, for NTSC & PAL monitors, special consideration must be taken.  This is because
  207.         // CCIR601  colors only range from 16-235, not 0-255.  
  208.     
  209.         if (kDisplayCodeNTSC == coreData->displayCode || kDisplayCodePAL == coreData->displayCode)
  210.         {
  211.             // NTSC of PAL, so build a 16-235 ramp to be CCIR601 compliant.
  212.             for (i = 0; i < gammaTable->gDataCnt ; i++)
  213.                 *correctionData++ = (i * 220 / 256) + 16;
  214.  
  215.         } 
  216.         else 
  217.         {
  218.             // Just build a normal 0-255 ramp.
  219.             for (i = 0; i < gammaTable->gDataCnt ; i++)
  220.                 *correctionData++ = i;        
  221.         }
  222.  
  223.     }
  224.     else
  225.     {
  226.     
  227.         // User supplied a gamma table, so make sure it is a valid one.
  228.         
  229.         ByteCount tableSize;
  230.         UInt32 formulaLoop;
  231.         UInt32 channelLoop;
  232.         UInt32 entryLoop;
  233.         
  234.         UInt8 *clientData;
  235.         UInt8 *newData;
  236.  
  237.  
  238.         err = kGDXErrInvalidGammaTable;            // Assume gamma table is invalid
  239.         
  240.         if (0 != clientGamma->gVersion)            // Only support version 0 of the GammaTbl structure
  241.             goto ErrorExit;
  242.         
  243.         if (0 != clientGamma->gType)            // Only support frame buffer invariant gamma tables
  244.             goto ErrorExit;
  245.             
  246.         if ((1 != clientGamma->gChanCnt) && (3 != clientGamma->gChanCnt))  // Only 1 or 3 channels
  247.             goto ErrorExit;
  248.             
  249.         if (8 < clientGamma->gDataWidth)        // Only support 8 bits or less of correction data/entry
  250.             goto ErrorExit;
  251.             
  252.         if (clientGamma->gDataCnt != (1 << clientGamma->gDataWidth)    )// gDataCnt must = 2^^gDataWidth
  253.             goto ErrorExit;
  254.         
  255.         // The client supplied gamma table is valid, so allocate enough memory to copy it.
  256.  
  257.         tableSize = sizeof(GammaTbl)                            // fixed size header
  258.                 + clientGamma->gFormulaSize                        // add formula size
  259.                 + clientGamma->gChanCnt * clientGamma->gDataCnt    // assume 1 byte/entry
  260.                 - 2;                                             // correct gFormulaData[0] counted twice
  261.     
  262.  
  263.         if (tableSize > coreData->maxGammaTableSize) 
  264.         {
  265.             coreData->maxGammaTableSize = 0;
  266.             
  267.             if (NULL != coreData->gammaTable)                    // Deallocate previous gamma table
  268.             {
  269.                 PoolDeallocate(coreData->gammaTable);
  270.                 coreData->gammaTable = NULL;
  271.             }
  272.             
  273.             coreData->gammaTable = PoolAllocateResident(tableSize, true);
  274.             if (NULL == coreData->gammaTable)
  275.             {
  276.                 err = kGDXErrUnableToAllocateGammaTable;
  277.                 goto ErrorExit;
  278.             }
  279.  
  280.             coreData->maxGammaTableSize = tableSize;
  281.             
  282.         }
  283.  
  284.         gammaTable = coreData->gammaTable;                        // Dereference for clarity
  285.  
  286.  
  287.         // Copy the client supplied gamma table into our freshly allocated one. This consists of 3
  288.         // stages:  copying the fixed sized header, the formula data, and the correction data.
  289.         
  290.         *gammaTable = *clientGamma;                                // Copy the fixed sized header        
  291.         
  292.         newData = (UInt8 *) &gammaTable->gFormulaData[0];        // Point to newGamma's formula data
  293.         clientData = (UInt8 *) &clientGamma->gFormulaData[0];    // Point to clientGamma's formula data
  294.         
  295.         // Copy the formula data (if any)
  296.         for (formulaLoop = 0 ; formulaLoop < gammaTable->gFormulaSize ; formulaLoop++)
  297.             *newData++ = *clientData++;
  298.  
  299.         // Copy the correction data.  Convientiently, after copying the formula data, the 'newData'
  300.         // pointer and the 'clientData' pointer are pointing to the their respective starting points
  301.         // of their correction data.
  302.         for (channelLoop = 0 ; channelLoop < gammaTable->gChanCnt ; channelLoop++)
  303.         {
  304.             for (entryLoop = 0 ; entryLoop < gammaTable->gDataCnt ; entryLoop++)        
  305.                 *newData++ = *clientData++;
  306.         }
  307.     }
  308.  
  309.     
  310.     // Check to see if we are in a direct color mode.  If we are, then we need to build a 
  311.     // black-to-white ramp in RGB and apply it to the hardware.
  312.     
  313.     if (coreData->directColor)
  314.     {
  315.         err = GraphicsUtilBlackToWhiteRamp(gammaTable, coreData->depthMode, coreData->bitsPerPixel, 
  316.                 coreData->luminanceMapping, coreData->directColor);
  317.         if (err)
  318.             goto ErrorExit;
  319.     }
  320.     
  321.     
  322.     err = kGDXErrNoError;                                // Everything okay
  323.  
  324. ErrorExit:
  325.  
  326.     return err;
  327. }
  328.  
  329.  
  330.  
  331. //=====================================================================================================
  332. //
  333. // GraphicsCoreGrayPage()
  334. //    This fills the specified video page with a dithered gray pattern in the absolute bit depth.
  335. //
  336. // For maximum speed, we will do this by filling each row of the frame buffer a 'long' (4 bytes) at a
  337. // time, and then write out whatever bytes are remaining.
  338. //
  339. //                             (# of pixels) * (# of bits/pixel)
  340. //    # of longs =          ---------------------------------
  341. //                             (8 bits/byte) (4 bytes/long)
  342. //
  343. //
  344. //                             (# of pixels) * (# of bits/pixel)
  345. //    remaining bytes =     ---------------------------------    MOD 4
  346. //                                   (8 bits/byte)
  347. //
  348. // We need four pieces of information in order to successfully gray the requested page:
  349. //
  350. //        base address of the page  -- this can be found by calling GraphicsCoreGetBaseAddress()
  351. //        rowBytes                   -- this can be found in the .vpRowBytes field of the VPBlock
  352. //        numberOfRows              -- this can be found in the .vpBounds.bottom of the VPBlock
  353. //        pixelsPerRow              -- this can be found in the .vpBounds.right of the VPBlock
  354. //
  355. //=====================================================================================================
  356. GDXErr GraphicsCoreGrayPage(const VDPageInfo *pageInfo)
  357. {
  358.  
  359.     // Define a new type which maps the absolute bit depth to the appropriate pattern to produce
  360.     // a dithered gray.  A dithered gray is produced by having a black-white-black-white pixel pattern.
  361.     
  362.     typedef struct BPPToGrayPatternMap BPPToGrayPatternMap;
  363.     struct BPPToGrayPatternMap
  364.     {
  365.         UInt32 bitsPerPixel;
  366.         UInt32 grayPattern;
  367.     };
  368.     
  369.     enum  {kMapSize = 6};
  370.     
  371.     BPPToGrayPatternMap bppMap[kMapSize] =
  372.     {
  373.         {1, 0xaaaaaaaa},            // Represents 32 pixels @ 1 bpp
  374.         {2, 0xcccccccc},            //     "      16   "    @ 2 bpp
  375.         {4, 0xf0f0f0f0},            //     "       8   "    @ 4 bpp
  376.         {8, 0xff00ff00},            //     "       4   "    @ 8 bpp
  377.         {16, 0xffff0000},            //     "       2   "    @ 16 bpp
  378.         {32, 0xffffffff}            //     "       1   "    @ 32 bpp (Invert to get next pixel)
  379.     };
  380.  
  381.     GraphicsCoreData *coreData = GraphicsCoreGetCoreData();
  382.     GDXErr err = kGDXErrUnknownError;                // Assume failure
  383.  
  384.     VDPageInfo baseAddressPageInfo ;                // To get address of page to gray
  385.     VDVideoParametersInfoRec parametersInfo;        // To fill out the 'VPBlock' structure
  386.     VPBlock vpBlock;                                // To get 'vpRowBytes' & 'vpBounds.bottom & .right'
  387.     
  388.     Ptr rowStart;                                    // Start address of row
  389.     SInt16 rowBytes;                                // Byte offset between each row 
  390.     SInt16 numberOfRows;                            // # of rows on the screen (vpBlock.vpBounds.bottom)
  391.     SInt16 pixelsPerRow;                            // # of pixels/row (vpBlock.vpBounds.right)
  392.     UInt32 longWrites;                                // # of long (4 byte) writes per row
  393.     UInt32 byteWrites;                                // # of remaining bytes (if any)
  394.     
  395.     UInt32 row;                                        // loop control variable
  396.     UInt32 i;                                        // loop control variable
  397.     
  398.     UInt32 *fillPtr;                                // Location in frame buffer to fill w/ gray pattern
  399.     UInt8 *bytePtr;                                    // Location in frame buffer to fill w/ gray pattern
  400.     
  401.     UInt32 grayPattern;                                // Fill pattern
  402.     UInt32 scratchPattern;                            // "Working Version" of grayPattern
  403.  
  404.     Boolean modePossible;                            // HAL sets if resolution, depthMode and page are valid
  405.     
  406.     SInt16 page = pageInfo->csPage;
  407.     
  408.     
  409.     // Make sure that the requested page to gray is valid for current DisplayModeID and DepthMode
  410.     err = GraphicsHALModePossible(coreData->displayModeID, coreData->depthMode, page, &modePossible);
  411.     if (err || !modePossible)
  412.     {
  413.         err = kGDXErrRequestedModeNotPossible;
  414.         goto ErrorExit;
  415.     }
  416.  
  417.     // Call GraphicsCoreGetBaseAddress() to determine the base address of the page to gray.
  418.     
  419.     baseAddressPageInfo.csPage = page;                                // Page we want base address of
  420.     
  421.     err = GraphicsCoreGetBaseAddress(&baseAddressPageInfo);            // Get the base address
  422.     if (err)
  423.         goto ErrorExit;
  424.     
  425.     // Call GraphicsCoreGetVideoParams() to obtain the VPBlock structure for current DisplayModeID at
  426.     // the current DepthMode.
  427.     
  428.     parametersInfo.csDisplayModeID = coreData->displayModeID;        
  429.     parametersInfo.csDepthMode = coreData->depthMode;
  430.     parametersInfo.csVPBlockPtr = &vpBlock;
  431.     
  432.     err = GraphicsCoreGetVideoParams(¶metersInfo);                // Get the VPBlock structure
  433.     if (err)
  434.         goto ErrorExit;
  435.             
  436.     rowBytes = vpBlock.vpRowBytes;                                    // Byte offset between each row     
  437.     numberOfRows = vpBlock.vpBounds.bottom;                            // Number of rows on the screen
  438.     pixelsPerRow = vpBlock.vpBounds.right;                            // Number of pixels/row
  439.     
  440.     longWrites = pixelsPerRow * coreData->bitsPerPixel / 8 / 4;        // # of longs per row
  441.     byteWrites = (pixelsPerRow * coreData->bitsPerPixel / 8) % 4;    // Remaining bytes per row
  442.     
  443.     rowStart = baseAddressPageInfo.csBaseAddr;        // 1st row starts at the base address of this page
  444.     
  445.     // Scan the 'BPPToGrayPatternMap' to find the correct gray pattern for the absolute bit depth.
  446.     for (i = 0 ; i < kMapSize ; i++)
  447.     {
  448.         if (bppMap[i].bitsPerPixel == coreData->bitsPerPixel)
  449.         {
  450.             grayPattern = bppMap[i].grayPattern;
  451.             break;
  452.         }
  453.     }
  454.  
  455.     // Fill the page with the dithered gray pattern.
  456.     
  457.     for (row = 0 ; row < numberOfRows ; row++)
  458.     {
  459.         scratchPattern = grayPattern;                // Get the gray pattern for the start of this row
  460.         fillPtr = (UInt32 *) rowStart;                // Point to the beginning of row
  461.         
  462.         // Write out the requisite number of longs
  463.         for (i = 0 ; i < longWrites ; i++)
  464.         {
  465.             *fillPtr = scratchPattern;
  466.             fillPtr++;
  467.             
  468.             if (32 == coreData->bitsPerPixel)        // In 32 bpp, you need to invert the pattern so a
  469.                 scratchPattern = ~scratchPattern;    // FFFFFFFF 00000000 FFFFFFFF etc is produced.
  470.         }
  471.         
  472.         bytePtr = (UInt8 *) fillPtr;
  473.  
  474.         // Now see if there are any byte writes to do.
  475.         for (i = 0 ; i < byteWrites ; i++)
  476.         {
  477.             *bytePtr = (UInt8) (scratchPattern >> 24) ;                    // Use most significant byte
  478.             bytePtr++;                                                    // Use most significant byte
  479.             scratchPattern = scratchPattern << 8;                        // Get next byte in proper place
  480.         }
  481.         
  482.         rowStart += rowBytes;                        // Point rowStart to beginning of next row
  483.         grayPattern = ~grayPattern;                    // Invert pattern so next row will start w/opposite
  484.     }
  485.                 
  486.     // Check to see if we are in a direct color mode.  If we are, then we need to build a 
  487.     // black-to-white ramp in RGB and apply it to the hardware.
  488.     
  489.     if ((coreData->directColor) && (NULL != coreData->gammaTable))
  490.     {
  491.         err = GraphicsUtilBlackToWhiteRamp(coreData->gammaTable, coreData->depthMode,
  492.                 coreData->bitsPerPixel, coreData->luminanceMapping, coreData->directColor);
  493.         if (err)
  494.             goto ErrorExit;
  495.     }
  496.  
  497.     err = kGDXErrNoError;                                    // Everything okay
  498.     
  499. ErrorExit:
  500.  
  501.     return err;
  502. }
  503.  
  504.  
  505.  
  506. //=====================================================================================================
  507. //
  508. // GraphicsCoreSetGray()
  509. //    This routine is used with indexed devices to determine whether the control
  510. //    routine with cscSetEntries fills a card's CLUT with actual colors or with the luminance-equivalent
  511. //    gray tones.  For actual colors, the control routine is passed a csMode value of 0; for gray tones
  512. //    it is passed a csMode value of 1.  Luminance equivalence should be determined by converting each
  513. //    RGB value into the hue-saturation-brightness system and then selecting a gray value of equal
  514. //    brightness.  Mapping colors to lumimance-equivalent gray tones lets a color monitor emulate
  515. //    a monochrome exactly.
  516. //
  517. //    If the cscSetGray call is issued to a direct device, it sets the internal mapping state flag 
  518. //    and returns a CtlGood result but does not cause the color table to be luminance mapped.
  519. //    Short of using the control routine/ cscDirectSetEntries, there is no way to preview
  520. //    luminnace-mapped color images on the color display of a direct device.
  521. //    (Cards & Drivers, p. 208)
  522. //
  523. //    Check the value of 'grayPtr->csMode'.  If it is 0, set 'luminanceMapping' to false ; 
  524. //    if 1, set 'luminanceMapping' to true.
  525. //    if directColor = true, subsequent calls to CoreSetEntries will NOT do luminance mapping
  526. //
  527. //=====================================================================================================
  528. GDXErr GraphicsCoreSetGray(VDGrayRecord *grayPtr)
  529. {
  530.     GraphicsCoreData *coreData = GraphicsCoreGetCoreData();
  531.     GDXErr err = kGDXErrUnknownError;                            // Assume failure
  532.     
  533.     if (0 == grayPtr->csMode)
  534.         coreData->luminanceMapping = false;
  535.     else
  536.         coreData->luminanceMapping = true;
  537.  
  538.     if ( coreData->monoOnly == true )
  539.     {
  540.         // If a Mono Only device, always set luminance mapping to true.
  541.         // Additionally, change 'csMode' to alert client that the connected display is 'monoOnly'
  542.         coreData->luminanceMapping = true;
  543.         grayPtr->csMode = 1;                
  544.     }
  545.     
  546.     err = kGDXErrNoError;                                        // Everything okay
  547.     
  548. ErrorExit:
  549.  
  550.     return err;
  551. }
  552.  
  553.  
  554.  
  555. //=====================================================================================================
  556. //
  557. // GraphicsCoreSetInterrupt()
  558. //    This controls the generation of the VBL interrupts.  To enable interrupts, pass a csMode value
  559. //    of 0; to disable interrupts, pass a csMode value of 1.
  560. //
  561. //    Note:  This does NOT install or remove interrupt handlers.  It merely calls the OSS to set the
  562. //    hardware as appropriate.
  563. //
  564. //=====================================================================================================
  565. GDXErr GraphicsCoreSetInterrupt(const VDFlagRecord *flag)
  566. {
  567.     GraphicsCoreData *coreData = GraphicsCoreGetCoreData();
  568.     GDXErr err = kGDXErrUnknownError;                            // Assume failure
  569.  
  570.     Boolean enableInterrupts; 
  571.     
  572.     if (0 == flag->csMode)
  573.         enableInterrupts = true;
  574.     else
  575.         enableInterrupts = false;
  576.         
  577.     (void) GraphicsOSSSetVBLInterrupt(enableInterrupts);
  578.     
  579.     coreData->interruptsEnabled = enableInterrupts;                // Save vbl interrupt state
  580.     err = kGDXErrNoError;                                        // Everything okay
  581.     
  582. ErrorExit:
  583.  
  584.     return err;
  585. }
  586.  
  587.  
  588.  
  589. //=====================================================================================================
  590. //
  591. // GraphicsCoreDirectSetEntries()
  592. //    Normally, color table animation is not used on a direct device, but there are some special
  593. //    circumstances under which an application may want to change the color table hardware.  This routine
  594. //    provides the direct device with indexed mode functionality idential to the regular 'cscSetEntries'
  595. //    call.  The 'cscDirectSetEntries' routine has exactly the same functions and parameters as the
  596. //    regular 'cscSetEntries' routine, but it works only on a direct device.  If this call is issued to
  597. //    an indexed device, it should return an error indication.
  598. //
  599. //=====================================================================================================
  600. GDXErr GraphicsCoreDirectSetEntries(const VDSetEntryRecord *setEntry)
  601. {
  602.     GraphicsCoreData *coreData  = GraphicsCoreGetCoreData() ;
  603.     GDXErr err = kGDXErrUnknownError;                                    // Assume failure
  604.  
  605.     // Check to make sure that were are in a direct, not indexed, mode.
  606.     if ( !(coreData->directColor) )
  607.     {
  608.         err = kGDXErrInvalidForDirectDevice;
  609.         goto ErrorExit;
  610.     }
  611.     
  612.     err = GraphicsUtilSetEntries(setEntry, coreData->gammaTable, coreData->depthMode,
  613.             coreData->bitsPerPixel, coreData->luminanceMapping, coreData->directColor);
  614.     
  615. ErrorExit:
  616.  
  617.     return err;
  618. }
  619.  
  620.  
  621.  
  622. //=====================================================================================================
  623. //
  624. // GraphicsCoreSwitchMode()
  625. //    This routine is quite similar to GraphicsCoreSetMode(), except that it supports "on-the-fly"
  626. //    resolution swithing.
  627. //    This routine lets you change the DepthMode and/or the current graphics page and/or the current
  628. //    DisplayModeID. 
  629. //
  630. //    For this routine, the relevant fields indicated by 'VDSwitchInfoRec' are:
  631. //            ->    csMode            desired depth mode
  632. //            ->    csData            desired DisplayModeID
  633. //            ->    csPage            desired display page
  634. //            <-    csBaseAddr        base address of desired page
  635. //
  636. //=====================================================================================================
  637. GDXErr GraphicsCoreSwitchMode(VDSwitchInfoRec *switchInfo)
  638. {
  639.     GraphicsCoreData *coreData = GraphicsCoreGetCoreData();
  640.     GDXErr err = kGDXErrUnknownError;                                    // Assume failure
  641.  
  642.     Boolean directColor;
  643.     void *baseAddress;
  644.     Boolean modePossible = false;
  645.     
  646.     DisplayModeID displayModeID = (DisplayModeID) switchInfo->csData;
  647.     DepthMode depthMode = (DepthMode) switchInfo->csMode;
  648.     SInt16 page = switchInfo->csPage;
  649.  
  650.     // Make sure that the requested 'DisplayModeID', 'DepthMode' and page are valid
  651.     err = GraphicsHALModePossible(displayModeID, depthMode, page, &modePossible);
  652.     if (!modePossible || err)
  653.     {
  654.         err = kGDXErrRequestedModeNotPossible;
  655.         goto ErrorExit;
  656.     }
  657.     
  658.     // Set the CLUT to 50% gray.  This is done because 50% gray looks the same at all pixel depths,
  659.     // so no funny screen artifacts will be seen during mode switching.
  660.     
  661.     err = GraphicsHALGrayCLUT(coreData->gammaTable);
  662.     if (err)
  663.         goto ErrorExit;
  664.         
  665.     err = GraphicsHALProgramHardware(displayModeID, depthMode, page, &directColor, &baseAddress);
  666.     if (err)
  667.         goto ErrorExit;
  668.             
  669.     // Request has been successfully completed, so update the coreData to relfect the current state.
  670.     
  671.     coreData->displayModeID = displayModeID;
  672.     coreData->depthMode = depthMode;
  673.     coreData->currentPage = page;
  674.     coreData->baseAddress = baseAddress;
  675.     coreData->directColor = directColor;
  676.     
  677.     // Return the new base address in switchInfo->csBaseAddr
  678.     switchInfo->csBaseAddr = baseAddress;
  679.     
  680.     // Map the relative bit depth (DepthMode) to absolute bit depth
  681.     err = GraphicsHALMapDepthModeToBPP(coreData->depthMode, &coreData->bitsPerPixel);
  682.     
  683.     if (err)
  684.         goto ErrorExit;
  685.     
  686.     err = kGDXErrNoError;                                                // Everything okay
  687.         
  688. ErrorExit:
  689.  
  690.     return err;
  691. }
  692.  
  693.  
  694.  
  695. //=====================================================================================================
  696. //
  697. // GraphicsCoreSetSync()
  698. //    If the display supported the VESA Device Power Management Standard (DPMS), it would respond
  699. //    to HSync and VSync in the following manner:
  700. //    The VESA Standards are:
  701. //    
  702. //    State           Vert Sync        Hor Sync        Video
  703. //    -----            --------        ---------        ------
  704. //    Active             Pulses          Pulses          Active
  705. //    Standby            Pulses           No Pulses          Blanked
  706. //    Idle            No Pulses          Pulses            Blanked
  707. //    Off                 No Pulses        No Pulses        Blanked
  708. //
  709. //
  710. //    For this routine, the relevant fields of the 'VDSyncInfoRec' structure are as follows:
  711. //            ->    csMode        bit field of the sync bits that need to be disabled/enabled
  712. //
  713. //                kDisableHorizontalSyncBit        set if HW should disable Horizontal Sync (No Pulses)
  714. //                kDisableVerticalSyncBit            set if HW should disable Vertical Sync (No Pulses)
  715. //                kDisableCompositeSyncBit        set if HW should disable Composite Sync (No Pulses)
  716. //                kSyncOnRedEnableBit                set if HW should sync on Red
  717. //                kSyncOnGreenEnableBit            set if HW should sync on Green
  718. //                kSyncOnBlueEnableBit            set if HW should sync on Blue
  719. //
  720. //
  721. //            ->    csFlags            Mask of the bits that are valid in the csMode bit field
  722. //
  723. //    Note! for compatibility with the Energy Saver cdev:
  724. //        To put a display into the Active state, is passes in csMode = 0x00, csFlags = 0x00
  725. //            map to csMode = 0x00, csFlags = 0x07
  726. //
  727. //    Somebody (3rd Party Screen Savers) sets csMode = 0xFF, csFlags = 0xFF to turn off a display...
  728. //            map to csMode = 0x07, csFlags = 0x07
  729. //
  730. //    For NEW callers, If v or h sync gets hit, csFlags should be 0x03.  This ensures that both v and h 
  731. //    sync get set to the correct state.
  732. //    
  733. //=====================================================================================================
  734. GDXErr GraphicsCoreSetSync(VDSyncInfoRec *sync)
  735. {
  736.     GDXErr err = kGDXErrUnknownError;                            // Assume failure
  737.  
  738.     UInt8 syncBitField = sync->csMode;                            // Bit field for syncs to hit
  739.     UInt8 syncBitFieldValid = sync->csFlags;                    // Mask for valid bits in syncBitField
  740.  
  741.  
  742.     // If csMode = 0x00, csFlags = 0x00, map to csMode = 0x00, csFlags = 0x07
  743.     if ( (0x00 == syncBitField) && (0x00 == syncBitFieldValid) )
  744.     {
  745.         syncBitField = 0;
  746.         syncBitFieldValid = kDPMSSyncMask;
  747.     }
  748.  
  749.     // If csMode = 0xFF, csFlags = 0xFF, map to csMode = 0x07, csFlags = 0x07
  750.     if ( (0xFF == syncBitField) && (0xFF == syncBitFieldValid) )
  751.     {
  752.         syncBitField = 0x07;
  753.         syncBitFieldValid = kDPMSSyncMask;
  754.     }
  755.     
  756.     // Error checking for "compatability" is done.
  757.     
  758.     // Make sure only 1 (if any) of the kSyncOn RGB bits is set
  759.     if ( (syncBitFieldValid & kSyncOnMask) > kSyncOnBlueMask )
  760.     {
  761.         err = kGDXErrInvalidParameters;
  762.         goto ErrorExit;
  763.     }
  764.     
  765.     err = GraphicsHALSetSync(syncBitField, syncBitFieldValid);
  766.     
  767.     sync->csFlags = syncBitFieldValid;                                // Return HAL's flags to caller
  768.         
  769. ErrorExit:
  770.  
  771.     return err;
  772. }
  773.  
  774.  
  775.  
  776. //=====================================================================================================
  777. //
  778. // GraphicsCoreSetPreferredConfiguration()
  779. //    This call is the counterpart to the GetPreferredConfiguration status call. This call will be used
  780. //    by clients to set the preferred DepthMode and DisplayModeID.  This means that the card should save
  781. //    this information in non-volatile RAM so that it persists accross reboots.
  782. //
  783. //    For this routine, the relevant fields of the 'VDSwitchInfoRec' structure are as follows:
  784. //        ->            csMode                    Depth of preferred resolution
  785. //        ->            csData                    DisplayModeID of preferred resolution
  786. //
  787. //=====================================================================================================
  788. GDXErr GraphicsCoreSetPreferredConfiguration(const VDSwitchInfoRec *switchInfo)
  789. {
  790.     GraphicsCoreData *coreData = GraphicsCoreGetCoreData() ;
  791.     GDXErr err = kGDXErrUnknownError;                                // Assume failure
  792.     GraphicsPreferred graphicsPreferred;
  793.     
  794.     
  795.     graphicsPreferred.depthMode = switchInfo->csMode;
  796.     graphicsPreferred.displayModeID = switchInfo->csData;
  797.     graphicsPreferred.displayCode = coreData->displayCode;
  798.     
  799.     err = GraphicsOSSSetCorePref(&coreData->regEntryID, &graphicsPreferred);
  800.         
  801. ErrorExit:
  802.  
  803.     return err;
  804. }
  805.  
  806.  
  807.  
  808.  
  809. //=====================================================================================================
  810. //
  811. // GraphicsCoreSetHardwareCursor()
  812. //    SetHardwareCursor is a required routine for drivers that support hardware cursors. QuickDraw uses
  813. //    the SetHardwareCursor control call to set up the hardware cursor and determine whether the hardware
  814. //    can support it. The driver must determine whether it can support the given cursor and, if so,
  815. //    program the hardware cursor frame buffer (or equivalent), set up the CLUT, and return noErr.
  816. //    If the driver cannot support the cursor it must return an error. The driver must remember whether
  817. //    this call was successful for subsequent GetHardwareCursorDrawState() or DrawHardwareCursor() calls,
  818. //    but should not change the cursor’s x or y coordinates or its visible state.
  819. //
  820. //=====================================================================================================
  821. GDXErr GraphicsCoreSetHardwareCursor(const VDSetHardwareCursorRec  *setHardwareCursor)
  822. {
  823.     GraphicsCoreData *coreData = GraphicsCoreGetCoreData() ;
  824.     GDXErr err = kGDXErrUnknownError;                                // Assume failure
  825.  
  826.     err = GraphicsHALSetHardwareCursor(coreData->gammaTable, 
  827.             (coreData->luminanceMapping && (!coreData->directColor)),
  828.             (void *) setHardwareCursor->csCursorRef);
  829.  
  830. ErrorExit:
  831.  
  832.     return err;
  833. }
  834.  
  835.  
  836.  
  837. //=====================================================================================================
  838. //
  839. // GraphicsCoreDrawHardwareCursor()
  840. //    This routines is called to set the hardware cursor's X and Y posisition, and its current visibility
  841. //    state.
  842. //
  843. //=====================================================================================================
  844. GDXErr GraphicsCoreDrawHardwareCursor(const VDDrawHardwareCursorRec  *drawHardwareCursor)
  845. {
  846.     GDXErr err = kGDXErrUnknownError;                                // Assume failure
  847.  
  848.     err = GraphicsHALDrawHardwareCursor(drawHardwareCursor->csCursorX,
  849.             drawHardwareCursor->csCursorY, drawHardwareCursor->csCursorVisible);
  850.  
  851. ErrorExit:
  852.  
  853.     return err;
  854. }
  855.  
  856.  
  857.  
  858. //=====================================================================================================
  859. //
  860. // GraphicsCoreSetPowerState()
  861. //    The graphics hw might have the ability to to go into some kind of power saving mode.  Just
  862. //    pass the call to the HAL.
  863. //
  864. //=====================================================================================================
  865. GDXErr GraphicsCoreSetPowerState(VDPowerStateRec *vdPowerState)
  866. {
  867.  
  868.     GDXErr err = kGDXErrUnknownError;                                // Assume failure
  869.     
  870.     err = GraphicsHALSetPowerState(vdPowerState);
  871.         
  872. ErrorExit:
  873.  
  874.     return err;
  875. }
  876.