📄 rleaccel.c
字号:
int ofs = 0; \ for(;;) { \ unsigned run; \ ofs += *(Type *)srcbuf; \ run = ((Type *)srcbuf)[1]; \ srcbuf += 2 * sizeof(Type); \ if(run) { \ do_blit(dstbuf + ofs * bpp, srcbuf, run, bpp, alpha); \ srcbuf += run * bpp; \ ofs += run; \ } else if(!ofs) \ break; \ if(ofs == w) { \ ofs = 0; \ dstbuf += dst->pitch; \ if(!--linecount) \ break; \ } \ } \ } while(0) CHOOSE_BLIT(RLEBLIT, alpha, fmt);#undef RLEBLIT }done: /* Unlock the destination if necessary */ if ( dst->flags & (GAL_HWSURFACE|GAL_ASYNCBLIT) ) { GAL_VideoDevice *video = current_video; GAL_VideoDevice *this = current_video;#if 0 video->UnlockHWSurface(this, dst);#endif } return(0);}#undef OPAQUE_BLIT/* * Per-pixel blitting macros for translucent pixels: * These use the same techniques as the per-surface blitting macros *//* * For 32bpp pixels, we have made sure the alpha is stored in the top * 8 bits, so proceed as usual */#define BLIT_TRANSL_888(src, dst) \ do { \ Uint32 s = src; \ Uint32 d = dst; \ unsigned alpha = s >> 24; \ Uint32 s1 = s & 0xff00ff; \ Uint32 d1 = d & 0xff00ff; \ d1 = (d1 + ((s1 - d1) * alpha >> 8)) & 0xff00ff; \ s &= 0xff00; \ d &= 0xff00; \ d = (d + ((s - d) * alpha >> 8)) & 0xff00; \ dst = d1 | d; \ } while(0)/* * For 16bpp pixels, we have stored the 5 most significant alpha bits in * bits 5-10. As before, we can process all 3 RGB components at the same time. */#define BLIT_TRANSL_565(src, dst) \ do { \ Uint32 s = src; \ Uint32 d = dst; \ unsigned alpha = (s & 0x3e0) >> 5; \ s &= 0x07e0f81f; \ d = (d | d << 16) & 0x07e0f81f; \ d += (s - d) * alpha >> 5; \ d &= 0x07e0f81f; \ dst = d | d >> 16; \ } while(0)#define BLIT_TRANSL_555(src, dst) \ do { \ Uint32 s = src; \ Uint32 d = dst; \ unsigned alpha = (s & 0x3e0) >> 5; \ s &= 0x03e07c1f; \ d = (d | d << 16) & 0x03e07c1f; \ d += (s - d) * alpha >> 5; \ d &= 0x03e07c1f; \ dst = d | d >> 16; \ } while(0)/* used to save the destination format in the encoding. Designed to be macro-compatible with GAL_PixelFormat but without the unneeded fields */typedef struct { Uint8 BytesPerPixel; Uint8 Rloss; Uint8 Gloss; Uint8 Bloss; Uint8 Rshift; Uint8 Gshift; Uint8 Bshift; Uint8 Ashift; Uint32 Rmask; Uint32 Gmask; Uint32 Bmask; Uint32 Amask;} RLEDestFormat;/* blit a pixel-alpha RLE surface clipped at the right and/or left edges */static void RLEAlphaClipBlit(int w, Uint8 *srcbuf, GAL_Surface *dst, Uint8 *dstbuf, GAL_Rect *srcrect){ GAL_PixelFormat *df = dst->format; /* * clipped blitter: Ptype is the destination pixel type, * Ctype the translucent count type, and do_blend the macro * to blend one pixel. */#define RLEALPHACLIPBLIT(Ptype, Ctype, do_blend) \ do { \ int linecount = srcrect->h; \ int left = srcrect->x; \ int right = left + srcrect->w; \ dstbuf -= left * sizeof(Ptype); \ do { \ int ofs = 0; \ /* blit opaque pixels on one line */ \ do { \ unsigned run; \ ofs += ((Ctype *)srcbuf)[0]; \ run = ((Ctype *)srcbuf)[1]; \ srcbuf += 2 * sizeof(Ctype); \ if(run) { \ /* clip to left and right borders */ \ int cofs = ofs; \ int crun = run; \ if(left - cofs > 0) { \ crun -= left - cofs; \ cofs = left; \ } \ if(crun > right - cofs) \ crun = right - cofs; \ if(crun > 0) \ PIXEL_COPY(dstbuf + cofs * sizeof(Ptype), \ srcbuf + (cofs - ofs) * sizeof(Ptype), \ (unsigned)crun, sizeof(Ptype)); \ srcbuf += run * sizeof(Ptype); \ ofs += run; \ } else if(!ofs) \ return; \ } while(ofs < w); \ /* skip padding if necessary */ \ if(sizeof(Ptype) == 2) \ srcbuf += (unsigned long)srcbuf & 2; \ /* blit translucent pixels on the same line */ \ ofs = 0; \ do { \ unsigned run; \ ofs += ((Uint16 *)srcbuf)[0]; \ run = ((Uint16 *)srcbuf)[1]; \ srcbuf += 4; \ if(run) { \ /* clip to left and right borders */ \ int cofs = ofs; \ int crun = run; \ if(left - cofs > 0) { \ crun -= left - cofs; \ cofs = left; \ } \ if(crun > right - cofs) \ crun = right - cofs; \ if(crun > 0) { \ Ptype *dst = (Ptype *)dstbuf + cofs; \ Uint32 *src = (Uint32 *)srcbuf + (cofs - ofs); \ int i; \ for(i = 0; i < crun; i++) \ do_blend(src[i], dst[i]); \ } \ srcbuf += run * 4; \ ofs += run; \ } \ } while(ofs < w); \ dstbuf += dst->pitch; \ } while(--linecount); \ } while(0) switch(df->BytesPerPixel) { case 2: if(df->Gmask == 0x07e0 || df->Rmask == 0x07e0 || df->Bmask == 0x07e0) RLEALPHACLIPBLIT(Uint16, Uint8, BLIT_TRANSL_565); else RLEALPHACLIPBLIT(Uint16, Uint8, BLIT_TRANSL_555); break; case 4: RLEALPHACLIPBLIT(Uint32, Uint16, BLIT_TRANSL_888); break; }}/* blit a pixel-alpha RLE surface */int GAL_RLEAlphaBlit(GAL_Surface *src, GAL_Rect *srcrect, GAL_Surface *dst, GAL_Rect *dstrect){ int x, y; int w = src->w; Uint8 *srcbuf, *dstbuf; GAL_PixelFormat *df = dst->format; /* Lock the destination if necessary */ if(dst->flags & (GAL_HWSURFACE|GAL_ASYNCBLIT)) { GAL_VideoDevice *video = current_video; GAL_VideoDevice *this = current_video;#if 0 if(video->LockHWSurface(this, dst) < 0) { return -1; }#endif } x = dstrect->x; y = dstrect->y; dstbuf = (Uint8 *)dst->pixels + dst->offset + y * dst->pitch + x * df->BytesPerPixel; srcbuf = (Uint8 *)src->map->sw_data->aux_data + sizeof(RLEDestFormat); { /* skip lines at the top if necessary */ int vskip = srcrect->y; if(vskip) { int ofs; if(df->BytesPerPixel == 2) { /* the 16/32 interleaved format */ do { /* skip opaque line */ ofs = 0; do { int run; ofs += srcbuf[0]; run = srcbuf[1]; srcbuf += 2; if(run) { srcbuf += 2 * run; ofs += run; } else if(!ofs) goto done; } while(ofs < w); /* skip padding */ srcbuf += (unsigned long)srcbuf & 2; /* skip translucent line */ ofs = 0; do { int run; ofs += ((Uint16 *)srcbuf)[0]; run = ((Uint16 *)srcbuf)[1]; srcbuf += 4 * (run + 1); ofs += run; } while(ofs < w); } while(--vskip); } else { /* the 32/32 interleaved format */ vskip <<= 1; /* opaque and translucent have same format */ do { ofs = 0; do { int run; ofs += ((Uint16 *)srcbuf)[0]; run = ((Uint16 *)srcbuf)[1]; srcbuf += 4; if(run) { srcbuf += 4 * run; ofs += run; } else if(!ofs) goto done; } while(ofs < w); } while(--vskip); } } } /* if left or right edge clipping needed, call clip blit */ if(srcrect->x || srcrect->w != src->w) { RLEAlphaClipBlit(w, srcbuf, dst, dstbuf, srcrect); } else { /* * non-clipped blitter. Ptype is the destination pixel type, * Ctype the translucent count type, and do_blend the * macro to blend one pixel. */#define RLEALPHABLIT(Ptype, Ctype, do_blend) \ do { \ int linecount = srcrect->h; \ do { \ int ofs = 0; \ /* blit opaque pixels on one line */ \ do { \ unsigned run; \ ofs += ((Ctype *)srcbuf)[0]; \ run = ((Ctype *)srcbuf)[1]; \ srcbuf += 2 * sizeof(Ctype); \ if(run) { \ PIXEL_COPY(dstbuf + ofs * sizeof(Ptype), srcbuf, \ run, sizeof(Ptype)); \ srcbuf += run * sizeof(Ptype); \ ofs += run; \ } else if(!ofs) \ goto done; \ } while(ofs < w); \ /* skip padding if necessary */ \ if(sizeof(Ptype) == 2) \ srcbuf += (unsigned long)srcbuf & 2; \ /* blit translucent pixels on the same line */ \ ofs = 0; \ do { \ unsigned run; \ ofs += ((Uint16 *)srcbuf)[0]; \ run = ((Uint16 *)srcbuf)[1]; \ srcbuf += 4; \ if(run) { \ Ptype *dst = (Ptype *)dstbuf + ofs; \ unsigned i; \ for(i = 0; i < run; i++) { \ Uint32 src = *(Uint32 *)srcbuf; \ do_blend(src, *dst); \ srcbuf += 4; \ dst++; \ } \ ofs += run; \ } \ } while(ofs < w); \ dstbuf += dst->pitch; \ } while(--linecount); \ } while(0) switch(df->BytesPerPixel) { case 2: if(df->Gmask == 0x07e0 || df->Rmask == 0x07e0 || df->Bmask == 0x07e0) RLEALPHABLIT(Uint16, Uint8, BLIT_TRANSL_565); else RLEALPHABLIT(Uint16, Uint8, BLIT_TRANSL_555); break; case 4: RLEALPHABLIT(Uint32, Uint16, BLIT_TRANSL_888); break; } } done: /* Unlock the destination if necessary */ if(dst->flags & (GAL_HWSURFACE|GAL_ASYNCBLIT)) { GAL_VideoDevice *video = current_video; GAL_VideoDevice *this = current_video;#if 0 video->UnlockHWSurface(this, dst);#endif } return 0;}/* * Auxiliary functions: * The encoding functions take 32bpp rgb + a, and * return the number of bytes copied to the destination. * The decoding functions copy to 32bpp rgb + a, and * return the number of bytes copied from the source. * These are only used in the encoder and un-RLE code and are therefore not * highly optimised. *//* encode 32bpp rgb + a into 16bpp rgb, losing alpha */static int copy_opaque_16(void *dst, Uint32 *src, int n, GAL_PixelFormat *sfmt, GAL_PixelFormat *dfmt){ int i; Uint16 *d = dst; for(i = 0; i < n; i++) { unsigned r, g, b; RGB_FROM_PIXEL(*src, sfmt, r, g, b); PIXEL_FROM_RGB(*d, dfmt, r, g, b); src++; d++; } return n * 2;}/* decode opaque pixels from 16bpp to 32bpp rgb + a */static int uncopy_opaque_16(Uint32 *dst, void *src, int n, RLEDestFormat *sfmt, GAL_PixelFormat *dfmt){ int i; Uint16 *s = src; unsigned alpha = dfmt->Amask ? 255 : 0; for(i = 0; i < n; i++) { unsigned r, g, b; RGB_FROM_PIXEL(*s, sfmt, r, g, b); PIXEL_FROM_RGBA(*dst, dfmt, r, g, b, alpha); s++; dst++; } return n * 2;}/* encode 32bpp rgb + a into 32bpp G0RAB format for blitting into 565 */static int copy_transl_565(void *dst, Uint32 *src, int n, GAL_PixelFormat *sfmt, GAL_PixelFormat *dfmt){ int i; Uint32 *d = dst; for(i = 0; i < n; i++) { unsigned r, g, b, a; Uint16 pix; RGBA_FROM_8888(*src, sfmt, r, g, b, a); PIXEL_FROM_RGB(pix, dfmt, r, g, b); *d = ((pix & 0x7e0) << 16) | (pix & 0xf81f) | ((a << 2) & 0x7e0); src++; d++; } return n * 4;}/* encode 32bpp rgb + a into 32bpp G0RAB format for blitting into 555 */static int copy_transl_555(void *dst, Uint32 *src, int n, GAL_PixelFormat *sfmt, GAL_PixelFormat *dfmt){ int i; Uint32 *d = dst; for(i = 0; i < n; i++) { unsigned r, g, b, a; Uint16 pix; RGBA_FROM_8888(*src, sfmt, r, g, b, a); PIXEL_FROM_RGB(pix, dfmt, r, g, b); *d = ((pix & 0x3e0) << 16) | (pix & 0xfc1f) | ((a << 2) & 0x3e0); src++; d++; } return n * 4;}/* decode translucent pixels from 32bpp GORAB to 32bpp rgb + a */static int uncopy_transl_16(Uint32 *dst, void *src, int n, RLEDestFormat *sfmt, GAL_PixelFormat *dfmt){ int i; Uint32 *s = src; for(i = 0; i < n; i++) { unsigned r, g, b, a; Uint32 pix = *s++; a = (pix & 0x3e0) >> 2; pix = (pix & ~0x3e0) | pix >> 16; RGB_FROM_PIXEL(pix, sfmt, r, g, b); PIXEL_FROM_RGBA(*dst, dfmt, r, g, b, a); dst++; } return n * 4;}/* encode 32bpp rgba into 32bpp rgba, keeping alpha (dual purpose) */static int copy_32(void *dst, Uint32 *src, int n, GAL_PixelFormat *sfmt, GAL_PixelFormat *dfmt){ int i; Uint32 *d = dst; for(i = 0; i < n; i++) { unsigned r, g, b, a; Uint32 pixel; RGBA_FROM_8888(*src, sfmt, r, g, b, a); PIXEL_FROM_RGB(pixel, dfmt, r, g, b); *d++ = pixel | a << 24; src++; } return n * 4;}/* decode 32bpp rgba into 32bpp rgba, keeping alpha (dual purpose) */static int uncopy_32(Uint32 *dst, void *src, int n, RLEDestFormat *sfmt, GAL_PixelFormat *dfmt){ int i; Uint32 *s = src; for(i = 0; i < n; i++) { unsigned r, g, b, a; Uint32 pixel = *s++; RGB_FROM_PIXEL(pixel, sfmt, r, g, b); a = pixel >> 24; PIXEL_FROM_RGBA(*dst, dfmt, r, g, b, a); dst++; } return n * 4;}#define ISOPAQUE(pixel, fmt) ((((pixel) & fmt->Amask) >> fmt->Ashift) == 255)#define ISTRANSL(pixel, fmt) \ ((unsigned)((((pixel) & fmt->Amask) >> fmt->Ashift) - 1U) < 254U)/* convert surface to be quickly alpha-blittable onto dest, if possible */static int RLEAlphaSurface(GAL_Surface *surface){ GAL_Surface *dest; GAL_PixelFormat *df; int maxsize = 0; int max_opaque_run; int max_transl_run = 65535; unsigned masksum; Uint8 *rlebuf, *dst; int (*copy_opaque)(void *, Uint32 *, int, GAL_PixelFormat *, GAL_PixelFormat *); int (*copy_transl)(void *, Uint32 *, int, GAL_PixelFormat *, GAL_PixelFormat *); dest = surface->map->dst; if(!dest) return -1; df = dest->format; if(surface->format->BitsPerPixel != 32)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -