[proposal] unified graphics interface

Started by g3gg0, February 22, 2014, 10:09:51 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

g3gg0

current state:
a thing that i personally consider a bit odd in magic lantern core is how the graphics code works.
everything, even fonts is being printed on screen directly. this can e.g. cause weird flickering if you redraw stuff.

when you want to "build" up a graphic and display it with only one operation, like a simple BitBlt you
have no other chance than implementing your drawing routines on your own.
for creating graphics, like the plots alex is doing, you can only write them on screen and then do a screenshot.
(in the hope that nothing printed over your graphs while you built them)

also these operations are only possible in bitmap buffer, which is a 8 bit per pixel indexed (palette) graphics buffer.
drawing/printing into the vram is not supported at all.


change:
for that reason i am starting a discussion for a new graphics backend, that should cover all current and (hopefully) future needs.
i hope that you take part in the discussion and maybe we can find someone who is able to implement that.

@all devs:
do you think this API will be usefule and would cover all use cases we currently have or will face in future?
(e.g. painting on ML's own back and front buffers before printing them on screen etc?)

@future devs:
this code is really simple to implement. you dont have to know ML or canon. this can even be tested on the computer standalone.
anyone who is interested in implementing it?


fundamentals:
- every operation happens on a "context" which tells the graph routines where they have to draw on (screen, ram, etc)
- all necessary information for drawing must be accessible in the context being passed
- every operation must support 8bpp and YUV color modes
- the graphics type is designed to be compatible to the screen buffers (BMP, LV, HD) without any hacks
- for easy usage, there are predefined contexts that are meant for printing on screen directly
   (e.g. when specifying CANON_BMP_FRONT the code will pick an internal graph_t which contains the screen's bmp configuration)


prototypes:
/* image data is stored in YUV422 packed, also known as YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr  */
#define PIX_FMT_YUYV422  0
/* image data is stored as 8 bits per pixel indexed. palette can be specified optionally */
#define PIX_FMT_PAL8     1

/* special cases: when specifying them, the routines will render on screen directly */
#define CANON_BMP_FRONT ((graph_t *) 1)
#define CANON_BMP_BACK  ((graph_t *) 2)
#define CANON_VRAM_HD   ((graph_t *) 3)
#define CANON_VRAM_PREV ((graph_t *) 4)

/* for any copy operation, specify how to proceed when destimation dimensions differ from source */
#define COPY_MODE_CROP   0
#define COPY_MODE_SCALE  1
#define COPY_MODE_BILIN  2


typedef struct
{
    /* pointer to raw image data */
    void *data;
    /* pixel format as specified in PIX_FMT macros */
    uint32_t pixel_format;
    /* image dimensions */
    graph_size_t size;
    /* optional palette, especially important when saving or copying to YUV targets */
    graph_palette_t *palette;
    /* if non-NULL, the graphic will be locked when drawing on it (t.b.d) */
    void *lock;
} graph_t;

typedef struct
{
    /* image width in pixels, visible content only */
    uint32_t width;
    /* image height in pixels, visible content only */
    uint32_t height;
    /* how wide every pixel line is, given in pixels */
    uint32_t pitch;
    /* number of invisible pixels left of the image data */
    uint32_t x_ofs;
    /* number of invisible pixels above the image data */
    uint32_t y_ofs;
} graph_size_t;


/* draw a single dot, color depends on image format. either palette index or full YUV word. size=1 must be optimized */
uint32_t graph_draw_pixel(graph_t *ctx, uint32_t x, uint32_t y, uint32_t radius, uint32_t color);
uint32_t graph_draw_line(graph_t *ctx, uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2, uint32_t radius, uint32_t color);
uint32_t graph_draw_rect(graph_t *ctx, uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2, uint32_t line_color, uint32_t fill_color);

/* width/height may be zero for auto */
uint32_t graph_copy(graph_t *dst, graph_t *src, uint32_t x, uint32_t y, uint32_t width, uint32_t height, uint32_t copy_mode);

/* font_t is the font type we use with bmp_printf etc */
uint32_t graph_printf(graph_t *dst, uint32_t x, uint32_t y, font_t font, char *msg, ...);

/* can be used to get the palette of the canon screen */
graph_palette_t *graph_get_palette();


/*
    data pointer is pointing here
   /
  |________________________________________________
  |         ^                                      |
  |         | y_ofs                                |
  |         |                                      |
  |       __v______________________________        |
  | x_ofs|                          ^      |       |
  |<---->|                   height |      |       |
  |      |                          |      |       |
  |      |       (image content)    |      |       |
  |      |                          |      |       |
  |      |             width        |      |       |
  |      |<-------------------------|----->|       |
  |      |__________________________v______|       |
  |                                                |
  |________________________________________________|
  |                     pitch                      |
  |<---------------------------------------------->|
 
*/



example:
e.g. either call
    graph_draw_pixel(CANON_BMP_FRONT, 10, 20, COLOR_WHITE);
or
    graph_draw_pixel(my_own_graph, 10, 20, COLOR_WHITE);
where 'my_own_graph' is a pointer to a custom graph context.
this may be displayed on screen later or saved using appropriate routines.


/* init sample graphic */
graph_t *my_own_graph = graph_alloc(PIX_FMT_PAL8, 1024, 768);

/* set a dot (width 1) */
graph_draw_pixel(my_own_graph, 10, 20, 1, COLOR_WHITE);

/* draw an ellipse, width 2 */
graph_draw_circle(my_own_graph, 90, 90, 40, 80, 2, COLOR_WHITE);

/* save it */
graph_save_bmp(my_own_graph, "ML/DATA/PLOT.BMP");

/* width/height may be zero for auto */
graph_copy(CANON_BMP_FRONT, my_own_graph, 0, 0, 0, 0, COPY_MODE_CROP);


Help us with datasheets - Help us with register dumps
magic lantern: 1Magic9991E1eWbGvrsx186GovYCXFbppY, server expenses: [email protected]
ONLY donate for things we have done, not for things you expect!

nanomad

Thumbs up from me, the API looks solid and I think we can live with the increased binary size if that means having consistent behaviour between buffers
EOS 1100D | EOS 650 (No, I didn't forget the D) | Ye Olde Canon EF Lenses ('87): 50 f/1.8 - 28 f/2.8 - 70-210 f/4 | EF-S 18-55 f/3.5-5.6 | Metz 36 AF-5