On Thu, Mar 07, 2019 at 08:19:28AM +0000, Mikolaj Kucharski wrote:
> Hi Matthieu,
> 
> On Tue, Feb 05, 2019 at 08:13:44AM +0100, Matthieu Herrb wrote:
> > On Mon, Feb 04, 2019 at 07:08:25PM +0000, Mikolaj Kucharski wrote:
> > > Hi,
> > > 
> > > Sorry for missing subject line in my initial report. I tested git
> > > checkout of commit c37c7ee0748ba828ec5d2c7304cd2a17af2c8109 of
> > > xf86-video-intel driver from:
> > > 
> > > https://gitlab.freedesktop.org/xorg/driver/xf86-video-intel.git
> > > 
> > > and it seems to work for me on Huawei MateBook X and the crash reported
> > > below is gone.
> > > 
> > > From what I can see, there are rare releases of xf86-video-intel driver,
> > > so would be possible to import to Xenocara git snapshot of the driver, if
> > > there is no recent code release?
> > 
> > Last time I tried there were a number of regression on some older
> > hardware. If you can identify which commit is fixing the crash, I
> > would be happy to check if it can be back-ported.
> 
> I spent some time git-bisect'ing the above mentioned repo and my tests
> show that commit e3edf2948467ad989590a347ffe687780192be16 is the very
> first commit which fixes the Xorg crash for me. I was bisecting between

It seems I'm off by one in terms of commits in the git repo history.
It's the next commit after above which makes the crash go away:

        9fb399aee99ad98996f872477c133f08795ec54c

> 692c14d405bb352697b67f36a034d4963e272b66 (2.99.916) and master at the
> time 6afed33b2d673d88674f0c76efe500ae414e8e1b.
> 
> There are number of commits between what I think is in base for Xenocara
> intel driver source code (692c14d405bb352697b67f36a034d4963e272b66) and
> working driver:
> 
> $ git rev-list 
> 692c14d405bb352697b67f36a034d4963e272b66..e3edf2948467ad989590a347ffe687780192be16
>  | wc -l                    
>       15

Per above off by one, it's 16 commits.
 
> In that range of commits there are multiple commits which reference bug
> report https://bugs.freedesktop.org/show_bug.cgi?id=77074 so I don't
> think backport is going to be a single commit. I didn't look into cherry
> picking some of the commits from above range, but I want to try that.
> However, before going that route, is this really good direction?

So I've looked into it and I have following list of patches, which I've
applied to xenocara/driver/xf86-video-intel (names have the commit id):

0001_30932a7b9d25_sna__Avoid_u16_underflow_when_comput.patch
0002_e0f7e9fc2f0b_sna__Initialise_and_check_for_batch_.patch
0003_faf0bdd477b9_sna__Add_some_DBG_spam_for_BLT_boxes.patch
0008_9b25eeee85d3_sna__Do_apply_damage_twice_for_miSpa.patch
0012_797369449b87_sna__Do_not_mark_the_pixmap_as_clear.patch
0016_9fb399aee99a_sna_blt__Fix_computation_of_remainai.patch

I think above is the minimal set of changes against OpenBSD's Xenocara
source code to make the crash which I'm facing go away. At the end of
this email I have `cvs -q diff -uN` output.

To explicitly list commit IDs of above changes:

$ grep -he ^commit 00{01,02,03,08,12,16}_*.patch
commit 30932a7b9d255c2037bee19e01aa3edc37b07386
commit e0f7e9fc2f0b39b9e939ff48edea29950f125420
commit faf0bdd477b9ec73f943c3101a3ae30fd6d579ea
commit 9b25eeee85d32223841640c3a39901e4b63707ce
commit 797369449b87cbd578f9fb96f34b065e548755f6
commit 9fb399aee99ad98996f872477c133f08795ec54c

As some commits depend on each other, order of applying is important.

> Matthieu, you wrote that there were number of regressions on some older
> hardware. Is it easy to reproduce the problem? Do you have access to the
> affected hardware or do you know who has it and is willing to test it?
> I'm asking as I'm not sure is backporting multiple commits going to
> scale and what new issues may come up and what else needs to be
> addressed if there will be new problems.
> 
> Anyway, I personally would prefer to focus efforts on updating the
> driver to latest commit (as of today it is
> 6afed33b2d673d88674f0c76efe500ae414e8e1b)
> 
> Let me know, what do you think.
> 
> > The state of the xf86-video-intel driver is sad. But everyone is
> > moving away from it to the modesettings driver. Hopefully the current
> > work on upgrading the kernel-side DRM code and the upcoming upgrade to
> > xserver 1,20.x will also improve the modesetting driver on OpenBSD, so
> > that less people will need to run the intel driver.
> 
> I see. What time frame are you talking about here, when you say
> "upcoming upgrade to xserver 1,20.x"?


Index: src/sna/kgem.h
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-intel/src/sna/kgem.h,v
retrieving revision 1.4
diff -u -p -u -r1.4 kgem.h
--- src/sna/kgem.h      12 Apr 2015 19:42:06 -0000      1.4
+++ src/sna/kgem.h      7 Mar 2019 12:37:43 -0000
@@ -428,6 +428,13 @@ static inline void _kgem_set_mode(struct
        kgem->mode = mode;
 }
 
+static inline int kgem_batch_space(struct kgem *kgem)
+{
+       int rem = kgem->surface - kgem->nbatch;
+       assert(rem > 0);
+       return rem - KGEM_BATCH_RESERVED;
+}
+
 static inline bool kgem_check_batch(struct kgem *kgem, int num_dwords)
 {
        assert(num_dwords > 0);
Index: src/sna/sna_accel.c
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-intel/src/sna/sna_accel.c,v
retrieving revision 1.8
diff -u -p -u -r1.8 sna_accel.c
--- src/sna/sna_accel.c 19 Nov 2017 20:16:12 -0000      1.8
+++ src/sna/sna_accel.c 7 Mar 2019 12:37:46 -0000
@@ -117,6 +117,10 @@
 #define FontSetPrivate(font, idx, data) xfont2_font_set_private(font, idx, 
data)
 #endif
 
+#define IS_CLIPPED     0x2
+#define RECTILINEAR    0x4
+#define OVERWRITES     0x8
+
 #if 0
 static void __sna_fallback_flush(DrawablePtr d)
 {
@@ -600,6 +604,7 @@ static bool sna_pixmap_free_cpu(struct s
        if (priv->ptr == NULL)
                return true;
 
+       DBG(("%s(pixmap=%ld)\n", __FUNCTION__, 
priv->pixmap->drawable.serialNumber));
        __sna_pixmap_free_cpu(sna, priv);
 
        priv->cpu_bo = NULL;
@@ -3459,12 +3464,15 @@ done:
                    priv->cpu_damage == NULL &&
                    (box_covers_pixmap(pixmap, &r.extents) ||
                     box_inplace(pixmap, &r.extents))) {
-                       DBG(("%s: large operation on undamaged, promoting to 
full GPU\n",
+                       DBG(("%s: large operation on undamaged, discarding CPU 
shadow\n",
                             __FUNCTION__));
                        assert(priv->gpu_bo);
                        assert(priv->gpu_bo->proxy == NULL);
-                       if (sna_pixmap_free_cpu(sna, priv, priv->cpu))
+                       if (sna_pixmap_free_cpu(sna, priv, priv->cpu)) {
+                               DBG(("%s: large operation on undamaged, 
promoting to full GPU\n",
+                                    __FUNCTION__));
                                sna_damage_all(&priv->gpu_damage, pixmap);
+                       }
                }
                if (DAMAGE_IS_ALL(priv->gpu_damage)) {
                        sna_pixmap_free_cpu(sna, priv, priv->cpu);
@@ -7990,7 +7998,7 @@ sna_fill_spans(DrawablePtr drawable, GCP
                        sna_fill_spans_blt(drawable,
                                           bo, damage,
                                           gc, color, n, pt, width, sorted,
-                                          &region.extents, flags & 2);
+                                          &region.extents, flags & IS_CLIPPED);
                } else {
                        /* Try converting these to a set of rectangles instead 
*/
                        xRectangle *rect;
@@ -8013,12 +8021,12 @@ sna_fill_spans(DrawablePtr drawable, GCP
                                i = sna_poly_fill_rect_tiled_blt(drawable,
                                                                 bo, damage,
                                                                 gc, n, rect,
-                                                                
&region.extents, flags & 2);
+                                                                
&region.extents, flags & IS_CLIPPED);
                        } else {
                                i = sna_poly_fill_rect_stippled_blt(drawable,
                                                                    bo, damage,
                                                                    gc, n, rect,
-                                                                   
&region.extents, flags & 2);
+                                                                   
&region.extents, flags & IS_CLIPPED);
                        }
                        free (rect);
 
@@ -8881,7 +8889,7 @@ sna_poly_point(DrawablePtr drawable, GCP
                if ((bo = sna_drawable_use_bo(drawable, PREFER_GPU,
                                              &region.extents, &damage)) &&
                    sna_poly_point_blt(drawable, bo, damage,
-                                      gc, mode, n, pt, flags & 2))
+                                      gc, mode, n, pt, flags & IS_CLIPPED))
                        return;
        }
 
@@ -9669,7 +9677,7 @@ sna_poly_line(DrawablePtr drawable, GCPt
             gc->lineStyle, gc->lineStyle == LineSolid,
             gc->lineWidth,
             gc->planemask, PM_IS_SOLID(drawable, gc->planemask),
-            data.flags & 4));
+            data.flags & RECTILINEAR));
 
        if (!PM_IS_SOLID(drawable, gc->planemask))
                goto fallback;
@@ -9697,7 +9705,7 @@ sna_poly_line(DrawablePtr drawable, GCPt
                DBG(("%s: trying solid fill [%08x]\n",
                     __FUNCTION__, (unsigned)color));
 
-               if (data.flags & 4) {
+               if (data.flags & RECTILINEAR) {
                        data.bo = sna_drawable_use_bo(drawable, PREFER_GPU,
                                                      &data.region.extents,
                                                      &data.damage);
@@ -9706,7 +9714,7 @@ sna_poly_line(DrawablePtr drawable, GCPt
                                              data.bo, data.damage,
                                              gc, color, mode, n, pt,
                                              &data.region.extents,
-                                             data.flags & 2))
+                                             data.flags & IS_CLIPPED))
                                return;
                } else { /* !rectilinear */
                        if ((data.bo = sna_drawable_use_bo(drawable,
@@ -9717,11 +9725,11 @@ sna_poly_line(DrawablePtr drawable, GCPt
                                                   data.bo, data.damage,
                                                   gc, mode, n, pt,
                                                   &data.region.extents,
-                                                  data.flags & 2))
+                                                  data.flags & IS_CLIPPED))
                                return;
 
                }
-       } else if (data.flags & 4) {
+       } else if (data.flags & RECTILINEAR) {
                /* Try converting these to a set of rectangles instead */
                data.bo = sna_drawable_use_bo(drawable, PREFER_GPU,
                                              &data.region.extents, 
&data.damage);
@@ -9779,13 +9787,13 @@ sna_poly_line(DrawablePtr drawable, GCPt
                                                                 data.bo, 
data.damage,
                                                                 gc, n - 1, 
rect + 1,
                                                                 
&data.region.extents,
-                                                                data.flags & 
2);
+                                                                data.flags & 
IS_CLIPPED);
                        } else {
                                i = sna_poly_fill_rect_stippled_blt(drawable,
                                                                    data.bo, 
data.damage,
                                                                    gc, n - 1, 
rect + 1,
                                                                    
&data.region.extents,
-                                                                   data.flags 
& 2);
+                                                                   data.flags 
& IS_CLIPPED);
                        }
                        free (rect);
 
@@ -9814,7 +9822,7 @@ spans_fallback:
 
                                data.op = &fill;
 
-                               if ((data.flags & 2) == 0) {
+                               if ((data.flags & IS_CLIPPED) == 0) {
                                        if (data.dx | data.dy)
                                                sna_gc_ops__tmp.FillSpans = 
sna_fill_spans__fill_offset;
                                        else
@@ -9842,7 +9850,7 @@ spans_fallback:
                        } else {
                                data.op = &fill;
 
-                               if ((data.flags & 2) == 0) {
+                               if ((data.flags & IS_CLIPPED) == 0) {
                                        if (data.dx | data.dy)
                                                sna_gc_ops__tmp.FillSpans = 
sna_fill_spans__dash_offset;
                                        else
@@ -9865,7 +9873,7 @@ spans_fallback:
 
                                DBG(("%s: miZeroLine (solid dash, clipped? %d 
(complex? %d)), fg pass [%08x]\n",
                                     __FUNCTION__,
-                                    !!(data.flags & 2), data.flags & 2 && 
!region_is_singular(&data.region),
+                                    !!(data.flags & IS_CLIPPED), data.flags & 
IS_CLIPPED && !region_is_singular(&data.region),
                                     gc->fgPixel));
 
                                if (!sna_fill_init_blt(&fill,
@@ -9881,7 +9889,7 @@ spans_fallback:
 
                                DBG(("%s: miZeroLine (solid dash, clipped? %d 
(complex? %d)), bg pass [%08x]\n",
                                     __FUNCTION__,
-                                    !!(data.flags & 2), data.flags & 2 && 
!region_is_singular(&data.region),
+                                    !!(data.flags & IS_CLIPPED), data.flags & 
IS_CLIPPED && !region_is_singular(&data.region),
                                     gc->bgPixel));
 
                                if (sna_fill_init_blt(&fill,
@@ -9951,7 +9959,7 @@ fallback:
                goto out;
        if (!sna_drawable_move_region_to_cpu(drawable, &data.region,
                                             drawable_gc_flags(drawable, gc,
-                                                              !(data.flags & 4 
&& n == 2))))
+                                                              !(data.flags & 
RECTILINEAR && n == 2))))
                goto out;
 
        if (sigtrap_get() == 0) {
@@ -10599,7 +10607,7 @@ sna_poly_segment(DrawablePtr drawable, G
             gc->lineStyle, gc->lineStyle == LineSolid,
             gc->lineWidth,
             gc->planemask, PM_IS_SOLID(drawable, gc->planemask),
-            data.flags & 4));
+            data.flags & RECTILINEAR));
        if (!PM_IS_SOLID(drawable, gc->planemask))
                goto fallback;
 
@@ -10609,7 +10617,7 @@ sna_poly_segment(DrawablePtr drawable, G
                DBG(("%s: trying blt solid fill [%08x, flags=%x] paths\n",
                     __FUNCTION__, (unsigned)color, data.flags));
 
-               if (data.flags & 4) {
+               if (data.flags & RECTILINEAR) {
                        if ((data.bo = sna_drawable_use_bo(drawable, PREFER_GPU,
                                                           &data.region.extents,
                                                           &data.damage)) &&
@@ -10617,7 +10625,7 @@ sna_poly_segment(DrawablePtr drawable, G
                                                 data.bo, data.damage,
                                                 gc, color, n, seg,
                                                 &data.region.extents,
-                                                data.flags & 2))
+                                                data.flags & IS_CLIPPED))
                                return;
                } else {
                        if ((data.bo = sna_drawable_use_bo(drawable,
@@ -10628,10 +10636,10 @@ sna_poly_segment(DrawablePtr drawable, G
                                                      data.bo, data.damage,
                                                      gc, n, seg,
                                                      &data.region.extents,
-                                                     data.flags & 2))
+                                                     data.flags & IS_CLIPPED))
                                return;
                }
-       } else if (data.flags & 4) {
+       } else if (data.flags & RECTILINEAR) {
                /* Try converting these to a set of rectangles instead */
                xRectangle *rect;
                int i;
@@ -10684,13 +10692,13 @@ sna_poly_segment(DrawablePtr drawable, G
                                                         data.bo, data.damage,
                                                         gc, n, rect,
                                                         &data.region.extents,
-                                                        data.flags & 2);
+                                                        data.flags);
                } else {
                        i = sna_poly_fill_rect_stippled_blt(drawable,
                                                            data.bo, 
data.damage,
                                                            gc, n, rect,
                                                            
&data.region.extents,
-                                                           data.flags & 2);
+                                                           data.flags);
                }
                free (rect);
 
@@ -10741,7 +10749,7 @@ spans_fallback:
 
                        data.op = &fill;
 
-                       if ((data.flags & 2) == 0) {
+                       if ((data.flags & IS_CLIPPED) == 0) {
                                if (data.dx | data.dy)
                                        sna_gc_ops__tmp.FillSpans = 
sna_fill_spans__fill_offset;
                                else
@@ -10799,7 +10807,7 @@ fallback:
                goto out;
        if (!sna_drawable_move_region_to_cpu(drawable, &data.region,
                                             drawable_gc_flags(drawable, gc,
-                                                              !(data.flags & 4 
&& n == 1))))
+                                                              !(data.flags & 
RECTILINEAR && n == 1))))
                goto out;
 
        if (sigtrap_get() == 0) {
@@ -11382,7 +11390,7 @@ sna_poly_rectangle(DrawablePtr drawable,
        if (!PM_IS_SOLID(drawable, gc->planemask))
                goto fallback;
 
-       if (flags & 4 && gc->fillStyle == FillSolid && gc->lineStyle == 
LineSolid && gc->joinStyle == JoinMiter) {
+       if (flags & RECTILINEAR && gc->fillStyle == FillSolid && gc->lineStyle 
== LineSolid && gc->joinStyle == JoinMiter) {
                DBG(("%s: trying blt solid fill [%08lx] paths\n",
                     __FUNCTION__, gc->fgPixel));
                if ((bo = sna_drawable_use_bo(drawable, PREFER_GPU,
@@ -11545,7 +11553,7 @@ sna_poly_arc(DrawablePtr drawable, GCPtr
                                                       FILL_POINTS | 
FILL_SPANS))
                                        goto fallback;
 
-                               if ((data.flags & 2) == 0) {
+                               if ((data.flags & IS_CLIPPED) == 0) {
                                        if (data.dx | data.dy)
                                                sna_gc_ops__tmp.FillSpans = 
sna_fill_spans__fill_offset;
                                        else
@@ -11638,7 +11646,7 @@ sna_poly_fill_rect_blt(DrawablePtr drawa
                       GCPtr gc, uint32_t pixel,
                       int n, const xRectangle *rect,
                       const BoxRec *extents,
-                      bool clipped)
+                      unsigned flags)
 {
        PixmapPtr pixmap = get_drawable_pixmap(drawable);
        struct sna *sna = to_sna_from_pixmap(pixmap);
@@ -11650,7 +11658,7 @@ sna_poly_fill_rect_blt(DrawablePtr drawa
             __FUNCTION__, pixmap->drawable.serialNumber, n,
             rect->x, rect->y, rect->width, rect->height,
             drawable->x, drawable->y,
-            clipped));
+            flags&2));
 
        if (n == 1 && region_is_singular(gc->pCompositeClip)) {
                BoxRec r;
@@ -11665,38 +11673,37 @@ sna_poly_fill_rect_blt(DrawablePtr drawa
                                r.x1 += dx; r.y1 += dy;
                                r.x2 += dx; r.y2 += dy;
                        }
-                       DBG(("%s: using fill_one() fast path: (%d, %d), (%d, 
%d). alu=%d, pixel=%08x\n",
-                            __FUNCTION__, r.x1, r.y1, r.x2, r.y2, gc->alu, 
pixel));
+                       DBG(("%s: using fill_one() fast path: (%d, %d), (%d, 
%d). alu=%d, pixel=%08x, damage?=%d\n",
+                            __FUNCTION__, r.x1, r.y1, r.x2, r.y2, gc->alu, 
pixel, damage != NULL));
 
+                       assert_pixmap_contains_box(pixmap, &r);
                        if (sna->render.fill_one(sna, pixmap, bo, pixel,
                                                 r.x1, r.y1, r.x2, r.y2,
                                                 gc->alu)) {
-                               if (damage) {
-                                       assert_pixmap_contains_box(pixmap, &r);
-                                       if (r.x2 - r.x1 == 
pixmap->drawable.width &&
-                                           r.y2 - r.y1 == 
pixmap->drawable.height)
-                                               sna_damage_all(damage, pixmap);
-                                       else
-                                               sna_damage_add_box(damage, &r);
-                               }
-                               assert_pixmap_damage(pixmap);
-
-                               if (alu_overwrites(gc->alu) &&
-                                   r.x2 - r.x1 == pixmap->drawable.width &&
+                               if (r.x2 - r.x1 == pixmap->drawable.width &&
                                    r.y2 - r.y1 == pixmap->drawable.height) {
-                                       struct sna_pixmap *priv = 
sna_pixmap(pixmap);
-                                       if (bo == priv->gpu_bo) {
-                                               assert(priv->gpu_bo->proxy == 
NULL);
-                                               
sna_damage_all(&priv->gpu_damage, pixmap);
-                                               
sna_damage_destroy(&priv->cpu_damage);
-                                               list_del(&priv->flush_list);
-                                               priv->clear = true;
-                                               priv->clear_color = gc->alu == 
GXcopyInverted ? ~pixel & ((1 << gc->depth) - 1) : pixel;
+                                       if (damage) {
+                                               sna_damage_all(damage, pixmap);
+                                               damage = NULL;
+                                       }
+                                       if (flags & OVERWRITES) {
+                                               struct sna_pixmap *priv = 
sna_pixmap(pixmap);
+                                               if (bo == priv->gpu_bo) {
+                                                       assert(damage == NULL 
|| damage == &priv->gpu_damage);
+                                                       
assert(priv->gpu_bo->proxy == NULL);
+                                                       
sna_damage_destroy(&priv->cpu_damage);
+                                                       
list_del(&priv->flush_list);
+                                                       priv->clear = true;
+                                                       priv->clear_color = 
gc->alu == GXcopyInverted ? ~pixel & ((1 << gc->depth) - 1) : pixel;
 
-                                               DBG(("%s: pixmap=%ld, marking 
clear [%08x]\n",
-                                                    __FUNCTION__, 
pixmap->drawable.serialNumber, priv->clear_color));
+                                                       DBG(("%s: pixmap=%ld, 
marking clear [%08x]\n",
+                                                            __FUNCTION__, 
pixmap->drawable.serialNumber, priv->clear_color));
+                                               }
                                        }
                                }
+                               if (damage)
+                                       sna_damage_add_box(damage, &r);
+                               assert_pixmap_damage(pixmap);
                        } else
                                success = false;
                }
@@ -11710,7 +11717,7 @@ sna_poly_fill_rect_blt(DrawablePtr drawa
        }
 
        get_drawable_deltas(drawable, pixmap, &dx, &dy);
-       if (!clipped) {
+       if ((flags & IS_CLIPPED) == 0) {
                dx += drawable->x;
                dy += drawable->y;
 
@@ -11918,7 +11925,7 @@ sna_poly_fill_polygon(DrawablePtr draw, 
 
                        data.op = &fill;
 
-                       if ((data.flags & 2) == 0) {
+                       if ((data.flags & IS_CLIPPED) == 0) {
                                if (data.dx | data.dy)
                                        sna_gc_ops__tmp.FillSpans = 
sna_fill_spans__fill_offset;
                                else
@@ -12174,7 +12181,7 @@ sna_poly_fill_rect_tiled_8x8_blt(Drawabl
                                sna->kgem.nbatch += 6;
                        }
                } else do {
-                       int n_this_time;
+                       int n_this_time, rem;
 
                        assert(sna->kgem.mode == KGEM_BLT);
                        b = sna->kgem.batch + sna->kgem.nbatch;
@@ -12217,8 +12224,9 @@ sna_poly_fill_rect_tiled_8x8_blt(Drawabl
                        }
 
                        n_this_time = n;
-                       if (3*n_this_time > sna->kgem.surface - 
sna->kgem.nbatch - KGEM_BATCH_RESERVED)
-                               n_this_time = (sna->kgem.surface - 
sna->kgem.nbatch - KGEM_BATCH_RESERVED) / 3;
+                       rem = kgem_batch_space(&sna->kgem);
+                       if (3*n_this_time > rem)
+                               n_this_time = rem / 3;
                        assert(n_this_time);
                        n -= n_this_time;
 
@@ -13079,7 +13087,7 @@ sna_poly_fill_rect_stippled_8x8_blt(Draw
                                sna->kgem.nbatch += 9;
                        }
                } else do {
-                       int n_this_time;
+                       int n_this_time, rem;
 
                        assert(sna->kgem.mode == KGEM_BLT);
                        b = sna->kgem.batch + sna->kgem.nbatch;
@@ -13117,8 +13125,9 @@ sna_poly_fill_rect_stippled_8x8_blt(Draw
                        }
 
                        n_this_time = n;
-                       if (3*n_this_time > sna->kgem.surface - 
sna->kgem.nbatch - KGEM_BATCH_RESERVED)
-                               n_this_time = (sna->kgem.surface - 
sna->kgem.nbatch - KGEM_BATCH_RESERVED) / 3;
+                       rem = kgem_batch_space(&sna->kgem);
+                       if (3*n_this_time > rem)
+                               n_this_time = rem / 3;
                        assert(n_this_time);
                        n -= n_this_time;
 
@@ -14756,11 +14765,14 @@ sna_poly_fill_rect(DrawablePtr draw, GCP
                goto fallback;
        }
 
+       if (alu_overwrites(gc->alu))
+               flags |= OVERWRITES;
+
        /* Clear the cpu damage so that we refresh the GPU status of the
         * pixmap upon a redraw after a period of inactivity.
         */
        hint = PREFER_GPU;
-       if (n == 1 && gc->fillStyle != FillStippled && alu_overwrites(gc->alu)) 
{
+       if (n == 1 && gc->fillStyle != FillStippled && flags & OVERWRITES) {
                int16_t dx, dy;
 
                region.data = NULL;
@@ -14770,7 +14782,7 @@ sna_poly_fill_rect(DrawablePtr draw, GCP
                        RegionTranslate(&region, dx, dy);
                }
 
-               if ((flags & 2) == 0) {
+               if ((flags & IS_CLIPPED) == 0) {
                        hint |= IGNORE_DAMAGE;
                        if (region_subsumes_drawable(&region, 
&pixmap->drawable)) {
                                discard_cpu_damage(sna, priv);
@@ -14821,21 +14833,21 @@ sna_poly_fill_rect(DrawablePtr draw, GCP
                if (sna_poly_fill_rect_blt(draw,
                                           bo, damage,
                                           gc, color, n, rect,
-                                          &region.extents, flags & 2))
+                                          &region.extents, flags))
                        return;
        } else if (gc->fillStyle == FillTiled) {
                DBG(("%s: tiled fill, testing for blt\n", __FUNCTION__));
 
                if (sna_poly_fill_rect_tiled_blt(draw, bo, damage,
                                                 gc, n, rect,
-                                                &region.extents, flags & 2))
+                                                &region.extents, flags))
                        return;
        } else {
                DBG(("%s: stippled fill, testing for blt\n", __FUNCTION__));
 
                if (sna_poly_fill_rect_stippled_blt(draw, bo, damage,
                                                    gc, n, rect,
-                                                   &region.extents, flags & 2))
+                                                   &region.extents, flags))
                        return;
        }
 
@@ -14889,19 +14901,22 @@ sna_poly_fill_rect__gpu(DrawablePtr draw
 
        if (gc_is_solid(gc, &color)) {
                (void)sna_poly_fill_rect_blt(draw,
-                                            data->bo, data->damage,
+                                            data->bo, NULL,
                                             gc, color, n, r,
-                                            &data->region.extents, true);
+                                            &data->region.extents,
+                                            IS_CLIPPED);
        } else if (gc->fillStyle == FillTiled) {
                (void)sna_poly_fill_rect_tiled_blt(draw,
-                                                  data->bo, data->damage,
+                                                  data->bo, NULL,
                                                   gc, n, r,
-                                                  &data->region.extents, true);
+                                                  &data->region.extents,
+                                                  IS_CLIPPED);
        } else {
                (void)sna_poly_fill_rect_stippled_blt(draw,
-                                                   data->bo, data->damage,
+                                                   data->bo, NULL,
                                                    gc, n, r,
-                                                   &data->region.extents, 
true);
+                                                   &data->region.extents,
+                                                   IS_CLIPPED);
        }
 }
 
@@ -14971,7 +14986,7 @@ sna_poly_fill_arc(DrawablePtr draw, GCPt
 
                        data.op = &fill;
 
-                       if ((data.flags & 2) == 0) {
+                       if ((data.flags & IS_CLIPPED) == 0) {
                                if (data.dx | data.dy)
                                        sna_gc_ops__tmp.FillSpans = 
sna_fill_spans__fill_offset;
                                else
@@ -17048,7 +17063,7 @@ void sna_accel_flush(struct sna *sna)
                        assert(priv->flush);
                        if (sna_pixmap_move_to_gpu(priv->pixmap,
                                                   MOVE_READ | __MOVE_FORCE)) {
-                               if (priv->flush & 2) {
+                               if (priv->flush & IS_CLIPPED) {
                                        kgem_bo_unclean(&sna->kgem, 
priv->gpu_bo);
                                        sna_damage_all(&priv->gpu_damage, 
priv->pixmap);
                                        assert(priv->cpu_damage == NULL);
Index: src/sna/sna_blt.c
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-intel/src/sna/sna_blt.c,v
retrieving revision 1.3
diff -u -p -u -r1.3 sna_blt.c
--- src/sna/sna_blt.c   12 Apr 2015 19:42:06 -0000      1.3
+++ src/sna/sna_blt.c   7 Mar 2019 12:37:46 -0000
@@ -176,7 +176,8 @@ static bool sna_blt_fill_init(struct sna
        {
                uint32_t *b;
 
-               if (!kgem_check_reloc(kgem, 1)) {
+               if (!kgem_check_batch(kgem, 24) ||
+                   !kgem_check_reloc(kgem, 1)) {
                        _kgem_submit(kgem);
                        if (!kgem_check_bo_fenced(kgem, bo))
                                return false;
@@ -232,6 +233,7 @@ static bool sna_blt_fill_init(struct sna
                sna->blt_state.fill_alu = alu;
        }
 
+       assert(sna->kgem.mode == KGEM_BLT);
        return true;
 }
 
@@ -1102,13 +1104,16 @@ inline static void _sna_blt_fill_boxes(s
 
        do {
                uint32_t *b = kgem->batch + kgem->nbatch;
-               int nbox_this_time;
+               int nbox_this_time, rem;
 
                assert(sna->kgem.mode == KGEM_BLT);
                nbox_this_time = nbox;
-               if (3*nbox_this_time > kgem->surface - kgem->nbatch - 
KGEM_BATCH_RESERVED)
-                       nbox_this_time = (kgem->surface - kgem->nbatch - 
KGEM_BATCH_RESERVED) / 3;
-               assert(nbox_this_time);
+               rem = kgem_batch_space(kgem);
+               if (3*nbox_this_time > rem)
+                       nbox_this_time = rem / 3;
+               DBG(("%s: emitting %d boxes out of %d (batch space %d)\n",
+                    __FUNCTION__, nbox_this_time, nbox, rem));
+               assert(nbox_this_time > 0);
                nbox -= nbox_this_time;
 
                kgem->nbatch += 3 * nbox_this_time;
@@ -1198,13 +1203,16 @@ static void blt_composite_fill_boxes_no_
 
        do {
                uint32_t *b = kgem->batch + kgem->nbatch;
-               int nbox_this_time;
+               int nbox_this_time, rem;
 
                assert(sna->kgem.mode == KGEM_BLT);
                nbox_this_time = nbox;
-               if (3*nbox_this_time > kgem->surface - kgem->nbatch - 
KGEM_BATCH_RESERVED)
-                       nbox_this_time = (kgem->surface - kgem->nbatch - 
KGEM_BATCH_RESERVED) / 3;
-               assert(nbox_this_time);
+               rem = kgem_batch_space(kgem);
+               if (3*nbox_this_time > rem)
+                       nbox_this_time = rem / 3;
+               DBG(("%s: emitting %d boxes out of %d (batch space %d)\n",
+                    __FUNCTION__, nbox_this_time, nbox, rem));
+               assert(nbox_this_time > 0);
                nbox -= nbox_this_time;
 
                kgem->nbatch += 3 * nbox_this_time;
@@ -1310,13 +1318,16 @@ static void blt_composite_fill_boxes__th
 
        do {
                uint32_t *b = kgem->batch + kgem->nbatch;
-               int nbox_this_time;
+               int nbox_this_time, rem;
 
                assert(sna->kgem.mode == KGEM_BLT);
                nbox_this_time = nbox;
-               if (3*nbox_this_time > kgem->surface - kgem->nbatch - 
KGEM_BATCH_RESERVED)
-                       nbox_this_time = (kgem->surface - kgem->nbatch - 
KGEM_BATCH_RESERVED) / 3;
-               assert(nbox_this_time);
+               rem = kgem_batch_space(kgem);
+               if (3*nbox_this_time > rem)
+                       nbox_this_time = rem / 3;
+               DBG(("%s: emitting %d boxes out of %d (batch space %d)\n",
+                    __FUNCTION__, nbox_this_time, nbox, rem));
+               assert(nbox_this_time > 0);
                nbox -= nbox_this_time;
 
                kgem->nbatch += 3 * nbox_this_time;
@@ -1386,6 +1397,7 @@ static bool
 begin_blt(struct sna *sna,
          struct sna_composite_op *op)
 {
+       assert(sna->kgem.mode == KGEM_BLT);
        if (!kgem_check_bo_fenced(&sna->kgem, op->dst.bo)) {
                kgem_submit(&sna->kgem);
                if (!kgem_check_bo_fenced(&sna->kgem, op->dst.bo))
@@ -1603,14 +1615,17 @@ static void blt_composite_copy_boxes__th
        if ((dst_dx | dst_dy) == 0) {
                uint64_t hdr = (uint64_t)br13 << 32 | cmd;
                do {
-                       int nbox_this_time;
+                       int nbox_this_time, rem;
 
                        nbox_this_time = nbox;
-                       if (8*nbox_this_time > kgem->surface - kgem->nbatch - 
KGEM_BATCH_RESERVED)
-                               nbox_this_time = (kgem->surface - kgem->nbatch 
- KGEM_BATCH_RESERVED) / 8;
+                       rem = kgem_batch_space(kgem);
+                       if (8*nbox_this_time > rem)
+                               nbox_this_time = rem / 8;
                        if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - 
kgem->nreloc)
                                nbox_this_time = (KGEM_RELOC_SIZE(kgem) - 
kgem->nreloc)/2;
-                       assert(nbox_this_time);
+                       DBG(("%s: emitting %d boxes out of %d (batch space 
%d)\n",
+                            __FUNCTION__, nbox_this_time, nbox, rem));
+                       assert(nbox_this_time > 0);
                        nbox -= nbox_this_time;
 
                        assert(sna->kgem.mode == KGEM_BLT);
@@ -1656,14 +1671,17 @@ static void blt_composite_copy_boxes__th
                } while (1);
        } else {
                do {
-                       int nbox_this_time;
+                       int nbox_this_time, rem;
 
                        nbox_this_time = nbox;
-                       if (8*nbox_this_time > kgem->surface - kgem->nbatch - 
KGEM_BATCH_RESERVED)
-                               nbox_this_time = (kgem->surface - kgem->nbatch 
- KGEM_BATCH_RESERVED) / 8;
+                       rem = kgem_batch_space(kgem);
+                       if (8*nbox_this_time > rem)
+                               nbox_this_time = rem / 8;
                        if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - 
kgem->nreloc)
                                nbox_this_time = (KGEM_RELOC_SIZE(kgem) - 
kgem->nreloc)/2;
-                       assert(nbox_this_time);
+                       DBG(("%s: emitting %d boxes out of %d (batch space 
%d)\n",
+                            __FUNCTION__, nbox_this_time, nbox, rem));
+                       assert(nbox_this_time > 0);
                        nbox -= nbox_this_time;
 
                        assert(sna->kgem.mode == KGEM_BLT);
@@ -1733,14 +1751,17 @@ static void blt_composite_copy_boxes__th
        if ((dst_dx | dst_dy) == 0) {
                uint64_t hdr = (uint64_t)br13 << 32 | cmd;
                do {
-                       int nbox_this_time;
+                       int nbox_this_time, rem;
 
                        nbox_this_time = nbox;
-                       if (10*nbox_this_time > kgem->surface - kgem->nbatch - 
KGEM_BATCH_RESERVED)
-                               nbox_this_time = (kgem->surface - kgem->nbatch 
- KGEM_BATCH_RESERVED) / 10;
+                       rem = kgem_batch_space(kgem);
+                       if (10*nbox_this_time > rem)
+                               nbox_this_time = rem / 10;
                        if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - 
kgem->nreloc)
                                nbox_this_time = (KGEM_RELOC_SIZE(kgem) - 
kgem->nreloc)/2;
-                       assert(nbox_this_time);
+                       DBG(("%s: emitting %d boxes out of %d (batch space 
%d)\n",
+                            __FUNCTION__, nbox_this_time, nbox, rem));
+                       assert(nbox_this_time > 0);
                        nbox -= nbox_this_time;
 
                        assert(kgem->mode == KGEM_BLT);
@@ -1788,14 +1809,17 @@ static void blt_composite_copy_boxes__th
                } while (1);
        } else {
                do {
-                       int nbox_this_time;
+                       int nbox_this_time, rem;
 
                        nbox_this_time = nbox;
-                       if (10*nbox_this_time > kgem->surface - kgem->nbatch - 
KGEM_BATCH_RESERVED)
-                               nbox_this_time = (kgem->surface - kgem->nbatch 
- KGEM_BATCH_RESERVED) / 10;
+                       rem = kgem_batch_space(kgem);
+                       if (10*nbox_this_time > rem)
+                               nbox_this_time = rem / 10;
                        if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - 
kgem->nreloc)
                                nbox_this_time = (KGEM_RELOC_SIZE(kgem) - 
kgem->nreloc)/2;
-                       assert(nbox_this_time);
+                       DBG(("%s: emitting %d boxes out of %d (batch space 
%d)\n",
+                            __FUNCTION__, nbox_this_time, nbox, rem));
+                       assert(nbox_this_time > 0);
                        nbox -= nbox_this_time;
 
                        assert(kgem->mode == KGEM_BLT);
@@ -3124,12 +3148,13 @@ fastcall static void sna_blt_fill_op_poi
 
        do {
                uint32_t *b = kgem->batch + kgem->nbatch;
-               int n_this_time;
+               int n_this_time, rem;
 
                assert(sna->kgem.mode == KGEM_BLT);
                n_this_time = n;
-               if (2*n_this_time > kgem->surface - kgem->nbatch - 
KGEM_BATCH_RESERVED)
-                       n_this_time = (kgem->surface - kgem->nbatch - 
KGEM_BATCH_RESERVED) / 2;
+               rem = kgem_batch_space(kgem);
+               if (2*n_this_time > rem)
+                       n_this_time = rem / 2;
                assert(n_this_time);
                n -= n_this_time;
 
@@ -3226,6 +3251,7 @@ bool sna_blt_fill(struct sna *sna, uint8
                               bo, bpp, alu, pixel))
                return false;
 
+       assert(sna->kgem.mode == KGEM_BLT);
        fill->blt   = sna_blt_fill_op_blt;
        fill->box   = sna_blt_fill_op_box;
        fill->boxes = sna_blt_fill_op_boxes;
@@ -3486,7 +3512,8 @@ bool sna_blt_fill_boxes(struct sna *sna,
        {
                uint32_t *b;
 
-               if (!kgem_check_reloc(kgem, 1)) {
+               if (!kgem_check_batch(kgem, 24) ||
+                   !kgem_check_reloc(kgem, 1)) {
                        _kgem_submit(kgem);
                        if (!kgem_check_bo_fenced(&sna->kgem, bo))
                                return false;
@@ -3543,12 +3570,15 @@ bool sna_blt_fill_boxes(struct sna *sna,
        }
 
        do {
-               int nbox_this_time;
+               int nbox_this_time, rem;
 
                nbox_this_time = nbox;
-               if (3*nbox_this_time > kgem->surface - kgem->nbatch - 
KGEM_BATCH_RESERVED)
-                       nbox_this_time = (kgem->surface - kgem->nbatch - 
KGEM_BATCH_RESERVED) / 3;
-               assert(nbox_this_time);
+               rem = kgem_batch_space(kgem);
+               if (3*nbox_this_time > rem)
+                       nbox_this_time = rem / 3;
+               DBG(("%s: emitting %d boxes out of %d (batch space %d)\n",
+                    __FUNCTION__, nbox_this_time, nbox, rem));
+               assert(nbox_this_time > 0);
                nbox -= nbox_this_time;
 
                assert(sna->kgem.mode == KGEM_BLT);
@@ -3622,6 +3652,7 @@ bool sna_blt_fill_boxes(struct sna *sna,
                                kgem->nbatch += 9;
                        }
                        assert(kgem->nbatch < kgem->surface);
+                       assert(kgem_check_batch(kgem, 3));
                }
        } while (nbox);
 
@@ -3728,14 +3759,17 @@ bool sna_blt_copy_boxes(struct sna *sna,
                if (kgem->gen >= 0100) {
                        uint64_t hdr = (uint64_t)br13 << 32 | cmd | 8;
                        do {
-                               int nbox_this_time;
+                               int nbox_this_time, rem;
 
                                nbox_this_time = nbox;
-                               if (10*nbox_this_time > kgem->surface - 
kgem->nbatch - KGEM_BATCH_RESERVED)
-                                       nbox_this_time = (kgem->surface - 
kgem->nbatch - KGEM_BATCH_RESERVED) / 8;
+                               rem = kgem_batch_space(kgem);
+                               if (10*nbox_this_time > rem)
+                                       nbox_this_time = rem / 10;
                                if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - 
kgem->nreloc)
                                        nbox_this_time = (KGEM_RELOC_SIZE(kgem) 
- kgem->nreloc)/2;
-                               assert(nbox_this_time);
+                               DBG(("%s: emitting %d boxes out of %d (batch 
space %d)\n",
+                                    __FUNCTION__, nbox_this_time, nbox, rem));
+                               assert(nbox_this_time > 0);
                                nbox -= nbox_this_time;
 
                                assert(sna->kgem.mode == KGEM_BLT);
@@ -3784,14 +3818,17 @@ bool sna_blt_copy_boxes(struct sna *sna,
                } else {
                        uint64_t hdr = (uint64_t)br13 << 32 | cmd | 6;
                        do {
-                               int nbox_this_time;
+                               int nbox_this_time, rem;
 
                                nbox_this_time = nbox;
-                               if (8*nbox_this_time > kgem->surface - 
kgem->nbatch - KGEM_BATCH_RESERVED)
-                                       nbox_this_time = (kgem->surface - 
kgem->nbatch - KGEM_BATCH_RESERVED) / 8;
+                               rem = kgem_batch_space(kgem);
+                               if (8*nbox_this_time > rem)
+                                       nbox_this_time = rem / 8;
                                if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - 
kgem->nreloc)
                                        nbox_this_time = (KGEM_RELOC_SIZE(kgem) 
- kgem->nreloc)/2;
-                               assert(nbox_this_time);
+                               DBG(("%s: emitting %d boxes out of %d (batch 
space %d)\n",
+                                    __FUNCTION__, nbox_this_time, nbox, rem));
+                               assert(nbox_this_time > 0);
                                nbox -= nbox_this_time;
 
                                assert(sna->kgem.mode == KGEM_BLT);
@@ -3840,14 +3877,17 @@ bool sna_blt_copy_boxes(struct sna *sna,
                if (kgem->gen >= 0100) {
                        cmd |= 8;
                        do {
-                               int nbox_this_time;
+                               int nbox_this_time, rem;
 
                                nbox_this_time = nbox;
-                               if (10*nbox_this_time > kgem->surface - 
kgem->nbatch - KGEM_BATCH_RESERVED)
-                                       nbox_this_time = (kgem->surface - 
kgem->nbatch - KGEM_BATCH_RESERVED) / 8;
+                               rem = kgem_batch_space(kgem);
+                               if (10*nbox_this_time > rem)
+                                       nbox_this_time = rem / 10;
                                if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - 
kgem->nreloc)
                                        nbox_this_time = (KGEM_RELOC_SIZE(kgem) 
- kgem->nreloc)/2;
-                               assert(nbox_this_time);
+                               DBG(("%s: emitting %d boxes out of %d (batch 
space %d)\n",
+                                    __FUNCTION__, nbox_this_time, nbox, rem));
+                               assert(nbox_this_time > 0);
                                nbox -= nbox_this_time;
 
                                assert(sna->kgem.mode == KGEM_BLT);
@@ -3896,14 +3936,17 @@ bool sna_blt_copy_boxes(struct sna *sna,
                } else {
                        cmd |= 6;
                        do {
-                               int nbox_this_time;
+                               int nbox_this_time, rem;
 
                                nbox_this_time = nbox;
-                               if (8*nbox_this_time > kgem->surface - 
kgem->nbatch - KGEM_BATCH_RESERVED)
-                                       nbox_this_time = (kgem->surface - 
kgem->nbatch - KGEM_BATCH_RESERVED) / 8;
+                               rem = kgem_batch_space(kgem);
+                               if (8*nbox_this_time > rem)
+                                       nbox_this_time = rem / 8;
                                if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - 
kgem->nreloc)
                                        nbox_this_time = (KGEM_RELOC_SIZE(kgem) 
- kgem->nreloc)/2;
-                               assert(nbox_this_time);
+                               DBG(("%s: emitting %d boxes out of %d (batch 
space %d)\n",
+                                    __FUNCTION__, nbox_this_time, nbox, rem));
+                               assert(nbox_this_time > 0);
                                nbox -= nbox_this_time;
 
                                assert(sna->kgem.mode == KGEM_BLT);
Index: src/sna/sna_io.c
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-intel/src/sna/sna_io.c,v
retrieving revision 1.3
diff -u -p -u -r1.3 sna_io.c
--- src/sna/sna_io.c    12 Apr 2015 19:42:06 -0000      1.3
+++ src/sna/sna_io.c    7 Mar 2019 12:37:47 -0000
@@ -484,11 +484,12 @@ fallback:
        if (sna->kgem.gen >= 0100) {
                cmd |= 8;
                do {
-                       int nbox_this_time;
+                       int nbox_this_time, rem;
 
                        nbox_this_time = tmp_nbox;
-                       if (10*nbox_this_time > kgem->surface - kgem->nbatch - 
KGEM_BATCH_RESERVED)
-                               nbox_this_time = (kgem->surface - kgem->nbatch 
- KGEM_BATCH_RESERVED) / 8;
+                       rem = kgem_batch_space(kgem);
+                       if (10*nbox_this_time > rem)
+                               nbox_this_time = rem / 8;
                        if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - 
kgem->nreloc)
                                nbox_this_time = (KGEM_RELOC_SIZE(kgem) - 
kgem->nreloc) / 2;
                        assert(nbox_this_time);
@@ -543,11 +544,11 @@ fallback:
        } else {
                cmd |= 6;
                do {
-                       int nbox_this_time;
+                       int nbox_this_time, rem;
 
                        nbox_this_time = tmp_nbox;
-                       if (8*nbox_this_time > kgem->surface - kgem->nbatch - 
KGEM_BATCH_RESERVED)
-                               nbox_this_time = (kgem->surface - kgem->nbatch 
- KGEM_BATCH_RESERVED) / 8;
+                       if (8*nbox_this_time > rem)
+                               nbox_this_time = rem / 8;
                        if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - 
kgem->nreloc)
                                nbox_this_time = (KGEM_RELOC_SIZE(kgem) - 
kgem->nreloc) / 2;
                        assert(nbox_this_time);
@@ -1029,11 +1030,12 @@ tile:
        if (kgem->gen >= 0100) {
                cmd |= 8;
                do {
-                       int nbox_this_time;
+                       int nbox_this_time, rem;
 
                        nbox_this_time = nbox;
-                       if (10*nbox_this_time > kgem->surface - kgem->nbatch - 
KGEM_BATCH_RESERVED)
-                               nbox_this_time = (kgem->surface - kgem->nbatch 
- KGEM_BATCH_RESERVED) / 8;
+                       rem = kgem_batch_space(kgem);
+                       if (10*nbox_this_time > rem)
+                               nbox_this_time = rem / 8;
                        if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - 
kgem->nreloc)
                                nbox_this_time = (KGEM_RELOC_SIZE(kgem) - 
kgem->nreloc) / 2;
                        assert(nbox_this_time);
@@ -1122,11 +1124,12 @@ tile:
        } else {
                cmd |= 6;
                do {
-                       int nbox_this_time;
+                       int nbox_this_time, rem;
 
                        nbox_this_time = nbox;
-                       if (8*nbox_this_time > kgem->surface - kgem->nbatch - 
KGEM_BATCH_RESERVED)
-                               nbox_this_time = (kgem->surface - kgem->nbatch 
- KGEM_BATCH_RESERVED) / 8;
+                       rem = kgem_batch_space(kgem);
+                       if (8*nbox_this_time > rem)
+                               nbox_this_time = rem / 8;
                        if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - 
kgem->nreloc)
                                nbox_this_time = (KGEM_RELOC_SIZE(kgem) - 
kgem->nreloc) / 2;
                        assert(nbox_this_time);
@@ -1530,11 +1533,12 @@ tile:
        if (sna->kgem.gen >= 0100) {
                cmd |= 8;
                do {
-                       int nbox_this_time;
+                       int nbox_this_time, rem;
 
                        nbox_this_time = nbox;
-                       if (10*nbox_this_time > kgem->surface - kgem->nbatch - 
KGEM_BATCH_RESERVED)
-                               nbox_this_time = (kgem->surface - kgem->nbatch 
- KGEM_BATCH_RESERVED) / 8;
+                       rem = kgem_batch_space(kgem);
+                       if (10*nbox_this_time > rem)
+                               nbox_this_time = rem / 8;
                        if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - 
kgem->nreloc)
                                nbox_this_time = (KGEM_RELOC_SIZE(kgem) - 
kgem->nreloc) / 2;
                        assert(nbox_this_time);
@@ -1627,11 +1631,12 @@ tile:
        } else {
                cmd |= 6;
                do {
-                       int nbox_this_time;
+                       int nbox_this_time, rem;
 
                        nbox_this_time = nbox;
-                       if (8*nbox_this_time > kgem->surface - kgem->nbatch - 
KGEM_BATCH_RESERVED)
-                               nbox_this_time = (kgem->surface - kgem->nbatch 
- KGEM_BATCH_RESERVED) / 8;
+                       rem = kgem_batch_space(kgem);
+                       if (8*nbox_this_time > rem)
+                               nbox_this_time = rem / 8;
                        if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - 
kgem->nreloc)
                                nbox_this_time = (KGEM_RELOC_SIZE(kgem) - 
kgem->nreloc) / 2;
                        assert(nbox_this_time);


-- 
Regards,
 Mikolaj

Reply via email to