/****************************************************************************
*
*					SciTech Multi-platform Graphics Library
*
*  ========================================================================
*
*    The contents of this file are subject to the SciTech MGL Public
*    License Version 1.0 (the "License"); you may not use this file
*    except in compliance with the License. You may obtain a copy of
*    the License at http://www.scitechsoft.com/mgl-license.txt
*
*    Software distributed under the License is distributed on an
*    "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
*    implied. See the License for the specific language governing
*    rights and limitations under the License.
*
*    The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
*
*    The Initial Developer of the Original Code is SciTech Software, Inc.
*    All Rights Reserved.
*
*  ========================================================================
*
* Language:		ANSI C
* Environment:	Any
*
* Description:  Demo showing how to use do alpha blended sprites with the MGL.
*               Shows how to use 32-bit ARGB or 8-bit+alpha bitmap data
*               for blending.
*
****************************************************************************/

#include "mglsamp.h"

#define ALPHA_RGBA_IMAGE_NAME    "blend.png"
#define ALPHA_GREY_IMAGE_NAME    "blndgrey.png"
#define ALPHA_8BIT_IMAGE_NAME    "blend8.png"

/*----------------------------- Global Variables --------------------------*/

char 			demoName[] = "alpha";
int 			bmpWidth,bmpHeight,bmpDepth;
int 			maxx,maxy;
pixel_format_t 	bmpPF;

/*------------------------------ Implementation ---------------------------*/

/****************************************************************************
PARAMETERS:
dc     		- Display dc

REMARKS:
Demo showing how to use memory dc's to store alpha sprites and to use blit
them from the memory dc to the display dc. Note that this version draws
the sprites direct to the screen, which is rather slow when drawing to
the hardware framebuffer because reads from the hardware framebuffer are
very slow.
****************************************************************************/
ibool alphaRGBABlit(
	MGLDC *dc)
{
	pixel_format_t 	bmpPF;
	MGLDC 			*memdc;
    int 			bmpWidth,bmpHeight,bmpDepth;
    bltfx_t         fx;

	/* Display title message at the top of the window. */
    mainWindow(dc,"System Memory Alpha Blit Demo - Direct to Screen");
    statusLine("Press any key to continue, ESC to Abort");

	/* Create a memory device context */
    if (!MGL_getPNGSize(ALPHA_RGBA_IMAGE_NAME,&bmpWidth,&bmpHeight,&bmpDepth,&bmpPF))
		MGL_fatalError("Unable to load PNG file!");
	if ((memdc = MGL_createMemoryDC(bmpWidth,bmpHeight,bmpDepth,&bmpPF)) == NULL)
		MGL_fatalError(MGL_errorMsg(MGL_result()));

	/* Load a bitmap into the memory device context. The palette gets
	 * loaded into the memory device context as well.
	 */
	if (!MGL_loadPNGIntoDC(memdc,ALPHA_RGBA_IMAGE_NAME,0,0,true))
		MGL_fatalError(MGL_errorMsg(MGL_result()));

    /* Setup alpha blended effects */
    fx.flags = MGL_BLT_BLEND;
    fx.srcBlendFunc = MGL_BLEND_SRCALPHAFAST;
    fx.dstBlendFunc = MGL_BLEND_SRCALPHAFAST;

	/* Copy image from image in memory to the screen. */
    while (!checkEvent())
        MGL_bitBltFxCoord(dc,memdc,0,0,bmpWidth,bmpHeight,MGL_random(maxx-bmpWidth),MGL_random(maxy-bmpHeight),&fx);

	/* Remove all device contexts from memory. */
    MGL_destroyDC(memdc);

	return pause();
}

/****************************************************************************
PARAMETERS:
dc     		- Display dc

REMARKS:
Demo showing how to use memory dc's to store alpha sprites and to use blit
them from the memory dc to the display dc. Note that this version draws
the sprites direct to the screen, which is rather slow when drawing to
the hardware framebuffer because reads from the hardware framebuffer are
very slow.
****************************************************************************/
ibool alphaGreyBlit(
	MGLDC *dc)
{
    palette_t       pal[256];
	pixel_format_t 	bmpPF;
	MGLDC 			*memdc;
    int 			bmpWidth,bmpHeight,bmpDepth,oldCheckId;
    bltfx_t         fx;

	/* Display title message at the top of the window. */
    mainWindow(dc,"System Memory Grey Alpha Blit Demo - Direct to Screen");
    statusLine("Press any key to continue, ESC to Abort");

	/* Create a memory device context */
    if (!MGL_getPNGSize(ALPHA_GREY_IMAGE_NAME,&bmpWidth,&bmpHeight,&bmpDepth,&bmpPF))
		MGL_fatalError("Unable to load PNG file!");
	if ((memdc = MGL_createMemoryDC(bmpWidth,bmpHeight,bmpDepth,&bmpPF)) == NULL)
		MGL_fatalError(MGL_errorMsg(MGL_result()));

	/* Load a bitmap into the memory device context. The palette gets
	 * loaded into the memory device context as well.
	 */
	if (!MGL_loadPNGIntoDC(memdc,ALPHA_GREY_IMAGE_NAME,0,0,true))
		MGL_fatalError(MGL_errorMsg(MGL_result()));

    /* Set the palette for the destination DC and turn of identity palette
     * checking. This provides the fastest blit performance because the
     * color translation vector is not re-built for every blit but is
     * instead taken from the destination DC color table (ie: bitmap
     * source palette is ignored).
     */
    MGL_getPalette(memdc,pal,MGL_getPaletteSize(memdc),0);
    MGL_setPalette(dc,pal,MGL_getPaletteSize(memdc),0);
    MGL_realizePalette(dc,MGL_getPaletteSize(memdc),0,true);
    oldCheckId = MGL_checkIdentityPalette(false);

    /* Setup alpha blended effects */
    fx.flags = MGL_BLT_BLEND;
    fx.srcBlendFunc = MGL_BLEND_SRCALPHAFAST;
    fx.dstBlendFunc = MGL_BLEND_SRCALPHAFAST;

	/* Copy image from image in memory to the screen. */
    while (!checkEvent())
        MGL_bitBltFxCoord(dc,memdc,0,0,bmpWidth,bmpHeight,MGL_random(maxx-bmpWidth),MGL_random(maxy-bmpHeight),&fx);

	/* Remove all device contexts from memory. */
    MGL_destroyDC(memdc);
    MGL_checkIdentityPalette(oldCheckId);
    MGL_setDefaultPalette(dc);
	return pause();
}

/****************************************************************************
PARAMETERS:
dc     		- Display dc

REMARKS:
Demo showing how to use memory dc's to store alpha sprites and to use blit
them from the memory dc to the display dc. Note that this version draws
the sprites direct to the screen, which is rather slow when drawing to
the hardware framebuffer because reads from the hardware framebuffer are
very slow.
****************************************************************************/
ibool alpha8BitBlit(
	MGLDC *dc)
{
    palette_t       pal[256];
	pixel_format_t 	bmpPF;
	MGLDC 			*memdc;
    int 			bmpWidth,bmpHeight,bmpDepth,oldCheckId;
    bltfx_t         fx;

	/* Display title message at the top of the window. */
    mainWindow(dc,"System Memory 8-bit + Alpha Blit Demo - Direct to Screen");
    statusLine("Press any key to continue, ESC to Abort");

	/* Create a memory device context */
    if (!MGL_getPNGSize(ALPHA_8BIT_IMAGE_NAME,&bmpWidth,&bmpHeight,&bmpDepth,&bmpPF))
		MGL_fatalError("Unable to load PNG file!");
	if ((memdc = MGL_createMemoryDC(bmpWidth,bmpHeight,bmpDepth,&bmpPF)) == NULL)
		MGL_fatalError(MGL_errorMsg(MGL_result()));

	/* Load a bitmap into the memory device context. The palette gets
	 * loaded into the memory device context as well.
	 */
	if (!MGL_loadPNGIntoDC(memdc,ALPHA_8BIT_IMAGE_NAME,0,0,true))
		MGL_fatalError(MGL_errorMsg(MGL_result()));

    /* Set the palette for the destination DC and turn of identity palette
     * checking. This provides the fastest blit performance because the
     * color translation vector is not re-built for every blit but is
     * instead taken from the destination DC color table (ie: bitmap
     * source palette is ignored).
     */
    MGL_getPalette(memdc,pal,MGL_getPaletteSize(memdc),0);
    MGL_setPalette(dc,pal,MGL_getPaletteSize(memdc),0);
    MGL_realizePalette(dc,MGL_getPaletteSize(memdc),0,true);
    oldCheckId = MGL_checkIdentityPalette(false);

    /* Setup alpha blended effects */
    fx.flags = MGL_BLT_BLEND;
    fx.srcBlendFunc = MGL_BLEND_SRCALPHAFAST;
    fx.dstBlendFunc = MGL_BLEND_SRCALPHAFAST;

	/* Copy image from image in memory to the screen. */
    while (!checkEvent())
        MGL_bitBltFxCoord(dc,memdc,0,0,bmpWidth,bmpHeight,MGL_random(maxx-bmpWidth),MGL_random(maxy-bmpHeight),&fx);

	/* Remove all device contexts from memory. */
    MGL_destroyDC(memdc);
    MGL_checkIdentityPalette(oldCheckId);
    MGL_setDefaultPalette(dc);
	return pause();
}

/****************************************************************************
PARAMETERS:
dc     		- Display dc

REMARKS:
Demo showing how to use memory dc's to store alpha sprites and to use blit
them from the memory dc to the display dc.

This version draws all the sprites to an intermediate system memory buffer
and then copies the changed rectangle of data to the display screen. This is
a lot faster than drawing direct to the framebuffer (even with the extra
copy to the screen) because system memory reads a cached and very fast.
****************************************************************************/
ibool alphaRGBABlitMem(
	MGLDC *dc)
{
	pixel_format_t 	bmpPF;
    MGLDC           *backdc;
	MGLDC 			*memdc;
    int 			x,y,bmpWidth,bmpHeight,bmpDepth;
    bltfx_t         fx;

	/* Display title message at the top of the window. */
    mainWindow(dc,"System Memory Alpha Blit Demo - Draw to back buffer");
    statusLine("Press any key to continue, ESC to Abort");

    /* Create a back buffer memory DC the size of the screen */
	if ((backdc = MGL_createMemoryDC(MGL_sizex(dc),MGL_sizey(dc),MGL_getBitsPerPixel(dc),&dc->pf)) == NULL)
		MGL_fatalError(MGL_errorMsg(MGL_result()));
    MGL_bitBltCoord(backdc,dc,0,0,MGL_sizex(dc),MGL_sizey(dc),0,0,MGL_REPLACE_MODE);

	/* Create a memory device context for the sprite bitmap */
    if (!MGL_getPNGSize(ALPHA_RGBA_IMAGE_NAME,&bmpWidth,&bmpHeight,&bmpDepth,&bmpPF))
		MGL_fatalError("Unable to load PNG file!");
	if ((memdc = MGL_createMemoryDC(bmpWidth,bmpHeight,bmpDepth,&bmpPF)) == NULL)
		MGL_fatalError(MGL_errorMsg(MGL_result()));

	/* Load a bitmap into the memory device context. The palette gets
	 * loaded into the memory device context as well.
	 */
	if (!MGL_loadPNGIntoDC(memdc,ALPHA_RGBA_IMAGE_NAME,0,0,true))
		MGL_fatalError(MGL_errorMsg(MGL_result()));

    /* Setup alpha blended effects */
    fx.flags = MGL_BLT_BLEND;
    fx.srcBlendFunc = MGL_BLEND_SRCALPHAFAST;
    fx.dstBlendFunc = MGL_BLEND_SRCALPHAFAST;

	/* Copy image from image in memory to the screen. */
    while (!checkEvent()) {
        x = MGL_random(maxx-bmpWidth);
        y = MGL_random(maxy-bmpHeight);
        MGL_bitBltFxCoord(backdc,memdc,0,0,bmpWidth,bmpHeight,x,y,&fx);
        MGL_bitBltCoord(dc,backdc,x,y,x+bmpWidth,y+bmpHeight,x,y,MGL_REPLACE_MODE);
        }

	/* Remove all device contexts from memory. */
    MGL_destroyDC(memdc);
    MGL_destroyDC(backdc);
	return pause();
}

/****************************************************************************
PARAMETERS:
dc     		- Display dc

REMARKS:
Demo showing how to use memory dc's to store alpha sprites and to use blit
them from the memory dc to the display dc.

This version draws all the sprites to an intermediate system memory buffer
and then copies the changed rectangle of data to the display screen. This is
a lot faster than drawing direct to the framebuffer (even with the extra
copy to the screen) because system memory reads a cached and very fast.
****************************************************************************/
ibool alphaGreyBlitMem(
	MGLDC *dc)
{
    palette_t       pal[256];
	pixel_format_t 	bmpPF;
    MGLDC           *backdc;
	MGLDC 			*memdc;
    int 			x,y,bmpWidth,bmpHeight,bmpDepth,oldCheckId;
    bltfx_t         fx;

	/* Display title message at the top of the window. */
    mainWindow(dc,"System Memory Grey Alpha Blit Demo - Draw to back buffer");
    statusLine("Press any key to continue, ESC to Abort");

    /* Create a back buffer memory DC the size of the screen */
	if ((backdc = MGL_createMemoryDC(MGL_sizex(dc),MGL_sizey(dc),MGL_getBitsPerPixel(dc),&dc->pf)) == NULL)
		MGL_fatalError(MGL_errorMsg(MGL_result()));
    MGL_bitBltCoord(backdc,dc,0,0,MGL_sizex(dc),MGL_sizey(dc),0,0,MGL_REPLACE_MODE);

	/* Create a memory device context for the sprite bitmap */
    if (!MGL_getPNGSize(ALPHA_GREY_IMAGE_NAME,&bmpWidth,&bmpHeight,&bmpDepth,&bmpPF))
		MGL_fatalError("Unable to load PNG file!");
	if ((memdc = MGL_createMemoryDC(bmpWidth,bmpHeight,bmpDepth,&bmpPF)) == NULL)
		MGL_fatalError(MGL_errorMsg(MGL_result()));

	/* Load a bitmap into the memory device context. The palette gets
	 * loaded into the memory device context as well.
	 */
	if (!MGL_loadPNGIntoDC(memdc,ALPHA_GREY_IMAGE_NAME,0,0,true))
		MGL_fatalError(MGL_errorMsg(MGL_result()));

    /* Set the palette for the destination DC and turn of identity palette
     * checking. This provides the fastest blit performance because the
     * color translation vector is not re-built for every blit but is
     * instead taken from the destination DC color table (ie: bitmap
     * source palette is ignored).
     */
    MGL_getPalette(memdc,pal,MGL_getPaletteSize(memdc),0);
    MGL_setPalette(backdc,pal,MGL_getPaletteSize(memdc),0);
    MGL_realizePalette(backdc,MGL_getPaletteSize(memdc),0,true);
    oldCheckId = MGL_checkIdentityPalette(false);

    /* Setup alpha blended effects */
    fx.flags = MGL_BLT_BLEND;
    fx.srcBlendFunc = MGL_BLEND_SRCALPHAFAST;
    fx.dstBlendFunc = MGL_BLEND_SRCALPHAFAST;

	/* Copy image from image in memory to the screen. */
    while (!checkEvent()) {
        x = MGL_random(maxx-bmpWidth);
        y = MGL_random(maxy-bmpHeight);
        MGL_bitBltFxCoord(backdc,memdc,0,0,bmpWidth,bmpHeight,x,y,&fx);
        MGL_bitBltCoord(dc,backdc,x,y,x+bmpWidth,y+bmpHeight,x,y,MGL_REPLACE_MODE);
        }

	/* Remove all device contexts from memory. */
    MGL_destroyDC(memdc);
    MGL_destroyDC(backdc);
    MGL_checkIdentityPalette(oldCheckId);
    MGL_setDefaultPalette(dc);
	return pause();
}

/****************************************************************************
PARAMETERS:
dc     		- Display dc

REMARKS:
Demo showing how to use memory dc's to store alpha sprites and to use blit
them from the memory dc to the display dc.

This version draws all the sprites to an intermediate system memory buffer
and then copies the changed rectangle of data to the display screen. This is
a lot faster than drawing direct to the framebuffer (even with the extra
copy to the screen) because system memory reads a cached and very fast.
****************************************************************************/
ibool alpha8BitBlitMem(
	MGLDC *dc)
{
    palette_t       pal[256];
	pixel_format_t 	bmpPF;
    MGLDC           *backdc;
	MGLDC 			*memdc;
    int 			x,y,bmpWidth,bmpHeight,bmpDepth,oldCheckId;
    bltfx_t         fx;

	/* Display title message at the top of the window. */
    mainWindow(dc,"System Memory 8-bit + Alpha Blit Demo - Draw to back buffer");
    statusLine("Press any key to continue, ESC to Abort");

    /* Create a back buffer memory DC the size of the screen */
	if ((backdc = MGL_createMemoryDC(MGL_sizex(dc),MGL_sizey(dc),MGL_getBitsPerPixel(dc),&dc->pf)) == NULL)
		MGL_fatalError(MGL_errorMsg(MGL_result()));
    MGL_bitBltCoord(backdc,dc,0,0,MGL_sizex(dc),MGL_sizey(dc),0,0,MGL_REPLACE_MODE);

	/* Create a memory device context for the sprite bitmap */
    if (!MGL_getPNGSize(ALPHA_8BIT_IMAGE_NAME,&bmpWidth,&bmpHeight,&bmpDepth,&bmpPF))
		MGL_fatalError("Unable to load PNG file!");
	if ((memdc = MGL_createMemoryDC(bmpWidth,bmpHeight,bmpDepth,&bmpPF)) == NULL)
		MGL_fatalError(MGL_errorMsg(MGL_result()));

	/* Load a bitmap into the memory device context. The palette gets
	 * loaded into the memory device context as well.
	 */
	if (!MGL_loadPNGIntoDC(memdc,ALPHA_8BIT_IMAGE_NAME,0,0,true))
		MGL_fatalError(MGL_errorMsg(MGL_result()));

    /* Set the palette for the destination DC and turn of identity palette
     * checking. This provides the fastest blit performance because the
     * color translation vector is not re-built for every blit but is
     * instead taken from the destination DC color table (ie: bitmap
     * source palette is ignored).
     */
    MGL_getPalette(memdc,pal,MGL_getPaletteSize(memdc),0);
    MGL_setPalette(backdc,pal,MGL_getPaletteSize(memdc),0);
    MGL_realizePalette(backdc,MGL_getPaletteSize(memdc),0,true);
    oldCheckId = MGL_checkIdentityPalette(false);

    /* Setup alpha blended effects */
    fx.flags = MGL_BLT_BLEND;
    fx.srcBlendFunc = MGL_BLEND_SRCALPHAFAST;
    fx.dstBlendFunc = MGL_BLEND_SRCALPHAFAST;

	/* Copy image from image in memory to the screen. */
    while (!checkEvent()) {
        x = MGL_random(maxx-bmpWidth);
        y = MGL_random(maxy-bmpHeight);
        MGL_bitBltFxCoord(backdc,memdc,0,0,bmpWidth,bmpHeight,x,y,&fx);
        MGL_bitBltCoord(dc,backdc,x,y,x+bmpWidth,y+bmpHeight,x,y,MGL_REPLACE_MODE);
        }

	/* Remove all device contexts from memory. */
    MGL_destroyDC(memdc);
    MGL_destroyDC(backdc);
    MGL_checkIdentityPalette(oldCheckId);
    MGL_setDefaultPalette(dc);
	return pause();
}

/****************************************************************************
PARAMETERS:
dc     		- Display dc

REMARKS:
Demo showing how to use load alpha sprites into a bitmap_t and to blit
them from the bitmap_t to the display dc.
****************************************************************************/
ibool alphaRGBABlitBitmap(
	MGLDC *dc)
{
    MGLDC           *backdc;
    bitmap_t        *bitmap;
    int 			x,y;
    bltfx_t         fx;

	/* Display title message at the top of the window. */
    mainWindow(dc,"System Memory Alpha Blit Demo - Draw from bitmap_t");
    statusLine("Press any key to continue, ESC to Abort");

    /* Create a back buffer memory DC the size of the screen */
	if ((backdc = MGL_createMemoryDC(MGL_sizex(dc),MGL_sizey(dc),MGL_getBitsPerPixel(dc),&dc->pf)) == NULL)
		MGL_fatalError(MGL_errorMsg(MGL_result()));
    MGL_bitBltCoord(backdc,dc,0,0,MGL_sizex(dc),MGL_sizey(dc),0,0,MGL_REPLACE_MODE);

	/* Load the PNG bitmap */
    if ((bitmap = MGL_loadPNG(ALPHA_RGBA_IMAGE_NAME,true)) == NULL)
		MGL_fatalError(MGL_errorMsg(MGL_result()));

    /* Setup alpha blended effects */
    fx.flags = MGL_BLT_BLEND;
    fx.srcBlendFunc = MGL_BLEND_SRCALPHAFAST;
    fx.dstBlendFunc = MGL_BLEND_SRCALPHAFAST;

	/* Copy image from image in memory to the screen. */
    while (!checkEvent()) {
        x = MGL_random(maxx - bitmap->width);
        y = MGL_random(maxy - bitmap->height);
        MGL_putBitmapFx(backdc,x,y,bitmap,&fx);
        MGL_bitBltCoord(dc,backdc,x,y,x+bitmap->width,y+bitmap->height,x,y,MGL_REPLACE_MODE);
        }

	/* Remove all device contexts from memory. */
    MGL_destroyDC(backdc);
    MGL_unloadBitmap(bitmap);
	return pause();
}

/****************************************************************************
PARAMETERS:
dc     		- Display dc

REMARKS:
Demo showing how to use load alpha sprites into a bitmap_t and to blit
them from the bitmap_t to the display dc.
****************************************************************************/
ibool alphaGreyBlitBitmap(
	MGLDC *dc)
{
    bitmap_t        *bitmap;
    MGLDC           *backdc;
    int 			x,y,oldCheckId;
    bltfx_t         fx;

	/* Display title message at the top of the window. */
    mainWindow(dc,"System Memory Grey Alpha Blit Demo - Draw from bitmap_t");
    statusLine("Press any key to continue, ESC to Abort");

    /* Create a back buffer memory DC the size of the screen */
	if ((backdc = MGL_createMemoryDC(MGL_sizex(dc),MGL_sizey(dc),MGL_getBitsPerPixel(dc),&dc->pf)) == NULL)
		MGL_fatalError(MGL_errorMsg(MGL_result()));
    MGL_bitBltCoord(backdc,dc,0,0,MGL_sizex(dc),MGL_sizey(dc),0,0,MGL_REPLACE_MODE);

	/* Load the PNG bitmap */
    if ((bitmap = MGL_loadPNG(ALPHA_GREY_IMAGE_NAME,true)) == NULL)
		MGL_fatalError(MGL_errorMsg(MGL_result()));

    /* Set the palette for the destination DC and turn of identity palette
     * checking. This provides the fastest blit performance because the
     * color translation vector is not re-built for every blit but is
     * instead taken from the destination DC color table (ie: bitmap
     * source palette is ignored).
     */
    if (bitmap->pal) {
        MGL_setPalette(backdc,bitmap->pal,256,0);
        MGL_realizePalette(backdc,256,0,true);
        }
    oldCheckId = MGL_checkIdentityPalette(false);

    /* Setup alpha blended effects */
    fx.flags = MGL_BLT_BLEND;
    fx.srcBlendFunc = MGL_BLEND_SRCALPHAFAST;
    fx.dstBlendFunc = MGL_BLEND_SRCALPHAFAST;

	/* Copy image from image in memory to the screen. */
    while (!checkEvent()) {
        x = MGL_random(maxx - bitmap->width);
        y = MGL_random(maxy - bitmap->height);
        MGL_putBitmapFx(backdc,x,y,bitmap,&fx);
        MGL_bitBltCoord(dc,backdc,x,y,x+bitmap->width,y+bitmap->height,x,y,MGL_REPLACE_MODE);
        }

	/* Remove all device contexts from memory. */
    MGL_destroyDC(backdc);
    MGL_unloadBitmap(bitmap);
    MGL_checkIdentityPalette(oldCheckId);
    MGL_setDefaultPalette(dc);
	return pause();
}

/****************************************************************************
PARAMETERS:
dc     		- Display dc

REMARKS:
Demo showing how to use load alpha sprites into a bitmap_t and to blit
them from the bitmap_t to the display dc.
****************************************************************************/
ibool alpha8BitBlitBitmap(
	MGLDC *dc)
{
    bitmap_t        *bitmap;
    MGLDC           *backdc;
    int 			x,y,oldCheckId;
    bltfx_t         fx;

	/* Display title message at the top of the window. */
    mainWindow(dc,"System Memory 8-bit + Alpha Blit Demo - Draw from bitmap_t");
    statusLine("Press any key to continue, ESC to Abort");

    /* Create a back buffer memory DC the size of the screen */
	if ((backdc = MGL_createMemoryDC(MGL_sizex(dc),MGL_sizey(dc),MGL_getBitsPerPixel(dc),&dc->pf)) == NULL)
		MGL_fatalError(MGL_errorMsg(MGL_result()));
    MGL_bitBltCoord(backdc,dc,0,0,MGL_sizex(dc),MGL_sizey(dc),0,0,MGL_REPLACE_MODE);

	/* Load the PNG bitmap */
    if ((bitmap = MGL_loadPNG(ALPHA_8BIT_IMAGE_NAME,true)) == NULL)
		MGL_fatalError(MGL_errorMsg(MGL_result()));

    /* Set the palette for the destination DC and turn of identity palette
     * checking. This provides the fastest blit performance because the
     * color translation vector is not re-built for every blit but is
     * instead taken from the destination DC color table (ie: bitmap
     * source palette is ignored).
     */
    if (bitmap->pal) {
        MGL_setPalette(backdc,bitmap->pal,256,0);
        MGL_realizePalette(backdc,256,0,true);
        }
    oldCheckId = MGL_checkIdentityPalette(false);

    /* Setup alpha blended effects */
    fx.flags = MGL_BLT_BLEND;
    fx.srcBlendFunc = MGL_BLEND_SRCALPHAFAST;
    fx.dstBlendFunc = MGL_BLEND_SRCALPHAFAST;

	/* Copy image from image in memory to the screen. */
    while (!checkEvent()) {
        x = MGL_random(maxx - bitmap->width);
        y = MGL_random(maxy - bitmap->height);
        MGL_putBitmapFx(backdc,x,y,bitmap,&fx);
        MGL_bitBltCoord(dc,backdc,x,y,x+bitmap->width,y+bitmap->height,x,y,MGL_REPLACE_MODE);
        }

	/* Remove all device contexts from memory. */
    MGL_destroyDC(backdc);
    MGL_unloadBitmap(bitmap);
    MGL_checkIdentityPalette(oldCheckId);
    MGL_setDefaultPalette(dc);
	return pause();
}

/****************************************************************************
PARAMETERS:
dc     		- Display dc

REMARKS:
Demo showing how to use memory dc's to store alpha sprites and to use blit
them from the memory dc to the display dc.

This version draws all the sprites to an intermediate system memory buffer
and then copies the changed rectangle of data to the display screen. This is
a lot faster than drawing direct to the framebuffer (even with the extra
copy to the screen) because system memory reads a cached and very fast.
****************************************************************************/
ibool alphaRGBABlitBitmapFromDC(
	MGLDC *dc)
{
	pixel_format_t 	bmpPF;
    MGLDC           *backdc;
	MGLDC 			*memdc;
    bitmap_t        *bitmap;
    int 			x,y,bmpWidth,bmpHeight,bmpDepth;
    bltfx_t         fx;

	/* Display title message at the top of the window. */
    mainWindow(dc,"System Memory Alpha Blit Demo - Bitmap from DC");
    statusLine("Press any key to continue, ESC to Abort");

    /* Create a back buffer memory DC the size of the screen */
	if ((backdc = MGL_createMemoryDC(MGL_sizex(dc),MGL_sizey(dc),MGL_getBitsPerPixel(dc),&dc->pf)) == NULL)
		MGL_fatalError(MGL_errorMsg(MGL_result()));
    MGL_bitBltCoord(backdc,dc,0,0,MGL_sizex(dc),MGL_sizey(dc),0,0,MGL_REPLACE_MODE);

	/* Create a memory device context for the sprite bitmap */
    if (!MGL_getPNGSize(ALPHA_RGBA_IMAGE_NAME,&bmpWidth,&bmpHeight,&bmpDepth,&bmpPF))
		MGL_fatalError("Unable to load PNG file!");
	if ((memdc = MGL_createMemoryDC(bmpWidth,bmpHeight,bmpDepth,&bmpPF)) == NULL)
		MGL_fatalError(MGL_errorMsg(MGL_result()));

	/* Load a bitmap into the memory device context. The palette gets
	 * loaded into the memory device context as well.
	 */
	if (!MGL_loadPNGIntoDC(memdc,ALPHA_RGBA_IMAGE_NAME,0,0,true))
		MGL_fatalError(MGL_errorMsg(MGL_result()));
    if ((bitmap = MGL_getBitmapFromDC(memdc,0,0,MGL_sizex(memdc),MGL_sizey(memdc),true)) == NULL)
		MGL_fatalError(MGL_errorMsg(MGL_result()));

    /* Setup alpha blended effects */
    fx.flags = MGL_BLT_BLEND;
    fx.srcBlendFunc = MGL_BLEND_SRCALPHAFAST;
    fx.dstBlendFunc = MGL_BLEND_SRCALPHAFAST;

	/* Copy image from image in memory to the screen. */
    while (!checkEvent()) {
        x = MGL_random(maxx-bmpWidth);
        y = MGL_random(maxy-bmpHeight);
        MGL_putBitmapFx(backdc,x,y,bitmap,&fx);
        MGL_bitBltCoord(dc,backdc,x,y,x+bmpWidth,y+bmpHeight,x,y,MGL_REPLACE_MODE);
        }

	/* Remove all device contexts from memory. */
    MGL_destroyDC(memdc);
    MGL_destroyDC(backdc);
    MGL_unloadBitmap(bitmap);
	return pause();
}

/****************************************************************************
PARAMETERS:
dc     		- Display dc

REMARKS:
Demo showing how to use memory dc's to store alpha sprites and to use blit
them from the memory dc to the display dc.

This version draws all the sprites to an intermediate system memory buffer
and then copies the changed rectangle of data to the display screen. This is
a lot faster than drawing direct to the framebuffer (even with the extra
copy to the screen) because system memory reads a cached and very fast.
****************************************************************************/
ibool alphaGreyBlitBitmapFromDC(
	MGLDC *dc)
{
    palette_t       pal[256];
	pixel_format_t 	bmpPF;
    MGLDC           *backdc;
	MGLDC 			*memdc;
    bitmap_t        *bitmap;
    int 			x,y,bmpWidth,bmpHeight,bmpDepth,oldCheckId;
    bltfx_t         fx;

	/* Display title message at the top of the window. */
    mainWindow(dc,"System Memory Grey Alpha Blit Demo - Bitmap from DC");
    statusLine("Press any key to continue, ESC to Abort");

    /* Create a back buffer memory DC the size of the screen */
	if ((backdc = MGL_createMemoryDC(MGL_sizex(dc),MGL_sizey(dc),MGL_getBitsPerPixel(dc),&dc->pf)) == NULL)
		MGL_fatalError(MGL_errorMsg(MGL_result()));
    MGL_bitBltCoord(backdc,dc,0,0,MGL_sizex(dc),MGL_sizey(dc),0,0,MGL_REPLACE_MODE);

	/* Create a memory device context for the sprite bitmap */
    if (!MGL_getPNGSize(ALPHA_GREY_IMAGE_NAME,&bmpWidth,&bmpHeight,&bmpDepth,&bmpPF))
		MGL_fatalError("Unable to load PNG file!");
	if ((memdc = MGL_createMemoryDC(bmpWidth,bmpHeight,bmpDepth,&bmpPF)) == NULL)
		MGL_fatalError(MGL_errorMsg(MGL_result()));

	/* Load a bitmap into the memory device context. The palette gets
	 * loaded into the memory device context as well.
	 */
	if (!MGL_loadPNGIntoDC(memdc,ALPHA_GREY_IMAGE_NAME,0,0,true))
		MGL_fatalError(MGL_errorMsg(MGL_result()));
    if ((bitmap = MGL_getBitmapFromDC(memdc,0,0,MGL_sizex(memdc),MGL_sizey(memdc),true)) == NULL)
		MGL_fatalError(MGL_errorMsg(MGL_result()));

    /* Set the palette for the destination DC and turn of identity palette
     * checking. This provides the fastest blit performance because the
     * color translation vector is not re-built for every blit but is
     * instead taken from the destination DC color table (ie: bitmap
     * source palette is ignored).
     */
    MGL_getPalette(memdc,pal,MGL_getPaletteSize(memdc),0);
    MGL_setPalette(backdc,pal,MGL_getPaletteSize(memdc),0);
    MGL_realizePalette(backdc,MGL_getPaletteSize(memdc),0,true);
    oldCheckId = MGL_checkIdentityPalette(false);

    /* Setup alpha blended effects */
    fx.flags = MGL_BLT_BLEND;
    fx.srcBlendFunc = MGL_BLEND_SRCALPHAFAST;
    fx.dstBlendFunc = MGL_BLEND_SRCALPHAFAST;

	/* Copy image from image in memory to the screen. */
    while (!checkEvent()) {
        x = MGL_random(maxx-bmpWidth);
        y = MGL_random(maxy-bmpHeight);
        MGL_putBitmapFx(backdc,x,y,bitmap,&fx);
        MGL_bitBltCoord(dc,backdc,x,y,x+bmpWidth,y+bmpHeight,x,y,MGL_REPLACE_MODE);
        }

	/* Remove all device contexts from memory. */
    MGL_destroyDC(memdc);
    MGL_destroyDC(backdc);
    MGL_unloadBitmap(bitmap);
    MGL_checkIdentityPalette(oldCheckId);
    MGL_setDefaultPalette(dc);
	return pause();
}

/****************************************************************************
PARAMETERS:
dc     		- Display dc

REMARKS:
Demo showing how to use memory dc's to store alpha sprites and to use blit
them from the memory dc to the display dc.

This version draws all the sprites to an intermediate system memory buffer
and then copies the changed rectangle of data to the display screen. This is
a lot faster than drawing direct to the framebuffer (even with the extra
copy to the screen) because system memory reads a cached and very fast.
****************************************************************************/
ibool alpha8BitBlitBitmapFromDC(
	MGLDC *dc)
{
    palette_t       pal[256];
	pixel_format_t 	bmpPF;
    MGLDC           *backdc;
	MGLDC 			*memdc;
    bitmap_t        *bitmap;
    int 			x,y,bmpWidth,bmpHeight,bmpDepth,oldCheckId;
    bltfx_t         fx;

	/* Display title message at the top of the window. */
    mainWindow(dc,"System Memory 8-bit + Alpha Blit Demo - Bitmap from DC");
    statusLine("Press any key to continue, ESC to Abort");

    /* Create a back buffer memory DC the size of the screen */
	if ((backdc = MGL_createMemoryDC(MGL_sizex(dc),MGL_sizey(dc),MGL_getBitsPerPixel(dc),&dc->pf)) == NULL)
		MGL_fatalError(MGL_errorMsg(MGL_result()));
    MGL_bitBltCoord(backdc,dc,0,0,MGL_sizex(dc),MGL_sizey(dc),0,0,MGL_REPLACE_MODE);

	/* Create a memory device context for the sprite bitmap */
    if (!MGL_getPNGSize(ALPHA_8BIT_IMAGE_NAME,&bmpWidth,&bmpHeight,&bmpDepth,&bmpPF))
		MGL_fatalError("Unable to load PNG file!");
	if ((memdc = MGL_createMemoryDC(bmpWidth,bmpHeight,bmpDepth,&bmpPF)) == NULL)
		MGL_fatalError(MGL_errorMsg(MGL_result()));

	/* Load a bitmap into the memory device context. The palette gets
	 * loaded into the memory device context as well.
	 */
	if (!MGL_loadPNGIntoDC(memdc,ALPHA_8BIT_IMAGE_NAME,0,0,true))
		MGL_fatalError(MGL_errorMsg(MGL_result()));
    if ((bitmap = MGL_getBitmapFromDC(memdc,0,0,MGL_sizex(memdc),MGL_sizey(memdc),true)) == NULL)
		MGL_fatalError(MGL_errorMsg(MGL_result()));

    /* Set the palette for the destination DC and turn of identity palette
     * checking. This provides the fastest blit performance because the
     * color translation vector is not re-built for every blit but is
     * instead taken from the destination DC color table (ie: bitmap
     * source palette is ignored).
     */
    MGL_getPalette(memdc,pal,MGL_getPaletteSize(memdc),0);
    MGL_setPalette(backdc,pal,MGL_getPaletteSize(memdc),0);
    MGL_realizePalette(backdc,MGL_getPaletteSize(memdc),0,true);
    oldCheckId = MGL_checkIdentityPalette(false);

    /* Setup alpha blended effects */
    fx.flags = MGL_BLT_BLEND;
    fx.srcBlendFunc = MGL_BLEND_SRCALPHAFAST;
    fx.dstBlendFunc = MGL_BLEND_SRCALPHAFAST;

	/* Copy image from image in memory to the screen. */
    while (!checkEvent()) {
        x = MGL_random(maxx-bmpWidth);
        y = MGL_random(maxy-bmpHeight);
        MGL_putBitmapFx(backdc,x,y,bitmap,&fx);
        MGL_bitBltCoord(dc,backdc,x,y,x+bmpWidth,y+bmpHeight,x,y,MGL_REPLACE_MODE);
        }

	/* Remove all device contexts from memory. */
    MGL_destroyDC(memdc);
    MGL_destroyDC(backdc);
    MGL_unloadBitmap(bitmap);
    MGL_checkIdentityPalette(oldCheckId);
    MGL_setDefaultPalette(dc);
	return pause();
}


void demo(MGLDC *dc)
{
	/* Get the screen size and store them. */
    maxx = MGL_maxx();
    maxy = MGL_maxy();

	/* Display title message at the top of the window. */
	if (dc->mi.bitsPerPixel < 15) {
		mainWindow(dc,"Alpha blending requires 15bpp or higher!");
        statusLine("Press any key to abort");
        pause();
        }
    else {
        if (!alphaRGBABlit(dc))
            return;
        if (!alphaGreyBlit(dc))
            return;
        if (!alpha8BitBlit(dc))
            return;
        if (!alphaRGBABlitMem(dc))
            return;
        if (!alphaGreyBlitMem(dc))
            return;
        if (!alpha8BitBlitMem(dc))
            return;
        if (!alphaRGBABlitBitmap(dc))
            return;
        if (!alphaGreyBlitBitmap(dc))
            return;
        if (!alpha8BitBlitBitmap(dc))
            return;
        if (!alphaRGBABlitBitmapFromDC(dc))
            return;
        if (!alphaGreyBlitBitmapFromDC(dc))
            return;
        if (!alpha8BitBlitBitmapFromDC(dc))
            return;
        }
}

