mirror of
https://github.com/VincentWei/MiniGUI.git
synced 2026-09-28 16:17:09 +08:00
2050 lines
61 KiB
C
2050 lines
61 KiB
C
/*
|
|
* This file is part of MiniGUI, a mature cross-platform windowing
|
|
* and Graphics User Interface (GUI) support system for embedded systems
|
|
* and smart IoT devices.
|
|
*
|
|
* Copyright (C) 2002~2018, Beijing FMSoft Technologies Co., Ltd.
|
|
* Copyright (C) 1998~2002, WEI Yongming
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Or,
|
|
*
|
|
* As this program is a library, any link to this program must follow
|
|
* GNU General Public License version 3 (GPLv3). If you cannot accept
|
|
* GPLv3, you need to be licensed from FMSoft.
|
|
*
|
|
* If you have got a commercial license of this program, please use it
|
|
* under the terms and conditions of the commercial license.
|
|
*
|
|
* For more information about the commercial license, please refer to
|
|
* <http://www.minigui.com/en/about/licensing-policy/>.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "common.h"
|
|
#include "newgal.h"
|
|
#include "sysvideo.h"
|
|
#include "blit.h"
|
|
#include "RLEaccel_c.h"
|
|
#include "pixels_c.h"
|
|
#include "memops.h"
|
|
#include "leaks.h"
|
|
|
|
/* Public routines */
|
|
/*
|
|
* Create an empty RGB surface of the appropriate depth
|
|
*/
|
|
GAL_Surface * GAL_CreateRGBSurface (Uint32 flags,
|
|
int width, int height, int depth,
|
|
Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
|
|
{
|
|
GAL_VideoDevice *video = current_video;
|
|
GAL_VideoDevice *this = current_video;
|
|
GAL_Surface *screen;
|
|
GAL_Surface *surface;
|
|
|
|
/* Check to see if we desire the surface in video memory */
|
|
if ( video ) {
|
|
screen = GAL_PublicSurface;
|
|
} else {
|
|
screen = NULL;
|
|
}
|
|
if ( screen && ((screen->flags&GAL_HWSURFACE) == GAL_HWSURFACE) ) {
|
|
if ( (flags&(GAL_SRCCOLORKEY|GAL_SRCALPHA)) != 0 ) {
|
|
flags |= GAL_HWSURFACE;
|
|
}
|
|
if ( (flags & GAL_SRCCOLORKEY) == GAL_SRCCOLORKEY ) {
|
|
if ( ! current_video->info.blit_hw_CC ) {
|
|
flags &= ~GAL_HWSURFACE;
|
|
}
|
|
}
|
|
if ( (flags & GAL_SRCALPHA) == GAL_SRCALPHA ) {
|
|
if ( ! current_video->info.blit_hw_A ) {
|
|
flags &= ~GAL_HWSURFACE;
|
|
}
|
|
}
|
|
} else {
|
|
flags &= ~GAL_HWSURFACE;
|
|
}
|
|
|
|
/* Allocate the surface */
|
|
surface = (GAL_Surface *)malloc(sizeof(*surface));
|
|
if ( surface == NULL ) {
|
|
GAL_OutOfMemory();
|
|
return(NULL);
|
|
}
|
|
if ((flags & GAL_HWSURFACE) == GAL_HWSURFACE)
|
|
surface->video = current_video;
|
|
else
|
|
surface->video = NULL;
|
|
|
|
surface->flags = GAL_SWSURFACE;
|
|
|
|
/* 2011-03-04 WanZheng,
|
|
* make it able to create a hardware surface
|
|
* with different color format against the screen surface
|
|
*/
|
|
#if 0
|
|
if ( (flags & GAL_HWSURFACE) == GAL_HWSURFACE ) {
|
|
depth = screen->format->BitsPerPixel;
|
|
Rmask = screen->format->Rmask;
|
|
Gmask = screen->format->Gmask;
|
|
Bmask = screen->format->Bmask;
|
|
Amask = screen->format->Amask;
|
|
}
|
|
#endif
|
|
if (Amask){
|
|
surface->flags |= GAL_SRCPIXELALPHA;
|
|
}
|
|
surface->format = GAL_AllocFormat(depth, Rmask, Gmask, Bmask, Amask);
|
|
if ( surface->format == NULL ) {
|
|
free(surface);
|
|
return(NULL);
|
|
}
|
|
surface->w = width;
|
|
surface->h = height;
|
|
surface->pitch = GAL_CalculatePitch(surface);
|
|
surface->pixels = NULL;
|
|
surface->offset = 0;
|
|
// for off-screen surface, DPI always be the default value
|
|
surface->dpi = GDCAP_DPI_DEFAULT;
|
|
surface->hwdata = NULL;
|
|
surface->map = NULL;
|
|
surface->format_version = 0;
|
|
GAL_SetClipRect(surface, NULL);
|
|
|
|
#ifdef _MGUSE_SYNC_UPDATE
|
|
/* Initialize update region */
|
|
InitClipRgn (&surface->update_region, &__mg_free_update_region_list);
|
|
#endif
|
|
|
|
/* Get the pixels */
|
|
if ( surface->w && surface->h ) {
|
|
if ( ((flags&GAL_HWSURFACE) == GAL_SWSURFACE) ||
|
|
(video->AllocHWSurface(this, surface) < 0) ) {
|
|
surface->pixels = malloc(surface->h*surface->pitch);
|
|
if ( surface->pixels == NULL ) {
|
|
GAL_FreeSurface(surface);
|
|
GAL_OutOfMemory();
|
|
return(NULL);
|
|
}
|
|
/* This is important for bitmaps */
|
|
memset(surface->pixels, 0, surface->h*surface->pitch);
|
|
surface->flags &= ~GAL_HWSURFACE;
|
|
}
|
|
}
|
|
|
|
/* Allocate an empty mapping */
|
|
surface->map = GAL_AllocBlitMap();
|
|
if ( surface->map == NULL ) {
|
|
GAL_FreeSurface(surface);
|
|
return(NULL);
|
|
}
|
|
|
|
/* The surface is ready to go */
|
|
surface->refcount = 1;
|
|
#ifdef CHECK_LEAKS
|
|
++surfaces_allocated;
|
|
#endif
|
|
return(surface);
|
|
}
|
|
/*
|
|
* Create an RGB surface from an existing memory buffer
|
|
*/
|
|
GAL_Surface * GAL_CreateRGBSurfaceFrom (void *pixels,
|
|
int width, int height, int depth, int pitch,
|
|
Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
|
|
{
|
|
GAL_Surface *surface;
|
|
|
|
surface = GAL_CreateRGBSurface(GAL_SWSURFACE, 0, 0, depth,
|
|
Rmask, Gmask, Bmask, Amask);
|
|
if ( surface != NULL ) {
|
|
surface->flags |= GAL_PREALLOC;
|
|
surface->pixels = pixels;
|
|
surface->w = width;
|
|
surface->h = height;
|
|
surface->pitch = pitch;
|
|
GAL_SetClipRect(surface, NULL);
|
|
}
|
|
return(surface);
|
|
}
|
|
/*
|
|
* Set the color key in a blittable surface
|
|
*/
|
|
int GAL_SetColorKey (GAL_Surface *surface, Uint32 flag, Uint32 key)
|
|
{
|
|
/* Sanity check the flag as it gets passed in */
|
|
if ( flag & GAL_SRCCOLORKEY ) {
|
|
if ( flag & (GAL_RLEACCEL|GAL_RLEACCELOK) ) {
|
|
flag = (GAL_SRCCOLORKEY | GAL_RLEACCELOK);
|
|
} else {
|
|
flag = GAL_SRCCOLORKEY;
|
|
}
|
|
} else {
|
|
flag = 0;
|
|
}
|
|
|
|
/* Optimize away operations that don't change anything */
|
|
if ( (flag == (surface->flags & (GAL_SRCCOLORKEY|GAL_RLEACCELOK))) &&
|
|
(key == surface->format->colorkey) ) {
|
|
return(0);
|
|
}
|
|
|
|
/* UnRLE surfaces before we change the colorkey */
|
|
if ( surface->flags & GAL_RLEACCEL ) {
|
|
GAL_UnRLESurface(surface, 1);
|
|
}
|
|
|
|
if ( flag ) {
|
|
GAL_VideoDevice *video = current_video;
|
|
GAL_VideoDevice *this = current_video;
|
|
|
|
surface->flags |= GAL_SRCCOLORKEY;
|
|
surface->format->colorkey = key;
|
|
if ( (surface->flags & GAL_HWACCEL) == GAL_HWACCEL ) {
|
|
if ( (video->SetHWColorKey == NULL) ||
|
|
(video->SetHWColorKey(this, surface, key) < 0) ) {
|
|
surface->flags &= ~GAL_HWACCEL;
|
|
}
|
|
}
|
|
if ( flag & GAL_RLEACCELOK ) {
|
|
surface->flags |= GAL_RLEACCELOK;
|
|
} else {
|
|
surface->flags &= ~GAL_RLEACCELOK;
|
|
}
|
|
} else {
|
|
surface->flags &= ~(GAL_SRCCOLORKEY|GAL_RLEACCELOK);
|
|
surface->format->colorkey = 0;
|
|
}
|
|
GAL_InvalidateMap(surface->map);
|
|
return(0);
|
|
}
|
|
int GAL_SetAlpha (GAL_Surface *surface, Uint32 flag, Uint8 value)
|
|
{
|
|
Uint32 oldflags = surface->flags;
|
|
Uint32 oldalpha = surface->format->alpha;
|
|
|
|
/* Sanity check the flag as it gets passed in */
|
|
if ( flag & GAL_SRCALPHA ) {
|
|
if ( flag & (GAL_RLEACCEL|GAL_RLEACCELOK) ) {
|
|
flag = GAL_SRCALPHA|GAL_RLEACCELOK;
|
|
} else {
|
|
flag = GAL_SRCALPHA;
|
|
}
|
|
|
|
/* Optimize away operations that don't change anything */
|
|
if ( (flag == (surface->flags & (GAL_SRCALPHA|GAL_RLEACCELOK)))
|
|
&& (!flag || value == oldalpha) ) {
|
|
return(0);
|
|
}
|
|
} else if ( flag & GAL_SRCPIXELALPHA ){
|
|
if ( flag & (GAL_RLEACCEL|GAL_RLEACCELOK) ) {
|
|
flag = GAL_SRCPIXELALPHA|GAL_RLEACCELOK;
|
|
} else {
|
|
flag = GAL_SRCPIXELALPHA;
|
|
}
|
|
} else {
|
|
flag = 0;
|
|
}
|
|
|
|
if(!(flag & GAL_RLEACCELOK) && (surface->flags & GAL_RLEACCEL))
|
|
GAL_UnRLESurface(surface, 1);
|
|
|
|
if ( flag ) {
|
|
GAL_VideoDevice *video = current_video;
|
|
GAL_VideoDevice *this = current_video;
|
|
|
|
if ( flag & GAL_SRCALPHA ) {
|
|
surface->flags |= GAL_SRCALPHA;
|
|
surface->format->alpha = value;
|
|
} else if ( flag & GAL_SRCPIXELALPHA ){
|
|
surface->flags |= GAL_SRCPIXELALPHA;
|
|
}
|
|
|
|
|
|
if ( (surface->flags & GAL_HWACCEL) == GAL_HWACCEL ) {
|
|
if ( (video->SetHWAlpha == NULL) ||
|
|
(video->SetHWAlpha(this, surface, value) < 0) ) {
|
|
surface->flags &= ~GAL_HWACCEL;
|
|
}
|
|
}
|
|
if ( flag & GAL_RLEACCELOK ) {
|
|
surface->flags |= GAL_RLEACCELOK;
|
|
} else {
|
|
surface->flags &= ~GAL_RLEACCELOK;
|
|
}
|
|
} else {
|
|
surface->flags &= ~GAL_SRCALPHA;
|
|
surface->flags &= ~GAL_SRCPIXELALPHA;
|
|
surface->format->alpha = GAL_ALPHA_OPAQUE;
|
|
}
|
|
/*
|
|
* The representation for software surfaces is independent of
|
|
* per-surface alpha, so no need to invalidate the blit mapping
|
|
* if just the alpha value was changed. (If either is 255, we still
|
|
* need to invalidate.)
|
|
*/
|
|
if((surface->flags & GAL_HWACCEL) == GAL_HWACCEL
|
|
|| oldflags != surface->flags
|
|
|| (((oldalpha + 1) ^ (value + 1)) & 0x100))
|
|
GAL_InvalidateMap(surface->map);
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* A function to calculate the intersection of two rectangles:
|
|
* return true if the rectangles intersect, false otherwise
|
|
*/
|
|
static inline
|
|
GAL_bool GAL_IntersectRect(const GAL_Rect *A, const GAL_Rect *B, GAL_Rect *intersection)
|
|
{
|
|
int Amin, Amax, Bmin, Bmax;
|
|
|
|
/* Horizontal intersection */
|
|
Amin = A->x;
|
|
Amax = Amin + A->w;
|
|
Bmin = B->x;
|
|
Bmax = Bmin + B->w;
|
|
if(Bmin > Amin)
|
|
Amin = Bmin;
|
|
intersection->x = Amin;
|
|
if(Bmax < Amax)
|
|
Amax = Bmax;
|
|
intersection->w = Amax - Amin > 0 ? Amax - Amin : 0;
|
|
|
|
/* Vertical intersection */
|
|
Amin = A->y;
|
|
Amax = Amin + A->h;
|
|
Bmin = B->y;
|
|
Bmax = Bmin + B->h;
|
|
if(Bmin > Amin)
|
|
Amin = Bmin;
|
|
intersection->y = Amin;
|
|
if(Bmax < Amax)
|
|
Amax = Bmax;
|
|
intersection->h = Amax - Amin > 0 ? Amax - Amin : 0;
|
|
|
|
return (intersection->w && intersection->h);
|
|
}
|
|
/*
|
|
* Set the clipping rectangle for a blittable surface
|
|
*/
|
|
GAL_bool GAL_SetClipRect(GAL_Surface *surface, GAL_Rect *rect)
|
|
{
|
|
GAL_Rect full_rect;
|
|
|
|
/* Don't do anything if there's no surface to act on */
|
|
if ( ! surface ) {
|
|
return GAL_FALSE;
|
|
}
|
|
|
|
/* Set up the full surface rectangle */
|
|
full_rect.x = 0;
|
|
full_rect.y = 0;
|
|
full_rect.w = surface->w;
|
|
full_rect.h = surface->h;
|
|
|
|
/* Set the clipping rectangle */
|
|
if ( ! rect ) {
|
|
surface->clip_rect = full_rect;
|
|
return 1;
|
|
}
|
|
return GAL_IntersectRect(rect, &full_rect, &surface->clip_rect);
|
|
}
|
|
void GAL_GetClipRect(GAL_Surface *surface, GAL_Rect *rect)
|
|
{
|
|
if ( surface && rect ) {
|
|
*rect = surface->clip_rect;
|
|
}
|
|
}
|
|
|
|
#if defined ( _MGGAL_SIGMA8654) || defined (_MGGAL_MSTAR) || defined (_MGGAL_STGFB)
|
|
# define MG_CONFIG_USE_OWN_OVERLAPPED_BITBLIT
|
|
#endif
|
|
|
|
#ifdef MG_CONFIG_USE_OWN_OVERLAPPED_BITBLIT
|
|
#include <assert.h>
|
|
|
|
static inline void galrect_2_rect(GAL_Rect *gal_rect, RECT *rc) {
|
|
rc->left = gal_rect->x;
|
|
rc->top = gal_rect->y;
|
|
rc->right = gal_rect->x + gal_rect->w;
|
|
rc->bottom = gal_rect->y + gal_rect->h;
|
|
}
|
|
|
|
int own_overlapped_bitblit(GAL_blit real_blit, struct GAL_Surface *src, GAL_Rect *srcrect,
|
|
struct GAL_Surface *dst, GAL_Rect *dstrect) {
|
|
int w, W, x;
|
|
int h, H, y;
|
|
int delta;
|
|
int ret = 0;
|
|
RECT intersect, src_rc, dst_rc;
|
|
|
|
assert(srcrect->w == dstrect->w || srcrect->h == dstrect->h);
|
|
|
|
galrect_2_rect(srcrect, &src_rc);
|
|
galrect_2_rect(dstrect, &dst_rc);
|
|
|
|
/* don't intersect or horizontal left or up or left-up overlapped blit directly */
|
|
if (! IntersectRect(&intersect, &src_rc, &dst_rc)
|
|
|| (dst_rc.top <= src_rc.top && dst_rc.left <= src_rc.left)) {
|
|
return real_blit(src, srcrect, dst, dstrect);
|
|
}
|
|
|
|
GAL_Rect src1, dst1;
|
|
|
|
/* vertical overlapped.
|
|
* if left-up right-up left-down right-down, horizontal is faster than vertical than use horizonatl mode. */
|
|
if ((dst_rc.top != src_rc.top) && (RECTH(intersect) <= RECTW(intersect))) {
|
|
h = RECTH(intersect);
|
|
H = RECTH(src_rc);
|
|
delta = H - h;
|
|
|
|
/* down or left-down or right-down overlapped, separate into per not-Intersect rect to blit,
|
|
* from bottom to up */
|
|
if (dst_rc.top > src_rc.top) {
|
|
for (y = H; y > 0; y -= delta) {
|
|
if (y < delta) {
|
|
delta = y;
|
|
}
|
|
src1.x = src_rc.left;
|
|
src1.y = src_rc.top + y - delta;
|
|
|
|
dst1.x = dst_rc.left;
|
|
dst1.y = dst_rc.top + y - delta;
|
|
|
|
src1.w = dst1.w = srcrect->w;
|
|
src1.h = dst1.h = delta;
|
|
|
|
ret |= real_blit(src, &src1, dst, &dst1);
|
|
}
|
|
}
|
|
/* up or left-up or right-up overlapped, just the same down except from up to bottom */
|
|
else {
|
|
for (y = 0; y < H; y += delta) {
|
|
if (y + delta > H) {
|
|
delta = H - y;
|
|
}
|
|
src1.x = src_rc.left;
|
|
src1.y = src_rc.top + y;
|
|
|
|
dst1.x = dst_rc.left;
|
|
dst1.y = dst_rc.top + y;
|
|
|
|
src1.w = dst1.w = srcrect->w;
|
|
src1.h = dst1.h = delta;
|
|
|
|
ret |= real_blit(src, &src1, dst, &dst1);
|
|
}
|
|
}
|
|
}
|
|
/* horizontal overlapped */
|
|
else {
|
|
w = RECTW(intersect);
|
|
W = RECTW(src_rc);
|
|
delta = W - w;
|
|
|
|
/* horizontal right overlapped, separate into per not-Intersect rect to blit,
|
|
* from right to left */
|
|
if (dst_rc.left > src_rc.left) {
|
|
for (x = W; x > 0; x -= delta) {
|
|
if (x < delta) {
|
|
delta = x;
|
|
}
|
|
src1.x = src_rc.left + x - delta;
|
|
src1.y = src_rc.top;
|
|
|
|
dst1.x = dst_rc.left + x - delta;
|
|
dst1.y = dst_rc.top;
|
|
|
|
src1.w = dst1.w = delta;
|
|
src1.h = dst1.h = srcrect->h;
|
|
|
|
ret |= real_blit(src, &src1, dst, &dst1);
|
|
}
|
|
}
|
|
/* horizontal left overlapped. just the same right except from left to right.
|
|
* this just for optimization overlapped blit speed. */
|
|
else {
|
|
for (x = 0; x < W; x += delta) {
|
|
if (x + delta > W) {
|
|
delta = W - x;
|
|
}
|
|
src1.x = src_rc.left + x;
|
|
src1.y = src_rc.top;
|
|
|
|
dst1.x = dst_rc.left + x;
|
|
dst1.y = dst_rc.top;
|
|
|
|
src1.w = dst1.w = delta;
|
|
src1.h = dst1.h = srcrect->h;
|
|
|
|
ret |= real_blit(src, &src1, dst, &dst1);
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Set up a blit between two surfaces -- split into three parts:
|
|
* The upper part, GAL_UpperBlit(), performs clipping and rectangle
|
|
* verification. The lower part is a pointer to a low level
|
|
* accelerated blitting function.
|
|
*
|
|
* These parts are separated out and each used internally by this
|
|
* library in the optimimum places. They are exported so that if
|
|
* you know exactly what you are doing, you can optimize your code
|
|
* by calling the one(s) you need.
|
|
*/
|
|
int GAL_LowerBlit (GAL_Surface *src, GAL_Rect *srcrect,
|
|
GAL_Surface *dst, GAL_Rect *dstrect)
|
|
{
|
|
GAL_blit do_blit;
|
|
int ret;
|
|
|
|
/* Check to make sure the blit mapping is valid */
|
|
if ( (src->map->dst != dst) ||
|
|
(src->map->dst->format_version != src->map->format_version) ) {
|
|
if ( GAL_MapSurface(src, dst) < 0 ) {
|
|
return(-1);
|
|
}
|
|
}
|
|
|
|
/* Figure out which blitter to use */
|
|
if ( (src->flags & GAL_HWACCEL) == GAL_HWACCEL ) {
|
|
do_blit = src->map->hw_blit;
|
|
} else {
|
|
do_blit = src->map->sw_blit;
|
|
}
|
|
|
|
#ifdef _MGGAL_S3C6410
|
|
{
|
|
extern int s3c6410_size_table[48];
|
|
int H = src->h / 10;
|
|
if (H >= sizeof(s3c6410_size_table)/sizeof(s3c6410_size_table[0])) {
|
|
H = sizeof(s3c6410_size_table)/sizeof(s3c6410_size_table[0]) - 1;
|
|
}
|
|
if (src->w/10 < s3c6410_size_table[H]) {
|
|
do_blit = src->map->sw_blit;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef MG_CONFIG_USE_OWN_OVERLAPPED_BITBLIT
|
|
ret = own_overlapped_bitblit(do_blit, src, srcrect, dst, dstrect);
|
|
#else
|
|
ret = do_blit(src, srcrect, dst, dstrect);
|
|
#endif
|
|
|
|
#if 0
|
|
{
|
|
static int n_sw=0, n_hw=0;
|
|
if ((src->flags & GAL_HWACCEL) == GAL_HWACCEL)
|
|
{
|
|
n_hw ++;
|
|
}
|
|
else
|
|
{
|
|
n_sw ++;
|
|
}
|
|
printf("[%06u] hw/blit=%d/%d %c size=%dX%d src=(%d %d),%p dst=(%d %d),%p\n",
|
|
times(NULL) % 1000000,
|
|
n_hw, n_hw+n_sw,
|
|
do_blit == src->map->sw_blit ? 'S':'H',
|
|
srcrect->w, srcrect->h,
|
|
srcrect->x, srcrect->y, src,
|
|
dstrect->x, dstrect->y, dst
|
|
);
|
|
}
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
int GAL_UpperBlit (GAL_Surface *src, GAL_Rect *srcrect,
|
|
GAL_Surface *dst, GAL_Rect *dstrect)
|
|
{
|
|
GAL_Rect fulldst;
|
|
int srcx, srcy, w, h;
|
|
|
|
if ( ! src || ! dst ) {
|
|
GAL_SetError("NEWGAL: GAL_UpperBlit: passed a NULL surface.\n");
|
|
return(-1);
|
|
}
|
|
|
|
/* If the destination rectangle is NULL, use the entire dest surface */
|
|
if ( dstrect == NULL ) {
|
|
fulldst.x = fulldst.y = 0;
|
|
dstrect = &fulldst;
|
|
}
|
|
|
|
/* clip the source rectangle to the source surface */
|
|
if(srcrect) {
|
|
int maxw, maxh;
|
|
|
|
srcx = srcrect->x;
|
|
w = srcrect->w;
|
|
if(srcx < 0) {
|
|
w += srcx;
|
|
dstrect->x -= srcx;
|
|
srcx = 0;
|
|
}
|
|
maxw = src->w - srcx;
|
|
if(maxw < w)
|
|
w = maxw;
|
|
|
|
srcy = srcrect->y;
|
|
h = srcrect->h;
|
|
if(srcy < 0) {
|
|
h += srcy;
|
|
dstrect->y -= srcy;
|
|
srcy = 0;
|
|
}
|
|
maxh = src->h - srcy;
|
|
if(maxh < h)
|
|
h = maxh;
|
|
|
|
} else {
|
|
srcx = srcy = 0;
|
|
w = src->w;
|
|
h = src->h;
|
|
}
|
|
|
|
/* clip the destination rectangle against the clip rectangle */
|
|
{
|
|
GAL_Rect *clip = &dst->clip_rect;
|
|
int dx, dy;
|
|
|
|
dx = clip->x - dstrect->x;
|
|
if(dx > 0) {
|
|
w -= dx;
|
|
dstrect->x += dx;
|
|
srcx += dx;
|
|
}
|
|
dx = dstrect->x + w - clip->x - clip->w;
|
|
if(dx > 0)
|
|
w -= dx;
|
|
|
|
dy = clip->y - dstrect->y;
|
|
if(dy > 0) {
|
|
h -= dy;
|
|
dstrect->y += dy;
|
|
srcy += dy;
|
|
}
|
|
dy = dstrect->y + h - clip->y - clip->h;
|
|
if(dy > 0)
|
|
h -= dy;
|
|
}
|
|
|
|
if(w > 0 && h > 0) {
|
|
GAL_Rect sr;
|
|
sr.x = srcx;
|
|
sr.y = srcy;
|
|
sr.w = dstrect->w = w;
|
|
sr.h = dstrect->h = h;
|
|
return GAL_LowerBlit(src, &sr, dst, dstrect);
|
|
}
|
|
dstrect->w = dstrect->h = 0;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* This function performs a fast fill of the given rectangle with 'color'
|
|
*/
|
|
int GAL_FillRect(GAL_Surface *dst, const GAL_Rect *dstrect, Uint32 color)
|
|
{
|
|
GAL_VideoDevice *video = dst->video;
|
|
GAL_VideoDevice *this = dst->video;
|
|
int x, y;
|
|
Uint8 *row;
|
|
GAL_Rect my_dstrect;
|
|
|
|
if (!video)
|
|
{
|
|
video = current_video;
|
|
this = current_video;
|
|
}
|
|
|
|
/* If 'dstrect' == NULL, then fill the whole surface */
|
|
if ( dstrect ) {
|
|
/* Perform clipping */
|
|
if ( !GAL_IntersectRect(dstrect, &dst->clip_rect, &my_dstrect) ) {
|
|
return(0);
|
|
}
|
|
} else {
|
|
my_dstrect = dst->clip_rect;
|
|
}
|
|
|
|
/* Check for hardware acceleration */
|
|
if ( ((dst->flags & GAL_HWSURFACE) == GAL_HWSURFACE) &&
|
|
video->info.blit_fill ) {
|
|
return(video->FillHWRect(this, dst, &my_dstrect, color));
|
|
}
|
|
|
|
row = (Uint8 *)dst->pixels+my_dstrect.y*dst->pitch+
|
|
my_dstrect.x*dst->format->BytesPerPixel;
|
|
if ( dst->format->palette || (color == 0) ) {
|
|
x = my_dstrect.w*dst->format->BytesPerPixel;
|
|
if ( !color && !((long)row&3) && !(x&3) && !(dst->pitch&3) ) {
|
|
int n = x >> 2;
|
|
for ( y=my_dstrect.h; y; --y ) {
|
|
GAL_memset4(row, 0, n);
|
|
row += dst->pitch;
|
|
}
|
|
} else {
|
|
#if 0
|
|
/*
|
|
* memset() on PPC (both glibc and codewarrior) uses
|
|
* the dcbz (Data Cache Block Zero) instruction, which
|
|
* causes an alignment exception if the destination is
|
|
* uncachable, so only use it on software surfaces
|
|
*/
|
|
if((dst->flags & GAL_HWSURFACE) == GAL_HWSURFACE) {
|
|
if(my_dstrect.w >= 8) {
|
|
/*
|
|
* 64-bit stores are probably most
|
|
* efficient to uncached video memory
|
|
*/
|
|
double fill;
|
|
memset(&fill, color, (sizeof fill));
|
|
for(y = my_dstrect.h; y; y--) {
|
|
Uint8 *d = row;
|
|
unsigned n = x;
|
|
unsigned nn;
|
|
Uint8 c = color;
|
|
double f = fill;
|
|
while((unsigned long)d
|
|
& (sizeof(double) - 1)) {
|
|
*d++ = c;
|
|
n--;
|
|
}
|
|
nn = n / (sizeof(double) * 4);
|
|
while(nn) {
|
|
((double *)d)[0] = f;
|
|
((double *)d)[1] = f;
|
|
((double *)d)[2] = f;
|
|
((double *)d)[3] = f;
|
|
d += 4*sizeof(double);
|
|
nn--;
|
|
}
|
|
n &= ~(sizeof(double) * 4 - 1);
|
|
nn = n / sizeof(double);
|
|
while(nn) {
|
|
*(double *)d = f;
|
|
d += sizeof(double);
|
|
nn--;
|
|
}
|
|
n &= ~(sizeof(double) - 1);
|
|
while(n) {
|
|
*d++ = c;
|
|
n--;
|
|
}
|
|
row += dst->pitch;
|
|
}
|
|
} else {
|
|
/* narrow boxes */
|
|
for(y = my_dstrect.h; y; y--) {
|
|
Uint8 *d = row;
|
|
Uint8 c = color;
|
|
int n = x;
|
|
while(n) {
|
|
*d++ = c;
|
|
n--;
|
|
}
|
|
row += dst->pitch;
|
|
}
|
|
}
|
|
} else
|
|
#endif /* __powerpc__ */
|
|
{
|
|
for(y = my_dstrect.h; y; y--) {
|
|
memset(row, color, x);
|
|
row += dst->pitch;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
switch (dst->format->BytesPerPixel) {
|
|
case 2:
|
|
for ( y=my_dstrect.h; y; --y ) {
|
|
Uint16 *pixels = (Uint16 *)row;
|
|
Uint16 c = color;
|
|
Uint32 cc = (Uint32)c << 16 | c;
|
|
int n = my_dstrect.w;
|
|
if((unsigned long)pixels & 3) {
|
|
*pixels++ = c;
|
|
n--;
|
|
}
|
|
if(n >> 1)
|
|
GAL_memset4(pixels, cc, n >> 1);
|
|
if(n & 1)
|
|
pixels[n - 1] = c;
|
|
row += dst->pitch;
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
if(GAL_BYTEORDER == GAL_BIG_ENDIAN)
|
|
color <<= 8;
|
|
for ( y=my_dstrect.h; y; --y ) {
|
|
Uint8 *pixels = row;
|
|
for ( x=my_dstrect.w; x; --x ) {
|
|
memcpy(pixels, &color, 3);
|
|
pixels += 3;
|
|
}
|
|
row += dst->pitch;
|
|
}
|
|
break;
|
|
|
|
case 4:
|
|
for(y = my_dstrect.h; y; --y) {
|
|
GAL_memset4(row, color, my_dstrect.w);
|
|
row += dst->pitch;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* We're done! */
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* Calculate the pad-aligned box sizew in a surface
|
|
*/
|
|
Uint32 GAL_GetBoxSize (GAL_Surface *surface, Uint32 w, Uint32 h, Uint32* pitch_p)
|
|
{
|
|
Uint32 pitch;
|
|
|
|
/* Box should be 4-byte aligned for speed */
|
|
pitch = w * surface->format->BytesPerPixel;
|
|
switch (surface->format->BitsPerPixel) {
|
|
case 1:
|
|
pitch = (pitch+7)/8;
|
|
break;
|
|
case 4:
|
|
pitch = (pitch+1)/2;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
pitch = (pitch + 3) & ~3; /* 4-byte aligning */
|
|
|
|
if (pitch_p)
|
|
*pitch_p = pitch;
|
|
|
|
return pitch * h;
|
|
}
|
|
|
|
/*
|
|
* This function performs a fast HW -> SW box copying.
|
|
*/
|
|
int GAL_GetBox (GAL_Surface *src, const GAL_Rect *rect, BITMAP* box)
|
|
{
|
|
Sint32 dst_x, dst_y, off_x, off_y, y;
|
|
Uint8 *srcrow, *dstrow;
|
|
Uint32 linelen;
|
|
GAL_Rect srcrect = {0, 0, 0, 0};
|
|
srcrect.w = src->w;
|
|
srcrect.h = src->h;
|
|
|
|
if (rect->h <= 0 || rect->w <= 0)
|
|
return -1;
|
|
|
|
box->bmType = BMP_TYPE_NORMAL;
|
|
box->bmBitsPerPixel = src->format->BitsPerPixel;
|
|
box->bmBytesPerPixel = src->format->BytesPerPixel;
|
|
box->bmWidth = rect->w;
|
|
box->bmHeight = rect->h;
|
|
box->bmAlphaMask = NULL;
|
|
box->bmAlphaPitch = 0;
|
|
|
|
dst_x = rect->x;
|
|
dst_y = rect->y;
|
|
|
|
/* Perform clipping */
|
|
if (!GAL_IntersectRect (rect, &srcrect, &srcrect)) {
|
|
return 0;
|
|
}
|
|
|
|
off_x = srcrect.x - dst_x;
|
|
off_y = srcrect.y - dst_y;
|
|
|
|
if ((box->bmPitch == 0) || (box->bmBits == NULL)) {
|
|
box->bmBits = malloc (GAL_GetBoxSize (src, box->bmWidth, box->bmHeight, &box->bmPitch));
|
|
if (box->bmBits == NULL) {
|
|
GAL_OutOfMemory ();
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
linelen = srcrect.w * box->bmBytesPerPixel;
|
|
srcrow = (Uint8 *)src->pixels + srcrect.y * src->pitch +
|
|
srcrect.x * src->format->BytesPerPixel;
|
|
dstrow = box->bmBits + off_y * box->bmPitch +
|
|
off_x * box->bmBytesPerPixel;
|
|
|
|
switch (box->bmBytesPerPixel) {
|
|
case 1:
|
|
if (((DWORD)srcrow & 3) || ((DWORD)dstrow & 3)
|
|
|| (linelen & 3) || (box->bmPitch & 3) || (src->pitch & 3))
|
|
goto slow_copy;
|
|
else {
|
|
int n = linelen >> 2;
|
|
for (y = srcrect.h; y; --y) {
|
|
GAL_memcpy4 (dstrow, srcrow, n);
|
|
srcrow += src->pitch;
|
|
dstrow += box->bmPitch;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
if ((((DWORD)srcrow & 3) != ((DWORD)dstrow & 3))
|
|
|| (box->bmPitch & 3) || (src->pitch & 3))
|
|
goto slow_copy;
|
|
|
|
for (y = srcrect.h; y; --y) {
|
|
Uint16 *dstpixels = (Uint16 *)dstrow;
|
|
Uint16 *srcpixels = (Uint16 *)srcrow;
|
|
int n = srcrect.w;
|
|
if ((DWORD)dstpixels & 3) {
|
|
*dstpixels = *srcpixels;
|
|
dstpixels++;
|
|
srcpixels++;
|
|
n--;
|
|
}
|
|
|
|
if (n >> 1)
|
|
GAL_memcpy4 (dstpixels, srcpixels, n >> 1);
|
|
if (n & 1)
|
|
dstpixels [n - 1] = srcpixels [n - 1];
|
|
|
|
srcrow += src->pitch;
|
|
dstrow += box->bmPitch;
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
goto slow_copy;
|
|
|
|
case 4:
|
|
for (y = srcrect.h; y; --y) {
|
|
GAL_memcpy4 (dstrow, srcrow, srcrect.w);
|
|
srcrow += src->pitch;
|
|
dstrow += box->bmPitch;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return(0);
|
|
|
|
slow_copy:
|
|
for (y = srcrect.h; y; --y) {
|
|
GAL_memcpy (dstrow, srcrow, linelen);
|
|
srcrow += src->pitch;
|
|
dstrow += box->bmPitch;
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* This function performs a fast SW -> HW box copying.
|
|
*/
|
|
|
|
// helpers
|
|
|
|
#include "blit.h"
|
|
|
|
/* aligned 32-bit bound for alpha mask array index */
|
|
#define GET_ALPHA_MASK_INDEX(srcrow, box, pitch, row) \
|
|
do { \
|
|
int x = (srcrow - (box)->bmBits) % (box)->bmPitch; \
|
|
int y = (srcrow - (box)->bmBits) / (box)->bmPitch; \
|
|
(pitch) = (box)->bmAlphaPitch; \
|
|
(row) = (y * (pitch)) + (x / (box)->bmBytesPerPixel); \
|
|
} while(0)
|
|
|
|
static int _PutBoxAlphaChannelEx (GAL_Surface* dst, BYTE* dstrow, BYTE* srcrow, Uint32 w, Uint32 h, BITMAP* box)
|
|
{
|
|
BYTE* dstpixels = dstrow;
|
|
BYTE* srcpixels = srcrow;
|
|
GAL_PixelFormat *dstfmt = dst->format;
|
|
int bpp = dstfmt->BytesPerPixel;
|
|
unsigned alpha = box->bmAlpha;
|
|
|
|
|
|
if (bpp == 1)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
if (!(box->bmType & BMP_TYPE_ALPHA_MASK)) {
|
|
while ( h-- ) {
|
|
dstpixels = dstrow;
|
|
srcpixels = srcrow;
|
|
DUFFS_LOOP(
|
|
{
|
|
Uint32 pixel;
|
|
unsigned sR;
|
|
unsigned sG;
|
|
unsigned sB;
|
|
unsigned sA;
|
|
unsigned dR;
|
|
unsigned dG;
|
|
unsigned dB;
|
|
DISEMBLE_RGBA (srcpixels, bpp, dstfmt, pixel, sR, sG, sB, sA);
|
|
DISEMBLE_RGB (dstpixels, bpp, dstfmt, pixel, dR, dG, dB);
|
|
ALPHA_BLEND (sR, sG, sB, (alpha*sA)/255, dR, dG, dB);
|
|
ASSEMBLE_RGBA (dstpixels, bpp, dstfmt, dR, dG, dB, alpha);
|
|
dstpixels += bpp;
|
|
srcpixels += bpp;
|
|
},
|
|
w);
|
|
srcrow += box->bmPitch;
|
|
dstrow += dst->pitch;
|
|
}
|
|
} else {
|
|
/* for aligned 32-bits bound */
|
|
int alpha_mask_index;
|
|
int alpha_mask_pitch;
|
|
int alpha_mask_row;
|
|
GET_ALPHA_MASK_INDEX (srcrow, box, alpha_mask_pitch, alpha_mask_row);
|
|
|
|
while ( h-- ) {
|
|
dstpixels = dstrow;
|
|
srcpixels = srcrow;
|
|
alpha_mask_index = alpha_mask_row;
|
|
DUFFS_LOOP(
|
|
{
|
|
Uint32 pixel;
|
|
unsigned sR;
|
|
unsigned sG;
|
|
unsigned sB;
|
|
unsigned sA;
|
|
unsigned dR;
|
|
unsigned dG;
|
|
unsigned dB;
|
|
DISEMBLE_RGB (srcpixels, bpp, dstfmt, pixel, sR, sG, sB);
|
|
DISEMBLE_RGB (dstpixels, bpp, dstfmt, pixel, dR, dG, dB);
|
|
sA = box->bmAlphaMask[alpha_mask_index];
|
|
ALPHA_BLEND (sR, sG, sB, (alpha*sA)/255, dR, dG, dB);
|
|
ASSEMBLE_RGBA (dstpixels, bpp, dstfmt, dR, dG, dB, alpha);
|
|
dstpixels += bpp;
|
|
srcpixels += bpp;
|
|
alpha_mask_index++;
|
|
},
|
|
w);
|
|
srcrow += box->bmPitch;
|
|
dstrow += dst->pitch;
|
|
alpha_mask_row += alpha_mask_pitch;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int _PutBoxAlpha (GAL_Surface* dst, BYTE* dstrow, BYTE* srcrow, Uint32 w, Uint32 h, BITMAP* box)
|
|
{
|
|
BYTE* dstpixels = dstrow;
|
|
BYTE* srcpixels = srcrow;
|
|
GAL_PixelFormat *dstfmt = dst->format;
|
|
int bpp = dstfmt->BytesPerPixel;
|
|
unsigned alpha = dstfmt->Amask ? GAL_ALPHA_OPAQUE : 0;
|
|
|
|
|
|
if (bpp == 1)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
if (!(box->bmType & BMP_TYPE_ALPHA_MASK)) {
|
|
if (dstfmt->Amask == 0xff000000 && dstfmt->BitsPerPixel == 32)
|
|
{
|
|
while(h--) {
|
|
Uint32 *srcp = (Uint32 *)srcrow;
|
|
Uint32 *dstp = (Uint32 *)dstrow;
|
|
unsigned char alpha;
|
|
DUFFS_LOOP4(
|
|
{
|
|
Uint32 s;
|
|
Uint32 d;
|
|
Uint32 s1;
|
|
Uint32 d1;
|
|
Uint32 sA;
|
|
Uint32 dA;
|
|
s = *srcp;
|
|
d = *dstp;
|
|
sA = s >> 24;
|
|
dA = d >> 24;
|
|
dA = sA + dA - ((sA * dA) >> 8);
|
|
if(dA > 255) dA = 255; //alpha may be greater than 255
|
|
alpha = s >> 24;
|
|
s1 = s & 0xff00ff;
|
|
d1 = d & 0xff00ff;
|
|
d1 = (d1 + (((s1 - d1) * alpha) >> 8))
|
|
& 0xff00ff;
|
|
s &= 0xff00;
|
|
d &= 0xff00;
|
|
d = (d + (((s - d) * alpha) >> 8)) & 0xff00;
|
|
*dstp = d1 | d | (dA << 24);
|
|
++srcp;
|
|
++dstp;
|
|
}, w);
|
|
srcrow += box->bmPitch;
|
|
dstrow += dst->pitch;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while ( h-- ) {
|
|
dstpixels = dstrow;
|
|
srcpixels = srcrow;
|
|
DUFFS_LOOP(
|
|
{
|
|
Uint32 pixel;
|
|
unsigned sR = 0;
|
|
unsigned sG = 0;
|
|
unsigned sB = 0;
|
|
unsigned sA = 0;
|
|
unsigned dR = 0;
|
|
unsigned dG = 0;
|
|
unsigned dB = 0;
|
|
unsigned dA = 0;
|
|
DISEMBLE_RGBA (srcpixels, bpp, dstfmt, pixel, sR, sG, sB, sA);
|
|
DISEMBLE_RGBA (dstpixels, bpp, dstfmt, pixel, dR, dG, dB, dA);
|
|
ALPHA_BLEND (sR, sG, sB, sA, dR, dG, dB);
|
|
dA = sA + dA - ((sA * dA) >> 8);
|
|
if(dA > 255) dA = 255; //alpha may be greater than 255
|
|
ASSEMBLE_RGBA (dstpixels, bpp, dstfmt, dR, dG, dB, dA);
|
|
dstpixels += bpp;
|
|
srcpixels += bpp;
|
|
},
|
|
w);
|
|
srcrow += box->bmPitch;
|
|
dstrow += dst->pitch;
|
|
}
|
|
}
|
|
} else {
|
|
/* for aligned 32-bits bound */
|
|
int alpha_mask_index;
|
|
int alpha_mask_pitch;
|
|
int alpha_mask_row;
|
|
GET_ALPHA_MASK_INDEX (srcrow, box, alpha_mask_pitch, alpha_mask_row);
|
|
|
|
while ( h-- ) {
|
|
dstpixels = dstrow;
|
|
srcpixels = srcrow;
|
|
alpha_mask_index = alpha_mask_row;
|
|
DUFFS_LOOP(
|
|
{
|
|
Uint32 pixel;
|
|
unsigned sR;
|
|
unsigned sG;
|
|
unsigned sB;
|
|
unsigned sA;
|
|
unsigned dR;
|
|
unsigned dG;
|
|
unsigned dB;
|
|
DISEMBLE_RGB (srcpixels, bpp, dstfmt, pixel, sR, sG, sB);
|
|
DISEMBLE_RGB (dstpixels, bpp, dstfmt, pixel, dR, dG, dB);
|
|
sA = box->bmAlphaMask[alpha_mask_index];
|
|
ALPHA_BLEND (sR, sG, sB, sA, dR, dG, dB);
|
|
ASSEMBLE_RGBA (dstpixels, bpp, dstfmt, dR, dG, dB, alpha);
|
|
dstpixels += bpp;
|
|
srcpixels += bpp;
|
|
alpha_mask_index++;
|
|
},
|
|
w);
|
|
srcrow += box->bmPitch;
|
|
dstrow += dst->pitch;
|
|
alpha_mask_row += alpha_mask_pitch;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int _PutBoxAlphaChannel (GAL_Surface* dst, BYTE* dstrow, BYTE* srcrow, Uint32 w, Uint32 h, BITMAP* box)
|
|
{
|
|
BYTE* dstpixels = dstrow;
|
|
BYTE* srcpixels = srcrow;
|
|
GAL_PixelFormat *dstfmt = dst->format;
|
|
int bpp = dstfmt->BytesPerPixel;
|
|
unsigned alpha = box->bmAlpha;
|
|
|
|
if (bpp == 1)
|
|
return -1;
|
|
|
|
while ( h-- ) {
|
|
dstpixels = dstrow;
|
|
srcpixels = srcrow;
|
|
DUFFS_LOOP(
|
|
{
|
|
Uint32 pixel;
|
|
unsigned sR;
|
|
unsigned sG;
|
|
unsigned sB;
|
|
unsigned dR;
|
|
unsigned dG;
|
|
unsigned dB;
|
|
DISEMBLE_RGB (srcpixels, bpp, dstfmt, pixel, sR, sG, sB);
|
|
DISEMBLE_RGB (dstpixels, bpp, dstfmt, pixel, dR, dG, dB);
|
|
ALPHA_BLEND (sR, sG, sB, alpha, dR, dG, dB);
|
|
ASSEMBLE_RGBA (dstpixels, bpp, dstfmt, dR, dG, dB, alpha);
|
|
dstpixels += bpp;
|
|
srcpixels += bpp;
|
|
},
|
|
w);
|
|
srcrow += box->bmPitch;
|
|
dstrow += dst->pitch;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int _PutBoxKeyAlphaChannelEx (GAL_Surface* dst, BYTE* dstrow, BYTE* srcrow, Uint32 w, Uint32 h, BITMAP* box)
|
|
{
|
|
BYTE* dstpixels = dstrow;
|
|
BYTE* srcpixels = srcrow;
|
|
Uint32 ckey = box->bmColorKey;
|
|
GAL_PixelFormat *dstfmt = dst->format;
|
|
int bpp = dstfmt->BytesPerPixel;
|
|
Uint32 rgbmask = ~dstfmt->Amask;
|
|
unsigned alpha = box->bmAlpha;
|
|
|
|
|
|
if (bpp == 1)
|
|
return -1;
|
|
|
|
if (!(box->bmType & BMP_TYPE_ALPHA_MASK)) {
|
|
while ( h-- ) {
|
|
dstpixels = dstrow;
|
|
srcpixels = srcrow;
|
|
DUFFS_LOOP(
|
|
{
|
|
Uint32 pixel;
|
|
unsigned sR;
|
|
unsigned sG;
|
|
unsigned sB;
|
|
unsigned sA;
|
|
unsigned dR;
|
|
unsigned dG;
|
|
unsigned dB;
|
|
RETRIEVE_RGB_PIXEL (srcpixels, bpp, pixel);
|
|
if ((pixel & rgbmask) != ckey ) {
|
|
RGBA_FROM_PIXEL (pixel, dstfmt, sR, sG, sB, sA);
|
|
DISEMBLE_RGB (dstpixels, bpp, dstfmt, pixel, dR, dG, dB);
|
|
ALPHA_BLEND (sR, sG, sB, (alpha*sA)/255, dR, dG, dB);
|
|
ASSEMBLE_RGBA (dstpixels, bpp, dstfmt, dR, dG, dB, alpha);
|
|
}
|
|
dstpixels += bpp;
|
|
srcpixels += bpp;
|
|
},
|
|
w);
|
|
srcrow += box->bmPitch;
|
|
dstrow += dst->pitch;
|
|
}
|
|
} else {
|
|
/* for aligned 32-bits bound */
|
|
int alpha_mask_index;
|
|
int alpha_mask_pitch;
|
|
int alpha_mask_row;
|
|
GET_ALPHA_MASK_INDEX (srcrow, box, alpha_mask_pitch, alpha_mask_row);
|
|
|
|
while ( h-- ) {
|
|
dstpixels = dstrow;
|
|
srcpixels = srcrow;
|
|
alpha_mask_index = alpha_mask_row;
|
|
DUFFS_LOOP(
|
|
{
|
|
Uint32 pixel;
|
|
unsigned sR;
|
|
unsigned sG;
|
|
unsigned sB;
|
|
unsigned sA;
|
|
unsigned dR;
|
|
unsigned dG;
|
|
unsigned dB;
|
|
RETRIEVE_RGB_PIXEL (srcpixels, bpp, pixel);
|
|
if ((pixel & rgbmask) != ckey ) {
|
|
RGB_FROM_PIXEL (pixel, dstfmt, sR, sG, sB);
|
|
DISEMBLE_RGB (dstpixels, bpp, dstfmt, pixel, dR, dG, dB);
|
|
sA = box->bmAlphaMask[alpha_mask_index];
|
|
ALPHA_BLEND (sR, sG, sB, (alpha*sA)/255, dR, dG, dB);
|
|
ASSEMBLE_RGBA (dstpixels, bpp, dstfmt, dR, dG, dB, alpha);
|
|
}
|
|
dstpixels += bpp;
|
|
srcpixels += bpp;
|
|
alpha_mask_index++;
|
|
},
|
|
w);
|
|
srcrow += box->bmPitch;
|
|
dstrow += dst->pitch;
|
|
alpha_mask_row += alpha_mask_pitch;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int _PutBoxKeyAlpha (GAL_Surface* dst, BYTE* dstrow, BYTE* srcrow, Uint32 w, Uint32 h, BITMAP* box)
|
|
{
|
|
BYTE* dstpixels = dstrow;
|
|
BYTE* srcpixels = srcrow;
|
|
Uint32 ckey = box->bmColorKey;
|
|
GAL_PixelFormat *dstfmt = dst->format;
|
|
int bpp = dstfmt->BytesPerPixel;
|
|
Uint32 rgbmask = ~dstfmt->Amask;
|
|
unsigned alpha = dstfmt->Amask ? GAL_ALPHA_OPAQUE : 0;
|
|
|
|
|
|
if (bpp == 1)
|
|
return -1;
|
|
|
|
if (!(box->bmType & BMP_TYPE_ALPHA_MASK)) {
|
|
while ( h-- ) {
|
|
dstpixels = dstrow;
|
|
srcpixels = srcrow;
|
|
DUFFS_LOOP(
|
|
{
|
|
Uint32 pixel;
|
|
unsigned sR;
|
|
unsigned sG;
|
|
unsigned sB;
|
|
unsigned sA;
|
|
unsigned dR;
|
|
unsigned dG;
|
|
unsigned dB;
|
|
RETRIEVE_RGB_PIXEL (srcpixels, bpp, pixel);
|
|
if ((pixel & rgbmask) != ckey ) {
|
|
RGBA_FROM_PIXEL (pixel, dstfmt, sR, sG, sB, sA);
|
|
DISEMBLE_RGB (dstpixels, bpp, dstfmt, pixel, dR, dG, dB);
|
|
ALPHA_BLEND (sR, sG, sB, sA, dR, dG, dB);
|
|
ASSEMBLE_RGBA (dstpixels, bpp, dstfmt, dR, dG, dB, alpha);
|
|
}
|
|
dstpixels += bpp;
|
|
srcpixels += bpp;
|
|
},
|
|
w);
|
|
srcrow += box->bmPitch;
|
|
dstrow += dst->pitch;
|
|
}
|
|
} else {
|
|
/* for aligned 32-bits bound */
|
|
int alpha_mask_index;
|
|
int alpha_mask_pitch;
|
|
int alpha_mask_row;
|
|
GET_ALPHA_MASK_INDEX (srcrow, box, alpha_mask_pitch, alpha_mask_row);
|
|
|
|
while ( h-- ) {
|
|
dstpixels = dstrow;
|
|
srcpixels = srcrow;
|
|
alpha_mask_index = alpha_mask_row;
|
|
DUFFS_LOOP(
|
|
{
|
|
Uint32 pixel;
|
|
unsigned sR;
|
|
unsigned sG;
|
|
unsigned sB;
|
|
unsigned sA;
|
|
unsigned dR;
|
|
unsigned dG;
|
|
unsigned dB;
|
|
RETRIEVE_RGB_PIXEL (srcpixels, bpp, pixel);
|
|
if ((pixel & rgbmask) != ckey ) {
|
|
RGB_FROM_PIXEL (pixel, dstfmt, sR, sG, sB);
|
|
DISEMBLE_RGB (dstpixels, bpp, dstfmt, pixel, dR, dG, dB);
|
|
sA = box->bmAlphaMask[alpha_mask_index];
|
|
ALPHA_BLEND (sR, sG, sB, sA, dR, dG, dB);
|
|
ASSEMBLE_RGBA (dstpixels, bpp, dstfmt, dR, dG, dB, alpha);
|
|
}
|
|
dstpixels += bpp;
|
|
srcpixels += bpp;
|
|
alpha_mask_index++;
|
|
},
|
|
w);
|
|
srcrow += box->bmPitch;
|
|
dstrow += dst->pitch;
|
|
alpha_mask_row += alpha_mask_pitch;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int _PutBoxKey (GAL_Surface* dst, BYTE* dstrow, BYTE* srcrow, Uint32 w, Uint32 h, BITMAP* box)
|
|
{
|
|
BYTE* dstpixels = dstrow;
|
|
BYTE* srcpixels = srcrow;
|
|
Uint32 ckey = box->bmColorKey;
|
|
GAL_PixelFormat *dstfmt = dst->format;
|
|
int bpp = dstfmt->BytesPerPixel;
|
|
unsigned alpha = dstfmt->Amask ? GAL_ALPHA_OPAQUE : 0;
|
|
|
|
if (bpp == 1) {
|
|
while (h--) {
|
|
unsigned int i;
|
|
dstpixels = dstrow;
|
|
srcpixels = srcrow;
|
|
for (i = 0; i < w; i++) {
|
|
if (*srcpixels != ckey)
|
|
*dstpixels = *srcpixels;
|
|
dstpixels += bpp;
|
|
srcpixels += bpp;
|
|
}
|
|
srcrow += box->bmPitch;
|
|
dstrow += dst->pitch;
|
|
}
|
|
}
|
|
#ifndef _FOR_MONOBITMAP
|
|
else while ( h-- ) {
|
|
dstpixels = dstrow;
|
|
srcpixels = srcrow;
|
|
DUFFS_LOOP(
|
|
{
|
|
Uint32 pixel;
|
|
unsigned sR;
|
|
unsigned sG;
|
|
unsigned sB;
|
|
RETRIEVE_RGB_PIXEL (srcpixels, bpp, pixel);
|
|
if ( pixel != ckey ) {
|
|
RGB_FROM_PIXEL (pixel, dstfmt, sR, sG, sB);
|
|
ASSEMBLE_RGBA (dstpixels, bpp, dstfmt, sR, sG, sB, alpha);
|
|
}
|
|
dstpixels += bpp;
|
|
srcpixels += bpp;
|
|
},
|
|
w);
|
|
srcrow += box->bmPitch;
|
|
dstrow += dst->pitch;
|
|
}
|
|
#else
|
|
else while ( h-- ) {
|
|
dstpixels = dstrow;
|
|
srcpixels = srcrow;
|
|
DUFFS_LOOP(
|
|
{
|
|
Uint32 pixel;
|
|
unsigned sR;
|
|
unsigned sG;
|
|
unsigned sB;
|
|
RETRIEVE_RGB_PIXEL (srcpixels, bpp, pixel);
|
|
if (pixel != ckey || ( pixel == ckey && box->bmType & BMP_TYPE_MONOKEY) ) {
|
|
if (pixel == ckey)
|
|
pixel = box->bmColorRep;
|
|
RGB_FROM_PIXEL (pixel, dstfmt, sR, sG, sB);
|
|
ASSEMBLE_RGBA (dstpixels, bpp, dstfmt, sR, sG, sB, alpha);
|
|
}
|
|
dstpixels += bpp;
|
|
srcpixels += bpp;
|
|
},
|
|
w);
|
|
srcrow += box->bmPitch;
|
|
dstrow += dst->pitch;
|
|
}
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int _PutBoxKeyAlphaChannel (GAL_Surface* dst, BYTE* dstrow, BYTE* srcrow, Uint32 w, Uint32 h, BITMAP* box)
|
|
{
|
|
BYTE* dstpixels = dstrow;
|
|
BYTE* srcpixels = srcrow;
|
|
Uint32 ckey = box->bmColorKey;
|
|
GAL_PixelFormat *dstfmt = dst->format;
|
|
int bpp = dstfmt->BytesPerPixel;
|
|
unsigned alpha = box->bmAlpha;
|
|
|
|
if (bpp == 1)
|
|
return -1;
|
|
|
|
while ( h-- ) {
|
|
dstpixels = dstrow;
|
|
srcpixels = srcrow;
|
|
DUFFS_LOOP(
|
|
{
|
|
Uint32 pixel;
|
|
unsigned sR;
|
|
unsigned sG;
|
|
unsigned sB;
|
|
unsigned dR;
|
|
unsigned dG;
|
|
unsigned dB;
|
|
RETRIEVE_RGB_PIXEL (srcpixels, bpp, pixel);
|
|
if ( pixel != ckey ) {
|
|
RGB_FROM_PIXEL (pixel, dstfmt, sR, sG, sB);
|
|
DISEMBLE_RGB (dstpixels, bpp, dstfmt, pixel, dR, dG, dB);
|
|
ALPHA_BLEND (sR, sG, sB, alpha, dR, dG, dB);
|
|
ASSEMBLE_RGBA (dstpixels, bpp, dstfmt, dR, dG, dB, alpha);
|
|
}
|
|
dstpixels += bpp;
|
|
srcpixels += bpp;
|
|
},
|
|
w);
|
|
srcrow += box->bmPitch;
|
|
dstrow += dst->pitch;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int GAL_PutBox (GAL_Surface *dst, const GAL_Rect *dstrect, BITMAP* box)
|
|
{
|
|
Uint32 box_x, box_y, off_x, off_y;
|
|
int y, w, h;
|
|
Uint8 *srcrow, *dstrow;
|
|
Uint32 linelen;
|
|
GAL_Rect my_dstrect;
|
|
|
|
/* If 'dstrect' == NULL, then put to (0, 0) */
|
|
if (dstrect) {
|
|
box_x = dstrect->x;
|
|
box_y = dstrect->y;
|
|
|
|
/* Perform clipping */
|
|
if (!GAL_IntersectRect (dstrect, &dst->clip_rect, &my_dstrect)) {
|
|
return 0;
|
|
}
|
|
} else {
|
|
box_x = 0;
|
|
box_y = 0;
|
|
|
|
my_dstrect = dst->clip_rect;
|
|
}
|
|
|
|
off_x = my_dstrect.x - box_x;
|
|
off_y = my_dstrect.y - box_y;
|
|
if (off_x >= box->bmWidth || off_y >= box->bmHeight ||
|
|
box->bmBytesPerPixel != dst->format->BytesPerPixel) {
|
|
return 0;
|
|
}
|
|
|
|
dstrow = (Uint8 *)dst->pixels + my_dstrect.y * dst->pitch +
|
|
my_dstrect.x * dst->format->BytesPerPixel;
|
|
srcrow = (Uint8 *)box->bmBits + off_y * box->bmPitch +
|
|
off_x * box->bmBytesPerPixel;
|
|
w = MIN (my_dstrect.w, box->bmWidth);
|
|
h = MIN (my_dstrect.h, box->bmHeight);
|
|
linelen = w * box->bmBytesPerPixel;
|
|
|
|
/* TODO: Check for hardware acceleration here */
|
|
|
|
if (box->bmType & BMP_TYPE_ALPHA) {
|
|
if ((box->bmType & BMP_TYPE_ALPHACHANNEL) && (box->bmType & BMP_TYPE_COLORKEY)) {
|
|
return _PutBoxKeyAlphaChannelEx (dst, dstrow, srcrow, w, h, box);
|
|
}
|
|
if ((box->bmType & BMP_TYPE_ALPHACHANNEL)) {
|
|
return _PutBoxAlphaChannelEx (dst, dstrow, srcrow, w, h, box);
|
|
}
|
|
else if ((box->bmType & BMP_TYPE_ALPHA) && (box->bmType & BMP_TYPE_COLORKEY)) {
|
|
return _PutBoxKeyAlpha (dst, dstrow, srcrow, w, h, box);
|
|
}
|
|
else if (box->bmType & BMP_TYPE_ALPHA) {
|
|
return _PutBoxAlpha (dst, dstrow, srcrow, w, h, box);
|
|
}
|
|
}
|
|
else if ((box->bmType & BMP_TYPE_ALPHACHANNEL) && (box->bmType & BMP_TYPE_COLORKEY)) {
|
|
return _PutBoxKeyAlphaChannel (dst, dstrow, srcrow, w, h, box);
|
|
}
|
|
else if (box->bmType & BMP_TYPE_COLORKEY) {
|
|
return _PutBoxKey (dst, dstrow, srcrow, w, h, box);
|
|
}
|
|
else if (box->bmType & BMP_TYPE_ALPHACHANNEL) {
|
|
return _PutBoxAlphaChannel (dst, dstrow, srcrow, w, h, box);
|
|
}
|
|
|
|
|
|
switch (dst->format->BytesPerPixel) {
|
|
case 1:
|
|
if (((DWORD)srcrow & 3) || ((DWORD)dstrow & 3)
|
|
|| (linelen & 3) || (box->bmPitch & 3) || (dst->pitch & 3))
|
|
goto slow_copy;
|
|
else {
|
|
int n = linelen >> 2;
|
|
for (y = h; y; --y) {
|
|
GAL_memcpy4 (dstrow, srcrow, n);
|
|
srcrow += box->bmPitch;
|
|
dstrow += dst->pitch;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
if ((((DWORD)dstrow & 3) != ((DWORD)srcrow & 3))
|
|
|| (box->bmPitch & 3) || (dst->pitch & 3))
|
|
goto slow_copy;
|
|
|
|
for (y = h; y; --y) {
|
|
Uint16 *dstpixels = (Uint16 *)dstrow;
|
|
Uint16 *srcpixels = (Uint16 *)srcrow;
|
|
int n = w;
|
|
if ((DWORD)dstpixels & 3) {
|
|
*dstpixels = *srcpixels;
|
|
dstpixels++;
|
|
srcpixels++;
|
|
n--;
|
|
}
|
|
|
|
if (n >> 1)
|
|
GAL_memcpy4 (dstpixels, srcpixels, n >> 1);
|
|
if (n & 1)
|
|
dstpixels [n - 1] = srcpixels [n - 1];
|
|
|
|
srcrow += box->bmPitch;
|
|
dstrow += dst->pitch;
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
goto slow_copy;
|
|
|
|
case 4:
|
|
for (y = h; y; --y) {
|
|
GAL_memcpy4 (dstrow, srcrow, w);
|
|
srcrow += box->bmPitch;
|
|
dstrow += dst->pitch;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
|
|
slow_copy:
|
|
for (y = h; y; --y) {
|
|
GAL_memcpy (dstrow, srcrow, linelen);
|
|
srcrow += box->bmPitch;
|
|
dstrow += dst->pitch;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Convert a surface into the specified pixel format.
|
|
*/
|
|
GAL_Surface * GAL_ConvertSurface (GAL_Surface *surface,
|
|
GAL_PixelFormat *format, Uint32 flags)
|
|
{
|
|
GAL_Surface *convert;
|
|
Uint32 colorkey = 0;
|
|
Uint8 alpha = 0;
|
|
Uint32 surface_flags;
|
|
GAL_Rect bounds;
|
|
|
|
/* Check for empty destination palette! (results in empty image) */
|
|
if ( format->palette != NULL ) {
|
|
int i;
|
|
for ( i=0; i<format->palette->ncolors; ++i ) {
|
|
if ( (format->palette->colors[i].r != 0) ||
|
|
(format->palette->colors[i].g != 0) ||
|
|
(format->palette->colors[i].b != 0) )
|
|
break;
|
|
}
|
|
if ( i == format->palette->ncolors ) {
|
|
GAL_SetError("NEWGAL: Empty destination palette.\n");
|
|
return(NULL);
|
|
}
|
|
}
|
|
|
|
/* Create a new surface with the desired format */
|
|
convert = GAL_CreateRGBSurface(flags,
|
|
surface->w, surface->h, format->BitsPerPixel,
|
|
format->Rmask, format->Gmask, format->Bmask, format->Amask);
|
|
if ( convert == NULL ) {
|
|
return(NULL);
|
|
}
|
|
|
|
/* Copy the palette if any */
|
|
if ( format->palette && convert->format->palette ) {
|
|
memcpy(convert->format->palette->colors,
|
|
format->palette->colors,
|
|
format->palette->ncolors*sizeof(GAL_Color));
|
|
convert->format->palette->ncolors = format->palette->ncolors;
|
|
}
|
|
|
|
/* Save the original surface color key and alpha */
|
|
surface_flags = surface->flags;
|
|
if ( (surface_flags & GAL_SRCCOLORKEY) == GAL_SRCCOLORKEY ) {
|
|
/* Convert colourkeyed surfaces to RGBA if requested */
|
|
if((flags & GAL_SRCCOLORKEY) != GAL_SRCCOLORKEY
|
|
&& format->Amask) {
|
|
surface_flags &= ~GAL_SRCCOLORKEY;
|
|
} else {
|
|
colorkey = surface->format->colorkey;
|
|
GAL_SetColorKey(surface, 0, 0);
|
|
}
|
|
}
|
|
if ( (surface_flags & GAL_SRCALPHA) == GAL_SRCALPHA ) {
|
|
alpha = surface->format->alpha;
|
|
GAL_SetAlpha(surface, 0, 0);
|
|
}
|
|
|
|
/* Copy over the image data */
|
|
bounds.x = 0;
|
|
bounds.y = 0;
|
|
bounds.w = surface->w;
|
|
bounds.h = surface->h;
|
|
GAL_LowerBlit(surface, &bounds, convert, &bounds);
|
|
|
|
/* Clean up the original surface, and update converted surface */
|
|
if ( convert != NULL ) {
|
|
GAL_SetClipRect(convert, &surface->clip_rect);
|
|
}
|
|
if ( (surface_flags & GAL_SRCCOLORKEY) == GAL_SRCCOLORKEY ) {
|
|
Uint32 cflags = surface_flags&(GAL_SRCCOLORKEY|GAL_RLEACCELOK);
|
|
if ( convert != NULL ) {
|
|
Uint8 keyR, keyG, keyB;
|
|
|
|
GAL_GetRGB(colorkey,surface->format,&keyR,&keyG,&keyB);
|
|
GAL_SetColorKey(convert, cflags|(flags&GAL_RLEACCELOK),
|
|
GAL_MapRGB(convert->format, keyR, keyG, keyB));
|
|
}
|
|
GAL_SetColorKey(surface, cflags, colorkey);
|
|
}
|
|
if ( (surface_flags & GAL_SRCALPHA) == GAL_SRCALPHA ) {
|
|
Uint32 aflags = surface_flags&(GAL_SRCALPHA|GAL_RLEACCELOK);
|
|
if ( convert != NULL ) {
|
|
GAL_SetAlpha(convert, aflags|(flags&GAL_RLEACCELOK),
|
|
alpha);
|
|
}
|
|
GAL_SetAlpha(surface, aflags, alpha);
|
|
}
|
|
|
|
/* We're ready to go! */
|
|
return(convert);
|
|
}
|
|
|
|
/*
|
|
* Free a surface created by the above function.
|
|
*/
|
|
void GAL_FreeSurface (GAL_Surface *surface)
|
|
{
|
|
/* Free anything that's not NULL, and not the screen surface */
|
|
if ((surface == NULL) ||
|
|
(current_video && (surface == GAL_VideoSurface))) {
|
|
return;
|
|
}
|
|
|
|
if (--surface->refcount > 0) {
|
|
return;
|
|
}
|
|
|
|
#ifdef _MGUSE_SYNC_UPDATE
|
|
EmptyClipRgn (&surface->update_region);
|
|
#endif
|
|
|
|
if ( (surface->flags & GAL_RLEACCEL) == GAL_RLEACCEL ) {
|
|
GAL_UnRLESurface(surface, 0);
|
|
}
|
|
if ( surface->format ) {
|
|
GAL_FreeFormat(surface->format);
|
|
surface->format = NULL;
|
|
}
|
|
if ( surface->map != NULL ) {
|
|
GAL_FreeBlitMap(surface->map);
|
|
surface->map = NULL;
|
|
}
|
|
if ( (surface->flags & GAL_HWSURFACE) == GAL_HWSURFACE ) {
|
|
GAL_VideoDevice *video = current_video;
|
|
GAL_VideoDevice *this = current_video;
|
|
video->FreeHWSurface(this, surface);
|
|
}
|
|
if ( surface->pixels &&
|
|
((surface->flags & GAL_PREALLOC) != GAL_PREALLOC) ) {
|
|
free(surface->pixels);
|
|
}
|
|
free(surface);
|
|
#ifdef CHECK_LEAKS
|
|
--surfaces_allocated;
|
|
#endif
|
|
}
|
|
|
|
#ifdef _MGRM_PROCESSES
|
|
void GAL_RequestHWSurface (const REQ_HWSURFACE* request, REP_HWSURFACE* reply)
|
|
{
|
|
if (current_video->RequestHWSurface) {
|
|
current_video->RequestHWSurface (current_video, request, reply);
|
|
} else if (request->offset == 0) {
|
|
reply->offset = 0;
|
|
} else {
|
|
/* NULL */
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
BYTE* gal_PutPixelKeyAlpha (GAL_Surface* dst, BYTE* dstrow,
|
|
Uint32 pixel, MYBITMAP_CONTXT* mybmp)
|
|
{
|
|
//BYTE* dstpixels = dstrow;
|
|
//BYTE* srcpixels = srcrow;
|
|
Uint32 ckey = mybmp->colorKey;
|
|
GAL_PixelFormat *dstfmt = dst->format;
|
|
GAL_PixelFormat *srcfmt = mybmp->AlphaPixelFormat;
|
|
int bpp = dstfmt->BytesPerPixel;
|
|
Uint32 rgbmask = ~srcfmt->Amask;
|
|
unsigned alpha = dstfmt->Amask ? GAL_ALPHA_OPAQUE : 0;
|
|
|
|
if (bpp == 1)
|
|
return dstrow;
|
|
|
|
//while ( h-- ) {
|
|
//dstpixels = dstrow;
|
|
//srcpixels = srcrow;
|
|
//DUFFS_LOOP(
|
|
{
|
|
//Uint32 pixel;
|
|
unsigned sR;
|
|
unsigned sG;
|
|
unsigned sB;
|
|
unsigned sA;
|
|
unsigned dR;
|
|
unsigned dG;
|
|
unsigned dB;
|
|
//RETRIEVE_RGB_PIXEL (srcpixels, bpp, pixel);
|
|
if ((pixel & rgbmask) != ckey ) {
|
|
RGBA_FROM_PIXEL (pixel, srcfmt, sR, sG, sB, sA);
|
|
DISEMBLE_RGB (dstrow, bpp, dstfmt, pixel, dR, dG, dB);
|
|
ALPHA_BLEND (sR, sG, sB, sA, dR, dG, dB);
|
|
ASSEMBLE_RGBA (dstrow, bpp, dstfmt, dR, dG, dB, alpha);
|
|
}
|
|
dstrow += bpp;
|
|
//srcpixels += bpp;
|
|
}
|
|
//w);
|
|
//srcrow += box->bmPitch;
|
|
//dstrow += dst->pitch;
|
|
//}
|
|
|
|
return dstrow;
|
|
}
|
|
|
|
BYTE* gal_PutPixelAlpha (GAL_Surface* dst, BYTE* dstrow,
|
|
Uint32 pixel, MYBITMAP_CONTXT* mybmp)
|
|
{
|
|
//BYTE* dstpixels = dstrow;
|
|
//BYTE* srcpixels = srcrow;
|
|
GAL_PixelFormat *dstfmt = dst->format;
|
|
GAL_PixelFormat *srcfmt = mybmp->AlphaPixelFormat;
|
|
int bpp = dstfmt->BytesPerPixel;
|
|
unsigned alpha = dstfmt->Amask ? GAL_ALPHA_OPAQUE : 0;
|
|
|
|
if (bpp == 1)
|
|
return dstrow;
|
|
|
|
//while ( h-- ) {
|
|
//dstpixels = dstrow;
|
|
//srcpixels = srcrow;
|
|
//DUFFS_LOOP(
|
|
{
|
|
//Uint32 pixel;
|
|
unsigned sR;
|
|
unsigned sG;
|
|
unsigned sB;
|
|
unsigned sA;
|
|
unsigned dR;
|
|
unsigned dG;
|
|
unsigned dB;
|
|
//RGB_FROM_PIXEL (pixel, srcfmt, sR, sG, sB);
|
|
RGBA_FROM_PIXEL(pixel, srcfmt, sR, sG, sB, sA);
|
|
pixel &= ~srcfmt->Amask;
|
|
//DISEMBLE_RGBA (srcpixels, bpp, srcfmt, pixel, sR, sG, sB, sA);
|
|
DISEMBLE_RGB (dstrow, bpp, dstfmt, pixel, dR, dG, dB);
|
|
ALPHA_BLEND (sR, sG, sB, sA, dR, dG, dB);
|
|
ASSEMBLE_RGBA (dstrow, bpp, dstfmt, dR, dG, dB, alpha);
|
|
dstrow += bpp;
|
|
//srcpixels += bpp;
|
|
}
|
|
//w);
|
|
//srcrow += box->bmPitch;
|
|
//dstrow += dst->pitch;
|
|
//}
|
|
|
|
return dstrow;
|
|
}
|
|
|
|
BYTE* gal_PutPixelKeyAlphaChannel (GAL_Surface* dst, BYTE* dstrow,
|
|
Uint32 pixel, MYBITMAP_CONTXT* mybmp)
|
|
{
|
|
//BYTE* dstpixels = dstrow;
|
|
//BYTE* srcpixels = srcrow;
|
|
Uint32 ckey = mybmp->colorKey;
|
|
GAL_PixelFormat *dstfmt = dst->format;
|
|
int bpp = dstfmt->BytesPerPixel;
|
|
unsigned alpha = mybmp->mybmp->alpha;
|
|
|
|
if (bpp == 1)
|
|
return dstrow;
|
|
|
|
//while ( h-- ) {
|
|
//dstpixels = dstrow;
|
|
//srcpixels = srcrow;
|
|
//DUFFS_LOOP(
|
|
{
|
|
//Uint32 pixel;
|
|
unsigned sR;
|
|
unsigned sG;
|
|
unsigned sB;
|
|
unsigned dR;
|
|
unsigned dG;
|
|
unsigned dB;
|
|
//RETRIEVE_RGB_PIXEL (srcpixels, bpp, pixel);
|
|
if ( pixel != ckey ) {
|
|
RGB_FROM_PIXEL (pixel, dstfmt, sR, sG, sB);
|
|
DISEMBLE_RGB (dstrow, bpp, dstfmt, pixel, dR, dG, dB);
|
|
ALPHA_BLEND (sR, sG, sB, alpha, dR, dG, dB);
|
|
ASSEMBLE_RGBA (dstrow, bpp, dstfmt, dR, dG, dB, alpha);
|
|
}
|
|
dstrow += bpp;
|
|
//srcpixels += bpp;
|
|
}//,
|
|
//w);
|
|
//srcrow += box->bmPitch;
|
|
//dstrow += dst->pitch;
|
|
//}
|
|
|
|
return dstrow;
|
|
}
|
|
|
|
BYTE* gal_PutPixelKey (GAL_Surface* dst, BYTE* dstrow,
|
|
Uint32 pixel, MYBITMAP_CONTXT* mybmp)
|
|
{
|
|
//BYTE* dstpixels = dstrow;
|
|
//BYTE* srcpixels = srcrow;
|
|
Uint32 ckey = mybmp->colorKey;
|
|
GAL_PixelFormat *dstfmt = dst->format;
|
|
int bpp = dstfmt->BytesPerPixel;
|
|
unsigned alpha = dstfmt->Amask ? GAL_ALPHA_OPAQUE : 0;
|
|
|
|
if (bpp == 1) {
|
|
//while (h--) {
|
|
//unsigned int i;
|
|
//dstpixels = dstrow;
|
|
//srcpixels = srcrow;
|
|
//for (i = 0; i < w; i++) {
|
|
if (pixel != ckey)
|
|
*dstrow = pixel;
|
|
dstrow += bpp;
|
|
//srcpixels += bpp;
|
|
//}
|
|
//srcrow += box->bmPitch;
|
|
//dstrow += dst->pitch;
|
|
//}
|
|
}
|
|
#ifndef _FOR_MONOBITMAP
|
|
else /*while ( h-- )*/ {
|
|
//dstpixels = dstrow;
|
|
//srcpixels = srcrow;
|
|
//DUFFS_LOOP(
|
|
{
|
|
//Uint32 pixel;
|
|
unsigned sR;
|
|
unsigned sG;
|
|
unsigned sB;
|
|
//RETRIEVE_RGB_PIXEL (srcpixels, bpp, pixel);
|
|
if ( pixel != ckey ) {
|
|
RGB_FROM_PIXEL (pixel, dstfmt, sR, sG, sB);
|
|
ASSEMBLE_RGBA (dstrow, bpp, dstfmt, sR, sG, sB, alpha);
|
|
}
|
|
dstrow += bpp;
|
|
//srcpixels += bpp;
|
|
}//,
|
|
//w);
|
|
//srcrow += box->bmPitch;
|
|
//dstrow += dst->pitch;
|
|
}
|
|
#else
|
|
else /*while ( h-- )*/ {
|
|
//dstpixels = dstrow;
|
|
//srcpixels = srcrow;
|
|
//DUFFS_LOOP(
|
|
{
|
|
//Uint32 pixel;
|
|
unsigned sR;
|
|
unsigned sG;
|
|
unsigned sB;
|
|
//RETRIEVE_RGB_PIXEL (srcpixels, bpp, pixel);
|
|
//here,the MYBITMAP has no BMP_TYPE_MONOKEY,need to fixed
|
|
if (pixel != ckey || ( pixel == ckey && mybmp->mybmp->flag & BMP_TYPE_MONOKEY) ) {
|
|
if (pixel == ckey)
|
|
pixel ^=1 ;
|
|
RGB_FROM_PIXEL (pixel, dstfmt, sR, sG, sB);
|
|
ASSEMBLE_RGBA (dstrow, bpp, dstfmt, sR, sG, sB, alpha);
|
|
}
|
|
dstrow += bpp;
|
|
//srcpixels += bpp;
|
|
}//,
|
|
//w);
|
|
//srcrow += box->bmPitch;
|
|
//dstrow += dst->pitch;
|
|
}
|
|
#endif
|
|
|
|
return dstrow;
|
|
}
|
|
|
|
BYTE* gal_PutPixelAlphaChannel (GAL_Surface* dst, BYTE* dstrow,
|
|
Uint32 pixel, MYBITMAP_CONTXT* mybmp)
|
|
{
|
|
//BYTE* dstpixels = dstrow;
|
|
//BYTE* srcpixels = srcrow;
|
|
GAL_PixelFormat *dstfmt = dst->format;
|
|
int bpp = dstfmt->BytesPerPixel;
|
|
unsigned alpha = mybmp->mybmp->alpha;
|
|
|
|
if (bpp == 1)
|
|
return dstrow;
|
|
|
|
//while ( h-- ) {
|
|
//dstpixels = dstrow;
|
|
//srcpixels = srcrow;
|
|
//DUFFS_LOOP(
|
|
{
|
|
//Uint32 pixel;
|
|
unsigned sR;
|
|
unsigned sG;
|
|
unsigned sB;
|
|
unsigned dR;
|
|
unsigned dG;
|
|
unsigned dB;
|
|
RGB_FROM_PIXEL(pixel, dstfmt, sR, sG, sB);
|
|
//DISEMBLE_RGB (srcpixels, bpp, dstfmt, pixel, sR, sG, sB);
|
|
DISEMBLE_RGB (dstrow, bpp, dstfmt, pixel, dR, dG, dB);
|
|
ALPHA_BLEND (sR, sG, sB, alpha, dR, dG, dB);
|
|
ASSEMBLE_RGBA (dstrow, bpp, dstfmt, dR, dG, dB, alpha);
|
|
dstrow += bpp;
|
|
//srcpixels += bpp;
|
|
}//,
|
|
//w);
|
|
//srcrow += box->bmPitch;
|
|
//dstrow += dst->pitch;
|
|
//}
|
|
|
|
return dstrow;
|
|
}
|
|
|