view src/video/cybergfx/SDL_cgximage.c @ 1982:3b4ce57c6215

First shot at new audio data types (int32 and float32). Notable changes: - Converters between types are autogenerated. Instead of making multiple passes over the data with seperate filters for endianess, size, signedness, etc, converting between data types is always one specialized filter. This simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases with the new types, and makes the actually conversions more CPU cache friendly. Left a stub for adding specific optimized versions of these routines (SSE/MMX/Altivec, assembler, etc) - Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This does not need to be run unless tweaking the code, and thus doesn't need integration into the build system. - Went through all the drivers and tried to weed out all the "Uint16" references that are better specified with the new SDL_AudioFormat typedef. - Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them with new SDL_AUDIO_* macros. - Added initial float32 and int32 support code. Theoretically, existing drivers will push these through converters to get the data they want to feed to the hardware. Still TODO: - Optimize and debug new converters. - Update the CoreAudio backend to accept float32 data directly. - Other backends, too? - SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files (both of which exist and can be generated by 'sox' for testing purposes). - Update the mixer to handle new datatypes. - Optionally update SDL_sound and SDL_mixer, etc.
author Ryan C. Gordon <icculus@icculus.org>
date Thu, 24 Aug 2006 12:10:46 +0000
parents c121d94672cb
children
line wrap: on
line source

/*
    SDL - Simple DirectMedia Layer
    Copyright (C) 1997-2006 Sam Lantinga

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

    Sam Lantinga
    slouken@libsdl.org
*/
#include "SDL_config.h"

#include "SDL_endian.h"
#include "SDL_cgximage_c.h"

#ifdef HAVE_KSTAT
#include <kstat.h>
#endif

#ifdef USE_CGX_WRITELUTPIXEL
#if defined(__SASC) || defined(__PPC__)
#define WLUT WriteLUTPixelArray
#else
void
WLUT(APTR a, UWORD b, UWORD c, UWORD d, struct RastPort *e, APTR f, UWORD g,
     UWORD h, UWORD i, UWORD l, UBYTE m)
{
    WriteLUTPixelArray(a, b, c, d, e, f, g, h, i, l, m);
}
#endif

#endif

/* Various screen update functions available */
static void CGX_NormalUpdate(_THIS, int numrects, SDL_Rect * rects);
static void CGX_FakeUpdate(_THIS, int numrects, SDL_Rect * rects);

BOOL SafeDisp = TRUE, SafeChange = TRUE;
struct MsgPort *safeport = NULL, *dispport = NULL;
ULONG safe_sigbit, disp_sigbit;
int use_picasso96 = 1;

int
CGX_SetupImage(_THIS, SDL_Surface * screen)
{
    SDL_Ximage = NULL;

    if (screen->flags & SDL_HWSURFACE) {
        ULONG pitch;

        if (!screen->hwdata) {
            if (!(screen->hwdata = SDL_malloc(sizeof(struct private_hwdata))))
                return -1;

            D(bug("Creating system accel struct\n"));
        }
        screen->hwdata->lock = NULL;
        screen->hwdata->allocated = 0;
        screen->hwdata->mask = NULL;
        screen->hwdata->bmap = SDL_RastPort->BitMap;
        screen->hwdata->videodata = this;

        if (!(screen->hwdata->lock = LockBitMapTags(screen->hwdata->bmap,
                                                    LBMI_BASEADDRESS,
                                                    (ULONG) & screen->
                                                    pixels,
                                                    LBMI_BYTESPERROW,
                                                    (ULONG) & pitch,
                                                    TAG_DONE))) {
            SDL_free(screen->hwdata);
            screen->hwdata = NULL;
            return -1;
        } else {
            UnLockBitMap(screen->hwdata->lock);
            screen->hwdata->lock = NULL;
        }

        screen->pitch = pitch;

        this->UpdateRects = CGX_FakeUpdate;

        D(bug
          ("Accel video image configured (%lx, pitch %ld).\n",
           screen->pixels, screen->pitch));
        return 0;
    }

    screen->pixels = SDL_malloc(screen->h * screen->pitch);

    if (screen->pixels == NULL) {
        SDL_OutOfMemory();
        return (-1);
    }

    SDL_Ximage = screen->pixels;

    if (SDL_Ximage == NULL) {
        SDL_SetError("Couldn't create XImage");
        return (-1);
    }

    this->UpdateRects = CGX_NormalUpdate;

    return (0);
}

void
CGX_DestroyImage(_THIS, SDL_Surface * screen)
{
    if (SDL_Ximage) {
        SDL_free(SDL_Ximage);
        SDL_Ximage = NULL;
    }
    if (screen) {
        screen->pixels = NULL;

        if (screen->hwdata) {
            SDL_free(screen->hwdata);
            screen->hwdata = NULL;
        }
    }
}

/* This is a hack to see whether this system has more than 1 CPU */
static int
num_CPU(void)
{
    return 1;
}

int
CGX_ResizeImage(_THIS, SDL_Surface * screen, Uint32 flags)
{
    int retval;

    D(bug("Calling ResizeImage()\n"));

    CGX_DestroyImage(this, screen);

    if (flags & SDL_INTERNALOPENGL) {   /* No image when using GL */
        retval = 0;
    } else {
        retval = CGX_SetupImage(this, screen);
        /* We support asynchronous blitting on the display */
        if (flags & SDL_ASYNCBLIT) {
            if (num_CPU() > 1) {
                screen->flags |= SDL_ASYNCBLIT;
            }
        }
    }
    return (retval);
}

int
CGX_AllocHWSurface(_THIS, SDL_Surface * surface)
{
    D(bug
      ("Alloc HW surface...%ld x %ld x %ld!\n", surface->w, surface->h,
       this->hidden->depth));

    if (surface == SDL_VideoSurface) {
        D(bug("Allocation skipped, it's system one!\n"));
        return 0;
    }

    if (!surface->hwdata) {
        if (!(surface->hwdata = SDL_malloc(sizeof(struct private_hwdata))))
            return -1;
    }

    surface->hwdata->mask = NULL;
    surface->hwdata->lock = NULL;
    surface->hwdata->videodata = this;
    surface->hwdata->allocated = 0;

    if (surface->hwdata->bmap =
        AllocBitMap(surface->w, surface->h, this->hidden->depth,
                    BMF_MINPLANES, SDL_Display->RastPort.BitMap)) {
        surface->hwdata->allocated = 1;
        surface->flags |= SDL_HWSURFACE;
        D(bug("...OK\n"));
        return 0;
    } else {
        SDL_free(surface->hwdata);
        surface->hwdata = NULL;
    }

    return (-1);
}

void
CGX_FreeHWSurface(_THIS, SDL_Surface * surface)
{
    if (surface && surface != SDL_VideoSurface && surface->hwdata) {
        D(bug("Free hw surface.\n"));

        if (surface->hwdata->mask)
            SDL_free(surface->hwdata->mask);

        if (surface->hwdata->bmap && surface->hwdata->allocated)
            FreeBitMap(surface->hwdata->bmap);

        SDL_free(surface->hwdata);
        surface->hwdata = NULL;
        surface->pixels = NULL;
        D(bug("end of free hw surface\n"));
    }
    return;
}

int
CGX_LockHWSurface(_THIS, SDL_Surface * surface)
{
    if (surface->hwdata) {
//              D(bug("Locking a bitmap...\n"));
        if (!surface->hwdata->lock) {
            Uint32 pitch;

            if (!
                (surface->hwdata->lock =
                 LockBitMapTags(surface->hwdata->bmap, LBMI_BASEADDRESS,
                                (ULONG) & surface->pixels,
                                LBMI_BYTESPERROW, (ULONG) & pitch, TAG_DONE)))
                return -1;

// surface->pitch e' a 16bit!

            surface->pitch = pitch;

            if (!currently_fullscreen && surface == SDL_VideoSurface)
                surface->pixels =
                    ((char *) surface->pixels) +
                    (surface->pitch *
                     (SDL_Window->BorderTop + SDL_Window->TopEdge) +
                     surface->format->BytesPerPixel *
                     (SDL_Window->BorderLeft + SDL_Window->LeftEdge));
        }
        D(
             else
             bug("Already locked!!!\n"));
    }
    return (0);
}

void
CGX_UnlockHWSurface(_THIS, SDL_Surface * surface)
{
    if (surface->hwdata && surface->hwdata->lock) {
        UnLockBitMap(surface->hwdata->lock);
        surface->hwdata->lock = NULL;
//              surface->pixels=NULL;
    }
}

int
CGX_FlipHWSurface(_THIS, SDL_Surface * surface)
{
    static int current = 0;

    if (this->hidden->dbuffer) {
        if (!SafeChange) {
            Wait(disp_sigbit);
// Non faccio nulla, vuoto solo la porta
            while (GetMsg(dispport) != NULL);
            SafeChange = TRUE;
        }

        if (ChangeScreenBuffer(SDL_Display, this->hidden->SB[current ^ 1])) {
            surface->hwdata->bmap = SDL_RastPort->BitMap =
                this->hidden->SB[current]->sb_BitMap;
            SafeChange = FALSE;
            SafeDisp = FALSE;
            current ^= 1;
        }

        if (!SafeDisp) {
            Wait(safe_sigbit);
            while (GetMsg(safeport) != NULL);
            SafeDisp = TRUE;
        }

    }
    return (0);
}

/* Byte-swap the pixels in the display image */
static void
CGX_SwapAllPixels(SDL_Surface * screen)
{
    int x, y;

    switch (screen->format->BytesPerPixel) {
    case 2:
        {
            Uint16 *spot;
            for (y = 0; y < screen->h; ++y) {
                spot = (Uint16 *) ((Uint8 *) screen->pixels +
                                   y * screen->pitch);
                for (x = 0; x < screen->w; ++x, ++spot) {
                    *spot = SDL_Swap16(*spot);
                }
            }
        }
        break;

    case 4:
        {
            Uint32 *spot;
            for (y = 0; y < screen->h; ++y) {
                spot = (Uint32 *) ((Uint8 *) screen->pixels +
                                   y * screen->pitch);
                for (x = 0; x < screen->w; ++x, ++spot) {
                    *spot = SDL_Swap32(*spot);
                }
            }
        }
        break;

    default:
        /* should never get here */
        break;
    }
}
static void
CGX_SwapPixels(SDL_Surface * screen, int numrects, SDL_Rect * rects)
{
    int i;
    int x, minx, maxx;
    int y, miny, maxy;

    switch (screen->format->BytesPerPixel) {
    case 2:
        {
            Uint16 *spot;
            for (i = 0; i < numrects; ++i) {
                minx = rects[i].x;
                maxx = rects[i].x + rects[i].w;
                miny = rects[i].y;
                maxy = rects[i].y + rects[i].h;
                for (y = miny; y < maxy; ++y) {
                    spot = (Uint16 *) ((Uint8 *) screen->pixels +
                                       y * screen->pitch + minx * 2);
                    for (x = minx; x < maxx; ++x, ++spot) {
                        *spot = SDL_Swap16(*spot);
                    }
                }
            }
        }
        break;

    case 4:
        {
            Uint32 *spot;
            for (i = 0; i < numrects; ++i) {
                minx = rects[i].x;
                maxx = rects[i].x + rects[i].w;
                miny = rects[i].y;
                maxy = rects[i].y + rects[i].h;
                for (y = miny; y < maxy; ++y) {
                    spot = (Uint32 *) ((Uint8 *) screen->pixels +
                                       y * screen->pitch + minx * 4);
                    for (x = minx; x < maxx; ++x, ++spot) {
                        *spot = SDL_Swap32(*spot);
                    }
                }
            }
        }
        break;

    default:
        /* should never get here */
        break;
    }
}

#ifdef __SASC

#define USE_WPA WritePixelArray
#else

void
USE_WPA(char *a, int b, int c, int d, struct RastPort *e, int f, int g,
        int h, int i, Uint32 l)
{
    WritePixelArray(a, b, c, d, e, f, g, h, i, l);
}

#endif

static void
CGX_FakeUpdate(_THIS, int numrects, SDL_Rect * rects)
{
}

static void
CGX_NormalUpdate(_THIS, int numrects, SDL_Rect * rects)
{
    int i, format, customroutine = 0;
#ifndef USE_CGX_WRITELUTPIXEL
    int bpp;
#endif
    if (this->hidden->same_format && !use_picasso96) {
        format = RECTFMT_RAW;
    } else
        switch (this->screen->format->BytesPerPixel) {
        case 4:
            format = RECTFMT_RGBA;
            break;
        case 3:
            format = RECTFMT_RGB;
            break;
        case 2:
            customroutine = 1;
            break;
        case 1:
//                      D(bug("soft depth: 8 hardbpp: %ld\n",this->hidden->depth));
            if (this->hidden->depth > 8) {
#ifndef USE_CGX_WRITELUTPIXEL
                if (this->hidden->depth > 32)
                    customroutine = 4;
                else if (this->hidden->depth > 16) {
                    bpp = this->hidden->BytesPerPixel;  // That one is the only one that needs bpp
                    customroutine = 2;  // The slow one!
                } else
                    customroutine = 3;
#else

                customroutine = 2;
#endif

//                              format=RECTFMT_LUT8;   Vecchia funzione x usare la WritePixelArray.
            } else
                customroutine = 1;
            break;
        default:
            D(bug("Unable to blit this surface!\n"));
            return;
        }

    /* Check for endian-swapped X server, swap if necessary (VERY slow!) */
    if (swap_pixels && ((this->screen->format->BytesPerPixel % 2) == 0)) {
        D(bug("Software Swapping! SLOOOW!\n"));
        CGX_SwapPixels(this->screen, numrects, rects);
        for (i = 0; i < numrects; ++i) {
            if (!rects[i].w) {  /* Clipped? */
                continue;
            }
            USE_WPA(this->screen->pixels, rects[i].x, rects[i].y,
                    this->screen->pitch, SDL_RastPort,
                    SDL_Window->BorderLeft + rects[i].x,
                    SDL_Window->BorderTop + rects[i].y, rects[i].w,
                    rects[i].h, format);
        }
        CGX_SwapPixels(this->screen, numrects, rects);
    } else if (customroutine == 2) {
#ifdef USE_CGX_WRITELUTPIXEL
        for (i = 0; i < numrects; ++i) {
            if (!rects[i].w) {  /* Clipped? */
                continue;
            }

            WLUT(this->screen->pixels, rects[i].x, rects[i].y,
                 this->screen->pitch, SDL_RastPort, SDL_XPixels,
                 SDL_Window->BorderLeft + rects[i].x,
                 SDL_Window->BorderTop + rects[i].y, rects[i].w,
                 rects[i].h, CTABFMT_XRGB8);
        }
#else
        unsigned char *bm_address;
        Uint32 destpitch;
        APTR handle;

        if (handle =
            LockBitMapTags(SDL_RastPort->BitMap, LBMI_BASEADDRESS,
                           &bm_address, LBMI_BYTESPERROW, &destpitch,
                           TAG_DONE)) {
            int srcwidth;
            unsigned char *destbase;
            register int j, k, t;
            register unsigned char *mask, *dst;
            register unsigned char *src, *dest;

// Aggiungo il bordo della finestra se sono fullscreen.
            if (currently_fullscreen)
                destbase = bm_address;
            else
                destbase =
                    bm_address + (SDL_Window->TopEdge +
                                  SDL_Window->BorderTop) * destpitch +
                    (SDL_Window->BorderLeft +
                     SDL_Window->LeftEdge) * this->hidden->BytesPerPixel;

            for (i = 0; i < numrects; ++i) {
                srcwidth = rects[i].w;

                if (!srcwidth) {        /* Clipped? */
                    continue;
                }

                dest = destbase + rects[i].x * this->hidden->BytesPerPixel;
                dest += (rects[i].y * destpitch);
                src = ((char *) (this->screen->pixels)) + rects[i].x;
                src += (rects[i].y * this->screen->pitch);

                for (j = rects[i].h; j; --j) {
                    dst = dest;
// SLOW routine, used for 8->24 bit mapping
                    for (k = 0; k < srcwidth; k++) {
                        mask = (unsigned char *) (&SDL_XPixels[src[k]]);
                        for (t = 0; t < bpp; t++) {
                            dst[t] = mask[t];
                        }
                        dst += bpp;
                    }
                    src += this->screen->pitch;
                    dest += destpitch;
                }
            }
            UnLockBitMap(handle);
        }
    } else if (customroutine == 3) {
        unsigned char *bm_address;
        Uint32 destpitch;
        APTR handle;

        if (handle =
            LockBitMapTags(SDL_RastPort->BitMap, LBMI_BASEADDRESS,
                           &bm_address, LBMI_BYTESPERROW, &destpitch,
                           TAG_DONE)) {
            int srcwidth;
            unsigned char *destbase;
            register int j, k;
            register unsigned char *src, *dest;
            register Uint16 *destl, *srcl;

            if (currently_fullscreen)
                destbase = bm_address;
            else
                destbase =
                    bm_address + (SDL_Window->TopEdge +
                                  SDL_Window->BorderTop) * destpitch +
                    (SDL_Window->BorderLeft +
                     SDL_Window->LeftEdge) * this->hidden->BytesPerPixel;

            for (i = 0; i < numrects; ++i) {
                srcwidth = rects[i].w;

                if (!srcwidth) {        /* Clipped? */
                    continue;
                }

                dest = destbase + rects[i].x * this->hidden->BytesPerPixel;
                dest += (rects[i].y * destpitch);
                src = ((char *) (this->screen->pixels)) + rects[i].x;
                src += (rects[i].y * this->screen->pitch);

// This is the fast, well not too slow, remapping code for 16bit displays

                for (j = rects[i].h; j; --j) {
                    destl = (Uint16 *) dest;

                    for (k = 0; k < srcwidth; k++) {
                        srcl = (Uint16 *) & SDL_XPixels[src[k]];
                        *destl = *srcl;
                        destl++;
                    }
                    src += this->screen->pitch;
                    dest += destpitch;
                }
            }
            UnLockBitMap(handle);
        }
    } else if (customroutine == 4) {
        unsigned char *bm_address;
        Uint32 destpitch;
        APTR handle;

        if (handle =
            LockBitMapTags(SDL_RastPort->BitMap, LBMI_BASEADDRESS,
                           &bm_address, LBMI_BYTESPERROW, &destpitch,
                           TAG_DONE)) {
            int srcwidth;
            unsigned char *destbase;
            register int j, k;
            register unsigned char *src, *dest;
            register Uint32 *destl, *srcl;

            if (currently_fullscreen)
                destbase = bm_address;
            else
                destbase =
                    bm_address + (SDL_Window->TopEdge +
                                  SDL_Window->BorderTop) * destpitch +
                    (SDL_Window->BorderLeft +
                     SDL_Window->LeftEdge) * this->hidden->BytesPerPixel;

            for (i = 0; i < numrects; ++i) {
                srcwidth = rects[i].w;

                if (!srcwidth) {        /* Clipped? */
                    continue;
                }

                dest = destbase + rects[i].x * this->hidden->BytesPerPixel;
                dest += (rects[i].y * destpitch);
                src = ((char *) (this->screen->pixels)) + rects[i].x;
                src += (rects[i].y * this->screen->pitch);

// This is the fast, well not too slow, remapping code for 32bit displays

                for (j = rects[i].h; j; --j) {
                    destl = (Uint32 *) dest;

                    for (k = 0; k < srcwidth; k++) {
                        srcl = (Uint32 *) & SDL_XPixels[src[k]];
                        *destl = *srcl;
                        destl++;
                    }
                    src += this->screen->pitch;
                    dest += destpitch;
                }
            }
            UnLockBitMap(handle);
        }
#endif
    } else if (customroutine) {
        unsigned char *bm_address;
        Uint32 destpitch;
        APTR handle;

//              D(bug("Using customroutine!\n"));

        if (handle =
            LockBitMapTags(SDL_RastPort->BitMap, LBMI_BASEADDRESS,
                           (ULONG) & bm_address, LBMI_BYTESPERROW,
                           (ULONG) & destpitch, TAG_DONE)) {
            unsigned char *destbase;
            register int j, srcwidth;
            register unsigned char *src, *dest;

// Aggiungo il bordo della finestra se sono fullscreen.
            if (currently_fullscreen)
                destbase = bm_address;
            else
                destbase =
                    bm_address + (SDL_Window->TopEdge +
                                  SDL_Window->BorderTop) * destpitch +
                    (SDL_Window->BorderLeft +
                     SDL_Window->LeftEdge) *
                    this->screen->format->BytesPerPixel;

            for (i = 0; i < numrects; ++i) {
                srcwidth = rects[i].w;

                if (!srcwidth) {        /* Clipped? */
                    continue;
                }

                dest =
                    destbase +
                    rects[i].x * this->screen->format->BytesPerPixel;
                dest += (rects[i].y * destpitch);
                src =
                    ((char *) (this->screen->pixels)) +
                    rects[i].x * this->screen->format->BytesPerPixel;
                src += (rects[i].y * this->screen->pitch);

                srcwidth *= this->screen->format->BytesPerPixel;

//                              D(bug("Rects: %ld,%ld %ld,%ld Src:%lx Dest:%lx\n",rects[i].x,rects[i].y,rects[i].w,rects[i].h,src,dest));

                for (j = rects[i].h; j; --j) {
                    SDL_memcpy(dest, src, srcwidth);
                    src += this->screen->pitch;
                    dest += destpitch;
                }
            }
            UnLockBitMap(handle);
//                      D(bug("Rectblit addr: %lx pitch: %ld rects:%ld srcptr: %lx srcpitch: %ld\n",bm_address,destpitch,numrects,this->screen->pixels,this->screen->pitch));
        }
    } else {
        for (i = 0; i < numrects; ++i) {
            if (!rects[i].w) {  /* Clipped? */
                continue;
            }
            USE_WPA(this->screen->pixels, rects[i].x, rects[i].y,
                    this->screen->pitch, SDL_RastPort,
                    SDL_Window->BorderLeft + rects[i].x,
                    SDL_Window->BorderTop + rects[i].y, rects[i].w,
                    rects[i].h, format);
        }
    }
}

void
CGX_RefreshDisplay(_THIS)
{
    int format, customroutine = 0;
#ifndef USE_CGX_WRITELUTPIXEL
    int bpp;
#endif
    /* Don't refresh a display that doesn't have an image (like GL) */
    if (!SDL_Ximage) {
        return;
    }

    if (this->hidden->same_format && !use_picasso96) {
        format = RECTFMT_RAW;
    } else
        switch (this->screen->format->BytesPerPixel) {
        case 4:
            format = RECTFMT_RGBA;
            break;
        case 3:
            format = RECTFMT_RGB;
            break;
        case 2:
            customroutine = 1;
            break;
        case 1:
//                      D(bug("soft depth: 8 hardbpp: %ld\n",this->hidden->depth));
            if (this->hidden->depth > 8) {
#ifndef USE_CGX_WRITELUTPIXEL
                if (this->hidden->depth > 32)
                    customroutine = 4;
                else if (this->hidden->depth > 16) {
                    bpp = this->hidden->BytesPerPixel;  // That one is the only one that needs bpp
                    customroutine = 2;  // The slow one!
                } else
                    customroutine = 3;
#else

                customroutine = 2;
#endif
//                              format=RECTFMT_LUT8;
            } else
                customroutine = 1;
            break;

        }

    /* Check for endian-swapped X server, swap if necessary */
    if (swap_pixels && ((this->screen->format->BytesPerPixel % 2) == 0)) {
        CGX_SwapAllPixels(this->screen);
        USE_WPA(this->screen->pixels, 0, 0, this->screen->pitch,
                SDL_RastPort, SDL_Window->BorderLeft,
                SDL_Window->BorderTop, this->screen->w, this->screen->h,
                format);
        CGX_SwapAllPixels(this->screen);
    } else if (customroutine == 2) {
#ifdef USE_CGX_WRITELUTPIXEL
        WLUT(this->screen->pixels, 0, 0, this->screen->pitch,
             SDL_RastPort, SDL_XPixels, SDL_Window->BorderLeft,
             SDL_Window->BorderTop, this->screen->w, this->screen->h,
             CTABFMT_XRGB8);
#else
        unsigned char *bm_address;
        Uint32 destpitch;
        APTR handle;

        if (handle =
            LockBitMapTags(SDL_RastPort->BitMap, LBMI_BASEADDRESS,
                           (ULONG) & bm_address, LBMI_BYTESPERROW,
                           (ULONG) & destpitch, TAG_DONE)) {
            register int j, k, t;
            register unsigned char *mask, *dst;
            register unsigned char *src, *dest;

// Aggiungo il bordo della finestra se sono fullscreen.
            if (!currently_fullscreen)
                dest =
                    bm_address + (SDL_Window->TopEdge +
                                  SDL_Window->BorderTop) * destpitch +
                    (SDL_Window->BorderLeft +
                     SDL_Window->LeftEdge) * this->hidden->BytesPerPixel;
            else
                dest = bm_address;

            src = this->screen->pixels;

            for (j = this->screen->h; j; --j) {
                dst = dest;
// SLOW routine, used for 8->24 bit mapping
                for (k = 0; k < this->screen->w; k++) {
                    mask = (unsigned char *) (&SDL_XPixels[src[k]]);
                    for (t = 0; t < bpp; t++) {
                        dst[t] = mask[t];
                    }
                    dst += bpp;
                }
                src += this->screen->pitch;
                dest += destpitch;
            }
            UnLockBitMap(handle);
        }
    } else if (customroutine == 3) {
        unsigned char *bm_address;
        Uint32 destpitch;
        APTR handle;

        if (handle =
            LockBitMapTags(SDL_RastPort->BitMap, LBMI_BASEADDRESS,
                           (ULONG) & bm_address, LBMI_BYTESPERROW,
                           (ULONG) & destpitch, TAG_DONE)) {
            register int j, k;
            register unsigned char *src, *dest;
            register Uint16 *destl, *srcl;

            if (!currently_fullscreen)
                dest =
                    bm_address + (SDL_Window->TopEdge +
                                  SDL_Window->BorderTop) * destpitch +
                    (SDL_Window->BorderLeft +
                     SDL_Window->LeftEdge) * this->hidden->BytesPerPixel;
            else
                dest = bm_address;

            src = this->screen->pixels;

// This is the fast, well not too slow, remapping code for 16bit displays

            for (j = this->screen->h; j; --j) {
                destl = (Uint16 *) dest;

                for (k = 0; k < this->screen->w; k++) {
                    srcl = (Uint16 *) & SDL_XPixels[src[k]];
                    *destl = *srcl;
                    destl++;
                }
                src += this->screen->pitch;
                dest += destpitch;
            }
            UnLockBitMap(handle);
        }
    } else if (customroutine == 4) {
        unsigned char *bm_address;
        Uint32 destpitch;
        APTR handle;

        if (handle =
            LockBitMapTags(SDL_RastPort->BitMap, LBMI_BASEADDRESS,
                           (ULONG) & bm_address, LBMI_BYTESPERROW,
                           (ULONG) & destpitch, TAG_DONE)) {
            register int j, k;
            register unsigned char *src, *dest;
            register Uint32 *destl, *srcl;

            if (!currently_fullscreen)
                dest =
                    bm_address + (SDL_Window->TopEdge +
                                  SDL_Window->BorderTop) * destpitch +
                    (SDL_Window->BorderLeft +
                     SDL_Window->LeftEdge) * this->hidden->BytesPerPixel;
            else
                dest = bm_address;

            src = this->screen->pixels;

// This is the fast, well not too slow, remapping code for 32bit displays

            for (j = this->screen->h; j; --j) {
                destl = (Uint32 *) dest;

                for (k = 0; k < this->screen->w; k++) {
                    srcl = (Uint32 *) & SDL_XPixels[src[k]];
                    *destl = *srcl;
                    destl++;
                }
                src += this->screen->pitch;
                dest += destpitch;
            }
            UnLockBitMap(handle);
        }
#endif
    } else if (customroutine) {
        unsigned char *bm_address;
        Uint32 destpitch;
        APTR handle;

        if (handle = LockBitMapTags(SDL_RastPort->BitMap,
                                    LBMI_BASEADDRESS, (ULONG) & bm_address,
                                    LBMI_BYTESPERROW, (ULONG) & destpitch,
                                    TAG_DONE)) {
            register int j;
            register unsigned char *src, *dest;

            if (!currently_fullscreen)
                dest =
                    bm_address + (SDL_Window->TopEdge +
                                  SDL_Window->BorderTop) * destpitch +
                    (SDL_Window->BorderLeft +
                     SDL_Window->LeftEdge) *
                    this->screen->format->BytesPerPixel;
            else
                dest = bm_address;

            src = this->screen->pixels;

//                      D(bug("addr: %lx pitch: %ld src:%lx srcpitch: %ld\n",dest,destpitch,this->screen->pixels,this->screen->pitch));

            if (this->screen->pitch == destpitch) {
                SDL_memcpy(dest, src, this->screen->pitch * this->screen->h);
            } else {
                for (j = this->screen->h; j; --j) {
                    SDL_memcpy(dest, src, this->screen->pitch);
                    src += this->screen->pitch;
                    dest += destpitch;
                }
            }

            UnLockBitMap(handle);
        }
    } else {
        USE_WPA(this->screen->pixels, 0, 0, this->screen->pitch,
                SDL_RastPort, SDL_Window->BorderLeft,
                SDL_Window->BorderTop, this->screen->w, this->screen->h,
                format);
    }

}

/* vi: set ts=4 sw=4 expandtab: */