diff options
Diffstat (limited to 'imlibrenderer/fbrenderer')
-rw-r--r-- | imlibrenderer/fbrenderer/fbrenderer.c | 375 | ||||
-rw-r--r-- | imlibrenderer/fbrenderer/fbrenderer.h | 65 |
2 files changed, 440 insertions, 0 deletions
diff --git a/imlibrenderer/fbrenderer/fbrenderer.c b/imlibrenderer/fbrenderer/fbrenderer.c new file mode 100644 index 0000000..87e2cd5 --- /dev/null +++ b/imlibrenderer/fbrenderer/fbrenderer.c @@ -0,0 +1,375 @@ +/** + * GraphTFT plugin for the Video Disk Recorder + * + * fbrenderer.c - A plugin for the Video Disk Recorder + * + * (c) 2004 Lars Tegeler, Sascha Volkenandt + * + * This code is distributed under the terms and conditions of the + * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details. + * + * $Id: fbrenderer.c,v 1.4 2012/09/27 13:07:12 wendel Exp $ + * + **/ + +#include <sys/mman.h> +#include <sys/ioctl.h> + +#include <fbrenderer.h> + +#include <libavcodec/avcodec.h> + +#include <common.h> +#include <setup.h> + +static unsigned char* frame_buffer; +static struct fb_var_screeninfo fb_vinfo; + +typedef unsigned char UINT8; + +//*************************************************************************** +// Object +//*************************************************************************** + +FbRenderer::FbRenderer(int x, int y, int width, int height, + string cfgPath, int utf, string thmPath) + : ImlibRenderer(x, y, width, height, cfgPath, utf, thmPath) +{ + fb_dev_name = 0; + initialized = no; +} + +FbRenderer::~FbRenderer() +{ + deinit(); +} + +//*************************************************************************** +// +//*************************************************************************** + +void FbRenderer::deinit() +{ + if (!initialized) + return; + + fb_orig_vinfo.xoffset = fb_vinfo.xoffset; + fb_orig_vinfo.yoffset = fb_vinfo.yoffset; + + if (ioctl(fb_dev_fd, FBIOPUT_VSCREENINFO, &fb_orig_vinfo)) + tell(4, "Can't reset original fb_var_screeninfo: %s", strerror(errno)); + + ::close(fb_dev_fd); + + if (frame_buffer) + munmap(frame_buffer, fb_size); + + initialized = no; +} + +//*************************************************************************** +// +//*************************************************************************** + +#ifndef AV_PIX_FMT_RGB32 +# define AV_PIX_FMT_RGB32 PIX_FMT_RGB32 +# define AV_PIX_FMT_RGB24 PIX_FMT_RGB24 +# define AV_PIX_FMT_RGB565 PIX_FMT_RGB565 +#endif + +int FbRenderer::init(int lazy) +{ + asprintf(&fb_dev_name, "%s", devname); + + // open framebuffer + + tell(4 , "Using framebuffer device '%s'", fb_dev_name); + + if ((fb_dev_fd = open(fb_dev_name, O_RDWR)) == -1) + { + tell(0, "Opening framebuffer device '%s' faild, error was '%s'", + fb_dev_name, strerror(errno)); + return fail; + } + + // read VScreen info from fb + + if (ioctl(fb_dev_fd, FBIOGET_VSCREENINFO, &fb_vinfo)) + { + tell(0, "Can't get VSCREENINFO, %s", strerror(errno)); + return fail; + } + + // Save VScreen info and try to set virtual image + + fb_orig_vinfo = fb_vinfo; + fb_vinfo.xres_virtual = fb_vinfo.xres; + fb_vinfo.yres_virtual = fb_vinfo.yres; + + fb_vinfo.xoffset = 0; + fb_vinfo.yoffset = 0; + + // fb_vinfo.bits_per_pixel = 32; + + // write VScreen info + + if (ioctl(fb_dev_fd, FBIOPUT_VSCREENINFO, &fb_vinfo)) + tell(0, "Can't put VSCREENINFO, %s", strerror(errno)); + + // read VScreen info from fb (again) this will be the 'accepted' resolutions from the fb + + if (ioctl(fb_dev_fd, FBIOGET_VSCREENINFO, &fb_vinfo)) + { + tell(0, "Can't get VSCREENINFO, %s", strerror(errno)); + return fail; + } + + // read VScreen info from fb + + if (ioctl(fb_dev_fd, FBIOGET_FSCREENINFO, &fb_finfo)) + { + tell(0, "Can't get FSCREENINFO, %s", strerror(errno)); + return fail; + } + + tell(0, "fb settings are (%d/%d) with a color depth of (%d)", + fb_vinfo.xres, fb_vinfo.yres, fb_vinfo.bits_per_pixel); + + dspWidth = fb_vinfo.xres; + dspHeight = fb_vinfo.yres; + + y_offset = fb_vinfo.yoffset; + fb_line_len = fb_finfo.line_length; + fb_size = fb_finfo.smem_len; + frame_buffer = 0; + + switch (fb_vinfo.bits_per_pixel) + { + case 32: tell(4, "FB using 32 bit depth"); fb_type = AV_PIX_FMT_RGB32; break; + case 24: tell(4, "FB using 24 bit depth"); fb_type = AV_PIX_FMT_RGB24; break; + case 16: tell(4, "FB using 16 bit depth"); fb_type = AV_PIX_FMT_RGB565; break; + default: tell(4, "FB color depth not supported -> %i bits per pixel", + fb_vinfo.bits_per_pixel); + } + + if ((frame_buffer = (unsigned char*)mmap(0, fb_size, PROT_READ | PROT_WRITE, MAP_SHARED, fb_dev_fd, 0)) == (unsigned char*)-1) + { + tell(0, "FB Can't mmap %s: %s", fb_dev_name, strerror(errno)); + return fail; + } + + initialized = yes; + + ImlibRenderer::init(lazy); + + return success; +} + +//*************************************************************************** +// +//*************************************************************************** + +#ifndef use_asm + +void FbRenderer::fbdev_draw_32(unsigned char* frame, int force) +{ + memcpy(frame_buffer, frame, 4*fb_vinfo.yres*fb_vinfo.xres); +} + +#else + +/* FIXME evil hack */ + +static void fbdev32(unsigned char * frame) +{ + __asm__ __volatile__( + + " pushl %%esi \n\t" + " pushl %%edi \n\t" + " pushl %%eax \n\t" + " pushl %%ecx \n\t" + + " movl fb_vinfo,%%eax \n\t" // Height + " movl fb_vinfo+4,%%ecx \n\t" // width + " imul %%eax,%%ecx \n\t" // mul + " movl frame_buffer,%%edi \n\t" // fbdev mmap'd buffer + " movl 8(%%ebp), %%esi \n\t" // Imlib2 buffer (frame) + " rep movsl \n\t" // move all longs at a time (4 bytes) + + " popl %%ecx \n\t" + " popl %%eax \n\t" + " popl %%edi \n\t" + " popl %%esi \n\t" + + :/*no output*/:/*no input*/:"memory","cc"); +} + +void FbRenderer::fbdev_draw_32(unsigned char* frame, int force) +{ + fbdev32(frame); +} + +#endif + +//*************************************************************************** +// +//*************************************************************************** + +#ifndef use_asm + +void FbRenderer::fbdev_draw_24(unsigned char* frame, int force) +{ + unsigned int i,a,b,c,x, out_offset = 0, in_offset = 0; + + x = fb_vinfo.xres*4; + + for (i = 0; i < fb_vinfo.yres; ++i) + { + for (a=0, b=0, c=0; a < fb_vinfo.xres; ++a, b+=3, c+=4) + { + frame_buffer[out_offset + b +0] = frame[in_offset + c +0]; + frame_buffer[out_offset + b +1] = frame[in_offset + c +1]; + frame_buffer[out_offset + b +2] = frame[in_offset + c +2]; + } + + out_offset += fb_line_len; + in_offset += x; + } +} + +#else + +/* FIXME evil hack */ + +static void fbdev24(unsigned char* frame) +{ + __asm__ __volatile__( + + " pushl %%esi \n\t" + " pushl %%edi \n\t" + " pushl %%eax \n\t" + " pushl %%ebx \n\t" + " pushl %%ecx \n\t" + " pushl %%edx \n\t" + + " movl fb_vinfo,%%eax \n\t" // fbdev mmap'd buffer + " movl fb_vinfo+4,%%edx \n\t" // fbdev mmap'd buffer + " imul %%eax,%%edx \n\t" // fbdev mmap'd buffer + " movl 8(%%ebp), %%esi \n\t" // Imlib2 buffer (frame) + " movl frame_buffer,%%edi \n\t" // fbdev mmap'd buffer + + " .lop: \n\t" + " leal 3,%%ecx \n\t" // fbdev mmap'd buffer + " rep movsb \n\t" // move 3 bytes at a time + " inc %%esi \n\t" // increment one byte, bypass Alpha + " dec %%edx \n\t" // dec counter + " jnz .lop \n\t" // loop :) + + " popl %%edx \n\t" + " popl %%ecx \n\t" + " popl %%ebx \n\t" + " popl %%eax \n\t" + " popl %%edi \n\t" + " popl %%esi \n\t" + + :/*no output*/:/*no input*/:"memory","cc"); +} + +void FbRenderer::fbdev_draw_24(unsigned char* frame, int force) +{ + fbdev24(frame); +} + +#endif + +//*************************************************************************** +// fbdev draw 16 +//*************************************************************************** + +void FbRenderer::fbdev_draw_16(unsigned char* frame, int force) +{ + static unsigned short* tmp = 0; + static unsigned int size = fb_vinfo.yres * fb_vinfo.xres; + static unsigned short* fb = (unsigned short*)frame_buffer; + + if (!tmp) + tmp = (unsigned short*)calloc(sizeof(unsigned short), size); + + LogDuration ld("FbRenderer::fbdev_draw_16()"); + + unsigned char B, G, R; + unsigned int x, y; + unsigned short v; + unsigned int out_offset = 0, in_offset = 0; + + for (y = 0; y < fb_vinfo.yres; y++) + { + for (x = 0; x < fb_vinfo.xres; x++, out_offset++, in_offset+=4) + { + R = (frame[in_offset + 2] >> 3) & 0x1f; + G = (frame[in_offset + 1] >> 2) & 0x3f; + B = (frame[in_offset + 0] >> 3) & 0x1f; + + v = ((G << 5) | B) | ((R << 3) | (G >> 3)) << 8; + + if (force || tmp[out_offset] != v) + { + tmp[out_offset] = v; + fb[out_offset] = v; + } + } + } +} + +//*************************************************************************** +// Refresh +//*************************************************************************** + +void FbRenderer::refresh(int force) +{ + LogDuration ld("FbRenderer::refresh()"); + + // refresh + + ImlibRenderer::refresh(force); + + // copy to buffer + + imlib_context_set_image(*pImageToDisplay); + + if (GraphTFTSetup.flipOSD) + { + imlib_image_flip_vertical(); + imlib_image_flip_horizontal(); + } + + UINT8* dataptr = (UINT8*)imlib_image_get_data_for_reading_only(); + + tell(4, "copy image with a depth of (%d) to framebuffer", + fb_vinfo.bits_per_pixel); + + switch (fb_vinfo.bits_per_pixel) + { + case 16 : fbdev_draw_16(dataptr, force); break; + case 24 : fbdev_draw_24(dataptr, force); break; + case 32 : fbdev_draw_32(dataptr, force); break; + + default : tell(0, "fbdevout.c: color depth not supported " + "-> %i bits per pixel", fb_vinfo.bits_per_pixel); + } + +#ifdef PVRFB + + struct ivtvfb_ioctl_dma_host_to_ivtv_args prep; + prep.source = frame_buffer; + prep.dest_offset = 0; + prep.count = width * height * 4; + ioctl(fb_dev_fd, IVTVFB_IOCTL_PREP_FRAME, &prep); + +#endif +} + +void FbRenderer::clear() +{ + ImlibRenderer::clear(); +} diff --git a/imlibrenderer/fbrenderer/fbrenderer.h b/imlibrenderer/fbrenderer/fbrenderer.h new file mode 100644 index 0000000..9de636e --- /dev/null +++ b/imlibrenderer/fbrenderer/fbrenderer.h @@ -0,0 +1,65 @@ +/** + * GraphTFT plugin for the Video Disk Recorder + * + * fbrenderer.h - A plugin for the Video Disk Recorder + * + * (c) 2004 Lars Tegeler, Sascha Volkenandt + * + * This code is distributed under the terms and conditions of the + * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details. + * + * $Id: fbrenderer.h,v 1.4 2012/09/27 13:07:12 wendel Exp $ + * + **/ + +//The most part of this Code is from the MMS V.2 Project: + +#ifndef __GTFT_FBRENDERER_HPP +#define __GTFT_FBRENDERER_HPP + +#include <linux/fb.h> + +#include <imlibrenderer.h> + +//*************************************************************************** +// +//*************************************************************************** + +class FbRenderer : public ImlibRenderer +{ + + public: + + FbRenderer(int x, int y, int width, int height, + string cfgPath, int utf, string thmPath); + ~FbRenderer(); + + int init(int lazy); + void deinit(); + + void refresh(int force = no); + void clear(); + + private: + + void fbdev_draw_32(unsigned char* frame, int force); + void fbdev_draw_24(unsigned char* frame, int force); + void fbdev_draw_16(unsigned char* frame, int force); + + // data + + char* fb_dev_name; + int initialized; + Imlib_Image _resized; + + int fb_dev_fd; + int fb_type; + size_t fb_size; + int fb_line_len; + int y_offset; + + struct fb_var_screeninfo fb_orig_vinfo; + struct fb_fix_screeninfo fb_finfo; +}; + +#endif // __GTFT_FBRENDERER_H |