Skip to content

Commit 83986c7

Browse files
docs: #2223 modify README.md file under double-buffer (#2771)
* fix: #2223 modify README.md file under double-buffer add - Real world example - In plain words - Wikipedia says - Programmatic example * fix: #2223 issue. modify readme.md file - adjust title, category, language, and tag
1 parent 2c35b34 commit 83986c7

File tree

1 file changed

+232
-3
lines changed

1 file changed

+232
-3
lines changed

double-buffer/README.md

+232-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,243 @@
1-
---
1+
---
22
title: Double Buffer
33
category: Behavioral
44
language: en
55
tag:
66
- Performance
77
- Game programming
8-
---
8+
---
99

1010
## Intent
11-
Double buffering is a term used to describe a device that has two buffers. The usage of multiple buffers increases the overall throughput of a device and helps prevents bottlenecks. This example shows using double buffer pattern on graphics. It is used to show one image or frame while a separate frame is being buffered to be shown next. This method makes animations and games look more realistic than the same done in a single buffer mode.
11+
Double buffering is a term used to describe a device that has two buffers. The usage of multiple
12+
buffers increases the overall throughput of a device and helps prevents bottlenecks. This example
13+
shows using double buffer pattern on graphics. It is used to show one image or frame while a separate
14+
frame is being buffered to be shown next. This method makes animations and games look more realistic
15+
than the same done in a single buffer mode.
16+
17+
## Explanation
18+
19+
Real world example
20+
> A typical example, and one that every game engine must address, is rendering. When the game draws
21+
> the world the users see, it does so one piece at a time -- the mountains in the distance,
22+
> the rolling hills, the trees, each in its turn. If the user watched the view draw incrementally
23+
> like that, the illusion of a coherent world would be shattered. The scene must update smoothly
24+
> and quickly, displaying a series of complete frames, each appearing instantly. Double buffering solves
25+
> the problem.
26+
27+
In plain words
28+
> It ensures a state that is being rendered correctly while that state is modifying incrementally. It is
29+
> widely used in computer graphics.
30+
31+
Wikipedia says
32+
> In computer science, multiple buffering is the use of more than one buffer to hold a block of data,
33+
> so that a "reader" will see a complete (though perhaps old) version of the data, rather than a
34+
> partially updated version of the data being created by a "writer". It is very commonly used for
35+
> computer display images.
36+
37+
**Programmatic Example**
38+
39+
Buffer interface that assures basic functionalities of a buffer.
40+
41+
```java
42+
/**
43+
* Buffer interface.
44+
*/
45+
public interface Buffer {
46+
47+
/**
48+
* Clear the pixel in (x, y).
49+
*
50+
* @param x X coordinate
51+
* @param y Y coordinate
52+
*/
53+
void clear(int x, int y);
54+
55+
/**
56+
* Draw the pixel in (x, y).
57+
*
58+
* @param x X coordinate
59+
* @param y Y coordinate
60+
*/
61+
void draw(int x, int y);
62+
63+
/**
64+
* Clear all the pixels.
65+
*/
66+
void clearAll();
67+
68+
/**
69+
* Get all the pixels.
70+
*
71+
* @return pixel list
72+
*/
73+
Pixel[] getPixels();
74+
75+
}
76+
```
77+
78+
One of the implementation of Buffer interface.
79+
```java
80+
/**
81+
* FrameBuffer implementation class.
82+
*/
83+
public class FrameBuffer implements Buffer {
84+
85+
public static final int WIDTH = 10;
86+
public static final int HEIGHT = 8;
87+
88+
private final Pixel[] pixels = new Pixel[WIDTH * HEIGHT];
89+
90+
public FrameBuffer() {
91+
clearAll();
92+
}
93+
94+
@Override
95+
public void clear(int x, int y) {
96+
pixels[getIndex(x, y)] = Pixel.WHITE;
97+
}
98+
99+
@Override
100+
public void draw(int x, int y) {
101+
pixels[getIndex(x, y)] = Pixel.BLACK;
102+
}
103+
104+
@Override
105+
public void clearAll() {
106+
Arrays.fill(pixels, Pixel.WHITE);
107+
}
108+
109+
@Override
110+
public Pixel[] getPixels() {
111+
return pixels;
112+
}
113+
114+
private int getIndex(int x, int y) {
115+
return x + WIDTH * y;
116+
}
117+
}
118+
```
119+
120+
```java
121+
/**
122+
* Pixel enum. Each pixel can be white (not drawn) or black (drawn).
123+
*/
124+
public enum Pixel {
125+
126+
WHITE,
127+
BLACK;
128+
}
129+
```
130+
Scene represents the game scene where current buffer has already been rendered.
131+
```java
132+
/**
133+
* Scene class. Render the output frame.
134+
*/
135+
@Slf4j
136+
public class Scene {
137+
138+
private final Buffer[] frameBuffers;
139+
140+
private int current;
141+
142+
private int next;
143+
144+
/**
145+
* Constructor of Scene.
146+
*/
147+
public Scene() {
148+
frameBuffers = new FrameBuffer[2];
149+
frameBuffers[0] = new FrameBuffer();
150+
frameBuffers[1] = new FrameBuffer();
151+
current = 0;
152+
next = 1;
153+
}
154+
155+
/**
156+
* Draw the next frame.
157+
*
158+
* @param coordinateList list of pixels of which the color should be black
159+
*/
160+
public void draw(List<? extends Pair<Integer, Integer>> coordinateList) {
161+
LOGGER.info("Start drawing next frame");
162+
LOGGER.info("Current buffer: " + current + " Next buffer: " + next);
163+
frameBuffers[next].clearAll();
164+
coordinateList.forEach(coordinate -> {
165+
var x = coordinate.getKey();
166+
var y = coordinate.getValue();
167+
frameBuffers[next].draw(x, y);
168+
});
169+
LOGGER.info("Swap current and next buffer");
170+
swap();
171+
LOGGER.info("Finish swapping");
172+
LOGGER.info("Current buffer: " + current + " Next buffer: " + next);
173+
}
174+
175+
public Buffer getBuffer() {
176+
LOGGER.info("Get current buffer: " + current);
177+
return frameBuffers[current];
178+
}
179+
180+
private void swap() {
181+
current = current ^ next;
182+
next = current ^ next;
183+
current = current ^ next;
184+
}
185+
186+
}
187+
```
188+
189+
```java
190+
public static void main(String[] args) {
191+
final var scene = new Scene();
192+
var drawPixels1 = List.of(
193+
new MutablePair<>(1, 1),
194+
new MutablePair<>(5, 6),
195+
new MutablePair<>(3, 2)
196+
);
197+
scene.draw(drawPixels1);
198+
var buffer1 = scene.getBuffer();
199+
printBlackPixelCoordinate(buffer1);
200+
201+
var drawPixels2 = List.of(
202+
new MutablePair<>(3, 7),
203+
new MutablePair<>(6, 1)
204+
);
205+
scene.draw(drawPixels2);
206+
var buffer2 = scene.getBuffer();
207+
printBlackPixelCoordinate(buffer2);
208+
}
209+
210+
private static void printBlackPixelCoordinate(Buffer buffer) {
211+
StringBuilder log = new StringBuilder("Black Pixels: ");
212+
var pixels = buffer.getPixels();
213+
for (var i = 0; i < pixels.length; ++i) {
214+
if (pixels[i] == Pixel.BLACK) {
215+
var y = i / FrameBuffer.WIDTH;
216+
var x = i % FrameBuffer.WIDTH;
217+
log.append(" (").append(x).append(", ").append(y).append(")");
218+
}
219+
}
220+
LOGGER.info(log.toString());
221+
}
222+
```
223+
224+
The console output
225+
```text
226+
[main] INFO com.iluwatar.doublebuffer.Scene - Start drawing next frame
227+
[main] INFO com.iluwatar.doublebuffer.Scene - Current buffer: 0 Next buffer: 1
228+
[main] INFO com.iluwatar.doublebuffer.Scene - Swap current and next buffer
229+
[main] INFO com.iluwatar.doublebuffer.Scene - Finish swapping
230+
[main] INFO com.iluwatar.doublebuffer.Scene - Current buffer: 1 Next buffer: 0
231+
[main] INFO com.iluwatar.doublebuffer.Scene - Get current buffer: 1
232+
[main] INFO com.iluwatar.doublebuffer.App - Black Pixels: (1, 1) (3, 2) (5, 6)
233+
[main] INFO com.iluwatar.doublebuffer.Scene - Start drawing next frame
234+
[main] INFO com.iluwatar.doublebuffer.Scene - Current buffer: 1 Next buffer: 0
235+
[main] INFO com.iluwatar.doublebuffer.Scene - Swap current and next buffer
236+
[main] INFO com.iluwatar.doublebuffer.Scene - Finish swapping
237+
[main] INFO com.iluwatar.doublebuffer.Scene - Current buffer: 0 Next buffer: 1
238+
[main] INFO com.iluwatar.doublebuffer.Scene - Get current buffer: 0
239+
[main] INFO com.iluwatar.doublebuffer.App - Black Pixels: (6, 1) (3, 7)
240+
```
12241

13242
## Class diagram
14243
![alt text](./etc/double-buffer.urm.png "Double Buffer pattern class diagram")

0 commit comments

Comments
 (0)