/*************************************************************************** * (c)2003-2009 Broadcom Corporation * * This program is the proprietary software of Broadcom Corporation and/or its * licensors, and may only be used, duplicated, modified or distributed pursuant * to the terms and conditions of a separate, written license agreement executed * between you and Broadcom (an "Authorized License"). Except as set forth in an * Authorized License, Broadcom grants no license (express or implied), right to * use, or waiver of any kind with respect to the Software, and Broadcom expressly * reserves all rights in and to the Software and all intellectual property rights * therein. IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU HAVE NO RIGHT TO USE THIS * SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY NOTIFY BROADCOM AND DISCONTINUE * ALL USE OF THE SOFTWARE. * * Except as expressly set forth in the Authorized License, * * 1. This program, including its structure, sequence and organization, * constitutes the valuable trade secrets of Broadcom, and you shall use all * reasonable efforts to protect the confidentiality thereof, and to use this * information only in connection with your use of Broadcom integrated circuit * products. * * 2. TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" * AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, REPRESENTATIONS OR * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO * THE SOFTWARE. BROADCOM SPECIFICALLY DISCLAIMS ANY AND ALL IMPLIED WARRANTIES * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, * LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION * OR CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT OF * USE OR PERFORMANCE OF THE SOFTWARE. * * 3. TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR ITS * LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR * EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO YOUR * USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT * ACTUALLY PAID FOR THE SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE * LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF * ANY LIMITED REMEDY. * * $brcm_Workfile: $ * $brcm_Revision: $ * $brcm_Date: $ * * Description: Soft Graphics Applib Implementation * * Revision History: * * $brcm_Log: $ * ***************************************************************************/ #include "b_softgfx_lib.h" #include "b_softgfx_priv.h" /* Define below macro to 1 for profiling softgfx API's */ #define PROFILE_SOFTGFX 0 #define GRAPHICS_DESTRIPE #if PROFILE_SOFTGFX #include #endif /* PROFILE_SOFTGFX */ BDBG_MODULE(b_softgfx); #define NA 0 static uint32_t B_SoftGfx_ColorOpMapping[B_SoftGfx_BlitColorOp_eMax] = { NA, /* B_SoftGfx_BlitColorOp_eCopySource */ SURFBLIT_BLEND_WITH_SPEC_ALPHA1,/* B_SoftGfx_BlitColorOp_eUseConstantAlpha */ SURFBLIT_BLEND_WITH_SRC1_ALPHA, /* B_SoftGfx_BlitColorOp_eUseSourceAlpha */ SURFBLIT_BLEND_WITH_SRC2_ALPHA, /* B_SoftGfx_BlitColorOp_eUseDestAlpha */ SURFBLIT_BLEND_WITH_AVG_ALPHA, /* B_SoftGfx_BlitColorOp_eUseBlendEquation */ }; static uint32_t B_SoftGfx_AlphaOpMapping[B_SoftGfx_BlitAlphaOp_eMax] = { SURFBLIT_SET_DEST_ALPHA_WITH_SRC1_ALPHA, /* B_SoftGfx_BlitAlphaOp_eCopySource */ SURFBLIT_SET_DEST_ALPHA_WITH_SRC2_ALPHA, /* B_SoftGfx_BlitAlphaOp_eCopyDest */ SURFBLIT_SET_DEST_ALPHA_WITH_SPEC_ALPHA2,/* B_SoftGfx_BlitAlphaOp_eCopyConstant */ SURFBLIT_SET_DEST_ALPHA_WITH_AVG_ALPHA /* B_SoftGfx_BlitAlphaOp_eUseBlendEquation */ }; static B_SoftGfx_BlitSettings sDefaultBlitSettings = { NULL, /* srcsurface */ NULL, /* dstsurface */ NULL, /* outsurface */ {0, 0, 0, 0}, /* srcrect */ 0, 0, /* dstx, dsty */ 0, 0, /* outx, outy */ B_SoftGfx_BlitColorOp_eCopySource, /* colorOp */ B_SoftGfx_BlitAlphaOp_eCopySource, /* alphaOp */ 0, /* constAlphaColorOp */ 0, /* constAlphaAlphaOp */ false, /* bApplyAntiFlutterFilter */ false, /* conversionMatrixEnabled */ { /* conversionMatrix */ 0, /* shift */ {1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0}/* coeffMatrix */ } }; static B_SoftGfx_ScaleSettings sDefaultScaleSettings = { NULL, /* srcsurface */ NULL, /* outsurface */ {0, 0, 0, 0}, /* srcrect */ {0, 0, 0, 0}, /* outrect */ false }; static bool B_SoftGfx_IsSupportedFillPixelFormat(NEXUS_PixelFormat format) { switch (format) { case NEXUS_PixelFormat_ePalette8: case NEXUS_PixelFormat_eA8_R8_G8_B8: #if B_SOFTGFX_RGBA8888_SUPPORT case NEXUS_PixelFormat_eR8_G8_B8_A8: #endif /* B_SOFTGFX_RGBA8888_SUPPORT */ case NEXUS_PixelFormat_eR5_G6_B5: case NEXUS_PixelFormat_eA1_R5_G5_B5: case NEXUS_PixelFormat_eR5_G5_B5_A1: case NEXUS_PixelFormat_eA4_R4_G4_B4: case NEXUS_PixelFormat_eR4_G4_B4_A4: case NEXUS_PixelFormat_eA8_Y8_Cb8_Cr8: return true; default: BDBG_ERR(("Unsupported pixel format %d",format)); return false; }/* switch */ } static bool B_SoftGfx_IsSupportedBlitPixelFormat(NEXUS_PixelFormat format) { switch (format) { case NEXUS_PixelFormat_eA8_R8_G8_B8: #if B_SOFTGFX_RGBA8888_SUPPORT case NEXUS_PixelFormat_eR8_G8_B8_A8: #endif /* B_SOFTGFX_RGBA8888_SUPPORT */ case NEXUS_PixelFormat_eR5_G6_B5: case NEXUS_PixelFormat_eA1_R5_G5_B5: case NEXUS_PixelFormat_eR5_G5_B5_A1: case NEXUS_PixelFormat_eA4_R4_G4_B4: case NEXUS_PixelFormat_eR4_G4_B4_A4: case NEXUS_PixelFormat_eA8_Y8_Cb8_Cr8: return true; default: BDBG_ERR(("Unsupported pixel format %d",format)); return false; }/* switch */ } static int bsoftgfx_create_surface( bgfx_surf_p soft_sur, /* Output param */ NEXUS_SurfaceHandle surface ) { bgfx_palette_t palette, *p_plt=NULL; NEXUS_SurfaceCreateSettings sCreateSettings; NEXUS_SurfaceMemory sMemory; BDBG_ASSERT(soft_sur); BDBG_ASSERT(surface); NEXUS_Surface_GetCreateSettings(surface, &sCreateSettings); NEXUS_Surface_GetMemory(surface, &sMemory); BDBG_MSG(("bsoftgfx_create_surface: Nexus Surface->createSettings -> pixel_format=%d palettepixelformat=%d, bpp=%d pitch=%d", sCreateSettings.pixelFormat, sCreateSettings.palettePixelFormat, sCreateSettings.bitsPerPixel, sMemory.pitch)); if((sMemory.palette != NULL) && (sMemory.numPaletteEntries != 0)) { BKNI_Memset(palette.clut, 0, sizeof(uint32_t)*PALETTE_SIZE); BKNI_Memcpy(palette.clut, sMemory.palette, sizeof(uint32_t)*sMemory.numPaletteEntries); p_plt = &palette; } else { p_plt = NULL; } soft_sur->format = sCreateSettings.pixelFormat; return bgfx_create(soft_sur, sCreateSettings.width, sCreateSettings.height, 0, 0, (uint8_t *)sMemory.buffer, sMemory.pitch, p_plt, BGFX_SURF_RGB); /* assuming only RGB surface is sufficient */ } static void bsoftgfx_destroy_surface(bgfx_surf_p soft_sur) { bgfx_destroy(soft_sur); return; } /*************************************************************************** Summary: Get default settings for B_SoftGfx_Open ***************************************************************************/ void B_SoftGfx_GetDefaultOpenSettings( B_SoftGfx_OpenSettings *pSettings /* [out] */ ) { BKNI_Memset(pSettings, 0, sizeof(*pSettings)); return; } /*************************************************************************** Summary: Open a Soft Graphics interface for blit and fill operations. ***************************************************************************/ B_SoftGfxHandle B_SoftGfx_Open( const B_SoftGfx_OpenSettings *pSettings ) { B_SoftGfx_OpenSettings defaultOpenSettings; B_SoftGfxHandle gfx; gfx = BKNI_Malloc(sizeof(*gfx)); if(!gfx) { BERR_TRACE(NEXUS_OUT_OF_SYSTEM_MEMORY); goto err_alloc; } BKNI_Memset(gfx, 0, sizeof(*gfx)); BDBG_OBJECT_SET(gfx, B_SoftGfx); if(!pSettings){ B_SoftGfx_GetDefaultOpenSettings(&defaultOpenSettings); pSettings = &defaultOpenSettings; } gfx->sOpenSettings = *pSettings; return gfx; err_alloc: return NULL; } /*************************************************************************** Summary: Close a Soft Graphics interface. ***************************************************************************/ void B_SoftGfx_Close( B_SoftGfxHandle handle ) { BDBG_OBJECT_ASSERT(handle, B_SoftGfx); BKNI_Free(handle); return; } /*************************************************************************** Summary: Get default settings for the structure. ***************************************************************************/ void B_SoftGfx_GetDefaultFillSettings( B_SoftGfx_FillSettings *pSettings /* [out] */ ) { BKNI_Memset(pSettings, 0, sizeof(*pSettings)); pSettings->colorOp = B_SoftGfx_FillOp_eCopy; pSettings->alphaOp = B_SoftGfx_FillOp_eCopy; } /*************************************************************************** Summary: Fill, tint or otherwise modify the pixels of an area of a surface using a constant value. This routine modifies the color channels and/or the alpha channel of the pixels of a surface using a constant value. Notes: 1) Normal fill opeartion can be achieved by specifying both colorOp and alphaOp as B_SoftGfx_FillOp_eCopy 2) If surface is in palette format then color represents the index to the clut. If surface is in non-palette format, say ARGB8888 or ARGB4444, then color parameter has to be in the ARGB8888 format. Ex: In ARGB4444 BLUE color is represented by 0xF00F. But, for filling an ARGB4444 surface with solid BLUE color, the color parameter should be 0xFF0000FF (as in ARGB8888 format). 3) Only B_SoftGfx_FillOp_eCopy operation is supported for palette surface. 4) Color channels of a non-paletter surface can be blended with the color channels of the constant color using constant alpha. For such operations, user needs to specify : colorOp = B_SoftGfx_FillOp_eBlend alphaOp = B_SoftGfx_FillOp_eIgnore ***************************************************************************/ NEXUS_Error B_SoftGfx_Fill( B_SoftGfxHandle handle, const B_SoftGfx_FillSettings *pSettings ) { bgfx_surf_t sur; NEXUS_Error err = NEXUS_SUCCESS; NEXUS_SurfaceCreateSettings sCreateSettings; NEXUS_SurfaceMemory sMemory; uint16_t width = 0; uint16_t height = 0; #if PROFILE_SOFTGFX struct timeval tv1,tv2; #endif /* PROFILE_SOFTGFX */ BDBG_OBJECT_ASSERT(handle, B_SoftGfx); if(!pSettings) { return BERR_TRACE(NEXUS_INVALID_PARAMETER); } BDBG_MSG(("B_SoftGfx_Fill: surface=0x%x rect[%d,%d,%d,%d] color=0x%x colorOp=%d alphaOp=%d", pSettings->surface, pSettings->rect.x,pSettings->rect.y, pSettings->rect.width, pSettings->rect.height, pSettings->color, pSettings->colorOp, pSettings->alphaOp)); /* Validate parameters & settings for fill */ NEXUS_Surface_GetCreateSettings(pSettings->surface, &sCreateSettings); NEXUS_Surface_GetMemory(pSettings->surface, &sMemory); if(!B_SoftGfx_IsSupportedFillPixelFormat(sCreateSettings.pixelFormat)) return BERR_TRACE(NEXUS_INVALID_PARAMETER); if(pSettings->rect.x < 0 || pSettings->rect.y < 0) { BDBG_ERR(("Negative coordinates [x,y]=[%d,%d] are not supported!", pSettings->rect.x,pSettings->rect.y)); return BERR_TRACE(NEXUS_INVALID_PARAMETER); } if((pSettings->rect.width == 0 && pSettings->rect.height != 0) || (pSettings->rect.width != 0 && pSettings->rect.height == 0)) { BDBG_ERR(("Either height[%d] / width[%d] is 0", pSettings->rect.width,pSettings->rect.height)); return BERR_TRACE(NEXUS_INVALID_PARAMETER); } /* create soft_surface */ bsoftgfx_create_surface(&sur, pSettings->surface); /* width,height of 0,0 fills the entire surface */ if(pSettings->rect.width == 0 && pSettings->rect.height == 0) { width = sCreateSettings.width; height = sCreateSettings.height; } else { width = pSettings->rect.width; height = pSettings->rect.height; } if((pSettings->colorOp == B_SoftGfx_FillOp_eCopy) && (pSettings->alphaOp == B_SoftGfx_FillOp_eCopy)) { #if PROFILE_SOFTGFX gettimeofday(&tv1,NULL); #endif /* PROFILE_SOFTGFX */ /* Normal fill operation */ bgfx_fill_rect(&sur, pSettings->rect.x, pSettings->rect.y, width, height, pSettings->color); #if PROFILE_SOFTGFX gettimeofday(&tv2,NULL); BDBG_ERR(("bgfx_fill_rect = %d ms",(int)((tv2.tv_sec-tv1.tv_sec)*1000+(tv2.tv_usec-tv1.tv_usec)/1000))); #endif /* PROFILE_SOFTGFX */ } else if ((pSettings->colorOp == B_SoftGfx_FillOp_eBlend) && (pSettings->alphaOp == B_SoftGfx_FillOp_eIgnore) && (sMemory.palette == NULL)&& (sCreateSettings.pixelFormat != NEXUS_PixelFormat_eR5_G6_B5)) { #if PROFILE_SOFTGFX gettimeofday(&tv1,NULL); #endif /* PROFILE_SOFTGFX */ /* Blend color channels with constant color using constant alpha */ err = bgfx_blend_fill_rect(&sur, pSettings->rect.x, pSettings->rect.y, width, height, pSettings->color); #if PROFILE_SOFTGFX gettimeofday(&tv2,NULL); BDBG_ERR(("bgfx_blend_fill_rect = %d ms",(int)((tv2.tv_sec-tv1.tv_sec)*1000+(tv2.tv_usec-tv1.tv_usec)/1000))); #endif /* PROFILE_SOFTGFX */ } else { BDBG_ERR(("B_SoftGfx_Fill: Not supported colorOp=%d alphaOp=%d palette=%p", pSettings->colorOp, pSettings->alphaOp, sMemory.palette)); err = NEXUS_NOT_SUPPORTED; } /* destroy soft_surface */ bsoftgfx_destroy_surface(&sur); return err; } /*************************************************************************** Summary: Get default settings for the structure. ***************************************************************************/ void B_SoftGfx_GetDefaultBlitSettings( B_SoftGfx_BlitSettings *pSettings /* [out] */ ) { *pSettings = sDefaultBlitSettings; return; } /*************************************************************************** Summary: Perform a block transfer (blit) from one or two surfaces to an output. Description: Blit can be a simple blit or alpha blended blit. See B_SoftGfx_BlitSettings for details. ***************************************************************************/ NEXUS_Error B_SoftGfx_Blit( B_SoftGfxHandle handle, const B_SoftGfx_BlitSettings *pSettings ) { NEXUS_Error err = NEXUS_SUCCESS; bgfx_surf_t src, dst, out; NEXUS_SurfaceCreateSettings sSrcCreateSettings, sDstCreateSettings, sOutCreateSettings; bgfx_color_matrix_t sColorMatrix; unsigned int i=0; #if PROFILE_SOFTGFX struct timeval tv1,tv2; #endif /* PROFILE_SOFTGFX */ BDBG_OBJECT_ASSERT(handle, B_SoftGfx); if(!pSettings) { return BERR_TRACE(NEXUS_INVALID_PARAMETER); } BDBG_MSG(("B_SoftGfx_Blit: src=%p rect[%d,%d,%d,%d] \ndst=%p [x,y]=[%d,%d]" " out=%p [x,y]=[%d,%d] \n colorOp=%d, alphaOp=%d" " constAlphaAlphaOp=0x%x constAlphaColorOp=0x%x", pSettings->srcsurface, pSettings->srcrect.x,pSettings->srcrect.y, pSettings->srcrect.width, pSettings->srcrect.height, pSettings->dstsurface, pSettings->dstx, pSettings->dsty, pSettings->outsurface, pSettings->outx, pSettings->outy, pSettings->colorOp, pSettings->alphaOp, pSettings->constAlphaAlphaOp, pSettings->constAlphaColorOp)); /* Validate parameters & settings for fill */ if(!pSettings->srcsurface) { return BERR_TRACE(NEXUS_INVALID_PARAMETER); } NEXUS_Surface_GetCreateSettings(pSettings->srcsurface, &sSrcCreateSettings); if(!B_SoftGfx_IsSupportedBlitPixelFormat(sSrcCreateSettings.pixelFormat)) return BERR_TRACE(NEXUS_INVALID_PARAMETER); if(!pSettings->outsurface) { return BERR_TRACE(NEXUS_INVALID_PARAMETER); } NEXUS_Surface_GetCreateSettings(pSettings->srcsurface, &sOutCreateSettings); if(!B_SoftGfx_IsSupportedBlitPixelFormat(sOutCreateSettings.pixelFormat)) return BERR_TRACE(NEXUS_INVALID_PARAMETER); if(pSettings->dstsurface) /* Dst surface is optional */ { NEXUS_Surface_GetCreateSettings(pSettings->srcsurface, &sDstCreateSettings); if(!B_SoftGfx_IsSupportedBlitPixelFormat(sDstCreateSettings.pixelFormat)) return BERR_TRACE(NEXUS_INVALID_PARAMETER); } if(pSettings->srcrect.x < 0 || pSettings->srcrect.y < 0 || pSettings->dstx < 0 || pSettings->dsty < 0 || pSettings->outx < 0 || pSettings->outy < 0) { BDBG_ERR(("Negative coordinates src[x,y]=[%d,%d] dst[x,y]=[%d,%d]" " out[x,y]=[%d,%d] are not supported!", pSettings->srcrect.x,pSettings->srcrect.y, pSettings->dstx, pSettings->dsty, pSettings->outx, pSettings->outy)); return BERR_TRACE(NEXUS_INVALID_PARAMETER); } if((pSettings->srcrect.width == 0 && pSettings->srcrect.height != 0) || (pSettings->srcrect.width != 0 && pSettings->srcrect.height == 0) || (pSettings->srcrect.width == 0 && pSettings->srcrect.height == 0)) { BDBG_ERR(("Height[%d] and/or width[%d] is 0", pSettings->srcrect.width,pSettings->srcrect.height)); return BERR_TRACE(NEXUS_INVALID_PARAMETER); } if(pSettings->colorOp == B_SoftGfx_BlitColorOp_eMax || pSettings->alphaOp == B_SoftGfx_BlitAlphaOp_eMax) { BDBG_ERR(("colorOp[%d] and/or alphaOp[%d] is invalid", pSettings->colorOp, pSettings->alphaOp)); return BERR_TRACE(NEXUS_INVALID_PARAMETER); } /* All sanity checks done by now */ /* Map to corresponding soft graphics operations */ if(pSettings->colorOp == B_SoftGfx_BlitColorOp_eCopySource && pSettings->alphaOp == B_SoftGfx_BlitAlphaOp_eCopySource) { /* Simple BLT operation */ if(sSrcCreateSettings.pixelFormat != sOutCreateSettings.pixelFormat) { BDBG_ERR(("srcsurface pixel format(%d) != out surface pixel format(%d)", sSrcCreateSettings.pixelFormat, sOutCreateSettings.pixelFormat)); return BERR_TRACE(NEXUS_INVALID_PARAMETER); } /* create soft surfaces */ bsoftgfx_create_surface(&src, pSettings->srcsurface); bsoftgfx_create_surface(&out, pSettings->outsurface); /* blit rect */ #if PROFILE_SOFTGFX gettimeofday(&tv1,NULL); #endif /* PROFILE_SOFTGFX */ sColorMatrix.shift = pSettings->conversionMatrix.shift; for(i = 0 ; i < B_SOFTGFX_COLOR_MATRIX_COEFF_COUNT ; i++) { sColorMatrix.coeffMatrix[i] = pSettings->conversionMatrix.coeffMatrix[i]; } err = bgfx_blit_rect(&src, &out, pSettings->srcrect.x, pSettings->srcrect.y, pSettings->outx, pSettings->outy, pSettings->srcrect.width, pSettings->srcrect.height, pSettings->conversionMatrixEnabled, &(sColorMatrix)); if(err) {BERR_TRACE(err); /* fall through */} #if PROFILE_SOFTGFX gettimeofday(&tv2,NULL); BDBG_ERR(("bgfx_blit_rect BLT = %d ms",(int)((tv2.tv_sec-tv1.tv_sec)*1000+(tv2.tv_usec-tv1.tv_usec)/1000))); #endif /* PROFILE_SOFTGFX */ if(pSettings->bApplyAntiFlutterFiler) { #if 1 /* DEPRECATED */ err = bgfx_anti_flutter_filter(&out, &out, pSettings->outx, pSettings->outy, pSettings->outx, pSettings->outy, pSettings->srcrect.width, pSettings->srcrect.height); if(err) {BERR_TRACE(err); /* fall through */} #else BDBG_WRN(("\n\n***********************************************************\n" "Anti-flutter support has been deprecated from softgfx.\n" "Please use anti-flutter from GFD block.\n" "***********************************************************\n")); #endif } /* destroy soft_surface */ bsoftgfx_destroy_surface(&src); bsoftgfx_destroy_surface(&out); } else { /* Blend operation */ unsigned int operation; /* Requires dst surface, check it! */ if(!pSettings->dstsurface) { return BERR_TRACE(NEXUS_INVALID_PARAMETER); } /* All three surfaces should be of the same pixel fornat */ if(sSrcCreateSettings.pixelFormat != sOutCreateSettings.pixelFormat || sSrcCreateSettings.pixelFormat != sDstCreateSettings.pixelFormat ) { BDBG_ERR(("src pixel format(%d) != out pixel format(%d) != dst pixel format(%d)", sSrcCreateSettings.pixelFormat, sOutCreateSettings.pixelFormat, sDstCreateSettings.pixelFormat)); return BERR_TRACE(NEXUS_INVALID_PARAMETER); } /* create soft surfaces */ bsoftgfx_create_surface(&src, pSettings->srcsurface); bsoftgfx_create_surface(&dst, pSettings->dstsurface); bsoftgfx_create_surface(&out, pSettings->outsurface); operation = B_SoftGfx_ColorOpMapping[pSettings->colorOp]| B_SoftGfx_AlphaOpMapping[pSettings->alphaOp]; BDBG_MSG(("Blend: operation=0x%x",operation)); #if PROFILE_SOFTGFX gettimeofday(&tv1,NULL); #endif /* PROFILE_SOFTGFX */ err = bgfx_blit_rect_multisuf_blending(&src, &dst, &out, pSettings->srcrect.x, pSettings->srcrect.y, pSettings->dstx, pSettings->dsty, pSettings->outx, pSettings->outy, pSettings->srcrect.width, pSettings->srcrect.height, operation, pSettings->constAlphaColorOp, pSettings->constAlphaAlphaOp); if(err) {BERR_TRACE(err); /* fall through */} #if PROFILE_SOFTGFX gettimeofday(&tv2,NULL); BDBG_ERR(("bgfx_blit_rect alpha-blend= %d ms",(int)((tv2.tv_sec-tv1.tv_sec)*1000+(tv2.tv_usec-tv1.tv_usec)/1000))); #endif /* PROFILE_SOFTGFX */ if(pSettings->bApplyAntiFlutterFiler) { #if 0 /* DEPRECATED */ err = bgfx_anti_flutter_filter(&out, &out, pSettings->outx, pSettings->outy, pSettings->outx, pSettings->outy, pSettings->srcrect.width, pSettings->srcrect.height); if(err) {BERR_TRACE(err); /* fall through */} #else BDBG_WRN(("\n\n***********************************************************\n" "Anti-flutter support has been deprecated from softgfx.\n" "Please use anti-flutter from GFD block.\n" "***********************************************************\n")); #endif } /* destroy soft_surface */ bsoftgfx_destroy_surface(&src); bsoftgfx_destroy_surface(&dst); bsoftgfx_destroy_surface(&out); } return err; } /*************************************************************************** Summary: Get default settings for the structure. ***************************************************************************/ void B_SoftGfx_GetDefaultScaleSettings( B_SoftGfx_ScaleSettings *pSettings /* [out] */ ) { *pSettings = sDefaultScaleSettings; return; } /*************************************************************************** Summary: Perform scale-up/down from one surfaces to another. Description: User can choose to enable filtering (slower but better quality) or not ***************************************************************************/ NEXUS_Error B_SoftGfx_Scale( B_SoftGfxHandle handle, B_SoftGfx_ScaleSettings *pSettings ) { NEXUS_Error err = NEXUS_SUCCESS; bgfx_surf_t src, out; NEXUS_SurfaceCreateSettings sSrcCreateSettings, sOutCreateSettings; #if PROFILE_SOFTGFX struct timeval tv1,tv2; #endif /* PROFILE_SOFTGFX */ BDBG_OBJECT_ASSERT(handle, B_SoftGfx); if( (0 == pSettings->srcsurface) || (0 == pSettings->outsurface)) { return BERR_TRACE(NEXUS_INVALID_PARAMETER); } BDBG_MSG(("B_SoftGfx_Scale: src=%p rect[%d,%d,%d,%d] " " out=%p rect[%d,%d,%d,%d], ApplySclFiltering=%d", pSettings->srcsurface, pSettings->srcrect.x, pSettings->srcrect.y, pSettings->srcrect.width, pSettings->srcrect.height, pSettings->outsurface, pSettings->outrect.x, pSettings->outrect.y, pSettings->outrect.width, pSettings->outrect.height, pSettings->bApplySclFiltering)); NEXUS_Surface_GetCreateSettings(pSettings->srcsurface, &sSrcCreateSettings); if(!B_SoftGfx_IsSupportedBlitPixelFormat(sSrcCreateSettings.pixelFormat)) return BERR_TRACE(NEXUS_INVALID_PARAMETER); NEXUS_Surface_GetCreateSettings(pSettings->outsurface, &sOutCreateSettings); if(!B_SoftGfx_IsSupportedBlitPixelFormat(sOutCreateSettings.pixelFormat)) return BERR_TRACE(NEXUS_INVALID_PARAMETER); if((sSrcCreateSettings.pixelFormat != NEXUS_PixelFormat_eA8_R8_G8_B8) ||(sOutCreateSettings.pixelFormat != NEXUS_PixelFormat_eA8_R8_G8_B8)) { BDBG_ERR(("B_SoftGfx_Scale: Currently this API only support ARGB8888 pixel format")); return BERR_TRACE(NEXUS_INVALID_PARAMETER); } if(pSettings->srcrect.width <= 0 || pSettings->srcrect.height <= 0 || pSettings->outrect.width <= 0 || pSettings->outrect.height <= 0) { BDBG_ERR(("B_SoftGfx_Scale: Invalid coordinates src_rect[%d,%d, %d, %d] out_rect[%d,%d,%d,%d]", pSettings->srcrect.x, pSettings->srcrect.y, pSettings->srcrect.width, pSettings->srcrect.height, pSettings->outrect.x, pSettings->outrect.y, pSettings->outrect.width, pSettings->outrect.height)); return BERR_TRACE(NEXUS_INVALID_PARAMETER); } if(pSettings->srcrect.x < 0 || pSettings->srcrect.y < 0 || pSettings->outrect.x < 0 || pSettings->outrect.y < 0) { BDBG_ERR(("Negative coordinates src[x,y]=[%d,%d] dst[x,y]=[%d,%d]" " are not supported!", pSettings->srcrect.x,pSettings->srcrect.y, pSettings->outrect.x,pSettings->outrect.y)); return BERR_TRACE(NEXUS_INVALID_PARAMETER); } /* create soft surfaces */ bsoftgfx_create_surface(&src, pSettings->srcsurface); bsoftgfx_create_surface(&out, pSettings->outsurface); /* blit rect */ #if PROFILE_SOFTGFX gettimeofday(&tv1,NULL); #endif /* PROFILE_SOFTGFX */ { uint32_t x_scl_ratio, y_scl_ratio; x_scl_ratio = (pSettings->outrect.width << 3) / pSettings->srcrect.width; y_scl_ratio = (pSettings->outrect.height << 3) / pSettings->srcrect.height; if ( (pSettings->outrect.width == pSettings->srcrect.width) && (pSettings->outrect.height == pSettings->srcrect.height) ) { err = bgfx_blit_rect(&src, &out, pSettings->srcrect.x, pSettings->srcrect.y, pSettings->outrect.x, pSettings->outrect.y, pSettings->srcrect.width, pSettings->srcrect.height, 0, NULL); if(err) {BERR_TRACE(err); /* fall through */} } else if ( (x_scl_ratio >= 16) && (y_scl_ratio >= 16) && pSettings->bApplySclFiltering ) { err = bgfx_blit_rect_scale_v_up_h_up(&src, &out, pSettings->srcrect.x, pSettings->srcrect.y, pSettings->outrect.x, pSettings->outrect.y, pSettings->srcrect.width, pSettings->srcrect.height, pSettings->outrect.width, pSettings->outrect.height); if(err) {BERR_TRACE(err); /* fall through */} } else if (x_scl_ratio <= 4 && y_scl_ratio <= 4 && pSettings->bApplySclFiltering ) { err = bgfx_blit_rect_scale_v_down_h_down(&src, &out, pSettings->srcrect.x, pSettings->srcrect.y, pSettings->outrect.x, pSettings->outrect.y, pSettings->srcrect.width, pSettings->srcrect.height, pSettings->outrect.width, pSettings->outrect.height); if(err) {BERR_TRACE(err); /* fall through */} } else { err = bgfx_blit_rect_scale(&src, &out, pSettings->srcrect.x, pSettings->srcrect.y, pSettings->outrect.x, pSettings->outrect.y, pSettings->srcrect.width, pSettings->srcrect.height, pSettings->outrect.width, pSettings->outrect.height); if(err) {BERR_TRACE(err); /* fall through */} } } #if PROFILE_SOFTGFX gettimeofday(&tv2,NULL); BDBG_ERR(("B_SoftGfx_Scale BLT = %d ms",(int)((tv2.tv_sec-tv1.tv_sec)*1000+(tv2.tv_usec-tv1.tv_usec)/1000))); #endif /* PROFILE_SOFTGFX */ /* destroy soft_surface */ bsoftgfx_destroy_surface(&src); bsoftgfx_destroy_surface(&out); return err; } #ifdef GRAPHICS_DESTRIPE typedef char (*NEXUS_StillDecoder_P_read_char_func)(const void *address); static char NEXUS_StillDecoder_P_read_char_host(const void *address) { return *(char *)address; } /* Destripe logic from Jeff Christensen's (christj) DestripeSample.c The source format 4:2:0. Each src row of chroma is 2 rows of dest chroma. AVD outputs in host endianness. Byte order on LE system is: luma: Y3 Y2 Y1 Y0 Y4 etc. chroma: Cr1 Cb1 Cr0 Cb0 Cr2 etc. The dest format is Y0CbY1Cr 4:2:2, 2 bytes per pixel, in host endianess. Byte order on LE system is: Cr0 Y1 Cb0 Y0 Cr1 Y3 Cb1 Y2 */ static int DestripeImage (const char *from, char *to, int image_wid, int image_hgt, int stripe_wid, int stripe_hgt, bool is_luma, NEXUS_StillDecoder_P_read_char_func read_func) { int stripe_size = stripe_wid * stripe_hgt; int pixels = image_wid * image_hgt; int i; int scol; int icol; const char *ptr; #if BSTD_CPU_ENDIAN==BSTD_ENDIAN_LITTLE if (is_luma) to++; /* For luma pixels, offset by one in order to interleave */ #else if (!is_luma) to++; /* For luma pixels, offset by one in order to interleave */ #endif scol = 0; icol = 0; ptr = from; for (i = 0; i < pixels; i++) { /* calc swap */ #if BSTD_CPU_ENDIAN==BSTD_ENDIAN_LITTLE int swapinc = (scol % 4 < 2) ? 2 : -2; *to = read_func(ptr+scol+swapinc); #else BSTD_UNUSED(read_func); *to = ptr[scol]; #endif if (!is_luma) { /* for 4:2:0 -> 4:2:2 conversion, each chroma value applies to 2 rows */ #if BSTD_CPU_ENDIAN==BSTD_ENDIAN_LITTLE *(to+(image_wid*2)) = read_func(ptr+scol+swapinc); #else *(to+(image_wid*2)) = ptr[scol]; #endif } to += 2; /* skip to next luma or chroma byte */ /* If we reach the end of a stripe, move down to the * next strip to continue this row. */ if (++scol == stripe_wid) { scol = 0; ptr += stripe_size; } /* If we reach the end of a row, go back to the 1st * stripe, but move down a row. Reset everything. */ if (++icol == image_wid) { from += stripe_wid; ptr = from; /* for 4:2:0 -> 4:2:2 conversion, we've already written 2 rows, so skip */ if (!is_luma) to += (image_wid*2); icol = 0; scol = 0; } } return 0; } /*************************************************************************** Summary: Create a new surface by copying from a striped surface Description: A striped surface is the output of NEXUS_StillDecoder_GetStripedSurface. ***************************************************************************/ NEXUS_SurfaceHandle B_SoftGfx_Destripe( NEXUS_StripedSurfaceHandle stripedSurface) { NEXUS_SurfaceCreateSettings surfaceCreateSettings; NEXUS_SurfaceHandle surface; NEXUS_SurfaceMemory mem; NEXUS_StillDecoder_P_read_char_func func=NEXUS_StillDecoder_P_read_char_host; NEXUS_StripedSurfaceCreateSettings sStripedSurfaceSettings; NEXUS_StripedSurface_GetCreateSettings(stripedSurface,&sStripedSurfaceSettings); if (sStripedSurfaceSettings.imageHeight== 0 || sStripedSurfaceSettings.imageWidth== 0) { return NULL; } /* create a bsurface_t which wraps the BSUR_Handle used by VDC */ NEXUS_Surface_GetDefaultCreateSettings(&surfaceCreateSettings); surfaceCreateSettings.height = sStripedSurfaceSettings.imageHeight; surfaceCreateSettings.width = sStripedSurfaceSettings.imageWidth; surfaceCreateSettings.pixelFormat = NEXUS_PixelFormat_eY08_Cb8_Y18_Cr8; surface = NEXUS_Surface_Create(&surfaceCreateSettings); if (!surface) {return NULL;} /* now destripe and do pixel conversion into the new buffer with a two pass algorithm */ NEXUS_Surface_GetMemory(surface, &mem); DestripeImage(sStripedSurfaceSettings.pLumaBuffer, mem.buffer, sStripedSurfaceSettings.imageWidth, sStripedSurfaceSettings.imageHeight, sStripedSurfaceSettings.stripedWidth, sStripedSurfaceSettings.lumaStripedHeight, true, func); DestripeImage(sStripedSurfaceSettings.pChromaBuffer, mem.buffer, sStripedSurfaceSettings.imageWidth, sStripedSurfaceSettings.imageHeight/2, sStripedSurfaceSettings.stripedWidth, sStripedSurfaceSettings.chromaStripedHeight, false, func); NEXUS_Surface_Flush(surface); return surface; } #endif/*Graphics Destripe support*/