renderer: add scissor test API

This commit is contained in:
Andrei Alexeyev 2021-08-17 05:10:12 +03:00
parent 54e212d6c5
commit a82b63045c
No known key found for this signature in database
GPG key ID: 72D26128040B9690
9 changed files with 95 additions and 1 deletions

View file

@ -720,6 +720,19 @@ void r_vertex_array_layout(VertexArray *varr, uint nattribs, VertexAttribFormat
B.vertex_array_layout(varr, nattribs, attribs);
}
void r_scissor(int x, int y, int w, int h) {
_r_state_touch_scissor();
B.scissor((IntRect) { x, y, w, h });
}
void r_scissor_rect(IntRect scissor) {
B.scissor(scissor);
}
void r_scissor_current(IntRect *scissor) {
B.scissor_current(scissor);
}
void r_vsync(VsyncMode mode) {
B.vsync(mode);
}

View file

@ -793,6 +793,11 @@ void r_vertex_array_attach_index_buffer(VertexArray *varr, IndexBuffer *ibuf) at
IndexBuffer* r_vertex_array_get_index_attachment(VertexArray *varr) attr_nonnull(1);
void r_vertex_array_layout(VertexArray *varr, uint nattribs, VertexAttribFormat attribs[nattribs]) attr_nonnull(1, 3);
// NOTE: setting all parameters to 0 disables the scissor test
void r_scissor(int x, int y, int w, int h);
void r_scissor_rect(IntRect scissor);
void r_scissor_current(IntRect *scissor) attr_nonnull(1);
void r_model_add_static(Model *out_mdl, Primitive prim, size_t num_vertices, GenericModelVertex vertices[num_vertices], size_t num_indices, uint indices[num_indices]);
const Model *r_model_get_quad(void) attr_returns_nonnull;

View file

@ -121,6 +121,9 @@ typedef struct RendererFuncs {
VertexBuffer* (*vertex_array_get_vertex_attachment)(VertexArray *varr, uint attachment);
IndexBuffer* (*vertex_array_get_index_attachment)(VertexArray *varr);
void (*scissor)(IntRect scissor);
void (*scissor_current)(IntRect *scissor);
void (*vsync)(VsyncMode mode);
VsyncMode (*vsync_current)(void);

View file

@ -85,6 +85,10 @@ void r_state_pop(void) {
B.framebuffer(S.framebuffer);
}
RESTORE(RSTATE_SCISSOR) {
B.scissor(S.scissor);
}
if(_r_state.head == _r_state.stack) {
_r_state.head = NULL;
} else {
@ -136,3 +140,9 @@ void _r_state_touch_framebuffer(void) {
S.framebuffer = B.framebuffer_current();
});
}
void _r_state_touch_scissor(void) {
TAINT(RSTATE_SCISSOR, {
B.scissor_current(&S.scissor);
});
}

View file

@ -20,6 +20,7 @@
RSTATE(SHADER) \
RSTATE(SHADER_UNIFORMS) \
RSTATE(RENDERTARGET) \
RSTATE(SCISSOR) \
typedef enum RendererStateID {
#define RSTATE(id) RSTATE_ID_##id,
@ -47,6 +48,7 @@ typedef struct RendererStateRollback {
ShaderProgram *shader;
// TODO uniforms
Framebuffer *framebuffer;
IntRect scissor;
} RendererStateRollback;
void _r_state_touch_capabilities(void);
@ -57,6 +59,7 @@ void _r_state_touch_depth_func(void);
void _r_state_touch_shader(void);
void _r_state_touch_uniform(Uniform *uniform);
void _r_state_touch_framebuffer(void);
void _r_state_touch_scissor(void);
void _r_state_init(void);
void _r_state_shutdown(void);

View file

@ -181,6 +181,7 @@ void gl33_framebuffer_clear(Framebuffer *framebuffer, ClearBufferFlags flags, co
Framebuffer *fb_saved = r_framebuffer_current();
r_framebuffer(framebuffer);
gl33_sync_framebuffer();
gl33_sync_scissor();
glClear(glflags);
r_framebuffer(fb_saved);
}

View file

@ -106,6 +106,12 @@ static struct {
FloatRect default_framebuffer;
} viewport;
struct {
IntRect pending;
IntRect active;
bool active_enabled;
} scissor;
Color color;
Color clear_color;
float clear_depth;
@ -379,7 +385,7 @@ static void gl33_apply_capability(RendererCapability cap, bool value) {
}
}
static void transform_viewport_origin(Framebuffer *fb, FloatRect *vp) {
static int get_framebuffer_height(Framebuffer *fb) {
int fb_height = 0;
if(fb == NULL) {
@ -396,6 +402,11 @@ static void transform_viewport_origin(Framebuffer *fb, FloatRect *vp) {
}
assert(fb_height > 0);
return fb_height;
}
static void transform_viewport_origin(Framebuffer *fb, FloatRect *vp) {
int fb_height = get_framebuffer_height(fb);
vp->y = fb_height - vp->y - vp->h;
}
@ -416,6 +427,37 @@ static void gl33_sync_viewport(void) {
}
}
void gl33_sync_scissor(void) {
bool pending_enabled =
R.scissor.pending.x &&
R.scissor.pending.y &&
R.scissor.pending.w &&
R.scissor.pending.h;
if(!pending_enabled) {
if(R.scissor.active_enabled) {
glDisable(GL_SCISSOR_TEST);
R.scissor.active_enabled = false;
}
return;
}
if(!R.scissor.active_enabled) {
glEnable(GL_SCISSOR_TEST);
R.scissor.active_enabled = true;
}
IntRect scissor = R.scissor.pending;
int fb_height = get_framebuffer_height(R.framebuffer.pending);
scissor.y = fb_height - scissor.y - scissor.h;
if(memcmp(&R.scissor.active, &scissor, sizeof(R.scissor.active))) {
glScissor(scissor.x, scissor.y, scissor.w, scissor.h);
R.scissor.active = scissor;
}
}
static IntExtent gl33_get_default_framebuffer_size(void) {
IntExtent s;
// TODO: cache this at window creation time and refresh on resize events?
@ -500,6 +542,7 @@ static void gl33_sync_state(void) {
gl33_sync_framebuffer();
gl33_sync_shader();
gl33_sync_viewport();
gl33_sync_scissor();
gl33_sync_magic_uniforms();
gl33_sync_uniforms(R.progs.active);
gl33_sync_texunits(true);
@ -1380,6 +1423,14 @@ static bool gl33_screenshot(Pixmap *out) {
return true;
}
static void gl33_scissor(IntRect scissor) {
R.scissor.pending = scissor;
}
static void gl33_scissor_current(IntRect *scissor) {
*scissor = R.scissor.pending;
}
RendererBackend _r_backend_gl33 = {
.name = "gl33",
.funcs = {
@ -1467,6 +1518,8 @@ RendererBackend _r_backend_gl33 = {
.vertex_array_get_vertex_attachment = gl33_vertex_array_get_vertex_attachment,
.vertex_array_attach_index_buffer = gl33_vertex_array_attach_index_buffer,
.vertex_array_get_index_attachment = gl33_vertex_array_get_index_attachment,
.scissor = gl33_scissor,
.scissor_current = gl33_scissor_current,
.vsync = gl33_vsync,
.vsync_current = gl33_vsync_current,
.swap = gl33_swap,

View file

@ -75,6 +75,7 @@ void gl33_sync_blend_mode(void);
void gl33_sync_cull_face_mode(void);
void gl33_sync_depth_test_func(void);
void gl33_sync_capabilities(void);
void gl33_sync_scissor(void);
void gl33_buffer_deleted(CommonBuffer *cbuf);
void gl33_vertex_buffer_deleted(VertexBuffer *vbuf);

View file

@ -179,6 +179,9 @@ static VertexBuffer* null_vertex_array_get_vertex_attachment(VertexArray *varr,
static IndexBuffer* null_vertex_array_get_index_attachment(VertexArray *varr) { return (void*)&placeholder; }
static void null_vertex_array_layout(VertexArray *varr, uint nattribs, VertexAttribFormat attribs[nattribs]) { }
static void null_scissor(IntRect scissor) { }
static void null_scissor_current(IntRect *scissor) { *scissor = (IntRect) { 0 }; }
static void null_vsync(VsyncMode mode) { }
static VsyncMode null_vsync_current(void) { return VSYNC_NONE; }
@ -273,6 +276,8 @@ RendererBackend _r_backend_null = {
.vertex_array_get_vertex_attachment = null_vertex_array_get_vertex_attachment,
.vertex_array_attach_index_buffer = null_vertex_array_attach_index_buffer,
.vertex_array_get_index_attachment = null_vertex_array_get_index_attachment,
.scissor = null_scissor,
.scissor_current = null_scissor_current,
.vsync = null_vsync,
.vsync_current = null_vsync_current,
.swap = null_swap,