void newLife( LIFE_T *life, int32_t size) { life->width = size; life->height = size; life->alignedWidth = ALIGN_TO_16(life->width); life->alignedHeight = ALIGN_TO_16(life->height); life->pitch = ALIGN_TO_16(life->width); life->buffer = calloc(1, life->pitch * life->alignedHeight); if (life->buffer == NULL) { fprintf(stderr, "life: memory exhausted\n"); exit(EXIT_FAILURE); } life->fieldLength = life->width * life->height; life->field = calloc(1, life->fieldLength); if (life->field == NULL) { fprintf(stderr, "life: memory exhausted\n"); exit(EXIT_FAILURE); } life->fieldNext = calloc(1, life->fieldLength); if (life->fieldNext == NULL) { fprintf(stderr, "life: memory exhausted\n"); exit(EXIT_FAILURE); } struct timeval tv; gettimeofday(&tv, NULL); srand(tv.tv_usec); int32_t row = 0; for (row = 0 ; row < life->height ; row++) { int32_t col = 0; for (col = 0 ; col < life->width ; col++) { if (rand() > (RAND_MAX / 2)) { setCell(life, col, row); } else { life->buffer[col + (row * life->alignedWidth)] = DEAD; } } } //--------------------------------------------------------------------- VC_IMAGE_TYPE_T type = VC_IMAGE_8BPP; uint32_t vc_image_ptr; int result = 0; life->frontResource = vc_dispmanx_resource_create( type, life->width | (life->pitch << 16), life->height | (life->alignedHeight << 16), &vc_image_ptr); assert(life->frontResource != 0); life->backResource = vc_dispmanx_resource_create( type, life->width | (life->pitch << 16), life->height | (life->alignedHeight << 16), &vc_image_ptr); assert(life->backResource != 0); //--------------------------------------------------------------------- vc_dispmanx_rect_set(&(life->bmpRect), 0, 0, life->width, life->height); result = vc_dispmanx_resource_write_data(life->frontResource, type, life->pitch, life->buffer, &(life->bmpRect)); assert(result == 0); //--------------------------------------------------------------------- long cores = sysconf(_SC_NPROCESSORS_ONLN); if (cores == -1) { cores = 1; } if (cores > LIFE_MAX_THREADS) { life->numberOfThreads = LIFE_MAX_THREADS; } else { life->numberOfThreads = cores; } pthread_barrier_init(&(life->startIterationBarrier), NULL, life->numberOfThreads + 1); pthread_barrier_init(&(life->finishedIterationBarrier), NULL, life->numberOfThreads + 1); //--------------------------------------------------------------------- int32_t heightStep = life->height / life->numberOfThreads; int32_t heightStart = 0; int32_t thread; for (thread = 0 ; thread < life->numberOfThreads ; thread++) { life->heightRange[thread].startHeight = heightStart; life->heightRange[thread].endHeight = heightStart + heightStep; heightStart += heightStep; pthread_create(&(life->threads[thread]), NULL, workerLife, life); } thread = life->numberOfThreads - 1; life->heightRange[thread].endHeight = life->height; //--------------------------------------------------------------------- memcpy(life->field, life->fieldNext, life->fieldLength); pthread_barrier_wait(&(life->startIterationBarrier)); }
void mempool_destroy(mempool p) { struct pool_segment *seg, *segnext; struct node *niter; mempool piter, pprev; char *ptr; int64 i; #ifdef MEMPOOL_DEBUG ShowDebug(read_message("Source.common.mempool_debug4"), p->name); #endif // Unlink from global list. EnterSpinLock(&l_mempoolListLock); piter = l_mempoolList; pprev = l_mempoolList; while(1) { if(piter == NULL) break; if(piter == p) { // unlink from list, // if(pprev == l_mempoolList) { // this (p) is list begin. so set next as head. l_mempoolList = p->next; } else { // replace prevs next wuth our next. pprev->next = p->next; } break; } pprev = piter; piter = piter->next; } p->next = NULL; LeaveSpinLock(&l_mempoolListLock); // Get both locks. EnterSpinLock(&p->segmentLock); EnterSpinLock(&p->nodeLock); if(p->num_nodes_free != p->num_nodes_total) ShowWarning(read_message("Source.common.mempool_destroy"), p->name, (p->num_nodes_total - p->num_nodes_free)); // Free All Segments (this will also free all nodes) // The segment pointer is the base pointer to the whole segment. seg = p->segments; while(1) { if(seg == NULL) break; segnext = seg->next; // .. if(p->ondealloc != NULL) { // walk over the segment, and call dealloc callback! ptr = (char *)seg; ptr += ALIGN_TO_16(sizeof(struct pool_segment)); for(i = 0; i < seg->num_nodes_total; i++) { niter = (struct node *)ptr; ptr += sizeof(struct node); ptr += p->elem_size; #ifdef MEMPOOLASSERT if(niter->magic != NODE_MAGIC) { ShowError(read_message("Source.common.mempool_destroy2"), p->name, niter); continue; } #endif p->ondealloc(NODE_TO_DATA(niter)); } }//endif: ondealloc callback? // simple .. aFree(seg); seg = segnext; } // Clear node ptr p->free_list = NULL; InterlockedExchange64(&p->num_nodes_free, 0); InterlockedExchange64(&p->num_nodes_total, 0); InterlockedExchange64(&p->num_segments, 0); InterlockedExchange64(&p->num_bytes_total, 0); LeaveSpinLock(&p->nodeLock); LeaveSpinLock(&p->segmentLock); // Free pool itself :D aFree(p->name); aFree(p); }//end: mempool_destroy()
mempool mempool_create(const char *name, uint64 elem_size, uint64 initial_count, uint64 realloc_count, memPoolOnNodeAllocationProc onNodeAlloc, memPoolOnNodeDeallocationProc onNodeDealloc) { //.. uint64 realloc_thresh; mempool pool; pool = (mempool)aCalloc(1, sizeof(struct mempool)); if(pool == NULL) { ShowFatalError(read_message("Source.common.mempool_create"), sizeof(struct mempool)); exit(EXIT_FAILURE); } // Check minimum initial count / realloc count requirements. if(initial_count < 50) initial_count = 50; if(realloc_count < 50) realloc_count = 50; // Set Reallocation threshold to 5% of realloc_count, at least 10. realloc_thresh = (realloc_count/100)*5; // if(realloc_thresh < 10) realloc_thresh = 10; // Initialize members.. pool->name = aStrdup(name); pool->elem_size = ALIGN_TO_16(elem_size); pool->elem_realloc_step = realloc_count; pool->elem_realloc_thresh = realloc_thresh; pool->onalloc = onNodeAlloc; pool->ondealloc = onNodeDealloc; InitializeSpinLock(&pool->segmentLock); InitializeSpinLock(&pool->nodeLock); // Initial Statistic values: pool->num_nodes_total = 0; pool->num_nodes_free = 0; pool->num_segments = 0; pool->num_bytes_total = 0; pool->peak_nodes_used = 0; pool->num_realloc_events = 0; // #ifdef MEMPOOL_DEBUG ShowDebug(read_message("Source.common.mempool_create"), pool->name, pool->elem_size, initial_count, pool->elem_realloc_step); #endif // Allocate first segment directly :) segment_allocate_add(pool, initial_count); // Add Pool to the global pool list EnterSpinLock(&l_mempoolListLock); pool->next = l_mempoolList; l_mempoolList = pool; LeaveSpinLock(&l_mempoolListLock); return pool; }//end: mempool_create()
static void segment_allocate_add(mempool p, uint64 count) { // Required Memory: // sz( segment ) // count * sz( real_node_size ) // // where real node size is: // ALIGN_TO_16( sz( node ) ) + p->elem_size // so the nodes usable address is nodebase + ALIGN_TO_16(sz(node)) // size_t total_sz; struct pool_segment *seg = NULL; struct node *nodeList = NULL; struct node *node = NULL; char *ptr = NULL; uint64 i; total_sz = ALIGN_TO_16(sizeof(struct pool_segment)) + ((size_t)count * (sizeof(struct node) + (size_t)p->elem_size)) ; #ifdef MEMPOOL_DEBUG ShowDebug(read_message("Source.common.mempool_debug"), p->name, count, (float)total_sz/1024.f/1024.f); #endif // allocate! (spin forever until weve got the memory.) i=0; while(1) { ptr = (char *)aMalloc(total_sz); if(ptr != NULL) break; i++; // increase failcount. if(!(i & 7)) { ShowWarning(read_message("Source.common.mempool_debug2"), (float)total_sz/1024.f/1024.f, i); #ifdef WIN32 Sleep(1000); #else sleep(1); #endif } else { rathread_yield(); /// allow/force vuln. ctxswitch } }//endwhile: allocation spinloop. // Clear Memory. memset(ptr, 0x00, total_sz); // Initialize segment struct. seg = (struct pool_segment *)ptr; ptr += ALIGN_TO_16(sizeof(struct pool_segment)); seg->pool = p; seg->num_nodes_total = count; seg->num_bytes = total_sz; // Initialze nodes! nodeList = NULL; for(i = 0; i < count; i++) { node = (struct node *)ptr; ptr += sizeof(struct node); ptr += p->elem_size; node->segment = seg; #ifdef MEMPOOLASSERT node->used = false; node->magic = NODE_MAGIC; #endif if(p->onalloc != NULL) p->onalloc(NODE_TO_DATA(node)); node->next = nodeList; nodeList = node; } // Link in Segment. EnterSpinLock(&p->segmentLock); seg->next = p->segments; p->segments = seg; LeaveSpinLock(&p->segmentLock); // Link in Nodes EnterSpinLock(&p->nodeLock); nodeList->next = p->free_list; p->free_list = nodeList; LeaveSpinLock(&p->nodeLock); // Increase Stats: InterlockedExchangeAdd64(&p->num_nodes_total, count); InterlockedExchangeAdd64(&p->num_nodes_free, count); InterlockedIncrement64(&p->num_segments); InterlockedExchangeAdd64(&p->num_bytes_total, total_sz); }//end: segment_allocate_add()
bool initImage( IMAGE_T *image, VC_IMAGE_TYPE_T type, int32_t width, int32_t height, bool dither) { switch (type) { case VC_IMAGE_4BPP: image->bitsPerPixel = 4; image->setPixelDirect = NULL; image->getPixelDirect = NULL; image->setPixelIndexed = setPixel4BPP; image->getPixelIndexed = getPixel4BPP; break; case VC_IMAGE_8BPP: image->bitsPerPixel = 8; image->setPixelDirect = NULL; image->getPixelDirect = NULL; image->setPixelIndexed = setPixel8BPP; image->getPixelIndexed = getPixel8BPP; break; case VC_IMAGE_RGB565: image->bitsPerPixel = 16; if (dither) { image->setPixelDirect = setPixelDitheredRGB565; } else { image->setPixelDirect = setPixelRGB565; } image->getPixelDirect = getPixelRGB565; image->setPixelIndexed = NULL; image->getPixelIndexed = NULL; break; case VC_IMAGE_RGB888: image->bitsPerPixel = 24; image->setPixelDirect = setPixelRGB888; image->getPixelDirect = getPixelRGB888; image->setPixelIndexed = NULL; image->getPixelIndexed = NULL; break; case VC_IMAGE_RGBA16: image->bitsPerPixel = 16; if (dither) { image->setPixelDirect = setPixelDitheredRGBA16; } else { image->setPixelDirect = setPixelRGBA16; } image->getPixelDirect = getPixelRGBA16; image->setPixelIndexed = NULL; image->getPixelIndexed = NULL; break; case VC_IMAGE_RGBA32: image->bitsPerPixel = 32; image->setPixelDirect = setPixelRGBA32; image->getPixelDirect = getPixelRGBA32; image->setPixelIndexed = NULL; image->getPixelIndexed = NULL; break; default: fprintf(stderr, "image: unknown type (%d)\n", type); return false; break; } image->type = type; image->width = width; image->height = height; image->pitch = (ALIGN_TO_16(width) * image->bitsPerPixel) / 8; image->alignedHeight = ALIGN_TO_16(height); image->size = image->pitch * image->alignedHeight; image->buffer = calloc(1, image->size); if (image->buffer == NULL) { fprintf(stderr, "image: memory exhausted\n"); return false; } return true; }
int main( int argc, char *argv[]) { int opt = 0; bool writeToStdout = false; char *pngName = DEFAULT_NAME; int32_t requestedWidth = 0; int32_t requestedHeight = 0; uint32_t displayNumber = DEFAULT_DISPLAY_NUMBER; int compression = Z_DEFAULT_COMPRESSION; int delay = DEFAULT_DELAY; VC_IMAGE_TYPE_T imageType = VC_IMAGE_RGBA32; int8_t dmxBytesPerPixel = 4; int result = 0; program = basename(argv[0]); //------------------------------------------------------------------- char *sopts = "c:d:D:Hh:p:w:s"; struct option lopts[] = { { "compression", required_argument, NULL, 'c' }, { "delay", required_argument, NULL, 'd' }, { "display", required_argument, NULL, 'D' }, { "height", required_argument, NULL, 'h' }, { "help", no_argument, NULL, 'H' }, { "pngname", required_argument, NULL, 'p' }, { "width", required_argument, NULL, 'w' }, { "stdout", no_argument, NULL, 's' }, { NULL, no_argument, NULL, 0 } }; while ((opt = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) { switch (opt) { case 'c': compression = atoi(optarg); if ((compression < 0) || (compression > 9)) { compression = Z_DEFAULT_COMPRESSION; } break; case 'd': delay = atoi(optarg); break; case 'D': displayNumber = atoi(optarg); break; case 'h': requestedHeight = atoi(optarg); break; case 'p': pngName = optarg; break; case 'w': requestedWidth = atoi(optarg); break; case 's': writeToStdout = true; break; case 'H': default: usage(); if (opt == 'H') { exit(EXIT_SUCCESS); } else { exit(EXIT_FAILURE); } break; } } //------------------------------------------------------------------- bcm_host_init(); //------------------------------------------------------------------- // // When the display is rotate (either 90 or 270 degrees) we need to // swap the width and height of the snapshot // char response[1024]; int displayRotated = 0; if (vc_gencmd(response, sizeof(response), "get_config int") == 0) { vc_gencmd_number_property(response, "display_rotate", &displayRotated); } //------------------------------------------------------------------- if (delay) { sleep(delay); } //------------------------------------------------------------------- DISPMANX_DISPLAY_HANDLE_T displayHandle = vc_dispmanx_display_open(displayNumber); if (displayHandle == 0) { fprintf(stderr, "%s: unable to open display %d\n", program, displayNumber); exit(EXIT_FAILURE); } DISPMANX_MODEINFO_T modeInfo; result = vc_dispmanx_display_get_info(displayHandle, &modeInfo); if (result != 0) { fprintf(stderr, "%s: unable to get display information\n", program); exit(EXIT_FAILURE); } int32_t pngWidth = modeInfo.width; int32_t pngHeight = modeInfo.height; if (requestedWidth > 0) { pngWidth = requestedWidth; if (requestedHeight == 0) { double numerator = modeInfo.height * requestedWidth; double denominator = modeInfo.width; pngHeight = (int32_t)ceil(numerator / denominator); } } if (requestedHeight > 0) { pngHeight = requestedHeight; if (requestedWidth == 0) { double numerator = modeInfo.width * requestedHeight; double denominator = modeInfo.height; pngWidth = (int32_t)ceil(numerator / denominator); } } //------------------------------------------------------------------- // only need to check low bit of displayRotated (value of 1 or 3). // If the display is rotated either 90 or 270 degrees (value 1 or 3) // the width and height need to be transposed. int32_t dmxWidth = pngWidth; int32_t dmxHeight = pngHeight; if (displayRotated & 1) { dmxWidth = pngHeight; dmxHeight = pngWidth; } int32_t dmxPitch = dmxBytesPerPixel * ALIGN_TO_16(dmxWidth); void *dmxImagePtr = malloc(dmxPitch * dmxHeight); if (dmxImagePtr == NULL) { fprintf(stderr, "%s: unable to allocated image buffer\n", program); exit(EXIT_FAILURE); } //------------------------------------------------------------------- uint32_t vcImagePtr = 0; DISPMANX_RESOURCE_HANDLE_T resourceHandle; resourceHandle = vc_dispmanx_resource_create(imageType, dmxWidth, dmxHeight, &vcImagePtr); result = vc_dispmanx_snapshot(displayHandle, resourceHandle, DISPMANX_NO_ROTATE); if (result != 0) { vc_dispmanx_resource_delete(resourceHandle); vc_dispmanx_display_close(displayHandle); fprintf(stderr, "%s: vc_dispmanx_snapshot() failed\n", program); exit(EXIT_FAILURE); } VC_RECT_T rect; result = vc_dispmanx_rect_set(&rect, 0, 0, dmxWidth, dmxHeight); if (result != 0) { vc_dispmanx_resource_delete(resourceHandle); vc_dispmanx_display_close(displayHandle); fprintf(stderr, "%s: vc_dispmanx_rect_set() failed\n", program); exit(EXIT_FAILURE); } result = vc_dispmanx_resource_read_data(resourceHandle, &rect, dmxImagePtr, dmxPitch); if (result != 0) { vc_dispmanx_resource_delete(resourceHandle); vc_dispmanx_display_close(displayHandle); fprintf(stderr, "%s: vc_dispmanx_resource_read_data() failed\n", program); exit(EXIT_FAILURE); } vc_dispmanx_resource_delete(resourceHandle); vc_dispmanx_display_close(displayHandle); //------------------------------------------------------------------- // Convert from RGBA (32 bit) to RGB (24 bit) int8_t pngBytesPerPixel = 3; int32_t pngPitch = pngBytesPerPixel * pngWidth; void *pngImagePtr = malloc(pngPitch * pngHeight); int32_t j = 0; for (j = 0 ; j < pngHeight ; j++) { int32_t dmxXoffset = 0; int32_t dmxYoffset = 0; switch (displayRotated & 3) { case 0: // 0 degrees if (displayRotated & 0x20000) // flip vertical { dmxYoffset = (dmxHeight - j - 1) * dmxPitch; } else { dmxYoffset = j * dmxPitch; } break; case 1: // 90 degrees if (displayRotated & 0x20000) // flip vertical { dmxXoffset = j * dmxBytesPerPixel; } else { dmxXoffset = (dmxWidth - j - 1) * dmxBytesPerPixel; } break; case 2: // 180 degrees if (displayRotated & 0x20000) // flip vertical { dmxYoffset = j * dmxPitch; } else { dmxYoffset = (dmxHeight - j - 1) * dmxPitch; } break; case 3: // 270 degrees if (displayRotated & 0x20000) // flip vertical { dmxXoffset = (dmxWidth - j - 1) * dmxBytesPerPixel; } else { dmxXoffset = j * dmxBytesPerPixel; } break; } int32_t i = 0; for (i = 0 ; i < pngWidth ; i++) { uint8_t *pngPixelPtr = pngImagePtr + (i * pngBytesPerPixel) + (j * pngPitch); switch (displayRotated & 3) { case 0: // 0 degrees if (displayRotated & 0x10000) // flip horizontal { dmxXoffset = (dmxWidth - i - 1) * dmxBytesPerPixel; } else { dmxXoffset = i * dmxBytesPerPixel; } break; case 1: // 90 degrees if (displayRotated & 0x10000) // flip horizontal { dmxYoffset = (dmxHeight - i - 1) * dmxPitch; } else { dmxYoffset = i * dmxPitch; } break; case 2: // 180 degrees if (displayRotated & 0x10000) // flip horizontal { dmxXoffset = i * dmxBytesPerPixel; } else { dmxXoffset = (dmxWidth - i - 1) * dmxBytesPerPixel; } break; case 3: // 270 degrees if (displayRotated & 0x10000) // flip horizontal { dmxYoffset = i * dmxPitch; } else { dmxYoffset = (dmxHeight - i - 1) * dmxPitch; } break; } uint8_t *dmxPixelPtr = dmxImagePtr + dmxXoffset + dmxYoffset; memcpy(pngPixelPtr, dmxPixelPtr, 3); } } free(dmxImagePtr); dmxImagePtr = NULL; //------------------------------------------------------------------- png_structp pngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (pngPtr == NULL) { fprintf(stderr, "%s: unable to allocated PNG write structure\n", program); exit(EXIT_FAILURE); } png_infop infoPtr = png_create_info_struct(pngPtr); if (infoPtr == NULL) { fprintf(stderr, "%s: unable to allocated PNG info structure\n", program); exit(EXIT_FAILURE); } if (setjmp(png_jmpbuf(pngPtr))) { fprintf(stderr, "%s: unable to create PNG\n", program); exit(EXIT_FAILURE); } FILE *pngfp = NULL; if (writeToStdout) { pngfp = stdout; } else { pngfp = fopen(pngName, "wb"); if (pngfp == NULL) { fprintf(stderr, "%s: unable to create %s - %s\n", program, pngName, strerror(errno)); exit(EXIT_FAILURE); } } png_init_io(pngPtr, pngfp); png_set_IHDR( pngPtr, infoPtr, pngWidth, pngHeight, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); if (compression != Z_DEFAULT_COMPRESSION) { png_set_compression_level(pngPtr, compression); } png_write_info(pngPtr, infoPtr); int y = 0; for (y = 0; y < pngHeight; y++) { png_write_row(pngPtr, pngImagePtr + (pngPitch * y)); } png_write_end(pngPtr, NULL); png_destroy_write_struct(&pngPtr, &infoPtr); if (pngfp != stdout) { fclose(pngfp); } //------------------------------------------------------------------- free(pngImagePtr); pngImagePtr = NULL; return 0; }