Remove rendering via framebuffer for transparent windows with images
There is no need for it with the current rendering pipeline. Images are blended with premult blending.
This commit is contained in:
parent
2a96b5cb25
commit
098a38a3a9
11 changed files with 11 additions and 79 deletions
|
|
@ -1,9 +0,0 @@
|
|||
uniform sampler2D image;
|
||||
|
||||
in vec2 texcoord;
|
||||
out vec4 color;
|
||||
|
||||
|
||||
void main() {
|
||||
color = texture(image, texcoord);
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
#define left -1.0f
|
||||
#define top 1.0f
|
||||
#define right 1.0f
|
||||
#define bottom -1.0f
|
||||
|
||||
const vec2 pos_map[] = vec2[4](
|
||||
vec2(right, top),
|
||||
vec2(right, bottom),
|
||||
vec2(left, bottom),
|
||||
vec2(left, top)
|
||||
);
|
||||
|
||||
out vec2 texcoord;
|
||||
|
||||
void main() {
|
||||
vec2 vertex = pos_map[gl_VertexID];
|
||||
gl_Position = vec4(vertex, 0, 1);
|
||||
texcoord = (vertex + 1.0) / 2.0;
|
||||
}
|
||||
|
|
@ -64,7 +64,8 @@ vec4 vec4_premul(vec4 rgba) {
|
|||
* multiple passes drawing the background and foreground separately and blending.
|
||||
*
|
||||
* 2a) Opaque bg with images under text
|
||||
* There are multiple passes, each pass is blended onto the previous using the opaque blend func (alpha, 1- alpha):
|
||||
* There are multiple passes, each pass is blended onto the previous using the opaque blend func (alpha, 1- alpha). TRANSPARENT is not
|
||||
* defined in the shaders.
|
||||
* 1) Draw background for all cells
|
||||
* 2) Draw the images that are supposed to be below both the background and text, if any. This happens in the graphics shader
|
||||
* 3) Draw the background of cells that don't have the default background if any images were drawn in 2 above
|
||||
|
|
@ -74,9 +75,8 @@ vec4 vec4_premul(vec4 rgba) {
|
|||
* 7) Draw the images that are supposed to be above text again in the graphics shader
|
||||
*
|
||||
* 2b) Transparent bg with images
|
||||
* First everything is rendered into a framebuffer, and then the framebuffer is blended onto
|
||||
* the screen. The framebuffer is needed because it allows access to the background color pixels
|
||||
* to blend with the image pixels. The steps are basically the same as for 2a.
|
||||
* Same as (2a) except blending is done with PREMULT_BLEND and TRANSPARENT is defined in the shaders. background_opacity
|
||||
* is applied to default colored background cells in step (1).
|
||||
*
|
||||
* In this shader exactly *one* of SIMPLE, SPECIAL, FOREGROUND or BACKGROUND will be defined, corresponding
|
||||
* to the appropriate rendering pass from above.
|
||||
|
|
|
|||
|
|
@ -825,7 +825,7 @@ render(monotonic_t now, bool input_read) {
|
|||
bool needs_render = w->is_damaged || w->live_resize.in_progress;
|
||||
if (w->viewport_size_dirty) {
|
||||
w->clear_count = 0;
|
||||
update_surface_size(w->viewport_width, w->viewport_height, w->offscreen_texture_id);
|
||||
update_surface_size(w->viewport_width, w->viewport_height, 0);
|
||||
w->viewport_size_dirty = false;
|
||||
needs_render = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -259,7 +259,6 @@ NO_CURSOR_SHAPE: int
|
|||
CURSOR_UNDERLINE: int
|
||||
DECAWM: int
|
||||
BGIMAGE_PROGRAM: int
|
||||
BLIT_PROGRAM: int
|
||||
CELL_BG_PROGRAM: int
|
||||
CELL_FG_PROGRAM: int
|
||||
CELL_PROGRAM: int
|
||||
|
|
|
|||
|
|
@ -326,7 +326,7 @@ framebuffer_size_callback(GLFWwindow *w, int width, int height) {
|
|||
window->live_resize.width = MAX(0, width); window->live_resize.height = MAX(0, height);
|
||||
window->live_resize.num_of_resize_events++;
|
||||
make_os_window_context_current(window);
|
||||
update_surface_size(width, height, window->offscreen_texture_id);
|
||||
update_surface_size(width, height, 0);
|
||||
request_tick_callback();
|
||||
} else log_error("Ignoring resize request for tiny size: %dx%d", width, height);
|
||||
global_state.callback_os_window = NULL;
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@
|
|||
#define BLEND_ONTO_OPAQUE_WITH_OPAQUE_OUTPUT glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); // blending onto opaque colors with final color having alpha 1
|
||||
#define BLEND_PREMULT glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // blending of pre-multiplied colors
|
||||
|
||||
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, TINT_PROGRAM, NUM_PROGRAMS };
|
||||
enum { SPRITE_MAP_UNIT, GRAPHICS_UNIT, BLIT_UNIT, BGIMAGE_UNIT };
|
||||
enum { CELL_PROGRAM, CELL_BG_PROGRAM, CELL_SPECIAL_PROGRAM, CELL_FG_PROGRAM, BORDERS_PROGRAM, GRAPHICS_PROGRAM, GRAPHICS_PREMULT_PROGRAM, GRAPHICS_ALPHA_MASK_PROGRAM, BGIMAGE_PROGRAM, TINT_PROGRAM, NUM_PROGRAMS };
|
||||
enum { SPRITE_MAP_UNIT, GRAPHICS_UNIT, BGIMAGE_UNIT };
|
||||
|
||||
// Sprites {{{
|
||||
typedef struct {
|
||||
|
|
@ -818,26 +818,12 @@ draw_cells_interleaved_premult(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen
|
|||
draw_tint(true, screen, crd);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
if (!os_window->offscreen_texture_id) {
|
||||
glGenFramebuffers(1, &os_window->offscreen_framebuffer);
|
||||
glGenTextures(1, &os_window->offscreen_texture_id);
|
||||
glBindTexture(GL_TEXTURE_2D, os_window->offscreen_texture_id);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA, os_window->viewport_width, os_window->viewport_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, os_window->offscreen_framebuffer);
|
||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, os_window->offscreen_texture_id, 0);
|
||||
/* if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) fatal("Offscreen framebuffer not complete"); */
|
||||
bind_program(CELL_BG_PROGRAM);
|
||||
if (!has_bgimage(os_window)) {
|
||||
// draw background for all cells
|
||||
glUniform1ui(cell_program_layouts[CELL_BG_PROGRAM].draw_bg_bitfield_location, 3);
|
||||
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
|
||||
} else blank_canvas(0, 0);
|
||||
}
|
||||
glEnable(GL_BLEND);
|
||||
BLEND_PREMULT;
|
||||
|
||||
|
|
@ -870,22 +856,7 @@ 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);
|
||||
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
if (!has_bgimage(os_window)) glDisable(GL_BLEND);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
// Now render the framebuffer to the screen
|
||||
bind_program(BLIT_PROGRAM);
|
||||
static bool blit_constants_set = false;
|
||||
if (!blit_constants_set) {
|
||||
glUniform1i(glGetUniformLocation(program_id(BLIT_PROGRAM), "image"), BLIT_UNIT);
|
||||
blit_constants_set = true;
|
||||
}
|
||||
glActiveTexture(GL_TEXTURE0 + BLIT_UNIT);
|
||||
glBindTexture(GL_TEXTURE_2D, os_window->offscreen_texture_id);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -964,10 +935,6 @@ draw_cells(ssize_t vao_idx, ssize_t gvao_idx, const ScreenRenderData *srd, OSWin
|
|||
// The scissor limits below are calculated to ensure that they do not
|
||||
// overlap with the pixels outside the draw area. We can't use the actual pixel window dimensions
|
||||
// because of the mapping of opengl's float based co-ord system to pixels.
|
||||
// for a test case (scissor is used to blit framebuffer in draw_cells_interleaved_premult) run:
|
||||
// kitty -o background=cyan -o background_opacity=0.7 -o cursor_blink_interval=0 -o window_margin_width=40 -o remember_initial_window_size=n -o initial_window_width=401 kitty +kitten icat --hold logo/kitty.png
|
||||
// Repeat incrementing window width by 1px each time over cursor_width number of pixels and see if any lines
|
||||
// appear at the borders of the content area
|
||||
unsigned scissor_base_width = os_window->live_resize.in_progress ? os_window->live_resize.width : (unsigned)os_window->viewport_width;
|
||||
unsigned scissor_base_height = os_window->live_resize.in_progress ? os_window->live_resize.height: (unsigned)os_window->viewport_height;
|
||||
#define SCALE(w, x) ((GLfloat)(scissor_base_##w) * (GLfloat)(x))
|
||||
|
|
@ -1201,7 +1168,7 @@ static PyMethodDef module_methods[] = {
|
|||
bool
|
||||
init_shaders(PyObject *module) {
|
||||
#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(BGIMAGE_PROGRAM); C(TINT_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(BGIMAGE_PROGRAM); C(TINT_PROGRAM);
|
||||
C(GLSL_VERSION);
|
||||
C(GL_VERSION);
|
||||
C(GL_VENDOR);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
from .constants import read_kitty_resource
|
||||
from .fast_data_types import (
|
||||
BGIMAGE_PROGRAM,
|
||||
BLIT_PROGRAM,
|
||||
CELL_BG_PROGRAM,
|
||||
CELL_FG_PROGRAM,
|
||||
CELL_PROGRAM,
|
||||
|
|
@ -149,7 +148,6 @@ def __call__(self, semi_transparent: bool = False, allow_recompile: bool = False
|
|||
opts = get_options()
|
||||
self.text_old_gamma = opts.text_composition_strategy == 'legacy'
|
||||
self.text_fg_override_threshold = max(0, min(opts.text_fg_override_threshold, 100)) * 0.01
|
||||
program_for('blit').compile(BLIT_PROGRAM, allow_recompile)
|
||||
cell = program_for('cell')
|
||||
if self.cell_program_replacer is null_replacer:
|
||||
self.cell_program_replacer = MultiReplacer(
|
||||
|
|
|
|||
|
|
@ -477,8 +477,6 @@ destroy_os_window_item(OSWindow *w) {
|
|||
remove_tab_inner(w, tab->id);
|
||||
}
|
||||
Py_CLEAR(w->window_title); Py_CLEAR(w->tab_bar_render_data.screen);
|
||||
if (w->offscreen_texture_id) free_texture(&w->offscreen_texture_id);
|
||||
if (w->offscreen_framebuffer) free_framebuffer(&w->offscreen_framebuffer);
|
||||
remove_vao(w->tab_bar_render_data.vao_idx);
|
||||
remove_vao(w->gvao_idx);
|
||||
free(w->tabs); w->tabs = NULL;
|
||||
|
|
|
|||
|
|
@ -189,7 +189,6 @@ typedef struct {
|
|||
typedef struct {
|
||||
void *handle;
|
||||
id_type id;
|
||||
uint32_t offscreen_framebuffer;
|
||||
struct {
|
||||
int x, y, w, h;
|
||||
bool is_set, was_maximized;
|
||||
|
|
@ -216,7 +215,6 @@ typedef struct {
|
|||
monotonic_t viewport_resized_at;
|
||||
LiveResizeInfo live_resize;
|
||||
bool has_pending_resizes, is_semi_transparent, shown_once, is_damaged;
|
||||
uint32_t offscreen_texture_id;
|
||||
unsigned int clear_count;
|
||||
color_type last_titlebar_color;
|
||||
float background_opacity;
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ def test_loading_extensions(self) -> None:
|
|||
|
||||
def test_loading_shaders(self) -> None:
|
||||
from kitty.shaders import Program
|
||||
for name in 'cell border bgimage tint blit graphics'.split():
|
||||
for name in 'cell border bgimage tint graphics'.split():
|
||||
Program(name)
|
||||
|
||||
def test_glfw_modules(self) -> None:
|
||||
|
|
|
|||
Loading…
Reference in a new issue