Add background_image
This commit is contained in:
parent
a67e4e550e
commit
9f364209af
26
kitty/bgimage_fragment.glsl
Normal file
26
kitty/bgimage_fragment.glsl
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#version GLSL_VERSION
|
||||||
|
#define LAYOUT_TYPE
|
||||||
|
|
||||||
|
uniform sampler2D image;
|
||||||
|
uniform float bgimage_opacity;
|
||||||
|
#ifdef TILED
|
||||||
|
uniform float bgimage_scale;
|
||||||
|
|
||||||
|
// These are of the window, not the screen.
|
||||||
|
uniform float width;
|
||||||
|
uniform float height;
|
||||||
|
#endif
|
||||||
|
in vec2 texcoord;
|
||||||
|
out vec4 color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
#ifdef TILED
|
||||||
|
vec2 txsz = vec2(width,height) / textureSize(image,0);
|
||||||
|
txsz /= bgimage_scale;
|
||||||
|
color = texture(image, texcoord * txsz);
|
||||||
|
#endif
|
||||||
|
#ifdef SIMPLE
|
||||||
|
color = texture(image, texcoord);
|
||||||
|
#endif
|
||||||
|
color = vec4(color.rgb, color.a * bgimage_opacity);
|
||||||
|
}
|
||||||
9
kitty/bgimage_vertex.glsl
Normal file
9
kitty/bgimage_vertex.glsl
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#version GLSL_VERSION
|
||||||
|
|
||||||
|
layout(location=0) in vec4 src;
|
||||||
|
out vec2 texcoord;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
texcoord = clamp(vec2(src[0], src[1]*-1), 0, 1);
|
||||||
|
gl_Position = src;
|
||||||
|
}
|
||||||
@ -60,11 +60,13 @@ class Borders:
|
|||||||
active_window,
|
active_window,
|
||||||
current_layout,
|
current_layout,
|
||||||
extra_blank_rects,
|
extra_blank_rects,
|
||||||
draw_window_borders=True
|
draw_window_borders=True,
|
||||||
|
draw_blank_rects=False
|
||||||
):
|
):
|
||||||
add_borders_rect(self.os_window_id, self.tab_id, 0, 0, 0, 0, BorderColor.default_bg)
|
add_borders_rect(self.os_window_id, self.tab_id, 0, 0, 0, 0, BorderColor.default_bg)
|
||||||
for br in chain(current_layout.blank_rects, extra_blank_rects):
|
if draw_blank_rects:
|
||||||
add_borders_rect(self.os_window_id, self.tab_id, *br, BorderColor.default_bg)
|
for br in chain(current_layout.blank_rects, extra_blank_rects):
|
||||||
|
add_borders_rect(self.os_window_id, self.tab_id, *br, BorderColor.default_bg)
|
||||||
bw, pw = self.border_width, self.padding_width
|
bw, pw = self.border_width, self.padding_width
|
||||||
if bw + pw <= 0:
|
if bw + pw <= 0:
|
||||||
return
|
return
|
||||||
|
|||||||
@ -657,6 +657,7 @@ render(monotonic_t now, bool input_read) {
|
|||||||
|
|
||||||
for (size_t i = 0; i < global_state.num_os_windows; i++) {
|
for (size_t i = 0; i < global_state.num_os_windows; i++) {
|
||||||
OSWindow *w = global_state.os_windows + i;
|
OSWindow *w = global_state.os_windows + i;
|
||||||
|
w->render_calls++;
|
||||||
if (!w->num_tabs) continue;
|
if (!w->num_tabs) continue;
|
||||||
if (!should_os_window_be_rendered(w)) {
|
if (!should_os_window_be_rendered(w)) {
|
||||||
update_os_window_title(w);
|
update_os_window_title(w);
|
||||||
@ -688,6 +689,7 @@ render(monotonic_t now, bool input_read) {
|
|||||||
if (!w->fonts_data) { log_error("No fonts data found for window id: %llu", w->id); continue; }
|
if (!w->fonts_data) { log_error("No fonts data found for window id: %llu", w->id); continue; }
|
||||||
if (prepare_to_render_os_window(w, now, &active_window_id, &active_window_bg, &num_visible_windows, &all_windows_have_same_bg)) needs_render = true;
|
if (prepare_to_render_os_window(w, now, &active_window_id, &active_window_bg, &num_visible_windows, &all_windows_have_same_bg)) needs_render = true;
|
||||||
if (w->last_active_window_id != active_window_id || w->last_active_tab != w->active_tab || w->focused_at_last_render != w->is_focused) needs_render = true;
|
if (w->last_active_window_id != active_window_id || w->last_active_tab != w->active_tab || w->focused_at_last_render != w->is_focused) needs_render = true;
|
||||||
|
if (w->render_calls < 3 && w->bgimage != NULL) needs_render = true;
|
||||||
if (needs_render) render_os_window(w, now, active_window_id, active_window_bg, num_visible_windows, all_windows_have_same_bg);
|
if (needs_render) render_os_window(w, now, active_window_id, active_window_bg, num_visible_windows, all_windows_have_same_bg);
|
||||||
}
|
}
|
||||||
last_render_at = now;
|
last_render_at = now;
|
||||||
|
|||||||
@ -846,6 +846,37 @@ of windows set :opt:`dynamic_background_opacity` to :code:`yes` (this is off by
|
|||||||
default as it has a performance cost)
|
default as it has a performance cost)
|
||||||
'''))
|
'''))
|
||||||
|
|
||||||
|
|
||||||
|
def startup_session(x):
|
||||||
|
if x.lower() == 'none':
|
||||||
|
return
|
||||||
|
x = os.path.expanduser(x)
|
||||||
|
x = os.path.expandvars(x)
|
||||||
|
if not os.path.isabs(x):
|
||||||
|
x = os.path.join(config_dir, x)
|
||||||
|
return x
|
||||||
|
|
||||||
|
|
||||||
|
o('background_image', 'none', option_type=startup_session, long_text=_('''
|
||||||
|
Path to a background image. Must be PNG.'''))
|
||||||
|
|
||||||
|
o('background_image_layout', 'tiling', option_type=choices('tiling', 'scaled', 'mirror_tiled'), long_text=_('''
|
||||||
|
Whether to tile or scale the background image.'''))
|
||||||
|
|
||||||
|
o('background_image_linear', False, long_text=_('''
|
||||||
|
When background image is scaled, whether linear interpolation should be used.'''))
|
||||||
|
|
||||||
|
o('background_image_opacity', 0.5, option_type=positive_float, long_text=_('''
|
||||||
|
Background image opacity, between 0.0 and 1.0 inclusive. This
|
||||||
|
can only ever decrease a background's opacity, if the image is already
|
||||||
|
semi-transparent, "1" is interpreted as the image's current transparency.'''))
|
||||||
|
|
||||||
|
o('background_image_scale', 1.0, option_type=positive_float, long_text=_('''
|
||||||
|
Only has an effect if :opt:`background_image_layout` is tiling, should be positive.'''))
|
||||||
|
|
||||||
|
o('background_image_scale', 1.0, option_type=positive_float, long_text=_('''
|
||||||
|
Only has an effect if :opt:`background_image_layout` is tiling, should be positive.'''))
|
||||||
|
|
||||||
o('dynamic_background_opacity', False, long_text=_('''
|
o('dynamic_background_opacity', False, long_text=_('''
|
||||||
Allow changing of the :opt:`background_opacity` dynamically, using either keyboard
|
Allow changing of the :opt:`background_opacity` dynamically, using either keyboard
|
||||||
shortcuts (:sc:`increase_background_opacity` and :sc:`decrease_background_opacity`)
|
shortcuts (:sc:`increase_background_opacity` and :sc:`decrease_background_opacity`)
|
||||||
@ -966,16 +997,6 @@ The default is to check every 24 hrs, set to zero to disable.
|
|||||||
'''))
|
'''))
|
||||||
|
|
||||||
|
|
||||||
def startup_session(x):
|
|
||||||
if x.lower() == 'none':
|
|
||||||
return
|
|
||||||
x = os.path.expanduser(x)
|
|
||||||
x = os.path.expandvars(x)
|
|
||||||
if not os.path.isabs(x):
|
|
||||||
x = os.path.join(config_dir, x)
|
|
||||||
return x
|
|
||||||
|
|
||||||
|
|
||||||
o('startup_session', 'none', option_type=startup_session, long_text=_('''
|
o('startup_session', 'none', option_type=startup_session, long_text=_('''
|
||||||
Path to a session file to use for all kitty instances. Can be overridden
|
Path to a session file to use for all kitty instances. Can be overridden
|
||||||
by using the :option:`kitty --session` command line option for individual
|
by using the :option:`kitty --session` command line option for individual
|
||||||
|
|||||||
@ -55,6 +55,7 @@ typedef enum MouseTrackingModes { NO_TRACKING, BUTTON_MODE, MOTION_MODE, ANY_MOD
|
|||||||
typedef enum MouseTrackingProtocols { NORMAL_PROTOCOL, UTF8_PROTOCOL, SGR_PROTOCOL, URXVT_PROTOCOL} MouseTrackingProtocol;
|
typedef enum MouseTrackingProtocols { NORMAL_PROTOCOL, UTF8_PROTOCOL, SGR_PROTOCOL, URXVT_PROTOCOL} MouseTrackingProtocol;
|
||||||
typedef enum MouseShapes { BEAM, HAND, ARROW } MouseShape;
|
typedef enum MouseShapes { BEAM, HAND, ARROW } MouseShape;
|
||||||
typedef enum { NONE, MENUBAR, WINDOW, ALL } WindowTitleIn;
|
typedef enum { NONE, MENUBAR, WINDOW, ALL } WindowTitleIn;
|
||||||
|
typedef enum { TILING, SCALED, MIRRORED } BackgroundImageLayout;
|
||||||
|
|
||||||
#define MAX_CHILDREN 512
|
#define MAX_CHILDREN 512
|
||||||
#define BLANK_CHAR 0
|
#define BLANK_CHAR 0
|
||||||
|
|||||||
@ -377,7 +377,7 @@ make_os_window_context_current(OSWindow *w) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline void
|
void
|
||||||
get_window_content_scale(GLFWwindow *w, float *xscale, float *yscale, double *xdpi, double *ydpi) {
|
get_window_content_scale(GLFWwindow *w, float *xscale, float *yscale, double *xdpi, double *ydpi) {
|
||||||
if (w) glfwGetWindowContentScale(w, xscale, yscale);
|
if (w) glfwGetWindowContentScale(w, xscale, yscale);
|
||||||
else {
|
else {
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
* Distributed under terms of the GPL3 license.
|
* Distributed under terms of the GPL3 license.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "gl.h"
|
||||||
#include "graphics.h"
|
#include "graphics.h"
|
||||||
#include "state.h"
|
#include "state.h"
|
||||||
|
|
||||||
@ -29,9 +30,8 @@ static bool send_to_gpu = true;
|
|||||||
GraphicsManager*
|
GraphicsManager*
|
||||||
grman_alloc() {
|
grman_alloc() {
|
||||||
GraphicsManager *self = (GraphicsManager *)GraphicsManager_Type.tp_alloc(&GraphicsManager_Type, 0);
|
GraphicsManager *self = (GraphicsManager *)GraphicsManager_Type.tp_alloc(&GraphicsManager_Type, 0);
|
||||||
self->images_capacity = 64;
|
self->images_capacity = self->capacity = 64;
|
||||||
self->images = calloc(self->images_capacity, sizeof(Image));
|
self->images = calloc(self->images_capacity, sizeof(Image));
|
||||||
self->capacity = 64;
|
|
||||||
self->render_data = calloc(self->capacity, sizeof(ImageRenderData));
|
self->render_data = calloc(self->capacity, sizeof(ImageRenderData));
|
||||||
if (self->images == NULL || self->render_data == NULL) {
|
if (self->images == NULL || self->render_data == NULL) {
|
||||||
PyErr_NoMemory();
|
PyErr_NoMemory();
|
||||||
@ -248,6 +248,38 @@ add_trim_predicate(Image *img) {
|
|||||||
return !img->data_loaded || (!img->client_id && !img->refcnt);
|
return !img->data_loaded || (!img->client_id && !img->refcnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool png_path_to_bitmap(uint8_t** data, unsigned int* width, unsigned int* height, size_t* sz) {
|
||||||
|
const char* path = OPT(background_image);
|
||||||
|
if (access(path, R_OK) != 0) {
|
||||||
|
log_error("File %s, (requested background image,) does not exist (%d)", path, errno);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
FILE* fp = fopen(path, "r");
|
||||||
|
if (fp == NULL) {
|
||||||
|
log_error("File %s, (requested background image,) could not be opened", path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
fseek(fp, 0L, SEEK_END);
|
||||||
|
size_t filesize = ftell(fp);
|
||||||
|
*data = calloc(filesize, sizeof(char));
|
||||||
|
fseek(fp, 0L, SEEK_SET); // rewind() deprecated on some platforms
|
||||||
|
fread(*data, sizeof(char), filesize, fp);
|
||||||
|
fclose(fp);
|
||||||
|
png_read_data d;
|
||||||
|
memset(&d, 0, sizeof(png_read_data));
|
||||||
|
inflate_png_inner(&d, *data, filesize);
|
||||||
|
if (!d.ok) {
|
||||||
|
log_error("File %s, (requested background image,) not readable by libpng", path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
free(*data);
|
||||||
|
*data = d.decompressed;
|
||||||
|
*sz = d.sz;
|
||||||
|
*height = d.height; *width = d.width;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline Image*
|
static inline Image*
|
||||||
find_or_create_image(GraphicsManager *self, uint32_t id, bool *existing) {
|
find_or_create_image(GraphicsManager *self, uint32_t id, bool *existing) {
|
||||||
if (id) {
|
if (id) {
|
||||||
@ -421,7 +453,7 @@ handle_add_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_
|
|||||||
size_t required_sz = (img->load_data.is_opaque ? 3 : 4) * img->width * img->height;
|
size_t required_sz = (img->load_data.is_opaque ? 3 : 4) * img->width * img->height;
|
||||||
if (img->load_data.data_sz != required_sz) ABRT(EINVAL, "Image dimensions: %ux%u do not match data size: %zu, expected size: %zu", img->width, img->height, img->load_data.data_sz, required_sz);
|
if (img->load_data.data_sz != required_sz) ABRT(EINVAL, "Image dimensions: %ux%u do not match data size: %zu, expected size: %zu", img->width, img->height, img->load_data.data_sz, required_sz);
|
||||||
if (LIKELY(img->data_loaded && send_to_gpu)) {
|
if (LIKELY(img->data_loaded && send_to_gpu)) {
|
||||||
send_image_to_gpu(&img->texture_id, img->load_data.data, img->width, img->height, img->load_data.is_opaque, img->load_data.is_4byte_aligned);
|
send_image_to_gpu(&img->texture_id, img->load_data.data, img->width, img->height, img->load_data.is_opaque, img->load_data.is_4byte_aligned, false, REPEAT_CLAMP);
|
||||||
free_load_data(&img->load_data);
|
free_load_data(&img->load_data);
|
||||||
self->used_storage += required_sz;
|
self->used_storage += required_sz;
|
||||||
img->used_storage = required_sz;
|
img->used_storage = required_sz;
|
||||||
|
|||||||
@ -55,6 +55,12 @@ typedef struct {
|
|||||||
size_t used_storage;
|
size_t used_storage;
|
||||||
} Image;
|
} Image;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t texture_id;
|
||||||
|
unsigned int height, width;
|
||||||
|
uint8_t* bitmap;
|
||||||
|
} BackgroundImage;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float vertices[16];
|
float vertices[16];
|
||||||
uint32_t texture_id, group_count;
|
uint32_t texture_id, group_count;
|
||||||
@ -71,6 +77,8 @@ typedef struct {
|
|||||||
Image *images;
|
Image *images;
|
||||||
size_t count, capacity;
|
size_t count, capacity;
|
||||||
ImageRenderData *render_data;
|
ImageRenderData *render_data;
|
||||||
|
Image bgimage;
|
||||||
|
ImageRenderData bgimage_rd;
|
||||||
bool layers_dirty;
|
bool layers_dirty;
|
||||||
// The number of images below MIN_ZINDEX / 2, then the number of refs between MIN_ZINDEX / 2 and -1 inclusive, then the number of refs above 0 inclusive.
|
// The number of images below MIN_ZINDEX / 2, then the number of refs between MIN_ZINDEX / 2 and -1 inclusive, then the number of refs above 0 inclusive.
|
||||||
size_t num_of_below_refs, num_of_negative_refs, num_of_positive_refs;
|
size_t num_of_below_refs, num_of_negative_refs, num_of_positive_refs;
|
||||||
@ -93,3 +101,4 @@ void grman_scroll_images(GraphicsManager *self, const ScrollData*, CellPixelSize
|
|||||||
void grman_resize(GraphicsManager*, index_type, index_type, index_type, index_type);
|
void grman_resize(GraphicsManager*, index_type, index_type, index_type, index_type);
|
||||||
void grman_rescale(GraphicsManager *self, CellPixelSize fg);
|
void grman_rescale(GraphicsManager *self, CellPixelSize fg);
|
||||||
void gpu_data_for_centered_image(ImageRenderData *ans, unsigned int screen_width_px, unsigned int screen_height_px, unsigned int width, unsigned int height);
|
void gpu_data_for_centered_image(ImageRenderData *ans, unsigned int screen_width_px, unsigned int screen_height_px, unsigned int width, unsigned int height);
|
||||||
|
bool png_path_to_bitmap(uint8_t** data, unsigned int* width, unsigned int* height, size_t* sz);
|
||||||
|
|||||||
@ -111,6 +111,7 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
|
|||||||
self->historybuf = alloc_historybuf(MAX(scrollback, lines), columns, OPT(scrollback_pager_history_size));
|
self->historybuf = alloc_historybuf(MAX(scrollback, lines), columns, OPT(scrollback_pager_history_size));
|
||||||
self->main_grman = grman_alloc();
|
self->main_grman = grman_alloc();
|
||||||
self->alt_grman = grman_alloc();
|
self->alt_grman = grman_alloc();
|
||||||
|
|
||||||
self->grman = self->main_grman;
|
self->grman = self->main_grman;
|
||||||
self->pending_mode.wait_time = 2.0;
|
self->pending_mode.wait_time = 2.0;
|
||||||
self->disable_ligatures = OPT(disable_ligatures);
|
self->disable_ligatures = OPT(disable_ligatures);
|
||||||
|
|||||||
109
kitty/shaders.c
109
kitty/shaders.c
@ -7,10 +7,12 @@
|
|||||||
|
|
||||||
#include "fonts.h"
|
#include "fonts.h"
|
||||||
#include "gl.h"
|
#include "gl.h"
|
||||||
|
#include "png-reader.h"
|
||||||
|
#include <png.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
enum { CELL_PROGRAM, CELL_BG_PROGRAM, CELL_SPECIAL_PROGRAM, CELL_FG_PROGRAM, BORDERS_PROGRAM, GRAPHICS_PROGRAM, GRAPHICS_PREMULT_PROGRAM, GRAPHICS_ALPHA_MASK_PROGRAM, BLIT_PROGRAM, NUM_PROGRAMS };
|
enum { CELL_PROGRAM, CELL_BG_PROGRAM, CELL_SPECIAL_PROGRAM, CELL_FG_PROGRAM, BORDERS_PROGRAM, GRAPHICS_PROGRAM, GRAPHICS_PREMULT_PROGRAM, GRAPHICS_ALPHA_MASK_PROGRAM, BLIT_PROGRAM, BGIMAGE_PROGRAM, BGIMAGE_TILED_PROGRAM, NUM_PROGRAMS };
|
||||||
enum { SPRITE_MAP_UNIT, GRAPHICS_UNIT, BLIT_UNIT };
|
enum { SPRITE_MAP_UNIT, GRAPHICS_UNIT, BLIT_UNIT, BGIMAGE_UNIT };
|
||||||
|
|
||||||
// Sprites {{{
|
// Sprites {{{
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -22,6 +24,7 @@ typedef struct {
|
|||||||
|
|
||||||
static const SpriteMap NEW_SPRITE_MAP = { .xnum = 1, .ynum = 1, .last_num_of_layers = 1, .last_ynum = -1 };
|
static const SpriteMap NEW_SPRITE_MAP = { .xnum = 1, .ynum = 1, .last_num_of_layers = 1, .last_ynum = -1 };
|
||||||
static GLint max_texture_size = 0, max_array_texture_layers = 0;
|
static GLint max_texture_size = 0, max_array_texture_layers = 0;
|
||||||
|
//static uint8_t *bg_image = NULL;
|
||||||
|
|
||||||
SPRITE_MAP_HANDLE
|
SPRITE_MAP_HANDLE
|
||||||
alloc_sprite_map(unsigned int cell_width, unsigned int cell_height) {
|
alloc_sprite_map(unsigned int cell_width, unsigned int cell_height) {
|
||||||
@ -132,14 +135,23 @@ send_sprite_to_gpu(FONTS_DATA_HANDLE fg, unsigned int x, unsigned int y, unsigne
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
send_image_to_gpu(GLuint *tex_id, const void* data, GLsizei width, GLsizei height, bool is_opaque, bool is_4byte_aligned) {
|
send_image_to_gpu(GLuint *tex_id, const void* data, GLsizei width, GLsizei height, bool is_opaque, bool is_4byte_aligned, bool linear, RepeatStrategy repeat) {
|
||||||
if (!(*tex_id)) { glGenTextures(1, tex_id); }
|
if (!(*tex_id)) { glGenTextures(1, tex_id); }
|
||||||
glBindTexture(GL_TEXTURE_2D, *tex_id);
|
glBindTexture(GL_TEXTURE_2D, *tex_id);
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, is_4byte_aligned ? 4 : 1);
|
glPixelStorei(GL_UNPACK_ALIGNMENT, is_4byte_aligned ? 4 : 1);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, linear ? GL_LINEAR : GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, linear ? GL_LINEAR : GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
RepeatStrategy r;
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
switch (repeat) {
|
||||||
|
case REPEAT_MIRROR:
|
||||||
|
r = GL_MIRRORED_REPEAT; break;
|
||||||
|
case REPEAT_CLAMP:
|
||||||
|
r = GL_CLAMP_TO_EDGE; break;
|
||||||
|
default:
|
||||||
|
r = GL_REPEAT;
|
||||||
|
}
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, r);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, r);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, is_opaque ? GL_RGB : GL_RGBA, GL_UNSIGNED_BYTE, data);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, is_opaque ? GL_RGB : GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,6 +335,47 @@ cell_prepare_to_render(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen, GLfloa
|
|||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
draw_bg(int program, OSWindow *w) {
|
||||||
|
if (w->bvao_idx == 0) {
|
||||||
|
const GLfloat screenrect[4][2] = {
|
||||||
|
{ -1.0, 1.0 },
|
||||||
|
{ -1.0, -1.0 },
|
||||||
|
{ 1.0, -1.0 },
|
||||||
|
{ 1.0, 1.0 },
|
||||||
|
};
|
||||||
|
w->bvao_idx = create_vao();
|
||||||
|
bind_vertex_array(w->bvao_idx);
|
||||||
|
glGenBuffers(1, &w->vbo_idx);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, w->vbo_idx);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, 4*2*sizeof(float), screenrect, GL_STATIC_DRAW);
|
||||||
|
}
|
||||||
|
bind_vertex_array(w->bvao_idx);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, w->vbo_idx);
|
||||||
|
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
|
||||||
|
bind_program(program);
|
||||||
|
static bool bgimage_constants_set;
|
||||||
|
if (!bgimage_constants_set) {
|
||||||
|
glUniform1i(glGetUniformLocation(program_id(program), "image"), BGIMAGE_UNIT);
|
||||||
|
glUniform1f(glGetUniformLocation(program_id(program), "bgimage_scale"), OPT(background_image_scale));
|
||||||
|
glUniform1f(glGetUniformLocation(program_id(program), "bgimage_opacity"), OPT(background_image_opacity));
|
||||||
|
bgimage_constants_set = true;
|
||||||
|
}
|
||||||
|
glUniform1f(glGetUniformLocation(program_id(program), "height"), (float)(w->window_height));
|
||||||
|
glUniform1f(glGetUniformLocation(program_id(program), "width"), (float)(w->window_width));
|
||||||
|
glActiveTexture(GL_TEXTURE0 + BGIMAGE_UNIT);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, w->bgimage->texture_id);
|
||||||
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||||
|
|
||||||
|
unbind_vertex_array();
|
||||||
|
unbind_program();
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
draw_graphics(int program, ssize_t vao_idx, ssize_t gvao_idx, ImageRenderData *data, GLuint start, GLuint count) {
|
draw_graphics(int program, ssize_t vao_idx, ssize_t gvao_idx, ImageRenderData *data, GLuint start, GLuint count) {
|
||||||
bind_program(program);
|
bind_program(program);
|
||||||
@ -389,16 +442,18 @@ draw_cells_simple(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
draw_cells_interleaved(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen) {
|
draw_cells_interleaved(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen, OSWindow *w) {
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
BLEND_ONTO_OPAQUE;
|
BLEND_ONTO_OPAQUE;
|
||||||
|
|
||||||
bind_program(CELL_BG_PROGRAM);
|
bind_program(CELL_BG_PROGRAM);
|
||||||
// draw background for all cells
|
// draw background for all cells
|
||||||
glUniform1ui(cell_program_layouts[CELL_BG_PROGRAM].draw_bg_bitfield_location, 3);
|
glUniform1ui(cell_program_layouts[CELL_BG_PROGRAM].draw_bg_bitfield_location, 3);
|
||||||
|
// This gives users a way to still use background images without a compositor.
|
||||||
|
if (OPT(background_opacity) != 0.0)
|
||||||
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
|
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
|
||||||
|
|
||||||
if (screen->grman->num_of_below_refs) {
|
if (screen->grman->num_of_below_refs || w->bgimage != NULL) {
|
||||||
draw_graphics(GRAPHICS_PROGRAM, vao_idx, gvao_idx, screen->grman->render_data, 0, screen->grman->num_of_below_refs);
|
draw_graphics(GRAPHICS_PROGRAM, vao_idx, gvao_idx, screen->grman->render_data, 0, screen->grman->num_of_below_refs);
|
||||||
bind_program(CELL_BG_PROGRAM);
|
bind_program(CELL_BG_PROGRAM);
|
||||||
// draw background for non-default bg cells
|
// draw background for non-default bg cells
|
||||||
@ -435,12 +490,13 @@ draw_cells_interleaved_premult(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen
|
|||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, os_window->offscreen_framebuffer);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, os_window->offscreen_framebuffer);
|
||||||
glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, os_window->offscreen_texture_id, 0);
|
glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, os_window->offscreen_texture_id, 0);
|
||||||
/* if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) fatal("Offscreen framebuffer not complete"); */
|
/* if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) fatal("Offscreen framebuffer not complete"); */
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
BLEND_PREMULT;
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
bind_program(CELL_BG_PROGRAM);
|
bind_program(CELL_BG_PROGRAM);
|
||||||
// draw background for all cells
|
// draw background for all cells
|
||||||
glUniform1ui(cell_program_layouts[CELL_BG_PROGRAM].draw_bg_bitfield_location, 3);
|
glUniform1ui(cell_program_layouts[CELL_BG_PROGRAM].draw_bg_bitfield_location, 3);
|
||||||
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
|
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
|
||||||
glEnable(GL_BLEND);
|
|
||||||
BLEND_PREMULT;
|
|
||||||
|
|
||||||
if (screen->grman->num_of_below_refs) {
|
if (screen->grman->num_of_below_refs) {
|
||||||
draw_graphics(GRAPHICS_PREMULT_PROGRAM, vao_idx, gvao_idx, screen->grman->render_data, 0, screen->grman->num_of_below_refs);
|
draw_graphics(GRAPHICS_PREMULT_PROGRAM, vao_idx, gvao_idx, screen->grman->render_data, 0, screen->grman->num_of_below_refs);
|
||||||
@ -469,11 +525,10 @@ draw_cells_interleaved_premult(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen
|
|||||||
|
|
||||||
if (screen->grman->num_of_positive_refs) draw_graphics(GRAPHICS_PREMULT_PROGRAM, vao_idx, gvao_idx, screen->grman->render_data, screen->grman->num_of_negative_refs + screen->grman->num_of_below_refs, screen->grman->num_of_positive_refs);
|
if (screen->grman->num_of_positive_refs) draw_graphics(GRAPHICS_PREMULT_PROGRAM, vao_idx, gvao_idx, screen->grman->render_data, screen->grman->num_of_negative_refs + screen->grman->num_of_below_refs, screen->grman->num_of_positive_refs);
|
||||||
|
|
||||||
glDisable(GL_BLEND);
|
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
|
||||||
// Now render the framebuffer to the screen
|
// Now render the framebuffer to the screen
|
||||||
glEnable(GL_SCISSOR_TEST);
|
|
||||||
bind_program(BLIT_PROGRAM); bind_vertex_array(blit_vertex_array);
|
bind_program(BLIT_PROGRAM); bind_vertex_array(blit_vertex_array);
|
||||||
static bool blit_constants_set = false;
|
static bool blit_constants_set = false;
|
||||||
if (!blit_constants_set) {
|
if (!blit_constants_set) {
|
||||||
@ -484,6 +539,7 @@ draw_cells_interleaved_premult(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen
|
|||||||
glBindTexture(GL_TEXTURE_2D, os_window->offscreen_texture_id);
|
glBindTexture(GL_TEXTURE_2D, os_window->offscreen_texture_id);
|
||||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||||
glDisable(GL_SCISSOR_TEST);
|
glDisable(GL_SCISSOR_TEST);
|
||||||
|
glDisable(GL_BLEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
@ -496,6 +552,7 @@ set_cell_uniforms(float current_inactive_text_alpha, bool force) {
|
|||||||
cell_uniform_data.amask_premult_loc = glGetUniformLocation(program_id(GRAPHICS_ALPHA_MASK_PROGRAM), "alpha_mask_premult");
|
cell_uniform_data.amask_premult_loc = glGetUniformLocation(program_id(GRAPHICS_ALPHA_MASK_PROGRAM), "alpha_mask_premult");
|
||||||
#define S(prog, name, val, type) { bind_program(prog); glUniform##type(glGetUniformLocation(program_id(prog), #name), val); }
|
#define S(prog, name, val, type) { bind_program(prog); glUniform##type(glGetUniformLocation(program_id(prog), #name), val); }
|
||||||
S(GRAPHICS_PROGRAM, image, GRAPHICS_UNIT, 1i);
|
S(GRAPHICS_PROGRAM, image, GRAPHICS_UNIT, 1i);
|
||||||
|
S(GRAPHICS_PROGRAM, image, BGIMAGE_UNIT, 1i);
|
||||||
S(GRAPHICS_PREMULT_PROGRAM, image, GRAPHICS_UNIT, 1i);
|
S(GRAPHICS_PREMULT_PROGRAM, image, GRAPHICS_UNIT, 1i);
|
||||||
S(CELL_PROGRAM, sprites, SPRITE_MAP_UNIT, 1i); S(CELL_FG_PROGRAM, sprites, SPRITE_MAP_UNIT, 1i);
|
S(CELL_PROGRAM, sprites, SPRITE_MAP_UNIT, 1i); S(CELL_FG_PROGRAM, sprites, SPRITE_MAP_UNIT, 1i);
|
||||||
S(CELL_PROGRAM, dim_opacity, OPT(dim_opacity), 1f); S(CELL_FG_PROGRAM, dim_opacity, OPT(dim_opacity), 1f);
|
S(CELL_PROGRAM, dim_opacity, OPT(dim_opacity), 1f); S(CELL_FG_PROGRAM, dim_opacity, OPT(dim_opacity), 1f);
|
||||||
@ -558,10 +615,10 @@ draw_cells(ssize_t vao_idx, ssize_t gvao_idx, GLfloat xstart, GLfloat ystart, GL
|
|||||||
);
|
);
|
||||||
#undef SCALE
|
#undef SCALE
|
||||||
if (os_window->is_semi_transparent) {
|
if (os_window->is_semi_transparent) {
|
||||||
if (screen->grman->count) draw_cells_interleaved_premult(vao_idx, gvao_idx, screen, os_window);
|
if (screen->grman->count || os_window->bgimage != NULL) draw_cells_interleaved_premult(vao_idx, gvao_idx, screen, os_window);
|
||||||
else draw_cells_simple(vao_idx, gvao_idx, screen);
|
else draw_cells_simple(vao_idx, gvao_idx, screen);
|
||||||
} else {
|
} else {
|
||||||
if (screen->grman->num_of_negative_refs || screen->grman->num_of_below_refs) draw_cells_interleaved(vao_idx, gvao_idx, screen);
|
if (screen->grman->num_of_negative_refs || screen->grman->num_of_below_refs || os_window->bgimage != NULL) draw_cells_interleaved(vao_idx, gvao_idx, screen, os_window);
|
||||||
else draw_cells_simple(vao_idx, gvao_idx, screen);
|
else draw_cells_simple(vao_idx, gvao_idx, screen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -604,16 +661,28 @@ create_border_vao(void) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
draw_borders(ssize_t vao_idx, unsigned int num_border_rects, BorderRect *rect_buf, bool rect_data_is_dirty, uint32_t viewport_width, uint32_t viewport_height, color_type active_window_bg, unsigned int num_visible_windows, bool all_windows_have_same_bg, OSWindow *w) {
|
draw_borders(ssize_t vao_idx, unsigned int num_border_rects, BorderRect *rect_buf, bool rect_data_is_dirty, uint32_t viewport_width, uint32_t viewport_height, color_type active_window_bg, unsigned int num_visible_windows, bool all_windows_have_same_bg, OSWindow *w) {
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
BLEND_ONTO_OPAQUE;
|
||||||
|
|
||||||
|
if (w->bgimage != NULL) {
|
||||||
|
int program;
|
||||||
|
if (OPT(background_image_layout) == TILING || OPT(background_image_layout) == MIRRORED) program = BGIMAGE_TILED_PROGRAM;
|
||||||
|
else program = BGIMAGE_PROGRAM;
|
||||||
|
|
||||||
|
draw_bg(program, w);
|
||||||
|
}
|
||||||
|
|
||||||
if (num_border_rects) {
|
if (num_border_rects) {
|
||||||
|
bind_vertex_array(vao_idx);
|
||||||
|
bind_program(BORDERS_PROGRAM);
|
||||||
if (rect_data_is_dirty) {
|
if (rect_data_is_dirty) {
|
||||||
size_t sz = sizeof(GLuint) * 5 * num_border_rects;
|
size_t sz = sizeof(GLuint) * 5 * num_border_rects;
|
||||||
void *borders_buf_address = alloc_and_map_vao_buffer(vao_idx, sz, 0, GL_STATIC_DRAW, GL_WRITE_ONLY);
|
void *borders_buf_address = alloc_and_map_vao_buffer(vao_idx, sz, 0, GL_STATIC_DRAW, GL_WRITE_ONLY);
|
||||||
if (borders_buf_address) memcpy(borders_buf_address, rect_buf, sz);
|
if (borders_buf_address) memcpy(borders_buf_address, rect_buf, sz);
|
||||||
unmap_vao_buffer(vao_idx, 0);
|
unmap_vao_buffer(vao_idx, 0);
|
||||||
}
|
}
|
||||||
bind_program(BORDERS_PROGRAM);
|
|
||||||
#define CV3(x) (((float)((x >> 16) & 0xff))/255.f), (((float)((x >> 8) & 0xff))/255.f), (((float)(x & 0xff))/255.f)
|
#define CV3(x) (((float)((x >> 16) & 0xff))/255.f), (((float)((x >> 8) & 0xff))/255.f), (((float)(x & 0xff))/255.f)
|
||||||
glUniform1f(border_uniform_locations[BORDER_background_opacity], w->is_semi_transparent ? w->background_opacity : 1.0f);
|
glUniform1f(border_uniform_locations[BORDER_background_opacity], w->is_semi_transparent ? MAX(w->background_opacity, OPT(background_image_opacity)) : 1.0f);
|
||||||
glUniform3f(border_uniform_locations[BORDER_active_border_color], CV3(OPT(active_border_color)));
|
glUniform3f(border_uniform_locations[BORDER_active_border_color], CV3(OPT(active_border_color)));
|
||||||
glUniform3f(border_uniform_locations[BORDER_inactive_border_color], CV3(OPT(inactive_border_color)));
|
glUniform3f(border_uniform_locations[BORDER_inactive_border_color], CV3(OPT(inactive_border_color)));
|
||||||
glUniform3f(border_uniform_locations[BORDER_bell_border_color], CV3(OPT(bell_border_color)));
|
glUniform3f(border_uniform_locations[BORDER_bell_border_color], CV3(OPT(bell_border_color)));
|
||||||
@ -621,11 +690,11 @@ draw_borders(ssize_t vao_idx, unsigned int num_border_rects, BorderRect *rect_bu
|
|||||||
color_type default_bg = (num_visible_windows > 1 && !all_windows_have_same_bg) ? OPT(background) : active_window_bg;
|
color_type default_bg = (num_visible_windows > 1 && !all_windows_have_same_bg) ? OPT(background) : active_window_bg;
|
||||||
glUniform3f(border_uniform_locations[BORDER_default_bg], CV3(default_bg));
|
glUniform3f(border_uniform_locations[BORDER_default_bg], CV3(default_bg));
|
||||||
#undef CV3
|
#undef CV3
|
||||||
bind_vertex_array(vao_idx);
|
|
||||||
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, num_border_rects);
|
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, num_border_rects);
|
||||||
unbind_vertex_array();
|
unbind_vertex_array();
|
||||||
unbind_program();
|
unbind_program();
|
||||||
}
|
}
|
||||||
|
glDisable(GL_BLEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
@ -722,7 +791,7 @@ static PyMethodDef module_methods[] = {
|
|||||||
bool
|
bool
|
||||||
init_shaders(PyObject *module) {
|
init_shaders(PyObject *module) {
|
||||||
#define C(x) if (PyModule_AddIntConstant(module, #x, x) != 0) { PyErr_NoMemory(); return false; }
|
#define C(x) if (PyModule_AddIntConstant(module, #x, x) != 0) { PyErr_NoMemory(); return false; }
|
||||||
C(CELL_PROGRAM); C(CELL_BG_PROGRAM); C(CELL_SPECIAL_PROGRAM); C(CELL_FG_PROGRAM); C(BORDERS_PROGRAM); C(GRAPHICS_PROGRAM); C(GRAPHICS_PREMULT_PROGRAM); C(GRAPHICS_ALPHA_MASK_PROGRAM); C(BLIT_PROGRAM);
|
C(CELL_PROGRAM); C(CELL_BG_PROGRAM); C(CELL_SPECIAL_PROGRAM); C(CELL_FG_PROGRAM); C(BORDERS_PROGRAM); C(GRAPHICS_PROGRAM); C(GRAPHICS_PREMULT_PROGRAM); C(GRAPHICS_ALPHA_MASK_PROGRAM); C(BLIT_PROGRAM); C(BGIMAGE_PROGRAM); C(BGIMAGE_TILED_PROGRAM);
|
||||||
C(GLSL_VERSION);
|
C(GLSL_VERSION);
|
||||||
C(GL_VERSION);
|
C(GL_VERSION);
|
||||||
C(GL_VENDOR);
|
C(GL_VENDOR);
|
||||||
|
|||||||
@ -81,6 +81,39 @@ add_os_window() {
|
|||||||
ans->tab_bar_render_data.vao_idx = create_cell_vao();
|
ans->tab_bar_render_data.vao_idx = create_cell_vao();
|
||||||
ans->gvao_idx = create_graphics_vao();
|
ans->gvao_idx = create_graphics_vao();
|
||||||
ans->background_opacity = OPT(background_opacity);
|
ans->background_opacity = OPT(background_opacity);
|
||||||
|
|
||||||
|
bool wants_bg = OPT(background_image) != NULL;
|
||||||
|
if (wants_bg) {
|
||||||
|
bool has_bg;
|
||||||
|
has_bg = global_state.bgimage != NULL;
|
||||||
|
|
||||||
|
if (!has_bg) {
|
||||||
|
BackgroundImage* bgimage = calloc(1, sizeof(BackgroundImage));
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
has_bg = png_path_to_bitmap(&bgimage->bitmap, &bgimage->width, &bgimage->height, &size);
|
||||||
|
if (has_bg) {
|
||||||
|
bgimage->texture_id = 0;
|
||||||
|
RepeatStrategy r;
|
||||||
|
switch (OPT(background_image_layout)) {
|
||||||
|
case TILING:
|
||||||
|
r = REPEAT_DEFAULT; break;
|
||||||
|
case SCALED:
|
||||||
|
r = REPEAT_CLAMP; break;
|
||||||
|
case MIRRORED:
|
||||||
|
r = REPEAT_MIRROR;
|
||||||
|
}
|
||||||
|
send_image_to_gpu(&bgimage->texture_id, bgimage->bitmap, bgimage->width,
|
||||||
|
bgimage->height, false, true, false, r);
|
||||||
|
ans->bgimage = bgimage;
|
||||||
|
global_state.bgimage = bgimage;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Reusing already loaded bgimage
|
||||||
|
ans->bgimage = global_state.bgimage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ans->font_sz_in_pts = global_state.font_sz_in_pts;
|
ans->font_sz_in_pts = global_state.font_sz_in_pts;
|
||||||
END_WITH_OS_WINDOW_REFS
|
END_WITH_OS_WINDOW_REFS
|
||||||
return ans;
|
return ans;
|
||||||
@ -416,6 +449,17 @@ window_title_in(PyObject *title_in) {
|
|||||||
return ALL;
|
return ALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BackgroundImageLayout bglayout(PyObject *layout_name) {
|
||||||
|
const char *name = PyUnicode_AsUTF8(layout_name);
|
||||||
|
switch(name[0]) {
|
||||||
|
case 't': return TILING;
|
||||||
|
case 'm': return MIRRORED;
|
||||||
|
case 's': return SCALED;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
return TILING;
|
||||||
|
}
|
||||||
|
|
||||||
static MouseShape
|
static MouseShape
|
||||||
pointer_shape(PyObject *shape_name) {
|
pointer_shape(PyObject *shape_name) {
|
||||||
const char *name = PyUnicode_AsUTF8(shape_name);
|
const char *name = PyUnicode_AsUTF8(shape_name);
|
||||||
@ -484,6 +528,10 @@ PYWRAP1(set_options) {
|
|||||||
S(cursor_blink_interval, parse_s_double_to_monotonic_t);
|
S(cursor_blink_interval, parse_s_double_to_monotonic_t);
|
||||||
S(cursor_stop_blinking_after, parse_s_double_to_monotonic_t);
|
S(cursor_stop_blinking_after, parse_s_double_to_monotonic_t);
|
||||||
S(background_opacity, PyFloat_AsFloat);
|
S(background_opacity, PyFloat_AsFloat);
|
||||||
|
S(background_image_opacity, PyFloat_AsFloat);
|
||||||
|
S(background_image_scale, PyFloat_AsFloat);
|
||||||
|
S(background_image_layout, bglayout);
|
||||||
|
S(background_image, (char*)PyUnicode_AsUTF8);
|
||||||
S(dim_opacity, PyFloat_AsFloat);
|
S(dim_opacity, PyFloat_AsFloat);
|
||||||
S(dynamic_background_opacity, PyObject_IsTrue);
|
S(dynamic_background_opacity, PyObject_IsTrue);
|
||||||
S(inactive_text_alpha, PyFloat_AsFloat);
|
S(inactive_text_alpha, PyFloat_AsFloat);
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
typedef enum { LEFT_EDGE, TOP_EDGE, RIGHT_EDGE, BOTTOM_EDGE } Edge;
|
typedef enum { LEFT_EDGE, TOP_EDGE, RIGHT_EDGE, BOTTOM_EDGE } Edge;
|
||||||
typedef enum { RESIZE_DRAW_STATIC, RESIZE_DRAW_SCALED, RESIZE_DRAW_BLANK, RESIZE_DRAW_SIZE } ResizeDrawStrategy;
|
typedef enum { RESIZE_DRAW_STATIC, RESIZE_DRAW_SCALED, RESIZE_DRAW_BLANK, RESIZE_DRAW_SIZE } ResizeDrawStrategy;
|
||||||
|
typedef enum { REPEAT_MIRROR, REPEAT_CLAMP, REPEAT_DEFAULT } RepeatStrategy;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
monotonic_t visual_bell_duration, cursor_blink_interval, cursor_stop_blinking_after, mouse_hide_wait, click_interval;
|
monotonic_t visual_bell_duration, cursor_blink_interval, cursor_stop_blinking_after, mouse_hide_wait, click_interval;
|
||||||
@ -37,6 +38,12 @@ typedef struct {
|
|||||||
int adjust_line_height_px, adjust_column_width_px;
|
int adjust_line_height_px, adjust_column_width_px;
|
||||||
float adjust_line_height_frac, adjust_column_width_frac;
|
float adjust_line_height_frac, adjust_column_width_frac;
|
||||||
float background_opacity, dim_opacity;
|
float background_opacity, dim_opacity;
|
||||||
|
|
||||||
|
char* background_image;
|
||||||
|
BackgroundImageLayout background_image_layout;
|
||||||
|
float background_image_opacity;
|
||||||
|
float background_image_scale;
|
||||||
|
|
||||||
bool dynamic_background_opacity;
|
bool dynamic_background_opacity;
|
||||||
float inactive_text_alpha;
|
float inactive_text_alpha;
|
||||||
float window_padding_width;
|
float window_padding_width;
|
||||||
@ -136,6 +143,7 @@ typedef struct {
|
|||||||
int viewport_width, viewport_height, window_width, window_height;
|
int viewport_width, viewport_height, window_width, window_height;
|
||||||
double viewport_x_ratio, viewport_y_ratio;
|
double viewport_x_ratio, viewport_y_ratio;
|
||||||
Tab *tabs;
|
Tab *tabs;
|
||||||
|
BackgroundImage *bgimage;
|
||||||
unsigned int active_tab, num_tabs, capacity, last_active_tab, last_num_tabs, last_active_window_id;
|
unsigned int active_tab, num_tabs, capacity, last_active_tab, last_num_tabs, last_active_window_id;
|
||||||
bool focused_at_last_render, needs_render;
|
bool focused_at_last_render, needs_render;
|
||||||
ScreenRenderData tab_bar_render_data;
|
ScreenRenderData tab_bar_render_data;
|
||||||
@ -158,8 +166,10 @@ typedef struct {
|
|||||||
id_type temp_font_group_id;
|
id_type temp_font_group_id;
|
||||||
enum RENDER_STATE render_state;
|
enum RENDER_STATE render_state;
|
||||||
monotonic_t last_render_frame_received_at;
|
monotonic_t last_render_frame_received_at;
|
||||||
|
uint64_t render_calls;
|
||||||
id_type last_focused_counter;
|
id_type last_focused_counter;
|
||||||
ssize_t gvao_idx;
|
ssize_t gvao_idx, bvao_idx;
|
||||||
|
unsigned int vbo_idx;
|
||||||
} OSWindow;
|
} OSWindow;
|
||||||
|
|
||||||
|
|
||||||
@ -168,6 +178,7 @@ typedef struct {
|
|||||||
|
|
||||||
id_type os_window_id_counter, tab_id_counter, window_id_counter;
|
id_type os_window_id_counter, tab_id_counter, window_id_counter;
|
||||||
PyObject *boss;
|
PyObject *boss;
|
||||||
|
BackgroundImage *bgimage;
|
||||||
OSWindow *os_windows;
|
OSWindow *os_windows;
|
||||||
size_t num_os_windows, capacity;
|
size_t num_os_windows, capacity;
|
||||||
OSWindow *callback_os_window;
|
OSWindow *callback_os_window;
|
||||||
@ -223,11 +234,12 @@ void draw_centered_alpha_mask(OSWindow *w, size_t screen_width, size_t screen_he
|
|||||||
void update_surface_size(int, int, uint32_t);
|
void update_surface_size(int, int, uint32_t);
|
||||||
void free_texture(uint32_t*);
|
void free_texture(uint32_t*);
|
||||||
void free_framebuffer(uint32_t*);
|
void free_framebuffer(uint32_t*);
|
||||||
void send_image_to_gpu(uint32_t*, const void*, int32_t, int32_t, bool, bool);
|
void send_image_to_gpu(uint32_t*, const void*, int32_t, int32_t, bool, bool, bool, RepeatStrategy);
|
||||||
void send_sprite_to_gpu(FONTS_DATA_HANDLE fg, unsigned int, unsigned int, unsigned int, pixel*);
|
void send_sprite_to_gpu(FONTS_DATA_HANDLE fg, unsigned int, unsigned int, unsigned int, pixel*);
|
||||||
void blank_canvas(float, color_type);
|
void blank_canvas(float, color_type);
|
||||||
void blank_os_window(OSWindow *);
|
void blank_os_window(OSWindow *);
|
||||||
void set_titlebar_color(OSWindow *w, color_type color);
|
void set_titlebar_color(OSWindow *w, color_type color);
|
||||||
|
void get_window_content_scale(GLFWwindow *w, float *xscale, float *yscale, double *xdpi, double *ydpi);
|
||||||
FONTS_DATA_HANDLE load_fonts_data(double, double, double);
|
FONTS_DATA_HANDLE load_fonts_data(double, double, double);
|
||||||
void send_prerendered_sprites_for_window(OSWindow *w);
|
void send_prerendered_sprites_for_window(OSWindow *w);
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
|
|||||||
@ -15,14 +15,14 @@ from .constants import (
|
|||||||
ScreenGeometry, WindowGeometry, appname, get_boss, wakeup
|
ScreenGeometry, WindowGeometry, appname, get_boss, wakeup
|
||||||
)
|
)
|
||||||
from .fast_data_types import (
|
from .fast_data_types import (
|
||||||
BLIT_PROGRAM, CELL_BG_PROGRAM, CELL_FG_PROGRAM, CELL_PROGRAM,
|
BLIT_PROGRAM, BGIMAGE_PROGRAM, BGIMAGE_TILED_PROGRAM, CELL_BG_PROGRAM,
|
||||||
CELL_SPECIAL_PROGRAM, CSI, DCS, DECORATION, DIM,
|
CELL_FG_PROGRAM, CELL_PROGRAM, CELL_SPECIAL_PROGRAM, CSI, DCS, DECORATION,
|
||||||
GRAPHICS_ALPHA_MASK_PROGRAM, GRAPHICS_PREMULT_PROGRAM, GRAPHICS_PROGRAM,
|
DIM, GRAPHICS_ALPHA_MASK_PROGRAM, GRAPHICS_PREMULT_PROGRAM,
|
||||||
MARK, MARK_MASK, OSC, REVERSE, SCROLL_FULL, SCROLL_LINE, SCROLL_PAGE,
|
GRAPHICS_PROGRAM, MARK, MARK_MASK, OSC, REVERSE, SCROLL_FULL, SCROLL_LINE,
|
||||||
STRIKETHROUGH, Screen, add_window, cell_size_for_window, compile_program,
|
SCROLL_PAGE, STRIKETHROUGH, Screen, add_window, cell_size_for_window,
|
||||||
get_clipboard_string, init_cell_program, set_clipboard_string,
|
compile_program, get_clipboard_string, init_cell_program,
|
||||||
set_titlebar_color, set_window_render_data, update_window_title,
|
set_clipboard_string, set_titlebar_color, set_window_render_data,
|
||||||
update_window_visibility, viewport_for_window
|
update_window_title, update_window_visibility, viewport_for_window
|
||||||
)
|
)
|
||||||
from .keys import defines, extended_key_event, keyboard_mode_name
|
from .keys import defines, extended_key_event, keyboard_mode_name
|
||||||
from .rgb import to_color
|
from .rgb import to_color
|
||||||
@ -83,6 +83,7 @@ def load_shader_programs(semi_transparent=False):
|
|||||||
vv = vv.replace('#define USE_SELECTION_FG', '#define DONT_USE_SELECTION_FG')
|
vv = vv.replace('#define USE_SELECTION_FG', '#define DONT_USE_SELECTION_FG')
|
||||||
ff = ff.replace('#define USE_SELECTION_FG', '#define DONT_USE_SELECTION_FG')
|
ff = ff.replace('#define USE_SELECTION_FG', '#define DONT_USE_SELECTION_FG')
|
||||||
compile_program(p, vv, ff)
|
compile_program(p, vv, ff)
|
||||||
|
|
||||||
v, f = load_shaders('graphics')
|
v, f = load_shaders('graphics')
|
||||||
for which, p in {
|
for which, p in {
|
||||||
'SIMPLE': GRAPHICS_PROGRAM,
|
'SIMPLE': GRAPHICS_PROGRAM,
|
||||||
@ -91,6 +92,15 @@ def load_shader_programs(semi_transparent=False):
|
|||||||
}.items():
|
}.items():
|
||||||
ff = f.replace('ALPHA_TYPE', which)
|
ff = f.replace('ALPHA_TYPE', which)
|
||||||
compile_program(p, v, ff)
|
compile_program(p, v, ff)
|
||||||
|
|
||||||
|
v, f = load_shaders('bgimage')
|
||||||
|
for which, p in {
|
||||||
|
'SIMPLE': BGIMAGE_PROGRAM,
|
||||||
|
'TILED': BGIMAGE_TILED_PROGRAM,
|
||||||
|
}.items():
|
||||||
|
ff = f.replace('LAYOUT_TYPE', which)
|
||||||
|
compile_program(p, v, ff)
|
||||||
|
|
||||||
init_cell_program()
|
init_cell_program()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user