GP2X Hardware Blitter Freezes


GernotFrisch

Member
Joined
Jan 2, 2007
Messages
445
Code:
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <unistd.h>
#include <stropts.h>
#include <memory.h>

volatile int Uppermemfd;
volatile void *UpperMem=NULL;
volatile unsigned long *gp2x_memreg32=NULL;
volatile unsigned short *gp2x_memreg16=NULL;
volatile unsigned long* blitter32=NULL;


#define SCREEN_COMMON 0x3000000
#define SCREEN0	0x3101000
#define SCREEN1 0x3381000

void Flip()
{
	//Wait till the blitter is ready
	printf("wait for blitter\n");
	while(blitter32[0x0034 >> 2] & 1) usleep(1);

printf("Wait for vlbank\n");
	// VBlank
	while(  gp2x_memreg16[0x1182>>1]&(1<<4) );
	while(!(gp2x_memreg16[0x1182>>1]&(1<<4)));

	//Set the destination as 16bit and enable it for use.
	blitter32[0x0000 >> 2] = (1 << 5) | (1 << 6);
	//Set the address of destination
	blitter32[0x0004 >> 2] = SCREEN0; // front screen buffer
	//Set the pitch of destination in bytes.
	blitter32[0x0008 >> 2] = 320*2;
	//Set a 16bit source, enable source and say the source is not controlled by CPU(?)
	blitter32[0x000C >> 2] = (1 << 8) | (1 << 7) | (1 << 5);
	//Set the source address
	blitter32[0x0010 >> 2] = SCREEN1; // 0x3101000 + 320*2*240;
	//Set the pitch of source in bytes
	blitter32[0x0014 >> 2] = 320*2;
	//Do nothing with patern
	blitter32[0x0020 >> 2] = 0;
	//Set the size 320 by 240
	blitter32[0x002C >> 2] = (240 << 16) | (320 << 0);
	//Clear the source input FIFO, positive X,Y. And do a copy ROP.
	blitter32[0x0030 >> 2] = (1 << 10) | (1 << 9) | (1 << 8) | 0xCC;
	//Make the blitter run.
	asm volatile("":::"memory");
	blitter32[0x0034 >> 2] = 0x0001;
printf("Copy OK\n");

}



int main()
{
  Uppermemfd = open("/dev/mem", O_RDWR);

  /* map the MMSP2 registers */
  gp2x_memreg32 = (unsigned long*)mmap(0, 0x10000, 3, MAP_SHARED, Uppermemfd, 0xc0000000);
  gp2x_memreg16 = (unsigned short*)gp2x_memreg32;
  
  /* map the blitter registers */
  blitter32 = (volatile unsigned long*)mmap(0, 0x100, 3, MAP_SHARED, Uppermemfd, 0xe0020000);

  volatile unsigned char* gp2x_mem = (volatile unsigned char*)mmap(0, 0xf00000, 3, MAP_SHARED, Uppermemfd, SCREEN_COMMON);
  void* pRawFrameBuffer = (void*)&gp2x_mem[0x100000];
  unsigned short* cBuffer = (unsigned short*)&gp2x_mem[0x180000];

  /* init the screen to 320x240 16bpp */
  gp2x_memreg16[0x28da >> 1]  = 0x004ab;
  gp2x_memreg16[0x290c >> 1]  = 640;
  
  /* enable the hardware acceleration */
  gp2x_memreg16[0x090a >> 1]  = 0xffff;
  gp2x_memreg16[0x0904 >> 1] |= (1 << 10);
	printf("Blitter: %p\n", blitter32);
	printf("writing to back buffer\n");


	memset(cBuffer, 0, 320*240*2);
	printf("worked!\n");

	for(int cc=0;++cc;)
	{
		Flip();
		// some gfx garbage to see if it moves
		// cBuffer[cc%(320*240)] = (cc*cc+1234);
	}
return 0;
}

Output:

Blitter: 0x40010000
writing to back buffer
worked!
wait for blitter
<freezes>

What can I do / what did I do wrong?
 

Mudi

You're pushing your luck little man
Joined
Jan 25, 2006
Messages
815
Website
mudiweb.com
You have to do the first blit without waiting for it to claim it's ready, if I recall correctly. Just do a junk blit of a black rectangle or something before the main loop
 

GernotFrisch

Member
Joined
Jan 2, 2007
Messages
445
I tried using a static variable and leaving the first "wait" out. But it freezes at the 2nd wait and will not show the backbuffer contents.
I'm really puzzled.
 

paeryn

Reclusive maniac
Joined
Nov 28, 2005
Messages
432
Age
50
Location
Sheffield, England
Website
paeryn.myby.co.uk
Mudi posted on Feb 1 2007 at 12:24 AM said:
You have to do the first blit without waiting for it to claim it's ready, if I recall correctly. Just do a junk blit of a black rectangle or something before the main loop
No, you must *always* wait for the blitter to be ready before you start a blit. You can pre-load the registers whilst a blit is in progress but you have to wait for the busy bit to clear before setting the final blit-start.

Anyway, to KungPhoo:
Your code as given compiles and runs fine for me. What toolchain are you using, and/or which version of GCC do you use?
You have a bug in that you define cBuffer as being 0x180000 from 0x3000000 whereas you blit from 0x3380000 but that just means you get garbage on the screen rather than the contents of cBuffer.
 
Last edited by a moderator:
Top