1 /* ______ ___ ___
2 * /\ _ \ /\_ \ /\_ \
3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8 * /\____/
9 * \_/__/
10 *
11 * OpenGL routines common to all OpenGL drivers.
12 *
13 * By Elias Pschernig and Milan Mimica.
14 *
15 */
16
17 #include "allegro5/allegro.h"
18 #include "allegro5/allegro_opengl.h"
19 #include "allegro5/internal/aintern.h"
20 #include "allegro5/internal/aintern_opengl.h"
21 #include "allegro5/internal/aintern_pixels.h"
22 #include "allegro5/transformations.h"
23
24 #ifdef ALLEGRO_IPHONE
25 #include "allegro5/internal/aintern_iphone.h"
26 #endif
27
28 #ifdef ALLEGRO_ANDROID
29 #include "allegro5/internal/aintern_android.h"
30 #endif
31
32 #include "ogl_helpers.h"
33
34 ALLEGRO_DEBUG_CHANNEL("opengl")
35
36 /* Helper to set up GL state as we want it. */
_al_ogl_setup_gl(ALLEGRO_DISPLAY * d)37 void _al_ogl_setup_gl(ALLEGRO_DISPLAY *d)
38 {
39 ALLEGRO_OGL_EXTRAS *ogl = d->ogl_extras;
40
41 if (ogl->backbuffer) {
42 ALLEGRO_BITMAP *target = al_get_target_bitmap();
43 _al_ogl_resize_backbuffer(ogl->backbuffer, d->w, d->h);
44 /* If we are currently targetting the backbuffer, we need to update the
45 * transformations. */
46 if (target && (target == ogl->backbuffer ||
47 target->parent == ogl->backbuffer)) {
48 /* vt should be set at this point, but doesn't hurt to check */
49 ASSERT(d->vt);
50 d->vt->update_transformation(d, target);
51 }
52 } else {
53 ogl->backbuffer = _al_ogl_create_backbuffer(d);
54 }
55 }
56
57
_al_ogl_set_target_bitmap(ALLEGRO_DISPLAY * display,ALLEGRO_BITMAP * bitmap)58 void _al_ogl_set_target_bitmap(ALLEGRO_DISPLAY *display, ALLEGRO_BITMAP *bitmap)
59 {
60 ALLEGRO_BITMAP *target = bitmap;
61 if (bitmap->parent)
62 target = bitmap->parent;
63
64 /* if either this bitmap or its parent (in the case of subbitmaps)
65 * is locked then don't do anything
66 */
67 if (bitmap->locked)
68 return;
69 if (bitmap->parent && bitmap->parent->locked)
70 return;
71
72 _al_ogl_setup_fbo(display, bitmap);
73 if (display->ogl_extras->opengl_target == target) {
74 _al_ogl_setup_bitmap_clipping(bitmap);
75 }
76 }
77
78
_al_ogl_unset_target_bitmap(ALLEGRO_DISPLAY * display,ALLEGRO_BITMAP * target)79 void _al_ogl_unset_target_bitmap(ALLEGRO_DISPLAY *display,
80 ALLEGRO_BITMAP *target)
81 {
82 if (!target)
83 return;
84 _al_ogl_finalize_fbo(display, target);
85 }
86
87
88 /* Function: al_set_current_opengl_context
89 */
al_set_current_opengl_context(ALLEGRO_DISPLAY * display)90 void al_set_current_opengl_context(ALLEGRO_DISPLAY *display)
91 {
92 ASSERT(display);
93
94 if (!(display->flags & ALLEGRO_OPENGL))
95 return;
96
97 if (display) {
98 ALLEGRO_BITMAP *bmp = al_get_target_bitmap();
99 if (bmp && _al_get_bitmap_display(bmp) &&
100 _al_get_bitmap_display(bmp) != display) {
101 al_set_target_bitmap(NULL);
102 }
103 }
104
105 _al_set_current_display_only(display);
106 }
107
108
_al_ogl_setup_bitmap_clipping(const ALLEGRO_BITMAP * bitmap)109 void _al_ogl_setup_bitmap_clipping(const ALLEGRO_BITMAP *bitmap)
110 {
111 int x_1, y_1, x_2, y_2, h;
112 bool use_scissor = true;
113
114 x_1 = bitmap->cl;
115 y_1 = bitmap->ct;
116 x_2 = bitmap->cr_excl;
117 y_2 = bitmap->cb_excl;
118 h = bitmap->h;
119
120 /* Drawing onto the sub bitmap is handled by clipping the parent. */
121 if (bitmap->parent) {
122 x_1 += bitmap->xofs;
123 y_1 += bitmap->yofs;
124 x_2 += bitmap->xofs;
125 y_2 += bitmap->yofs;
126 h = bitmap->parent->h;
127 }
128
129 if (x_1 == 0 && y_1 == 0 && x_2 == bitmap->w && y_2 == bitmap->h) {
130 if (bitmap->parent) {
131 /* Can only disable scissor if the sub-bitmap covers the
132 * complete parent.
133 */
134 if (bitmap->xofs == 0 && bitmap->yofs == 0 &&
135 bitmap->w == bitmap->parent->w && bitmap->h == bitmap->parent->h)
136 {
137 use_scissor = false;
138 }
139 }
140 else {
141 use_scissor = false;
142 }
143 }
144 if (!use_scissor) {
145 glDisable(GL_SCISSOR_TEST);
146 }
147 else {
148 glEnable(GL_SCISSOR_TEST);
149
150 #ifdef ALLEGRO_IPHONE
151 _al_iphone_clip(bitmap, x_1, y_1, x_2, y_2);
152 #else
153 /* OpenGL is upside down, so must adjust y_2 to the height. */
154 glScissor(x_1, h - y_2, x_2 - x_1, y_2 - y_1);
155 #endif
156 }
157 }
158
159
_al_ogl_get_backbuffer(ALLEGRO_DISPLAY * d)160 ALLEGRO_BITMAP *_al_ogl_get_backbuffer(ALLEGRO_DISPLAY *d)
161 {
162 return (ALLEGRO_BITMAP *)d->ogl_extras->backbuffer;
163 }
164
165
_al_ogl_resize_backbuffer(ALLEGRO_BITMAP * b,int w,int h)166 bool _al_ogl_resize_backbuffer(ALLEGRO_BITMAP *b, int w, int h)
167 {
168 int pitch;
169 ALLEGRO_BITMAP_EXTRA_OPENGL *extra = b->extra;
170
171 pitch = w * al_get_pixel_size(al_get_bitmap_format(b));
172
173 b->w = w;
174 b->h = h;
175 b->pitch = pitch;
176 b->cl = 0;
177 b->ct = 0;
178 b->cr_excl = w;
179 b->cb_excl = h;
180 al_identity_transform(&b->proj_transform);
181 al_orthographic_transform(&b->proj_transform, 0, 0, -1.0, w, h, 1.0);
182
183 /* There is no texture associated with the backbuffer so no need to care
184 * about texture size limitations. */
185 extra->true_w = w;
186 extra->true_h = h;
187
188 b->memory = NULL;
189
190 return true;
191 }
192
193
_al_ogl_create_backbuffer(ALLEGRO_DISPLAY * disp)194 ALLEGRO_BITMAP* _al_ogl_create_backbuffer(ALLEGRO_DISPLAY *disp)
195 {
196 ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_backbuffer;
197 ALLEGRO_BITMAP *backbuffer;
198 int format;
199
200 ALLEGRO_DEBUG("Creating backbuffer\n");
201
202 // FIXME: _al_deduce_color_format would work fine if the display paramerers
203 // are filled in, for OpenGL ES
204 if (IS_OPENGLES) {
205 if (disp->extra_settings.settings[ALLEGRO_COLOR_SIZE] == 16) {
206 format = ALLEGRO_PIXEL_FORMAT_RGB_565;
207 }
208 else {
209 format = ALLEGRO_PIXEL_FORMAT_ABGR_8888_LE;
210 }
211 }
212 else {
213 format = _al_deduce_color_format(&disp->extra_settings);
214 /* Eww. No OpenGL hardware in the world does that - let's just
215 * switch to some default.
216 */
217 if (al_get_pixel_size(format) == 3) {
218 /* Or should we use RGBA? Maybe only if not Nvidia cards? */
219 format = ALLEGRO_PIXEL_FORMAT_ABGR_8888;
220 }
221 }
222 ALLEGRO_TRACE_CHANNEL_LEVEL("display", 1)("Deduced format %s for backbuffer.\n",
223 _al_pixel_format_name(format));
224
225 /* Now that the display backbuffer has a format, update extra_settings so
226 * the user can query it back.
227 */
228 _al_set_color_components(format, &disp->extra_settings, ALLEGRO_REQUIRE);
229 disp->backbuffer_format = format;
230
231 ALLEGRO_DEBUG("Creating backbuffer bitmap\n");
232 /* Using ALLEGRO_NO_PRESERVE_TEXTURE prevents extra memory being allocated */
233 backbuffer = _al_ogl_create_bitmap(disp, disp->w, disp->h,
234 format, ALLEGRO_VIDEO_BITMAP | ALLEGRO_NO_PRESERVE_TEXTURE);
235 if (!backbuffer) {
236 ALLEGRO_DEBUG("Backbuffer bitmap creation failed.\n");
237 return NULL;
238 }
239
240 backbuffer->w = disp->w;
241 backbuffer->h = disp->h;
242 backbuffer->cl = 0;
243 backbuffer->ct = 0;
244 backbuffer->cr_excl = disp->w;
245 backbuffer->cb_excl = disp->h;
246 al_identity_transform(&backbuffer->transform);
247 al_identity_transform(&backbuffer->proj_transform);
248 al_orthographic_transform(&backbuffer->proj_transform, 0, 0, -1.0, disp->w, disp->h, 1.0);
249
250 ALLEGRO_TRACE_CHANNEL_LEVEL("display", 1)(
251 "Created backbuffer bitmap (actual format: %s)\n",
252 _al_pixel_format_name(al_get_bitmap_format(backbuffer)));
253
254 ogl_backbuffer = backbuffer->extra;
255 ogl_backbuffer->true_w = disp->w;
256 ogl_backbuffer->true_h = disp->h;
257 ogl_backbuffer->is_backbuffer = 1;
258 backbuffer->_display = disp;
259
260 return backbuffer;
261 }
262
263
_al_ogl_destroy_backbuffer(ALLEGRO_BITMAP * b)264 void _al_ogl_destroy_backbuffer(ALLEGRO_BITMAP *b)
265 {
266 al_destroy_bitmap(b);
267 }
268
269
270 /* vi: set sts=3 sw=3 et: */
271