diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-04-20 16:48:26 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-04-20 16:48:26 +0300 |
commit | 4bd016cf3125b8341d0c690e9e3ecace582f54d7 (patch) | |
tree | 7ab51f846c7608f17bcfa9363266753a377631c7 /src/ui | |
parent | 4f840655fcb69f151c73121d790344296f6b43e6 (diff) |
DocumentWidget: Pre-rendering finetuning
Ensure there is more buffered content available in the current scrolling direction, and also make sure that all buffers get pre-rendered after a short delay with the view being stationary.
Diffstat (limited to 'src/ui')
-rw-r--r-- | src/ui/documentwidget.c | 138 | ||||
-rw-r--r-- | src/ui/visbuf.c | 86 |
2 files changed, 146 insertions, 78 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 42018e19..2229b7f7 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -157,14 +157,14 @@ struct Impl_DrawBufs { | |||
157 | int flags; | 157 | int flags; |
158 | SDL_Texture * sideIconBuf; | 158 | SDL_Texture * sideIconBuf; |
159 | iTextBuf * timestampBuf; | 159 | iTextBuf * timestampBuf; |
160 | iRangei lastVis; | 160 | uint32_t lastRenderTime; |
161 | }; | 161 | }; |
162 | 162 | ||
163 | static void init_DrawBufs(iDrawBufs *d) { | 163 | static void init_DrawBufs(iDrawBufs *d) { |
164 | d->flags = 0; | 164 | d->flags = 0; |
165 | d->sideIconBuf = NULL; | 165 | d->sideIconBuf = NULL; |
166 | d->timestampBuf = NULL; | 166 | d->timestampBuf = NULL; |
167 | iZap(d->lastVis); | 167 | d->lastRenderTime = 0; |
168 | } | 168 | } |
169 | 169 | ||
170 | static void deinit_DrawBufs(iDrawBufs *d) { | 170 | static void deinit_DrawBufs(iDrawBufs *d) { |
@@ -794,14 +794,6 @@ static void updateVisible_DocumentWidget_(iDocumentWidget *d) { | |||
794 | !isSuccess_GmStatusCode(d->sourceStatus)); | 794 | !isSuccess_GmStatusCode(d->sourceStatus)); |
795 | const iRangei visRange = visibleRange_DocumentWidget_(d); | 795 | const iRangei visRange = visibleRange_DocumentWidget_(d); |
796 | const iRect bounds = bounds_Widget(as_Widget(d)); | 796 | const iRect bounds = bounds_Widget(as_Widget(d)); |
797 | if (!equal_Rangei(visRange, d->drawBufs->lastVis)) { | ||
798 | /* After scrolling/resizing stops, begin prendering the visbuf contents. | ||
799 | `Periodic` is used for detecting when the visible range has been modified. */ | ||
800 | removeTicker_App(prerender_DocumentWidget_, d); | ||
801 | remove_Periodic(periodic_App(), d); | ||
802 | add_Periodic(periodic_App(), d, | ||
803 | format_CStr("document.render from:%d to:%d", visRange.start, visRange.end)); | ||
804 | } | ||
805 | setRange_ScrollWidget(d->scroll, (iRangei){ 0, scrollMax_DocumentWidget_(d) }); | 797 | setRange_ScrollWidget(d->scroll, (iRangei){ 0, scrollMax_DocumentWidget_(d) }); |
806 | const int docSize = size_GmDocument(d->doc).y; | 798 | const int docSize = size_GmDocument(d->doc).y; |
807 | setThumb_ScrollWidget(d->scroll, | 799 | setThumb_ScrollWidget(d->scroll, |
@@ -829,6 +821,11 @@ static void updateVisible_DocumentWidget_(iDocumentWidget *d) { | |||
829 | recent->normScrollY = normScrollPos_DocumentWidget_(d); | 821 | recent->normScrollY = normScrollPos_DocumentWidget_(d); |
830 | } | 822 | } |
831 | } | 823 | } |
824 | /* After scrolling/resizing stops, begin pre-rendering the visbuf contents. */ { | ||
825 | removeTicker_App(prerender_DocumentWidget_, d); | ||
826 | remove_Periodic(periodic_App(), d); | ||
827 | add_Periodic(periodic_App(), d, "document.render"); | ||
828 | } | ||
832 | } | 829 | } |
833 | 830 | ||
834 | static void updateWindowTitle_DocumentWidget_(const iDocumentWidget *d) { | 831 | static void updateWindowTitle_DocumentWidget_(const iDocumentWidget *d) { |
@@ -1763,10 +1760,9 @@ static iBool handlePinch_DocumentWidget_(iDocumentWidget *d, const char *cmd) { | |||
1763 | 1760 | ||
1764 | static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) { | 1761 | static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) { |
1765 | iWidget *w = as_Widget(d); | 1762 | iWidget *w = as_Widget(d); |
1766 | if (equal_Command(cmd, "document.render")) { | 1763 | if (equal_Command(cmd, "document.render")) /* Periodic makes direct dispatch to here */ { |
1767 | const iRangei vis = { argLabel_Command(cmd, "from"), argLabel_Command(cmd, "to") }; | 1764 | // printf("%u: document.render\n", SDL_GetTicks()); |
1768 | const iRangei current = visibleRange_DocumentWidget_(d); | 1765 | if (SDL_GetTicks() - d->drawBufs->lastRenderTime > 150) { |
1769 | if (equal_Rangei(vis, current)) { | ||
1770 | remove_Periodic(periodic_App(), d); | 1766 | remove_Periodic(periodic_App(), d); |
1771 | /* Scrolling has stopped, begin filling up the buffer. */ | 1767 | /* Scrolling has stopped, begin filling up the buffer. */ |
1772 | if (d->visBuf->buffers[0].texture) { | 1768 | if (d->visBuf->buffers[0].texture) { |
@@ -1824,6 +1820,8 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
1824 | updateWindowTitle_DocumentWidget_(d); | 1820 | updateWindowTitle_DocumentWidget_(d); |
1825 | allocVisBuffer_DocumentWidget_(d); | 1821 | allocVisBuffer_DocumentWidget_(d); |
1826 | animateMedia_DocumentWidget_(d); | 1822 | animateMedia_DocumentWidget_(d); |
1823 | remove_Periodic(periodic_App(), d); | ||
1824 | removeTicker_App(prerender_DocumentWidget_, d); | ||
1827 | return iFalse; | 1825 | return iFalse; |
1828 | } | 1826 | } |
1829 | else if (equal_Command(cmd, "tab.created")) { | 1827 | else if (equal_Command(cmd, "tab.created")) { |
@@ -3704,6 +3702,13 @@ static void drawPin_(iPaint *p, iRect rangeRect, int dir) { | |||
3704 | init1_I2(gap_UI * 2)), pinColor); | 3702 | init1_I2(gap_UI * 2)), pinColor); |
3705 | } | 3703 | } |
3706 | 3704 | ||
3705 | static void extend_GmRunRange_(iGmRunRange *runs) { | ||
3706 | if (runs->start) { | ||
3707 | runs->start--; | ||
3708 | runs->end++; | ||
3709 | } | ||
3710 | } | ||
3711 | |||
3707 | static iBool render_DocumentWidget_(const iDocumentWidget *d, iDrawContext *ctx, iBool prerenderExtra) { | 3712 | static iBool render_DocumentWidget_(const iDocumentWidget *d, iDrawContext *ctx, iBool prerenderExtra) { |
3708 | iBool didDraw = iFalse; | 3713 | iBool didDraw = iFalse; |
3709 | const iRect bounds = bounds_Widget(constAs_Widget(d)); | 3714 | const iRect bounds = bounds_Widget(constAs_Widget(d)); |
@@ -3712,6 +3717,7 @@ static iBool render_DocumentWidget_(const iDocumentWidget *d, iDrawContext *ctx, | |||
3712 | const iRangei full = { 0, size_GmDocument(d->doc).y }; | 3717 | const iRangei full = { 0, size_GmDocument(d->doc).y }; |
3713 | const iRangei vis = ctx->vis; | 3718 | const iRangei vis = ctx->vis; |
3714 | iVisBuf *visBuf = d->visBuf; /* will be updated now */ | 3719 | iVisBuf *visBuf = d->visBuf; /* will be updated now */ |
3720 | d->drawBufs->lastRenderTime = SDL_GetTicks(); | ||
3715 | /* Swap buffers around to have room available both before and after the visible region. */ | 3721 | /* Swap buffers around to have room available both before and after the visible region. */ |
3716 | allocVisBuffer_DocumentWidget_(d); | 3722 | allocVisBuffer_DocumentWidget_(d); |
3717 | reposition_VisBuf(visBuf, vis); | 3723 | reposition_VisBuf(visBuf, vis); |
@@ -3721,11 +3727,11 @@ static iBool render_DocumentWidget_(const iDocumentWidget *d, iDrawContext *ctx, | |||
3721 | iForIndices(i, visBuf->buffers) { | 3727 | iForIndices(i, visBuf->buffers) { |
3722 | iVisBufTexture *buf = &visBuf->buffers[i]; | 3728 | iVisBufTexture *buf = &visBuf->buffers[i]; |
3723 | iVisBufMeta * meta = buf->user; | 3729 | iVisBufMeta * meta = buf->user; |
3724 | const iRangei bufRange = bufferRange_VisBuf(visBuf, i); | 3730 | const iRangei bufRange = intersect_Rangei(bufferRange_VisBuf(visBuf, i), full); |
3725 | const iRangei bufVisRange = intersect_Rangei(bufRange, vis); | 3731 | const iRangei bufVisRange = intersect_Rangei(bufRange, vis); |
3726 | ctx->widgetBounds = moved_Rect(ctxWidgetBounds, init_I2(0, -buf->origin)); | 3732 | ctx->widgetBounds = moved_Rect(ctxWidgetBounds, init_I2(0, -buf->origin)); |
3727 | ctx->viewPos = init_I2(left_Rect(ctx->docBounds) - left_Rect(bounds), -buf->origin); | 3733 | ctx->viewPos = init_I2(left_Rect(ctx->docBounds) - left_Rect(bounds), -buf->origin); |
3728 | //printf(" buffer %zu: invalid range %d...%d\n", i, invalidRange[i].start, invalidRange[i].end); | 3734 | // printf(" buffer %zu: buf vis range %d...%d\n", i, bufVisRange.start, bufVisRange.end); |
3729 | if (!prerenderExtra && !isEmpty_Range(&bufVisRange)) { | 3735 | if (!prerenderExtra && !isEmpty_Range(&bufVisRange)) { |
3730 | didDraw = iTrue; | 3736 | didDraw = iTrue; |
3731 | if (isEmpty_Rangei(buf->validRange)) { | 3737 | if (isEmpty_Rangei(buf->validRange)) { |
@@ -3737,10 +3743,7 @@ static iBool render_DocumentWidget_(const iDocumentWidget *d, iDrawContext *ctx, | |||
3737 | iZap(ctx->runsDrawn); | 3743 | iZap(ctx->runsDrawn); |
3738 | render_GmDocument(d->doc, bufVisRange, drawRun_DrawContext_, ctx); | 3744 | render_GmDocument(d->doc, bufVisRange, drawRun_DrawContext_, ctx); |
3739 | meta->runsDrawn = ctx->runsDrawn; | 3745 | meta->runsDrawn = ctx->runsDrawn; |
3740 | if (meta->runsDrawn.start) { | 3746 | extend_GmRunRange_(&meta->runsDrawn); |
3741 | meta->runsDrawn.start--; | ||
3742 | meta->runsDrawn.end++; | ||
3743 | } | ||
3744 | buf->validRange = bufVisRange; | 3747 | buf->validRange = bufVisRange; |
3745 | // printf(" buffer %zu valid %d...%d\n", i, bufRange.start, bufRange.end); | 3748 | // printf(" buffer %zu valid %d...%d\n", i, bufRange.start, bufRange.end); |
3746 | } | 3749 | } |
@@ -3750,19 +3753,19 @@ static iBool render_DocumentWidget_(const iDocumentWidget *d, iDrawContext *ctx, | |||
3750 | if (meta->runsDrawn.start) { | 3753 | if (meta->runsDrawn.start) { |
3751 | beginTarget_Paint(p, buf->texture); | 3754 | beginTarget_Paint(p, buf->texture); |
3752 | meta->runsDrawn.start = renderProgressive_GmDocument(d->doc, meta->runsDrawn.start, | 3755 | meta->runsDrawn.start = renderProgressive_GmDocument(d->doc, meta->runsDrawn.start, |
3753 | -1, iInvalidSize, | 3756 | -1, iInvalidSize, |
3754 | bufVisRange, | 3757 | bufVisRange, |
3755 | drawRun_DrawContext_, | 3758 | drawRun_DrawContext_, |
3756 | ctx); | 3759 | ctx); |
3757 | buf->validRange.start = bufVisRange.start; | 3760 | buf->validRange.start = bufVisRange.start; |
3758 | } | 3761 | } |
3759 | if (meta->runsDrawn.end) { | 3762 | if (meta->runsDrawn.end) { |
3760 | beginTarget_Paint(p, buf->texture); | 3763 | beginTarget_Paint(p, buf->texture); |
3761 | meta->runsDrawn.end = renderProgressive_GmDocument(d->doc, meta->runsDrawn.end, | 3764 | meta->runsDrawn.end = renderProgressive_GmDocument(d->doc, meta->runsDrawn.end, |
3762 | +1, iInvalidSize, | 3765 | +1, iInvalidSize, |
3763 | bufVisRange, | 3766 | bufVisRange, |
3764 | drawRun_DrawContext_, | 3767 | drawRun_DrawContext_, |
3765 | ctx); | 3768 | ctx); |
3766 | buf->validRange.end = bufVisRange.end; | 3769 | buf->validRange.end = bufVisRange.end; |
3767 | } | 3770 | } |
3768 | } | 3771 | } |
@@ -3770,38 +3773,62 @@ static iBool render_DocumentWidget_(const iDocumentWidget *d, iDrawContext *ctx, | |||
3770 | /* Progressively draw the rest of the buffer if it isn't fully valid. */ | 3773 | /* Progressively draw the rest of the buffer if it isn't fully valid. */ |
3771 | if (prerenderExtra && !equal_Rangei(bufRange, buf->validRange)) { | 3774 | if (prerenderExtra && !equal_Rangei(bufRange, buf->validRange)) { |
3772 | const iGmRun *next; | 3775 | const iGmRun *next; |
3773 | if (meta->runsDrawn.start) { | 3776 | // printf("%zu: prerenderExtra (start:%p end:%p)\n", i, meta->runsDrawn.start, meta->runsDrawn.end); |
3774 | const iRangei upper = intersect_Rangei(bufRange, (iRangei){ full.start, buf->validRange.start }); | 3777 | if (meta->runsDrawn.start == NULL) { |
3775 | if (upper.end > upper.start) { | 3778 | /* Haven't drawn anything yet in this buffer, so let's try seeding it. */ |
3776 | beginTarget_Paint(p, buf->texture); | 3779 | const int rh = lineHeight_Text(paragraph_FontId); |
3777 | next = renderProgressive_GmDocument(d->doc, meta->runsDrawn.start, | 3780 | const int y = i >= iElemCount(visBuf->buffers) / 2 ? bufRange.start : (bufRange.end - rh); |
3778 | -1, 1, upper, | 3781 | beginTarget_Paint(p, buf->texture); |
3779 | drawRun_DrawContext_, | 3782 | fillRect_Paint(p, (iRect){ zero_I2(), visBuf->texSize }, tmBackground_ColorId); |
3780 | ctx); | 3783 | buf->validRange = (iRangei){ y, y + rh }; |
3781 | if (meta->runsDrawn.start != next) { | 3784 | iZap(ctx->runsDrawn); |
3782 | meta->runsDrawn.start = next; | 3785 | render_GmDocument(d->doc, buf->validRange, drawRun_DrawContext_, ctx); |
3783 | didDraw = iTrue; | 3786 | meta->runsDrawn = ctx->runsDrawn; |
3787 | extend_GmRunRange_(&meta->runsDrawn); | ||
3788 | // printf("%zu: seeded, next %p:%p\n", i, meta->runsDrawn.start, meta->runsDrawn.end); | ||
3789 | didDraw = iTrue; | ||
3790 | } | ||
3791 | else { | ||
3792 | if (meta->runsDrawn.start) { | ||
3793 | const iRangei upper = intersect_Rangei(bufRange, (iRangei){ full.start, buf->validRange.start }); | ||
3794 | if (upper.end > upper.start) { | ||
3795 | beginTarget_Paint(p, buf->texture); | ||
3796 | next = renderProgressive_GmDocument(d->doc, meta->runsDrawn.start, | ||
3797 | -1, 1, upper, | ||
3798 | drawRun_DrawContext_, | ||
3799 | ctx); | ||
3800 | if (next && meta->runsDrawn.start != next) { | ||
3801 | meta->runsDrawn.start = next; | ||
3802 | buf->validRange.start = bottom_Rect(next->visBounds); | ||
3803 | didDraw = iTrue; | ||
3804 | } | ||
3805 | else { | ||
3806 | buf->validRange.start = bufRange.start; | ||
3807 | } | ||
3784 | } | 3808 | } |
3785 | buf->validRange.start = bufRange.start; | ||
3786 | } | 3809 | } |
3787 | } | 3810 | if (!didDraw && meta->runsDrawn.end) { |
3788 | if (meta->runsDrawn.end) { | 3811 | const iRangei lower = intersect_Rangei(bufRange, (iRangei){ buf->validRange.end, full.end }); |
3789 | const iRangei lower = intersect_Rangei(bufRange, (iRangei){ buf->validRange.end, full.end }); | 3812 | if (lower.end > lower.start) { |
3790 | if (lower.end > lower.start) { | 3813 | beginTarget_Paint(p, buf->texture); |
3791 | beginTarget_Paint(p, buf->texture); | 3814 | next = renderProgressive_GmDocument(d->doc, meta->runsDrawn.end, |
3792 | next = renderProgressive_GmDocument(d->doc, meta->runsDrawn.end, | 3815 | +1, 1, lower, |
3793 | +1, 1, lower, | 3816 | drawRun_DrawContext_, |
3794 | drawRun_DrawContext_, | 3817 | ctx); |
3795 | ctx); | 3818 | if (next && meta->runsDrawn.end != next) { |
3796 | if (meta->runsDrawn.end != next) { | 3819 | meta->runsDrawn.end = next; |
3797 | meta->runsDrawn.end = next; | 3820 | buf->validRange.end = top_Rect(next->visBounds); |
3798 | didDraw = iTrue; | 3821 | didDraw = iTrue; |
3822 | } | ||
3823 | else { | ||
3824 | buf->validRange.end = bufRange.end; | ||
3825 | } | ||
3799 | } | 3826 | } |
3800 | buf->validRange.end = bufRange.end; | ||
3801 | } | 3827 | } |
3802 | } | 3828 | } |
3803 | } | 3829 | } |
3804 | /* Draw any invalidated runs that fall within this buffer. */ { | 3830 | /* Draw any invalidated runs that fall within this buffer. */ |
3831 | if (!prerenderExtra) { | ||
3805 | const iRangei bufRange = { buf->origin, buf->origin + visBuf->texSize.y }; | 3832 | const iRangei bufRange = { buf->origin, buf->origin + visBuf->texSize.y }; |
3806 | /* Clear full-width backgrounds first in case there are any dynamic elements. */ { | 3833 | /* Clear full-width backgrounds first in case there are any dynamic elements. */ { |
3807 | iConstForEach(PtrSet, r, d->invalidRuns) { | 3834 | iConstForEach(PtrSet, r, d->invalidRuns) { |
@@ -3826,6 +3853,9 @@ static iBool render_DocumentWidget_(const iDocumentWidget *d, iDrawContext *ctx, | |||
3826 | } | 3853 | } |
3827 | } | 3854 | } |
3828 | endTarget_Paint(p); | 3855 | endTarget_Paint(p); |
3856 | if (prerenderExtra && didDraw) { | ||
3857 | return iTrue; | ||
3858 | } | ||
3829 | } | 3859 | } |
3830 | clear_PtrSet(d->invalidRuns); | 3860 | clear_PtrSet(d->invalidRuns); |
3831 | } | 3861 | } |
diff --git a/src/ui/visbuf.c b/src/ui/visbuf.c index e9bfee58..88a5fd60 100644 --- a/src/ui/visbuf.c +++ b/src/ui/visbuf.c | |||
@@ -38,7 +38,7 @@ void deinit_VisBuf(iVisBuf *d) { | |||
38 | } | 38 | } |
39 | 39 | ||
40 | void invalidate_VisBuf(iVisBuf *d) { | 40 | void invalidate_VisBuf(iVisBuf *d) { |
41 | int origin = d->vis.start - d->texSize.y; | 41 | int origin = iMax(0, d->vis.start - d->texSize.y); |
42 | iForIndices(i, d->buffers) { | 42 | iForIndices(i, d->buffers) { |
43 | d->buffers[i].origin = origin; | 43 | d->buffers[i].origin = origin; |
44 | origin += d->texSize.y; | 44 | origin += d->texSize.y; |
@@ -109,10 +109,41 @@ static size_t take_(size_t *avail, size_t *numAvail, size_t index) { | |||
109 | } | 109 | } |
110 | #endif | 110 | #endif |
111 | 111 | ||
112 | static void roll_VisBuf_(iVisBuf *d, int dir) { | ||
113 | const size_t lastPos = iElemCount(d->buffers) - 1; | ||
114 | if (dir < 0) { | ||
115 | /* Last buffer is moved to the beginning. */ | ||
116 | SDL_Texture *last = d->buffers[lastPos].texture; | ||
117 | void * user = d->buffers[lastPos].user; | ||
118 | memmove(d->buffers + 1, d->buffers, sizeof(iVisBufTexture) * lastPos); | ||
119 | d->buffers[0].texture = last; | ||
120 | d->buffers[0].user = user; | ||
121 | d->buffers[0].origin = d->buffers[1].origin - d->texSize.y; | ||
122 | iZap(d->buffers[0].validRange); | ||
123 | if (d->bufferInvalidated) { | ||
124 | d->bufferInvalidated(d, 0); | ||
125 | } | ||
126 | } | ||
127 | else { | ||
128 | /* First buffer is moved to the end. */ | ||
129 | SDL_Texture *first = d->buffers[0].texture; | ||
130 | void * user = d->buffers[0].user; | ||
131 | memmove(d->buffers, d->buffers + 1, sizeof(iVisBufTexture) * lastPos); | ||
132 | d->buffers[lastPos].texture = first; | ||
133 | d->buffers[lastPos].user = user; | ||
134 | d->buffers[lastPos].origin = d->buffers[lastPos - 1].origin + d->texSize.y; | ||
135 | iZap(d->buffers[lastPos].validRange); | ||
136 | if (d->bufferInvalidated) { | ||
137 | d->bufferInvalidated(d, lastPos); | ||
138 | } | ||
139 | } | ||
140 | } | ||
141 | |||
112 | iBool reposition_VisBuf(iVisBuf *d, const iRangei vis) { | 142 | iBool reposition_VisBuf(iVisBuf *d, const iRangei vis) { |
113 | if (equal_Rangei(vis, d->vis)) { | 143 | if (equal_Rangei(vis, d->vis)) { |
114 | return iFalse; | 144 | return iFalse; |
115 | } | 145 | } |
146 | const int moveDir = vis.end > d->vis.end ? +1 : -1; | ||
116 | d->vis = vis; | 147 | d->vis = vis; |
117 | iBool wasChanged = iFalse; | 148 | iBool wasChanged = iFalse; |
118 | const size_t lastPos = iElemCount(d->buffers) - 1; | 149 | const size_t lastPos = iElemCount(d->buffers) - 1; |
@@ -122,36 +153,26 @@ iBool reposition_VisBuf(iVisBuf *d, const iRangei vis) { | |||
122 | wasChanged = iTrue; | 153 | wasChanged = iTrue; |
123 | } | 154 | } |
124 | else { | 155 | else { |
125 | /* Roll up. */ | 156 | /* Check for mandatory rolls. */ |
126 | while (d->buffers[0].origin > vis.start) { | 157 | while (d->buffers[0].origin > vis.start) { |
127 | SDL_Texture *last = d->buffers[lastPos].texture; | 158 | roll_VisBuf_(d, -1); |
128 | void * user = d->buffers[lastPos].user; | ||
129 | memmove(d->buffers + 1, d->buffers, sizeof(iVisBufTexture) * lastPos); | ||
130 | d->buffers[0].texture = last; | ||
131 | d->buffers[0].user = user; | ||
132 | d->buffers[0].origin = d->buffers[1].origin - d->texSize.y; | ||
133 | iZap(d->buffers[0].validRange); | ||
134 | if (d->bufferInvalidated) { | ||
135 | d->bufferInvalidated(d, 0); | ||
136 | } | ||
137 | wasChanged = iTrue; | 159 | wasChanged = iTrue; |
138 | } | 160 | } |
139 | if (!wasChanged) { | 161 | if (!wasChanged) { |
140 | /* Roll down. */ | ||
141 | while (d->buffers[lastPos].origin + d->texSize.y < vis.end) { | 162 | while (d->buffers[lastPos].origin + d->texSize.y < vis.end) { |
142 | SDL_Texture *first = d->buffers[0].texture; | 163 | roll_VisBuf_(d, +1); |
143 | void * user = d->buffers[0].user; | ||
144 | memmove(d->buffers, d->buffers + 1, sizeof(iVisBufTexture) * lastPos); | ||
145 | d->buffers[lastPos].texture = first; | ||
146 | d->buffers[lastPos].user = user; | ||
147 | d->buffers[lastPos].origin = d->buffers[lastPos - 1].origin + d->texSize.y; | ||
148 | iZap(d->buffers[lastPos].validRange); | ||
149 | if (d->bufferInvalidated) { | ||
150 | d->bufferInvalidated(d, lastPos); | ||
151 | } | ||
152 | wasChanged = iTrue; | 164 | wasChanged = iTrue; |
153 | } | 165 | } |
154 | } | 166 | } |
167 | /* Scroll-direction dependent optional rolls, with a bit of overscroll allowed. */ | ||
168 | if (moveDir > 0 && d->buffers[0].origin + d->texSize.y + d->texSize.y / 4 < vis.start) { | ||
169 | roll_VisBuf_(d, +1); | ||
170 | wasChanged = iTrue; | ||
171 | } | ||
172 | else if (moveDir < 0 && d->buffers[lastPos].origin - d->texSize.y / 4 > vis.end) { | ||
173 | roll_VisBuf_(d, -1); | ||
174 | wasChanged = iTrue; | ||
175 | } | ||
155 | } | 176 | } |
156 | #if 0 | 177 | #if 0 |
157 | if (wasChanged) { | 178 | if (wasChanged) { |
@@ -228,7 +249,9 @@ void draw_VisBuf(const iVisBuf *d, const iInt2 topLeft, const iRangei yClipBound | |||
228 | d->texSize.x, | 249 | d->texSize.x, |
229 | d->texSize.y }; | 250 | d->texSize.y }; |
230 | if (dst.y >= yClipBounds.end || dst.y + dst.h < yClipBounds.start) { | 251 | if (dst.y >= yClipBounds.end || dst.y + dst.h < yClipBounds.start) { |
252 | #if !defined (DEBUG_SCALE) | ||
231 | continue; /* Outside the clipping area. */ | 253 | continue; /* Outside the clipping area. */ |
254 | #endif | ||
232 | } | 255 | } |
233 | #if defined (DEBUG_SCALE) | 256 | #if defined (DEBUG_SCALE) |
234 | dst.w *= DEBUG_SCALE; | 257 | dst.w *= DEBUG_SCALE; |
@@ -239,5 +262,20 @@ void draw_VisBuf(const iVisBuf *d, const iInt2 topLeft, const iRangei yClipBound | |||
239 | dst.y += get_Window()->root->rect.size.y / 4; | 262 | dst.y += get_Window()->root->rect.size.y / 4; |
240 | #endif | 263 | #endif |
241 | SDL_RenderCopy(render, buf->texture, NULL, &dst); | 264 | SDL_RenderCopy(render, buf->texture, NULL, &dst); |
242 | } | 265 | #if defined (DEBUG_SCALE) |
266 | SDL_SetRenderDrawColor(render, 0, 0, 255, 255); | ||
267 | SDL_RenderDrawRect(render, &dst); | ||
268 | #endif | ||
269 | } | ||
270 | #if defined (DEBUG_SCALE) | ||
271 | SDL_Rect dst = { topLeft.x, yClipBounds.start, d->texSize.x, 2 * d->texSize.y }; | ||
272 | dst.w *= DEBUG_SCALE; | ||
273 | dst.h *= DEBUG_SCALE; | ||
274 | dst.x *= DEBUG_SCALE; | ||
275 | dst.y *= DEBUG_SCALE; | ||
276 | dst.x += get_Window()->root->rect.size.x / 4; | ||
277 | dst.y += get_Window()->root->rect.size.y / 4; | ||
278 | SDL_SetRenderDrawColor(render, 255, 255, 255, 255); | ||
279 | SDL_RenderDrawRect(render, &dst); | ||
280 | #endif | ||
243 | } | 281 | } |