summaryrefslogtreecommitdiff
path: root/ui.cpp
diff options
context:
space:
mode:
authorquou <quou@disroot.org>2024-12-30 12:44:28 +1100
committerquou <quou@disroot.org>2024-12-30 14:11:22 +1100
commite8baea58dd5c92b62c4eef1b5c1ca9648f44e7d7 (patch)
treee0e9685b8ae53e7984258965b8ad486d1781c8a3 /ui.cpp
parent90eed5c3684a6dd751afc2bcb7ae0ac919c143a8 (diff)
ui renderer clipping
Diffstat (limited to 'ui.cpp')
-rw-r--r--ui.cpp91
1 files changed, 78 insertions, 13 deletions
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);
}