80 lines
3.4 KiB
C
80 lines
3.4 KiB
C
/* wallpaper.c — 壁纸背景层缓存实现(M2:磁盘加载版)
|
||
*
|
||
* 流程:FAT32 流式读桌面材质包 textures/back.rgba(889×500 RGBA 字节流)
|
||
* → WALLPAPER_STAGING_ADDR 暂存 → 双线性缩放(对齐像素中心,8.8 定点)
|
||
* → WALLPAPER_ADDR 背景层缓存。
|
||
* 数组字节序 R,G,B,A;framebuffer u32 = 0xAARRGGBB(R 在 bit16)。 */
|
||
#include "wallpaper.h"
|
||
|
||
/* 材质包 back.rgba 尺寸(与 gen_textures.py 的 back 889×500 一致;运行时按文件大小校验) */
|
||
#define WP_SRC_W 889
|
||
#define WP_SRC_H 500
|
||
|
||
static wp_u32 *g_wp_layer = 0;
|
||
static int g_wp_w = 0, g_wp_h = 0;
|
||
static wp_u32 g_wp_src_w = WP_SRC_W, g_wp_src_h = WP_SRC_H;
|
||
|
||
int wallpaper_init(wallpaper_read_fn read_to, int fb_w, int fb_h) {
|
||
if (!read_to || fb_w <= 0 || fb_h <= 0) return -1;
|
||
if ((wp_u64)fb_w * (wp_u64)fb_h * 4u > WALLPAPER_MAX) return -2;
|
||
|
||
/* 1. 流式读原始 RGBA 到暂存区(PE surface 区,启动期独占) */
|
||
wp_u32 src_total = g_wp_src_w * g_wp_src_h * 4u;
|
||
if (src_total > WALLPAPER_STAGING_MAX) return -3;
|
||
wp_u32 got = 0;
|
||
if (read_to("system/deshab64/desktop/textures/back.rgba",
|
||
(wp_u8 *)WALLPAPER_STAGING_ADDR, src_total, &got) != 0)
|
||
return -4;
|
||
if (got < src_total) {
|
||
/* 文件比预期小:按实际行数截断(防御,正常部署不会发生) */
|
||
if (got < g_wp_src_w * 4u) return -5;
|
||
g_wp_src_h = got / (g_wp_src_w * 4u);
|
||
}
|
||
const wp_u8 *src = (const wp_u8 *)WALLPAPER_STAGING_ADDR;
|
||
|
||
/* 2. 双线性缩放到背景层缓存 */
|
||
g_wp_layer = (wp_u32 *)WALLPAPER_ADDR;
|
||
g_wp_w = fb_w;
|
||
g_wp_h = fb_h;
|
||
int sw = (int)g_wp_src_w, sh = (int)g_wp_src_h;
|
||
for (int y = 0; y < fb_h; y++) {
|
||
wp_i64 fy64 = ((wp_i64)y * sh << 8) / fb_h; /* 8.8 定点 */
|
||
int sy0 = (int)(fy64 >> 8);
|
||
int fy = (int)(fy64 & 0xFF);
|
||
int sy1 = (sy0 + 1 < sh) ? sy0 + 1 : sy0;
|
||
if (sy0 >= sh) sy0 = sy1 = sh - 1;
|
||
for (int x = 0; x < fb_w; x++) {
|
||
wp_i64 fx64 = ((wp_i64)x * sw << 8) / fb_w;
|
||
int sx0 = (int)(fx64 >> 8);
|
||
int fx = (int)(fx64 & 0xFF);
|
||
int sx1 = (sx0 + 1 < sw) ? sx0 + 1 : sx0;
|
||
if (sx0 >= sw) sx0 = sx1 = sw - 1;
|
||
|
||
const wp_u8 *p00 = src + ((wp_i64)sy0 * sw + sx0) * 4;
|
||
const wp_u8 *p10 = src + ((wp_i64)sy0 * sw + sx1) * 4;
|
||
const wp_u8 *p01 = src + ((wp_i64)sy1 * sw + sx0) * 4;
|
||
const wp_u8 *p11 = src + ((wp_i64)sy1 * sw + sx1) * 4;
|
||
|
||
wp_u32 r, g, b;
|
||
{
|
||
wp_u32 rtop = ((wp_u32)p00[0] * (256 - fx) + (wp_u32)p10[0] * fx) >> 8;
|
||
wp_u32 rbot = ((wp_u32)p01[0] * (256 - fx) + (wp_u32)p11[0] * fx) >> 8;
|
||
wp_u32 gtop = ((wp_u32)p00[1] * (256 - fx) + (wp_u32)p10[1] * fx) >> 8;
|
||
wp_u32 gbot = ((wp_u32)p01[1] * (256 - fx) + (wp_u32)p11[1] * fx) >> 8;
|
||
wp_u32 btop = ((wp_u32)p00[2] * (256 - fx) + (wp_u32)p10[2] * fx) >> 8;
|
||
wp_u32 bbot = ((wp_u32)p01[2] * (256 - fx) + (wp_u32)p11[2] * fx) >> 8;
|
||
r = (rtop * (256 - fy) + rbot * fy) >> 8;
|
||
g = (gtop * (256 - fy) + gbot * fy) >> 8;
|
||
b = (btop * (256 - fy) + bbot * fy) >> 8;
|
||
}
|
||
g_wp_layer[(wp_i64)y * fb_w + x] =
|
||
0xFF000000u | (r << 16) | (g << 8) | b;
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
wp_u32 *wallpaper_layer(void) {
|
||
return g_wp_layer;
|
||
}
|