⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cursor.c

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 C
字号:
//
// Permedia3 Sample Display Driver
// cursor.c
//
// Copyright (c) 2000 Microsoft Corporation. All rights reserved.
//
// This module contains the code for managing the cursor. This is implemented
// using the hardware cursor on the Permedia 3.

#include "pch.h"  // Precompiled header support.
#include "debug.h"
#include "struct.h"
#include "proto.h"
#include "register.h"

// Each time we set a cursor, we record the unique value from that cursor.
// This helps us not set the same cursor twice. Start with a sentinal value.

#define HIDDEN_CURSOR 0xFFFFFFFF

static ULONG l_CurrentCursor = HIDDEN_CURSOR;

// Internal prototypes. These functions are not exposed outside this module.

static void
SetCursorPalette(
  BYTE Index,
  BYTE Red,
  BYTE Green,
  BYTE Blue
  );

static BYTE
MonoCursorInterleave(
  BYTE AndBits,
  BYTE XorBits,
  BOOL HighNibble
  );

ULONG
DrvSetPointerShape(
  SURFOBJ *  Surface,
  SURFOBJ *  AndXorMask,
  SURFOBJ *  Colors,
  XLATEOBJ * ColorsXlate,
  LONG       XHot,
  LONG       YHot,
  LONG       X,
  LONG       Y,
  RECTL *    BoundaryRect,
  FLONG      Flags
  )
{
  // DrvSetPointerShape
  // This function is called by GDI to set the cursor shape, hot spot,
  // and position. We rely on GDI calling this at least once as part of
  // it's boot-up sequence.

  // Local variables.

  // This is the function's return value. You can find the definition of the
  // SPS_* macros in winddi.h.

  ULONG FnRetVal = SPS_ERROR;

  ULONG i;
  ULONG j;
  ULONG Register;

  ULONG Height;
  ULONG Width;
  ULONG BytesInCursor;
  LONG  Stride;

  BYTE * AndMask;
  BYTE * XorMask;

  BYTE PixelValues;

  // Check parameters.

  // Windows CE does not currently use the BoundaryRect or the Flags
  // parameters.

  Assert(BoundaryRect == NULL);
  Assert(Flags == 0);

  Enter(L"DrvSetPointerShape");

  // !TODO! FIFO Space check?

  // Move the cursor.

  DrvMovePointer(Surface, X, Y, BoundaryRect);

  if (AndXorMask == NULL ||
      AndXorMask->iUniq != l_CurrentCursor) {

    // Disable the cursor for update.

    WriteMaskedRdReg(r_RDCursorMode,
                     b_RDCursorMode_CursorEnable,
                     0);

    // Disable byte doubling and position readback. The DDI interface has no
    // provision for cursor position readback, so it doesn't matter what mode
    // we use.

    WriteRdReg(r_RDCursorControl, 0);
 
    // Set the new hot-spot.

    WriteRdReg(r_RDCursorHotSpotX,
               (BYTE)(XHot & b_RDCursorHotSpotX_X));

    WriteRdReg(r_RDCursorHotSpotY,
               (BYTE)(YHot & b_RDCursorHotSpotY_Y));

    // Update the pointer itself.

    if (AndXorMask) {

      if (!Colors) {

        // It's a monochrome cursor.

        // Enable "Microsoft Windows" monochrome mode. Also make sure that we
        // disable reverse pixel ordering while we're at it.

        WriteMaskedRdReg(r_RDCursorMode,
                         b_RDCursorMode_Type |
                         b_RDCursorMode_ReversePixelOrder,
                         0);

        // Setup our "palette." Black as color 1 and white as color 2.

        SetCursorPalette(1, 0x00, 0x00, 0x00);
        SetCursorPalette(2, 0xFF, 0xFF, 0xFF);

        // Load the monochrome bitmap by getting the AND and the XOR bits
        // from their respective locations, smashing them together, and
        // dropping them in the palette cursor pattern bits.

        // Check size first. Can only be 32x32 or 64x64.

        Height = AndXorMask->sizlBitmap.cy;
        Width = AndXorMask->sizlBitmap.cx;
        Stride = AndXorMask->lDelta;
        BytesInCursor = (Width / 8) * (Height / 2);

        // Set our pointers. The XOR mask is first in the AndXorMask, and the
        // AND mask is directly after it. (Note that we need to position these
        // pointers correctly based on if the bitmap is top-up or bottom-down.)

        if (Stride > 0) {
          XorMask = (BYTE *)AndXorMask->pvScan0;
          AndMask = ((BYTE *)AndXorMask->pvScan0) + BytesInCursor;
        }
        else {
          XorMask = ((BYTE *)AndXorMask->pvScan0) - BytesInCursor;
          AndMask = (BYTE *)AndXorMask->pvScan0;
        }

        // Note that because there are two masks, the height is double.

        if ((Width == 32 && Height == 64)) {

          // Use partition 0 -> We can then share "pixel plotting" code
          // with 64x64.

          WriteMaskedRdReg(r_RDCursorMode,
                           b_RDCursorMode_Format,
                           2);
        }
        else if ((Width == 64 && Height == 128)) {

          WriteMaskedRdReg(r_RDCursorMode,
                           b_RDCursorMode_Format,
                           0);
        }
        else {
          Error(L"Unsupported cursor size.\n");
        }

        // Iterate over scanlines in the cursor. For each scanline, iterate over
        // the bytes in the scanline. Each byte needs to be interleaved. This
        // resolves into 8 pixels. There are 4 pixels per register, so each inner
        // loop results in two byte register writes.

        for (i = 0, Register = r_RDCursorPattern; 
             i < (Height / 2); 
             i++, AndMask += Stride, XorMask += Stride) {

          for (j = 0; j < (Width / 8); j++) {

            PixelValues = MonoCursorInterleave(*(AndMask + j),
                                               *(XorMask + j),
                                               TRUE);

            WriteRdReg(Register++, PixelValues);

            PixelValues = MonoCursorInterleave(*(AndMask + j),
                                               *(XorMask + j),
                                               FALSE);

            WriteRdReg(Register++, PixelValues);
          }
        }

        // Re-enable the cursor.

        WriteMaskedRdReg(r_RDCursorMode,
                         b_RDCursorMode_CursorEnable,
                         b_RDCursorMode_CursorEnable);

        l_CurrentCursor = AndXorMask->iUniq;
        FnRetVal = SPS_ACCEPT_NOEXCLUDE;
      }
      else {

        Message(L"Color cursors are not yet implemented!\n");
        FnRetVal = SPS_DECLINE;
      }  
    }
    else {

      // No AndXorMask means that we should hide the cursor. We
      // accomplish this by leaving the cursor disabled.

      l_CurrentCursor = HIDDEN_CURSOR;
      FnRetVal = SPS_ACCEPT_NOEXCLUDE;
    }
  }
  else {

    // Don't change the cursor to something it already is!

    FnRetVal = SPS_ACCEPT_NOEXCLUDE;
  }

  Exit(L"DrvSetPointerShape");

  return FnRetVal;
}
 
void 
DrvMovePointer(
  SURFOBJ * Surface,
  LONG      X,
  LONG      Y,
  RECTL *   BoundaryRect
  )
{
  // DrvMovePointer
  // This function is called by GDI in order to position the cursor. Note
  // that the Permedia3 does not complete a cursor position change until
  // the RDCursorYHigh register is written to in order to avoid artifacts
  // from half-formed positions.

  // Check parameters.

  // We can only position the pointer on the primary surface.

  Assert(((PERM3_SURFACE *)Surface->dhsurf)->Ptr == GetPrimarySurface()->Ptr);

  Assert(X >= 0 && X < (LONG)GetDisplayModeWidth(GetCurrentMode()));
  Assert(Y >= 0 && Y < (LONG)GetDisplayModeHeight(GetCurrentMode()));

  // Windows CE does not currently use the BoundaryRect.

  Assert(BoundaryRect == NULL);

  // !TODO! FIFO space check.

  Enter(L"DrvMovePointer");

  // Write the X position.

  WriteRdReg(r_RDCursorXLow,
             (BYTE)(X & b_RDCursorXLow_XLow));

  WriteRdReg(r_RDCursorXHigh,
             (BYTE)((X >> 8) & b_RDCursorXHigh_XHigh));

  // Write the Y position.

  WriteRdReg(r_RDCursorYLow,
             (BYTE)(Y & b_RDCursorYLow_YLow));

  WriteRdReg(r_RDCursorYHigh,
             (BYTE)((Y >> 8) & b_RDCursorYHigh_YHigh));

  Exit(L"DrvMovePointer");
}

void
SetCursorPalette(
  BYTE Index,
  BYTE Red,
  BYTE Green,
  BYTE Blue
  )
{
  // SetCursorPalette
  // This function helps set the registers that define a particular color
  // for a particular index for the cursor. The Permedia3 literature refers
  // to that palette as color index 1 to 15. We will continue that
  // nomenclature, but note that color index 1 is offset 0 from the beginning
  // of the palette registers.

  // Local constants.

  // Location of the R, G, and B components in relation to a base index 
  // offset.

  const ULONG RedOffset = 0;
  const ULONG GreenOffset = 1;
  const ULONG BlueOffset = 2;

  // Local variables.

  ULONG IndexBase;

  // Check parameters.

  // Red, Green, and Blue can be anything.

  Assert(Index <= 15);

  Enter(L"SetCursorPalette");

  // !TODO! FIFO space check

  // Compute the base address of the registers for this index. Note that the
  // Permedia's cursor palette is "upside-down." That's why we need the extra
  // subtraction. 

  IndexBase = r_RDCursorPalette + ((15 - Index) * 3);

  // Write the colors.

  WriteRdReg(IndexBase + RedOffset,
             Red);

  WriteRdReg(IndexBase + GreenOffset,
             Green);

  WriteRdReg(IndexBase + BlueOffset,
             Blue);

  Exit(L"SetCursorPalette");
}

BYTE
MonoCursorInterleave(
  BYTE AndBits,
  BYTE XorBits,
  BOOL HighNibble
  )
{
  // MonoCursorInterleave
  // This function interleaves 4 bits from the high and low bits values
  // into a single byte. We determine which nibble to interleave from
  // from the BOOL.

  // Local variables.

  BYTE FnRetVal;

  // Check parameters.

  // No checking necessary for AndBits, XorBits, and HighNibble.

  Enter(L"MonoCursorInterleave");

  // Check if we are reading from the high nibble.

  if (HighNibble) {

    FnRetVal = ((AndBits & 0x00000010) << 3) |
               ((XorBits & 0x00000010) << 2) |
               ((AndBits & 0x00000020)     ) |
               ((XorBits & 0x00000020) >> 1) |
               ((AndBits & 0x00000040) >> 3) |
               ((XorBits & 0x00000040) >> 4) |
               ((AndBits & 0x00000080) >> 6) |
               ((XorBits & 0x00000080) >> 7);

  }
  else {

    FnRetVal = ((AndBits & 0x00000001) << 7) |
               ((XorBits & 0x00000001) << 6) |
               ((AndBits & 0x00000002) << 4) |
               ((XorBits & 0x00000002) << 3) |
               ((AndBits & 0x00000004) << 1) |
               ((XorBits & 0x00000004)     ) |
               ((AndBits & 0x00000008) >> 2) |
               ((XorBits & 0x00000008) >> 3);
  }

  Exit(L"MonoCursorInterleave");

  return FnRetVal;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -