[media] vivid: move PRINTSTR to separate functions

Commit 84cb7be43c broke vivid-tpg
(uninitialized variable p).

This patch takes a different approach: four different functions are
created, one for each PRINTSTR version.

In order to avoid the 'the frame size of 1308 bytes is larger than 1024
bytes' warning I had to mark those functions with 'noinline'. For
whatever reason gcc seems to inline this aggressively and it is doing
weird things with the stack.

I tried to read the assembly code, but I couldn't see what exactly it
was doing on the stack.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
This commit is contained in:
Hans Verkuil 2015-06-05 13:09:31 -03:00 committed by Mauro Carvalho Chehab
parent 64d5702229
commit c70316f2a1

View File

@ -1462,40 +1462,10 @@ static void tpg_precalculate_line(struct tpg_data *tpg)
/* need this to do rgb24 rendering */ /* need this to do rgb24 rendering */
typedef struct { u16 __; u8 _; } __packed x24; typedef struct { u16 __; u8 _; } __packed x24;
void tpg_gen_text(const struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2], #define PRINTSTR(PIXTYPE) do { \
int y, int x, char *text) unsigned vdiv = tpg->vdownsampling[p]; \
{ unsigned hdiv = tpg->hdownsampling[p]; \
int line; int line; \
unsigned step = V4L2_FIELD_HAS_T_OR_B(tpg->field) ? 2 : 1;
unsigned div = step;
unsigned first = 0;
unsigned len = strlen(text);
unsigned p;
if (font8x16 == NULL || basep == NULL)
return;
/* Checks if it is possible to show string */
if (y + 16 >= tpg->compose.height || x + 8 >= tpg->compose.width)
return;
if (len > (tpg->compose.width - x) / 8)
len = (tpg->compose.width - x) / 8;
if (tpg->vflip)
y = tpg->compose.height - y - 16;
if (tpg->hflip)
x = tpg->compose.width - x - 8;
y += tpg->compose.top;
x += tpg->compose.left;
if (tpg->field == V4L2_FIELD_BOTTOM)
first = 1;
else if (tpg->field == V4L2_FIELD_SEQ_TB || tpg->field == V4L2_FIELD_SEQ_BT)
div = 2;
/* Print text */
#define PRINTSTR(PIXTYPE) for (p = 0; p < tpg->planes; p++) { \
unsigned vdiv = tpg->vdownsampling[p]; \
unsigned hdiv = tpg->hdownsampling[p]; \
PIXTYPE fg; \ PIXTYPE fg; \
PIXTYPE bg; \ PIXTYPE bg; \
memcpy(&fg, tpg->textfg[p], sizeof(PIXTYPE)); \ memcpy(&fg, tpg->textfg[p], sizeof(PIXTYPE)); \
@ -1546,19 +1516,83 @@ void tpg_gen_text(const struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2],
} \ } \
} while (0) } while (0)
switch (tpg->twopixelsize[p]) { static noinline void tpg_print_str_2(const struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2],
case 2: unsigned p, unsigned first, unsigned div, unsigned step,
PRINTSTR(u8); int y, int x, char *text, unsigned len)
break; {
case 4: PRINTSTR(u8);
PRINTSTR(u16); }
break;
case 6: static noinline void tpg_print_str_4(const struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2],
PRINTSTR(x24); unsigned p, unsigned first, unsigned div, unsigned step,
break; int y, int x, char *text, unsigned len)
case 8: {
PRINTSTR(u32); PRINTSTR(u16);
break; }
static noinline void tpg_print_str_6(const struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2],
unsigned p, unsigned first, unsigned div, unsigned step,
int y, int x, char *text, unsigned len)
{
PRINTSTR(x24);
}
static noinline void tpg_print_str_8(const struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2],
unsigned p, unsigned first, unsigned div, unsigned step,
int y, int x, char *text, unsigned len)
{
PRINTSTR(u32);
}
void tpg_gen_text(const struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2],
int y, int x, char *text)
{
unsigned step = V4L2_FIELD_HAS_T_OR_B(tpg->field) ? 2 : 1;
unsigned div = step;
unsigned first = 0;
unsigned len = strlen(text);
unsigned p;
if (font8x16 == NULL || basep == NULL)
return;
/* Checks if it is possible to show string */
if (y + 16 >= tpg->compose.height || x + 8 >= tpg->compose.width)
return;
if (len > (tpg->compose.width - x) / 8)
len = (tpg->compose.width - x) / 8;
if (tpg->vflip)
y = tpg->compose.height - y - 16;
if (tpg->hflip)
x = tpg->compose.width - x - 8;
y += tpg->compose.top;
x += tpg->compose.left;
if (tpg->field == V4L2_FIELD_BOTTOM)
first = 1;
else if (tpg->field == V4L2_FIELD_SEQ_TB || tpg->field == V4L2_FIELD_SEQ_BT)
div = 2;
for (p = 0; p < tpg->planes; p++) {
/* Print text */
switch (tpg->twopixelsize[p]) {
case 2:
tpg_print_str_2(tpg, basep, p, first, div, step, y, x,
text, len);
break;
case 4:
tpg_print_str_4(tpg, basep, p, first, div, step, y, x,
text, len);
break;
case 6:
tpg_print_str_6(tpg, basep, p, first, div, step, y, x,
text, len);
break;
case 8:
tpg_print_str_8(tpg, basep, p, first, div, step, y, x,
text, len);
break;
}
} }
} }