This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM5728: GC320 blt question

Part Number: AM5728

Hi expert,

In Processor SDK 3.1. gc320-tests only shows how to bitblt/clear data to a new surface created by gcoSURF_Construct.

How can I use vivante API to bitblt data to a existed v4l2 buffer or kms frambuffer?

Regards,

Hugo

  • Hi,

    The software team have been notified. They will respond here.
  • Dear Biser

    Is there any update for this issue?
    Thanks for your support.
  • I have escalated the request.
  • More test cases can be found here -

    Check if this helps.

  • Check attached file that uses vivante API to bitblt data to a existed drm buffer.

    /****************************************************************************
    *
    *    Copyright 2012 - 2015 Vivante Corporation, Santa Clara, California.
    *    All Rights Reserved.
    *
    *    Permission is hereby granted, free of charge, to any person obtaining
    *    a copy of this software and associated documentation files (the
    *    'Software'), to deal in the Software without restriction, including
    *    without limitation the rights to use, copy, modify, merge, publish,
    *    distribute, sub license, and/or sell copies of the Software, and to
    *    permit persons to whom the Software is furnished to do so, subject
    *    to the following conditions:
    *
    *    The above copyright notice and this permission notice (including the
    *    next paragraph) shall be included in all copies or substantial
    *    portions of the Software.
    *
    *    THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
    *    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
    *    IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
    *    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    *    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    *    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    *
    *****************************************************************************/
    
    
    #include <galUtil.h>
    #include "gutsystem.h"
    
    /* drm headers */
    #include <omap/omap_drm.h>
    #include <libdrm/omap_drmif.h>
    #include <xf86drm.h>
    
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/mman.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <errno.h>
    
    //#define VIVANTE_DEBUG
    
    /* Version info. */
    static const char c_szFrameworkInfo[] = "\tGAL Test Framework Version 3.1 \n";
    
    /* Test case. */
    static char        g_caseName[MAX_BUFFER_SIZE + 1]    = "";
    static char        g_simpleCaseName[MAX_BUFFER_SIZE + 1]  = "";
    
    gctHANDLE   g_caseDll           = gcvNULL;
    static GalTest     *g_testObject       = gcvNULL;
    
    /* Base objects */
    static GalRuntime g_Runtime;
    static gctUINT s_frameNo;
    static gctBOOL g_UseRange = gcvFALSE;
    
    #if defined(LINUX) || defined(ANDROID)
    /* Video memory mapping. */
    static gctPHYS_ADDR g_InternalPhysical, g_ExternalPhysical, g_ContiguousPhysical;
    static gctSIZE_T    g_InternalSize,     g_ExternalSize,     g_ContiguousSize;
    static gctPOINTER   g_Internal,         g_External,         g_Contiguous;
    #endif
    
    static gctSTRING        g_Argv2Test[MAX_ARG_COUNT] = {"",};
    
    int g_alloc_fd = -1;
    
    static void PrintUsage()
    {
        sysOutput("Usage: galRunTest2 gltTestCase.dll [-option value] [...]\n"
                "options:\n"
    #ifdef VIVANTE_DEBUG
                "\tw\tThe width of the target surface.\n"
                "\th\tThe height of the target surface.\n"
                "\tf\tThe format of the target surface.\n"
                "\tp\tThe pool of the target surface.\n"
    #endif
                "\ts\tenable/disable. Enable/disable target saving.\n"
                "\tc\tThe config file.\n");
    }
    
    static const struct PoolInfo
    {
        gctCONST_STRING name;
        gcePOOL         type;
    } c_PoolInfos[] =
    {
        {"DEFAULT", gcvPOOL_DEFAULT},
        {"VIRTUAL", gcvPOOL_VIRTUAL},
        {"SYSTEM",  gcvPOOL_SYSTEM},
    };
    
    static gcePOOL ConvToTargetPool(const char *name)
    {
        int i;
    
        for (i = 0; i < sizeof(c_PoolInfos) / sizeof(c_PoolInfos[0]); i++)
        {
            if (strcmp(name, c_PoolInfos[i].name) == 0) {
                return c_PoolInfos[i].type;
            }
        }
    
        sysOutput("*WARN* Unsupport target surface pool: \"%s\", "
                "use default value: \"gcvPOOL_DEFAULT\"\n", name);
        return gcvPOOL_DEFAULT;
    }
    
    static const char * ConvToTargetPoolStr(gcePOOL pool)
    {
        int i;
    
        for (i = 0; i < sizeof(c_PoolInfos) / sizeof(c_PoolInfos[0]); i++)
        {
            if (c_PoolInfos[i].type == pool) {
                return c_PoolInfos[i].name;
            }
        }
    
        return "Unknown Pool Type";
    }
    
    
    gctBOOL ConfigSetup(const char* cfgName)
    {
        FILE* config;
        char strTemp[MAX_BUFFER_SIZE];
    
        config = fopen(cfgName, "r");
        if (config == gcvNULL)
        {
            sysOutput("There's no config file: %s\n", cfgName);
            return gcvFALSE;
        }
    
        fscanf (config, "Screen Width = %d\n", &g_Runtime.width);
        fscanf (config, "Screen Height = %d\n", &g_Runtime.height);
        fscanf (config, "Surface Format = %s\n", strTemp);
        g_Runtime.format = GalQueryFormat(strTemp);
        if (g_Runtime.format == gcvSURF_UNKNOWN)
        {
            sysOutput("Unknown format: %s\n", strTemp);
            return gcvFALSE;
        }
    
        fscanf (config, "Surface Pool = %s\n", strTemp);
        g_Runtime.pool = ConvToTargetPool(strTemp);
    
        fclose (config);
        return gcvTRUE;
    }
    
    /*
     *  Name:       ParseArgs( int argc, char *argv[] )
     *  Returns:    0 when successed.
     *  Parameters: arguments, the command line arguments to parse.
     *  Description:This function parses the command line arguments and set the corresponding variables, e.g., the bitmap directory, the log file directory and so on.
    */
    static int ParseArgs(int argc, char *argv[])
    {
        int     i;
        int     result          = 0;
        char    *str;
        char strCfgName[MAX_BUFFER_SIZE]= {'\0',};
    #ifdef VIVANTE_DEBUG
        gctUINT cmdWidth = 0, cmdHeight = 0;
        gceSURF_FORMAT cmdFormat = gcvSURF_UNKNOWN;
        gcePOOL cmdPool = -1;
    #endif /* VIVANTE_DEBUG */
    
        /* Set g_caseName. */
        memset(g_caseName, 0, sizeof(g_caseName));
        strncpy(g_caseName, argv[1], strlen(argv[1]));
    
        /* Start from argv[2]. */
        i = 2;
        while (i < argc)
        {
            str = argv[i];
            if ((str[0] == '-' || str[0] == '/') && str[2] == '\0')
            {
                switch (str[1])
                {
    #ifdef VIVANTE_DEBUG
                    case 'w':
                        {
                            assert(argv[i + 1] != NULL);
                            cmdWidth = atoi(argv[i + 1]);
                            i += 2;
                        }
                        continue;
    
                    case 'h':
                        {
                            assert(argv[i + 1] != NULL);
                            cmdHeight = atoi(argv[i + 1]);
                            i += 2;
                        }
                        continue;
    
                    case 'f':
                        {
                            assert(argv[i + 1] != NULL);
                            cmdFormat = ConvToTargetFormat(argv[i + 1]);
                            i += 2;
                        }
                        continue;
    
                    case 'p':
                        {
                            assert(argv[i + 1] != NULL);
                            cmdPool = ConvToTargetPool(argv[i + 1]);
                            i += 2;
                        }
                        continue;
    #endif /* VIVNATE_DEBUG */
                    case 'n':
                        {
                            assert(argv[i + 1] != NULL);
                            g_Runtime.startFrame = atoi(argv[i + 1]);
                            g_Runtime.endFrame = atoi(argv[i + 2]);
                            i += 3;
                            if (g_Runtime.startFrame > g_Runtime.endFrame)
                            {
                                sysOutput("start frame no.%d is bigger than end frame no.%d\n",
                                            g_Runtime.startFrame, g_Runtime.endFrame);
                                result = -1;
                            }
                            else
                            {
                                g_UseRange = gcvTRUE;
                            }
                        }
                        continue;
    
                    case 'c':
                        {
                            if (argv[i + 1] == NULL)
                            {
                                sysOutput("please specify the config file following -c\n");
                                result = -1;
                            }
                            strncpy(strCfgName, argv[i + 1], strlen(argv[i + 1]));
                            i += 2;
                         }
                        continue;
    
                    case 's':
                        {
                            if (argv[i + 1] == NULL)
                            {
                                sysOutput("please specify enable/disable following -s\n");
                                result = -1;
                            }
    
                            if (!strncmp("enable", argv[i + 1], 6))
                            {
                                g_Runtime.saveTarget = gcvTRUE;
                            }
                            else if (!strncmp("disable", argv[i + 1], 7))
                            {
                                g_Runtime.saveTarget = gcvFALSE;
                                g_Runtime.noSaveTargetNew = gcvTRUE;
                            }
                            else
                            {
                                sysOutput("please specify enable/disable following -s\n");
                                result = -1;
                            }
    
                            i += 2;
                         }
                        continue;
    
                    case 't':
                        {
                            if (argv[i + 1] == NULL)
                            {
                                sysOutput("please specify enable/disable following -t\n");
                                result = -1;
                            }
    
                            if (!strncmp("enable", argv[i + 1], 6))
                            {
                                g_Runtime.createTarget = gcvTRUE;
                            }
                            else if (!strncmp("disable", argv[i + 1], 7))
                            {
                                g_Runtime.createTarget = gcvFALSE;
                            }
                            else
                            {
                                sysOutput("please specify enable/disable following -s\n");
                                result = -1;
                            }
    
                            i += 2;
                         }
                        continue;
    
    
                    default:
                        break;
                }
            }
    
            {
                g_Argv2Test[g_Runtime.argc] = argv[i];
                i++;
    
                ++g_Runtime.argc;
                if (g_Runtime.argc > MAX_ARG_COUNT)
                {
                    sysOutput("Arguments for test too much\n");
                    result = -1;
                }
            }
        }
    
        /* Use cfg file to cover the default values. */
    #ifdef VIVANTE_DEBUG
        if (strCfgName[0] != '\0')
        {
            ConfigSetup(strCfgName);
        }
    
        // use command value to cover the default values
        if (cmdWidth != 0)
        {
            g_Runtime.width = cmdWidth;
        }
    
        if (cmdHeight != 0)
        {
            g_Runtime.height = cmdHeight;
        }
    
        if (cmdFormat != gcvSURF_UNKNOWN)
        {
            g_Runtime.format = cmdFormat;
        }
    
        if (cmdPool != -1)
        {
            g_Runtime.pool = cmdPool;
        }
    #else
        if (strCfgName[0] == '\0')
        {
            sysOutput("Please specify config file with -c\n");
            return -1;
        }
    
        if (!ConfigSetup(strCfgName))
            return -1;
    #endif
    
        return result;
    }
    
    int ChipCheck(GalRuntime *rt)
    {
        gceSTATUS status;
        gctUINT32 i;
        gctINT ret = 0;
    
        status = gcoHAL_QueryChipIdentity(rt->hal, &rt->ChipModel, &rt->ChipRevision, &rt->ChipFeatures, gcvNULL);
        if (status < 0)
        {
            GalOutput(GalOutputType_Log, "*ERROR* Failed to query chip info (status = 0x%x)\n", status);
            ret = -1;
            goto EXIT;
        }
    
        status = gcoOS_ReadRegister(rt->os, 0x98, &rt->PatchRevision);
        if (status < 0)
        {
            GalOutput(GalOutputType_Log, "*ERROR* Failed to read patch version (status = 0x%x)\n", status);
            ret = -2;
            goto EXIT;
        }
    
        GalOutput(GalOutputType_Log, "=================== Chip Information ==================\n");
        GalOutput(GalOutputType_Log, "Chip : GC%x\n", rt->ChipModel);
        GalOutput(GalOutputType_Log, "Chip revision: 0x%08x\n", rt->ChipRevision);
        GalOutput(GalOutputType_Log, "Patch revision: 0x%08x\n", rt->PatchRevision);
        GalOutput(GalOutputType_Log, "Chip Features: 0x%08x\n", rt->ChipFeatures);
    
        status = gcoHAL_QueryChipMinorFeatures(rt->hal, &rt->ChipMinorFeaturesNumber, gcvNULL);
        if (status < 0)
        {
            GalOutput(GalOutputType_Log, "*ERROR* Failed to query minor feature count (status = 0x%x)\n", status);
            ret = -2;
            goto EXIT;
        }
    
        if (MAX_MINORFEATURE_NUMBER < rt->ChipMinorFeaturesNumber)
        {
            GalOutput(GalOutputType_Log, "*ERROR* no enough space for minor features\n");
            ret = -3;
            goto EXIT;
        }
    
        status = gcoHAL_QueryChipMinorFeatures(rt->hal, &rt->ChipMinorFeaturesNumber, rt->ChipMinorFeatures);
        if (status < 0)
        {
            GalOutput(GalOutputType_Log, "*ERROR* Failed to query minor features (status = 0x%x)\n", status);
            ret = -4;
            goto EXIT;
        }
    
        for (i = 0; i < rt->ChipMinorFeaturesNumber; i++)
        {
            GalOutput(GalOutputType_Log, "Chip MinorFeatures%d: 0x%08x\n", i, rt->ChipMinorFeatures[i]);
        }
    
        GalOutput(GalOutputType_Log, "=======================================================\n");
    
    EXIT:
    
        return ret;
    }
    
    static void close_target_surface()
    {
        close(g_alloc_fd);
    }
    
    static void* create_target_surface()
    {
        /* omapdrm vars */
        struct omap_device *dev;
        struct omap_bo *bo;
        int dmabuf_fd;
        int i;
    
        uint32_t size, flags = 0;
        void *vaddr = gcvNULL;
    
        /* Vivante DDK vars */
        gcsSURF_FORMAT_INFO_PTR info[2];    /* format parameters */
        int bpr;
        size_t stride;
    
        //g_alloc_fd = drmOpen("omapdrm", NULL);
        g_alloc_fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);
        if (g_alloc_fd <= 0) {
            sysOutput("*ERROR* Failed to open omapdrm device\n");
            return gcvNULL;
        }
        //sysOutput("\tINFO: opened omapdrm device\n");
    
        dev = omap_device_new(g_alloc_fd);
        if (dev == gcvNULL) {
            sysOutput("*ERROR* Failed to get omap device\n");
            return gcvNULL;
        }
        //sysOutput("\tINFO: got omap_device\n");
    
        /* calculate the size of the buffer needed. Use gcoSURF_QueryFormat API to
         * format parameters descriptor - this contains information on format as
         * needed by the Vivante driver
         */
        gcmVERIFY_OK(gcoSURF_QueryFormat(g_Runtime.format, info));
        //sysOutput("\tINFO: bits per pixel: %d\n", info[0]->bitsPerPixel);
    
        /* Vivante HAL needs 16 pixel alignment in width and 4 pixel alignment in
         * height.
         */
        bpr = ((g_Runtime.width + 15) & ~15) * (info[0]->bitsPerPixel / 8);
        sysOutput("\tINFO: bytes per row: %d\n", bpr);
        size = bpr * ((g_Runtime.height + 3) & ~3);
        stride = bpr;
        //sysOutput("\tINFO: height: %d\n \
          //      \tINFO: width: %d\n \
            //    \tINFO: size: %d\n \
              //  \tINFO: stride: %d\n",
                //g_Runtime.height, g_Runtime.width, size, stride);
        
        /* TODO: need to get the flags right here */
        /* MEM_CACHED, MEM_WRITE, */
        //flags &= ~OMAP_BO_CACHE_MASK;   /* MEM_CACHED */
        flags = OMAP_BO_WC;            /* write combine */
        //flags &= ~OMAP_BO_TILED_MASK;   /* non-Tiler */
    
        bo = omap_bo_new(dev, size, flags);
        if (!bo) {
            sysOutput("*ERROR* Failed to create omap bo\n");
            return gcvNULL;
        }
        //sysOutput("\tINFO: created omap bo object with size: %d\n", omap_bo_size(bo));
    
        /* get dmabuf fd that can be shared */
        dmabuf_fd = omap_bo_dmabuf(bo);
        if (dmabuf_fd <= 0) {
            sysOutput("*ERROR* Failed to get dmabuf fd from bo");
            omap_bo_del(bo);
            return gcvNULL;
        }
        //sysOutput("\tINFO: got the dmabuf handle: 0x%x\n", dmabuf_fd);
    
        /* now that we have a share fd, we don't need bo in this process any more.
         * Free it (which just drops the refcount)
         */
        //omap_bo_del(bo);
        //sysOutput("\tINFO: deleted omap bo object\n");
    
        /* map the dmabuf to this process, we can `mmap` the `dmabuf_fd` directly
         * here. TODO
         * we use omap_bo API anyway
         */
        vaddr = omap_bo_map(bo);
        //vaddr = mmap(0, size, PROT_READ | PROT_WRITE,
        //        MAP_SHARED, dmabuf_fd, 0);
        if (!vaddr) {
            sysOutput("*ERROR* could not mmap dmabuf - %s\n", strerror(errno));
            return -errno;
        }
        /*
         * `omap_bo` might not have backing pages at this point, make sure you got
         * them by writing into it.
         */
        memset(vaddr, 0, size);
        sysOutput("INFO: initialized the bo\n");
        
        //sysOutput("\tINFO: mapped the omap bo to this process\n");
    
        /* we mapped the bo, dont the omap_device anymore */
        //omap_device_del(dev);
        //sysOutput("\tINFO: deleted omap_device\n");
    
        return vaddr;
    
    }
    
    /*
     *  Name:       Initialize()
     *  Parameters: case_name, the name of the dll of the test case.
    */
    
    static gctBOOL Initialize()
    {
        PGalCreateTestObject createTestObject;
        gceSTATUS status;
    
        /* Load test dll */
        g_caseDll = sysLoadModule(g_caseName);
        if (g_caseDll == gcvNULL)
        {
            sysOutput("*ERROR* Failed to load: \"%s\"\n", g_caseName);
            return gcvFALSE;
        }
    
        createTestObject = (PGalCreateTestObject)sysGetProcAddress(g_caseDll, "GalCreateTestObject");
        if (createTestObject == gcvNULL)
        {
            sysOutput("*ERROR* Failed to find: \"GalCreateTestObject\" in %s\n", g_caseName);
            return gcvFALSE;
        }
    
        /* Setup log file objects. */
        if (!sysSetupLog(g_simpleCaseName))
        {
            sysOutput("*ERROR* Failed to set up log\n");
            return gcvFALSE;
        }
    
        /* Construct the gcoOS object. */
        status = gcoOS_Construct(gcvNULL, &g_Runtime.os);
        if (status < 0)
        {
            sysOutput("*ERROR* Failed to construct OS object (status = %d)\n", status);
            return gcvFALSE;
        }
    
        /* Construct the gcoHAL object. */
        status = gcoHAL_Construct(gcvNULL, g_Runtime.os, &g_Runtime.hal);
        if (status < 0)
        {
            sysOutput("*ERROR* Failed to construct GAL object (status = %d)\n", status);
            return gcvFALSE;
        }
    
        if (!gcoHAL_IsFeatureAvailable(g_Runtime.hal, gcvFEATURE_2DPE20))
        {
            switch (g_Runtime.format)
            {
            /* PE1.0 support. */
            case gcvSURF_X4R4G4B4:
            case gcvSURF_A4R4G4B4:
            case gcvSURF_X1R5G5B5:
            case gcvSURF_A1R5G5B5:
            case gcvSURF_X8R8G8B8:
            case gcvSURF_A8R8G8B8:
            case gcvSURF_R5G6B5:
                break;
    
            default:
                sysOutput("*ERROR* the target format %d is not supported by the hardware.\n",
                    g_Runtime.format);
                return gcvFALSE;
            }
        }
    
    #if defined(LINUX) || defined(ANDROID)
        /* Query the amount of video memory. */
        status = gcoHAL_QueryVideoMemory(g_Runtime.hal,
                                         &g_InternalPhysical, &g_InternalSize,
                                         &g_ExternalPhysical, &g_ExternalSize,
                                         &g_ContiguousPhysical, &g_ContiguousSize);
        if (gcmIS_ERROR(status))
        {
            sysOutput("gcoHAL_QueryVideoMemory failed %d.", status);
            return gcvFALSE;
        }
    
        /* Map the local internal memory. */
        if (g_InternalSize > 0)
        {
            status = gcoHAL_MapMemory(g_Runtime.hal,
                                      g_InternalPhysical, g_InternalSize,
                                      &g_Internal);
            if (gcmIS_ERROR(status))
            {
                sysOutput("gcoHAL_MapMemory failed %d.", status);
                return gcvFALSE;
            }
        }
    
        /* Map the local external memory. */
        if (g_ExternalSize > 0)
        {
            status = gcoHAL_MapMemory(g_Runtime.hal,
                                      g_ExternalPhysical, g_ExternalSize,
                                      &g_External);
            if (gcmIS_ERROR(status))
            {
                sysOutput("gcoHAL_MapMemory failed %d.", status);
                return gcvFALSE;
            }
        }
    
        /* Map the contiguous memory. */
        if (g_ContiguousSize > 0)
        {
            status = gcoHAL_MapMemory(g_Runtime.hal,
                                      g_ContiguousPhysical, g_ContiguousSize,
                                      &g_Contiguous);
            if (gcmIS_ERROR(status))
            {
                sysOutput("gcoHAL_MapMemory failed %d.", status);
                return gcvFALSE;
            }
        }
    #endif
    
        status = gcoHAL_Get2DEngine(g_Runtime.hal, &g_Runtime.engine2d);
        if (status < 0)
        {
            sysOutput("*ERROR* Failed to get 2D engine object (status = %d)\n", status);
            return gcvFALSE;
        }
    
        if (g_Runtime.createTarget)
        {
            void *vaddr = gcvNULL;
            size_t stride, size, bpr;
    
            gcsSURF_FORMAT_INFO_PTR info[2];
            gctUINT address[3];
            gctPOINTER memory[3];
            gctSHBUF shBuf = gcvNULL;
            gceHARDWARE_TYPE type;
            unsigned long phys = ~0U;
    
            vaddr = create_target_surface();
            if (!vaddr) {
                sysOutput("*ERROR*: Failed to create drm target surface ");
                return gcvFALSE;
            }
    
            gcoHAL_GetHardwareType(gcvNULL, &type);
    
            /* now that we created gem buffer and mapped it to this process, we need to
             * map this to GC320 MMU. First we get the hardware type, to figure which
             * version of MMU is the HAL using. Then set this buffer as an underlying
             * buffer to the gcoSURF object.
             */
            //set_default_hardware_type();
    
            /* create a wrapper gcoSURF surface object, because we are mapping the user
             * allocated buffer pool should be gcvPOOL_USER */
            status = gcoSURF_Construct(
                    gcvNULL,
                    g_Runtime.width,
                    g_Runtime.height,
                    1,
                    gcvSURF_BITMAP,
                    g_Runtime.format,
                    gcvPOOL_USER,
                    &g_Runtime.target);
            if (status < 0) {
                sysOutput("*ERROR* Failed to create gcoSURF object");
                return gcvFALSE;
            }
            /* calculate the size of the buffer needed. Use gcoSURF_QueryFormat API to
             * format parameters descriptor - this contains information on format as
             * needed by the Vivante driver
             */
            status = gcoSURF_QueryFormat(g_Runtime.format, info);
            if (status < 0) {
                sysOutput("*ERROR* Failed to create query format info");
                return gcvFALSE;
            }
    
            /* Vivante HAL needs 16 pixel alignment in width and 4 pixel alignment in
             * height.
             */
            bpr = ((g_Runtime.width + 15) & ~15) * (info[0]->bitsPerPixel / 8);
            //size = bpr * ((g_Runtime.height + 3) && ~3);
            stride = bpr;
            
            /* set the underlying buffer */
            status = gcoSURF_SetBuffer(
                        g_Runtime.target,
                        gcvSURF_BITMAP,
                        g_Runtime.format,
                        stride,
                        vaddr,
                        phys);
            if (status < 0) {
                sysOutput("*ERROR* Failed to set buffer for gcoSURF object");
                return gcvFALSE;
            }
            
            /* set window size */
            status = gcoSURF_SetWindow(
                        g_Runtime.target, 0, 0, g_Runtime.width, g_Runtime.height);
            if (status < 0) {
                sysOutput("*ERROR* Failed to set window for gcoSURF object");
                return gcvFALSE;
            }
    
            /* lock surface */
            status = gcoSURF_Lock(g_Runtime.target, address, memory);
            if (status < 0) {
                sysOutput("*ERROR* Failed to lock gcoSURF object");
                return gcvFALSE;
            }
    
    #if gcdYINTERLACED_RENDERING
            /* Set Y inverted content flag */
            gcmONERROR(
                    gcoSURF_SetFlags(g_Runtime.target,
                        gcvSURF_FLAG_CONTENT_YINVERTED,
                        gcvTRUE));
    #endif
    
            /* Alloc shared buffer */
            /* TODO: This is for sharing across processes, shouldn't the dmabuf be
             * sufficient, do we need to call this function
             */
            status = gcoSURF_AllocShBuffer(g_Runtime.target, &shBuf);
            if (status < 0) {
                sysOutput("*ERROR* Failed to create shared gcoSURF object");
                return gcvFALSE;
            }
            gcoHAL_SetHardwareType(gcvNULL, type);
    
        }
        else
            g_Runtime.target = gcvNULL;
    
    
        g_Runtime.pe20      = gcoHAL_IsFeatureAvailable(g_Runtime.hal, gcvFEATURE_2DPE20);
    #if gcvVERSION_MAJOR >= 4
        g_Runtime.fullDFB     = gcoHAL_IsFeatureAvailable(g_Runtime.hal, gcvFEATURE_FULL_DIRECTFB);
    #else
        g_Runtime.fullDFB     = gcvFALSE;
    #endif
    
        // log chip info
        if (ChipCheck(&g_Runtime) < 0)
        {
            sysOutput("*ERROR* Check chip info failed!\n");
            return gcvFALSE;
        }
    
        // output framework cfg info
        GalOutput(GalOutputType_Log, c_szFrameworkInfo);
    
        GalOutput(GalOutputType_Log,
            "===================== Test Config =====================\n"
            "\tscreen window width : %d\n"
            "\tscreen window height: %d\n"
            "\tsurface format: %s\n"
            "\tsurface pool: %s\n"
            "=======================================================\n",
            g_Runtime.width,
            g_Runtime.height,
            GalQueryFormatStr(g_Runtime.format),
            ConvToTargetPoolStr(g_Runtime.pool));
    
        g_testObject = createTestObject(&g_Runtime);
    
        /* output test case description */
        if (g_Runtime.wholeDescription != gcvNULL)
        {
            GalOutput(GalOutputType_Log, g_Runtime.wholeDescription);
        }
    
        if (g_testObject == gcvNULL)
        {
            if (!g_Runtime.notSupport)
                sysOutput("*ERROR* Failed to create test object for %s\n", g_caseName);
            return gcvFALSE;
        }
    
        s_frameNo = g_Runtime.startFrame; /* Frame Number. */
    
        return gcvTRUE;
    }
    
    /*
     *  Name:       Finalize()
     *  Returns:    None.
     *  Parameters: None.
     *  Description:Free all resource that the framework has used. These may include the memory resource it used, and the egl system resource and so on.
     *              Here it includes "finalize the test object(case)", "free egl resource", "free library resource", "finalize output file resource" and
     *              "destroy win32 resource".
    */
    static void Finalize()
    {
        if (g_testObject != gcvNULL)
        {
            if (g_testObject->destroy != gcvNULL) g_testObject->destroy(g_testObject);
        }
    
        if (g_Runtime.wholeDescription != gcvNULL)
        {
            free(g_Runtime.wholeDescription);
        }
    
        if (g_caseDll != gcvNULL)
            sysUnloadModule(g_caseDll);
    
        if (g_Runtime.hal != gcvNULL)
        {
            gcoHAL_Commit(g_Runtime.hal, gcvTRUE);
        }
    
        if (g_Runtime.target != gcvNULL)
        {
            gceHARDWARE_TYPE type;
    
            gcoHAL_GetHardwareType(gcvNULL, &type);
            //set_default_hardware_type();
    
            gcmVERIFY_OK(gcoSURF_Unlock(g_Runtime.target, gcvNULL));
            gcmVERIFY_OK(gcoSURF_Destroy(g_Runtime.target));
            gcmVERIFY_OK(gcoHAL_Commit(gcvNULL, gcvTRUE));
    
            gcoHAL_SetHardwareType(gcvNULL, type);
    
            close_target_surface();
        }
    
    #if defined(LINUX) || defined(ANDROID)
        if (g_Internal != gcvNULL)
        {
            /* Unmap the local internal memory. */
            gcmVERIFY_OK(gcoHAL_UnmapMemory(g_Runtime.hal,
                                            g_InternalPhysical, g_InternalSize,
                                            g_Internal));
        }
    
        if (g_External != gcvNULL)
        {
            /* Unmap the local external memory. */
            gcmVERIFY_OK(gcoHAL_UnmapMemory(g_Runtime.hal,
                                            g_ExternalPhysical, g_ExternalSize,
                                            g_External));
        }
    
        if (g_Contiguous != gcvNULL)
        {
            /* Unmap the contiguous memory. */
            gcmVERIFY_OK(gcoHAL_UnmapMemory(g_Runtime.hal,
                                            g_ContiguousPhysical, g_ContiguousSize,
                                            g_Contiguous));
        }
    #endif
    
        if (g_Runtime.hal != gcvNULL)
        {
            gcoHAL_Commit(g_Runtime.hal, gcvTRUE);
            gcoHAL_Destroy(g_Runtime.hal);
        }
    
        if (g_Runtime.os != gcvNULL)
        {
            gcoOS_Destroy(g_Runtime.os);
        }
    
        GalFinalizeOutput();
    }
    
    static gctBOOL MakeSimpleCaseName(char simpleCaseName[MAX_BUFFER_SIZE + 1], char *caseName)
    {
        char *start = caseName;
        size_t len = strlen(caseName);
        assert(len < MAX_BUFFER_SIZE);
    
        memset(simpleCaseName, 0, sizeof(simpleCaseName));
    
        do {
            char *end;
            int i;
    
            start = strstr(start, PREFIX);
            if (start != '\0')
            {
                strcpy(simpleCaseName, start);
                start += sizeof(PREFIX);
            }
            else
            {
                return gcvFALSE;
            }
    
            end = strstr(simpleCaseName, SURFFIX);
            if (end != gcvNULL)
            {
                *end = '\0';
            }
    
            for (i = 0; simpleCaseName[i] != '\0'; i++)
            {
                if (!((simpleCaseName[i] >= 'a' && simpleCaseName[i] <= 'z')
                    || (simpleCaseName[i] >= 'A' && simpleCaseName[i] <= 'Z')
                    || (simpleCaseName[i] >= '0' && simpleCaseName[i] <= '9')
                    || (simpleCaseName[i] == '_')))
                {
                    break;
                }
            }
    
            if (simpleCaseName[i] == '\0')
            {
                return gcvTRUE;
            }
        } while (start);
    
        return gcvFALSE;
    }
    
    /*
     *  Name:       Run()
     *  Returns:    None.
     *  Parameters: None.
    */
    static gctBOOL Run()
    {
        do {
            char bmpFileName[MAX_BUFFER_SIZE * 2];
    
            if (g_testObject == gcvNULL || g_testObject->render == gcvNULL ||
               (g_Runtime.createTarget && g_Runtime.target == gcvNULL))
            {
                break;
            }
    
            /* Notes: Some cases use accumulated vaule by frame number inside test body.
             *        You may be not expected to get the result images by rendering only one/some frames.
             */
            if (s_frameNo+1 > g_testObject->frameCount)
            {
                GalOutput(GalOutputType_Console,
                    "Frame %d is beyend range. Total frames are %d.\n", s_frameNo, g_testObject->frameCount);
                break;
            }
    
            GalOutput(GalOutputType_Result|GalOutputType_Console,
                "Begin to render %s frame %d ...\n", g_simpleCaseName, s_frameNo);
    
            /* clear target surface to black. */
            if (g_Runtime.target != gcvNULL && g_Runtime.cleanTarget)
            {
                if(gcmIS_ERROR(Gal2DCleanSurface(g_Runtime.hal, g_Runtime.target, COLOR_ARGB8(0x00, 0x00, 0x00, 0x00))))
                {
                    break;
                }
            }
    
            /* generate bmp file name */
            sprintf(bmpFileName, "%s%s_%03d.bmp", g_bmpPath, g_simpleCaseName, s_frameNo);
            if (g_Runtime.saveTarget)
            {
                g_Runtime.saveFullName = gcvNULL;
            }
            else
            {
                g_Runtime.saveFullName = bmpFileName;
            }
    
            if (g_testObject->render(g_testObject, s_frameNo) == gcvTRUE)
            {
                /* Rendering succeed. */
                GalOutput(GalOutputType_Result|GalOutputType_Console,
                    "Rendering %s frame %d ... succeed\n", g_simpleCaseName, s_frameNo);
            }
            else
            {
                /* Failed. */
                GalOutput(GalOutputType_Result|GalOutputType_Console,
                    "Rendering %s frame %d ... failed\n", g_simpleCaseName, s_frameNo);
                break;
            }
    
            if (g_Runtime.saveTarget)
            {
                // save rendering result
                if (!GalSaveSurface2DIB(g_Runtime.target, bmpFileName))
                {
                    GalOutput(GalOutputType_Error|GalOutputType_Console,
                        "*ERROR* Failed to save bmp file: %s\n", bmpFileName);
                    break;
                }
            }
    
            /* next frame */
            s_frameNo++;
    
            return (s_frameNo < g_testObject->frameCount && (!g_UseRange || s_frameNo <= g_Runtime.endFrame));
    
        } while (gcvFALSE);
    
        GalOutput(GalOutputType_Error|GalOutputType_Console,
                        "*ERROR* Rendering failed in frame %d!!!\n", s_frameNo);
        /* stop rendering. */
        return gcvFALSE;
    }
    
    
    /*******************************************************************************
    **
    **  main
    **
    **  Test entry point.
    **
    **  INPUT:
    **
    **      Command lines.
    **
    **  OUTPUT:
    **
    **      Nothing.
    **
    **  RETURN:
    **
    **      int
    **          Exit value.
    */
    int main(int argc, char *argv[])
    {
        int i;
    
        /* Assume failure. */
        int result = -1;
    
        if (argc < 4)
        {
            sysOutput("The parameters are too less!!!");
            PrintUsage();
            return result;
        }
    
        // echo cmd line
        for (i = 0; i < argc; i++)
        {
            sysOutput("%s ", argv[i]);
            if (i == argc - 1)
                sysOutput("\n");
        }
    
        /* default arguements */
        memset(&g_Runtime, 0, sizeof(g_Runtime));
    
        /* target surface. */
        g_Runtime.target    = gcvNULL;
        g_Runtime.width   = 640;
        g_Runtime.height  = 480;
        g_Runtime.format  = gcvSURF_A8R8G8B8;
        g_Runtime.pool  = gcvPOOL_DEFAULT;
    
        g_Runtime.argc      = 0;
        g_Runtime.argv      = g_Argv2Test;
        g_Runtime.saveTarget    = gcvTRUE;
        g_Runtime.noSaveTargetNew = gcvFALSE;
        g_Runtime.cleanTarget = gcvTRUE;
        g_Runtime.createTarget = gcvTRUE;
        g_Runtime.notSupport = gcvFALSE;
        g_Runtime.startFrame = 0;
        g_Runtime.endFrame = 0;
    
        /* check command arguements */
        if (ParseArgs(argc, argv) != 0)
        {
            PrintUsage();
            return 1;
        }
    
        if (!MakeSimpleCaseName(g_simpleCaseName, g_caseName))
        {
            sysOutput("Invalid case name:%s. Should include string "PREFIX"*"SURFFIX"\n", g_caseName);
            return 2;
        }
    
        do
        {
            /* Initialize the test. */
            if (!Initialize())
            {
                if (!g_Runtime.notSupport)
                    sysOutput("Initialize test failed\n");
                else
                    sysOutput("Cannot initialize test because hw feature is not supported.\n");
                result = 0;
                break;
            }
    
            while (Run())
            {
            }
    
            result = 0;
        }
        while (gcvFALSE);
    
        /* Cleanup the test environment. */
        Finalize();
    
        return result;
    }
    
    

  • Thanks. It's really helpful to me.