1// Warning: This file was created by make_scanline_drawers.py - do not edit.
2
3#if __GNUC__
4#define _AL_EXPECT_FAIL(expr) __builtin_expect((expr), 0)
5#else
6#define _AL_EXPECT_FAIL(expr) (expr)
7#endif
8
9static void shader_solid_any_draw_shade(uintptr_t state, int x1, int y, int x2)
10{
11   state_solid_any_2d *s = (state_solid_any_2d *) state;
12   ALLEGRO_COLOR cur_color = s->cur_color;
13
14   ALLEGRO_BITMAP *target = s->target;
15
16   if (target->parent) {
17      x1 += target->xofs;
18      x2 += target->xofs;
19      y += target->yofs;
20      target = target->parent;
21   }
22
23   x1 -= target->lock_x;
24   x2 -= target->lock_x;
25   y -= target->lock_y;
26   y--;
27
28   if (y < 0 || y >= target->lock_h) {
29      return;
30   }
31
32   if (x1 < 0) {
33
34      x1 = 0;
35   }
36
37   if (x2 > target->lock_w - 1) {
38      x2 = target->lock_w - 1;
39   }
40
41   {
42      int op, src_mode, dst_mode;
43      int op_alpha, src_alpha, dst_alpha;
44      ALLEGRO_COLOR const_color;
45      al_get_separate_bitmap_blender(&op, &src_mode, &dst_mode, &op_alpha, &src_alpha, &dst_alpha);
46      const_color = al_get_blend_color();
47
48      {
49	 {
50	    const int dst_format = target->locked_region.format;
51	    uint8_t *dst_data = (uint8_t *) target->lock_data + y * target->locked_region.pitch + x1 * target->locked_region.pixel_size;
52
53	    if (op == ALLEGRO_ADD && src_mode == ALLEGRO_ONE && src_alpha == ALLEGRO_ONE && op_alpha == ALLEGRO_ADD && dst_mode == ALLEGRO_INVERSE_ALPHA && dst_alpha == ALLEGRO_INVERSE_ALPHA) {
54
55	       {
56		  {
57		     for (; x1 <= x2; x1++) {
58			ALLEGRO_COLOR src_color = cur_color;
59
60			{
61			   ALLEGRO_COLOR dst_color;
62			   ALLEGRO_COLOR result;
63			   _AL_INLINE_GET_PIXEL(dst_format, dst_data, dst_color, false);
64			   _al_blend_alpha_inline(&src_color, &dst_color, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA, NULL, &result);
65			   _AL_INLINE_PUT_PIXEL(dst_format, dst_data, result, true);
66			}
67
68		     }
69		  }
70	       }
71	    } else if (op == ALLEGRO_ADD && src_mode == ALLEGRO_ALPHA && src_alpha == ALLEGRO_ALPHA && op_alpha == ALLEGRO_ADD && dst_mode == ALLEGRO_INVERSE_ALPHA && dst_alpha == ALLEGRO_INVERSE_ALPHA) {
72
73	       {
74		  {
75		     for (; x1 <= x2; x1++) {
76			ALLEGRO_COLOR src_color = cur_color;
77
78			{
79			   ALLEGRO_COLOR dst_color;
80			   ALLEGRO_COLOR result;
81			   _AL_INLINE_GET_PIXEL(dst_format, dst_data, dst_color, false);
82			   _al_blend_alpha_inline(&src_color, &dst_color, ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, NULL, &result);
83			   _AL_INLINE_PUT_PIXEL(dst_format, dst_data, result, true);
84			}
85
86		     }
87		  }
88	       }
89	    } else if (op == ALLEGRO_ADD && src_mode == ALLEGRO_ONE && src_alpha == ALLEGRO_ONE && op_alpha == ALLEGRO_ADD && dst_mode == ALLEGRO_ONE && dst_alpha == ALLEGRO_ONE) {
90
91	       {
92		  {
93		     for (; x1 <= x2; x1++) {
94			ALLEGRO_COLOR src_color = cur_color;
95
96			{
97			   ALLEGRO_COLOR dst_color;
98			   ALLEGRO_COLOR result;
99			   _AL_INLINE_GET_PIXEL(dst_format, dst_data, dst_color, false);
100			   _al_blend_alpha_inline(&src_color, &dst_color, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE, NULL, &result);
101			   _AL_INLINE_PUT_PIXEL(dst_format, dst_data, result, true);
102			}
103
104		     }
105		  }
106	       }
107	    } else if (dst_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888) {
108	       {
109		  for (; x1 <= x2; x1++) {
110		     ALLEGRO_COLOR src_color = cur_color;
111
112		     {
113			ALLEGRO_COLOR dst_color;
114			ALLEGRO_COLOR result;
115			_AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, dst_color, false);
116			_al_blend_inline(&src_color, &dst_color, op, src_mode, dst_mode, op_alpha, src_alpha, dst_alpha, &const_color, &result);
117			_AL_INLINE_PUT_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, result, true);
118		     }
119
120		  }
121	       }
122	    } else {
123	       {
124		  for (; x1 <= x2; x1++) {
125		     ALLEGRO_COLOR src_color = cur_color;
126
127		     {
128			ALLEGRO_COLOR dst_color;
129			ALLEGRO_COLOR result;
130			_AL_INLINE_GET_PIXEL(dst_format, dst_data, dst_color, false);
131			_al_blend_inline(&src_color, &dst_color, op, src_mode, dst_mode, op_alpha, src_alpha, dst_alpha, &const_color, &result);
132			_AL_INLINE_PUT_PIXEL(dst_format, dst_data, result, true);
133		     }
134
135		  }
136	       }
137	    }
138	 }
139      }
140   }
141}
142
143static void shader_solid_any_draw_opaque(uintptr_t state, int x1, int y, int x2)
144{
145   state_solid_any_2d *s = (state_solid_any_2d *) state;
146   ALLEGRO_COLOR cur_color = s->cur_color;
147
148   ALLEGRO_BITMAP *target = s->target;
149
150   if (target->parent) {
151      x1 += target->xofs;
152      x2 += target->xofs;
153      y += target->yofs;
154      target = target->parent;
155   }
156
157   x1 -= target->lock_x;
158   x2 -= target->lock_x;
159   y -= target->lock_y;
160   y--;
161
162   if (y < 0 || y >= target->lock_h) {
163      return;
164   }
165
166   if (x1 < 0) {
167
168      x1 = 0;
169   }
170
171   if (x2 > target->lock_w - 1) {
172      x2 = target->lock_w - 1;
173   }
174
175   {
176      {
177	 {
178	    const int dst_format = target->locked_region.format;
179	    uint8_t *dst_data = (uint8_t *) target->lock_data + y * target->locked_region.pitch + x1 * target->locked_region.pixel_size;
180
181	    if (dst_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888) {
182	       {
183		  for (; x1 <= x2; x1++) {
184		     ALLEGRO_COLOR src_color = cur_color;
185
186		     _AL_INLINE_PUT_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, src_color, true);
187
188		  }
189	       }
190	    } else {
191	       {
192		  for (; x1 <= x2; x1++) {
193		     ALLEGRO_COLOR src_color = cur_color;
194
195		     _AL_INLINE_PUT_PIXEL(dst_format, dst_data, src_color, true);
196
197		  }
198	       }
199	    }
200	 }
201      }
202   }
203}
204
205static void shader_grad_any_draw_shade(uintptr_t state, int x1, int y, int x2)
206{
207   state_grad_any_2d *gs = (state_grad_any_2d *) state;
208   state_solid_any_2d *s = &gs->solid;
209   ALLEGRO_COLOR cur_color = s->cur_color;
210
211   ALLEGRO_BITMAP *target = s->target;
212
213   if (target->parent) {
214      x1 += target->xofs;
215      x2 += target->xofs;
216      y += target->yofs;
217      target = target->parent;
218   }
219
220   x1 -= target->lock_x;
221   x2 -= target->lock_x;
222   y -= target->lock_y;
223   y--;
224
225   if (y < 0 || y >= target->lock_h) {
226      return;
227   }
228
229   if (x1 < 0) {
230
231      cur_color.r += gs->color_dx.r * -x1;
232      cur_color.g += gs->color_dx.g * -x1;
233      cur_color.b += gs->color_dx.b * -x1;
234      cur_color.a += gs->color_dx.a * -x1;
235
236      x1 = 0;
237   }
238
239   if (x2 > target->lock_w - 1) {
240      x2 = target->lock_w - 1;
241   }
242
243   {
244      int op, src_mode, dst_mode;
245      int op_alpha, src_alpha, dst_alpha;
246      ALLEGRO_COLOR const_color;
247      al_get_separate_bitmap_blender(&op, &src_mode, &dst_mode, &op_alpha, &src_alpha, &dst_alpha);
248      const_color = al_get_blend_color();
249
250      {
251	 {
252	    const int dst_format = target->locked_region.format;
253	    uint8_t *dst_data = (uint8_t *) target->lock_data + y * target->locked_region.pitch + x1 * target->locked_region.pixel_size;
254
255	    if (op == ALLEGRO_ADD && src_mode == ALLEGRO_ONE && src_alpha == ALLEGRO_ONE && op_alpha == ALLEGRO_ADD && dst_mode == ALLEGRO_INVERSE_ALPHA && dst_alpha == ALLEGRO_INVERSE_ALPHA) {
256
257	       {
258		  {
259		     for (; x1 <= x2; x1++) {
260			ALLEGRO_COLOR src_color = cur_color;
261
262			{
263			   ALLEGRO_COLOR dst_color;
264			   ALLEGRO_COLOR result;
265			   _AL_INLINE_GET_PIXEL(dst_format, dst_data, dst_color, false);
266			   _al_blend_alpha_inline(&src_color, &dst_color, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA, NULL, &result);
267			   _AL_INLINE_PUT_PIXEL(dst_format, dst_data, result, true);
268			}
269
270			cur_color.r += gs->color_dx.r;
271			cur_color.g += gs->color_dx.g;
272			cur_color.b += gs->color_dx.b;
273			cur_color.a += gs->color_dx.a;
274
275		     }
276		  }
277	       }
278	    } else if (op == ALLEGRO_ADD && src_mode == ALLEGRO_ALPHA && src_alpha == ALLEGRO_ALPHA && op_alpha == ALLEGRO_ADD && dst_mode == ALLEGRO_INVERSE_ALPHA && dst_alpha == ALLEGRO_INVERSE_ALPHA) {
279
280	       {
281		  {
282		     for (; x1 <= x2; x1++) {
283			ALLEGRO_COLOR src_color = cur_color;
284
285			{
286			   ALLEGRO_COLOR dst_color;
287			   ALLEGRO_COLOR result;
288			   _AL_INLINE_GET_PIXEL(dst_format, dst_data, dst_color, false);
289			   _al_blend_alpha_inline(&src_color, &dst_color, ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, NULL, &result);
290			   _AL_INLINE_PUT_PIXEL(dst_format, dst_data, result, true);
291			}
292
293			cur_color.r += gs->color_dx.r;
294			cur_color.g += gs->color_dx.g;
295			cur_color.b += gs->color_dx.b;
296			cur_color.a += gs->color_dx.a;
297
298		     }
299		  }
300	       }
301	    } else if (op == ALLEGRO_ADD && src_mode == ALLEGRO_ONE && src_alpha == ALLEGRO_ONE && op_alpha == ALLEGRO_ADD && dst_mode == ALLEGRO_ONE && dst_alpha == ALLEGRO_ONE) {
302
303	       {
304		  {
305		     for (; x1 <= x2; x1++) {
306			ALLEGRO_COLOR src_color = cur_color;
307
308			{
309			   ALLEGRO_COLOR dst_color;
310			   ALLEGRO_COLOR result;
311			   _AL_INLINE_GET_PIXEL(dst_format, dst_data, dst_color, false);
312			   _al_blend_alpha_inline(&src_color, &dst_color, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE, NULL, &result);
313			   _AL_INLINE_PUT_PIXEL(dst_format, dst_data, result, true);
314			}
315
316			cur_color.r += gs->color_dx.r;
317			cur_color.g += gs->color_dx.g;
318			cur_color.b += gs->color_dx.b;
319			cur_color.a += gs->color_dx.a;
320
321		     }
322		  }
323	       }
324	    } else if (dst_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888) {
325	       {
326		  for (; x1 <= x2; x1++) {
327		     ALLEGRO_COLOR src_color = cur_color;
328
329		     {
330			ALLEGRO_COLOR dst_color;
331			ALLEGRO_COLOR result;
332			_AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, dst_color, false);
333			_al_blend_inline(&src_color, &dst_color, op, src_mode, dst_mode, op_alpha, src_alpha, dst_alpha, &const_color, &result);
334			_AL_INLINE_PUT_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, result, true);
335		     }
336
337		     cur_color.r += gs->color_dx.r;
338		     cur_color.g += gs->color_dx.g;
339		     cur_color.b += gs->color_dx.b;
340		     cur_color.a += gs->color_dx.a;
341
342		  }
343	       }
344	    } else {
345	       {
346		  for (; x1 <= x2; x1++) {
347		     ALLEGRO_COLOR src_color = cur_color;
348
349		     {
350			ALLEGRO_COLOR dst_color;
351			ALLEGRO_COLOR result;
352			_AL_INLINE_GET_PIXEL(dst_format, dst_data, dst_color, false);
353			_al_blend_inline(&src_color, &dst_color, op, src_mode, dst_mode, op_alpha, src_alpha, dst_alpha, &const_color, &result);
354			_AL_INLINE_PUT_PIXEL(dst_format, dst_data, result, true);
355		     }
356
357		     cur_color.r += gs->color_dx.r;
358		     cur_color.g += gs->color_dx.g;
359		     cur_color.b += gs->color_dx.b;
360		     cur_color.a += gs->color_dx.a;
361
362		  }
363	       }
364	    }
365	 }
366      }
367   }
368}
369
370static void shader_grad_any_draw_opaque(uintptr_t state, int x1, int y, int x2)
371{
372   state_grad_any_2d *gs = (state_grad_any_2d *) state;
373   state_solid_any_2d *s = &gs->solid;
374   ALLEGRO_COLOR cur_color = s->cur_color;
375
376   ALLEGRO_BITMAP *target = s->target;
377
378   if (target->parent) {
379      x1 += target->xofs;
380      x2 += target->xofs;
381      y += target->yofs;
382      target = target->parent;
383   }
384
385   x1 -= target->lock_x;
386   x2 -= target->lock_x;
387   y -= target->lock_y;
388   y--;
389
390   if (y < 0 || y >= target->lock_h) {
391      return;
392   }
393
394   if (x1 < 0) {
395
396      cur_color.r += gs->color_dx.r * -x1;
397      cur_color.g += gs->color_dx.g * -x1;
398      cur_color.b += gs->color_dx.b * -x1;
399      cur_color.a += gs->color_dx.a * -x1;
400
401      x1 = 0;
402   }
403
404   if (x2 > target->lock_w - 1) {
405      x2 = target->lock_w - 1;
406   }
407
408   {
409      {
410	 {
411	    const int dst_format = target->locked_region.format;
412	    uint8_t *dst_data = (uint8_t *) target->lock_data + y * target->locked_region.pitch + x1 * target->locked_region.pixel_size;
413
414	    if (dst_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888) {
415	       {
416		  for (; x1 <= x2; x1++) {
417		     ALLEGRO_COLOR src_color = cur_color;
418
419		     _AL_INLINE_PUT_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, src_color, true);
420
421		     cur_color.r += gs->color_dx.r;
422		     cur_color.g += gs->color_dx.g;
423		     cur_color.b += gs->color_dx.b;
424		     cur_color.a += gs->color_dx.a;
425
426		  }
427	       }
428	    } else {
429	       {
430		  for (; x1 <= x2; x1++) {
431		     ALLEGRO_COLOR src_color = cur_color;
432
433		     _AL_INLINE_PUT_PIXEL(dst_format, dst_data, src_color, true);
434
435		     cur_color.r += gs->color_dx.r;
436		     cur_color.g += gs->color_dx.g;
437		     cur_color.b += gs->color_dx.b;
438		     cur_color.a += gs->color_dx.a;
439
440		  }
441	       }
442	    }
443	 }
444      }
445   }
446}
447
448static void shader_texture_solid_any_draw_shade(uintptr_t state, int x1, int y, int x2)
449{
450   state_texture_solid_any_2d *s = (state_texture_solid_any_2d *) state;
451
452   float u = s->u;
453   float v = s->v;
454
455   ALLEGRO_BITMAP *target = s->target;
456
457   if (target->parent) {
458      x1 += target->xofs;
459      x2 += target->xofs;
460      y += target->yofs;
461      target = target->parent;
462   }
463
464   x1 -= target->lock_x;
465   x2 -= target->lock_x;
466   y -= target->lock_y;
467   y--;
468
469   if (y < 0 || y >= target->lock_h) {
470      return;
471   }
472
473   if (x1 < 0) {
474
475      u += s->du_dx * -x1;
476      v += s->dv_dx * -x1;
477
478      x1 = 0;
479   }
480
481   if (x2 > target->lock_w - 1) {
482      x2 = target->lock_w - 1;
483   }
484
485   {
486      int op, src_mode, dst_mode;
487      int op_alpha, src_alpha, dst_alpha;
488      ALLEGRO_COLOR const_color;
489      al_get_separate_bitmap_blender(&op, &src_mode, &dst_mode, &op_alpha, &src_alpha, &dst_alpha);
490      const_color = al_get_blend_color();
491
492      {
493	 const int offset_x = s->texture->parent ? s->texture->xofs : 0;
494	 const int offset_y = s->texture->parent ? s->texture->yofs : 0;
495	 ALLEGRO_BITMAP *texture = s->texture->parent ? s->texture->parent : s->texture;
496	 const int src_format = texture->locked_region.format;
497	 const int src_size = texture->locked_region.pixel_size;
498
499	 /* Ensure u in [0, s->w) and v in [0, s->h). */
500	 while (u < 0)
501	    u += s->w;
502	 while (v < 0)
503	    v += s->h;
504	 u = fmodf(u, s->w);
505	 v = fmodf(v, s->h);
506	 ASSERT(0 <= u);
507	 ASSERT(u < s->w);
508	 ASSERT(0 <= v);
509	 ASSERT(v < s->h);
510
511	 {
512	    const int dst_format = target->locked_region.format;
513	    uint8_t *dst_data = (uint8_t *) target->lock_data + y * target->locked_region.pitch + x1 * target->locked_region.pixel_size;
514
515	    if (op == ALLEGRO_ADD && src_mode == ALLEGRO_ONE && src_alpha == ALLEGRO_ONE && op_alpha == ALLEGRO_ADD && dst_mode == ALLEGRO_INVERSE_ALPHA && dst_alpha == ALLEGRO_INVERSE_ALPHA) {
516
517	       if (dst_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888 && src_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888) {
518		  uint8_t *lock_data = texture->locked_region.data;
519		  const int src_pitch = texture->locked_region.pitch;
520		  const al_fixed du_dx = al_ftofix(s->du_dx);
521		  const al_fixed dv_dx = al_ftofix(s->dv_dx);
522
523		  {
524		     al_fixed uu = al_ftofix(u);
525		     al_fixed vv = al_ftofix(v);
526		     const int uu_ofs = offset_x - texture->lock_x;
527		     const int vv_ofs = offset_y - texture->lock_y;
528		     const al_fixed w = al_ftofix(s->w);
529		     const al_fixed h = al_ftofix(s->h);
530
531		     for (; x1 <= x2; x1++) {
532			const int src_x = (uu >> 16) + uu_ofs;
533			const int src_y = (vv >> 16) + vv_ofs;
534			uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
535
536			ALLEGRO_COLOR src_color;
537			_AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, src_data, src_color, false);
538
539			SHADE_COLORS(src_color, s->cur_color);
540
541			{
542			   ALLEGRO_COLOR dst_color;
543			   ALLEGRO_COLOR result;
544			   _AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, dst_color, false);
545			   _al_blend_alpha_inline(&src_color, &dst_color, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA, NULL, &result);
546			   _AL_INLINE_PUT_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, result, true);
547			}
548
549			uu += du_dx;
550			vv += dv_dx;
551
552			if (_AL_EXPECT_FAIL(uu < 0))
553			   uu += w;
554			else if (_AL_EXPECT_FAIL(uu >= w))
555			   uu -= w;
556
557			if (_AL_EXPECT_FAIL(vv < 0))
558			   vv += h;
559			else if (_AL_EXPECT_FAIL(vv >= h))
560			   vv -= h;
561
562		     }
563		  }
564	       } else {
565		  uint8_t *lock_data = texture->locked_region.data;
566		  const int src_pitch = texture->locked_region.pitch;
567		  const al_fixed du_dx = al_ftofix(s->du_dx);
568		  const al_fixed dv_dx = al_ftofix(s->dv_dx);
569
570		  {
571		     al_fixed uu = al_ftofix(u);
572		     al_fixed vv = al_ftofix(v);
573		     const int uu_ofs = offset_x - texture->lock_x;
574		     const int vv_ofs = offset_y - texture->lock_y;
575		     const al_fixed w = al_ftofix(s->w);
576		     const al_fixed h = al_ftofix(s->h);
577
578		     for (; x1 <= x2; x1++) {
579			const int src_x = (uu >> 16) + uu_ofs;
580			const int src_y = (vv >> 16) + vv_ofs;
581			uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
582
583			ALLEGRO_COLOR src_color;
584			_AL_INLINE_GET_PIXEL(src_format, src_data, src_color, false);
585
586			SHADE_COLORS(src_color, s->cur_color);
587
588			{
589			   ALLEGRO_COLOR dst_color;
590			   ALLEGRO_COLOR result;
591			   _AL_INLINE_GET_PIXEL(dst_format, dst_data, dst_color, false);
592			   _al_blend_alpha_inline(&src_color, &dst_color, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA, NULL, &result);
593			   _AL_INLINE_PUT_PIXEL(dst_format, dst_data, result, true);
594			}
595
596			uu += du_dx;
597			vv += dv_dx;
598
599			if (_AL_EXPECT_FAIL(uu < 0))
600			   uu += w;
601			else if (_AL_EXPECT_FAIL(uu >= w))
602			   uu -= w;
603
604			if (_AL_EXPECT_FAIL(vv < 0))
605			   vv += h;
606			else if (_AL_EXPECT_FAIL(vv >= h))
607			   vv -= h;
608
609		     }
610		  }
611	       }
612	    } else if (op == ALLEGRO_ADD && src_mode == ALLEGRO_ALPHA && src_alpha == ALLEGRO_ALPHA && op_alpha == ALLEGRO_ADD && dst_mode == ALLEGRO_INVERSE_ALPHA && dst_alpha == ALLEGRO_INVERSE_ALPHA) {
613
614	       if (dst_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888 && src_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888) {
615		  uint8_t *lock_data = texture->locked_region.data;
616		  const int src_pitch = texture->locked_region.pitch;
617		  const al_fixed du_dx = al_ftofix(s->du_dx);
618		  const al_fixed dv_dx = al_ftofix(s->dv_dx);
619
620		  {
621		     al_fixed uu = al_ftofix(u);
622		     al_fixed vv = al_ftofix(v);
623		     const int uu_ofs = offset_x - texture->lock_x;
624		     const int vv_ofs = offset_y - texture->lock_y;
625		     const al_fixed w = al_ftofix(s->w);
626		     const al_fixed h = al_ftofix(s->h);
627
628		     for (; x1 <= x2; x1++) {
629			const int src_x = (uu >> 16) + uu_ofs;
630			const int src_y = (vv >> 16) + vv_ofs;
631			uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
632
633			ALLEGRO_COLOR src_color;
634			_AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, src_data, src_color, false);
635
636			SHADE_COLORS(src_color, s->cur_color);
637
638			{
639			   ALLEGRO_COLOR dst_color;
640			   ALLEGRO_COLOR result;
641			   _AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, dst_color, false);
642			   _al_blend_alpha_inline(&src_color, &dst_color, ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, NULL, &result);
643			   _AL_INLINE_PUT_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, result, true);
644			}
645
646			uu += du_dx;
647			vv += dv_dx;
648
649			if (_AL_EXPECT_FAIL(uu < 0))
650			   uu += w;
651			else if (_AL_EXPECT_FAIL(uu >= w))
652			   uu -= w;
653
654			if (_AL_EXPECT_FAIL(vv < 0))
655			   vv += h;
656			else if (_AL_EXPECT_FAIL(vv >= h))
657			   vv -= h;
658
659		     }
660		  }
661	       } else {
662		  uint8_t *lock_data = texture->locked_region.data;
663		  const int src_pitch = texture->locked_region.pitch;
664		  const al_fixed du_dx = al_ftofix(s->du_dx);
665		  const al_fixed dv_dx = al_ftofix(s->dv_dx);
666
667		  {
668		     al_fixed uu = al_ftofix(u);
669		     al_fixed vv = al_ftofix(v);
670		     const int uu_ofs = offset_x - texture->lock_x;
671		     const int vv_ofs = offset_y - texture->lock_y;
672		     const al_fixed w = al_ftofix(s->w);
673		     const al_fixed h = al_ftofix(s->h);
674
675		     for (; x1 <= x2; x1++) {
676			const int src_x = (uu >> 16) + uu_ofs;
677			const int src_y = (vv >> 16) + vv_ofs;
678			uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
679
680			ALLEGRO_COLOR src_color;
681			_AL_INLINE_GET_PIXEL(src_format, src_data, src_color, false);
682
683			SHADE_COLORS(src_color, s->cur_color);
684
685			{
686			   ALLEGRO_COLOR dst_color;
687			   ALLEGRO_COLOR result;
688			   _AL_INLINE_GET_PIXEL(dst_format, dst_data, dst_color, false);
689			   _al_blend_alpha_inline(&src_color, &dst_color, ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, NULL, &result);
690			   _AL_INLINE_PUT_PIXEL(dst_format, dst_data, result, true);
691			}
692
693			uu += du_dx;
694			vv += dv_dx;
695
696			if (_AL_EXPECT_FAIL(uu < 0))
697			   uu += w;
698			else if (_AL_EXPECT_FAIL(uu >= w))
699			   uu -= w;
700
701			if (_AL_EXPECT_FAIL(vv < 0))
702			   vv += h;
703			else if (_AL_EXPECT_FAIL(vv >= h))
704			   vv -= h;
705
706		     }
707		  }
708	       }
709	    } else if (op == ALLEGRO_ADD && src_mode == ALLEGRO_ONE && src_alpha == ALLEGRO_ONE && op_alpha == ALLEGRO_ADD && dst_mode == ALLEGRO_ONE && dst_alpha == ALLEGRO_ONE) {
710
711	       if (dst_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888 && src_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888) {
712		  uint8_t *lock_data = texture->locked_region.data;
713		  const int src_pitch = texture->locked_region.pitch;
714		  const al_fixed du_dx = al_ftofix(s->du_dx);
715		  const al_fixed dv_dx = al_ftofix(s->dv_dx);
716
717		  {
718		     al_fixed uu = al_ftofix(u);
719		     al_fixed vv = al_ftofix(v);
720		     const int uu_ofs = offset_x - texture->lock_x;
721		     const int vv_ofs = offset_y - texture->lock_y;
722		     const al_fixed w = al_ftofix(s->w);
723		     const al_fixed h = al_ftofix(s->h);
724
725		     for (; x1 <= x2; x1++) {
726			const int src_x = (uu >> 16) + uu_ofs;
727			const int src_y = (vv >> 16) + vv_ofs;
728			uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
729
730			ALLEGRO_COLOR src_color;
731			_AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, src_data, src_color, false);
732
733			SHADE_COLORS(src_color, s->cur_color);
734
735			{
736			   ALLEGRO_COLOR dst_color;
737			   ALLEGRO_COLOR result;
738			   _AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, dst_color, false);
739			   _al_blend_alpha_inline(&src_color, &dst_color, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE, NULL, &result);
740			   _AL_INLINE_PUT_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, result, true);
741			}
742
743			uu += du_dx;
744			vv += dv_dx;
745
746			if (_AL_EXPECT_FAIL(uu < 0))
747			   uu += w;
748			else if (_AL_EXPECT_FAIL(uu >= w))
749			   uu -= w;
750
751			if (_AL_EXPECT_FAIL(vv < 0))
752			   vv += h;
753			else if (_AL_EXPECT_FAIL(vv >= h))
754			   vv -= h;
755
756		     }
757		  }
758	       } else {
759		  uint8_t *lock_data = texture->locked_region.data;
760		  const int src_pitch = texture->locked_region.pitch;
761		  const al_fixed du_dx = al_ftofix(s->du_dx);
762		  const al_fixed dv_dx = al_ftofix(s->dv_dx);
763
764		  {
765		     al_fixed uu = al_ftofix(u);
766		     al_fixed vv = al_ftofix(v);
767		     const int uu_ofs = offset_x - texture->lock_x;
768		     const int vv_ofs = offset_y - texture->lock_y;
769		     const al_fixed w = al_ftofix(s->w);
770		     const al_fixed h = al_ftofix(s->h);
771
772		     for (; x1 <= x2; x1++) {
773			const int src_x = (uu >> 16) + uu_ofs;
774			const int src_y = (vv >> 16) + vv_ofs;
775			uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
776
777			ALLEGRO_COLOR src_color;
778			_AL_INLINE_GET_PIXEL(src_format, src_data, src_color, false);
779
780			SHADE_COLORS(src_color, s->cur_color);
781
782			{
783			   ALLEGRO_COLOR dst_color;
784			   ALLEGRO_COLOR result;
785			   _AL_INLINE_GET_PIXEL(dst_format, dst_data, dst_color, false);
786			   _al_blend_alpha_inline(&src_color, &dst_color, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE, NULL, &result);
787			   _AL_INLINE_PUT_PIXEL(dst_format, dst_data, result, true);
788			}
789
790			uu += du_dx;
791			vv += dv_dx;
792
793			if (_AL_EXPECT_FAIL(uu < 0))
794			   uu += w;
795			else if (_AL_EXPECT_FAIL(uu >= w))
796			   uu -= w;
797
798			if (_AL_EXPECT_FAIL(vv < 0))
799			   vv += h;
800			else if (_AL_EXPECT_FAIL(vv >= h))
801			   vv -= h;
802
803		     }
804		  }
805	       }
806	    } else if (dst_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888 && src_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888) {
807	       uint8_t *lock_data = texture->locked_region.data;
808	       const int src_pitch = texture->locked_region.pitch;
809	       const al_fixed du_dx = al_ftofix(s->du_dx);
810	       const al_fixed dv_dx = al_ftofix(s->dv_dx);
811
812	       {
813		  al_fixed uu = al_ftofix(u);
814		  al_fixed vv = al_ftofix(v);
815		  const int uu_ofs = offset_x - texture->lock_x;
816		  const int vv_ofs = offset_y - texture->lock_y;
817		  const al_fixed w = al_ftofix(s->w);
818		  const al_fixed h = al_ftofix(s->h);
819
820		  for (; x1 <= x2; x1++) {
821		     const int src_x = (uu >> 16) + uu_ofs;
822		     const int src_y = (vv >> 16) + vv_ofs;
823		     uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
824
825		     ALLEGRO_COLOR src_color;
826		     _AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, src_data, src_color, false);
827
828		     SHADE_COLORS(src_color, s->cur_color);
829
830		     {
831			ALLEGRO_COLOR dst_color;
832			ALLEGRO_COLOR result;
833			_AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, dst_color, false);
834			_al_blend_inline(&src_color, &dst_color, op, src_mode, dst_mode, op_alpha, src_alpha, dst_alpha, &const_color, &result);
835			_AL_INLINE_PUT_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, result, true);
836		     }
837
838		     uu += du_dx;
839		     vv += dv_dx;
840
841		     if (_AL_EXPECT_FAIL(uu < 0))
842			uu += w;
843		     else if (_AL_EXPECT_FAIL(uu >= w))
844			uu -= w;
845
846		     if (_AL_EXPECT_FAIL(vv < 0))
847			vv += h;
848		     else if (_AL_EXPECT_FAIL(vv >= h))
849			vv -= h;
850
851		  }
852	       }
853	    } else {
854	       uint8_t *lock_data = texture->locked_region.data;
855	       const int src_pitch = texture->locked_region.pitch;
856	       const al_fixed du_dx = al_ftofix(s->du_dx);
857	       const al_fixed dv_dx = al_ftofix(s->dv_dx);
858
859	       {
860		  al_fixed uu = al_ftofix(u);
861		  al_fixed vv = al_ftofix(v);
862		  const int uu_ofs = offset_x - texture->lock_x;
863		  const int vv_ofs = offset_y - texture->lock_y;
864		  const al_fixed w = al_ftofix(s->w);
865		  const al_fixed h = al_ftofix(s->h);
866
867		  for (; x1 <= x2; x1++) {
868		     const int src_x = (uu >> 16) + uu_ofs;
869		     const int src_y = (vv >> 16) + vv_ofs;
870		     uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
871
872		     ALLEGRO_COLOR src_color;
873		     _AL_INLINE_GET_PIXEL(src_format, src_data, src_color, false);
874
875		     SHADE_COLORS(src_color, s->cur_color);
876
877		     {
878			ALLEGRO_COLOR dst_color;
879			ALLEGRO_COLOR result;
880			_AL_INLINE_GET_PIXEL(dst_format, dst_data, dst_color, false);
881			_al_blend_inline(&src_color, &dst_color, op, src_mode, dst_mode, op_alpha, src_alpha, dst_alpha, &const_color, &result);
882			_AL_INLINE_PUT_PIXEL(dst_format, dst_data, result, true);
883		     }
884
885		     uu += du_dx;
886		     vv += dv_dx;
887
888		     if (_AL_EXPECT_FAIL(uu < 0))
889			uu += w;
890		     else if (_AL_EXPECT_FAIL(uu >= w))
891			uu -= w;
892
893		     if (_AL_EXPECT_FAIL(vv < 0))
894			vv += h;
895		     else if (_AL_EXPECT_FAIL(vv >= h))
896			vv -= h;
897
898		  }
899	       }
900	    }
901	 }
902      }
903   }
904}
905
906static void shader_texture_solid_any_draw_shade_white(uintptr_t state, int x1, int y, int x2)
907{
908   state_texture_solid_any_2d *s = (state_texture_solid_any_2d *) state;
909
910   float u = s->u;
911   float v = s->v;
912
913   ALLEGRO_BITMAP *target = s->target;
914
915   if (target->parent) {
916      x1 += target->xofs;
917      x2 += target->xofs;
918      y += target->yofs;
919      target = target->parent;
920   }
921
922   x1 -= target->lock_x;
923   x2 -= target->lock_x;
924   y -= target->lock_y;
925   y--;
926
927   if (y < 0 || y >= target->lock_h) {
928      return;
929   }
930
931   if (x1 < 0) {
932
933      u += s->du_dx * -x1;
934      v += s->dv_dx * -x1;
935
936      x1 = 0;
937   }
938
939   if (x2 > target->lock_w - 1) {
940      x2 = target->lock_w - 1;
941   }
942
943   {
944      int op, src_mode, dst_mode;
945      int op_alpha, src_alpha, dst_alpha;
946      ALLEGRO_COLOR const_color;
947      al_get_separate_bitmap_blender(&op, &src_mode, &dst_mode, &op_alpha, &src_alpha, &dst_alpha);
948      const_color = al_get_blend_color();
949
950      {
951	 const int offset_x = s->texture->parent ? s->texture->xofs : 0;
952	 const int offset_y = s->texture->parent ? s->texture->yofs : 0;
953	 ALLEGRO_BITMAP *texture = s->texture->parent ? s->texture->parent : s->texture;
954	 const int src_format = texture->locked_region.format;
955	 const int src_size = texture->locked_region.pixel_size;
956
957	 /* Ensure u in [0, s->w) and v in [0, s->h). */
958	 while (u < 0)
959	    u += s->w;
960	 while (v < 0)
961	    v += s->h;
962	 u = fmodf(u, s->w);
963	 v = fmodf(v, s->h);
964	 ASSERT(0 <= u);
965	 ASSERT(u < s->w);
966	 ASSERT(0 <= v);
967	 ASSERT(v < s->h);
968
969	 {
970	    const int dst_format = target->locked_region.format;
971	    uint8_t *dst_data = (uint8_t *) target->lock_data + y * target->locked_region.pitch + x1 * target->locked_region.pixel_size;
972
973	    if (op == ALLEGRO_ADD && src_mode == ALLEGRO_ONE && src_alpha == ALLEGRO_ONE && op_alpha == ALLEGRO_ADD && dst_mode == ALLEGRO_INVERSE_ALPHA && dst_alpha == ALLEGRO_INVERSE_ALPHA) {
974
975	       if (dst_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888 && src_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888) {
976		  uint8_t *lock_data = texture->locked_region.data;
977		  const int src_pitch = texture->locked_region.pitch;
978		  const al_fixed du_dx = al_ftofix(s->du_dx);
979		  const al_fixed dv_dx = al_ftofix(s->dv_dx);
980
981		  {
982		     al_fixed uu = al_ftofix(u);
983		     al_fixed vv = al_ftofix(v);
984		     const int uu_ofs = offset_x - texture->lock_x;
985		     const int vv_ofs = offset_y - texture->lock_y;
986		     const al_fixed w = al_ftofix(s->w);
987		     const al_fixed h = al_ftofix(s->h);
988
989		     for (; x1 <= x2; x1++) {
990			const int src_x = (uu >> 16) + uu_ofs;
991			const int src_y = (vv >> 16) + vv_ofs;
992			uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
993
994			ALLEGRO_COLOR src_color;
995			_AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, src_data, src_color, false);
996
997			{
998			   ALLEGRO_COLOR dst_color;
999			   ALLEGRO_COLOR result;
1000			   _AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, dst_color, false);
1001			   _al_blend_alpha_inline(&src_color, &dst_color, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA, NULL, &result);
1002			   _AL_INLINE_PUT_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, result, true);
1003			}
1004
1005			uu += du_dx;
1006			vv += dv_dx;
1007
1008			if (_AL_EXPECT_FAIL(uu < 0))
1009			   uu += w;
1010			else if (_AL_EXPECT_FAIL(uu >= w))
1011			   uu -= w;
1012
1013			if (_AL_EXPECT_FAIL(vv < 0))
1014			   vv += h;
1015			else if (_AL_EXPECT_FAIL(vv >= h))
1016			   vv -= h;
1017
1018		     }
1019		  }
1020	       } else {
1021		  uint8_t *lock_data = texture->locked_region.data;
1022		  const int src_pitch = texture->locked_region.pitch;
1023		  const al_fixed du_dx = al_ftofix(s->du_dx);
1024		  const al_fixed dv_dx = al_ftofix(s->dv_dx);
1025
1026		  {
1027		     al_fixed uu = al_ftofix(u);
1028		     al_fixed vv = al_ftofix(v);
1029		     const int uu_ofs = offset_x - texture->lock_x;
1030		     const int vv_ofs = offset_y - texture->lock_y;
1031		     const al_fixed w = al_ftofix(s->w);
1032		     const al_fixed h = al_ftofix(s->h);
1033
1034		     for (; x1 <= x2; x1++) {
1035			const int src_x = (uu >> 16) + uu_ofs;
1036			const int src_y = (vv >> 16) + vv_ofs;
1037			uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
1038
1039			ALLEGRO_COLOR src_color;
1040			_AL_INLINE_GET_PIXEL(src_format, src_data, src_color, false);
1041
1042			{
1043			   ALLEGRO_COLOR dst_color;
1044			   ALLEGRO_COLOR result;
1045			   _AL_INLINE_GET_PIXEL(dst_format, dst_data, dst_color, false);
1046			   _al_blend_alpha_inline(&src_color, &dst_color, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA, NULL, &result);
1047			   _AL_INLINE_PUT_PIXEL(dst_format, dst_data, result, true);
1048			}
1049
1050			uu += du_dx;
1051			vv += dv_dx;
1052
1053			if (_AL_EXPECT_FAIL(uu < 0))
1054			   uu += w;
1055			else if (_AL_EXPECT_FAIL(uu >= w))
1056			   uu -= w;
1057
1058			if (_AL_EXPECT_FAIL(vv < 0))
1059			   vv += h;
1060			else if (_AL_EXPECT_FAIL(vv >= h))
1061			   vv -= h;
1062
1063		     }
1064		  }
1065	       }
1066	    } else if (op == ALLEGRO_ADD && src_mode == ALLEGRO_ALPHA && src_alpha == ALLEGRO_ALPHA && op_alpha == ALLEGRO_ADD && dst_mode == ALLEGRO_INVERSE_ALPHA && dst_alpha == ALLEGRO_INVERSE_ALPHA) {
1067
1068	       if (dst_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888 && src_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888) {
1069		  uint8_t *lock_data = texture->locked_region.data;
1070		  const int src_pitch = texture->locked_region.pitch;
1071		  const al_fixed du_dx = al_ftofix(s->du_dx);
1072		  const al_fixed dv_dx = al_ftofix(s->dv_dx);
1073
1074		  {
1075		     al_fixed uu = al_ftofix(u);
1076		     al_fixed vv = al_ftofix(v);
1077		     const int uu_ofs = offset_x - texture->lock_x;
1078		     const int vv_ofs = offset_y - texture->lock_y;
1079		     const al_fixed w = al_ftofix(s->w);
1080		     const al_fixed h = al_ftofix(s->h);
1081
1082		     for (; x1 <= x2; x1++) {
1083			const int src_x = (uu >> 16) + uu_ofs;
1084			const int src_y = (vv >> 16) + vv_ofs;
1085			uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
1086
1087			ALLEGRO_COLOR src_color;
1088			_AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, src_data, src_color, false);
1089
1090			{
1091			   ALLEGRO_COLOR dst_color;
1092			   ALLEGRO_COLOR result;
1093			   _AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, dst_color, false);
1094			   _al_blend_alpha_inline(&src_color, &dst_color, ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, NULL, &result);
1095			   _AL_INLINE_PUT_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, result, true);
1096			}
1097
1098			uu += du_dx;
1099			vv += dv_dx;
1100
1101			if (_AL_EXPECT_FAIL(uu < 0))
1102			   uu += w;
1103			else if (_AL_EXPECT_FAIL(uu >= w))
1104			   uu -= w;
1105
1106			if (_AL_EXPECT_FAIL(vv < 0))
1107			   vv += h;
1108			else if (_AL_EXPECT_FAIL(vv >= h))
1109			   vv -= h;
1110
1111		     }
1112		  }
1113	       } else {
1114		  uint8_t *lock_data = texture->locked_region.data;
1115		  const int src_pitch = texture->locked_region.pitch;
1116		  const al_fixed du_dx = al_ftofix(s->du_dx);
1117		  const al_fixed dv_dx = al_ftofix(s->dv_dx);
1118
1119		  {
1120		     al_fixed uu = al_ftofix(u);
1121		     al_fixed vv = al_ftofix(v);
1122		     const int uu_ofs = offset_x - texture->lock_x;
1123		     const int vv_ofs = offset_y - texture->lock_y;
1124		     const al_fixed w = al_ftofix(s->w);
1125		     const al_fixed h = al_ftofix(s->h);
1126
1127		     for (; x1 <= x2; x1++) {
1128			const int src_x = (uu >> 16) + uu_ofs;
1129			const int src_y = (vv >> 16) + vv_ofs;
1130			uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
1131
1132			ALLEGRO_COLOR src_color;
1133			_AL_INLINE_GET_PIXEL(src_format, src_data, src_color, false);
1134
1135			{
1136			   ALLEGRO_COLOR dst_color;
1137			   ALLEGRO_COLOR result;
1138			   _AL_INLINE_GET_PIXEL(dst_format, dst_data, dst_color, false);
1139			   _al_blend_alpha_inline(&src_color, &dst_color, ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, NULL, &result);
1140			   _AL_INLINE_PUT_PIXEL(dst_format, dst_data, result, true);
1141			}
1142
1143			uu += du_dx;
1144			vv += dv_dx;
1145
1146			if (_AL_EXPECT_FAIL(uu < 0))
1147			   uu += w;
1148			else if (_AL_EXPECT_FAIL(uu >= w))
1149			   uu -= w;
1150
1151			if (_AL_EXPECT_FAIL(vv < 0))
1152			   vv += h;
1153			else if (_AL_EXPECT_FAIL(vv >= h))
1154			   vv -= h;
1155
1156		     }
1157		  }
1158	       }
1159	    } else if (op == ALLEGRO_ADD && src_mode == ALLEGRO_ONE && src_alpha == ALLEGRO_ONE && op_alpha == ALLEGRO_ADD && dst_mode == ALLEGRO_ONE && dst_alpha == ALLEGRO_ONE) {
1160
1161	       if (dst_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888 && src_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888) {
1162		  uint8_t *lock_data = texture->locked_region.data;
1163		  const int src_pitch = texture->locked_region.pitch;
1164		  const al_fixed du_dx = al_ftofix(s->du_dx);
1165		  const al_fixed dv_dx = al_ftofix(s->dv_dx);
1166
1167		  {
1168		     al_fixed uu = al_ftofix(u);
1169		     al_fixed vv = al_ftofix(v);
1170		     const int uu_ofs = offset_x - texture->lock_x;
1171		     const int vv_ofs = offset_y - texture->lock_y;
1172		     const al_fixed w = al_ftofix(s->w);
1173		     const al_fixed h = al_ftofix(s->h);
1174
1175		     for (; x1 <= x2; x1++) {
1176			const int src_x = (uu >> 16) + uu_ofs;
1177			const int src_y = (vv >> 16) + vv_ofs;
1178			uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
1179
1180			ALLEGRO_COLOR src_color;
1181			_AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, src_data, src_color, false);
1182
1183			{
1184			   ALLEGRO_COLOR dst_color;
1185			   ALLEGRO_COLOR result;
1186			   _AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, dst_color, false);
1187			   _al_blend_alpha_inline(&src_color, &dst_color, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE, NULL, &result);
1188			   _AL_INLINE_PUT_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, result, true);
1189			}
1190
1191			uu += du_dx;
1192			vv += dv_dx;
1193
1194			if (_AL_EXPECT_FAIL(uu < 0))
1195			   uu += w;
1196			else if (_AL_EXPECT_FAIL(uu >= w))
1197			   uu -= w;
1198
1199			if (_AL_EXPECT_FAIL(vv < 0))
1200			   vv += h;
1201			else if (_AL_EXPECT_FAIL(vv >= h))
1202			   vv -= h;
1203
1204		     }
1205		  }
1206	       } else {
1207		  uint8_t *lock_data = texture->locked_region.data;
1208		  const int src_pitch = texture->locked_region.pitch;
1209		  const al_fixed du_dx = al_ftofix(s->du_dx);
1210		  const al_fixed dv_dx = al_ftofix(s->dv_dx);
1211
1212		  {
1213		     al_fixed uu = al_ftofix(u);
1214		     al_fixed vv = al_ftofix(v);
1215		     const int uu_ofs = offset_x - texture->lock_x;
1216		     const int vv_ofs = offset_y - texture->lock_y;
1217		     const al_fixed w = al_ftofix(s->w);
1218		     const al_fixed h = al_ftofix(s->h);
1219
1220		     for (; x1 <= x2; x1++) {
1221			const int src_x = (uu >> 16) + uu_ofs;
1222			const int src_y = (vv >> 16) + vv_ofs;
1223			uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
1224
1225			ALLEGRO_COLOR src_color;
1226			_AL_INLINE_GET_PIXEL(src_format, src_data, src_color, false);
1227
1228			{
1229			   ALLEGRO_COLOR dst_color;
1230			   ALLEGRO_COLOR result;
1231			   _AL_INLINE_GET_PIXEL(dst_format, dst_data, dst_color, false);
1232			   _al_blend_alpha_inline(&src_color, &dst_color, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE, NULL, &result);
1233			   _AL_INLINE_PUT_PIXEL(dst_format, dst_data, result, true);
1234			}
1235
1236			uu += du_dx;
1237			vv += dv_dx;
1238
1239			if (_AL_EXPECT_FAIL(uu < 0))
1240			   uu += w;
1241			else if (_AL_EXPECT_FAIL(uu >= w))
1242			   uu -= w;
1243
1244			if (_AL_EXPECT_FAIL(vv < 0))
1245			   vv += h;
1246			else if (_AL_EXPECT_FAIL(vv >= h))
1247			   vv -= h;
1248
1249		     }
1250		  }
1251	       }
1252	    } else if (dst_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888 && src_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888) {
1253	       uint8_t *lock_data = texture->locked_region.data;
1254	       const int src_pitch = texture->locked_region.pitch;
1255	       const al_fixed du_dx = al_ftofix(s->du_dx);
1256	       const al_fixed dv_dx = al_ftofix(s->dv_dx);
1257
1258	       {
1259		  al_fixed uu = al_ftofix(u);
1260		  al_fixed vv = al_ftofix(v);
1261		  const int uu_ofs = offset_x - texture->lock_x;
1262		  const int vv_ofs = offset_y - texture->lock_y;
1263		  const al_fixed w = al_ftofix(s->w);
1264		  const al_fixed h = al_ftofix(s->h);
1265
1266		  for (; x1 <= x2; x1++) {
1267		     const int src_x = (uu >> 16) + uu_ofs;
1268		     const int src_y = (vv >> 16) + vv_ofs;
1269		     uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
1270
1271		     ALLEGRO_COLOR src_color;
1272		     _AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, src_data, src_color, false);
1273
1274		     {
1275			ALLEGRO_COLOR dst_color;
1276			ALLEGRO_COLOR result;
1277			_AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, dst_color, false);
1278			_al_blend_inline(&src_color, &dst_color, op, src_mode, dst_mode, op_alpha, src_alpha, dst_alpha, &const_color, &result);
1279			_AL_INLINE_PUT_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, result, true);
1280		     }
1281
1282		     uu += du_dx;
1283		     vv += dv_dx;
1284
1285		     if (_AL_EXPECT_FAIL(uu < 0))
1286			uu += w;
1287		     else if (_AL_EXPECT_FAIL(uu >= w))
1288			uu -= w;
1289
1290		     if (_AL_EXPECT_FAIL(vv < 0))
1291			vv += h;
1292		     else if (_AL_EXPECT_FAIL(vv >= h))
1293			vv -= h;
1294
1295		  }
1296	       }
1297	    } else {
1298	       uint8_t *lock_data = texture->locked_region.data;
1299	       const int src_pitch = texture->locked_region.pitch;
1300	       const al_fixed du_dx = al_ftofix(s->du_dx);
1301	       const al_fixed dv_dx = al_ftofix(s->dv_dx);
1302
1303	       {
1304		  al_fixed uu = al_ftofix(u);
1305		  al_fixed vv = al_ftofix(v);
1306		  const int uu_ofs = offset_x - texture->lock_x;
1307		  const int vv_ofs = offset_y - texture->lock_y;
1308		  const al_fixed w = al_ftofix(s->w);
1309		  const al_fixed h = al_ftofix(s->h);
1310
1311		  for (; x1 <= x2; x1++) {
1312		     const int src_x = (uu >> 16) + uu_ofs;
1313		     const int src_y = (vv >> 16) + vv_ofs;
1314		     uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
1315
1316		     ALLEGRO_COLOR src_color;
1317		     _AL_INLINE_GET_PIXEL(src_format, src_data, src_color, false);
1318
1319		     {
1320			ALLEGRO_COLOR dst_color;
1321			ALLEGRO_COLOR result;
1322			_AL_INLINE_GET_PIXEL(dst_format, dst_data, dst_color, false);
1323			_al_blend_inline(&src_color, &dst_color, op, src_mode, dst_mode, op_alpha, src_alpha, dst_alpha, &const_color, &result);
1324			_AL_INLINE_PUT_PIXEL(dst_format, dst_data, result, true);
1325		     }
1326
1327		     uu += du_dx;
1328		     vv += dv_dx;
1329
1330		     if (_AL_EXPECT_FAIL(uu < 0))
1331			uu += w;
1332		     else if (_AL_EXPECT_FAIL(uu >= w))
1333			uu -= w;
1334
1335		     if (_AL_EXPECT_FAIL(vv < 0))
1336			vv += h;
1337		     else if (_AL_EXPECT_FAIL(vv >= h))
1338			vv -= h;
1339
1340		  }
1341	       }
1342	    }
1343	 }
1344      }
1345   }
1346}
1347
1348static void shader_texture_solid_any_draw_opaque(uintptr_t state, int x1, int y, int x2)
1349{
1350   state_texture_solid_any_2d *s = (state_texture_solid_any_2d *) state;
1351
1352   float u = s->u;
1353   float v = s->v;
1354
1355   ALLEGRO_BITMAP *target = s->target;
1356
1357   if (target->parent) {
1358      x1 += target->xofs;
1359      x2 += target->xofs;
1360      y += target->yofs;
1361      target = target->parent;
1362   }
1363
1364   x1 -= target->lock_x;
1365   x2 -= target->lock_x;
1366   y -= target->lock_y;
1367   y--;
1368
1369   if (y < 0 || y >= target->lock_h) {
1370      return;
1371   }
1372
1373   if (x1 < 0) {
1374
1375      u += s->du_dx * -x1;
1376      v += s->dv_dx * -x1;
1377
1378      x1 = 0;
1379   }
1380
1381   if (x2 > target->lock_w - 1) {
1382      x2 = target->lock_w - 1;
1383   }
1384
1385   {
1386      {
1387	 const int offset_x = s->texture->parent ? s->texture->xofs : 0;
1388	 const int offset_y = s->texture->parent ? s->texture->yofs : 0;
1389	 ALLEGRO_BITMAP *texture = s->texture->parent ? s->texture->parent : s->texture;
1390	 const int src_format = texture->locked_region.format;
1391	 const int src_size = texture->locked_region.pixel_size;
1392
1393	 /* Ensure u in [0, s->w) and v in [0, s->h). */
1394	 while (u < 0)
1395	    u += s->w;
1396	 while (v < 0)
1397	    v += s->h;
1398	 u = fmodf(u, s->w);
1399	 v = fmodf(v, s->h);
1400	 ASSERT(0 <= u);
1401	 ASSERT(u < s->w);
1402	 ASSERT(0 <= v);
1403	 ASSERT(v < s->h);
1404
1405	 {
1406	    const int dst_format = target->locked_region.format;
1407	    uint8_t *dst_data = (uint8_t *) target->lock_data + y * target->locked_region.pitch + x1 * target->locked_region.pixel_size;
1408
1409	    if (dst_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888 && src_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888) {
1410	       uint8_t *lock_data = texture->locked_region.data;
1411	       const int src_pitch = texture->locked_region.pitch;
1412	       const al_fixed du_dx = al_ftofix(s->du_dx);
1413	       const al_fixed dv_dx = al_ftofix(s->dv_dx);
1414
1415	       const float steps = x2 - x1 + 1;
1416	       const float end_u = u + steps * s->du_dx;
1417	       const float end_v = v + steps * s->dv_dx;
1418	       if (end_u >= 0 && end_u < s->w && end_v >= 0 && end_v < s->h) {
1419
1420		  {
1421		     al_fixed uu = al_ftofix(u) + ((offset_x - texture->lock_x) << 16);
1422		     al_fixed vv = al_ftofix(v) + ((offset_y - texture->lock_y) << 16);
1423
1424		     for (; x1 <= x2; x1++) {
1425			const int src_x = (uu >> 16) + 0;
1426			const int src_y = (vv >> 16) + 0;
1427			uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
1428
1429			ALLEGRO_COLOR src_color;
1430			_AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, src_data, src_color, false);
1431
1432			SHADE_COLORS(src_color, s->cur_color);
1433
1434			_AL_INLINE_PUT_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, src_color, true);
1435
1436			uu += du_dx;
1437			vv += dv_dx;
1438
1439		     }
1440		  }
1441	       } else {
1442		  al_fixed uu = al_ftofix(u);
1443		  al_fixed vv = al_ftofix(v);
1444		  const int uu_ofs = offset_x - texture->lock_x;
1445		  const int vv_ofs = offset_y - texture->lock_y;
1446		  const al_fixed w = al_ftofix(s->w);
1447		  const al_fixed h = al_ftofix(s->h);
1448
1449		  for (; x1 <= x2; x1++) {
1450		     const int src_x = (uu >> 16) + uu_ofs;
1451		     const int src_y = (vv >> 16) + vv_ofs;
1452		     uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
1453
1454		     ALLEGRO_COLOR src_color;
1455		     _AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, src_data, src_color, false);
1456
1457		     SHADE_COLORS(src_color, s->cur_color);
1458
1459		     _AL_INLINE_PUT_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, src_color, true);
1460
1461		     uu += du_dx;
1462		     vv += dv_dx;
1463
1464		     if (_AL_EXPECT_FAIL(uu < 0))
1465			uu += w;
1466		     else if (_AL_EXPECT_FAIL(uu >= w))
1467			uu -= w;
1468
1469		     if (_AL_EXPECT_FAIL(vv < 0))
1470			vv += h;
1471		     else if (_AL_EXPECT_FAIL(vv >= h))
1472			vv -= h;
1473
1474		  }
1475	       }
1476	    } else {
1477	       uint8_t *lock_data = texture->locked_region.data;
1478	       const int src_pitch = texture->locked_region.pitch;
1479	       const al_fixed du_dx = al_ftofix(s->du_dx);
1480	       const al_fixed dv_dx = al_ftofix(s->dv_dx);
1481
1482	       const float steps = x2 - x1 + 1;
1483	       const float end_u = u + steps * s->du_dx;
1484	       const float end_v = v + steps * s->dv_dx;
1485	       if (end_u >= 0 && end_u < s->w && end_v >= 0 && end_v < s->h) {
1486
1487		  {
1488		     al_fixed uu = al_ftofix(u) + ((offset_x - texture->lock_x) << 16);
1489		     al_fixed vv = al_ftofix(v) + ((offset_y - texture->lock_y) << 16);
1490
1491		     for (; x1 <= x2; x1++) {
1492			const int src_x = (uu >> 16) + 0;
1493			const int src_y = (vv >> 16) + 0;
1494			uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
1495
1496			ALLEGRO_COLOR src_color;
1497			_AL_INLINE_GET_PIXEL(src_format, src_data, src_color, false);
1498
1499			SHADE_COLORS(src_color, s->cur_color);
1500
1501			_AL_INLINE_PUT_PIXEL(dst_format, dst_data, src_color, true);
1502
1503			uu += du_dx;
1504			vv += dv_dx;
1505
1506		     }
1507		  }
1508	       } else {
1509		  al_fixed uu = al_ftofix(u);
1510		  al_fixed vv = al_ftofix(v);
1511		  const int uu_ofs = offset_x - texture->lock_x;
1512		  const int vv_ofs = offset_y - texture->lock_y;
1513		  const al_fixed w = al_ftofix(s->w);
1514		  const al_fixed h = al_ftofix(s->h);
1515
1516		  for (; x1 <= x2; x1++) {
1517		     const int src_x = (uu >> 16) + uu_ofs;
1518		     const int src_y = (vv >> 16) + vv_ofs;
1519		     uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
1520
1521		     ALLEGRO_COLOR src_color;
1522		     _AL_INLINE_GET_PIXEL(src_format, src_data, src_color, false);
1523
1524		     SHADE_COLORS(src_color, s->cur_color);
1525
1526		     _AL_INLINE_PUT_PIXEL(dst_format, dst_data, src_color, true);
1527
1528		     uu += du_dx;
1529		     vv += dv_dx;
1530
1531		     if (_AL_EXPECT_FAIL(uu < 0))
1532			uu += w;
1533		     else if (_AL_EXPECT_FAIL(uu >= w))
1534			uu -= w;
1535
1536		     if (_AL_EXPECT_FAIL(vv < 0))
1537			vv += h;
1538		     else if (_AL_EXPECT_FAIL(vv >= h))
1539			vv -= h;
1540
1541		  }
1542	       }
1543	    }
1544	 }
1545      }
1546   }
1547}
1548
1549static void shader_texture_solid_any_draw_opaque_white(uintptr_t state, int x1, int y, int x2)
1550{
1551   state_texture_solid_any_2d *s = (state_texture_solid_any_2d *) state;
1552
1553   float u = s->u;
1554   float v = s->v;
1555
1556   ALLEGRO_BITMAP *target = s->target;
1557
1558   if (target->parent) {
1559      x1 += target->xofs;
1560      x2 += target->xofs;
1561      y += target->yofs;
1562      target = target->parent;
1563   }
1564
1565   x1 -= target->lock_x;
1566   x2 -= target->lock_x;
1567   y -= target->lock_y;
1568   y--;
1569
1570   if (y < 0 || y >= target->lock_h) {
1571      return;
1572   }
1573
1574   if (x1 < 0) {
1575
1576      u += s->du_dx * -x1;
1577      v += s->dv_dx * -x1;
1578
1579      x1 = 0;
1580   }
1581
1582   if (x2 > target->lock_w - 1) {
1583      x2 = target->lock_w - 1;
1584   }
1585
1586   {
1587      {
1588	 const int offset_x = s->texture->parent ? s->texture->xofs : 0;
1589	 const int offset_y = s->texture->parent ? s->texture->yofs : 0;
1590	 ALLEGRO_BITMAP *texture = s->texture->parent ? s->texture->parent : s->texture;
1591	 const int src_format = texture->locked_region.format;
1592	 const int src_size = texture->locked_region.pixel_size;
1593
1594	 /* Ensure u in [0, s->w) and v in [0, s->h). */
1595	 while (u < 0)
1596	    u += s->w;
1597	 while (v < 0)
1598	    v += s->h;
1599	 u = fmodf(u, s->w);
1600	 v = fmodf(v, s->h);
1601	 ASSERT(0 <= u);
1602	 ASSERT(u < s->w);
1603	 ASSERT(0 <= v);
1604	 ASSERT(v < s->h);
1605
1606	 {
1607	    const int dst_format = target->locked_region.format;
1608	    uint8_t *dst_data = (uint8_t *) target->lock_data + y * target->locked_region.pitch + x1 * target->locked_region.pixel_size;
1609
1610	    if (dst_format == src_format && src_size == 4) {
1611	       uint8_t *lock_data = texture->locked_region.data;
1612	       const int src_pitch = texture->locked_region.pitch;
1613	       const al_fixed du_dx = al_ftofix(s->du_dx);
1614	       const al_fixed dv_dx = al_ftofix(s->dv_dx);
1615
1616	       const float steps = x2 - x1 + 1;
1617	       const float end_u = u + steps * s->du_dx;
1618	       const float end_v = v + steps * s->dv_dx;
1619	       if (end_u >= 0 && end_u < s->w && end_v >= 0 && end_v < s->h) {
1620
1621		  {
1622		     al_fixed uu = al_ftofix(u) + ((offset_x - texture->lock_x) << 16);
1623		     al_fixed vv = al_ftofix(v) + ((offset_y - texture->lock_y) << 16);
1624
1625		     for (; x1 <= x2; x1++) {
1626			const int src_x = (uu >> 16) + 0;
1627			const int src_y = (vv >> 16) + 0;
1628			uint8_t *src_data = lock_data + src_y * src_pitch + src_x * 4;
1629
1630			switch (4) {
1631			case 4:
1632			   memcpy(dst_data, src_data, 4);
1633			   dst_data += 4;
1634			   break;
1635			case 3:
1636			   memcpy(dst_data, src_data, 3);
1637			   dst_data += 3;
1638			   break;
1639			case 2:
1640			   *dst_data++ = *src_data++;
1641			   *dst_data++ = *src_data;
1642			   break;
1643			case 1:
1644			   *dst_data++ = *src_data;
1645			   break;
1646			}
1647
1648			uu += du_dx;
1649			vv += dv_dx;
1650
1651		     }
1652		  }
1653	       } else {
1654		  al_fixed uu = al_ftofix(u);
1655		  al_fixed vv = al_ftofix(v);
1656		  const int uu_ofs = offset_x - texture->lock_x;
1657		  const int vv_ofs = offset_y - texture->lock_y;
1658		  const al_fixed w = al_ftofix(s->w);
1659		  const al_fixed h = al_ftofix(s->h);
1660
1661		  for (; x1 <= x2; x1++) {
1662		     const int src_x = (uu >> 16) + uu_ofs;
1663		     const int src_y = (vv >> 16) + vv_ofs;
1664		     uint8_t *src_data = lock_data + src_y * src_pitch + src_x * 4;
1665
1666		     switch (4) {
1667		     case 4:
1668			memcpy(dst_data, src_data, 4);
1669			dst_data += 4;
1670			break;
1671		     case 3:
1672			memcpy(dst_data, src_data, 3);
1673			dst_data += 3;
1674			break;
1675		     case 2:
1676			*dst_data++ = *src_data++;
1677			*dst_data++ = *src_data;
1678			break;
1679		     case 1:
1680			*dst_data++ = *src_data;
1681			break;
1682		     }
1683
1684		     uu += du_dx;
1685		     vv += dv_dx;
1686
1687		     if (_AL_EXPECT_FAIL(uu < 0))
1688			uu += w;
1689		     else if (_AL_EXPECT_FAIL(uu >= w))
1690			uu -= w;
1691
1692		     if (_AL_EXPECT_FAIL(vv < 0))
1693			vv += h;
1694		     else if (_AL_EXPECT_FAIL(vv >= h))
1695			vv -= h;
1696
1697		  }
1698	       }
1699	    } else if (dst_format == src_format && src_size == 3) {
1700	       uint8_t *lock_data = texture->locked_region.data;
1701	       const int src_pitch = texture->locked_region.pitch;
1702	       const al_fixed du_dx = al_ftofix(s->du_dx);
1703	       const al_fixed dv_dx = al_ftofix(s->dv_dx);
1704
1705	       const float steps = x2 - x1 + 1;
1706	       const float end_u = u + steps * s->du_dx;
1707	       const float end_v = v + steps * s->dv_dx;
1708	       if (end_u >= 0 && end_u < s->w && end_v >= 0 && end_v < s->h) {
1709
1710		  {
1711		     al_fixed uu = al_ftofix(u) + ((offset_x - texture->lock_x) << 16);
1712		     al_fixed vv = al_ftofix(v) + ((offset_y - texture->lock_y) << 16);
1713
1714		     for (; x1 <= x2; x1++) {
1715			const int src_x = (uu >> 16) + 0;
1716			const int src_y = (vv >> 16) + 0;
1717			uint8_t *src_data = lock_data + src_y * src_pitch + src_x * 3;
1718
1719			switch (3) {
1720			case 4:
1721			   memcpy(dst_data, src_data, 4);
1722			   dst_data += 4;
1723			   break;
1724			case 3:
1725			   memcpy(dst_data, src_data, 3);
1726			   dst_data += 3;
1727			   break;
1728			case 2:
1729			   *dst_data++ = *src_data++;
1730			   *dst_data++ = *src_data;
1731			   break;
1732			case 1:
1733			   *dst_data++ = *src_data;
1734			   break;
1735			}
1736
1737			uu += du_dx;
1738			vv += dv_dx;
1739
1740		     }
1741		  }
1742	       } else {
1743		  al_fixed uu = al_ftofix(u);
1744		  al_fixed vv = al_ftofix(v);
1745		  const int uu_ofs = offset_x - texture->lock_x;
1746		  const int vv_ofs = offset_y - texture->lock_y;
1747		  const al_fixed w = al_ftofix(s->w);
1748		  const al_fixed h = al_ftofix(s->h);
1749
1750		  for (; x1 <= x2; x1++) {
1751		     const int src_x = (uu >> 16) + uu_ofs;
1752		     const int src_y = (vv >> 16) + vv_ofs;
1753		     uint8_t *src_data = lock_data + src_y * src_pitch + src_x * 3;
1754
1755		     switch (3) {
1756		     case 4:
1757			memcpy(dst_data, src_data, 4);
1758			dst_data += 4;
1759			break;
1760		     case 3:
1761			memcpy(dst_data, src_data, 3);
1762			dst_data += 3;
1763			break;
1764		     case 2:
1765			*dst_data++ = *src_data++;
1766			*dst_data++ = *src_data;
1767			break;
1768		     case 1:
1769			*dst_data++ = *src_data;
1770			break;
1771		     }
1772
1773		     uu += du_dx;
1774		     vv += dv_dx;
1775
1776		     if (_AL_EXPECT_FAIL(uu < 0))
1777			uu += w;
1778		     else if (_AL_EXPECT_FAIL(uu >= w))
1779			uu -= w;
1780
1781		     if (_AL_EXPECT_FAIL(vv < 0))
1782			vv += h;
1783		     else if (_AL_EXPECT_FAIL(vv >= h))
1784			vv -= h;
1785
1786		  }
1787	       }
1788	    } else if (dst_format == src_format && src_size == 2) {
1789	       uint8_t *lock_data = texture->locked_region.data;
1790	       const int src_pitch = texture->locked_region.pitch;
1791	       const al_fixed du_dx = al_ftofix(s->du_dx);
1792	       const al_fixed dv_dx = al_ftofix(s->dv_dx);
1793
1794	       const float steps = x2 - x1 + 1;
1795	       const float end_u = u + steps * s->du_dx;
1796	       const float end_v = v + steps * s->dv_dx;
1797	       if (end_u >= 0 && end_u < s->w && end_v >= 0 && end_v < s->h) {
1798
1799		  {
1800		     al_fixed uu = al_ftofix(u) + ((offset_x - texture->lock_x) << 16);
1801		     al_fixed vv = al_ftofix(v) + ((offset_y - texture->lock_y) << 16);
1802
1803		     for (; x1 <= x2; x1++) {
1804			const int src_x = (uu >> 16) + 0;
1805			const int src_y = (vv >> 16) + 0;
1806			uint8_t *src_data = lock_data + src_y * src_pitch + src_x * 2;
1807
1808			switch (2) {
1809			case 4:
1810			   memcpy(dst_data, src_data, 4);
1811			   dst_data += 4;
1812			   break;
1813			case 3:
1814			   memcpy(dst_data, src_data, 3);
1815			   dst_data += 3;
1816			   break;
1817			case 2:
1818			   *dst_data++ = *src_data++;
1819			   *dst_data++ = *src_data;
1820			   break;
1821			case 1:
1822			   *dst_data++ = *src_data;
1823			   break;
1824			}
1825
1826			uu += du_dx;
1827			vv += dv_dx;
1828
1829		     }
1830		  }
1831	       } else {
1832		  al_fixed uu = al_ftofix(u);
1833		  al_fixed vv = al_ftofix(v);
1834		  const int uu_ofs = offset_x - texture->lock_x;
1835		  const int vv_ofs = offset_y - texture->lock_y;
1836		  const al_fixed w = al_ftofix(s->w);
1837		  const al_fixed h = al_ftofix(s->h);
1838
1839		  for (; x1 <= x2; x1++) {
1840		     const int src_x = (uu >> 16) + uu_ofs;
1841		     const int src_y = (vv >> 16) + vv_ofs;
1842		     uint8_t *src_data = lock_data + src_y * src_pitch + src_x * 2;
1843
1844		     switch (2) {
1845		     case 4:
1846			memcpy(dst_data, src_data, 4);
1847			dst_data += 4;
1848			break;
1849		     case 3:
1850			memcpy(dst_data, src_data, 3);
1851			dst_data += 3;
1852			break;
1853		     case 2:
1854			*dst_data++ = *src_data++;
1855			*dst_data++ = *src_data;
1856			break;
1857		     case 1:
1858			*dst_data++ = *src_data;
1859			break;
1860		     }
1861
1862		     uu += du_dx;
1863		     vv += dv_dx;
1864
1865		     if (_AL_EXPECT_FAIL(uu < 0))
1866			uu += w;
1867		     else if (_AL_EXPECT_FAIL(uu >= w))
1868			uu -= w;
1869
1870		     if (_AL_EXPECT_FAIL(vv < 0))
1871			vv += h;
1872		     else if (_AL_EXPECT_FAIL(vv >= h))
1873			vv -= h;
1874
1875		  }
1876	       }
1877	    } else {
1878	       uint8_t *lock_data = texture->locked_region.data;
1879	       const int src_pitch = texture->locked_region.pitch;
1880	       const al_fixed du_dx = al_ftofix(s->du_dx);
1881	       const al_fixed dv_dx = al_ftofix(s->dv_dx);
1882
1883	       const float steps = x2 - x1 + 1;
1884	       const float end_u = u + steps * s->du_dx;
1885	       const float end_v = v + steps * s->dv_dx;
1886	       if (end_u >= 0 && end_u < s->w && end_v >= 0 && end_v < s->h) {
1887
1888		  {
1889		     al_fixed uu = al_ftofix(u) + ((offset_x - texture->lock_x) << 16);
1890		     al_fixed vv = al_ftofix(v) + ((offset_y - texture->lock_y) << 16);
1891
1892		     for (; x1 <= x2; x1++) {
1893			const int src_x = (uu >> 16) + 0;
1894			const int src_y = (vv >> 16) + 0;
1895			uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
1896
1897			ALLEGRO_COLOR src_color;
1898			_AL_INLINE_GET_PIXEL(src_format, src_data, src_color, false);
1899
1900			_AL_INLINE_PUT_PIXEL(dst_format, dst_data, src_color, true);
1901
1902			uu += du_dx;
1903			vv += dv_dx;
1904
1905		     }
1906		  }
1907	       } else {
1908		  al_fixed uu = al_ftofix(u);
1909		  al_fixed vv = al_ftofix(v);
1910		  const int uu_ofs = offset_x - texture->lock_x;
1911		  const int vv_ofs = offset_y - texture->lock_y;
1912		  const al_fixed w = al_ftofix(s->w);
1913		  const al_fixed h = al_ftofix(s->h);
1914
1915		  for (; x1 <= x2; x1++) {
1916		     const int src_x = (uu >> 16) + uu_ofs;
1917		     const int src_y = (vv >> 16) + vv_ofs;
1918		     uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
1919
1920		     ALLEGRO_COLOR src_color;
1921		     _AL_INLINE_GET_PIXEL(src_format, src_data, src_color, false);
1922
1923		     _AL_INLINE_PUT_PIXEL(dst_format, dst_data, src_color, true);
1924
1925		     uu += du_dx;
1926		     vv += dv_dx;
1927
1928		     if (_AL_EXPECT_FAIL(uu < 0))
1929			uu += w;
1930		     else if (_AL_EXPECT_FAIL(uu >= w))
1931			uu -= w;
1932
1933		     if (_AL_EXPECT_FAIL(vv < 0))
1934			vv += h;
1935		     else if (_AL_EXPECT_FAIL(vv >= h))
1936			vv -= h;
1937
1938		  }
1939	       }
1940	    }
1941	 }
1942      }
1943   }
1944}
1945
1946static void shader_texture_grad_any_draw_shade(uintptr_t state, int x1, int y, int x2)
1947{
1948   state_texture_grad_any_2d *gs = (state_texture_grad_any_2d *) state;
1949   state_texture_solid_any_2d *s = &gs->solid;
1950   ALLEGRO_COLOR cur_color = s->cur_color;
1951
1952   float u = s->u;
1953   float v = s->v;
1954
1955   ALLEGRO_BITMAP *target = s->target;
1956
1957   if (target->parent) {
1958      x1 += target->xofs;
1959      x2 += target->xofs;
1960      y += target->yofs;
1961      target = target->parent;
1962   }
1963
1964   x1 -= target->lock_x;
1965   x2 -= target->lock_x;
1966   y -= target->lock_y;
1967   y--;
1968
1969   if (y < 0 || y >= target->lock_h) {
1970      return;
1971   }
1972
1973   if (x1 < 0) {
1974
1975      u += s->du_dx * -x1;
1976      v += s->dv_dx * -x1;
1977
1978      cur_color.r += gs->color_dx.r * -x1;
1979      cur_color.g += gs->color_dx.g * -x1;
1980      cur_color.b += gs->color_dx.b * -x1;
1981      cur_color.a += gs->color_dx.a * -x1;
1982
1983      x1 = 0;
1984   }
1985
1986   if (x2 > target->lock_w - 1) {
1987      x2 = target->lock_w - 1;
1988   }
1989
1990   {
1991      int op, src_mode, dst_mode;
1992      int op_alpha, src_alpha, dst_alpha;
1993      ALLEGRO_COLOR const_color;
1994      al_get_separate_bitmap_blender(&op, &src_mode, &dst_mode, &op_alpha, &src_alpha, &dst_alpha);
1995      const_color = al_get_blend_color();
1996
1997      {
1998	 const int offset_x = s->texture->parent ? s->texture->xofs : 0;
1999	 const int offset_y = s->texture->parent ? s->texture->yofs : 0;
2000	 ALLEGRO_BITMAP *texture = s->texture->parent ? s->texture->parent : s->texture;
2001	 const int src_format = texture->locked_region.format;
2002	 const int src_size = texture->locked_region.pixel_size;
2003
2004	 /* Ensure u in [0, s->w) and v in [0, s->h). */
2005	 while (u < 0)
2006	    u += s->w;
2007	 while (v < 0)
2008	    v += s->h;
2009	 u = fmodf(u, s->w);
2010	 v = fmodf(v, s->h);
2011	 ASSERT(0 <= u);
2012	 ASSERT(u < s->w);
2013	 ASSERT(0 <= v);
2014	 ASSERT(v < s->h);
2015
2016	 {
2017	    const int dst_format = target->locked_region.format;
2018	    uint8_t *dst_data = (uint8_t *) target->lock_data + y * target->locked_region.pitch + x1 * target->locked_region.pixel_size;
2019
2020	    if (op == ALLEGRO_ADD && src_mode == ALLEGRO_ONE && src_alpha == ALLEGRO_ONE && op_alpha == ALLEGRO_ADD && dst_mode == ALLEGRO_INVERSE_ALPHA && dst_alpha == ALLEGRO_INVERSE_ALPHA) {
2021
2022	       if (dst_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888 && src_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888) {
2023		  uint8_t *lock_data = texture->locked_region.data;
2024		  const int src_pitch = texture->locked_region.pitch;
2025		  const al_fixed du_dx = al_ftofix(s->du_dx);
2026		  const al_fixed dv_dx = al_ftofix(s->dv_dx);
2027
2028		  {
2029		     al_fixed uu = al_ftofix(u);
2030		     al_fixed vv = al_ftofix(v);
2031		     const int uu_ofs = offset_x - texture->lock_x;
2032		     const int vv_ofs = offset_y - texture->lock_y;
2033		     const al_fixed w = al_ftofix(s->w);
2034		     const al_fixed h = al_ftofix(s->h);
2035
2036		     for (; x1 <= x2; x1++) {
2037			const int src_x = (uu >> 16) + uu_ofs;
2038			const int src_y = (vv >> 16) + vv_ofs;
2039			uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
2040
2041			ALLEGRO_COLOR src_color;
2042			_AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, src_data, src_color, false);
2043
2044			SHADE_COLORS(src_color, cur_color);
2045
2046			{
2047			   ALLEGRO_COLOR dst_color;
2048			   ALLEGRO_COLOR result;
2049			   _AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, dst_color, false);
2050			   _al_blend_alpha_inline(&src_color, &dst_color, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA, NULL, &result);
2051			   _AL_INLINE_PUT_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, result, true);
2052			}
2053
2054			uu += du_dx;
2055			vv += dv_dx;
2056
2057			if (_AL_EXPECT_FAIL(uu < 0))
2058			   uu += w;
2059			else if (_AL_EXPECT_FAIL(uu >= w))
2060			   uu -= w;
2061
2062			if (_AL_EXPECT_FAIL(vv < 0))
2063			   vv += h;
2064			else if (_AL_EXPECT_FAIL(vv >= h))
2065			   vv -= h;
2066
2067			cur_color.r += gs->color_dx.r;
2068			cur_color.g += gs->color_dx.g;
2069			cur_color.b += gs->color_dx.b;
2070			cur_color.a += gs->color_dx.a;
2071
2072		     }
2073		  }
2074	       } else {
2075		  uint8_t *lock_data = texture->locked_region.data;
2076		  const int src_pitch = texture->locked_region.pitch;
2077		  const al_fixed du_dx = al_ftofix(s->du_dx);
2078		  const al_fixed dv_dx = al_ftofix(s->dv_dx);
2079
2080		  {
2081		     al_fixed uu = al_ftofix(u);
2082		     al_fixed vv = al_ftofix(v);
2083		     const int uu_ofs = offset_x - texture->lock_x;
2084		     const int vv_ofs = offset_y - texture->lock_y;
2085		     const al_fixed w = al_ftofix(s->w);
2086		     const al_fixed h = al_ftofix(s->h);
2087
2088		     for (; x1 <= x2; x1++) {
2089			const int src_x = (uu >> 16) + uu_ofs;
2090			const int src_y = (vv >> 16) + vv_ofs;
2091			uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
2092
2093			ALLEGRO_COLOR src_color;
2094			_AL_INLINE_GET_PIXEL(src_format, src_data, src_color, false);
2095
2096			SHADE_COLORS(src_color, cur_color);
2097
2098			{
2099			   ALLEGRO_COLOR dst_color;
2100			   ALLEGRO_COLOR result;
2101			   _AL_INLINE_GET_PIXEL(dst_format, dst_data, dst_color, false);
2102			   _al_blend_alpha_inline(&src_color, &dst_color, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA, NULL, &result);
2103			   _AL_INLINE_PUT_PIXEL(dst_format, dst_data, result, true);
2104			}
2105
2106			uu += du_dx;
2107			vv += dv_dx;
2108
2109			if (_AL_EXPECT_FAIL(uu < 0))
2110			   uu += w;
2111			else if (_AL_EXPECT_FAIL(uu >= w))
2112			   uu -= w;
2113
2114			if (_AL_EXPECT_FAIL(vv < 0))
2115			   vv += h;
2116			else if (_AL_EXPECT_FAIL(vv >= h))
2117			   vv -= h;
2118
2119			cur_color.r += gs->color_dx.r;
2120			cur_color.g += gs->color_dx.g;
2121			cur_color.b += gs->color_dx.b;
2122			cur_color.a += gs->color_dx.a;
2123
2124		     }
2125		  }
2126	       }
2127	    } else if (op == ALLEGRO_ADD && src_mode == ALLEGRO_ALPHA && src_alpha == ALLEGRO_ALPHA && op_alpha == ALLEGRO_ADD && dst_mode == ALLEGRO_INVERSE_ALPHA && dst_alpha == ALLEGRO_INVERSE_ALPHA) {
2128
2129	       if (dst_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888 && src_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888) {
2130		  uint8_t *lock_data = texture->locked_region.data;
2131		  const int src_pitch = texture->locked_region.pitch;
2132		  const al_fixed du_dx = al_ftofix(s->du_dx);
2133		  const al_fixed dv_dx = al_ftofix(s->dv_dx);
2134
2135		  {
2136		     al_fixed uu = al_ftofix(u);
2137		     al_fixed vv = al_ftofix(v);
2138		     const int uu_ofs = offset_x - texture->lock_x;
2139		     const int vv_ofs = offset_y - texture->lock_y;
2140		     const al_fixed w = al_ftofix(s->w);
2141		     const al_fixed h = al_ftofix(s->h);
2142
2143		     for (; x1 <= x2; x1++) {
2144			const int src_x = (uu >> 16) + uu_ofs;
2145			const int src_y = (vv >> 16) + vv_ofs;
2146			uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
2147
2148			ALLEGRO_COLOR src_color;
2149			_AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, src_data, src_color, false);
2150
2151			SHADE_COLORS(src_color, cur_color);
2152
2153			{
2154			   ALLEGRO_COLOR dst_color;
2155			   ALLEGRO_COLOR result;
2156			   _AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, dst_color, false);
2157			   _al_blend_alpha_inline(&src_color, &dst_color, ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, NULL, &result);
2158			   _AL_INLINE_PUT_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, result, true);
2159			}
2160
2161			uu += du_dx;
2162			vv += dv_dx;
2163
2164			if (_AL_EXPECT_FAIL(uu < 0))
2165			   uu += w;
2166			else if (_AL_EXPECT_FAIL(uu >= w))
2167			   uu -= w;
2168
2169			if (_AL_EXPECT_FAIL(vv < 0))
2170			   vv += h;
2171			else if (_AL_EXPECT_FAIL(vv >= h))
2172			   vv -= h;
2173
2174			cur_color.r += gs->color_dx.r;
2175			cur_color.g += gs->color_dx.g;
2176			cur_color.b += gs->color_dx.b;
2177			cur_color.a += gs->color_dx.a;
2178
2179		     }
2180		  }
2181	       } else {
2182		  uint8_t *lock_data = texture->locked_region.data;
2183		  const int src_pitch = texture->locked_region.pitch;
2184		  const al_fixed du_dx = al_ftofix(s->du_dx);
2185		  const al_fixed dv_dx = al_ftofix(s->dv_dx);
2186
2187		  {
2188		     al_fixed uu = al_ftofix(u);
2189		     al_fixed vv = al_ftofix(v);
2190		     const int uu_ofs = offset_x - texture->lock_x;
2191		     const int vv_ofs = offset_y - texture->lock_y;
2192		     const al_fixed w = al_ftofix(s->w);
2193		     const al_fixed h = al_ftofix(s->h);
2194
2195		     for (; x1 <= x2; x1++) {
2196			const int src_x = (uu >> 16) + uu_ofs;
2197			const int src_y = (vv >> 16) + vv_ofs;
2198			uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
2199
2200			ALLEGRO_COLOR src_color;
2201			_AL_INLINE_GET_PIXEL(src_format, src_data, src_color, false);
2202
2203			SHADE_COLORS(src_color, cur_color);
2204
2205			{
2206			   ALLEGRO_COLOR dst_color;
2207			   ALLEGRO_COLOR result;
2208			   _AL_INLINE_GET_PIXEL(dst_format, dst_data, dst_color, false);
2209			   _al_blend_alpha_inline(&src_color, &dst_color, ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, NULL, &result);
2210			   _AL_INLINE_PUT_PIXEL(dst_format, dst_data, result, true);
2211			}
2212
2213			uu += du_dx;
2214			vv += dv_dx;
2215
2216			if (_AL_EXPECT_FAIL(uu < 0))
2217			   uu += w;
2218			else if (_AL_EXPECT_FAIL(uu >= w))
2219			   uu -= w;
2220
2221			if (_AL_EXPECT_FAIL(vv < 0))
2222			   vv += h;
2223			else if (_AL_EXPECT_FAIL(vv >= h))
2224			   vv -= h;
2225
2226			cur_color.r += gs->color_dx.r;
2227			cur_color.g += gs->color_dx.g;
2228			cur_color.b += gs->color_dx.b;
2229			cur_color.a += gs->color_dx.a;
2230
2231		     }
2232		  }
2233	       }
2234	    } else if (op == ALLEGRO_ADD && src_mode == ALLEGRO_ONE && src_alpha == ALLEGRO_ONE && op_alpha == ALLEGRO_ADD && dst_mode == ALLEGRO_ONE && dst_alpha == ALLEGRO_ONE) {
2235
2236	       if (dst_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888 && src_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888) {
2237		  uint8_t *lock_data = texture->locked_region.data;
2238		  const int src_pitch = texture->locked_region.pitch;
2239		  const al_fixed du_dx = al_ftofix(s->du_dx);
2240		  const al_fixed dv_dx = al_ftofix(s->dv_dx);
2241
2242		  {
2243		     al_fixed uu = al_ftofix(u);
2244		     al_fixed vv = al_ftofix(v);
2245		     const int uu_ofs = offset_x - texture->lock_x;
2246		     const int vv_ofs = offset_y - texture->lock_y;
2247		     const al_fixed w = al_ftofix(s->w);
2248		     const al_fixed h = al_ftofix(s->h);
2249
2250		     for (; x1 <= x2; x1++) {
2251			const int src_x = (uu >> 16) + uu_ofs;
2252			const int src_y = (vv >> 16) + vv_ofs;
2253			uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
2254
2255			ALLEGRO_COLOR src_color;
2256			_AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, src_data, src_color, false);
2257
2258			SHADE_COLORS(src_color, cur_color);
2259
2260			{
2261			   ALLEGRO_COLOR dst_color;
2262			   ALLEGRO_COLOR result;
2263			   _AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, dst_color, false);
2264			   _al_blend_alpha_inline(&src_color, &dst_color, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE, NULL, &result);
2265			   _AL_INLINE_PUT_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, result, true);
2266			}
2267
2268			uu += du_dx;
2269			vv += dv_dx;
2270
2271			if (_AL_EXPECT_FAIL(uu < 0))
2272			   uu += w;
2273			else if (_AL_EXPECT_FAIL(uu >= w))
2274			   uu -= w;
2275
2276			if (_AL_EXPECT_FAIL(vv < 0))
2277			   vv += h;
2278			else if (_AL_EXPECT_FAIL(vv >= h))
2279			   vv -= h;
2280
2281			cur_color.r += gs->color_dx.r;
2282			cur_color.g += gs->color_dx.g;
2283			cur_color.b += gs->color_dx.b;
2284			cur_color.a += gs->color_dx.a;
2285
2286		     }
2287		  }
2288	       } else {
2289		  uint8_t *lock_data = texture->locked_region.data;
2290		  const int src_pitch = texture->locked_region.pitch;
2291		  const al_fixed du_dx = al_ftofix(s->du_dx);
2292		  const al_fixed dv_dx = al_ftofix(s->dv_dx);
2293
2294		  {
2295		     al_fixed uu = al_ftofix(u);
2296		     al_fixed vv = al_ftofix(v);
2297		     const int uu_ofs = offset_x - texture->lock_x;
2298		     const int vv_ofs = offset_y - texture->lock_y;
2299		     const al_fixed w = al_ftofix(s->w);
2300		     const al_fixed h = al_ftofix(s->h);
2301
2302		     for (; x1 <= x2; x1++) {
2303			const int src_x = (uu >> 16) + uu_ofs;
2304			const int src_y = (vv >> 16) + vv_ofs;
2305			uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
2306
2307			ALLEGRO_COLOR src_color;
2308			_AL_INLINE_GET_PIXEL(src_format, src_data, src_color, false);
2309
2310			SHADE_COLORS(src_color, cur_color);
2311
2312			{
2313			   ALLEGRO_COLOR dst_color;
2314			   ALLEGRO_COLOR result;
2315			   _AL_INLINE_GET_PIXEL(dst_format, dst_data, dst_color, false);
2316			   _al_blend_alpha_inline(&src_color, &dst_color, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE, NULL, &result);
2317			   _AL_INLINE_PUT_PIXEL(dst_format, dst_data, result, true);
2318			}
2319
2320			uu += du_dx;
2321			vv += dv_dx;
2322
2323			if (_AL_EXPECT_FAIL(uu < 0))
2324			   uu += w;
2325			else if (_AL_EXPECT_FAIL(uu >= w))
2326			   uu -= w;
2327
2328			if (_AL_EXPECT_FAIL(vv < 0))
2329			   vv += h;
2330			else if (_AL_EXPECT_FAIL(vv >= h))
2331			   vv -= h;
2332
2333			cur_color.r += gs->color_dx.r;
2334			cur_color.g += gs->color_dx.g;
2335			cur_color.b += gs->color_dx.b;
2336			cur_color.a += gs->color_dx.a;
2337
2338		     }
2339		  }
2340	       }
2341	    } else if (dst_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888 && src_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888) {
2342	       uint8_t *lock_data = texture->locked_region.data;
2343	       const int src_pitch = texture->locked_region.pitch;
2344	       const al_fixed du_dx = al_ftofix(s->du_dx);
2345	       const al_fixed dv_dx = al_ftofix(s->dv_dx);
2346
2347	       {
2348		  al_fixed uu = al_ftofix(u);
2349		  al_fixed vv = al_ftofix(v);
2350		  const int uu_ofs = offset_x - texture->lock_x;
2351		  const int vv_ofs = offset_y - texture->lock_y;
2352		  const al_fixed w = al_ftofix(s->w);
2353		  const al_fixed h = al_ftofix(s->h);
2354
2355		  for (; x1 <= x2; x1++) {
2356		     const int src_x = (uu >> 16) + uu_ofs;
2357		     const int src_y = (vv >> 16) + vv_ofs;
2358		     uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
2359
2360		     ALLEGRO_COLOR src_color;
2361		     _AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, src_data, src_color, false);
2362
2363		     SHADE_COLORS(src_color, cur_color);
2364
2365		     {
2366			ALLEGRO_COLOR dst_color;
2367			ALLEGRO_COLOR result;
2368			_AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, dst_color, false);
2369			_al_blend_inline(&src_color, &dst_color, op, src_mode, dst_mode, op_alpha, src_alpha, dst_alpha, &const_color, &result);
2370			_AL_INLINE_PUT_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, result, true);
2371		     }
2372
2373		     uu += du_dx;
2374		     vv += dv_dx;
2375
2376		     if (_AL_EXPECT_FAIL(uu < 0))
2377			uu += w;
2378		     else if (_AL_EXPECT_FAIL(uu >= w))
2379			uu -= w;
2380
2381		     if (_AL_EXPECT_FAIL(vv < 0))
2382			vv += h;
2383		     else if (_AL_EXPECT_FAIL(vv >= h))
2384			vv -= h;
2385
2386		     cur_color.r += gs->color_dx.r;
2387		     cur_color.g += gs->color_dx.g;
2388		     cur_color.b += gs->color_dx.b;
2389		     cur_color.a += gs->color_dx.a;
2390
2391		  }
2392	       }
2393	    } else {
2394	       uint8_t *lock_data = texture->locked_region.data;
2395	       const int src_pitch = texture->locked_region.pitch;
2396	       const al_fixed du_dx = al_ftofix(s->du_dx);
2397	       const al_fixed dv_dx = al_ftofix(s->dv_dx);
2398
2399	       {
2400		  al_fixed uu = al_ftofix(u);
2401		  al_fixed vv = al_ftofix(v);
2402		  const int uu_ofs = offset_x - texture->lock_x;
2403		  const int vv_ofs = offset_y - texture->lock_y;
2404		  const al_fixed w = al_ftofix(s->w);
2405		  const al_fixed h = al_ftofix(s->h);
2406
2407		  for (; x1 <= x2; x1++) {
2408		     const int src_x = (uu >> 16) + uu_ofs;
2409		     const int src_y = (vv >> 16) + vv_ofs;
2410		     uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
2411
2412		     ALLEGRO_COLOR src_color;
2413		     _AL_INLINE_GET_PIXEL(src_format, src_data, src_color, false);
2414
2415		     SHADE_COLORS(src_color, cur_color);
2416
2417		     {
2418			ALLEGRO_COLOR dst_color;
2419			ALLEGRO_COLOR result;
2420			_AL_INLINE_GET_PIXEL(dst_format, dst_data, dst_color, false);
2421			_al_blend_inline(&src_color, &dst_color, op, src_mode, dst_mode, op_alpha, src_alpha, dst_alpha, &const_color, &result);
2422			_AL_INLINE_PUT_PIXEL(dst_format, dst_data, result, true);
2423		     }
2424
2425		     uu += du_dx;
2426		     vv += dv_dx;
2427
2428		     if (_AL_EXPECT_FAIL(uu < 0))
2429			uu += w;
2430		     else if (_AL_EXPECT_FAIL(uu >= w))
2431			uu -= w;
2432
2433		     if (_AL_EXPECT_FAIL(vv < 0))
2434			vv += h;
2435		     else if (_AL_EXPECT_FAIL(vv >= h))
2436			vv -= h;
2437
2438		     cur_color.r += gs->color_dx.r;
2439		     cur_color.g += gs->color_dx.g;
2440		     cur_color.b += gs->color_dx.b;
2441		     cur_color.a += gs->color_dx.a;
2442
2443		  }
2444	       }
2445	    }
2446	 }
2447      }
2448   }
2449}
2450
2451static void shader_texture_grad_any_draw_opaque(uintptr_t state, int x1, int y, int x2)
2452{
2453   state_texture_grad_any_2d *gs = (state_texture_grad_any_2d *) state;
2454   state_texture_solid_any_2d *s = &gs->solid;
2455   ALLEGRO_COLOR cur_color = s->cur_color;
2456
2457   float u = s->u;
2458   float v = s->v;
2459
2460   ALLEGRO_BITMAP *target = s->target;
2461
2462   if (target->parent) {
2463      x1 += target->xofs;
2464      x2 += target->xofs;
2465      y += target->yofs;
2466      target = target->parent;
2467   }
2468
2469   x1 -= target->lock_x;
2470   x2 -= target->lock_x;
2471   y -= target->lock_y;
2472   y--;
2473
2474   if (y < 0 || y >= target->lock_h) {
2475      return;
2476   }
2477
2478   if (x1 < 0) {
2479
2480      u += s->du_dx * -x1;
2481      v += s->dv_dx * -x1;
2482
2483      cur_color.r += gs->color_dx.r * -x1;
2484      cur_color.g += gs->color_dx.g * -x1;
2485      cur_color.b += gs->color_dx.b * -x1;
2486      cur_color.a += gs->color_dx.a * -x1;
2487
2488      x1 = 0;
2489   }
2490
2491   if (x2 > target->lock_w - 1) {
2492      x2 = target->lock_w - 1;
2493   }
2494
2495   {
2496      {
2497	 const int offset_x = s->texture->parent ? s->texture->xofs : 0;
2498	 const int offset_y = s->texture->parent ? s->texture->yofs : 0;
2499	 ALLEGRO_BITMAP *texture = s->texture->parent ? s->texture->parent : s->texture;
2500	 const int src_format = texture->locked_region.format;
2501	 const int src_size = texture->locked_region.pixel_size;
2502
2503	 /* Ensure u in [0, s->w) and v in [0, s->h). */
2504	 while (u < 0)
2505	    u += s->w;
2506	 while (v < 0)
2507	    v += s->h;
2508	 u = fmodf(u, s->w);
2509	 v = fmodf(v, s->h);
2510	 ASSERT(0 <= u);
2511	 ASSERT(u < s->w);
2512	 ASSERT(0 <= v);
2513	 ASSERT(v < s->h);
2514
2515	 {
2516	    const int dst_format = target->locked_region.format;
2517	    uint8_t *dst_data = (uint8_t *) target->lock_data + y * target->locked_region.pitch + x1 * target->locked_region.pixel_size;
2518
2519	    if (dst_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888 && src_format == ALLEGRO_PIXEL_FORMAT_ARGB_8888) {
2520	       uint8_t *lock_data = texture->locked_region.data;
2521	       const int src_pitch = texture->locked_region.pitch;
2522	       const al_fixed du_dx = al_ftofix(s->du_dx);
2523	       const al_fixed dv_dx = al_ftofix(s->dv_dx);
2524
2525	       const float steps = x2 - x1 + 1;
2526	       const float end_u = u + steps * s->du_dx;
2527	       const float end_v = v + steps * s->dv_dx;
2528	       if (end_u >= 0 && end_u < s->w && end_v >= 0 && end_v < s->h) {
2529
2530		  {
2531		     al_fixed uu = al_ftofix(u) + ((offset_x - texture->lock_x) << 16);
2532		     al_fixed vv = al_ftofix(v) + ((offset_y - texture->lock_y) << 16);
2533
2534		     for (; x1 <= x2; x1++) {
2535			const int src_x = (uu >> 16) + 0;
2536			const int src_y = (vv >> 16) + 0;
2537			uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
2538
2539			ALLEGRO_COLOR src_color;
2540			_AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, src_data, src_color, false);
2541
2542			SHADE_COLORS(src_color, cur_color);
2543
2544			_AL_INLINE_PUT_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, src_color, true);
2545
2546			uu += du_dx;
2547			vv += dv_dx;
2548
2549			cur_color.r += gs->color_dx.r;
2550			cur_color.g += gs->color_dx.g;
2551			cur_color.b += gs->color_dx.b;
2552			cur_color.a += gs->color_dx.a;
2553
2554		     }
2555		  }
2556	       } else {
2557		  al_fixed uu = al_ftofix(u);
2558		  al_fixed vv = al_ftofix(v);
2559		  const int uu_ofs = offset_x - texture->lock_x;
2560		  const int vv_ofs = offset_y - texture->lock_y;
2561		  const al_fixed w = al_ftofix(s->w);
2562		  const al_fixed h = al_ftofix(s->h);
2563
2564		  for (; x1 <= x2; x1++) {
2565		     const int src_x = (uu >> 16) + uu_ofs;
2566		     const int src_y = (vv >> 16) + vv_ofs;
2567		     uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
2568
2569		     ALLEGRO_COLOR src_color;
2570		     _AL_INLINE_GET_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, src_data, src_color, false);
2571
2572		     SHADE_COLORS(src_color, cur_color);
2573
2574		     _AL_INLINE_PUT_PIXEL(ALLEGRO_PIXEL_FORMAT_ARGB_8888, dst_data, src_color, true);
2575
2576		     uu += du_dx;
2577		     vv += dv_dx;
2578
2579		     if (_AL_EXPECT_FAIL(uu < 0))
2580			uu += w;
2581		     else if (_AL_EXPECT_FAIL(uu >= w))
2582			uu -= w;
2583
2584		     if (_AL_EXPECT_FAIL(vv < 0))
2585			vv += h;
2586		     else if (_AL_EXPECT_FAIL(vv >= h))
2587			vv -= h;
2588
2589		     cur_color.r += gs->color_dx.r;
2590		     cur_color.g += gs->color_dx.g;
2591		     cur_color.b += gs->color_dx.b;
2592		     cur_color.a += gs->color_dx.a;
2593
2594		  }
2595	       }
2596	    } else {
2597	       uint8_t *lock_data = texture->locked_region.data;
2598	       const int src_pitch = texture->locked_region.pitch;
2599	       const al_fixed du_dx = al_ftofix(s->du_dx);
2600	       const al_fixed dv_dx = al_ftofix(s->dv_dx);
2601
2602	       const float steps = x2 - x1 + 1;
2603	       const float end_u = u + steps * s->du_dx;
2604	       const float end_v = v + steps * s->dv_dx;
2605	       if (end_u >= 0 && end_u < s->w && end_v >= 0 && end_v < s->h) {
2606
2607		  {
2608		     al_fixed uu = al_ftofix(u) + ((offset_x - texture->lock_x) << 16);
2609		     al_fixed vv = al_ftofix(v) + ((offset_y - texture->lock_y) << 16);
2610
2611		     for (; x1 <= x2; x1++) {
2612			const int src_x = (uu >> 16) + 0;
2613			const int src_y = (vv >> 16) + 0;
2614			uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
2615
2616			ALLEGRO_COLOR src_color;
2617			_AL_INLINE_GET_PIXEL(src_format, src_data, src_color, false);
2618
2619			SHADE_COLORS(src_color, cur_color);
2620
2621			_AL_INLINE_PUT_PIXEL(dst_format, dst_data, src_color, true);
2622
2623			uu += du_dx;
2624			vv += dv_dx;
2625
2626			cur_color.r += gs->color_dx.r;
2627			cur_color.g += gs->color_dx.g;
2628			cur_color.b += gs->color_dx.b;
2629			cur_color.a += gs->color_dx.a;
2630
2631		     }
2632		  }
2633	       } else {
2634		  al_fixed uu = al_ftofix(u);
2635		  al_fixed vv = al_ftofix(v);
2636		  const int uu_ofs = offset_x - texture->lock_x;
2637		  const int vv_ofs = offset_y - texture->lock_y;
2638		  const al_fixed w = al_ftofix(s->w);
2639		  const al_fixed h = al_ftofix(s->h);
2640
2641		  for (; x1 <= x2; x1++) {
2642		     const int src_x = (uu >> 16) + uu_ofs;
2643		     const int src_y = (vv >> 16) + vv_ofs;
2644		     uint8_t *src_data = lock_data + src_y * src_pitch + src_x * src_size;
2645
2646		     ALLEGRO_COLOR src_color;
2647		     _AL_INLINE_GET_PIXEL(src_format, src_data, src_color, false);
2648
2649		     SHADE_COLORS(src_color, cur_color);
2650
2651		     _AL_INLINE_PUT_PIXEL(dst_format, dst_data, src_color, true);
2652
2653		     uu += du_dx;
2654		     vv += dv_dx;
2655
2656		     if (_AL_EXPECT_FAIL(uu < 0))
2657			uu += w;
2658		     else if (_AL_EXPECT_FAIL(uu >= w))
2659			uu -= w;
2660
2661		     if (_AL_EXPECT_FAIL(vv < 0))
2662			vv += h;
2663		     else if (_AL_EXPECT_FAIL(vv >= h))
2664			vv -= h;
2665
2666		     cur_color.r += gs->color_dx.r;
2667		     cur_color.g += gs->color_dx.g;
2668		     cur_color.b += gs->color_dx.b;
2669		     cur_color.a += gs->color_dx.a;
2670
2671		  }
2672	       }
2673	    }
2674	 }
2675      }
2676   }
2677}
2678