blt_alpha.cpp

来自「6410BSP3」· C++ 代码 · 共 651 行 · 第 1/2 页

CPP
651
字号
#if ALPHABIT_WORKAROUND1                  
        // SW Solution, just fix the alphabit
        // Not good, need to implement as assembler.
        MultiplyAlphaBit((DWORD *)pBltParms->pSrc->Buffer(), 
                        ABS(pBltParms->pSrc->Stride()*pBltParms->pSrc->Height()), 
                        pBltParms->blendFunction.SourceConstantAlpha);
#endif         
#if ALPHABIT_WORKAROUND2
        // Workaround2
        // The only possible same scenario to MS SW alphablend is
        // 1. Fading Source Surface
        // 2. Create Destination Scratch Surface and Clone destination surface.
        // 3. Do Constant Alphablend with Fading Source Surface and Destination Scratch Surface.
        // 4. Do Per-Pixel Alphablend with Destination Scratch Surface and Destination Surface.
        // Through this scenario, but destination surface's alphabit has source surface's one.
        // Only RGB pixel has almost same result to MS SW alphablend.
        // This requires 4 memory copies
        
        // Do SCA between Source and Destination Scratch
        // We should make another Destination Scratch surface, this will have some blended pixel
        
        // 0. backup real destination Surface.
        memcpy(&descRealDstSurface, &descDstSurface, sizeof(SURFACE_DESCRIPTOR));

        CopyRect((LPRECT)&rectBackupCloneDst, (LPRECT)&rectDstBackup);

        // 1.Create Destination Scratch Surface for Source Constant AlphaBlending with Source Scratch Surface
        // This Cloned Destination surface should have 32bpp alphaformat
        // The trick is change the color format of pDst
        bHWSuccess = CreateScratchSurface(pBltParms->pDst, &pDstClone, (LPRECTL)&rectBackupCloneDst, &descDstSurface, gpe32Bpp, FALSE);
        
        descDstSurface.dwColorMode = GetHWColorFormat(pDstClone);
        pBltParms->prclDst = (LPRECTL)&rectBackupCloneDst;
        
        if ( DMDO_90 == pBltParms->pDst->Rotate() || DMDO_270 == pBltParms->pDst->Rotate() )
        {
            pDstClone->SetRotation( pDstClone->Height(), pDstClone->Width(), pBltParms->pDst->Rotate() );

            // Adjust the source rectangle for this case.
            RotateRectl(pBltParms->prclDst);
        }

        if(!bHWSuccess)
        {
            memcpy(&descDstSurface, &descRealDstSurface, sizeof(SURFACE_DESCRIPTOR));
            goto PostHWBitBlt;
        }

        // 2.Copy Destination Surface's contents
        // This will be processed by 2DHW with color converting
        // 2-1 Set Source as Real Destination Surface
        pBltParms->pSrc = pDstBackup;            
        pBltParms->prclSrc = (LPRECTL)&rectDstBackup;
        // 2-2 Set Destination as Cloned desitnation surface
        pBltParms->pDst = pDstClone;            
        m_oG2D->SetAlphaMode(G2D_NO_ALPHA_MODE); //< Source Constant AlphaBlend
        // Alpha = Alpha*(Alpha/256)
        m_oG2D->SetAlphaValue((pBltParms->blendFunction.SourceConstantAlpha*pBltParms->blendFunction.SourceConstantAlpha)>>8);

        bHWSuccess = HWBitBlt(pBltParms, &descRealDstSurface, &descDstSurface);
        
        if(!bHWSuccess)
        {
            goto PostHWBitBlt;
        }

        m_oG2D->SetAlphaMode(G2D_ALPHA_MODE); //< Source Constant AlphaBlend

        // Set Source as Source Scratch Surface
        pBltParms->pSrc = SrcScratchSurf;
        pBltParms->prclSrc = (LPRECTL)&rectSrcBackup;
        
        // 3.Do SCA from faded source surface to cloned destination surface.
        bHWSuccess = HWBitBlt(pBltParms, &descSrcSurface, &descDstSurface);

        // 4. assign cloned destination surface as source surface.
        pBltParms->pSrc = pDstClone;
        pBltParms->prclSrc = pBltParms->prclDst;
        memcpy(&descSrcSurface, &descDstSurface, sizeof(SURFACE_DESCRIPTOR));            
        // 5. restore original destination surface.
        pBltParms->pDst = pDstBackup;
        pBltParms->prclDst = (LPRECTL)&rectDstBackup;
        memcpy(&descDstSurface, &descRealDstSurface, sizeof(SURFACE_DESCRIPTOR));

        // 6. do PPA with cloned destination surface that is assigned to source scratch surface.
        ///////////
#endif            
        if(bHWSuccess)
        {
            // Keep Going
            bHWSuccess = FALSE;
        }
        else
        {
            goto PostHWBitBlt;
        }

        // Do PPA
        m_oG2D->SetAlphaMode(G2D_PP_ALPHA_SOURCE_MODE); //< Per-Pixel AlphaBlend
        m_oG2D->SetAlphaValue(pBltParms->blendFunction.SourceConstantAlpha/*0xff*/);                    //< Per-Pixel Opaque, dummy value
    }
    else if(pBltParms->blendFunction.SourceConstantAlpha != 0xFF)
    {
        if(descDstSurface.dwBaseaddr == descSrcSurface.dwBaseaddr)
        {
            RETAILMSG(DISP_ZONE_2D,(TEXT("FadingMode\r\n")));            
            m_oG2D->SetAlphaMode(G2D_FADING_MODE); //< Self Fading AlphaBlend
        }
        else{
            RETAILMSG(DISP_ZONE_2D,(TEXT("Constant\r\n")));        
            m_oG2D->SetAlphaMode(G2D_ALPHA_MODE);   //< Constant Alpha
        }
        m_oG2D->SetAlphaValue(pBltParms->blendFunction.SourceConstantAlpha);            
    }
    else if(pBltParms->blendFunction.AlphaFormat != 0)
    {
        RETAILMSG(DISP_ZONE_2D,(TEXT("PerPixelMode\r\n")));            
        m_oG2D->SetAlphaMode(G2D_PP_ALPHA_SOURCE_MODE); //< Per-Pixel AlphaBlend
        m_oG2D->SetAlphaValue(pBltParms->blendFunction.SourceConstantAlpha/*0xff*/);                    //< Per-Pixel Opaque, dummy value
    }
    else    // No AlphaBlend
    {
        /// Transparency does not relate with alpha blending
        m_oG2D->SetAlphaMode(G2D_NO_ALPHA_MODE);    
        /// No transparecy with alphablend
        m_oG2D->SetAlphaValue(0xff);
    }

    RETAILMSG(FALSE,(TEXT("PixelDst:0x%x\n"), *((DWORD*)pBltParms->pDst->Buffer())));            
    /// Real Register Surface Description setting will be done in HWBitBlt
    bHWSuccess = HWBitBlt(pBltParms, &descSrcSurface, &descDstSurface);

    RETAILMSG(FALSE,(TEXT("PixelDstAfter:0x%x\n"), *((DWORD*)pBltParms->pDst->Buffer())));            

PostHWBitBlt:    
    if(!bHWSuccess)
    {
        RETAILMSG(DISP_ZONE_WARNING,(TEXT("HWBitBlt Failed\r\n")));    
    }
    else    // TODO: Post mortem, Alphabit multiplying    
    {

    }

    if(pDstClone != NULL)
    {
        delete pDstClone;
    }    
    if(OldSrcSurf != NULL)
    {
        RETAILMSG(DISP_ZONE_2D,(TEXT("Release Source Scratch Surface\r\n")));
        pBltParms->pSrc = OldSrcSurf;
        if(SrcScratchSurf)
        {
            RETAILMSG(DISP_ZONE_2D,(TEXT("Delete Source Scratch Surface\r\n")));                
            delete SrcScratchSurf;        
        }
    }
    RETAILMSG(DISP_ZONE_2D,(TEXT("Source Scratch Surface is destroyed\r\n")));    
    if(OldDstSurf != NULL)
    {
        if(m_dwPhyAddrOfSurface[1] == NULL) // copy
        {
            DWORD dwTopOffset;
            dwTopOffset = rectlDstBackup.top * pBltParms->pDst->Stride();
            RETAILMSG(DISP_ZONE_2D,(TEXT("Release Destination Scratch Surface\r\n")));    
            pBltParms->pDst = OldDstSurf;    
            // Copy ScratchBuffer to Original Image Buffer
            RETAILMSG(DISP_ZONE_2D,(TEXT("DstScratch:0x%x, OriDstBuffer:0x%x, Offset:(%d), Dst:0x%x  Size:%d\r\n"), 
            DstScratchSurf->Buffer(), pBltParms->pDst->Buffer(),
                dwTopOffset,
//                (BYTE *)((DWORD)pBltParms->pDst->Buffer() + ABS(pBltParms->pDst->Stride()) + RECT_HEIGHT(pBltParms->prclDst) * pBltParms->pDst->Stride()),
                (BYTE *)((DWORD)pBltParms->pDst->Buffer() + dwTopOffset),
                ABS(DstScratchSurf->Height() * DstScratchSurf->Stride())));
                
            memcpy((BYTE *)((DWORD)pBltParms->pDst->Buffer() + dwTopOffset),
                (BYTE *)DstScratchSurf->Buffer(), 
                ABS(DstScratchSurf->Stride()* RECT_HEIGHT(pBltParms->prclDst))
                );
        }
        else
        {
            RETAILMSG(DISP_ZONE_2D,(TEXT("Release Destination Scratch Surface\r\n")));    
            pBltParms->pDst = OldDstSurf;    
            // Copy ScratchBuffer to Original Image Buffer
            RETAILMSG(DISP_ZONE_2D,(TEXT("DstScratch:0x%x, OriDstBuffer:0x%x, Offset:(%d), Dst:0x%x  Size:%d\r\n"), 
            DstScratchSurf->Buffer(), pBltParms->pDst->Buffer(),
                RECT_HEIGHT(pBltParms->prclDst) * pBltParms->pDst->Stride(),
                (BYTE *)((DWORD)pBltParms->pDst->Buffer() + ABS(pBltParms->pDst->Stride()) + RECT_HEIGHT(pBltParms->prclDst) * pBltParms->pDst->Stride()),
                ABS(DstScratchSurf->Height() * DstScratchSurf->Stride())));

            for(DWORD i = 0; i < (DWORD)DstScratchSurf->Height(); i++)
            {
                memcpy((BYTE *)((DWORD)pBltParms->pDst->Buffer() + pBltParms->pDst->Stride() * (i + pBltParms->prclDst->top)),
                    (BYTE *)DstScratchSurf->Buffer()+ i * ABS(DstScratchSurf->Stride()), 
                    ABS(DstScratchSurf->Stride())
                    );
            }
        }        
        if(DstScratchSurf)
        {
            delete DstScratchSurf;
        }

    }

    RETAILMSG(DISP_ZONE_2D,(TEXT("Recover Rect\r\n")));    
    CopyRect((LPRECT)pBltParms->prclSrc, &rectlSrcBackup);
    CopyRect((LPRECT)pBltParms->prclDst, &rectlDstBackup);

    RETAILMSG(DISP_ZONE_2D,(TEXT("Rerotate Rect\r\n")));    
    if(pBltParms->pDst->IsRotate())
    {
        RotateRectlBack(prclDst);
        if(pBltParms->prclClip)
        {
        RotateRectlBack(pBltParms->prclClip);
        }
    }
    if(pBltParms->pSrc->IsRotate())
    {
        RotateRectlBack(prclSrc);
    }
    if (pBltParms->bltFlags & BLT_TRANSPARENT)
    {
        m_oG2D->SetTransparentMode(0, pBltParms->solidColor);// turn off Transparency
    }
    RETAILMSG(DISP_ZONE_2D,(TEXT("Check HW Success:%d\r\n"),bHWSuccess));        
    if(!bHWSuccess)
    {
        return EmulatedBlt(pBltParms);
    }

    return  S_OK;
}

void S3C6410Disp::MultiplyAlphaBit(DWORD *pdwStartAddress, DWORD dwBufferLength, DWORD AlphaConstant)
{            
    // Premultiplying Alphabit for Target Area that already processed by fading.
    // We assume the target surface's color depth is 32bpp.
    DWORD orgPixel;
    DWORD rgb;
    DWORD alpha;
    DWORD *pdwEndAddress;
    pdwEndAddress = pdwStartAddress + dwBufferLength;
    while(pdwEndAddress != pdwStartAddress)
    {
        orgPixel = *(pdwStartAddress);
        rgb = (orgPixel & 0x00FFFFFF);
        alpha = (((orgPixel>>24)*AlphaConstant)>>8)<<24;
        *(pdwStartAddress) = rgb | alpha;
        pdwStartAddress++;
    };
}


// This function will change the surface descriptor directly,
// So, caller should backup the surface descriptor or clone.
BOOL S3C6410Disp::CreateScratchSurface(GPESurf* OriginalSurface, DDGPESurf** ScratchSurface, PRECTL NewSurfaceSize, SURFACE_DESCRIPTOR *NewSurfaceDescriptor, EGPEFormat NewColorFormat, BOOL bCopy)
{
    DWORD dwTopOffset = 0;
    DWORD OriginalBuffer = (DWORD)OriginalSurface->Buffer();
    int OriginalStride = OriginalSurface->Stride();
    
    DWORD ScratchBuffer = 0;
    int ScratchStride = 0;
    int ScratchHeight = 0;

    AllocSurface((DDGPESurf**)ScratchSurface, ABS(SURFACE_WIDTH(OriginalSurface)),
                                RECT_HEIGHT(NewSurfaceSize),
                                NewColorFormat,
                                EGPEFormatToEDDGPEPixelFormat[NewColorFormat], 
                                GPE_REQUIRE_VIDEO_MEMORY);
    if(*ScratchSurface == NULL)
    {
        RETAILMSG(DISP_ZONE_WARNING,(TEXT("Scratch Surface Allocation is failed for AlphaBlend %d\n"), __LINE__));
        RETAILMSG(DISP_ZONE_WARNING,(TEXT("Maybe There's no sufficient video memory. please increase video memory\r\n")));
        RETAILMSG(DISP_ZONE_WARNING,(TEXT("try to redirect to SW Emulated Bitblt\r\n")));
        return FALSE;
    }

    ScratchBuffer = (DWORD)((*ScratchSurface)->Buffer());
    ScratchStride = (*ScratchSurface)->Stride();
    ScratchHeight = (*ScratchSurface)->Height();

    if(bCopy)
    {
        // Copy Original Image to ScratchBuffer

        dwTopOffset = NewSurfaceSize->top * OriginalStride;  //< This will be used for Stride > 0
        RETAILMSG(DISP_ZONE_2D,(TEXT("ScratchBuffer:0x%x, OriBuffer:0x%x, TopOffset:(%d), Offset:(%d), Src:0x%x  Size:%d\r\n"), 
            (*ScratchSurface)->Buffer(), OriginalBuffer,
            dwTopOffset,    //< This will be used for Stride > 0
            RECT_HEIGHT(NewSurfaceSize) * OriginalStride,
            (BYTE *)(OriginalBuffer + ABS(OriginalStride) + RECT_HEIGHT(NewSurfaceSize) * OriginalStride),
            ABS(ScratchHeight * ScratchStride)));

        if(OriginalStride > 0)
        {
            memcpy((BYTE *)ScratchBuffer, 
                (BYTE *)(OriginalBuffer + dwTopOffset),
                ABS(ScratchStride* RECT_HEIGHT(NewSurfaceSize))
                );
        }
        else
        {
            for(DWORD i = 0; i < (DWORD)ScratchHeight; i++)
            {
                memcpy((BYTE *)ScratchBuffer+ i * ABS(ScratchStride), 
                    (BYTE *)(OriginalBuffer + OriginalStride * (i + NewSurfaceSize->top)),
                    ABS(ScratchStride)
                    );
            }
        }
    }
    
    // Assign Scratch Surface as Source Surface
    NewSurfaceDescriptor->dwBaseaddr = (m_VideoMemoryPhysicalBase + (*ScratchSurface)->OffsetInVideoMemory());
    NewSurfaceDescriptor->dwVertRes = RECT_HEIGHT(NewSurfaceSize);
    NewSurfaceSize->top = 0;
    NewSurfaceSize->bottom = NewSurfaceDescriptor->dwVertRes;

    return TRUE;
}

⌨️ 快捷键说明

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