Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
Archivo: al3d.c Proyecto: bjorndm/ekq
int main(void) {
  ALLEGRO_VERTEX        v[8];
  ALLEGRO_DISPLAY     * display;
  ALLEGRO_TRANSFORM     perst;
  ALLEGRO_TRANSFORM     camt;
  ALLEGRO_BITMAP      * texture, * texture2;
  ALLEGRO_EVENT_QUEUE * queue;
  ALLEGRO_EVENT         event;
  ALLEGRO_FONT        * font;
  int                   busy  = 1;
  float                 cx    = 0;
  float                 cy    = -2; // 128;
  float                 cz    = 0;
  int                   face  = 0; 
  int                   hori  = 0;
  float                 angle = 0;
  float                 theta = 0;  
  float                 near  = 2;
  float                 far   = 8192;
  float                 zoom  = 1;
  float                 scale = 1.0;
  float                 us    = 20; 
  float                 ratio = 480.0 / 640.0;
  al_init();  
  al_init_image_addon();
  al_init_font_addon();
  al_install_keyboard();
  font  = al_create_builtin_font();
  
  queue = al_create_event_queue();  
  al_set_new_display_option(ALLEGRO_DEPTH_SIZE, 16, ALLEGRO_SUGGEST);
  
  display  = al_create_display(640, 480);
  al_register_event_source(queue, al_get_keyboard_event_source());  
  texture  = al_load_bitmap("tile_1.png");
  texture2 = al_load_bitmap("tile_2.png");
  
  /* Allegro coordinates: +Y is down, +X is to the right, 
   * and +Z comes "out of" the screen.
   * 
   */
  
  
  while (busy) {
    init_vertex(v+0,   0,   0,   0,   0,   0, 1, 0, 0, 1);
    init_vertex(v+1,   0,   0,  us,   0, 256, 0, 1, 0, 1);
    init_vertex(v+2,  us,   0,  us, 256, 256, 0, 0, 1, 1);
    init_vertex(v+3,  us,   0,   0, 256,   0, 1, 1, 0, 1);
    init_vertex(v+4,  us, -us,   0, 256, 256, 1, 0, 1, 1);
    init_vertex(v+5,   0, -us,   0, 256,   0, 0, 1, 1, 1); 
    init_vertex(v+6,   0, -us,  us, 256, 256, 0, 0, 0, 1); 
    init_vertex(v+7,   0,   0,  us,   0, 256, 1, 1, 1, 1); 
  
  
    al_identity_transform(&camt);
    al_scale_transform_3d(&camt, scale, scale, scale);
    al_translate_transform_3d(&camt, cx, cy, cz);
  
    angle = face * 0.125 * ALLEGRO_PI;
    al_rotate_transform_3d(&camt, 0, -1, 0, angle); 
    theta = hori * 0.125 * ALLEGRO_PI;
    al_rotate_transform_3d(&camt, -1, 0, 0, theta); 
    
    al_use_transform(&camt);
    // al_set_projection_transform(display, &perst);

  
    al_clear_to_color(al_map_rgb_f(0.75, 0.75, 0.95));
    al_set_render_state(ALLEGRO_DEPTH_TEST, 1);
    al_clear_depth_buffer(far);

    
    
    al_identity_transform(&perst);
    al_perspective_transform(&perst, -1, ratio, near, 
                                      1,  -ratio, far);
    al_use_projection_transform(&perst);

    al_draw_filled_rectangle(0, 0, 4, 5, al_map_rgb_f(0, 0.25, 0.25));
    
        
    al_draw_prim(v, NULL, texture, 0, 8, ALLEGRO_PRIM_TRIANGLE_FAN);
    
    draw_textured_colored_rectangle_3d(0 , -us, 0, us, us, 0, 
                                       1.0, 1.0, texture2, al_map_rgb_f(1,1,1));
    
    draw_textured_colored_rectangle_3d(0 , -us, 0, 0, us, us, 
                                       1.0, 1.0, texture2, al_map_rgb_f(1,1,1));

    draw_textured_colored_rectangle_3d(0 , 0, 0, us, 0, us,
                                       1.0, 1.0, texture2, al_map_rgb_f(1,1,1));
     
    
    al_identity_transform(&perst);
    al_orthographic_transform(&perst, 0, 0, -1.0, 640, 480, 1.0);
 
    al_identity_transform(&camt);
    al_use_projection_transform(&perst);
    al_use_transform(&camt);
    al_draw_filled_rectangle(111, 22, 133, 44, al_map_rgb_f(0.25, 0.25, 0));

    
    al_draw_multiline_textf(font, al_map_rgb_f(1,1,1), 10, 10, 620, 0, 0,
      "Coords: (%f %f %f)\nAngle: (%f %f)\nView: [%f %f %f %f]\nScale: %f", 
               cx, cy, cz,        angle, theta,   near, far, zoom, scale); 
    
    
    
    al_flip_display();  
    al_wait_for_event(queue, &event);
    
    if (event.type == ALLEGRO_EVENT_KEY_DOWN) { 
      switch (event.keyboard.keycode) {
        case ALLEGRO_KEY_RIGHT:
          cx += 8;
          break;

        case ALLEGRO_KEY_LEFT:
          cx -= 8;
          break;
          
        case ALLEGRO_KEY_UP:
          cy += 8;
          break;
          
        case ALLEGRO_KEY_DOWN:
          cy -= 8;
          break;  
        
        case ALLEGRO_KEY_HOME:
          cz += 8;
          break;
          
        case ALLEGRO_KEY_END:
          cz -= 8;
          break;  
          
        case ALLEGRO_KEY_R:
          face++;
          break;
      
        case ALLEGRO_KEY_L:
          face--;
          break;
          
        case ALLEGRO_KEY_H:
          hori++;
          break;
      
        case ALLEGRO_KEY_G:
          hori--;
          break;
  
          
        case ALLEGRO_KEY_N:
          near *= 2.0;
          break;
          
        case ALLEGRO_KEY_M:
          near /= 2.0;
          break;

        case ALLEGRO_KEY_F:
          far += 64;
          break;
          
        case ALLEGRO_KEY_V:
          far -= 64;
          break;
        
        case ALLEGRO_KEY_Z:
          zoom *= 2.0f;
          break;
          
        case ALLEGRO_KEY_S:
          zoom /= 2.0f;
          break;
        
        case ALLEGRO_KEY_A:
          scale *= 2.0f;
          break;
          
        case ALLEGRO_KEY_Q:
          scale /= 2.0f;
          break;
          
        case ALLEGRO_KEY_ESCAPE:
          busy = 0 ;
          break;
  
        default:
          break;
      }
    }
  }
  
  al_destroy_bitmap(texture);
  al_destroy_bitmap(texture2);
  
  
  return 0;  
}
Ejemplo n.º 3
0
ALLEGRO_BITMAP *_al_create_bitmap_params(ALLEGRO_DISPLAY *current_display,
   int w, int h, int format, int flags)
{
   ALLEGRO_SYSTEM *system = al_get_system_driver();
   ALLEGRO_BITMAP *bitmap;
   ALLEGRO_BITMAP **back;
   int64_t mul;
   bool result;

   /* Reject bitmaps where a calculation pixel_size*w*h would overflow
    * int.  Supporting such bitmaps would require a lot more work.
    */
   mul = 4 * (int64_t) w * (int64_t) h;
   if (mul > (int64_t) INT_MAX) {
      ALLEGRO_WARN("Rejecting %dx%d bitmap\n", w, h);
      return NULL;
   }

   if ((flags & ALLEGRO_MEMORY_BITMAP) ||
         !current_display ||
         !current_display->vt ||
         current_display->vt->create_bitmap == NULL ||
         _al_vector_size(&system->displays) < 1)
   {
      if (flags & ALLEGRO_VIDEO_BITMAP)
         return NULL;

      return create_memory_bitmap(current_display, w, h, format, flags);
   }

   /* Else it's a display bitmap */

   bitmap = current_display->vt->create_bitmap(current_display, w, h,
      format, flags);
   if (!bitmap) {
      ALLEGRO_ERROR("failed to create display bitmap\n");
      return NULL;
   }

   bitmap->_display = current_display;
   bitmap->w = w;
   bitmap->h = h;
   bitmap->locked = false;
   bitmap->cl = 0;
   bitmap->ct = 0;
   bitmap->cr_excl = w;
   bitmap->cb_excl = h;
   al_identity_transform(&bitmap->transform);
   al_identity_transform(&bitmap->inverse_transform);
   bitmap->inverse_transform_dirty = false;
   al_identity_transform(&bitmap->proj_transform);
   al_orthographic_transform(&bitmap->proj_transform, 0, 0, -1.0, w, h, 1.0);
   bitmap->parent = NULL;
   bitmap->xofs = 0;
   bitmap->yofs = 0;
   bitmap->_flags |= ALLEGRO_VIDEO_BITMAP;
   bitmap->dirty = !(bitmap->_flags & ALLEGRO_NO_PRESERVE_TEXTURE);

   /* The display driver should have set the bitmap->memory field if
    * appropriate; video bitmaps may leave it NULL.
    */

   ASSERT(bitmap->pitch >= w * al_get_pixel_size(bitmap->_format));
   result = bitmap->vt->upload_bitmap(bitmap);

   if (!result) {
      al_destroy_bitmap(bitmap);
      if (flags & ALLEGRO_VIDEO_BITMAP)
         return NULL;
      /* With ALLEGRO_CONVERT_BITMAP, just use a memory bitmap instead if
      * video failed.
      */
      return create_memory_bitmap(current_display, w, h, format, flags);
   }
   
   /* We keep a list of bitmaps depending on the current display so that we can
    * convert them to memory bimaps when the display is destroyed. */
   back = _al_vector_alloc_back(&current_display->bitmaps);
   *back = bitmap;

   return bitmap;
}
Ejemplo n.º 4
0
// 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);
}