1 /* ______ ___ ___
2 * /\ _ \ /\_ \ /\_ \
3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8 * /\____/
9 * \_/__/
10 *
11 * OpenGL implementation of some of the primitive routines.
12 *
13 *
14 * By Pavel Sountsov.
15 *
16 * See readme.txt for copyright information.
17 */
18
19 #define ALLEGRO_INTERNAL_UNSTABLE
20
21 #include "allegro5/allegro.h"
22 #include "allegro5/allegro_primitives.h"
23 #include "allegro5/allegro_opengl.h"
24 #include "allegro5/internal/aintern_prim_opengl.h"
25 #include "allegro5/internal/aintern_prim_soft.h"
26 #include "allegro5/platform/alplatf.h"
27 #include "allegro5/internal/aintern_prim.h"
28
29 #ifdef ALLEGRO_CFG_OPENGL
30
31 #include "allegro5/allegro_opengl.h"
32 #include "allegro5/internal/aintern_opengl.h"
33
convert_storage(ALLEGRO_PRIM_STORAGE storage,GLenum * type,int * ncoord,bool * normalized)34 static void convert_storage(ALLEGRO_PRIM_STORAGE storage, GLenum* type, int* ncoord, bool* normalized)
35 {
36 switch(storage) {
37 case ALLEGRO_PRIM_FLOAT_2:
38 *type = GL_FLOAT;
39 *ncoord = 2;
40 *normalized = false;
41 break;
42 case ALLEGRO_PRIM_FLOAT_3:
43 *type = GL_FLOAT;
44 *ncoord = 3;
45 *normalized = false;
46 break;
47 case ALLEGRO_PRIM_SHORT_2:
48 *type = GL_SHORT;
49 *ncoord = 2;
50 *normalized = false;
51 break;
52 case ALLEGRO_PRIM_FLOAT_1:
53 *type = GL_FLOAT;
54 *ncoord = 1;
55 *normalized = false;
56 break;
57 case ALLEGRO_PRIM_FLOAT_4:
58 *type = GL_FLOAT;
59 *ncoord = 4;
60 *normalized = false;
61 break;
62 case ALLEGRO_PRIM_UBYTE_4:
63 *type = GL_UNSIGNED_BYTE;
64 *ncoord = 4;
65 *normalized = false;
66 break;
67 case ALLEGRO_PRIM_SHORT_4:
68 *type = GL_SHORT;
69 *ncoord = 4;
70 *normalized = false;
71 break;
72 case ALLEGRO_PRIM_NORMALIZED_UBYTE_4:
73 *type = GL_UNSIGNED_BYTE;
74 *ncoord = 4;
75 *normalized = true;
76 break;
77 case ALLEGRO_PRIM_NORMALIZED_SHORT_2:
78 *type = GL_SHORT;
79 *ncoord = 2;
80 *normalized = true;
81 break;
82 case ALLEGRO_PRIM_NORMALIZED_SHORT_4:
83 *type = GL_SHORT;
84 *ncoord = 4;
85 *normalized = true;
86 break;
87 case ALLEGRO_PRIM_NORMALIZED_USHORT_2:
88 *type = GL_UNSIGNED_SHORT;
89 *ncoord = 2;
90 *normalized = true;
91 break;
92 case ALLEGRO_PRIM_NORMALIZED_USHORT_4:
93 *type = GL_UNSIGNED_SHORT;
94 *ncoord = 4;
95 *normalized = true;
96 break;
97 #ifndef ALLEGRO_CFG_OPENGLES
98 case ALLEGRO_PRIM_HALF_FLOAT_2:
99 *type = GL_HALF_FLOAT;
100 *ncoord = 2;
101 *normalized = false;
102 break;
103 case ALLEGRO_PRIM_HALF_FLOAT_4:
104 *type = GL_HALF_FLOAT;
105 *ncoord = 4;
106 *normalized = false;
107 break;
108 #endif
109 default:
110 ASSERT(0);
111 }
112 }
113
setup_state(const char * vtxs,const ALLEGRO_VERTEX_DECL * decl,ALLEGRO_BITMAP * texture)114 static void setup_state(const char* vtxs, const ALLEGRO_VERTEX_DECL* decl, ALLEGRO_BITMAP* texture)
115 {
116 ALLEGRO_DISPLAY *display = al_get_current_display();
117 GLenum type;
118 int ncoord;
119 bool normalized;
120
121 if (display->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) {
122 #ifdef ALLEGRO_CFG_OPENGL_PROGRAMMABLE_PIPELINE
123 if(decl) {
124 ALLEGRO_VERTEX_ELEMENT* e;
125 int i;
126
127 e = &decl->elements[ALLEGRO_PRIM_POSITION];
128 if(e->attribute) {
129 convert_storage(e->storage, &type, &ncoord, &normalized);
130
131 if (display->ogl_extras->varlocs.pos_loc >= 0) {
132 glVertexAttribPointer(display->ogl_extras->varlocs.pos_loc, ncoord, type, normalized, decl->stride, vtxs + e->offset);
133 glEnableVertexAttribArray(display->ogl_extras->varlocs.pos_loc);
134 }
135 } else {
136 if (display->ogl_extras->varlocs.pos_loc >= 0) {
137 glDisableVertexAttribArray(display->ogl_extras->varlocs.pos_loc);
138 }
139 }
140
141 e = &decl->elements[ALLEGRO_PRIM_TEX_COORD];
142 if(!e->attribute)
143 e = &decl->elements[ALLEGRO_PRIM_TEX_COORD_PIXEL];
144 if(e->attribute) {
145 convert_storage(e->storage, &type, &ncoord, &normalized);
146
147 if (display->ogl_extras->varlocs.texcoord_loc >= 0) {
148 glVertexAttribPointer(display->ogl_extras->varlocs.texcoord_loc, ncoord, type, normalized, decl->stride, vtxs + e->offset);
149 glEnableVertexAttribArray(display->ogl_extras->varlocs.texcoord_loc);
150 }
151 } else {
152 if (display->ogl_extras->varlocs.texcoord_loc >= 0) {
153 glDisableVertexAttribArray(display->ogl_extras->varlocs.texcoord_loc);
154 }
155 }
156
157 e = &decl->elements[ALLEGRO_PRIM_COLOR_ATTR];
158 if(e->attribute) {
159 if (display->ogl_extras->varlocs.color_loc >= 0) {
160 glVertexAttribPointer(display->ogl_extras->varlocs.color_loc, 4, GL_FLOAT, true, decl->stride, vtxs + e->offset);
161 glEnableVertexAttribArray(display->ogl_extras->varlocs.color_loc);
162 }
163 } else {
164 if (display->ogl_extras->varlocs.color_loc >= 0) {
165 glDisableVertexAttribArray(display->ogl_extras->varlocs.color_loc);
166 }
167 }
168
169 for (i = 0; i < _ALLEGRO_PRIM_MAX_USER_ATTR; i++) {
170 e = &decl->elements[ALLEGRO_PRIM_USER_ATTR + i];
171 if (e->attribute) {
172 convert_storage(e->storage, &type, &ncoord, &normalized);
173
174 if (display->ogl_extras->varlocs.user_attr_loc[i] >= 0) {
175 glVertexAttribPointer(display->ogl_extras->varlocs.user_attr_loc[i], ncoord, type, normalized, decl->stride, vtxs + e->offset);
176 glEnableVertexAttribArray(display->ogl_extras->varlocs.user_attr_loc[i]);
177 }
178 } else {
179 if (display->ogl_extras->varlocs.user_attr_loc[i] >= 0) {
180 glDisableVertexAttribArray(display->ogl_extras->varlocs.user_attr_loc[i]);
181 }
182 }
183 }
184 } else {
185 if (display->ogl_extras->varlocs.pos_loc >= 0) {
186 glVertexAttribPointer(display->ogl_extras->varlocs.pos_loc, 3, GL_FLOAT, false, sizeof(ALLEGRO_VERTEX), vtxs + offsetof(ALLEGRO_VERTEX, x));
187 glEnableVertexAttribArray(display->ogl_extras->varlocs.pos_loc);
188 }
189
190 if (display->ogl_extras->varlocs.texcoord_loc >= 0) {
191 glVertexAttribPointer(display->ogl_extras->varlocs.texcoord_loc, 2, GL_FLOAT, false, sizeof(ALLEGRO_VERTEX), vtxs + offsetof(ALLEGRO_VERTEX, u));
192 glEnableVertexAttribArray(display->ogl_extras->varlocs.texcoord_loc);
193 }
194
195 if (display->ogl_extras->varlocs.color_loc >= 0) {
196 glVertexAttribPointer(display->ogl_extras->varlocs.color_loc, 4, GL_FLOAT, true, sizeof(ALLEGRO_VERTEX), vtxs + offsetof(ALLEGRO_VERTEX, color));
197 glEnableVertexAttribArray(display->ogl_extras->varlocs.color_loc);
198 }
199 }
200 #endif
201 }
202 else {
203 #ifdef ALLEGRO_CFG_OPENGL_FIXED_FUNCTION
204 if(decl) {
205 ALLEGRO_VERTEX_ELEMENT* e;
206 e = &decl->elements[ALLEGRO_PRIM_POSITION];
207 if(e->attribute) {
208 glEnableClientState(GL_VERTEX_ARRAY);
209
210 convert_storage(e->storage, &type, &ncoord, &normalized);
211
212 glVertexPointer(ncoord, type, decl->stride, vtxs + e->offset);
213 } else {
214 glDisableClientState(GL_VERTEX_ARRAY);
215 }
216
217 e = &decl->elements[ALLEGRO_PRIM_TEX_COORD];
218 if(!e->attribute)
219 e = &decl->elements[ALLEGRO_PRIM_TEX_COORD_PIXEL];
220 if(texture && e->attribute) {
221 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
222
223 convert_storage(e->storage, &type, &ncoord, &normalized);
224
225 glTexCoordPointer(ncoord, type, decl->stride, vtxs + e->offset);
226 } else {
227 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
228 }
229
230 e = &decl->elements[ALLEGRO_PRIM_COLOR_ATTR];
231 if(e->attribute) {
232 glEnableClientState(GL_COLOR_ARRAY);
233
234 glColorPointer(4, GL_FLOAT, decl->stride, vtxs + e->offset);
235 } else {
236 glDisableClientState(GL_COLOR_ARRAY);
237 glColor4f(1, 1, 1, 1);
238 }
239 } else {
240 glEnableClientState(GL_COLOR_ARRAY);
241 glEnableClientState(GL_VERTEX_ARRAY);
242 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
243 if (!(display->flags & ALLEGRO_PROGRAMMABLE_PIPELINE))
244 glDisableClientState(GL_NORMAL_ARRAY);
245
246 glVertexPointer(3, GL_FLOAT, sizeof(ALLEGRO_VERTEX), vtxs + offsetof(ALLEGRO_VERTEX, x));
247 glColorPointer(4, GL_FLOAT, sizeof(ALLEGRO_VERTEX), vtxs + offsetof(ALLEGRO_VERTEX, color));
248 glTexCoordPointer(2, GL_FLOAT, sizeof(ALLEGRO_VERTEX), vtxs + offsetof(ALLEGRO_VERTEX, u));
249 }
250 #endif
251 }
252
253 if (texture) {
254 GLuint gl_texture = al_get_opengl_texture(texture);
255 int true_w, true_h;
256 int tex_x, tex_y;
257 float mat[4][4] = {
258 {1, 0, 0, 0},
259 {0, -1, 0, 0},
260 {0, 0, 1, 0},
261 {0, 0, 0, 1}
262 };
263 int height;
264
265 if (texture->parent)
266 height = texture->parent->h;
267 else
268 height = texture->h;
269
270 al_get_opengl_texture_size(texture, &true_w, &true_h);
271 al_get_opengl_texture_position(texture, &tex_x, &tex_y);
272
273 mat[3][0] = (float)tex_x / true_w;
274 mat[3][1] = (float)(height - tex_y) / true_h;
275
276 if(decl) {
277 if(decl->elements[ALLEGRO_PRIM_TEX_COORD_PIXEL].attribute) {
278 mat[0][0] = 1.0f / true_w;
279 mat[1][1] = -1.0f / true_h;
280 } else {
281 mat[0][0] = (float)al_get_bitmap_width(texture) / true_w;
282 mat[1][1] = -(float)al_get_bitmap_height(texture) / true_h;
283 }
284 } else {
285 mat[0][0] = 1.0f / true_w;
286 mat[1][1] = -1.0f / true_h;
287 }
288
289 if (!(display->flags & ALLEGRO_PROGRAMMABLE_PIPELINE)) {
290 glBindTexture(GL_TEXTURE_2D, gl_texture);
291 }
292
293 if (display->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) {
294 #ifdef ALLEGRO_CFG_OPENGL_PROGRAMMABLE_PIPELINE
295 GLint handle;
296
297 handle = display->ogl_extras->varlocs.tex_matrix_loc;
298 if (handle >= 0)
299 glUniformMatrix4fv(handle, 1, false, (float *)mat);
300
301 handle = display->ogl_extras->varlocs.use_tex_matrix_loc;
302 if (handle >= 0)
303 glUniform1i(handle, 1);
304
305 if (display->ogl_extras->varlocs.use_tex_loc >= 0) {
306 glUniform1i(display->ogl_extras->varlocs.use_tex_loc, 1);
307 }
308 if (display->ogl_extras->varlocs.tex_loc >= 0) {
309 glActiveTexture(GL_TEXTURE0);
310 glBindTexture(GL_TEXTURE_2D, al_get_opengl_texture(texture));
311 glUniform1i(display->ogl_extras->varlocs.tex_loc, 0); // 0th sampler
312 }
313 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
314 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
315 #endif
316 }
317 else {
318 #ifdef ALLEGRO_CFG_OPENGL_FIXED_FUNCTION
319 glMatrixMode(GL_TEXTURE);
320 glLoadMatrixf(mat[0]);
321 glMatrixMode(GL_MODELVIEW);
322
323 glEnable(GL_TEXTURE_2D);
324 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
325 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
326 #endif
327 }
328 } else {
329 /* Don't unbind the texture here if shaders are used, since the user may
330 * have set the 0'th texture unit manually via the shader API. */
331 if (!(display->flags & ALLEGRO_PROGRAMMABLE_PIPELINE)) {
332 glBindTexture(GL_TEXTURE_2D, 0);
333 }
334 }
335 }
336
revert_state(ALLEGRO_BITMAP * texture)337 static void revert_state(ALLEGRO_BITMAP* texture)
338 {
339 ALLEGRO_DISPLAY *display = al_get_current_display();
340
341 if(texture) {
342 if (display->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) {
343 #ifdef ALLEGRO_CFG_OPENGL_PROGRAMMABLE_PIPELINE
344 float identity[16] = {
345 1, 0, 0, 0,
346 0, 1, 0, 0,
347 0, 0, 1, 0,
348 0, 0, 0, 1
349 };
350 GLint handle;
351 handle = display->ogl_extras->varlocs.tex_matrix_loc;
352 if (handle >= 0)
353 glUniformMatrix4fv(handle, 1, false, identity);
354 handle = display->ogl_extras->varlocs.use_tex_matrix_loc;
355 if (handle >= 0)
356 glUniform1i(handle, 0);
357 if (display->ogl_extras->varlocs.use_tex_loc >= 0)
358 glUniform1i(display->ogl_extras->varlocs.use_tex_loc, 0);
359 #endif
360 }
361 else {
362 #ifdef ALLEGRO_CFG_OPENGL_FIXED_FUNCTION
363 glDisable(GL_TEXTURE_2D);
364 glMatrixMode(GL_TEXTURE);
365 glLoadIdentity();
366 glMatrixMode(GL_MODELVIEW);
367 #endif
368 }
369 }
370
371 if (display->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) {
372 #ifdef ALLEGRO_CFG_OPENGL_PROGRAMMABLE_PIPELINE
373 if (display->ogl_extras->varlocs.pos_loc >= 0)
374 glDisableVertexAttribArray(display->ogl_extras->varlocs.pos_loc);
375 if (display->ogl_extras->varlocs.color_loc >= 0)
376 glDisableVertexAttribArray(display->ogl_extras->varlocs.color_loc);
377 if (display->ogl_extras->varlocs.texcoord_loc >= 0)
378 glDisableVertexAttribArray(display->ogl_extras->varlocs.texcoord_loc);
379 #endif
380 }
381 else {
382 #ifdef ALLEGRO_CFG_OPENGL_FIXED_FUNCTION
383 glDisableClientState(GL_COLOR_ARRAY);
384 glDisableClientState(GL_VERTEX_ARRAY);
385 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
386 #endif
387 }
388 }
389
draw_prim_raw(ALLEGRO_BITMAP * target,ALLEGRO_BITMAP * texture,ALLEGRO_VERTEX_BUFFER * vertex_buffer,const void * vtx,const ALLEGRO_VERTEX_DECL * decl,int start,int end,int type)390 static int draw_prim_raw(ALLEGRO_BITMAP* target, ALLEGRO_BITMAP* texture,
391 ALLEGRO_VERTEX_BUFFER* vertex_buffer,
392 const void* vtx, const ALLEGRO_VERTEX_DECL* decl,
393 int start, int end, int type)
394 {
395 int num_primitives = 0;
396 ALLEGRO_DISPLAY *disp = _al_get_bitmap_display(target);
397 ALLEGRO_BITMAP *opengl_target = target;
398 ALLEGRO_BITMAP_EXTRA_OPENGL *extra;
399 int num_vtx = end - start;
400
401 if (target->parent) {
402 opengl_target = target->parent;
403 }
404 extra = opengl_target->extra;
405
406 if ((!extra->is_backbuffer && disp->ogl_extras->opengl_target !=
407 opengl_target) || al_is_bitmap_locked(target)) {
408 if (vertex_buffer) {
409 return _al_draw_buffer_common_soft(vertex_buffer, texture, NULL, start, end, type);
410 }
411 else {
412 return _al_draw_prim_soft(texture, vtx, decl, start, end, type);
413 }
414 }
415
416 if (vertex_buffer) {
417 glBindBuffer(GL_ARRAY_BUFFER, (GLuint)vertex_buffer->common.handle);
418 }
419
420 _al_opengl_set_blender(disp);
421 setup_state(vtx, decl, texture);
422
423 switch (type) {
424 case ALLEGRO_PRIM_LINE_LIST: {
425 glDrawArrays(GL_LINES, start, num_vtx);
426 num_primitives = num_vtx / 2;
427 break;
428 };
429 case ALLEGRO_PRIM_LINE_STRIP: {
430 glDrawArrays(GL_LINE_STRIP, start, num_vtx);
431 num_primitives = num_vtx - 1;
432 break;
433 };
434 case ALLEGRO_PRIM_LINE_LOOP: {
435 glDrawArrays(GL_LINE_LOOP, start, num_vtx);
436 num_primitives = num_vtx;
437 break;
438 };
439 case ALLEGRO_PRIM_TRIANGLE_LIST: {
440 glDrawArrays(GL_TRIANGLES, start, num_vtx);
441 num_primitives = num_vtx / 3;
442 break;
443 };
444 case ALLEGRO_PRIM_TRIANGLE_STRIP: {
445 glDrawArrays(GL_TRIANGLE_STRIP, start, num_vtx);
446 num_primitives = num_vtx - 2;
447 break;
448 };
449 case ALLEGRO_PRIM_TRIANGLE_FAN: {
450 glDrawArrays(GL_TRIANGLE_FAN, start, num_vtx);
451 num_primitives = num_vtx - 2;
452 break;
453 };
454 case ALLEGRO_PRIM_POINT_LIST: {
455 glDrawArrays(GL_POINTS, start, num_vtx);
456 num_primitives = num_vtx;
457 break;
458 };
459 }
460
461 revert_state(texture);
462
463 if (vertex_buffer) {
464 glBindBuffer(GL_ARRAY_BUFFER, 0);
465 }
466
467 return num_primitives;
468 }
469
draw_prim_indexed_raw(ALLEGRO_BITMAP * target,ALLEGRO_BITMAP * texture,ALLEGRO_VERTEX_BUFFER * vertex_buffer,const void * vtx,const ALLEGRO_VERTEX_DECL * decl,ALLEGRO_INDEX_BUFFER * index_buffer,const int * indices,int start,int end,int type)470 static int draw_prim_indexed_raw(ALLEGRO_BITMAP* target, ALLEGRO_BITMAP* texture,
471 ALLEGRO_VERTEX_BUFFER* vertex_buffer,
472 const void* vtx, const ALLEGRO_VERTEX_DECL* decl,
473 ALLEGRO_INDEX_BUFFER* index_buffer,
474 const int* indices,
475 int start, int end, int type)
476 {
477 int num_primitives = 0;
478 ALLEGRO_DISPLAY *disp = _al_get_bitmap_display(target);
479 ALLEGRO_BITMAP *opengl_target = target;
480 ALLEGRO_BITMAP_EXTRA_OPENGL *extra;
481 const char* idx = (const char*)indices;
482 int start_offset = 0;
483 GLenum idx_size = GL_UNSIGNED_INT;
484 bool use_buffers = index_buffer != NULL;
485 int num_vtx = end - start;
486 #if defined ALLEGRO_IPHONE
487 GLushort* iphone_idx = NULL;
488 #endif
489
490 if (use_buffers) {
491 idx_size = index_buffer->index_size == 4 ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
492 start_offset = start * index_buffer->index_size;
493 }
494
495 if (target->parent) {
496 opengl_target = target->parent;
497 }
498 extra = opengl_target->extra;
499
500 if ((!extra->is_backbuffer && disp->ogl_extras->opengl_target !=
501 opengl_target) || al_is_bitmap_locked(target)) {
502 if (use_buffers) {
503 return _al_draw_buffer_common_soft(vertex_buffer, texture, index_buffer, start, end, type);
504 }
505 else {
506 return _al_draw_prim_indexed_soft(texture, vtx, decl, indices, num_vtx, type);
507 }
508 }
509
510 #if defined ALLEGRO_IPHONE
511 if (!use_buffers) {
512 int ii;
513 iphone_idx = al_malloc(num_vtx * sizeof(GLushort));
514 for (ii = start; ii < end; ii++) {
515 iphone_idx[ii] = (GLushort)indices[ii];
516 }
517 idx = iphone_idx;
518 start = 0;
519 idx_size = GL_UNSIGNED_SHORT;
520 }
521 #endif
522
523 _al_opengl_set_blender(disp);
524
525 if (use_buffers) {
526 glBindBuffer(GL_ARRAY_BUFFER, (GLuint)vertex_buffer->common.handle);
527 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, (GLuint)index_buffer->common.handle);
528 }
529
530 setup_state(vtx, decl, texture);
531
532 switch (type) {
533 case ALLEGRO_PRIM_LINE_LIST: {
534 glDrawElements(GL_LINES, num_vtx, idx_size, idx + start_offset);
535 num_primitives = num_vtx / 2;
536 break;
537 };
538 case ALLEGRO_PRIM_LINE_STRIP: {
539 glDrawElements(GL_LINE_STRIP, num_vtx, idx_size, idx + start_offset);
540 num_primitives = num_vtx - 1;
541 break;
542 };
543 case ALLEGRO_PRIM_LINE_LOOP: {
544 /* Unimplemented, as it's too hard to do for Direct3D */
545 break;
546 };
547 case ALLEGRO_PRIM_TRIANGLE_LIST: {
548 glDrawElements(GL_TRIANGLES, num_vtx, idx_size, idx + start_offset);
549 num_primitives = num_vtx / 3;
550 break;
551 };
552 case ALLEGRO_PRIM_TRIANGLE_STRIP: {
553 glDrawElements(GL_TRIANGLE_STRIP, num_vtx, idx_size, idx + start_offset);
554 num_primitives = num_vtx - 2;
555 break;
556 };
557 case ALLEGRO_PRIM_TRIANGLE_FAN: {
558 glDrawElements(GL_TRIANGLE_FAN, num_vtx, idx_size, idx + start_offset);
559 num_primitives = num_vtx - 2;
560 break;
561 };
562 case ALLEGRO_PRIM_POINT_LIST: {
563 /* Unimplemented, as it's too hard to do for Direct3D */
564 break;
565 };
566 }
567
568 revert_state(texture);
569
570 if (use_buffers) {
571 glBindBuffer(GL_ARRAY_BUFFER, 0);
572 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
573 }
574
575 #if defined ALLEGRO_IPHONE
576 al_free(iphone_idx);
577 #endif
578
579 return num_primitives;
580 }
581
582 #endif /* ALLEGRO_CFG_OPENGL */
583
_al_draw_prim_opengl(ALLEGRO_BITMAP * target,ALLEGRO_BITMAP * texture,const void * vtxs,const ALLEGRO_VERTEX_DECL * decl,int start,int end,int type)584 int _al_draw_prim_opengl(ALLEGRO_BITMAP* target, ALLEGRO_BITMAP* texture, const void* vtxs, const ALLEGRO_VERTEX_DECL* decl, int start, int end, int type)
585 {
586 #ifdef ALLEGRO_CFG_OPENGL
587 return draw_prim_raw(target, texture, 0, vtxs, decl, start, end, type);
588 #else
589 (void)target;
590 (void)texture;
591 (void)vtxs;
592 (void)start;
593 (void)end;
594 (void)type;
595 (void)decl;
596
597 return 0;
598 #endif
599 }
600
_al_draw_vertex_buffer_opengl(ALLEGRO_BITMAP * target,ALLEGRO_BITMAP * texture,ALLEGRO_VERTEX_BUFFER * vertex_buffer,int start,int end,int type)601 int _al_draw_vertex_buffer_opengl(ALLEGRO_BITMAP* target, ALLEGRO_BITMAP* texture, ALLEGRO_VERTEX_BUFFER* vertex_buffer, int start, int end, int type)
602 {
603 #ifdef ALLEGRO_CFG_OPENGL
604 return draw_prim_raw(target, texture, vertex_buffer, 0, vertex_buffer->decl, start, end, type);
605 #else
606 (void)target;
607 (void)texture;
608 (void)vertex_buffer;
609 (void)start;
610 (void)end;
611 (void)type;
612
613 return 0;
614 #endif
615 }
616
_al_draw_prim_indexed_opengl(ALLEGRO_BITMAP * target,ALLEGRO_BITMAP * texture,const void * vtxs,const ALLEGRO_VERTEX_DECL * decl,const int * indices,int num_vtx,int type)617 int _al_draw_prim_indexed_opengl(ALLEGRO_BITMAP *target, ALLEGRO_BITMAP* texture, const void* vtxs, const ALLEGRO_VERTEX_DECL* decl, const int* indices, int num_vtx, int type)
618 {
619 #ifdef ALLEGRO_CFG_OPENGL
620 return draw_prim_indexed_raw(target, texture, NULL, vtxs, decl, NULL, indices, 0, num_vtx, type);
621 #else
622 (void)target;
623 (void)texture;
624 (void)vtxs;
625 (void)decl;
626 (void)indices;
627 (void)num_vtx;
628 (void)type;
629
630 return 0;
631 #endif
632 }
633
_al_draw_indexed_buffer_opengl(ALLEGRO_BITMAP * target,ALLEGRO_BITMAP * texture,ALLEGRO_VERTEX_BUFFER * vertex_buffer,ALLEGRO_INDEX_BUFFER * index_buffer,int start,int end,int type)634 int _al_draw_indexed_buffer_opengl(ALLEGRO_BITMAP* target, ALLEGRO_BITMAP* texture, ALLEGRO_VERTEX_BUFFER* vertex_buffer, ALLEGRO_INDEX_BUFFER* index_buffer, int start, int end, int type)
635 {
636 #ifdef ALLEGRO_CFG_OPENGL
637 return draw_prim_indexed_raw(target, texture, vertex_buffer, NULL, vertex_buffer->decl, index_buffer, NULL, start, end, type);
638 #else
639 (void)target;
640 (void)texture;
641 (void)vertex_buffer;
642 (void)index_buffer;
643 (void)start;
644 (void)end;
645 (void)type;
646
647 return 0;
648 #endif
649 }
650
651 #ifdef ALLEGRO_CFG_OPENGL
create_buffer_common(ALLEGRO_BUFFER_COMMON * common,GLenum type,const void * initial_data,int size,int flags)652 static bool create_buffer_common(ALLEGRO_BUFFER_COMMON* common, GLenum type, const void* initial_data, int size, int flags)
653 {
654 GLuint vbo;
655 GLenum usage;
656
657 switch (flags)
658 {
659 #if !defined ALLEGRO_CFG_OPENGLES
660 case ALLEGRO_PRIM_BUFFER_STREAM:
661 usage = GL_STREAM_DRAW;
662 break;
663 #endif
664 case ALLEGRO_PRIM_BUFFER_STATIC:
665 usage = GL_STATIC_DRAW;
666 break;
667 case ALLEGRO_PRIM_BUFFER_DYNAMIC:
668 usage = GL_DYNAMIC_DRAW;
669 break;
670 default:
671 usage = GL_STATIC_DRAW;
672 }
673
674 glGenBuffers(1, &vbo);
675 glBindBuffer(type, vbo);
676 glBufferData(type, size, initial_data, usage);
677 glBindBuffer(type, 0);
678
679 if (glGetError())
680 return false;
681
682 common->handle = vbo;
683 common->local_buffer_length = 0;
684 return true;
685 }
686 #endif
687
_al_create_vertex_buffer_opengl(ALLEGRO_VERTEX_BUFFER * buf,const void * initial_data,size_t num_vertices,int flags)688 bool _al_create_vertex_buffer_opengl(ALLEGRO_VERTEX_BUFFER* buf, const void* initial_data, size_t num_vertices, int flags)
689 {
690 #ifdef ALLEGRO_CFG_OPENGL
691 int stride = buf->decl ? buf->decl->stride : (int)sizeof(ALLEGRO_VERTEX);
692
693 return create_buffer_common(&buf->common, GL_ARRAY_BUFFER, initial_data, num_vertices * stride, flags);
694 #else
695 (void)buf;
696 (void)initial_data;
697 (void)num_vertices;
698 (void)flags;
699
700 return false;
701 #endif
702 }
703
_al_create_index_buffer_opengl(ALLEGRO_INDEX_BUFFER * buf,const void * initial_data,size_t num_indices,int flags)704 bool _al_create_index_buffer_opengl(ALLEGRO_INDEX_BUFFER* buf, const void* initial_data, size_t num_indices, int flags)
705 {
706 #ifdef ALLEGRO_CFG_OPENGL
707 return create_buffer_common(&buf->common, GL_ELEMENT_ARRAY_BUFFER, initial_data, num_indices * buf->index_size, flags);;
708 #else
709 (void)buf;
710 (void)initial_data;
711 (void)num_indices;
712 (void)flags;
713
714 return false;
715 #endif
716 }
717
_al_destroy_vertex_buffer_opengl(ALLEGRO_VERTEX_BUFFER * buf)718 void _al_destroy_vertex_buffer_opengl(ALLEGRO_VERTEX_BUFFER* buf)
719 {
720 #ifdef ALLEGRO_CFG_OPENGL
721 glDeleteBuffers(1, (GLuint*)&buf->common.handle);
722 al_free(buf->common.locked_memory);
723 #else
724 (void)buf;
725 #endif
726 }
727
_al_destroy_index_buffer_opengl(ALLEGRO_INDEX_BUFFER * buf)728 void _al_destroy_index_buffer_opengl(ALLEGRO_INDEX_BUFFER* buf)
729 {
730 #ifdef ALLEGRO_CFG_OPENGL
731 glDeleteBuffers(1, (GLuint*)&buf->common.handle);
732 al_free(buf->common.locked_memory);
733 #else
734 (void)buf;
735 #endif
736 }
737
738 #ifdef ALLEGRO_CFG_OPENGL
lock_buffer_common(ALLEGRO_BUFFER_COMMON * common,GLenum type)739 static void* lock_buffer_common(ALLEGRO_BUFFER_COMMON* common, GLenum type)
740 {
741 if (common->local_buffer_length < common->lock_length) {
742 common->locked_memory = al_realloc(common->locked_memory, common->lock_length);
743 common->local_buffer_length = common->lock_length;
744 }
745
746 if (common->lock_flags != ALLEGRO_LOCK_WRITEONLY) {
747 #if !defined ALLEGRO_CFG_OPENGLES
748 glBindBuffer(type, (GLuint)common->handle);
749 glGetBufferSubData(type, common->lock_offset, common->lock_length, common->locked_memory);
750 glBindBuffer(type, 0);
751 if (glGetError())
752 return 0;
753 #else
754 (void)type;
755 return 0;
756 #endif
757 }
758 return common->locked_memory;
759 }
760 #endif
761
_al_lock_vertex_buffer_opengl(ALLEGRO_VERTEX_BUFFER * buf)762 void* _al_lock_vertex_buffer_opengl(ALLEGRO_VERTEX_BUFFER* buf)
763 {
764 #ifdef ALLEGRO_CFG_OPENGL
765 return lock_buffer_common(&buf->common, GL_ARRAY_BUFFER);
766 #else
767 (void)buf;
768
769 return 0;
770 #endif
771 }
772
_al_lock_index_buffer_opengl(ALLEGRO_INDEX_BUFFER * buf)773 void* _al_lock_index_buffer_opengl(ALLEGRO_INDEX_BUFFER* buf)
774 {
775 #ifdef ALLEGRO_CFG_OPENGL
776 return lock_buffer_common(&buf->common, GL_ELEMENT_ARRAY_BUFFER);
777 #else
778 (void)buf;
779
780 return 0;
781 #endif
782 }
783
784 #ifdef ALLEGRO_CFG_OPENGL
unlock_buffer_common(ALLEGRO_BUFFER_COMMON * common,GLenum type)785 static void unlock_buffer_common(ALLEGRO_BUFFER_COMMON* common, GLenum type)
786 {
787 if (common->lock_flags != ALLEGRO_LOCK_READONLY) {
788 glBindBuffer(type, (GLuint)common->handle);
789 glBufferSubData(type, common->lock_offset, common->lock_length, common->locked_memory);
790 glBindBuffer(type, 0);
791 }
792 }
793 #endif
794
_al_unlock_vertex_buffer_opengl(ALLEGRO_VERTEX_BUFFER * buf)795 void _al_unlock_vertex_buffer_opengl(ALLEGRO_VERTEX_BUFFER* buf)
796 {
797 #ifdef ALLEGRO_CFG_OPENGL
798 unlock_buffer_common(&buf->common, GL_ARRAY_BUFFER);
799 #else
800 (void)buf;
801 #endif
802 }
803
_al_unlock_index_buffer_opengl(ALLEGRO_INDEX_BUFFER * buf)804 void _al_unlock_index_buffer_opengl(ALLEGRO_INDEX_BUFFER* buf)
805 {
806 #ifdef ALLEGRO_CFG_OPENGL
807 unlock_buffer_common(&buf->common, GL_ELEMENT_ARRAY_BUFFER);
808 #else
809 (void)buf;
810 #endif
811 }
812