#include #include #include //--- // Internal functions //--- struct imgbox { struct { struct { int start; int end; } y; struct { int start; int end; } x; } img; struct { uint16_t *vram; int voff; } surface; }; /* dsubimage_default_render() : raw-format image render */ static void dsubimage_default_render(image_t const *image, struct imgbox *box) { (void)image; (void)box; #if 0 uint16_t *vram; uint16_t *vidxs; uint16_t *vidx; int voff; vram = surface->draw; voff = box->surface.idx.offset; vidxs = &vram[box->surface.idx.start]; for (int iy = box->img.y.start; iy < box->img.y.end; ++iy) { vidx = vidxs; for (int ix = box->img.x.start; ix < box->img.x.end; ++ix) { *(vidx++) = image_decode_pixel( image, image_get_pixel(image, ix, iy) ); } vidxs = &vidxs[voff]; } #endif } /* dsubimage_alpha_render() : alpha-format image render */ static void dsubimage_alpha_render(image_t const *image, struct imgbox *box) { uint16_t *vram; uint16_t *data; uint16_t pixel; uint16_t alpha; int voff; int c; voff = box->surface.voff; vram = box->surface.vram; alpha = image_alpha(image->format); for (int iy = box->img.y.start; iy < box->img.y.end; ++iy) { data = vram; c = 0; for (int ix = box->img.x.start; ix < box->img.x.end; ++ix) { pixel = image_get_pixel(image, ix, iy); if (pixel != alpha) data[c] = image_decode_pixel(image, pixel); c += 1; } vram = &vram[voff]; } } //--- // Kernel-level API //--- void dsubimage_render( dsurface_t *surface, int x, int y, image_t const *image, int left, int top, int width, int height ) { uint16_t *vram; int vxs; int vys; /* precalculate culling information */ if (x < 0) { left -= x; width += x; x = 0; } if (y < 0) { top -= y; height += y; y = 0; } /* check error */ if (top < 0 || left < 0 || width < 0 || height < 0) return; /* check culling */ if (y >= surface->y2 || y + height < surface->y1 || x >= surface->x2 || x + width < surface->x1) { return; } /* precalculate geometry information (both image and vram) */ vxs = x - surface->x1; vys = y - surface->y1; if (vxs < 0) { vxs = 0; left += (surface->x1 - x); width -= (surface->x1 - x); } if (vys < 0) { vys = 0; top += (surface->y1 - y); height -= (surface->y1 + y); } if ((size_t)(vxs + width) > surface->width) width = surface->width - vxs; if ((size_t)(vys + height) > surface->height) height = surface->height - vys; vram = surface->frag; /* prepare box request */ struct imgbox imgbox = { .img = { .y = { .start = top, .end = top + height }, .x = { .start = left, .end = left + width } }, .surface = { .vram = &vram[(surface->width * vys) + vxs], .voff = surface->width } }; #if 0 dclear(C_WHITE); dprint(0, 0, C_BLACK, "surface.x1 = %d\n" "surface.x2 = %d\n" "surface.y1 = %d\n" "surface.y2 = %d\n" "surface.width = %d\n" "surface.height = %d\n" "\n" "img.y.start = %d\n" "img.y.end = %d\n" "img.x.start = %d\n" "img.x.end = %d\n" "\n" "image.x = %d\n" "image.y = %d\n" "image.width = %d\n" "image.heigt = %d\n", surface->x1, surface->x2, surface->y1, surface->y2, surface->width, surface->height, imgbox.img.y.start, imgbox.img.y.end, imgbox.img.x.start, imgbox.img.x.end, x, y, width, height ); dupdate(); while(1) { __asm__ volatile ("sleep"); } #endif /* send drawing request in the approriate optimized function */ if (IMAGE_IS_ALPHA(image->format)) { dsubimage_alpha_render(image, &imgbox); return; } dsubimage_default_render(image, &imgbox); } /* dimage_render(): Render a full image */ void dimage_render(dsurface_t *surface, int x, int y, image_t const *img) { dsubimage_render(surface, x, y, img, 0, 0, img->width, img->height); } //--- // Dstack API //--- /* dimage_dstack(): dstack wrapper primitive */ void dimage_dstack(dsurface_t *surface, uint32_t *args) { dimage_render( surface, (int)args[0], (int)args[1], (image_t*)(uintptr_t)args[2] ); } /* dsubimage_dstack(): dstack wrapper primitive */ void dsubimage_dstack(dsurface_t *surface, uint32_t *args) { dsubimage_render( surface, (int)args[0], (int)args[1], (image_t*)(uintptr_t)args[2], (int)args[3], (int)args[4], (int)args[5], (int)args[6] ); } //--- // User-level API //--- /* dimage(): Render a full image */ void dimage(image_t const *image, int x, int y, int mode) { if (mode & DIMAGE_CENTER) { x -= image->width >> 1; } if (mode & DIMAGE_RIGHT) { x -= image->width; } if (mode & DIMAGE_MIDDLE) { y -= image->height >> 1; } if (mode & DIMAGE_BOTTOM) { y -= image->height; } dstack_add_action( &DSTACK_CALL(&dimage_dstack, x, y, (uintptr_t)image), NULL, NULL ); } /* dsubimage(): Render a section of an image */ void dsubimage( int x, int y, image_t const *image, int left, int top, int width, int height ) { dstack_add_action( &DSTACK_CALL( &dsubimage_dstack, x, y, (uintptr_t)image, left, top, width, height ), NULL, NULL ); }