tuxtxt: fix display with scaling FB, use hw accel if available

* Use a separate framebuffer and backbuffer on SPARK (the framebuffer
  is not big enough to have both buffers in it).
* make tuxtxt work correctly with scaling FB (1080 full-HD modes)
* improve performance by using the blitter to copy from back- to frame
  buffer if available (spark)
This commit is contained in:
Stefan Seyfried
2012-03-11 18:47:57 +01:00
parent 47f09004d8
commit 99952cb9d7
2 changed files with 99 additions and 37 deletions

View File

@@ -11,6 +11,8 @@
* * * *
* ported 2009 to HD1 by Coolstream LTD * * ported 2009 to HD1 by Coolstream LTD *
* * * *
* TD and SPARK port (C) 2010-2012 Stefan Seyfried *
* *
******************************************************************************/ ******************************************************************************/
#include "teletext.h" #include "teletext.h"
@@ -34,11 +36,23 @@ static int sub_pid, sub_page;
static bool use_gui; static bool use_gui;
static int cfg_national_subset; static int cfg_national_subset;
static int screen_x, screen_y, screen_w, screen_h;
//#define USE_FBPAN // FBIOPAN_DISPLAY seems to be working in current driver //#define USE_FBPAN // FBIOPAN_DISPLAY seems to be working in current driver
unsigned char *getFBp(int *y)
{
if (*y < (int)var_screeninfo.yres)
return lfb;
*y -= var_screeninfo.yres;
return lbb;
}
void FillRect(int x, int y, int w, int h, int color) void FillRect(int x, int y, int w, int h, int color)
{ {
unsigned char *p = lfb + x*4 + y * fix_screeninfo.line_length; unsigned char *p = getFBp(&y);
p += x*4 + y * fix_screeninfo.line_length;
#if !HAVE_TRIPLEDRAGON #if !HAVE_TRIPLEDRAGON
unsigned int col = bgra[color][3] << 24 | bgra[color][2] << 16 | bgra[color][1] << 8 | bgra[color][0]; unsigned int col = bgra[color][3] << 24 | bgra[color][2] << 16 | bgra[color][1] << 8 | bgra[color][0];
#else #else
@@ -53,6 +67,7 @@ void FillRect(int x, int y, int w, int h, int color)
} }
} }
void FillBorder(int color) void FillBorder(int color)
{ {
int ys = (var_screeninfo.yres-var_screeninfo.yoffset); int ys = (var_screeninfo.yres-var_screeninfo.yoffset);
@@ -239,7 +254,8 @@ void ClearFB(int /*color*/)
void ClearB(int color) void ClearB(int color)
{ {
FillRect(0,0,var_screeninfo.xres,var_screeninfo.yres*2,color); FillRect(0, 0, var_screeninfo.xres, var_screeninfo.yres, color); /* framebuffer */
FillRect(0, var_screeninfo.yres, var_screeninfo.xres, var_screeninfo.yres, color); /* backbuffer */
} }
int GetCurFontWidth() int GetCurFontWidth()
@@ -247,6 +263,7 @@ int GetCurFontWidth()
int mx = (displaywidth)%(40-nofirst); // # of unused pixels int mx = (displaywidth)%(40-nofirst); // # of unused pixels
int abx = (mx == 0 ? displaywidth+1 : (displaywidth)/(mx+1));// distance between 'inserted' pixels int abx = (mx == 0 ? displaywidth+1 : (displaywidth)/(mx+1));// distance between 'inserted' pixels
int nx= abx+1-((PosX-sx) % (abx+1)); // # of pixels to next insert int nx= abx+1-((PosX-sx) % (abx+1)); // # of pixels to next insert
return fontwidth+(((PosX+fontwidth+1-sx) <= displaywidth && nx <= fontwidth+1) ? 1 : 0); return fontwidth+(((PosX+fontwidth+1-sx) <= displaywidth && nx <= fontwidth+1) ? 1 : 0);
} }
@@ -1624,7 +1641,9 @@ int tuxtx_main(int _rc, int pid, int page, int source)
} }
rc = _rc; rc = _rc;
lfb = (unsigned char *) CFrameBuffer::getInstance()->getFrameBufferPointer(); CFrameBuffer *fbp = CFrameBuffer::getInstance();
lfb = (unsigned char *)fbp->getFrameBufferPointer();
lbb = (unsigned char *)fbp->getBackBufferPointer();
tuxtxt_cache.vtxtpid = pid; tuxtxt_cache.vtxtpid = pid;
@@ -1657,10 +1676,15 @@ int tuxtx_main(int _rc, int pid, int page, int source)
ex = x + w - 10; ex = x + w - 10;
ey = y + h - 10; ey = y + h - 10;
#endif #endif
int x = CFrameBuffer::getInstance()->getScreenX(); screen_x = fbp->scaleX(fbp->getScreenX());
int y = CFrameBuffer::getInstance()->getScreenY(); screen_y = fbp->scaleY(fbp->getScreenY());
int w = CFrameBuffer::getInstance()->getScreenWidth(); screen_w = fbp->scaleX(fbp->getScreenWidth());
int h = CFrameBuffer::getInstance()->getScreenHeight(); screen_h = fbp->scaleY(fbp->getScreenHeight());
int x = screen_x;
int y = screen_y;
int w = screen_w;
int h = screen_h;
int tx = 0; int tx = 0;
if (!screen_mode1) if (!screen_mode1)
@@ -1859,6 +1883,7 @@ FT_Error MyFaceRequester(FTC_FaceID face_id, FT_Library plibrary, FT_Pointer /*r
******************************************************************************/ ******************************************************************************/
extern std::string ttx_font_file; extern std::string ttx_font_file;
static bool ft_init_done = false; static bool ft_init_done = false;
static int oldfontheight = 0;
int Init(int source) int Init(int source)
{ {
int error, i; int error, i;
@@ -2021,7 +2046,7 @@ int Init(int source)
fontwidth_topmenumain = (TV43STARTX-sx) / 40; fontwidth_topmenumain = (TV43STARTX-sx) / 40;
fontwidth_topmenusmall = (TVENDX - TOPMENUSTARTX) / TOPMENUCHARS; fontwidth_topmenusmall = (TVENDX - TOPMENUSTARTX) / TOPMENUCHARS;
//fontwidth_small = (TV169FULLSTARTX-sx) / 40; //fontwidth_small = (TV169FULLSTARTX-sx) / 40;
fontwidth_small = (CFrameBuffer::getInstance()->getScreenWidth()/2) / 40; fontwidth_small = (screen_w / 2) / 40;
ymosaic[0] = 0; /* y-offsets for 2*3 mosaic */ ymosaic[0] = 0; /* y-offsets for 2*3 mosaic */
ymosaic[1] = (fontheight + 1) / 3; ymosaic[1] = (fontheight + 1) / 3;
ymosaic[2] = (fontheight * 2 + 1) / 3; ymosaic[2] = (fontheight * 2 + 1) / 3;
@@ -2063,7 +2088,7 @@ int Init(int source)
} }
} }
#endif #endif
if(!ft_init_done || font_file != ttx_font_file) { if(!ft_init_done || font_file != ttx_font_file || fontheight != oldfontheight) {
printf("TuxTxt: init fontlibrary\n"); printf("TuxTxt: init fontlibrary\n");
if(ft_init_done) { if(ft_init_done) {
FTC_Manager_Done(manager); FTC_Manager_Done(manager);
@@ -2113,6 +2138,7 @@ int Init(int source)
} }
font_file = ttx_font_file; font_file = ttx_font_file;
ft_init_done = true; ft_init_done = true;
oldfontheight = fontheight;
ascender = (usettf ? fontheight * face->ascender / face->units_per_EM : 16); ascender = (usettf ? fontheight * face->ascender / face->units_per_EM : 16);
} }
@@ -3916,9 +3942,9 @@ void SwitchScreenMode(int newscreenmode)
if (screenmode==1) /* split with topmenu */ if (screenmode==1) /* split with topmenu */
{ {
int x = CFrameBuffer::getInstance()->getScreenX(); int x = screen_x;
int w = CFrameBuffer::getInstance()->getScreenWidth(); int w = screen_w;
int h = CFrameBuffer::getInstance()->getScreenHeight(); int h = screen_h;
fw = fontwidth_topmenumain; fw = fontwidth_topmenumain;
tx = 0; /* split means we start at the left edge */ tx = 0; /* split means we start at the left edge */
@@ -3945,18 +3971,20 @@ void SwitchScreenMode(int newscreenmode)
} }
else /* 2: split with full height tv picture */ else /* 2: split with full height tv picture */
{ {
StartX = CFrameBuffer::getInstance()->getScreenX(); StartX = screen_x;
fw = fontwidth_small; fw = fontwidth_small;
tx = TV169FULLSTARTX; tx = TV169FULLSTARTX;
ty = TV169FULLSTARTY; ty = TV169FULLSTARTY;
tw = TV169FULLWIDTH; tw = TV169FULLWIDTH;
th = TV169FULLHEIGHT; th = TV169FULLHEIGHT;
displaywidth = CFrameBuffer::getInstance()->getScreenWidth()/2; displaywidth = screen_w / 2;
} }
setfontwidth(fw); setfontwidth(fw);
videoDecoder->Pig(tx, ty, tw, th, CFrameBuffer::getInstance()->getScreenWidth(true), CFrameBuffer::getInstance()->getScreenHeight(true)); CFrameBuffer *f = CFrameBuffer::getInstance();
videoDecoder->Pig(tx, ty, tw, th,
f->scaleX(f->getScreenWidth(true)), f->scaleY(f->getScreenHeight(true)));
#if 0 #if 0
int sm = 0; int sm = 0;
ioctl(pig, VIDIOC_OVERLAY, &sm); ioctl(pig, VIDIOC_OVERLAY, &sm);
@@ -3978,8 +4006,8 @@ void SwitchScreenMode(int newscreenmode)
#endif #endif
videoDecoder->Pig(-1, -1, -1, -1); videoDecoder->Pig(-1, -1, -1, -1);
int x = CFrameBuffer::getInstance()->getScreenX(); int x = screen_x;
int w = CFrameBuffer::getInstance()->getScreenWidth(); int w = screen_w;
//int h = CFrameBuffer::getInstance()->getScreenHeight(); //int h = CFrameBuffer::getInstance()->getScreenHeight();
int tx = 0; int tx = 0;
/* see comment above on the TTX window dimensions */ /* see comment above on the TTX window dimensions */
@@ -4122,7 +4150,8 @@ void RenderDRCS( //FIX ME
void DrawVLine(int x, int y, int l, int color) void DrawVLine(int x, int y, int l, int color)
{ {
unsigned char *p = lfb + x*4 + y * fix_screeninfo.line_length; unsigned char *p = getFBp(&y);
p += x*4 + y * fix_screeninfo.line_length;
for ( ; l > 0 ; l--) for ( ; l > 0 ; l--)
{ {
@@ -4134,11 +4163,12 @@ void DrawVLine(int x, int y, int l, int color)
void DrawHLine(int x, int y, int l, int color) void DrawHLine(int x, int y, int l, int color)
{ {
int ltmp; int ltmp;
unsigned char *p = getFBp(&y);
if (l > 0) if (l > 0)
{ {
for (ltmp=0; ltmp <= l; ltmp++) for (ltmp=0; ltmp <= l; ltmp++)
{ {
memmove(lfb + x*4 + ltmp*4 + y * fix_screeninfo.line_length, bgra[color], 4); memmove(p + x*4 + ltmp*4 + y * fix_screeninfo.line_length, bgra[color], 4);
} }
} }
} }
@@ -4154,7 +4184,9 @@ void FillRectMosaicSeparated(int x, int y, int w, int h, int fgcolor, int bgcolo
void FillTrapez(int x0, int y0, int l0, int xoffset1, int h, int l1, int color) void FillTrapez(int x0, int y0, int l0, int xoffset1, int h, int l1, int color)
{ {
unsigned char *p = lfb + x0*4 + y0 * fix_screeninfo.line_length; unsigned char *p = getFBp(&y0);
p += x0 * 4 + y0 * fix_screeninfo.line_length;
int xoffset, l; int xoffset, l;
int yoffset; int yoffset;
int ltmp; int ltmp;
@@ -4176,7 +4208,9 @@ void FillTrapez(int x0, int y0, int l0, int xoffset1, int h, int l1, int color)
void FlipHorz(int x, int y, int w, int h) void FlipHorz(int x, int y, int w, int h)
{ {
unsigned char *buf= new unsigned char[w*4]; unsigned char *buf= new unsigned char[w*4];
unsigned char *p = lfb + x*4 + y * fix_screeninfo.line_length; unsigned char *p = getFBp(&y);
p += x * 4 + y * fix_screeninfo.line_length;
int w1,h1; int w1,h1;
if(buf != NULL){ if(buf != NULL){
for (h1 = 0 ; h1 < h ; h1++) for (h1 = 0 ; h1 < h ; h1++)
@@ -4194,7 +4228,10 @@ void FlipHorz(int x, int y, int w, int h)
void FlipVert(int x, int y, int w, int h) void FlipVert(int x, int y, int w, int h)
{ {
unsigned char *buf= new unsigned char[w*4]; unsigned char *buf= new unsigned char[w*4];
unsigned char *p = lfb + x*4 + y * fix_screeninfo.line_length, *p1, *p2; unsigned char *p1, *p2;
unsigned char *p = getFBp(&y);
p += x*4 + y * fix_screeninfo.line_length;
int h1; int h1;
if(buf != NULL){ if(buf != NULL){
for (h1 = 0 ; h1 < h/2 ; h1++) for (h1 = 0 ; h1 < h/2 ; h1++)
@@ -4455,7 +4492,10 @@ void RenderChar(int Char, tstPageAttr *Attribute, int zoom, int yoffset)
else if (*aShapes[Char - 0x20] == S_ADT) else if (*aShapes[Char - 0x20] == S_ADT)
{ {
int x,y,f,c; int x,y,f,c;
unsigned char* p = lfb + PosX*4 + (PosY+yoffset)* fix_screeninfo.line_length; y = yoffset;
unsigned char *p = getFBp(&y);
p += PosX * 4 + PosY * fix_screeninfo.line_length;
for (y=0; y<fontheight;y++) for (y=0; y<fontheight;y++)
{ {
for (f=0; f<factor; f++) for (f=0; f<factor; f++)
@@ -4499,8 +4539,10 @@ void RenderChar(int Char, tstPageAttr *Attribute, int zoom, int yoffset)
return; return;
} }
axdrcs[12] = curfontwidth; /* adjust last x-offset according to position, FIXME: double width */ axdrcs[12] = curfontwidth; /* adjust last x-offset according to position, FIXME: double width */
int y = yoffset;
unsigned char *q = getFBp(&y);
RenderDRCS(p, RenderDRCS(p,
lfb + PosX*4 + (yoffset + PosY) * fix_screeninfo.line_length, q + PosX * 4 + PosY * fix_screeninfo.line_length,
axdrcs, fgcolor, bgcolor); axdrcs, fgcolor, bgcolor);
} }
else else
@@ -4774,8 +4816,10 @@ void RenderChar(int Char, tstPageAttr *Attribute, int zoom, int yoffset)
if (ascender - sbit->top + TTFShiftY + sbit->height > fontheight) if (ascender - sbit->top + TTFShiftY + sbit->height > fontheight)
sbit->height = fontheight - ascender + sbit->top - TTFShiftY; /* limit char height to defined/calculated fontheight */ sbit->height = fontheight - ascender + sbit->top - TTFShiftY; /* limit char height to defined/calculated fontheight */
int y = yoffset;
p = getFBp(&y);
p += PosX * 4 + (PosY + Row) * fix_screeninfo.line_length; /* running pointer into framebuffer */
p = lfb + PosX*4 + (yoffset + PosY + Row) * fix_screeninfo.line_length; /* running pointer into framebuffer */
for (Row = sbit->height; Row; Row--) /* row counts up, but down may be a little faster :) */ for (Row = sbit->height; Row; Row--) /* row counts up, but down may be a little faster :) */
{ {
int pixtodo = (usettf ? sbit->width : curfontwidth); int pixtodo = (usettf ? sbit->width : curfontwidth);
@@ -5179,7 +5223,7 @@ void RenderPage()
fontwidth_topmenumain = (TV43STARTX-sx) / (40-nofirst); fontwidth_topmenumain = (TV43STARTX-sx) / (40-nofirst);
fontwidth_topmenusmall = (TVENDX - TOPMENUSTARTX) / TOPMENUCHARS; fontwidth_topmenusmall = (TVENDX - TOPMENUSTARTX) / TOPMENUCHARS;
//fontwidth_small = (TV169FULLSTARTX-sx) / (40-nofirst); //fontwidth_small = (TV169FULLSTARTX-sx) / (40-nofirst);
fontwidth_small = (CFrameBuffer::getInstance()->getScreenWidth()/2) / (40-nofirst); fontwidth_small = (screen_w / 2) / (40 - nofirst);
switch(screenmode) switch(screenmode)
{ {
case 0: case 0:
@@ -5187,7 +5231,7 @@ void RenderPage()
displaywidth = ex - sx; displaywidth = ex - sx;
break; break;
case 2: setfontwidth(fontwidth_small); case 2: setfontwidth(fontwidth_small);
displaywidth = CFrameBuffer::getInstance()->getScreenWidth() / 2; displaywidth = screen_w / 2;
break; break;
} }
if (transpmode || (boxed && !screenmode)) if (transpmode || (boxed && !screenmode))
@@ -5540,6 +5584,9 @@ void CopyBB2FB()
{ {
unsigned char *src, *dst, *topsrc; unsigned char *src, *dst, *topsrc;
int fillcolor, i, screenwidth, swtmp; int fillcolor, i, screenwidth, swtmp;
#ifdef HAVE_SPARK_HARDWARE
CFrameBuffer *f = CFrameBuffer::getInstance();
#endif
/* line 25 */ /* line 25 */
if (!pagecatching && use_gui) if (!pagecatching && use_gui)
@@ -5560,12 +5607,16 @@ void CopyBB2FB()
if (ioctl(fb, FBIOPAN_DISPLAY, &var_screeninfo) == -1) if (ioctl(fb, FBIOPAN_DISPLAY, &var_screeninfo) == -1)
perror("TuxTxt <FBIOPAN_DISPLAY>"); perror("TuxTxt <FBIOPAN_DISPLAY>");
#else #else
memmove(lfb, lfb+fix_screeninfo.line_length * var_screeninfo.yres, fix_screeninfo.line_length*var_screeninfo.yres); #ifdef HAVE_SPARK_HARDWARE
f->blit2FB(lbb, var_screeninfo.xres, var_screeninfo.yres, 0, 0, 0, 0, false, false);
#else
memcpy(lfb, lbb, fix_screeninfo.line_length*var_screeninfo.yres);
#endif
#endif #endif
/* adapt background of backbuffer if changed */ /* adapt background of backbuffer if changed */
if (StartX > 0 && *lfb != *(lfb + fix_screeninfo.line_length * var_screeninfo.yres)) { if (StartX > 0 && *lfb != *lbb) {
FillBorder(*(lfb + fix_screeninfo.line_length * var_screeninfo.yoffset)); FillBorder(*lbb);
// ClearBB(*(lfb + var_screeninfo.xres * var_screeninfo.yoffset)); // ClearBB(*(lfb + var_screeninfo.xres * var_screeninfo.yoffset));
} }
@@ -5577,8 +5628,11 @@ void CopyBB2FB()
return; return;
} }
src = dst = topsrc = lfb + StartY*fix_screeninfo.line_length; src = topsrc = lbb + StartY * fix_screeninfo.line_length;
dst = lfb + StartY * fix_screeninfo.line_length;
#ifdef USE_FBPAN
#error USE_FBPAN code is not working right now.
if (var_screeninfo.yoffset) if (var_screeninfo.yoffset)
dst += fix_screeninfo.line_length * var_screeninfo.yres; dst += fix_screeninfo.line_length * var_screeninfo.yres;
else else
@@ -5586,6 +5640,7 @@ void CopyBB2FB()
src += fix_screeninfo.line_length * var_screeninfo.yres; src += fix_screeninfo.line_length * var_screeninfo.yres;
topsrc += fix_screeninfo.line_length * var_screeninfo.yres; topsrc += fix_screeninfo.line_length * var_screeninfo.yres;
} }
#endif
/* copy line25 in normal height */ /* copy line25 in normal height */
if (!pagecatching ) if (!pagecatching )
memmove(dst+(24*fontheight)*fix_screeninfo.line_length, src + (24*fontheight)*fix_screeninfo.line_length, fix_screeninfo.line_length*fontheight); memmove(dst+(24*fontheight)*fix_screeninfo.line_length, src + (24*fontheight)*fix_screeninfo.line_length, fix_screeninfo.line_length*fontheight);
@@ -5601,9 +5656,15 @@ void CopyBB2FB()
/* copy topmenu in normal height (since PIG also keeps dimensions) */ /* copy topmenu in normal height (since PIG also keeps dimensions) */
if (screenmode == 1) if (screenmode == 1)
{ {
unsigned char *topdst = dst;
screenwidth = ( TV43STARTX ) * 4; screenwidth = ( TV43STARTX ) * 4;
#ifdef HAVE_SPARK_HARDWARE
int cx = var_screeninfo.xres - TV43STARTX; /* x start */
int cw = TV43STARTX; /* width */
int cy = StartY;
int ch = 24*fontheight;
f->blit2FB(lbb, cw, ch, cx, cy, cx, cy, false, false);
#else
unsigned char *topdst = dst;
size_t width = ex * sizeof(fb_pixel_t) - screenwidth; size_t width = ex * sizeof(fb_pixel_t) - screenwidth;
topsrc += screenwidth; topsrc += screenwidth;
@@ -5614,6 +5675,7 @@ void CopyBB2FB()
topdst += fix_screeninfo.line_length; topdst += fix_screeninfo.line_length;
topsrc += fix_screeninfo.line_length; topsrc += fix_screeninfo.line_length;
} }
#endif
} }
else if (screenmode == 2) else if (screenmode == 2)
screenwidth = ( TV169FULLSTARTX ) * 4; screenwidth = ( TV169FULLSTARTX ) * 4;

View File

@@ -85,19 +85,18 @@ int tv_pip_y;
#define fontwidth_small_lcd 8 #define fontwidth_small_lcd 8
#define TV43STARTX (ex) #define TV43STARTX (ex)
#define TVENDX (CFrameBuffer::getInstance()->getScreenX() + CFrameBuffer::getInstance()->getScreenWidth()) //ex #define TVENDX (screen_x + screen_w) //ex
// #define TVENDY (StartY + 25*fontheight) // #define TVENDY (StartY + 25*fontheight)
// #define TV43WIDTH (TVENDX - TV43STARTX) // #define TV43WIDTH (TVENDX - TV43STARTX)
// #define TV43HEIGHT (TV43WIDTH *9/16) // #define TV43HEIGHT (TV43WIDTH *9/16)
// #define TV43STARTY (TVENDY - TV43HEIGHT) // #define TV43STARTY (TVENDY - TV43HEIGHT)
//#define TV169FULLSTARTX (sx+ 8*40) //(sx +(ex +1 - sx)/2) //#define TV169FULLSTARTX (sx+ 8*40) //(sx +(ex +1 - sx)/2)
#define TV169FULLSTARTX (CFrameBuffer::getInstance()->getScreenX() + CFrameBuffer::getInstance()->getScreenWidth()/2) #define TV169FULLSTARTX (screen_x + screen_w / 2)
#define TV169FULLSTARTY sy #define TV169FULLSTARTY sy
//#define TV169FULLWIDTH (ex - sx)/2 //#define TV169FULLWIDTH (ex - sx)/2
#define TV169FULLWIDTH (CFrameBuffer::getInstance()->getScreenWidth()/2) #define TV169FULLWIDTH (screen_w / 2)
#define TV169FULLHEIGHT (ey - sy) #define TV169FULLHEIGHT (ey - sy)
#define TOPMENUSTARTX TV43STARTX+2 #define TOPMENUSTARTX TV43STARTX+2
//#define TOPMENUENDX TVENDX //#define TOPMENUENDX TVENDX
#define TOPMENUSTARTY StartY #define TOPMENUSTARTY StartY
@@ -205,6 +204,7 @@ const char *ObjectType[] =
/* framebuffer stuff */ /* framebuffer stuff */
static unsigned char *lfb = 0; static unsigned char *lfb = 0;
static unsigned char *lbb = 0;
struct fb_var_screeninfo var_screeninfo; struct fb_var_screeninfo var_screeninfo;
struct fb_fix_screeninfo fix_screeninfo; struct fb_fix_screeninfo fix_screeninfo;