From e8baea58dd5c92b62c4eef1b5c1ca9648f44e7d7 Mon Sep 17 00:00:00 2001 From: quou Date: Mon, 30 Dec 2024 12:44:28 +1100 Subject: ui renderer clipping --- ui.cpp | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 78 insertions(+), 13 deletions(-) (limited to 'ui.cpp') diff --git a/ui.cpp b/ui.cpp index 2060a78..5814204 100644 --- a/ui.cpp +++ b/ui.cpp @@ -129,6 +129,9 @@ UI::Colour::Colour(unsigned rgb, uint8_t a): b((rgb) & 0xff), a(a) {} +UI::Rect::Rect(int x, int y, int w, int h): + x(x), y(y), w(w), h(h) {} + void UI::Vertex_Buffer::init(Device* dev) { buf.init( dev, @@ -138,6 +141,7 @@ void UI::Vertex_Buffer::init(Device* dev) { ); init_indices(dev); usage = 0; + start = 0; next = 0; } @@ -199,6 +203,7 @@ void UI::Vertex_Buffer::add_quad( ) { Vertex* verts; int index = usage * 4; + int* scissor = ui->pipeline->scissor; float r, g, b, a; if (usage >= vertex_buffer_count) { if (!next) { @@ -208,6 +213,35 @@ void UI::Vertex_Buffer::add_quad( next->add_quad(ui, x, y, w, h, u0, v0, u1, v1, col); return; } + if ( + clip.x < scissor[0] || + clip.y < scissor[1] || + clip.x + clip.w > scissor[0] + scissor[2] || + clip.y + clip.h > scissor[1] + scissor[3] || + (( + clip.x != scissor[0] || + clip.y != scissor[1] || + clip.w != scissor[2] || + clip.h != scissor[3] + ) && ( + x < clip.x || + y < clip.y || + x + w > clip.x + clip.w || + y + h > clip.y + clip.h + )) + ) { + ui->mesh.draw( + ui, + ui->device->get_ctx(), + *ui->pipeline, + *ui->render_pass + ); + scissor[0] = clip.x; + scissor[1] = clip.y; + scissor[2] = clip.w; + scissor[3] = clip.h; + ui->pipeline->hash(); + } r = col.r_f(); g = col.g_f(); b = col.b_f(); @@ -254,17 +288,44 @@ void UI::Vertex_Buffer::add_text( const char* txt, Colour col ) { - for (; *txt; txt++) - add_char(ui, x += 10, y, *txt, col); + for (; *txt; txt++, x += 10) + add_char(ui, x, y, *txt, col); } void UI::Vertex_Buffer::update_buffer(Context& ctx) { buf.update(ctx); +} + +void UI::Vertex_Buffer::reset(const Rect& c) { + start = 0; + usage = 0; + dirty = true; + clip = c; + if (next) + next->reset(c); +} + +void UI::Vertex_Buffer::set_clip(const Rect& r) { + clip = r; if (next) - next->update_buffer(ctx); + next->set_clip(r); } -void UI::Vertex_Buffer::draw(UI* ui, Context& ctx, Pipeline& pip, Render_Pass& rp) { +void UI::Vertex_Buffer::draw( + UI* ui, + Context& ctx, + Pipeline& pip, + Render_Pass& rp +) { + if (usage == start) { + if (next) + next->draw(ui, ctx, pip, rp); + return; + } + if (dirty) { + update_buffer(ctx); + dirty = false; + } Vertex_Buffer_Binding binding[] = {{ .id = buf.gpuonly, .offset = 0, @@ -277,12 +338,13 @@ void UI::Vertex_Buffer::draw(UI* ui, Context& ctx, Pipeline& pip, Render_Pass& r Draw d{}; d.verts = binding; d.inds = indb; - d.vertex_count = usage * 6; + d.vertex_count = (usage - start) * 6; d.instance_count = 1; + d.first_vertex = start * 6; ctx.submit(d, pip, rp); if (next) next->draw(ui, ctx, pip, rp); - usage = 0; + start = usage; } UI* UI::create(Device* dev, Arena* a, Shader_Id sh) { @@ -345,7 +407,6 @@ void UI::update(Arena* s) { } void UI::render(Arena* s, Texture_Id target) { - int i, c = 2000; Context& ctx = device->get_ctx(); Texture& t = device->get_texture(target); UI_CBuffer* config = (UI_CBuffer*)cbuffer.map(device); @@ -358,12 +419,10 @@ void UI::render(Arena* s, Texture_Id target) { cbuffer.unmap(device); cbuffer.update(ctx); - mesh.add_text(this, 10, 10, "Hello, world!", 0xff00ff); - Pipeline_Builder pb(s, device); pb.begin_rp(); pb.rp_target(device->get_backbuffer(), Clear_Mode::restore); - Render_Pass& pass = pb.build_rp(); + render_pass = &pb.build_rp(); pb.begin(); pb.shader(shader); @@ -375,8 +434,14 @@ void UI::render(Arena* s, Texture_Id target) { ); pb.cbuffer(shader_info.config_binding, cbuffer.gpuonly); pb.texture(shader_info.atlas_binding, atlas, sampler); - Pipeline& pip = pb.build(); + pipeline = &pb.build(); - mesh.update_buffer(ctx); - mesh.draw(this, ctx, pip, pass); + mesh.reset(Rect(0, 0, t.w, t.h)); + mesh.add_text(this, 10, 10, "Hello, world!", 0xffffff); + mesh.add_text(this, 10, 30, "Hello, world!", 0xffffff); + mesh.set_clip(Rect(0, 0, 35, 100)); + mesh.add_text(this, 10, 50, "Hello, world!", 0xffffff); + mesh.set_clip(Rect(0, 0, t.w, t.h)); + mesh.add_text(this, 10, 70, "Hello, world!", 0xffffff); + mesh.draw(this, ctx, *pipeline, *render_pass); } -- cgit v1.2.3-54-g00ecf