From 4e9208f7682be4a62ba8a6a44e139ad9ef8ef6bf Mon Sep 17 00:00:00 2001 From: Francesco Abbate Date: Mon, 14 Jun 2021 17:48:06 +0200 Subject: [PATCH] WIP: working on the draw_image rencache command Work in progress, do not compile and it is largely incomplete. The idea is to implement a new command into the rencache, DRAW_IMAGE. The command should blit into the rendering surface a rectangular portion of a given image. We should have a "repository" of images to be used for this operations. Each image should be identified by an image ID. The image ID in turn should have three components: - the node the image belongs to (each node can potentially produce multiple images). - an identifier of a specific rect withing a specific image of the node. For example for a DocView we may divide the document in pages and draw each page in a different image. We should in addition divide the image in rects so that an update in the image does not trigger the update of the whole image but only of a pert of it. The page and the rect within would provide a way to index the image. - an identifier of the "revision" of the image. The idea is that to trigger an update upon a DRAW_IMAGE command the image_id has to change. If the image is always the same the "revision" number will track updates within an existing image. In turn we should allow the views to render into an image and then issue rencache commands to draw parts of the image (rects) using the DRAW_IMAGE command. This part is not yet implemented. --- src/rencache.c | 22 +++++++++++++++++++++- src/renderer.c | 33 ++++++++++++++++++++++++++++----- src/renderer.h | 4 ++++ 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/src/rencache.c b/src/rencache.c index 143ae477..5523a30e 100644 --- a/src/rencache.c +++ b/src/rencache.c @@ -8,7 +8,7 @@ #define CELL_SIZE 96 #define COMMAND_BARE_SIZE offsetof(Command, text) -enum { SET_CLIP, DRAW_TEXT, DRAW_RECT, DRAW_TEXT_SUBPIXEL }; +enum { SET_CLIP, DRAW_TEXT, DRAW_RECT, DRAW_TEXT_SUBPIXEL, DRAW_IMAGE }; typedef struct { int8_t type; @@ -21,6 +21,7 @@ typedef struct { FontDesc *font_desc; CPReplaceTable *replacements; RenColor replace_color; + uint32_t image_id; /* FIXME: do not add a new field but use unions or alias another field. */ char text[0]; } Command; @@ -148,6 +149,20 @@ void rencache_draw_rect(RenCache *rc, RenRect rect, RenColor color) { } } + +void rencache_draw_image(RenCache *rc, int image_id, int x, int y, RenRect image_rect) { + RenRect rect = {x, y, image_rect.width, image_rect.height}; + if (!rects_overlap(rc->screen_rect, rect)) { return; } + Command *cmd = push_command(rc, DRAW_IMAGE, COMMAND_BARE_SIZE + 2 * sizeof(int)); + int *img_coord = (int *) cmd->text; + if (cmd) { + cmd->rect = rect; + cmd->image_id = image_id; + img_coord[0] = image_rect.x; + img_coord[1] = image_rect.y; + } +} + int rencache_draw_text(RenCache *rc, lua_State *L, FontDesc *font_desc, int font_index, const char *text, int x, int y, RenColor color, bool draw_subpixel, CPReplaceTable *replacements, RenColor replace_color) @@ -268,6 +283,7 @@ void rencache_end_frame(RenCache *rc, lua_State *L) { /* redraw updated regions */ for (int i = 0; i < rect_count; i++) { + const int *image_coord; /* draw */ RenRect r = rc->rect_buf[i]; ren_set_clip_rect(rc->ren_surface, r); @@ -292,6 +308,10 @@ void rencache_end_frame(RenCache *rc, lua_State *L) { cmd->subpixel_scale * cmd->rect.x + cmd->x_subpixel_offset, cmd->rect.y, cmd->color, cmd->replacements, cmd->replace_color); break; + case DRAW_IMAGE: + image_coord = (const int *) cmd->text; + ren_draw_image(rc->ren_surface, cmd->image_id, image_coord[0], image_coord[1], cmd->rect); + break; } } diff --git a/src/renderer.c b/src/renderer.c index 12042f55..15fd2258 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -127,14 +127,28 @@ void ren_resize_window() { renwin_resize_surface(&window_renderer); } +/* FIXME: all this stuff. */ +#define IMAGE_CELL_SIZE 96 +#define IMAGE_CELL_X 80 + +static inline int image_cell_idx(int x, int y) { + return x + y * IMAGE_CELLS_X; +} void ren_update_rects(RenSurface *ren, RenRect *rects, int count) { if (ren->type == SurfaceTexture) { - // FIXME: this is now a NOP because we don't present the rectangles into - // the screen neither we upload them into a texture. - // The problem is that the information about the update rects is lost for - // later when the rendering commands are sent to the window. - // rentex_update_rects((RenTexture *) ren->data, rects, count); + RenTexture *rentex = (RenTexture *) ren->data; + for (int i = 0; i < count; i++) { + RenRect irect = image_rect_to_index(rects[i]); + /* Increment the revision number for all cells that needs to be updated, + i.e. those that overlaps with one of the update rectangles. */ + for (int x = irect.x; x < irect.x + irect.width; x++) { + for (int y = irect.y; y < irect.y + irect.height; y++) { + int idx = image_cell_idx(x, y); + rentex->revisions[idx] += 1: + } + } + } } else { RenWindow *renwin = (RenWindow *) ren->data; if (renwin->initial_frame) { @@ -438,3 +452,12 @@ int ren_get_font_subpixel_scale(RenSurface *ren, FontDesc *font_desc) { RenFont *font = font_desc_get_font_at_scale(font_desc, surface_scale); return FR_Subpixel_Scale(font->renderer) * surface_scale; } + +void ren_draw_image(RenSurface *ren, uint32_t image_id, int image_x, int image_y, RenRect rect) { + SDL_Rect image_rect; + SDL_Surface *image_surf = image_get(image_id, &image_rect, image_x, image_y); + SDL_Surface *surface = ren_surface_get_surface(ren); + SDL_Rect dst_rect = {rect.x, rect.y, 0, 0}; + SDL_BlitSurface(image_surf,image_rect, surface, &dst_rect); +} + diff --git a/src/renderer.h b/src/renderer.h index c671005b..b8e4a3bd 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -21,10 +21,13 @@ enum { typedef struct { uint8_t b, g, r, a; } RenColor; typedef struct { int x, y, width, height; } RenRect; +// FIXME: ensure this Max is okay or use dynamic allocation. +#define TEXTURE_REVS_MAX 256 struct RenTexture { SDL_Surface *surface; int surface_scale; RenRect clip; /* Clipping rect in pixel coordinates. */ + int revisions[TEXTURE_REVS_MAX]; }; typedef struct RenTexture RenTexture; @@ -73,6 +76,7 @@ int ren_font_subpixel_round(int width, int subpixel_scale, int orientation); void ren_draw_rect(RenSurface *ren, RenRect rect, RenColor color); void ren_draw_text(RenSurface *ren, FontDesc *font_desc, const char *text, int x, int y, RenColor color, CPReplaceTable *replacements, RenColor replace_color); void ren_draw_text_subpixel(RenSurface *ren, FontDesc *font_desc, const char *text, int x_subpixel, int y, RenColor color, CPReplaceTable *replacements, RenColor replace_color); +void ren_draw_image(RenSurface *ren, uint32_t image_id, int image_x, int image_y, RenRect rect); void ren_cp_replace_init(CPReplaceTable *rep_table); void ren_cp_replace_free(CPReplaceTable *rep_table);