1 /* This code is (C) AllegroGL contributors, and double licensed under
2  * the GPL and zlib licenses. See gpl.txt or zlib.txt for details.
3  */
4 /** \file glvtable.c
5   * \brief Allegro->OpenGL conversion vtable.
6   */
7 
8 #include <string.h>
9 
10 #include <allegro.h>
11 
12 #ifdef ALLEGRO_WINDOWS
13 #include <winalleg.h>
14 #endif
15 
16 #include "alleggl.h"
17 #include "allglint.h"
18 #include "glvtable.h"
19 #include <allegro/internal/aintern.h>
20 #ifdef ALLEGRO_MACOSX
21 #include <OpenGL/glu.h>
22 #else
23 #include <GL/glu.h>
24 #endif
25 
26 
27 static GFX_VTABLE allegro_gl_screen_vtable;
28 static GLuint __allegro_gl_pool_texture = 0;
29 
30 static GLuint __allegro_gl_dummy_texture = 0; /* For ATI Rage Pro */
31 
32 static int __agl_owning_drawing_pattern_tex = FALSE;
33 GLuint __agl_drawing_pattern_tex = 0;
34 BITMAP *__agl_drawing_pattern_bmp = 0;
35 static int __agl_drawing_mode = DRAW_MODE_SOLID;
36 
37 
38 /** \defgroup glvtable Allegro Graphics Driver
39  *  These functions are used to implement Allegro function over an
40  *  OpenGL screen.
41  *
42  *  Keep in mind that some restictions mentioned in Allegro docs about video
43  *  bitmaps and the screen do not apply when using AllegroGL GFX driver. Namely:
44  *  - Reading from video bitmaps is just as fast as reading from memory bitmaps.
45  *  - Doing translucent/transparent drawing on the screen can be very fast if
46  *    the source is a video bitmap.
47  *  - Drawing from video bitmap to a video bitmap will be pretty fast on modern
48  *    GFX cards with appropiate drivers installed.
49  *  - There are dozen of places in the Allegro docs where it says that a memory
50  *    bitmap must be used (drawing_mode(), polygon3d(), stretch_sprite() etc.).
51  *    This doesn't apply when AllegroGL is used. You can also use video bitmaps
52  *    and it will be quite fast.
53  *
54  *  \{
55  */
56 
57 
58 /* Computes the next power of two if the number wasn't a power of two to start
59  * with. Ref: http://bob.allegronetwork.com/prog/tricks.html#roundtonextpowerof2
60  */
__allegro_gl_make_power_of_2(int x)61 int __allegro_gl_make_power_of_2(int x) {
62 	x--;
63 	x |= (x >> 1);
64 	x |= (x >> 2);
65 	x |= (x >> 4);
66 	x |= (x >> 8);
67 	x |= (x >> 16);
68 	x++;
69 	return x;
70 }
71 
72 
73 
74 /* allegro_gl_drawing_mode (GFX_DRIVER vtable entry):
75  * Sets the drawing mode. Same implementation to all GFX vtables.
76  */
allegro_gl_drawing_mode(void)77 void allegro_gl_drawing_mode(void) {
78 	if (__agl_drawing_mode == _drawing_mode)
79 		return;
80 
81 	switch (__agl_drawing_mode) {
82 		case DRAW_MODE_TRANS:
83 			glDisable(GL_BLEND);
84 		break;
85 		case DRAW_MODE_XOR:
86 			glDisable(GL_COLOR_LOGIC_OP);
87 		break;
88 		case DRAW_MODE_COPY_PATTERN:
89 			glDisable(GL_TEXTURE_2D);
90 			glBindTexture(GL_TEXTURE_2D, 0);
91 			if (__agl_owning_drawing_pattern_tex && __agl_drawing_pattern_tex)
92 				glDeleteTextures(1, &__agl_drawing_pattern_tex);
93 			__agl_drawing_pattern_tex = 0;
94 			__agl_drawing_pattern_bmp = 0;
95 		break;
96 	}
97 
98 	__agl_drawing_mode = _drawing_mode;
99 
100 	switch (_drawing_mode) {
101 		case DRAW_MODE_TRANS:
102 			glEnable(GL_BLEND);
103 		break;
104 
105 		case DRAW_MODE_XOR:
106 			glEnable(GL_COLOR_LOGIC_OP);
107 			glLogicOp(GL_XOR);
108 		break;
109 
110 		case DRAW_MODE_COPY_PATTERN:
111 			if (is_memory_bitmap(_drawing_pattern)) {
112 				__agl_drawing_pattern_tex =
113 									allegro_gl_make_texture(_drawing_pattern);
114 				__agl_drawing_pattern_bmp = _drawing_pattern;
115 				__agl_owning_drawing_pattern_tex = TRUE;
116 			}
117 			else if (is_video_bitmap(_drawing_pattern)) {
118 				AGL_VIDEO_BITMAP *bmp = _drawing_pattern->extra;
119 				__agl_drawing_pattern_tex = bmp->tex;
120 				__agl_drawing_pattern_bmp = bmp->memory_copy;
121 				__agl_owning_drawing_pattern_tex = FALSE;
122 			}
123 
124 			glEnable(GL_TEXTURE_2D);
125 			glBindTexture(GL_TEXTURE_2D, __agl_drawing_pattern_tex);
126 
127 			break;
128 	}
129 }
130 
131 
split_color(int color,GLubyte * r,GLubyte * g,GLubyte * b,GLubyte * a,int color_depth)132 void split_color(int color, GLubyte *r, GLubyte *g, GLubyte *b, GLubyte *a,
133 						int color_depth)
134 {
135 	AGL_LOG(2, "glvtable.c:split_color\n");
136 	*r = getr_depth(color_depth, color);
137 	*g = getg_depth(color_depth, color);
138 	*b = getb_depth(color_depth, color);
139 	if (color_depth == 32)
140 		*a = geta_depth(color_depth, color);
141 	else
142 		*a = 255;
143 }
144 
145 
146 /* allegro_gl_created_sub_bitmap:
147  */
allegro_gl_created_sub_bitmap(BITMAP * bmp,BITMAP * parent)148 void allegro_gl_created_sub_bitmap(BITMAP *bmp, BITMAP *parent)
149 {
150    bmp->extra = parent;
151 }
152 
153 
154 /* static void allegro_gl_screen_acquire(struct BITMAP *bmp) */
155 /** acquire_bitmap(screen) overload.
156   * This doesn't do anything, since OpenGL rendering context
157   * doesn't need locking. You don't need to call this function
158   * in your program.
159   */
allegro_gl_screen_acquire(struct BITMAP * bmp)160 static void allegro_gl_screen_acquire(struct BITMAP *bmp) {}
161 
162 
163 
164 /* static void allegro_gl_screen_release(struct BITMAP *bmp) */
165 /** release_bitmap(screen) overload.
166   * This doesn't do anything, since OpenGL rendering context
167   * doesn't need locking. You don't need to call this function
168   * in your program.
169   */
allegro_gl_screen_release(struct BITMAP * bmp)170 static void allegro_gl_screen_release(struct BITMAP *bmp) {}
171 
172 
173 
allegro_gl_screen_getpixel(struct BITMAP * bmp,int x,int y)174 static int allegro_gl_screen_getpixel(struct BITMAP *bmp, int x, int y)
175 {
176 	GLubyte pixel[3];
177 	AGL_LOG(2, "glvtable.c:allegro_gl_screen_getpixel\n");
178 	if (bmp->clip && (x < bmp->cl || x >= bmp->cr
179 	                                          || y < bmp->ct || y >= bmp->cb)) {
180 		return -1;
181 	}
182 	if (is_sub_bitmap(bmp)) {
183 		x += bmp->x_ofs;
184 		y += bmp->y_ofs;
185 	}
186 	glReadPixels(x, bmp->h - y - 1, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, pixel);
187 
188 	return makecol_depth(bitmap_color_depth(screen),
189 	                                              pixel[0], pixel[1], pixel[2]);
190 }
191 
192 
193 
allegro_gl_screen_putpixel(struct BITMAP * bmp,int x,int y,int color)194 static void allegro_gl_screen_putpixel(struct BITMAP *bmp, int x, int y,
195                                                                       int color)
196 {
197 	GLubyte r, g, b, a;
198 	AGL_LOG(2, "glvtable.c:allegro_gl_screen_putpixel\n");
199 	split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
200 	if (bmp->clip && (x < bmp->cl || x >= bmp->cr
201 	                                          || y < bmp->ct || y >= bmp->cb)) {
202 		return;
203 	}
204 
205 	if (is_sub_bitmap(bmp)) {
206 		x += bmp->x_ofs;
207 		y += bmp->y_ofs;
208 	}
209 
210 	glColor4ub(r, g, b, a);
211 	glBegin(GL_POINTS);
212 		glVertex2f(x, y);
213 	glEnd();
214 }
215 
216 
217 
allegro_gl_screen_vline(struct BITMAP * bmp,int x,int y1,int y2,int color)218 static void allegro_gl_screen_vline(struct BITMAP *bmp, int x, int y1, int y2,
219                                                                       int color)
220 {
221 	GLubyte r, g, b, a;
222 	AGL_LOG(2, "glvtable.c:allegro_gl_screen_vline\n");
223 
224 	if (y1 > y2) {
225 		int temp = y1;
226 		y1 = y2;
227 		y2 = temp;
228 	}
229 
230 	if (bmp->clip) {
231 		if ((x < bmp->cl) || (x >= bmp->cr)) {
232 			return;
233 		}
234 		if ((y1 >= bmp->cb) || (y2 < bmp->ct)) {
235 			return;
236 		}
237 		if (y1 < bmp->ct) {
238 			y1 = bmp->ct;
239 		}
240 		if (y2 >= bmp->cb) {
241 			y2 = bmp->cb - 1;
242 		}
243 	}
244 
245 	if (is_sub_bitmap(bmp)) {
246 		x += bmp->x_ofs;
247 		y1 += bmp->y_ofs;
248 		y2 += bmp->y_ofs;
249 	}
250 
251 	split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
252 
253 	glColor4ub(r, g, b, a);
254 	glBegin(GL_LINES);
255 		glVertex2f(x, y1);
256 		glVertex2f(x, y2 + 0.325 * 3);
257 	glEnd();
258 
259 	return;
260 }
261 
262 
263 
allegro_gl_screen_hline(struct BITMAP * bmp,int x1,int y,int x2,int color)264 static void allegro_gl_screen_hline(struct BITMAP *bmp, int x1, int y, int x2,
265                                                                       int color)
266 {
267 	GLubyte r, g, b, a;
268 	AGL_LOG(2, "glvtable.c:allegro_gl_hline\n");
269 
270 	if (x1 > x2) {
271 		int temp = x1;
272 		x1 = x2;
273 		x2 = temp;
274 	}
275 	if (bmp->clip) {
276 		if ((y < bmp->ct) || (y >= bmp->cb)) {
277 			return;
278 		}
279 		if ((x1 >= bmp->cr) || (x2 < bmp->cl)) {
280 			return;
281 		}
282 		if (x1 < bmp->cl) {
283 			x1 = bmp->cl;
284 		}
285 		if (x2 >= bmp->cr) {
286 			x2 = bmp->cr - 1;
287 		}
288 	}
289 	if (is_sub_bitmap(bmp)) {
290 		x1 += bmp->x_ofs;
291 		x2 += bmp->x_ofs;
292 		y += bmp->y_ofs;
293 	}
294 
295 	split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
296 
297 	glColor4ub(r, g, b, a);
298 	glBegin(GL_LINES);
299 		glVertex2f(x1 - 0.325, y);
300 		glVertex2f(x2 + 0.325 * 2, y);
301 	glEnd();
302 
303 	return;
304 }
305 
306 
307 
allegro_gl_screen_line(struct BITMAP * bmp,int x1,int y1,int x2,int y2,int color)308 static void allegro_gl_screen_line(struct BITMAP *bmp, int x1, int y1, int x2,
309                                                               int y2, int color)
310 {
311 	GLubyte r, g, b, a;
312 	AGL_LOG(2, "glvtable.c:allegro_gl_screen_line\n");
313 
314 	if (bmp->clip) {
315 		glPushAttrib(GL_SCISSOR_BIT);
316 		glEnable(GL_SCISSOR_TEST);
317 		glScissor(bmp->x_ofs + bmp->cl, bmp->h + bmp->y_ofs - bmp->cb,
318 		                                  bmp->cr - bmp->cl, bmp->cb - bmp->ct);
319 	}
320 	if (is_sub_bitmap(bmp)) {
321 		x1 += bmp->x_ofs;
322 		x2 += bmp->x_ofs;
323 		y1 += bmp->y_ofs;
324 		y2 += bmp->y_ofs;
325 	}
326 
327 	split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
328 
329 	glColor4ub(r, g, b, a);
330 	glBegin(GL_LINES);
331 		glVertex2f(x1 + 0.1625, y1 + 0.1625);
332 		glVertex2f(x2 + 0.1625, y2 + 0.1625);
333 	glEnd();
334 
335 	/* OpenGL skips the endpoint when drawing lines */
336 	glBegin(GL_POINTS);
337 		glVertex2f(x2 + 0.1625, y2 + 0.1625);
338 	glEnd();
339 
340 	if (bmp->clip) {
341 		glPopAttrib();
342 	}
343 
344 	return;
345 }
346 
347 
348 #define SET_TEX_COORDS(x, y)  \
349 	do {                      \
350 		if (__agl_drawing_pattern_tex) {  \
351 			glTexCoord2f (                \
352 				(x - _drawing_x_anchor) / (float)__agl_drawing_pattern_bmp->w,\
353 				(y - _drawing_y_anchor) / (float)__agl_drawing_pattern_bmp->h \
354 			);                                                                \
355 		}                                                                     \
356 	} while(0)
357 
358 
allegro_gl_screen_rectfill(struct BITMAP * bmp,int x1,int y1,int x2,int y2,int color)359 void allegro_gl_screen_rectfill(struct BITMAP *bmp, int x1, int y1,
360                                                       int x2, int y2, int color)
361 {
362 	GLubyte r, g, b, a;
363 	GLfloat old_col[4];
364 	AGL_LOG(2, "glvtable.c:allegro_gl_screen_rectfill\n");
365 
366 	if (x1 > x2) {
367 		int temp = x1;
368 		x1 = x2;
369 		x2 = temp;
370 	}
371 
372 	if (y1 > y2) {
373 		int temp = y1;
374 		y1 = y2;
375 		y2 = temp;
376 	}
377 
378 	if (bmp->clip) {
379 		if ((x1 > bmp->cr) || (x2 < bmp->cl)) {
380 			return;
381 		}
382 		if (x1 < bmp->cl) {
383 			x1 = bmp->cl;
384 		}
385 		if (x2 > bmp->cr) {
386 			x2 = bmp->cr;
387 		}
388 		if ((y1 > bmp->cb) || (y2 < bmp->ct)) {
389 			return;
390 		}
391 		if (y1 < bmp->ct) {
392 			y1 = bmp->ct;
393 		}
394 		if (y2 > bmp->cb) {
395 			y2 = bmp->cb;
396 		}
397 	}
398 	if (is_sub_bitmap(bmp)) {
399 		x1 += bmp->x_ofs;
400 		x2 += bmp->x_ofs;
401 		y1 += bmp->y_ofs;
402 		y2 += bmp->y_ofs;
403 	}
404 
405 	glGetFloatv(GL_CURRENT_COLOR, old_col);
406 	split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
407 	glColor4ub(r, g, b, a);
408 
409 	glBegin(GL_QUADS);
410 		SET_TEX_COORDS(x1, y1);
411 		glVertex2f(x1, y1);
412 		SET_TEX_COORDS(x2, y1);
413 		glVertex2f(x2, y1);
414 		SET_TEX_COORDS(x2, y2);
415 		glVertex2f(x2, y2);
416 		SET_TEX_COORDS(x1, y2);
417 		glVertex2f(x1, y2);
418 	glEnd();
419 
420 	glColor4fv(old_col);
421 
422 	return;
423 }
424 
425 
426 
allegro_gl_screen_triangle(struct BITMAP * bmp,int x1,int y1,int x2,int y2,int x3,int y3,int color)427 static void allegro_gl_screen_triangle(struct BITMAP *bmp, int x1, int y1,
428                                       int x2, int y2, int x3, int y3, int color)
429 {
430 	GLubyte r, g, b, a;
431 	AGL_LOG(2, "glvtable.c:allegro_gl_screen_triangle\n");
432 
433 	split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
434 
435 	if (bmp->clip) {
436 		glPushAttrib(GL_SCISSOR_BIT);
437 		glEnable(GL_SCISSOR_TEST);
438 		glScissor(bmp->x_ofs + bmp->cl, bmp->h + bmp->y_ofs - bmp->cb,
439 		                                 bmp->cr - bmp->cl, bmp->cb - bmp->ct);
440 	}
441 	if (is_sub_bitmap(bmp)) {
442 		x1 += bmp->x_ofs;
443 		y1 += bmp->y_ofs;
444 		x2 += bmp->x_ofs;
445 		y2 += bmp->y_ofs;
446 		x3 += bmp->x_ofs;
447 		y3 += bmp->y_ofs;
448 	}
449 
450 	glColor4ub(r, g, b, a);
451 	glBegin(GL_TRIANGLES);
452 		SET_TEX_COORDS(x1, y1);
453 		glVertex2f(x1, y1);
454 		SET_TEX_COORDS(x2, y2);
455 		glVertex2f(x2, y2);
456 		SET_TEX_COORDS(x3, y3);
457 		glVertex2f(x3, y3);
458 	glEnd();
459 
460 	if (bmp->clip) {
461 		glPopAttrib();
462 	}
463 }
464 
465 
466 
467 #define BITMAP_BLIT_CLIP(source, dest, source_x, source_y, dest_x, dest_y, \
468                                                           width, height) { \
469 	if (dest->clip) {                                                      \
470 		if ((dest_x >= dest->cr) || (dest_y >= dest->cb)                   \
471 		 || (dest_x + width < dest->cl) || (dest_y + height < dest->ct)) { \
472 			width = 0;                                                     \
473 		}                                                                  \
474 		if (dest_x < dest->cl) {                                           \
475 			width += dest_x - dest->cl;                                    \
476 			source_x -= dest_x - dest->cl;                                 \
477 			dest_x = dest->cl;                                             \
478 		}                                                                  \
479 		if (dest_y < dest->ct) {                                           \
480 			height += dest_y - dest->ct;                                   \
481 			source_y -= dest_y - dest->ct;                                 \
482 			dest_y = dest->ct;                                             \
483 		}                                                                  \
484 		if (dest_x + width > dest->cr) {                                   \
485 			width = dest->cr - dest_x;                                     \
486 		}                                                                  \
487 		if (dest_y + height > dest->cb) {                                  \
488 			height = dest->cb - dest_y;                                    \
489 		}                                                                  \
490 	}                                                                      \
491 	if (source->clip) {                                                    \
492 		if ((source_x >= source->cr) || (source_y >= source->cb)           \
493 		 || (source_x + width < source->cl)                                \
494 		 || (source_y + height < source->ct)) {                            \
495 			width = 0;                                                     \
496 		}                                                                  \
497 		if (source_x < source->cl) {                                       \
498 			width += source_x - source->cl;                                \
499 			dest_x -= source_x - source->cl;                               \
500 			source_x = source->cl;                                         \
501 		}                                                                  \
502 		if (source_y < source->ct) {                                       \
503 			height += source_y - source->ct;                               \
504 			dest_y -= source_y - source->ct;                               \
505 			source_y = source->ct;                                         \
506 		}                                                                  \
507 		if (source_x + width > source->cr) {                               \
508 			width = source->cr - source_x;                                 \
509 		}                                                                  \
510 		if (source_y + height > source->cb) {                              \
511 			height = source->cb - source_y;                                \
512 		}                                                                  \
513 	}                                                                      \
514 }
515 
516 
517 
518 
allegro_gl_screen_blit_from_memory(struct BITMAP * source,struct BITMAP * dest,int source_x,int source_y,int dest_x,int dest_y,int width,int height)519 static void allegro_gl_screen_blit_from_memory(
520     struct BITMAP *source, struct BITMAP *dest,
521     int source_x, int source_y, int dest_x, int dest_y, int width, int height)
522 {
523 	GLfloat saved_zoom_x, saved_zoom_y;
524 	GLint saved_row_length;
525 	BITMAP *temp = NULL;
526 	void *data;
527 	AGL_LOG(2, "glvtable.c:allegro_gl_screen_blit_from_memory\n");
528 
529 	BITMAP_BLIT_CLIP(source, dest, source_x, source_y, dest_x, dest_y,
530 	                                                             width, height);
531 
532 	if (width <= 0 || height <= 0) {
533 		return;
534 	}
535 
536 
537 	if (is_sub_bitmap(dest)) {
538 		dest_x += dest->x_ofs;
539 		dest_y += dest->y_ofs;
540 	}
541 
542 	/* Note: We don't need to offset the source bitmap coordinates
543 	 * because we use source->line[] directly, which is already offsetted for
544 	 * us.
545 	 */
546 	data = source->line[source_y]
547 	     + source_x * BYTES_PER_PIXEL(bitmap_color_depth(source));
548 
549 	/* If packed pixels (or GL 1.2) isn't supported, then we need to convert
550 	 * the bitmap into something GL can understand - 24-bpp should do it.
551 	 */
552 	if (!allegro_gl_extensions_GL.EXT_packed_pixels
553 	                                       && bitmap_color_depth(source) < 24) {
554 		temp = create_bitmap_ex(24, width, height);
555 
556 		if (temp) {
557 			blit(source, temp, source_x, source_y, 0, 0, width, height);
558 			source_x = 0;
559 			source_y = 0;
560 			data = temp->line[0];
561 		}
562 		else {
563 			/* XXX <rohannessian> Report error? */
564 			return;
565 		}
566 		source = temp;
567 	}
568 
569 
570 	/* Save state */
571 	glGetFloatv(GL_ZOOM_X, &saved_zoom_x);
572 	glGetFloatv(GL_ZOOM_Y, &saved_zoom_y);
573 	glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
574 
575 	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
576 
577 	glRasterPos2i(dest_x, dest_y);
578 
579 	/* XXX <rohannessian> I wonder if it would be faster to use glDrawPixels()
580 	 * one line at a time instead of playing with the Zoom factor.
581 	 */
582 	glPixelZoom (1.0, -1.0);
583 	glPixelStorei(GL_UNPACK_ROW_LENGTH,
584 	                (source->line[1] - source->line[0])
585 	                / BYTES_PER_PIXEL(source->vtable->color_depth));
586 
587 	glDrawPixels(width, height, __allegro_gl_get_bitmap_color_format(source, 0),
588 		__allegro_gl_get_bitmap_type(source, 0), data);
589 
590 	/* Restore state */
591 	glPixelZoom(saved_zoom_x, saved_zoom_y);
592 	glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
593 
594 	if (temp) {
595 		destroy_bitmap(temp);
596 	}
597 	return;
598 }
599 
600 
601 
allegro_gl_screen_blit_to_memory(struct BITMAP * source,struct BITMAP * dest,int source_x,int source_y,int dest_x,int dest_y,int width,int height)602 static void allegro_gl_screen_blit_to_memory(
603       struct BITMAP *source, struct BITMAP *dest,
604       int source_x, int source_y, int dest_x, int dest_y, int width, int height)
605 {
606 	GLint saved_row_length;
607 	GLint saved_alignment;
608 	GLint saved_pack_invert;
609 
610 	BITMAP *bmp = NULL;
611 
612 	AGL_LOG(2, "glvtable.c:allegro_gl_screen_blit_to_memory\n");
613 
614 	BITMAP_BLIT_CLIP(source, dest, source_x, source_y, dest_x, dest_y,
615 	                                                             width, height);
616 
617 	if (is_sub_bitmap(source)) {
618 		source_x += source->x_ofs;
619 		source_y += source->y_ofs;
620 	}
621 	if (is_sub_bitmap(dest)) {
622 		dest_x += dest->x_ofs;
623 		dest_y += dest->y_ofs;
624 	}
625 
626 	if (width <= 0 || height <= 0) {
627 		return;
628 	}
629 
630 	/* Note that glPixelZoom doesn't affect reads -- so we have to do a flip.
631 	 * We can do this by reading into a temporary bitmap then flipping that to
632 	 * the destination, -OR- use the GL_MESA_pack_invert extension to do it
633 	 * for us.
634 	 *
635 	 * If GL_EXT_packed_pixels isn't supported, then we can't use
636 	 * MESA_pack_invert on 16-bpp bitmaps or less.
637 	 */
638 
639 	if ( !allegro_gl_extensions_GL.MESA_pack_invert
640 	 || (!allegro_gl_extensions_GL.EXT_packed_pixels
641 	   && bitmap_color_depth(dest) < 24)) {
642 
643 		/* XXX <rohannessian> Bitmap format should be the same as the source
644 		 * dest bitmap!
645 		 */
646 		if ((!allegro_gl_extensions_GL.EXT_packed_pixels
647 		   && bitmap_color_depth(dest) < 24)) {
648 			bmp = create_bitmap_ex(24, width, height);
649 		}
650 		else {
651 			bmp = create_bitmap_ex(bitmap_color_depth(dest), width, height);
652 		}
653 		if (!bmp)
654 			return;
655 	}
656 
657 	glGetIntegerv(GL_PACK_ROW_LENGTH, &saved_row_length);
658 	glGetIntegerv(GL_PACK_ALIGNMENT,  &saved_alignment);
659 	glPixelStorei(GL_PACK_ROW_LENGTH, 0);
660 	glPixelStorei(GL_PACK_ALIGNMENT,  1);
661 
662 	if (!allegro_gl_extensions_GL.MESA_pack_invert) {
663 
664 		glReadPixels(source_x, source->h - source_y - height, width, height,
665 			__allegro_gl_get_bitmap_color_format(bmp, 0),
666 			__allegro_gl_get_bitmap_type(bmp, 0), bmp->dat);
667 	}
668 	else {
669 		glGetIntegerv(GL_PACK_INVERT_MESA, &saved_pack_invert);
670 		glPixelStorei(GL_PACK_INVERT_MESA, TRUE);
671 		glPixelStorei(GL_PACK_ROW_LENGTH,
672 		              (dest->line[1] - dest->line[0])
673 		               / BYTES_PER_PIXEL(dest->vtable->color_depth));
674 
675 		glReadPixels(source_x, source->h - source_y - height, width, height,
676 			__allegro_gl_get_bitmap_color_format(dest, 0),
677 			__allegro_gl_get_bitmap_type(dest, 0), dest->line[0]);
678 
679 		glPixelStorei(GL_PACK_INVERT_MESA, saved_pack_invert);
680 	}
681 
682 	glPixelStorei(GL_PACK_ROW_LENGTH, saved_row_length);
683 	glPixelStorei(GL_PACK_ALIGNMENT,  saved_alignment);
684 
685 	/* Flip image if needed (glPixelZoom doesn't affect reads) */
686 	if (bmp) {
687 
688 		int y, dy;
689 
690 		for (y = 0, dy = dest_y + height - 1; y < height; y++, dy--) {
691 			blit(bmp, dest, 0, y, dest_x, dy, width, 1);
692 		}
693 
694 		destroy_bitmap(bmp);
695 	}
696 
697 	return;
698 }
699 
700 
701 
702 
allegro_gl_screen_blit_to_self(struct BITMAP * source,struct BITMAP * dest,int source_x,int source_y,int dest_x,int dest_y,int width,int height)703 void allegro_gl_screen_blit_to_self (
704      struct BITMAP *source, struct BITMAP *dest,
705      int source_x, int source_y, int dest_x, int dest_y, int width, int height)
706 {
707 	AGL_LOG(2, "glvtable.c:allegro_gl_screen_blit_to_self\n");
708 
709 	BITMAP_BLIT_CLIP(source, dest, source_x, source_y, dest_x, dest_y,
710 	                                                             width, height);
711 
712 	if (is_sub_bitmap(source)) {
713 		source_x += source->x_ofs;
714 		source_y += source->y_ofs;
715 	}
716 	if (is_sub_bitmap(dest)) {
717 		dest_x += dest->x_ofs;
718 		dest_y += dest->y_ofs;
719 	}
720 
721 	if (width <= 0 || height <= 0) {
722 		return;
723 	}
724 
725 	/* screen -> screen */
726 	if (is_screen_bitmap(source) && is_screen_bitmap(dest)) {
727 		glRasterPos2i(dest_x, dest_y + height - 1);
728 		glCopyPixels(source_x, SCREEN_H - source_y - height, width, height,
729 		                                                              GL_COLOR);
730 	}
731 	/* video -> screen */
732 	else if (is_screen_bitmap(dest) && is_video_bitmap(source)) {
733 		AGL_VIDEO_BITMAP *vid;
734 		BITMAP *source_parent = source;
735 		GLfloat current_color[4];
736 
737 		while (source_parent->id & BMP_ID_SUB) {
738 			source_parent = (BITMAP *)source_parent->extra;
739 		}
740 		vid = source_parent->extra;
741 
742 		glGetFloatv(GL_CURRENT_COLOR, current_color);
743 		glColor4ub(255, 255, 255, 255);
744 
745 		while (vid) {
746 			int sx, sy;           /* source coordinates */
747 			int dx, dy;           /* destination coordinates */
748 			int w, h;
749 
750 			if (source_x >= vid->x_ofs + vid->memory_copy->w ||
751 				source_y >= vid->y_ofs + vid->memory_copy->h ||
752 				vid->x_ofs >= source_x + width ||
753 				vid->y_ofs >= source_y + height) {
754 				vid = vid->next;
755 				continue;
756 			}
757 
758 			sx = MAX(vid->x_ofs, source_x) - vid->x_ofs;
759 			w = MIN(vid->x_ofs + vid->memory_copy->w, source_x + width)
760 			  - vid->x_ofs - sx;
761 			sy = MAX(vid->y_ofs, source_y) - vid->y_ofs;
762 			h = MIN(vid->y_ofs + vid->memory_copy->h, source_y + height)
763 			  - vid->y_ofs - sy;
764 
765 			dx = dest_x + vid->x_ofs + sx - source_x;
766 			dy = dest_y + vid->y_ofs + sy - source_y;
767 
768 			glEnable(vid->target);
769 			glBindTexture(vid->target, vid->tex);
770 
771 			if (vid->target == GL_TEXTURE_2D) {
772 				float tx = sx / (float)vid->memory_copy->w;
773 				float ty = sy / (float)vid->memory_copy->h;
774 				float tw = w / (float)vid->memory_copy->w;
775 				float th = h / (float)vid->memory_copy->h;
776 
777 				glBegin(GL_QUADS);
778 					glTexCoord2f(tx, ty);
779 					glVertex2f(dx, dy);
780 					glTexCoord2f(tx, ty + th);
781 					glVertex2f(dx, dy + h);
782 					glTexCoord2f(tx + tw, ty + th);
783 					glVertex2f(dx + w, dy + h);
784 					glTexCoord2f(tx + tw, ty);
785 					glVertex2f(dx + w, dy);
786 				glEnd();
787 			}
788 			else {
789 				glBegin(GL_QUADS);
790 					glTexCoord2i(sx, sy);
791 					glVertex2f(dx, dy);
792 					glTexCoord2i(sx, sy + h);
793 					glVertex2f(dx, dy + h);
794 					glTexCoord2i(sx + w, sy + h);
795 					glVertex2f(dx + w, dy + h);
796 					glTexCoord2i(sx + w, sy);
797 					glVertex2f(dx + w, dy);
798 				glEnd();
799 			}
800 
801 			glBindTexture(vid->target, 0);
802 			glDisable(vid->target);
803 
804 			vid = vid->next;
805 		}
806 
807 		glColor4fv(current_color);
808 	}
809 	/* screen -> video */
810 	else if (is_screen_bitmap(source) && is_video_bitmap(dest)) {
811 
812 		AGL_VIDEO_BITMAP *vid;
813 		BITMAP *source_parent = source;
814 
815 		while (source_parent->id & BMP_ID_SUB) {
816 			source_parent = (BITMAP *)source_parent->extra;
817 		}
818 
819 		vid = dest->extra;
820 
821 		while (vid) {
822 			int sx, sy;           /* source coordinates */
823 			int dx, dy;           /* destination coordinates */
824 			int w, h;
825 
826 			if (dest_x >= vid->x_ofs + vid->memory_copy->w ||
827 				dest_y >= vid->y_ofs + vid->memory_copy->h ||
828 				vid->x_ofs >= dest_x + width ||
829 				vid->y_ofs >= dest_y + height) {
830 				vid = vid->next;
831 				continue;
832 			}
833 
834 			dx = MAX(vid->x_ofs, dest_x) - vid->x_ofs;
835 			w = MIN(vid->x_ofs + vid->memory_copy->w, dest_x + width)
836 			  - vid->x_ofs - dx;
837 			dy = MAX(vid->y_ofs, dest_y) - vid->y_ofs;
838 			h = MIN(vid->y_ofs + vid->memory_copy->h, dest_y + height)
839 			  - vid->y_ofs - dy;
840 
841 			sx = source_x + vid->x_ofs + dx - dest_x;
842 			sy = source_y + vid->y_ofs + dy - dest_y;
843 
844 			/* We cannot use glCopyTexSubImage2D() here because it will flip the image. */
845 			allegro_gl_screen_blit_to_memory(source, vid->memory_copy,
846 			                                 sx, sy, dx, dy, w, h);
847 
848 			allegro_gl_video_blit_from_memory(vid->memory_copy, dest, 0, 0,
849 				vid->x_ofs, vid->y_ofs, vid->memory_copy->w, vid->memory_copy->h);
850 
851 			vid = vid->next;
852 		}
853 	}
854 	else if (is_video_bitmap(source) && is_video_bitmap(dest)) {
855 		allegro_gl_video_blit_to_self(source, dest, source_x, source_y,
856 									  dest_x, dest_y, width, height);
857 	}
858 }
859 
860 
861 
allegro_gl_upload_and_display_texture(struct BITMAP * source,int source_x,int source_y,int dest_x,int dest_y,int width,int height,int flip_dir,GLint format,GLint type)862 void allegro_gl_upload_and_display_texture(struct BITMAP *source,
863      int source_x, int source_y, int dest_x, int dest_y, int width, int height,
864      int flip_dir, GLint format, GLint type)
865 {
866 	float tx, ty;
867 	GLint saved_row_length;
868 	int bytes_per_pixel = BYTES_PER_PIXEL(bitmap_color_depth(source));
869 	int i, j;
870 
871 	glEnable(GL_ALPHA_TEST);
872 	glAlphaFunc(GL_GREATER, 0.0f);
873 
874 	glEnable(GL_TEXTURE_2D);
875 	glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
876 
877 	glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
878 	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
879 
880 	glPixelStorei(GL_UNPACK_ROW_LENGTH,
881 	                     (source->line[1] - source->line[0]) / bytes_per_pixel);
882 
883 	for (i = 0; i <= abs(width) / 256; i++) {
884 		for (j = 0; j <= abs(height) / 256; j++) {
885 
886 			void *data = source->line[source_y + j * 256]
887 			                           + (source_x + i * 256) * bytes_per_pixel;
888 			int w = abs(width)  - i * 256;
889 			int h = abs(height) - j * 256;
890 			int dx = dest_x + i * 256;
891 			int dy = dest_y + j * 256;
892 
893 			w = (w & -256) ? 256 : w;
894 			h = (h & -256) ? 256 : h;
895 
896 			glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, type, data);
897 
898 			tx = (float)w / 256.;
899 			ty = (float)h / 256.;
900 
901 			if (flip_dir & AGL_H_FLIP) {
902 				dx = 2*dest_x + width - dx;
903 				w = -w;
904 			}
905 
906 			if (flip_dir & AGL_V_FLIP) {
907 				dy = 2*dest_y + height - dy;
908 				h = -h;
909 			}
910 
911 			if (width < 0)  w = -w;
912 			if (height < 0) h = -h;
913 
914 			glBegin(GL_QUADS);
915 				glTexCoord2f(0., 0.);
916 				glVertex2i(dx, dy);
917 				glTexCoord2f(0., ty);
918 				glVertex2i(dx, dy + h);
919 				glTexCoord2f(tx, ty);
920 				glVertex2i(dx + w, dy + h);
921 				glTexCoord2f(tx, 0.);
922 				glVertex2i(dx + w, dy);
923 			glEnd();
924 		}
925 	}
926 
927 	/* Restore state */
928 	glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
929 	glBindTexture(GL_TEXTURE_2D, 0);
930 	glDisable(GL_TEXTURE_2D);
931 	glDisable(GL_ALPHA_TEST);
932 
933 	return;
934 }
935 
936 
937 
do_screen_masked_blit_standard(GLint format,GLint type,struct BITMAP * temp,int source_x,int source_y,int dest_x,int dest_y,int width,int height,int flip_dir,int blit_type)938 static void do_screen_masked_blit_standard(GLint format, GLint type, struct BITMAP *temp, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int flip_dir, int blit_type)
939 {
940 	glPushAttrib(GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT);
941 
942 	if (blit_type & AGL_NO_ROTATION) {
943 		GLint saved_row_length;
944 		float dx = dest_x, dy = dest_y;
945 		GLfloat zoom_x, zoom_y, old_zoom_x, old_zoom_y;
946 
947 		glEnable(GL_ALPHA_TEST);
948 		glAlphaFunc(GL_GREATER, 0.0f);
949 
950 		glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
951 		glGetFloatv(GL_ZOOM_X, &old_zoom_x);
952 		glGetFloatv(GL_ZOOM_Y, &old_zoom_y);
953 
954 		if (flip_dir & AGL_H_FLIP) {
955 			zoom_x = -1.0f;
956 			/* Without the -0.5 below, we get an invalid position,
957 			 * and the operation is ignored by OpenGL. */
958 			dx += abs(width) - 0.5;
959 		}
960 		else {
961 			zoom_x = (float) width / abs(width);
962 		}
963 
964 		if (flip_dir & AGL_V_FLIP) {
965 			zoom_y = 1.0f;
966 			dy += abs(height) - 0.5;
967 		}
968 		else {
969 			zoom_y = -1.0f * width / abs(width);
970 		}
971 
972 		glRasterPos2f(dx, dy);
973 		glPixelZoom(zoom_x, zoom_y);
974 		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
975 		glPixelStorei(GL_UNPACK_ROW_LENGTH,
976 		        (temp->line[1] - temp->line[0])
977 		        / BYTES_PER_PIXEL(bitmap_color_depth(temp)));
978 
979 		glDrawPixels(abs(width), abs(height), format, type, temp->line[0]);
980 
981 		glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
982 		glPixelZoom(old_zoom_x, old_zoom_y);
983 	}
984 	else {
985 		allegro_gl_upload_and_display_texture(temp, 0, 0, dest_x, dest_y, width, height,
986 		                           flip_dir, format, type);
987 	}
988 
989 	glPopAttrib();
990 }
991 
992 
993 
screen_masked_blit_standard(struct BITMAP * source,int source_x,int source_y,int dest_x,int dest_y,int width,int height,int flip_dir,int blit_type)994 static void screen_masked_blit_standard(struct BITMAP *source,
995     int source_x, int source_y, int dest_x, int dest_y, int width, int height,
996     int flip_dir, int blit_type)
997 {
998 	BITMAP *temp = NULL;
999 
1000 	GLint format, type;
1001 
1002 	format = __allegro_gl_get_bitmap_color_format(source, AGL_TEXTURE_MASKED);
1003 	type   = __allegro_gl_get_bitmap_type(source, AGL_TEXTURE_MASKED);
1004 
1005 	temp = __allegro_gl_munge_bitmap(AGL_TEXTURE_MASKED, source,
1006 	                        source_x, source_y, abs(width), abs(height),
1007 	                        &type, &format);
1008 
1009 	if (temp) {
1010 		source = temp;
1011 	}
1012 
1013 	do_screen_masked_blit_standard(format, type, source, source_x, source_y,
1014 		dest_x, dest_y, width, height, flip_dir, blit_type);
1015 
1016 	if (temp) {
1017 		destroy_bitmap(temp);
1018 	}
1019 
1020 	return;
1021 }
1022 
1023 
1024 
__allegro_gl_init_nv_register_combiners(BITMAP * bmp)1025 static void __allegro_gl_init_nv_register_combiners(BITMAP *bmp)
1026 {
1027 	GLfloat mask_color[4];
1028 	int depth = bitmap_color_depth(bmp);
1029 	int color = bitmap_mask_color(bmp);
1030 
1031 	mask_color[0] = getr_depth(depth, color) / 255.;
1032 	mask_color[1] = getg_depth(depth, color) / 255.;
1033 	mask_color[2] = getb_depth(depth, color) / 255.;
1034 	mask_color[3] = 0.;
1035 
1036 	glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, mask_color);
1037 	glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 2);
1038 	glEnable(GL_REGISTER_COMBINERS_NV);
1039 
1040 	glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV,
1041 		GL_TEXTURE0_ARB, GL_SIGNED_IDENTITY_NV, GL_RGB);
1042 	glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV,
1043 		GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_RGB);
1044 	glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV,
1045 		GL_CONSTANT_COLOR0_NV, GL_SIGNED_IDENTITY_NV, GL_RGB);
1046 	glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV,
1047 		GL_ZERO, GL_EXPAND_NORMAL_NV, GL_RGB);
1048 	glCombinerOutputNV(GL_COMBINER0_NV, GL_RGB, GL_DISCARD_NV,
1049 		GL_DISCARD_NV, GL_SPARE0_NV, GL_NONE, GL_NONE,
1050 		GL_FALSE, GL_FALSE, GL_FALSE);
1051 
1052 	glCombinerInputNV(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_A_NV,
1053 		GL_SPARE0_NV, GL_SIGNED_IDENTITY_NV, GL_RGB);
1054 	glCombinerInputNV(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_B_NV,
1055 		GL_SPARE0_NV, GL_SIGNED_IDENTITY_NV, GL_RGB);
1056 	glCombinerOutputNV(GL_COMBINER1_NV, GL_RGB, GL_SPARE1_NV,
1057 		GL_DISCARD_NV, GL_DISCARD_NV, GL_NONE, GL_NONE,
1058 		GL_TRUE, GL_FALSE, GL_FALSE);
1059 
1060 	glFinalCombinerInputNV(GL_VARIABLE_A_NV, GL_TEXTURE0_ARB,
1061 		GL_UNSIGNED_IDENTITY_NV, GL_RGB);
1062 	glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_ZERO,
1063 		GL_UNSIGNED_INVERT_NV, GL_RGB);
1064 	glFinalCombinerInputNV(GL_VARIABLE_C_NV, GL_ZERO,
1065 		GL_UNSIGNED_IDENTITY_NV, GL_RGB);
1066 	glFinalCombinerInputNV(GL_VARIABLE_D_NV, GL_ZERO,
1067 		GL_UNSIGNED_IDENTITY_NV, GL_RGB);
1068 	glFinalCombinerInputNV(GL_VARIABLE_G_NV, GL_SPARE1_NV,
1069 		GL_UNSIGNED_IDENTITY_NV, GL_BLUE);
1070 
1071 	return;
1072 }
1073 
1074 
1075 
screen_masked_blit_nv_register(struct BITMAP * source,int source_x,int source_y,int dest_x,int dest_y,int width,int height,int flip_dir,int blit_type)1076 static void screen_masked_blit_nv_register(struct BITMAP *source,
1077     int source_x, int source_y, int dest_x, int dest_y, int width, int height,
1078     int flip_dir, int blit_type)
1079 {
1080 	BITMAP *temp = NULL;
1081 	GLint type   = __allegro_gl_get_bitmap_type(source, 0);
1082 	GLint format = __allegro_gl_get_bitmap_color_format(source, 0);
1083 
1084 	if (type == -1) {
1085 		temp = create_bitmap_ex(24, width, height);
1086 		if (!temp) {
1087 			return;
1088 		}
1089 		blit(source, temp, source_x, source_y, 0, 0, width, height);
1090 		source = temp;
1091 		source_x = 0;
1092 		source_y = 0;
1093 
1094 		type   = __allegro_gl_get_bitmap_type(source, 0);
1095 		format = __allegro_gl_get_bitmap_color_format(source, 0);
1096 	}
1097 
1098 	glPushAttrib(GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT);
1099 	__allegro_gl_init_nv_register_combiners(source);
1100 
1101 	allegro_gl_upload_and_display_texture(source, source_x, source_y, dest_x, dest_y,
1102 	                           width, height, flip_dir, format, type);
1103 
1104 	glPopAttrib();
1105 
1106 	if (temp) {
1107 		destroy_bitmap(temp);
1108 	}
1109 	return;
1110 }
1111 
1112 
1113 
__allegro_gl_init_combine_textures(BITMAP * bmp)1114 static void __allegro_gl_init_combine_textures(BITMAP *bmp)
1115 {
1116 	GLubyte mask_color[4];
1117 
1118 	split_color(bitmap_mask_color(bmp), &mask_color[0], &mask_color[1],
1119 	    &mask_color[2], &mask_color[3], bitmap_color_depth(bmp));
1120 	glColor4ubv(mask_color);
1121 
1122 	glActiveTexture(GL_TEXTURE0);
1123 	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
1124 	glEnable(GL_TEXTURE_2D);
1125 	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD_SIGNED_ARB);
1126 	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
1127 	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
1128 	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_ONE_MINUS_SRC_COLOR);
1129 
1130 	/* Dot the result of the subtract with itself. Store it in the alpha
1131 	 * component. The alpha should then be 0 if the color fragment was equal to
1132 	 * the mask color, or >0 otherwise.
1133 	 */
1134 	glActiveTexture(GL_TEXTURE1);
1135 	glEnable(GL_TEXTURE_2D);
1136 	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
1137 	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_DOT3_RGBA_ARB);
1138 	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
1139 	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
1140 
1141 	/* Put the original RGB value in its place */
1142 
1143 	glActiveTexture(GL_TEXTURE2);
1144 	glEnable(GL_TEXTURE_2D);
1145 	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
1146 	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
1147 	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
1148 	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
1149 	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB);
1150 
1151 	glActiveTexture(GL_TEXTURE0);
1152 
1153 	return;
1154 }
1155 
1156 
1157 
screen_masked_blit_combine_tex(struct BITMAP * source,int source_x,int source_y,int dest_x,int dest_y,int width,int height,int flip_dir,int blit_type)1158 static void screen_masked_blit_combine_tex(struct BITMAP *source,
1159     int source_x, int source_y, int dest_x, int dest_y, int width, int height,
1160     int flip_dir, int blit_type)
1161 {
1162 	float tx, ty;
1163 	BITMAP *temp = NULL;
1164 	GLint saved_row_length;
1165 	GLint type   = __allegro_gl_get_bitmap_type(source, 0);
1166 	GLint format = __allegro_gl_get_bitmap_color_format(source, 0);
1167 	int bytes_per_pixel;
1168 	int i, j;
1169 	GLfloat current_color[4];
1170 
1171 	if (type == -1) {
1172 		temp = create_bitmap_ex(24, width, height);
1173 		if (!temp)
1174 			return;
1175 		blit(source, temp, source_x, source_y, 0, 0, width, height);
1176 		source = temp;
1177 		source_x = 0;
1178 		source_y = 0;
1179 
1180 		type   = __allegro_gl_get_bitmap_type(source, 0);
1181 		format = __allegro_gl_get_bitmap_color_format(source, 0);
1182 	}
1183 
1184 	glEnable(GL_TEXTURE_2D);
1185 	glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
1186 
1187 	glPushAttrib(GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT);
1188 	glGetFloatv(GL_CURRENT_COLOR, current_color);
1189 	__allegro_gl_init_combine_textures(source);
1190 
1191 	glActiveTexture(GL_TEXTURE0);
1192 	glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
1193 	glActiveTexture(GL_TEXTURE1);
1194 	glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
1195 	glActiveTexture(GL_TEXTURE2);
1196 	glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
1197 	glActiveTexture(GL_TEXTURE0);
1198 
1199 	bytes_per_pixel = BYTES_PER_PIXEL(bitmap_color_depth(source));
1200 
1201 	glEnable(GL_ALPHA_TEST);
1202 	glAlphaFunc(GL_GREATER, 0.0f);
1203 
1204 	glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
1205 	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1206 
1207 	glPixelStorei(GL_UNPACK_ROW_LENGTH,
1208 	                     (source->line[1] - source->line[0]) / bytes_per_pixel);
1209 
1210 	for (i = 0; i <= width / 256; i++) {
1211 		for (j = 0; j <= height / 256; j++) {
1212 
1213 			void *data = source->line[source_y + j * 256]
1214 			                           + (source_x + i * 256) * bytes_per_pixel;
1215 			int w = width - i * 256;
1216 			int h = height - j * 256;
1217 			int dx = dest_x + i * 256;
1218 			int dy = dest_y + j * 256;
1219 
1220 			w = (w & -256) ? 256 : w;
1221 			h = (h & -256) ? 256 : h;
1222 
1223 			glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, type, data);
1224 
1225 			tx = (float)w / 256.;
1226 			ty = (float)h / 256.;
1227 
1228 			if (flip_dir & AGL_H_FLIP) {
1229 				dx = 2*dest_x + width - dx;
1230 				w = -w;
1231 			}
1232 
1233 			if (flip_dir & AGL_V_FLIP) {
1234 				dy = 2*dest_y + height - dy;
1235 				h = -h;
1236 			}
1237 
1238 			glBegin(GL_QUADS);
1239 				glMultiTexCoord2f(GL_TEXTURE0, 0., 0.);
1240 				glMultiTexCoord2f(GL_TEXTURE1, 0., 0.);
1241 				glMultiTexCoord2f(GL_TEXTURE2, 0., 0.);
1242 				glVertex2f(dx, dy);
1243 				glMultiTexCoord2f(GL_TEXTURE0, 0., ty);
1244 				glMultiTexCoord2f(GL_TEXTURE1, 0., ty);
1245 				glMultiTexCoord2f(GL_TEXTURE2, 0., ty);
1246 				glVertex2f(dx, dy + h);
1247 				glMultiTexCoord2f(GL_TEXTURE0, tx, ty);
1248 				glMultiTexCoord2f(GL_TEXTURE1, tx, ty);
1249 				glMultiTexCoord2f(GL_TEXTURE2, tx, ty);
1250 				glVertex2f(dx + w, dy + h);
1251 				glMultiTexCoord2f(GL_TEXTURE0, tx, 0.);
1252 				glMultiTexCoord2f(GL_TEXTURE1, tx, 0.);
1253 				glMultiTexCoord2f(GL_TEXTURE2, tx, 0.);
1254 				glVertex2f(dx + w, dy);
1255 			glEnd();
1256 		}
1257 	}
1258 
1259 	/* Restore state */
1260 	glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
1261 	glBindTexture(GL_TEXTURE_2D, 0);
1262 	glDisable(GL_TEXTURE_2D);
1263 	glPopAttrib();
1264 	glColor4fv(current_color);
1265 
1266 	if (temp) {
1267 		destroy_bitmap(temp);
1268 	}
1269 
1270 	return;
1271 }
1272 
1273 
1274 
do_masked_blit_screen(struct BITMAP * source,struct BITMAP * dest,int source_x,int source_y,int dest_x,int dest_y,int width,int height,int flip_dir,int blit_type)1275 void do_masked_blit_screen(struct BITMAP *source, struct BITMAP *dest,
1276      int source_x, int source_y, int dest_x, int dest_y, int width, int height,
1277      int flip_dir, int blit_type)
1278 {
1279 
1280 	/* XXX <rohannessian> We should merge this clip code with the
1281 	 * BITMAP_BLIT_CLIP macro
1282 	 */
1283 
1284 	/* Clipping of destination bitmap */
1285 	if (dest->clip && (blit_type & AGL_NO_ROTATION)) {
1286 		if ((dest_x >= dest->cr) || (dest_y >= dest->cb)
1287 		 || (dest_x + width < dest->cl) || (dest_y + height < dest->ct)) {
1288 			return;
1289 		}
1290 		if (flip_dir & AGL_H_FLIP) {
1291 			if (dest_x < dest->cl) {
1292 				width += dest_x - dest->cl;
1293 				dest_x = dest->cl;
1294 			}
1295 			if (dest_x + width > dest->cr) {
1296 				source_x += dest_x + width - dest->cr;
1297 				width = dest->cr - dest_x;
1298 			}
1299 		}
1300 		else {
1301 			if (dest_x < dest->cl) {
1302 				width += dest_x - dest->cl;
1303 				source_x -= dest_x - dest->cl;
1304 				dest_x = dest->cl;
1305 			}
1306 			if (dest_x + width > dest->cr) {
1307 				width = dest->cr - dest_x;
1308 			}
1309 		}
1310 		if (flip_dir & AGL_V_FLIP) {
1311 			if (dest_y < dest->ct) {
1312 				height += dest_y - dest->ct;
1313 				dest_y = dest->ct;
1314 			}
1315 			if (dest_y + height > dest->cb) {
1316 				source_y += dest_y + height - dest->cb;
1317 				height = dest->cb - dest_y;
1318 			}
1319 		}
1320 		else {
1321 			if (dest_y < dest->ct) {
1322 				height += dest_y - dest->ct;
1323 				source_y -= dest_y - dest->ct;
1324 				dest_y = dest->ct;
1325 			}
1326 			if (dest_y + height > dest->cb) {
1327 				height = dest->cb - dest_y;
1328 			}
1329 		}
1330 	}
1331 
1332 	/* Clipping of source bitmap */
1333 	if (source->clip && (blit_type & AGL_REGULAR_BMP)) {
1334 		if ((source_x >= source->cr) || (source_y >= source->cb)
1335 		 || (source_x + width < source->cl)
1336 		 || (source_y + height < source->ct)) {
1337 			return;
1338 		}
1339 		if (source_x < source->cl) {
1340 			width += source_x - source->cl;
1341 			dest_x -= source_x - source->cl;
1342 			source_x = source->cl;
1343 		}
1344 		if (source_y < source->ct) {
1345 			height += source_y - source->ct;
1346 			dest_y -= source_y - source->ct;
1347 			source_y = source->ct;
1348 		}
1349 		if (source_x + width > source->cr) {
1350 			width = source->cr - source_x;
1351 		}
1352 		if (source_y + height > source->cb) {
1353 			height = source->cb - source_y;
1354 		}
1355 	}
1356 	if (is_sub_bitmap(dest)) {
1357 		dest_x += dest->x_ofs;
1358 		dest_y += dest->y_ofs;
1359 	}
1360 	if (width <= 0 || height <= 0)
1361 		return;
1362 
1363 	/* memory -> screen */
1364 	if (!is_video_bitmap(source) && !is_screen_bitmap(source)) {
1365 
1366 		__allegro_gl_driver->screen_masked_blit(source, source_x, source_y,
1367 		                    dest_x, dest_y, width, height, flip_dir, blit_type);
1368 	}
1369 	/* video -> screen */
1370 	else if (is_video_bitmap(source)) {
1371 		AGL_VIDEO_BITMAP *vid;
1372 		BITMAP *source_parent = source;
1373 
1374 		int use_combiners = 0;
1375 
1376 		/* Special combiner paths */
1377 		if (allegro_gl_extensions_GL.NV_register_combiners
1378 		 || allegro_gl_info.num_texture_units >= 3) {
1379 
1380 			use_combiners = 1;
1381 
1382 			glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT);
1383 
1384 			if (allegro_gl_extensions_GL.NV_register_combiners) {
1385 				__allegro_gl_init_nv_register_combiners(source);
1386 			}
1387 			else {
1388 				__allegro_gl_init_combine_textures(source);
1389 			}
1390 
1391 			glEnable(GL_ALPHA_TEST);
1392 			glAlphaFunc(GL_GREATER, 0.0f);
1393 		}
1394 
1395 		while (source_parent->id & BMP_ID_SUB) {
1396 			source_parent = (BITMAP *)source_parent->extra;
1397 		}
1398 		vid = source_parent->extra;
1399 
1400 		while (vid) {
1401 			int sx, sy;           /* source coordinates */
1402 			int dx, dy;           /* destination coordinates */
1403 			int w, h;
1404 
1405 			if (source_x >= vid->x_ofs + vid->memory_copy->w ||
1406 				source_y >= vid->y_ofs + vid->memory_copy->h ||
1407 				vid->x_ofs >= source_x + width ||
1408 				vid->y_ofs >= source_y + height) {
1409 				vid = vid->next;
1410 				continue;
1411 			}
1412 
1413 			sx = MAX (vid->x_ofs, source_x) - vid->x_ofs;
1414 			w = MIN (vid->x_ofs + vid->memory_copy->w, source_x + width)
1415 			  - vid->x_ofs - sx;
1416 			sy = MAX (vid->y_ofs, source_y) - vid->y_ofs;
1417 			h = MIN (vid->y_ofs + vid->memory_copy->h, source_y + height)
1418 			  - vid->y_ofs - sy;
1419 
1420 			dx = dest_x + vid->x_ofs + sx - source_x;
1421 			dy = dest_y + vid->y_ofs + sy - source_y;
1422 
1423 			if (flip_dir & AGL_H_FLIP) {
1424 				dx = 2*dest_x + width - dx;
1425 				w = -w;
1426 			}
1427 
1428 			if (flip_dir & AGL_V_FLIP) {
1429 				dy = 2*dest_y + height - dy;
1430 				h = -h;
1431 			}
1432 
1433 			if (use_combiners) {
1434 				if (allegro_gl_extensions_GL.NV_register_combiners) {
1435 					glEnable(vid->target);
1436 					glBindTexture(vid->target, vid->tex);
1437 					glTexParameteri(vid->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1438 					glTexParameteri(vid->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1439 
1440 					if (vid->target == GL_TEXTURE_2D) {
1441 						float tx = sx / (float)vid->memory_copy->w;
1442 						float ty = sy / (float)vid->memory_copy->h;
1443 						float tw = abs(w) / (float)vid->memory_copy->w;
1444 						float th = abs(h) / (float)vid->memory_copy->h;
1445 
1446 						glBegin(GL_QUADS);
1447 							glTexCoord2f(tx, ty);
1448 							glVertex2f(dx, dy);
1449 							glTexCoord2f(tx, ty + th);
1450 							glVertex2f(dx, dy + h);
1451 							glTexCoord2f(tx + tw, ty + th);
1452 							glVertex2f(dx + w, dy + h);
1453 							glTexCoord2f(tx + tw, ty);
1454 							glVertex2f(dx + w, dy);
1455 						glEnd();
1456 					}
1457 					else {
1458 						glBegin(GL_QUADS);
1459 							glTexCoord2i(sx, sy);
1460 							glVertex2f(dx, dy);
1461 							glTexCoord2i(sx, sy + h);
1462 							glVertex2f(dx, dy + h);
1463 							glTexCoord2i(sx + w, sy + h);
1464 							glVertex2f(dx + w, dy + h);
1465 							glTexCoord2i(sx + w, sy);
1466 							glVertex2f(dx + w, dy);
1467 						glEnd();
1468 					}
1469 
1470 					glBindTexture(vid->target, 0);
1471 					glDisable(vid->target);
1472 				}
1473 				else {
1474 					glEnable(vid->target);
1475 					glActiveTexture(GL_TEXTURE0);
1476 					glBindTexture(vid->target, vid->tex);
1477 					glActiveTexture(GL_TEXTURE1);
1478 					glBindTexture(vid->target, vid->tex);
1479 					glActiveTexture(GL_TEXTURE2);
1480 					glBindTexture(vid->target, vid->tex);
1481 					glActiveTexture(GL_TEXTURE0);
1482 					glTexParameteri(vid->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1483 					glTexParameteri(vid->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1484 
1485 					if (vid->target == GL_TEXTURE_2D) {
1486 						float tx, ty, tw, th; /* texture coordinates */
1487 						tx = sx / (float)vid->memory_copy->w;
1488 						ty = sy / (float)vid->memory_copy->h;
1489 						tw = abs(w) / (float)vid->memory_copy->w;
1490 						th = abs(h) / (float)vid->memory_copy->h;
1491 
1492 						glBegin(GL_QUADS);
1493 							glMultiTexCoord2f(GL_TEXTURE0, tx, ty);
1494 							glMultiTexCoord2f(GL_TEXTURE1, tx, ty);
1495 							glMultiTexCoord2f(GL_TEXTURE2, tx, ty);
1496 							glVertex2f(dx, dy);
1497 							glMultiTexCoord2f(GL_TEXTURE0, tx, ty + th);
1498 							glMultiTexCoord2f(GL_TEXTURE1, tx, ty + th);
1499 							glMultiTexCoord2f(GL_TEXTURE2, tx, ty + th);
1500 							glVertex2f(dx, dy + h);
1501 							glMultiTexCoord2f(GL_TEXTURE0, tx + tw, ty + th);
1502 							glMultiTexCoord2f(GL_TEXTURE1, tx + tw, ty + th);
1503 							glMultiTexCoord2f(GL_TEXTURE2, tx + tw, ty + th);
1504 							glVertex2f(dx + w, dy + h);
1505 							glMultiTexCoord2f(GL_TEXTURE0, tx + tw, ty);
1506 							glMultiTexCoord2f(GL_TEXTURE1, tx + tw, ty);
1507 							glMultiTexCoord2f(GL_TEXTURE2, tx + tw, ty);
1508 							glVertex2f(dx + w, dy);
1509 						glEnd();
1510 					}
1511 					else {
1512 						glBegin(GL_QUADS);
1513 							glMultiTexCoord2i(GL_TEXTURE0, dx, dy);
1514 							glMultiTexCoord2i(GL_TEXTURE1, dx, dy);
1515 							glMultiTexCoord2i(GL_TEXTURE2, dx, dy);
1516 							glVertex2f(dx, dy);
1517 							glMultiTexCoord2i(GL_TEXTURE0, dx, dy + h);
1518 							glMultiTexCoord2i(GL_TEXTURE1, dx, dy + h);
1519 							glMultiTexCoord2i(GL_TEXTURE2, dx, dy + h);
1520 							glVertex2f(dx, dy + h);
1521 							glMultiTexCoord2i(GL_TEXTURE0, dx + w, dy + h);
1522 							glMultiTexCoord2i(GL_TEXTURE1, dx + w, dy + h);
1523 							glMultiTexCoord2i(GL_TEXTURE2, dx + w, dy + h);
1524 							glVertex2f(dx + w, dy + h);
1525 							glMultiTexCoord2i(GL_TEXTURE0, dx + w, dy);
1526 							glMultiTexCoord2i(GL_TEXTURE1, dx + w, dy);
1527 							glMultiTexCoord2i(GL_TEXTURE2, dx + w, dy);
1528 							glVertex2f(dx + w, dy);
1529 						glEnd();
1530 					}
1531 
1532 					glBindTexture(vid->target, 0);
1533 					glDisable(vid->target);
1534 				}
1535 			}
1536 			else {
1537 				screen_masked_blit_standard(vid->memory_copy, sx, sy, dx, dy,
1538 				                            w, h, FALSE, blit_type);
1539 			}
1540 
1541 			vid = vid->next;
1542 		}
1543 
1544 		if (use_combiners) {
1545 			glPopAttrib();
1546 		}
1547 	}
1548 	return;
1549 }
1550 
1551 
1552 
__allegro_gl_convert_rle_sprite(AL_CONST struct RLE_SPRITE * sprite,int trans)1553 static BITMAP* __allegro_gl_convert_rle_sprite(AL_CONST struct RLE_SPRITE *sprite, int trans)
1554 {
1555 	BITMAP *temp = NULL;
1556 	int y, x, src_depth;
1557 	signed long src_mask;
1558 
1559 	#define DRAW_RLE_8888(bits)					\
1560 	{								\
1561 		for (y = 0; y < sprite->h; y++) {			\
1562 			signed long c = *s++;				\
1563 			for (x = 0; x < sprite->w;) {			\
1564 				if (c == src_mask)			\
1565 					break;				\
1566 				if (c > 0) {				\
1567 					/* Run of solid pixels */	\
1568 					for (c--; c>=0; c--) {		\
1569 						unsigned long col = *s++;		\
1570 						if (bits == 32 && trans)		\
1571 							_putpixel32(temp, x++, y, makeacol32(getr32(col), getg32(col), getb32(col), geta32(col))); \
1572 						else			\
1573 							_putpixel32(temp, x++, y, makeacol32(getr##bits(col), getg##bits(col), getb##bits(col), 255)); \
1574 					}				\
1575 				}					\
1576 				else {					\
1577 					/* Run of transparent pixels */	\
1578 					hline(temp, x, y, x-c+1, 0);	\
1579 					x -= c;				\
1580 				}					\
1581 				c = *s++;				\
1582 			}						\
1583 		}							\
1584 	}
1585 
1586 	src_depth = sprite->color_depth;
1587 	if (src_depth == 8)
1588 		src_mask = 0;
1589 	else
1590 		src_mask = makecol_depth(src_depth, 255, 0, 255);
1591 
1592 	temp = create_bitmap_ex(32, sprite->w, sprite->h);
1593 	if (!temp) return NULL;
1594 
1595 	/* RGBA 8888 */
1596 	switch(src_depth) {
1597 		case 8:
1598 		{
1599 			signed char *s = (signed char*)sprite->dat;
1600 			DRAW_RLE_8888(8);
1601 			break;
1602 		}
1603 		case 15:
1604 		{
1605 			int16_t *s = (int16_t*)sprite->dat;
1606 			DRAW_RLE_8888(15);
1607 			break;
1608 		}
1609 		case 16:
1610 		{
1611 			int16_t *s = (int16_t*)sprite->dat;
1612 			DRAW_RLE_8888(16);
1613 			break;
1614 		}
1615 		case 24:
1616 		{
1617 			int32_t *s = (int32_t*)sprite->dat;
1618 			DRAW_RLE_8888(24);
1619 			break;
1620 		}
1621 		case 32:
1622 		{
1623 			int32_t *s = (int32_t*)sprite->dat;
1624 			DRAW_RLE_8888(32);
1625 			break;
1626 		}
1627 	}
1628 
1629 	return temp;
1630 }
1631 
1632 
1633 
allegro_gl_screen_draw_rle_sprite(struct BITMAP * bmp,AL_CONST struct RLE_SPRITE * sprite,int x,int y)1634 void allegro_gl_screen_draw_rle_sprite(struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)
1635 {
1636 	BITMAP *temp = NULL, *temp2 = NULL;
1637 	int source_x = 0, source_y = 0;
1638 	int width = sprite->w, height = sprite->h;
1639 
1640 	temp = __allegro_gl_convert_rle_sprite(sprite, FALSE);
1641 	if (!temp)
1642 		return;
1643 
1644 	BITMAP_BLIT_CLIP(temp, bmp, source_x, source_y, x, y, width, height);
1645 
1646 	if (is_sub_bitmap(bmp)) {
1647 		x += bmp->x_ofs;
1648 		y += bmp->y_ofs;
1649 	}
1650 
1651 	if (width <= 0 || height <= 0) {
1652 		destroy_bitmap(temp);
1653 		return;
1654 	}
1655 
1656 	temp2 = create_sub_bitmap(temp, source_x, source_y, width, height);
1657 	if (!temp2) {
1658 		destroy_bitmap(temp);
1659 		return;
1660 	}
1661 
1662 	do_screen_masked_blit_standard(GL_RGBA,
1663 		__allegro_gl_get_bitmap_type(temp2, AGL_TEXTURE_MASKED), temp2,
1664 		0, 0, x, y, width, height, FALSE, AGL_NO_ROTATION);
1665 
1666 	destroy_bitmap(temp2);
1667 	destroy_bitmap(temp);
1668 }
1669 
1670 
allegro_gl_screen_draw_trans_rgba_rle_sprite(struct BITMAP * bmp,AL_CONST struct RLE_SPRITE * sprite,int x,int y)1671 static void allegro_gl_screen_draw_trans_rgba_rle_sprite(struct BITMAP *bmp,
1672 							AL_CONST struct RLE_SPRITE *sprite, int x, int y) {
1673 	BITMAP *temp = NULL, *temp2 = NULL;
1674 	int source_x = 0, source_y = 0;
1675 	int width = sprite->w, height = sprite->h;
1676 
1677 	temp = __allegro_gl_convert_rle_sprite(sprite, TRUE);
1678 	if (!temp)
1679 		return;
1680 
1681 	BITMAP_BLIT_CLIP(temp, bmp, source_x, source_y, x, y, width, height);
1682 
1683 	if (is_sub_bitmap(bmp)) {
1684 		x += bmp->x_ofs;
1685 		y += bmp->y_ofs;
1686 	}
1687 
1688 	if (width <= 0 || height <= 0) {
1689 		destroy_bitmap(temp);
1690 		return;
1691 	}
1692 
1693 	temp2 = create_sub_bitmap(temp, source_x, source_y, width, height);
1694 	if (!temp2) {
1695 		destroy_bitmap(temp);
1696 		return;
1697 	}
1698 
1699 	if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP)
1700 		glEnable(GL_COLOR_LOGIC_OP);
1701 	else
1702 		glEnable(GL_BLEND);
1703 
1704 	allegro_gl_upload_and_display_texture(temp2, 0, 0, x, y, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE);
1705 
1706 	if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP)
1707 		glDisable(GL_COLOR_LOGIC_OP);
1708 	else
1709 		glDisable(GL_BLEND);
1710 
1711 	destroy_bitmap(temp2);
1712 	destroy_bitmap(temp);
1713 }
1714 
1715 
1716 
allegro_gl_screen_masked_blit(struct BITMAP * source,struct BITMAP * dest,int source_x,int source_y,int dest_x,int dest_y,int width,int height)1717 static void allegro_gl_screen_masked_blit(struct BITMAP *source,
1718     struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y,
1719     int width, int height)
1720 {
1721 	AGL_LOG(2, "glvtable.c:allegro_gl_screen_masked_blit\n");
1722 	do_masked_blit_screen(source, dest, source_x, source_y, dest_x, dest_y,
1723 	                      width, height, FALSE, AGL_REGULAR_BMP | AGL_NO_ROTATION);
1724 }
1725 
1726 
1727 
allegro_gl_screen_draw_sprite(struct BITMAP * bmp,struct BITMAP * sprite,int x,int y)1728 static void allegro_gl_screen_draw_sprite(struct BITMAP *bmp,
1729     struct BITMAP *sprite, int x, int y)
1730 {
1731 	AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_sprite\n");
1732 	do_masked_blit_screen(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
1733 	                      FALSE, AGL_NO_ROTATION);
1734 }
1735 
1736 
1737 
allegro_gl_screen_draw_sprite_v_flip(struct BITMAP * bmp,struct BITMAP * sprite,int x,int y)1738 static void allegro_gl_screen_draw_sprite_v_flip(struct BITMAP *bmp,
1739     struct BITMAP *sprite, int x, int y)
1740 {
1741 	AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_sprite_v_flip\n");
1742 	do_masked_blit_screen(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
1743 	                      AGL_V_FLIP, AGL_NO_ROTATION);
1744 }
1745 
1746 
1747 
allegro_gl_screen_draw_sprite_h_flip(struct BITMAP * bmp,struct BITMAP * sprite,int x,int y)1748 static void allegro_gl_screen_draw_sprite_h_flip(struct BITMAP *bmp,
1749     struct BITMAP *sprite, int x, int y)
1750 {
1751 	AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_sprite_h_flip\n");
1752 	do_masked_blit_screen(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
1753 	                      AGL_H_FLIP, AGL_NO_ROTATION);
1754 }
1755 
1756 
1757 
allegro_gl_screen_draw_sprite_vh_flip(struct BITMAP * bmp,struct BITMAP * sprite,int x,int y)1758 static void allegro_gl_screen_draw_sprite_vh_flip(struct BITMAP *bmp,
1759     struct BITMAP *sprite, int x, int y)
1760 {
1761 	AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_sprite_vh_flip\n");
1762 	do_masked_blit_screen(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
1763 	                      AGL_V_FLIP | AGL_H_FLIP, AGL_NO_ROTATION);
1764 }
1765 
1766 
1767 
allegro_gl_screen_pivot_scaled_sprite_flip(struct BITMAP * bmp,struct BITMAP * sprite,fixed x,fixed y,fixed cx,fixed cy,fixed angle,fixed scale,int v_flip)1768 static void allegro_gl_screen_pivot_scaled_sprite_flip(struct BITMAP *bmp,
1769     struct BITMAP *sprite, fixed x, fixed y, fixed cx, fixed cy, fixed angle,
1770     fixed scale, int v_flip)
1771 {
1772 	double dscale = fixtof(scale);
1773 	GLint matrix_mode;
1774 	AGL_LOG(2, "glvtable.c:allegro_gl_screen_pivot_scaled_sprite_flip\n");
1775 
1776 #define BIN_2_DEG(x) (-(x) * 180.0 / 128)
1777 
1778 	glGetIntegerv(GL_MATRIX_MODE, &matrix_mode);
1779 	glMatrixMode(GL_MODELVIEW);
1780 	glPushMatrix();
1781 	glTranslated(fixtof(x), fixtof(y), 0.);
1782 	glRotated(BIN_2_DEG(fixtof(angle)), 0., 0., -1.);
1783 	glScaled(dscale, dscale, dscale);
1784 	glTranslated(-fixtof(x+cx), -fixtof(y+cy), 0.);
1785 
1786 	do_masked_blit_screen(sprite, bmp, 0, 0, fixtoi(x), fixtoi(y),
1787 	                      sprite->w, sprite->h, v_flip ? AGL_V_FLIP : FALSE, FALSE);
1788 	glPopMatrix();
1789 	glMatrixMode(matrix_mode);
1790 
1791 #undef BIN_2_DEG
1792 
1793 	return;
1794 }
1795 
1796 
1797 
allegro_gl_screen_draw_trans_rgba_sprite(struct BITMAP * bmp,struct BITMAP * sprite,int x,int y)1798 static void allegro_gl_screen_draw_trans_rgba_sprite(struct BITMAP *bmp,
1799 	struct BITMAP *sprite, int x, int y) {
1800 
1801 	if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP)
1802 		glEnable(GL_COLOR_LOGIC_OP);
1803 	else
1804 		glEnable(GL_BLEND);
1805 
1806 	/* video -> screen */
1807 	if (is_video_bitmap(sprite)) {
1808 		allegro_gl_screen_blit_to_self(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h);
1809 	}
1810 	/* memory -> screen */
1811 	else if (is_memory_bitmap(sprite)) {
1812 		GLint format = __allegro_gl_get_bitmap_color_format(sprite, AGL_TEXTURE_HAS_ALPHA);
1813 		GLint type = __allegro_gl_get_bitmap_type(sprite, 0);
1814 		allegro_gl_upload_and_display_texture(sprite, 0, 0, x, y, sprite->w, sprite->h, 0, format, type);
1815 	}
1816 
1817 	if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP)
1818 		glDisable(GL_COLOR_LOGIC_OP);
1819 	else
1820 		glDisable(GL_BLEND);
1821 
1822 	return;
1823 }
1824 
1825 
1826 
allegro_gl_screen_draw_sprite_ex(struct BITMAP * bmp,struct BITMAP * sprite,int x,int y,int mode,int flip)1827 static void allegro_gl_screen_draw_sprite_ex(struct BITMAP *bmp,
1828     struct BITMAP *sprite, int x, int y, int mode, int flip)
1829 {
1830 	int lflip = 0;
1831 	int matrix_mode;
1832 	AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_sprite_ex\n");
1833 
1834 	/* convert allegro's flipping flags to AGL's flags */
1835 	switch (flip) {
1836 		case DRAW_SPRITE_NO_FLIP:
1837 			lflip = FALSE;
1838 		break;
1839 		case DRAW_SPRITE_V_FLIP:
1840 			lflip = AGL_V_FLIP;
1841 		break;
1842 		case DRAW_SPRITE_H_FLIP:
1843 			lflip = AGL_H_FLIP;
1844 		break;
1845 		case DRAW_SPRITE_VH_FLIP:
1846 			lflip = AGL_V_FLIP | AGL_H_FLIP;
1847 		break;
1848 	}
1849 
1850 	switch (mode) {
1851 		case DRAW_SPRITE_NORMAL:
1852 			do_masked_blit_screen(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
1853 				lflip, AGL_NO_ROTATION);
1854 		break;
1855 		case DRAW_SPRITE_TRANS:
1856 			if (lflip) {
1857 				glGetIntegerv(GL_MATRIX_MODE, &matrix_mode);
1858 				glMatrixMode(GL_MODELVIEW);
1859 				glPushMatrix();
1860 
1861 				glTranslatef(x, y, 0.f);
1862 				glScalef((lflip&AGL_H_FLIP) ? -1 : 1, (lflip&AGL_V_FLIP)? -1 : 1, 1);
1863 				glTranslatef(-x, -y, 0);
1864 				glTranslatef((lflip&AGL_H_FLIP) ? -sprite->w : 0,
1865 						     (lflip&AGL_V_FLIP) ? -sprite->h : 0, 0);
1866 			}
1867 
1868 			allegro_gl_screen_draw_trans_rgba_sprite(bmp, sprite, x, y);
1869 
1870 			if (lflip) {
1871 				glPopMatrix();
1872 				glMatrixMode(matrix_mode);
1873 			}
1874 		break;
1875 		case DRAW_SPRITE_LIT:
1876 		/* unsupported */
1877 		break;
1878 	}
1879 }
1880 
1881 
1882 
allegro_gl_screen_draw_glyph_ex(struct BITMAP * bmp,AL_CONST struct FONT_GLYPH * glyph,int x,int y,int color,int bg,int flip)1883 void allegro_gl_screen_draw_glyph_ex(struct BITMAP *bmp,
1884                                   AL_CONST struct FONT_GLYPH *glyph, int x, int y,
1885 								  int color, int bg, int flip)
1886 {
1887 	GLubyte r, g, b, a;
1888 	int x_offs = 0;
1889 	int i;
1890 
1891 	AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_glyph_ex\n");
1892 
1893 	if (bmp->clip) {
1894 		glPushAttrib(GL_SCISSOR_BIT);
1895 		glEnable(GL_SCISSOR_TEST);
1896 		glScissor(bmp->x_ofs + bmp->cl, bmp->h + bmp->y_ofs - bmp->cb,
1897 		          bmp->cr - bmp->cl, bmp->cb - bmp->ct);
1898 
1899 		if (x < bmp->cl) {
1900 			x_offs -= x - bmp->cl;
1901 			x = bmp->cl;
1902 		}
1903 	}
1904 	if (is_sub_bitmap(bmp)) {
1905 		x += bmp->x_ofs;
1906 		y += bmp->y_ofs;
1907 	}
1908 
1909 	if (bg != -1) {
1910 		split_color(bg, &r, &g, &b, &a, bitmap_color_depth(bmp));
1911 		glColor4ub(r, g, b, a);
1912 		glRecti(x, y, x + glyph->w, y + glyph->h);
1913 	}
1914 
1915 	split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
1916 	glColor4ub(r, g, b, a);
1917 	glRasterPos2i(x, y);
1918 	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1919 	glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
1920 
1921 	if (flip) {
1922 		for (i = 0; i < glyph->h; i++) {
1923 			glBitmap(glyph->w, 1, x_offs, i, 0, 2,
1924 		                                 glyph->dat + i * ((glyph->w + 7) / 8));
1925 		}
1926 	}
1927 	else {
1928 		for (i = 0; i < glyph->h; i++) {
1929 			glBitmap(glyph->w, 1, x_offs, i, 0, 0,
1930 		                                 glyph->dat + i * ((glyph->w + 7) / 8));
1931 		}
1932 	}
1933 
1934 	if (bmp->clip) {
1935 		glPopAttrib();
1936 	}
1937 
1938 	return;
1939 }
1940 
1941 
1942 
allegro_gl_screen_draw_glyph(struct BITMAP * bmp,AL_CONST struct FONT_GLYPH * glyph,int x,int y,int color,int bg)1943 static void allegro_gl_screen_draw_glyph(struct BITMAP *bmp,
1944                                   AL_CONST struct FONT_GLYPH *glyph, int x, int y,
1945 								  int color, int bg) {
1946 	allegro_gl_screen_draw_glyph_ex(bmp, glyph, x, y, color, bg, 0);
1947 }
1948 
1949 
1950 
allegro_gl_screen_draw_color_glyph_ex(struct BITMAP * bmp,struct BITMAP * sprite,int x,int y,int color,int bg,int flip)1951 void allegro_gl_screen_draw_color_glyph_ex(struct BITMAP *bmp,
1952     struct BITMAP *sprite, int x, int y, int color, int bg, int flip)
1953 {
1954 
1955 	/* Implementation note: we should try building textures and see how well
1956 	 * those work instead of of DrawPixels with a weird I_TO_RGBA mapping.
1957 	 */
1958 	static GLfloat red_map[256];
1959 	static GLfloat green_map[256];
1960 	static GLfloat blue_map[256];
1961 	static GLfloat alpha_map[256];
1962 	GLubyte r, g, b, a;
1963 	int i;
1964 	GLint saved_row_length;
1965 	GLint width, height;
1966 	int sprite_x = 0, sprite_y = 0;
1967 	void *data;
1968 	int *table;
1969 
1970 	width = sprite->w;
1971 	height = sprite->h;
1972 
1973 	if (bmp->clip) {
1974 		if ((x >= bmp->cr) || (y >= bmp->cb) || (x + width < bmp->cl)
1975 		 || (y + height < bmp->ct)) {
1976 			return;
1977 		}
1978 		if (x < bmp->cl) {
1979 			width += x - bmp->cl;
1980 			sprite_x -= (x - bmp->cl);
1981 			x = bmp->cl;
1982 		}
1983 		if (y < bmp->ct) {
1984 			height += y - bmp->ct;
1985 			sprite_y -= (y - bmp->ct);
1986 			y = bmp->ct;
1987 		}
1988 		if (x + width > bmp->cr) {
1989 			width = bmp->cr - x;
1990 		}
1991 		if (y + height > bmp->cb) {
1992 			height = bmp->cb - y;
1993 		}
1994 	}
1995 	if (is_sub_bitmap(bmp)) {
1996 		x += bmp->x_ofs;
1997 		y += bmp->y_ofs;
1998 	}
1999 
2000 	data = sprite->line[sprite_y]
2001 	     + sprite_x * BYTES_PER_PIXEL(bitmap_color_depth(sprite));
2002 
2003 	if (bg < 0) {
2004 		glAlphaFunc(GL_GREATER, 0.0f);
2005 		glEnable(GL_ALPHA_TEST);
2006 		alpha_map[0] = 0.;
2007 	}
2008 	else {
2009 		split_color(bg, &r, &g, &b, &a, bitmap_color_depth(bmp));
2010 		red_map[0] = r / 255.;
2011 		green_map[0] = g / 255.;
2012 		blue_map[0] = b / 255.;
2013 		alpha_map[0] = 1.;
2014 	}
2015 
2016 	if (color < 0) {
2017 		table = _palette_expansion_table(bitmap_color_depth(bmp));
2018 
2019 		for(i = 1; i < 255; i++) {
2020 			split_color(table[i], &r, &g, &b, &a, bitmap_color_depth(bmp));
2021 			red_map[i] = r / 255.;
2022 			green_map[i] = g / 255.;
2023 			blue_map[i] = b / 255.;
2024 			alpha_map[i] = 1.;
2025 		}
2026 	}
2027 	else {
2028 		split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
2029 
2030 		for(i = 1; i < 255; i++) {
2031 			red_map[i] = r / 255.;
2032 			green_map[i] = g / 255.;
2033 			blue_map[i] = b / 255.;
2034 			alpha_map[i] = 1.;
2035 		}
2036 	}
2037 
2038 	glPixelMapfv(GL_PIXEL_MAP_I_TO_R, 256, red_map);
2039 	glPixelMapfv(GL_PIXEL_MAP_I_TO_G, 256, green_map);
2040 	glPixelMapfv(GL_PIXEL_MAP_I_TO_B, 256, blue_map);
2041 	glPixelMapfv(GL_PIXEL_MAP_I_TO_A, 256, alpha_map);
2042 
2043 	glRasterPos2i(x, y);
2044 	glPushAttrib(GL_PIXEL_MODE_BIT);
2045 	glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
2046 
2047 	glPixelZoom(1.0, flip ? -1.0 : 1.0);
2048 	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2049 	glPixelStorei(GL_UNPACK_ROW_LENGTH, sprite->w);
2050 	glPixelTransferi(GL_MAP_COLOR, GL_TRUE);
2051 
2052 	glDrawPixels(width, height, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, data);
2053 	glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
2054 	glPopAttrib();
2055 	if (bg < 0) {
2056 		glDisable(GL_ALPHA_TEST);
2057 	}
2058 
2059 	return;
2060 }
2061 
2062 
2063 
allegro_gl_screen_draw_color_glyph(struct BITMAP * bmp,struct BITMAP * sprite,int x,int y,int color,int bg)2064 static void allegro_gl_screen_draw_color_glyph(struct BITMAP *bmp,
2065     struct BITMAP *sprite, int x, int y, int color, int bg) {
2066 	allegro_gl_screen_draw_color_glyph_ex(bmp, sprite, x, y, color, bg, 1);
2067 }
2068 
2069 
2070 
allegro_gl_screen_draw_character(struct BITMAP * bmp,struct BITMAP * sprite,int x,int y,int color,int bg)2071 static void allegro_gl_screen_draw_character(struct BITMAP *bmp,
2072                          struct BITMAP *sprite, int x, int y, int color, int bg)
2073 {
2074 	AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_character\n");
2075 	allegro_gl_screen_draw_color_glyph(bmp, sprite, x, y, color, bg);
2076 }
2077 
2078 
2079 
allegro_gl_screen_draw_256_sprite(struct BITMAP * bmp,struct BITMAP * sprite,int x,int y)2080 static void allegro_gl_screen_draw_256_sprite(struct BITMAP *bmp,
2081                                             struct BITMAP *sprite, int x, int y)
2082 {
2083 	AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_256_sprite\n");
2084 	allegro_gl_screen_draw_color_glyph(bmp, sprite, x, y, -1, -1);
2085 }
2086 
2087 
2088 
allegro_gl_screen_clear_to_color(struct BITMAP * bmp,int color)2089 void allegro_gl_screen_clear_to_color(struct BITMAP *bmp, int color)
2090 {
2091 	if (__agl_drawing_pattern_tex || bmp->clip) {
2092 		allegro_gl_screen_rectfill(bmp, 0, 0, bmp->w, bmp->h, color);
2093 	}
2094 	else {
2095 		GLubyte r, g, b, a;
2096 		GLfloat old_col[4];
2097 
2098 		split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
2099 
2100 		glGetFloatv(GL_COLOR_CLEAR_VALUE, old_col);
2101 		glClearColor(((float) r / 255), ((float) g / 255), ((float) b / 255),
2102 					 ((float) a / 255));
2103 
2104 		glClear(GL_COLOR_BUFFER_BIT);
2105 		glClearColor(old_col[0], old_col[1], old_col[2], old_col[3]);
2106 	}
2107 
2108 	return;
2109 }
2110 
2111 
2112 
2113 /* TODO: Handle concave and self-intersecting. */
allegro_gl_screen_polygon(struct BITMAP * bmp,int vertices,AL_CONST int * points,int color)2114 static void allegro_gl_screen_polygon(struct BITMAP *bmp, int vertices,
2115 									  AL_CONST int *points, int color) {
2116 	GLubyte r, g, b, a;
2117 	int i;
2118 
2119 	split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
2120 	glColor4ub(r, g, b, a);
2121 
2122 	glPushAttrib(GL_SCISSOR_BIT);
2123 
2124 	if (bmp->clip) {
2125 		glEnable(GL_SCISSOR_TEST);
2126 		glScissor(bmp->x_ofs + bmp->cl, bmp->h + bmp->y_ofs - bmp->cb,
2127 				  bmp->cr - bmp->cl, bmp->cb - bmp->ct);
2128 	}
2129 	else {
2130 		glScissor(0, 0, bmp->w, bmp->h);
2131 	}
2132 
2133 	glBegin(GL_POLYGON);
2134 		for (i = 0; i < vertices*2-1; i+=2) {
2135 			SET_TEX_COORDS(points[i], points[i+1]);
2136 			if (is_sub_bitmap(bmp)) {
2137 				glVertex2f(points[i] + bmp->x_ofs, points[i+1] + bmp->y_ofs);
2138 			}
2139 			else {
2140 				glVertex2f(points[i], points[i+1]);
2141 			}
2142 		}
2143 	glEnd();
2144 
2145 	glPopAttrib();
2146 }
2147 
2148 
2149 
allegro_gl_screen_rect(struct BITMAP * bmp,int x1,int y1,int x2,int y2,int color)2150 static void allegro_gl_screen_rect(struct BITMAP *bmp,
2151 								   int x1, int y1, int x2, int y2, int color) {
2152 	GLubyte r, g, b, a;
2153 
2154 	split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
2155 	glColor4ub(r, g, b, a);
2156 
2157 	glPushAttrib(GL_SCISSOR_BIT);
2158 
2159 	if (bmp->clip) {
2160 		glEnable(GL_SCISSOR_TEST);
2161 		glScissor(bmp->x_ofs + bmp->cl, bmp->h + bmp->y_ofs - bmp->cb,
2162 				  bmp->cr - bmp->cl, bmp->cb - bmp->ct);
2163 	}
2164 	else {
2165 		glScissor(0, 0, bmp->w, bmp->h);
2166 	}
2167 	if (is_sub_bitmap(bmp)) {
2168 		x1 += bmp->x_ofs;
2169 		x2 += bmp->x_ofs;
2170 		y1 += bmp->y_ofs;
2171 		y2 += bmp->y_ofs;
2172 	}
2173 
2174 	glBegin(GL_LINE_STRIP);
2175 		glVertex2f(x1, y1);
2176 		glVertex2f(x2, y1);
2177 		glVertex2f(x2, y2);
2178 		glVertex2f(x1, y2);
2179 		glVertex2f(x1, y1);
2180 	glEnd();
2181 
2182 	glPopAttrib();
2183 }
2184 
2185 
2186 
allegro_gl_screen_polygon3d_f(struct BITMAP * bmp,int type,struct BITMAP * texture,int vc,V3D_f * vtx[])2187 void allegro_gl_screen_polygon3d_f(struct BITMAP *bmp, int type,
2188 								   struct BITMAP *texture, int vc,
2189 								   V3D_f *vtx[]) {
2190 	int i;
2191 	int use_z = FALSE;
2192 
2193 	if (type & POLYTYPE_ZBUF) {
2194 		use_z = TRUE;
2195 		type &= ~POLYTYPE_ZBUF;
2196 	}
2197 
2198 	if (type == POLYTYPE_PTEX || type == POLYTYPE_PTEX_TRANS)
2199 		use_z = TRUE;
2200 
2201 	if (bmp->clip) {
2202 		glPushAttrib(GL_SCISSOR_BIT);
2203 		glEnable(GL_SCISSOR_TEST);
2204 		glScissor(bmp->x_ofs + bmp->cl, bmp->h + bmp->y_ofs - bmp->cb,
2205 				  bmp->cr - bmp->cl, bmp->cb - bmp->ct);
2206 	}
2207 	if (is_sub_bitmap(bmp)) {
2208 		for (i = 0; i < vc*2-1; i+=2) {
2209 			vtx[i] += bmp->x_ofs;
2210 			vtx[i+1] += bmp->y_ofs;
2211 		}
2212 	}
2213 
2214 	if (use_z) {
2215 		glEnable(GL_DEPTH_TEST);
2216 		glDepthFunc(GL_LESS);
2217 		glDepthMask(GL_TRUE);
2218 	}
2219 
2220 	glColor4ub(255, 255, 255, 255);
2221 
2222 	if (type == POLYTYPE_ATEX || type == POLYTYPE_PTEX
2223 	 || type == POLYTYPE_ATEX_TRANS || type == POLYTYPE_PTEX_TRANS) {
2224 		drawing_mode(DRAW_MODE_COPY_PATTERN, texture, 0, 0);
2225 	}
2226 
2227 	if (type == POLYTYPE_ATEX_TRANS || type == POLYTYPE_PTEX_TRANS) {
2228 		glEnable(GL_BLEND);
2229 	}
2230 
2231 	glBegin(GL_POLYGON);
2232 		for (i = 0; i < vc; i++) {
2233 			if (type == POLYTYPE_FLAT)
2234 				glColor3ub(getr(vtx[0]->c), getg(vtx[0]->c), getb(vtx[0]->c));
2235 			else if (type == POLYTYPE_GRGB)
2236 				glColor3ub(getr24(vtx[i]->c), getg24(vtx[i]->c), getb24(vtx[i]->c));
2237 			else if (type == POLYTYPE_GCOL)
2238 				glColor3ub(getr(vtx[i]->c), getg(vtx[i]->c), getb(vtx[i]->c));
2239 			else if (type == POLYTYPE_ATEX || type == POLYTYPE_PTEX
2240 				  || type == POLYTYPE_ATEX_TRANS || type == POLYTYPE_PTEX_TRANS) {
2241 					SET_TEX_COORDS(vtx[i]->u, vtx[i]->v);
2242 			}
2243 
2244 			if (use_z)
2245 				glVertex3f(vtx[i]->x, vtx[i]->y, 1.f / vtx[i]->z);
2246 			else
2247 				glVertex2f(vtx[i]->x, vtx[i]->y);
2248 		}
2249 	glEnd();
2250 
2251 	if (bmp->clip)
2252 		glPopAttrib();
2253 
2254 	if (use_z) {
2255 		glDisable(GL_DEPTH_TEST);
2256 		glDepthMask(GL_FALSE);
2257 	}
2258 
2259 	if (type == POLYTYPE_ATEX || type == POLYTYPE_PTEX
2260 	 || type == POLYTYPE_ATEX_TRANS || type == POLYTYPE_PTEX_TRANS) {
2261 		solid_mode();
2262 	}
2263 
2264 	if (type == POLYTYPE_ATEX_TRANS || type == POLYTYPE_PTEX_TRANS)
2265 		glDisable(GL_BLEND);
2266 }
2267 
2268 
2269 
allegro_gl_screen_polygon3d(struct BITMAP * bmp,int type,struct BITMAP * texture,int vc,V3D * vtx[])2270 static void allegro_gl_screen_polygon3d(struct BITMAP *bmp, int type,
2271 										struct BITMAP *texture, int vc,
2272 										V3D *vtx[]) {
2273 	int i;
2274 	V3D_f **vtx_f = malloc(vc * sizeof(struct V3D_f*));
2275 	if (!vtx_f)
2276 		return;
2277 
2278 	for (i = 0; i < vc; i++) {
2279 		vtx_f[i] = malloc(sizeof(struct V3D_f));
2280 		if (!vtx_f[i]) {
2281 			int k;
2282 			for (k = 0; k < i; k++)
2283 				free(vtx_f[k]);
2284 			free(vtx_f);
2285 			return;
2286 		}
2287 		vtx_f[i]->c = vtx[i]->c;
2288 		vtx_f[i]->u = fixtof(vtx[i]->u);
2289 		vtx_f[i]->v = fixtof(vtx[i]->v);
2290 		vtx_f[i]->x = fixtof(vtx[i]->x);
2291 		vtx_f[i]->y = fixtof(vtx[i]->y);
2292 		vtx_f[i]->z = fixtof(vtx[i]->z);
2293 	}
2294 
2295 	allegro_gl_screen_polygon3d_f(bmp, type, texture, vc, vtx_f);
2296 	for (i = 0; i < vc; i++)
2297 		free(vtx_f[i]);
2298 	free(vtx_f);
2299 }
2300 
2301 
allegro_gl_screen_quad3d_f(struct BITMAP * bmp,int type,struct BITMAP * texture,V3D_f * v1,V3D_f * v2,V3D_f * v3,V3D_f * v4)2302 static void allegro_gl_screen_quad3d_f(struct BITMAP *bmp, int type,
2303 									   struct BITMAP *texture,
2304 									   V3D_f *v1, V3D_f *v2, V3D_f *v3, V3D_f *v4) {
2305 
2306 	V3D_f *vtx_f[4];
2307 	vtx_f[0] = v1;
2308 	vtx_f[1] = v2;
2309 	vtx_f[2] = v3;
2310 	vtx_f[3] = v4;
2311 
2312 	allegro_gl_screen_polygon3d_f(bmp, type, texture, 4, vtx_f);
2313 }
2314 
2315 
2316 
allegro_gl_screen_quad3d(struct BITMAP * bmp,int type,struct BITMAP * texture,V3D * v1,V3D * v2,V3D * v3,V3D * v4)2317 static void allegro_gl_screen_quad3d(struct BITMAP *bmp, int type,
2318 			struct BITMAP *texture, V3D *v1, V3D *v2, V3D *v3, V3D *v4) {
2319 
2320 	V3D *vtx[4];
2321 	vtx[0] = v1;
2322 	vtx[1] = v2;
2323 	vtx[2] = v3;
2324 	vtx[3] = v4;
2325 
2326 	allegro_gl_screen_polygon3d(bmp, type, texture, 4, vtx);
2327 }
2328 
2329 
2330 
allegro_gl_screen_triangle3d(struct BITMAP * bmp,int type,struct BITMAP * texture,V3D * v1,V3D * v2,V3D * v3)2331 static void allegro_gl_screen_triangle3d(struct BITMAP *bmp, int type,
2332 										 struct BITMAP *texture,
2333 										 V3D *v1, V3D *v2, V3D *v3) {
2334 	V3D *vtx[3];
2335 	vtx[0] = v1;
2336 	vtx[1] = v2;
2337 	vtx[2] = v3;
2338 
2339 	allegro_gl_screen_polygon3d(bmp, type, texture, 3, vtx);
2340 }
2341 
2342 
2343 
allegro_gl_screen_triangle3d_f(struct BITMAP * bmp,int type,struct BITMAP * texture,V3D_f * v1,V3D_f * v2,V3D_f * v3)2344 static void allegro_gl_screen_triangle3d_f(struct BITMAP *bmp, int type,
2345 										   struct BITMAP *texture,
2346 										   V3D_f *v1, V3D_f *v2, V3D_f *v3) {
2347 	V3D_f *vtx_f[3];
2348 	vtx_f[0] = v1;
2349 	vtx_f[1] = v2;
2350 	vtx_f[2] = v3;
2351 
2352 	allegro_gl_screen_polygon3d_f(bmp, type, texture, 3, vtx_f);
2353 }
2354 
2355 
2356 
__allegro_gl__glvtable_update_vtable(GFX_VTABLE ** vtable)2357 void __allegro_gl__glvtable_update_vtable(GFX_VTABLE ** vtable)
2358 {
2359 	int maskcolor = (*vtable)->mask_color;
2360 	int depth = (*vtable)->color_depth;
2361 
2362 	AGL_LOG(2, "glvtable.c:__allegro_gl__glvtable_update_vtable\n");
2363 	allegro_gl_screen_vtable.color_depth = depth;
2364 	/* makecol_depth is used below instead of the MASK_COLOR_x constants
2365 	 * because we may have changed the RGB shift values in order to
2366 	 * use the packed pixels extension
2367 	 */
2368 	allegro_gl_screen_vtable.mask_color =
2369 	    makecol_depth(depth, getr(maskcolor), getg(maskcolor), getb(maskcolor));
2370 
2371 	*vtable = &allegro_gl_screen_vtable;
2372 
2373 	__allegro_gl_driver->screen_masked_blit = screen_masked_blit_standard;
2374 	if (allegro_gl_extensions_GL.NV_register_combiners) {
2375 		__allegro_gl_driver->screen_masked_blit
2376 		                                       = screen_masked_blit_nv_register;
2377 	}
2378 	else if (allegro_gl_info.num_texture_units >= 3) {
2379 		__allegro_gl_driver->screen_masked_blit =
2380 		                                         screen_masked_blit_combine_tex;
2381 	}
2382 }
2383 
2384 
2385 
2386 /* Saved projection matrix */
2387 static double allegro_gl_projection_matrix[16];
2388 static double allegro_gl_modelview_matrix[16];
2389 
2390 
2391 
2392 /** \ingroup allegro
2393   * Prepares for Allegro drawing to the screen.
2394   *
2395   * Since AllegroGL actually calls OpenGL commands to perform Allegro functions
2396   * for 2D drawing, some OpenGL capabilities may interfer with those operations
2397   * In order to obtain the expected results, allegro_gl_set_allegro_mode() must
2398   * be called to disable the depth test, texturing, fog and lighting and set
2399   * the view matrices to an appropriate state. Call
2400   * allegro_gl_unset_allegro_mode() to restore OpenGL in its previous state.
2401   *
2402   * You should encapsulate all Allegro code dealing with the screen in
2403   * between allegro_gl_set_allegro_mode() and allegro_gl_unset_allegro_mode().
2404   *
2405   * If you need to use regular OpenGL commands in between, you may do so,
2406   * but you can get unexpected results. This is generally not recommended.
2407   * You should first call allegro_gl_unset_allegro_mode() to restore the
2408   * original OpenGL matrices. After that, you may freely call any OpenGL
2409   * command. Don't forget to call back allegro_gl_set_allegro_mode() to switch
2410   * back to Allegro commands.
2411   *
2412   * AllegroGL saves the current OpenGL state with glPushAttrib so you should
2413   * make sure that at least one level is available in the attribute stack
2414   * otherwise the next call to allegro_gl_unset_allegro_mode() may fail.
2415   *
2416   * Also note that allegro_gl_set_allegro_mode() implicitely calls
2417   * allegro_gl_set_projection() so you do not need to do it yourself.
2418   *
2419   * \sa	allegro_gl_unset_allegro_mode() allegro_gl_set_projection()
2420   * \sa allegro_gl_unset_projection()
2421   */
allegro_gl_set_allegro_mode(void)2422 void allegro_gl_set_allegro_mode(void)
2423 {
2424 	AGL_LOG(2, "glvtable.c:allegro_gl_set_allegro_mode\n");
2425 
2426 	/* Save the OpenGL state  then set it up */
2427 	glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_TRANSFORM_BIT
2428 	           | GL_POINT_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2429 	glDisable(GL_DEPTH_TEST);
2430 	glDisable(GL_CULL_FACE);
2431 	glDisable(GL_FOG);
2432 	glDisable(GL_LIGHTING);
2433 	glDisable(GL_BLEND);
2434 	glDisable(GL_ALPHA_TEST);
2435 	glDepthMask(GL_FALSE);
2436 	glEnable(GL_TEXTURE_2D);
2437 	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2438 	glPointSize(1.);
2439 
2440 	/* Create pool texture */
2441 	if (!__allegro_gl_pool_texture) {
2442 		glGenTextures(1, &__allegro_gl_pool_texture);
2443 	}
2444 
2445 	glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
2446 		/* Create a texture without defining the data */
2447 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0,
2448 	             GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2449 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2450 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2451 
2452 	glBindTexture(GL_TEXTURE_2D, 0);
2453 	allegro_gl_set_projection();
2454 
2455 	/* For some reason, ATI Rage Pro isn't able to draw correctly without a
2456 	 * texture bound. So we bind a dummy 1x1 texture to work around the issue.
2457 	 */
2458 	if (allegro_gl_info.is_ati_rage_pro) {
2459 		if (!__allegro_gl_dummy_texture) {
2460 			GLubyte tex[4] = {255, 255, 255, 255};
2461 			glGenTextures(1, &__allegro_gl_dummy_texture);
2462 			glBindTexture(GL_TEXTURE_2D, __allegro_gl_dummy_texture);
2463 			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0,
2464 			             GL_RGBA, GL_UNSIGNED_BYTE, tex);
2465 		}
2466 		glBindTexture(GL_TEXTURE_2D, __allegro_gl_dummy_texture);
2467 	}
2468 #ifdef ALLEGRO_MACOSX
2469 	/* MacOSX 10.2.x has a bug: glRasterPos causes a crash (it is used in
2470 	 *'blit'). This stops it happening.
2471 	 */
2472 	glBegin(GL_POINTS);
2473 	glEnd();
2474 #endif
2475 }
2476 
2477 
2478 
2479 /** \ingroup allegro
2480   * Restores previous OpenGL settings.
2481   *
2482   * Restores the OpenGL state that have saved during the last call of
2483   * allegro_gl_set_allegro_mode().
2484   *
2485   * Note that allegro_gl_unset_allegro_mode implicitely calls
2486   * allegro_gl_unset_projection() so you do not need to do it yourself.
2487   *
2488   * \sa	allegro_gl_set_allegro_mode() allegro_gl_set_projection()
2489   * \sa allegro_gl_unset_projection()
2490   */
allegro_gl_unset_allegro_mode(void)2491 void allegro_gl_unset_allegro_mode(void)
2492 {
2493 	AGL_LOG(2, "glvtable.c:allegro_gl_unset_allegro_mode\n");
2494 
2495 	switch(allegro_gl_display_info.vidmem_policy) {
2496 		case AGL_KEEP:
2497 			break;
2498 		case AGL_RELEASE:
2499 			if (__allegro_gl_pool_texture) {
2500 				glDeleteTextures(1, &__allegro_gl_pool_texture);
2501 				__allegro_gl_pool_texture = 0;
2502 			}
2503 			break;
2504 	}
2505 	allegro_gl_unset_projection();
2506 	glPopAttrib();
2507 }
2508 
2509 
2510 
2511 /** \ingroup allegro
2512   * Prepares for Allegro drawing to the screen.
2513   *
2514   * This function sets the OpenGL projection and modelview matrices so
2515   * that 2D OpenGL coordinates match the usual Allegro coordinate system.
2516   *
2517   * OpenGL uses a completely different coordinate system than Allegro. So
2518   * to be able to use Allegro operations on the screen, you first need
2519   * to properly set up the OpenGL projection and modelview matrices.
2520   * AllegroGL provides this set of functions to allow proper alignment of
2521   * OpenGL coordinates with their Allegro counterparts.
2522   *
2523   * Since AllegroGL actually calls OpenGL commands to perform Allegro functions
2524   * for 2D drawing, some OpenGL capabilities such as texturing or depth testing
2525   * may interfer with those operations. In order to prevent such inconveniences,
2526   * you should call allegro_gl_set_allegro_mode() instead of
2527   * allegro_gl_set_projection()
2528   *
2529   * allegro_gl_set_projection() and allegro_gl_unset_projection() are not
2530   * nestable, which means that you should not call allegro_gl_set_projection()
2531   * inside another allegro_gl_set_projection() block. Similarly for
2532   * allegro_gl_unset_projection().
2533   *
2534   * Have a look at examp/exalleg.c for an example of
2535   * combining Allegro drawing commands and OpenGL.
2536   *
2537   * \sa allegro_gl_unset_projection() allegro_gl_set_allegro_mode()
2538   * \sa allegro_gl_unset_allegro_mode()
2539   */
allegro_gl_set_projection(void)2540 void allegro_gl_set_projection(void)
2541 {
2542 	GLint v[4];
2543 	AGL_LOG(2, "glvtable.c:allegro_gl_set_projection\n");
2544 
2545 	/* Setup OpenGL matrices */
2546 	glGetIntegerv(GL_VIEWPORT, &v[0]);
2547 	glMatrixMode(GL_MODELVIEW);
2548 	glGetDoublev(GL_MODELVIEW_MATRIX, allegro_gl_modelview_matrix);
2549 	glLoadIdentity();
2550 	glMatrixMode(GL_PROJECTION);
2551 	glGetDoublev(GL_PROJECTION_MATRIX, allegro_gl_projection_matrix);
2552 	glLoadIdentity();
2553 	gluOrtho2D(v[0] - 0.325, v[0] + v[2] - 0.325, v[1] + v[3] - 0.325, v[1] - 0.325);
2554 }
2555 
2556 
2557 
2558 /** \ingroup allegro
2559   * Restores previously saved projection.
2560   *
2561   * This function returns the projection and modelview matrices to their
2562   * state before the last allegro_gl_set_projection() was called.
2563   *
2564   * \sa allegro_gl_set_projection() allegro_gl_set_allegro_mode()
2565   * \sa allegro_gl_unset_allegro_mode()
2566   */
allegro_gl_unset_projection(void)2567 void allegro_gl_unset_projection(void)
2568 {
2569 	AGL_LOG(2, "glvtable.c:allegro_gl_unset_projection\n");
2570 	glMatrixMode(GL_PROJECTION);
2571 	glLoadMatrixd(allegro_gl_projection_matrix);
2572 	glMatrixMode(GL_MODELVIEW);
2573 	glLoadMatrixd(allegro_gl_modelview_matrix);
2574 }
2575 
2576 
2577 
allegro_gl_memory_blit_between_formats(struct BITMAP * src,struct BITMAP * dest,int source_x,int source_y,int dest_x,int dest_y,int width,int height)2578 void allegro_gl_memory_blit_between_formats(struct BITMAP *src,
2579     struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y,
2580     int width, int height)
2581 {
2582 	AGL_LOG(2, "AGL::blit_between_formats\n");
2583 
2584 	/* screen -> memory */
2585 	if (is_screen_bitmap(src)) {
2586 		allegro_gl_screen_blit_to_memory(src, dest, source_x, source_y,
2587 		                                 dest_x, dest_y, width, height);
2588 		return;
2589 	}
2590 
2591 	/* video -> memory */
2592 	if (is_video_bitmap(src)) {
2593 		allegro_gl_video_blit_to_memory(src, dest, source_x, source_y,
2594 		                                dest_x, dest_y, width, height);
2595 		return;
2596 	}
2597 
2598 	/* memory -> screen */
2599 	if (is_screen_bitmap(dest)) {
2600 		allegro_gl_screen_blit_from_memory(src, dest, source_x, source_y,
2601 		                                   dest_x, dest_y, width, height);
2602 		return;
2603 	}
2604 
2605 	/* memory -> video */
2606 	if (is_video_bitmap(dest)) {
2607 		allegro_gl_video_blit_from_memory(src, dest, source_x, source_y,
2608 		                                  dest_x, dest_y, width, height);
2609 		return;
2610 	}
2611 
2612 	switch(bitmap_color_depth(dest)) {
2613 		#ifdef ALLEGRO_COLOR8
2614 		case 8:
2615 			__blit_between_formats8(src, dest, source_x, source_y,
2616 			                        dest_x, dest_y, width, height);
2617 			return;
2618 		#endif
2619 		#ifdef ALLEGRO_COLOR16
2620 		case 15:
2621 			__blit_between_formats15(src, dest, source_x, source_y,
2622 			                         dest_x, dest_y, width, height);
2623 			return;
2624 		case 16:
2625 			__blit_between_formats16(src, dest, source_x, source_y,
2626 			                         dest_x, dest_y, width, height);
2627 			return;
2628 		#endif
2629 		#ifdef ALLEGRO_COLOR24
2630 		case 24:
2631 			__blit_between_formats24(src, dest, source_x, source_y,
2632 			                         dest_x, dest_y, width, height);
2633 			return;
2634 		#endif
2635 		#ifdef ALLEGRO_COLOR32
2636 		case 32:
2637 			__blit_between_formats32(src, dest, source_x, source_y,
2638 			                         dest_x, dest_y, width, height);
2639 			return;
2640 		#endif
2641 		default:
2642 			TRACE("--== ERROR ==-- AGL::blit_between_formats : %i -> %i bpp\n",
2643 			      bitmap_color_depth(src), bitmap_color_depth(dest));
2644 			return;
2645 	}
2646 }
2647 
2648 
2649 
dummy_unwrite_bank(void)2650 static void dummy_unwrite_bank(void)
2651 {
2652 }
2653 
2654 
2655 
2656 static GFX_VTABLE allegro_gl_screen_vtable = {
2657 	0,
2658 	0,
2659 	dummy_unwrite_bank,			//void *unwrite_bank;
2660 	NULL,						//AL_METHOD(void, set_clip, (struct BITMAP *bmp));
2661 	allegro_gl_screen_acquire,
2662 	allegro_gl_screen_release,
2663 	NULL,						//AL_METHOD(struct BITMAP *, create_sub_bitmap, (struct BITMAP *parent, int x, int y, int width, int height));
2664 	NULL,						//AL_METHOD(void, created_sub_bitmap, (struct BITMAP *bmp, struct BITMAP *parent));
2665 	allegro_gl_screen_getpixel,
2666 	allegro_gl_screen_putpixel,
2667 	allegro_gl_screen_vline,
2668 	allegro_gl_screen_hline,
2669 	allegro_gl_screen_hline,
2670 	allegro_gl_screen_line,
2671 	allegro_gl_screen_line,
2672 	allegro_gl_screen_rectfill,
2673 	allegro_gl_screen_triangle,
2674 	allegro_gl_screen_draw_sprite,
2675 	allegro_gl_screen_draw_256_sprite,
2676 	allegro_gl_screen_draw_sprite_v_flip,
2677 	allegro_gl_screen_draw_sprite_h_flip,
2678 	allegro_gl_screen_draw_sprite_vh_flip,
2679 	allegro_gl_screen_draw_trans_rgba_sprite,
2680 	allegro_gl_screen_draw_trans_rgba_sprite,
2681 	NULL,						//AL_METHOD(void, draw_lit_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color));
2682 	allegro_gl_screen_draw_rle_sprite,
2683 	allegro_gl_screen_draw_trans_rgba_rle_sprite,
2684 	allegro_gl_screen_draw_trans_rgba_rle_sprite,
2685 	NULL,						//AL_METHOD(void, draw_lit_rle_sprite, (struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y, int color));
2686 	allegro_gl_screen_draw_character,
2687 	allegro_gl_screen_draw_glyph,
2688 	allegro_gl_screen_blit_from_memory,
2689 	allegro_gl_screen_blit_to_memory,
2690 	NULL,						//AL_METHOD(void, blit_from_system, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height));
2691 	NULL,						//AL_METHOD(void, blit_to_system, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height));
2692 	allegro_gl_screen_blit_to_self,
2693 	allegro_gl_screen_blit_to_self, /* ..._forward */
2694 	allegro_gl_screen_blit_to_self, /* ..._backward */
2695 	allegro_gl_memory_blit_between_formats,
2696 	allegro_gl_screen_masked_blit,
2697 	allegro_gl_screen_clear_to_color,
2698 	allegro_gl_screen_pivot_scaled_sprite_flip,
2699 	NULL,                       //AL_METHOD(void, do_stretch_blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height, int masked));
2700 	NULL,                       //AL_METHOD(void, draw_gouraud_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int c1, int c2, int c3, int c4));
2701 	NULL,                       //AL_METHOD(void, draw_sprite_end, (void));
2702 	NULL,                       //AL_METHOD(void, blit_end, (void));
2703 	allegro_gl_screen_polygon,
2704 	allegro_gl_screen_rect,
2705 	_soft_circle,               //AL_METHOD(void, circle, (struct BITMAP *bmp, int x, int y, int radius, int color));
2706 	_soft_circlefill,           //AL_METHOD(void, circlefill, (struct BITMAP *bmp, int x, int y, int radius, int color));
2707 	_soft_ellipse,              //AL_METHOD(void, ellipse, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color));
2708 	_soft_ellipsefill,          //AL_METHOD(void, ellipsefill, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color));
2709 	_soft_arc,                  //AL_METHOD(void, arc, (struct BITMAP *bmp, int x, int y, fixed ang1, fixed ang2, int r, int color));
2710 	_soft_spline,               //AL_METHOD(void, spline, (struct BITMAP *bmp, AL_CONST int points[8], int color));
2711 	_soft_floodfill,            //AL_METHOD(void, floodfill, (struct BITMAP *bmp, int x, int y, int color));
2712 	allegro_gl_screen_polygon3d,
2713 	allegro_gl_screen_polygon3d_f,
2714 	allegro_gl_screen_triangle3d,
2715 	allegro_gl_screen_triangle3d_f,
2716 	allegro_gl_screen_quad3d,
2717 	allegro_gl_screen_quad3d_f,
2718 	allegro_gl_screen_draw_sprite_ex
2719 };
2720 
2721 /** \} */
2722