[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [MiNT] gradients,FreeMiNT 1.18



just so people know whats what, here is the code parts:

struct gradient
{
	struct xa_data_hdr *allocs;
	short wmask, hmask;
	short w, h;
	short method;
	short n_steps;
	short steps[8];
	struct rgb_1000 c[16];
};

here are 2 different structs (from c source):

static struct xa_gradient sel_popent_gradient =
{
	NULL,
	0, -1,
	16, 0,
	0,0,{0},
	{{950,950,1000},{800,800,1000}},
};

static struct xa_gradient indbutt_gradient =
{
	NULL,
	-1,   0,
	 0,  16,
	4, 1, { -35, 0, },
	{{700,700,700},{900,900,900},{700,700,700}},	
};


the function with the gradient algorithms:


void _cdecl
create_gradient(XAMFDB *pm, struct rgb_1000 *c, short method, short
n_steps, short *steps, short w, short h )
{
	pm->mfdb.fd_addr = NULL;

	if (screen.pixel_fmt >= 0)
	{
		if (screen.planes > 8)
		{
			int i, j, pixelsize;
			char *data, *ed;
			char *d;
			short wdwidth;
			long pixel, size, scanlen, red, green, blue, ired, igreen, iblue;
			void * (*to)(struct rgb_1000 *pal, void *imgdata);
			void (*rp)(void *, void *, int);
			struct rgb_1000 col;
			
			wdwidth = (w + 15) >> 4;
// 			size = 2L * (long)wdwidth * (long)(screen.planes == 15 ? 16 :
screen.planes) * h;
// 			display("size0 %ld", size);
			switch (screen.planes)
			{
				case 15: to = f_to15[screen.pixel_fmt]; pixelsize = 2; rp =
repeat_16bpixel; break;
				case 16: to = f_to16[screen.pixel_fmt]; pixelsize = 2; rp =
repeat_16bpixel; break;
				case 24: to = f_to24[screen.pixel_fmt]; pixelsize = 3; rp =
repeat_24bpixel; break; //toI24b; break;
				case 32: to = f_to32[screen.pixel_fmt]; pixelsize = 4; rp =
repeat_32bpixel; break; //toM32b; break;
				default: to = NULL; pixelsize = 0; rp = NULL; break;
			}
			scanlen = (long)pixelsize * ((w + 15) & ~15);
			size = (long)scanlen * h;
// 			display("size1 %ld, scanlen = %ld", size, scanlen);
			
			if (!to || !(data = kmalloc(size)))
				return;
// 			display("data %lx, size %ld, to = %lx", data, size, to);

			pm->d_w = w;
			pm->d_h = h;
			pm->mfdb.fd_addr = data; //(void *)((long)pm + sizeof(*pm));
			pm->mfdb.fd_w = (w + 15) & ~15;
			pm->mfdb.fd_h = h;
			pm->mfdb.fd_wdwidth = wdwidth;
			pm->mfdb.fd_stand = 0;
			pm->mfdb.fd_nplanes = screen.planes == 15 ? 16 : screen.planes;
			pm->mfdb.fd_r1 = pm->mfdb.fd_r2 = pm->mfdb.fd_r3 = 0;
			
			scanlen = pm->mfdb.fd_w * pixelsize;

			
			data = pm->mfdb.fd_addr;
			ed = data + size;

			switch (method)
			{
			
			case 0:
			{
				ired = ((long)(c[1].red - c[0].red) << 16) / h;
				igreen = ((long)(c[1].green - c[0].green) << 16) / h;
				iblue = ((long)(c[1].blue - c[0].blue) << 16) / h;
				
				red = (long)c[0].red << 16;
				green = (long)c[0].green << 16;
				blue = (long)c[0].blue << 16;

// 				d = (void *)&pixel;
				for (i = 0; i < h; i++)
				{
					col.red = red >> 16;
					col.green = green >> 16;
					col.blue = blue >> 16;
				#if 1
					(*to)(&col, &pixel);
					(*rp)(&pixel, data, w);
				#else
					for (j = 0; j < w; j++)
					{
						d = (*to)(&col, d);
					}
				#endif
					red += ired;
					green += igreen;
					blue += iblue;
				
					data += scanlen;
				}
				break;
			}
			case 1:
			{
				long rgb[3];
			
				ired = ((long)(c[1].red - c[0].red) << 16) / w;
				igreen = ((long)(c[1].green - c[0].green) << 16) / w;
				iblue = ((long)(c[1].blue - c[0].blue) << 16) / w;
				red = (long)c[0].red << 16;
				green = (long)c[0].green << 16;
				blue = (long)c[0].blue << 16;
			
				rgb[0] = red;
				rgb[1] = green;
				rgb[2] = blue;
				for (i = 0; i < h; i++)
				{
					d = data;
					for (j = 0; j < w; j++)
					{
						col.red = red >> 16;
						col.green = green >> 16;
						col.blue = blue >> 16;
						d = (*to)(&col, d);

						red += ired;
						green += igreen;
						blue += iblue;
					}
					red = rgb[0];
					green = rgb[1];
					blue = rgb[2];
					col = c[0];
					
					data += scanlen;
				}
				break;
			}
			case 2:
			{
				struct rgb_1000 strt;
				long rgb[3];
				long yred, ygreen, yblue;

				yred = ((long)(c[1].red - c[0].red) << 16)  / h;
				ygreen = ((long)(c[1].green - c[0].green) << 16) / h;
				yblue = ((long)(c[1].blue - c[0].blue) << 16) / h;
								
				
				col = strt = c[0]; //*start;
				rgb[0] = (long)strt.red << 16;
				rgb[1] = (long)strt.green << 16;
				rgb[2] = (long)strt.blue << 16;
				
				for (i = 0; i < h; i++)
				{
					d = data;

					ired = ((long)(c[1].red - strt.red) << 16) / w;
					igreen = ((long)(c[1].green - strt.green) << 16) / w;
					iblue = ((long)(c[1].blue - strt.blue) << 16) / w;
					
					red = (long)strt.red << 16;
					green = (long)strt.green << 16;
					blue = (long)strt.blue << 16;
			
					for (j = 0; j < w; j++)
					{
						col.red = red >> 16;
						col.green = green >> 16;
						col.blue = blue >> 16;
						d = (*to)(&col, d);

						red += ired;
						green += igreen;
						blue += iblue;
					}
					
					rgb[0] += yred;
					rgb[1] += ygreen;
					rgb[2] += yblue;
					
					strt.red = rgb[0] >> 16;
					strt.green = rgb[1] >> 16;
					strt.blue = rgb[2] >> 16;
					
					data += scanlen;
				}
				break;
			}
			case 3:
			{
				short h1, h2, step = steps[0];
				
				if (step < 0)
				{
					step = -step;
					if (step > 100)
						step = 100;
					h1 = ((long)h * step) / 100;
					h2 = h - h1;
				}
				else
				{
					h1 = step;
					h2 = h - step;
				}
				
				ired = ((long)(c[1].red - c[0].red) << 16) / h1;
				igreen = ((long)(c[1].green - c[0].green) << 16) / h1;
				iblue = ((long)(c[1].blue - c[0].blue) << 16) / h1;
				
				red = (long)c[0].red << 16;
				green = (long)c[0].green << 16;
				blue = (long)c[0].blue << 16;
					
					col.red = red >> 16;
					col.green = green >> 16;
					col.blue = blue >> 16;
				
				for (i = 0; i < h1; i++)
				{
// 					d = data;
					
					(*to)(&col, &pixel);
					(*rp)(&pixel, data, w);
					
// 					for (j = 0; j < w; j++)
// 					{
// 						d = (*to)(&col, d);
// 					}

					red += ired;
					green += igreen;
					blue += iblue;
					col.red = red >> 16;
					col.green = green >> 16;
					col.blue = blue >> 16;
				
					data += scanlen;
				}
				
				ired = ((long)(c[2].red - col.red) << 16) / h2;
				igreen = ((long)(c[2].green - col.green) << 16) / h2;
				iblue = ((long)(c[2].blue - col.blue) << 16) / h2;
			
				red = (long)col.red << 16;
				green = (long)col.green << 16;
				blue = (long)col.blue << 16;
					col.red = red >> 16;
					col.green = green >> 16;
					col.blue = blue >> 16;
				for (i = 0; i < h2; i++)
				{
					(*to)(&col, &pixel);
					(*rp)(&pixel, data, w);
// 					d = data;
// 					for (j = 0; j < w; j++)
// 					{
// 						d = (*to)(&col, d);
// 					}
					red += ired;
					green += igreen;
					blue += iblue;
					col.red = red >> 16;
					col.green = green >> 16;
					col.blue = blue >> 16;
				
					data += scanlen;
				}
				break;
			}
			case 4:
			{
				short w1, w2, step = steps[0];
				if (step < 0)
				{
					step = -step;
					if (step > 100)
						step = 100;
					w1 = ((long)w * step) / 100;
					w2 = w - w1;
				}
				else
				{
					w1 = step;
					w2 = w - step;
				}
				
				for (i = 0; i < h; i++)
				{
					d = data;

					ired =   ((long)(c[1].red - c[0].red) << 16) / w1;
					igreen = ((long)(c[1].green - c[0].green) << 16) / w1;
					iblue =  ((long)(c[1].blue - c[0].blue) << 16) / w1;
					
					red =	(long)c[0].red << 16;
					green =	(long)c[0].green << 16;
					blue =	(long)c[0].blue << 16;
					for (j = 0; j < w1; j++)
					{
						col.red = red >> 16;
						col.green = green >> 16;
						col.blue = blue >> 16;
						d = (*to)(&col, d);
						red += ired;
						green += igreen;
						blue += iblue;
					}
					
					ired =   ((long)(c[2].red - col.red) << 16) / w2;
					igreen = ((long)(c[2].green - col.green) << 16) / w2;
					iblue =  ((long)(c[2].blue - col.blue) << 16) / w2;
					
					red =   (long)col.red << 16;
					green = (long)col.green << 16;
					blue =  (long)col.blue << 16;
					for (j = 0; j < w2; j++)
					{
						col.red = red >> 16;
						col.green = green >> 16;
						col.blue = blue >> 16;
						d = (*to)(&col, d);
						red += ired;
						green += igreen;
						blue += iblue;
					}
					data += scanlen;
				}		
				break;
				default:;
				}
			}
// 			if (data > ed || d > ed)
// 				display("end %lx, data = %lx, d = %lx", ed, data, d);
		}
	}
}

------------------------------

between them, gradients are created on-the-fly (at render time) per
box area, and the impact on memory is much less than for image
textures

by the way, after gradients are created, are become textures, the same
as regular image textures, occupying the same texture objects (and
more - not all objects use image textures atm, some are missing or
duplicated in code when not using gradients)

Paul