Esempio n. 1
0
		int Initialize()
		{
			fbfd = 0;
			fbp = 0;

			setlogmask(LOG_UPTO(LOG_DEBUG));
			openlog("fbcp", LOG_NDELAY | LOG_PID, LOG_USER);

			bcm_host_init();

			display = vc_dispmanx_display_open(0);
			if (!display) {
				syslog(LOG_ERR, "Unable to open primary display");
				return -1;
			}
			ret = vc_dispmanx_display_get_info(display, &display_info);
			if (ret) {
				syslog(LOG_ERR, "Unable to get primary display information");
				return -1;
			}
			syslog(LOG_INFO, "Primary display is %d x %d", display_info.width, display_info.height);


			fbfd = open("/dev/fb1", O_RDWR);
			if (!fbfd) {
				syslog(LOG_ERR, "Unable to open secondary display");
				return -1;
			}
			if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) {
				syslog(LOG_ERR, "Unable to get secondary display information");
				return -1;
			}
			if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
				syslog(LOG_ERR, "Unable to get secondary display information");
				return -1;
			}

			syslog(LOG_INFO, "Second display is %d x %d %dbps\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);

			screen_resource = vc_dispmanx_resource_create(VC_IMAGE_RGB565, vinfo.xres, vinfo.yres, &image_prt);
			if (!screen_resource) {
				syslog(LOG_ERR, "Unable to create screen buffer");
				close(fbfd);
				vc_dispmanx_display_close(display);
				return -1;
			}

			fbp = (char*) mmap(0, finfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
			if (fbp <= 0) {
				syslog(LOG_ERR, "Unable to create mamory mapping");
				close(fbfd);
				ret = vc_dispmanx_resource_delete(screen_resource);
				vc_dispmanx_display_close(display);
				return -1;
			}

			vc_dispmanx_rect_set(&rect1, 0, 0, vinfo.xres, vinfo.yres);
			return 1;
		}
Esempio n. 2
0
void save_snapshot(void)
{
  DISPMANX_DISPLAY_HANDLE_T display;
  DISPMANX_MODEINFO_T info;
  DISPMANX_RESOURCE_HANDLE_T resource;
  VC_IMAGE_TYPE_T type = VC_IMAGE_RGB888;
  VC_IMAGE_TRANSFORM_T transform = 0;
  VC_RECT_T rect;
  void *image;
  uint32_t vc_image_ptr;
  int ret;
  uint32_t screen = 0;

  fprintf(stderr,"\nWriting snapshot...\n");
  //fprintf(stderr,"Open display[%i]...\n", screen );
  display = vc_dispmanx_display_open( screen );

  ret = vc_dispmanx_display_get_info(display, &info);
  assert(ret == 0);
  //fprintf(stderr,"Display is %d x %d\n", info.width, info.height );

  image = calloc( 1, info.width * 3 * info.height );

  assert(image);

  resource = vc_dispmanx_resource_create(type, info.width, info.height,&vc_image_ptr);

  vc_dispmanx_snapshot(display, resource, transform);

  vc_dispmanx_rect_set(&rect, 0, 0, info.width, info.height);
  vc_dispmanx_resource_read_data(resource, &rect, image, info.width*3);

  char* home = getenv("HOME");
  char filename[1024];
  if (!home)
    home = "/tmp";

  snprintf(filename,sizeof(filename),"%s/pidvbip-%u.ppm",home,(unsigned int)time(NULL));
  FILE *fp = fopen(filename, "wb");
  fprintf(fp, "P6\n%d %d\n255\n", info.width, info.height);
  fwrite(image, info.width*3*info.height, 1, fp);
  fclose(fp);

  fprintf(stderr,"\nSnapshot written to %s\n",filename);

  ret = vc_dispmanx_resource_delete( resource );
  assert( ret == 0 );
  ret = vc_dispmanx_display_close(display );
  assert( ret == 0 );

  free(image);
}
int main(void)
{
    DISPMANX_DISPLAY_HANDLE_T   display;
    DISPMANX_MODEINFO_T         info;
    DISPMANX_RESOURCE_HANDLE_T  resource;
    VC_IMAGE_TYPE_T type = VC_IMAGE_RGB888;
    VC_IMAGE_TRANSFORM_T   transform = 0;
    VC_RECT_T         rect;

    void                       *image;
    uint32_t                    vc_image_ptr;

    int                   ret;

    uint32_t        screen = 0;

    bcm_host_init();

    printf("Open display[%i]...\n", screen );
    display = vc_dispmanx_display_open( screen );

    ret = vc_dispmanx_display_get_info(display, &info);
    assert(ret == 0);
    printf( "Display is %d x %d\n", info.width, info.height );

    image = calloc( 1, info.width * 3 * info.height );

    assert(image);

    resource = vc_dispmanx_resource_create( type,
                                                  info.width,
                                                  info.height,
                                                  &vc_image_ptr );

    vc_dispmanx_snapshot(display, resource, transform);

    vc_dispmanx_rect_set(&rect, 0, 0, info.width, info.height);
    vc_dispmanx_resource_read_data(resource, &rect, image, info.width*3); 

    FILE *fp = fopen("out.ppm", "wb");
    fprintf(fp, "P6\n%d %d\n255\n", info.width, info.height);
    fwrite(image, info.width*3*info.height, 1, fp);
    fclose(fp);

    ret = vc_dispmanx_resource_delete( resource );
    assert( ret == 0 );
    ret = vc_dispmanx_display_close(display );
    assert( ret == 0 );

    return 0;
}
Esempio n. 4
0
//------------------------------------------------------------------------------
//
bool OsdGraphics::Init()
{
    uint32_t screen = 0;

    printf("Open display[%i]...\n", screen );
    m_Display = vc_dispmanx_display_open( screen );

    if (vc_dispmanx_display_get_info( m_Display, &m_Info))
    {
        std::cout << "OsdGraphics::Init: vc_dispmanx_display_get_info failed" << std::endl;
        return(false);
    }
    printf( "Display is %d x %d\n", m_Info.width, m_Info.height );
}
Esempio n. 5
0
void vo_open(RECT_VARS_T* vars, int screen)
{
    int ret;

    /* Init from dispmanx.c */

    DEBUGF("Open display[%i]...\n", screen );
    vars->display = vc_dispmanx_display_open( screen );

    ret = vc_dispmanx_display_get_info( vars->display, &vars->info);
    assert(ret == 0);
    DEBUGF( "Display is %d x %d\n", vars->info.width, vars->info.height );

    /* End of dispmanx.c init */
}
Esempio n. 6
0
void dispmanxtest() {
	DISPMANX_DISPLAY_HANDLE_T display;
	int ret;
	DISPMANX_MODEINFO_T displayinfo;
	DISPMANX_RESOURCE_HANDLE_T res;
	int width = 1024;
	int height = 576;
	uint32_t vc_image_ptr;
	DISPMANX_UPDATE_HANDLE_T update;
	VC_RECT_T dst_rect,src_rect;
	DISPMANX_ELEMENT_HANDLE_T element;

	
	bcm_host_init();
	display = vc_dispmanx_display_open(0);
	ret = vc_dispmanx_display_get_info( display, &displayinfo);
	assert(ret==0);
	printf("display is %dx%d\n",displayinfo.width,displayinfo.height);
	res = vc_dispmanx_resource_create(VC_IMAGE_YUV420,width,height,&vc_image_ptr);
	vc_image_ptr = vc_dispmanx_resource_get_image_handle(res);
	printf("vc_image_ptr %x\n",vc_image_ptr);
	assert(res);
	update = vc_dispmanx_update_start(10);
	assert(update);
	vc_dispmanx_rect_set(&src_rect,0,0,width<<16,height<<16);
	vc_dispmanx_rect_set(&dst_rect,0,(displayinfo.height - height)/2,width-32,height);
	element = vc_dispmanx_element_add(update,display,2000,&dst_rect,res,&src_rect,DISPMANX_PROTECTION_NONE,NULL,NULL,DISPMANX_NO_ROTATE);
	ret = vc_dispmanx_update_submit_sync(update);
	assert(ret==0);
	uint8_t *rawfb = (uint8_t*)mapmem(vc_image_ptr,0x1000);
	for (int i=0; i<0x100; i++) {
		printf("%02x ",rawfb[i]);
	}
	printf("\n");
	unmapmem(rawfb,0x1000);
	puts("sleeping");
	sleep(10);
	update = vc_dispmanx_update_start(10);
	assert(update);
	ret = vc_dispmanx_element_remove(update,element);
	assert(ret==0);
	ret = vc_dispmanx_update_submit_sync(update);
	assert(ret==0);
	ret = vc_dispmanx_resource_delete(res);
	assert(ret==0);
	ret = vc_dispmanx_display_close(display);
	assert(ret==0);
}
Esempio n. 7
0
void CRBP::GetDisplaySize(int &width, int &height)
{
  DISPMANX_DISPLAY_HANDLE_T display;
  DISPMANX_MODEINFO_T info;

  display = vc_dispmanx_display_open( 0 /*screen*/ );
  if (vc_dispmanx_display_get_info(display, &info) == 0)
  {
    width = info.width;
    height = info.height;
  }
  else
  {
    width = 0;
    height = 0;
  }
  vc_dispmanx_display_close(display );
}
Esempio n. 8
0
SliceMngr::SliceMngr(){
  int result;
  uint16_t background = 0x000F;
  DISPMANX_UPDATE_HANDLE_T update;
  mState = 0;
  bcm_host_init();
  mDisplay = vc_dispmanx_display_open(0);
  if(mDisplay == 0){
    return;
  }
  result = vc_dispmanx_display_get_info(mDisplay, &mInfo);
  if(result != 0){
    return;
  }
  initBackgroundLayer(&mBackground, background, 1);
  initImage(&(mImage.image), VC_IMAGE_RGBA32, mInfo.width, mInfo.height, false);
  createResourceImageLayer(&mImage, 0);
  vc_dispmanx_rect_set(&(mImage.srcRect),
		       0 << 16,
                       0 << 16,
                       mImage.image.width << 16,
                       mImage.image.height << 16);

  vc_dispmanx_rect_set(&(mImage.dstRect),
                       (mInfo.width - mImage.image.width) / 2,
                       (mInfo.height - mImage.image.height) / 2,
                       mImage.image.width,
		       mImage.image.height);
  update = vc_dispmanx_update_start(0);
  if(update == 0){
    return;
  }
  addElementBackgroundLayer(&mBackground, mDisplay, update);
  addElementImageLayerCentered(&mImage, &mInfo, mDisplay, update);
  result = vc_dispmanx_update_submit_sync(update);
  if(result != 0){
    return;
  }
  mState = 1;
}
Esempio n. 9
0
int32_t graphics_get_display_size( const uint16_t display_number,
                                                    uint32_t *width,
                                                    uint32_t *height)
{
   DISPMANX_DISPLAY_HANDLE_T display_handle = 0;
   DISPMANX_MODEINFO_T mode_info;
   int32_t success = -1;

   if (display_handle == 0) {
      // Display must be opened first.
      display_handle = vc_dispmanx_display_open(display_number);
      vcos_assert(display_handle);
   }
   if (display_handle) {
      success = vc_dispmanx_display_get_info(display_handle, &mode_info);
         
      if( success >= 0 )
      {
         if( NULL != width )
         {
            *width = mode_info.width;
         }
         
         if( NULL != height )
         {
            *height = mode_info.height;
         }
      }
   }
      
   if ( display_handle )
   {
      vc_dispmanx_display_close(display_handle);
      display_handle = 0;
   }

   return success;
}
Esempio n. 10
0
int main(int argc, char *argv[]) {
    int quality = 75;
    if (argc == 2) {
        quality = atoi(argv[1]);
        if (quality < 10 || quality > 100) {
            fprintf(stderr, "invalid quality. must be between 10 and 100\n");
            return 1;
        }
    }

    bcm_host_init();

    uint32_t screen = 0;

    DISPMANX_DISPLAY_HANDLE_T display = vc_dispmanx_display_open(screen);
    DISPMANX_MODEINFO_T info;

    int ret = vc_dispmanx_display_get_info(display, &info);
    assert(ret == 0);

    /* DispmanX expects buffer rows to be aligned to a 32 bit boundary */
    int pitch = ALIGN_UP(2 * info.width, 32);

    uint32_t vc_image_ptr;
    VC_IMAGE_TYPE_T type = VC_IMAGE_RGB565;
    DISPMANX_RESOURCE_HANDLE_T resource = vc_dispmanx_resource_create(
        type, info.width, info.height, &vc_image_ptr
    );
    
    VC_IMAGE_TRANSFORM_T transform = 0;
    vc_dispmanx_snapshot(display, resource, transform);

    VC_RECT_T rect;
    vc_dispmanx_rect_set(&rect, 0, 0, info.width, info.height);

    unsigned char *image = malloc(pitch * info.height);
    assert(image);
    vc_dispmanx_resource_read_data(resource, &rect, image, info.width * 2);

    ret = vc_dispmanx_resource_delete(resource);
    assert(ret == 0);

    ret = vc_dispmanx_display_close(display);
    assert(ret == 0);

    struct jpeg_compress_struct cinfo;
    struct jpeg_error_mgr jerr;
    JSAMPROW row_pointer[1];

    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_compress(&cinfo);
    jpeg_stdio_dest(&cinfo, stdout);

    cinfo.image_width = info.width;
    cinfo.image_height = info.height;
    cinfo.input_components = 3;
    cinfo.in_color_space = JCS_RGB;

    jpeg_set_defaults(&cinfo);
    jpeg_set_quality(&cinfo, quality, TRUE);
    jpeg_start_compress(&cinfo, TRUE);

    int row_stride = cinfo.image_width * 3;
    while (cinfo.next_scanline < cinfo.image_height) {
        unsigned char row[row_stride];
        unsigned char *dst = &row[0];
        uint16_t *src = (uint16_t*)(image + pitch * cinfo.next_scanline);
        for (int x = 0; x < cinfo.image_width; x++, src++) {
            *dst++ = ((*src & 0xf800) >> 11) << 3;
            *dst++ = ((*src & 0x07e0) >>  5) << 2;
            *dst++ = ((*src & 0x001f) >>  0) << 3;
        }
        row_pointer[0] = row;
        jpeg_write_scanlines(&cinfo, row_pointer, 1);
    }
    jpeg_finish_compress(&cinfo);
    jpeg_destroy_compress(&cinfo);
    return 0;
}
static SDL_Surface *DISPMANX_SetVideoMode(_THIS, SDL_Surface *current,
				int width, int height, int bpp, Uint32 flags)
{
//MAC Recuerda que aqui­,originalmente, nos llegaban las dimensiones de un modo de video
// aproximado en SDL_Video.c de entre los modos de video disponibles. AHORA YA NO.
//Ahora lo que hacemos es que nos lleguen directamente la altura y anchura del modo 
//en el que quiere correr la aplicacion, 
//Luego se escala ese modo, de cuanta menos resolucion mejor, (ya que hay
//que hacer una escritura de ram a grafica en la funcion FlipHWScreen), al modo fisico, que
//es en realidad el unico modo grafico que existe, el modo en que hemos arrancado.
//Esto explica por que creamos el plano de overlay a parte, 
//ya que cuando SDL_Video.c llama a SetVideoMode aun no se tienen listos los 
//offsets horizontal y vertical donde empieza el modo de video pequenio 
//(el modo en que corre la app internamente) sobre el grande (el modo fisico).
	
	//Si nos pasan width=0 y height=0, interpreto que el programa no quiere video sino
	//que solo necesita entrar en modo grafico, asi que salto alli:
	if ((width == 0) | (height == 0)) goto go_video_console;	

	//MAC Inicializamos el SOC (bcm_host_init) SOLO si no hemos pasado antes por aqui­. Lo mismo con el fondo.
	//Si ya hemos pasado antes, hacemos limpieza, pero dejamos el fondo sin tocar.
	if (dispvars->pixmem != NULL){
		//Hacemos limpieza de resources, pero dejamos el fondo. No hay problema porque solo lo ponemos
		//si no hemos pasado por aqui antes.
		DISPMANX_FreeResources();	
	}
	else {
    		uint32_t screen = 0;
		
		bcm_host_init();
		
		//MAC Abrimos el display dispmanx
		printf("Dispmanx: Opening display %i\n", screen );
        	dispvars->display = vc_dispmanx_display_open( screen );

		//MAC Recuperamos algunos datos de la configuracion del buffer actual
		vc_dispmanx_display_get_info( dispvars->display, &(dispvars->amode));
		printf( "Dispmanx: Physical video mode is %d x %d\n", 
		dispvars->amode.width, dispvars->amode.height );
		
		//Ponemos el element de fondo negro tanto si se respeta el ratio como si no, 
		//porque si no, se nos vera­a la consola al cambiar de resolucion durante el programa.
		DISPMANX_BlankBackground();
	}	
	


	//-------Bloque de lista de resoluciones, originalmente en VideoInit--------------
	//Para la aplicacion SDL, el unico modo de video disponible va a ser siempre el que pida. 
	
	DISPMANX_AddMode(this, width, height, (((bpp+7)/8)-1));

	//---------------------------------------------------------------------------------	
	
	Uint32 Rmask;
	Uint32 Gmask;
	Uint32 Bmask;
	
	//dispvars->pitch = width * ((bpp+7) /8);

	//MAC Establecemos el pitch en funcion del bpp deseado
        //Lo alineamos a 16 porque es el aligment interno de dispmanx(en ejemp)
	dispvars->bits_per_pixel = bpp;	
        dispvars->pitch = ( ALIGN_UP( width, 16 ) * (bpp/8) );
        //Alineamos la atura a 16 por el mismo motivo (ver ejemplo hello_disp)
        height = ALIGN_UP( height, 16);

	switch (bpp){
	   case 8:
		dispvars->pix_format = VC_IMAGE_8BPP;	       
		break;
	   
	   case 16:
		dispvars->pix_format = VC_IMAGE_RGB565;	       
		break;

	   case 32:
		dispvars->pix_format = VC_IMAGE_XRGB8888;	       
	        break;
           
           default:
	      printf ("\n[ERROR] - wrong bpp: %d\n",bpp);
	      return (NULL);
	}	
	    	
	//MAC blah 
	this->UpdateRects = DISPMANX_DirectUpdate;

	printf ("\nUsing internal program mode: %d x %d %d bpp", 
		width, height, dispvars->bits_per_pixel);	

	//MAC Por ahora en DISPMANX usamos el mismo modo q ya esta establecido
	printf ("\nUsing physical mode: %d x %d %d bpp",
		dispvars->amode.width, dispvars->amode.height,
		dispvars->bits_per_pixel);
	
	//-----------------------------------------------------------------------------
	//Esta parte no es fundamental, solo sirve para conservar el ratio del juego.
	//Si no se hace y simplemente quitas estas lineas, se estira al modo fisico y ya, 
	//quedando la imagen deformada si es de 4:3 en una tele de 16:9, que es lo que pasaba antes.	
	//Simplemente hallamos ese ratio y con el hallamos la nueva anchura, considerando
	//como altura la maxima fisica que tenemos establecida, o sea, la altura del modo fisico establecido. 
	//Tambien se calcula la posicion horizontal en que debe empezar el rect de destino (dst_ypos), 
	//para que no quede pegado a la parte izquierda de la pantalla al ser menor que la resolucion fisica, que
	//obviamente no cambia. 
	//Queda obsoleto si cambiamos la resolucion a una que tenga el mismo ratio que el modo original del juego.
	
	dispvars->ignore_ratio = (int) SDL_getenv("SDL_DISPMANX_IGNORE_RATIO");

	if (dispvars->ignore_ratio)
		vc_dispmanx_rect_set( &(dispvars->dst_rect), 0, 0, 
	   		dispvars->amode.width , dispvars->amode.height );
	else {
		float orig_ratio = ((float)width / (float)height); 
		int dst_width = dispvars->amode.height * orig_ratio;	
		
		//Si la anchura de la imagen escalada nos sale mayor que el ancho fisico de pantalla,
		//mantenemos el ancho fisico de pantalla como anchura maxima.
		if (dst_width > dispvars->amode.width) dst_width = dispvars->amode.width;

		int dst_ypos  = (dispvars->amode.width - dst_width) / 2; 
		printf ("\nUsing proportion ratio: %d / %d = %f", width, height, orig_ratio);
		printf ("\nProgram rect, respecting original ratio: %d x %d \n", 
		dst_width, dispvars->amode.height);

		vc_dispmanx_rect_set( &(dispvars->dst_rect), dst_ypos, 0, 
	   		dst_width , dispvars->amode.height );
			
	}

	//---------------------------Dejamos configurados los rects---------------------
	//Recuerda que los rects NO contienen ninguna informacion visual, solo son tamanio, rectangulos
	//descritos para que los entiendan las funciones vc, solo tamanios de areas.
	//
	//bmp_rect: se usa solo para el volcado del buffer en RAM al resource que toque. Define el tamanio
	//del area a copiar de RAM (pixmem) al resource (dispmam->resources[]) usando write_data(), por
	//eso, y para acabarlo de entender del todo, su altura y anchura son las internas del juego, width y height.
	//
	//src_rect y dst_rect: se usan porque un element necesita dos rects definidos: src_rect es el tamanio del area
	//de entrada,o sea, el tamanio con el que clipeamos la imagen de origen, y dst_rect es el tamanio del area de
	//salida, o sea, el tamanio con que se vera, escalada por hardware, en el element.
	//
	//Por todo esto, src_rect tendra generalmente la altura y anchura de la imagen original, o dicho de otro
	//modo la altura y anchura que usa el juego internamente (width << 16 y height << 16 por algun rollo de
	//tamanio de variable), y dst_rect tendra las dimensiones del area de pantalla a la que queremos escalar
	//esa imagen: si le damos las dimensiones fisicas totales de la pantalla, escalara sin respetar el ratio.   
	//Asi­que lo he corregido manteniendo la altura maxima de la pantalla fisica, y calculando la anchura
	//a partir de dicha altura y el ratio de la imagen (de la resolucion del juego) original.
	//
	//Debes pensar siempre de la siguiente manera: un element, que es como un cristal-lupa, un resource 
	//(aunque tengas dos, en un momento dado el element solo tiene uno) que es como la imagen original,
	//muy pequenita al fondo, y un "embudo", cuyo tamanio del extremo inferior pegado a la imagen original 
	//es de tamanio src_rect, y cuyo tamanio del extremo superior, pegado al element, es de tamanio dst_rect.
	
	vc_dispmanx_rect_set (&(dispvars->bmp_rect), 0, 0, 
	   width, height);	
	
	vc_dispmanx_rect_set (&(dispvars->src_rect), 0, 0, 
	   width << 16, height << 16);	

	//------------------------------------------------------------------------------
	
	//MAC Establecemos alpha. Para transparencia descomentar flags con or.
	VC_DISPMANX_ALPHA_T layerAlpha;
	/*layerAlpha.flags = (DISPMANX_FLAGS_ALPHA_FROM_SOURCE | 
           DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS);*/
	layerAlpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS;
	layerAlpha.opacity = 255;
	layerAlpha.mask	   = 0;
	dispvars->alpha = &layerAlpha;
	
	//MAC Creo los resources. Me hacen falta dos para el double buffering
	dispvars->resources[0] = vc_dispmanx_resource_create( 
	   dispvars->pix_format, width, height, 
	   &(dispvars->vc_image_ptr) );
	
	dispvars->resources[1] = vc_dispmanx_resource_create( 
	   dispvars->pix_format, width, height,
	   &(dispvars->vc_image_ptr) );
	
	//Reservo memoria para el array de pixles en RAM 
    	dispvars->pixmem = calloc( 1, dispvars->pitch * height);
    	//dispvars->pixmem=malloc ( dispvars->pitch * dispvars->amode.height );

	//MAC Esta llamada a ReallocFormat es lo que impedia­a ver algo...
	Rmask = 0;
	Gmask = 0;
	Bmask = 0;
	if ( ! SDL_ReallocFormat(current, bpp, Rmask, Gmask, Bmask, 0) ) {
		return(NULL);
	}
	
	//Preparamos SDL para trabajar sobre el nuevo framebuffer

	//No queremos HWSURFACEs por la manera en que funciona nuestro backend, ya que la app solo
	//debe conocer el buffer en RAM para que las actualizaciones no sean bloqueantes.
	//TAMPOCO queremos DOUBLEBUFFER: realmente piensa lo que estas haciendo: actualizas la 
	//superficie de video, que esta en la RAM, copias a VRAM y, saltandote las normas del API,
	//esperas a evento de vsync para hacer el buffer swapping. Asi­ que la app NO SABE NADA de 
	//double buffering ni debe saberlo. UpdateRect() debe hacer lo que antes hacia­a FlipHWSurface,
	//ya que de cara a la APP, solo hay una actualizacion del buffer de dibujado, NO de pantalla,
	//ya que carecemos de acceso directo a la VRAM.
	//Permitimos HWPALETTEs, cosa que solo se activa si el juego pide un modo de 8bpp porque,
	//tanto si conseguimos modificar la paleta por hard como si tenemos que indexar los valores
	//como estamos haciendo hasta ahora emulando asi la paleta, nos interesa que los juegos
	//entren en SetColors(), y sin paleta por hardware no entran.
	
	current->flags |= SDL_FULLSCREEN;	
	if (flags & SDL_DOUBLEBUF){
	   current->flags &= ~SDL_DOUBLEBUF;	
	}
	if (flags & SDL_HWSURFACE){
	   current->flags &= ~SDL_HWSURFACE;
	   current->flags |= SDL_SWSURFACE;
	}	
	if (flags & SDL_HWPALETTE)
	   current->flags |= SDL_HWPALETTE;	
	
	current->w = width;
	current->h = height;

	current->pitch  = dispvars->pitch;
	current->pixels = dispvars->pixmem;
	
	//DISPMANX_FreeHWSurfaces(this);
	//DISPMANX_InitHWSurfaces(this, current, surfaces_mem, surfaces_len);
	
	//this->screen = current;
	//this->screen = NULL;

	//Aniadimos el element.
	dispvars->update = vc_dispmanx_update_start( 0 );
	
	dispvars->element = vc_dispmanx_element_add( dispvars->update, 
	   dispvars->display, 0 /*layer*/, &(dispvars->dst_rect), 	   
	   dispvars->resources[flip_page], &(dispvars->src_rect), 
	   DISPMANX_PROTECTION_NONE, dispvars->alpha, 0 /*clamp*/, 
	   /*VC_IMAGE_ROT0*/ 0 );
	
	vc_dispmanx_update_submit_sync( dispvars->update );		
	
	/* We're done */
	//MAC Disable graphics 1
	//Aqui ponemos la terminal en modo grafico. Ya no se imprimiran mas mensajes en la consola a partir de aqui. 
	go_video_console:
	if ( DISPMANX_EnterGraphicsMode(this) < 0 )
        	return(NULL);

	
	return(current);
}
Esempio n. 12
0
static bool gfx_ctx_init(void)
{
   RARCH_LOG("[VC/EGL]: Initializing...\n");
   if (g_inited)
   {
      RARCH_ERR("[VC/EGL]: Attempted to re-initialize driver.\n");
      return false;
   }

   EGLint num_config;
   static EGL_DISPMANX_WINDOW_T nativewindow;

   DISPMANX_ELEMENT_HANDLE_T dispman_element;
   DISPMANX_DISPLAY_HANDLE_T dispman_display;
   DISPMANX_UPDATE_HANDLE_T dispman_update;
   DISPMANX_MODEINFO_T dispman_modeinfo;
   VC_RECT_T dst_rect;
   VC_RECT_T src_rect;

   static const EGLint attribute_list[] =
   {
      EGL_RED_SIZE, 8,
      EGL_GREEN_SIZE, 8,
      EGL_BLUE_SIZE, 8,
      EGL_ALPHA_SIZE, 8,
      EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
      EGL_NONE
   };

   static const EGLint context_attributes[] =
   {
      EGL_CONTEXT_CLIENT_VERSION, 2,
      EGL_NONE
   };

   bcm_host_init();

   // get an EGL display connection
   g_egl_dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
   if (!g_egl_dpy)
      goto error;

   // initialize the EGL display connection
   if (!eglInitialize(g_egl_dpy, NULL, NULL))
      goto error;

   // get an appropriate EGL frame buffer configuration
   if (!eglChooseConfig(g_egl_dpy, attribute_list, &g_config, 1, &num_config))
      goto error;

   // create an EGL rendering context
   g_egl_ctx = eglCreateContext(g_egl_dpy, g_config, EGL_NO_CONTEXT, (g_api == GFX_CTX_OPENGL_ES_API) ? context_attributes : NULL);
   if (!g_egl_ctx)
      goto error;

   // create an EGL window surface
   if (graphics_get_display_size(0 /* LCD */, &g_fb_width, &g_fb_height) < 0)
      goto error;

   dst_rect.x = 0;
   dst_rect.y = 0;
   dst_rect.width = g_fb_width;
   dst_rect.height = g_fb_height;

   src_rect.x = 0;
   src_rect.y = 0;
   src_rect.width = g_fb_width << 16;
   src_rect.height = g_fb_height << 16;

   dispman_display = vc_dispmanx_display_open(0 /* LCD */);
   vc_dispmanx_display_get_info(dispman_display, &dispman_modeinfo);
   dispman_update = vc_dispmanx_update_start(0);

   VC_DISPMANX_ALPHA_T alpha;
   alpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS;
   alpha.opacity = 255;
   alpha.mask = 0;

   dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display,
      0 /*layer*/, &dst_rect, 0 /*src*/,
      &src_rect, DISPMANX_PROTECTION_NONE, &alpha, 0 /*clamp*/, DISPMANX_NO_ROTATE);

   nativewindow.element = dispman_element;
   nativewindow.width = g_fb_width;
   nativewindow.height = g_fb_height;
   vc_dispmanx_update_submit_sync(dispman_update);

   g_egl_surf = eglCreateWindowSurface(g_egl_dpy, g_config, &nativewindow, NULL);
   if (!g_egl_surf)
      goto error;

   // connect the context to the surface
   if (!eglMakeCurrent(g_egl_dpy, g_egl_surf, g_egl_surf, g_egl_ctx))
      goto error;

   return true;

error:
   gfx_ctx_destroy();
   return false;
}
Esempio n. 13
0
static void *rpi_init(const video_info_t *video, const input_driver_t **input, void **input_data)
{
   int32_t success;
   EGLBoolean result;
   EGLint num_config;
   rpi_t *rpi = (rpi_t*)calloc(1, sizeof(rpi_t));
   *input = NULL;

   static EGL_DISPMANX_WINDOW_T nativewindow;

   DISPMANX_ELEMENT_HANDLE_T dispman_element;
   DISPMANX_DISPLAY_HANDLE_T dispman_display;
   DISPMANX_UPDATE_HANDLE_T dispman_update;
   DISPMANX_MODEINFO_T dispman_modeinfo;
   VC_RECT_T dst_rect;
   VC_RECT_T src_rect;

   static const EGLint attribute_list[] =
   {
      EGL_RED_SIZE, 8,
      EGL_GREEN_SIZE, 8,
      EGL_BLUE_SIZE, 8,
      EGL_ALPHA_SIZE, 8,
      EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
      EGL_NONE
   };

   EGLConfig config;

   bcm_host_init();

   // get an EGL display connection
   rpi->mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
   rarch_assert(rpi->mDisplay != EGL_NO_DISPLAY);

   // initialize the EGL display connection
   result = eglInitialize(rpi->mDisplay, NULL, NULL);
   rarch_assert(result != EGL_FALSE);
   eglBindAPI(EGL_OPENVG_API);

   // get an appropriate EGL frame buffer configuration
   result = eglChooseConfig(rpi->mDisplay, attribute_list, &config, 1, &num_config);
   rarch_assert(result != EGL_FALSE);

   // create an EGL rendering context
   rpi->mContext = eglCreateContext(rpi->mDisplay, config, EGL_NO_CONTEXT, NULL);
   rarch_assert(rpi->mContext != EGL_NO_CONTEXT);

   // create an EGL window surface
   success = graphics_get_display_size(0 /* LCD */, &rpi->mScreenWidth, &rpi->mScreenHeight);
   rarch_assert(success >= 0);

   dst_rect.x = 0;
   dst_rect.y = 0;
   dst_rect.width = rpi->mScreenWidth;
   dst_rect.height = rpi->mScreenHeight;

   src_rect.x = 0;
   src_rect.y = 0;
   src_rect.width = rpi->mScreenWidth << 16;
   src_rect.height = rpi->mScreenHeight << 16;

   dispman_display = vc_dispmanx_display_open(0 /* LCD */);
   vc_dispmanx_display_get_info(dispman_display, &dispman_modeinfo);
   dispman_update = vc_dispmanx_update_start(0);

   dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display,
      0 /*layer*/, &dst_rect, 0 /*src*/,
      &src_rect, DISPMANX_PROTECTION_NONE, 0 /*alpha*/, 0 /*clamp*/, DISPMANX_NO_ROTATE);

   nativewindow.element = dispman_element;
   nativewindow.width = rpi->mScreenWidth;
   nativewindow.height = rpi->mScreenHeight;
   vc_dispmanx_update_submit_sync(dispman_update);

   rpi->mSurface = eglCreateWindowSurface(rpi->mDisplay, config, &nativewindow, NULL);
   rarch_assert(rpi->mSurface != EGL_NO_SURFACE);

   // connect the context to the surface
   result = eglMakeCurrent(rpi->mDisplay, rpi->mSurface, rpi->mSurface, rpi->mContext);
   rarch_assert(result != EGL_FALSE);

   rpi->mTexType = video->rgb32 ? VG_sABGR_8888 : VG_sARGB_1555;
   rpi->mKeepAspect = video->force_aspect;

   // check for SD televisions: they should always be 4:3
   if (dispman_modeinfo.width == 720 && (dispman_modeinfo.height == 480 || dispman_modeinfo.height == 576))
      rpi->mScreenAspect = 4.0f / 3.0f;
   else
      rpi->mScreenAspect = (float)dispman_modeinfo.width / dispman_modeinfo.height;

   VGfloat clearColor[4] = {0, 0, 0, 1};
   vgSetfv(VG_CLEAR_COLOR, 4, clearColor);

   rpi->mTextureWidth = rpi->mTextureHeight = video->input_scale * RARCH_SCALE_BASE;
   // We can't use the native format because there's no sXRGB_1555 type and
   // emulation cores can send 0 in the top bit. We lose some speed on
   // conversion but I doubt it has any real affect, since we are only drawing
   // one image at the end of the day. Still keep the alpha channel for ABGR.
   rpi->mImage = vgCreateImage(video->rgb32 ? VG_sABGR_8888 : VG_sXBGR_8888,
         rpi->mTextureWidth, rpi->mTextureHeight,
         video->smooth ? VG_IMAGE_QUALITY_BETTER : VG_IMAGE_QUALITY_NONANTIALIASED);
   rpi_set_nonblock_state(rpi, !video->vsync);

   linuxraw_input_t *linuxraw_input = (linuxraw_input_t*)input_linuxraw.init();
   if (linuxraw_input)
   {
      *input = (const input_driver_t *)&input_linuxraw;
      *input_data = linuxraw_input;
   }

#ifdef HAVE_FREETYPE
   if (g_settings.video.font_enable)
   {
      rpi->mFont = vgCreateFont(0);
      rpi->mFontHeight = g_settings.video.font_size * (g_settings.video.font_scale ? (float) rpi->mScreenWidth / 1280.0f : 1.0f);

      const char *path = g_settings.video.font_path;
      if (!*path || !path_file_exists(path))
         path = font_renderer_get_default_font();

      rpi->mFontRenderer = font_renderer_new(path, rpi->mFontHeight);

      if (rpi->mFont != VG_INVALID_HANDLE && rpi->mFontRenderer)
      {
         rpi->mFontsOn = true;

         rpi->mPaintFg = vgCreatePaint();
         rpi->mPaintBg = vgCreatePaint();
         VGfloat paintFg[] = { g_settings.video.msg_color_r, g_settings.video.msg_color_g, g_settings.video.msg_color_b, 1.0f };
         VGfloat paintBg[] = { g_settings.video.msg_color_r / 2.0f, g_settings.video.msg_color_g / 2.0f, g_settings.video.msg_color_b / 2.0f, 0.5f };

         vgSetParameteri(rpi->mPaintFg, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
         vgSetParameterfv(rpi->mPaintFg, VG_PAINT_COLOR, 4, paintFg);

         vgSetParameteri(rpi->mPaintBg, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
         vgSetParameterfv(rpi->mPaintBg, VG_PAINT_COLOR, 4, paintBg);
      }
   }
#endif

   struct sigaction sa;
   sa.sa_handler = rpi_kill;
   sa.sa_flags = SA_RESTART;
   sigemptyset(&sa.sa_mask);
   sigaction(SIGINT, &sa, NULL);
   sigaction(SIGTERM, &sa, NULL);

   return rpi;
}
Esempio n. 14
0
static void *gfx_ctx_vc_init(video_frame_info_t *video_info, void *video_driver)
{
   VC_DISPMANX_ALPHA_T alpha;
   EGLint n, major, minor;

   DISPMANX_ELEMENT_HANDLE_T dispman_element;
   DISPMANX_DISPLAY_HANDLE_T dispman_display;
   DISPMANX_UPDATE_HANDLE_T dispman_update;
   DISPMANX_MODEINFO_T dispman_modeinfo;
   VC_RECT_T dst_rect;
   VC_RECT_T src_rect;

#ifdef HAVE_EGL
   static const EGLint attribute_list[] =
   {
      EGL_RED_SIZE, 8,
      EGL_GREEN_SIZE, 8,
      EGL_BLUE_SIZE, 8,
      EGL_ALPHA_SIZE, 8,
      EGL_DEPTH_SIZE, 16,
      EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
      EGL_NONE
   };

   static const EGLint context_attributes[] =
   {
      EGL_CONTEXT_CLIENT_VERSION, 2,
      EGL_NONE
   };
#endif
   settings_t *settings = config_get_ptr();
   vc_ctx_data_t *vc    = NULL;

   if (g_egl_inited)
   {
      RARCH_ERR("[VC/EGL]: Attempted to re-initialize driver.\n");
      return NULL;
   }

   vc = (vc_ctx_data_t*)calloc(1, sizeof(*vc));

   if (!vc)
       return NULL;

   /* If we set this env variable, Broadcom's EGL implementation will block
    * on vsync with a double buffer when we call eglSwapBuffers. Less input lag!
    * Has to be done before any EGL call.
    * NOTE this is commented out because it should be the right way to do it, but
    * currently it doesn't work, so we are using an vsync callback based solution.*/
   /* if (video_info->max_swapchain_images <= 2)
      setenv("V3D_DOUBLE_BUFFER", "1", 1);
   else
      setenv("V3D_DOUBLE_BUFFER", "0", 1); */

   bcm_host_init();

#ifdef HAVE_EGL
   if (!egl_init_context(&vc->egl, EGL_NONE, EGL_DEFAULT_DISPLAY,
            &major, &minor, &n, attribute_list))
   {
      egl_report_error();
      goto error;
   }

   if (!egl_create_context(&vc->egl, (vc_api == GFX_CTX_OPENGL_ES_API)
            ? context_attributes : NULL))
   {
      egl_report_error();
      goto error;
   }
#endif

   /* Create an EGL window surface. */
   if (graphics_get_display_size(0 /* LCD */, &vc->fb_width, &vc->fb_height) < 0)
      goto error;

   dst_rect.x      = 0;
   dst_rect.y      = 0;
   dst_rect.width  = vc->fb_width;
   dst_rect.height = vc->fb_height;

   src_rect.x      = 0;
   src_rect.y      = 0;

   /* Use dispmanx upscaling if fullscreen_x
    * and fullscreen_y are set. */
   if ((settings->uints.video_fullscreen_x != 0) &&
       (settings->uints.video_fullscreen_y != 0))
   {
      /* Keep input and output aspect ratio equal.
       * There are other aspect ratio settings which can be used to stretch video output. */

      /* Calculate source and destination aspect ratios. */
      float srcAspect        = (float)settings->uints.video_fullscreen_x / (float)settings->uints.video_fullscreen_y;
      float dstAspect        = (float)vc->fb_width / (float)vc->fb_height;
      /* If source and destination aspect ratios are not equal correct source width. */
      if (srcAspect != dstAspect)
         src_rect.width      = (unsigned)(settings->uints.video_fullscreen_y * dstAspect) << 16;
      else
         src_rect.width      = settings->uints.video_fullscreen_x << 16;
      src_rect.height        = settings->uints.video_fullscreen_y << 16;
   }
   else
   {
      src_rect.width         = vc->fb_width << 16;
      src_rect.height        = vc->fb_height << 16;
   }

   dispman_display           = vc_dispmanx_display_open(0 /* LCD */);
   vc->dispman_display       = dispman_display;

   vc_dispmanx_display_get_info(dispman_display, &dispman_modeinfo);

   dispman_update            = vc_dispmanx_update_start(0);

   alpha.flags               = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS;
   alpha.opacity             = 255;
   alpha.mask                = 0;

   dispman_element           = vc_dispmanx_element_add(dispman_update, dispman_display,
         0 /*layer*/, &dst_rect, 0 /*src*/,
         &src_rect, DISPMANX_PROTECTION_NONE, &alpha, 0 /*clamp*/, DISPMANX_NO_ROTATE);

   vc->native_window.element = dispman_element;

   /* Use dispmanx upscaling if fullscreen_x and fullscreen_y are set. */

   if (settings->uints.video_fullscreen_x != 0 &&
       settings->uints.video_fullscreen_y != 0)
   {
      /* Keep input and output aspect ratio equal.
       * There are other aspect ratio settings which
       * can be used to stretch video output. */

      /* Calculate source and destination aspect ratios. */
      float srcAspect = (float)settings->uints.video_fullscreen_x
         / (float)settings->uints.video_fullscreen_y;
      float dstAspect = (float)vc->fb_width / (float)vc->fb_height;

      /* If source and destination aspect ratios are not equal correct source width. */
      if (srcAspect != dstAspect)
         vc->native_window.width = (unsigned)(settings->uints.video_fullscreen_y * dstAspect);
      else
         vc->native_window.width = settings->uints.video_fullscreen_x;
      vc->native_window.height   = settings->uints.video_fullscreen_y;
   }
   else
   {
      vc->native_window.width = vc->fb_width;
      vc->native_window.height = vc->fb_height;
   }
   vc_dispmanx_update_submit_sync(dispman_update);

#ifdef HAVE_EGL
   if (!egl_create_surface(&vc->egl, &vc->native_window))
      goto error;
#endif

   /* For vsync after eglSwapBuffers when max_swapchain < 3 */
   vc->vsync_condition       = scond_new();
   vc->vsync_condition_mutex = slock_new();
   vc->vsync_callback_set    = false;

   if (video_info->max_swapchain_images <= 2)
   {
      /* Start sending vsync callbacks so we can wait for vsync after eglSwapBuffers */
      vc_dispmanx_vsync_callback(vc->dispman_display,
            dispmanx_vsync_callback, (void*)vc);
      vc->vsync_callback_set = true;
   }

   return vc;

error:
   gfx_ctx_vc_destroy(video_driver);
   return NULL;
}
Esempio n. 15
0
static void open_screen(struct uae_prefs *p)
{

  VC_DISPMANX_ALPHA_T alpha = { (DISPMANX_FLAGS_ALPHA_T ) (DISPMANX_FLAGS_ALPHA_FROM_SOURCE | DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS), 
                            255, /*alpha 0->255*/
                            0 };


  uint32_t     vc_image_ptr;
  int          width;
  int          height;

#ifdef PICASSO96
  if (screen_is_picasso)
  {
    width  = picasso_vidinfo.width;
    height = picasso_vidinfo.height;
  } else
#endif
  {
    p->gfx_resolution = p->gfx_size.width > 600 ? 1 : 0;
    width  = p->gfx_size.width;
    height = p->gfx_size.height;
  }


  //if(prSDLScreen != NULL)
  //{
  //  SDL_FreeSurface(prSDLScreen);
  //  prSDLScreen = NULL;
  //} 

  if(Dummy_prSDLScreen == NULL )
  {
    const SDL_VideoInfo* videoInfo = SDL_GetVideoInfo ();
    printf("DispmanX: Current resolution: %d x %d %d bpp\n",videoInfo->current_w, videoInfo->current_h, videoInfo->vfmt->BitsPerPixel);
    Dummy_prSDLScreen = SDL_SetVideoMode(videoInfo->current_w,videoInfo->current_h,16,SDL_SWSURFACE |SDL_FULLSCREEN);
    //Dummy_prSDLScreen = SDL_SetVideoMode(800,480,16,SDL_SWSURFACE );
  }

  SDL_ShowCursor(SDL_DISABLE);

  // check if resolution hasn't change in menu. otherwise free the resources so that they will be re-generated with new resolution.
  if ((dispmanxresource_amigafb_1 != 0) && 
     ((blit_rect.width != width) || (blit_rect.height != height) || (currprefs.gfx_correct_aspect != changed_prefs.gfx_correct_aspect)))
  {
	printf("Emulation resolution change detected.\n");
	if(prSDLScreen != NULL )
	{
		SDL_FreeSurface(prSDLScreen);
		prSDLScreen = 0;
	}
	graphics_dispmanshutdown();
	vc_dispmanx_resource_delete( dispmanxresource_amigafb_1 );
	vc_dispmanx_resource_delete( dispmanxresource_amigafb_2 );
	dispmanxresource_amigafb_1 = 0;
	dispmanxresource_amigafb_2 = 0;
  }

  if (dispmanxresource_amigafb_1 == 0)
  {
	printf("Emulation resolution: Width %i Height: %i\n",width,height);
	currprefs.gfx_correct_aspect = changed_prefs.gfx_correct_aspect;
	prSDLScreen = SDL_CreateRGBSurface(SDL_SWSURFACE,width,height,16,
		Dummy_prSDLScreen->format->Rmask,
		Dummy_prSDLScreen->format->Gmask,
		Dummy_prSDLScreen->format->Bmask,
		Dummy_prSDLScreen->format->Amask);

	dispmanxdisplay = vc_dispmanx_display_open( 0 );
	vc_dispmanx_display_get_info( dispmanxdisplay, &dispmanxdinfo);

	dispmanxresource_amigafb_1 = vc_dispmanx_resource_create( VC_IMAGE_RGB565,  width,   height,  &vc_image_ptr);
	dispmanxresource_amigafb_2 = vc_dispmanx_resource_create( VC_IMAGE_RGB565,  width,   height,  &vc_image_ptr);
	vc_dispmanx_rect_set( &blit_rect, 0, 0, width,height);
	vc_dispmanx_resource_write_data(  dispmanxresource_amigafb_1,
                                    VC_IMAGE_RGB565,
                                    width *2,
                                    prSDLScreen->pixels,
                                    &blit_rect );
	vc_dispmanx_rect_set( &src_rect, 0, 0, width << 16, height << 16 );

  }
  // 16/9 to 4/3 ratio adaptation.
  if (currprefs.gfx_correct_aspect == 0)
  {
	// Fullscreen.
	vc_dispmanx_rect_set( &dst_rect, (dispmanxdinfo.width * 1)/100,
							(dispmanxdinfo.height * 2)/100 ,
							dispmanxdinfo.width - (dispmanxdinfo.width * 2)/100 ,
							dispmanxdinfo.height - (dispmanxdinfo.height * 4)/100 );
  }
  else
  {
	// 4/3 shrink.
	vc_dispmanx_rect_set( &dst_rect, ((dispmanxdinfo.width * 13)/100) ,
							(dispmanxdinfo.height * 2)/100 ,
							(dispmanxdinfo.width - ((dispmanxdinfo.width * 26)/100)) ,
							dispmanxdinfo.height - (dispmanxdinfo.height * 4)/100 );
  }

  // For debug, in order to avoid full screen.
  //vc_dispmanx_rect_set( &dst_rect, (dispmanxdinfo.width /2),
  //                     (dispmanxdinfo.height /2) ,
  //                     (dispmanxdinfo.width - (dispmanxdinfo.width * 6)/100 )/2,
  //                     (dispmanxdinfo.height - (dispmanxdinfo.height * 7)/100 )/2);


  if (DispManXElementpresent == 0)
  {
     DispManXElementpresent = 1;
     dispmanxupdate = vc_dispmanx_update_start( 10 );
     dispmanxelement = vc_dispmanx_element_add( dispmanxupdate,
                                        dispmanxdisplay,
                                        2000,               // layer
                                        &dst_rect,
                                        dispmanxresource_amigafb_1,
                                        &src_rect,
                                        DISPMANX_PROTECTION_NONE,
                                        &alpha,
                                        NULL,             // clamp
                                        DISPMANX_NO_ROTATE );

    vc_dispmanx_update_submit(dispmanxupdate,NULL,NULL);
    //dispmanxupdate = vc_dispmanx_update_start( 10 );
  }

  if(prSDLScreen != NULL)
  {
    InitAmigaVidMode(p);
    init_row_map();
  }    
  //framecnt = 1; // Don't draw frame before reset done
}
Esempio n. 16
0
int
main(
    int argc,
    char *argv[])
{
    int opt = 0;

    bool writeToStdout = false;
    char *pngName = DEFAULT_NAME;
    int32_t requestedWidth = 0;
    int32_t requestedHeight = 0;
    uint32_t displayNumber = DEFAULT_DISPLAY_NUMBER;
    int compression = Z_DEFAULT_COMPRESSION;
    int delay = DEFAULT_DELAY;

    VC_IMAGE_TYPE_T imageType = VC_IMAGE_RGBA32;
    int8_t dmxBytesPerPixel  = 4;

    int result = 0;

    program = basename(argv[0]);

    //-------------------------------------------------------------------

    char *sopts = "c:d:D:Hh:p:w:s";

    struct option lopts[] =
    {
        { "compression", required_argument, NULL, 'c' },
        { "delay", required_argument, NULL, 'd' },
        { "display", required_argument, NULL, 'D' },
        { "height", required_argument, NULL, 'h' },
        { "help", no_argument, NULL, 'H' },
        { "pngname", required_argument, NULL, 'p' },
        { "width", required_argument, NULL, 'w' },
        { "stdout", no_argument, NULL, 's' },
        { NULL, no_argument, NULL, 0 }
    };

    while ((opt = getopt_long(argc, argv, sopts, lopts, NULL)) != -1)
    {
        switch (opt)
        {
        case 'c':

            compression = atoi(optarg);

            if ((compression < 0) || (compression > 9))
            {
                compression = Z_DEFAULT_COMPRESSION;
            }

            break;

        case 'd':

            delay = atoi(optarg);
            break;

        case 'D':

            displayNumber = atoi(optarg);
            break;

        case 'h':

            requestedHeight = atoi(optarg);
            break;

        case 'p':

            pngName = optarg;
            break;

        case 'w':

            requestedWidth = atoi(optarg);
            break;

        case 's':

            writeToStdout = true;
            break;

        case 'H':
        default:

            usage();

            if (opt == 'H')
            {
                exit(EXIT_SUCCESS);
            }
            else
            {
                exit(EXIT_FAILURE);
            }

            break;
        }
    }

    //-------------------------------------------------------------------

    bcm_host_init();

    //-------------------------------------------------------------------
    //
    // When the display is rotate (either 90 or 270 degrees) we need to
    // swap the width and height of the snapshot
    //

    char response[1024];
    int displayRotated = 0;

    if (vc_gencmd(response, sizeof(response), "get_config int") == 0)
    {
        vc_gencmd_number_property(response,
                                  "display_rotate",
                                  &displayRotated);
    }

    //-------------------------------------------------------------------

    if (delay)
    {
        sleep(delay);
    }

    //-------------------------------------------------------------------

    DISPMANX_DISPLAY_HANDLE_T displayHandle
        = vc_dispmanx_display_open(displayNumber);

    if (displayHandle == 0)
    {
        fprintf(stderr,
                "%s: unable to open display %d\n",
                program,
                displayNumber);

        exit(EXIT_FAILURE);
    }

    DISPMANX_MODEINFO_T modeInfo;
    result = vc_dispmanx_display_get_info(displayHandle, &modeInfo);

    if (result != 0)
    {
        fprintf(stderr, "%s: unable to get display information\n", program);
        exit(EXIT_FAILURE);
    }

    int32_t pngWidth = modeInfo.width;
    int32_t pngHeight = modeInfo.height;

    if (requestedWidth > 0)
    {
        pngWidth = requestedWidth;

        if (requestedHeight == 0)
        {
            double numerator = modeInfo.height * requestedWidth;
            double denominator = modeInfo.width;

            pngHeight = (int32_t)ceil(numerator / denominator);
        }
    }

    if (requestedHeight > 0)
    {
        pngHeight = requestedHeight;

        if (requestedWidth == 0)
        {
            double numerator = modeInfo.width * requestedHeight;
            double denominator = modeInfo.height;

            pngWidth = (int32_t)ceil(numerator / denominator);
        }
    }

    //-------------------------------------------------------------------
    // only need to check low bit of displayRotated (value of 1 or 3).
    // If the display is rotated either 90 or 270 degrees (value 1 or 3)
    // the width and height need to be transposed.

    int32_t dmxWidth = pngWidth;
    int32_t dmxHeight = pngHeight;

    if (displayRotated & 1)
    {
        dmxWidth = pngHeight;
        dmxHeight = pngWidth;
    }

    int32_t dmxPitch = dmxBytesPerPixel * ALIGN_TO_16(dmxWidth);

    void *dmxImagePtr = malloc(dmxPitch * dmxHeight);

    if (dmxImagePtr == NULL)
    {
        fprintf(stderr, "%s: unable to allocated image buffer\n", program);
        exit(EXIT_FAILURE);
    }

    //-------------------------------------------------------------------

    uint32_t vcImagePtr = 0;
    DISPMANX_RESOURCE_HANDLE_T resourceHandle;
    resourceHandle = vc_dispmanx_resource_create(imageType,
                                                 dmxWidth,
                                                 dmxHeight,
                                                 &vcImagePtr);

    result = vc_dispmanx_snapshot(displayHandle,
                                  resourceHandle,
                                  DISPMANX_NO_ROTATE);

    if (result != 0)
    {
        vc_dispmanx_resource_delete(resourceHandle);
        vc_dispmanx_display_close(displayHandle);

        fprintf(stderr, "%s: vc_dispmanx_snapshot() failed\n", program);
        exit(EXIT_FAILURE);
    }

    VC_RECT_T rect;
    result = vc_dispmanx_rect_set(&rect, 0, 0, dmxWidth, dmxHeight);

    if (result != 0)
    {
        vc_dispmanx_resource_delete(resourceHandle);
        vc_dispmanx_display_close(displayHandle);

        fprintf(stderr, "%s: vc_dispmanx_rect_set() failed\n", program);
        exit(EXIT_FAILURE);
    }

    result = vc_dispmanx_resource_read_data(resourceHandle,
                                            &rect,
                                            dmxImagePtr,
                                            dmxPitch);


    if (result != 0)
    {
        vc_dispmanx_resource_delete(resourceHandle);
        vc_dispmanx_display_close(displayHandle);

        fprintf(stderr,
                "%s: vc_dispmanx_resource_read_data() failed\n",
                program);

        exit(EXIT_FAILURE);
    }

    vc_dispmanx_resource_delete(resourceHandle);
    vc_dispmanx_display_close(displayHandle);

    //-------------------------------------------------------------------
    // Convert from RGBA (32 bit) to RGB (24 bit)

    int8_t pngBytesPerPixel = 3;
    int32_t pngPitch = pngBytesPerPixel * pngWidth;
    void *pngImagePtr = malloc(pngPitch * pngHeight);

    int32_t j = 0;
    for (j = 0 ; j < pngHeight ; j++)
    {
        int32_t dmxXoffset = 0;
        int32_t dmxYoffset = 0;

        switch (displayRotated & 3)
        {
        case 0: // 0 degrees

            if (displayRotated & 0x20000) // flip vertical
            {
                dmxYoffset = (dmxHeight - j - 1) * dmxPitch;
            }
            else
            {
                dmxYoffset = j * dmxPitch;
            }

            break;

        case 1: // 90 degrees


            if (displayRotated & 0x20000) // flip vertical
            {
                dmxXoffset = j * dmxBytesPerPixel;
            }
            else
            {
                dmxXoffset = (dmxWidth - j - 1) * dmxBytesPerPixel;
            }

            break;

        case 2: // 180 degrees

            if (displayRotated & 0x20000) // flip vertical
            {
                dmxYoffset = j * dmxPitch;
            }
            else
            {
                dmxYoffset = (dmxHeight - j - 1) * dmxPitch;
            }

            break;

        case 3: // 270 degrees

            if (displayRotated & 0x20000) // flip vertical
            {
                dmxXoffset = (dmxWidth - j - 1) * dmxBytesPerPixel;
            }
            else
            {
                dmxXoffset = j * dmxBytesPerPixel;
            }

            break;
        }

        int32_t i = 0;
        for (i = 0 ; i < pngWidth ; i++)
        {
            uint8_t *pngPixelPtr = pngImagePtr
                                 + (i * pngBytesPerPixel)
                                 + (j * pngPitch);

            switch (displayRotated & 3)
            {
            case 0: // 0 degrees

                if (displayRotated & 0x10000) // flip horizontal
                {
                    dmxXoffset = (dmxWidth - i - 1) * dmxBytesPerPixel;
                }
                else
                {
                    dmxXoffset = i * dmxBytesPerPixel;
                }

                break;

            case 1: // 90 degrees

                if (displayRotated & 0x10000) // flip horizontal
                {
                    dmxYoffset = (dmxHeight - i - 1) * dmxPitch;
                }
                else
                {
                    dmxYoffset = i * dmxPitch;
                }

                break;

            case 2: // 180 degrees

                if (displayRotated & 0x10000) // flip horizontal
                {
                    dmxXoffset = i * dmxBytesPerPixel;
                }
                else
                {
                    dmxXoffset = (dmxWidth - i - 1) * dmxBytesPerPixel;
                }

                break;

            case 3: // 270 degrees

                if (displayRotated & 0x10000) // flip horizontal
                {
                    dmxYoffset = i * dmxPitch;
                }
                else
                {
                    dmxYoffset = (dmxHeight - i - 1) * dmxPitch;
                }

                break;
            }

            uint8_t *dmxPixelPtr = dmxImagePtr + dmxXoffset + dmxYoffset;

            memcpy(pngPixelPtr, dmxPixelPtr, 3);
        }
    }

    free(dmxImagePtr);
    dmxImagePtr = NULL;

    //-------------------------------------------------------------------

    png_structp pngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
                                                 NULL,
                                                 NULL,
                                                 NULL);

    if (pngPtr == NULL)
    {
        fprintf(stderr,
                "%s: unable to allocated PNG write structure\n",
                program);

        exit(EXIT_FAILURE);
    }

    png_infop infoPtr = png_create_info_struct(pngPtr);

    if (infoPtr == NULL)
    {
        fprintf(stderr,
                "%s: unable to allocated PNG info structure\n",
                program);

        exit(EXIT_FAILURE);
    }

    if (setjmp(png_jmpbuf(pngPtr)))
    {
        fprintf(stderr, "%s: unable to create PNG\n", program);
        exit(EXIT_FAILURE);
    }

    FILE *pngfp = NULL;

    if (writeToStdout)
    {
        pngfp = stdout;
    }
    else
    {
        pngfp = fopen(pngName, "wb");

        if (pngfp == NULL)
        {
            fprintf(stderr,
                    "%s: unable to create %s - %s\n",
                    program,
                    pngName,
                    strerror(errno));

            exit(EXIT_FAILURE);
        }
    }

    png_init_io(pngPtr, pngfp);

    png_set_IHDR(
        pngPtr,
        infoPtr,
        pngWidth,
        pngHeight,
        8,
        PNG_COLOR_TYPE_RGB,
        PNG_INTERLACE_NONE,
        PNG_COMPRESSION_TYPE_BASE,
        PNG_FILTER_TYPE_BASE);

    if (compression != Z_DEFAULT_COMPRESSION)
    {
        png_set_compression_level(pngPtr, compression);
    }

    png_write_info(pngPtr, infoPtr);

    int y = 0;
    for (y = 0; y < pngHeight; y++)
    {
        png_write_row(pngPtr, pngImagePtr + (pngPitch * y));
    }

    png_write_end(pngPtr, NULL);
    png_destroy_write_struct(&pngPtr, &infoPtr);

    if (pngfp != stdout)
    {
        fclose(pngfp);
    }

    //-------------------------------------------------------------------

    free(pngImagePtr);
    pngImagePtr = NULL;

    return 0;
}
Esempio n. 17
0
static int DISPMANX_VideoInit(_THIS, SDL_PixelFormat *vformat)
{
	int i;
	int ret = 0;
#if !SDL_THREADS_DISABLED
	/* Create the hardware surface lock mutex */
	hw_lock = SDL_CreateMutex();
	if ( hw_lock == NULL ) {
		SDL_SetError("Unable to create lock mutex");
		DISPMANX_VideoQuit(this);
		return(-1);
	}
#endif
	//MAC Inicializamos el SOC
	bcm_host_init();
		
	//MAC Abrimos el display dispmanx
	uint32_t screen = 0;
	printf("dispmanx: Opening display[%i]...\n", screen );
        dispvars->display = vc_dispmanx_display_open( screen );
	
	//MAC Recuperamos algunos datos de la configuración del buffer actual
	vc_dispmanx_display_get_info( dispvars->display, &(dispvars->amode));
	assert(ret == 0);
	vformat->BitsPerPixel = 16; //Pon lo que quieras.Era para restaurar fb
	
	//MAC Para que las funciones GetVideoInfo() devuelvan un SDL_VideoInfo con contenidos.
	this->info.current_w = dispvars->amode.width;
        this->info.current_h = dispvars->amode.height;
        this->info.wm_available = 0;
        this->info.hw_available = 1;
	this->info.video_mem = 32768 /1024;
		
	printf( "Physical video mode is %d x %d\n", 
	   dispvars->amode.width, dispvars->amode.height );
	
	/* Limpiamos LAS listas de modos disponibles */
	for ( i=0; i<NUM_MODELISTS; ++i ) {
		SDL_nummodes[i] = 0;
		SDL_modelist[i] = NULL;
	}	
	
	// Añadimos nuestros modos de vídeo	
	
	//En DISPMANX sólo tenemos el modo de vídeo que se está usando 
	//actualmente, sea cual sea, y los demás modos se escalan a ese 
	//por hardware. SDL NO entiende de timings (incluyendo tasas de 
	//refresco), así que eso no se tiene que resolver aquí, supongo.

	for (i = 0; i < NUM_MODELISTS; i++){
              //Añado cada modo a la lista 0 (8bpp), lista 1 (16), lista 2(24)..
              //Por eso itero hasta NUM_MODELIST: cada MODELIST es para un bpp.
              DISPMANX_AddMode(this, i, dispvars->amode.width, 
	          dispvars->amode.height, 0);
              printf("Adding video mode: %d x %d - %d bpp\n", dispvars->amode.width,
                 dispvars->amode.height, (i+1)*8);
        }

	/* Enable mouse and keyboard support */
	if ( DISPMANX_OpenKeyboard(this) < 0 ) {
		DISPMANX_VideoQuit(this);
		return(-1);
	}
	if ( DISPMANX_OpenMouse(this) < 0 ) {
		const char *sdl_nomouse;
		//MAC Si esto da problemas, es por los premisos de gpm sobre
		//el ratón en /dev/mice. Edita /etc/init.d/gpm y añade
		//en la sección start() la línea chmod 0666{MOUSEDEV}
		sdl_nomouse = SDL_getenv("SDL_NOMOUSE");
		if ( ! sdl_nomouse ) {
			printf("\nERR - Couldn't open mouse. Look for permissions in /etc/init.d/gpm.\n");
			DISPMANX_VideoQuit(this);
			return(-1);
		}
	}

	/* We're done! */
	return(0);
}
Esempio n. 18
0
int main(int argc, char** argv) {
    cam = new PiCam(160, 120, &process_frame);
    std::cout << "Initialized camera" << std::endl;

    int ret;
    display = vc_dispmanx_display_open(0); // "window"
    std::cout << "Opened display" << std::endl;

    unsigned int vc_image_ptr;

    display_resource = vc_dispmanx_resource_create(VC_IMAGE_RGB888, 160 | (160*3) << 16, 120, &vc_image_ptr);
    std::cout << "Created resource" << std::endl;

    VC_DISPMANX_ALPHA_T alpha = { /*DISPMANX_FLAGS_ALPHA_FROM_SOURCE |*/ DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS,
                                                                         255, /*alpha 0->255*/
                                                                         0
                                };
    VC_RECT_T dst_rect;
    VC_RECT_T src_rect;

    DISPMANX_MODEINFO_T info;
    ret = vc_dispmanx_display_get_info(display, &info);
    assert(ret==0);
    std::cout << "Got display info" << std::endl;

    //vc_dispmanx_rect_set( &dst_rect, 0, 0, 160, 120);
    vc_dispmanx_rect_set( &src_rect, 0, 0, 160<<16, 120<<16);

    vc_dispmanx_rect_set( &dst_rect, ( info.width - 160 ) / 2,
                          ( info.height - 120 ) / 2,
                          160,
                          120 );

    DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start(10);
    assert(update != DISPMANX_NO_HANDLE);
    std::cout << "Started update" << std::endl;

    element = vc_dispmanx_element_add(  update,
                                        display,
                                        2000,               // layer
                                        &dst_rect,
                                        display_resource,
                                        &src_rect,
                                        DISPMANX_PROTECTION_NONE,
                                        &alpha,
                                        NULL,             // clamp
                                        //VC_IMAGE_ROT0 );
                                        DISPMANX_NO_ROTATE);
    std::cout << "Added element" << std::endl;
    ret = vc_dispmanx_update_submit_sync(update);
    assert(ret == 0);
    std::cout << "Finished update" << std::endl;



    //cv::namedWindow("RPi Cam Raw", cv::WINDOW_AUTOSIZE);
    //cv::namedWindow("RPi Cam Proc", cv::WINDOW_AUTOSIZE);

    //hist = cv::Mat(240, 320, CV_8UC3, 0);

    /*
    cv::createTrackbar("Hue", "RPi Cam", &hue, 255, &doNothing);
    cv::createTrackbar("Range", "RPi Cam", &range, 128, &doNothing);
    cv::createTrackbar("Min Sat", "RPi Cam", &s_min, 255, &doNothing);
    cv::createTrackbar("Max Sat", "RPi Cam", &s_max, 255, &doNothing);
    cv::createTrackbar("Min Value", "RPi Cam", &v_min, 255, &doNothing);
    cv::createTrackbar("Max Value", "RPi Cam", &v_max, 255, &doNothing);
    */
    //cv::createTrackbar("Histogram", "RPi Cam Raw", &_hist_, 1, &doHistogram);
    //cv::createTrackbar("Threshold", "RPi Cam Raw", &threshold, 1000, &doNothing);
    std::cout << "Setup dispmanx" << std::endl;

    cam->start();
    //vcos_sleep(100000);
    //std::cout << (n / 100.0) << " FPS\n";
    //cv::waitKey(0);
    return 0;
}
Esempio n. 19
0
static bool dispmanx_setup_scale(void *data, unsigned width,
      unsigned height, unsigned pitch)
{
	int i, dst_ypos;
	VC_DISPMANX_ALPHA_T layerAlpha;    
  	struct dispmanx_video *_dispvars = data;

   if (!_dispvars)
      return false;

	/* Since internal frame resolution seems to have changed, we change the 
    * internal frame resolution in use, and call dispmanx_setup_scale()
    * again to set the rects, etc. */
	_dispvars->width = width;
	_dispvars->height = height;

	/* Total pitch, including things the cores 
    * render between "visible" scanlines. */
	_dispvars->pitch = pitch;

	/* The "visible" width obtained from the core pitch. */
	_dispvars->visible_width = pitch / _dispvars->bytes_per_pixel;

	dispmanx_free_main_resources(_dispvars);
	vc_dispmanx_display_get_info(_dispvars->display, &(_dispvars->amode));

	// We choose the pixel format depending on the bpp of the frame.
	switch (_dispvars->bytes_per_pixel)
   {
      case 2:	
         _dispvars->pixFormat = VC_IMAGE_RGB565;	       
         break;
      case 4:	
         _dispvars->pixFormat = VC_IMAGE_XRGB8888;	       
         break;
      default:
         RARCH_ERR("video_dispmanx: wrong pixel format\n");
         return NULL;
   }	

	/* Transparency disabled */
	layerAlpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS;
	layerAlpha.opacity = 255;
	layerAlpha.mask = 0;
	_dispvars->alpha = &layerAlpha;	

  	switch (g_settings.video.aspect_ratio_idx)
   {
      case ASPECT_RATIO_4_3: 
         _dispvars->aspect = (float)4 / (float)3;
         break;
      case ASPECT_RATIO_16_9: 
         _dispvars->aspect = (float)16 / (float)9;
         break;
      case ASPECT_RATIO_16_10: 
         _dispvars->aspect = (float)16 / (float)10;
         break;
      case ASPECT_RATIO_16_15: 
         _dispvars->aspect = (float)16 / (float)15;
         break;
      case ASPECT_RATIO_CORE: 
         _dispvars->aspect = (float)_dispvars->width / (float)_dispvars->height;
         break;
      default: 
         _dispvars->aspect = (float)_dispvars->width / (float)_dispvars->height;
         break;
   }    

	int dst_width = _dispvars->amode.height * _dispvars->aspect;	
		
	/* If we obtain a scaled image width that is bigger than the physical screen width,
    * then we keep the physical screen width as our maximun width. */
#if 0
	if (dst_width > _dispvars->amode.width) 
	dst_width = _dispvars->amode.width;
#endif
	dst_ypos = (_dispvars->amode.width - dst_width) / 2; 

	vc_dispmanx_rect_set(&(_dispvars->dstRect), dst_ypos, 0, 
	   	dst_width, _dispvars->amode.height);
	
	/* We configure the rects now. */
	vc_dispmanx_rect_set(&(_dispvars->bmpRect), 0, 0, _dispvars->width, _dispvars->height);	
	vc_dispmanx_rect_set(&(_dispvars->srcRect), 0, 0, _dispvars->width << 16, _dispvars->height << 16);	

	/* We create as many resources as pages */
	for (i = 0; i < NUMPAGES; i++)
		_dispvars->resources[i] = vc_dispmanx_resource_create(_dispvars->pixFormat, 
			_dispvars->visible_width, _dispvars->height, &(_dispvars->vcImagePtr));

	/* Add element. */
	_dispvars->update = vc_dispmanx_update_start(0);
	
	_dispvars->element = vc_dispmanx_element_add(_dispvars->update, _dispvars->display, 0,
		&(_dispvars->dstRect), _dispvars->resources[0], &(_dispvars->srcRect), 
		DISPMANX_PROTECTION_NONE, _dispvars->alpha, 0, (DISPMANX_TRANSFORM_T)0);
	
	vc_dispmanx_update_submit_sync(_dispvars->update);		

	return true;
}
Esempio n. 20
0
static void *gfx_ctx_vc_init(void *video_driver)
{
   VC_DISPMANX_ALPHA_T alpha;
   EGLint n, major, minor;
   static EGL_DISPMANX_WINDOW_T nativewindow;

   DISPMANX_ELEMENT_HANDLE_T dispman_element;
   DISPMANX_DISPLAY_HANDLE_T dispman_display;
   DISPMANX_UPDATE_HANDLE_T dispman_update;
   DISPMANX_MODEINFO_T dispman_modeinfo;
   VC_RECT_T dst_rect;
   VC_RECT_T src_rect;

#ifdef HAVE_EGL
   static const EGLint attribute_list[] =
   {
      EGL_RED_SIZE, 8,
      EGL_GREEN_SIZE, 8,
      EGL_BLUE_SIZE, 8,
      EGL_ALPHA_SIZE, 8,
      EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
      EGL_NONE
   };

   static const EGLint context_attributes[] =
   {
      EGL_CONTEXT_CLIENT_VERSION, 2,
      EGL_NONE
   };
#endif
   settings_t *settings = config_get_ptr();
   vc_ctx_data_t *vc    = NULL;

   if (g_egl_inited)
   {
      RARCH_ERR("[VC/EGL]: Attempted to re-initialize driver.\n");
      return NULL;
   }

   vc = (vc_ctx_data_t*)calloc(1, sizeof(*vc));

   if (!vc)
       return NULL;

   bcm_host_init();

#ifdef HAVE_EGL
   if (!egl_init_context(&vc->egl, EGL_DEFAULT_DISPLAY,
            &major, &minor, &n, attribute_list))
   {
      egl_report_error();
      goto error;
   }

   if (!egl_create_context(&vc->egl, (vc_api == GFX_CTX_OPENGL_ES_API) ? context_attributes : NULL))
   {
      egl_report_error();
      goto error;
   }
#endif

   /* Create an EGL window surface. */
   if (graphics_get_display_size(0 /* LCD */, &vc->fb_width, &vc->fb_height) < 0)
      goto error;

   dst_rect.x = 0;
   dst_rect.y = 0;
   dst_rect.width = vc->fb_width;
   dst_rect.height = vc->fb_height;

   src_rect.x = 0;
   src_rect.y = 0;

   /* Use dispmanx upscaling if fullscreen_x 
    * and fullscreen_y are set. */
   if (settings->video.fullscreen_x != 0 &&
      settings->video.fullscreen_y != 0)
   {
      /* Keep input and output aspect ratio equal.
       * There are other aspect ratio settings which can be used to stretch video output. */

      /* Calculate source and destination aspect ratios. */
      float srcAspect = (float)settings->video.fullscreen_x / (float)settings->video.fullscreen_y;
      float dstAspect = (float)vc->fb_width / (float)vc->fb_height;
      /* If source and destination aspect ratios are not equal correct source width. */
      if (srcAspect != dstAspect)
         src_rect.width = (unsigned)(settings->video.fullscreen_y * dstAspect) << 16;
      else
         src_rect.width = settings->video.fullscreen_x << 16;
      src_rect.height = settings->video.fullscreen_y << 16;
   }
   else
   {
      src_rect.width  = vc->fb_width << 16;
      src_rect.height = vc->fb_height << 16;
   }

   dispman_display = vc_dispmanx_display_open(0 /* LCD */);
   vc_dispmanx_display_get_info(dispman_display, &dispman_modeinfo);
   dispman_update = vc_dispmanx_update_start(0);

   alpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS;
   alpha.opacity = 255;
   alpha.mask = 0;

   dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display,
      0 /*layer*/, &dst_rect, 0 /*src*/,
      &src_rect, DISPMANX_PROTECTION_NONE, &alpha, 0 /*clamp*/, DISPMANX_NO_ROTATE);

   nativewindow.element = dispman_element;

   /* Use dispmanx upscaling if fullscreen_x and fullscreen_y are set. */

   if (settings->video.fullscreen_x != 0 &&
      settings->video.fullscreen_y != 0)
   {
      /* Keep input and output aspect ratio equal.
       * There are other aspect ratio settings which 
       * can be used to stretch video output. */

      /* Calculate source and destination aspect ratios. */
      float srcAspect = (float)settings->video.fullscreen_x / (float)settings->video.fullscreen_y;
      float dstAspect = (float)vc->fb_width / (float)vc->fb_height;

      /* If source and destination aspect ratios are not equal correct source width. */
      if (srcAspect != dstAspect)
         nativewindow.width = (unsigned)(settings->video.fullscreen_y * dstAspect);
      else
         nativewindow.width = settings->video.fullscreen_x;
      nativewindow.height = settings->video.fullscreen_y;
   }
   else
   {
      nativewindow.width = vc->fb_width;
      nativewindow.height = vc->fb_height;
   }
   vc_dispmanx_update_submit_sync(dispman_update);

#ifdef HAVE_EGL
   if (!egl_create_surface(&vc->egl, &nativewindow))
      goto error;
#endif

   return vc;

error:
   gfx_ctx_vc_destroy(video_driver);
   return NULL;
}
static EGL_DISPMANX_WINDOW_T *check_default(EGLNativeWindowType win)
{
   int wid = (int)win;
   if(wid>-NUM_WIN && wid <=0) {
      /*
       * Special identifiers indicating the default windows. Either use the
       * one we've got or create a new one
       * simple hack for VMCSX_VC4_1.0 release to demonstrate concurrent running of apps under linux

       * win ==  0 => full screen window on display 0
       * win == -1 => 1/4 screen top left window on display 0
       * win == -2 => 1/4 screen top right window on display 0
       * win == -3 => 1/4 screen bottom left window on display 0
       * win == -4 => 1/4 screen bottom right window on display 0
       * win == -5 => full screen window on display 2

       * it is expected that Open WFC will provide a proper mechanism in the near future
       */
      wid = -wid;

      if (!have_default_dwin[wid]) {
         DISPMANX_DISPLAY_HANDLE_T display = vc_dispmanx_display_open( (wid == 5) ? 2 : 0 );
         DISPMANX_MODEINFO_T info;
         vc_dispmanx_display_get_info(display, &info);
         int32_t dw = info.width, dh = info.height;

         DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start( 0 );
         VC_DISPMANX_ALPHA_T alpha = {DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS, 255, 0};
         VC_RECT_T dst_rect;
         VC_RECT_T src_rect;

         int x, y, width, height, layer;

         switch(wid)
         {
         case 0:
            x = 0;    y = 0;    width = dw;   height = dh;   layer = 0; break;
         case 1:
            x = 0;    y = 0;    width = dw/2; height = dh/2; layer = 0; break;
         case 2:
            x = dw/2; y = 0;    width = dw/2; height = dh/2; layer = 0; break;
         case 3:
            x = 0;    y = dh/2; width = dw/2; height = dh/2; layer = 0; break;
         case 4:
            x = dw/2; y = dh/2; width = dw/2; height = dh/2; layer = 0; break;
         case 5:
            x = 0;    y = 0;    width = dw;   height = dh;   layer = 0; break;
         }

         src_rect.x = 0;
         src_rect.y = 0;
         src_rect.width = width << 16;
         src_rect.height = height << 16;

         dst_rect.x = x;
         dst_rect.y = y;
         dst_rect.width = width;
         dst_rect.height = height;

         default_dwin[wid].element = vc_dispmanx_element_add ( update, display,
            layer, &dst_rect, 0/*src*/,
            &src_rect, DISPMANX_PROTECTION_NONE, &alpha, 0/*clamp*/, 0/*transform*/);

         default_dwin[wid].width = width;
         default_dwin[wid].height = height;

         vc_dispmanx_update_submit_sync( update );

         have_default_dwin[wid] = true;
      }
      return &default_dwin[wid];
   } else
      return (EGL_DISPMANX_WINDOW_T*)win;
}
Esempio n. 22
0
static bool gfx_ctx_vc_init(void *data)
{
   EGLint num_config;
   static EGL_DISPMANX_WINDOW_T nativewindow;

   DISPMANX_ELEMENT_HANDLE_T dispman_element;
   DISPMANX_DISPLAY_HANDLE_T dispman_display;
   DISPMANX_UPDATE_HANDLE_T dispman_update;
   DISPMANX_MODEINFO_T dispman_modeinfo;
   VC_RECT_T dst_rect;
   VC_RECT_T src_rect;

   static const EGLint attribute_list[] =
   {
      EGL_RED_SIZE, 8,
      EGL_GREEN_SIZE, 8,
      EGL_BLUE_SIZE, 8,
      EGL_ALPHA_SIZE, 8,
      EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
      EGL_NONE
   };

   static const EGLint context_attributes[] =
   {
      EGL_CONTEXT_CLIENT_VERSION, 2,
      EGL_NONE
   };
   settings_t *settings = config_get_ptr();

   RARCH_LOG("[VC/EGL]: Initializing...\n");
   if (g_inited)
   {
      RARCH_ERR("[VC/EGL]: Attempted to re-initialize driver.\n");
      return false;
   }

   bcm_host_init();

   /* Get an EGL display connection. */
   g_egl_dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
   if (!g_egl_dpy)
      goto error;

   /* Initialize the EGL display connection. */
   if (!eglInitialize(g_egl_dpy, NULL, NULL))
      goto error;

   /* Get an appropriate EGL frame buffer configuration. */
   if (!eglChooseConfig(g_egl_dpy, attribute_list, &g_egl_config, 1, &num_config))
      goto error;

   /* Create an EGL rendering context. */
   g_egl_ctx = eglCreateContext(
         g_egl_dpy, g_egl_config, EGL_NO_CONTEXT,
         (g_api == GFX_CTX_OPENGL_ES_API) ? context_attributes : NULL);
   if (!g_egl_ctx)
      goto error;

   if (g_use_hw_ctx)
   {
      g_egl_hw_ctx = eglCreateContext(g_egl_dpy, g_egl_config, g_egl_ctx,
            context_attributes);
      RARCH_LOG("[VC/EGL]: Created shared context: %p.\n", (void*)g_egl_hw_ctx);

      if (g_egl_hw_ctx == EGL_NO_CONTEXT)
         goto error;
   }

   /* Create an EGL window surface. */
   if (graphics_get_display_size(0 /* LCD */, &g_fb_width, &g_fb_height) < 0)
      goto error;

   dst_rect.x = 0;
   dst_rect.y = 0;
   dst_rect.width = g_fb_width;
   dst_rect.height = g_fb_height;

   src_rect.x = 0;
   src_rect.y = 0;

   /* Use dispmanx upscaling if fullscreen_x 
    * and fullscreen_y are set. */
   if (settings->video.fullscreen_x != 0 &&
      settings->video.fullscreen_y != 0)
   {
      /* Keep input and output aspect ratio equal.
       * There are other aspect ratio settings which can be used to stretch video output. */

      /* Calculate source and destination aspect ratios. */
      float srcAspect = (float)settings->video.fullscreen_x / (float)settings->video.fullscreen_y;
      float dstAspect = (float)g_fb_width / (float)g_fb_height;
      /* If source and destination aspect ratios are not equal correct source width. */
      if (srcAspect != dstAspect)
         src_rect.width = (unsigned)(settings->video.fullscreen_y * dstAspect) << 16;
      else
         src_rect.width = settings->video.fullscreen_x << 16;
      src_rect.height = settings->video.fullscreen_y << 16;
   }
   else
   {
      src_rect.width = g_fb_width << 16;
      src_rect.height = g_fb_height << 16;
   }

   dispman_display = vc_dispmanx_display_open(0 /* LCD */);
   vc_dispmanx_display_get_info(dispman_display, &dispman_modeinfo);
   dispman_update = vc_dispmanx_update_start(0);

   VC_DISPMANX_ALPHA_T alpha;
   alpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS;
   alpha.opacity = 255;
   alpha.mask = 0;

   dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display,
      0 /*layer*/, &dst_rect, 0 /*src*/,
      &src_rect, DISPMANX_PROTECTION_NONE, &alpha, 0 /*clamp*/, DISPMANX_NO_ROTATE);

   nativewindow.element = dispman_element;

   /* Use dispmanx upscaling if fullscreen_x and fullscreen_y are set. */

   if (settings->video.fullscreen_x != 0 &&
      settings->video.fullscreen_y != 0)
   {
      /* Keep input and output aspect ratio equal.
       * There are other aspect ratio settings which 
       * can be used to stretch video output. */

      /* Calculate source and destination aspect ratios. */
      float srcAspect = (float)settings->video.fullscreen_x / (float)settings->video.fullscreen_y;
      float dstAspect = (float)g_fb_width / (float)g_fb_height;

      /* If source and destination aspect ratios are not equal correct source width. */
      if (srcAspect != dstAspect)
         nativewindow.width = (unsigned)(settings->video.fullscreen_y * dstAspect);
      else
         nativewindow.width = settings->video.fullscreen_x;
      nativewindow.height = settings->video.fullscreen_y;
   }
   else
   {
      nativewindow.width = g_fb_width;
      nativewindow.height = g_fb_height;
   }
   vc_dispmanx_update_submit_sync(dispman_update);

   g_egl_surf = eglCreateWindowSurface(g_egl_dpy, g_egl_config, &nativewindow, NULL);
   if (!g_egl_surf)
      goto error;

   /* Connect the context to the surface. */
   if (!eglMakeCurrent(g_egl_dpy, g_egl_surf, g_egl_surf, g_egl_ctx))
      goto error;

   return true;

error:
   gfx_ctx_vc_destroy(data);
   return false;
}
Esempio n. 23
0
static void *display_thread (void *unused)
{
	VC_DISPMANX_ALPHA_T alpha = {
		(DISPMANX_FLAGS_ALPHA_T)(DISPMANX_FLAGS_ALPHA_FROM_SOURCE | DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS), 
		255 /*alpha 0->255*/ , 	0
	};
	uint32_t vc_image_ptr;
	SDL_Surface *Dummy_prSDLScreen;
	int width, height;
	bool callback_registered = false;
	
  for(;;) {
    display_thread_busy = false;
    uae_u32 signal = read_comm_pipe_u32_blocking(display_pipe);
    display_thread_busy = true;
    switch(signal) {
      case DISPLAY_SIGNAL_SETUP:
        if(!callback_registered) {
  				bcm_host_init();
  				dispmanxdisplay = vc_dispmanx_display_open(0);
  			  vc_dispmanx_vsync_callback(dispmanxdisplay, vsync_callback, NULL);
  			  callback_registered = true;
  			}
			  break;

			case DISPLAY_SIGNAL_SUBSHUTDOWN:
				if (DispManXElementpresent == 1) {
					DispManXElementpresent = 0;
					dispmanxupdate = vc_dispmanx_update_start(0);
					vc_dispmanx_element_remove(dispmanxupdate, dispmanxelement);
					vc_dispmanx_update_submit_sync(dispmanxupdate);
				}
			
				if (dispmanxresource_amigafb_1 != 0) {
					vc_dispmanx_resource_delete(dispmanxresource_amigafb_1);
					dispmanxresource_amigafb_1 = 0;
			  }
				if (dispmanxresource_amigafb_2 != 0) {
					vc_dispmanx_resource_delete(dispmanxresource_amigafb_2);
					dispmanxresource_amigafb_2 = 0;
			  }
			  
			  if(prSDLScreen != NULL) {
			    SDL_FreeSurface(prSDLScreen);
			    prSDLScreen = NULL;
			  }
        uae_sem_post (&display_sem);
        break;
				
			case DISPLAY_SIGNAL_OPEN:
				width = display_width;
				height = display_height;
				
				Dummy_prSDLScreen = SDL_SetVideoMode(width, height, 16, SDL_SWSURFACE | SDL_FULLSCREEN);
				prSDLScreen = SDL_CreateRGBSurface(SDL_HWSURFACE, width, height, 16,
					Dummy_prSDLScreen->format->Rmask,	Dummy_prSDLScreen->format->Gmask, Dummy_prSDLScreen->format->Bmask, Dummy_prSDLScreen->format->Amask);
				SDL_FreeSurface(Dummy_prSDLScreen);
			
				vc_dispmanx_display_get_info(dispmanxdisplay, &dispmanxdinfo);
			
				dispmanxresource_amigafb_1 = vc_dispmanx_resource_create(VC_IMAGE_RGB565, width, height, &vc_image_ptr);
				dispmanxresource_amigafb_2 = vc_dispmanx_resource_create(VC_IMAGE_RGB565, width, height, &vc_image_ptr);
			
				vc_dispmanx_rect_set(&blit_rect, 0, 0, width, height);
				vc_dispmanx_resource_write_data(dispmanxresource_amigafb_1, VC_IMAGE_RGB565, prSDLScreen->pitch, prSDLScreen->pixels, &blit_rect);
				vc_dispmanx_rect_set(&src_rect, 0, 0, width << 16, height << 16);
			
				// 16/9 to 4/3 ratio adaptation.
				if (currprefs.gfx_correct_aspect == 0 || screen_is_picasso) {
				  // Fullscreen.
					int scaled_width = dispmanxdinfo.width * currprefs.gfx_fullscreen_ratio / 100;
					int scaled_height = dispmanxdinfo.height * currprefs.gfx_fullscreen_ratio / 100;
					vc_dispmanx_rect_set( &dst_rect, (dispmanxdinfo.width - scaled_width)/2, (dispmanxdinfo.height - scaled_height)/2,
						scaled_width,	scaled_height);
				}	else {
				  // 4/3 shrink.
					int scaled_width = dispmanxdinfo.width * currprefs.gfx_fullscreen_ratio / 100;
					int scaled_height = dispmanxdinfo.height * currprefs.gfx_fullscreen_ratio / 100;
					vc_dispmanx_rect_set( &dst_rect, (dispmanxdinfo.width - scaled_width / 16 * 12)/2, (dispmanxdinfo.height - scaled_height)/2,
						scaled_width/16*12,	scaled_height);
				}
			
				if (DispManXElementpresent == 0) {
					DispManXElementpresent = 1;
					dispmanxupdate = vc_dispmanx_update_start(0);
					dispmanxelement = vc_dispmanx_element_add(dispmanxupdate, dispmanxdisplay,	2,               // layer
						&dst_rect, dispmanxresource_amigafb_1, &src_rect,	DISPMANX_PROTECTION_NONE,	&alpha,	NULL, DISPMANX_NO_ROTATE);
			
					vc_dispmanx_update_submit(dispmanxupdate, NULL, NULL);
				}
        uae_sem_post (&display_sem);
        break;

			case DISPLAY_SIGNAL_SHOW:
				if (current_resource_amigafb == 1) {
					current_resource_amigafb = 0;
				  vc_dispmanx_resource_write_data(dispmanxresource_amigafb_1, VC_IMAGE_RGB565,
					  adisplays.gfxvidinfo.drawbuffer.rowbytes, adisplays.gfxvidinfo.drawbuffer.bufmem, &blit_rect);
				  dispmanxupdate = vc_dispmanx_update_start(0);
				  vc_dispmanx_element_change_source(dispmanxupdate, dispmanxelement, dispmanxresource_amigafb_1);
				} else {
					current_resource_amigafb = 1;
					vc_dispmanx_resource_write_data(dispmanxresource_amigafb_2,	VC_IMAGE_RGB565,
						adisplays.gfxvidinfo.drawbuffer.rowbytes,	adisplays.gfxvidinfo.drawbuffer.bufmem,	&blit_rect);
					dispmanxupdate = vc_dispmanx_update_start(0);
					vc_dispmanx_element_change_source(dispmanxupdate, dispmanxelement, dispmanxresource_amigafb_2);
				}
			  vc_dispmanx_update_submit(dispmanxupdate, NULL, NULL);
				break;
								
      case DISPLAY_SIGNAL_QUIT:
        callback_registered = false;
			  vc_dispmanx_vsync_callback(dispmanxdisplay, NULL, NULL);
				vc_dispmanx_display_close(dispmanxdisplay);
				bcm_host_deinit();
				SDL_VideoQuit();
        display_tid = 0;
        return 0;
    }
  }
}
Esempio n. 24
0
int process() {
    DISPMANX_DISPLAY_HANDLE_T display;
    DISPMANX_MODEINFO_T display_info;
    DISPMANX_RESOURCE_HANDLE_T screen_resource;
    VC_IMAGE_TRANSFORM_T transform;
    uint32_t image_prt;
    VC_RECT_T rect1;
    int ret;
    int fbfd = 0;
    char *fbp = 0;

    struct fb_var_screeninfo vinfo;
    struct fb_fix_screeninfo finfo;


    bcm_host_init();

    display = vc_dispmanx_display_open(0);
    if (!display) {
        syslog(LOG_ERR, "Unable to open primary display");
        return -1;
    }
    ret = vc_dispmanx_display_get_info(display, &display_info);
    if (ret) {
        syslog(LOG_ERR, "Unable to get primary display information");
        return -1;
    }
    syslog(LOG_INFO, "Primary display is %d x %d", display_info.width, display_info.height);


    fbfd = open("/dev/fb1", O_RDWR);
    if (!fbfd) {
        syslog(LOG_ERR, "Unable to open secondary display");
        return -1;
    }
    if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) {
        syslog(LOG_ERR, "Unable to get secondary display information");
        return -1;
    }
    if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
        syslog(LOG_ERR, "Unable to get secondary display information");
        return -1;
    }

    syslog(LOG_INFO, "Second display is %d x %d %dbps\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);

    screen_resource = vc_dispmanx_resource_create(VC_IMAGE_RGB565, vinfo.xres, vinfo.yres, &image_prt);
    if (!screen_resource) {
        syslog(LOG_ERR, "Unable to create screen buffer");
        close(fbfd);
        vc_dispmanx_display_close(display);
        return -1;
    }

    fbp = (char*) mmap(0, finfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
    if (fbp <= 0) {
        syslog(LOG_ERR, "Unable to create mamory mapping");
        close(fbfd);
        ret = vc_dispmanx_resource_delete(screen_resource);
        vc_dispmanx_display_close(display);
        return -1;
    }

    vc_dispmanx_rect_set(&rect1, 0, 0, vinfo.xres, vinfo.yres);

    while (1) {
        ret = vc_dispmanx_snapshot(display, screen_resource, 0);
        vc_dispmanx_resource_read_data(screen_resource, &rect1, fbp, vinfo.xres * vinfo.bits_per_pixel / 8);
        usleep(25 * 1000);
    }

    munmap(fbp, finfo.smem_len);
    close(fbfd);
    ret = vc_dispmanx_resource_delete(screen_resource);
    vc_dispmanx_display_close(display);
}
Esempio n. 25
0
int main(int argc, char *argv[])
{
    uint16_t background = 0x000F;
    int32_t layer = 1;
    uint32_t displayNumber = 0;
    int32_t xOffset = 0;
    int32_t yOffset = 0;
    uint32_t timeout = 0;
    bool xOffsetSet = false;
    bool yOffsetSet = false;
    bool interactive = true;

    program = basename(argv[0]);

    //---------------------------------------------------------------------

    int opt = 0;

    while ((opt = getopt(argc, argv, "b:d:l:x:y:t:n")) != -1)
    {
        switch(opt)
        {
        case 'b':

            background = strtol(optarg, NULL, 16);
            break;

        case 'd':

            displayNumber = strtol(optarg, NULL, 10);
            break;

        case 'l':

            layer = strtol(optarg, NULL, 10);
            break;

        case 'x':

            xOffset = strtol(optarg, NULL, 10);
            xOffsetSet = true;
            break;

        case 'y':

            yOffset = strtol(optarg, NULL, 10);
            yOffsetSet = true;
            break;
        
        case 't':

            timeout = atoi(optarg);
            break;

        case 'n':

            interactive = false;
            break;

        default:

            usage();
            break;
        }
    }

    //---------------------------------------------------------------------

    if (optind >= argc)
    {
        usage();
    }

    //---------------------------------------------------------------------

    IMAGE_LAYER_T imageLayer;

    const char *imagePath = argv[optind];

    if(strcmp(imagePath, "-") == 0)
    {
        // Use stdin
        if (loadPngFile(&(imageLayer.image), stdin) == false)
        {
            fprintf(stderr, "unable to load %s\n", imagePath);
            exit(EXIT_FAILURE);
        }
    }
    else
    {
        // Load image from path
        if (loadPng(&(imageLayer.image), imagePath) == false)
        {
            fprintf(stderr, "unable to load %s\n", imagePath);
            exit(EXIT_FAILURE);
        }
    }

    //---------------------------------------------------------------------

    if (signal(SIGINT, signalHandler) == SIG_ERR)
    {
        perror("installing SIGINT signal handler");
        exit(EXIT_FAILURE);
    }

    //---------------------------------------------------------------------

    if (signal(SIGTERM, signalHandler) == SIG_ERR)
    {
        perror("installing SIGTERM signal handler");
        exit(EXIT_FAILURE);
    }

    //---------------------------------------------------------------------

    bcm_host_init();

    //---------------------------------------------------------------------

    DISPMANX_DISPLAY_HANDLE_T display
        = vc_dispmanx_display_open(displayNumber);
    assert(display != 0);

    //---------------------------------------------------------------------

    DISPMANX_MODEINFO_T info;
    int result = vc_dispmanx_display_get_info(display, &info);
    assert(result == 0);

    //---------------------------------------------------------------------

    BACKGROUND_LAYER_T backgroundLayer;

    if (background > 0)
    {
        initBackgroundLayer(&backgroundLayer, background, 0);
    }

    createResourceImageLayer(&imageLayer, layer);

    //---------------------------------------------------------------------

    DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start(0);
    assert(update != 0);

    if (background > 0)
    {
        addElementBackgroundLayer(&backgroundLayer, display, update);
    }

    if (xOffsetSet == false)
    {
        xOffset = (info.width - imageLayer.image.width) / 2;
    }

    if (yOffsetSet == false)
    {
        yOffset = (info.height - imageLayer.image.height) / 2;
    }

    addElementImageLayerOffset(&imageLayer,
                               xOffset,
                               yOffset,
                               display,
                               update);

    result = vc_dispmanx_update_submit_sync(update);
    assert(result == 0);

    //---------------------------------------------------------------------

    int32_t step = 1;
    uint32_t currentTime = 0;

    // Sleep for 10 milliseconds every run-loop
    const int sleepMilliseconds = 10;

    while (run)
    {
        int c = 0;
        if (interactive && keyPressed(&c))
        {
            c = tolower(c);

            bool moveLayer = false;

            switch (c)
            {
            case 27:

                run = false;
                break;

            case 'a':

                xOffset -= step;
                moveLayer = true;
                break;

            case 'd':

                xOffset += step;
                moveLayer = true;
                break;

            case 'w':

                yOffset -= step;
                moveLayer = true;
                break;

            case 's':

                yOffset += step;
                moveLayer = true;
                break;

            case '+':

                if (step == 1)
                {
                    step = 5;
                }
                else if (step == 5)
                {
                    step = 10;
                }
                else if (step == 10)
                {
                    step = 20;
                }
                break;

            case '-':

                if (step == 20)
                {
                    step = 10;
                }
                else if (step == 10)
                {
                    step = 5;
                }
                else if (step == 5)
                {
                    step = 1;
                }
                break;
            }

            if (moveLayer)
            {
                update = vc_dispmanx_update_start(0);
                assert(update != 0);

                moveImageLayer(&imageLayer, xOffset, yOffset, update);

                result = vc_dispmanx_update_submit_sync(update);
                assert(result == 0);
            }
        }

        //---------------------------------------------------------------------

        usleep(sleepMilliseconds * 1000);

        currentTime += sleepMilliseconds;
        if (timeout != 0 && currentTime >= timeout) {
            run = false;
        }
    }

    //---------------------------------------------------------------------

    keyboardReset();

    //---------------------------------------------------------------------

    if (background > 0)
    {
        destroyBackgroundLayer(&backgroundLayer);
    }

    destroyImageLayer(&imageLayer);

    //---------------------------------------------------------------------

    result = vc_dispmanx_display_close(display);
    assert(result == 0);

    //---------------------------------------------------------------------

    return 0;
}
int
main(
    int argc,
    char *argv[])
{
    const char *program = basename(argv[0]);

    int fps = DEFAULT_FPS;
    suseconds_t frameDuration =  1000000 / fps;
    bool isDaemon =  false;
    uint32_t sourceDisplayNumber = DEFAULT_SOURCE_DISPLAY_NUMBER;
    uint32_t destDisplayNumber = DEFAULT_DESTINATION_DISPLAY_NUMBER;
	int32_t layerNumber = DEFAULT_LAYER_NUMBER;
    const char *pidfile = NULL;

    //---------------------------------------------------------------------

    static const char *sopts = "d:f:hl:p:s:D";
    static struct option lopts[] = 
    {
        { "destination", required_argument, NULL, 'd' },
        { "fps", required_argument, NULL, 'f' },
        { "help", no_argument, NULL, 'h' },
        { "layer", required_argument, NULL, 'l' },
        { "pidfile", required_argument, NULL, 'p' },
        { "source", required_argument, NULL, 's' },
        { "daemon", no_argument, NULL, 'D' },
        { NULL, no_argument, NULL, 0 }
    };

    int opt = 0;

    while ((opt = getopt_long(argc, argv, sopts, lopts, NULL)) != -1)
    {
        switch (opt)
        {
        case 'd':

            destDisplayNumber = atoi(optarg);
            break;

        case 'f':

            fps = atoi(optarg);

            if (fps > 0)
            {
                frameDuration = 1000000 / fps;
            }
            else
            {
                fps = 1000000 / frameDuration;
            }

            break;

        case 'h':

            printUsage(stdout, program);
            exit(EXIT_SUCCESS);

            break;

        case 'l':

            layerNumber = atoi(optarg);
            break;

        case 'p':

            pidfile = optarg;

            break;

        case 's':

            sourceDisplayNumber = atoi(optarg);
            break;

        case 'D':

            isDaemon = true;
            break;

        default:

            printUsage(stderr, program);
            exit(EXIT_FAILURE);

            break;
        }
    }

    //---------------------------------------------------------------------

    struct pidfh *pfh = NULL;

    if (isDaemon)
    {
        if (pidfile != NULL)
        {
            pid_t otherpid;
            pfh = pidfile_open(pidfile, 0600, &otherpid);

            if (pfh == NULL)
            {
                fprintf(stderr,
                        "%s is already running %jd\n",
                        program,
                        (intmax_t)otherpid);
                exit(EXIT_FAILURE);
            }
        }
        
        if (daemon(0, 0) == -1)
        {
            fprintf(stderr, "daemonize failed\n");

            exitAndRemovePidFile(EXIT_FAILURE, pfh);
        }

        if (pfh)
        {
            pidfile_write(pfh);
        }

        openlog(program, LOG_PID, LOG_USER);
    }

    //---------------------------------------------------------------------

    if (signal(SIGINT, signalHandler) == SIG_ERR)
    {
        perrorLog(isDaemon, program, "installing SIGINT signal handler");

        exitAndRemovePidFile(EXIT_FAILURE, pfh);
    }

    //---------------------------------------------------------------------

    if (signal(SIGTERM, signalHandler) == SIG_ERR)
    {
        perrorLog(isDaemon, program, "installing SIGTERM signal handler");

        exitAndRemovePidFile(EXIT_FAILURE, pfh);
    }

    //---------------------------------------------------------------------

    bcm_host_init();

    //---------------------------------------------------------------------

    int result = 0;

    //---------------------------------------------------------------------
    // Make sure the VC_DISPLAY variable isn't set. 

    unsetenv("VC_DISPLAY");

    //---------------------------------------------------------------------

    DISPMANX_DISPLAY_HANDLE_T sourceDisplay
        = vc_dispmanx_display_open(sourceDisplayNumber);

    if (sourceDisplay == 0)
    {
        messageLog(isDaemon,
                   program,
                   LOG_ERR,
                   "open source display failed");
        exitAndRemovePidFile(EXIT_FAILURE, pfh);
    }

    DISPMANX_MODEINFO_T sourceInfo;

    result = vc_dispmanx_display_get_info(sourceDisplay, &sourceInfo);

    if (result != 0)
    {
        messageLog(isDaemon,
                   program,
                   LOG_ERR,
                   "getting source display dimensions failed");

        exitAndRemovePidFile(EXIT_FAILURE, pfh);
    }

    //---------------------------------------------------------------------

    DISPMANX_DISPLAY_HANDLE_T destDisplay
        = vc_dispmanx_display_open(destDisplayNumber);

    if (destDisplay == 0)
    {
        messageLog(isDaemon,
                   program,
                   LOG_ERR,
                   "open destination display failed");
        exitAndRemovePidFile(EXIT_FAILURE, pfh);
    }

    DISPMANX_MODEINFO_T destInfo;

    result = vc_dispmanx_display_get_info(destDisplay, &destInfo);

    if (result != 0)
    {
        messageLog(isDaemon,
                   program,
                   LOG_ERR,
                   "getting destination display dimensions failed");
        exitAndRemovePidFile(EXIT_FAILURE, pfh);
    }

    //---------------------------------------------------------------------

    messageLog(isDaemon,
               program,
               LOG_INFO,
               "copying from [%d] %dx%d to [%d] %dx%d",
               sourceDisplayNumber,
               sourceInfo.width,
               sourceInfo.height,
               destDisplayNumber,
               destInfo.width,
               destInfo.height);

    //---------------------------------------------------------------------

    uint32_t image_ptr;

    DISPMANX_RESOURCE_HANDLE_T resource = 
        vc_dispmanx_resource_create(VC_IMAGE_RGBA32,
                                    destInfo.width,
                                    destInfo.height,
                                    &image_ptr);

    //---------------------------------------------------------------------

    VC_RECT_T sourceRect;
    vc_dispmanx_rect_set(&sourceRect,
                         0,
                         0,
                         destInfo.width << 16,
                         destInfo.height << 16);
    
    VC_RECT_T destRect;
    vc_dispmanx_rect_set(&destRect, 0, 0, 0, 0);

    //---------------------------------------------------------------------

    VC_DISPMANX_ALPHA_T alpha =
    {
        DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS,
        255,
        0
    };

    DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start(0);

    if (update == 0)
    {
        messageLog(isDaemon,
                   program,
                   LOG_ERR,
                   "display update failed");
        exitAndRemovePidFile(EXIT_FAILURE, pfh);
    }

    DISPMANX_ELEMENT_HANDLE_T element;
    element = vc_dispmanx_element_add(update,
                                      destDisplay,
                                      layerNumber,
                                      &destRect,
                                      resource,
                                      &sourceRect,
                                      DISPMANX_PROTECTION_NONE,
                                      &alpha,
                                      NULL,
                                      DISPMANX_NO_ROTATE);
    if (element == 0)
    {
        messageLog(isDaemon,
                   program,
                   LOG_ERR,
                   "failed to create DispmanX element");
        exitAndRemovePidFile(EXIT_FAILURE, pfh);
    }

    vc_dispmanx_update_submit_sync(update);

    //---------------------------------------------------------------------

    struct timeval start_time;
    struct timeval end_time;
    struct timeval elapsed_time;

    //---------------------------------------------------------------------

    while (run)
    {
        gettimeofday(&start_time, NULL);

        //-----------------------------------------------------------------

        result = vc_dispmanx_snapshot(sourceDisplay,
                                      resource,
                                      DISPMANX_NO_ROTATE);

        if (result != 0)
        {
            messageLog(isDaemon,
                       program,
                       LOG_ERR,
                       "DispmanX snapshot failed");
            exitAndRemovePidFile(EXIT_FAILURE, pfh);
        }

        //-----------------------------------------------------------------

        update = vc_dispmanx_update_start(0);

        if (update == 0)
        {
            messageLog(isDaemon,
                       program,
                       LOG_ERR,
                       "display update failed");
            exitAndRemovePidFile(EXIT_FAILURE, pfh);
        }

        vc_dispmanx_element_change_source(update, element, resource);
        vc_dispmanx_update_submit_sync(update);

        //-----------------------------------------------------------------

        gettimeofday(&end_time, NULL);
        timersub(&end_time, &start_time, &elapsed_time);

        if (elapsed_time.tv_sec == 0)
        {
            if (elapsed_time.tv_usec < frameDuration)
            {
                usleep(frameDuration -  elapsed_time.tv_usec);
            }
        }
    }

    //---------------------------------------------------------------------

    update = vc_dispmanx_update_start(0);
    vc_dispmanx_element_remove(update, element);
    vc_dispmanx_update_submit_sync(update);

    vc_dispmanx_resource_delete(resource);

    vc_dispmanx_display_close(sourceDisplay);
    vc_dispmanx_display_close(destDisplay);

    //---------------------------------------------------------------------

    messageLog(isDaemon, program, LOG_INFO, "exiting");

    if (isDaemon)
    {
        closelog();
    }

    if (pfh)
    {
        pidfile_remove(pfh);
    }

    //---------------------------------------------------------------------

    return 0 ;
}