src/video/SDL_blit_0.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 16 May 2005 05:34:58 +0000
changeset 1057 e9d23bb80140
parent 769 b8d311d90021
child 1058 e6c91fd1911e
permissions -rw-r--r--
Date: Mon, 02 May 2005 04:23:16 -0500
From: Jonathan Atkins
Subject: Re: [PATCH] *CRITICAL* 8bit direct RGB palette not being created

I think that SDL_AllocFormat should create the palette for all 8bit
surfaces. And when the RGBAmasks match the normal 3:3:2:0 we need to
apply the old behavior. If the mask doesn't match that, then we need
to make the right palette assuming the masks are valid (I don't think
we validate any masks for high color surfaces...so we wouldn't here)
Then there's always a palette available for the 8bit surfaces.
This restores the normal behavior and allows for masks to create
palettes automatically for odd masks even, which would be a neato
thing to have in there, as SDL never did this before.
slouken@0
     1
/*
slouken@0
     2
    SDL - Simple DirectMedia Layer
slouken@769
     3
    Copyright (C) 1997-2004 Sam Lantinga
slouken@0
     4
slouken@0
     5
    This library is free software; you can redistribute it and/or
slouken@0
     6
    modify it under the terms of the GNU Library General Public
slouken@0
     7
    License as published by the Free Software Foundation; either
slouken@0
     8
    version 2 of the License, or (at your option) any later version.
slouken@0
     9
slouken@0
    10
    This library is distributed in the hope that it will be useful,
slouken@0
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@0
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@0
    13
    Library General Public License for more details.
slouken@0
    14
slouken@0
    15
    You should have received a copy of the GNU Library General Public
slouken@0
    16
    License along with this library; if not, write to the Free
slouken@0
    17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
slouken@0
    18
slouken@0
    19
    Sam Lantinga
slouken@252
    20
    slouken@libsdl.org
slouken@0
    21
*/
slouken@0
    22
slouken@0
    23
#ifdef SAVE_RCSID
slouken@0
    24
static char rcsid =
slouken@0
    25
 "@(#) $Id$";
slouken@0
    26
#endif
slouken@0
    27
slouken@0
    28
#include <stdio.h>
slouken@0
    29
#include <string.h>
slouken@0
    30
slouken@0
    31
#include "SDL_types.h"
slouken@0
    32
#include "SDL_video.h"
slouken@0
    33
#include "SDL_blit.h"
slouken@0
    34
slouken@0
    35
/* Functions to blit from bitmaps to other surfaces */
slouken@0
    36
slouken@0
    37
static void BlitBto1(SDL_BlitInfo *info)
slouken@0
    38
{
slouken@0
    39
	int c;
slouken@0
    40
	int width, height;
slouken@0
    41
	Uint8 *src, *map, *dst;
slouken@0
    42
	int srcskip, dstskip;
slouken@0
    43
slouken@0
    44
	/* Set up some basic variables */
slouken@0
    45
	width = info->d_width;
slouken@0
    46
	height = info->d_height;
slouken@0
    47
	src = info->s_pixels;
slouken@0
    48
	srcskip = info->s_skip;
slouken@0
    49
	dst = info->d_pixels;
slouken@0
    50
	dstskip = info->d_skip;
slouken@0
    51
	map = info->table;
slouken@0
    52
	srcskip += width-(width+7)/8;
slouken@0
    53
slouken@0
    54
	if ( map ) {
slouken@0
    55
		while ( height-- ) {
slouken@0
    56
		        Uint8 byte = 0, bit;
slouken@0
    57
	    		for ( c=0; c<width; ++c ) {
slouken@91
    58
				if ( (c&7) == 0 ) {
slouken@0
    59
					byte = *src++;
slouken@0
    60
				}
slouken@0
    61
				bit = (byte&0x80)>>7;
slouken@0
    62
				if ( 1 ) {
slouken@0
    63
				  *dst = map[bit];
slouken@0
    64
				}
slouken@0
    65
				dst++;
slouken@0
    66
				byte <<= 1;
slouken@0
    67
			}
slouken@0
    68
			src += srcskip;
slouken@0
    69
			dst += dstskip;
slouken@0
    70
		}
slouken@0
    71
	} else {
slouken@0
    72
		while ( height-- ) {
slouken@0
    73
		        Uint8 byte = 0, bit;
slouken@0
    74
	    		for ( c=0; c<width; ++c ) {
slouken@91
    75
				if ( (c&7) == 0 ) {
slouken@0
    76
					byte = *src++;
slouken@0
    77
				}
slouken@0
    78
				bit = (byte&0x80)>>7;
slouken@0
    79
				if ( 1 ) {
slouken@0
    80
				  *dst = bit;
slouken@0
    81
				}
slouken@0
    82
				dst++;
slouken@0
    83
				byte <<= 1;
slouken@0
    84
			}
slouken@0
    85
			src += srcskip;
slouken@0
    86
			dst += dstskip;
slouken@0
    87
		}
slouken@0
    88
	}
slouken@0
    89
}
slouken@0
    90
static void BlitBto2(SDL_BlitInfo *info)
slouken@0
    91
{
slouken@0
    92
	int c;
slouken@0
    93
	int width, height;
slouken@0
    94
	Uint8 *src;
slouken@0
    95
	Uint16 *map, *dst;
slouken@0
    96
	int srcskip, dstskip;
slouken@0
    97
slouken@0
    98
	/* Set up some basic variables */
slouken@0
    99
	width = info->d_width;
slouken@0
   100
	height = info->d_height;
slouken@0
   101
	src = info->s_pixels;
slouken@0
   102
	srcskip = info->s_skip;
slouken@0
   103
	dst = (Uint16 *)info->d_pixels;
slouken@0
   104
	dstskip = info->d_skip/2;
slouken@0
   105
	map = (Uint16 *)info->table;
slouken@0
   106
	srcskip += width-(width+7)/8;
slouken@0
   107
slouken@0
   108
	while ( height-- ) {
slouken@0
   109
	        Uint8 byte = 0, bit;
slouken@0
   110
	    	for ( c=0; c<width; ++c ) {
slouken@91
   111
			if ( (c&7) == 0 ) {
slouken@0
   112
				byte = *src++;
slouken@0
   113
			}
slouken@0
   114
			bit = (byte&0x80)>>7;
slouken@0
   115
			if ( 1 ) {
slouken@0
   116
				*dst = map[bit];
slouken@0
   117
			}
slouken@0
   118
			byte <<= 1;
slouken@0
   119
			dst++;
slouken@0
   120
		}
slouken@0
   121
		src += srcskip;
slouken@0
   122
		dst += dstskip;
slouken@0
   123
	}
slouken@0
   124
}
slouken@0
   125
static void BlitBto3(SDL_BlitInfo *info)
slouken@0
   126
{
slouken@0
   127
	int c, o;
slouken@0
   128
	int width, height;
slouken@0
   129
	Uint8 *src, *map, *dst;
slouken@0
   130
	int srcskip, dstskip;
slouken@0
   131
slouken@0
   132
	/* Set up some basic variables */
slouken@0
   133
	width = info->d_width;
slouken@0
   134
	height = info->d_height;
slouken@0
   135
	src = info->s_pixels;
slouken@0
   136
	srcskip = info->s_skip;
slouken@0
   137
	dst = info->d_pixels;
slouken@0
   138
	dstskip = info->d_skip;
slouken@0
   139
	map = info->table;
slouken@0
   140
	srcskip += width-(width+7)/8;
slouken@0
   141
slouken@0
   142
	while ( height-- ) {
slouken@0
   143
	        Uint8 byte = 0, bit;
slouken@0
   144
	    	for ( c=0; c<width; ++c ) {
slouken@91
   145
			if ( (c&7) == 0 ) {
slouken@0
   146
				byte = *src++;
slouken@0
   147
			}
slouken@0
   148
			bit = (byte&0x80)>>7;
slouken@0
   149
			if ( 1 ) {
slouken@0
   150
				o = bit * 4;
slouken@0
   151
				dst[0] = map[o++];
slouken@0
   152
				dst[1] = map[o++];
slouken@0
   153
				dst[2] = map[o++];
slouken@0
   154
			}
slouken@0
   155
			byte <<= 1;
slouken@0
   156
			dst += 3;
slouken@0
   157
		}
slouken@0
   158
		src += srcskip;
slouken@0
   159
		dst += dstskip;
slouken@0
   160
	}
slouken@0
   161
}
slouken@0
   162
static void BlitBto4(SDL_BlitInfo *info)
slouken@0
   163
{
slouken@0
   164
	int width, height;
slouken@0
   165
	Uint8 *src;
slouken@0
   166
	Uint32 *map, *dst;
slouken@0
   167
	int srcskip, dstskip;
slouken@0
   168
	int c;
slouken@0
   169
slouken@0
   170
	/* Set up some basic variables */
slouken@0
   171
	width = info->d_width;
slouken@0
   172
	height = info->d_height;
slouken@0
   173
	src = info->s_pixels;
slouken@0
   174
	srcskip = info->s_skip;
slouken@0
   175
	dst = (Uint32 *)info->d_pixels;
slouken@0
   176
	dstskip = info->d_skip/4;
slouken@0
   177
	map = (Uint32 *)info->table;
slouken@0
   178
	srcskip += width-(width+7)/8;
slouken@0
   179
slouken@0
   180
	while ( height-- ) {
slouken@0
   181
	        Uint8 byte = 0, bit;
slouken@0
   182
	    	for ( c=0; c<width; ++c ) {
slouken@91
   183
			if ( (c&7) == 0 ) {
slouken@0
   184
				byte = *src++;
slouken@0
   185
			}
slouken@0
   186
			bit = (byte&0x80)>>7;
slouken@0
   187
			if ( 1 ) {
slouken@0
   188
				*dst = map[bit];
slouken@0
   189
			}
slouken@0
   190
			byte <<= 1;
slouken@0
   191
			dst++;
slouken@0
   192
		}
slouken@0
   193
		src += srcskip;
slouken@0
   194
		dst += dstskip;
slouken@0
   195
	}
slouken@0
   196
}
slouken@0
   197
slouken@0
   198
static void BlitBto1Key(SDL_BlitInfo *info)
slouken@0
   199
{
slouken@0
   200
        int width = info->d_width;
slouken@0
   201
	int height = info->d_height;
slouken@0
   202
	Uint8 *src = info->s_pixels;
slouken@0
   203
	Uint8 *dst = info->d_pixels;
slouken@0
   204
	int srcskip = info->s_skip;
slouken@0
   205
	int dstskip = info->d_skip;
slouken@0
   206
	Uint32 ckey = info->src->colorkey;
slouken@0
   207
	Uint8 *palmap = info->table;
slouken@0
   208
	int c;
slouken@0
   209
slouken@0
   210
	/* Set up some basic variables */
slouken@0
   211
	srcskip += width-(width+7)/8;
slouken@0
   212
slouken@0
   213
	if ( palmap ) {
slouken@0
   214
		while ( height-- ) {
slouken@0
   215
		        Uint8  byte = 0, bit;
slouken@0
   216
	    		for ( c=0; c<width; ++c ) {
slouken@91
   217
				if ( (c&7) == 0 ) {
slouken@0
   218
					byte = *src++;
slouken@0
   219
				}
slouken@0
   220
				bit = (byte&0x80)>>7;
slouken@0
   221
				if ( bit != ckey ) {
slouken@0
   222
				  *dst = palmap[bit];
slouken@0
   223
				}
slouken@0
   224
				dst++;
slouken@0
   225
				byte <<= 1;
slouken@0
   226
			}
slouken@0
   227
			src += srcskip;
slouken@0
   228
			dst += dstskip;
slouken@0
   229
		}
slouken@0
   230
	} else {
slouken@0
   231
		while ( height-- ) {
slouken@0
   232
		        Uint8  byte = 0, bit;
slouken@0
   233
	    		for ( c=0; c<width; ++c ) {
slouken@91
   234
				if ( (c&7) == 0 ) {
slouken@0
   235
					byte = *src++;
slouken@0
   236
				}
slouken@0
   237
				bit = (byte&0x80)>>7;
slouken@0
   238
				if ( bit != ckey ) {
slouken@0
   239
				  *dst = bit;
slouken@0
   240
				}
slouken@0
   241
				dst++;
slouken@0
   242
				byte <<= 1;
slouken@0
   243
			}
slouken@0
   244
			src += srcskip;
slouken@0
   245
			dst += dstskip;
slouken@0
   246
		}
slouken@0
   247
	}
slouken@0
   248
}
slouken@0
   249
slouken@0
   250
static void BlitBto2Key(SDL_BlitInfo *info)
slouken@0
   251
{
slouken@0
   252
        int width = info->d_width;
slouken@0
   253
	int height = info->d_height;
slouken@0
   254
	Uint8 *src = info->s_pixels;
slouken@0
   255
	Uint16 *dstp = (Uint16 *)info->d_pixels;
slouken@0
   256
	int srcskip = info->s_skip;
slouken@0
   257
	int dstskip = info->d_skip;
slouken@0
   258
	Uint32 ckey = info->src->colorkey;
slouken@0
   259
	Uint8 *palmap = info->table;
slouken@0
   260
	int c;
slouken@0
   261
slouken@0
   262
	/* Set up some basic variables */
slouken@0
   263
	srcskip += width-(width+7)/8;
slouken@0
   264
	dstskip /= 2;
slouken@0
   265
slouken@0
   266
	while ( height-- ) {
slouken@0
   267
	        Uint8 byte = 0, bit;
slouken@0
   268
	    	for ( c=0; c<width; ++c ) {
slouken@91
   269
			if ( (c&7) == 0 ) {
slouken@0
   270
				byte = *src++;
slouken@0
   271
			}
slouken@0
   272
			bit = (byte&0x80)>>7;
slouken@0
   273
			if ( bit != ckey ) {
slouken@0
   274
				*dstp=((Uint16 *)palmap)[bit];
slouken@0
   275
			}
slouken@0
   276
			byte <<= 1;
slouken@0
   277
			dstp++;
slouken@0
   278
		}
slouken@0
   279
		src += srcskip;
slouken@0
   280
		dstp += dstskip;
slouken@0
   281
	}
slouken@0
   282
}
slouken@0
   283
slouken@0
   284
static void BlitBto3Key(SDL_BlitInfo *info)
slouken@0
   285
{
slouken@0
   286
        int width = info->d_width;
slouken@0
   287
	int height = info->d_height;
slouken@0
   288
	Uint8 *src = info->s_pixels;
slouken@0
   289
	Uint8 *dst = info->d_pixels;
slouken@0
   290
	int srcskip = info->s_skip;
slouken@0
   291
	int dstskip = info->d_skip;
slouken@0
   292
	Uint32 ckey = info->src->colorkey;
slouken@0
   293
	Uint8 *palmap = info->table;
slouken@0
   294
	int c;
slouken@0
   295
slouken@0
   296
	/* Set up some basic variables */
slouken@0
   297
	srcskip += width-(width+7)/8;
slouken@0
   298
slouken@0
   299
	while ( height-- ) {
slouken@0
   300
	        Uint8  byte = 0, bit;
slouken@0
   301
	    	for ( c=0; c<width; ++c ) {
slouken@91
   302
			if ( (c&7) == 0 ) {
slouken@0
   303
				byte = *src++;
slouken@0
   304
			}
slouken@0
   305
			bit = (byte&0x80)>>7;
slouken@0
   306
			if ( bit != ckey ) {
slouken@0
   307
				memcpy(dst, &palmap[bit*4], 3);
slouken@0
   308
			}
slouken@0
   309
			byte <<= 1;
slouken@0
   310
			dst += 3;
slouken@0
   311
		}
slouken@0
   312
		src += srcskip;
slouken@0
   313
		dst += dstskip;
slouken@0
   314
	}
slouken@0
   315
}
slouken@0
   316
slouken@0
   317
static void BlitBto4Key(SDL_BlitInfo *info)
slouken@0
   318
{
slouken@0
   319
        int width = info->d_width;
slouken@0
   320
	int height = info->d_height;
slouken@0
   321
	Uint8 *src = info->s_pixels;
slouken@0
   322
	Uint32 *dstp = (Uint32 *)info->d_pixels;
slouken@0
   323
	int srcskip = info->s_skip;
slouken@0
   324
	int dstskip = info->d_skip;
slouken@0
   325
	Uint32 ckey = info->src->colorkey;
slouken@0
   326
	Uint8 *palmap = info->table;
slouken@0
   327
	int c;
slouken@0
   328
slouken@0
   329
	/* Set up some basic variables */
slouken@0
   330
	srcskip += width-(width+7)/8;
slouken@0
   331
	dstskip /= 4;
slouken@0
   332
slouken@0
   333
	while ( height-- ) {
slouken@0
   334
	        Uint8 byte = 0, bit;
slouken@0
   335
	    	for ( c=0; c<width; ++c ) {
slouken@91
   336
			if ( (c&7) == 0 ) {
slouken@0
   337
				byte = *src++;
slouken@0
   338
			}
slouken@0
   339
			bit = (byte&0x80)>>7;
slouken@0
   340
			if ( bit != ckey ) {
slouken@0
   341
				*dstp=((Uint32 *)palmap)[bit];
slouken@0
   342
			}
slouken@0
   343
			byte <<= 1;
slouken@0
   344
			dstp++;
slouken@0
   345
		}
slouken@0
   346
		src += srcskip;
slouken@0
   347
		dstp += dstskip;
slouken@0
   348
	}
slouken@0
   349
}
slouken@0
   350
slouken@0
   351
static void BlitBtoNAlpha(SDL_BlitInfo *info)
slouken@0
   352
{
slouken@0
   353
        int width = info->d_width;
slouken@0
   354
	int height = info->d_height;
slouken@0
   355
	Uint8 *src = info->s_pixels;
slouken@0
   356
	Uint8 *dst = info->d_pixels;
slouken@0
   357
	int srcskip = info->s_skip;
slouken@0
   358
	int dstskip = info->d_skip;
slouken@0
   359
	const SDL_Color *srcpal	= info->src->palette->colors;
slouken@0
   360
	SDL_PixelFormat *dstfmt = info->dst;
slouken@0
   361
	int  dstbpp;
slouken@0
   362
	int c;
slouken@0
   363
	const int A = info->src->alpha;
slouken@0
   364
slouken@0
   365
	/* Set up some basic variables */
slouken@0
   366
	dstbpp = dstfmt->BytesPerPixel;
slouken@0
   367
	srcskip += width-(width+7)/8;
slouken@0
   368
slouken@0
   369
	while ( height-- ) {
slouken@0
   370
	        Uint8 byte = 0, bit;
slouken@0
   371
	    	for ( c=0; c<width; ++c ) {
slouken@91
   372
			if ( (c&7) == 0 ) {
slouken@0
   373
				byte = *src++;
slouken@0
   374
			}
slouken@0
   375
			bit = (byte&0x80)>>7;
slouken@0
   376
			if ( 1 ) {
slouken@0
   377
			        Uint32 pixel;
slouken@0
   378
			        unsigned sR, sG, sB;
slouken@0
   379
				unsigned dR, dG, dB;
slouken@0
   380
				sR = srcpal[bit].r;
slouken@0
   381
				sG = srcpal[bit].g;
slouken@0
   382
				sB = srcpal[bit].b;
slouken@0
   383
				DISEMBLE_RGB(dst, dstbpp, dstfmt,
slouken@0
   384
							pixel, dR, dG, dB);
slouken@0
   385
				ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB);
slouken@0
   386
			  	ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB);
slouken@0
   387
			}
slouken@0
   388
			byte <<= 1;
slouken@0
   389
			dst += dstbpp;
slouken@0
   390
		}
slouken@0
   391
		src += srcskip;
slouken@0
   392
		dst += dstskip;
slouken@0
   393
	}
slouken@0
   394
}
slouken@0
   395
slouken@0
   396
static void BlitBtoNAlphaKey(SDL_BlitInfo *info)
slouken@0
   397
{
slouken@0
   398
        int width = info->d_width;
slouken@0
   399
	int height = info->d_height;
slouken@0
   400
	Uint8 *src = info->s_pixels;
slouken@0
   401
	Uint8 *dst = info->d_pixels;
slouken@0
   402
	int srcskip = info->s_skip;
slouken@0
   403
	int dstskip = info->d_skip;
slouken@0
   404
	SDL_PixelFormat *srcfmt = info->src;
slouken@0
   405
	SDL_PixelFormat *dstfmt = info->dst;
slouken@0
   406
	const SDL_Color *srcpal	= srcfmt->palette->colors;
slouken@0
   407
	int dstbpp;
slouken@0
   408
	int c;
slouken@0
   409
	const int A = srcfmt->alpha;
slouken@0
   410
	Uint32 ckey = srcfmt->colorkey;
slouken@0
   411
slouken@0
   412
	/* Set up some basic variables */
slouken@0
   413
	dstbpp = dstfmt->BytesPerPixel;
slouken@0
   414
	srcskip += width-(width+7)/8;
slouken@0
   415
slouken@0
   416
	while ( height-- ) {
slouken@0
   417
	        Uint8  byte = 0, bit;
slouken@0
   418
	    	for ( c=0; c<width; ++c ) {
slouken@91
   419
			if ( (c&7) == 0 ) {
slouken@0
   420
				byte = *src++;
slouken@0
   421
			}
slouken@0
   422
			bit = (byte&0x80)>>7;
slouken@0
   423
			if ( bit != ckey ) {
slouken@0
   424
			        int sR, sG, sB;
slouken@0
   425
				int dR, dG, dB;
slouken@0
   426
				Uint32 pixel;
slouken@0
   427
				sR = srcpal[bit].r;
slouken@0
   428
				sG = srcpal[bit].g;
slouken@0
   429
				sB = srcpal[bit].b;
slouken@0
   430
				DISEMBLE_RGB(dst, dstbpp, dstfmt,
slouken@0
   431
							pixel, dR, dG, dB);
slouken@0
   432
				ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB);
slouken@0
   433
			  	ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB);
slouken@0
   434
			}
slouken@0
   435
			byte <<= 1;
slouken@0
   436
			dst += dstbpp;
slouken@0
   437
		}
slouken@0
   438
		src += srcskip;
slouken@0
   439
		dst += dstskip;
slouken@0
   440
	}
slouken@0
   441
}
slouken@0
   442
slouken@0
   443
static SDL_loblit bitmap_blit[] = {
slouken@0
   444
	NULL, BlitBto1, BlitBto2, BlitBto3, BlitBto4
slouken@0
   445
};
slouken@0
   446
slouken@0
   447
static SDL_loblit colorkey_blit[] = {
slouken@0
   448
    NULL, BlitBto1Key, BlitBto2Key, BlitBto3Key, BlitBto4Key
slouken@0
   449
};
slouken@0
   450
slouken@0
   451
SDL_loblit SDL_CalculateBlit0(SDL_Surface *surface, int blit_index)
slouken@0
   452
{
slouken@0
   453
	int which;
slouken@0
   454
slouken@1057
   455
	if ( surface->format->BitsPerPixel > 1 ) {
slouken@1057
   456
		/* We don't support sub 8-bit packed pixel modes */
slouken@1057
   457
		return NULL;
slouken@1057
   458
	}
slouken@0
   459
	if ( surface->map->dst->format->BitsPerPixel < 8 ) {
slouken@0
   460
		which = 0;
slouken@0
   461
	} else {
slouken@0
   462
		which = surface->map->dst->format->BytesPerPixel;
slouken@0
   463
	}
slouken@0
   464
	switch(blit_index) {
slouken@0
   465
	case 0:			/* copy */
slouken@0
   466
	    return bitmap_blit[which];
slouken@0
   467
slouken@0
   468
	case 1:			/* colorkey */
slouken@0
   469
	    return colorkey_blit[which];
slouken@0
   470
slouken@0
   471
	case 2:			/* alpha */
slouken@0
   472
	    return which >= 2 ? BlitBtoNAlpha : NULL;
slouken@0
   473
slouken@0
   474
	case 4:			/* alpha + colorkey */
slouken@0
   475
	    return which >= 2 ? BlitBtoNAlphaKey : NULL;
slouken@0
   476
	}
slouken@0
   477
	return NULL;
slouken@0
   478
}
slouken@0
   479