summaryrefslogtreecommitdiff
path: root/fb.c
diff options
context:
space:
mode:
authorrodri <rgl@antares-labs.eu>2024-08-17 12:17:46 +0000
committerrodri <rgl@antares-labs.eu>2024-08-17 12:17:46 +0000
commit56e8e3de24e7fea36f165b653a8efc8c38145d4c (patch)
treec1558a4ef810d82a11d31ab085dd849c7b5bba7f /fb.c
parentd0a7561dd20847504b2449e17fd791f6c2800c84 (diff)
downloadlibgraphics-56e8e3de24e7fea36f165b653a8efc8c38145d4c.tar.gz
libgraphics-56e8e3de24e7fea36f165b653a8efc8c38145d4c.tar.bz2
libgraphics-56e8e3de24e7fea36f165b653a8efc8c38145d4c.zip
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.
Diffstat (limited to 'fb.c')
-rw-r--r--fb.c70
1 files changed, 53 insertions, 17 deletions
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;
@@ -193,6 +201,36 @@ framebufctl_upscalememdraw(Framebufctl *ctl, Memimage *dst, Point off, Point sca
}
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)
{
Framebuf *fb;
@@ -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;