Re: MIT-SHM example



Rose Cumming wrote:
> thanks for your replies anyways. I'm studying some rationales related to
> what you said.
> 
> I have some working code that has a refresh rate of over 24fps on a
> relatively small window (using gdk drawing primitives). I also played
> with gtkglextmm
> 
> since you suggested,
> "using XImage has a number of costs *regardless* of whether MIT-SHM is
> present or not. it is *not* the fastest way to draw an image all the
> time",
> 
> say for example, to render on a nearly full-screen window (say the
> screen has a resolution of 1280x1024pixels) in a timely fashion, like a
> video player. with raw RGB input data.
> 
> What will be your suggestion for a fast way? say targeting at a 20-24fps?
> you know how MPlayer or Xine does graphics rendering?

the easiest way by far would be to use SDL, it's not only cross-platform
but also pretty fast at what it does and damn simple to use ( I wrote a
blitting, motion blurring and zooming anitaliased screensaver in under a
day's work ) and if you're loading and displaying images out of files
there's nothing faster around anyway except GL (but you need 3d hardware
for that)

I'm not quite sure if it is possible to integrate it with Gtk but it
does provide it's own windows and if you're drawing full-screen it does
not really matter, documentation is pretty crappy but there are some
good tutorials around:

http://sol.planet-d.net
http://lazyfooproductions.com/SDL_tutorials/index.php

mplayer and xine use the XV extension I bellieve

The file I attached is one of the examples from sol.planet-d.net but
with slightly faster blitting functions, I used it as a base for my
screensaver.

-Bartek
/* sol_05.c - blending! */

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <SDL/SDL.h>

#define SW 800		// screen width and height
#define SH 600
#define ANGLE 0.05
#define PITCH (screen->pitch / 4) // save some typing!

SDL_Surface *screen;
unsigned int *tempbuf;

const unsigned char sprite[] = 
{
0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,
0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,
0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,
0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0
};

void drawsprite(int x, int y, unsigned int color)
	{
	int i,j,c,yofs;
	yofs = y * (screen->pitch / 4) + x;
	for( i = 0, c = 0; i < 16; i++)
		{
		for(j = 0; j < 16; j++, c++)
			{
			if(sprite[c])
				{
				((unsigned int*)screen->pixels)[yofs+j] = color;
				}
			}
		yofs += (screen->pitch / 4);
		}
	}		

unsigned int blend_avg(unsigned int source, unsigned int target)
	{
	unsigned int sourcer = (source >> 0) & 0xff;
	unsigned int sourceg = (source >> 8) & 0xff;
	unsigned int sourceb = (source >> 16) & 0xff;
	unsigned int targetr = (target >> 0) & 0xff;
	unsigned int targetg = (target >> 8) & 0xff;
	unsigned int targetb = (target >> 16) & 0xff;
	
	targetr = (sourcer + targetr)/2;
	targetg = (sourceg + targetg)/2;
	targetb = (sourceb + targetb)/2;
	
	return ((targetr << 0)|(targetg<<8)|(targetb<<16));
	}
	
unsigned int blend_mul(unsigned int source, unsigned int target)
	{
	unsigned int sourcer = (source >> 0) & 0xff;
	unsigned int sourceg = (source >> 8) & 0xff;
	unsigned int sourceb = (source >> 16) & 0xff;
	unsigned int targetr = (target >> 0) & 0xff;
	unsigned int targetg = (target >> 8) & 0xff;
	unsigned int targetb = (target >> 16) & 0xff;
	
	targetr = (sourcer*targetr) >> 8;
	targetg = (sourceg*targetg) >> 8;
	targetb = (sourceb*targetb) >> 8;
	
	return ((targetr << 0)|(targetg<<8)|(targetb<<16));
	}
	
unsigned int blend_add(unsigned int source, unsigned int target)
	{
	unsigned int sourcer = (source >> 0) & 0xff;
	unsigned int sourceg = (source >> 8) & 0xff;
	unsigned int sourceb = (source >> 16) & 0xff;
	unsigned int targetr = (target >> 0) & 0xff;
	unsigned int targetg = (target >> 8) & 0xff;
	unsigned int targetb = (target >> 16) & 0xff;
	
	targetr += sourcer;
	targetg += sourceg;
	targetb += sourceb;
	
	if(targetr > 0xff) targetr=0xff;
	if(targetb > 0xff) targetb=0xff;
	if(targetg > 0xff) targetg=0xff;
	
	return ((targetr << 0)|(targetg<<8)|(targetb<<16));
	}

void scaleblit()
	{
	int i, j, yofs;
	yofs = 0;
	
	for(i=0;i<SH;i++)
		{
		for(j= 0;j<SW;j++)
			{
			//int c= (int)((i*0.95f)+12)*PITCH + (int)((j*0.95f)+16);
			
			int c = ((95*i/100)+20)*PITCH + ((95*j/100)+15);
			((unsigned int*)screen->pixels)[yofs+j] = 
					blend_avg(tempbuf[c],((unsigned int*)screen->pixels)[yofs+j]);
			}
		yofs += PITCH;
		}
	}
	
void rotateblit()
	{
	int i, j, yofs;
	yofs = 0;
	
	for(i=0;i<SH;i++)
		{
		for(j=0;j<SW;j++)
			{
				int newx = SW/2+(int)( ( (1-ANGLE)*(j-SW/2) )+( (ANGLE)*(i-SH/2))     );
				int newy = SH/2+(int)( (-(ANGLE)*(j-SW/2) ) + ( (1-ANGLE)*(i-SH/2) ) );

				if(newx < SW && newy < SH && newx > 0 && newy > 0)
					((unsigned int*)screen->pixels)[newy*PITCH+newx] = 
																tempbuf[i*SW+j];
				//}
			}
		yofs += PITCH;
		}
	}
	
void init(void)
	{
	tempbuf = malloc(SW*SH*sizeof(unsigned int));
	}
	
void render(void)
	{
	// Lock surface if needed
	if(SDL_MUSTLOCK(screen))
		if(SDL_LockSurface(screen) < 0)
			{
			fprintf(stderr,"Could not lock screen!");
			return;
			}
			
	int tick = SDL_GetTicks();
	
	int i, d;
	for(i = 0; i<128;i++)
		{
		d=tick+i*4;
		/*
		drawsprite(	(int)(320+sin(d*0.0034f)*sin(d*0.0134f)*300),
						(int)(240+cos(d*0.0033f)*sin(d*0.0234f)*220),
						((int)(sin((tick*0.2+i)*0.234897f)*127 + 128) << 16) |
						((int)(sin((tick*0.2+i)*0.123489f)*127 + 128) << 8)  |
						((int)(sin((tick*0.2+i)*0.312348f)*127 + 128) << 0)); */
		
		drawsprite(	(int)(SW/2+sin(d*0.0034f)*sin(d*0.0134f)*((SW/2)-20)),
						(int)(SH/2+cos(d*0.0033f)*cos(d*0.0234f)*((SH/2)-29)),
						((int)(sin((tick*0.2+i)*0.234897f)*127 + 128) << 16) |
						((int)(sin((tick*0.2+i)*0.123489f)*127 + 128) << 8)  |
						((int)(sin((tick*0.2+i)*0.312348f)*127 + 128) << 0));

		}
	memcpy(	tempbuf, // dest
				((unsigned long*)screen->pixels), // source
				SH*PITCH*4);
					
	rotateblit();	
	scaleblit();
	
	/* for(i=0;i<SH;i++)
		memcpy(	tempbuf + i * SW, 
					((unsigned long*)screen->pixels)+i*PITCH,
					SW*4);*/
	
	
	// Unlock screen if needed
	if(SDL_MUSTLOCK(screen))
		SDL_UnlockSurface(screen);
		
	// tell SDL to update screen
	SDL_UpdateRect(screen, 0, 0, SW, SH);
	}	
	

int main(int argc, char **argv)
	{	
	// initialize SDL
	if( SDL_Init(SDL_INIT_VIDEO) < 0)
		{
		fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
		exit(1);
		}
		
		
	// Register SDL_Quit to be called at exit
	atexit(SDL_Quit);
	
	// Attempt to create 640x480 32 surface
	if( (screen = SDL_SetVideoMode(SW, SH, 32, SDL_HWSURFACE)) == NULL)
		{
		fprintf(stderr, "Unable to create screen surface: %s\n", SDL_GetError());
		exit(1);
		}
		
	init();

	while(1)
		{
		render();
		
		// Poll for events and handle the ones we care about		
		SDL_Event event;
		while(SDL_PollEvent(&event))
			{
			switch(event.type)
				{
				case SDL_KEYDOWN:
					break;
					
				case SDL_KEYUP:
					if(event.key.keysym.sym == SDLK_ESCAPE)
						return 0;
					break;
					
				case SDL_QUIT:
					return(0);
					
				default:
					break;
				}
			}
		}
	
	return 0;
	}
				
	
	


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