Example #1
0
static void ogl_lock_region_nonbb_readwrite_fbo(
   ALLEGRO_BITMAP *bitmap, ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap,
   int x, int gl_y, int w, int h, int format)
{
   const int pixel_size = al_get_pixel_size(format);
   const int pitch = ogl_pitch(w, pixel_size);
   GLint old_fbo;
   GLenum e;

   glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &old_fbo);

   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ogl_bitmap->fbo_info->fbo);

   ogl_bitmap->lock_buffer = al_malloc(pitch * h);

   glReadPixels(x, gl_y, w, h,
      get_glformat(format, 2),
      get_glformat(format, 1),
      ogl_bitmap->lock_buffer);

   e = glGetError();
   if (e) {
      ALLEGRO_ERROR("glReadPixels for format %s failed (%s).\n",
         _al_format_name(format), _al_gl_error_string(e));
   }

   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, old_fbo);

   bitmap->locked_region.data = ogl_bitmap->lock_buffer + pitch * (h - 1);
   bitmap->locked_region.format = format;
   bitmap->locked_region.pitch = -pitch;
   bitmap->locked_region.pixel_size = pixel_size;
}
Example #2
0
static void ogl_lock_region_nonbb_readwrite_nonfbo(
   ALLEGRO_BITMAP *bitmap, ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap,
   int x, int gl_y, int w, int h, int format)
{
   /* No FBO - fallback to reading the entire texture */
   const int pixel_size = al_get_pixel_size(format);
   const int pitch = ogl_pitch(ogl_bitmap->true_w, pixel_size);
   GLenum e;
   (void) w;

   ogl_bitmap->lock_buffer = al_malloc(pitch * ogl_bitmap->true_h);

   glBindTexture(GL_TEXTURE_2D, ogl_bitmap->texture);
   glGetTexImage(GL_TEXTURE_2D, 0,
      get_glformat(format, 2),
      get_glformat(format, 1),
      ogl_bitmap->lock_buffer);

   e = glGetError();
   if (e) {
      ALLEGRO_ERROR("glGetTexImage for format %s failed (%s).\n",
         _al_format_name(format), _al_gl_error_string(e));
   }

   bitmap->locked_region.data = ogl_bitmap->lock_buffer +
      pitch * (gl_y + h - 1) + pixel_size * x;
   bitmap->locked_region.format = format;
   bitmap->locked_region.pitch = -pitch;
   bitmap->locked_region.pixel_size = pixel_size;
}
Example #3
0
static void ogl_unlock_region_nonbb_nonfbo(ALLEGRO_BITMAP *bitmap,
   ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap, int gl_y)
{
   const int lock_format = bitmap->locked_region.format;
   unsigned char *start_ptr;
   GLenum e;

   if (bitmap->lock_flags & ALLEGRO_LOCK_WRITEONLY) {
      ALLEGRO_DEBUG("Unlocking non-backbuffer non-FBO WRITEONLY\n");
      start_ptr = ogl_bitmap->lock_buffer;
   }
   else {
      ALLEGRO_DEBUG("Unlocking non-backbuffer non-FBO READWRITE\n");
      glPixelStorei(GL_UNPACK_ROW_LENGTH, ogl_bitmap->true_w);
      start_ptr = (unsigned char *)bitmap->lock_data
            + (bitmap->lock_h - 1) * bitmap->locked_region.pitch;
   }

   glTexSubImage2D(GL_TEXTURE_2D, 0,
      bitmap->lock_x, gl_y,
      bitmap->lock_w, bitmap->lock_h,
      get_glformat(lock_format, 2),
      get_glformat(lock_format, 1),
      start_ptr);

   e = glGetError();
   if (e) {
      ALLEGRO_ERROR("glTexSubImage2D for format %s failed (%s).\n",
         _al_pixel_format_name(lock_format), _al_gl_error_string(e));
   }
}
Example #4
0
static void ogl_unlock_region_nonbb_fbo_writeonly(ALLEGRO_BITMAP *bitmap,
   ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap, int gl_y, int orig_format)
{
   const int lock_format = bitmap->locked_region.format;
   const int orig_pixel_size = al_get_pixel_size(orig_format);
   const int dst_pitch = bitmap->lock_w * orig_pixel_size;
   unsigned char * const tmpbuf = al_malloc(dst_pitch * bitmap->lock_h);
   GLenum e;

   _al_convert_bitmap_data(
      ogl_bitmap->lock_buffer,
      bitmap->locked_region.format,
      -bitmap->locked_region.pitch,
      tmpbuf,
      orig_format,
      dst_pitch,
      0, 0, 0, 0,
      bitmap->lock_w, bitmap->lock_h);

   glTexSubImage2D(GL_TEXTURE_2D, 0,
      bitmap->lock_x, gl_y,
      bitmap->lock_w, bitmap->lock_h,
      get_glformat(orig_format, 2),
      get_glformat(orig_format, 1),
      tmpbuf);
   e = glGetError();
   if (e) {
      ALLEGRO_ERROR("glTexSubImage2D for format %d failed (%s).\n",
         lock_format, _al_gl_error_string(e));
   }

   al_free(tmpbuf);
}
Example #5
0
static bool ogl_lock_region_backbuffer(
   ALLEGRO_BITMAP *bitmap, ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap,
   int x, int gl_y, int w, int h, int format, int flags)
{
   const int pixel_size = al_get_pixel_size(format);
   const int pitch = ogl_pitch(w, pixel_size);
   GLenum e;

   ogl_bitmap->lock_buffer = al_malloc(pitch * h);
   if (ogl_bitmap->lock_buffer == NULL) {
      return false;
   }

   if (!(flags & ALLEGRO_LOCK_WRITEONLY)) {
      glReadPixels(x, gl_y, w, h,
         get_glformat(format, 2),
         get_glformat(format, 1),
         ogl_bitmap->lock_buffer);
      e = glGetError();
      if (e) {
         ALLEGRO_ERROR("glReadPixels for format %s failed (%s).\n",
            _al_pixel_format_name(format), _al_gl_error_string(e));
         al_free(ogl_bitmap->lock_buffer);
         ogl_bitmap->lock_buffer = NULL;
         return false;
      }
   }

   bitmap->locked_region.data = ogl_bitmap->lock_buffer + pitch * (h - 1);
   bitmap->locked_region.format = format;
   bitmap->locked_region.pitch = -pitch;
   bitmap->locked_region.pixel_size = pixel_size;
   return true;
}
Example #6
0
static void ogl_unlock_region_backbuffer(ALLEGRO_BITMAP *bitmap,
      ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap, int gl_y)
{
   const int lock_format = bitmap->locked_region.format;
   bool popmatrix = false;
   GLenum e;
   GLint program = 0;
   ALLEGRO_DISPLAY *display = al_get_current_display();

   if (display->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) {
      // FIXME: This is a hack where we temporarily disable the active shader.
      // It will only work on Desktop OpenGL in non-strict mode where we even
      // can switch back to the fixed pipeline. The correct way would be to not
      // use any OpenGL 2 functions (like glDrawPixels). Probably we will want
      // separate OpenGL <= 2 (including OpenGL ES 1) and OpenGL >= 3 (including
      // OpenGL ES >= 2) drivers at some point.
      glGetIntegerv(GL_CURRENT_PROGRAM, &program);
      glUseProgram(0);
   }

   /* glWindowPos2i may not be available. */
   if (al_get_opengl_version() >= _ALLEGRO_OPENGL_VERSION_1_4) {
      glWindowPos2i(bitmap->lock_x, gl_y);
   }
   else {
      /* glRasterPos is affected by the current modelview and projection
       * matrices (so maybe we actually need to reset both of them?).
       * The coordinate is also clipped; the small offset was required to
       * prevent it being culled on one of my machines. --pw
       *
       * Consider using glWindowPos2fMESAemulate from:
       * http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall/
       */
      glPushMatrix();
      glLoadIdentity();
      glRasterPos2f(bitmap->lock_x, bitmap->lock_y + bitmap->lock_h - 1e-4f);
      popmatrix = true;
   }

   glDisable(GL_TEXTURE_2D);
   glDisable(GL_BLEND);
   glDrawPixels(bitmap->lock_w, bitmap->lock_h,
      get_glformat(lock_format, 2),
      get_glformat(lock_format, 1),
      ogl_bitmap->lock_buffer);
   e = glGetError();
   if (e) {
      ALLEGRO_ERROR("glDrawPixels for format %s failed (%s).\n",
         _al_pixel_format_name(lock_format), _al_gl_error_string(e));
   }

   if (popmatrix) {
      glPopMatrix();
   }

   if (program != 0) {
      glUseProgram(program);
   }
}
Example #7
0
static bool check_gl_error(const char* name)
{
   GLenum err = glGetError();
   if (err != 0) {
      ALLEGRO_WARN("%s (%s)\n", name, _al_gl_error_string(err));
      return false;
   }
   return true;
}
Example #8
0
static void use_fbo_for_bitmap(ALLEGRO_DISPLAY *display,
   ALLEGRO_BITMAP *bitmap, ALLEGRO_FBO_INFO *info)
{
   ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap = bitmap->extra;
   GLint e;

   if (info->fbo_state == FBO_INFO_UNUSED)
      info->fbo_state = FBO_INFO_TRANSIENT;
   info->owner = bitmap;
   info->last_use_time = al_get_time();
   ogl_bitmap->fbo_info = info;

   /* Bind to the FBO. */
   _al_ogl_bind_framebuffer(info->fbo);

   /* Attach the texture. */
   if (ANDROID_PROGRAMMABLE_PIPELINE(al_get_current_display())) {
      glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
         GL_TEXTURE_2D, ogl_bitmap->texture, 0);
   }
   else {
      glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
         GL_TEXTURE_2D, ogl_bitmap->texture, 0);
   }
   e = glGetError();
   if (e) {
      ALLEGRO_DEBUG("glFrameBufferTexture2DEXT failed! fbo=%d texture=%d (%s)",
         info->fbo, ogl_bitmap->texture, _al_gl_error_string(e));
   }

   /* See comment about unimplemented functions on Android above */
   if (UNLESS_ANDROID_OR_RPI(
         glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT))
   {
      /* For some reason, we cannot use the FBO with this
       * texture. So no reason to keep re-trying, output a log
       * message and switch to (extremely slow) software mode.
       */
      ALLEGRO_ERROR("Could not use FBO for bitmap with format %s.\n",
         _al_pixel_format_name(al_get_bitmap_format(bitmap)));
      ALLEGRO_ERROR("*** SWITCHING TO SOFTWARE MODE ***\n");
      _al_ogl_bind_framebuffer(0);
      glDeleteFramebuffersEXT(1, &info->fbo);
      _al_ogl_reset_fbo_info(info);
      ogl_bitmap->fbo_info = NULL;
   }
   else {
      display->ogl_extras->opengl_target = bitmap;
   }
}
Example #9
0
static void xdpy_flip_display(ALLEGRO_DISPLAY *d)
{
   ALLEGRO_SYSTEM_XGLX *system = (ALLEGRO_SYSTEM_XGLX *)al_get_system_driver();
   ALLEGRO_DISPLAY_XGLX *glx = (ALLEGRO_DISPLAY_XGLX *)d;

   int e = glGetError();
   if (e) {
      ALLEGRO_ERROR("OpenGL error was not 0: %s\n", _al_gl_error_string(e));
   }

   if (d->extra_settings.settings[ALLEGRO_SINGLE_BUFFER])
      glFlush();
   else
      glXSwapBuffers(system->gfxdisplay, glx->glxwindow);
}
Example #10
0
GLint _al_ogl_bind_framebuffer(GLint fbo)
{
   GLint old_fbo = _al_android_get_curr_fbo();
   GLint e;

   if (ANDROID_PROGRAMMABLE_PIPELINE(al_get_current_display())) {
      glBindFramebuffer(GL_FRAMEBUFFER, fbo);
   }
   else {
      glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
   }
   e = glGetError();
   if (e) {
      ALLEGRO_DEBUG("glBindFramebufferEXT failed (%s)",
         _al_gl_error_string(e));
   }
   _al_android_set_curr_fbo(fbo);
   return old_fbo;
}
Example #11
0
static void ogl_unlock_region_backbuffer(ALLEGRO_BITMAP *bitmap,
      ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap, int gl_y)
{
   const int lock_format = bitmap->locked_region.format;
   bool popmatrix = false;
   GLenum e;

   /* glWindowPos2i may not be available. */
   if (al_get_opengl_version() >= _ALLEGRO_OPENGL_VERSION_1_4) {
      glWindowPos2i(bitmap->lock_x, gl_y);
   }
   else {
      /* glRasterPos is affected by the current modelview and projection
       * matrices (so maybe we actually need to reset both of them?).
       * The coordinate is also clipped; the small offset was required to
       * prevent it being culled on one of my machines. --pw
       *
       * Consider using glWindowPos2fMESAemulate from:
       * http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall/
       */
      glPushMatrix();
      glLoadIdentity();
      glRasterPos2f(bitmap->lock_x, bitmap->lock_y + bitmap->lock_h - 1e-4f);
      popmatrix = true;
   }

   glDisable(GL_TEXTURE_2D);
   glDisable(GL_BLEND);
   glDrawPixels(bitmap->lock_w, bitmap->lock_h,
      get_glformat(lock_format, 2),
      get_glformat(lock_format, 1),
      ogl_bitmap->lock_buffer);
   e = glGetError();
   if (e) {
      ALLEGRO_ERROR("glDrawPixels for format %s failed (%s).\n",
         _al_format_name(lock_format), _al_gl_error_string(e));
   }

   if (popmatrix) {
      glPopMatrix();
   }
}
Example #12
0
static bool glsl_use_shader(ALLEGRO_SHADER *shader, ALLEGRO_DISPLAY *display,
   bool set_projview_matrix_from_display)
{
   ALLEGRO_SHADER_GLSL_S *gl_shader;
   GLuint program_object;
   GLenum err;

   if (!(display->flags & ALLEGRO_OPENGL)) {
      return false;
   }

   gl_shader = (ALLEGRO_SHADER_GLSL_S *)shader;
   program_object = gl_shader->program_object;

   glGetError(); /* clear error */
   glUseProgram(program_object);
   err = glGetError();
   if (err != GL_NO_ERROR) {
      ALLEGRO_WARN("glUseProgram(%u) failed: %s\n", program_object,
         _al_gl_error_string(err));
      display->ogl_extras->program_object = 0;
      return false;
   }

   display->ogl_extras->program_object = program_object;

   /* Copy variable locations. */
   display->ogl_extras->varlocs = gl_shader->varlocs;

   /* Optionally set projview matrix.  We skip this when it is known that the
    * matrices in the display are out of date and are about to be clobbered
    * itself.
    */
   if (set_projview_matrix_from_display) {
      _al_glsl_set_projview_matrix(
         display->ogl_extras->varlocs.projview_matrix_loc, &display->projview_transform);
   }

   return true;
}
Example #13
0
static void ogl_unlock_region_nonbb_fbo_readwrite(ALLEGRO_BITMAP *bitmap,
   ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap, int gl_y)
{
   const int lock_format = bitmap->locked_region.format;
   GLenum e;
   GLint tex_internalformat;

   glTexSubImage2D(GL_TEXTURE_2D, 0, bitmap->lock_x, gl_y,
      bitmap->lock_w, bitmap->lock_h,
      get_glformat(lock_format, 2),
      get_glformat(lock_format, 1),
      ogl_bitmap->lock_buffer);

   e = glGetError();
   if (e) {
      ALLEGRO_ERROR("glTexSubImage2D for format %s failed (%s).\n",
         _al_pixel_format_name(lock_format), _al_gl_error_string(e));
      glGetTexLevelParameteriv(GL_TEXTURE_2D, 0,
         GL_TEXTURE_INTERNAL_FORMAT, &tex_internalformat);
      ALLEGRO_DEBUG("x/y/w/h: %d/%d/%d/%d, internal format: %d\n",
         bitmap->lock_x, gl_y, bitmap->lock_w, bitmap->lock_h,
         tex_internalformat);
   }
}
Example #14
0
ALLEGRO_LOCKED_REGION *_al_ogl_lock_region_new(ALLEGRO_BITMAP *bitmap,
   int x, int y, int w, int h, int format, int flags)
{
   ALLEGRO_BITMAP_EXTRA_OPENGL * const ogl_bitmap = bitmap->extra;
   const GLint gl_y = bitmap->h - y - h;
   ALLEGRO_DISPLAY *disp;
   ALLEGRO_DISPLAY *old_disp = NULL;
   ALLEGRO_BITMAP *old_target = al_get_target_bitmap();
   GLenum e;
   bool ok;
   bool restore_fbo = false;

   if (format == ALLEGRO_PIXEL_FORMAT_ANY) {
      /* Never pick compressed formats with ANY, as it interacts weirdly with
       * existing code (e.g. al_get_pixel_size() etc) */
      int bitmap_format = al_get_bitmap_format(bitmap);
      if (_al_pixel_format_is_compressed(bitmap_format)) {
         // XXX Get a good format from the driver?
         format = ALLEGRO_PIXEL_FORMAT_ABGR_8888_LE;
      }
      else {
         format = bitmap_format;
      }
   }

   disp = al_get_current_display();
   format = _al_get_real_pixel_format(disp, format);

   /* Change OpenGL context if necessary. */
   if (!disp ||
      (_al_get_bitmap_display(bitmap)->ogl_extras->is_shared == false &&
       _al_get_bitmap_display(bitmap) != disp))
   {
      old_disp = disp;
      _al_set_current_display_only(_al_get_bitmap_display(bitmap));
   }

   ok = true;

   /* Set up the pixel store state.  We will need to match it when unlocking.
    * There may be other pixel store state we should be setting.
    * See also pitfalls 7 & 8 from:
    * http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall/
    */
   glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
   {
      const int pixel_size = al_get_pixel_size(format);
      const int pixel_alignment = ogl_pixel_alignment(pixel_size);
      glPixelStorei(GL_PACK_ALIGNMENT, pixel_alignment);
      e = glGetError();
      if (e) {
         ALLEGRO_ERROR("glPixelStorei(GL_PACK_ALIGNMENT, %d) failed (%s).\n",
            pixel_alignment, _al_gl_error_string(e));
         ok = false;
      }
   }

   if (ok) {
      if (ogl_bitmap->is_backbuffer) {
         ALLEGRO_DEBUG("Locking backbuffer\n");
         ok = ogl_lock_region_backbuffer(bitmap, ogl_bitmap,
            x, gl_y, w, h, format, flags);
      }
      else if (flags & ALLEGRO_LOCK_WRITEONLY) {
         ALLEGRO_DEBUG("Locking non-backbuffer WRITEONLY\n");
         ok = ogl_lock_region_nonbb_writeonly(bitmap, ogl_bitmap,
            x, gl_y, w, h, format);
      }
      else {
         ALLEGRO_DEBUG("Locking non-backbuffer READWRITE\n");
         ok = ogl_lock_region_nonbb_readwrite(bitmap, ogl_bitmap,
            x, gl_y, w, h, format, &restore_fbo);
      }
   }

   glPopClientAttrib();

   /* Restore state after switching FBO. */
   if (restore_fbo) {
      if (!old_target) {
         /* Old target was NULL; release the context. */
         _al_set_current_display_only(NULL);
      }
      else if (!_al_get_bitmap_display(old_target)) {
         /* Old target was memory bitmap; leave the current display alone. */
      }
      else if (old_target != bitmap) {
         /* Old target was another OpenGL bitmap. */
         _al_ogl_setup_fbo(_al_get_bitmap_display(old_target), old_target);
      }
   }

   ASSERT(al_get_target_bitmap() == old_target);

   if (old_disp != NULL) {
      _al_set_current_display_only(old_disp);
   }

   if (ok) {
      return &bitmap->locked_region;
   }

   ALLEGRO_ERROR("Failed to lock region\n");
   ASSERT(ogl_bitmap->lock_buffer == NULL);
   return NULL;
}
Example #15
0
static void ogl_flush_vertex_cache(ALLEGRO_DISPLAY *disp)
{
    GLuint current_texture;
    ALLEGRO_OGL_EXTRAS *o = disp->ogl_extras;

    if (!disp->vertex_cache)
        return;
    if (disp->num_cache_vertices == 0)
        return;

    if (disp->flags & ALLEGRO_USE_PROGRAMMABLE_PIPELINE) {
#ifndef ALLEGRO_CFG_NO_GLES2
        if (disp->ogl_extras->use_tex_loc >= 0) {
            glUniform1i(disp->ogl_extras->use_tex_loc, 1);
        }
        if (disp->ogl_extras->use_tex_matrix_loc >= 0) {
            glUniform1i(disp->ogl_extras->use_tex_matrix_loc, 0);
        }
#endif
    }
    else {
        glEnable(GL_TEXTURE_2D);
    }

    glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&current_texture);
    if (current_texture != disp->cache_texture) {
        if (disp->flags & ALLEGRO_USE_PROGRAMMABLE_PIPELINE) {
#ifndef ALLEGRO_CFG_NO_GLES2
            /* Use texture unit 0 */
            glActiveTexture(GL_TEXTURE0);
            if (disp->ogl_extras->tex_loc >= 0)
                glUniform1i(disp->ogl_extras->tex_loc, 0);
#endif
        }
        glBindTexture(GL_TEXTURE_2D, disp->cache_texture);
    }

#if !defined ALLEGRO_IPHONE && !defined ALLEGRO_ANDROID
    if (disp->flags & ALLEGRO_USE_PROGRAMMABLE_PIPELINE) {
        int stride = sizeof(ALLEGRO_OGL_BITMAP_VERTEX);
        int bytes = disp->num_cache_vertices * stride;

        /* We create the VAO and VBO on first use. */
        if (o->vao == 0) {
            glGenVertexArrays(1, &o->vao);
            ALLEGRO_DEBUG("new VAO: %u\n", o->vao);
        }
        glBindVertexArray(o->vao);

        if (o->vbo == 0) {
            glGenBuffers(1, &o->vbo);
            ALLEGRO_DEBUG("new VBO: %u\n", o->vbo);
        }
        glBindBuffer(GL_ARRAY_BUFFER, o->vbo);

        /* Then we upload data into it. */
        glBufferData(GL_ARRAY_BUFFER, bytes, disp->vertex_cache, GL_STREAM_DRAW);

        /* Finally set the "pos", "texccord" and "color" attributes used by our
         * shader and enable them.
         */
        if (o->pos_loc >= 0)  {
            glVertexAttribPointer(o->pos_loc, 2, GL_FLOAT, false, stride,
                                  (void *)offsetof(ALLEGRO_OGL_BITMAP_VERTEX, x));
            glEnableVertexAttribArray(o->pos_loc);
        }

        if (o->texcoord_loc >= 0) {
            glVertexAttribPointer(o->texcoord_loc, 2, GL_FLOAT, false, stride,
                                  (void *)offsetof(ALLEGRO_OGL_BITMAP_VERTEX, tx));
            glEnableVertexAttribArray(o->texcoord_loc);
        }

        if (o->color_loc >= 0) {
            glVertexAttribPointer(o->color_loc, 4, GL_FLOAT, false, stride,
                                  (void *)offsetof(ALLEGRO_OGL_BITMAP_VERTEX, r));
            glEnableVertexAttribArray(o->color_loc);
        }
    }
    else
#endif
    {
        vert_ptr_on(disp, 2, GL_FLOAT, sizeof(ALLEGRO_OGL_BITMAP_VERTEX),
                    (char *)(disp->vertex_cache) + offsetof(ALLEGRO_OGL_BITMAP_VERTEX, x));
        tex_ptr_on(disp, 2, GL_FLOAT, sizeof(ALLEGRO_OGL_BITMAP_VERTEX),
                   (char*)(disp->vertex_cache) + offsetof(ALLEGRO_OGL_BITMAP_VERTEX, tx));
        color_ptr_on(disp, 4, GL_FLOAT, sizeof(ALLEGRO_OGL_BITMAP_VERTEX),
                     (char*)(disp->vertex_cache) + offsetof(ALLEGRO_OGL_BITMAP_VERTEX, r));

        if (!(disp->flags & ALLEGRO_USE_PROGRAMMABLE_PIPELINE))
            glDisableClientState(GL_NORMAL_ARRAY);
    }

    glDrawArrays(GL_TRIANGLES, 0, disp->num_cache_vertices);

#ifdef DEBUGMODE
    {
        int e = glGetError();
        if (e) {
            ALLEGRO_WARN("glDrawArrays failed: %s\n", _al_gl_error_string(e));
        }
    }
#endif

#if !defined ALLEGRO_IPHONE && !defined ALLEGRO_ANDROID
    if (disp->flags & ALLEGRO_USE_PROGRAMMABLE_PIPELINE) {
        if (o->pos_loc >= 0) glDisableVertexAttribArray(o->pos_loc);
        if (o->texcoord_loc >= 0) glDisableVertexAttribArray(o->texcoord_loc);
        if (o->color_loc >= 0) glDisableVertexAttribArray(o->color_loc);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindVertexArray(0);
    }
    else
#endif
    {
        vert_ptr_off(disp);
        tex_ptr_off(disp);
        color_ptr_off(disp);
    }

    disp->num_cache_vertices = 0;

    if (disp->flags & ALLEGRO_USE_PROGRAMMABLE_PIPELINE) {
#ifndef ALLEGRO_CFG_NO_GLES2
        if (disp->ogl_extras->use_tex_loc >= 0)
            glUniform1i(disp->ogl_extras->use_tex_loc, 0);
#endif
    }
}
Example #16
0
bool _al_ogl_create_persistent_fbo(ALLEGRO_BITMAP *bitmap)
{
   ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap;
   ALLEGRO_FBO_INFO *info;
   GLint old_fbo, e;

   if (bitmap->parent)
      bitmap = bitmap->parent;
   ogl_bitmap = bitmap->extra;

   /* Don't continue if the bitmap does not belong to the current display. */
   if (_al_get_bitmap_display(bitmap)->ogl_extras->is_shared == false &&
         _al_get_bitmap_display(bitmap) != al_get_current_display()) {
      return false;
   }

   if (ogl_bitmap->is_backbuffer) {
      return false;
   }

   ASSERT(!ogl_bitmap->fbo_info);

   info = al_malloc(sizeof(ALLEGRO_FBO_INFO));
   if (ANDROID_PROGRAMMABLE_PIPELINE(al_get_current_display())) {
      glGenFramebuffers(1, &info->fbo);
   }
   else {
      glGenFramebuffersEXT(1, &info->fbo);
   }
   if (info->fbo == 0) {
      al_free(info);
      return false;
   }

   old_fbo = _al_ogl_bind_framebuffer(info->fbo);

   if (ANDROID_PROGRAMMABLE_PIPELINE(al_get_current_display())) {
      glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
         GL_TEXTURE_2D, ogl_bitmap->texture, 0);
   }
   else {
      glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
         GL_TEXTURE_2D, ogl_bitmap->texture, 0);
   }

   e = glGetError();
   if (e) {
      ALLEGRO_DEBUG("glFrameBufferTexture2DEXT failed! fbo=%d texture=%d (%s)",
         info->fbo, ogl_bitmap->texture, _al_gl_error_string(e));
   }

   /* You'll see this a couple times in this file: some ES 1.1 functions aren't
    * implemented on Android. This is an ugly workaround.
    */
   if (UNLESS_ANDROID_OR_RPI(
         glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT))
   {
      ALLEGRO_ERROR("FBO incomplete.\n");
      _al_ogl_bind_framebuffer(old_fbo);
      glDeleteFramebuffersEXT(1, &info->fbo);
      al_free(info);
      return false;
   }

   _al_ogl_bind_framebuffer(old_fbo);

   info->fbo_state = FBO_INFO_PERSISTENT;
   info->owner = bitmap;
   info->last_use_time = al_get_time();
   ogl_bitmap->fbo_info = info;
   ALLEGRO_DEBUG("Persistent FBO: %u\n", info->fbo);
   return true;
}
Example #17
0
static void ogl_unlock_region_non_readonly(ALLEGRO_BITMAP *bitmap,
   ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap)
{
   const int lock_format = bitmap->locked_region.format;
   const int gl_y = bitmap->h - bitmap->lock_y - bitmap->lock_h;
   ALLEGRO_DISPLAY *old_disp = NULL;
   ALLEGRO_DISPLAY *disp;
   int orig_format;
   bool biased_alpha = false;
   GLenum e;

   disp = al_get_current_display();
   orig_format = _al_get_real_pixel_format(disp, _al_get_bitmap_memory_format(bitmap));

   /* Change OpenGL context if necessary. */
   if (!disp ||
      (_al_get_bitmap_display(bitmap)->ogl_extras->is_shared == false &&
       _al_get_bitmap_display(bitmap) != disp))
   {
      old_disp = disp;
      _al_set_current_display_only(_al_get_bitmap_display(bitmap));
   }

   /* Keep this in sync with ogl_lock_region. */
   glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
   {
      const int lock_pixel_size = al_get_pixel_size(lock_format);
      const int pixel_alignment = ogl_pixel_alignment(lock_pixel_size);
      glPixelStorei(GL_UNPACK_ALIGNMENT, pixel_alignment);
      e = glGetError();
      if (e) {
         ALLEGRO_ERROR("glPixelStorei(GL_UNPACK_ALIGNMENT, %d) failed (%s).\n",
            pixel_alignment, _al_gl_error_string(e));
      }
   }
   if (exactly_15bpp(lock_format)) {
      /* OpenGL does not support 15-bpp internal format without an alpha,
       * so when storing such data we must ensure the alpha bit is set.
       */
      glPixelTransferi(GL_ALPHA_BIAS, 1);
      biased_alpha = true;
   }

   if (ogl_bitmap->is_backbuffer) {
      ALLEGRO_DEBUG("Unlocking backbuffer\n");
      ogl_unlock_region_backbuffer(bitmap, ogl_bitmap, gl_y);
   }
   else {
      glBindTexture(GL_TEXTURE_2D, ogl_bitmap->texture);
      if (ogl_bitmap->fbo_info) {
         ALLEGRO_DEBUG("Unlocking non-backbuffer (FBO)\n");
         ogl_unlock_region_nonbb_fbo(bitmap, ogl_bitmap, gl_y, orig_format);
      }
      else {
         ALLEGRO_DEBUG("Unlocking non-backbuffer (non-FBO)\n");
         ogl_unlock_region_nonbb_nonfbo(bitmap, ogl_bitmap, gl_y);
      }

      /* If using FBOs, we need to regenerate mipmaps explicitly now. */
      /* XXX why don't we check ogl_bitmap->fbo_info? */
      if ((al_get_bitmap_flags(bitmap) & ALLEGRO_MIPMAP) &&
         al_get_opengl_extension_list()->ALLEGRO_GL_EXT_framebuffer_object)
      {
         glGenerateMipmapEXT(GL_TEXTURE_2D);
         e = glGetError();
         if (e) {
            ALLEGRO_ERROR("glGenerateMipmapEXT for texture %d failed (%s).\n",
               ogl_bitmap->texture, _al_gl_error_string(e));
         }
      }
   }

   if (biased_alpha) {
      glPixelTransferi(GL_ALPHA_BIAS, 0);
   }
   glPopClientAttrib();

   if (old_disp) {
      _al_set_current_display_only(old_disp);
   }
}
Example #18
0
ALLEGRO_LOCKED_REGION *_al_ogl_lock_region_new(ALLEGRO_BITMAP *bitmap,
   int x, int y, int w, int h, int format, int flags)
{
   ALLEGRO_BITMAP_EXTRA_OPENGL * const ogl_bitmap = bitmap->extra;
   const GLint gl_y = bitmap->h - y - h;
   ALLEGRO_DISPLAY *disp;
   ALLEGRO_DISPLAY *old_disp = NULL;
   GLenum e;

   if (format == ALLEGRO_PIXEL_FORMAT_ANY) {
      format = bitmap->format;
   }

   disp = al_get_current_display();
   format = _al_get_real_pixel_format(disp, format);

   /* Change OpenGL context if necessary. */
   if (!disp ||
      (bitmap->display->ogl_extras->is_shared == false &&
       bitmap->display != disp))
   {
      old_disp = disp;
      _al_set_current_display_only(bitmap->display);
   }

   /* Set up the pixel store state.  We will need to match it when unlocking.
    * There may be other pixel store state we should be setting.
    * See also pitfalls 7 & 8 from:
    * http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall/
    */
   glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
   {
      const int pixel_size = al_get_pixel_size(format);
      const int pixel_alignment = ogl_pixel_alignment(pixel_size);
      glPixelStorei(GL_PACK_ALIGNMENT, pixel_alignment);
      e = glGetError();
      if (e) {
         ALLEGRO_ERROR("glPixelStorei(GL_PACK_ALIGNMENT, %d) failed (%s).\n",
            pixel_alignment, _al_gl_error_string(e));
      }
   }

   if (ogl_bitmap->is_backbuffer) {
      ALLEGRO_DEBUG("Locking backbuffer\n");
      ogl_lock_region_backbuffer(bitmap, ogl_bitmap,
         x, gl_y, w, h, format, flags);
   }
   else if (flags & ALLEGRO_LOCK_WRITEONLY) {
      ALLEGRO_DEBUG("Locking non-backbuffer WRITEONLY\n");
      ogl_lock_region_nonbb_writeonly(bitmap, ogl_bitmap,
         x, gl_y, w, h, format);
   }
   else {
      ALLEGRO_DEBUG("Locking non-backbuffer READWRITE\n");
      ogl_lock_region_nonbb_readwrite(bitmap, ogl_bitmap,
         x, gl_y, w, h, format);
   }

   glPopClientAttrib();

   if (old_disp != NULL) {
      _al_set_current_display_only(old_disp);
   }

   return &bitmap->locked_region;
}