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.
This commit is contained in:
Francesco Abbate 2021-06-14 17:48:06 +02:00
parent 23c6b182f6
commit 4e9208f768
3 changed files with 53 additions and 6 deletions

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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);