MHEG5  18.9.0
MHEG5 Documentation
mg_osd.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright © 2014 The DTVKit Open Software Foundation Ltd (www.dtvkit.org)
3  * Copyright © 2008 Ocean Blue Software Ltd
4  *
5  * This file is part of a DTVKit Software Component
6  * You are permitted to copy, modify or distribute this file subject to the terms
7  * of the DTVKit 1.0 Licence which can be found in licence.txt or at www.dtvkit.org
8  *
9  * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
10  * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
11  * OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
12  *
13  * If you or your organisation is not a member of DTVKit then you have access
14  * to this source code outside of the terms of the licence agreement
15  * and you are expected to delete this and any associated files immediately.
16  * Further information on DTVKit, membership and terms can be found at www.dtvkit.org
17  *******************************************************************************/
25 /*---includes for this file--------------------------------------------------*/
26 #include "mh5profile.h"
27 #include "stb_osd.h"
28 #include "dvb_video.h"
29 #include "decoder.h"
30 #include "osd_utils.h"
31 #include "glue_memory.h"
32 #include "glue_debug.h"
33 #include "mg_api.h"
34 #include "mg_osd.h"
35 
36 #include "mg_fontapi.h"
37 
38 #ifndef OSD_32_BIT
39  #ifndef OSD_31_BIT
40  #ifndef OSD_16_BIT
41  #ifndef OSD_8_BIT
42 /* oops - we should be supporting something! */
43  #error "Should define at least one of OSD_8_BIT, OSD_16_BIT, OSD_31_BIT or OSD_32_BIT!"
44  #endif
45  #endif
46  #endif
47 #endif
48 
49 /*---constant definitions for this file--------------------------------------*/
50 #define MAGIC_SURF 0x5e4f
51 
52 #define DESKTOP_COLOUR 0xff000000
53 #define TOTAL_TRANSPARENCY 0x00000000
54 
55 /*
56  * SD_BlendColour( U8BIT pixel, U8BIT colour, ColourBlend last )
57  */
58 #define SD_BlendColour( pxl, clr, prv, swtch )
59 
60 #define C2L_ALPHA_CHNNL 0xf000
61 
62 #define C4L_ALPHA_CHNNL 0xff000000
63 
64 #ifdef OSD_8_BIT
65 /* Offsets into the MHEG palette */
66 #define OFFSET_SEMI (PALETTE_OFFSET + 1)
67 #define OFFSET_GREY (PALETTE_OFFSET + 49)
68 #define OFFSET_BLACK (PALETTE_OFFSET + 53)
69 #define OFFSET_WHITE (PALETTE_OFFSET + 187)
70 #define DESKTOP_COLOUR_INDEX OFFSET_BLACK
71 /* Number of colours in the D-Book palette */
72 #define NUM_SUBT_COLOURS 64
73 #define NUM_MHEG_COLOURS 188
74 #define NUM_MANU_COLOURS 4
75 
76 /*---local typedef structs for this file-------------------------------------*/
77 
78 typedef struct _NearCol
79 {
80  const U8BIT red[8];
81  const U8BIT green[16];
82  const U8BIT blue[4];
83 } NearCol;
84 
85 /*---global variable declarations for this file----------------------*/
86 
87 /* MHEG palette
88  * For OSDColour, the transparency is reversed from the UK profile spec.
89  * (i.e. opaque in UK prof is 0x00, but for OSDColor, it is 0xff ) */
90 OSDColor dbook_colour_palette[NUM_SUBT_COLOURS + NUM_MHEG_COLOURS + NUM_MANU_COLOURS] =
91 {
92  /* Subtitle colours */
93  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
94  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
95  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
96  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
97  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
98  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
99  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
100  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
101 
102  /* Fully transparent (index: 0) */
103  0x00000000,
104 
105  /* Semi-transparent (index: 1-48) */
106  0xb3000000, 0xb30000ff, 0xb3550000, 0xb35500ff, 0xb3aa0000, 0xb3aa00ff, 0xb3ff0000, 0xb3ff00ff,
107  0xb3003300, 0xb30033ff, 0xb3553300, 0xb35533ff, 0xb3aa3300, 0xb3aa33ff, 0xb3ff3300, 0xb3ff33ff,
108  0xb3006600, 0xb30066ff, 0xb3556600, 0xb35566ff, 0xb3aa6600, 0xb3aa66ff, 0xb3ff6600, 0xb3ff66ff,
109  0xb3009900, 0xb30099ff, 0xb3559900, 0xb35599ff, 0xb3aa9900, 0xb3aa99ff, 0xb3ff9900, 0xb3ff99ff,
110  0xb300cc00, 0xb300ccff, 0xb355cc00, 0xb355ccff, 0xb3aacc00, 0xb3aaccff, 0xb3ffcc00, 0xb3ffccff,
111  0xb300ff00, 0xb300ffff, 0xb355ff00, 0xb355ffff, 0xb3aaff00, 0xb3aaffff, 0xb3ffff00, 0xb3ffffff,
112 
113  /* Opaque greys (index: 49-52) */
114  0xff2a2a2a, 0xff555555, 0xffaaaaaa, 0xffd4d4d4,
115 
116  /* Opaque (index: 53-187) */
117  0xff000000, 0xff00007f, 0xff0000ff, 0xff001f00, 0xff001f7f, 0xff001fff, 0xff003f00, 0xff003f7f,
118  0xff003fff, 0xff005f00, 0xff005f7f, 0xff005fff, 0xff007f00, 0xff007f7f, 0xff007fff, 0xff009f00,
119  0xff009f7f, 0xff009fff, 0xff00bf00, 0xff00bf7f, 0xff00bfff, 0xff00df00, 0xff00df7f, 0xff00dfff,
120  0xff00ff00, 0xff00ff7f, 0xff00ffff, 0xff3f0000, 0xff3f007f, 0xff3f00ff, 0xff3f1f00, 0xff3f1f7f,
121  0xff3f1fff, 0xff3f3f00, 0xff3f3f7f, 0xff3f3fff, 0xff3f5f00, 0xff3f5f7f, 0xff3f5fff, 0xff3f7f00,
122  0xff3f7f7f, 0xff3f7fff, 0xff3f9f00, 0xff3f9f7f, 0xff3f9fff, 0xff3fbf00, 0xff3fbf7f, 0xff3fbfff,
123  0xff3fdf00, 0xff3fdf7f, 0xff3fdfff, 0xff3fff00, 0xff3fff7f, 0xff3fffff, 0xff7f0000, 0xff7f007f,
124  0xff7f00ff, 0xff7f1f00, 0xff7f1f7f, 0xff7f1fff, 0xff7f3f00, 0xff7f3f7f, 0xff7f3fff, 0xff7f5f00,
125  0xff7f5f7f, 0xff7f5fff, 0xff7f7f00, 0xff7f7f7f, 0xff7f7fff, 0xff7f9f00, 0xff7f9f7f, 0xff7f9fff,
126  0xff7fbf00, 0xff7fbf7f, 0xff7fbfff, 0xff7fdf00, 0xff7fdf7f, 0xff7fdfff, 0xff7fff00, 0xff7fff7f,
127  0xff7fffff, 0xffbf0000, 0xffbf007f, 0xffbf00ff, 0xffbf1f00, 0xffbf1f7f, 0xffbf1fff, 0xffbf3f00,
128  0xffbf3f7f, 0xffbf3fff, 0xffbf5f00, 0xffbf5f7f, 0xffbf5fff, 0xffbf7f00, 0xffbf7f7f, 0xffbf7fff,
129  0xffbf9f00, 0xffbf9f7f, 0xffbf9fff, 0xffbfbf00, 0xffbfbf7f, 0xffbfbfff, 0xffbfdf00, 0xffbfdf7f,
130  0xffbfdfff, 0xffbfff00, 0xffbfff7f, 0xffbfffff, 0xffff0000, 0xffff007f, 0xffff00ff, 0xffff1f00,
131  0xffff1f7f, 0xffff1fff, 0xffff3f00, 0xffff3f7f, 0xffff3fff, 0xffff5f00, 0xffff5f7f, 0xffff5fff,
132  0xffff7f00, 0xffff7f7f, 0xffff7fff, 0xffff9f00, 0xffff9f7f, 0xffff9fff, 0xffffbf00, 0xffffbf7f,
133  0xffffbfff, 0xffffdf00, 0xffffdf7f, 0xffffdfff, 0xffffff00, 0xffffff7f, 0xffffffff,
134 
135  /* Manufacturer colours */
136  0x00000000, 0x00000000, 0x00000000, 0x00000000
137 };
138 
139 OSDColor *mg_palette = NULL;
140 static S_REGION osd_update_rgn;
141 
142 #endif /* OSD_8_BIT */
143 
145  0, 0, /* output screen coordinate system */
146  0, 0, /* output OSD coordinate system */
147  0, 0, /* input coordinate system (e.g. mheg scene) */
148  { 1, 1 }, /* OSD horizontal scaling factor */
149  { 1, 1 }, /* OSD vertical scaling factor */
150  { 1, 1 }, /* Video horizontal scaling factor */
151  { 1, 1 }, /* Video vertical scaling factor */
152  { 1, 1 }, /* Line width scaling factor */
153  NULL, /* screen surface handle */
154  NULL, /* screen buffer */
155  0, /* screen stride */
156  0, /* offset_left */
157  COLOUR_FORMAT_PALETTE, /* colour depth */
158  #if defined(OSD_31_BIT) && defined(OSD_32_BIT)
159  0xff,
160  #endif
161 };
162 
163 /*---local (static) variable declarations for this file----------------------*/
164 
165 /*---local (static) function declarations for this file----------------------*/
166 
167 static U16BIT OSD_GCD( U16BIT a, U16BIT b );
168 
169 /*---global function definitions---------------------------------------------*/
170 
172 {
173  if (mg_ctxt.colour_format >= 16 &&
174  mg_ctxt.out_osd_width >= 1280 &&
175  mg_ctxt.out_osd_height >= 720)
176  {
177  return TRUE;
178  }
179  return FALSE;
180 }
181 
182 void MG_OSDInit( U16BIT inWidth, U16BIT inHeight,
183  U16BIT outWidth, U16BIT outHeight )
184 {
185  BOOLEAN out_changed, inp_changed;
186  U16BIT gcd;
187 
188  FUNCTION_START(x)
189  inp_changed = (mg_ctxt.input_width != inWidth ||
190  mg_ctxt.input_height != inHeight) ? TRUE : FALSE;
191  out_changed = (mg_ctxt.out_osd_width != outWidth ||
192  mg_ctxt.out_osd_height != outHeight) ? TRUE : FALSE;
193 
194  if (out_changed || inp_changed)
195  {
196  TRACE(TSTATE, ("in=(%d,%d) out=(%d,%d)", inWidth, inHeight, outWidth, outHeight))
197 
198  mg_ctxt.input_width = inWidth;
199  mg_ctxt.input_height = inHeight;
200  mg_ctxt.out_osd_width = outWidth;
201  mg_ctxt.out_osd_height = outHeight;
202 
203  //gcd = OSD_GCD(inWidth,outWidth);
204  gcd = OSD_GCD( OSD_GCD(inWidth, outWidth), OSD_GCD(inHeight, outHeight));
205  mg_ctxt.osd_x.mlt = outWidth / gcd;
206  mg_ctxt.osd_x.div = inWidth / gcd;
207  //gcd = OSD_GCD(inHeight,outHeight);
208  mg_ctxt.osd_y.mlt = outHeight / gcd;
209  mg_ctxt.osd_y.div = inHeight / gcd;
210 
211  gcd = OSD_GCD(inWidth, mg_ctxt.out_video_width);
212  mg_ctxt.vid_x.mlt = mg_ctxt.out_video_width / gcd;
213  mg_ctxt.vid_x.div = inWidth / gcd;
214 
215  gcd = OSD_GCD(inHeight, mg_ctxt.out_video_height);
216  mg_ctxt.vid_y.mlt = mg_ctxt.out_video_height / gcd;
217  mg_ctxt.vid_y.div = inHeight / gcd;
218 
219  /* mean factor is used for line width:
220  * mean = (sx/nx + sy/ny) / 2 = (sx*ny + sy * nx) / (2 * nx * ny)
221  */
222  mg_ctxt.line_w.mlt = ((mg_ctxt.osd_x.mlt * mg_ctxt.osd_y.div +
223  mg_ctxt.osd_y.mlt * mg_ctxt.osd_x.div));
224  mg_ctxt.line_w.div = (2 * mg_ctxt.osd_x.div * mg_ctxt.osd_y.div);
225 
226  gcd = OSD_GCD(mg_ctxt.line_w.mlt, mg_ctxt.line_w.div);
227  mg_ctxt.line_w.mlt /= gcd;
228  mg_ctxt.line_w.div /= gcd;
229 
230  if (!MG_FontInit( MG_IsHdSupported()))
231  {
232  TRACE(TERROR, ("MG_FontInit Failed!\n"))
233  }
234  }
235  if (out_changed)
236  {
237  TRACE(TGRAPHICS, ("About to Initialise OSD"))
239  {
240  #ifdef OSD_8_BIT
241  STB_OSDSetMhegPalette( 0, NUM_MHEG_COLOURS + PALETTE_OFFSET, (U32BIT *)mg_palette );
242  #endif /*OSD_8_BIT*/
243  }
244  mg_ctxt.hw_handle = STB_OSDMhegSetResolution(outWidth, outHeight, mg_ctxt.colour_format);
245  DVB_MhegSetScalingResolution(outWidth, outHeight);
246  }
247  FUNCTION_FINISH(x)
248 }
249 
250 void MG_OSDMhegInit( U16BIT inWidth, U16BIT inHeight, E_ASPECT_RATIO sar )
251 {
252  FUNCTION_START(x)
253 #ifdef NO_SCALE_ASPECT
254  USE_UNWANTED_PARAM(sar);
255 #else
257  {
258  if (!mg_ctxt.offset_left)
259  {
260  MG_OSDclear();
261  }
262  mg_ctxt.offset_left = mg_ctxt.out_osd_width >> 3;
263  }
264  else
265  {
266  if (mg_ctxt.offset_left)
267  {
268  MG_OSDclear();
269  }
270  mg_ctxt.offset_left = 0;
271  }
272 #endif /*NO_SCALE_ASPECT*/
273  MG_OSDInit( inWidth, inHeight, mg_ctxt.out_osd_width, mg_ctxt.out_osd_height );
274  FUNCTION_FINISH(x)
275 }
276 
281 E_MhegErr MG_Initialise( U16BIT screenWidth, U16BIT screenHeight, U8BIT colourDepth )
282 {
283  E_MhegErr result;
284  FUNCTION_START(x)
285  TRACE(TSTATE, ("(screen= %d x %d, %d bit)", screenWidth, screenHeight, colourDepth))
286  if (colourDepth == 0)
287  {
288  /* Resolution change, just get the current value */
289  colourDepth = mg_ctxt.colour_format;
290  }
291  else
292  {
293  mg_ctxt.colour_format = colourDepth;
294  }
295  if (screenWidth < 720 || screenHeight < 576
296  #ifndef OSD_8_BIT
297  || (colourDepth == COLOUR_FORMAT_PALETTE)
298  #endif
299  #ifndef OSD_16_BIT
300  || (colourDepth == COLOUR_FORMAT_ARGB4444)
301  #endif
302  #ifndef OSD_31_BIT
303  || (colourDepth == COLOUR_FORMAT_ARGB7888)
304  #endif
305  #ifndef OSD_32_BIT
306  || (colourDepth == COLOUR_FORMAT_ARGB8888)
307  #endif
308  )
309  {
310  DPL1(("- Invalid Graphic Capabilities\n"));
311  result = MHERR_BAD_PARAMETER;
312  TRACE(TSTATE,("result=%d",result))
313  }
314  else
315  {
316  result = MHERR_OK;
317 
318  #if defined(OSD_31_BIT) && defined(OSD_32_BIT)
319  // ST platform
320  mg_ctxt.max_alpha = (mg_ctxt.colour_format == COLOUR_FORMAT_ARGB7888) ? 128 : 255;
321  #endif
322 
323  mg_ctxt.out_video_width = screenWidth;
324  mg_ctxt.out_video_height = screenHeight;
325 
326  TRACE(TSTATE,("result=%d",result))
327 
328  #ifdef OSD_8_BIT
330  {
331  TRACE(TSTATE,("result=%d",result))
332  mg_palette = &dbook_colour_palette[NUM_SUBT_COLOURS - PALETTE_OFFSET];
333  if (mg_ctxt.hw_handle == NULL)
334  {
335  mg_ctxt.hw_handle = STB_OSDMhegCreateSurface( screenWidth, screenHeight, TRUE, 0 );
336  if (mg_ctxt.hw_handle == NULL)
337  {
338  result = MHERR_OTHER;
339  }
340  }
341  mg_ctxt.screen_stride = screenWidth;
342  if (mg_ctxt.screen_buff == NULL)
343  {
344  mg_ctxt.screen_buff = STB_OSDMhegLockBuffer( mg_ctxt.hw_handle, &mg_ctxt.screen_stride );
345  }
346  TRACE(TGRAPHICS, ("hdl=0x%x, buff=0x%x, stride=%d cft=%d", mg_ctxt.hw_handle,
347  mg_ctxt.screen_buff, mg_ctxt.screen_stride, mg_ctxt.colour_format))
348  }
349  #endif /*OSD_8_BIT*/
350 
351  MG_OSDInit( SD_WIDTH, SD_HEIGHT, screenWidth, screenHeight );
352  }
353  TRACE(TSTATE,("result=%d",result))
354  FUNCTION_FINISH(x)
355  return result;
356 }
357 
367 void MG_Terminate(void)
368 {
369  FUNCTION_START(OSDExit)
370 
371  #ifdef OSD_8_BIT
372  if (mg_ctxt.screen_buff != NULL)
373  {
376  mg_ctxt.screen_buff = NULL;
377  }
378  #endif
379 
380  MG_FontExit();
381 
382  mg_ctxt.out_osd_width = 0;
383 
384  FUNCTION_FINISH(OSDExit)
385 }
386 
387 #ifdef OSD_8_BIT
388 
397 static void DrawRectangle8Bit( S_REGION rgn, U8BIT colour_index, BOOLEAN overwrite )
398 {
399  U16BIT x, y, w;
400  U8BIT *buffer;
401 
402  assert( colour_index < NUM_MHEG_COLOURS );
403 
404  w = rgn.right - rgn.left;
405  buffer = mg_ctxt.screen_buff;
406  buffer += (rgn.top * mg_ctxt.screen_stride) + rgn.left;
407 
408  TRACE(TGRAPHICS, ("rgn=%d,%d,%d,%d col=0x%x ow=%d", rgn.left, rgn.top, rgn.right, rgn.bottom, colour_index, overwrite))
409  /*TRACE(TGRAPHICS,("b=0x%x",buffer))*/
410  if (overwrite)
411  {
412  for (y = rgn.top; y != rgn.bottom; y++)
413  {
414  memset(buffer, colour_index, w );
415  buffer += mg_ctxt.screen_stride;
416  }
417  }
418  else
419  {
420  w = mg_ctxt.screen_stride - w;
421  for (y = rgn.top; y != rgn.bottom; y++)
422  {
423  for (x = rgn.left; x != rgn.right; x++)
424  {
425  OSD_BlendPixels(buffer, colour_index);
426  ++buffer;
427  }
428  buffer += w;
429  }
430  }
431  /* Update region size */
432  if (rgn.left < osd_update_rgn.left)
433  {
434  osd_update_rgn.left = rgn.left;
435  }
436  if (rgn.top < osd_update_rgn.top)
437  {
438  osd_update_rgn.top = rgn.top;
439  }
440  if (rgn.right > osd_update_rgn.right)
441  {
442  osd_update_rgn.right = rgn.right;
443  }
444  if (rgn.bottom > osd_update_rgn.bottom)
445  {
446  osd_update_rgn.bottom = rgn.bottom;
447  }
448 }
449 
450 #endif /* OSD_8_BIT */
451 
452 
459 static void DrawClippedRectangle( S_REGION *overlap, S_REGION rgn, OSDColor fore_col )
460 {
461  if (rgn.left < overlap->left)
462  {
463  rgn.left = overlap->left;
464  }
465  if (rgn.right > overlap->right)
466  {
467  rgn.right = overlap->right;
468  }
469  if (rgn.top < overlap->top)
470  {
471  rgn.top = overlap->top;
472  }
473  if (rgn.bottom > overlap->bottom)
474  {
475  rgn.bottom = overlap->bottom;
476  }
477  if ((rgn.bottom > rgn.top) && (rgn.right > rgn.left))
478  {
479  TRACE(TGRAPHICS, ("region (%d,%d,%d,%d)", rgn.left, rgn.top, rgn.right, rgn.bottom))
481  {
482  #ifdef OSD_8_BIT
483  if (fore_col != OFFSET_TRANS)
484  {
485  /*TRACE(TGRAPHICS,("col=0x%x",fore_col))*/
486  DrawRectangle8Bit( rgn, (U8BIT)fore_col, (fore_col >= OFFSET_OPAQUE));
487  }
488  #endif
489  }
491  {
492  #ifdef OSD_16_BIT
493  if ((fore_col & C2L_ALPHA_CHNNL) != 0)
494  {
495  S_RECTANGLE rect;
496  rect.left = rgn.left;
497  rect.width = rgn.right - rgn.left;
498  rect.top = rgn.top;
499  rect.height = rgn.bottom - rgn.top;
500  #ifndef NO_SCALE_ASPECT
501  if (mg_ctxt.offset_left)
502  {
503  rect.left *= 3;
504  rect.left >>= 2;
505  rect.left += mg_ctxt.offset_left;
506  rect.width *= 3;
507  rect.width >>= 2;
508  }
509  #endif /*NO_SCALE_ASPECT*/
510  //TRACE(TGRAPHICS,("actual (%d,%d,%d,%d)",rect.left, rect.top, rect.left+rect.width, rect.top+rect.height));
511  STB_OSDMhegFillRectangle( &rect, fore_col, ((fore_col & C2L_ALPHA_CHNNL) == C2L_ALPHA_CHNNL) ?
513  }
514  #endif
515  }
516 
517  ELSE
518  {
519  #if defined(OSD_31_BIT) || defined(OSD_32_BIT)
520  if ((fore_col & C4L_ALPHA_CHNNL) != 0)
521  {
522  S_RECTANGLE rect;
523  OSDColor col;
524  ConvertAlpha(fore_col, col);
525  rect.left = rgn.left;
526  rect.width = rgn.right - rgn.left;
527  rect.top = rgn.top;
528  rect.height = rgn.bottom - rgn.top;
529  #ifndef NO_SCALE_ASPECT
530  if (mg_ctxt.offset_left)
531  {
532  rect.left *= 3;
533  rect.left >>= 2;
534  rect.left += mg_ctxt.offset_left;
535  rect.width *= 3;
536  rect.width >>= 2;
537  }
538  #endif /*NO_SCALE_ASPECT*/
539  //TRACE(TGRAPHICS,("actual (%d,%d,%d,%d)",rect.left, rect.top, rect.left+rect.width, rect.top+rect.height))
540  STB_OSDMhegFillRectangle( &rect, col, ((col >> 24) == MAX_ALPHA) ?
542  }
543  #endif
544  }
545  }
546 }
547 
566 void MG_OSDdisplayRectangle( S_REGION *overlap, int x, int y, int width, int height,
567  int line_width, /*int lineStyle,*/ OSDColor lineColour, OSDColor fillColour )
568 {
569  OSDColor tmp_col;
570  S_REGION scaled_overlap;
571  TRACE(TGRAPHICS, ("x=%d,y=%d,w=%d,h=%d", x, y, width, height));
572  if (width > 0 && height > 0)
573  {
574  S_REGION rgn, outline_region, inner_region;
575  rgn.left = x;
576  rgn.top = y;
577  rgn.right = x + width;
578  rgn.bottom = y + height;
579  scaled_overlap = *overlap;
580  TRACE(TGRAPHICS, ("line_width=%d line_col=%x fill_col=%x", line_width, lineColour, fillColour));
581 
583  {
584  #ifdef OSD_8_BIT
585  tmp_col = (OSDColor)OSD_FindNearestColourIndex(lineColour);
586  #endif
587  }
589  {
590  #ifdef OSD_16_BIT
591  tmp_col = MakeHD2Color( lineColour );
592  rgn.left = HD_X_SCALEUP(rgn.left);
593  rgn.top = HD_Y_SCALEUP(rgn.top);
594  rgn.right = HD_X_SCALEUP(rgn.right);
595  rgn.bottom = HD_Y_SCALEUP(rgn.bottom);
596  scaled_overlap.left = HD_X_SCALEUP(overlap->left);
597  scaled_overlap.top = HD_Y_SCALEUP(overlap->top);
598  scaled_overlap.right = HD_X_SCALEUP(overlap->right);
599  scaled_overlap.bottom = HD_Y_SCALEUP(overlap->bottom);
600  line_width = HD_W_SCALEUP(line_width);
601  #endif
602  }
603 
604  ELSE
605  {
606  #if defined(OSD_31_BIT) || defined(OSD_32_BIT)
607  tmp_col = lineColour;
608  rgn.left = HD_X_SCALEUP(rgn.left);
609  rgn.top = HD_Y_SCALEUP(rgn.top);
610  rgn.right = HD_X_SCALEUP(rgn.right);
611  rgn.bottom = HD_Y_SCALEUP(rgn.bottom);
612  scaled_overlap.left = HD_X_SCALEUP(overlap->left);
613  scaled_overlap.top = HD_Y_SCALEUP(overlap->top);
614  scaled_overlap.right = HD_X_SCALEUP(overlap->right);
615  scaled_overlap.bottom = HD_Y_SCALEUP(overlap->bottom);
616  line_width = HD_W_SCALEUP(line_width);
617  #endif
618  }
619 
620  assert( rgn.right >= rgn.left );
621  assert( rgn.bottom >= rgn.top );
622 
623  if (line_width > (rgn.right - rgn.left))
624  {
625  line_width = rgn.right - rgn.left;
626  }
627  if (line_width > (rgn.bottom - rgn.top))
628  {
629  line_width = rgn.bottom - rgn.top;
630  }
631 
632  if (line_width > 0)
633  {
634  TRACE(TGRAPHICS, ("l_col=%x", tmp_col));
635 
636  /* Check if we can combine all into a single rectangle (without any "inner" area) */
637  if ((rgn.top + line_width >= rgn.bottom - line_width) ||
638  (rgn.left + line_width >= rgn.right - line_width))
639  {
640  /* Combine into a single rectangle */
641  outline_region.left = rgn.left;
642  outline_region.top = rgn.top;
643  outline_region.right = rgn.right;
644  outline_region.bottom = rgn.bottom;
645 
646  DrawClippedRectangle( &scaled_overlap, outline_region, tmp_col );
647  }
648  else
649  {
650  /* Top */
651  outline_region.left = rgn.left;
652  outline_region.top = rgn.top;
653  outline_region.bottom = rgn.top + line_width;
654  outline_region.right = rgn.right;
655 
656  DrawClippedRectangle( &scaled_overlap, outline_region, tmp_col );
657 
658  /* Bottom */
659  outline_region.left = rgn.left;
660  outline_region.top = rgn.bottom - line_width;
661  outline_region.bottom = rgn.bottom;
662  outline_region.right = rgn.right;
663 
664  DrawClippedRectangle( &scaled_overlap, outline_region, tmp_col );
665 
666  /* Left */
667  outline_region.left = rgn.left;
668  outline_region.top = rgn.top + line_width;
669  outline_region.bottom = rgn.bottom - line_width;
670  outline_region.right = rgn.left + line_width;
671 
672  DrawClippedRectangle( &scaled_overlap, outline_region, tmp_col );
673 
674  /* Right */
675  outline_region.left = rgn.right - line_width;
676  outline_region.top = rgn.top + line_width;
677  outline_region.bottom = rgn.bottom - line_width;
678  outline_region.right = rgn.right;
679 
680  DrawClippedRectangle( &scaled_overlap, outline_region, tmp_col );
681  }
682  }
683  if (width > line_width && height > line_width)
684  {
686  {
687  #ifdef OSD_8_BIT
688  tmp_col = (OSDColor)OSD_FindNearestColourIndex(fillColour);
689  #endif
690  }
692  {
693  #ifdef OSD_16_BIT
694  tmp_col = MakeHD2Color( fillColour );
695  #endif
696  }
697 
698  ELSE
699  {
700  #if defined(OSD_31_BIT) || defined(OSD_32_BIT)
701  tmp_col = fillColour;
702  #endif
703  }
704  TRACE(TGRAPHICS, ("f_col=%x", tmp_col))
705 
706  inner_region.left = rgn.left + line_width;
707  inner_region.top = rgn.top + line_width;
708  inner_region.right = rgn.right - line_width;
709  inner_region.bottom = rgn.bottom - line_width;
710 
711  DrawClippedRectangle( &scaled_overlap, inner_region, tmp_col );
712  }
713  }
714 }
715 
730 {
731  FUNCTION_START(OSDDisplayVideo)
732 
733  TRACE(TGRAPHICS, ("OSDdisplayVideo( %d,%d,%d,%d )\n", rgn.top, rgn.left, rgn.right, rgn.bottom))
734 
735  /* 'punch' hole through OSD for viewing video behind */
736  if ((rgn.bottom > rgn.top) && (rgn.right > rgn.left))
737  {
739  {
740  #ifdef OSD_8_BIT
741  DrawRectangle8Bit( rgn, 0, TRUE );
742  #endif
743  }
745  {
746  #ifdef OSD_16_BIT
747  S_RECTANGLE rect;
748  rgn.top = HD_Y_SCALEUP(rgn.top);
749  rgn.bottom = HD_Y_SCALEUP(rgn.bottom);
750  rgn.left = HD_X_SCALEUP(rgn.left);
751  rgn.right = HD_X_SCALEUP(rgn.right);
752  rect.left = rgn.left;
753  rect.top = rgn.top;
754  rect.width = rgn.right - rgn.left;
755  rect.height = rgn.bottom - rgn.top;
756  #ifndef NO_SCALE_ASPECT
757  if (mg_ctxt.offset_left)
758  {
759  rect.left *= 3;
760  rect.left >>= 2;
761  rect.left += mg_ctxt.offset_left;
762  rect.width *= 3;
763  rect.width >>= 2;
764  }
765  #endif /*NO_SCALE_ASPECT*/
767  #endif
768  }
769 
770  ELSE
771  {
772  #if defined(OSD_31_BIT) || defined(OSD_32_BIT)
773  S_RECTANGLE rect;
774  rgn.top = HD_Y_SCALEUP(rgn.top);
775  rgn.bottom = HD_Y_SCALEUP(rgn.bottom);
776  rgn.left = HD_X_SCALEUP(rgn.left);
777  rgn.right = HD_X_SCALEUP(rgn.right);
778  rect.left = rgn.left;
779  rect.top = rgn.top;
780  rect.width = rgn.right - rgn.left;
781  rect.height = rgn.bottom - rgn.top;
782  #ifndef NO_SCALE_ASPECT
783  if (mg_ctxt.offset_left)
784  {
785  rect.left *= 3;
786  rect.left >>= 2;
787  rect.left += mg_ctxt.offset_left;
788  rect.width *= 3;
789  rect.width >>= 2;
790  }
791  #endif /*NO_SCALE_ASPECT*/
793  #endif
794  }
795  }
796 
797  TRACE(TGRAPHICS, (""))
798  FUNCTION_FINISH(OSDDisplayVideo)
799 }
800 
808 void MG_OSDerase( S_REGION rgn, OSDColor colour )
809 {
810  FUNCTION_START(OSDerase);
811 
812  TRACE(TGRAPHICS, ("region (%d,%d,%d,%d)", rgn.left, rgn.top, rgn.right, rgn.bottom))
813  /* Clear area to black */
814  if ((rgn.bottom > rgn.top) && (rgn.right > rgn.left))
815  {
817  {
818  #ifdef OSD_8_BIT
819  DrawRectangle8Bit( rgn, OSD_FindNearestColourIndex(colour), TRUE );
820  #endif
821  }
823  {
824  #ifdef OSD_16_BIT
825  S_RECTANGLE rect;
826  rgn.top = HD_Y_SCALEUP(rgn.top);
827  rgn.bottom = HD_Y_SCALEUP(rgn.bottom);
828  rgn.left = HD_X_SCALEUP(rgn.left);
829  rgn.right = HD_X_SCALEUP(rgn.right);
830  //TRACE(TGRAPHICS,("actual(%d,%d,%d,%d)",rgn.left, rgn.top, rgn.right, rgn.bottom))
831  rect.left = rgn.left;
832  rect.top = rgn.top;
833  rect.width = rgn.right - rgn.left;
834  rect.height = rgn.bottom - rgn.top;
835  #ifndef NO_SCALE_ASPECT
836  if (mg_ctxt.offset_left)
837  {
838  rect.left *= 3;
839  rect.left >>= 2;
840  rect.left += mg_ctxt.offset_left;
841  rect.width *= 3;
842  rect.width >>= 2;
843  }
844  #endif /*NO_SCALE_ASPECT*/
846  #endif
847  }
848 
849  ELSE
850  {
851  #if defined(OSD_31_BIT) || defined(OSD_32_BIT)
852  S_RECTANGLE rect;
853  OSDColor col;
854  ConvertAlpha(colour, col);
855  rgn.top = HD_Y_SCALEUP(rgn.top);
856  rgn.bottom = HD_Y_SCALEUP(rgn.bottom);
857  rgn.left = HD_X_SCALEUP(rgn.left);
858  rgn.right = HD_X_SCALEUP(rgn.right);
859  //TRACE(TGRAPHICS,("actual(%d,%d,%d,%d)",rgn.left, rgn.top, rgn.right, rgn.bottom))
860  rect.left = rgn.left;
861  rect.top = rgn.top;
862  rect.width = rgn.right - rgn.left;
863  rect.height = rgn.bottom - rgn.top;
864  #ifndef NO_SCALE_ASPECT
865  if (mg_ctxt.offset_left)
866  {
867  rect.left *= 3;
868  rect.left >>= 2;
869  rect.left += mg_ctxt.offset_left;
870  rect.width *= 3;
871  rect.width >>= 2;
872  }
873  #endif /*NO_SCALE_ASPECT*/
875  #endif
876  }
877  }
878 
879  FUNCTION_FINISH(OSDerase)
880 }
881 
888 void MG_OSDclear(void)
889 {
891  TRACE(TGRAPHICS, (""))
893  {
894  #ifdef OSD_8_BIT
895  S_REGION rgn = { 0, 0, 720, 576 };
896  DrawRectangle8Bit( rgn, 0, TRUE );
897  MG_OSDUpdate();
898  #endif
899  }
900  ELSE
901  {
902  #if defined(OSD_16_BIT) || defined(OSD_31_BIT) || defined(OSD_32_BIT)
905  #endif
906  }
908 }
909 
910 #ifdef OSD_8_BIT
911 
912 void MG_OSDUpdate( void )
913 {
915  {
916  S_RECTANGLE rect;
917  rect.left = osd_update_rgn.left;
918  rect.top = osd_update_rgn.top;
919  rect.width = osd_update_rgn.right - osd_update_rgn.left;
920  rect.height = osd_update_rgn.bottom - osd_update_rgn.top;
921  #ifdef _TRACING
922  {
923  U8BIT *data;
924  data = (U8BIT *)mg_ctxt.screen_buff + (osd_update_rgn.top * mg_ctxt.screen_stride) + osd_update_rgn.left;
925  data += mg_ctxt.screen_stride * (rect.height / 2);
926  TRACE(TGRAPHICS, ("Middle OSD Line:"))
927  TRACE_BUFF(TGRAPHICS, data, rect.width)
928  }
929  #endif
930  TRACE(TGRAPHICS, ("regn (%d,%d,%d,%d)", osd_update_rgn.left, osd_update_rgn.top,
931  osd_update_rgn.right, osd_update_rgn.bottom))
932  TRACE(TGRAPHICS, ("rect (%d,%d,%d,%d)", rect.left, rect.top, rect.width, rect.height))
933  STB_OSDMhegBlitBitmap( mg_ctxt.hw_handle, &rect, mg_ctxt.screen_stride,
934  osd_update_rgn.left, osd_update_rgn.top, STB_BLIT_COPY );
936  osd_update_rgn.left = mg_ctxt.out_osd_width;
937  osd_update_rgn.top = mg_ctxt.out_osd_height;
938  osd_update_rgn.right = 0;
939  osd_update_rgn.bottom = 0;
940  }
941  ELSE
942  {
943  TRACE(TGRAPHICS, (""))
944  #if defined(OSD_16_BIT) || defined(OSD_32_BIT)
946  #endif
947  }
948 }
949 
960 U8BIT OSD_FindNearestColourIndex(OSDColor target)
961 {
962  U8BIT r, g, b, a;
963  static OSDColor target_cache = 0x00000000;
964  static U8BIT offset_cache = OFFSET_TRANS;
965  static const NearCol mg_nearest_colour = {
966  /* red */ {0, 27, 27, 54, 54, 81, 81, 108},
967  /* green*/ {0, 3, 3, 6, 6, 9, 9, 12, 12, 15, 15, 18, 18, 21, 21, 24},
968  /* blue */ {0, 1, 1, 2}
969  };
970 
971  if (target != target_cache)
972  {
973  target_cache = target;
974 
975  a = (U8BIT)(((target >> 24) & 0xff) ^ 0xff);
976  r = (U8BIT)((target >> 16) & 0xff);
977  g = (U8BIT)((target >> 8) & 0xff);
978  b = (U8BIT)(target & 0xff);
979 
980  if (a < 0x19)
981  {
982  if (r == g && g == b && ((r > 21 && r < 106) || (r > 148 && r < 233)))
983  {
984  /* grey */
985  offset_cache = (r >> 6) + OFFSET_GREY;
986  }
987  else
988  {
989  /* opaque */
990  offset_cache = mg_nearest_colour.red[r >> 5] + mg_nearest_colour.green[g >> 4] +
991  mg_nearest_colour.blue[b >> 6] + OFFSET_BLACK;
992  }
993  }
994  else if (a <= 0xe6)
995  {
996  /* semi-transparent */
997  offset_cache = (b >> 7) + OFFSET_SEMI;
998 
999  if (r & 0x80)
1000  {
1001  if (r <= 212)
1002  {
1003  offset_cache += 4;
1004  }
1005  else
1006  {
1007  offset_cache += 6;
1008  }
1009  }
1010  else
1011  {
1012  if (r > 42)
1013  {
1014  offset_cache += 2;
1015  }
1016  }
1017 
1018  if (g & 0x80)
1019  {
1020  if (g <= 178)
1021  {
1022  offset_cache += 24;
1023  }
1024  else
1025  {
1026  if (g <= 229)
1027  {
1028  offset_cache += 32;
1029  }
1030  else
1031  {
1032  offset_cache += 40;
1033  }
1034  }
1035  }
1036  else
1037  {
1038  if (g <= 71)
1039  {
1040  if (g <= 25)
1041  {
1042  offset_cache += 0;
1043  }
1044  else
1045  {
1046  offset_cache += 8;
1047  }
1048  }
1049  else
1050  {
1051  offset_cache += 16;
1052  }
1053  }
1054  }
1055  else
1056  {
1057  /* fully transparent */
1058  offset_cache = OFFSET_TRANS;
1059  }
1060  }
1061 
1062  return offset_cache;
1063 }
1064 
1074 void OSD_BlendPixels(U8BIT *pixel, U8BIT colour)
1075 {
1076  static U8BIT back_colour_cache[2] = {0, 0};
1077  static U8BIT colour_cache[2] = {0, 0};
1078  static U8BIT offset_cache[2] = {0, 0};
1079  static U8BIT lru = 0;
1080 
1081  U8BIT back_colour;
1082  U8BIT front_red_index, front_green_index, front_blue_index;
1083  U8BIT back_red_index, back_green_index, back_blue_index, back_grey_index;
1084  U8BIT red_index, green_index, blue_index;
1085  U8BIT red_value, green_value, blue_value;
1086  OSDColor back;
1087 
1088  static const U8BIT red_blend[4][8] = {
1089  { 0, 0, 0, 27, 27, 27, 27, 27},
1090  { 27, 27, 27, 54, 54, 54, 54, 54},
1091  { 54, 54, 54, 54, 54, 81, 81, 81},
1092  { 81, 81, 81, 81, 81, 108, 108, 108}
1093  };
1094  static const U8BIT green_blend[6][16] = {
1095  { 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 6, 6, 6, 6, 6},
1096  { 3, 3, 3, 6, 6, 6, 6, 6, 6, 9, 9, 9, 9, 9, 9, 9},
1097  { 6, 9, 9, 9, 9, 9, 9, 9, 9, 12, 12, 12, 12, 12, 12, 15},
1098  { 9, 12, 12, 12, 12, 12, 12, 15, 15, 15, 15, 15, 15, 15, 15, 18},
1099  {12, 15, 15, 15, 15, 15, 15, 18, 18, 18, 18, 18, 18, 21, 21, 21},
1100  {18, 18, 18, 18, 18, 18, 18, 21, 21, 21, 21, 21, 21, 24, 24, 24}
1101  };
1102  static const U8BIT blue_blend[2][4] = {
1103  {0, 0, 0, 1},
1104  {1, 2, 2, 2}
1105  };
1106  static const U8BIT black_red_blend[4] = {0, 59, 119, 179};
1107  static const U8BIT black_green_blend[6] = {0, 35, 71, 107, 143, 179};
1108  static const U8BIT black_blue_blend[2] = {0, 179};
1109  static const U8BIT grey_red_blend[4][4] = {
1110  {12, 25, 50, 63},
1111  {72, 85, 110, 122},
1112  {131, 144, 170, 182},
1113  {191, 204, 229, 242}
1114  };
1115  static const U8BIT grey_green_blend[6][4] = {
1116  {12, 25, 50, 63},
1117  {48, 61, 86, 98},
1118  {84, 96, 122, 134},
1119  {119, 132, 158, 170},
1120  {155, 168, 193, 206},
1121  {191, 204, 229, 242}
1122  };
1123  static const U8BIT grey_blue_blend[2][4] = {
1124  {12, 25, 50, 63},
1125  {191, 204, 229, 242}
1126  };
1127  static const U8BIT back_red[8] = {
1128  0, 63, 63, 127, 127, 191, 191, 255
1129  };
1130  static const U8BIT back_green[16] = {
1131  0, 31, 31, 63, 63, 95, 95, 127, 127, 159, 159, 191, 191, 223, 223, 255
1132  };
1133  static const U8BIT back_blue[4] = {
1134  0, 127, 127, 255
1135  };
1136  static const U8BIT front_red[4] = {
1137  0, 85, 170, 255
1138  };
1139  static const U8BIT front_green[6] = {
1140  0, 51, 102, 153, 204, 255
1141  };
1142  static const U8BIT front_blue[2] = {
1143  0, 255
1144  };
1145  static const U8BIT opaque_grey_blend[2][4] = {
1146  {OFFSET_BLACK, OFFSET_GREY, OFFSET_GREY, OFFSET_GREY + 1},
1147  {OFFSET_GREY + 2, OFFSET_GREY + 3, OFFSET_GREY + 3, OFFSET_WHITE}
1148  };
1149  static const U8BIT grey_grey_blend[2][4] = {
1150  {OFFSET_BLACK, OFFSET_GREY, OFFSET_GREY, OFFSET_GREY},
1151  {OFFSET_GREY + 2, OFFSET_GREY + 2, OFFSET_WHITE, OFFSET_WHITE}
1152  };
1153 
1154  /* Top colour is fully transparent so return immediately leaving
1155  the target pixel unchanged */
1156  assert( colour != OFFSET_TRANS );
1157 
1158  back_colour = *pixel;
1159 
1160  /* Two levels of cache, for text speed-up */
1161  if (back_colour_cache[0] == back_colour &&
1162  colour_cache[0] == colour)
1163  {
1164  *pixel = offset_cache[0];
1165  }
1166  else if (back_colour_cache[1] == back_colour &&
1167  colour_cache[1] == colour)
1168  {
1169  *pixel = offset_cache[1];
1170  }
1171  else
1172  {
1173  back_colour_cache[lru] = back_colour;
1174  colour_cache[lru] = colour;
1175 
1176  if (colour >= OFFSET_OPAQUE || back_colour < OFFSET_OPAQUE)
1177  {
1178  /* Back colour is (semi-)transparent, or front colour is opaque */
1179  offset_cache[lru] = colour;
1180  }
1181  else
1182  {
1183  assert( mg_palette != NULL );
1184 
1185  /* Front colour is semi-transparent, back colour is opaque */
1186  colour -= OFFSET_SEMI;
1187  back = mg_palette[*pixel];
1188 
1189  front_red_index = (colour >> 1) & 0x3; /* Front red index */
1190  front_green_index = (colour >> 3) & 0x7; /* Front green index */
1191  front_blue_index = colour & 0x1; /* Front blue index */
1192  if (back_colour == OFFSET_BLACK)
1193  {
1194  /* Back colour is black */
1195 
1196  /* Lookup blended colours */
1197  red_value = black_red_blend[front_red_index];
1198  green_value = black_green_blend[front_green_index];
1199  blue_value = black_blue_blend[front_blue_index];
1200  offset_cache[lru] = OSD_FindNearestColourIndex((0xff << 24) | (red_value << 16) | (green_value << 8) | blue_value);
1201  }
1202  else if (back_colour > OFFSET_BLACK)
1203  {
1204  /* Back colour is not grey */
1205  back_red_index = (back >> 21) & 0x7;
1206  back_green_index = (back >> 12) & 0xf;
1207  back_blue_index = (back >> 6) & 0x3;
1208 
1209  /* Special case: "grey" on "grey" */
1210  if (back_red[back_red_index] == back_green[back_green_index] &&
1211  back_red[back_red_index] == back_blue[back_blue_index] &&
1212  front_red[front_red_index] == front_green[front_green_index] &&
1213  front_red[front_red_index] == front_blue[front_blue_index])
1214  {
1215  /* Approximate as grey ONLY */
1216  offset_cache[lru] = opaque_grey_blend[back_blue_index][front_blue_index];
1217  }
1218  else
1219  {
1220  /* Lookup blended indices */
1221  red_index = red_blend[front_red_index][back_red_index];
1222  green_index = green_blend[front_green_index][back_green_index];
1223  blue_index = blue_blend[front_blue_index][back_blue_index];
1224 
1225  /* Semi-transparent on opaque is opaque */
1226  offset_cache[lru] = OFFSET_BLACK + red_index + green_index + blue_index;
1227  }
1228  }
1229  else
1230  {
1231  /* Back colour is grey */
1232  back_grey_index = (back >> 6) & 0x3;
1233 
1234  /* Special case: real grey on "grey" */
1235  if (front_red[front_red_index] == front_green[front_green_index] &&
1236  front_red[front_red_index] == front_blue[front_blue_index])
1237  {
1238  offset_cache[lru] = grey_grey_blend[front_blue_index][back_grey_index];
1239  }
1240  else
1241  {
1242  /* Lookup blended colours */
1243  red_value = grey_red_blend[front_red_index][back_grey_index];
1244  green_value = grey_green_blend[front_green_index][back_grey_index];
1245  blue_value = grey_blue_blend[front_blue_index][back_grey_index];
1246  offset_cache[lru] = OSD_FindNearestColourIndex((0xff << 24) | (red_value << 16) | (green_value << 8) | blue_value);
1247  }
1248  }
1249  }
1250  *pixel = offset_cache[lru];
1251  lru = 1 - lru;
1252  }
1253 }
1254 
1255 #endif /* OSD_8_BIT */
1256 
1266 void MG_DisplayImage( S_SURFACE *surf, S_REGION *overlap, S32BIT x, S32BIT y )
1267 {
1268  S32BIT w1, y1, w2, y2;
1269  S32BIT fr, tr, fc, tc;
1270 
1271  assert( surf );
1272 
1273  /* Calculate rows and columns in update region - (without considering possible 4:3 aspect) */
1274  w1 = (overlap->left * mg_ctxt.osd_x.mlt) / mg_ctxt.osd_x.div;
1275  w2 = (overlap->right * mg_ctxt.osd_x.mlt) / mg_ctxt.osd_x.div;
1276 
1277  y1 = (overlap->top * mg_ctxt.osd_y.mlt) / mg_ctxt.osd_y.div;
1278  y2 = (overlap->bottom * mg_ctxt.osd_y.mlt) / mg_ctxt.osd_y.div;
1279 
1280  TRACE(TGRAPHICS, ("HDoverlap(l=%d,t=%d,r=%d,b=%d)", w1, y1, w2, y2))
1281  TRACE(TGRAPHICS, ("Surf(%d,%d) type=%d posn(%d,%d)", surf->width, surf->height, surf->srf_type, x, y))
1282 
1283  /* from column */
1284  if (x < w1)
1285  {
1286  fc = w1 - x;
1287  x = w1;
1288  }
1289  else
1290  {
1291  fc = 0;
1292  }
1293 
1294  /* to column */
1295  tc = surf->width;
1296  if (x + tc - fc > w2)
1297  {
1298  tc = fc + w2 - x;
1299  }
1300 
1301  /* from row */
1302  if (y < y1)
1303  {
1304  fr = y1 - y;
1305  y = y1;
1306  }
1307  else
1308  {
1309  fr = 0;
1310  }
1311 
1312  /* to row */
1313  tr = surf->height;
1314  if (y + tr - fr > y2)
1315  {
1316  tr = fr + y2 - y;
1317  }
1318 
1319  if (fc < tc && fr < tr)
1320  {
1321  TRACE(TGRAPHICS, ("actual(l=%d,t=%d,r=%d,b=%d)", x + fc, y + fr, x + tc, y + tr))
1322 
1324  {
1325  #ifdef OSD_8_BIT
1326  S32BIT i, j;
1327  U8BIT *pixndx, *srfndx;
1328 
1329  w1 = tc - fc;
1330  y1 = tr - fr;
1331 
1332  pixndx = mg_ctxt.screen_buff;
1333  pixndx += y * mg_ctxt.screen_stride + x;
1334  srfndx = surf->col_buff;
1335  srfndx += fr * surf->width + fc;
1336  if (surf->opaque)
1337  {
1338  w2 = surf->width;
1339  y2 = mg_ctxt.screen_stride;
1340  for (i = fr; i != tr; ++i)
1341  {
1342  memcpy(pixndx, srfndx, w1);
1343  pixndx += y2;
1344  srfndx += w2;
1345  }
1346  }
1347  else
1348  {
1349  w2 = surf->width - w1;
1350  y2 = mg_ctxt.screen_stride - w1;
1351  for (i = fr; i != tr; ++i)
1352  {
1353  for (j = fc; j != tc; ++j)
1354  {
1355  if (*srfndx != OFFSET_TRANS)
1356  {
1357  OSD_BlendPixels(pixndx, *srfndx);
1358  }
1359  ++pixndx;
1360  ++srfndx;
1361  }
1362  srfndx += w2;
1363  pixndx += y2;
1364  }
1365  }
1366  /* Update region size */
1367  if (x < osd_update_rgn.left)
1368  {
1369  osd_update_rgn.left = x;
1370  }
1371  if (y < osd_update_rgn.top)
1372  {
1373  osd_update_rgn.top = y;
1374  }
1375  if (x + w1 > osd_update_rgn.right)
1376  {
1377  osd_update_rgn.right = x + w1;
1378  }
1379  if (y + y1 > osd_update_rgn.bottom)
1380  {
1381  osd_update_rgn.bottom = y + y1;
1382  }
1383  #endif /*OSD_8_BIT*/
1384  }
1386  {
1387  #ifdef OSD_16_BIT
1388  S_RECTANGLE rect;
1389  rect.left = fc;
1390  rect.top = fr;
1391  rect.width = tc - fc;
1392  rect.height = tr - fr;
1393  #ifdef NO_SCALE_ASPECT
1394  STB_OSDMhegBlitBitmap( surf->hw_handle, &rect, surf->buff_pitch, x, y,
1395  (surf->opaque) ? STB_BLIT_COPY : STB_BLIT_A_BLEND );
1396  #else
1397  {
1398  S_RECTANGLE dstr;
1399  dstr.top = y;
1400  dstr.height= rect.height;
1401  if (mg_ctxt.offset_left)
1402  {
1403  dstr.left = ((x*3)/4) + mg_ctxt.offset_left;
1404  dstr.width = (rect.width*3)/4;
1405  }
1406  else
1407  {
1408  dstr.left = x;
1409  dstr.width = rect.width;
1410  }
1411  STB_OSDMhegBlitStretch( &rect, surf->hw_handle, &dstr, mg_ctxt.hw_handle,
1412  (surf->opaque) ? STB_BLIT_COPY : STB_BLIT_A_BLEND );
1413  }
1414  #endif /*NO_SCALE_ASPECT*/
1415  #endif
1416  }
1417 
1418  ELSE
1419  {
1420  #if defined(OSD_31_BIT) || defined(OSD_32_BIT)
1421  S_RECTANGLE rect;
1422  rect.left = fc;
1423  rect.top = fr;
1424  rect.width = tc - fc;
1425  rect.height = tr - fr;
1426  #ifdef NO_SCALE_ASPECT
1427  STB_OSDMhegBlitBitmap( surf->hw_handle, &rect, surf->buff_pitch, x, y,
1428  (surf->opaque) ? STB_BLIT_COPY : STB_BLIT_A_BLEND );
1429  #else
1430  {
1431  S_RECTANGLE dstr;
1432  dstr.top = y;
1433  dstr.height= rect.height;
1434  if (mg_ctxt.offset_left)
1435  {
1436  dstr.left = ((x*3)/4) + mg_ctxt.offset_left;
1437  dstr.width = (rect.width*3)/4;
1438  }
1439  else
1440  {
1441  dstr.left = x;
1442  dstr.width = rect.width;
1443  }
1444  STB_OSDMhegBlitStretch( &rect, surf->hw_handle, &dstr, mg_ctxt.hw_handle,
1445  (surf->opaque) ? STB_BLIT_COPY : STB_BLIT_A_BLEND );
1446  }
1447  #endif /*NO_SCALE_ASPECT*/
1448  #endif /*OSD_32_BIT*/
1449  }
1450  }
1451 }
1452 
1453 void MG_OSDdisplayImage( void *data, S_REGION *overlap, int x, int y )
1454 {
1455  MG_DisplayImage((S_SURFACE *)data, overlap,
1456  (x * mg_ctxt.osd_x.mlt) / mg_ctxt.osd_x.div,
1457  (y * mg_ctxt.osd_y.mlt) / mg_ctxt.osd_y.div );
1458 }
1459 
1460 #ifdef SRF_MEM_DGB
1461 static S_SURFACE *surflist_head = NULL;
1462 static S_SURFACE *surflist_tail = NULL;
1463 static U32BIT surfpixel_total = 0;
1464 static U32BIT surfpixel_tmax = 0;
1465 
1466 void OSD_DbgAddSurf( S_SURFACE *srf )
1467 {
1468  assert( srf != NULL );
1469  if (surflist_tail == NULL)
1470  {
1471  /*first one*/
1472  assert( surflist_head == NULL );
1473  surflist_head = srf;
1474  surflist_tail = srf;
1475  srf->prev = NULL;
1476  }
1477  else
1478  {
1479  surflist_tail->next = srf;
1480  srf->prev = surflist_tail;
1481  surflist_tail = srf;
1482  }
1483  srf->next = NULL;
1484  surfpixel_total += srf->width * srf->height;
1485  if (surfpixel_total > surfpixel_tmax)
1486  {
1487  surfpixel_tmax = surfpixel_total;
1488  }
1489 }
1490 
1491 void OSD_DbgRemSurf( S_SURFACE *srf )
1492 {
1493  assert( srf != NULL );
1494  surfpixel_total -= srf->width * srf->height;
1495  if (surflist_head == srf)
1496  {
1497  surflist_head = srf->next;
1498  if (surflist_head != NULL)
1499  {
1500  surflist_head->prev = NULL;
1501  }
1502  }
1503  else
1504  {
1505  assert( srf->prev );
1506  srf->prev->next = srf->next;
1507  }
1508  if (surflist_tail == srf)
1509  {
1510  surflist_tail = srf->prev;
1511  if (surflist_tail != NULL)
1512  {
1513  surflist_tail->next = NULL;
1514  }
1515  }
1516  else
1517  {
1518  assert( srf->next );
1519  srf->next->prev = srf->prev;
1520  }
1521 }
1522 
1523 void OSD_DbgListSrf(void)
1524 {
1525  S_SURFACE *srf = surflist_head;
1526 }
1527 
1528 #endif /*SRF_MEM_DGB*/
1529 
1536 void MG_FreeData( void *data )
1537 {
1538  S_SURFACE *srf = (S_SURFACE *)data;
1539  assert(data);
1541  {
1542  #ifdef OSD_8_BIT
1543  if (srf->col_buff != NULL)
1544  {
1545  OSD_MemFree( srf->col_buff );
1546  }
1547  #endif
1548  }
1549  ELSE
1550  {
1551  #if defined(OSD_16_BIT) || defined(OSD_31_BIT) || defined(OSD_32_BIT)
1552  if (srf->hw_handle)
1553  {
1555  OSD_DbgRemSurf( srf );
1556  }
1557  #endif
1558  }
1559  OSD_MemFree( data );
1560 }
1561 
1562 #ifdef SURFACE_THRESHOLD
1563 
1570 void MG_ApplySurfaceThreshold(void **data, S32BIT threshold)
1571 {
1572  S_SURFACE *surface;
1573  S32BIT total;
1574 
1575  if (*data != NULL && threshold > 0)
1576  {
1577  surface = (*data);
1578  total = surface->width * surface->height;
1579  if (total >= threshold)
1580  {
1581  MG_FreeData(surface);
1582  *data = NULL;
1583  }
1584  }
1585 }
1586 
1587 #endif
1588 
1600 static U16BIT OSD_GCD( U16BIT a, U16BIT b )
1601 {
1602  U16BIT c;
1603 
1604  /* Find the GCD */
1605  if (b != 0)
1606  {
1607  c = a % b;
1608  while (c != 0)
1609  {
1610  a = b;
1611  b = c;
1612  c = a % b;
1613  }
1614  }
1615 
1616  return b;
1617 }
1618 
OSD utility functions.
U8BIT colour_format
Definition: mg_ctxt.h:94
U16BIT out_osd_width
Definition: mg_ctxt.h:81
#define IF_COL_DEPTH(cd)
Definition: mg_ctxt.h:65
#define FUNCTION_FINISH(name)
Definition: glue_debug.h:143
S_MGContext mg_ctxt
Definition: mg_osd.c:144
void MG_FontExit(void)
Free all data associated with built-in font and terminate freetype library.
Definition: mg_font.c:185
void * col_buff
Definition: mg_osd.h:41
#define HD_W_SCALEUP(w)
Definition: mg_ctxt.h:102
U16BIT mlt
Definition: mg_ctxt.h:73
const char * data
Definition: mh5gate.c:56
#define HD_Y_SCALEUP(y)
Definition: mg_ctxt.h:106
void MG_OSDInit(U16BIT inWidth, U16BIT inHeight, U16BIT outWidth, U16BIT outHeight)
Definition: mg_osd.c:182
void MG_FreeData(void *data)
free surface buffer
Definition: mg_osd.c:1536
#define COLOUR_FORMAT_ARGB7888
Definition: mheg5_control.h:81
U32BIT height
Definition: osdtype.h:59
S32BIT left
Definition: osdtype.h:56
Debug tracing.
#define MakeHD2Color(osdcol)
Definition: osd_utils.h:56
void * hw_handle
Definition: mg_ctxt.h:90
U32BIT width
Definition: osdtype.h:58
U32BIT OSDColor
Definition: osdtypes.h:41
#define COLOUR_FORMAT_ARGB4444
Definition: mheg5_control.h:80
U16BIT out_osd_height
Definition: mg_ctxt.h:82
#define SD_HEIGHT
Definition: osdtype.h:30
void MG_OSDdisplayVideo(S_REGION rgn)
Display video window.
Definition: mg_osd.c:729
S_RATIO osd_y
Definition: mg_ctxt.h:86
void STB_OSDMhegClear(void)
Clear MHEG&#39;s entire OSD.
S_RATIO vid_y
Definition: mg_ctxt.h:88
S16BIT top
Definition: osdtypes.h:46
void STB_OSDMhegFillRectangle(S_RECTANGLE *pRect, U32BIT colour, E_BLIT_OP bflg)
Draw a filled rectangle on OSD back buffer in the location given. Where pixel colour is less than fou...
void * STB_OSDMhegCreateSurface(U16BIT width, U16BIT height, BOOLEAN init, U32BIT colour)
Creates a hardware surface on which MHEG5 engine will draw an individual MHEG object. At its basic the function can just allocate the buffer to be returned by STB_OSDMhegLockBuffer(). It&#39;s size being: (width * height * bytes_per_pixel) Also, when &#39;init&#39; is TRUE, function initialises surface buffer to the specified colour. For pixel colour format of less than four bytes, use least significant bits of &#39;colour&#39;.
void MG_OSDdisplayRectangle(S_REGION *overlap, int x, int y, int width, int height, int line_width, OSDColor lineColour, OSDColor fillColour)
Draw rectangle.
Definition: mg_osd.c:566
U16BIT offset_left
Definition: mg_ctxt.h:93
BOOLEAN MG_IsHdSupported(void)
Definition: mg_osd.c:171
void MG_Terminate(void)
Free all OSD resources.
Definition: mg_osd.c:367
#define MG_OSDUpdate
Definition: mg_api.h:34
void MG_OSDerase(S_REGION rgn, OSDColor colour)
Display video window.
Definition: mg_osd.c:808
E_MhegErr
Definition: mherrors.h:28
#define TOTAL_TRANSPARENCY
Definition: mg_osd.c:53
S32BIT top
Definition: osdtype.h:57
void MG_OSDMhegInit(U16BIT inWidth, U16BIT inHeight, E_ASPECT_RATIO sar)
Initialise the on screen display Initialise the font and fill in font info.
Definition: mg_osd.c:250
void * screen_buff
Definition: mg_ctxt.h:91
U32BIT buff_pitch
Definition: mg_osd.h:43
uint8_t U8BIT
Definition: techtype.h:82
BOOLEAN MG_FontInit(BOOLEAN isHD)
Initialise freetype library and load "built-in" font.
Definition: mg_font.c:92
void MG_OSDdisplayImage(void *data, S_REGION *overlap, int x, int y)
Definition: mg_osd.c:1453
DVB Video functions are required by MHEG5 engine. All required functions should be non-blocking...
void * hw_handle
Definition: mg_osd.h:42
Memory functions.
S_RATIO vid_x
Definition: mg_ctxt.h:87
This file defines the profile for the MHEG engine.
void * STB_OSDMhegSetResolution(U16BIT width, U16BIT height, U8BIT bits)
Sets the size of the OSD to be used by MHEG engine. The return must be a surface handle for the entir...
#define OSD_DbgRemSurf(s)
Definition: mg_osd.h:91
S_RATIO line_w
Definition: mg_ctxt.h:89
void STB_OSDMhegDestroySurface(void *surface)
This function destroys surface and all data allocated by STB_OSDMhegCreateSurface() ...
U16BIT height
Definition: mg_osd.h:40
Interface to OSD.
S16BIT right
Definition: osdtypes.h:47
#define DPL1(x)
Definition: glue_debug.h:191
#define ELSE
Definition: mg_ctxt.h:66
U32BIT screen_stride
Definition: mg_ctxt.h:92
void MG_OSDclear(void)
Clear entire OSD to colour.
Definition: mg_osd.c:888
#define C4L_ALPHA_CHNNL
Definition: mg_osd.c:62
#define OSD_DbgAddSurf(s)
Definition: mg_osd.h:90
U16BIT input_height
Definition: mg_ctxt.h:84
U16BIT out_video_height
Definition: mg_ctxt.h:80
U8BIT opaque
Definition: mg_osd.h:44
int32_t S32BIT
Definition: techtype.h:87
void STB_OSDMhegUpdate(void)
Commit OSD changes to the screen - changes given by previous calls to STB_OSDMhegDrawRectangle() and ...
S16BIT bottom
Definition: osdtypes.h:48
uint16_t U16BIT
Definition: techtype.h:84
The functions in this file are OPTIONALLY provided by Receiver Platform *.
U16BIT width
Definition: mg_osd.h:39
Font file handling with the Freetype.
U8BIT srf_type
Definition: mg_osd.h:45
S16BIT left
Definition: osdtypes.h:45
#define COLOUR_FORMAT_PALETTE
Definition: mheg5_control.h:79
#define COLOUR_FORMAT_ARGB8888
Definition: mheg5_control.h:82
Definition: mg_png.c:52
#define FALSE
Definition: techtype.h:68
void DVB_MhegSetScalingResolution(U16BIT width, U16BIT height)
Set Mheg scaling resolution for video.
#define SD_WIDTH
Definition: osdtype.h:31
#define HD_X_SCALEUP(x)
Definition: mg_ctxt.h:104
U16BIT div
Definition: mg_ctxt.h:74
void * STB_OSDMhegLockBuffer(void *surface, U32BIT *pPitch)
Converts hardware surface handle returned by STB_OSDMhegCreateSurface() to buffer address that the en...
U8BIT BOOLEAN
Definition: techtype.h:99
E_ASPECT_RATIO DVB_MhegGetDisplayAspectRatio(void)
Get display aspect ratio.
#define USE_UNWANTED_PARAM(param)
Definition: techtype.h:48
#define TRUE
Definition: techtype.h:69
void STB_OSDMhegBlitStretch(S_RECTANGLE *pSrcRect, void *src_surf, S_RECTANGLE *pDstRect, void *dst_surf, E_BLIT_OP bflg)
Stretch blit bitmap data from source surface to destination surface using source and destination rect...
#define TRACE_BUFF(t, d, l)
Definition: glue_debug.h:120
void STB_OSDMhegBlitBitmap(void *surface, S_RECTANGLE *pRect, U32BIT pitch, U16BIT screen_x, U16BIT screen_y, E_BLIT_OP bflg)
Render bitmap on OSD back buffer in the given screen location, with given operation. The bitmap is referenced &#39;surface&#39; - a handle returned by STB_OSDMhegCreateSurface()
U16BIT out_video_width
Definition: mg_ctxt.h:79
E_ASPECT_RATIO
Definition: osdtype.h:39
#define FUNCTION_START(name)
Definition: glue_debug.h:142
#define OSD_MemFree
Definition: glue_memory.h:97
Graphics functions required by the HD MHEG5 engine. All references to colour used in these functions ...
S_RATIO osd_x
Definition: mg_ctxt.h:85
#define C2L_ALPHA_CHNNL
Definition: mg_osd.c:60
uint32_t U32BIT
Definition: techtype.h:86
void MG_DisplayImage(S_SURFACE *surf, S_REGION *overlap, S32BIT x, S32BIT y)
Copy the image to the screen buffer.
Definition: mg_osd.c:1266
void STB_OSDMhegUnlockBuffer(void *surface)
This function informs HW that MHEG5 is finished writing to the buffer.
U16BIT input_width
Definition: mg_ctxt.h:83
E_MhegErr MG_Initialise(U16BIT screenWidth, U16BIT screenHeight, U8BIT colourDepth)
Initialise OSD, font, and font fill information. Should only be called at start up.
Definition: mg_osd.c:281
#define TRACE(t, x)
Definition: glue_debug.h:118