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/visbuf.c | |
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/visbuf.c')
-rw-r--r-- | src/ui/visbuf.c | 86 |
1 files changed, 62 insertions, 24 deletions
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 | } |