/* Function: al_hold_bitmap_drawing */ void al_hold_bitmap_drawing(bool hold) { ALLEGRO_DISPLAY *current_display = al_get_current_display(); if (current_display) { if (hold && !current_display->cache_enabled) { /* * Set the hardware transformation to identity, but keep the bitmap * transform the same as it was. Relies on the fact that when bitmap * holding is turned on, al_use_transform does not update the hardware * transformation. */ ALLEGRO_TRANSFORM old, ident; al_copy_transform(&old, al_get_current_transform()); al_identity_transform(&ident); al_use_transform(&ident); current_display->cache_enabled = hold; al_use_transform(&old); } else { current_display->cache_enabled = hold; } if (!hold) { current_display->vt->flush_vertex_cache(current_display); /* * Reset the hardware transform to match the stored transform. */ al_use_transform(al_get_current_transform()); } } }
void _al_draw_bitmap_region_memory(ALLEGRO_BITMAP *src, ALLEGRO_COLOR tint, int sx, int sy, int sw, int sh, int dx, int dy, int flags) { int op, src_mode, dst_mode; int op_alpha, src_alpha, dst_alpha; float xtrans, ytrans; ASSERT(src->parent == NULL); al_get_separate_blender(&op, &src_mode, &dst_mode, &op_alpha, &src_alpha, &dst_alpha); if (_AL_DEST_IS_ZERO && _AL_SRC_NOT_MODIFIED_TINT_WHITE && _al_transform_is_translation(al_get_current_transform(), &xtrans, &ytrans)) { _al_draw_bitmap_region_memory_fast(src, sx, sy, sw, sh, dx + xtrans, dy + ytrans, flags); return; } /* We used to have special cases for translation/scaling only, but the * general version received much more optimisation and ended up being * faster. */ _al_draw_transformed_scaled_bitmap_memory(src, tint, sx, sy, sw, sh, dx, dy, sw, sh, flags); }
static void _draw_tinted_rotated_scaled_bitmap_region(ALLEGRO_BITMAP *bitmap, ALLEGRO_COLOR tint, float cx, float cy, float angle, float xscale, float yscale, float sx, float sy, float sw, float sh, float dx, float dy, int flags) { ALLEGRO_TRANSFORM backup; ALLEGRO_TRANSFORM t; ALLEGRO_BITMAP *parent = bitmap; float const orig_sw = sw; float const orig_sh = sh; ASSERT(bitmap); al_copy_transform(&backup, al_get_current_transform()); al_identity_transform(&t); if (bitmap->parent) { parent = bitmap->parent; sx += bitmap->xofs; sy += bitmap->yofs; } if (sx < 0) { sw += sx; al_translate_transform(&t, -sx, 0); sx = 0; } if (sy < 0) { sh += sy; al_translate_transform(&t, 0, -sy); sy = 0; } if (sx + sw > parent->w) sw = parent->w - sx; if (sy + sh > parent->h) sh = parent->h - sy; if (flags & ALLEGRO_FLIP_HORIZONTAL) { al_scale_transform(&t, -1, 1); al_translate_transform(&t, orig_sw, 0); flags &= ~ALLEGRO_FLIP_HORIZONTAL; } if (flags & ALLEGRO_FLIP_VERTICAL) { al_scale_transform(&t, 1, -1); al_translate_transform(&t, 0, orig_sh); flags &= ~ALLEGRO_FLIP_VERTICAL; } al_translate_transform(&t, -cx, -cy); al_scale_transform(&t, xscale, yscale); al_rotate_transform(&t, angle); al_translate_transform(&t, dx, dy); al_compose_transform(&t, &backup); al_use_transform(&t); _bitmap_drawer(parent, tint, sx, sy, sw, sh, flags); al_use_transform(&backup); }
void Renderer::draw() { //int dw = al_get_display_width(dpy_); //int dh = al_get_display_height(dpy_); ALLEGRO_TRANSFORM trans; al_identity_transform(&trans); al_compose_transform(&trans, &camera_transform_); al_rotate_transform_3d(&trans, 1.0, 0.0, 0.0, rx_look); setupProjection(&trans); al_identity_transform(&trans); al_use_transform(&trans); getWorldPos(camera_pos_); al_copy_transform(&cur3d_transform_, al_get_current_transform()); glEnable(GL_DEPTH_TEST); // Accept fragment if it closer to the camera than the former one glDepthFunc(GL_LEQUAL); glEnable(GL_CULL_FACE); glFrontFace(GL_CCW); glEnable(GL_ALPHA_TEST); if(!setShader(SHADER_DEFAULT)) { NBT_Debug("failed to set default shader"); } glBindVertexArray(vao_); resManager_->setAtlasUniforms(); for(auto &it: chunkData_) { ChunkData *cd = it.second; ALLEGRO_TRANSFORM ctrans; al_identity_transform(&ctrans); al_translate_transform_3d(&ctrans, cd->x()*15.0, 0.0, cd->z()*15.0); al_use_transform(&ctrans); cd->draw(&ctrans); } glBindVertexArray(0); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); //drawSelection(); resManager_->unsetAtlasUniforms(); }
void m_draw_tinted_bitmap_identity_view(MBITMAP *bmp, MCOLOR tint, int x, int y, int flags) { ALLEGRO_TRANSFORM backup, t; al_copy_transform(&backup, al_get_current_transform()); al_identity_transform(&t); al_use_transform(&t); m_draw_tinted_bitmap(bmp, tint, x, y, flags); al_use_transform(&backup); }
static void _al_draw_transformed_scaled_bitmap_memory( ALLEGRO_BITMAP *src, ALLEGRO_COLOR tint, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int flags) { ALLEGRO_TRANSFORM local_trans; al_identity_transform(&local_trans); al_translate_transform(&local_trans, dx, dy); al_compose_transform(&local_trans, al_get_current_transform()); _al_draw_transformed_bitmap_memory(src, tint, sx, sy, sw, sh, dw, dh, &local_trans, flags); }
void prepareForScreenGrab1() { prepareForScreenGrabBackupBitmap = al_get_target_bitmap(); int dx, dy, dw, dh; get_screen_offset_size(&dx, &dy, &dw, &dh); m_set_target_bitmap(tmpbuffer); ALLEGRO_TRANSFORM t; al_copy_transform(&prepareForScreenGrabBackup, al_get_current_transform()); al_identity_transform(&t); al_scale_transform(&t, screenScaleX, screenScaleY); al_translate_transform(&t, dx, dy); al_use_transform(&t); preparingForScreenGrab = true; }
void _al_draw_pixel_memory(ALLEGRO_BITMAP *bitmap, float x, float y, ALLEGRO_COLOR *color) { ALLEGRO_COLOR result; int ix, iy; /* * Probably not worth it to check for identity */ al_transform_coordinates(al_get_current_transform(), &x, &y); ix = (int)x; iy = (int)y; _al_blend_memory(color, bitmap, ix, iy, &result); _al_put_pixel(bitmap, ix, iy, result); }
void start_text() { if (!text_draw_on) { text_draw_on = true; int dx, dy, dw, dh; get_screen_offset_size(&dx, &dy, &dw, &dh); al_copy_transform(&old_view, al_get_current_transform()); ALLEGRO_TRANSFORM v; al_identity_transform(&v); al_scale_transform(&v, textScaleX, textScaleY); if (al_get_bitmap_width(al_get_target_bitmap()) == al_get_display_width(display) && al_get_bitmap_height(al_get_target_bitmap()) == al_get_display_height(display)) { al_translate_transform(&v, dx, dy); } al_use_transform(&v); } }
void m_draw_tinted_scaled_bitmap_identity_view( MBITMAP *bmp, MCOLOR tint, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int flags ) { ALLEGRO_TRANSFORM backup, t; al_copy_transform(&backup, al_get_current_transform()); al_identity_transform(&t); al_use_transform(&t); al_draw_tinted_scaled_bitmap( bmp->bitmap, tint, sx, sy, sw, sh, dx, dy, dw, dh, 0 ); al_use_transform(&backup); }
void draw_blast(Blast *blast) { ALLEGRO_TRANSFORM transform; if(al_get_current_transform() == NULL) { fprintf(stderr, "no target bitmap."); } al_identity_transform(&transform); al_rotate_transform(&transform, 1.58525 + head2theta(blast->heading)); al_translate_transform(&transform, blast->sx, blast->sy); al_use_transform(&transform); /* many small lines will eventually create a dashed line */ al_draw_line(0, 0, 0, -10, blast->color, 3.0f); al_draw_line(0, -15, 0, -25, blast->color, 3.0f); al_draw_line(0, -30, 0, -40, blast->color, 3.0f); al_draw_line(0, -45, 0, -60, blast->color, 3.0f); al_draw_line(0, -65, 0, -80, blast->color, 3.0f); al_draw_line(0, -85, 0, -100, blast->color, 3.0f); al_draw_line(0, -105, 0, -120, blast->color, 3.0f); }
void DrawMenuState(struct Game *game, struct MenuResources *data) { const ALLEGRO_TRANSFORM *tmp_trans = al_get_current_transform(); ALLEGRO_TRANSFORM trans, cur_trans; al_copy_transform(&trans, tmp_trans); al_copy_transform(&cur_trans, tmp_trans); al_translate_transform(&trans, (al_get_display_width(game->display) / 320.0) * 100, (al_get_display_height(game->display) / 260.0) * ((180-data->screen_pos) - 48)); al_use_transform(&trans); ALLEGRO_FONT *font = data->font; char* text = malloc(255*sizeof(char)); struct ALLEGRO_COLOR color; switch (data->menustate) { case MENUSTATE_MAIN: case MENUSTATE_HIDDEN: if (!data->invisible) { DrawTextWithShadow(font, data->selected==0 ? al_map_rgb(128,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.5, ALLEGRO_ALIGN_CENTRE, "Start game"); DrawTextWithShadow(font, data->selected==1 ? al_map_rgb(128,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.6, ALLEGRO_ALIGN_CENTRE, "Options"); DrawTextWithShadow(font, data->selected==2 ? al_map_rgb(128,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.7, ALLEGRO_ALIGN_CENTRE, "About"); DrawTextWithShadow(font, data->selected==3 ? al_map_rgb(128,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.8, ALLEGRO_ALIGN_CENTRE, "Exit"); } break; case MENUSTATE_OPTIONS: DrawTextWithShadow(font, data->selected==0 ? al_map_rgb(128,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.5, ALLEGRO_ALIGN_CENTRE, "Video settings"); DrawTextWithShadow(font, data->selected==1 ? al_map_rgb(128,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.6, ALLEGRO_ALIGN_CENTRE, "Audio settings"); DrawTextWithShadow(font, data->selected==3 ? al_map_rgb(128,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.8, ALLEGRO_ALIGN_CENTRE, "Back"); break; case MENUSTATE_AUDIO: if (game->config.music) snprintf(text, 255, "Music volume: %d0%%", game->config.music); else sprintf(text, "Music disabled"); DrawTextWithShadow(font, data->selected==0 ? al_map_rgb(128,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.5, ALLEGRO_ALIGN_CENTRE, text); if (game->config.fx) snprintf(text, 255, "Effects volume: %d0%%", game->config.fx); else sprintf(text, "Effects disabled"); DrawTextWithShadow(font, data->selected==1 ? al_map_rgb(128,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.6, ALLEGRO_ALIGN_CENTRE, text); DrawTextWithShadow(font, data->selected==3 ? al_map_rgb(128,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.8, ALLEGRO_ALIGN_CENTRE, "Back"); break; case MENUSTATE_ABOUT: al_use_transform(&cur_trans); About(game, data); break; case MENUSTATE_VIDEO: if (data->options.fullscreen) { sprintf(text, "Fullscreen: yes"); color = al_map_rgba(0,0,0,128); } else { sprintf(text, "Fullscreen: no"); color = data->selected==1 ? al_map_rgb(128,255,128) : al_map_rgb(255,255,255); } DrawTextWithShadow(font, data->selected==0 ? al_map_rgb(128,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.5, ALLEGRO_ALIGN_CENTRE, text); sprintf(text, "Resolution: %dx", data->options.resolution); DrawTextWithShadow(font, color, game->viewport.width*0.5, game->viewport.height*0.6, ALLEGRO_ALIGN_CENTRE, text); DrawTextWithShadow(font, data->selected==3 ? al_map_rgb(128,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.8, ALLEGRO_ALIGN_CENTRE, "Back"); break; default: data->selected=0; DrawTextWithShadow(font, data->selected==0 ? al_map_rgb(128,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.5, ALLEGRO_ALIGN_CENTRE, "Not implemented yet"); break; } free(text); al_use_transform(&cur_trans); }
static INLINE void transform_vertex(float* x, float* y) { al_transform_coordinates(al_get_current_transform(), x, y); }
bool _al_opengl_set_blender(ALLEGRO_DISPLAY *ogl_disp) { int op, src_color, dst_color, op_alpha, src_alpha, dst_alpha; const int blend_modes[8] = { GL_ZERO, GL_ONE, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_COLOR, GL_DST_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_ONE_MINUS_DST_COLOR }; const int blend_equations[3] = { GL_FUNC_ADD, GL_FUNC_SUBTRACT, GL_FUNC_REVERSE_SUBTRACT }; (void)ogl_disp; al_get_separate_blender(&op, &src_color, &dst_color, &op_alpha, &src_alpha, &dst_alpha); /* glBlendFuncSeparate was only included with OpenGL 1.4 */ /* (And not in OpenGL ES) */ #if !defined ALLEGRO_GP2XWIZ #if !defined ALLEGRO_IPHONE && !defined ALLEGRO_ANDROID if (ogl_disp->ogl_extras->ogl_info.version >= _ALLEGRO_OPENGL_VERSION_1_4) { #else if (ogl_disp->ogl_extras->ogl_info.version >= _ALLEGRO_OPENGL_VERSION_2_0) { #endif glEnable(GL_BLEND); glBlendFuncSeparate(blend_modes[src_color], blend_modes[dst_color], blend_modes[src_alpha], blend_modes[dst_alpha]); if (ogl_disp->ogl_extras->ogl_info.version >= _ALLEGRO_OPENGL_VERSION_2_0) { glBlendEquationSeparate( blend_equations[op], blend_equations[op_alpha]); } else { glBlendEquation(blend_equations[op]); } } else { if (src_color == src_alpha && dst_color == dst_alpha) { glEnable(GL_BLEND); glBlendFunc(blend_modes[src_color], blend_modes[dst_color]); } else { ALLEGRO_ERROR("Blender unsupported with this OpenGL version (%d %d %d %d %d %d)\n", op, src_color, dst_color, op_alpha, src_alpha, dst_alpha); return false; } } #else glEnable(GL_BLEND); glBlendFunc(blend_modes[src_color], blend_modes[dst_color]); #endif return true; } /* These functions make drawing calls use shaders or the fixed pipeline * based on what the user has set up. FIXME: OpenGL only right now. */ static void vert_ptr_on(ALLEGRO_DISPLAY *display, int n, GLint t, int stride, void *v) { /* Only use this shader stuff with GLES2+ or equivalent */ if (display->flags & ALLEGRO_USE_PROGRAMMABLE_PIPELINE) { #ifndef ALLEGRO_CFG_NO_GLES2 if (display->ogl_extras->pos_loc >= 0) { glVertexAttribPointer(display->ogl_extras->pos_loc, n, t, false, stride, v); glEnableVertexAttribArray(display->ogl_extras->pos_loc); } #endif } else { glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(n, t, stride, v); } } static void vert_ptr_off(ALLEGRO_DISPLAY *display) { if (display->flags & ALLEGRO_USE_PROGRAMMABLE_PIPELINE) { #ifndef ALLEGRO_CFG_NO_GLES2 if (display->ogl_extras->pos_loc >= 0) { glDisableVertexAttribArray(display->ogl_extras->pos_loc); } #endif } else { glDisableClientState(GL_VERTEX_ARRAY); } } static void color_ptr_on(ALLEGRO_DISPLAY *display, int n, GLint t, int stride, void *v) { if (display->flags & ALLEGRO_USE_PROGRAMMABLE_PIPELINE) { #ifndef ALLEGRO_CFG_NO_GLES2 if (display->ogl_extras->color_loc >= 0) { glVertexAttribPointer(display->ogl_extras->color_loc, n, t, false, stride, v); glEnableVertexAttribArray(display->ogl_extras->color_loc); } #endif } else { glEnableClientState(GL_COLOR_ARRAY); glColorPointer(n, t, stride, v); } } static void color_ptr_off(ALLEGRO_DISPLAY *display) { if (display->flags & ALLEGRO_USE_PROGRAMMABLE_PIPELINE) { #ifndef ALLEGRO_CFG_NO_GLES2 if (display->ogl_extras->color_loc >= 0) { glDisableVertexAttribArray(display->ogl_extras->color_loc); } #endif } else { glDisableClientState(GL_COLOR_ARRAY); } } static void tex_ptr_on(ALLEGRO_DISPLAY *display, int n, GLint t, int stride, void *v) { if (display->flags & ALLEGRO_USE_PROGRAMMABLE_PIPELINE) { #ifndef ALLEGRO_CFG_NO_GLES2 if (display->ogl_extras->texcoord_loc >= 0) { glVertexAttribPointer(display->ogl_extras->texcoord_loc, n, t, false, stride, v); glEnableVertexAttribArray(display->ogl_extras->texcoord_loc); } #endif } else { glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(n, t, stride, v); } } static void tex_ptr_off(ALLEGRO_DISPLAY *display) { if (display->flags & ALLEGRO_USE_PROGRAMMABLE_PIPELINE) { #ifndef ALLEGRO_CFG_NO_GLES2 if (display->ogl_extras->texcoord_loc >= 0) { glDisableVertexAttribArray(display->ogl_extras->texcoord_loc); } #endif } else { glDisableClientState(GL_TEXTURE_COORD_ARRAY); } } /* Dummy implementation of clear. */ static void ogl_clear(ALLEGRO_DISPLAY *d, ALLEGRO_COLOR *color) { ALLEGRO_DISPLAY *ogl_disp = (void *)d; ALLEGRO_BITMAP *target = al_get_target_bitmap(); ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_target; float r, g, b, a; if (target->parent) target = target->parent; ogl_target = target->extra; if ((!ogl_target->is_backbuffer && ogl_disp->ogl_extras->opengl_target != target) || target->locked) { _al_clear_memory(color); return; } al_unmap_rgba_f(*color, &r, &g, &b, &a); /* There's a very nasty bug in Android 2.1 that makes glClear cause * screen flicker (appears to me it's swapping buffers.) Work around * by drawing two triangles instead on that OS. */ #ifdef ALLEGRO_ANDROID if (ogl_target->is_backbuffer && _al_android_is_os_2_1()) { GLfloat v[8] = { 0, d->h, 0, 0, d->w, d->h, d->w, 0 }; GLfloat c[16] = { r, g, b, a, r, g, b, a, r, g, b, a, r, g, b, a }; ALLEGRO_TRANSFORM bak1, bak2, t; al_copy_transform(&bak1, &d->proj_transform); al_copy_transform(&bak2, al_get_current_transform()); al_identity_transform(&t); al_ortho_transform(&t, 0, d->w, d->h, 0, -1, 1); al_set_projection_transform(d, &t); al_identity_transform(&t); al_use_transform(&t); _al_opengl_set_blender(d); vert_ptr_on(d, 2, GL_FLOAT, 2*sizeof(float), v); color_ptr_on(d, 4, GL_FLOAT, 4*sizeof(float), c); if (!(d->flags & ALLEGRO_USE_PROGRAMMABLE_PIPELINE)) { glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); } glDisable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); vert_ptr_off(d); color_ptr_off(d); al_set_projection_transform(d, &bak1); al_use_transform(&bak2); return; } #endif glClearColor(r, g, b, a); glClear(GL_COLOR_BUFFER_BIT); }
bool _al_opengl_set_blender(ALLEGRO_DISPLAY *ogl_disp) { int op, src_color, dst_color, op_alpha, src_alpha, dst_alpha; ALLEGRO_COLOR const_color; const int blend_modes[10] = { GL_ZERO, GL_ONE, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_COLOR, GL_DST_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_ONE_MINUS_DST_COLOR, #if defined(ALLEGRO_CFG_OPENGLES2) || !defined(ALLEGRO_CFG_OPENGLES) GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR #else GL_ONE, GL_ONE #endif }; const int blend_equations[3] = { GL_FUNC_ADD, GL_FUNC_SUBTRACT, GL_FUNC_REVERSE_SUBTRACT }; (void)ogl_disp; al_get_separate_blender(&op, &src_color, &dst_color, &op_alpha, &src_alpha, &dst_alpha); const_color = al_get_blend_color(); /* glBlendFuncSeparate was only included with OpenGL 1.4 */ #if !defined ALLEGRO_CFG_OPENGLES if (ogl_disp->ogl_extras->ogl_info.version >= _ALLEGRO_OPENGL_VERSION_1_4) { #else /* FIXME: At this time (09/2014) there are a lot of Android phones that * don't support glBlendFuncSeparate even though they claim OpenGL ES 2.0 * support. Rather than not work on 20-25% of phones, we just don't support * separate blending on Android for now. */ #ifdef ALLEGRO_ANDROID if (false) { #else if (ogl_disp->ogl_extras->ogl_info.version >= _ALLEGRO_OPENGL_VERSION_2_0) { #endif #endif glEnable(GL_BLEND); #if defined(ALLEGRO_CFG_OPENGLES2) || !defined(ALLEGRO_CFG_OPENGLES) #ifndef ALLEGRO_ANDROID_HACK_X86_64 glBlendColor(const_color.r, const_color.g, const_color.b, const_color.a); #endif #endif glBlendFuncSeparate(blend_modes[src_color], blend_modes[dst_color], blend_modes[src_alpha], blend_modes[dst_alpha]); if (ogl_disp->ogl_extras->ogl_info.version >= _ALLEGRO_OPENGL_VERSION_2_0) { glBlendEquationSeparate( blend_equations[op], blend_equations[op_alpha]); } else { glBlendEquation(blend_equations[op]); } } else { if (src_color == src_alpha && dst_color == dst_alpha) { glEnable(GL_BLEND); #if defined(ALLEGRO_CFG_OPENGLES2) || !defined(ALLEGRO_CFG_OPENGLES) #ifndef ALLEGRO_ANDROID_HACK_X86_64 glBlendColor(const_color.r, const_color.g, const_color.b, const_color.a); #endif #endif glBlendFunc(blend_modes[src_color], blend_modes[dst_color]); } else { ALLEGRO_ERROR("Blender unsupported with this OpenGL version (%d %d %d %d %d %d)\n", op, src_color, dst_color, op_alpha, src_alpha, dst_alpha); return false; } } return true; } /* These functions make drawing calls use shaders or the fixed pipeline * based on what the user has set up. FIXME: OpenGL only right now. */ static void vert_ptr_on(ALLEGRO_DISPLAY *display, int n, GLint t, int stride, void *v) { /* Only use this shader stuff with GLES2+ or equivalent */ if (display->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) { #ifdef ALLEGRO_CFG_OPENGL_PROGRAMMABLE_PIPELINE if (display->ogl_extras->varlocs.pos_loc >= 0) { glVertexAttribPointer(display->ogl_extras->varlocs.pos_loc, n, t, false, stride, v); glEnableVertexAttribArray(display->ogl_extras->varlocs.pos_loc); } #endif } else { glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(n, t, stride, v); } } static void vert_ptr_off(ALLEGRO_DISPLAY *display) { if (display->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) { #ifdef ALLEGRO_CFG_OPENGL_PROGRAMMABLE_PIPELINE if (display->ogl_extras->varlocs.pos_loc >= 0) { glDisableVertexAttribArray(display->ogl_extras->varlocs.pos_loc); } #endif } else { glDisableClientState(GL_VERTEX_ARRAY); } } static void color_ptr_on(ALLEGRO_DISPLAY *display, int n, GLint t, int stride, void *v) { if (display->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) { #ifdef ALLEGRO_CFG_OPENGL_PROGRAMMABLE_PIPELINE if (display->ogl_extras->varlocs.color_loc >= 0) { glVertexAttribPointer(display->ogl_extras->varlocs.color_loc, n, t, false, stride, v); glEnableVertexAttribArray(display->ogl_extras->varlocs.color_loc); } #endif } else { glEnableClientState(GL_COLOR_ARRAY); glColorPointer(n, t, stride, v); } } static void color_ptr_off(ALLEGRO_DISPLAY *display) { if (display->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) { #ifdef ALLEGRO_CFG_OPENGL_PROGRAMMABLE_PIPELINE if (display->ogl_extras->varlocs.color_loc >= 0) { glDisableVertexAttribArray(display->ogl_extras->varlocs.color_loc); } #endif } else { glDisableClientState(GL_COLOR_ARRAY); } } static void tex_ptr_on(ALLEGRO_DISPLAY *display, int n, GLint t, int stride, void *v) { if (display->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) { #ifdef ALLEGRO_CFG_OPENGL_PROGRAMMABLE_PIPELINE if (display->ogl_extras->varlocs.texcoord_loc >= 0) { glVertexAttribPointer(display->ogl_extras->varlocs.texcoord_loc, n, t, false, stride, v); glEnableVertexAttribArray(display->ogl_extras->varlocs.texcoord_loc); } #endif } else { glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(n, t, stride, v); } } static void tex_ptr_off(ALLEGRO_DISPLAY *display) { if (display->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) { #ifdef ALLEGRO_CFG_OPENGL_PROGRAMMABLE_PIPELINE if (display->ogl_extras->varlocs.texcoord_loc >= 0) { glDisableVertexAttribArray(display->ogl_extras->varlocs.texcoord_loc); } #endif } else { glDisableClientState(GL_TEXTURE_COORD_ARRAY); } } /* There's a very nasty bug in Android 2.1 that makes glClear cause * screen flicker (appears to me it's swapping buffers.) Work around * by drawing two triangles instead on that OS. */ static void ogl_clear_android_2_1_workaround(ALLEGRO_DISPLAY *d, float r, float g, float b, float a) { GLfloat v[8] = { 0, d->h, 0, 0, d->w, d->h, d->w, 0 }; GLfloat c[16] = { r, g, b, a, r, g, b, a, r, g, b, a, r, g, b, a }; ALLEGRO_TRANSFORM bak1, bak2, t; al_copy_transform(&bak1, al_get_current_projection_transform()); al_copy_transform(&bak2, al_get_current_transform()); al_identity_transform(&t); al_orthographic_transform(&t, 0, 0, -1, d->w, d->h, 1); al_use_projection_transform(&t); al_identity_transform(&t); al_use_transform(&t); _al_opengl_set_blender(d); vert_ptr_on(d, 2, GL_FLOAT, 2*sizeof(float), v); color_ptr_on(d, 4, GL_FLOAT, 4*sizeof(float), c); if (!(d->flags & ALLEGRO_PROGRAMMABLE_PIPELINE)) { glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); } glDisable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); vert_ptr_off(d); color_ptr_off(d); al_use_projection_transform(&bak1); al_use_transform(&bak2); } static void ogl_clear(ALLEGRO_DISPLAY *d, ALLEGRO_COLOR *color) { ALLEGRO_DISPLAY *ogl_disp = (void *)d; ALLEGRO_BITMAP *target = al_get_target_bitmap(); ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_target; float r, g, b, a; if (target->parent) target = target->parent; ogl_target = target->extra; if ((!ogl_target->is_backbuffer && ogl_disp->ogl_extras->opengl_target != target) || target->locked) { _al_clear_bitmap_by_locking(target, color); return; } al_unmap_rgba_f(*color, &r, &g, &b, &a); if (ogl_target->is_backbuffer && IS_ANDROID_AND(_al_android_is_os_2_1())) { ogl_clear_android_2_1_workaround(d, r, g, b, a); return; } glClearColor(r, g, b, a); glClear(GL_COLOR_BUFFER_BIT); }
// Render function. // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data) { // Backup Allegro state that will be modified ALLEGRO_TRANSFORM last_transform = *al_get_current_transform(); ALLEGRO_TRANSFORM last_projection_transform = *al_get_current_projection_transform(); int last_clip_x, last_clip_y, last_clip_w, last_clip_h; al_get_clipping_rectangle(&last_clip_x, &last_clip_y, &last_clip_w, &last_clip_h); int last_blender_op, last_blender_src, last_blender_dst; al_get_blender(&last_blender_op, &last_blender_src, &last_blender_dst); // Setup render state al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA); // Setup orthographic projection matrix // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). { float L = draw_data->DisplayPos.x; float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; float T = draw_data->DisplayPos.y; float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; ALLEGRO_TRANSFORM transform; al_identity_transform(&transform); al_use_transform(&transform); al_orthographic_transform(&transform, L, T, 1.0f, R, B, -1.0f); al_use_projection_transform(&transform); } for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; // Allegro's implementation of al_draw_indexed_prim() for DX9 is completely broken. Unindex our buffers ourselves. // FIXME-OPT: Unfortunately Allegro doesn't support 32-bits packed colors so we have to convert them to 4 float as well.. static ImVector<ImDrawVertAllegro> vertices; vertices.resize(cmd_list->IdxBuffer.Size); for (int i = 0; i < cmd_list->IdxBuffer.Size; i++) { const ImDrawVert* src_v = &cmd_list->VtxBuffer[cmd_list->IdxBuffer[i]]; ImDrawVertAllegro* dst_v = &vertices[i]; dst_v->pos = src_v->pos; dst_v->uv = src_v->uv; unsigned char* c = (unsigned char*)&src_v->col; dst_v->col = al_map_rgba(c[0], c[1], c[2], c[3]); } const int* indices = NULL; if (sizeof(ImDrawIdx) == 2) { // FIXME-OPT: Unfortunately Allegro doesn't support 16-bit indices.. You can '#define ImDrawIdx int' in imconfig.h to request Dear ImGui to output 32-bit indices. // Otherwise, we convert them from 16-bit to 32-bit at runtime here, which works perfectly but is a little wasteful. static ImVector<int> indices_converted; indices_converted.resize(cmd_list->IdxBuffer.Size); for (int i = 0; i < cmd_list->IdxBuffer.Size; ++i) indices_converted[i] = (int)cmd_list->IdxBuffer.Data[i]; indices = indices_converted.Data; } else if (sizeof(ImDrawIdx) == 4) { indices = (const int*)cmd_list->IdxBuffer.Data; } // Render command lists int idx_offset = 0; ImVec2 clip_off = draw_data->DisplayPos; for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; if (pcmd->UserCallback) { pcmd->UserCallback(cmd_list, pcmd); } else { ALLEGRO_BITMAP* texture = (ALLEGRO_BITMAP*)pcmd->TextureId; al_set_clipping_rectangle(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y, pcmd->ClipRect.z - pcmd->ClipRect.x, pcmd->ClipRect.w - pcmd->ClipRect.y); al_draw_prim(&vertices[0], g_VertexDecl, texture, idx_offset, idx_offset + pcmd->ElemCount, ALLEGRO_PRIM_TRIANGLE_LIST); } idx_offset += pcmd->ElemCount; } } // Restore modified Allegro state al_set_blender(last_blender_op, last_blender_src, last_blender_dst); al_set_clipping_rectangle(last_clip_x, last_clip_y, last_clip_w, last_clip_h); al_use_transform(&last_transform); al_use_projection_transform(&last_projection_transform); }
VALUE rbal_get_current_transform(VALUE r_) { ALLEGRO_TRANSFORM * trans = (ALLEGRO_TRANSFORM *) al_get_current_transform(); return rbal_transform_wrap(trans, RBAL_NO_GC); }