Re: [AD] offscreen sub bitmaps revisited |
[ Thread Index |
Date Index
| More lists.liballeg.org/allegro-developers Archives
]
- To: "Coordination of admins/developers of the game programming library Allegro" <alleg-developers@xxxxxxxxxx>
- Subject: Re: [AD] offscreen sub bitmaps revisited
- From: Matthew Leverton <meffer@xxxxxxxxxx>
- Date: Sun, 27 Jun 2010 00:06:25 -0500
On Sat, Jun 26, 2010 at 1:04 PM, Matthew Leverton <meffer@xxxxxxxxxx> wrote:
> On Sat, Jun 26, 2010 at 7:52 AM, Elias Pschernig
>> You can apply the patch as is I'd say, will be more
>> motivation to fix things properly.
>>
Applied the attached patch.
Drawing from and to out-of-bounds memory sub-bitmaps should work now.
Tested with ex_subbitmap on regular, scaled, and flipped bitmaps.
I'm assuming it doesn't work with transformations on memory bitmaps.
OpenGL is buggy when blitting from an out-of-bounds source sub bitmap.
Haven't tested D3D.
--
Matthew Leverton
Index: src/bitmap.c
===================================================================
--- src/bitmap.c (revision 13401)
+++ src/bitmap.c (working copy)
@@ -616,34 +616,12 @@
{
ALLEGRO_BITMAP *bitmap;
- /* Clip */
- if (x < 0) {
- w += x;
- if (w < 0) w = 0;
- x = 0;
- }
- if (y < 0) {
- h += y;
- if (h < 0) h = 0;
- y = 0;
- }
- if (x+w > parent->w) {
- w = parent->w - x;
- }
- if (y+h > parent->h) {
- h = parent->h - y;
- }
-
if (parent->parent) {
x += parent->xofs;
y += parent->yofs;
parent = parent->parent;
}
- /* Note:
- * Drivers are guaranteed that the parent is not a subbitmap itself
- * and that the passed rectangle lies fully within the parent.
- */
if (parent->display && parent->display->vt &&
parent->display->vt->create_sub_bitmap)
{
Index: src/memblit.c
===================================================================
--- src/memblit.c (revision 13401)
+++ src/memblit.c (working copy)
@@ -166,8 +166,108 @@
#define SRC_NOT_MODIFIED \
src_mode == ALLEGRO_ONE && src_alpha == ALLEGRO_ONE && \
tint.r == 1.0f && tint.g == 1.0f && tint.b == 1.0f && tint.a == 1.0f
+
+/* sub-bitmaps may originate and extend off its parents boundaries in any
+ * direction. The HANDLE_SUB_BITMAPS macro takes post-clipped coordinates
+ * for both the source and destination bitmaps and further restricts them
+ * as necessary. The wr and hr parameters are the ratio of source
+ * width & height to destination width & height _before_ clipping.
+ *
+ * First the left (top) coordinates are moved inward. Then the right
+ * (bottom) coordinates are moved inward. The changes are applied
+ * simultaneously to the complementary bitmap with scaling taken into
+ * consideration.
+ *
+ * The coordinates are modified, and the sub-bitmaps are set to the
+ * parent bitmaps. If nothing needs to be drawn, the macro exits the
+ * function.
+ */
+#define HANDLE_SUB_BITMAPS(src, sx, sy, sw, sh, dest, dx, dy, dw, dh, wr, hr) \
+ \
+ if (dest->parent) { \
+ dx += dest->xofs; \
+ if (dx < 0) { \
+ int scaled_width = dx * wr; \
+ sw += scaled_width; \
+ sx -= scaled_width; \
+ dw += dx; \
+ dx = 0; \
+ } \
+ else if (dx >= dest->parent->w) { \
+ return; \
+ } \
+ \
+ dy += dest->yofs; \
+ if (dy < 0) { \
+ int scaled_height = dy * hr; \
+ sh += scaled_height; \
+ sy -= scaled_height; \
+ dh += dy; \
+ dy = 0; \
+ } \
+ else if (dy >= dest->parent->h) { \
+ return; \
+ } \
+ \
+ dest = dest->parent; \
+ \
+ if (dx + dw > dest->w) { \
+ sw -= (dx + dw - dest->w) * wr; \
+ dw = dest->w - dx; \
+ } \
+ \
+ if (dy + dh > dest->h) { \
+ sh -= (dy + dh - dest->h) * hr; \
+ dh = dest->h - dy; \
+ } \
+ \
+ if (dw <= 0 || dh <= 0) { \
+ return; \
+ } \
+ } \
+ \
+ if (src->parent) { \
+ sx += src->xofs; \
+ if (sx < 0) { \
+ int scaled_width = sx / wr; \
+ dw += scaled_width; \
+ dx -= scaled_width; \
+ sw += sx; \
+ sx = 0; \
+ } \
+ else if (sx >= src->parent->w) { \
+ return; \
+ } \
+ \
+ sy += src->yofs; \
+ if (sy < 0) { \
+ int scaled_height = sy / hr; \
+ dh += scaled_height; \
+ dy -= scaled_height; \
+ sh += sy; \
+ sy = 0; \
+ } \
+ else if (sy >= src->parent->h) { \
+ return; \
+ } \
+ \
+ src = src->parent; \
+ \
+ if (sx + sw > src->w) { \
+ dw -= (sx + sw - src->w) / wr; \
+ sw = src->w - sx; \
+ } \
+ \
+ if (sy + sh > src->h) { \
+ dh -= (sy + sh - src->h) / hr; \
+ sh = src->h - sy; \
+ } \
+ \
+ if (sw <= 0 || sh <= 0) { \
+ return; \
+ } \
+ }
-
void _al_draw_bitmap_region_memory(ALLEGRO_BITMAP *bitmap,
ALLEGRO_COLOR tint,
int sx, int sy, int sw, int sh,
@@ -182,6 +282,7 @@
int xinc, yinc;
int yd;
int sxd;
+ int dw, dh;
if(!is_identity(al_get_current_transform()))
{
@@ -228,19 +329,11 @@
return;
}
- /* Handle sub bitmaps */
- if (dest->parent) {
- dx += dest->xofs;
- dy += dest->yofs;
- dest = dest->parent;
- }
+ dw = sw;
+ dh = sh;
+
+ HANDLE_SUB_BITMAPS(bitmap, sx, sy, sw, sh, dest, dx, dy, dw, dh, 1.0f, 1.0f)
- if (bitmap->parent) {
- sx += bitmap->xofs;
- sy += bitmap->yofs;
- bitmap = bitmap->parent;
- }
-
#ifdef ALLEGRO_GP2XWIZ
if (src_mode == ALLEGRO_ALPHA &&
dst_mode == ALLEGRO_INVERSE_ALPHA &&
@@ -431,19 +524,8 @@
if (dw == 0 || dh == 0)
return;
- /* Handle sub bitmaps */
- if (dest->parent) {
- dx += dest->xofs;
- dy += dest->yofs;
- dest = dest->parent;
- }
+ HANDLE_SUB_BITMAPS(src, sx, sy, sw, sh, dest, dx, dy, dw, dh, sxinc, syinc)
- if (src->parent) {
- sx += src->xofs;
- sy += src->yofs;
- src = src->parent;
- }
-
if (!(src_region = al_lock_bitmap(src, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READONLY))) {
return;
}
@@ -1256,6 +1338,7 @@
ALLEGRO_BITMAP *dest = al_get_target_bitmap();
int x;
int y;
+ int dw, dh;
ASSERT(_al_pixel_format_is_real(bitmap->format));
ASSERT(_al_pixel_format_is_real(dest->format));
@@ -1283,19 +1366,11 @@
sh -= inc;
}
- /* Handle sub bitmaps */
- if (dest->parent) {
- dx += dest->xofs;
- dy += dest->yofs;
- dest = dest->parent;
- }
+ dw = sw;
+ dh = sh;
+
+ HANDLE_SUB_BITMAPS(bitmap, sx, sy, sw, sh, dest, dx, dy, dw, dh, 1.0f, 1.0f)
- if (bitmap->parent) {
- sx += bitmap->xofs;
- sy += bitmap->yofs;
- bitmap = bitmap->parent;
- }
-
/* Fast paths for no flipping */
if (!(flags & ALLEGRO_FLIP_HORIZONTAL) &&
!(flags & ALLEGRO_FLIP_VERTICAL)) {
@@ -1419,19 +1494,8 @@
if (dw == 0 || dh == 0)
return;
- /* Handle sub bitmaps */
- if (dest->parent) {
- dx += dest->xofs;
- dy += dest->yofs;
- dest = dest->parent;
- }
+ HANDLE_SUB_BITMAPS(src, sx, sy, sw, sh, dest, dx, dy, dw, dh, sxinc, syinc)
- if (src->parent) {
- sx += src->xofs;
- sy += src->yofs;
- src = src->parent;
- }
-
if (src->format == dest->format) {
if (!(src_region = al_lock_bitmap(src, ALLEGRO_PIXEL_FORMAT_ANY,
ALLEGRO_LOCK_READONLY))) {
Index: docs/src/refman/graphics.txt
===================================================================
--- docs/src/refman/graphics.txt (revision 13401)
+++ docs/src/refman/graphics.txt (working copy)
@@ -301,8 +301,7 @@
pre-existing (parent) bitmap, but possibly with a different size and
clipping settings.
-If the sub-bitmap does not lie completely inside the parent bitmap, then
-it is automatically clipped so that it does.
+The sub-bitmap may originate off or extend past the parent bitmap.
See the discussion in [al_get_backbuffer] about using sub-bitmaps of
the backbuffer.
Index: examples/ex_subbitmap.c
===================================================================
--- examples/ex_subbitmap.c (revision 13401)
+++ examples/ex_subbitmap.c (working copy)
@@ -50,8 +50,8 @@
int dst_y2 = DST_HEIGHT-1;
Mode mode = PLAIN_BLIT;
+int draw_flags = 0;
-
int main(void)
{
ALLEGRO_BITMAP *src_subbmp[2] = {NULL, NULL};
@@ -147,16 +147,20 @@
al_set_target_bitmap(dst_subbmp[1]);
switch (mode) {
case PLAIN_BLIT:
- al_draw_bitmap(src_subbmp[1], 0, 0, 0);
+ {
+ al_draw_bitmap(src_subbmp[1], 0, 0, draw_flags);
break;
+ }
case SCALED_BLIT:
+ {
al_draw_scaled_bitmap(src_subbmp[1],
0, 0, al_get_bitmap_width(src_subbmp[1]),
al_get_bitmap_height(src_subbmp[1]),
0, 0, al_get_bitmap_width(dst_subbmp[1]),
al_get_bitmap_height(dst_subbmp[1]),
- 0);
+ draw_flags);
break;
+ }
}
#define SWAP_GREATER(f1, f2) { \
@@ -222,6 +226,14 @@
mode = SCALED_BLIT;
redraw = true;
}
+ else if (event.keyboard.unichar == 'h') {
+ draw_flags ^= ALLEGRO_FLIP_HORIZONTAL;
+ redraw = true;
+ }
+ else if (event.keyboard.unichar == 'v') {
+ draw_flags ^= ALLEGRO_FLIP_VERTICAL;
+ redraw = true;
+ }
}
else if (event.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN &&
event.mouse.button == 1) {