/**************************************************************************** * examples/fboverlay/fboverlay_main.c * * Copyright (C) 2018 Gregory Nutt. All rights reserved. * Author: Marco Krahl * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. Neither the name NuttX nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include #include #include #include #include /**************************************************************************** * Preprocessor Definitions ****************************************************************************/ /**************************************************************************** * Private Types ****************************************************************************/ /**************************************************************************** * Private Data ****************************************************************************/ /**************************************************************************** * Private Functions ****************************************************************************/ /**************************************************************************** * Name: rgb8888 * * Description: * Color conversion from argb8888 to rgb color channel * * Parameters: * argb - argb8888 color * a - Reference ot 8-bit alpha channel * r - Reference ot 8-bit red channel * g - Reference ot 8-bit green channel * b - Reference ot 8-bit blue channel * ****************************************************************************/ #ifdef CONFIG_FB_CMAP static void rgb8888(uint32_t argb, uint8_t * a, uint8_t * r, uint8_t * g, uint8_t * b) { *a = (uint8_t)(argb >> 24); *r = (uint8_t)(argb >> 16); *g = (uint8_t)(argb >> 8); *b = (uint8_t)argb; } #endif /**************************************************************************** * Name: rgb565 * * Description: * Color conversion from argb8888 to rgb565 * * Parameters: * argb - argb8888 color * ****************************************************************************/ #ifdef CONFIG_FB_FMT_RGB16_565 static uint16_t rgb565(uint32_t argb) { uint16_t r = (argb >> 8) & 0xf800; uint16_t g = (argb >> 5) & 0x7e0; uint16_t b = (argb >> 3) & 0x1f; return (r | g | b); } #endif /**************************************************************************** * Name: draw_rect8 * * Description: * Draw a rectangle for 8 bit color mode * * Parameters: * fbmem - Points to framebuffer start address * oinfo - Refence to overlay information * area - Area draw * color - cmap color entry * ****************************************************************************/ #ifdef CONFIG_FB_CMAP static void draw_rect8(FAR void *fbmem, FAR struct fb_overlayinfo_s * oinfo, FAR const struct fb_area_s * area, uint8_t color) { FAR uint8_t *dest; FAR uint8_t *row; int x; int y; printf("Fill area (%d,%d,%d,%d) with color: %08x\n" , area->x, area->y, area->w, area->h, color); row = (FAR uint8_t *)fbmem + oinfo->stride * area->y; for (y = 0; y < area->h; y++) { dest = row + area->x; for (x = 0; x < area->w; x++) { *dest++ = color; } row += oinfo->stride; } } #endif /**************************************************************************** * Name: draw_rect16 * * Description: * Draw a rectangle for 16 bit color mode * * Parameters: * fbmem - Points to framebuffer start address * oinfo - Refence to overlay information * area - Area draw * rgb - rgb565 color * ****************************************************************************/ static void draw_rect16(FAR void *fbmem, FAR struct fb_overlayinfo_s * oinfo, FAR const struct fb_area_s * area, uint16_t rgb) { FAR uint16_t *dest; FAR uint8_t *row; int x; int y; printf("Fill area (%d,%d,%d,%d) with color: %04x\n", area->x, area->y, area->w, area->h, rgb); row = (FAR uint8_t *)fbmem + oinfo->stride * area->y; for (y = 0; y < area->h; y++) { dest = ((FAR uint16_t *)row) + area->x; for (x = 0; x < area->w; x++) { *dest++ = rgb; } row += oinfo->stride; } } /**************************************************************************** * Name: draw_rect24 * * Description: * Draw a rectangle for 24 bit color mode * * Parameters: * fbmem - Points to framebuffer start address * oinfo - Refence to overlay information * area - Area draw * rgb - rgb888 color * ****************************************************************************/ static void draw_rect24(FAR void *fbmem, FAR struct fb_overlayinfo_s * oinfo, FAR const struct fb_area_s * area, uint32_t rgb) { int x; int y; uint8_t r; uint8_t g; uint8_t b; FAR uint8_t *dest; FAR uint8_t *row; r = rgb; g = (rgb >> 8); b = (rgb >> 16); printf("Fill area (%d,%d,%d,%d) with color: %08x -> (r,g,b) = " "(%02x,%02x,%02x)\n", area->x, area->y, area->w, area->h, rgb, b, g, r); row = (FAR uint8_t *)fbmem + oinfo->stride * area->y; for (y = 0; y < area->h; y++) { dest = row + area->x * 3; for (x = 0; x < area->w; x++) { *dest++ = r; *dest++ = g; *dest++ = b; } row += oinfo->stride; } } /**************************************************************************** * Name: draw_rect32 * * Description: * Draw a rectangle for 32 bit color mode * * Parameters: * fbmem - Points to framebuffer start address * oinfo - Refence to overlay information * area - Area draw * argb - argb8888 color * ****************************************************************************/ static void draw_rect32(FAR void *fbmem, FAR struct fb_overlayinfo_s * oinfo, FAR const struct fb_area_s * area, uint32_t argb) { int x; int y; FAR uint32_t *dest; FAR uint8_t *row; printf("Fill area (%d,%d,%d,%d) with color: %08x -> (a,r,g,b) = " "(%02x,%02x,%02x,%02x)\n", area->x, area->y, area->w, area->h, argb, argb >> 24, argb >> 16, argb >> 8, argb); row = (FAR uint8_t *)fbmem + oinfo->stride * area->y; for (y = 0; y < area->h; y++) { dest = ((FAR uint32_t *)row) + area->x; for (x = 0; x < area->w; x++) { *dest++ = argb; } row += oinfo->stride; } } /**************************************************************************** * Name: video_cmap * * Description: * Sets cmap * * Parameters: * fb - Open framebuffer filehandle * cmap - Readonly reference to color map * ****************************************************************************/ #ifdef CONFIG_FB_CMAP static int video_putcmap(int fb, FAR const struct fb_cmap_s *cmap) { int n; int ret; printf("Set cmap\n"); for (n = cmap->first; n < cmap->len; n++) { printf(" Color %d: (a,r,g,b) = (%02x,%02x,%02x,%02x)\n", n, # ifdef CONFIG_CMAP_TRANSPARENCY cmap->transp[n], # else (uint8_t)0xff, # endif cmap->red[n], cmap->green[n], cmap->blue[n]); } ret = ioctl(fb, FBIOPUT_CMAP, (unsigned long)(uintptr_t)cmap); if (ret != OK) { fprintf(stderr, "Unable to set camp\n"); } return ret; } /**************************************************************************** * Name: video_getcmap * * Description: * Sets cmap * * Parameters: * fb - Open framebuffer filehandle * cmap - Reference to color map * ****************************************************************************/ static int video_getcmap(int fb, FAR struct fb_cmap_s *cmap) { int n; int ret; ret = ioctl(fb, FBIOGET_CMAP, (unsigned long)(uintptr_t)cmap); if (ret != OK) { fprintf(stderr, "Unable to set camp\n"); } printf("Get cmap\n"); for (n = cmap->first; n < cmap->len; n++) { printf(" Color %d: (a,r,g,b) = (%02x,%02x,%02x,%02x)\n", n, # ifdef CONFIG_CMAP_TRANSPARENCY cmap->transp[n], # else (uint8_t)0xff, # endif cmap->red[n], cmap->green[n], cmap->blue[n]); } return ret; } #endif /* CONFIG_FB_CMAP */ /**************************************************************************** * Name: print_video_info * * Description: * Prints video information * * Parameters: * fb - Open framebuffer filehandle * ****************************************************************************/ static void print_video_info(int fb) { int ret; struct fb_videoinfo_s vinfo; ret = ioctl(fb, FBIOGET_VIDEOINFO, (unsigned long)(uintptr_t)&vinfo); if (ret != OK) { fprintf(stderr, "Unable to get video information\n"); return; } printf("VideoInfo:\n" " fmt: %u\n" " xres: %u\n" " yres: %u\n" " nplanes: %u\n" "noverlays: %u\n", vinfo.fmt, vinfo.xres, vinfo.yres, vinfo.nplanes, vinfo.noverlays); } /**************************************************************************** * Name: print_plane_info * * Description: * Prints plane information * * Parameters: * fb - Open framebuffer filehandle * ****************************************************************************/ static void print_plane_info(int fb) { int ret; FAR void *fbmem; struct fb_planeinfo_s pinfo; ret = ioctl(fb, FBIOGET_PLANEINFO, (unsigned long)(uintptr_t)&pinfo); if (ret != OK) { fprintf(stderr, "Unable to get plane information\n"); return; } fbmem = mmap(NULL, pinfo.fblen, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FILE, fb, 0); if (fbmem == MAP_FAILED) { fprintf(stderr, "ERROR: ioctl(FBIO_MMAP) failed: %d\n", errno); return; } printf("PlaneInfo:\n" " fbmem: %p\n" " fblen: %lu\n" " stride: %u\n" " display: %u\n" " bpp: %u\n", pinfo.fbmem, (unsigned long)pinfo.fblen, pinfo.stride, pinfo.display, pinfo.bpp, fbmem); } /**************************************************************************** * Name: print_overlay_info * * Description: * Prints overlay information * * Parameters: * fb - Open framebuffer filehandle * overlayno - Overlay number * ****************************************************************************/ static void print_overlay_info(int fb, uint8_t overlayno) { int ret; FAR void *fbmem; struct fb_overlayinfo_s oinfo; /* Select overlay to compare fbmem from overlayinfo and the one by mmap */ ret = ioctl(fb, FBIO_SELECT_OVERLAY, overlayno); if (ret != OK) { fprintf(stderr, "Unable to select overlay: %d\n", overlayno); return; } oinfo.overlay = overlayno; ret = ioctl(fb, FBIOGET_OVERLAYINFO, (unsigned long)(uintptr_t)&oinfo); if (ret != OK) { fprintf(stderr, "Unable to get overlay information\n"); return; } fbmem = mmap(NULL, oinfo.fblen, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FILE, fb, 0); if (fbmem == MAP_FAILED) { fprintf(stderr, "ERROR: ioctl(FBIO_MMAP) failed: %d\n", errno); return; } printf("OverlayInfo:\n" " fbmem: %p\n" " fblen: %lu\n" " stride: %u\n" " overlay: %u\n" " bpp: %u\n" " blank: %08x\n" "chromakey: %08x\n" " color: %08x\n" " transp: %02x\n" " mode: %08x\n" " accl: %08x\n" " mmap: %p\n", oinfo.fbmem, (unsigned long)oinfo.fblen, oinfo.stride, oinfo.overlay, oinfo.bpp, oinfo.blank, oinfo.chromakey, oinfo.color, oinfo.transp.transp, oinfo.transp.transp_mode, oinfo.accl, fbmem); } /**************************************************************************** * Name: overlay_fill * * Description: * Fill the overlay area with a user defined color * * Parameters: * fb - Open framebuffer filehandle * overlayno - Overlay number * color - color * ****************************************************************************/ static int overlay_fill(int fb, uint8_t overlayno, uint32_t color, FAR const struct fb_area_s * area) { int ret; FAR void *fbmem; struct fb_videoinfo_s vinfo; struct fb_overlayinfo_s oinfo; ret = ioctl(fb, FBIOGET_VIDEOINFO, (unsigned long)((uintptr_t)&vinfo)); if (ret < 0) { fprintf(stderr, "Unable to get video info\n"); return -1; } oinfo.overlay = overlayno; ret = ioctl(fb, FBIOGET_OVERLAYINFO, (unsigned long)((uintptr_t)&oinfo)); if (ret < 0) { fprintf(stderr, "Unable to get overlay info\n"); return -1; } ret = ioctl(fb, FBIO_SELECT_OVERLAY, overlayno); if (ret != OK) { fprintf(stderr, "Unable to select overlay: %d\n", overlayno); return -1; } fbmem = mmap(NULL, oinfo.fblen, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FILE, fb, 0); if (fbmem == MAP_FAILED) { fprintf(stderr, "ERROR: ioctl(FBIO_MMAP) failed\n"); ret = -1; } else { uint32_t offset = (area->y + area->h - 1) * oinfo.stride + (area->x + area->w) * oinfo.bpp / 8; if (offset > oinfo.fblen) { fprintf(stderr, "Area is out of range: %d >= %d\n", offset, oinfo.fblen); return -1; } #ifdef CONFIG_FB_SYNC ret = ioctl(fb, FBIO_WAITFORVSYNC, 0); if (ret != OK) { fprintf(stderr, "Unable to sync upon vertical line\n"); } #endif #ifdef CONFIG_FB_CMAP if (vinfo.fmt == FB_FMT_RGB8) { draw_rect8(fbmem, &oinfo, area, color); } #endif else if (vinfo.fmt == FB_FMT_RGB16_565) { draw_rect16(fbmem, &oinfo, area, color); } else if (vinfo.fmt == FB_FMT_RGB24) { draw_rect24(fbmem, &oinfo, area, color); } else if (vinfo.fmt == FB_FMT_RGB32) { draw_rect32(fbmem, &oinfo, area, color); } } return ret; } /**************************************************************************** * Name: overlay_accl * * Description: * Determines overlay acceleration support * * Parameters: * fb - Open framebuffer filehandle * overlayno - Overlay number * accl - Acceleration to detect * * Return: * OK - Success * ERROR - Failed ****************************************************************************/ static int overlay_accl(int fb, uint8_t overlayno, uint32_t accl) { int ret; struct fb_overlayinfo_s oinfo; oinfo.overlay = overlayno; ret = ioctl(fb, FBIOGET_OVERLAYINFO, (unsigned long)((uintptr_t)&oinfo)); if (ret != OK) { fprintf(stderr, "Unable to get overlay information\n"); return -1; } printf("%s: %08x %08x\n", __func__, oinfo.accl, accl); return (oinfo.accl & accl) ? OK : -1; } /**************************************************************************** * Name: overlay_color * * Description: * Set overlay color * * Parameters: * fb - Open framebuffer filehandle * oinfo - Overlay information * ****************************************************************************/ static int overlay_color(int fb, FAR struct fb_overlayinfo_s *oinfo) { int ret; printf("Overlay: %d, set color: 0x%08x\n", oinfo->overlay, oinfo->color); ret = overlay_accl(fb, oinfo->overlay, FB_ACCL_COLOR); if (ret != OK) { fprintf(stderr, "No hardware acceleration to set a color within the " "selected overlay area\n"); } else { #ifdef CONFIG_FB_SYNC ret = ioctl(fb, FBIO_WAITFORVSYNC, 0); if (ret != OK) { fprintf(stderr, "Unable to sync upon vertical line\n"); } #endif ret = ioctl(fb, FBIOSET_COLOR, (unsigned long)(uintptr_t)oinfo); if (ret != OK) { fprintf(stderr, "Unable to set overlay color\n"); } } return ret; } /**************************************************************************** * Name: overlay_chromakey * * Description: * Set overlay chromakey * * Parameters: * fb - Open framebuffer filehandle * oinfo - Overlay information * ****************************************************************************/ static int overlay_chromakey(int fb, FAR struct fb_overlayinfo_s *oinfo) { int ret; printf("Overlay: %d, set chromakey: 0x%08x\n", oinfo->overlay, oinfo->chromakey); ret = overlay_accl(fb, oinfo->overlay, FB_ACCL_CHROMA); if (ret != OK) { fprintf(stderr, "No hardware acceleration to set the chromakey within " "the selected overlay area\n"); } else { #ifdef CONFIG_FB_SYNC ret = ioctl(fb, FBIO_WAITFORVSYNC, 0); if (ret != OK) { fprintf(stderr, "Unable to sync upon vertical line\n"); } #endif ret = ioctl(fb, FBIOSET_CHROMAKEY, (unsigned long)(uintptr_t)oinfo); if (ret != OK) { fprintf(stderr, "Unable to set overlay chroma key\n"); } } return ret; } /**************************************************************************** * Name: overlay_transp * * Description: * Set overlay transparency * * Parameters: * fb - Open framebuffer filehandle * oinfo - Overlay information * ****************************************************************************/ static int overlay_transp(int fb, FAR struct fb_overlayinfo_s *oinfo) { int ret; printf("Overlay: %d, set transp: %d, transp_mode: %08x\n", oinfo->overlay, oinfo->transp.transp, oinfo->transp.transp_mode); ret = overlay_accl(fb, oinfo->overlay, FB_ACCL_TRANSP); if (ret != OK) { fprintf(stderr, "No hardware acceleration to set the transparency within " "the selected overlay area\n"); } else { #ifdef CONFIG_FB_SYNC ret = ioctl(fb, FBIO_WAITFORVSYNC, 0); if (ret != OK) { fprintf(stderr, "Unable to sync upon vertical line\n"); } #endif ret = ioctl(fb, FBIOSET_TRANSP, (unsigned long)(uintptr_t)oinfo); if (ret != OK) { fprintf(stderr, "Unable to set transparency\n"); } } return ret; } /**************************************************************************** * Name: overlay_blank * * Description: * Enable or disable overlay * * Parameters: * fb - Open framebuffer filehandle * oinfo - Overlay information * ****************************************************************************/ static int overlay_blank(int fb, FAR struct fb_overlayinfo_s *oinfo) { int ret; printf("Overlay: %d, set blank: %08x\n", oinfo->overlay, oinfo->blank); ret = ioctl(fb, FBIOSET_BLANK, (unsigned long)(uintptr_t)oinfo); if (ret != OK) { fprintf(stderr, "Unable to blank overlay\n"); } return ret; } /**************************************************************************** * Name: overlay_area * * Description: * Select overlay area * * Parameters: * fb - Open framebuffer filehandle * oinfo - Overlay information * ****************************************************************************/ static int overlay_area(int fb, FAR struct fb_overlayinfo_s *oinfo) { int ret; printf("Overlay: %d, set xpos: %d, ypos: %d, xres: %d, yres: %d\n", oinfo->overlay, oinfo->sarea.x, oinfo->sarea.y, oinfo->sarea.w, oinfo->sarea.h); ret = overlay_accl(fb, oinfo->overlay, FB_ACCL_AREA); if (ret != OK) { fprintf(stderr, "No hardware acceleration to select area within " "the selected overlay area\n"); } else { ret = ioctl(fb, FBIOSET_AREA, (unsigned long)(uintptr_t)oinfo); if (ret != OK) { fprintf(stderr, "Unable to select area\n"); } } return ret; } /**************************************************************************** * Name: overlay_blit * * Description: * Blit content from source to destination overlay * * Parameters: * fb - Open framebuffer filehandle * blit - Blit control information * ****************************************************************************/ #ifdef CONFIG_FB_OVERLAY_BLIT static int overlay_blit(int fb, FAR struct fb_overlayblit_s *blit) { int ret; ret = overlay_accl(fb, blit->src.overlay, FB_ACCL_BLIT); if (ret == OK) { ret = overlay_accl(fb, blit->dest.overlay, FB_ACCL_BLIT); } if (ret != OK) { fprintf(stderr, "Hardware blit not supported\n"); } else { # ifdef CONFIG_FB_SYNC ret = ioctl(fb, FBIO_WAITFORVSYNC, 0); if (ret != OK) { fprintf(stderr, "Unable to sync upon vertical line\n"); } # endif ret = ioctl(fb, FBIOSET_BLIT, (unsigned long)(uintptr_t)blit); if (ret != OK) { fprintf(stderr, "Unable to blit overlay content\n"); } } return ret; } /**************************************************************************** * Name: overlay_blend * * Description: * Blend content from foreground and background overlay to a destination * overlay * * Parameters: * fb - Open framebuffer filehandle * blend - Blend operation information * ****************************************************************************/ static int overlay_blend(int fb, FAR struct fb_overlayblend_s *blend) { int ret; ret = overlay_accl(fb, blend->foreground.overlay, FB_ACCL_BLEND); if (ret == OK) { ret = overlay_accl(fb, blend->background.overlay, FB_ACCL_BLEND); } if (ret == OK) { ret = overlay_accl(fb, blend->dest.overlay, FB_ACCL_BLEND); } if (ret != OK) { fprintf(stderr, "Hardware blending not supported\n"); } else { # ifdef CONFIG_FB_SYNC ret = ioctl(fb, FBIO_WAITFORVSYNC, 0); if (ret != OK) { fprintf(stderr, "Unable to sync upon vertical line\n"); } # endif ret = ioctl(fb, FBIOSET_BLEND, (unsigned long)(uintptr_t)blend); if (ret != OK) { fprintf(stderr, "Unable to blend overlay content\n"); } } return ret; } #endif /* CONFIG_FB_OVERLAY_BLIT */ /**************************************************************************** * Name: fbopen * * Description: * Open framebuffer device * * Parameters: * device - Path to framebuffer device * * Return: * Open filehandle to framebuffer device or ERROR when failed ****************************************************************************/ static int fbopen(const char * device) { int fb = open(device, O_RDWR); if (fb < 0) { fprintf(stderr, "Unable to open framebuffer device: %s\n", device); return EXIT_FAILURE; } return fb; } /**************************************************************************** * Name: usage * * Description: * Commandline info * * Parameters: * progname - Name of the programm * ****************************************************************************/ static void usage(const char * progname) { fprintf(stderr, "usage: %s