*** /home3/kit/empeg/src/empeg/kernel/arch/arm/special/empeg_display.c.bak	Tue May 29 19:20:51 2001
--- /home3/kit/empeg/src/empeg/kernel/arch/arm/special/empeg_display.c	Tue May 29 22:29:33 2001
***************
*** 232,237 ****
--- 232,244 ----
  	int queue_wp;
  	int queue_used;
  	int queue_free;
+ 	unsigned char *overlay_software_buffer;
+ 	unsigned char *overlay_software_queue;
+ 	int overlay_queue_rp;
+ 	int overlay_queue_wp;
+ 	int overlay_queue_used;
+ 	int overlay_queue_free;
+ 	int overlay_mode;
  
  	unsigned power : 1;
  };
***************
*** 483,494 ****
--- 490,525 ----
  
  }
  
+ // add display buffer to overlay queue
+ static void display_overlay_queue_add(struct display_dev *dev)
+ {
+ 	unsigned long flags;
+ 	if (dev->overlay_queue_free) {
+ 		save_flags_cli(flags);
+ 		INC_QUEUE_INDEX(dev->overlay_queue_wp);
+ 		dev->overlay_queue_free--;
+ 		dev->overlay_queue_used++;
+ 		restore_flags(flags);
+ 	}
+ 
+ 	/* Strictly speaking this isn't necessary but we do it anyway. */
+ 	display_flush_cache((unsigned long)dev->overlay_software_queue + dev->overlay_queue_wp * EMPEG_SCREEN_SIZE,
+ 			    EMPEG_SCREEN_SIZE);
+ 
+ 	memcpy(dev->overlay_software_queue + dev->overlay_queue_wp * EMPEG_SCREEN_SIZE,
+ 	       dev->overlay_software_buffer,
+ 	       EMPEG_SCREEN_SIZE);
+ }
+ 
+ 
  /* Display the current top of queue. If there isn't anything in the
     queue then just re-use the last one. */
     
  void display_queue_draw(struct display_dev *dev)
  {
  	unsigned long flags;
+ 	int iScreenFetch = 0;
+ 
  	if (dev->queue_used) {
  		save_flags_cli(flags);
  		DEBUGK("Spare in queue. Removing one.\n");
***************
*** 506,511 ****
--- 537,585 ----
  		       dev->queue_free,
  		       dev->queue_used);
  		restore_flags(flags);
+ 		iScreenFetch = 1;
+ 	if( dev->overlay_mode > 0 )
+ 	{
+ 		unsigned char* pSrc;
+ 		unsigned char* pDst;
+ 		const int iWidthBytes = (EMPEG_SCREEN_WIDTH * EMPEG_SCREEN_BPP / 8);
+ 		if( dev->overlay_queue_used )
+ 		{
+ 			save_flags_cli(flags);
+ 			dev->overlay_queue_used--;
+ 			dev->overlay_queue_free++;
+ 			INC_QUEUE_INDEX(dev->overlay_queue_rp);
+ 			restore_flags(flags);
+ 		}
+ 
+ 		// mix display buffers
+ 		pSrc = dev->overlay_software_queue + dev->overlay_queue_rp * EMPEG_SCREEN_SIZE;
+ 		pDst = dev->software_queue + dev->queue_rp * EMPEG_SCREEN_SIZE;
+ 
+ 		// scale 32 pixel rows into 24 pixel rows
+ 		if( iScreenFetch )
+ 		{
+ #ifdef SCALE
+ 			memcpy( pDst + 3 * iWidthBytes, pDst + 4 * iWidthBytes, iWidthBytes*3 );
+ 			memcpy( pDst + 6 * iWidthBytes, pDst + 8 * iWidthBytes, iWidthBytes*3 );
+ 			memcpy( pDst + 9 * iWidthBytes, pDst + 12 * iWidthBytes, iWidthBytes*3 );
+ 			memcpy( pDst + 12 * iWidthBytes, pDst + 16 * iWidthBytes, iWidthBytes*3 );
+ 			memcpy( pDst + 15 * iWidthBytes, pDst + 20 * iWidthBytes, iWidthBytes*3 );
+ 			memcpy( pDst + 18 * iWidthBytes, pDst + 24 * iWidthBytes, iWidthBytes*3 );
+ 			memcpy( pDst + 21 * iWidthBytes, pDst + 28 * iWidthBytes, iWidthBytes*3 );
+ #endif
+ 			memcpy( pDst + 24 * iWidthBytes, pSrc + 24 * iWidthBytes, iWidthBytes/2);
+ 			memcpy( pDst + 25 * iWidthBytes, pSrc + 25 * iWidthBytes, iWidthBytes/2);
+ 			memcpy( pDst + 26 * iWidthBytes, pSrc + 26 * iWidthBytes, iWidthBytes/2);
+ 			memcpy( pDst + 27 * iWidthBytes, pSrc + 27 * iWidthBytes, iWidthBytes/2);
+ 			memcpy( pDst + 28 * iWidthBytes, pSrc + 28 * iWidthBytes, iWidthBytes/2);
+ 			memcpy( pDst + 29 * iWidthBytes, pSrc + 29 * iWidthBytes, iWidthBytes/2);
+ 			memcpy( pDst + 30 * iWidthBytes, pSrc + 30 * iWidthBytes, iWidthBytes/2);
+ 			memcpy( pDst + 31 * iWidthBytes, pSrc + 31 * iWidthBytes, iWidthBytes/2);
+ 		}
+ 		// copy remaining 8 pixel rows from overlay image
+ //		memcpy( pDst + 24 * iWidthBytes, pSrc + 24 * iWidthBytes, iWidthBytes*8 );
+ 	}
  	}
  	DEBUGK("Blatting from queue entry %d.\n", dev->queue_rp);
  	display_blat(dev, dev->software_queue + dev->queue_rp * EMPEG_SCREEN_SIZE);
***************
*** 561,566 ****
--- 635,643 ----
  	unsigned long offset = address - vma->vm_start + vma->vm_offset;
  	unsigned long pageptr = (unsigned long)dev->software_buffer;
  
+ 	if( vma->vm_file->f_flags & O_SYNC )
+ 		pageptr = (unsigned long)dev->overlay_software_buffer;
+ 
  	if (offset >= PAGE_SIZE)
  		return 0;
  	
***************
*** 745,751 ****
  		
  	case EMPEG_DISPLAY_ENQUEUE:
  	case 6: /* Enqueue screen */
! 	        display_queue_add(dev);
  		break;
  
  	case EMPEG_DISPLAY_POPQUEUE:
--- 822,831 ----
  		
  	case EMPEG_DISPLAY_ENQUEUE:
  	case 6: /* Enqueue screen */
! 		if( filp->f_flags & O_SYNC )
! 			display_overlay_queue_add(dev);
! 		else
! 		        display_queue_add(dev);
  		break;
  
  	case EMPEG_DISPLAY_POPQUEUE:
***************
*** 773,778 ****
--- 853,866 ----
  			display_sendcontrol(level);
  		}
  		break;	
+ 	case _IOW('d', 12, int):
+ 	case 12:
+ 		// set display overlay mode
+ 		{
+ 			int ret;
+ 			if((ret = get_user(dev->overlay_mode, (int *) arg)) != 0) return ret;
+ 		}
+ 		break;
  
  	default:
  		return(-EINVAL);
***************
*** 878,883 ****
--- 966,979 ----
             both see the same data. */
  //	flush_page_to_ram(MAP_NR(dev->software_buffer));
  //	uncache_page(MAP_NR(dev->software_buffer));
+ 
+ 	dev->overlay_software_buffer = (void *)get_free_page(GFP_KERNEL);
+ 	// allocate buffers for overlay display
+ 	dev->overlay_software_queue = (void *)__get_free_pages(GFP_KERNEL, BUFFER_COUNT_ORDER);
+ 	memset(dev->overlay_software_queue, 0, (1<<BUFFER_COUNT_ORDER)*PAGE_SIZE);
+ 	dev->overlay_queue_rp = dev->overlay_queue_wp = dev->overlay_queue_used = 0;
+ 	dev->overlay_queue_free = BUFFER_COUNT;
+ 	dev->overlay_mode = 0;
  
  	/* Setup normal palette */
  	display_setpalette(dev, PALETTE_STANDARD);
