Work on rendering to FBO
This commit is contained in:
parent
f85c050235
commit
ffff343e3d
11
kitty/blit_fragment.glsl
Normal file
11
kitty/blit_fragment.glsl
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#version GLSL_VERSION
|
||||||
|
|
||||||
|
uniform sampler2D image;
|
||||||
|
|
||||||
|
in vec2 texcoord;
|
||||||
|
out vec4 color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
color = texture(image, texcoord);
|
||||||
|
color = vec4(color.rgb / color.a, color.a);
|
||||||
|
}
|
||||||
30
kitty/blit_vertex.glsl
Normal file
30
kitty/blit_vertex.glsl
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#version GLSL_VERSION
|
||||||
|
#define vleft -1.0
|
||||||
|
#define vtop 1.0
|
||||||
|
#define vright 1.0
|
||||||
|
#define vbottom -1.0
|
||||||
|
|
||||||
|
#define tleft 0
|
||||||
|
#define ttop 1
|
||||||
|
#define tright 1
|
||||||
|
#define tbottom 0
|
||||||
|
|
||||||
|
const vec2 viewport_xpos = vec2(vleft, vright);
|
||||||
|
const vec2 viewport_ypos = vec2(vtop, vbottom);
|
||||||
|
const vec2 texture_xpos = vec2(tleft, tright);
|
||||||
|
const vec2 texture_ypos = vec2(ttop, tbottom);
|
||||||
|
|
||||||
|
const uvec2 pos_map[] = uvec2[4](
|
||||||
|
uvec2(1, 0), // right, top
|
||||||
|
uvec2(1, 1), // right, bottom
|
||||||
|
uvec2(0, 1), // left, bottom
|
||||||
|
uvec2(0, 0) // left, top
|
||||||
|
);
|
||||||
|
|
||||||
|
out vec2 texcoord;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
uvec2 pos = pos_map[gl_VertexID];
|
||||||
|
gl_Position = vec4(viewport_xpos[pos[0]], viewport_ypos[pos[1]], 0, 1);
|
||||||
|
texcoord = vec2(texture_xpos[pos[0]], texture_ypos[pos[1]]);
|
||||||
|
}
|
||||||
@ -601,7 +601,7 @@ render(double now) {
|
|||||||
if (!w->num_tabs || !should_os_window_be_rendered(w)) continue;
|
if (!w->num_tabs || !should_os_window_be_rendered(w)) continue;
|
||||||
make_os_window_context_current(w);
|
make_os_window_context_current(w);
|
||||||
if (w->viewport_size_dirty) {
|
if (w->viewport_size_dirty) {
|
||||||
update_surface_size(w->viewport_width, w->viewport_height);
|
update_surface_size(w->viewport_width, w->viewport_height, w->offscreen_texture_id);
|
||||||
w->viewport_size_dirty = false;
|
w->viewport_size_dirty = false;
|
||||||
}
|
}
|
||||||
unsigned int active_window_id = 0;
|
unsigned int active_window_id = 0;
|
||||||
|
|||||||
@ -63,8 +63,12 @@ gl_init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
update_surface_size(int w, int h) {
|
update_surface_size(int w, int h, GLuint offscreen_texture_id) {
|
||||||
glViewport(0, 0, w, h);
|
glViewport(0, 0, w, h);
|
||||||
|
if (offscreen_texture_id) {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, offscreen_texture_id);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -251,7 +255,7 @@ typedef struct {
|
|||||||
ssize_t buffers[10];
|
ssize_t buffers[10];
|
||||||
} VAO;
|
} VAO;
|
||||||
|
|
||||||
static VAO vaos[2*MAX_CHILDREN + 10] = {{0}};
|
static VAO vaos[4*MAX_CHILDREN + 10] = {{0}};
|
||||||
|
|
||||||
static ssize_t
|
static ssize_t
|
||||||
create_vao() {
|
create_vao() {
|
||||||
|
|||||||
@ -9,8 +9,8 @@
|
|||||||
#include "fonts.h"
|
#include "fonts.h"
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
|
|
||||||
enum { CELL_PROGRAM, CELL_BG_PROGRAM, CELL_SPECIAL_PROGRAM, CELL_FG_PROGRAM, CURSOR_PROGRAM, BORDERS_PROGRAM, GRAPHICS_PROGRAM, NUM_PROGRAMS };
|
enum { CELL_PROGRAM, CELL_BG_PROGRAM, CELL_SPECIAL_PROGRAM, CELL_FG_PROGRAM, CURSOR_PROGRAM, BORDERS_PROGRAM, GRAPHICS_PROGRAM, BLIT_PROGRAM, NUM_PROGRAMS };
|
||||||
enum { SPRITE_MAP_UNIT, GRAPHICS_UNIT };
|
enum { SPRITE_MAP_UNIT, GRAPHICS_UNIT, BLIT_UNIT };
|
||||||
|
|
||||||
// Sprites {{{
|
// Sprites {{{
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -142,6 +142,8 @@ typedef struct {
|
|||||||
} CellProgramLayout;
|
} CellProgramLayout;
|
||||||
|
|
||||||
static CellProgramLayout cell_program_layouts[NUM_PROGRAMS];
|
static CellProgramLayout cell_program_layouts[NUM_PROGRAMS];
|
||||||
|
static GLuint offscreen_framebuffer = 0;
|
||||||
|
static ssize_t blit_vertex_array;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
init_cell_program() {
|
init_cell_program() {
|
||||||
@ -158,7 +160,8 @@ init_cell_program() {
|
|||||||
C(p, colors, 0); C(p, sprite_coords, 1); C(p, is_selected, 2);
|
C(p, colors, 0); C(p, sprite_coords, 1); C(p, is_selected, 2);
|
||||||
}
|
}
|
||||||
#undef C
|
#undef C
|
||||||
|
glGenFramebuffers(1, &offscreen_framebuffer);
|
||||||
|
blit_vertex_array = create_vao();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CELL_BUFFERS enum { cell_data_buffer, selection_buffer, uniform_buffer };
|
#define CELL_BUFFERS enum { cell_data_buffer, selection_buffer, uniform_buffer };
|
||||||
@ -278,7 +281,6 @@ static void
|
|||||||
draw_graphics(ssize_t vao_idx, ssize_t gvao_idx, ImageRenderData *data, GLuint start, GLuint count) {
|
draw_graphics(ssize_t vao_idx, ssize_t gvao_idx, ImageRenderData *data, GLuint start, GLuint count) {
|
||||||
bind_vertex_array(gvao_idx);
|
bind_vertex_array(gvao_idx);
|
||||||
bind_program(GRAPHICS_PROGRAM);
|
bind_program(GRAPHICS_PROGRAM);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
static bool graphics_constants_set = false;
|
static bool graphics_constants_set = false;
|
||||||
if (!graphics_constants_set) {
|
if (!graphics_constants_set) {
|
||||||
glUniform1i(glGetUniformLocation(program_id(GRAPHICS_PROGRAM), "image"), GRAPHICS_UNIT);
|
glUniform1i(glGetUniformLocation(program_id(GRAPHICS_PROGRAM), "image"), GRAPHICS_UNIT);
|
||||||
@ -312,34 +314,55 @@ draw_all_cells(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 *os_window) {
|
||||||
(void)vao_idx; (void)gvao_idx; (void)screen;
|
if (!os_window->offscreen_texture_id) {
|
||||||
/* bind_program(CELL_BACKGROUND_PROGRAM); */
|
glGenTextures(1, &os_window->offscreen_texture_id);
|
||||||
/* glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns); */
|
glBindTexture(GL_TEXTURE_2D, os_window->offscreen_texture_id);
|
||||||
/* glEnable(GL_BLEND); */
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, os_window->viewport_width, os_window->viewport_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||||
/* glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); */
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
/* */
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
/* if (screen->grman->num_of_negative_refs) draw_graphics(vao_idx, gvao_idx, screen->grman->render_data, 0, screen->grman->num_of_negative_refs); */
|
}
|
||||||
/* */
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, offscreen_framebuffer);
|
||||||
/* bind_program(CELL_SPECIAL_PROGRAM); */
|
glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, os_window->offscreen_texture_id, 0);
|
||||||
/* glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns); */
|
/* if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) fatal("offscreen framebuffer not complete"); */
|
||||||
/* */
|
|
||||||
/* bind_program(CELL_FOREGROUND_PROGRAM); */
|
bind_program(CELL_BG_PROGRAM);
|
||||||
/* glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns); */
|
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
|
||||||
/* */
|
glEnable(GL_BLEND);
|
||||||
/* if (screen->grman->num_of_positive_refs) draw_graphics(vao_idx, gvao_idx, screen->grman->render_data, screen->grman->num_of_negative_refs, screen->grman->num_of_positive_refs); */
|
if (screen->grman->num_of_negative_refs) draw_graphics(vao_idx, gvao_idx, screen->grman->render_data, 0, screen->grman->num_of_negative_refs);
|
||||||
/* glDisable(GL_BLEND); */
|
|
||||||
|
bind_program(CELL_SPECIAL_PROGRAM);
|
||||||
|
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
|
||||||
|
|
||||||
|
bind_program(CELL_FG_PROGRAM);
|
||||||
|
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
|
||||||
|
|
||||||
|
if (screen->grman->num_of_positive_refs) draw_graphics(vao_idx, gvao_idx, screen->grman->render_data, screen->grman->num_of_negative_refs, screen->grman->num_of_positive_refs);
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
|
// Now render the framebuffer to the screen reversing alpha pre-multiplication
|
||||||
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
bind_program(BLIT_PROGRAM); bind_vertex_array(blit_vertex_array);
|
||||||
|
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);
|
||||||
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||||
|
glDisable(GL_SCISSOR_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
draw_cells(ssize_t vao_idx, ssize_t gvao_idx, GLfloat xstart, GLfloat ystart, GLfloat dx, GLfloat dy, Screen *screen, OSWindow *os_window) {
|
draw_cells(ssize_t vao_idx, ssize_t gvao_idx, GLfloat xstart, GLfloat ystart, GLfloat dx, GLfloat dy, Screen *screen, OSWindow *os_window) {
|
||||||
cell_prepare_to_render(vao_idx, gvao_idx, screen, xstart, ystart, dx, dy);
|
cell_prepare_to_render(vao_idx, gvao_idx, screen, xstart, ystart, dx, dy);
|
||||||
GLfloat h = (GLfloat)screen->lines * dy;
|
GLfloat w = (GLfloat)screen->columns * dx, h = (GLfloat)screen->lines * dy;
|
||||||
#define SCALE(w, x) ((GLfloat)(os_window->viewport_##w) * (GLfloat)(x))
|
#define SCALE(w, x) ((GLfloat)(os_window->viewport_##w) * (GLfloat)(x))
|
||||||
glScissor(
|
glScissor(
|
||||||
(GLint)(SCALE(width, (xstart + 1.0f) / 2.0f)),
|
(GLint)(SCALE(width, (xstart + 1.0f) / 2.0f)),
|
||||||
(GLint)(SCALE(height, ((ystart - h) + 1.0f) / 2.0f)),
|
(GLint)(SCALE(height, ((ystart - h) + 1.0f) / 2.0f)),
|
||||||
(GLsizei)(ceilf(SCALE(width, (float)screen->columns * dx / 2.0f))),
|
(GLsizei)(ceilf(SCALE(width, w / 2.0f))),
|
||||||
(GLsizei)(ceilf(SCALE(height, h / 2.0f)))
|
(GLsizei)(ceilf(SCALE(height, h / 2.0f)))
|
||||||
);
|
);
|
||||||
#undef SCALE
|
#undef SCALE
|
||||||
@ -350,7 +373,7 @@ draw_cells(ssize_t vao_idx, ssize_t gvao_idx, GLfloat xstart, GLfloat ystart, GL
|
|||||||
cell_constants_set = true;
|
cell_constants_set = true;
|
||||||
}
|
}
|
||||||
bool needs_complex_rendering = screen->grman->num_of_negative_refs || (screen->grman->num_of_positive_refs && os_window->is_semi_transparent);
|
bool needs_complex_rendering = screen->grman->num_of_negative_refs || (screen->grman->num_of_positive_refs && os_window->is_semi_transparent);
|
||||||
if (needs_complex_rendering) draw_cells_interleaved(vao_idx, gvao_idx, screen);
|
if (needs_complex_rendering) draw_cells_interleaved(vao_idx, gvao_idx, screen, os_window);
|
||||||
else draw_all_cells(vao_idx, gvao_idx, screen);
|
else draw_all_cells(vao_idx, gvao_idx, screen);
|
||||||
}
|
}
|
||||||
// }}}
|
// }}}
|
||||||
@ -527,7 +550,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(CURSOR_PROGRAM); C(BORDERS_PROGRAM); C(GRAPHICS_PROGRAM);
|
C(CELL_PROGRAM); C(CELL_BG_PROGRAM); C(CELL_SPECIAL_PROGRAM); C(CELL_FG_PROGRAM); C(CURSOR_PROGRAM); C(BORDERS_PROGRAM); C(GRAPHICS_PROGRAM); C(BLIT_PROGRAM);
|
||||||
C(GLSL_VERSION);
|
C(GLSL_VERSION);
|
||||||
C(GL_VERSION);
|
C(GL_VERSION);
|
||||||
C(GL_VENDOR);
|
C(GL_VENDOR);
|
||||||
|
|||||||
@ -174,6 +174,7 @@ destroy_os_window_item(OSWindow *w) {
|
|||||||
remove_tab_inner(w, tab->id);
|
remove_tab_inner(w, tab->id);
|
||||||
}
|
}
|
||||||
Py_CLEAR(w->window_title); Py_CLEAR(w->tab_bar_render_data.screen);
|
Py_CLEAR(w->window_title); Py_CLEAR(w->tab_bar_render_data.screen);
|
||||||
|
if (w->offscreen_texture_id) free_texture(&w->offscreen_texture_id);
|
||||||
remove_vao(w->tab_bar_render_data.vao_idx);
|
remove_vao(w->tab_bar_render_data.vao_idx);
|
||||||
free(w->tabs); w->tabs = NULL;
|
free(w->tabs); w->tabs = NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -103,6 +103,7 @@ typedef struct {
|
|||||||
double last_resize_at;
|
double last_resize_at;
|
||||||
bool has_pending_resizes;
|
bool has_pending_resizes;
|
||||||
bool is_semi_transparent;
|
bool is_semi_transparent;
|
||||||
|
uint32_t offscreen_texture_id;
|
||||||
} OSWindow;
|
} OSWindow;
|
||||||
|
|
||||||
|
|
||||||
@ -159,7 +160,7 @@ ssize_t create_graphics_vao();
|
|||||||
ssize_t create_border_vao();
|
ssize_t create_border_vao();
|
||||||
void draw_cells(ssize_t, ssize_t, float, float, float, float, Screen *, OSWindow *);
|
void draw_cells(ssize_t, ssize_t, float, float, float, float, Screen *, OSWindow *);
|
||||||
void draw_cursor(CursorRenderInfo *, bool);
|
void draw_cursor(CursorRenderInfo *, bool);
|
||||||
void update_surface_size(int, int);
|
void update_surface_size(int, int, uint32_t);
|
||||||
void free_texture(uint32_t*);
|
void free_texture(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);
|
||||||
void send_sprite_to_gpu(unsigned int, unsigned int, unsigned int, uint8_t*);
|
void send_sprite_to_gpu(unsigned int, unsigned int, unsigned int, uint8_t*);
|
||||||
|
|||||||
@ -12,7 +12,7 @@ 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 (
|
||||||
BRACKETED_PASTE_END, BRACKETED_PASTE_START, CELL_BG_PROGRAM,
|
BLIT_PROGRAM, BRACKETED_PASTE_END, BRACKETED_PASTE_START, CELL_BG_PROGRAM,
|
||||||
CELL_FG_PROGRAM, CELL_PROGRAM, CELL_SPECIAL_PROGRAM, CURSOR_PROGRAM,
|
CELL_FG_PROGRAM, CELL_PROGRAM, CELL_SPECIAL_PROGRAM, CURSOR_PROGRAM,
|
||||||
GRAPHICS_PROGRAM, SCROLL_FULL, SCROLL_LINE, SCROLL_PAGE, Screen,
|
GRAPHICS_PROGRAM, SCROLL_FULL, SCROLL_LINE, SCROLL_PAGE, Screen,
|
||||||
add_window, compile_program, glfw_post_empty_event, init_cell_program,
|
add_window, compile_program, glfw_post_empty_event, init_cell_program,
|
||||||
@ -54,6 +54,7 @@ def calculate_gl_geometry(window_geometry, viewport_width, viewport_height, cell
|
|||||||
def load_shader_programs(semi_transparent=0):
|
def load_shader_programs(semi_transparent=0):
|
||||||
v, f = load_shaders('cell')
|
v, f = load_shaders('cell')
|
||||||
compile_program(GRAPHICS_PROGRAM, *load_shaders('graphics'))
|
compile_program(GRAPHICS_PROGRAM, *load_shaders('graphics'))
|
||||||
|
compile_program(BLIT_PROGRAM, *load_shaders('blit'))
|
||||||
for which, p in {
|
for which, p in {
|
||||||
'SIMPLE': CELL_PROGRAM,
|
'SIMPLE': CELL_PROGRAM,
|
||||||
'BACKGROUND': CELL_BG_PROGRAM,
|
'BACKGROUND': CELL_BG_PROGRAM,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user