Hide graphics internal APIs

This commit is contained in:
Kovid Goyal 2024-07-11 06:10:33 +05:30
parent 53eff7927a
commit c410ab8a8f
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
5 changed files with 82 additions and 66 deletions

View file

@ -12,6 +12,7 @@
#include "emoji.h"
#include "unicode-data.h"
#include "glyph-cache.h"
#include "kitty-uthash.h"
#define MISSING_GLYPH (NUM_UNDERLINE_STYLES + 2)
#define MAX_NUM_EXTRA_GLYPHS_PUA 4u

View file

@ -5,6 +5,8 @@
* Distributed under terms of the GPL3 license.
*/
#define GRAPHICS_INTERNAL_APIS
#include "kitty-uthash.h"
#include "graphics.h"
#include "state.h"
#include "disk-cache.h"
@ -859,13 +861,13 @@ is_cell_image(const ImageRef *self) { return self->virtual_ref_id != 0; }
// - `columns` - the number of columns we want to display
// - `rows` - the number of rows we want to display
// - `cell` - the size of a screen cell
Image *grman_put_cell_image(GraphicsManager *self, uint32_t screen_row,
void grman_put_cell_image(GraphicsManager *self, uint32_t screen_row,
uint32_t screen_col, uint32_t image_id,
uint32_t placement_id, uint32_t img_col,
uint32_t img_row, uint32_t columns, uint32_t rows,
CellPixelSize cell) {
Image *img = img_by_client_id(self, image_id);
if (img == NULL) return NULL;
if (img == NULL) return;
ImageRef *virt_img_ref = NULL;
if (placement_id) {
@ -886,7 +888,7 @@ Image *grman_put_cell_image(GraphicsManager *self, uint32_t screen_row,
}
}
if (!virt_img_ref) return NULL;
if (!virt_img_ref) return;
// Create the ref structure on stack first. We will not create a real
// reference if the image is completely out of bounds.
@ -958,8 +960,7 @@ Image *grman_put_cell_image(GraphicsManager *self, uint32_t screen_row,
uint32_t col_offset = ref.cell_x_offset / cell.width;
ref.cell_x_offset %= cell.width;
ref.start_column += col_offset;
if (ref.num_cols <= col_offset)
return img;
if (ref.num_cols <= col_offset) return;
ref.num_cols -= col_offset;
}
if (ref.src_y < 0) {
@ -969,8 +970,7 @@ Image *grman_put_cell_image(GraphicsManager *self, uint32_t screen_row,
uint32_t row_offset = ref.cell_y_offset / cell.height;
ref.cell_y_offset %= cell.height;
ref.start_row += row_offset;
if (ref.num_rows <= row_offset)
return img;
if (ref.num_rows <= row_offset) return;
ref.num_rows -= row_offset;
}
@ -979,16 +979,14 @@ Image *grman_put_cell_image(GraphicsManager *self, uint32_t screen_row,
if (ref.src_x + ref.src_width > img->width) {
float redundant_w = ref.src_x + ref.src_width - img->width;
uint32_t redundant_cols = (uint32_t)(redundant_w * x_scale) / cell.width;
if (ref.num_cols <= redundant_cols)
return img;
if (ref.num_cols <= redundant_cols) return;
ref.src_width -= redundant_cols * cell.width / x_scale;
ref.num_cols -= redundant_cols;
}
if (ref.src_y + ref.src_height > img->height) {
float redundant_h = ref.src_y + ref.src_height - img->height;
uint32_t redundant_rows = (uint32_t)(redundant_h * y_scale) / cell.height;
if (ref.num_rows <= redundant_rows)
return img;
if (ref.num_rows <= redundant_rows) return;
ref.src_height -= redundant_rows * cell.height / y_scale;
ref.num_rows -= redundant_rows;
}
@ -1004,7 +1002,6 @@ Image *grman_put_cell_image(GraphicsManager *self, uint32_t screen_row,
update_src_rect(real_ref, img);
update_dest_rect(real_ref, ref.num_cols, ref.num_rows, cell);
return img;
}
static void remove_ref(Image *img, ImageRef *ref);
@ -2428,4 +2425,15 @@ init_graphics(PyObject *module) {
Py_INCREF(&GraphicsManager_Type);
return true;
}
void grman_mark_layers_dirty(GraphicsManager *self) { self->layers_dirty = true; }
void grman_set_window_id(GraphicsManager *self, id_type id) { self->window_id = id; }
GraphicsRenderData grman_render_data(GraphicsManager *self) {
GraphicsRenderData ans = {
.count=self->render_data.count, .capacity=self->render_data.capacity, .images=self->render_data.item,
.num_of_below_refs=self->num_of_below_refs, .num_of_negative_refs=self->num_of_negative_refs,
.num_of_positive_refs=self->num_of_positive_refs
};
return ans;
}
// }}}

View file

@ -7,7 +7,6 @@
#pragma once
#include "data-types.h"
#include "monotonic.h"
#include "kitty-uthash.h"
typedef struct {
unsigned char action, transmission_type, compressed, delete_action;
@ -30,6 +29,22 @@ typedef struct {
float left, top, right, bottom;
} ImageRect;
typedef struct {
ImageRect src_rect, dest_rect;
uint32_t texture_id, group_count;
int z_index;
id_type image_id, ref_id;
} ImageRenderData;
typedef struct {
uint32_t texture_id;
unsigned int height, width;
uint8_t* bitmap;
uint32_t refcnt;
} BackgroundImage;
#ifdef GRAPHICS_INTERNAL_APIS
typedef struct {
float src_width, src_height, src_x, src_y;
uint32_t cell_x_offset, cell_y_offset, num_cols, num_rows, effective_num_rows, effective_num_cols;
@ -87,20 +102,6 @@ typedef struct {
hash_handle_type hh;
} Image;
typedef struct {
uint32_t texture_id;
unsigned int height, width;
uint8_t* bitmap;
uint32_t refcnt;
} BackgroundImage;
typedef struct {
ImageRect src_rect, dest_rect;
uint32_t texture_id, group_count;
int z_index;
id_type image_id, ref_id;
} ImageRenderData;
typedef struct {
id_type image_id;
uint32_t frame_id;
@ -142,7 +143,9 @@ typedef struct {
bool has_images_needing_animation, context_made_current_for_this_command;
id_type window_id;
} GraphicsManager;
#else
typedef struct {int x;} *GraphicsManager;
#endif
typedef struct {
int32_t amt, limit;
@ -179,11 +182,15 @@ gl_pos_y(const unsigned int px_from_top_margin, const unsigned int viewport_size
return 1.f - px_from_top_margin * px;
}
typedef struct GraphicsRenderData {
size_t count, capacity, num_of_below_refs, num_of_negative_refs, num_of_positive_refs;
ImageRenderData *images;
} GraphicsRenderData;
GraphicsManager* grman_alloc(bool for_paused_rendering);
void grman_clear(GraphicsManager*, bool, CellPixelSize fg);
const char* grman_handle_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_t *payload, Cursor *c, bool *is_dirty, CellPixelSize fg);
Image* grman_put_cell_image(GraphicsManager *self, uint32_t row, uint32_t col, uint32_t image_id, uint32_t placement_id, uint32_t x, uint32_t y, uint32_t w, uint32_t h, CellPixelSize cell);
void grman_put_cell_image(GraphicsManager *self, uint32_t row, uint32_t col, uint32_t image_id, uint32_t placement_id, uint32_t x, uint32_t y, uint32_t w, uint32_t h, CellPixelSize cell);
bool grman_update_layers(GraphicsManager *self, unsigned int scrolled_by, float screen_left, float screen_top, float dx, float dy, unsigned int num_cols, unsigned int num_rows, CellPixelSize);
void grman_scroll_images(GraphicsManager *self, const ScrollData*, CellPixelSize fg);
void grman_resize(GraphicsManager*, index_type, index_type, index_type, index_type, index_type, index_type);
@ -197,3 +204,6 @@ bool png_from_data(void *png_data, size_t png_data_sz, const char *path_for_erro
bool scan_active_animations(GraphicsManager *self, const monotonic_t now, monotonic_t *minimum_gap, bool os_window_context_set);
void scale_rendered_graphic(ImageRenderData*, float xstart, float ystart, float x_scale, float y_scale);
void grman_pause_rendering(GraphicsManager *self, GraphicsManager *dest);
void grman_mark_layers_dirty(GraphicsManager *self);
void grman_set_window_id(GraphicsManager *self, id_type id);
GraphicsRenderData grman_render_data(GraphicsManager *self);

View file

@ -142,7 +142,8 @@ new_screen_object(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
) {
Py_CLEAR(self); return NULL;
}
self->main_grman->window_id = self->window_id; self->alt_grman->window_id = self->window_id;
grman_set_window_id(self->main_grman, self->window_id);
grman_set_window_id(self->alt_grman, self->window_id);
self->alt_tabstops = self->main_tabstops + self->columns;
self->tabstops = self->main_tabstops;
init_tabstops(self->main_tabstops, self->columns);
@ -1065,7 +1066,7 @@ screen_toggle_screen_buffer(Screen *self, bool save_cursor, bool clear_alt_scree
}
screen_history_scroll(self, SCROLL_FULL, false);
self->is_dirty = true;
self->grman->layers_dirty = true;
grman_mark_layers_dirty(self->grman);
clear_selection(&self->selections);
global_state.check_for_active_animated_images = true;
}

View file

@ -574,15 +574,14 @@ viewport_for_cells(const CellRenderData *crd) {
}
static void
draw_cells_simple(ssize_t vao_idx, Screen *screen, const CellRenderData *crd, bool is_semi_transparent) {
draw_cells_simple(ssize_t vao_idx, Screen *screen, const CellRenderData *crd, GraphicsRenderData grd, bool is_semi_transparent) {
bind_program(CELL_PROGRAM);
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
GraphicsManager *grman = screen->paused_rendering.expires_at && screen->paused_rendering.grman ? screen->paused_rendering.grman : screen->grman;
if (grman->render_data.count) {
if (grd.count) {
glEnable(GL_BLEND);
int program = GRAPHICS_PROGRAM;
if (is_semi_transparent) { BLEND_PREMULT; program = GRAPHICS_PREMULT_PROGRAM; } else { BLEND_ONTO_OPAQUE; }
draw_graphics(program, vao_idx, grman->render_data.item, 0, grman->render_data.count, viewport_for_cells(crd));
draw_graphics(program, vao_idx, grd.images, 0, grd.count, viewport_for_cells(crd));
glDisable(GL_BLEND);
}
}
@ -865,7 +864,7 @@ draw_visual_bell_flash(GLfloat intensity, const CellRenderData *crd, Screen *scr
}
static void
draw_cells_interleaved(ssize_t vao_idx, Screen *screen, OSWindow *w, const CellRenderData *crd, const WindowLogoRenderData *wl) {
draw_cells_interleaved(ssize_t vao_idx, Screen *screen, OSWindow *w, const CellRenderData *crd, GraphicsRenderData grd, const WindowLogoRenderData *wl) {
glEnable(GL_BLEND);
BLEND_ONTO_OPAQUE;
@ -879,21 +878,20 @@ draw_cells_interleaved(ssize_t vao_idx, Screen *screen, OSWindow *w, const CellR
BLEND_ONTO_OPAQUE;
}
GraphicsManager *grman = screen->paused_rendering.expires_at && screen->paused_rendering.grman ? screen->paused_rendering.grman : screen->grman;
if (grman->num_of_below_refs || has_bgimage(w) || wl) {
if (grd.num_of_below_refs || has_bgimage(w) || wl) {
if (wl) {
draw_window_logo(vao_idx, w, wl, crd);
BLEND_ONTO_OPAQUE;
}
if (grman->num_of_below_refs) draw_graphics(
GRAPHICS_PROGRAM, vao_idx, grman->render_data.item, 0, grman->num_of_below_refs, viewport_for_cells(crd));
if (grd.num_of_below_refs) draw_graphics(
GRAPHICS_PROGRAM, vao_idx, grd.images, 0, grd.num_of_below_refs, viewport_for_cells(crd));
bind_program(CELL_BG_PROGRAM);
// draw background for non-default bg cells
glUniform1ui(cell_program_layouts[CELL_BG_PROGRAM].uniforms.draw_bg_bitfield, 2);
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
}
if (grman->num_of_negative_refs) draw_graphics(GRAPHICS_PROGRAM, vao_idx, grman->render_data.item, grman->num_of_below_refs, grman->num_of_negative_refs, viewport_for_cells(crd));
if (grd.num_of_negative_refs) draw_graphics(GRAPHICS_PROGRAM, vao_idx, grd.images, grd.num_of_below_refs, grd.num_of_negative_refs, viewport_for_cells(crd));
bind_program(CELL_SPECIAL_PROGRAM);
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
@ -903,13 +901,13 @@ draw_cells_interleaved(ssize_t vao_idx, Screen *screen, OSWindow *w, const CellR
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
BLEND_ONTO_OPAQUE;
if (grman->num_of_positive_refs) draw_graphics(GRAPHICS_PROGRAM, vao_idx, grman->render_data.item, grman->num_of_negative_refs + grman->num_of_below_refs, grman->num_of_positive_refs, viewport_for_cells(crd));
if (grd.num_of_positive_refs) draw_graphics(GRAPHICS_PROGRAM, vao_idx, grd.images, grd.num_of_negative_refs + grd.num_of_below_refs, grd.num_of_positive_refs, viewport_for_cells(crd));
glDisable(GL_BLEND);
}
static void
draw_cells_interleaved_premult(ssize_t vao_idx, Screen *screen, OSWindow *os_window, const CellRenderData *crd, const WindowLogoRenderData *wl) {
draw_cells_interleaved_premult(ssize_t vao_idx, Screen *screen, OSWindow *os_window, const CellRenderData *crd, GraphicsRenderData grd, const WindowLogoRenderData *wl) {
if (OPT(background_tint) > 0.f) {
glEnable(GL_BLEND);
draw_tint(true, screen, crd);
@ -924,14 +922,13 @@ draw_cells_interleaved_premult(ssize_t vao_idx, Screen *screen, OSWindow *os_win
glEnable(GL_BLEND);
BLEND_PREMULT;
GraphicsManager *grman = screen->paused_rendering.expires_at && screen->paused_rendering.grman ? screen->paused_rendering.grman : screen->grman;
if (grman->num_of_below_refs || has_bgimage(os_window) || wl) {
if (grd.num_of_below_refs || has_bgimage(os_window) || wl) {
if (wl) {
draw_window_logo(vao_idx, os_window, wl, crd);
BLEND_PREMULT;
}
if (grman->num_of_below_refs) draw_graphics(
GRAPHICS_PREMULT_PROGRAM, vao_idx, grman->render_data.item, 0, grman->num_of_below_refs, viewport_for_cells(crd));
if (grd.num_of_below_refs) draw_graphics(
GRAPHICS_PREMULT_PROGRAM, vao_idx, grd.images, 0, grd.num_of_below_refs, viewport_for_cells(crd));
bind_program(CELL_BG_PROGRAM);
// Draw background for non-default bg cells
glUniform1ui(cell_program_layouts[CELL_BG_PROGRAM].uniforms.draw_bg_bitfield, 2);
@ -942,8 +939,8 @@ draw_cells_interleaved_premult(ssize_t vao_idx, Screen *screen, OSWindow *os_win
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
}
if (grman->num_of_negative_refs) {
draw_graphics(GRAPHICS_PREMULT_PROGRAM, vao_idx, grman->render_data.item, grman->num_of_below_refs, grman->num_of_negative_refs, viewport_for_cells(crd));
if (grd.num_of_negative_refs) {
draw_graphics(GRAPHICS_PREMULT_PROGRAM, vao_idx, grd.images, grd.num_of_below_refs, grd.num_of_negative_refs, viewport_for_cells(crd));
}
bind_program(CELL_SPECIAL_PROGRAM);
@ -952,7 +949,7 @@ draw_cells_interleaved_premult(ssize_t vao_idx, Screen *screen, OSWindow *os_win
bind_program(CELL_FG_PROGRAM);
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
if (grman->num_of_positive_refs) draw_graphics(GRAPHICS_PREMULT_PROGRAM, vao_idx, grman->render_data.item, grman->num_of_negative_refs + grman->num_of_below_refs, grman->num_of_positive_refs, viewport_for_cells(crd));
if (grd.num_of_positive_refs) draw_graphics(GRAPHICS_PREMULT_PROGRAM, vao_idx, grd.images, grd.num_of_negative_refs + grd.num_of_below_refs, grd.num_of_positive_refs, viewport_for_cells(crd));
glDisable(GL_BLEND);
}
@ -1037,24 +1034,26 @@ draw_cells(ssize_t vao_idx, const WindowRenderData *srd, OSWindow *os_window, bo
has_underlying_image = true;
set_on_gpu_state(window->window_logo.instance, true);
} else wl = NULL;
ImageRenderData *previous_graphics_render_data = NULL;
ImageRenderData *scaled_render_data = NULL;
GraphicsManager *grman = screen->paused_rendering.expires_at && screen->paused_rendering.grman ? screen->paused_rendering.grman : screen->grman;
if (os_window->live_resize.in_progress && grman->render_data.count && (crd.x_ratio != 1 || crd.y_ratio != 1)) {
previous_graphics_render_data = malloc(sizeof(previous_graphics_render_data[0]) * grman->render_data.capacity);
if (previous_graphics_render_data) {
memcpy(previous_graphics_render_data, grman->render_data.item, sizeof(previous_graphics_render_data[0]) * grman->render_data.count);
for (size_t i = 0; i < grman->render_data.count; i++)
scale_rendered_graphic(grman->render_data.item + i, srd->xstart, srd->ystart, crd.x_ratio, crd.y_ratio);
GraphicsRenderData grd = grman_render_data(grman);
if (os_window->live_resize.in_progress && grd.count && (crd.x_ratio != 1 || crd.y_ratio != 1)) {
scaled_render_data = malloc(sizeof(scaled_render_data[0]) * grd.count);
if (scaled_render_data) {
memcpy(scaled_render_data, grd.images, sizeof(scaled_render_data[0]) * grd.count);
grd.images = scaled_render_data;
for (size_t i = 0; i < grd.count; i++)
scale_rendered_graphic(grd.images + i, srd->xstart, srd->ystart, crd.x_ratio, crd.y_ratio);
}
}
bool use_premult = false;
has_underlying_image |= grman->num_of_below_refs > 0 || grman->num_of_negative_refs > 0;
has_underlying_image |= grd.num_of_below_refs > 0 || grd.num_of_negative_refs > 0;
if (os_window->is_semi_transparent) {
if (has_underlying_image) { draw_cells_interleaved_premult(vao_idx, screen, os_window, &crd, wl); use_premult = true; }
else draw_cells_simple(vao_idx, screen, &crd, os_window->is_semi_transparent);
if (has_underlying_image) { draw_cells_interleaved_premult(vao_idx, screen, os_window, &crd, grd, wl); use_premult = true; }
else draw_cells_simple(vao_idx, screen, &crd, grd, os_window->is_semi_transparent);
} else {
if (has_underlying_image) draw_cells_interleaved(vao_idx, screen, os_window, &crd, wl);
else draw_cells_simple(vao_idx, screen, &crd, os_window->is_semi_transparent);
if (has_underlying_image) draw_cells_interleaved(vao_idx, screen, os_window, &crd, grd, wl);
else draw_cells_simple(vao_idx, screen, &crd, grd, os_window->is_semi_transparent);
}
draw_scroll_indicator(use_premult, screen, &crd);
@ -1065,10 +1064,7 @@ draw_cells(ssize_t vao_idx, const WindowRenderData *srd, OSWindow *os_window, bo
if (window && screen->display_window_char) draw_window_number(os_window, screen, &crd, window);
if (OPT(show_hyperlink_targets) && window && screen->current_hyperlink_under_mouse.id && !is_mouse_hidden(os_window)) draw_hyperlink_target(os_window, screen, &crd, window);
if (previous_graphics_render_data) {
free(grman->render_data.item);
grman->render_data.item = previous_graphics_render_data;
}
free(scaled_render_data);
}
// }}}