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

📄 blt.c

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 C
📖 第 1 页 / 共 3 页
字号:
  // DrvTransparentBlt
  // This function peforms a GDI BitBlt. It is capable of only SRCCOPY blits,
  // with color conversion, clipping, stretching, and a source color key.

  // Other ROPs, masked blits, brushes and alpha blending are not expressable.

  // Local variables.

  PERM3_BLT_PARAM Parameters;
  PERM3_SURFACE   Dest;
  RECT            LocalDestRect;
  PERM3_SURFACE   Source;
  RECT            LocalSourceRect;
  BOOL            FnRetVal;  // Return value for this function.
  ENUMRECTS     * ClipperRects = NULL;
  ULONG           SizeofClipperRects;
  ULONG           ClipperSortDirection = CD_ANY;
  COLOR_SPACE     ColorKey;

  // Check parameters.

  Assert(sizeof(SIZE) == sizeof(SIZEL));
  Assert(sizeof(RECT) == sizeof(RECTL));
  Assert(sizeof(POINT) == sizeof(POINTL));

  // !TODO! Change this once we return something real from DrvEnablePDEV.

  Assert((ULONG)DestSurface->dhpdev == 123);

  Enter(L"DrvTransparentBlt");

  memset(&Parameters, 0, sizeof(PERM3_BLT_PARAM));

  // Fill in Parameters.

  Parameters.Rop = 0x0000CCCC;  // SRCCOPY

  // SRCCOPY must have source.

  Assert(SourceSurface != NULL);

  // Destination surface details.

  SurfobjToPerm3Surface(&Dest,
                        DestSurface,
                        Xlate,
                        FALSE);

  Parameters.Destination = (const SURFACE *)&Dest;

  if (DestRect != NULL) {

    // We know that RECT and RECL are really the same thing. The assert above
    // protects this.

    Parameters.DestRect = (RECT *)DestRect;
  }
  else {

    LocalDestRect.left = 0;
    LocalDestRect.top = 0;
    LocalDestRect.right = Dest.Size.cx;
    LocalDestRect.bottom = Dest.Size.cy;
    Parameters.DestRect = &LocalDestRect;
  }

  // Reject blits that have no height or width.

  if (Parameters.DestRect->top == Parameters.DestRect->bottom ||
      Parameters.DestRect->left == Parameters.DestRect->right) {

    return TRUE;
  }

  // Source surface details.

  SurfobjToPerm3Surface(&Source,
                        SourceSurface,
                        Xlate,
                        TRUE);

  Parameters.Source = (const SURFACE *)&Source;

  if (SourceRect != NULL) {

    // We know that RECT and RECL are really the same thing. The assert above
    // protects this.

    Parameters.SourceRect = (RECT *)SourceRect;
  }
  else {

    LocalSourceRect.left = 0;
    LocalSourceRect.top = 0;
    LocalSourceRect.right = Source.Size.cx;
    LocalSourceRect.bottom = Source.Size.cy;
    Parameters.SourceRect = &LocalSourceRect;
  }

  // Check for an overlap, and set the blitting direction appropriately.

  if (Source.Ptr == Dest.Ptr) {

    if (Parameters.SourceRect->bottom > Parameters.DestRect->top &&
        Parameters.SourceRect->top < Parameters.DestRect->bottom &&
        Parameters.SourceRect->right > Parameters.DestRect->left &&
        Parameters.SourceRect->left < Parameters.DestRect->right) {

      if (Parameters.SourceRect->top == Parameters.DestRect->top) {

        // Horizontal blt, just set ScanXPositive appropriately.

        Parameters.ScanXPositive = (BOOL)(Parameters.SourceRect->left >= Parameters.DestRect->left);
      }
      else {

        // Non horizontal blts, just set ScanYPositive appropriately.

        Parameters.ScanYPositive = (BOOL)(Parameters.SourceRect->top >= Parameters.DestRect->top);
      }

      // Might need particular clipping rectangles sort order.

      if (Clipper) {

        if (Parameters.SourceRect->top > Parameters.DestRect->top) {

          ClipperSortDirection = (Parameters.SourceRect->left > Parameters.DestRect->left) ? CD_RIGHTDOWN : CD_LEFTDOWN;
        }
        else {
          
          ClipperSortDirection = (Parameters.SourceRect->left > Parameters.DestRect->left) ? CD_RIGHTUP : CD_LEFTUP;
        }
      }
    }
  }

  if (Clipper && Clipper->iDComplexity != DC_TRIVIAL) {

    if (Clipper->iDComplexity == DC_RECT) {

      Parameters.ClipRectCount = 1;
      Parameters.ClipRect = (const RECT *)&(Clipper->rclBounds);
    }
    else if (Clipper->iDComplexity == DC_COMPLEX) {

      // Extract all of the rectangles from GDI.

      Parameters.ClipRectCount = CLIPOBJ_cEnumStart(Clipper,
                                                    TRUE,
                                                    CT_RECTANGLES,
                                                    ClipperSortDirection,
                                                    0);

      // The ENUMRECTS strcuture already contains space for 1 rectangle.

      SizeofClipperRects = sizeof(ENUMRECTS) +
                           sizeof(RECT) * (Parameters.ClipRectCount - 1);
      ClipperRects = SystemAlloc(SizeofClipperRects);
      if (ClipperRects) {

        CLIPOBJ_bEnum(Clipper,
                      SizeofClipperRects,
                      (ULONG *)ClipperRects);

        Assert(ClipperRects->c == Parameters.ClipRectCount);

        Parameters.ClipRect = (const RECT *)ClipperRects->arcl;
      }
      else {

        Error(L"System memory allocation failure.\n");
      }
    }
    else {
      Error(L"Unknown clipping complexity.\n");
    }
  }

  // Setup the color key.

  Parameters.ColorKeyType = SourceColorKey;
 
  ColorKey.LowValue = TransColor;
  ColorKey.HighValue = TransColor;

  Parameters.SourceColorKey = &ColorKey;

  // Call the Blt with our newly constructed parameter block.

  FnRetVal = TryBothBlt(&Parameters);

  FreeSurfobjDerivedPerm3Surface(&Dest);
  FreeSurfobjDerivedPerm3Surface(&Source);

  if (ClipperRects) {
    SystemFree(ClipperRects);
  }

  Exit(L"DrvTransparentBlt");

  return FnRetVal;
}


BOOL
TryBothBlt(
  PERM3_BLT_PARAM * Parameters
  )
{
  // TryBothBlt
  // This function attempts a hardware blt to fulfill the given parameter
  // block, and if that fails, attempts a software fallover.

  // Local variables.

  BOOL         FnRetVal = FALSE;  // Return value for this function.
  ULONG        i;
  ULONG        ClipRectCount;

  // Check parameters.

  // !TODO!

  Enter(L"TryBothBlt");

  ClipRectCount = Parameters->ClipRectCount;

  if (ClipRectCount == 0 || ClipRectCount == 1) {

    if (!(FnRetVal = HardwareBlt(Parameters))) {

      FnRetVal = SoftwareBlt(Parameters);
    }
  }
  else {

    Parameters->ClipRectCount = 1;

    for (i = 0; i < ClipRectCount; i++) {

      if (!(FnRetVal = HardwareBlt(Parameters))) {

        FnRetVal = SoftwareBlt(Parameters);
      }
      if (!FnRetVal) break;
      ((RECT *)Parameters->ClipRect)++;
    }
  }

  Exit(L"TryBothBlt");

  return FnRetVal;
}

BOOL
HardwareBlt(
  PERM3_BLT_PARAM * Parameters
  )
{
  // HardwareBlt
  // This function attempts to execute the blit specified in the parameters
  // block using the Permedia3 display hardware. It fails blits that it
  // doesn't support by returning FALSE. This allows us an attempt with the
  // software fallover.

  // Local constants.

  // These are used to index into the flags arrays for which surfaces are
  // needed (according to the ROP,) for a particular blit.

  const ULONG Foreground = 0;
  const ULONG Background = 1;

  // Local variables.

  BOOL    FnRetVal = FALSE;  // Return value for this function.

  ULONG   DestRectHeight;
  ULONG   DestRectWidth;

  // Source surface offset in memory. Computed from the source and destination
  // positions.

  ULONG   SourceOffset;

  // The first bit to consume from the first 32 bit value in the bit mask.

  ULONG   BitMaskOffset;

  // We accumulate the bits we will write into the Config2D and Render2D
  // registers here.

  ULONG   Config2D;
  ULONG   Render2D;

  // Foreground and background Permedia3 logicops.

  USHORT  Logicop[2];

  // Flags that we compute concerning the nature of the blit.

  BOOL    NeedMask;
  BOOL    NeedSource[2];
  BOOL    NeedDestRead[2];
  BOOL    NeedPattern[2];

  // Did we turn on clipping?

  BOOL    ResetClipping = FALSE;

  // Did we turn on chromakeying?

  BOOL    ResetChromaKey = FALSE;

  // Need to compute color format to program chromkeying.

  ULONG   ColorFormat;

  // Foreground and background ROP3s.

  BYTE    Rop3[2];

  // Check parameters.

  Assert(Parameters != NULL);
  Assert(Parameters->Destination != NULL);  

  // !TODO! Finish parameters checks...

  Enter(L"HardwareBlt");

  // Save pointer derefrences by caching values from the parameters structure.

  Assert((Parameters->Rop >> 16) == 0);

  Rop3[Foreground] = (BYTE)Parameters->Rop;
  Rop3[Background] = (BYTE)(Parameters->Rop >> 8);

  // Save us some computations.

  DestRectWidth = RectWidth(Parameters->DestRect);
  DestRectHeight = RectHeight(Parameters->DestRect);

  // Blitting is a multipart task. Each blit is composed of several different,
  // hardware chores, which are shared. For example, destination rectangles
  // and surface setup is the same for nearly every blit, so the code can be
  // shared.

  Config2D = 0;
  Render2D = b_Render2D_SpanOperation;

  // The first job is to discover some information about the nature of the
  // blit we are performing by checking out the ROP.

  NeedMask = (BOOL)(Rop3[Foreground] != Rop3[Background]);

  NeedDestRead[Foreground] = (BOOL)((((Rop3[Foreground] >> 1) ^ Rop3[Foreground]) & 0x55) != 0);
  NeedSource[Foreground]   = (BOOL)((((Rop3[Foreground] >> 2) ^ Rop3[Foreground]) & 0x33) != 0);
  NeedPattern[Foreground]  = (BOOL)((((Rop3[Foreground] >> 4) ^ Rop3[Foreground]) & 0x0F) != 0);

  if (NeedMask) {
    NeedDestRead[Background]   = (BOOL)((((Rop3[Background] >> 1) ^ Rop3[Background]) & 0x55) != 0);
    NeedSource[Background] = (BOOL)((((Rop3[Background] >> 2) ^ Rop3[Background]) & 0x33) != 0);
    NeedPattern[Background]  = (BOOL)((((Rop3[Background] >> 4) ^ Rop3[Background]) & 0x0F) != 0);
  }
  else {
    NeedDestRead[Background] = FALSE;
    NeedSource[Background]   = FALSE;
    NeedPattern[Background]  = FALSE;
  }

  // Determine the logic-op(s). The nature of the Permedia3 span hardware will
  // only allow us destination readback along with another surface (could be
  // source, constant color, or LUT pattern data.)

  Logicop[Foreground] = LookupLogicop(Rop3[Foreground]);
  if (Logicop[Foreground] == NO_APPROPRIATE_OP) {

    // Bail. We cannot accelerate this ROP.

    return FALSE;
  }
  Assert((NeedSource[Foreground] & NeedPattern[Foreground]) != 1);

  Config2D |= b_Config2D_ForegroundLogicalOpEnable;
  Config2D |= (Logicop[Foreground] << 7);

  if (NeedMask) {

    Logicop[Background] = LookupLogicop(Rop3[Background]);
    if ((Logicop[Background] == NO_APPROPRIATE_OP)         ||
        (NeedSource[Foreground] & NeedPattern[Background]) ||
        (NeedPattern[Foreground] & NeedSource[Background])) {

      // Bail we cannot accelerate this ROP.

      return FALSE;
    }
    Assert((NeedSource[Background] & NeedPattern[Background]) != 1);

    Config2D |= b_Config2D_BackgroundLogicalOpEnable;
    Config2D |= (Logicop[Background] << 12);
  }

  // Check the remaining restrictions on this functions capability. Punt
  // anything we can't handle.

  if (Parameters->Destination->Type != VideoMemory) return FALSE;
  if (!IsSameFormat(Parameters->Destination->Format,
                    (const FORMAT *)GetDisplayModeFormat(GetCurrentMode()))) return FALSE;

  if (Parameters->Source) {
    if (Parameters->Source->Type != VideoMemory) return FALSE;
    if (!IsSameFormat(Parameters->Source->Format,
                      Parameters->Destination->Format)) return FALSE;
    if (RectWidth(Parameters->SourceRect) != RectWidth(Parameters->DestRect)) return FALSE;
    if (RectHeight(Parameters->SourceRect) != RectHeight(Parameters->DestRect)) return FALSE;
  }
  if (Parameters->Mask) {
    if (Parameters->Mask->Format->BitsPerPixel != 1) return FALSE;
  }
  if (Parameters->ColorKeyType == SourceAndDestColorKey) return FALSE;
  if (Parameters->Brush) {
    if (Parameters->Brush->Size.cx != 8 ||
        Parameters->Brush->Size.cy != 8) {
      return FALSE;
    }
    if (!IsSameFormat(Parameters->Brush->Format,
                      (const FORMAT *)GetDisplayModeFormat(GetCurrentMode()))) return FALSE;
  }

  // Make sure we are in the 2D rendering context.

  Restore2DContext();

  // The next step is to setup the hardware for a masked blit, if necessary.

  if (NeedMask) {

    Assert(Parameters->Mask != NULL);

    // Specifies that we need to use the opaque spans (background ROPS.)
    // Bit mask consumption order is specified as part of the 2D context.

    Config2D |= b_Config2D_OpaqueSpan;

    Render2D |= (2 << 12); // SyncOnBitMask

    // Compute which bit needs to be consumed first in the first ulong.
    // !TODO! How is this impacted by mirroring the bit mask?

    BitMaskOffset = (Parameters->MaskRect->left & 0x0000001F);

    WriteRegUlong(r_RasterizerMode,
                  b_RasterizerMode_MirrorBitMask  |
                  (3 << 7) |  // byteswap bitmasks ABCD => DCBA
                  (BitMaskOffset << 10)           |
                  b_RasterizerMode_BitMaskPacking |
                  b_RasterizerMode_YLimitsEnable  |
                  b_RasterizerMode_OpaqueSpans);
  }
  else {

    Assert(Parameters->Mask == NULL);
  }

⌨️ 快捷键说明

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