static int create(void) { destroy(); pf_page1 = create_video_bitmap(SCREEN_W, SCREEN_H); pf_page2 = create_video_bitmap(SCREEN_W, SCREEN_H); if ((!pf_page1) || (!pf_page2)) { destroy(); return DEMO_ERROR_VIDEOMEMORY; } pf_active_page = pf_page1; return DEMO_OK; }
/* * call-seq: * create_video_bitmap(width, height) -> a_bmp or nil * * Allocates a video memory bitmap of the specified size. This can be used to * allocate offscreen video memory for storing source graphics ready for a * hardware accelerated blitting operation, or to create multiple video memory * pages which can then be displayed by calling show_video_bitmap. Read the * introduction of this chapter for a comparison with other types of bitmaps and * other specific details. * * Warning: video memory bitmaps are usually allocated from the same space as * the screen bitmap, so they may overlap with it; it is therefore not a good * idea to use the global screen at the same time as any surfaces returned by * this function. * * Return value: Returns a reference to the bitmap on success, or nil if you * have run out of video ram. Remember to destroy this bitmap before any * subsequent call to set_gfx_mode. */ VALUE a4r_API_create_video_bitmap(VALUE self, VALUE width, VALUE height) { // TODO: Change to call destroy_bitmap on free? BITMAP *bmp = create_video_bitmap(FIX2INT(width), FIX2INT(height)); if (bmp == NULL) return Qnil; VALUE obj = Data_Wrap_Struct(cAPI_BITMAP, 0, 0, bmp); return obj; }
SCREEN::SCREEN(int width, int height, bool windowed, bool db, bool videobuf_tiles) : w(width), h(height), doublebuffer(db) { if (!doublebuffer) { // page flipping // set graphics mode set_color_depth(32); if (set_gfx_mode((windowed ? GFX_AUTODETECT_WINDOWED : GFX_AUTODETECT_FULLSCREEN), width, height, width, height * 2) != 0) { // get video memory now (smart drivers) printf("warning: set_gfx_mode(): %s\n", allegro_error); if (set_gfx_mode((windowed ? GFX_AUTODETECT_WINDOWED : GFX_AUTODETECT_FULLSCREEN), width, height, 0, 0) != 0) { // just open screen now and hope we can get the video memory later (DirectX) printf("warning: set_gfx_mode(%dx%d): %s\n", width, height, allegro_error); panic("failed to open screen with requested resolution"); } } // get video memory video_page[0] = create_video_bitmap(width, height); video_page[1] = create_video_bitmap(width, height); if (videobuf_tiles) video_page[2] = create_video_bitmap(width + 2 * WORLD_RENDER_BORDER_SIZE, height + 2 * WORLD_RENDER_BORDER_SIZE); else video_page[2] = NULL; // error if (!video_page[0] || !video_page[1]) panic("unable to acquire sufficient video memory for requested resolution"); if (!video_page[2] && videobuf_tiles) printf("unable to acquire video memory for tile background; using a memory bitmap instead"); // set current screen video_page_offscreen = 0; offscreen = video_page[video_page_offscreen]; // flip page flip_page(); } else { // double buffering set_color_depth(32); if (set_gfx_mode((windowed ? GFX_AUTODETECT_WINDOWED : GFX_AUTODETECT_FULLSCREEN), width, height, 0, 0) != 0) { // double buffering printf("warning: set_gfx_mode(%dx%d): %s\n", width, height, allegro_error); panic("failed to open screen with requested resolution"); } video_page[0] = create_bitmap(width, height); video_page[1] = NULL; video_page[2] = NULL; offscreen = video_page[0]; } gui_set_screen(offscreen); // for the allegro gui routines }
BITMAP *clone_bitmap(int bpp, BITMAP *src, double scale, bool vidmem) { BITMAP *dest, *convert; if ( !src ) return 0; int W, H; W = iround( src->w * scale ); H = iround( src->h * scale ); dest = create_bitmap_ex(bpp, W, H); convert = create_bitmap_ex(bpp, src->w, src->h); // use this to convert color depth blit(src, convert, 0, 0, 0, 0, src->w, src->h); if (W != src->w || H != src->h ) stretch_blit(convert, dest, 0, 0, convert->w, convert->h, 0, 0, dest->w, dest->h); else blit(convert, dest, 0, 0, 0, 0, W, H); del_bitmap(&convert); // try to store this in memory, if there's enough room for it // cause the menu-bitmaps are pretty large, and take lotsa time to draw ... if (vidmem) { convert = create_video_bitmap(W, H); if (convert) { blit(dest, convert, 0, 0, 0, 0, W, H); del_bitmap(&dest); dest = convert; } } return dest; }
int uip_vgamode(void) { int depth, rate; unsigned long screenbase; for (rate = 60; rate <= 70; rate += 10) { for (depth = 15; depth <= 16; depth++) { LOG_VERBOSE(("Trying mode 640x480 depth %d rate %d", depth, rate)); set_color_depth(depth); request_refresh_rate(rate); if ((set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 480 * 2) < 0)) { LOG_VERBOSE(("Mode not supported")); continue; } if (SCREEN_W != 640 || SCREEN_H != 480) { LOG_CRITICAL(("Screen not approriate for depth %d rate %d", depth, rate)); continue; } goto WHEE; } } LOG_CRITICAL(("Failed to find suitable mode")); return 1; WHEE: uip_vga = 1; if (uip_forceredshift != -1 && uip_forcegreenshift != -1 && uip_forceblueshift != -1) { uip_uipinfo->redshift = uip_forceredshift; uip_uipinfo->greenshift = uip_forcegreenshift; uip_uipinfo->blueshift = uip_forceblueshift; } else { uip_uipinfo->redshift = ui_topbit(makecol(255, 0, 0)) - 4; uip_uipinfo->greenshift = ui_topbit(makecol(0, 255, 0)) - 4; uip_uipinfo->blueshift = ui_topbit(makecol(0, 0, 255)) - 4; } if ((uip_bank0 = create_video_bitmap(640, 480)) == NULL || (uip_bank1 = create_video_bitmap(640, 480)) == NULL) { uip_textmode(); LOG_CRITICAL(("Failed to allocate memory pages")); return 1; } if (is_linear_bitmap(uip_bank0) == 0 || is_linear_bitmap(uip_bank1) == 0 || is_video_bitmap(uip_bank0) == 0 || is_video_bitmap(uip_bank1) == 0) { uip_textmode(); LOG_CRITICAL(("Allocated bitmaps not suitable or linear addressing mode " "not supported by hardware")); return 1; } /* don't you just hate MS platforms? */ __djgpp_nearptr_enable(); __dpmi_get_segment_base_address(uip_bank0->seg, &screenbase); uip_uipinfo->screenmem0 = (uint8 *)(screenbase + uip_bank0->line[0] - __djgpp_base_address); __dpmi_get_segment_base_address(uip_bank1->seg, &screenbase); uip_uipinfo->screenmem1 = (uint8 *)(screenbase + uip_bank1->line[0] - __djgpp_base_address); uip_uipinfo->linewidth = 2 * VIRTUAL_W; /* 16 bit */ uip_displaybank(0); /* set current to 0th bank */ uip_clearscreen(); /* clear bank */ ui_setupscreen(); /* setup bank */ uip_displaybank(-1); /* toggle bank */ uip_clearscreen(); /* clear bank */ ui_setupscreen(); /* setup bank */ if (install_keyboard() == -1) { uip_textmode(); LOG_CRITICAL(("Unable to initialise keyboard")); return 1; } if (uip_bank0->y_ofs != 0 || uip_bank1->y_ofs != 480) { uip_textmode(); LOG_CRITICAL(("sorry, I don't understand this video layout")); return 1; } keyboard_lowlevel_callback = uip_keyboardhandler; uip_keypoll = keyboard_needs_poll()? 1 : 0; return 0; }
int main(int argc, char *argv[]) { char buf[256]; PALETTE pal; BITMAP *image; BITMAP *page[2]; BITMAP *vimage; IMAGE images[MAX_IMAGES]; int num_images = 4; int page_num = 1; int done = FALSE; int i; if (allegro_init() != 0) return 1; install_keyboard(); install_timer(); /* see comments in exflip.c */ #ifdef ALLEGRO_VRAM_SINGLE_SURFACE if (set_gfx_mode(GFX_AUTODETECT, 1024, 768, 0, 2 * 768 + 200) != 0) { #else if (set_gfx_mode(GFX_AUTODETECT, 1024, 768, 0, 0) != 0) { #endif set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Error setting graphics mode\n%s\n", allegro_error); return 1; } /* read in the source graphic */ replace_filename(buf, argv[0], "mysha.pcx", sizeof(buf)); image = load_bitmap(buf, pal); if (!image) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Error reading %s!\n", buf); return 1; } set_palette(pal); /* initialise the images to random positions */ for (i=0; i<MAX_IMAGES; i++) init_image(images+i); /* create two video memory bitmaps for page flipping */ page[0] = create_video_bitmap(SCREEN_W, SCREEN_H); page[1] = create_video_bitmap(SCREEN_W, SCREEN_H); /* create a video memory bitmap to store our picture */ vimage = create_video_bitmap(image->w, image->h); if ((!page[0]) || (!page[1]) || (!vimage)) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Not enough video memory (need two 1024x768 pages " "and a 320x200 image)\n"); return 1; } /* copy the picture into offscreen video memory */ blit(image, vimage, 0, 0, 0, 0, image->w, image->h); while (!done) { acquire_bitmap(page[page_num]); /* clear the screen */ clear_bitmap(page[page_num]); /* draw onto it */ for (i=0; i<num_images; i++) blit(vimage, page[page_num], 0, 0, images[i].x, images[i].y, vimage->w, vimage->h); textprintf_ex(page[page_num], font, 0, 0, 255, -1, "Images: %d (arrow keys to change)", num_images); /* tell the user which functions are being done in hardware */ if (gfx_capabilities & GFX_HW_FILL) textout_ex(page[page_num], font, "Clear: hardware accelerated", 0, 16, 255, -1); else textout_ex(page[page_num], font, "Clear: software (urgh, this " "is not good!)", 0, 16, 255, -1); if (gfx_capabilities & GFX_HW_VRAM_BLIT) textout_ex(page[page_num], font, "Blit: hardware accelerated", 0, 32, 255, -1); else textout_ex(page[page_num], font, "Blit: software (urgh, this program " "will run too sloooooowly without hardware acceleration!)", 0, 32, 255, -1); release_bitmap(page[page_num]); /* page flip */ show_video_bitmap(page[page_num]); page_num = 1-page_num; /* deal with keyboard input */ while (keypressed()) { switch (readkey()>>8) { case KEY_UP: case KEY_RIGHT: if (num_images < MAX_IMAGES) num_images++; break; case KEY_DOWN: case KEY_LEFT: if (num_images > 0) num_images--; break; case KEY_ESC: done = TRUE; break; } } /* bounce the images around the screen */ for (i=0; i<num_images; i++) update_image(images+i); } destroy_bitmap(image); destroy_bitmap(vimage); destroy_bitmap(page[0]); destroy_bitmap(page[1]); return 0; } END_OF_MAIN()
int main(void) { BITMAP *buffer; BITMAP *page1, *page2; BITMAP *active_page; int c; if (allegro_init() != 0) return 1; install_timer(); install_keyboard(); /* Some platforms do page flipping by making one large screen that you * can then scroll, while others give you several smaller, unique * surfaces. If you use the create_video_bitmap() function, the same * code can work on either kind of platform, but you have to be careful * how you set the video mode in the first place. We want two pages of * 320x200 video memory, but if we just ask for that, on DOS Allegro * might use a VGA driver that won't later be able to give us a second * page of vram. But if we ask for the full 320x400 virtual screen that * we want, the call will fail when using DirectX drivers that can't do * this. So we try two different mode sets, first asking for the 320x400 * size, and if that doesn't work, for 320x200. */ if (set_gfx_mode(GFX_AUTODETECT, 320, 200, 0, 400) != 0) { if (set_gfx_mode(GFX_AUTODETECT, 320, 200, 0, 0) != 0) { if (set_gfx_mode(GFX_SAFE, 320, 200, 0, 0) != 0) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Unable to set any graphic mode\n%s\n", allegro_error); return 1; } } } set_palette(desktop_palette); /* allocate the memory buffer */ buffer = create_bitmap(SCREEN_W, SCREEN_H); /* first with a double buffer... */ clear_keybuf(); c = retrace_count+32; while (retrace_count-c <= SCREEN_W+32) { clear_to_color(buffer, makecol(255, 255, 255)); circlefill(buffer, retrace_count-c, SCREEN_H/2, 32, makecol(0, 0, 0)); textprintf_ex(buffer, font, 0, 0, makecol(0, 0, 0), -1, "Double buffered (%s)", gfx_driver->name); blit(buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H); if (keypressed()) break; } destroy_bitmap(buffer); /* now create two video memory bitmaps for the page flipping */ page1 = create_video_bitmap(SCREEN_W, SCREEN_H); page2 = create_video_bitmap(SCREEN_W, SCREEN_H); if ((!page1) || (!page2)) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Unable to create two video memory pages\n"); return 1; } active_page = page2; /* do the animation using page flips... */ clear_keybuf(); for (c=-32; c<=SCREEN_W+32; c++) { clear_to_color(active_page, makecol(255, 255, 255)); circlefill(active_page, c, SCREEN_H/2, 32, makecol(0, 0, 0)); textprintf_ex(active_page, font, 0, 0, makecol(0, 0, 0), -1, "Page flipping (%s)", gfx_driver->name); show_video_bitmap(active_page); if (active_page == page1) active_page = page2; else active_page = page1; if (keypressed()) break; } destroy_bitmap(page1); destroy_bitmap(page2); return 0; }