From 56e8e3de24e7fea36f165b653a8efc8c38145d4c Mon Sep 17 00:00:00 2001 From: rodri Date: Sat, 17 Aug 2024 12:17:46 +0000 Subject: unify drawing routines and add clipped fb drawing support. now changing the viewport offset will correctly show the portion of the framebuffer that's visible, including support for upscaled views. --- fb.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 17 deletions(-) (limited to 'fb.c') diff --git a/fb.c b/fb.c index 4b1f82e..2c1d494 100644 --- a/fb.c +++ b/fb.c @@ -93,18 +93,7 @@ scale3x_filter(ulong *dst, Framebuf *fb, Point sp) //} static void -framebufctl_draw(Framebufctl *ctl, Image *dst, Point off) -{ - Framebuf *fb; - - qlock(ctl); - fb = ctl->getfb(ctl); - loadimage(dst, rectaddpt(fb->r, addpt(dst->r.min, off)), (uchar*)fb->cb, Dx(fb->r)*Dy(fb->r)*4); - qunlock(ctl); -} - -static void -framebufctl_upscaledraw(Framebufctl *ctl, Image *dst, Point off, Point scale) +upscaledraw(Framebufctl *ctl, Image *dst, Point off, Point scale) { void (*filter)(ulong*, Framebuf*, Point); Framebuf *fb; @@ -143,18 +132,37 @@ framebufctl_upscaledraw(Framebufctl *ctl, Image *dst, Point off, Point scale) } static void -framebufctl_memdraw(Framebufctl *ctl, Memimage *dst, Point off) +framebufctl_draw(Framebufctl *ctl, Image *dst, Point off, Point scale) { Framebuf *fb; + Rectangle sr, dr; + ulong *cb; + int y; + + if(scale.x > 1 || scale.y > 1){ + upscaledraw(ctl, dst, off, scale); + return; + } qlock(ctl); fb = ctl->getfb(ctl); - loadmemimage(dst, rectaddpt(fb->r, addpt(dst->r.min, off)), (uchar*)fb->cb, Dx(fb->r)*Dy(fb->r)*4); + sr = rectaddpt(fb->r, off); + dr = rectsubpt(dst->r, dst->r.min); + if(rectinrect(sr, dr)) + loadimage(dst, rectaddpt(sr, dst->r.min), (uchar*)fb->cb, Dx(fb->r)*Dy(fb->r)*4); + else if(rectclip(&sr, dr)){ + cb = emalloc(Dx(sr)*Dy(sr)*4); + /* TODO there must be a cleaner way to do this */ + for(y = sr.min.y; y < sr.max.y; y++) + memmove(&cb[(y - sr.min.y)*Dx(sr)], &fb->cb[max(y - off.y,0)*Dx(fb->r) + max(-off.x,0)], Dx(sr)*4); + loadimage(dst, rectaddpt(sr, dst->r.min), (uchar*)cb, Dx(sr)*Dy(sr)*4); + free(cb); + } qunlock(ctl); } static void -framebufctl_upscalememdraw(Framebufctl *ctl, Memimage *dst, Point off, Point scale) +upscalememdraw(Framebufctl *ctl, Memimage *dst, Point off, Point scale) { void (*filter)(ulong*, Framebuf*, Point); Framebuf *fb; @@ -192,6 +200,36 @@ framebufctl_upscalememdraw(Framebufctl *ctl, Memimage *dst, Point off, Point sca free(blk); } +static void +framebufctl_memdraw(Framebufctl *ctl, Memimage *dst, Point off, Point scale) +{ + Framebuf *fb; + Rectangle sr, dr; + ulong *cb; + int y; + + if(scale.x > 1 || scale.y > 1){ + upscalememdraw(ctl, dst, off, scale); + return; + } + + qlock(ctl); + fb = ctl->getfb(ctl); + sr = rectaddpt(fb->r, off); + dr = rectsubpt(dst->r, dst->r.min); + if(rectinrect(sr, dr)) + loadmemimage(dst, rectaddpt(sr, dst->r.min), (uchar*)fb->cb, Dx(fb->r)*Dy(fb->r)*4); + else if(rectclip(&sr, dr)){ + cb = emalloc(Dx(sr)*Dy(sr)*4); + /* TODO there must be a cleaner way to do this */ + for(y = sr.min.y; y < sr.max.y; y++) + memmove(&cb[(y - sr.min.y)*Dx(sr)], &fb->cb[max(y - off.y,0)*Dx(fb->r) + max(-off.x,0)], Dx(sr)*4); + loadmemimage(dst, rectaddpt(sr, dst->r.min), (uchar*)cb, Dx(sr)*Dy(sr)*4); + free(cb); + } + qunlock(ctl); +} + static void framebufctl_drawnormals(Framebufctl *ctl, Image *dst) { @@ -280,9 +318,7 @@ mkfbctl(Rectangle r) fc->fb[0] = mkfb(r); fc->fb[1] = mkfb(r); fc->draw = framebufctl_draw; - fc->upscaledraw = framebufctl_upscaledraw; fc->memdraw = framebufctl_memdraw; - fc->upscalememdraw = framebufctl_upscalememdraw; fc->drawnormals = framebufctl_drawnormals; fc->swap = framebufctl_swap; fc->reset = framebufctl_reset; -- cgit v1.2.3