Changeset 81856 in vbox
- Timestamp:
- Nov 14, 2019 11:46:05 PM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPWddm.cpp
r81813 r81856 2538 2538 } 2539 2539 2540 /** Find which area of a 32 bit mouse pointer bitmap is actually used. 2541 * Zero pixels on the right and the bottom of the bitmap are considered unused. 2542 * 2543 * @param pPixels The bitmap. 2544 * @param Pitch The bitmap scanline size in bytes. 2545 * @param Width The bitmap width. 2546 * @param Height The bitmap height. 2547 * @param piMaxFilledPixel Where to store the maximum index of non-zero pixel within a scanline. 2548 * @param piMaxFilledScanline Where to store the zero based index of the last scanline with non-zero pixels. 2549 */ 2550 static void vboxWddmPointerFindDimensionsColor(void const *pPixels, UINT Pitch, UINT Width, UINT Height, 2551 LONG *piMaxFilledPixel, LONG *piMaxFilledScanline) 2552 { 2553 /* Windows always uses the maximum pointer size VBOXWDDM_C_POINTER_MAX_* 2554 * Exclude zero pixels (which are transparent anyway) from the right and the bottom of the bitmap. 2555 */ 2556 DWORD const *pdwScanline = (DWORD *)pPixels; 2557 LONG iMaxFilledScanline = -1; 2558 LONG iMaxFilledPixel = -1; 2559 for (ULONG y = 0; y < Height; ++y) 2560 { 2561 LONG iLastFilledPixel = -1; 2562 for (ULONG x = 0; x < Width; ++x) 2563 { 2564 if (pdwScanline[x]) 2565 iLastFilledPixel = x; 2566 } 2567 2568 iMaxFilledPixel = RT_MAX(iMaxFilledPixel, iLastFilledPixel); 2569 2570 if (iLastFilledPixel >= 0) 2571 { 2572 /* Scanline contains non-zero pixels. */ 2573 iMaxFilledScanline = y; 2574 } 2575 2576 pdwScanline = (DWORD *)((uint8_t *)pdwScanline + Pitch); 2577 } 2578 2579 *piMaxFilledPixel = iMaxFilledPixel; 2580 *piMaxFilledScanline = iMaxFilledScanline; 2581 } 2582 2583 /** Find which area of a 1 bit AND/XOR mask bitmap is actually used, i.e. filled with actual data. 2584 * For the AND mask the bytes with a value 0xff on the right and the bottom of the bitmap are considered unused. 2585 * For the XOR mask the blank value is 0x00. 2586 * 2587 * @param pPixels The 1bit bitmap. 2588 * @param Pitch The 1bit bitmap scanline size in bytes. 2589 * @param Width The bitmap width. 2590 * @param Height The bitmap height. 2591 * @param Blank The value of the unused bytes in the supplied bitmap. 2592 * @param piMaxFilledPixel Where to store the maximum index of a filled pixel within a scanline. 2593 * @param piMaxFilledScanline Where to store the zero based index of the last scanline with filled pixels. 2594 */ 2595 static void vboxWddmPointerFindDimensionsMono(void const *pPixels, UINT Pitch, UINT Width, UINT Height, BYTE Blank, 2596 LONG *piMaxFilledPixel, LONG *piMaxFilledScanline) 2597 { 2598 /* Windows always uses the maximum pointer size VBOXWDDM_C_POINTER_MAX_* 2599 * Exclude the blank pixels (which are transparent anyway) from the right and the bottom of the bitmap. 2600 */ 2601 BYTE const *pbScanline = (BYTE *)pPixels; 2602 LONG iMaxFilledScanline = -1; 2603 LONG iMaxFilledByte = -1; 2604 for (ULONG y = 0; y < Height; ++y) 2605 { 2606 LONG iLastFilledByte = -1; 2607 for (ULONG x = 0; x < Width / 8; ++x) 2608 { 2609 if (pbScanline[x] != Blank) 2610 iLastFilledByte = x; 2611 } 2612 2613 iMaxFilledByte = RT_MAX(iMaxFilledByte, iLastFilledByte); 2614 2615 if (iLastFilledByte >= 0) 2616 { 2617 /* Scanline contains filled pixels. */ 2618 iMaxFilledScanline = y; 2619 } 2620 2621 pbScanline += Pitch; 2622 } 2623 2624 *piMaxFilledPixel = iMaxFilledByte * 8; 2625 *piMaxFilledScanline = iMaxFilledScanline; 2626 } 2627 2628 /** Adjust the width and the height of the mouse pointer bitmap. 2629 * See comments in the function for the adjustment criteria. 2630 * 2631 * @param iMaxX The index of the rightmost pixel which we want to keep. 2632 * @param iMaxY The index of the bottom-most pixel which we want to keep. 2633 * @param XHot The mouse pointer hot spot. 2634 * @param YHot The mouse pointer hot spot. 2635 * @param pWidth Where to store the bitmap width. 2636 * @param pHeight Where to store the bitmap height. 2637 */ 2638 static void vboxWddmPointerAdjustDimensions(LONG iMaxX, LONG iMaxY, UINT XHot, UINT YHot, 2639 ULONG *pWidth, ULONG *pHeight) 2640 { 2641 /* Both input parameters are zero based indexes, add 1 to get a width and a height. */ 2642 ULONG W = iMaxX + 1; 2643 ULONG H = iMaxY + 1; 2644 2645 /* Always include the hotspot point. */ 2646 W = RT_MAX(XHot, W); 2647 H = RT_MAX(YHot, H); 2648 2649 /* Align to 8 pixels, because the XOR/AND pointers are aligned like that. 2650 * The AND mask has one bit per pixel with 8 bits per byte. 2651 * In case the host can't deal with unaligned data. 2652 */ 2653 W = RT_ALIGN_T(W, 8, ULONG); 2654 H = RT_ALIGN_T(H, 8, ULONG); 2655 2656 /* Do not send bitmaps with zero dimensions. Actually make the min size 32x32. */ 2657 W = RT_MAX(32, W); 2658 H = RT_MAX(32, H); 2659 2660 /* Make it square. Some hosts are known to require square pointers. */ 2661 W = RT_MAX(W, H); 2662 H = W; 2663 2664 /* Do not exceed the supported size. 2665 * Actually this should not be necessary because Windows never creates such pointers. 2666 */ 2667 W = RT_MIN(W, VBOXWDDM_C_POINTER_MAX_WIDTH); 2668 H = RT_MIN(H, VBOXWDDM_C_POINTER_MAX_HEIGHT); 2669 2670 *pWidth = W; 2671 *pHeight = H; 2672 } 2673 2540 2674 BOOL vboxWddmPointerCopyColorData(CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape, PVIDEO_POINTER_ATTRIBUTES pPointerAttributes) 2541 2675 { … … 2548 2682 * Exclude zero pixels (which are transparent anyway) from the right and the bottom of the bitmap. 2549 2683 */ 2550 DWORD *pdwScanline = (DWORD *)pSetPointerShape->pPixels; 2551 LONG iLastNonZeroScanline = -1; 2552 LONG iMaxNonZeroPixel = -1; 2553 for (y = 0; y < pSetPointerShape->Height; ++y) 2554 { 2555 LONG iLastNonZeroPixel = -1; 2556 for (x = 0; x < pSetPointerShape->Width; ++x) 2557 { 2558 if (pdwScanline[x]) 2559 iLastNonZeroPixel = x; 2560 } 2561 2562 iMaxNonZeroPixel = RT_MAX(iMaxNonZeroPixel, iLastNonZeroPixel); 2563 2564 if (iLastNonZeroPixel >= 0) 2565 { 2566 /* Scanline contains non-zero pixels. */ 2567 iLastNonZeroScanline = y; 2568 } 2569 2570 pdwScanline = (DWORD *)((uint8_t *)pdwScanline + pSetPointerShape->Pitch); 2571 } 2572 2573 /* Both variabled are zero based indexes, add 1 for width and height. */ 2574 srcMaskW = iMaxNonZeroPixel + 1; 2575 srcMaskH = iLastNonZeroScanline + 1; 2576 2577 /* Align to 4 pixels. Bitmap is 16 bytes aligned (in case the host can't deal with unaligned data). */ 2578 srcMaskW = RT_ALIGN_T(srcMaskW, 4, ULONG); 2579 srcMaskH = RT_ALIGN_T(srcMaskH, 4, ULONG); 2580 2581 /* Do not send bitmaps with zero dimensions. Actually make the min size 32x32. */ 2582 srcMaskW = RT_MAX(32, srcMaskW); 2583 srcMaskH = RT_MAX(32, srcMaskH); 2584 2585 /* Make it square. */ 2586 srcMaskW = RT_MAX(srcMaskW, srcMaskH); 2587 srcMaskH = srcMaskW; 2588 2589 /* truncate masks if we exceed supported size */ 2590 pPointerAttributes->Width = min(srcMaskW, VBOXWDDM_C_POINTER_MAX_WIDTH); 2591 pPointerAttributes->Height = min(srcMaskH, VBOXWDDM_C_POINTER_MAX_HEIGHT); 2684 LONG iMaxFilledPixel; 2685 LONG iMaxFilledScanline; 2686 vboxWddmPointerFindDimensionsColor(pSetPointerShape->pPixels, pSetPointerShape->Pitch, 2687 pSetPointerShape->Width, pSetPointerShape->Height, 2688 &iMaxFilledPixel, &iMaxFilledScanline); 2689 2690 vboxWddmPointerAdjustDimensions(iMaxFilledPixel, iMaxFilledScanline, 2691 pSetPointerShape->XHot, pSetPointerShape->YHot, 2692 &srcMaskW, &srcMaskH); 2693 2694 pPointerAttributes->Width = srcMaskW; 2695 pPointerAttributes->Height = srcMaskH; 2592 2696 pPointerAttributes->WidthInBytes = pPointerAttributes->Width * 4; 2593 2697 … … 2642 2746 BYTE *pSrc, *pDst, bit; 2643 2747 2644 srcMaskW = pSetPointerShape->Width; 2645 srcMaskH = pSetPointerShape->Height; 2646 2647 /* truncate masks if we exceed supported size */ 2648 pPointerAttributes->Width = min(srcMaskW, VBOXWDDM_C_POINTER_MAX_WIDTH); 2649 pPointerAttributes->Height = min(srcMaskH, VBOXWDDM_C_POINTER_MAX_HEIGHT); 2748 /* Windows always uses the maximum pointer size VBOXWDDM_C_POINTER_MAX_* 2749 * Exclude unused pixels (which are transparent anyway) from the right and the bottom of the bitmap. 2750 */ 2751 LONG iMaxFilledPixelAND; 2752 LONG iMaxFilledScanlineAND; 2753 vboxWddmPointerFindDimensionsMono(pSetPointerShape->pPixels, pSetPointerShape->Pitch, 2754 pSetPointerShape->Width, pSetPointerShape->Height, 0xff, 2755 &iMaxFilledPixelAND, &iMaxFilledScanlineAND); 2756 2757 LONG iMaxFilledPixelXOR; 2758 LONG iMaxFilledScanlineXOR; 2759 vboxWddmPointerFindDimensionsMono((BYTE *)pSetPointerShape->pPixels + pSetPointerShape->Height * pSetPointerShape->Pitch, 2760 pSetPointerShape->Pitch, 2761 pSetPointerShape->Width, pSetPointerShape->Height, 0x00, 2762 &iMaxFilledPixelXOR, &iMaxFilledScanlineXOR); 2763 2764 LONG iMaxFilledPixel = RT_MAX(iMaxFilledPixelAND, iMaxFilledPixelXOR); 2765 LONG iMaxFilledScanline = RT_MAX(iMaxFilledScanlineAND, iMaxFilledScanlineXOR); 2766 2767 vboxWddmPointerAdjustDimensions(iMaxFilledPixel, iMaxFilledScanline, 2768 pSetPointerShape->XHot, pSetPointerShape->YHot, 2769 &srcMaskW, &srcMaskH); 2770 2771 pPointerAttributes->Width = srcMaskW; 2772 pPointerAttributes->Height = srcMaskH; 2650 2773 pPointerAttributes->WidthInBytes = pPointerAttributes->Width * 4; 2651 2774 … … 2661 2784 2662 2785 /* convert XOR mask to RGB0 DIB, it start in pPointerAttributes->Pixels should be 4bytes aligned */ 2663 pSrc = (BYTE*)pSetPointerShape->pPixels + srcMaskH*pSetPointerShape->Pitch;2786 pSrc = (BYTE*)pSetPointerShape->pPixels + pSetPointerShape->Height*pSetPointerShape->Pitch; 2664 2787 pDst = pPointerAttributes->Pixels + RT_ALIGN_T(dstBytesPerLine*pPointerAttributes->Height, 4, ULONG); 2665 2788 dstBytesPerLine = pPointerAttributes->Width * 4;
Note:
See TracChangeset
for help on using the changeset viewer.