Triple Buffering in Full Screen
Kevin Epps

I've played other peoples examples using triple buffering in fullscreen mode, but I c an't seem to play mine in fullscreen mode. The exe will play, but once it get's to the function that uses triple buffering, it shuts down.

Here's the function (For those of you perfectionists out there: My code is a little messy and CAN be cleaned up, but I don't really do all of that until the function does what I want it to do. So please, don't waste my time telling me how I can clean it up or scolding me because it isn't clean. Thanks..)

#SelectExpand
1///FOREST STAGE FUNCTION/////////// 2 3void forest_stage() 4{ 5 bgm bg_music; 6 Blue_ninja ninja[5]; 7 Layer layer[9]; 8 bg_music.init(BMG_BAMBOO, 0, -1, 1); 9 exit_buffer = create_video_bitmap(256, 192); 10 exit_font = load_font("exit_font.bmp", NULL, 0); 11 exit_font_small = load_font("exit_font_small.bmp", NULL, 0); 12 bool run = true; 13 bool draw=false; 14 char buf[4096]; 15 // between logic updates 16 int fpsCount = 0; 17 speed_counter = 0; 18 //BITMAP *test_pic; 19 int stage_frame_counter = 0; 20 temp = load_png("keiku01f.png", NULL); 21 bg = load_bitmap("forest-6.gif", NULL); 22 grass[0] = load_png("grass_1_2.png", NULL); 23 grass[1] = load_png("grass_2_2.png", NULL); 24 grass[2] = load_png("grass_3_2.png", NULL); 25 grass[3] = load_png("grass_upper_2.png", NULL); 26 foreground = load_bitmap("foreground-2.gif", NULL); 27 exit_back = load_bitmap("exit_back.gif", NULL); 28 //test_pic = load_png("finalsamurair.png", NULL); 29 front_trees = load_png("front_trees_2.png", NULL); 30 31 layer[0].init(bg, 0, 0.2); 32 layer[1].init(foreground, 0, 0.4); 33 layer[2].init(grass[3], 335, 0.6); 34 layer[3].init(grass[0], 355, 0.8); 35 //layer[4].init(map_layer, 0, 1.0); 36 layer[5].init(grass[0], 419, 1.2); 37 layer[6].init(grass[1], 429, 1.4); 38 layer[7].init(grass[2], 439, 1.6); 39 layer[8].init(front_trees, 0, 1.8); 40 destroy_bitmap(bg); 41 destroy_bitmap(foreground); 42 destroy_bitmap(front_trees); 43 destroy_bitmap(grass[0]); 44 destroy_bitmap(grass[1]); 45 destroy_bitmap(grass[2]); 46 destroy_bitmap(grass[3]); 47 player.init(temp, 88); 48 //enemy.init(temp_two, 88); 49 //for(int o; o < 5; o++) 50 //{ 51 ninja[0].init(4, 4, 4, 100, 285); 52 ninja[1].init(4, 4, 4, 200, 285); 53 ninja[2].init(4, 4, 4, 300, 285); 54 ninja[3].init(4, 4, 4, 500, 265); 55 ninja[4].init(4, 4, 4, 800, 265); 56 //} 57 Screen background; 58 //set_palette(pal); 59 int button = 0; 60 //load the map 61 if (MapLoad("sample-5.fmp")) exit(0); 62 //buffer = create_video_bitmap (WIDTH, HEIGHT); 63 clear(buffer); 64 bg_music.play(); 65 //main loop 66 while (run) 67 { 68 while(speed_counter!=0) 69 { 70 71 //if (timer.check_timer(120) > 0) 72 //{ 73 sprintf(buf, "P: %d, C: %d, N: %d, FPS: %d", button, (int)((int)(player.x - (int)(camera.x*layer[2].speed))*layer[2].speed), ninja[4].x, FpsTimer); 74 player.do_action(); 75 player.key_presser(); 76 player.scroll(); 77 ninja[0].do_action(); 78 ninja[0].determine_direction(player.x); 79 ninja[0].start_strike(player.x, 1); 80 ninja[1].do_action(); 81 ninja[1].determine_direction(player.x); 82 ninja[1].start_strike(player.x, 1); 83 ninja[2].do_action(); 84 ninja[2].determine_direction(player.x); 85 ninja[2].start_strike(player.x, 1); 86 ninja[3].do_action(); 87 ninja[3].determine_direction(player.x); 88 ninja[3].start_strike(player.x, 0); 89 ninja[4].do_action(); 90 ninja[4].determine_direction((((int)(player.x*layer[2].speed)) + ((int)(camera.x*layer[2].speed)))); 91 ninja[4].start_strike((((int)(player.x*layer[2].speed)) + ((int)(camera.x*layer[2].speed))), 0); 92 //enemy.do_action(); 93 //enemy.key_presser(); 94 //enemy.scroll(); 95 if(key[KEY_F]) 96 { 97 if(!bg_music.fade_out(0, 10)) 98 { 99 bg_music.fade_out(0, 10); 100 } 101 } 102 if(key[KEY_G]) 103 { 104 if(!bg_music.fade_in(255, 10)) 105 { 106 bg_music.fade_in(255, 10); 107 } 108 } 109 if(player.x < 5) 110 { 111 player.x = 5; 112 } 113 if(player.x > 6340) 114 { 115 player.x = 6340; 116 } 117 move_camera(6400, 480); 118 draw=true; 119 speed_counter--; 120 } 121 //This is the closing bracket for the (speed_counter > 0) test 122 //blur(bg, 5); 123 //clear_to_color(buffer, makecol(255,0,255)); 124 //draw_sprite(blurbuffer, bg, -player.mapxoff, -player.mapyoff); 125 //background.draw(bg, -player.mapxoff, -); 126 //background.add_layer(bg, 0, , -player.mapyoff); 127 //if (needToRedraw) { 128 if(draw) { 129 BeginDrawing(); 130 131 // draw, pard'ner!! 132 clear(buffer); 133 masked_blit(layer[0].sprite, buffer, 0, 0, -((int)(camera.x*layer[0].speed)%layer[0].sprite->w), layer[0].y - camera.y*layer[0].speed, layer[0].sprite->w, layer[0].sprite->h); 134 masked_blit(layer[0].sprite, buffer, 0, 0, layer[0].sprite->w - ((int)(camera.x*layer[0].speed)%layer[0].sprite->w), layer[0].y - camera.y*layer[0].speed, layer[0].sprite->w, layer[0].sprite->h); 135 masked_blit(layer[1].sprite, buffer, 0, 0, -((int)(camera.x*layer[1].speed)%layer[1].sprite->w), layer[1].y - camera.y*layer[1].speed, layer[1].sprite->w, layer[1].sprite->h); 136 masked_blit(layer[1].sprite, buffer, 0, 0, layer[1].sprite->w - ((int)(camera.x*layer[1].speed)%layer[1].sprite->w), layer[1].y - camera.y*layer[1].speed, layer[1].sprite->w, layer[1].sprite->h); 137 ninja[3].draw(buffer, ((int)(camera.x*layer[2].speed)), camera.y); 138 ninja[4].draw(buffer, ((int)(camera.x*layer[2].speed)), camera.y); 139 masked_blit(layer[2].sprite, buffer, 0, 0, -((int)(camera.x*layer[2].speed)%layer[2].sprite->w), layer[2].y - camera.y*layer[2].speed, layer[2].sprite->w, layer[2].sprite->h); 140 masked_blit(layer[2].sprite, buffer, 0, 0, layer[2].sprite->w - ((int)(camera.x*layer[2].speed)%layer[2].sprite->w), layer[2].y - camera.y*layer[2].speed, layer[2].sprite->w, layer[2].sprite->h); 141 ninja[0].draw(buffer, ((int)(camera.x*layer[3].speed)), camera.y); 142 ninja[1].draw(buffer, ((int)(camera.x*layer[3].speed)), camera.y); 143 ninja[2].draw(buffer, ((int)(camera.x*layer[3].speed)), camera.y); 144 145 masked_blit(layer[3].sprite, buffer, 0, 0, -((int)(camera.x*layer[3].speed)%layer[3].sprite->w), layer[3].y - camera.y*layer[3].speed, layer[3].sprite->w, layer[3].sprite->h); 146 147 masked_blit(layer[3].sprite, buffer, 0, 0, layer[3].sprite->w - ((int)(camera.x*layer[3].speed)%layer[3].sprite->w), layer[3].y - camera.y*layer[3].speed, layer[3].sprite->w, layer[3].sprite->h); 148 149 MapDrawBGT(buffer, camera.x, camera.y, 0, 0, WIDTH-1, HEIGHT-1); 150 //draw foreground tiles 151 MapDrawFG(buffer, camera.x, camera.y, 0, 0, WIDTH-1, HEIGHT-1, 0); 152 player.draw(buffer, camera.x, camera.y); 153 masked_blit(layer[5].sprite, buffer, 0, 0, -((int)(camera.x*layer[5].speed)%layer[5].sprite->w), layer[5].y - camera.y*layer[5].speed, layer[5].sprite->w, layer[5].sprite->h); 154 masked_blit(layer[5].sprite, buffer, 0, 0, layer[5].sprite->w - ((int)(camera.x*layer[5].speed)%layer[5].sprite->w), layer[5].y - camera.y*layer[5].speed, layer[5].sprite->w, layer[5].sprite->h); 155 masked_blit(layer[6].sprite, buffer, 0, 0, -((int)(camera.x*layer[6].speed)%layer[6].sprite->w), layer[6].y - camera.y*layer[6].speed, layer[6].sprite->w, layer[6].sprite->h); 156 masked_blit(layer[6].sprite, buffer, 0, 0, layer[6].sprite->w - ((int)(camera.x*layer[6].speed)%layer[6].sprite->w), layer[6].y - camera.y*layer[6].speed, layer[6].sprite->w, layer[6].sprite->h); 157 masked_blit(layer[7].sprite, buffer, 0, 0, -((int)(camera.x*layer[7].speed)%layer[7].sprite->w), layer[7].y - camera.y*layer[7].speed, layer[7].sprite->w, layer[7].sprite->h); 158 masked_blit(layer[7].sprite, buffer, 0, 0, layer[7].sprite->w - ((int)(camera.x*layer[7].speed)%layer[7].sprite->w), layer[7].y - camera.y*layer[7].speed, layer[7].sprite->w, layer[7].sprite->h); 159 masked_blit(layer[8].sprite, buffer, 0, 0, -((int)(camera.x*layer[8].speed)%layer[8].sprite->w), layer[8].y - camera.y*layer[8].speed, layer[8].sprite->w, layer[8].sprite->h); 160 masked_blit(layer[8].sprite, buffer, 0, 0, layer[8].sprite->w - ((int)(camera.x*layer[8].speed)%layer[8].sprite->w), layer[8].y - camera.y*layer[8].speed, layer[8].sprite->w, layer[8].sprite->h); 161 textprintf_ex(buffer, font, 200, 100, makecol(255,255,255), makecol(0,0,0), buf); 162 //draw_sprite(buffer, test_pic, 0, 0); 163 EndDrawing(); 164 xframe_count++; 165 while(speed_counter == 0){rest(1);} 166 draw=false; 167 } 168 169 } //while 170 171 for(int k = 0; k < 9; k++) 172 { 173 layer[k].kill(); 174 } 175}

BeginDrawing() function:

void BeginDrawing()
{
        acquire_bitmap(buffer);
}

EndDrawing() function:

#SelectExpand
1void EndDrawing() 2{ 3 release_bitmap(buffer); 4 5 switch(videoupdatemethod) 6 { 7 case DOUBLEBUFFERING: 8 blit(buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H); 9 break; 10 11 case PAGEFLIPPING: 12 show_video_bitmap(buffer); 13 14 if(buffer == pages[0]) 15 buffer = pages[1]; 16 else 17 buffer = pages[0]; 18 break; 19 20 case TRIPLEBUFFERING: 21 do { } while (poll_scroll()); 22 23 request_video_bitmap(buffer); 24 25 if(buffer == pages[0]) 26 { 27 buffer = pages[1]; 28 } 29 else if(buffer == pages[1]) 30 { 31 buffer = pages[2]; 32 } 33 else 34 { 35 buffer = pages[0]; 36 } 37 break; 38 39 default: 40 41 break; 42 } 43}

Is there anything that I'm doing wrong in my forest_stage function that fullscreen doesn't like?

Richard Phipps

Search on the forums for Chris Barrys 'screen update' code. That lets you chose double buffering, page flipping, or triple buffering and returns error codes if it fails. Maybe that will help you.

Neil Walker

Have you checked to see if triple buffering is working? what you might also find useful is trying to store your sprites as video memory too. Anyway, you didn't post your code for your graphics initialisation, but you should do something like this, what it does is determine what mode I want and tries fallbacks if it can't, e.g. if it can't get triple then it tries paging, etc. Note the triple buffering code first sees if it is available and if not it attempts to kick-start it.

1 switch(GameConfiguration->CapsGraphics.GraphicsMode)
2 {
3 case MODE_TRIPLE:
4 if(gfx_capabilities & GFX_CAN_TRIPLE_BUFFER) CanDoIt=true;
5 else CanDoIt=(enable_triple_buffer()==0);
6 
7 if(CanDoIt)
8 {
9 Configuration::LogEntry("System Wanted and can do Triple buffering");
10 BitmapPages[0]=create_video_bitmap(GameConfiguration->CapsGraphics.ScrWidth,GameConfiguration->CapsGraphics.ScrHeight);
11 BitmapPages[1]=create_video_bitmap(GameConfiguration->CapsGraphics.ScrWidth,GameConfiguration->CapsGraphics.ScrHeight);
12 BitmapPages[2]=create_video_bitmap(GameConfiguration->CapsGraphics.ScrWidth,GameConfiguration->CapsGraphics.ScrHeight);
13 if(!BitmapPages[0] || !BitmapPages[1] || !BitmapPages[2])
14 {
15 Configuration::LogEntry("Failed creating the 3 video bitmaps for Triple Buffering. Trying Paging");
16 if(BitmapPages[0]) destroy_bitmap(BitmapPages[0]);
17 if(BitmapPages[1]) destroy_bitmap(BitmapPages[1]);
18 if(BitmapPages[2]) destroy_bitmap(BitmapPages[2]);
19 BitmapPages[0]=BitmapPages[1]=BitmapPages[2]=NULL;
20 //then fall through to paged
21 CanDoIt=false;
22 }
23 else
24 {
25 clear_to_color(BitmapPages[0],makecol(0,0,0));
26 clear_to_color(BitmapPages[1],makecol(0,0,0));
27 clear_to_color(BitmapPages[2],makecol(0,0,0));
28 Configuration::LogEntry("Got Triple Buffering");
29 GameConfiguration->CapsActualSystem.GraphicsMode=MODE_TRIPLE;
30 }
31 }
32 else
33 Configuration::LogEntry("Wanted Triple but System reported it cannot. Trying Paged");
34 
35 if(CanDoIt)
36 break;
37 case MODE_PAGED:
38 BitmapPages[0]=create_video_bitmap(GameConfiguration->CapsGraphics.ScrWidth,GameConfiguration->CapsGraphics.ScrHeight);
39 BitmapPages[1]=create_video_bitmap(GameConfiguration->CapsGraphics.ScrWidth,GameConfiguration->CapsGraphics.ScrHeight);
40 BitmapPages[2]=NULL;
41 if(!BitmapPages[0] || !BitmapPages[1])
42 {
43 Configuration::LogEntry("Failed creating the 2 video bitmaps for Paged Buffering. Trying Double");
44 if(BitmapPages[0]) destroy_bitmap(BitmapPages[0]);
45 if(BitmapPages[1]) destroy_bitmap(BitmapPages[1]);
46 BitmapPages[0]=BitmapPages[1]=BitmapPages[2]=NULL;
47 //then fall through to system
48 CanDoIt=false;
49 }
50 else
51 {
52 clear_to_color(BitmapPages[0],makecol(0,0,0));
53 clear_to_color(BitmapPages[1],makecol(0,0,0));
54 Configuration::LogEntry("Got Paged Buffering");
55 GameConfiguration->CapsActualSystem.GraphicsMode=MODE_PAGED;
56 CanDoIt=true;
57 }
58 if(CanDoIt)
59 break;
60 case MODE_SYSTEMDOUBLE:
61 BitmapPages[0]=create_system_bitmap(GameConfiguration->CapsGraphics.ScrWidth,GameConfiguration->CapsGraphics.ScrHeight);
62 BitmapPages[1]=BitmapPages[2]=NULL;
63 //should always be a bitmap as system falls back to memory bitmap if not available
64 if(BitmapPages[0])
65 {
66 if(is_system_bitmap(BitmapPages[0]))
67 {
68 GameConfiguration->CapsActualSystem.GraphicsMode=MODE_SYSTEMDOUBLE;
69 clear_to_color(BitmapPages[0],makecol(0,0,0));
70 Configuration::LogEntry("Got System Double Buffering.");
71 CanDoIt=true;
72 break;
73 }
74 else
75 {
76 destroy_bitmap(BitmapPages[0]);
77 BitmapPages[0]=NULL;
78 Configuration::LogEntry("Failed creating System bitmap. Trying Double");
79 CanDoIt=false;
80 }
81 }
82 else
83 Configuration::LogEntry("Failed to get a System, trying double");
84 default:
85 //double - DR needs to be done by user
86 Configuration::LogEntry("Using double buffering");
87 BitmapPages[0]=create_bitmap(GameConfiguration->CapsGraphics.ScrWidth,GameConfiguration->CapsGraphics.ScrHeight);
88 if(BitmapPages[0])
89 {
90 GameConfiguration->CapsActualSystem.GraphicsMode=MODE_DOUBLE;
91 Configuration::LogEntry("Got Double Buffering");
92 CanDoIt=true;
93 }
94 else
95 Configuration::LogEntry("Failed to get a Double Buffer. Crikey!");
96 }

then in my drawing loop I do something like this:

1 //set correct buffer
2 //double/system is always pointing at one and only page
3 //need to modify if using dirty.
4 if(this->GameConfiguration->CapsActualSystem.GraphicsMode<=MODE_SYSTEMDOUBLE)
5 {
6 //double buffering to either a memory or a system bitmap
7 if(GameConfiguration->CapsGraphics.VSync) vsync();
8 blit(DrawingSurface, screen, 0, 0, 0, 0,GameConfiguration->CapsGraphics.ScrWidth,GameConfiguration->CapsGraphics.ScrHeight);
9 }
10 else
11 {
12 //release_bitmap(DrawingSurface);
13 if(this->GameConfiguration->CapsActualSystem.GraphicsMode==MODE_PAGED)
14 {
15 show_video_bitmap(BitmapPages[BitmapPagesActive]);
16 //show_video_bitmap(DrawingSurface);
17 BitmapPagesActive=1-BitmapPagesActive;
18 DrawingSurface=BitmapPages[BitmapPagesActive];
19 }
20 else
21 {
22 //triple
23 do{}while(poll_scroll());
24 request_video_bitmap(BitmapPages[BitmapPagesActive]);
25 //request_video_bitmap(DrawingSurface);
26 BitmapPagesActive=(BitmapPagesActive+1)%3;
27 DrawingSurface=BitmapPages[BitmapPagesActive];
28 }
29 }

So when I'm drawing my sprites and stuff before I call this code all I need worry about is blitting to 'DrawingSurface' and it does it, regardless of whether I'm using triple, paging, double, system double.

e.g. draw_sprite(DrawingSurface,somesprite,x,y);
The params may be the wrong way round, but you get the picture :)

the 'BitmapPagesActive' is just an int that tells me which is the currently active drawing page. It is an index to the array of bitmaps created at top.

Thread #564396. Printed from Allegro.cc