void gp2x_frontend_init(void) { int ret; uint32_t display_width, display_height; VC_RECT_T dst_rect; VC_RECT_T src_rect; surface_width = 640; surface_height = 480; gp2x_screen8=0; gp2x_screen15=(unsigned short *) calloc(1, 640*480*2); graphics_get_display_size(0 /* LCD */, &display_width, &display_height); dispman_display = vc_dispmanx_display_open( 0 ); assert( dispman_display != 0 ); // Add border around bitmap for TV display_width -= options.display_border * 2; display_height -= options.display_border * 2; //Create two surfaces for flipping between //Make sure bitmap type matches the source for better performance uint32_t crap; resource0 = vc_dispmanx_resource_create(VC_IMAGE_RGB565, 640, 480, &crap); resource1 = vc_dispmanx_resource_create(VC_IMAGE_RGB565, 640, 480, &crap); vc_dispmanx_rect_set( &dst_rect, options.display_border, options.display_border, display_width, display_height); vc_dispmanx_rect_set( &src_rect, 0, 0, 640 << 16, 480 << 16); //Make sure mame and background overlay the menu program dispman_update = vc_dispmanx_update_start( 0 ); // create the 'window' element - based on the first buffer resource (resource0) dispman_element = vc_dispmanx_element_add( dispman_update, dispman_display, 1, &dst_rect, resource0, &src_rect, DISPMANX_PROTECTION_NONE, 0, 0, (DISPMANX_TRANSFORM_T) 0 ); ret = vc_dispmanx_update_submit_sync( dispman_update ); // setup swapping of double buffers cur_res = resource1; prev_res = resource0; }
ViewBackend::Cursor::Cursor(WPE::LibinputServer::Client& targetClient, DISPMANX_DISPLAY_HANDLE_T displayHandle, uint32_t displayWidth, uint32_t displayHeight) : targetClient(targetClient) , position({ 0, 0 }) , displaySize({ displayWidth, displayHeight }) { static VC_DISPMANX_ALPHA_T alpha = { static_cast<DISPMANX_FLAGS_ALPHA_T>(DISPMANX_FLAGS_ALPHA_FROM_SOURCE), 255, 0 }; DISPMANX_UPDATE_HANDLE_T updateHandle = vc_dispmanx_update_start(0); uint32_t imagePtr; VC_RECT_T rect; vc_dispmanx_rect_set(&rect, 0, 0, CursorData::width, CursorData::height); DISPMANX_RESOURCE_HANDLE_T pointerResource = vc_dispmanx_resource_create(VC_IMAGE_RGBA32, CursorData::width, CursorData::height, &imagePtr); vc_dispmanx_resource_write_data(pointerResource, VC_IMAGE_RGBA32, CursorData::width * 4, CursorData::data, &rect); VC_RECT_T srcRect, destRect; vc_dispmanx_rect_set(&srcRect, 0, 0, CursorData::width << 16, CursorData::height << 16); vc_dispmanx_rect_set(&destRect, position.first, position.second, cursorWidth, cursorHeight); cursorHandle = vc_dispmanx_element_add(updateHandle, displayHandle, 10, &destRect, pointerResource, &srcRect, DISPMANX_PROTECTION_NONE, &alpha, nullptr, DISPMANX_NO_ROTATE); vc_dispmanx_resource_delete(pointerResource); vc_dispmanx_update_submit_sync(updateHandle); }
static void DISPMANX_BlankBackground(void) { //MAC: Funcion que simplemente pone un element nuevo cuyo resource es de un solo pixel de color negro, //se escala a pantalla completa y listo. // we create a 1x1 black pixel image that is added to display just behind video VC_IMAGE_TYPE_T type = VC_IMAGE_RGB565; uint32_t vc_image_ptr; uint16_t image = 0x0000; // black VC_RECT_T dst_rect, src_rect; dispvars->b_resource = vc_dispmanx_resource_create( type, 1 /*width*/, 1 /*height*/, &vc_image_ptr ); vc_dispmanx_rect_set( &dst_rect, 0, 0, 1, 1); vc_dispmanx_resource_write_data( dispvars->b_resource, type, sizeof(image), &image, &dst_rect ); vc_dispmanx_rect_set( &src_rect, 0, 0, 1<<16, 1<<16); vc_dispmanx_rect_set( &dst_rect, 0, 0, 0, 0); dispvars->b_update = vc_dispmanx_update_start(0); dispvars->b_element = vc_dispmanx_element_add(dispvars->b_update, dispvars->display, -1 /*layer*/, &dst_rect, dispvars->b_resource, &src_rect, DISPMANX_PROTECTION_NONE, NULL, NULL, (DISPMANX_TRANSFORM_T)0 ); vc_dispmanx_update_submit_sync( dispvars->b_update ); }
static void frontend_init(void) { uint32_t display_width=0, display_height=0; VC_RECT_T dst_rect; VC_RECT_T src_rect; bcm_host_init(); //initialise dispmanx display and resources fe_screen=(unsigned short *) calloc(1, 640*480*2); graphics_get_display_size(0 /* LCD */, &display_width, &display_height); fe_display = vc_dispmanx_display_open( 0 ); //Create two surfaces for flipping between //Make sure bitmap type matches the source for better performance uint32_t crap; fe_resource = vc_dispmanx_resource_create(VC_IMAGE_RGB565, 640, 480, &crap); vc_dispmanx_rect_set( &dst_rect, 0, 0, display_width, display_height); vc_dispmanx_rect_set( &src_rect, 0, 0, 640 << 16, 480 << 16); //Make sure mame and background overlay the menu program fe_update = vc_dispmanx_update_start( 0 ); // create the 'window' element - based on the first buffer resource (resource0) fe_element = vc_dispmanx_element_add( fe_update, fe_display, 1, &dst_rect, fe_resource, &src_rect, DISPMANX_PROTECTION_NONE, 0, 0, (DISPMANX_TRANSFORM_T) 0 ); vc_dispmanx_update_submit_sync( fe_update ); }
static void dispmanx_surface_setup(void *data, int width, int height, int pitch, float aspect, struct dispmanx_surface *surface) { struct dispmanx_video *_dispvars = data; int i, dst_width, dst_height, dst_xpos, dst_ypos; /* Allocate memory for all the pages in each surface * and initialize variables inside each page's struct. */ surface->pages = calloc(surface->numpages, sizeof(struct dispmanx_page)); for (i = 0; i < surface->numpages; i++) { surface->pages[i].used = false; surface->pages[i].dispvars = _dispvars; surface->pages[i].page_used_mutex = slock_new(); } /* Internal frame dimensions. Pitch is total pitch including info * between scanlines */ surface->width = width; surface->height = height; surface->pitch = pitch; surface->aspect = aspect; /* The "visible" width obtained from the core pitch. We blit based on * the "visible" width, for cores with things between scanlines. */ int visible_width = pitch / surface->bpp; dst_width = _dispvars->dispmanx_height * aspect; dst_height = _dispvars->dispmanx_height; /* 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 (dst_width > _dispvars->dispmanx_width) dst_width = _dispvars->dispmanx_width; dst_xpos = (_dispvars->dispmanx_width - dst_width) / 2; dst_ypos = (_dispvars->dispmanx_height - dst_height) / 2; /* We configure the rects now. */ vc_dispmanx_rect_set(&surface->dst_rect, dst_xpos, dst_ypos, dst_width, dst_height); vc_dispmanx_rect_set(&surface->bmp_rect, 0, 0, width, height); vc_dispmanx_rect_set(&surface->src_rect, 0, 0, width << 16, height << 16); for (i = 0; i < surface->numpages; i++) { surface->pages[i].resource = vc_dispmanx_resource_create(surface->pixformat, visible_width, height, &(_dispvars->vc_image_ptr)); } /* Add element. */ _dispvars->update = vc_dispmanx_update_start(0); surface->element = vc_dispmanx_element_add( _dispvars->update,_dispvars->display, surface->layer, &surface->dst_rect, surface->pages[0].resource, &surface->src_rect, DISPMANX_PROTECTION_NONE, &surface->alpha, 0, (DISPMANX_TRANSFORM_T)0); vc_dispmanx_update_submit_sync(_dispvars->update); surface->setup = true; }
bool initBackgroundLayer( BACKGROUND_LAYER_T *bg, uint16_t colour, int32_t layer) { int result = 0; VC_IMAGE_TYPE_T type = VC_IMAGE_RGBA16; uint32_t vc_image_ptr; bg->resource = vc_dispmanx_resource_create(type, 1, 1, &vc_image_ptr); if(!bg->resource) return false; //--------------------------------------------------------------------- VC_RECT_T dst_rect; vc_dispmanx_rect_set(&dst_rect, 0, 0, 1, 1); bg->layer = layer; result = vc_dispmanx_resource_write_data(bg->resource, type, sizeof(colour), &colour, &dst_rect); if(result != DISPMANX_SUCCESS){ result = vc_dispmanx_resource_delete(bg->resource); return false; } return true; }
void vo_display_frame (RECT_VARS_T* vars, int width, int height, int chroma_width, int chroma_height, uint8_t * const * buf, int num) { int ret; static VC_RECT_T src_rect; static VC_RECT_T dst_rect; static VC_DISPMANX_ALPHA_T alpha = { DISPMANX_FLAGS_ALPHA_FROM_SOURCE | DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS, 255, /*alpha 0->255*/ 0 }; int pitch = VO_ALIGN_UP(width,32); assert((height % 16) == 0); assert((chroma_height % 16) == 0); if (num == 0) { vars->resource = vc_dispmanx_resource_create( VC_IMAGE_YUV420, width, height, &vars->vc_image_ptr ); assert( vars->resource ); vars->update = vc_dispmanx_update_start( 10 ); assert( vars->update ); vc_dispmanx_rect_set( &src_rect, 0, 0, width << 16, height << 16 ); vc_dispmanx_rect_set( &dst_rect, 0, 0, vars->info.width, vars->info.height); vars->element = vc_dispmanx_element_add( vars->update, vars->display, 2000, // layer &dst_rect, vars->resource, &src_rect, DISPMANX_PROTECTION_NONE, &alpha, NULL, // clamp VC_IMAGE_ROT0 ); ret = vc_dispmanx_update_submit( vars->update, NULL, NULL); vc_dispmanx_rect_set( &dst_rect, 0, 0, width, (3*height)/2); } ret = vc_dispmanx_resource_write_data( vars->resource, VC_IMAGE_YUV420, pitch, buf[0], &dst_rect ); assert( ret == 0 ); vars->update = vc_dispmanx_update_start( 10 ); assert( vars->update ); //ret = vc_dispmanx_update_submit_sync( vars->update ); ret = vc_dispmanx_update_submit( vars->update, NULL, NULL); assert( ret == 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; }
static void show_cursor(ALLEGRO_DISPLAY_RASPBERRYPI *d) { if (d->cursor_data == NULL || cursor_added) { return; } int width = d->cursor_width; int height = d->cursor_height; uint32_t unused; cursor_resource = vc_dispmanx_resource_create(VC_IMAGE_ARGB8888, width, height, &unused); VC_RECT_T r; r.x = 0; r.y = 0; r.width = width; r.height = height; int dpitch = pot(sizeof(uint32_t) * width); dispman_update = vc_dispmanx_update_start(0); vc_dispmanx_resource_write_data(cursor_resource, VC_IMAGE_ARGB8888, dpitch, d->cursor_data, &r); vc_dispmanx_update_submit_sync(dispman_update); ALLEGRO_MOUSE_STATE state; al_get_mouse_state(&state); dst_rect.x = state.x+d->cursor_offset_x; dst_rect.y = state.y+d->cursor_offset_y; dst_rect.width = width; dst_rect.height = height; src_rect.x = 0; src_rect.y = 0; src_rect.width = width << 16; src_rect.height = height << 16; dispman_update = vc_dispmanx_update_start(0); cursor_element = vc_dispmanx_element_add( dispman_update, dispman_display, 0/*layer*/, &dst_rect, cursor_resource, &src_rect, DISPMANX_PROTECTION_NONE, 0 /*alpha*/, 0/*clamp*/, 0/*transform*/ ); vc_dispmanx_update_submit_sync(dispman_update); cursor_added = true; }
unsigned char *CRBP::CaptureDisplay(int width, int height, int *pstride, bool swap_red_blue) { DISPMANX_DISPLAY_HANDLE_T display; DISPMANX_RESOURCE_HANDLE_T resource; VC_RECT_T rect; unsigned char *image = NULL; uint32_t vc_image_ptr; int stride; display = vc_dispmanx_display_open( 0 /*screen*/ ); stride = ((width + 15) & ~15) * 4; image = new unsigned char [height * stride]; if (image) { resource = vc_dispmanx_resource_create( VC_IMAGE_RGBA32, width, height, &vc_image_ptr ); vc_dispmanx_snapshot(display, resource, (DISPMANX_TRANSFORM_T)0); vc_dispmanx_rect_set(&rect, 0, 0, width, height); vc_dispmanx_resource_read_data(resource, &rect, image, stride); vc_dispmanx_resource_delete( resource ); vc_dispmanx_display_close(display ); // we need to save in BGRA order so Swap RGBA -> BGRA if (swap_red_blue) { for (int y = 0; y < height; y++) { unsigned char *p = image + y * stride; for (int x = 0; x < width; x++, p+=4) { unsigned char t = p[0]; p[0] = p[2]; p[2] = t; } } } // assume we need to pack image if caller doesn't want stride if (!pstride && stride > width*4) { for (int y = 0; y < height; y++) { unsigned char *in = image + y * stride; unsigned char *out = image + y * width * 4; memmove(out, in, width*4); } } } if (pstride) *pstride = stride; return image; }
uint32_t allocate_and_set_vc_handle(gralloc_private_handle_t *private_handle) { uint32_t vc_handle = 0; DISPMANX_RESOURCE_HANDLE_T resource_handle = vc_dispmanx_resource_create( convert_android_to_vc_img_type(private_handle->pixel_format), private_handle->w, private_handle->h, &vc_handle); //vc_dispmanx_resource_create set vc_handle to 0 //call to vc_dispmanx_resource_get_image_handle is needed vc_handle = vc_dispmanx_resource_get_image_handle(resource_handle); return vc_handle; }
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); }
NativeResource::NativeResource(unsigned int x, unsigned int y, unsigned int w, unsigned int h, VC_IMAGE_TYPE_T type, void * _imageData, int _imagePitch) : resourceHandle(0), rgbType(type), nativeImageHandle(0), imageData(_imageData ), imagePitch(_imagePitch) { int ret; setRegion(x,y,w,h); resourceHandle = vc_dispmanx_resource_create( rgbType, region.width, region.height, &nativeImageHandle ); ret = vc_dispmanx_resource_write_data( resourceHandle, rgbType, imagePitch, imageData, ®ion ); if ( ret != 0 ) throw runtime_error("runtime error : NativeResource::NativeResource ** resourceWriteData failed."); }
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; }
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); }
/* Create a cursor from a surface */ static SDL_Cursor * RPI_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y) { RPI_CursorData *curdata; SDL_Cursor *cursor; int ret; VC_RECT_T dst_rect; Uint32 dummy; SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888); SDL_assert(surface->pitch == surface->w * 4); cursor = (SDL_Cursor *) SDL_calloc(1, sizeof(*cursor)); if (cursor == NULL) { SDL_OutOfMemory(); return NULL; } curdata = (RPI_CursorData *) SDL_calloc(1, sizeof(*curdata)); if (curdata == NULL) { SDL_OutOfMemory(); SDL_free(cursor); return NULL; } curdata->hot_x = hot_x; curdata->hot_y = hot_y; curdata->w = surface->w; curdata->h = surface->h; /* This usage is inspired by Wayland/Weston RPI code, how they figured this out is anyone's guess */ curdata->resource = vc_dispmanx_resource_create( VC_IMAGE_ARGB8888, surface->w | (surface->pitch << 16), surface->h | (surface->h << 16), &dummy ); SDL_assert(curdata->resource); vc_dispmanx_rect_set( &dst_rect, 0, 0, curdata->w, curdata->h); /* A note from Weston: * vc_dispmanx_resource_write_data() ignores ifmt, * rect.x, rect.width, and uses stride only for computing * the size of the transfer as rect.height * stride. * Therefore we can only write rows starting at x=0. */ ret = vc_dispmanx_resource_write_data( curdata->resource, VC_IMAGE_ARGB8888, surface->pitch, surface->pixels, &dst_rect ); SDL_assert ( ret == DISPMANX_SUCCESS ); cursor->driverdata = curdata; return cursor; }
static struct dmx_region_t *dmx_region_new(vout_display_t *vd, DISPMANX_UPDATE_HANDLE_T update, subpicture_region_t *region) { vout_display_sys_t *sys = vd->sys; video_format_t *fmt = ®ion->fmt; struct dmx_region_t *dmx_region = malloc(sizeof(struct dmx_region_t)); uint32_t image_handle; dmx_region->pos_x = region->i_x; dmx_region->pos_y = region->i_y; vc_dispmanx_rect_set(&dmx_region->bmp_rect, 0, 0, fmt->i_visible_width, fmt->i_visible_height); vc_dispmanx_rect_set(&dmx_region->src_rect, 0, 0, fmt->i_visible_width << 16, fmt->i_visible_height << 16); vc_dispmanx_rect_set(&dmx_region->dst_rect, region->i_x, region->i_y, fmt->i_visible_width, fmt->i_visible_height); dmx_region->resource = vc_dispmanx_resource_create(VC_IMAGE_RGBA32, dmx_region->bmp_rect.width | (region->p_picture->p[0].i_pitch << 16), dmx_region->bmp_rect.height | (dmx_region->bmp_rect.height << 16), &image_handle); vc_dispmanx_resource_write_data(dmx_region->resource, VC_IMAGE_RGBA32, region->p_picture->p[0].i_pitch, region->p_picture->p[0].p_pixels, &dmx_region->bmp_rect); dmx_region->alpha.flags = DISPMANX_FLAGS_ALPHA_FROM_SOURCE | DISPMANX_FLAGS_ALPHA_MIX; dmx_region->alpha.opacity = region->i_alpha; dmx_region->alpha.mask = DISPMANX_NO_HANDLE; dmx_region->element = vc_dispmanx_element_add(update, sys->dmx_handle, sys->layer + 1, &dmx_region->dst_rect, dmx_region->resource, &dmx_region->src_rect, DISPMANX_PROTECTION_NONE, &dmx_region->alpha, NULL, VC_IMAGE_ROT0); dmx_region->next = NULL; dmx_region->picture = region->p_picture; return dmx_region; }
unsigned char *CRBP::CaptureDisplay(int width, int height, int *pstride, bool swap_red_blue, bool video_only) { DISPMANX_DISPLAY_HANDLE_T display; DISPMANX_RESOURCE_HANDLE_T resource; VC_RECT_T rect; unsigned char *image = NULL; uint32_t vc_image_ptr; int stride; uint32_t flags = 0; if (video_only) flags |= DISPMANX_SNAPSHOT_NO_RGB|DISPMANX_SNAPSHOT_FILL; if (swap_red_blue) flags |= DISPMANX_SNAPSHOT_SWAP_RED_BLUE; if (!pstride) flags |= DISPMANX_SNAPSHOT_PACK; display = vc_dispmanx_display_open( 0 /*screen*/ ); stride = ((width + 15) & ~15) * 4; image = new unsigned char [height * stride]; if (image) { resource = vc_dispmanx_resource_create( VC_IMAGE_RGBA32, width, height, &vc_image_ptr ); vc_dispmanx_snapshot(display, resource, (DISPMANX_TRANSFORM_T)flags); vc_dispmanx_rect_set(&rect, 0, 0, width, height); vc_dispmanx_resource_read_data(resource, &rect, image, stride); vc_dispmanx_resource_delete( resource ); vc_dispmanx_display_close(display ); } if (pstride) *pstride = stride; return image; }
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; } } }
// Initialize the OpenGL library void initGL(int width, int height) { #ifdef PLATFORM_RPI // Start clock gettimeofday(&tv, NULL); timeStart = (unsigned long long)(tv.tv_sec) * 1000 + (unsigned long long)(tv.tv_usec) / 1000; // Start OpenGL ES bcm_host_init(); // Clear application state EGLBoolean result; EGLint num_config; static const EGLint attribute_list[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, // EGL_SAMPLE_BUFFERS, 1, EGL_SAMPLES, 4, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_DEPTH_SIZE, 16, EGL_NONE }; static const EGLint context_attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; EGLConfig config; // get an EGL display connection display = eglGetDisplay(EGL_DEFAULT_DISPLAY); assert(display!=EGL_NO_DISPLAY); check(); // initialize the EGL display connection result = eglInitialize(display, NULL, NULL); assert(EGL_FALSE != result); check(); // get an appropriate EGL frame buffer configuration result = eglChooseConfig(display, attribute_list, &config, 1, &num_config); assert(EGL_FALSE != result); check(); // get an appropriate EGL frame buffer configuration result = eglBindAPI(EGL_OPENGL_ES_API); assert(EGL_FALSE != result); check(); // create an EGL rendering context context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attributes); assert(context != EGL_NO_CONTEXT); check(); static EGL_DISPMANX_WINDOW_T nativeviewport; VC_RECT_T dst_rect; VC_RECT_T src_rect; uint32_t dest_image_handle; uint32_t screen_width = width; uint32_t screen_height = height; // Initially the viewport is for all the screen dst_rect.x = 0; dst_rect.y = 0; dst_rect.width = screen_width; dst_rect.height = screen_height; src_rect.x = 0; src_rect.y = 0; src_rect.width = screen_width << 16; src_rect.height = screen_height << 16; DISPMANX_RESOURCE_HANDLE_T dispman_resource; dispman_resource = vc_dispmanx_resource_create(VC_IMAGE_RGBA32, screen_width, screen_height, &dest_image_handle); dispman_display = vc_dispmanx_display_open_offscreen(dispman_resource, DISPMANX_NO_ROTATE); // dispman_display = vc_dispmanx_display_open( 0 /* LCD */); DISPMANX_UPDATE_HANDLE_T dispman_update; dispman_update = vc_dispmanx_update_start(0); DISPMANX_ELEMENT_HANDLE_T dispman_element; 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_TRANSFORM_T)0/*transform*/); nativeviewport.element = dispman_element; nativeviewport.width = screen_width; nativeviewport.height = screen_height; vc_dispmanx_update_submit_sync(dispman_update); check(); surface = eglCreateWindowSurface(display, config, &nativeviewport, NULL); assert(surface != EGL_NO_SURFACE); check(); // connect the context to the surface result = eglMakeCurrent(display, surface, surface, context); assert(EGL_FALSE != result); check(); glViewport(0.0f, 0.0f, (float)screen_width, (float)screen_height); check(); #else // ---------------------------------------- using GLFW // if (!glfwInit()) { return; } glfwWindowHint(GLFW_SAMPLES, 2); glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); window = glfwCreateWindow(width, height, "", NULL, NULL); if (!window) { glfwTerminate(); } // Make the main_window's context current glfwMakeContextCurrent(window); #endif }
int main(int argc, char **argv) { DISPMANX_DISPLAY_HANDLE_T main_display_handle; DISPMANX_RESOURCE_HANDLE_T screen_resource_handle; VC_RECT_T rectangle; int ret; uint32_t image_prt; uint16_t image[2][ PICTURE_PIXELS ]; uint32_t current_frame = 0, old_frame=1; uint32_t i, x, y, start, end, count; uint16_t *p_current_frame, *p_old_frame, *p_start; bcm_host_init(); if ( !bcm2835_init() ) return ( -1 ); TFT_init_board(); TFT_hard_reset(); RAIO_init(); //clear old image p_old_frame = &image[ old_frame ][0]; for(x=0; x<76800; x++) { *p_old_frame++ = 0x1111; } // open main framebuffer device main_display_handle = vc_dispmanx_display_open( 0 ); if ( !main_display_handle ) { printf("\n Unable to open primary display"); return( -1 ); } // now build up the shadow area for RAIO screen_resource_handle = vc_dispmanx_resource_create( VC_IMAGE_RGB565, DISPLAY_WIDTH, DISPLAY_HEIGHT, &image_prt ); if ( !screen_resource_handle ) { printf("\n Unable to create screen buffer"); vc_dispmanx_display_close( main_display_handle ); return ( -1 ); } vc_dispmanx_rect_set( &rectangle, 0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT ); while( 1 ) { ret = vc_dispmanx_snapshot( main_display_handle, screen_resource_handle, DISPMANX_NO_ROTATE ); vc_dispmanx_resource_read_data( screen_resource_handle, &rectangle, &image[ current_frame ][0], DISPLAY_WIDTH*2 ); i=0; p_current_frame = &image[ current_frame ][ 0 ]; p_old_frame = &image[ old_frame ][ 0 ]; while (i<PICTURE_PIXELS) { while (( *p_current_frame == *p_old_frame) && (i<PICTURE_PIXELS) ) { p_current_frame++; p_old_frame++; i = i+1; } p_start = p_current_frame; start = i; while (( *p_current_frame != *p_old_frame) && (i<PICTURE_PIXELS) ) { p_current_frame++; p_old_frame++; i = i+1; } count = i - start; y=start/DISPLAY_WIDTH; x=start-y*DISPLAY_WIDTH; RAIO_set_cursor( x, y ); RAIO_Write_Picture( p_start, count ); } old_frame = current_frame; if ( current_frame == 0 ) current_frame = 1; else current_frame = 0; // 100ms -> 10 fps usleep( 100 * 1000 ); } return ( 0 ); }
void newLife( LIFE_T *life, int32_t size) { life->width = size; life->height = size; life->alignedWidth = ALIGN_TO_16(life->width); life->alignedHeight = ALIGN_TO_16(life->height); life->pitch = ALIGN_TO_16(life->width); life->buffer = calloc(1, life->pitch * life->alignedHeight); if (life->buffer == NULL) { fprintf(stderr, "life: memory exhausted\n"); exit(EXIT_FAILURE); } life->fieldLength = life->width * life->height; life->field = calloc(1, life->fieldLength); if (life->field == NULL) { fprintf(stderr, "life: memory exhausted\n"); exit(EXIT_FAILURE); } life->fieldNext = calloc(1, life->fieldLength); if (life->fieldNext == NULL) { fprintf(stderr, "life: memory exhausted\n"); exit(EXIT_FAILURE); } struct timeval tv; gettimeofday(&tv, NULL); srand(tv.tv_usec); int32_t row = 0; for (row = 0 ; row < life->height ; row++) { int32_t col = 0; for (col = 0 ; col < life->width ; col++) { if (rand() > (RAND_MAX / 2)) { setCell(life, col, row); } else { life->buffer[col + (row * life->alignedWidth)] = DEAD; } } } //--------------------------------------------------------------------- VC_IMAGE_TYPE_T type = VC_IMAGE_8BPP; uint32_t vc_image_ptr; int result = 0; life->frontResource = vc_dispmanx_resource_create( type, life->width | (life->pitch << 16), life->height | (life->alignedHeight << 16), &vc_image_ptr); assert(life->frontResource != 0); life->backResource = vc_dispmanx_resource_create( type, life->width | (life->pitch << 16), life->height | (life->alignedHeight << 16), &vc_image_ptr); assert(life->backResource != 0); //--------------------------------------------------------------------- vc_dispmanx_rect_set(&(life->bmpRect), 0, 0, life->width, life->height); result = vc_dispmanx_resource_write_data(life->frontResource, type, life->pitch, life->buffer, &(life->bmpRect)); assert(result == 0); //--------------------------------------------------------------------- long cores = sysconf(_SC_NPROCESSORS_ONLN); if (cores == -1) { cores = 1; } if (cores > LIFE_MAX_THREADS) { life->numberOfThreads = LIFE_MAX_THREADS; } else { life->numberOfThreads = cores; } pthread_barrier_init(&(life->startIterationBarrier), NULL, life->numberOfThreads + 1); pthread_barrier_init(&(life->finishedIterationBarrier), NULL, life->numberOfThreads + 1); //--------------------------------------------------------------------- int32_t heightStep = life->height / life->numberOfThreads; int32_t heightStart = 0; int32_t thread; for (thread = 0 ; thread < life->numberOfThreads ; thread++) { life->heightRange[thread].startHeight = heightStart; life->heightRange[thread].endHeight = heightStart + heightStep; heightStart += heightStep; pthread_create(&(life->threads[thread]), NULL, workerLife, life); } thread = life->numberOfThreads - 1; life->heightRange[thread].endHeight = life->height; //--------------------------------------------------------------------- memcpy(life->field, life->fieldNext, life->fieldLength); pthread_barrier_wait(&(life->startIterationBarrier)); }
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; }
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 veraa 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. //Asique 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 impediaa 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 haciaa 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); }
static void dispmanx_set_texture_frame(void *data, const void *frame, bool rgb32, unsigned width, unsigned height, float alpha) { struct dispmanx_video *_dispvars = data; if (!_dispvars) return; /* If we're entering the menu in this frame, * we must setup rects, resources and menu element. */ if (width != _dispvars->menu_width || height != _dispvars->menu_height) { int i, dst_width, dst_ypos; VC_DISPMANX_ALPHA_T layerAlpha; /* Sanity check */ if (width == 0 || height == 0) return; _dispvars->menu_width = width; _dispvars->menu_height = height; _dispvars->menu_pitch = width * (rgb32 ? 4 : 2); _dispvars->menu_pixFormat = VC_IMAGE_RGBA16; _dispvars->menu_flip_page = 0; /* Transparency disabled */ layerAlpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS; #if 0 layerAlpha.opacity = (unsigned char)(255.0f * alpha); #endif layerAlpha.opacity = 210; layerAlpha.mask = 0; _dispvars->menu_alpha = &layerAlpha; 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->menu_dstRect), dst_ypos, 0, dst_width, _dispvars->amode.height); /* We configure the rects now. */ vc_dispmanx_rect_set(&(_dispvars->menu_bmpRect), 0, 0, _dispvars->menu_width, _dispvars->menu_height); vc_dispmanx_rect_set(&(_dispvars->menu_srcRect), 0, 0, _dispvars->menu_width << 16, _dispvars->menu_height << 16); /* We create two resources for the menu element. */ _dispvars->menu_resources[0] = vc_dispmanx_resource_create(_dispvars->menu_pixFormat, _dispvars->menu_width, _dispvars->menu_height, &(_dispvars->vcImagePtr)); _dispvars->menu_resources[1] = vc_dispmanx_resource_create(_dispvars->menu_pixFormat, _dispvars->menu_width, _dispvars->menu_height, &(_dispvars->vcImagePtr)); /* Add the menu element. */ _dispvars->update = vc_dispmanx_update_start(0); _dispvars->menu_element = vc_dispmanx_element_add(_dispvars->update, _dispvars->display, 0, &(_dispvars->menu_dstRect), _dispvars->menu_resources[0], &(_dispvars->menu_srcRect), DISPMANX_PROTECTION_NONE, _dispvars->menu_alpha, 0, (DISPMANX_TRANSFORM_T)0); vc_dispmanx_update_submit_sync(_dispvars->update); } /* Flipping is done in every frame, * in the gfx_frame function. * That's why why change flip page here instead. */ _dispvars->menu_flip_page = !_dispvars->menu_flip_page; /* Frame blitting. */ vc_dispmanx_resource_write_data(_dispvars->menu_resources[_dispvars->menu_flip_page], _dispvars->menu_pixFormat, _dispvars->menu_pitch, (void *)frame, &(_dispvars->menu_bmpRect)); /* We don't flip the menu buffers here: * that's done in the gfx_frame function when menu is active. */ }
static jlong fbDispmanCreateNativeCursor(JNIEnv *env, jint x, jint y, jbyte *srcArray, jint width, jint height) { VC_RECT_T pixelRect; int rc; uint32_t imagePtr; jbyte *allocatedBuffer = NULL; DispmanCursorImage *cursorImage = (DispmanCursorImage *)malloc(sizeof(DispmanCursorImage)); //Width should be aligned to 16 pixels if (width % 16 != 0) { int newWidth = width + 16 - (width % 16); allocatedBuffer = (jbyte *)malloc(newWidth * height * 4); int i; int offset = 0; for (i = 0; i < height; ++i) { memcpy(allocatedBuffer + offset, srcArray, width * 4); memset(allocatedBuffer + offset + (width * 4), 0, (newWidth - width) * 4); offset += newWidth * 4; srcArray += width * 4; } width = newWidth; srcArray = allocatedBuffer; } pixelRect.x = 0; pixelRect.y = 0; pixelRect.width = width; pixelRect.height = height; cursorImage->x = x; cursorImage->y = y; cursorImage->width = width; cursorImage->height = height; cursorImage->resource = vc_dispmanx_resource_create(VC_IMAGE_ARGB8888, width, height, &imagePtr); if (cursorImage->resource == 0) { GLASS_LOG_SEVERE("Cannot create resource"); if (allocatedBuffer != NULL) { free(allocatedBuffer); allocatedBuffer = NULL; } free(cursorImage); return 0; } rc = vc_dispmanx_resource_write_data(cursorImage->resource, VC_IMAGE_ARGB8888, width * 4, srcArray, &pixelRect); if (allocatedBuffer != NULL) { free(allocatedBuffer); allocatedBuffer = NULL; } if (rc != 0) { GLASS_LOG_SEVERE("Cannot write pixels"); free(cursorImage); return 0; } return ptr_to_jlong(cursorImage); }
static jboolean fbDispmanRobotScreenCapture(jint x, jint y, jint width, jint height, jint *pixels) { FILE *fb; unsigned int *pixelBuffer = NULL; unsigned char *pixelBufferPtr = NULL; unsigned char *dst = (unsigned char *) pixels; int i = 0; int fbFileHandle; struct fb_var_screeninfo screenInfo; unsigned int dstByteStride = width * 4; VC_IMAGE_TRANSFORM_T transform = 0; DISPMANX_RESOURCE_HANDLE_T resource = 0; DISPMANX_DISPLAY_HANDLE_T display = 0; DISPMANX_RESOURCE_HANDLE_T screenResource = 0; uint32_t imagePtr; int rc; GLASS_LOG_FINE("Capture %i,%i+%ix%i", x, y, width, height); if (width < 1 || height < 1) { GLASS_LOG_SEVERE("Failed. width/height values must be at least = 1"); return JNI_FALSE; } GLASS_LOG_FINE("open(%s, O_RDONLY)", FB_DEVICE); fbFileHandle = open(FB_DEVICE, O_RDONLY); if (fbFileHandle < 0) { GLASS_LOG_SEVERE("Cannot open framebuffer"); return JNI_FALSE; } GLASS_LOG_FINE("ioctl(%s, FBIOGET_VSCREENINFO)", FB_DEVICE); if (ioctl(fbFileHandle, FBIOGET_VSCREENINFO, &screenInfo)) { GLASS_LOG_SEVERE("Cannot get screen info"); GLASS_LOG_FINE("close(%s)", FB_DEVICE); close(fbFileHandle); return JNI_FALSE; } GLASS_LOG_FINE("Read screen info: res=%ix%i, offset=%ix%i", screenInfo.xres, screenInfo.yres, screenInfo.xoffset, screenInfo.yoffset); GLASS_LOG_FINE("close(%s)", FB_DEVICE); close(fbFileHandle); VC_RECT_T pixelRect = { 0, 0, screenInfo.xres, screenInfo.yres }; int pixelBufferLength = screenInfo.xres * screenInfo.yres * 4; pixelBuffer = (unsigned int *) malloc(pixelBufferLength); pixelBufferPtr = (unsigned char *) pixelBuffer; if (pixelBuffer == NULL) { printf("Failed to allocate temporary pixel buffer\n"); return JNI_FALSE; } GLASS_LOG_FINE("fopen(%s, \"r\") to read %ix%i pixels at bit depth %i\n", FB_DEVICE, width, height, screenInfo.bits_per_pixel); display = vc_dispmanx_display_open(0 /* LCD */); if (display == 0) { fprintf(stderr, "fbRobotScreenCapture: Dispman: Cannot open display\n"); free(pixelBuffer); return JNI_FALSE; } // create the resource for the snapshot screenResource = vc_dispmanx_resource_create(VC_IMAGE_ARGB8888, screenInfo.xres, screenInfo.yres, &imagePtr); if (!screenResource) { fprintf(stderr, "fbRobotScreenCapture: Cannot create resource\n"); vc_dispmanx_display_close(display); free(pixelBuffer); return JNI_FALSE; } rc = vc_dispmanx_snapshot(display, screenResource, transform); rc = 0; if (rc) { fprintf(stderr, "fbRobotScreenCapture: snapshot failed\n"); vc_dispmanx_display_close(display); free(pixelBuffer); return JNI_FALSE; } rc = vc_dispmanx_resource_read_data(screenResource, &pixelRect, pixelBuffer, screenInfo.xres * 4); if (rc) { fprintf(stderr, "fbRobotScreenCapture: Cannot read pixels %d\n", rc); vc_dispmanx_display_close(display); free(pixelBuffer); return JNI_FALSE; } rc = vc_dispmanx_resource_delete(screenResource); if (rc) { fprintf(stderr, "fbRobotScreenCapture: failed to free buffer %d\n", rc); vc_dispmanx_display_close(display); free(pixelBuffer); return JNI_FALSE; } screenResource = 0; if (x < 0) { pixelBuffer += -x; width += x; x = 0; } if (y < 0) { pixelBuffer += -y * (int)screenInfo.xres; height += y; y = 0; } int widthLimit = width; int heightLimit = height; // Required height is larger than screen's height if ((int) screenInfo.yres < height) { heightLimit = (int) screenInfo.yres; } // Required width is larger than screen's width if ((int) screenInfo.xres < width) { widthLimit = (int) screenInfo.xres; } // Required height is out of range if (((int) screenInfo.yres - y) < height) { heightLimit = (int) screenInfo.yres - y; } // Required width is out of range if (((int) screenInfo.xres - x) < width) { widthLimit = (int) screenInfo.xres - x; } if (widthLimit > 0 && heightLimit > 0) { // copy the relevant portion of the screen to the supplied pixel array int offset = y * screenInfo.xres * 4 + x * 4; for (i = 0; i < heightLimit; i++) { memcpy(dst + i * dstByteStride, pixelBufferPtr + offset, widthLimit * 4); offset += screenInfo.xres * 4; } } else { GLASS_LOG_SEVERE("Failed to take a snapshot, some of parameters are illegal"); free(pixelBuffer); return JNI_FALSE; } vc_dispmanx_display_close(display); free(pixelBuffer); return JNI_TRUE; }
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 }
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); }
void pi_setvideo_mode(int width, int height) { uint32_t display_width, display_height; uint32_t display_x = 0, display_y = 0; float display_ratio, game_ratio; VC_RECT_T dst_rect; VC_RECT_T src_rect; surface_width = width; surface_height = height; VideoBuffer = (unsigned short *) calloc(1, width * height * 4); // get an EGL display connection display = eglGetDisplay(EGL_DEFAULT_DISPLAY); assert(display != EGL_NO_DISPLAY); // initialize the EGL display connection EGLBoolean result = eglInitialize(display, NULL, NULL); assert(EGL_FALSE != result); // get an appropriate EGL frame buffer configuration EGLint num_config; EGLConfig config; 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 }; result = eglChooseConfig(display, attribute_list, &config, 1, &num_config); assert(EGL_FALSE != result); result = eglBindAPI(EGL_OPENGL_ES_API); assert(EGL_FALSE != result); // create an EGL rendering context static const EGLint context_attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attributes); assert(context != EGL_NO_CONTEXT); // create an EGL window surface int32_t success = graphics_get_display_size(0, &display_width, &display_height); assert(success >= 0); display_adj_width = display_width - (config_options.option_display_border * 2); display_adj_height = display_height - (config_options.option_display_border * 2); if (config_options.display_smooth_stretch) { //We use the dispmanx scaler to smooth stretch the display //so GLES2 doesn't have to handle the performance intensive postprocessing uint32_t sx, sy; // Work out the position and size on the display display_ratio = (float) display_width / (float) display_height; game_ratio = (float) width / (float) height; display_x = sx = display_adj_width; display_y = sy = display_adj_height; if (config_options.maintain_aspect_ratio || game_ratio < 1) { if (game_ratio > display_ratio) sy = (float) display_adj_width / (float) game_ratio; else sx = (float) display_adj_height * (float) game_ratio; } // Centre bitmap on screen display_x = (display_x - sx) / 2; display_y = (display_y - sy) / 2; vc_dispmanx_rect_set(&dst_rect, display_x + config_options.option_display_border, display_y + config_options.option_display_border, sx, sy); } else vc_dispmanx_rect_set(&dst_rect, config_options.option_display_border, config_options.option_display_border, display_adj_width, display_adj_height); if (config_options.display_smooth_stretch) vc_dispmanx_rect_set(&src_rect, 0, 0, width << 16, height << 16); else vc_dispmanx_rect_set(&src_rect, 0, 0, display_adj_width << 16, display_adj_height << 16); dispman_display = vc_dispmanx_display_open(0); dispman_update = vc_dispmanx_update_start(0); dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display, 10, &dst_rect, 0, &src_rect, DISPMANX_PROTECTION_NONE, NULL, NULL, DISPMANX_NO_ROTATE); //Black background surface dimensions vc_dispmanx_rect_set(&dst_rect, 0, 0, display_width, display_height); vc_dispmanx_rect_set(&src_rect, 0, 0, 128 << 16, 128 << 16); //Create a blank background for the whole screen, make sure width is divisible by 32! uint32_t crap; resource_bg = vc_dispmanx_resource_create(VC_IMAGE_RGB565, 128, 128, &crap); dispman_element_bg = vc_dispmanx_element_add(dispman_update, dispman_display, 9, &dst_rect, resource_bg, &src_rect, DISPMANX_PROTECTION_NONE, 0, 0, (DISPMANX_TRANSFORM_T) 0); nativewindow.element = dispman_element; if (config_options.display_smooth_stretch) { nativewindow.width = width; nativewindow.height = height; } else { nativewindow.width = display_adj_width; nativewindow.height = display_adj_height; } vc_dispmanx_update_submit_sync(dispman_update); surface = eglCreateWindowSurface(display, config, &nativewindow, NULL); assert(surface != EGL_NO_SURFACE); // connect the context to the surface result = eglMakeCurrent(display, surface, surface, context); assert(EGL_FALSE != result); //Smooth stretch the display size for GLES2 is the size of the bitmap //otherwise let GLES2 upscale (NEAR) to the size of the display if (config_options.display_smooth_stretch) gles2_create(width, height, width, height, 16); else gles2_create(display_adj_width, display_adj_height, width, height, 16); }