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
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.
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
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; }