Tool/software: Linux
Hello,
In order to display 1280 * 720 size BMP images on the screen, 2D and 3D GPUs are used for each LCD.
The 3D GPU was more than twice as slow as the 2D GPU, causing problems with screen synchronization.
2D GPU Is 4 milli Second, but 3D GPU Is milli Second.
We are curious.
I expected the 3D GPU to be faster than the 2D GPU.
Are you hit late?
Attach the sample code used for the test.
(2D_galRunTest2.c,3D_kmscube.c,bmp720.bmp )
Attach the sample code used for the test.
(2D_galRunTest2.c,3D_kmscube.c,bmp720.bmp )
/**************************************************************************** * * Copyright (c) 2005 - 2015 by Vivante Corp. All rights reserved. * * The material in this file is confidential and contains trade secrets * of Vivante Corporation. This is proprietary information owned by * Vivante Corporation. No part of this work may be disclosed, * reproduced, copied, transmitted, or used in any way for any purpose, * without the express written permission of Vivante Corporation. * *****************************************************************************/ #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> /* leejoonho : */ #define TIMEDEBUG #ifdef TIMEDEBUG #include <sys/time.h> #endif #ifdef TIMEDEBUG static struct timeval timeStart; static char g_timeBuf[20]; #define DPRINTF(fmt, args...) printf("[%s] :" fmt, GetStartedTime(), ## args) char* GetStartedTime(void) { struct timeval currentTime; int hours, minutes, seconds; int milliseconds; gettimeofday(¤tTime, NULL); if (currentTime.tv_usec < timeStart.tv_usec) { milliseconds = (currentTime.tv_usec - timeStart.tv_usec + 1000000)/1000; currentTime.tv_sec--; } else { milliseconds = (currentTime.tv_usec - timeStart.tv_usec)/1000; } /* Calculate the time */ hours = (currentTime.tv_sec - timeStart.tv_sec)/3600; minutes = (((currentTime.tv_sec - timeStart.tv_sec)/60))%60; seconds = (currentTime.tv_sec - timeStart.tv_sec)%60; memset(g_timeBuf, 0, sizeof(g_timeBuf)); sprintf(g_timeBuf, "%02u:%02u:%02u.%03u", hours, minutes, seconds, milliseconds); return g_timeBuf; } #endif /* TIMEDEBUG */ //#define VIVANTE_DEBUG #define GOOD_RECT(rect) (rect.left < rect.right && rect.top < rect.bottom) /* Version info. */ static const char c_szFrameworkInfo[] = "\tGAL Test Framework Version 3.1 \n"; /* Base objects */ static GalRuntime g_Runtime; #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; typedef struct Test2D { GalTest base; GalRuntime *runtime; // destination surface gcoSURF dstSurf; gceSURF_FORMAT dstFormat; gctUINT dstWidth; gctUINT dstHeight; gctINT dstStride; gctUINT32 dstPhyAddr; gctPOINTER dstLgcAddr; //source surface gcoSURF src1Surf; gceSURF_FORMAT src1Format; gctUINT src1Width; gctUINT src1Height; gctINT src1Stride[3]; gctUINT32 src1PhyAddr[3]; gctPOINTER src1LgcAddr[3]; gcoSURF src2Surf; gceSURF_FORMAT src2Format; gctUINT src2Width; gctUINT src2Height; gctINT src2Stride[3]; gctUINT32 src2PhyAddr[3]; gctPOINTER src2LgcAddr[3]; gctUINT alpha; } Test2D; typedef struct SurfaceGeom { gctINT width; gctINT height; gceSURF_FORMAT format; }SurfaceGeom; Test2D* GalTest2D; static SurfaceGeom dstGeom ={0,}, src1Geom= {0,}, src2Geom= {0,}; static gcsRECT dstrect={0,}, src1rect={0,}, src2rect={0,}, cliprect={0,}, src2auxdstrect={0,}; static gctUINT32 src2Angle = 0; const char *dstFile = NULL, *src1File = NULL, *src2File = NULL; gctBOOL IsFileVimg(const char* szFilename) { gctINT len = strlen(szFilename); return(strcmp(&(szFilename[len-4]), "vimg") == 0); } gctBOOL IsFileRaw(const char* szFilename) { gctINT len = strlen(szFilename); return((strcmp(&(szFilename[len-3]), "raw") == 0) || (strcmp(&(szFilename[len-3]), "yuv") == 0)); } gctBOOL IsFileBmp(const char* szFilename) { gctINT len = strlen(szFilename); return(strcmp(&(szFilename[len-3]), "bmp") == 0); } gctINT GetStride(gctINT width, gceSURF_FORMAT format) { size_t stride; gcsSURF_FORMAT_INFO_PTR info[2]; gcmVERIFY_OK(gcoSURF_QueryFormat(format, info)); stride = ((width + 15) & ~15); switch(format) { case gcvSURF_YUY2: case gcvSURF_UYVY: case gcvSURF_YVYU: case gcvSURF_VYUY: stride *= 2; break; case gcvSURF_YV12: case gcvSURF_I420: case gcvSURF_NV12: case gcvSURF_NV21: case gcvSURF_NV16: case gcvSURF_NV61: break; default: stride *= info[0]->bitsPerPixel / 8; break; } return(stride); } gctUINT GetAddressStrideNum(gceSURF_FORMAT format) { gctUINT numPlanes; switch (format) { case gcvSURF_YUY2: case gcvSURF_UYVY: numPlanes = 1; break; case gcvSURF_I420: case gcvSURF_YV12: numPlanes = 3; break; case gcvSURF_NV16: case gcvSURF_NV12: case gcvSURF_NV61: case gcvSURF_NV21: numPlanes = 2; break; default: numPlanes = 1; } return numPlanes; } gceSTATUS LoadFileToSurface(const char* source, Test2D *t2d) { gcoSURF *surf; const char* file; SurfaceGeom src; gceSTATUS status = gcvSTATUS_OK ; printf("DBG111 : at %s\n", __FUNCTION__); if(!strcmp(source, "src1")) { surf = &t2d->src1Surf; file = src1File; memcpy((void*)&src, (void*)&src1Geom, sizeof(SurfaceGeom)); } else { surf = &t2d->src2Surf; file = src2File; memcpy((void*)&src, (void*)&src2Geom, sizeof(SurfaceGeom)); } printf("DBG222 : file(%s) at %s\n", file, __FUNCTION__); if ( !file ) { status = -1; } else { if(IsFileVimg(file)) status = GalLoadVimgToSurface(file, surf); else if(IsFileBmp(file)){ printf("DBG : after IsFileBmp. at %s\n", __FUNCTION__); *surf = GalLoadDIB2Surface(t2d->runtime->hal, file); if(*surf == NULL) status = -1; } else if(IsFileRaw(file)) { gctUINT stride; if(src.width <=0 || src.height <= 0) { sysOutput("For raw source files Geometry needs to be set. example: -src1 NV12 720x480\n"); return -1; } stride = GetStride(src.width, src.format); status = GalLoadRawToSurface(file, src.width, src.height, stride, src.format, surf); } else { sysOutput("Not a valid type file. Only bmp, raw/yuv or vimg supported\n"); status = -1;; } } printf("DBG33 : at %s\n", __FUNCTION__); return status; } gctBOOL TextToInt(gctINT* val, const char** p, const char end) { gctBOOL success = gcvTRUE; gctINT v = 0; gctBOOL vneg = gcvFALSE; if(**p == '-') { vneg = gcvTRUE; (*p)++; } do { if((**p <'0') || (**p >'9')) { success = gcvFALSE; goto Error; } v = (v * 10) + (**p - '0'); (*p)++; }while(**p != end); *val = vneg ? -v : v; Error: return(success); } gctBOOL TextToValPair(gctINT *val1, gctINT *val2, const char **p, const char sep, const char end) { gctBOOL success; const char* szVals = *p; if(!(success = TextToInt(val1, p, sep))) { sysOutput("Invalid first value of value pair: %s\n", szVals); } else { (*p)++; if(!(success = TextToInt(val2, p, end))) { sysOutput("Invalid second value of value pair: %s\n", szVals); } } return(success); } const char* GetRect(gcsRECT* rect, const char* p) { const char* szErr = 0; if(!TextToValPair(&rect->left, &rect->top, &p, ',', '-')) { szErr = "Invalid upper left coordinate"; goto Error; } if(*p) p++; if(!TextToValPair(&rect->right, &rect->bottom, &p, 'x', '\0')) { szErr = "Invalid size"; goto Error; } Error: return(szErr); } const char* HexToUL(unsigned long *val, const char* p) { const char* szErr = 0; *val = 0; char c = *p; while(c) { if((c >= '0') && (c <= '9')) *val = (*val * 16) + (c - '0'); else if((c >= 'A') && (c <= 'F')) *val = (*val * 16) + (10 + c - 'A'); else if((c >= 'a') && (c <= 'f')) *val = (*val * 16) + (10 + c - 'a'); else { szErr = "Invalid hex value"; break; } p++; c = *p; } return(szErr); } gctBOOL ParseFile(const char** szFile, gctINT argc, const char* argv[], gctINT* arg) { gctBOOL success = gcvFALSE; if((*arg + 1) >= argc) { sysOutput("No filename provided with %s option (ex. %s image.bmp).\n", argv[*arg], argv[*arg]); goto Error; } *szFile = argv[*arg + 1]; sysOutput("%s %s\n", argv[*arg], *szFile); *arg += 2; success = gcvTRUE; Error: return(success); } gctBOOL ParseAlpha(gctINT argc, const char* argv[], gctINT *arg) { gctBOOL success = gcvFALSE; const char* szErr; unsigned long alpha; szErr = HexToUL(&alpha, argv[*arg + 1]); if(szErr) { sysOutput("%s with -alpha option.\n", szErr); goto Error; } if(alpha > 0xFF) { sysOutput("Invalid alpha value provided for -alpha option: %s (ex. -rop 80).\n", argv[*arg + 1]); goto Error; } // GalTest2D->alpha = (unsigned char)alpha; sysOutput("-alpha %02X\n", alpha); *arg += 2; success = gcvTRUE; Error: return(success); } gctBOOL ParseRect(gcsRECT* rect, gctINT argc, const char* argv[], gctINT* arg) { const char* szErr = 0; if((*arg + 1) >= argc) { sysOutput("No rectangle provided with %s option (ex. %s 0,0-640x480)\n", argv[*arg], argv[*arg]); goto Error; } szErr = GetRect(rect, argv[*arg + 1]); if(szErr) { sysOutput("%s with option %s (ex. %s 0,0-640x480)\n", szErr, argv[*arg], argv[*arg]); goto Error; } sysOutput("%s %d,%d-%dx%d\n", argv[*arg], rect->left, rect->top, rect->right, rect->bottom); rect->right += rect->left; rect->bottom += rect->top; *arg += 2; Error: return(szErr == 0); } const char* GetDimensions(gctINT *w, gctINT *h, const char* p) { const char* szErr = 0; gctINT width = 0, height = 0; if(!TextToValPair(&width, &height, &p, 'x', '\0')) { szErr = "Invalid size specified"; goto Error; } if((width <= 0) || (height <= 0)) { szErr = "Invalid surface size"; goto Error; } *w = width; *h = height; Error: return(szErr); } gctBOOL ParseSurf(SurfaceGeom *geom, gctINT argc, const char* argv[], gctINT *arg) { gctBOOL success = gcvFALSE; const char* szErr = NULL; if((*arg + 2) >= argc) { sysOutput("Details not provided with %s option.\n", argv[*arg]); goto Error; } geom->format = GalQueryFormat(argv[*arg + 1]); if(geom->format == gcvSURF_UNKNOWN) { sysOutput("unknown format %s.\n", argv[*arg]); goto Error; } // Next param is dimension // Only calculate dimensions if the next char is a digit. if ( (argv[*arg + 2][0] >= '0') && (argv[*arg + 2][0] <= '9') ) { szErr = GetDimensions(&geom->width, &geom->height, argv[*arg + 2]); if (szErr) { sysOutput("Error '%s' while getting surface dimensions\n",szErr); *arg += 3; success = gcvFALSE; goto Error; } sysOutput("%s %s %dx%d\n", argv[*arg], argv[*arg + 1], geom->width, geom->height); } else { sysOutput("invalid parameter '%s' with option %s.\n", argv[*arg + 2], argv[*arg]); goto Error; } *arg += 3; success = gcvTRUE; Error: return(success); } void Usage(const char* szapp) { sysOutput("USAGE: %s\n", szapp); sysOutput("-dst <format> ###x### \n" " Specify a destination surface format and size.\n" " Destination format is always forced to A8R8G8B8\n" " If not specified 800x480 will be considered\n"); sysOutput("-dstrect ###,###-###x###\n" " Specify a rectangle within the destination surface which receives the BLT.\n" " If not specified dst surface width and height will be considered\n"); sysOutput("-dstfile <file.>bmp\n" " Specify a file into which to save the results. Must be a BMP \n"); sysOutput("-src1 <format> ###x### \n" " Specify a source surface format and size.\n" " Not needed for bmp and vimg files. Required only for raw files\n"); sysOutput("-src1rect ###,###-###x###\n" " Specify a rectangle within the source surface used as the source for the BLT.\n" " If not specified, src1 actual image width and height will be considered\n"); sysOutput("-src1file <file.>bmp|vimg|raw\n" " Specify a file from which the source surface is initialized. The image is\n" " placed in the upper left corner of the source surface and clipped if\n" " necessary.\n"); sysOutput("-alpha <AA>\n" " Specify the global alpha value as a hexadecimal value between 00\n" " (transparent) to FF (opaque).\n"); sysOutput("-src2 <format> ###x### \n" " Specify a source2 surface format and size.\n" " Not needed for bmp and vimg files. Required only for raw files\n"); sysOutput("-src2rect ###,###-###x###\n" " Specify a rectangle within the source2 surface used as the\n" " source2 for the BLT.\n" " If not specified, src2 actual image width and height will be considered\n"); sysOutput("-src2file <file.>|bmp|raw|vimg" " Specify a file from which the source2 surface is initialized. The\n" " image is placed in the upper left corner of the source2 surface and\n" " clipped if necessary.\n"); sysOutput("-src2auxdstrect ###,###-###x###\n" " Specify a destination source2 surface used as the\n" " source2 for the Strectching on src1 background.\n" " If not specified, 0,0-256x256 will be considered\n"); sysOutput("-src2angle ###\n" " Specify orientation of source2 in degrees supported values are 0, 90, 180 and 270.\n"); sysOutput("-blend clear|src1|src2|src1over|src2over|src1in|src2in|src1out|src2out|src1atop|src2atop|xor|plus|remote|global\n" " Specify the type of blend to use. Multiple -blend parameters can be specified.\n"); sysOutput("-cliprect ###,###-###x###\n" " Specify a rectangle which is used to indicate the area in the destination\n" " which is written, and outside of which the destination is not modified.\n"); } gctBOOL ParseCmdLine(gctINT argc, const char* argv[]) { gctBOOL success = gcvFALSE; for(gctINT arg = 1; arg < argc;) { if(!strcmp(argv[arg], "-dst")) { if(!ParseSurf(&dstGeom, argc, argv, &arg)) goto Error; } else if(!strcmp(argv[arg], "-dstfile")) { if(!ParseFile(&dstFile, argc, argv, &arg)) goto Error; } else if(!strcmp(argv[arg], "-dstrect")) { if(!ParseRect(&dstrect, argc, argv, &arg)) goto Error; } else if(!strcmp(argv[arg], "-src1")) { if(!ParseSurf(&src1Geom, argc, argv, &arg)) goto Error; } else if(!strcmp(argv[arg], "-src1rect")) { if(!ParseRect(&src1rect, argc, argv, &arg)) goto Error; } else if(!strcmp(argv[arg], "-src1file")) { if(!ParseFile(&src1File, argc, argv, &arg)) goto Error; } else if(!strcmp(argv[arg], "-src2")) { if(!ParseSurf(&src2Geom, argc, argv, &arg)) goto Error; } else if(!strcmp(argv[arg], "-src2file")) { if(!ParseFile(&src2File, argc, argv, &arg)) goto Error; } else if(!strcmp(argv[arg], "-src2rect")) { if(!ParseRect(&src2rect, argc, argv, &arg)) goto Error; } else if(!strcmp(argv[arg], "-src2angle")) { if(arg + 1 >= argc) { sysOutput("No angle provided with -src2angle option.\n"); goto Error; } src2Angle = atoi(argv[arg + 1]); sysOutput("src2 orientation %d\n", src2Angle); arg += 2; } else if(!strcmp(argv[arg], "-src2auxdstrect")) { if(!ParseRect(&src2auxdstrect, argc, argv, &arg)) goto Error; } else if(!strcmp(argv[arg], "-cliprect")) { if(!ParseRect(&cliprect, argc, argv, &arg)) goto Error; } /////////////////////////////// else if(!strcmp(argv[arg], "-alpha")) { if(!ParseAlpha(argc, argv, &arg)) goto Error; } else { sysOutput("Unrecognized option %s\n", argv[arg]); goto Error; } /////////////////////////////// } success = gcvTRUE; Error: return(success); } static const struct PoolInfo { gctCONST_STRING name; gcePOOL type; } c_PoolInfos[] = { {"DEFAULT", gcvPOOL_DEFAULT}, {"VIRTUAL", gcvPOOL_VIRTUAL}, {"SYSTEM", gcvPOOL_SYSTEM}, }; static void close_fd() { close(g_alloc_fd); g_alloc_fd = -1; } static void* create_drm_buffer(gctUINT width, gctUINT height, gceSURF_FORMAT format, size_t *stride) { /* omapdrm vars */ struct omap_device *dev; struct omap_bo *bo; uint32_t size, flags = 0; void *vaddr = gcvNULL; size_t stride1; /* Vivante DDK vars */ gcsSURF_FORMAT_INFO_PTR info[2]; /* format parameters */ int bpr; //g_alloc_fd = drmOpen("omapdrm", NULL); if(g_alloc_fd == -1) { 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 %d\n", g_alloc_fd); } 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(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. */ stride1 = ((width + 15) & ~15); bpr = ((width + 15) & ~15) *(double) ((double)info[0]->bitsPerPixel / 8); // sysOutput("\tINFO: bytes per row: %d bpp %d\n", bpr, info[0]->bitsPerPixel); size = bpr * ((height + 3) & ~3); switch(format) { case gcvSURF_YUY2: case gcvSURF_UYVY: case gcvSURF_YVYU: case gcvSURF_VYUY: stride1 *= 2; break; case gcvSURF_YV12: case gcvSURF_I420: case gcvSURF_NV12: case gcvSURF_NV21: case gcvSURF_NV16: case gcvSURF_NV61: break; default: stride1 *= info[0]->bitsPerPixel / 8; break; } *stride = stride1; /* 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 */ sysOutput("size = %d stride %d\n", size, stride1); bo = omap_bo_new(dev, size, flags); if (!bo) { sysOutput("*ERROR* Failed to create omap bo\n"); return gcvNULL; } vaddr = omap_bo_map(bo); if (!vaddr) { sysOutput("*ERROR* could not mmap dmabuf - %s\n", strerror(errno)); return gcvNULL; } /* * `omap_bo` might not have backing pages at this point, make sure you got * them by writing into it. */ memset(vaddr, 0, size); return vaddr; } /* * Name: Initialize() * Parameters: case_name, the name of the dll of the test case. */ static gctBOOL Initialize() { // PGalCreateTestObject createTestObject; gceSTATUS status; /* 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; gceHARDWARE_TYPE type; unsigned long phys = ~0U; vaddr = create_drm_buffer(g_Runtime.width, g_Runtime.height, g_Runtime.format, &stride); 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; } /* 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; } 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 GalTest2D = (Test2D*)malloc(sizeof(Test2D)); if(!GalTest2D){ sysOutput("Error: Failed to allocate Test2D\n"); return gcvFALSE; } GalTest2D->runtime = &g_Runtime; GalTest2D->dstSurf = g_Runtime.target; GalTest2D->dstFormat = g_Runtime.format; GalTest2D->dstWidth = 0; GalTest2D->dstHeight = 0; GalTest2D->dstStride = 0; GalTest2D->dstPhyAddr = 0; GalTest2D->dstLgcAddr = 0; GalTest2D->src1Surf = gcvNULL; GalTest2D->src1Width = 0; GalTest2D->src1Height = 0; GalTest2D->src1Stride[0] = 0; GalTest2D->src1Stride[1] = 0; GalTest2D->src1Stride[2] = 0; GalTest2D->src1PhyAddr[0] = 0; GalTest2D->src1LgcAddr[0] = 0; GalTest2D->src1PhyAddr[1] = 0; GalTest2D->src1LgcAddr[1] = 0; GalTest2D->src1PhyAddr[2] = 0; GalTest2D->src1LgcAddr[2] = 0; GalTest2D->src1Format = gcvSURF_UNKNOWN; GalTest2D->src2Surf = gcvNULL; GalTest2D->src2Width = 0; GalTest2D->src2Height = 0; GalTest2D->src2Stride[0] = 0; GalTest2D->src2Stride[1] = 0; GalTest2D->src2Stride[2] = 0; GalTest2D->src2PhyAddr[0] = 0; GalTest2D->src2LgcAddr[0] = 0; GalTest2D->src2PhyAddr[1] = 0; GalTest2D->src2LgcAddr[1] = 0; GalTest2D->src2PhyAddr[2] = 0; GalTest2D->src2LgcAddr[2] = 0; GalTest2D->src2Format = gcvSURF_UNKNOWN; gcoSURF_GetAlignedSize(GalTest2D->dstSurf, &GalTest2D->dstWidth, &GalTest2D->dstHeight, &GalTest2D->dstStride); gcoSURF_Lock(GalTest2D->dstSurf, &GalTest2D->dstPhyAddr, &GalTest2D->dstLgcAddr); 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_Runtime.hal != gcvNULL) { gcoHAL_Commit(g_Runtime.hal, gcvTRUE); } if(GalTest2D->src1Surf != NULL) { if(GalTest2D->src1LgcAddr) gcoSURF_Unlock(GalTest2D->src1Surf, GalTest2D->src1LgcAddr); GalTest2D->src1LgcAddr[0] = NULL; GalTest2D->src1LgcAddr[1] = NULL; GalTest2D->src1LgcAddr[2] = NULL; gcoSURF_Destroy(GalTest2D->src1Surf); } if(GalTest2D->src2Surf != NULL) { if(GalTest2D->src2LgcAddr) gcoSURF_Unlock(GalTest2D->src2Surf, GalTest2D->src2LgcAddr); GalTest2D->src2LgcAddr[0] = NULL; GalTest2D->src2LgcAddr[1] = NULL; GalTest2D->src2LgcAddr[2] = NULL; gcoSURF_Destroy(GalTest2D->src2Surf); } 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_fd(); #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(); free(GalTest2D); } static gctBOOL Render(Test2D *t2d) { gctUINT8 horKernel = 1, verKernel = 1; gcsRECT srcRect; gco2D egn2D = t2d->runtime->engine2d; gceSTATUS status; //size_t stride; //void* VirtAddr; //gceHARDWARE_TYPE type; //unsigned long phys = ~0U; gcsRECT srcRect2 ; gctUINT numPlanes; gctINT temp; gceSURF_ROTATION srcRotation = gcvSURF_0_DEGREE, dstRotation = gcvSURF_0_DEGREE; gcsRECT dstRect = {0, 0, t2d->dstWidth, t2d->dstHeight}; gcsRECT clipRect = {0, 0, t2d->dstWidth , t2d->dstHeight }; Gal2DCleanSurface(g_Runtime.hal, g_Runtime.target, COLOR_ARGB8(0x00, 0x00, 0x00, 0x00)); if ( LoadFileToSurface("src1", t2d) == 0 ) { printf("DBG : src1 processing. at %s\n", __FUNCTION__); gcmONERROR(gcoSURF_GetAlignedSize(t2d->src1Surf, gcvNULL, gcvNULL, t2d->src1Stride)); gcmONERROR(gcoSURF_GetSize(t2d->src1Surf, &t2d->src1Width, &t2d->src1Height, gcvNULL)); gcmONERROR(gcoSURF_GetFormat(t2d->src1Surf, gcvNULL, &t2d->src1Format)); gcmONERROR(gcoSURF_Lock(t2d->src1Surf, t2d->src1PhyAddr, t2d->src1LgcAddr)); if(GOOD_RECT(src1rect)) { srcRect.left = src1rect.left; srcRect.top = src1rect.top; srcRect.right = src1rect.right; srcRect.bottom = src1rect.bottom; } else { srcRect.left = 0; srcRect.top = 0; srcRect.right = t2d->src1Width; srcRect.bottom = t2d->src1Height; } if(GOOD_RECT(dstrect)){ dstRect.left = dstrect.left; dstRect.top = dstrect.top; dstRect.right = dstrect.right; dstRect.bottom = dstrect.bottom; } // set clippint rect gcmONERROR(gco2D_SetClipping(egn2D, &dstRect)); // set kernel size gcmONERROR(gco2D_SetKernelSize(egn2D, horKernel, verKernel)); //printf("DBG : before gcoSURF_FilterBlit. at %s\n", __FUNCTION__); gcmONERROR(gcoSURF_FilterBlit(t2d->src1Surf, t2d->dstSurf, &srcRect, &dstRect, &dstRect)); //printf("DBG : after gcoSURF_FilterBlit. at %s\n", __FUNCTION__); //DPRINTF("after gcoSURF_FilterBlit.\n"); } if(src2File) { printf("src2 load.\n"); LoadFileToSurface("src2", t2d); #ifdef TIMEDEBUG gettimeofday(&timeStart, NULL); #endif DPRINTF("before alphablending.\n"); gcmONERROR(gcoSURF_GetAlignedSize(t2d->src2Surf, gcvNULL, gcvNULL, t2d->src2Stride)); gcmONERROR(gcoSURF_GetSize(t2d->src2Surf, &t2d->src2Width, &t2d->src2Height, gcvNULL)); printf("DBG : src2Width(%d) src2Height(%d) at %s\n", t2d->src2Width, t2d->src2Height, __FUNCTION__); gcmONERROR(gcoSURF_GetFormat(t2d->src2Surf, gcvNULL, &t2d->src2Format)); gcmONERROR(gcoSURF_Lock(t2d->src2Surf, t2d->src2PhyAddr, t2d->src2LgcAddr)); if(src2Angle != 0 && src2Angle != 90 && src2Angle != 180 && src2Angle != 270) src2Angle = 0; if(GOOD_RECT(src2rect)){ srcRect2.left = src2rect.left; srcRect2.top = src2rect.top; srcRect2.right = src2rect.right; srcRect2.bottom = src2rect.bottom; } else { srcRect2.left = 0; srcRect2.top = 0; srcRect2.right = t2d->src2Width; srcRect2.bottom = t2d->src2Height; } if(GOOD_RECT(src2auxdstrect)){ dstRect.left = src2auxdstrect.left; dstRect.top = src2auxdstrect.top; dstRect.right = src2auxdstrect.right; dstRect.bottom = src2auxdstrect.bottom; } else { dstRect.left= 0; dstRect.top = 0; #if 1 dstRect.right = g_Runtime.width; dstRect.bottom = g_Runtime.height; #else /* ���ĺ���������� �۰� �ϰ� ���� */ dstRect.right = 256; dstRect.bottom = 256; #endif } if(src2Angle == 180) { gcmONERROR(gco2D_SetBitBlitMirror(egn2D, gcvTRUE, gcvTRUE)); } else if(src2Angle == 90) { dstRotation = gcvSURF_90_DEGREE; temp = clipRect.right; clipRect.right = clipRect.bottom; clipRect.bottom = temp; } else if(src2Angle == 270) { srcRotation = gcvSURF_90_DEGREE; temp = srcRect2.right; srcRect2.right = srcRect2.bottom; srcRect2.bottom = temp; } numPlanes = GetAddressStrideNum(t2d->src2Format); gcmONERROR(gco2D_SetGenericSource(egn2D, t2d->src2PhyAddr, numPlanes, (gctUINT*)t2d->src2Stride, numPlanes, gcvLINEAR, t2d->src2Format, srcRotation, t2d->src2Width, t2d->src2Height)); gcmONERROR(gco2D_SetSource(egn2D, &srcRect2)); gcmONERROR(gco2D_SetTarget(egn2D, t2d->dstPhyAddr, t2d->dstStride, dstRotation, t2d->dstWidth)); gcmONERROR(gco2D_SetClipping(egn2D, &clipRect)); #if 1 gcmONERROR(gco2D_SetSourceGlobalColorAdvanced(egn2D, 0x80 << 24)); gcmONERROR(gco2D_SetTargetGlobalColorAdvanced(egn2D, 0x80 << 24)); gcmONERROR(gco2D_EnableAlphaBlendAdvanced(egn2D, gcvSURF_PIXEL_ALPHA_STRAIGHT, gcvSURF_PIXEL_ALPHA_STRAIGHT, gcvSURF_GLOBAL_ALPHA_ON, gcvSURF_GLOBAL_ALPHA_ON, gcvSURF_BLEND_STRAIGHT, gcvSURF_BLEND_STRAIGHT)); #endif // gcmONERROR(gco2D_Blit(egn2D, 1, &dstRect, 0xCC, 0xCC, t2d->dstFormat)); //stretch and blit gcmONERROR(gco2D_SetStretchRectFactors( egn2D, &srcRect2, &dstRect )); gcmONERROR(gco2D_StretchBlit( egn2D, 1, &dstRect, 0xCC, 0xCC, t2d->dstFormat )); gcmONERROR(gco2D_SetBitBlitMirror(egn2D, gcvFALSE, gcvFALSE)); gcmONERROR(gco2D_DisableAlphaBlend(egn2D)); } #if 0 gcmONERROR(gco2D_Flush(egn2D)); #else printf("DBG : skip flush.. at %s\n", __FUNCTION__); #endif gcmONERROR(gcoHAL_Commit(t2d->runtime->hal, gcvTRUE)); DPRINTF("after gcoHAL_Commit.\n"); printf("DBG : width(%d) height(%d) stride(%d) at %s\n", GalTest2D->dstWidth, GalTest2D->dstHeight, GalTest2D->dstStride, __FUNCTION__); GalSaveDIB(GalTest2D->dstLgcAddr, gcvSURF_A8R8G8B8, GalTest2D->dstStride, GalTest2D->dstWidth, GalTest2D->dstHeight, "/tmp/test.bmp"); return gcvTRUE; OnError: GalOutput(GalOutputType_Error | GalOutputType_Console, "%s(%d) failed:%s\n",__FUNCTION__, __LINE__, gcoOS_DebugStatus2Name(status)); return gcvFALSE; } /* * Name: Run() * Returns: None. * Parameters: None. */ /******************************************************************************* ** ** main ** ** Test entry point. ** ** INPUT: ** ** Command lines. ** ** OUTPUT: ** ** Nothing. ** ** RETURN: ** ** int ** Exit value. */ int main(int argc, const char *argv[]) { /* Assume failure. */ int result = -1; const char* bmpFileName ; if(argc < 2){ Usage(argv[0]); return 1; } if(!ParseCmdLine(argc, argv)) return 1; bmpFileName = dstFile; /* default arguements */ memset(&g_Runtime, 0, sizeof(g_Runtime)); /* target surface. */ g_Runtime.target = gcvNULL; if(dstGeom.width != 0 && dstGeom.height != 0){ g_Runtime.width = dstGeom.width; g_Runtime.height = dstGeom.height; } else { g_Runtime.width = 800; g_Runtime.height = 480; } printf("DBG : width(%d) height(%d) at %s\n", g_Runtime.width, g_Runtime.height, __FUNCTION__); g_Runtime.format = gcvSURF_A8R8G8B8; //g_Runtime.format = gcvSURF_NV12; //printf("DBG : force gcvSURF_NV12. at %s\n", __FUNCTION__); g_Runtime.pool = gcvPOOL_DEFAULT; g_Runtime.argc = 0; g_Runtime.argv = g_Argv2Test; g_Runtime.saveTarget = gcvTRUE; g_Runtime.noSaveTargetNew = gcvFALSE; // error //g_Runtime.cleanTarget = gcvTRUE; g_Runtime.createTarget = gcvTRUE; // error //g_Runtime.notSupport = gcvFALSE; 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; } //sleep(1); //DPRINTF("before Render.\n"); Render(GalTest2D); //DPRINTF("after Render.\n"); if(bmpFileName) GalSaveSurface2DIB(g_Runtime.target, bmpFileName); result = 0; } while (gcvFALSE); /* Cleanup the test environment. */ Finalize(); sysOutput("Successfully completed\n"); return result; }
/* * Copyright (c) 2012 Arvin Schnell <arvin.schnell@gmail.com> * Copyright (c) 2012 Rob Clark <rob@ti.com> * Copyright (c) 2013 Anand Balagopalakrishnan <anandb@ti.com> * * 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 * THE AUTHORS OR COPYRIGHT HOLDERS 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. */ /* Based on a egl cube test app originally written by Arvin Schnell */ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <signal.h> #include <xf86drm.h> #include <xf86drmMode.h> #include <gbm.h> #include "esUtil.h" #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) /* #define PBUFFDEF */ #define FBODEF #define MAX_DISPLAYS (4) uint8_t DISP_ID = 0; uint8_t all_display = 0; int8_t connector_id = -1; static struct { EGLDisplay display; EGLConfig config; EGLContext context; EGLSurface surface; GLuint program; GLuint program_texture; GLint samplerLoc; GLint modelviewmatrix, modelviewprojectionmatrix, normalmatrix; GLuint vbo; GLuint positionsoffset, colorsoffset, normalsoffset; GLuint vertex_shader, fragment_shader; } gl; static struct { struct gbm_device *dev; struct gbm_surface *surface; } gbm; static struct { int fd; uint32_t ndisp; uint32_t crtc_id[MAX_DISPLAYS]; uint32_t connector_id[MAX_DISPLAYS]; uint32_t resource_id; uint32_t encoder[MAX_DISPLAYS]; drmModeModeInfo *mode[MAX_DISPLAYS]; drmModeConnector *connectors[MAX_DISPLAYS]; } drm; struct drm_fb { struct gbm_bo *bo; uint32_t fb_id; }; struct omap_bo* bo_test; unsigned char* lpOut; static unsigned long long GetUSTime() { struct timeval now; unsigned long long ustime; gettimeofday( &now, NULL ); ustime = (unsigned long long)now.tv_sec * 1000000LL + (unsigned long long)now.tv_usec; return ustime; } static int init_drm(void) { static const char *modules[] = { "omapdrm", "i915", "radeon", "nouveau", "vmwgfx", "exynos" }; drmModeRes *resources; drmModeConnector *connector = NULL; drmModeEncoder *encoder = NULL; int i, j; uint32_t maxRes, curRes; printf("[dbg:%s] Load module()\n", __func__); for (i = 0; i < ARRAY_SIZE(modules); i++) { printf("trying to load module %s...", modules[i]); // drm.fd = drmOpen(modules[i], NULL); drm.fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC); if (drm.fd < 0) { printf("failed.\n"); } else { printf("success.\n"); break; } } if (drm.fd < 0) { printf("could not open drm device\n"); return -1; } resources = drmModeGetResources(drm.fd); if (!resources) { printf("drmModeGetResources failed: %s\n", strerror(errno)); return -1; } drm.resource_id = (uint32_t) resources; /* find a connected connector: */ for (i = 0; i < resources->count_connectors; i++) { connector = drmModeGetConnector(drm.fd, resources->connectors[i]); if (connector->connection == DRM_MODE_CONNECTED) { /* choose the first supported mode */ drm.mode[drm.ndisp] = &connector->modes[0]; drm.connector_id[drm.ndisp] = connector->connector_id; for (j=0; j<resources->count_encoders; j++) { encoder = drmModeGetEncoder(drm.fd, resources->encoders[j]); if (encoder->encoder_id == connector->encoder_id) break; drmModeFreeEncoder(encoder); encoder = NULL; } if (!encoder) { printf("no encoder!\n"); return -1; } drm.encoder[drm.ndisp] = (uint32_t) encoder; drm.crtc_id[drm.ndisp] = encoder->crtc_id; drm.connectors[drm.ndisp] = connector; printf("### Display [%d]: CRTC = %d, Connector = %d\n", drm.ndisp, drm.crtc_id[drm.ndisp], drm.connector_id[drm.ndisp]); printf("\tMode chosen [%s] : Clock => %d, Vertical refresh => %d, Type => %d\n", drm.mode[drm.ndisp]->name, drm.mode[drm.ndisp]->clock, drm.mode[drm.ndisp]->vrefresh, drm.mode[drm.ndisp]->type); printf("\tHorizontal => %d, %d, %d, %d, %d\n", drm.mode[drm.ndisp]->hdisplay, drm.mode[drm.ndisp]->hsync_start, drm.mode[drm.ndisp]->hsync_end, drm.mode[drm.ndisp]->htotal, drm.mode[drm.ndisp]->hskew); printf("\tVertical => %d, %d, %d, %d, %d\n", drm.mode[drm.ndisp]->vdisplay, drm.mode[drm.ndisp]->vsync_start, drm.mode[drm.ndisp]->vsync_end, drm.mode[drm.ndisp]->vtotal, drm.mode[drm.ndisp]->vscan); /* If a connector_id is specified, use the corresponding display */ if ((connector_id != -1) && (connector_id == drm.connector_id[drm.ndisp])) { DISP_ID = drm.ndisp; } /* If all displays are enabled, choose the connector with maximum * resolution as the primary display */ if (all_display) { maxRes = drm.mode[DISP_ID]->vdisplay * drm.mode[DISP_ID]->hdisplay; curRes = drm.mode[drm.ndisp]->vdisplay * drm.mode[drm.ndisp]->hdisplay; if (curRes > maxRes) { DISP_ID = drm.ndisp; } } drm.ndisp++; } else { drmModeFreeConnector(connector); } } if (drm.ndisp == 0) { /* we could be fancy and listen for hotplug events and wait for * a connector.. */ printf("no connected connector!\n"); return -1; } return 0; } static int init_gbm(void) { printf("[dbg:%s] gbm_create_device()\n", __func__); gbm.dev = gbm_create_device(drm.fd); gbm.surface = gbm_surface_create(gbm.dev, drm.mode[DISP_ID]->hdisplay, drm.mode[DISP_ID]->vdisplay, GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING ); if (!gbm.surface) { printf("failed to create gbm surface\n"); return -1; } return 0; } static int init_gl(void) { GLchar* vShaderStr = "attribute vec4 vPosition; \n" "attribute vec4 aColor; \n" "varying vec4 vColor; \n" "void main() \n" "{ \n" " vColor = aColor; \n" " gl_Position = vPosition; \n" "} \n"; GLchar* fShaderStr = "precision mediump float; \n" "varying vec4 vColor; \n" "void main() \n" "{ \n" " gl_FragColor = vColor; \n" "} \n"; //======================================================= GLchar* vShaderStr_1 = "attribute vec4 vPosition; \n" "attribute vec2 a_texCoord; \n" "varying vec2 v_texCoord; \n" "void main() \n" "{ \n" " v_texCoord = a_texCoord; \n" " gl_Position = vPosition; \n" "} \n"; GLchar* fShaderStr_1 = "precision mediump float; \n" "uniform sampler2D s_texture; \n" "varying vec2 v_texCoord; \n" "void main() \n" "{ \n" " gl_FragColor = texture2D(s_texture, v_texCoord);\n" "} \n"; static const EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; #ifdef PBUFFDEF static const EGLint config_attribs[] = { EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_RED_SIZE, 5, EGL_GREEN_SIZE, 6, EGL_BLUE_SIZE, 5, EGL_DEPTH_SIZE, 1, EGL_NONE, }; static const EGLint config_pb_attribs[] = { EGL_WIDTH, 1920, EGL_HEIGHT, 1080, EGL_LARGEST_PBUFFER, EGL_TRUE, EGL_NONE, }; #else static const EGLint config_attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BUFFER_SIZE, 32, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE }; #endif int major, minor, n; gl.display = eglGetDisplay(gbm.dev); if (!eglInitialize(gl.display, &major, &minor)) { printf("failed to initialize\n"); return -1; } if (!eglBindAPI(EGL_OPENGL_ES_API)) { printf("failed to bind api EGL_OPENGL_ES_API\n"); return -1; } if (!eglChooseConfig(gl.display, config_attribs, &gl.config, 1, &n) || n != 1) { printf("failed to choose config: %d\n", n); return -1; } gl.context = eglCreateContext(gl.display, gl.config, EGL_NO_CONTEXT, context_attribs); if (gl.context == NULL) { printf("failed to create context\n"); return -1; } #ifdef PBUFFDEF gl.surface = eglCreatePbufferSurface(gl.display, gl.config, config_pb_attribs); if (gl.surface == EGL_NO_SURFACE) { printf("failed to create egl surface\n"); return -1; } #else gl.surface = eglCreateWindowSurface(gl.display, gl.config, gbm.surface, NULL); if (gl.surface == EGL_NO_SURFACE) { printf("failed to create egl surface\n"); return -1; } #endif eglMakeCurrent(gl.display, gl.surface, gl.surface, gl.context); GLint compiled = 0; GLint logLen = 0; GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShader, 1, &vShaderStr, NULL); glCompileShader(vertexShader); glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &compiled); if (!compiled) { printf("[dbg:%s] vertex compilation failed.\n", __func__); glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &logLen); if (logLen > 1) { GLchar* log = malloc(sizeof(char) * logLen); glGetProgramInfoLog(vertexShader, logLen, NULL, log); printf("[err:%s] %s\n", __func__, log+8); free(log); } glDeleteShader(vertexShader); return -1; } GLuint fragShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragShader, 1, &fShaderStr, NULL); glCompileShader(fragShader); glGetShaderiv(fragShader, GL_COMPILE_STATUS, &compiled); if (!compiled) { printf("[dbg:%s] frag compilation failed.\n", __func__); glDeleteShader(fragShader); return -1; } GLuint program = glCreateProgram(); if (!program) { printf("[dbg:%s] create program failed.\n", __func__); return -1; } glAttachShader(program, vertexShader); glAttachShader(program, fragShader); glBindAttribLocation(program, 0, "aColor"); glBindAttribLocation(program, 1, "vPosition"); glLinkProgram(program); GLint linked; glGetProgramiv(program, GL_LINK_STATUS, &linked); if (!linked) { GLint infoLen = 0; glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen); if (infoLen > 1) { char* infoLog = malloc(sizeof(char) * infoLen); glGetProgramInfoLog(program, infoLen, NULL, infoLog); printf("[dbg:%s] linking program failed:\n%s\n", __func__, infoLog); free(infoLog); } glDeleteProgram(program); return -1; } gl.program = program; GLuint vertexShader_1 = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShader_1, 1, &vShaderStr_1, NULL); glCompileShader(vertexShader_1); glGetShaderiv(vertexShader_1, GL_COMPILE_STATUS, &compiled); if (!compiled) { printf("[dbg:%s] vertex compilation failed.\n", __func__); glGetShaderiv(vertexShader_1, GL_INFO_LOG_LENGTH, &logLen); if (logLen > 1) { GLchar* log = malloc(sizeof(char) * logLen); glGetProgramInfoLog(vertexShader_1, logLen, NULL, log); printf("[err:%s] %s\n", __func__, log+8); free(log); } glDeleteShader(vertexShader_1); return -1; } GLuint fragShader_1 = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragShader_1, 1, &fShaderStr_1, NULL); glCompileShader(fragShader_1); glGetShaderiv(fragShader_1, GL_COMPILE_STATUS, &compiled); if (!compiled) { printf("[dbg:%s] frag compilation failed.\n", __func__); glDeleteShader(fragShader_1); return -1; } program = glCreateProgram(); if (!program) { printf("[dbg:%s] create program failed.\n", __func__); return -1; } glAttachShader(program, vertexShader_1); glAttachShader(program, fragShader_1); glBindAttribLocation(program, 0, "vPosition"); glBindAttribLocation(program, 1, "a_texCoord"); glLinkProgram(program); glGetProgramiv(program, GL_LINK_STATUS, &linked); if (!linked) { GLint infoLen = 0; glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen); if (infoLen > 1) { char* infoLog = malloc(sizeof(char) * infoLen); glGetProgramInfoLog(program, infoLen, NULL, infoLog); printf("[dbg:%s] linking program failed:\n%s\n", __func__, infoLog); free(infoLog); } glDeleteProgram(program); return -1; } gl.program_texture = program; gl.samplerLoc = glGetUniformLocation(gl.program_texture, "s_texture"); glEnable(GL_BLEND); glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glClearColor(1.0, 1.0, 1.0, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); return 0; } static void exit_gbm(void) { gbm_surface_destroy(gbm.surface); gbm_device_destroy(gbm.dev); return; } static void exit_gl(void) { glDeleteProgram(gl.program); glDeleteBuffers(1, &gl.vbo); glDeleteShader(gl.fragment_shader); glDeleteShader(gl.vertex_shader); eglDestroySurface(gl.display, gl.surface); eglDestroyContext(gl.display, gl.context); eglTerminate(gl.display); return; } static void exit_drm(void) { drmModeRes *resources; int i; resources = (drmModeRes *)drm.resource_id; for (i = 0; i < resources->count_connectors; i++) { drmModeFreeEncoder(drm.encoder[i]); drmModeFreeConnector(drm.connectors[i]); } drmModeFreeResources(drm.resource_id); drmClose(drm.fd); return; } void cleanup_kmscube(void) { exit_gl(); exit_gbm(); exit_drm(); printf("Cleanup of GL, GBM and DRM completed\n"); return; } static void draw(uint32_t i) { static int cnt = 0; // vPosition static const GLfloat vVertices_2[] = { -1.0, -1.0, 0, 1.0, -1.0, 0, -1.0, 1.0, 0, 1.0, 1.0, 0}; // a_texCoord static const GLfloat vVertices_3[] = { 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0}; static const GLfloat vVertices_4[] = { 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0 }; int width = drm.mode[DISP_ID]->hdisplay; int height = drm.mode[DISP_ID]->vdisplay; glDisable(GL_DEPTH_TEST); #ifdef FBODEF GLuint tb[10]; for (int i = 0; i < 2; i++) { glGenTextures(1, &tb[i]); //http://blog.naver.com/mywjdp/220802452130 glBindTexture(GL_TEXTURE_2D, tb[i]); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); unsigned long long prev = GetUSTime(); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8_OES, 1280, 720, 0, GL_RGBA, GL_UNSIGNED_BYTE, lpOut); printf("[dbg:%s] glTexImage2D elapsed time[%d]: %llu\n", __func__, i, GetUSTime() - prev); } glBindTexture(GL_TEXTURE_2D, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUseProgram(gl.program_texture); for (int i = 0; i < 2; i++) { glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vVertices_2); glEnableVertexAttribArray(0); if ( i & 1 ) { glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, vVertices_3); glEnableVertexAttribArray(1); } else { glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, vVertices_4); glEnableVertexAttribArray(1); } /* printf("[dbg:%s] glActiveTexture(%d) \n", __func__, i); */ glActiveTexture(GL_TEXTURE0 + i); glBindTexture(GL_TEXTURE_2D, tb[i]); glUniform1i(gl.samplerLoc, i); unsigned long long prev = GetUSTime(); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); printf("[dbg:%s] Blend elapsed time[%d]: %llu\n", __func__, i, GetUSTime() - prev); } #endif } static void drm_fb_destroy_callback(struct gbm_bo *bo, void *data) { struct drm_fb *fb = data; struct gbm_device *gbm = gbm_bo_get_device(bo); if (fb->fb_id) { drmModeRmFB(drm.fd, fb->fb_id); } free(fb); } static struct drm_fb * drm_fb_get_from_bo(struct gbm_bo *bo) { struct drm_fb *fb = gbm_bo_get_user_data(bo); uint32_t width, height, stride, handle; int ret; if (fb) { return fb; } fb = calloc(1, sizeof *fb); fb->bo = bo; width = gbm_bo_get_width(bo); height = gbm_bo_get_height(bo); stride = gbm_bo_get_stride(bo); handle = gbm_bo_get_handle(bo).u32; ret = drmModeAddFB(drm.fd, width, height, 24, 32, stride, handle, &fb->fb_id); if (ret) { printf("failed to create fb: %s\n", strerror(errno)); free(fb); return NULL; } gbm_bo_set_user_data(bo, fb, drm_fb_destroy_callback); return fb; } static void page_flip_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data) { int *waiting_for_flip = data; *waiting_for_flip = 0; } void print_usage() { printf("Usage : kmscube <options>\n"); printf("\t-h : Help\n"); printf("\t-a : Enable all displays\n"); printf("\t-c <id> : Display using connector_id [if not specified, use the first connected connector]\n"); printf("\t-n <number> (optional): Number of frames to render\n"); } int kms_signalhandler(int signum) { switch(signum) { case SIGINT: case SIGTERM: /* Allow the pending page flip requests to be completed before * the teardown sequence */ sleep(1); printf("Handling signal number = %d\n", signum); cleanup_kmscube(); break; default: printf("Unknown signal\n"); break; } exit(1); } #pragma pack(1) typedef struct tagBMP_FILEHEADER { unsigned short bmpType; //0x00 unsigned long dwSize; //0x02 unsigned long dwRev0; //0x06 unsigned long dwDataOffset; //0x0a } BMP_FILEHEADER, *LPBMP_FILEHEADER; typedef struct tagBMP_INFOHEADER { unsigned long headerSize; //0x0e signed long width; //0x12 signed long height; //0x16 unsigned short planes; //0x1a unsigned short bitsPerPixel; //0x1c unsigned long compression; //0x1e unsigned long sizeOfBitmap; //0x22 signed long horzResolution; //0x26 signed long vertResolution; //0x2a unsigned long colorsUsed; //0x2e unsigned long colorsImportant; //0x32 } BMP_INFOHEADER, *LPBMP_INFOHEADER; #pragma pack() int LoadSpriteData( unsigned char* lpBuf, unsigned char* lpOutAdd ) { printf("[dbg:%s] lpIn: %p, lpOut: %p\n", __func__, lpBuf, lpOutAdd); printf("[dbg:%s] clorsImportant: %p\n", __func__, (unsigned char*)&((LPBMP_INFOHEADER)0x00)->colorsImportant + 0x0e); int Ret = 0; LPBMP_FILEHEADER lpFileHeader = (LPBMP_FILEHEADER)lpBuf; LPBMP_INFOHEADER lpInfoHeader = (LPBMP_INFOHEADER)(lpBuf + sizeof(BMP_FILEHEADER)); unsigned char* lpTmp = lpBuf + lpFileHeader->dwDataOffset; printf("[dbg:%s] Data: %p\n", __func__, lpTmp); printf("[dbg:%s] [%d x %d]\n", __func__, lpFileHeader->dwSize, lpInfoHeader->bitsPerPixel); int xcou; int Width = 1280; int Height = 720; unsigned char* lpDataAdd = lpTmp + Width * (Height - 1) * 4; printf("[dbg:%s] lpDataAdd: %p\n", __func__, lpDataAdd); while ( Height-- ) { for ( xcou = 0; xcou < Width; xcou++ ) { *lpOutAdd++ = lpDataAdd[3]; // Red *lpOutAdd++ = lpDataAdd[2]; // Green *lpOutAdd++ = lpDataAdd[1]; // Blue *lpOutAdd++ = lpDataAdd[0]; // Alpha lpDataAdd += 4; } lpDataAdd -= (Width * 2) * 4; } Ret = 1; return Ret; } int main(int argc, char *argv[]) { fd_set fds; drmEventContext evctx = { .version = DRM_EVENT_CONTEXT_VERSION, .page_flip_handler = page_flip_handler, }; struct gbm_bo *bo; struct drm_fb *fb; uint32_t i = 0; int ret; int opt; int frame_count = -1; printf("[dbg:%s] init_drm()\n", __func__); ret = init_drm(); printf("### Primary display => ConnectorId = %d, Resolution = %dx%d\n", drm.connector_id[DISP_ID], drm.mode[DISP_ID]->hdisplay, drm.mode[DISP_ID]->vdisplay); FD_ZERO(&fds); FD_SET(drm.fd, &fds); printf("[dbg:%s] init_gbm()\n", __func__); ret = init_gbm(); if (ret) { printf("failed to initialize GBM\n"); return ret; } printf("[dbg:%s] init_gl()\n", __func__); ret = init_gl(); if (ret) { printf("failed to initialize EGL\n"); return ret; } printf("[dbg:%s] Init screen\n", __func__ ); /* clear the color buffer */ /* glClearColor(0.0, 0.0, 0.0, 0.0); */ /* glClear(GL_COLOR_BUFFER_BIT); */ eglSwapBuffers(gl.display, gl.surface); bo = gbm_surface_lock_front_buffer(gbm.surface); fb = drm_fb_get_from_bo(bo); printf("[dbg:%s] drmModeSetCrtc()\n", __func__); /* set mode: */ if (all_display) { for (i=0; i<drm.ndisp; i++) { ret = drmModeSetCrtc(drm.fd, drm.crtc_id[i], fb->fb_id, 0, 0, &drm.connector_id[i], 1, drm.mode[i]); if (ret) { printf("display %d failed to set mode: %s\n", i, strerror(errno)); return ret; } } } else { ret = drmModeSetCrtc(drm.fd, drm.crtc_id[DISP_ID], fb->fb_id, 0, 0, &drm.connector_id[DISP_ID], 1, drm.mode[DISP_ID]); if (ret) { printf("display %d failed to set mode: %s\n", DISP_ID, strerror(errno)); return ret; } } // bmp load bo_test = omap_bo_new(omap_device_new(drm.fd), 1280 * 720 * 4, 3); printf("omap_bo_new\n"); lpOut = omap_bo_map(bo_test); printf("lpOut: %p\n", lpOut); printf("omap_bo_map\n"); FILE* lpFile; lpFile = fopen("/home/root/bmp720.bmp", "r"); fseek(lpFile, 0, SEEK_END); int FileSize = ftell(lpFile); unsigned char* lpBuf = (unsigned char*)malloc(FileSize); fseek(lpFile, 0, SEEK_SET); fread(lpBuf, FileSize, 1, lpFile); printf("lpIn: %p\n", lpBuf); fclose(lpFile); LoadSpriteData(lpBuf, lpOut); printf("LoadSpriteData\n"); int done = 0; while (frame_count != 0) { struct gbm_bo *next_bo; int waiting_for_flip = 1; if (done == 1) { printf("Exit Sleep 10 sec \n"); sleep(10); break; } printf("[dbg:%s] draw()\n", __func__); draw(i++); done = 1; eglSwapBuffers(gl.display, gl.surface); next_bo = gbm_surface_lock_front_buffer(gbm.surface); fb = drm_fb_get_from_bo(next_bo); /* Here you could also update drm plane layers if you want hw composition */ ret = drmModePageFlip(drm.fd, drm.crtc_id[DISP_ID], fb->fb_id, DRM_MODE_PAGE_FLIP_EVENT, &waiting_for_flip); if (ret) { printf("failed to queue page flip: %s\n", strerror(errno)); return -1; } while (waiting_for_flip) { ret = select(drm.fd + 1, &fds, NULL, NULL, NULL); if (ret < 0) { printf("select err: %s\n", strerror(errno)); return ret; } else if (ret == 0) { printf("select timeout!\n"); return -1; } else if (FD_ISSET(0, &fds)) { continue; } drmHandleEvent(drm.fd, &evctx); } /* release last buffer to render on again: */ gbm_surface_release_buffer(gbm.surface, bo); bo = next_bo; if(frame_count >= 0) { frame_count--; } } cleanup_kmscube(); printf("\n Exiting kmscube \n"); omap_bo_del(bo_test); free(lpBuf); return ret; }
