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

📄 blt.c

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 C
📖 第 1 页 / 共 3 页
字号:

  // Setup clipping (scissoring, technically)

  if (Parameters->ClipRectCount == 1) {

    ResetClipping = TRUE;

    // Setup scissor coordinates.

    WriteRegUlong(r_ScissorMinXY,
                  PackXY(Parameters->ClipRect->left,
                         Parameters->ClipRect->top));

    WriteRegUlong(r_ScissorMaxXY,
                  PackXY(Parameters->ClipRect->right,
                         Parameters->ClipRect->bottom));

    // Enable scissoring.

    Config2D |= b_Config2D_UserScissorEnable;
  }

  // Setup the blit destination, possibly with readback and overlap.

  // !TODO! System memory destiantions?

  Assert(Parameters->Destination->Type == VideoMemory);

  Config2D |= b_Config2D_FBWriteEnable;

  Render2D |= PackXY(DestRectWidth, DestRectHeight);

  WriteRegUlong(r_RectanglePosition,
                PackXY(Parameters->DestRect->left, Parameters->DestRect->top));

  WriteRegUlong(r_FBWriteBufferAddr0, 
                VirtualToOffset(Parameters->Destination->Ptr));
                            
  WriteRegUlong(r_FBWriteBufferWidth0, 
                Parameters->Destination->Size.cx);

  // Handle destination readback. This is different than overlap, which is
  // when the source and destination surfaces are the same and the rectangles
  // overlap. Here, we need to read the destination pixel as it is a component
  // in the formula which will determine the value we write back. This is
  // known as read-modify-write.

  if (NeedDestRead[Foreground] || NeedDestRead[Background]) {

    Config2D |= b_Config2D_FBDestReadEnable;

    WriteRegUlong(r_FBDestReadBufferAddr0,
                  VirtualToOffset(Parameters->Destination->Ptr));

    WriteRegUlong(r_FBDestReadBufferWidth0,
                  Parameters->Destination->Size.cx);

    WriteRegUlong(r_FBDestReadMode,
                  b_FBDestReadMode_ReadEnable |
                  b_FBDestReadMode_Enable0);
  }

  // Setup the blit source.

  if (NeedSource[Foreground] || NeedSource[Background]) {

    Render2D |= b_Render2D_FBReadSourceEnable;

    Assert(Parameters->Source != NULL);
    
    // !TODO! System memory sources?

    Assert(Parameters->Source->Type == VideoMemory);

    WriteRegUlong(r_FBSourceReadMode,
                  b_FBSourceReadMode_ReadEnable);

    WriteRegUlong(r_FBSourceReadBufferAddr,
                  VirtualToOffset(Parameters->Source->Ptr));

    WriteRegUlong(r_FBSourceReadBufferWidth,
                  Parameters->Source->Size.cx);

    // This is the packed offset the memory needs to be moved if you view
    // the entriety of video memory as a single surface.

    SourceOffset = PackXY((Parameters->SourceRect->left - Parameters->DestRect->left),
                          (Parameters->SourceRect->top - Parameters->DestRect->top));

    WriteRegUlong(r_FBSourceReadBufferOffset, SourceOffset);

    // !TODO! bottom-up bitmaps.

    if (Parameters->ScanXPositive) {
      Render2D |= b_Render2D_IncreasingXWhenSet;
    }

    if (Parameters->ScanYPositive) {
      Render2D |= b_Render2D_IncreasingYWhenSet;
    }

    // We need to do a blocking blit if the horizontal overlap is less than
    // a single span apart.
 
    if (Abs(Parameters->SourceRect->left - Parameters->DestRect->right) < 64) {

      Config2D |= b_Config2D_Blocking;
    }
  }
  else {

    Assert(Parameters->Source == NULL);

    // With no source, there can be no overlap.
    // !TODO! bottom-up bitmaps?

    Render2D |= (b_Render2D_IncreasingXWhenSet |
                 b_Render2D_IncreasingYWhenSet);  
  }

  // Setup the blit pattern.

  if (NeedPattern[Foreground] || NeedPattern[Background]) {

    if (Parameters->PatternType == SolidPattern) {

      // It's a solid brush, just set the color in. While the Permedia allows
      // us the potential of a different solid color for foreground and
      // background, GDI does not.

      WriteRegUlong(r_ForegroundColor,
                    Parameters->FillValue);

      WriteRegUlong(r_BackgroundColor,
                    Parameters->FillValue);

      Config2D |= b_Config2D_UseConstantSource;
    }
    else if (Parameters->PatternType == BitmapPattern) {

      // Load the bitmap brush into the hardware LUT.

      HwBrush(Parameters);

      Config2D |= b_Config2D_LUTModeEnable;
    }
  }

  // Setup hardware color keying.

  // We punt blits that have both source and destination color keys
  // above.

  if (Parameters->ColorKeyType != NoColorKey) {

    // Color keying shared some bits with the alpha blending unit. We do not
    // enable alpha blending, only set the relevant bits.

    WriteRegUlong(r_AlphaBlendAlphaMode,
                  (1 << 14)); // AlphaConversion = Shift

    // Set color format and order and conversion to shift. This is slightly
    // hacky, but we know that the primary will always use the
    // l_PixelTable, which is actually PERM3_FORMATs.

    switch (((const PERM3_FORMAT *)GetPrimarySurface()->Format)->RDColorFormat) {
    case 64:  ColorFormat = 0; break;
    case 65:  ColorFormat = 2; break;
    case 66:  ColorFormat = 1; break;
    case 80:  ColorFormat = 3; break;
    case 96:  ColorFormat = 16; break;
    case 97:  ColorFormat = 18; break;
    case 98:  ColorFormat = 17; break;
    case 112: ColorFormat = 19; break;
    default:
      Error(L"Unknown RDColorFormat!\n");
      ColorFormat = 0;
      break;
    }

    WriteRegUlong(r_AlphaBlendColorMode,
                  (ColorFormat << 12) |
                  (1 << 17));

    if (Parameters->ColorKeyType == SourceColorKey) {

      ResetChromaKey = TRUE;

      WriteRegUlong(r_ChromaUpper,
                    Parameters->SourceColorKey->HighValue);
      WriteRegUlong(r_ChromaLower,
                    Parameters->SourceColorKey->LowValue);

      // Setup colors come from FBSourceData, if the color matches it is
      // rejected. If it fails the test, it is passed.

      WriteRegUlong(r_ChromaTestMode,
                    b_ChromaTestMode_Enable |
                    (1 << 3)); // Reject passed colors
    }
    else if (Parameters->ColorKeyType == DestColorKey) {

      ResetChromaKey = TRUE;

      WriteRegUlong(r_ChromaUpper,
                    Parameters->DestColorKey->HighValue);
      WriteRegUlong(r_ChromaLower,
                    Parameters->DestColorKey->LowValue);

      // Setup colors come from FBData, if the color matches it is
      // passed. If it fails the test, it is rejected.

      WriteRegUlong(r_ChromaTestMode,
                    b_ChromaTestMode_Enable |
                    (1 << 1) |  // Source = FBData
                    (1 << 5));  // Reject failed colors
    }
  }

  WriteRegUlong(r_Config2D, Config2D);
  WriteRegUlong(r_Render2D, Render2D);

  if (NeedMask) {

    // Load the bit mask into the hardware.

    UploadBitMask((const PERM3_SURFACE *)Parameters->Mask,
                  Parameters->MaskRect);
  }

  if (ResetClipping) {

    // Turn off scissoring.

    WriteRegUlong(r_ScissorModeAnd,
                  !b_ScissorModeAnd_UserScissorEnable);
  }

  if (ResetChromaKey) {

    // Turn off chromakeying.

    WriteRegUlong(r_ChromaTestModeAnd,
                  !b_ChromaTestModeAnd_Enable);
  }

  FnRetVal = TRUE;

  Exit(L"HardwareBlt");

  return FnRetVal;
}

USHORT
LookupLogicop(
  BYTE Rop3
  )
{
  // LookupLogicop
  // This function returns the appropriate Permedia3 logicop for a given
  // raster operation. It returns an error code if no logicop can be used
  // for the given ROP.

  USHORT Logicop;

  Enter(L"LookupLogicop");

  switch (Rop3) {

  case 0x00 : // 0

    Logicop = 0x0; // Clear
    break;

  case 0x88 : // DSa
  case 0xA0 : // DPa

    Logicop = 0x1; // And
    break;

  case 0x44 : // SDna
  case 0x50 : // PDna

    Logicop = 0x2; // AndReverse
    break;

  case 0xCC : // S
  case 0xF0 : // P
    
    Logicop = 0x3; // Copy
    break;

  case 0x0A : // DPna
  case 0x22 : // DSna

    Logicop = 0x4; // AndInvert
    break;

  case 0xAA : // D

    Logicop = 0x5; // Noop
    break;

  case 0x5A : // DPx
  case 0x66 : // DSx

    Logicop = 0x6; // Xor
    break;

  case 0xEE : // DSo
  case 0xFA : // DPo

    Logicop = 0x7; // Or
    break;

  case 0x05 : // DPon
  case 0x11 : // DSon

    Logicop = 0x8; // Nor
    break;

  case 0x99 : // DSxn
  case 0xA5 : // DPxn

    Logicop = 0x9; // Equiv
    break;

  case 0x55 : // Dn

    Logicop = 0xA; // Invert
    break;

  case 0xDD : // SDno
  case 0xF5 : // PDno

    Logicop = 0xB; // OrReverse
    break;

  case 0x0F : // Pn
  case 0x33 : // Sn

    Logicop = 0xC; // CopyInvert
    break;

  case 0xAF : // DPno
  case 0xBB : // DSno

    Logicop = 0xD; // OrInvert
    break;

  case 0x5F : // DPan
  case 0x77 : // DSan

    Logicop = 0xE; // Nand
    break;

  case 0xFF : // 1

    Logicop = 0xF; // Set
    break;

  default :

    Logicop = NO_APPROPRIATE_OP;
    break;
  }   

  Exit(L"LookupLogicop");

  return Logicop;
}

void
UploadBitMask(
  const PERM3_SURFACE * Mask,
  const RECT          * Rect
  )
{
  // UploadBitMask
  // This function sends a bit mask, as given by the pointer, stride and rect
  // parameters to the hardware.

  // A note on the organization of 1bpp surfaces:
  // 1 bpp surfaces are organized as an array of lines, where each line's
  // size (in bytes, always,) is given by the stride. Within the line, the
  // top-left pixel is in bit 7 of the first byte and filled down so that
  // pixel (7,0) is in bit 0 of the first byte. Pixel (8,0) is then bit 7
  // of the 2nd byte.

  // Local variables.

  BYTE * Scanline;
  BYTE * InScanline;
  ULONG  ScanlineCount;
  ULONG  CurrentBytesInScanline;
  ULONG  i;
  union u_UlongWithByteAccess {
    ULONG  Ulong;
    struct {
      BYTE   Byte1;  // Bits 0-7
      BYTE   Byte2;  // Bits 8-15
      BYTE   Byte3;  // Bits 16-23
      BYTE   Byte4;  // Bits 24-31
    };
  } TransferValue;

  // Check parameters.

  // !TODO!

  Enter(L"UploadBitMask");

  // We need to determine the byte that contains the first bits in the line.

  Scanline = ((BYTE *)Mask->Ptr + (Rect->top * Mask->Stride) + (Rect->left / 8)); // !TODO! >> 3
  ScanlineCount = RectHeight(Rect);

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

    CurrentBytesInScanline = Mask->Stride;
    InScanline = Scanline;

    do {

      TransferValue.Ulong = 0;

      if (CurrentBytesInScanline >= 4) {

        // We have at least a whole ulong left, so just transfer it.

        WriteRegUlong(r_BitMaskPattern, *((ULONG UNALIGNED *)InScanline));
        InScanline += 4;
        CurrentBytesInScanline -= 4;
      }
      else if (CurrentBytesInScanline == 3) {

        TransferValue.Byte1 = *InScanline++;
        TransferValue.Byte2 = *InScanline++;
        TransferValue.Byte3 = *InScanline++;
        WriteRegUlong(r_BitMaskPattern, TransferValue.Ulong);
        CurrentBytesInScanline -= 3;
      }
      else if (CurrentBytesInScanline == 2) {

        TransferValue.Byte1 = *InScanline++;
        TransferValue.Byte2 = *InScanline++;
        WriteRegUlong(r_BitMaskPattern, TransferValue.Ulong);
        CurrentBytesInScanline -= 2;
      }
      else if (CurrentBytesInScanline == 1) {

        TransferValue.Byte1 = *InScanline++;
        WriteRegUlong(r_BitMaskPattern, TransferValue.Ulong);
        CurrentBytesInScanline -= 1;
      }
    } while (CurrentBytesInScanline > 0);

    Scanline += Mask->Stride;
  }

  Exit(L"UploadBitMask");
}

⌨️ 快捷键说明

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