xref: /haiku/src/tests/kits/game/chart/ChartRender.cpp (revision 050ad934becd6f77ba5b1be449cab65c3809533f)
1 /*
2 
3 	ChartRender.c
4 
5 	by Pierre Raynaud-Richard.
6 
7 	Copyright 1998 Be Incorporated, All Rights Reserved.
8 
9 */
10 
11 /* This file has been designed to be easy to compile as a stand-alone
12    piece of code, allowing you to use advanced intel compiler, even
13    if they are compatible with the whole Be environment. To accomplish
14    that purpose, all declarations were concentrated in ChartRender.h
15    (see that header file for more infos). */
16 #include "ChartRender.h"
17 
18 /* This table provide the horizontal and vertical offset of the matrix
19    of pixel used for drawing stars. This matrix is designed as follow:
20 
21     --  [00] [01] [02] [03]  --
22    [04] [05] [06] [07] [08] [09]
23    [10] [11] [12] [13] [14] [15]
24    [16] [17] [18] [19] [20] [21]
25    [22] [23] [24] [25] [26] [27]
26     --  [28] [29] [30] [31]  --
27 
28    The reference pixel is [12]. */
29 int8	pattern_dh[32] = {
30 		-1, 0, 1, 2,
31 	-2, -1, 0, 1, 2, 3,
32 	-2, -1, 0, 1, 2, 3,
33 	-2, -1, 0, 1, 2, 3,
34 	-2, -1, 0, 1, 2, 3,
35 		-1, 0, 1, 2
36 };
37 
38 int8	pattern_dv[32] = {
39 		-2, -2, -2, -2,
40 	-1, -1, -1, -1, -1, -1,
41 	0,	0,	0,	0,	0,	0,
42 	1,	1,	1,	1,	1,	1,
43 	2,	2,	2,	2,	2,	2,
44 		3,	3,	3,	3
45 };
46 
47 /* Those table contains a preprocessed version of the 32 size of star,
48    represented in the 32 pixels matrix, by alpha-blending density [0 to 7].
49    Those matrix are stored in packed format, as a the list of all pixel
50    whose alpha-blending density is > 0. There is 4 cases because every
51    star can be aligned at half a pixel in both direction (we implement
52    sub-pixel precision and anti-aliasing to reduce the jittering). */
53 static	uint8	pattern_list[4*LEVEL_COUNT][32];
54 static	uint8	pattern_list_count[4*LEVEL_COUNT];
55 static	uint8	pattern_color_offset[4*LEVEL_COUNT][32];
56 /* this table store the alpha-blending level of the center pixel. This
57    is used for size so small that only the center pixel is lighted. */
58 static	uint8	pixel_color_offset[LEVEL_COUNT];
59 
60 /* Those mask are use for fast clipping, to determine which of the 32
61    pixels of the standard star matrix are visible when coming closer
62    from a left, right, top or bottom clipping border. */
63 static uint32	visible_mask_left[6] = {
64 	0xffffffff,
65 	0xffbefbef,
66 	0xef3cf3ce,
67 	0xce38e38c,
68 	0x8c30c308,
69 	0x08208200
70 };
71 
72 static uint32	visible_mask_right[6] = {
73 	0xffffffff,
74 	0xf7df7dff,
75 	0x73cf3cf7,
76 	0x31c71c73,
77 	0x10c30c31,
78 	0x00410410,
79 };
80 
81 static uint32	visible_mask_top[6] = {
82 	0xffffffff,
83 	0xfffffff0,
84 	0xfffffc00,
85 	0xffff0000,
86 	0xffc00000,
87 	0xf0000000
88 };
89 
90 static uint32	visible_mask_bottom[6] = {
91 	0xffffffff,
92 	0x0fffffff,
93 	0x003fffff,
94 	0x0000ffff,
95 	0x000003ff,
96 	0x0000000f
97 };
98 
99 /* Private functions used only internally. */
100 bool		ProjectStar(star *s, geometry *geo);
101 bool		CheckClipping(star *s, buffer *buf, bool reset_clipping);
102 void		DrawStar(star *s, buffer *buf);
103 void		EraseStar(star *s, buffer *buf);
104 
105 
106 /* This function initialise the 32 sizes of anti-aliased star, each one
107    represented in 4 different half-pixel alignement :
108    x : -0.25, y : -0.25
109    x : +0.25, y : -0.25
110    x : -0.25, y : +0.25
111    x : +0.25, y : +0.25 */
InitPatterns()112 void InitPatterns()
113 {
114 	int32		i, j, k, count;
115 	float		radius, x0, y0, x, y, dist, delta;
116 	uint8		color;
117 	uint8		*list, *color_offset;
118 
119 	/* do the 4 half-pixel alignement */
120 	for (j=0; j<4; j++) {
121 		if (j&1) x0 = 1.25;
122 		else	 x0 = 0.75;
123 		if (j&2) y0 = 1.25;
124 		else	 y0 = 0.75;
125 
126 		/* do the 32 sizes */
127 		for (i=0; i<LEVEL_COUNT; i++) {
128 			radius = (float)(i+1) * (2.8/(float)LEVEL_COUNT);
129 			count = 0;
130 			list = pattern_list[j*LEVEL_COUNT + i];
131 			color_offset = pattern_color_offset[j*LEVEL_COUNT + i];
132 
133 			/* scan the 32 pixels of the matrix */
134 			for (k=0; k<32; k++) {
135 				x = ((float)pattern_dh[k] + ROUNDING) - x0;
136 				y = ((float)pattern_dv[k] + ROUNDING) - y0;
137 
138 				dist = sqrt(x*x + y*y);
139 				/* process non source pixel */
140 				if (dist > 0.5) {
141 					delta = radius - dist + 0.5;
142 					if (delta >= 1.0) {
143 						*color_offset++ = 7;
144 						*list++ = k;
145 						count++;
146 					}
147 					else if (delta > 0.5) {
148 						*color_offset++ = (uint8)(7.499 - 16.0 * (1.0 - delta) * (1.0 - delta) + ROUNDING);
149 						*list++ = k;
150 						count++;
151 					}
152 					else if (delta > 0) {
153 						color = (uint8)(16.0 * delta * delta);
154 						if (color > 0) {
155 							*color_offset++ = color;
156 							*list++ = k;
157 							count++;
158 						}
159 					}
160 				}
161 				/* process source pixel (the one containing the center of the star) */
162 				else {
163 					if (radius < 0.25) {
164 						color = (uint8)(32.0 * radius * radius + ROUNDING);
165 						if (color == 0)
166 							color++;
167 					}
168 					else if (radius < 0.75) {
169 						delta = radius + 0.25;
170 						color = (uint8)(7.499 - 22.0 * (1.0 - delta) * (1.0 - delta) + ROUNDING);
171 					}
172 					else
173 						color = 7;
174 					*color_offset++ = color;
175 					*list++ = k;
176 					count++;
177 					pixel_color_offset[i] = color;
178 				}
179 			}
180 			pattern_list_count[j*LEVEL_COUNT + i] = count;
181 		}
182 	}
183 }
184 
185 /* Project a star (s) in the view space of the camera, as described by (geo).
186    Returns true if the star seems to be visible (in the pyramid of vision,
187    closer than the rear plan, farther than the front plan), or false if it's
188    clear that the star isnot visible. */
ProjectStar(star * s,geometry * geo)189 bool ProjectStar(star *s, geometry *geo)
190 {
191 	int32		h_double, v_double, level;
192 	float		x0, y0, z0, x, y, z, inv_z;
193 
194 	/* Calculate the coordinate of the star after doing the cycling operation
195 	   that convert the cube of the starfield in a torus. This ensure that
196 	   get the copy of the star that is the only one likely to be visible from
197 	   the camera. */
198 	x0 = s->x;
199 	if (x0 < geo->cutx)
200 		x0 += 1.0;
201 	y0 = s->y;
202 	if (y0 < geo->cuty)
203 		y0 += 1.0;
204 	z0 = s->z;
205 	if (z0 < geo->cutz)
206 		z0 += 1.0;
207 	/* Translate the star relative to the position of the camera. */
208 	x0 -= geo->x;
209 	y0 -= geo->y;
210 	z0 -= geo->z;
211 
212 	/* Calculate the z coordinate (depth) of the star in the camera referential. */
213 	z = geo->m[0][2]*x0 + geo->m[1][2]*y0 + geo->m[2][2]*z0;
214 
215 	/* Do the rear and front plan clipping */
216 	if ((z < geo->z_min) || (z > geo->z_max))
217 		return false;
218 
219 	/* Calculate the x coordinate (horizontal) of the star in the camera referential. */
220 	x = geo->m[0][0]*x0 + geo->m[1][0]*y0 + geo->m[2][0]*z0;
221 
222 	/* Do the left and right clipping based on the pyramid of vision. */
223 	if ((x < geo->xz_min*z-BORDER_CLIPPING) || (x > geo->xz_max*z+BORDER_CLIPPING))
224 		return false;
225 
226 	/* Calculate the y coordinate (vertical) of the star in the camera referential. */
227 	y = geo->m[0][1]*x0 + geo->m[1][1]*y0 + geo->m[2][1]*z0;
228 
229 	/* Do the top and bottom clipping based on the pyramid of vision. */
230 	if ((y < geo->yz_min*z-BORDER_CLIPPING) || (y > geo->yz_max*z+BORDER_CLIPPING))
231 		return false;
232 
233 	/* Calculate the invert of z, used to project both H and V coordinate. Apply
234 	   the zoom-factor at the same time. The zoom-factor was overscale by a factor
235 	   of two in advance, for the half-pixel precision processing */
236 	inv_z = geo->zoom_factor/z;
237 
238 	/* Calculate the double pixel coordinate in the buffer (in half-pixel). */
239 	h_double = (int32)(x * inv_z + geo->offset_h);
240 	v_double = (int32)(y * inv_z + geo->offset_v);
241 
242 	/* Calculate the light level of the star. We use that little weird function
243 	   to a get faster gradient to black near the rear plan. */
244 	level = (int32)(s->size * (inv_z * geo->z_max_square - z * geo->zoom_factor)) >> 8;
245 	/* The light level can go higher that our max (saturation). */
246 	if (level >= LEVEL_COUNT)
247 		level = LEVEL_COUNT-1;
248 
249 	/* Get the real pixel coordinate in the buffer from the double coordinates */
250 	s->h = h_double >> 1;
251 	s->v = v_double >> 1;
252 	/* Save the light level (used to recognize single pixel star) */
253 	s->level = level;
254 	/* switch between the 4 pattern table use for the 4 half-aligned. */
255 	if ((h_double & 1) == 1) level += LEVEL_COUNT;
256 	if ((v_double & 1) == 1) level += 2*LEVEL_COUNT;
257 	s->pattern_level = level;
258 	return true;
259 }
260 
261 /* Once a star has been projected (using ProjectStar), we need to determine
262    which pixel of the star matrix are visible (if any). This depend of the
263    clipping of the specific buffer you're using. This function will do that
264    for the star (s), in the buffer (buf). It will return false if the star
265    is fully invisible, true if not. The flag reset_clipping is used to
266    reprocess the clipping from scratch, or to just cumulate the new clipping
267    to the last drawing clipping (this is needed when updating the clipping
268    of every stars after changing the clipping region of the buffer). */
CheckClipping(star * s,buffer * buf,bool reset_clipping)269 bool CheckClipping(star *s, buffer *buf, bool reset_clipping)
270 {
271 	int32			delta;
272 	uint32			i, total_visible, tmp_visible;
273 	clipping_rect	box;
274 	clipping_rect	*r;
275 
276 	/* Simple case : the star is represented by only one pixel. */
277 	if (pattern_list_count[s->pattern_level] == 1) {
278 		/* if the pixel is not in the bounding box of the clipping region,
279 		   the star is guarantee to be invisible. */
280 		if ((s->h < buf->clip_bounds.left) ||
281 			(s->h > buf->clip_bounds.right) ||
282 			(s->v < buf->clip_bounds.top) ||
283 			(s->v > buf->clip_bounds.bottom))
284 			goto invisible;
285 		/* if the clipping region contains only one rectangle, then it's
286 		   equal to its bounding box, so no further test are needed. */
287 		if (buf->clip_list_count == 1)
288 			goto visible;
289 		/* In the other case, we need to go through the list of rectangle
290 		   of the clipping region and check if the pixel is in any of those */
291 		r = buf->clip_list;
292 		for (i=0; i<buf->clip_list_count; r++, i++)
293 			if ((s->h >= r->left) &&
294 				(s->h <= r->right) &&
295 				(s->v >= r->top) &&
296 				(s->v <= r->bottom))
297 				goto visible;
298 		/* The pixel is not visible. The star is marked as not drawn. */
299 	invisible:
300 		s->last_draw_offset = INVALID;
301 		return false;
302 	visible:
303 		/* The pixel is visible. The offset at which the star should be draw is
304 		   calculated and store for using by drawing (and erasing later). */
305 		s->last_draw_offset = s->v * buf->bytes_per_row + s->h * buf->bytes_per_pixel;
306 		return true;
307 	}
308 	/* Complex case : the star is represented by more than one pixel. */
309 	else {
310 		/* Calculate the box the bounding box of the matrix of 32 pixels used
311 		   to represent the star, called box. */
312 		box.left = s->h - 2;
313 		box.right = s->h + 3;
314 		box.top = s->v - 2;
315 		box.bottom = s->v + 3;
316 
317 		/* Check if the box is fully outside of the bounding box of the clipping
318 		   region. That woudl guarantee that the star is invisible. */
319 		if ((box.right < buf->clip_bounds.left) ||
320 			(box.left > buf->clip_bounds.right) ||
321 			(box.bottom < buf->clip_bounds.top) ||
322 			(box.top > buf->clip_bounds.bottom))
323 			goto invisible_pat;
324 
325 		/* Now, we have to go through the list of rectangle of the clipping region
326 		   and cumulate the mask of the star matrix pixels that are visible in any
327 		   of those rectangle. At start time, the mask is empty. */
328 		total_visible = 0;
329 		r = buf->clip_list;
330 		for (i=0; i<buf->clip_list_count; r++, i++) {
331 			/* When reseting the clipping, all pixel of the matrix are tested. In
332 			   the other mode, only the pixel previously visible are tested (as we
333 			   want to know which one of the previously drawn pixel still need to
334 			   be erased. */
335 			if (reset_clipping)
336 				tmp_visible = 0xffffffff;
337 			else
338 				tmp_visible = s->last_draw_pattern;
339 
340 			/* Calculate the clipping on the left side of the rectangle. */
341 			delta = r->left-box.left;
342 			if (delta > 5)
343 				continue;
344 			if (delta > 0)
345 				tmp_visible &= visible_mask_left[delta];
346 
347 			/* Calculate the clipping on the right side of the rectangle. */
348 			delta = box.right-r->right;
349 			if (delta > 5)
350 				continue;
351 			if (delta > 0)
352 				tmp_visible &= visible_mask_right[delta];
353 
354 			/* Calculate the clipping on the top side of the rectangle. */
355 			delta = r->top-box.top;
356 			if (delta > 5)
357 				continue;
358 			if (delta > 0)
359 				tmp_visible &= visible_mask_top[delta];
360 
361 			/* Calculate the clipping on the bottom side of the rectangle. */
362 			delta = box.bottom-r->bottom;
363 			if (delta > 5)
364 				continue;
365 			if (delta > 0)
366 				tmp_visible &= visible_mask_bottom[delta];
367 
368 			/* Pixel of the matrix not clipped out at that point are visible
369 			   inside this rectangle of the clipping region. We need to add
370 			   them to the mask of currently known visible pixel. */
371 			total_visible |= tmp_visible;
372 			/* If all pixel of the matrix are already visible, no need to continue
373 			   further. */
374 			if (total_visible == 0xffffffff)
375 				goto visible_pat;
376 		}
377 		/* If no pixel are visible, then we know... */
378 		if (total_visible != 0)
379 			goto visible_pat;
380 
381 		/* The star is not visible. It's marked as not drawn. */
382 	invisible_pat:
383 		s->last_draw_offset = INVALID;
384 		return false;
385 	visible_pat:
386 		/* The star is partially visible. The offset at which the star should be
387 		   draw is calculated and store for using by drawing (and erasing later).
388 		   The mask of which pixel of the matrix are visible is store for use
389 		   at drawing and erasing time. */
390 		s->last_draw_offset = s->v * buf->bytes_per_row + s->h * buf->bytes_per_pixel;
391 		s->last_draw_pattern = total_visible;
392 		return true;
393 	}
394 }
395 
396 /* After calling ProjectStar and CheckClipping, we're finally ready to
397    draw the star in its destination buffer. So let's do it... */
DrawStar(star * s,buffer * buf)398 void DrawStar(star *s, buffer *buf)
399 {
400 	int32		i, index, count;
401 	uint8		*draw8;
402 	uint16		*draw16;
403 	uint32		*draw32;
404 	uint32		*colors;
405 	uint8		*pat_list;
406 	uint8		*pat_color_offset;
407 
408 	/* Simple case : the star is represented by only one pixel. */
409 	count = pattern_list_count[s->pattern_level];
410 	if (count == 1) {
411 		/* Depending the depth mode of the drawing buffer... */
412 		switch (buf->depth_mode) {
413 		case PIXEL_1_BYTE :
414 			/* Get the pointer to the address we want to draw to... */
415 			draw8 = (uint8*)((char*)buf->bits + s->last_draw_offset);
416 			/* ... and write the color pattern we want to use depending of
417 			   the lighting level and the color scheme of the star. */
418 			*draw8 = buf->colors[s->color_type][pixel_color_offset[s->level]];
419 			break;
420 		case PIXEL_2_BYTES :
421 			/* Same thing for 2 bytes mode */
422 			draw16 = (uint16*)((char*)buf->bits + s->last_draw_offset);
423 			*draw16 = buf->colors[s->color_type][pixel_color_offset[s->level]];
424 			break;
425 		case PIXEL_4_BYTES :
426 			/* Same thing for 4 bytes mode */
427 			draw32 = (uint32*)((char*)buf->bits + s->last_draw_offset);
428 			*draw32 = buf->colors[s->color_type][pixel_color_offset[s->level]];
429 			break;
430 		}
431 	}
432 	/* Complex case : the star is represented by a multiple pixels. */
433 	else {
434 		/* Pointer to the color table used depending the color scheme of
435 		   the star. */
436 		colors = buf->colors[s->color_type];
437 		pat_list = pattern_list[s->pattern_level];
438 		pat_color_offset = pattern_color_offset[s->pattern_level];
439 
440 		/* Plot all pixel used to represent the star one after one... */
441 		for (i=0; i<count; i++) {
442 			/* This is the index of the pixel in the matrix */
443 			index = pat_list[i];
444 			/* Check if this pixel is visible (using the result of the clipping) */
445 			if (s->last_draw_pattern & (1<<index)) {
446 				switch (buf->depth_mode) {
447 				case PIXEL_1_BYTE :
448 					/* Get the pointer to the address we want to draw to... */
449 					draw8 = (uint8*)((char*)buf->pattern_bits[index] + s->last_draw_offset);
450 					/* ... and write the color pattern we want to use depending of
451 					   the lighting level and the color scheme of the star. */
452 					*draw8 = colors[pat_color_offset[i]];
453 					break;
454 				case PIXEL_2_BYTES :
455 					/* Same thing for 2 bytes mode */
456 					draw16 = (uint16*)((char*)buf->pattern_bits[index] + s->last_draw_offset);
457 					*draw16 = colors[pat_color_offset[i]];
458 					break;
459 				case PIXEL_4_BYTES :
460 					/* Same thing for 4 bytes mode */
461 					draw32 = (uint32*)((char*)buf->pattern_bits[index] + s->last_draw_offset);
462 					*draw32 = colors[pat_color_offset[i]];
463 					break;
464 				}
465 			}
466 		}
467 	}
468 }
469 
470 /* Before redrawing a star at its new position, we need to erase what we draw
471    at the previous frame... */
EraseStar(star * s,buffer * buf)472 void EraseStar(star *s, buffer *buf)
473 {
474 	int32		i, index, count;
475 	uint8		*draw8;
476 	uint16		*draw16;
477 	uint32		*draw32;
478 	uint32		back_color;
479 	uint8		*pat_list;
480 
481 	/* Color pattern we use to erase the buffer. */
482 	back_color = buf->back_color;
483 
484 	/* Simple case : the star is represented by only one pixel. */
485 	count = pattern_list_count[s->pattern_level];
486 	if (count == 1) {
487 		/* Depending the depth mode of the drawing buffer... */
488 		switch (buf->depth_mode) {
489 		case PIXEL_1_BYTE :
490 			/* Get the pointer to the address we want to erase... */
491 			draw8 = (uint8*)((char*)buf->bits + s->last_draw_offset);
492 			/* ... and write the background color pattern. */
493 			*draw8 = back_color;
494 			break;
495 		case PIXEL_2_BYTES :
496 			/* Same thing for 2 bytes mode */
497 			draw16 = (uint16*)((char*)buf->bits + s->last_draw_offset);
498 			*draw16 = back_color;
499 			break;
500 		case PIXEL_4_BYTES :
501 			/* Same thing for 4 bytes mode */
502 			draw32 = (uint32*)((char*)buf->bits + s->last_draw_offset);
503 			*draw32 = back_color;
504 			break;
505 		}
506 	}
507 	/* Complex case : the star is represented by a multiple pixels. */
508 	else {
509 		pat_list = pattern_list[s->pattern_level];
510 
511 		/* Erase all pixel used to represent the star one after one... */
512 		for (i=0; i<count; i++) {
513 			index = pat_list[i];
514 			/* Check if this pixel is visible (using the result of the clipping) */
515 			if (s->last_draw_pattern & (1<<index)) {
516 				switch (buf->depth_mode) {
517 				case PIXEL_1_BYTE :
518 					/* Get the pointer to the address we want to draw to... */
519 					draw8 = (uint8*)((char*)buf->pattern_bits[index] + s->last_draw_offset);
520 					/* ... and write the background color pattern. */
521 					*draw8 = back_color;
522 					break;
523 				case PIXEL_2_BYTES :
524 					/* Same thing for 2 bytes mode */
525 					draw16 = (uint16*)((char*)buf->pattern_bits[index] + s->last_draw_offset);
526 					*draw16 = back_color;
527 					break;
528 				case PIXEL_4_BYTES :
529 					/* Same thing for 4 bytes mode */
530 					draw32 = (uint32*)((char*)buf->pattern_bits[index] + s->last_draw_offset);
531 					*draw32 = back_color;
532 					break;
533 				}
534 			}
535 		}
536 	}
537 }
538 
539 /* This function do the transition from previous state to the new state
540    as described in (geo), in the buffer (buf), for the list of star (sp) */
RefreshStarPacket(buffer * buf,star_packet * sp,geometry * geo)541 void RefreshStarPacket(buffer *buf, star_packet *sp, geometry *geo)
542 {
543 	int32			i, min_count;
544 	star			*s;
545 
546 	// TODO: For some reason, when selecting the "2 threads" option under vmware,
547 	// some weird timing calculations finish with setting the star packet count to
548 	// a negative number. This screws all the next calculations, and the animation
549 	// then comes to a stop.
550 	sp->count = max_c(sp->count, 0);
551 
552 	/* Calculate the number of stars that were process during the
553 	   previous frame and still need to be process for that frame. */
554 	min_count = sp->erase_count;
555 	if (sp->count < min_count)
556 		min_count = sp->count;
557 
558 	s = sp->list;
559 
560 	/* For all those star... */
561 	for (i=0; i<min_count; s++, i++) {
562 		/* ... erase them if necessary, ... */
563 		if (s->last_draw_offset != INVALID)
564 			EraseStar(s, buf);
565 		/* ... project them at their new position, ... */
566 		if (ProjectStar(s, geo)) {
567 			/* ... check the clipping of the buffer if the star are in
568 			   the pyramid of vision, ... */
569 			if (CheckClipping(s, buf, true))
570 				/* ... and draw them if they're really visible. */
571 				DrawStar(s, buf);
572 		}
573 		/* ... or mark them as invisible if they're not in the pyramid
574 		   of vision. */
575 		else
576 			s->last_draw_offset = INVALID;
577 	}
578 
579 	/* For star that were process at the previous frame but that we don't
580 	   want to process anymore, we just need to erase them. */
581 	for (; i<sp->erase_count; s++, i++) {
582 		if (s->last_draw_offset != INVALID)
583 			EraseStar(s, buf);
584 	}
585 
586 	/* For star that were not process before, but are now, we just need to
587 	   go through the projection, clipping and drawing steps. */
588 	for (; i<sp->count; s++, i++) {
589 		if (ProjectStar(s, geo)) {
590 			if (CheckClipping(s, buf, true))
591 				DrawStar(s, buf);
592 		}
593 		else
594 			s->last_draw_offset = INVALID;
595 	}
596 }
597 
598 /* Update the clipping visibility of all star of the list (sp) to
599   respect the new clipping defined for the buffer (buf). */
RefreshClipping(buffer * buf,star_packet * sp)600 void RefreshClipping(buffer *buf, star_packet *sp)
601 {
602 	star		*s;
603 	int32		i;
604 
605 	s = sp->list;
606 	for (i=0; i<sp->erase_count; s++, i++) {
607 		if (s->last_draw_offset != INVALID)
608 			CheckClipping(s, buf, false);
609 	}
610 }
611 
612 
613