[AD] opengl clipping state

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


exnew_lines shows a bug in the OpenGL driver: a call to
al_set_clipping_rectangle(bitmap) where bitmap is the target bitmap won't
update the OpenGL state immediately.  Does the following fix look okay?

Previously I was worried about what happens if you set the clipping rectangle
from one thread while it is set as the target bitmap for another thread, but I
guess you can't do that.

Peter

diff --git a/include/allegro5/internal/aintern_bitmap.h b/include/allegro5/internal/aintern_bitmap.h
index 4908efe..33af5c8 100644
--- a/include/allegro5/internal/aintern_bitmap.h
+++ b/include/allegro5/internal/aintern_bitmap.h
@@ -84,6 +84,8 @@ struct ALLEGRO_BITMAP_INTERFACE
     * read the contents of an associated texture.
     */
 
+   void (*update_clipping_rectangle)(ALLEGRO_BITMAP *bitmap);
+
    void (*destroy_bitmap)(ALLEGRO_BITMAP *bitmap);
 
    ALLEGRO_LOCKED_REGION * (*lock_region)(ALLEGRO_BITMAP *bitmap,
diff --git a/include/allegro5/internal/aintern_opengl.h b/include/allegro5/internal/aintern_opengl.h
index 04feca1..10261ec 100644
--- a/include/allegro5/internal/aintern_opengl.h
+++ b/include/allegro5/internal/aintern_opengl.h
@@ -87,6 +87,7 @@ ALLEGRO_BITMAP *_al_ogl_create_sub_bitmap(ALLEGRO_DISPLAY *d, ALLEGRO_BITMAP *pa
 
 /* common driver */
 void _al_ogl_set_target_bitmap(ALLEGRO_DISPLAY *display, ALLEGRO_BITMAP *bitmap);
+void _al_ogl_setup_bitmap_clipping(const ALLEGRO_BITMAP *bitmap);
 ALLEGRO_BITMAP *_al_ogl_get_backbuffer(ALLEGRO_DISPLAY *d);
 ALLEGRO_BITMAP_OGL* _al_ogl_create_backbuffer(ALLEGRO_DISPLAY *disp);
 void _al_ogl_destroy_backbuffer(ALLEGRO_BITMAP_OGL *b);

diff --git a/src/display_new.c b/src/display_new.c
index dd753cb..e8115c2 100644
--- a/src/display_new.c
+++ b/src/display_new.c
@@ -458,6 +458,7 @@ bool al_wait_for_vsync(void)
  * pixels get clipped to. The default is to clip pixels
  * to the entire bitmap.
  */
+/* XXX this seems like it belongs in bitmap_new.c */
 void al_set_clipping_rectangle(int x, int y, int width, int height)
 {
    ALLEGRO_BITMAP *bitmap = al_get_target_bitmap();
@@ -483,6 +484,10 @@ void al_set_clipping_rectangle(int x, int y, int width, int height)
    bitmap->ct = y;
    bitmap->cr = x + width;
    bitmap->cb = y + height;
+
+   if (bitmap->vt->update_clipping_rectangle) {
+      bitmap->vt->update_clipping_rectangle(bitmap);
+   }
 }
 
 
@@ -491,6 +496,7 @@ void al_set_clipping_rectangle(int x, int y, int width, int height)
  *
  * Gets the clipping rectangle of the target bitmap.
  */
+/* XXX this seems like it belongs in bitmap_new.c */
 void al_get_clipping_rectangle(int *x, int *y, int *w, int *h)
 {
    ALLEGRO_BITMAP *bitmap = al_get_target_bitmap();
diff --git a/src/opengl/ogl_bitmap.c b/src/opengl/ogl_bitmap.c
index d3b04ad..59dc2dc 100644
--- a/src/opengl/ogl_bitmap.c
+++ b/src/opengl/ogl_bitmap.c
@@ -314,6 +313,19 @@ static bool ogl_upload_bitmap(ALLEGRO_BITMAP *bitmap, int x, int y,
 
 
 
+static void ogl_update_clipping_rectangle(ALLEGRO_BITMAP *bitmap)
+{
+   ALLEGRO_DISPLAY *display = al_get_current_display();
+   ALLEGRO_DISPLAY_OGL *ogl_disp = (void *)display;
+   ALLEGRO_BITMAP_OGL *ogl_bitmap = (void *)bitmap;
+
+   if (ogl_disp->opengl_target == ogl_bitmap) {
+      _al_ogl_setup_bitmap_clipping(bitmap);
+   }
+}
+
+
+
 /* OpenGL cannot "lock" pixels, so instead we update our memory copy and
  * return a pointer into that.
  */
@@ -450,12 +462,13 @@ static ALLEGRO_BITMAP_INTERFACE *ogl_bitmap_driver(void)
    memset(glbmp_vt, 0, sizeof *glbmp_vt);
 
    glbmp_vt->draw_bitmap = ogl_draw_bitmap;
-   glbmp_vt->upload_bitmap = ogl_upload_bitmap;
-   glbmp_vt->destroy_bitmap = ogl_destroy_bitmap;
-   glbmp_vt->draw_scaled_bitmap = ogl_draw_scaled_bitmap;
    glbmp_vt->draw_bitmap_region = ogl_draw_bitmap_region;
-   glbmp_vt->draw_rotated_scaled_bitmap = ogl_draw_rotated_scaled_bitmap;
+   glbmp_vt->draw_scaled_bitmap = ogl_draw_scaled_bitmap;
    glbmp_vt->draw_rotated_bitmap = ogl_draw_rotated_bitmap;
+   glbmp_vt->draw_rotated_scaled_bitmap = ogl_draw_rotated_scaled_bitmap;
+   glbmp_vt->upload_bitmap = ogl_upload_bitmap;
+   glbmp_vt->update_clipping_rectangle = ogl_update_clipping_rectangle;
+   glbmp_vt->destroy_bitmap = ogl_destroy_bitmap;
    glbmp_vt->lock_region = ogl_lock_region;
    glbmp_vt->unlock_region = ogl_unlock_region;
 
diff --git a/src/opengl/ogl_display.c b/src/opengl/ogl_display.c
index ab89752..f499f14 100644
--- a/src/opengl/ogl_display.c
+++ b/src/opengl/ogl_display.c
@@ -80,33 +80,38 @@ void _al_ogl_set_target_bitmap(ALLEGRO_DISPLAY *display, ALLEGRO_BITMAP *bitmap)
    }
 
    if (ogl_disp->opengl_target == ogl_bitmap) {
-      int x_1, y_1, x_2, y_2;
+      _al_ogl_setup_bitmap_clipping(bitmap);
+   }
+}
 
-      x_1 = bitmap->cl;
-      y_1 = bitmap->ct;
-      /* In OpenGL, coordinates are the top-left corner of pixels, so we need
-       * to add one to the right and bottom edge.
-       */
-      x_2 = bitmap->cr + 1;
-      y_2 = bitmap->cb + 1;
-
-      /* Drawing onto the sub bitmap is handled by clipping the parent. */
-      if (bitmap->parent) {
-         x_1 += bitmap->xofs;
-         y_1 += bitmap->yofs;
-         x_2 += bitmap->xofs;
-         y_2 += bitmap->yofs;
-      }
 
-      if (x_1 == 0 &&  y_1 == 0 && x_2 == bitmap->w && y_2 == bitmap->h)
-      {
-         glDisable(GL_SCISSOR_TEST);
-      }
-      else {
-         glEnable(GL_SCISSOR_TEST);
-         /* OpenGL is upside down, so must adjust y_2 to the height. */
-         glScissor(x_1, bitmap->h - y_2, x_2 - x_1, y_2 - y_1);
-      }
+void _al_ogl_setup_bitmap_clipping(const ALLEGRO_BITMAP *bitmap)
+{
+   int x_1, y_1, x_2, y_2;
+
+   x_1 = bitmap->cl;
+   y_1 = bitmap->ct;
+   /* In OpenGL, coordinates are the top-left corner of pixels, so we need
+    * to add one to the right and bottom edge.
+    */
+   x_2 = bitmap->cr + 1;
+   y_2 = bitmap->cb + 1;
+
+   /* Drawing onto the sub bitmap is handled by clipping the parent. */
+   if (bitmap->parent) {
+      x_1 += bitmap->xofs;
+      y_1 += bitmap->yofs;
+      x_2 += bitmap->xofs;
+      y_2 += bitmap->yofs;
+   }
+
+   if (x_1 == 0 &&  y_1 == 0 && x_2 == bitmap->w && y_2 == bitmap->h) {
+      glDisable(GL_SCISSOR_TEST);
+   }
+   else {
+      glEnable(GL_SCISSOR_TEST);
+      /* OpenGL is upside down, so must adjust y_2 to the height. */
+      glScissor(x_1, bitmap->h - y_2, x_2 - x_1, y_2 - y_1);
    }
 }
 






Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/