Previous 199869 Revisions Next

r28728 Wednesday 19th March, 2014 at 17:18:56 UTC by Oliver Stöneberg
renamed rendersw.c to rendersw.inc
[src/emu]emu.mak rendersw.c rendersw.inc* video.c
[src/mess/drivers]cxhumax.c
[src/osd/sdl]drawsdl.c sdl.mak
[src/osd/windows]drawdd.c drawgdi.c windows.mak

trunk/src/osd/windows/drawdd.c
r28727r28728
1818#include "render.h"
1919#include "rendutil.h"
2020#include "options.h"
21#include "rendersw.c"
21#include "rendersw.inc"
2222
2323// MAMEOS headers
2424#include "winmain.h"
trunk/src/osd/windows/windows.mak
r28727r28728
349349CCOMFLAGS += -DDIRECT3D_VERSION=0x0900
350350
351351# extra dependencies
352$(WINOBJ)/drawdd.o :    $(SRC)/emu/rendersw.c
353$(WINOBJ)/drawgdi.o :   $(SRC)/emu/rendersw.c
352$(WINOBJ)/drawdd.o :    $(SRC)/emu/rendersw.inc
353$(WINOBJ)/drawgdi.o :   $(SRC)/emu/rendersw.inc
354354$(WINOBJ)/winmidi.o:    $(SRC)/osd/portmedia/pmmidi.c
355355
356356ifndef USE_QTDEBUG
trunk/src/osd/windows/drawgdi.c
r28727r28728
1212
1313// MAME headers
1414#include "emu.h"
15#include "rendersw.c"
15#include "rendersw.inc"
1616
1717// MAMEOS headers
1818#include "window.h"
trunk/src/osd/sdl/drawsdl.c
r28727r28728
1616// MAME headers
1717#include "emu.h"
1818#include "ui/ui.h"
19#include "rendersw.c"
19#include "rendersw.inc"
2020
2121// standard SDL headers
2222#include "sdlinc.h"
trunk/src/osd/sdl/sdl.mak
r28727r28728
771771endif # solaris
772772
773773# drawSDL depends on the core software renderer, so make sure it exists
774$(SDLOBJ)/drawsdl.o : $(SRC)/emu/rendersw.c $(SDLSRC)/drawogl.c
774$(SDLOBJ)/drawsdl.o : $(SRC)/emu/rendersw.inc $(SDLSRC)/drawogl.c
775775$(SDLOBJ)/drawogl.o : $(SDLSRC)/texcopy.c $(SDLSRC)/texsrc.h
776776
777777# draw13 depends on blit13.h
trunk/src/emu/rendersw.c
r28727r28728
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles
3/***************************************************************************
4
5    rendersw.c
6
7    Software-only rasterization system.
8
9***************************************************************************/
10
11
12#include "emucore.h"
13#include "eminline.h"
14#include "video/rgbutil.h"
15#include "render.h"
16
17
18template<typename _PixelType, int _SrcShiftR, int _SrcShiftG, int _SrcShiftB, int _DstShiftR, int _DstShiftG, int _DstShiftB, bool _NoDestRead = false, bool _BilinearFilter = false>
19class software_renderer
20{
21private:
22   // internal structs
23   struct quad_setup_data
24   {
25      INT32           dudx, dvdx, dudy, dvdy;
26      INT32           startu, startv;
27      INT32           startx, starty;
28      INT32           endx, endy;
29   };
30
31   // internal helpers
32   static inline bool is_opaque(float alpha) { return (alpha >= (_NoDestRead ? 0.5f : 1.0f)); }
33   static inline bool is_transparent(float alpha) { return (alpha < (_NoDestRead ? 0.5f : 0.0001f)); }
34   static inline rgb_t apply_intensity(int intensity, rgb_t color) { return color.scale8(intensity); }
35   static inline float round_nearest(float f) { return floor(f + 0.5f); }
36
37   // destination pixels are written based on the values of the template parameters
38   static inline _PixelType dest_assemble_rgb(UINT32 r, UINT32 g, UINT32 b) { return (r << _DstShiftR) | (g << _DstShiftG) | (b << _DstShiftB); }
39   static inline _PixelType dest_rgb_to_pixel(UINT32 r, UINT32 g, UINT32 b) { return dest_assemble_rgb(r >> _SrcShiftR, g >> _SrcShiftG, b >> _SrcShiftB); }
40
41   // source 32-bit pixels are in MAME standardized format
42   static inline UINT32 source32_r(rgb_t pixel) { return (pixel >> (16 + _SrcShiftR)) & (0xff >> _SrcShiftR); }
43   static inline UINT32 source32_g(rgb_t pixel) { return (pixel >> ( 8 + _SrcShiftG)) & (0xff >> _SrcShiftG); }
44   static inline UINT32 source32_b(rgb_t pixel) { return (pixel >> ( 0 + _SrcShiftB)) & (0xff >> _SrcShiftB); }
45
46   // destination pixel masks are based on the template parameters as well
47   static inline UINT32 dest_r(_PixelType pixel) { return (pixel >> _DstShiftR) & (0xff >> _SrcShiftR); }
48   static inline UINT32 dest_g(_PixelType pixel) { return (pixel >> _DstShiftG) & (0xff >> _SrcShiftG); }
49   static inline UINT32 dest_b(_PixelType pixel) { return (pixel >> _DstShiftB) & (0xff >> _SrcShiftB); }
50
51   // generic conversion with special optimization for destinations in the standard format
52   static inline _PixelType source32_to_dest(rgb_t pixel)
53   {
54      if (_SrcShiftR == 0 && _SrcShiftG == 0 && _SrcShiftB == 0 && _DstShiftR == 16 && _DstShiftG == 8 && _DstShiftB == 0)
55         return pixel;
56      else
57         return dest_assemble_rgb(source32_r(pixel), source32_g(pixel), source32_b(pixel));
58   }
59
60
61   //-------------------------------------------------
62   //  ycc_to_rgb - convert YCC to RGB; the YCC pixel
63   //  contains Y in the LSB, Cb << 8, and Cr << 16
64   //  This actually a YCbCr conversion,
65   //  details my be found in chapter 6.4 ff of
66   //  http://softwarecommunity.intel.com/isn/downloads/softwareproducts/pdfs/346495.pdf
67   //  The document also contains the constants below as floats.
68   //-------------------------------------------------
69
70   static inline UINT32 clamp16_shift8(UINT32 x)
71   {
72      return ((INT32(x) < 0) ? 0 : (x > 65535 ? 255: x >> 8));
73   }
74
75   static inline UINT32 ycc_to_rgb(UINT32 ycc)
76   {
77      // original equations:
78      //
79      //  C = Y - 16
80      //  D = Cb - 128
81      //  E = Cr - 128
82      //
83      //  R = clip(( 298 * C           + 409 * E + 128) >> 8)
84      //  G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8)
85      //  B = clip(( 298 * C + 516 * D           + 128) >> 8)
86      //
87      //  R = clip(( 298 * (Y - 16)                    + 409 * (Cr - 128) + 128) >> 8)
88      //  G = clip(( 298 * (Y - 16) - 100 * (Cb - 128) - 208 * (Cr - 128) + 128) >> 8)
89      //  B = clip(( 298 * (Y - 16) + 516 * (Cb - 128)                    + 128) >> 8)
90      //
91      //  R = clip(( 298 * Y - 298 * 16                        + 409 * Cr - 409 * 128 + 128) >> 8)
92      //  G = clip(( 298 * Y - 298 * 16 - 100 * Cb + 100 * 128 - 208 * Cr + 208 * 128 + 128) >> 8)
93      //  B = clip(( 298 * Y - 298 * 16 + 516 * Cb - 516 * 128                        + 128) >> 8)
94      //
95      //  R = clip(( 298 * Y - 298 * 16                        + 409 * Cr - 409 * 128 + 128) >> 8)
96      //  G = clip(( 298 * Y - 298 * 16 - 100 * Cb + 100 * 128 - 208 * Cr + 208 * 128 + 128) >> 8)
97      //  B = clip(( 298 * Y - 298 * 16 + 516 * Cb - 516 * 128                        + 128) >> 8)
98      //
99      //  Now combine constants:
100      //
101      //  R = clip(( 298 * Y            + 409 * Cr - 56992) >> 8)
102      //  G = clip(( 298 * Y - 100 * Cb - 208 * Cr + 34784) >> 8)
103      //  B = clip(( 298 * Y + 516 * Cb            - 70688) >> 8)
104      //
105      //  Define common = 298 * y - 56992. This will save one addition
106      //
107      //  R = clip(( common            + 409 * Cr -     0) >> 8)
108      //  G = clip(( common - 100 * Cb - 208 * Cr + 91776) >> 8)
109      //  B = clip(( common + 516 * Cb            - 13696) >> 8)
110      //
111
112      UINT8 y = ycc;
113      UINT8 cb = ycc >> 8;
114      UINT8 cr = ycc >> 16;
115
116      UINT32 common = 298 * y - 56992;
117      UINT32 r = (common +            409 * cr);
118      UINT32 g = (common - 100 * cb - 208 * cr + 91776);
119      UINT32 b = (common + 516 * cb - 13696);
120
121      // Now clamp and shift back
122      return rgb_t(clamp16_shift8(r), clamp16_shift8(g), clamp16_shift8(b));
123   }
124
125
126   //-------------------------------------------------
127   //  get_texel_palette16 - return a texel from a
128   //  palettized 16bpp source
129   //-------------------------------------------------
130
131   static inline UINT32 get_texel_palette16(const render_texinfo &texture, INT32 curu, INT32 curv)
132   {
133      if (_BilinearFilter)
134      {
135         INT32 u0 = curu >> 16;
136         INT32 u1 = 1;
137         if (u0 < 0) u0 = u1 = 0;
138         else if (u0 + 1 >= texture.width) u0 = texture.width - 1, u1 = 0;
139         INT32 v0 = curv >> 16;
140         INT32 v1 = texture.rowpixels;
141         if (v0 < 0) v0 = v1 = 0;
142         else if (v0 + 1 >= texture.height) v0 = texture.height - 1, v1 = 0;
143
144         const UINT16 *texbase = reinterpret_cast<const UINT16 *>(texture.base);
145         texbase += v0 * texture.rowpixels + u0;
146
147         rgb_t pix00 = texture.palette[texbase[0]];
148         rgb_t pix01 = texture.palette[texbase[u1]];
149         rgb_t pix10 = texture.palette[texbase[v1]];
150         rgb_t pix11 = texture.palette[texbase[u1 + v1]];
151         return rgb_bilinear_filter(pix00, pix01, pix10, pix11, curu >> 8, curv >> 8);
152      }
153      else
154      {
155         const UINT16 *texbase = reinterpret_cast<const UINT16 *>(texture.base) + (curv >> 16) * texture.rowpixels + (curu >> 16);
156         return texture.palette[texbase[0]];
157      }
158   }
159
160
161   //-------------------------------------------------
162   //  get_texel_palette16a - return a texel from a
163   //  palettized 16bpp source with alpha
164   //-------------------------------------------------
165
166   static inline UINT32 get_texel_palette16a(const render_texinfo &texture, INT32 curu, INT32 curv)
167   {
168      if (_BilinearFilter)
169      {
170         INT32 u0 = curu >> 16;
171         INT32 u1 = 1;
172         if (u0 < 0) u0 = u1 = 0;
173         else if (u0 + 1 >= texture.width) u0 = texture.width - 1, u1 = 0;
174         INT32 v0 = curv >> 16;
175         INT32 v1 = texture.rowpixels;
176         if (v0 < 0) v0 = v1 = 0;
177         else if (v0 + 1 >= texture.height) v0 = texture.height - 1, v1 = 0;
178
179         const UINT16 *texbase = reinterpret_cast<const UINT16 *>(texture.base);
180         texbase += v0 * texture.rowpixels + u0;
181
182         rgb_t pix00 = texture.palette[texbase[0]];
183         rgb_t pix01 = texture.palette[texbase[u1]];
184         rgb_t pix10 = texture.palette[texbase[v1]];
185         rgb_t pix11 = texture.palette[texbase[u1 + v1]];
186         return rgba_bilinear_filter(pix00, pix01, pix10, pix11, curu >> 8, curv >> 8);
187      }
188      else
189      {
190         const UINT16 *texbase = reinterpret_cast<const UINT16 *>(texture.base) + (curv >> 16) * texture.rowpixels + (curu >> 16);
191         return texture.palette[texbase[0]];
192      }
193   }
194
195
196   //-------------------------------------------------
197   //  get_texel_yuy16 - return a texel from a 16bpp
198   //  YCbCr source (pixel is returned as Cr-Cb-Y)
199   //-------------------------------------------------
200
201   static inline UINT32 get_texel_yuy16(const render_texinfo &texture, INT32 curu, INT32 curv)
202   {
203      if (_BilinearFilter)
204      {
205         INT32 u0 = curu >> 16;
206         INT32 u1 = 1;
207         if (u0 < 0) u0 = u1 = 0;
208         else if (u0 + 1 >= texture.width) u0 = texture.width - 1, u1 = 0;
209         INT32 v0 = curv >> 16;
210         INT32 v1 = texture.rowpixels;
211         if (v0 < 0) v0 = v1 = 0;
212         else if (v0 + 1 >= texture.height) v0 = texture.height - 1, v1 = 0;
213
214         const UINT16 *texbase = reinterpret_cast<const UINT16 *>(texture.base);
215         texbase += v0 * texture.rowpixels + (u0 & ~1);
216
217         rgb_t pix00, pix01, pix10, pix11;
218         if ((curu & 0x10000) == 0)
219         {
220            rgb_t cbcr = ((texbase[0] & 0xff) << 8) | ((texbase[1] & 0xff) << 16);
221            pix00 = (texbase[0] >> 8) | cbcr;
222            pix01 = (texbase[u1] >> 8) | cbcr;
223            cbcr = ((texbase[v1 + 0] & 0xff) << 8) | ((texbase[v1 + 1] & 0xff) << 16);
224            pix10 = (texbase[v1 + 0] >> 8) | cbcr;
225            pix11 = (texbase[v1 + u1] >> 8) | cbcr;
226         }
227         else
228         {
229            rgb_t cbcr = ((texbase[0] & 0xff) << 8) | ((texbase[1] & 0xff) << 16);
230            pix00 = (texbase[1] >> 8) | cbcr;
231            if (u1 != 0)
232            {
233               cbcr = ((texbase[2] & 0xff) << 8) | ((texbase[3] & 0xff) << 16);
234               pix01 = (texbase[2] >> 8) | cbcr;
235            }
236            else
237               pix01 = pix00;
238            cbcr = ((texbase[v1 + 0] & 0xff) << 8) | ((texbase[v1 + 1] & 0xff) << 16);
239            pix10 = (texbase[v1 + 1] >> 8) | cbcr;
240            if (u1 != 0)
241            {
242               cbcr = ((texbase[v1 + 2] & 0xff) << 8) | ((texbase[v1 + 3] & 0xff) << 16);
243               pix11 = (texbase[v1 + 2] >> 8) | cbcr;
244            }
245            else
246               pix11 = pix10;
247         }
248         return rgb_bilinear_filter(pix00, pix01, pix10, pix11, curu >> 8, curv >> 8);
249      }
250      else
251      {
252         const UINT16 *texbase = reinterpret_cast<const UINT16 *>(texture.base) + (curv >> 16) * texture.rowpixels + (curu >> 17) * 2;
253         return (texbase[(curu >> 16) & 1] >> 8) | ((texbase[0] & 0xff) << 8) | ((texbase[1] & 0xff) << 16);
254      }
255   }
256
257
258   //-------------------------------------------------
259   //  get_texel_rgb32 - return a texel from a 32bpp
260   //  RGB source
261   //-------------------------------------------------
262
263   static inline UINT32 get_texel_rgb32(const render_texinfo &texture, INT32 curu, INT32 curv)
264   {
265      if (_BilinearFilter)
266      {
267         INT32 u0 = curu >> 16;
268         INT32 u1 = 1;
269         if (u0 < 0) u0 = u1 = 0;
270         else if (u0 + 1 >= texture.width) u0 = texture.width - 1, u1 = 0;
271         INT32 v0 = curv >> 16;
272         INT32 v1 = texture.rowpixels;
273         if (v0 < 0) v0 = v1 = 0;
274         else if (v0 + 1 >= texture.height) v0 = texture.height - 1, v1 = 0;
275
276         const UINT32 *texbase = reinterpret_cast<const UINT32 *>(texture.base);
277         texbase += v0 * texture.rowpixels + u0;
278
279         rgb_t pix00 = texbase[0];
280         rgb_t pix01 = texbase[u1];
281         rgb_t pix10 = texbase[v1];
282         rgb_t pix11 = texbase[u1 + v1];
283         return rgb_bilinear_filter(pix00, pix01, pix10, pix11, curu >> 8, curv >> 8);
284      }
285      else
286      {
287         const UINT32 *texbase = reinterpret_cast<const UINT32 *>(texture.base) + (curv >> 16) * texture.rowpixels + (curu >> 16);
288         return texbase[0];
289      }
290   }
291
292
293   //-------------------------------------------------
294   //  get_texel_argb32 - return a texel from a 32bpp
295   //  ARGB source
296   //-------------------------------------------------
297
298   static inline UINT32 get_texel_argb32(const render_texinfo &texture, INT32 curu, INT32 curv)
299   {
300      if (_BilinearFilter)
301      {
302         INT32 u0 = curu >> 16;
303         INT32 u1 = 1;
304         if (u0 < 0) u0 = u1 = 0;
305         else if (u0 + 1 >= texture.width) u0 = texture.width - 1, u1 = 0;
306         INT32 v0 = curv >> 16;
307         INT32 v1 = texture.rowpixels;
308         if (v0 < 0) v0 = v1 = 0;
309         else if (v0 + 1 >= texture.height) v0 = texture.height - 1, v1 = 0;
310
311         const UINT32 *texbase = reinterpret_cast<const UINT32 *>(texture.base);
312         texbase += v0 * texture.rowpixels + u0;
313
314         rgb_t pix00 = texbase[0];
315         rgb_t pix01 = texbase[u1];
316         rgb_t pix10 = texbase[v1];
317         rgb_t pix11 = texbase[u1 + v1];
318         return rgba_bilinear_filter(pix00, pix01, pix10, pix11, curu >> 8, curv >> 8);
319      }
320      else
321      {
322         const UINT32 *texbase = reinterpret_cast<const UINT32 *>(texture.base) + (curv >> 16) * texture.rowpixels + (curu >> 16);
323         return texbase[0];
324      }
325   }
326
327
328   //-------------------------------------------------
329   //  draw_aa_pixel - draw an antialiased pixel
330   //-------------------------------------------------
331
332   static inline void draw_aa_pixel(_PixelType *dstdata, UINT32 pitch, int x, int y, rgb_t col)
333   {
334      _PixelType *dest = dstdata + y * pitch + x;
335      UINT32 dpix = _NoDestRead ? 0 : *dest;
336      UINT32 dr = source32_r(col) + dest_r(dpix);
337      UINT32 dg = source32_g(col) + dest_g(dpix);
338      UINT32 db = source32_b(col) + dest_b(dpix);
339      dr = (dr | -(dr >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
340      dg = (dg | -(dg >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
341      db = (db | -(db >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
342      *dest = dest_assemble_rgb(dr, dg, db);
343   }
344
345
346   //-------------------------------------------------
347   //  draw_line - draw a line or point
348   //-------------------------------------------------
349
350   static void draw_line(const render_primitive &prim, _PixelType *dstdata, INT32 width, INT32 height, UINT32 pitch)
351   {
352      // internal tables
353      static UINT32 s_cosine_table[2049];
354
355      // compute the start/end coordinates
356      int x1 = int(prim.bounds.x0 * 65536.0f);
357      int y1 = int(prim.bounds.y0 * 65536.0f);
358      int x2 = int(prim.bounds.x1 * 65536.0f);
359      int y2 = int(prim.bounds.y1 * 65536.0f);
360
361      // handle color and intensity
362      UINT32 col = rgb_t(int(255.0f * prim.color.r * prim.color.a), int(255.0f * prim.color.g * prim.color.a), int(255.0f * prim.color.b * prim.color.a));
363
364      if (PRIMFLAG_GET_ANTIALIAS(prim.flags))
365      {
366         // build up the cosine table if we haven't yet
367         if (s_cosine_table[0] == 0)
368            for (int entry = 0; entry <= 2048; entry++)
369               s_cosine_table[entry] = int(double(1.0 / cos(atan(double(entry) / 2048.0))) * 0x10000000 + 0.5);
370
371         int beam = prim.width * 65536.0f;
372         if (beam < 0x00010000)
373            beam = 0x00010000;
374
375         // draw an anti-aliased line
376         int dx = abs(x1 - x2);
377         int dy = abs(y1 - y2);
378
379         if (dx >= dy)
380         {
381            int sx = ((x1 <= x2) ? 1 : -1);
382            int sy = (dy == 0) ? 0 : div_32x32_shift(y2 - y1, dx, 16);
383            if (sy < 0)
384               dy--;
385            x1 >>= 16;
386            int xx = x2 >> 16;
387            int bwidth = mul_32x32_hi(beam << 4, s_cosine_table[abs(sy) >> 5]);
388            y1 -= bwidth >> 1; // start back half the diameter
389            for (;;)
390            {
391               if (x1 >= 0 && x1 < width)
392               {
393                  dx = bwidth;    // init diameter of beam
394                  dy = y1 >> 16;
395                  if (dy >= 0 && dy < height)
396                     draw_aa_pixel(dstdata, pitch, x1, dy, apply_intensity(0xff & (~y1 >> 8), col));
397                  dy++;
398                  dx -= 0x10000 - (0xffff & y1); // take off amount plotted
399                  UINT8 a1 = (dx >> 8) & 0xff;   // calc remainder pixel
400                  dx >>= 16;                   // adjust to pixel (solid) count
401                  while (dx--)                 // plot rest of pixels
402                  {
403                     if (dy >= 0 && dy < height)
404                        draw_aa_pixel(dstdata, pitch, x1, dy, col);
405                     dy++;
406                  }
407                  if (dy >= 0 && dy < height)
408                     draw_aa_pixel(dstdata, pitch, x1, dy, apply_intensity(a1,col));
409               }
410               if (x1 == xx) break;
411               x1 += sx;
412               y1 += sy;
413            }
414         }
415         else
416         {
417            int sy = ((y1 <= y2) ? 1: -1);
418            int sx = (dx == 0) ? 0 : div_32x32_shift(x2 - x1, dy, 16);
419            if (sx < 0)
420               dx--;
421            y1 >>= 16;
422            int yy = y2 >> 16;
423            int bwidth = mul_32x32_hi(beam << 4,s_cosine_table[abs(sx) >> 5]);
424            x1 -= bwidth >> 1; // start back half the width
425            for (;;)
426            {
427               if (y1 >= 0 && y1 < height)
428               {
429                  dy = bwidth;    // calc diameter of beam
430                  dx = x1 >> 16;
431                  if (dx >= 0 && dx < width)
432                     draw_aa_pixel(dstdata, pitch, dx, y1, apply_intensity(0xff & (~x1 >> 8), col));
433                  dx++;
434                  dy -= 0x10000 - (0xffff & x1); // take off amount plotted
435                  UINT8 a1 = (dy >> 8) & 0xff;   // remainder pixel
436                  dy >>= 16;                   // adjust to pixel (solid) count
437                  while (dy--)                 // plot rest of pixels
438                  {
439                     if (dx >= 0 && dx < width)
440                        draw_aa_pixel(dstdata, pitch, dx, y1, col);
441                     dx++;
442                  }
443                  if (dx >= 0 && dx < width)
444                     draw_aa_pixel(dstdata, pitch, dx, y1, apply_intensity(a1, col));
445               }
446               if (y1 == yy) break;
447               y1 += sy;
448               x1 += sx;
449            }
450         }
451      }
452      else // use good old Bresenham for non-antialiasing 980317 BW
453      {
454         x1 = (x1 + 0x8000) >> 16;
455         y1 = (y1 + 0x8000) >> 16;
456         x2 = (x2 + 0x8000) >> 16;
457         y2 = (y2 + 0x8000) >> 16;
458
459         int dx = abs(x1 - x2);
460         int dy = abs(y1 - y2);
461         int sx = (x1 <= x2) ? 1 : -1;
462         int sy = (y1 <= y2) ? 1 : -1;
463         int cx = dx / 2;
464         int cy = dy / 2;
465
466         if (dx >= dy)
467         {
468            for (;;)
469            {
470               if (x1 >= 0 && x1 < width && y1 >= 0 && y1 < height)
471                  draw_aa_pixel(dstdata, pitch, x1, y1, col);
472               if (x1 == x2) break;
473               x1 += sx;
474               cx -= dy;
475               if (cx < 0)
476               {
477                  y1 += sy;
478                  cx += dx;
479               }
480            }
481         }
482         else
483         {
484            for (;;)
485            {
486               if (x1 >= 0 && x1 < width && y1 >= 0 && y1 < height)
487                  draw_aa_pixel(dstdata, pitch, x1, y1, col);
488               if (y1 == y2) break;
489               y1 += sy;
490               cy -= dx;
491               if (cy < 0)
492               {
493                  x1 += sx;
494                  cy += dy;
495               }
496            }
497         }
498      }
499   }
500
501
502
503   //**************************************************************************
504   //  RECT RASTERIZERS
505   //**************************************************************************
506
507   //-------------------------------------------------
508   //  draw_rect - draw a solid rectangle
509   //-------------------------------------------------
510
511   static void draw_rect(const render_primitive &prim, _PixelType *dstdata, INT32 width, INT32 height, UINT32 pitch)
512   {
513      render_bounds fpos = prim.bounds;
514      assert(fpos.x0 <= fpos.x1);
515      assert(fpos.y0 <= fpos.y1);
516
517      // clamp to integers
518      INT32 startx = round_nearest(fpos.x0);
519      INT32 starty = round_nearest(fpos.y0);
520      INT32 endx = round_nearest(fpos.x1);
521      INT32 endy = round_nearest(fpos.y1);
522
523      // ensure we fit
524      if (startx < 0) startx = 0;
525      if (startx >= width) startx = width;
526      if (endx < 0) endx = 0;
527      if (endx >= width) endx = width;
528      if (starty < 0) starty = 0;
529      if (starty >= height) starty = height;
530      if (endy < 0) endy = 0;
531      if (endy >= height) endy = height;
532
533      // bail if nothing left
534      if (fpos.x0 > fpos.x1 || fpos.y0 > fpos.y1)
535         return;
536
537      // only support alpha and "none" blendmodes
538      assert(PRIMFLAG_GET_BLENDMODE(prim.flags) == BLENDMODE_NONE ||
539            PRIMFLAG_GET_BLENDMODE(prim.flags) == BLENDMODE_ALPHA);
540
541      // fast case: no alpha
542      if (PRIMFLAG_GET_BLENDMODE(prim.flags) == BLENDMODE_NONE || is_opaque(prim.color.a))
543      {
544         UINT32 r = UINT32(256.0f * prim.color.r);
545         UINT32 g = UINT32(256.0f * prim.color.g);
546         UINT32 b = UINT32(256.0f * prim.color.b);
547         UINT32 pix;
548
549         // clamp R,G,B to 0-256 range
550         if (r > 0xff) { if (INT32(r) < 0) r = 0; else r = 0xff; }
551         if (g > 0xff) { if (INT32(g) < 0) g = 0; else g = 0xff; }
552         if (b > 0xff) { if (INT32(b) < 0) b = 0; else b = 0xff; }
553         pix = dest_rgb_to_pixel(r, g, b);
554
555         // loop over rows
556         for (INT32 y = starty; y < endy; y++)
557         {
558            _PixelType *dest = dstdata + y * pitch + startx;
559
560            // loop over cols
561            for (INT32 x = startx; x < endx; x++)
562               *dest++ = pix;
563         }
564      }
565
566      // alpha and/or coloring case
567      else if (!is_transparent(prim.color.a))
568      {
569         UINT32 rmask = dest_rgb_to_pixel(0xff,0x00,0x00);
570         UINT32 gmask = dest_rgb_to_pixel(0x00,0xff,0x00);
571         UINT32 bmask = dest_rgb_to_pixel(0x00,0x00,0xff);
572         UINT32 r = UINT32(256.0f * prim.color.r * prim.color.a);
573         UINT32 g = UINT32(256.0f * prim.color.g * prim.color.a);
574         UINT32 b = UINT32(256.0f * prim.color.b * prim.color.a);
575         UINT32 inva = UINT32(256.0f * (1.0f - prim.color.a));
576
577         // clamp R,G,B and inverse A to 0-256 range
578         if (r > 0xff) { if (INT32(r) < 0) r = 0; else r = 0xff; }
579         if (g > 0xff) { if (INT32(g) < 0) g = 0; else g = 0xff; }
580         if (b > 0xff) { if (INT32(b) < 0) b = 0; else b = 0xff; }
581         if (inva > 0x100) { if (INT32(inva) < 0) inva = 0; else inva = 0x100; }
582
583         // pre-shift the RGBA pieces
584         r = dest_rgb_to_pixel(r, 0, 0) << 8;
585         g = dest_rgb_to_pixel(0, g, 0) << 8;
586         b = dest_rgb_to_pixel(0, 0, b) << 8;
587
588         // loop over rows
589         for (INT32 y = starty; y < endy; y++)
590         {
591            _PixelType *dest = dstdata + y * pitch + startx;
592
593            // loop over cols
594            for (INT32 x = startx; x < endx; x++)
595            {
596               UINT32 dpix = _NoDestRead ? 0 : *dest;
597               UINT32 dr = (r + ((dpix & rmask) * inva)) & (rmask << 8);
598               UINT32 dg = (g + ((dpix & gmask) * inva)) & (gmask << 8);
599               UINT32 db = (b + ((dpix & bmask) * inva)) & (bmask << 8);
600               *dest++ = (dr | dg | db) >> 8;
601            }
602         }
603      }
604   }
605
606
607   //**************************************************************************
608   //  16-BIT PALETTE RASTERIZERS
609   //**************************************************************************
610
611   //-------------------------------------------------
612   //  draw_quad_palette16_none - perform
613   //  rasterization of a 16bpp palettized texture
614   //-------------------------------------------------
615
616   static void draw_quad_palette16_none(const render_primitive &prim, _PixelType *dstdata, UINT32 pitch, quad_setup_data &setup)
617   {
618      INT32 dudx = setup.dudx;
619      INT32 dvdx = setup.dvdx;
620      INT32 endx = setup.endx;
621
622      // ensure all parameters are valid
623      assert(prim.texture.palette != NULL);
624
625      // fast case: no coloring, no alpha
626      if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a))
627      {
628         // loop over rows
629         for (INT32 y = setup.starty; y < setup.endy; y++)
630         {
631            _PixelType *dest = dstdata + y * pitch + setup.startx;
632            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
633            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
634
635            // loop over cols
636            for (INT32 x = setup.startx; x < endx; x++)
637            {
638               UINT32 pix = get_texel_palette16(prim.texture, curu, curv);
639               *dest++ = source32_to_dest(pix);
640               curu += dudx;
641               curv += dvdx;
642            }
643         }
644      }
645
646      // coloring-only case
647      else if (is_opaque(prim.color.a))
648      {
649         UINT32 sr = UINT32(256.0f * prim.color.r);
650         UINT32 sg = UINT32(256.0f * prim.color.g);
651         UINT32 sb = UINT32(256.0f * prim.color.b);
652
653         // clamp R,G,B to 0-256 range
654         if (sr > 0x100) { if (INT32(sr) < 0) sr = 0; else sr = 0x100; }
655         if (sg > 0x100) { if (INT32(sg) < 0) sg = 0; else sg = 0x100; }
656         if (sb > 0x100) { if (INT32(sb) < 0) sb = 0; else sb = 0x100; }
657
658         // loop over rows
659         for (INT32 y = setup.starty; y < setup.endy; y++)
660         {
661            _PixelType *dest = dstdata + y * pitch + setup.startx;
662            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
663            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
664
665            // loop over cols
666            for (INT32 x = setup.startx; x < endx; x++)
667            {
668               UINT32 pix = get_texel_palette16(prim.texture, curu, curv);
669               UINT32 r = (source32_r(pix) * sr) >> 8;
670               UINT32 g = (source32_g(pix) * sg) >> 8;
671               UINT32 b = (source32_b(pix) * sb) >> 8;
672
673               *dest++ = dest_assemble_rgb(r, g, b);
674               curu += dudx;
675               curv += dvdx;
676            }
677         }
678      }
679
680      // alpha and/or coloring case
681      else if (!is_transparent(prim.color.a))
682      {
683         UINT32 sr = UINT32(256.0f * prim.color.r * prim.color.a);
684         UINT32 sg = UINT32(256.0f * prim.color.g * prim.color.a);
685         UINT32 sb = UINT32(256.0f * prim.color.b * prim.color.a);
686         UINT32 invsa = UINT32(256.0f * (1.0f - prim.color.a));
687
688         // clamp R,G,B and inverse A to 0-256 range
689         if (sr > 0x100) { if (INT32(sr) < 0) sr = 0; else sr = 0x100; }
690         if (sg > 0x100) { if (INT32(sg) < 0) sg = 0; else sg = 0x100; }
691         if (sb > 0x100) { if (INT32(sb) < 0) sb = 0; else sb = 0x100; }
692         if (invsa > 0x100) { if (INT32(invsa) < 0) invsa = 0; else invsa = 0x100; }
693
694         // loop over rows
695         for (INT32 y = setup.starty; y < setup.endy; y++)
696         {
697            _PixelType *dest = dstdata + y * pitch + setup.startx;
698            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
699            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
700
701            // loop over cols
702            for (INT32 x = setup.startx; x < endx; x++)
703            {
704               UINT32 pix = get_texel_palette16(prim.texture, curu, curv);
705               UINT32 dpix = _NoDestRead ? 0 : *dest;
706               UINT32 r = (source32_r(pix) * sr + dest_r(dpix) * invsa) >> 8;
707               UINT32 g = (source32_g(pix) * sg + dest_g(dpix) * invsa) >> 8;
708               UINT32 b = (source32_b(pix) * sb + dest_b(dpix) * invsa) >> 8;
709
710               *dest++ = dest_assemble_rgb(r, g, b);
711               curu += dudx;
712               curv += dvdx;
713            }
714         }
715      }
716   }
717
718
719   //-------------------------------------------------
720   //  draw_quad_palette16_add - perform
721   //  rasterization of a 16bpp palettized texture
722   //-------------------------------------------------
723
724   static void draw_quad_palette16_add(const render_primitive &prim, _PixelType *dstdata, UINT32 pitch, quad_setup_data &setup)
725   {
726      INT32 dudx = setup.dudx;
727      INT32 dvdx = setup.dvdx;
728      INT32 endx = setup.endx;
729
730      // ensure all parameters are valid
731      assert(prim.texture.palette != NULL);
732
733      // fast case: no coloring, no alpha
734      if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a))
735      {
736         // loop over rows
737         for (INT32 y = setup.starty; y < setup.endy; y++)
738         {
739            _PixelType *dest = dstdata + y * pitch + setup.startx;
740            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
741            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
742
743            // loop over cols
744            for (INT32 x = setup.startx; x < endx; x++)
745            {
746               UINT32 pix = get_texel_palette16(prim.texture, curu, curv);
747               if ((pix & 0xffffff) != 0)
748               {
749                  UINT32 dpix = _NoDestRead ? 0 : *dest;
750                  UINT32 r = source32_r(pix) + dest_r(dpix);
751                  UINT32 g = source32_g(pix) + dest_g(dpix);
752                  UINT32 b = source32_b(pix) + dest_b(dpix);
753                  r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
754                  g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
755                  b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
756                  *dest = dest_assemble_rgb(r, g, b);
757               }
758               dest++;
759               curu += dudx;
760               curv += dvdx;
761            }
762         }
763      }
764
765      // alpha and/or coloring case
766      else
767      {
768         UINT32 sr = UINT32(256.0f * prim.color.r * prim.color.a);
769         UINT32 sg = UINT32(256.0f * prim.color.g * prim.color.a);
770         UINT32 sb = UINT32(256.0f * prim.color.b * prim.color.a);
771
772         // clamp R,G,B and inverse A to 0-256 range
773         if (sr > 0x100) { if (INT32(sr) < 0) sr = 0; else sr = 0x100; }
774         if (sg > 0x100) { if (INT32(sg) < 0) sg = 0; else sg = 0x100; }
775         if (sb > 0x100) { if (INT32(sb) < 0) sb = 0; else sb = 0x100; }
776
777         // loop over rows
778         for (INT32 y = setup.starty; y < setup.endy; y++)
779         {
780            _PixelType *dest = dstdata + y * pitch + setup.startx;
781            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
782            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
783
784            // loop over cols
785            for (INT32 x = setup.startx; x < endx; x++)
786            {
787               UINT32 pix = get_texel_palette16(prim.texture, curu, curv);
788               if ((pix & 0xffffff) != 0)
789               {
790                  UINT32 dpix = _NoDestRead ? 0 : *dest;
791                  UINT32 r = ((source32_r(pix) * sr) >> 8) + dest_r(dpix);
792                  UINT32 g = ((source32_g(pix) * sg) >> 8) + dest_g(dpix);
793                  UINT32 b = ((source32_b(pix) * sb) >> 8) + dest_b(dpix);
794                  r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
795                  g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
796                  b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
797                  *dest++ = dest_assemble_rgb(r, g, b);
798                  curu += dudx;
799                  curv += dvdx;
800               }
801            }
802         }
803      }
804   }
805
806
807
808   //**************************************************************************
809   //  16-BIT ALPHA PALETTE RASTERIZERS
810   //**************************************************************************
811
812   //-------------------------------------------------
813   //  draw_quad_palettea16_alpha - perform
814   //  rasterization using standard alpha blending
815   //-------------------------------------------------
816
817   static void draw_quad_palettea16_alpha(const render_primitive &prim, _PixelType *dstdata, UINT32 pitch, quad_setup_data &setup)
818   {
819      INT32 dudx = setup.dudx;
820      INT32 dvdx = setup.dvdx;
821      INT32 endx = setup.endx;
822
823      // ensure all parameters are valid
824      assert(prim.texture.palette != NULL);
825
826      // fast case: no coloring, no alpha
827      if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a))
828      {
829         // loop over rows
830         for (INT32 y = setup.starty; y < setup.endy; y++)
831         {
832            _PixelType *dest = dstdata + y * pitch + setup.startx;
833            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
834            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
835
836            // loop over cols
837            for (INT32 x = setup.startx; x < endx; x++)
838            {
839               UINT32 pix = get_texel_palette16a(prim.texture, curu, curv);
840               UINT32 ta = pix >> 24;
841               if (ta != 0)
842               {
843                  UINT32 dpix = _NoDestRead ? 0 : *dest;
844                  UINT32 invta = 0x100 - ta;
845                  UINT32 r = (source32_r(pix) * ta + dest_r(dpix) * invta) >> 8;
846                  UINT32 g = (source32_g(pix) * ta + dest_g(dpix) * invta) >> 8;
847                  UINT32 b = (source32_b(pix) * ta + dest_b(dpix) * invta) >> 8;
848
849                  *dest = dest_assemble_rgb(r, g, b);
850               }
851               dest++;
852               curu += dudx;
853               curv += dvdx;
854            }
855         }
856      }
857
858      // alpha and/or coloring case
859      else
860      {
861         UINT32 sr = UINT32(256.0f * prim.color.r);
862         UINT32 sg = UINT32(256.0f * prim.color.g);
863         UINT32 sb = UINT32(256.0f * prim.color.b);
864         UINT32 sa = UINT32(256.0f * prim.color.a);
865
866         // clamp R,G,B and inverse A to 0-256 range
867         if (sr > 0x100) { if (INT32(sr) < 0) sr = 0; else sr = 0x100; }
868         if (sg > 0x100) { if (INT32(sg) < 0) sg = 0; else sg = 0x100; }
869         if (sb > 0x100) { if (INT32(sb) < 0) sb = 0; else sb = 0x100; }
870         if (sa > 0x100) { if (INT32(sa) < 0) sa = 0; else sa = 0x100; }
871
872         // loop over rows
873         for (INT32 y = setup.starty; y < setup.endy; y++)
874         {
875            _PixelType *dest = dstdata + y * pitch + setup.startx;
876            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
877            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
878
879            // loop over cols
880            for (INT32 x = setup.startx; x < endx; x++)
881            {
882               UINT32 pix = get_texel_palette16a(prim.texture, curu, curv);
883               UINT32 ta = (pix >> 24) * sa;
884               if (ta != 0)
885               {
886                  UINT32 dpix = _NoDestRead ? 0 : *dest;
887                  UINT32 invsta = (0x10000 - ta) << 8;
888                  UINT32 r = (source32_r(pix) * sr * ta + dest_r(dpix) * invsta) >> 24;
889                  UINT32 g = (source32_g(pix) * sg * ta + dest_g(dpix) * invsta) >> 24;
890                  UINT32 b = (source32_b(pix) * sb * ta + dest_b(dpix) * invsta) >> 24;
891
892                  *dest = dest_assemble_rgb(r, g, b);
893               }
894               dest++;
895               curu += dudx;
896               curv += dvdx;
897            }
898         }
899      }
900   }
901
902
903
904   //**************************************************************************
905   //  16-BIT YUY RASTERIZERS
906   //**************************************************************************
907
908   //-------------------------------------------------
909   //  draw_quad_yuy16_none - perform
910   //  rasterization of a 16bpp YUY image
911   //-------------------------------------------------
912
913   static void draw_quad_yuy16_none(const render_primitive &prim, _PixelType *dstdata, UINT32 pitch, quad_setup_data &setup)
914   {
915      const rgb_t *palbase = prim.texture.palette;
916      INT32 dudx = setup.dudx;
917      INT32 dvdx = setup.dvdx;
918      INT32 endx = setup.endx;
919
920      // fast case: no coloring, no alpha
921      if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a))
922      {
923         // loop over rows
924         for (INT32 y = setup.starty; y < setup.endy; y++)
925         {
926            _PixelType *dest = dstdata + y * pitch + setup.startx;
927            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
928            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
929
930            // no lookup case
931            if (palbase == NULL)
932            {
933               // loop over cols
934               for (INT32 x = setup.startx; x < endx; x++)
935               {
936                  UINT32 pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv));
937                  *dest++ = source32_to_dest(pix);
938                  curu += dudx;
939                  curv += dvdx;
940               }
941            }
942
943            // lookup case
944            else
945            {
946               // loop over cols
947               for (INT32 x = setup.startx; x < endx; x++)
948               {
949                  UINT32 pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv));
950                  *dest++ = source32_to_dest(pix);
951                  curu += dudx;
952                  curv += dvdx;
953               }
954            }
955         }
956      }
957
958      // coloring-only case
959      else if (is_opaque(prim.color.a))
960      {
961         UINT32 sr = UINT32(256.0f * prim.color.r);
962         UINT32 sg = UINT32(256.0f * prim.color.g);
963         UINT32 sb = UINT32(256.0f * prim.color.b);
964
965         // clamp R,G,B to 0-256 range
966         if (sr > 0x100) { if (INT32(sr) < 0) sr = 0; else sr = 0x100; }
967         if (sg > 0x100) { if (INT32(sg) < 0) sg = 0; else sg = 0x100; }
968         if (sb > 0x100) { if (INT32(sb) < 0) sb = 0; else sb = 0x100; }
969
970         // loop over rows
971         for (INT32 y = setup.starty; y < setup.endy; y++)
972         {
973            _PixelType *dest = dstdata + y * pitch + setup.startx;
974            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
975            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
976
977            // no lookup case
978            if (palbase == NULL)
979            {
980               // loop over cols
981               for (INT32 x = setup.startx; x < endx; x++)
982               {
983                  UINT32 pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv));
984                  UINT32 r = (source32_r(pix) * sr) >> 8;
985                  UINT32 g = (source32_g(pix) * sg) >> 8;
986                  UINT32 b = (source32_b(pix) * sb) >> 8;
987
988                  *dest++ = dest_assemble_rgb(r, g, b);
989                  curu += dudx;
990                  curv += dvdx;
991               }
992            }
993
994            // lookup case
995            else
996            {
997               // loop over cols
998               for (INT32 x = setup.startx; x < endx; x++)
999               {
1000                  UINT32 pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv));
1001                  UINT32 r = (source32_r(pix) * sr) >> 8;
1002                  UINT32 g = (source32_g(pix) * sg) >> 8;
1003                  UINT32 b = (source32_b(pix) * sb) >> 8;
1004
1005                  *dest++ = dest_assemble_rgb(r, g, b);
1006                  curu += dudx;
1007                  curv += dvdx;
1008               }
1009            }
1010         }
1011      }
1012
1013      // alpha and/or coloring case
1014      else if (!is_transparent(prim.color.a))
1015      {
1016         UINT32 sr = UINT32(256.0f * prim.color.r * prim.color.a);
1017         UINT32 sg = UINT32(256.0f * prim.color.g * prim.color.a);
1018         UINT32 sb = UINT32(256.0f * prim.color.b * prim.color.a);
1019         UINT32 invsa = UINT32(256.0f * (1.0f - prim.color.a));
1020
1021         // clamp R,G,B and inverse A to 0-256 range
1022         if (sr > 0x100) { if (INT32(sr) < 0) sr = 0; else sr = 0x100; }
1023         if (sg > 0x100) { if (INT32(sg) < 0) sg = 0; else sg = 0x100; }
1024         if (sb > 0x100) { if (INT32(sb) < 0) sb = 0; else sb = 0x100; }
1025         if (invsa > 0x100) { if (INT32(invsa) < 0) invsa = 0; else invsa = 0x100; }
1026
1027         // loop over rows
1028         for (INT32 y = setup.starty; y < setup.endy; y++)
1029         {
1030            _PixelType *dest = dstdata + y * pitch + setup.startx;
1031            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
1032            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
1033
1034            // no lookup case
1035            if (palbase == NULL)
1036            {
1037               // loop over cols
1038               for (INT32 x = setup.startx; x < endx; x++)
1039               {
1040                  UINT32 pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv));
1041                  UINT32 dpix = _NoDestRead ? 0 : *dest;
1042                  UINT32 r = (source32_r(pix) * sr + dest_r(dpix) * invsa) >> 8;
1043                  UINT32 g = (source32_g(pix) * sg + dest_g(dpix) * invsa) >> 8;
1044                  UINT32 b = (source32_b(pix) * sb + dest_b(dpix) * invsa) >> 8;
1045
1046                  *dest++ = dest_assemble_rgb(r, g, b);
1047                  curu += dudx;
1048                  curv += dvdx;
1049               }
1050            }
1051
1052            // lookup case
1053            else
1054            {
1055               // loop over cols
1056               for (INT32 x = setup.startx; x < endx; x++)
1057               {
1058                  UINT32 pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv));
1059                  UINT32 dpix = _NoDestRead ? 0 : *dest;
1060                  UINT32 r = (source32_r(pix) * sr + dest_r(dpix) * invsa) >> 8;
1061                  UINT32 g = (source32_g(pix) * sg + dest_g(dpix) * invsa) >> 8;
1062                  UINT32 b = (source32_b(pix) * sb + dest_b(dpix) * invsa) >> 8;
1063
1064                  *dest++ = dest_assemble_rgb(r, g, b);
1065                  curu += dudx;
1066                  curv += dvdx;
1067               }
1068            }
1069         }
1070      }
1071   }
1072
1073
1074   //**************************************************************************
1075   //  32-BIT RGB QUAD RASTERIZERS
1076   //**************************************************************************
1077
1078   //-------------------------------------------------
1079   //  draw_quad_rgb32 - perform rasterization of
1080   //  a 32bpp RGB texture
1081   //-------------------------------------------------
1082
1083   static void draw_quad_rgb32(const render_primitive &prim, _PixelType *dstdata, UINT32 pitch, quad_setup_data &setup)
1084   {
1085      const rgb_t *palbase = prim.texture.palette;
1086      INT32 dudx = setup.dudx;
1087      INT32 dvdx = setup.dvdx;
1088      INT32 endx = setup.endx;
1089
1090      // fast case: no coloring, no alpha
1091      if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a))
1092      {
1093         // loop over rows
1094         for (INT32 y = setup.starty; y < setup.endy; y++)
1095         {
1096            _PixelType *dest = dstdata + y * pitch + setup.startx;
1097            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
1098            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
1099
1100            // no lookup case
1101            if (palbase == NULL)
1102            {
1103               // loop over cols
1104               for (INT32 x = setup.startx; x < endx; x++)
1105               {
1106                  UINT32 pix = get_texel_rgb32(prim.texture, curu, curv);
1107                  *dest++ = source32_to_dest(pix);
1108                  curu += dudx;
1109                  curv += dvdx;
1110               }
1111            }
1112
1113            // lookup case
1114            else
1115            {
1116               // loop over cols
1117               for (INT32 x = setup.startx; x < endx; x++)
1118               {
1119                  UINT32 pix = get_texel_rgb32(prim.texture, curu, curv);
1120                  UINT32 r = palbase[(pix >> 16) & 0xff] >> _SrcShiftR;
1121                  UINT32 g = palbase[(pix >> 8) & 0xff] >> _SrcShiftG;
1122                  UINT32 b = palbase[(pix >> 0) & 0xff] >> _SrcShiftB;
1123
1124                  *dest++ = dest_assemble_rgb(r, g, b);
1125                  curu += dudx;
1126                  curv += dvdx;
1127               }
1128            }
1129         }
1130      }
1131
1132      // coloring-only case
1133      else if (is_opaque(prim.color.a))
1134      {
1135         UINT32 sr = UINT32(256.0f * prim.color.r);
1136         UINT32 sg = UINT32(256.0f * prim.color.g);
1137         UINT32 sb = UINT32(256.0f * prim.color.b);
1138
1139         // clamp R,G,B to 0-256 range
1140         if (sr > 0x100) { if (INT32(sr) < 0) sr = 0; else sr = 0x100; }
1141         if (sg > 0x100) { if (INT32(sg) < 0) sg = 0; else sg = 0x100; }
1142         if (sb > 0x100) { if (INT32(sb) < 0) sb = 0; else sb = 0x100; }
1143
1144         // loop over rows
1145         for (INT32 y = setup.starty; y < setup.endy; y++)
1146         {
1147            _PixelType *dest = dstdata + y * pitch + setup.startx;
1148            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
1149            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
1150
1151            // no lookup case
1152            if (palbase == NULL)
1153            {
1154               // loop over cols
1155               for (INT32 x = setup.startx; x < endx; x++)
1156               {
1157                  UINT32 pix = get_texel_rgb32(prim.texture, curu, curv);
1158                  UINT32 r = (source32_r(pix) * sr) >> 8;
1159                  UINT32 g = (source32_g(pix) * sg) >> 8;
1160                  UINT32 b = (source32_b(pix) * sb) >> 8;
1161
1162                  *dest++ = dest_assemble_rgb(r, g, b);
1163                  curu += dudx;
1164                  curv += dvdx;
1165               }
1166            }
1167
1168            // lookup case
1169            else
1170            {
1171               // loop over cols
1172               for (INT32 x = setup.startx; x < endx; x++)
1173               {
1174                  UINT32 pix = get_texel_rgb32(prim.texture, curu, curv);
1175                  UINT32 r = (palbase[(pix >> 16) & 0xff] * sr) >> (8 + _SrcShiftR);
1176                  UINT32 g = (palbase[(pix >> 8) & 0xff] * sg) >> (8 + _SrcShiftG);
1177                  UINT32 b = (palbase[(pix >> 0) & 0xff] * sb) >> (8 + _SrcShiftB);
1178
1179                  *dest++ = dest_assemble_rgb(r, g, b);
1180                  curu += dudx;
1181                  curv += dvdx;
1182               }
1183            }
1184         }
1185      }
1186
1187      // alpha and/or coloring case
1188      else if (!is_transparent(prim.color.a))
1189      {
1190         UINT32 sr = UINT32(256.0f * prim.color.r * prim.color.a);
1191         UINT32 sg = UINT32(256.0f * prim.color.g * prim.color.a);
1192         UINT32 sb = UINT32(256.0f * prim.color.b * prim.color.a);
1193         UINT32 invsa = UINT32(256.0f * (1.0f - prim.color.a));
1194
1195         // clamp R,G,B and inverse A to 0-256 range
1196         if (sr > 0x100) { if (INT32(sr) < 0) sr = 0; else sr = 0x100; }
1197         if (sg > 0x100) { if (INT32(sg) < 0) sg = 0; else sg = 0x100; }
1198         if (sb > 0x100) { if (INT32(sb) < 0) sb = 0; else sb = 0x100; }
1199         if (invsa > 0x100) { if (INT32(invsa) < 0) invsa = 0; else invsa = 0x100; }
1200
1201         // loop over rows
1202         for (INT32 y = setup.starty; y < setup.endy; y++)
1203         {
1204            _PixelType *dest = dstdata + y * pitch + setup.startx;
1205            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
1206            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
1207
1208            // no lookup case
1209            if (palbase == NULL)
1210            {
1211               // loop over cols
1212               for (INT32 x = setup.startx; x < endx; x++)
1213               {
1214                  UINT32 pix = get_texel_rgb32(prim.texture, curu, curv);
1215                  UINT32 dpix = _NoDestRead ? 0 : *dest;
1216                  UINT32 r = (source32_r(pix) * sr + dest_r(dpix) * invsa) >> 8;
1217                  UINT32 g = (source32_g(pix) * sg + dest_g(dpix) * invsa) >> 8;
1218                  UINT32 b = (source32_b(pix) * sb + dest_b(dpix) * invsa) >> 8;
1219
1220                  *dest++ = dest_assemble_rgb(r, g, b);
1221                  curu += dudx;
1222                  curv += dvdx;
1223               }
1224            }
1225
1226            // lookup case
1227            else
1228            {
1229               // loop over cols
1230               for (INT32 x = setup.startx; x < endx; x++)
1231               {
1232                  UINT32 pix = get_texel_rgb32(prim.texture, curu, curv);
1233                  UINT32 dpix = _NoDestRead ? 0 : *dest;
1234                  UINT32 r = ((palbase[(pix >> 16) & 0xff] >> _SrcShiftR) * sr + dest_r(dpix) * invsa) >> 8;
1235                  UINT32 g = ((palbase[(pix >> 8) & 0xff] >> _SrcShiftG) * sg + dest_g(dpix) * invsa) >> 8;
1236                  UINT32 b = ((palbase[(pix >> 0) & 0xff] >> _SrcShiftB) * sb + dest_b(dpix) * invsa) >> 8;
1237
1238                  *dest++ = dest_assemble_rgb(r, g, b);
1239                  curu += dudx;
1240                  curv += dvdx;
1241               }
1242            }
1243         }
1244      }
1245   }
1246
1247
1248   //-------------------------------------------------
1249   //  draw_quad_rgb32_add - perform
1250   //  rasterization by using RGB add
1251   //-------------------------------------------------
1252
1253   static void draw_quad_rgb32_add(const render_primitive &prim, _PixelType *dstdata, UINT32 pitch, quad_setup_data &setup)
1254   {
1255      const rgb_t *palbase = prim.texture.palette;
1256      INT32 dudx = setup.dudx;
1257      INT32 dvdx = setup.dvdx;
1258      INT32 endx = setup.endx;
1259
1260      // simply can't do this without reading from the dest
1261      if (_NoDestRead)
1262         return;
1263
1264      // fast case: no coloring, no alpha
1265      if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a))
1266      {
1267         // loop over rows
1268         for (INT32 y = setup.starty; y < setup.endy; y++)
1269         {
1270            _PixelType *dest = dstdata + y * pitch + setup.startx;
1271            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
1272            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
1273
1274            // no lookup case
1275            if (palbase == NULL)
1276            {
1277               // loop over cols
1278               for (INT32 x = setup.startx; x < endx; x++)
1279               {
1280                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1281                  UINT32 dpix = _NoDestRead ? 0 : *dest;
1282                  UINT32 r = source32_r(pix) + dest_r(dpix);
1283                  UINT32 g = source32_g(pix) + dest_g(dpix);
1284                  UINT32 b = source32_b(pix) + dest_b(dpix);
1285                  r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
1286                  g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
1287                  b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
1288                  *dest++ = dest_assemble_rgb(r, g, b);
1289                  curu += dudx;
1290                  curv += dvdx;
1291               }
1292            }
1293
1294            // lookup case
1295            else
1296            {
1297               // loop over cols
1298               for (INT32 x = setup.startx; x < endx; x++)
1299               {
1300                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1301                  UINT32 dpix = _NoDestRead ? 0 : *dest;
1302                  UINT32 r = (palbase[(pix >> 16) & 0xff] >> _SrcShiftR) + dest_r(dpix);
1303                  UINT32 g = (palbase[(pix >> 8) & 0xff] >> _SrcShiftG) + dest_g(dpix);
1304                  UINT32 b = (palbase[(pix >> 0) & 0xff] >> _SrcShiftB) + dest_b(dpix);
1305                  r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
1306                  g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
1307                  b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
1308                  *dest++ = dest_assemble_rgb(r, g, b);
1309                  curu += dudx;
1310                  curv += dvdx;
1311               }
1312            }
1313         }
1314      }
1315
1316      // alpha and/or coloring case
1317      else
1318      {
1319         UINT32 sr = UINT32(256.0f * prim.color.r);
1320         UINT32 sg = UINT32(256.0f * prim.color.g);
1321         UINT32 sb = UINT32(256.0f * prim.color.b);
1322         UINT32 sa = UINT32(256.0f * prim.color.a);
1323
1324         // clamp R,G,B and inverse A to 0-256 range
1325         if (sr > 0x100) { if (INT32(sr) < 0) sr = 0; else sr = 0x100; }
1326         if (sg > 0x100) { if (INT32(sg) < 0) sg = 0; else sg = 0x100; }
1327         if (sb > 0x100) { if (INT32(sb) < 0) sb = 0; else sb = 0x100; }
1328         if (sa > 0x100) { if (INT32(sa) < 0) sa = 0; else sa = 0x100; }
1329
1330         // loop over rows
1331         for (INT32 y = setup.starty; y < setup.endy; y++)
1332         {
1333            _PixelType *dest = dstdata + y * pitch + setup.startx;
1334            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
1335            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
1336
1337            // no lookup case
1338            if (palbase == NULL)
1339            {
1340               // loop over cols
1341               for (INT32 x = setup.startx; x < endx; x++)
1342               {
1343                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1344                  UINT32 dpix = _NoDestRead ? 0 : *dest;
1345                  UINT32 r = ((source32_r(pix) * sr * sa) >> 16) + dest_r(dpix);
1346                  UINT32 g = ((source32_g(pix) * sg * sa) >> 16) + dest_g(dpix);
1347                  UINT32 b = ((source32_b(pix) * sb * sa) >> 16) + dest_b(dpix);
1348                  r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
1349                  g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
1350                  b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
1351                  *dest++ = dest_assemble_rgb(r, g, b);
1352                  curu += dudx;
1353                  curv += dvdx;
1354               }
1355            }
1356
1357            // lookup case
1358            else
1359            {
1360               // loop over cols
1361               for (INT32 x = setup.startx; x < endx; x++)
1362               {
1363                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1364                  UINT32 dpix = _NoDestRead ? 0 : *dest;
1365                  UINT32 r = ((palbase[(pix >> 16) & 0xff] * sr * sa) >> (16 + _SrcShiftR)) + dest_r(dpix);
1366                  UINT32 g = ((palbase[(pix >> 8) & 0xff] * sr * sa) >> (16 + _SrcShiftR)) + dest_g(dpix);
1367                  UINT32 b = ((palbase[(pix >> 0) & 0xff] * sr * sa) >> (16 + _SrcShiftR)) + dest_b(dpix);
1368                  r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
1369                  g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
1370                  b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
1371                  *dest++ = dest_assemble_rgb(r, g, b);
1372                  curu += dudx;
1373                  curv += dvdx;
1374               }
1375            }
1376         }
1377      }
1378   }
1379
1380
1381
1382   //**************************************************************************
1383   //  32-BIT ARGB QUAD RASTERIZERS
1384   //**************************************************************************
1385
1386   //-------------------------------------------------
1387   //  draw_quad_argb32_alpha - perform
1388   //  rasterization using standard alpha blending
1389   //-------------------------------------------------
1390
1391   static void draw_quad_argb32_alpha(const render_primitive &prim, _PixelType *dstdata, UINT32 pitch, quad_setup_data &setup)
1392   {
1393      const rgb_t *palbase = prim.texture.palette;
1394      INT32 dudx = setup.dudx;
1395      INT32 dvdx = setup.dvdx;
1396      INT32 endx = setup.endx;
1397
1398      // fast case: no coloring, no alpha
1399      if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a))
1400      {
1401         // loop over rows
1402         for (INT32 y = setup.starty; y < setup.endy; y++)
1403         {
1404            _PixelType *dest = dstdata + y * pitch + setup.startx;
1405            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
1406            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
1407
1408            // no lookup case
1409            if (palbase == NULL)
1410            {
1411               // loop over cols
1412               for (INT32 x = setup.startx; x < endx; x++)
1413               {
1414                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1415                  UINT32 ta = pix >> 24;
1416                  if (ta != 0)
1417                  {
1418                     UINT32 dpix = _NoDestRead ? 0 : *dest;
1419                     UINT32 invta = 0x100 - ta;
1420                     UINT32 r = (source32_r(pix) * ta + dest_r(dpix) * invta) >> 8;
1421                     UINT32 g = (source32_g(pix) * ta + dest_g(dpix) * invta) >> 8;
1422                     UINT32 b = (source32_b(pix) * ta + dest_b(dpix) * invta) >> 8;
1423
1424                     *dest = dest_assemble_rgb(r, g, b);
1425                  }
1426                  dest++;
1427                  curu += dudx;
1428                  curv += dvdx;
1429               }
1430            }
1431
1432            // lookup case
1433            else
1434            {
1435               // loop over cols
1436               for (INT32 x = setup.startx; x < endx; x++)
1437               {
1438                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1439                  UINT32 ta = pix >> 24;
1440                  if (ta != 0)
1441                  {
1442                     UINT32 dpix = _NoDestRead ? 0 : *dest;
1443                     UINT32 invta = 0x100 - ta;
1444                     UINT32 r = ((palbase[(pix >> 16) & 0xff] >> _SrcShiftR) * ta + dest_r(dpix) * invta) >> 8;
1445                     UINT32 g = ((palbase[(pix >> 8) & 0xff] >> _SrcShiftG) * ta + dest_g(dpix) * invta) >> 8;
1446                     UINT32 b = ((palbase[(pix >> 0) & 0xff] >> _SrcShiftB) * ta + dest_b(dpix) * invta) >> 8;
1447
1448                     *dest = dest_assemble_rgb(r, g, b);
1449                  }
1450                  dest++;
1451                  curu += dudx;
1452                  curv += dvdx;
1453               }
1454            }
1455         }
1456      }
1457
1458      // alpha and/or coloring case
1459      else
1460      {
1461         UINT32 sr = UINT32(256.0f * prim.color.r);
1462         UINT32 sg = UINT32(256.0f * prim.color.g);
1463         UINT32 sb = UINT32(256.0f * prim.color.b);
1464         UINT32 sa = UINT32(256.0f * prim.color.a);
1465
1466         // clamp R,G,B and inverse A to 0-256 range
1467         if (sr > 0x100) { if (INT32(sr) < 0) sr = 0; else sr = 0x100; }
1468         if (sg > 0x100) { if (INT32(sg) < 0) sg = 0; else sg = 0x100; }
1469         if (sb > 0x100) { if (INT32(sb) < 0) sb = 0; else sb = 0x100; }
1470         if (sa > 0x100) { if (INT32(sa) < 0) sa = 0; else sa = 0x100; }
1471
1472         // loop over rows
1473         for (INT32 y = setup.starty; y < setup.endy; y++)
1474         {
1475            _PixelType *dest = dstdata + y * pitch + setup.startx;
1476            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
1477            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
1478
1479            // no lookup case
1480            if (palbase == NULL)
1481            {
1482               // loop over cols
1483               for (INT32 x = setup.startx; x < endx; x++)
1484               {
1485                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1486                  UINT32 ta = (pix >> 24) * sa;
1487                  if (ta != 0)
1488                  {
1489                     UINT32 dpix = _NoDestRead ? 0 : *dest;
1490                     UINT32 invsta = (0x10000 - ta) << 8;
1491                     UINT32 r = (source32_r(pix) * sr * ta + dest_r(dpix) * invsta) >> 24;
1492                     UINT32 g = (source32_g(pix) * sg * ta + dest_g(dpix) * invsta) >> 24;
1493                     UINT32 b = (source32_b(pix) * sb * ta + dest_b(dpix) * invsta) >> 24;
1494
1495                     *dest = dest_assemble_rgb(r, g, b);
1496                  }
1497                  dest++;
1498                  curu += dudx;
1499                  curv += dvdx;
1500               }
1501            }
1502
1503
1504            // lookup case
1505            else
1506            {
1507               // loop over cols
1508               for (INT32 x = setup.startx; x < endx; x++)
1509               {
1510                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1511                  UINT32 ta = (pix >> 24) * sa;
1512                  if (ta != 0)
1513                  {
1514                     UINT32 dpix = _NoDestRead ? 0 : *dest;
1515                     UINT32 invsta = (0x10000 - ta) << 8;
1516                     UINT32 r = ((palbase[(pix >> 16) & 0xff] >> _SrcShiftR) * sr * ta + dest_r(dpix) * invsta) >> 24;
1517                     UINT32 g = ((palbase[(pix >> 8) & 0xff] >> _SrcShiftG) * sg * ta + dest_g(dpix) * invsta) >> 24;
1518                     UINT32 b = ((palbase[(pix >> 0) & 0xff] >> _SrcShiftB) * sb * ta + dest_b(dpix) * invsta) >> 24;
1519
1520                     *dest = dest_assemble_rgb(r, g, b);
1521                  }
1522                  dest++;
1523                  curu += dudx;
1524                  curv += dvdx;
1525               }
1526            }
1527         }
1528      }
1529   }
1530
1531
1532   //-------------------------------------------------
1533   //  draw_quad_argb32_multiply - perform
1534   //  rasterization using RGB multiply
1535   //-------------------------------------------------
1536
1537   static void draw_quad_argb32_multiply(const render_primitive &prim, _PixelType *dstdata, UINT32 pitch, quad_setup_data &setup)
1538   {
1539      const rgb_t *palbase = prim.texture.palette;
1540      INT32 dudx = setup.dudx;
1541      INT32 dvdx = setup.dvdx;
1542      INT32 endx = setup.endx;
1543
1544      // simply can't do this without reading from the dest
1545      if (_NoDestRead)
1546         return;
1547
1548      // fast case: no coloring, no alpha
1549      if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a))
1550      {
1551         // loop over rows
1552         for (INT32 y = setup.starty; y < setup.endy; y++)
1553         {
1554            _PixelType *dest = dstdata + y * pitch + setup.startx;
1555            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
1556            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
1557
1558            // no lookup case
1559            if (palbase == NULL)
1560            {
1561               // loop over cols
1562               for (INT32 x = setup.startx; x < endx; x++)
1563               {
1564                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1565                  UINT32 dpix = _NoDestRead ? 0 : *dest;
1566                  UINT32 r = (source32_r(pix) * dest_r(dpix)) >> (8 - _SrcShiftR);
1567                  UINT32 g = (source32_g(pix) * dest_g(dpix)) >> (8 - _SrcShiftG);
1568                  UINT32 b = (source32_b(pix) * dest_b(dpix)) >> (8 - _SrcShiftB);
1569
1570                  *dest++ = dest_assemble_rgb(r, g, b);
1571                  curu += dudx;
1572                  curv += dvdx;
1573               }
1574            }
1575            else
1576            {
1577               // loop over cols
1578               for (INT32 x = setup.startx; x < endx; x++)
1579               {
1580                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1581                  UINT32 dpix = _NoDestRead ? 0 : *dest;
1582                  UINT32 r = (palbase[(pix >> 16) & 0xff] * dest_r(dpix)) >> 8;
1583                  UINT32 g = (palbase[(pix >> 8) & 0xff] * dest_g(dpix)) >> 8;
1584                  UINT32 b = (palbase[(pix >> 0) & 0xff] * dest_b(dpix)) >> 8;
1585
1586                  *dest++ = dest_assemble_rgb(r, g, b);
1587                  curu += dudx;
1588                  curv += dvdx;
1589               }
1590            }
1591         }
1592      }
1593
1594      // alpha and/or coloring case
1595      else
1596      {
1597         UINT32 sr = UINT32(256.0f * prim.color.r * prim.color.a);
1598         UINT32 sg = UINT32(256.0f * prim.color.g * prim.color.a);
1599         UINT32 sb = UINT32(256.0f * prim.color.b * prim.color.a);
1600
1601         // clamp R,G,B and inverse A to 0-256 range
1602         if (sr > 0x100) { if (INT32(sr) < 0) sr = 0; else sr = 0x100; }
1603         if (sg > 0x100) { if (INT32(sg) < 0) sg = 0; else sg = 0x100; }
1604         if (sb > 0x100) { if (INT32(sb) < 0) sb = 0; else sb = 0x100; }
1605
1606         // loop over rows
1607         for (INT32 y = setup.starty; y < setup.endy; y++)
1608         {
1609            _PixelType *dest = dstdata + y * pitch + setup.startx;
1610            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
1611            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
1612
1613            // no lookup case
1614            if (palbase == NULL)
1615            {
1616               // loop over cols
1617               for (INT32 x = setup.startx; x < endx; x++)
1618               {
1619                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1620                  UINT32 dpix = _NoDestRead ? 0 : *dest;
1621                  UINT32 r = (source32_r(pix) * sr * dest_r(dpix)) >> (16 - _SrcShiftR);
1622                  UINT32 g = (source32_g(pix) * sg * dest_g(dpix)) >> (16 - _SrcShiftG);
1623                  UINT32 b = (source32_b(pix) * sb * dest_b(dpix)) >> (16 - _SrcShiftB);
1624
1625                  *dest++ = dest_assemble_rgb(r, g, b);
1626                  curu += dudx;
1627                  curv += dvdx;
1628               }
1629            }
1630            else
1631            {
1632               // loop over cols
1633               for (INT32 x = setup.startx; x < endx; x++)
1634               {
1635                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1636                  UINT32 dpix = _NoDestRead ? 0 : *dest;
1637                  UINT32 r = (palbase[(pix >> 16) & 0xff] * sr * dest_r(dpix)) >> 16;
1638                  UINT32 g = (palbase[(pix >> 8) & 0xff] * sg * dest_g(dpix)) >> 16;
1639                  UINT32 b = (palbase[(pix >> 0) & 0xff] * sb * dest_b(dpix)) >> 16;
1640
1641                  *dest++ = dest_assemble_rgb(r, g, b);
1642                  curu += dudx;
1643                  curv += dvdx;
1644               }
1645            }
1646         }
1647      }
1648   }
1649
1650
1651   //-------------------------------------------------
1652   //  draw_quad_argb32_add - perform
1653   //  rasterization by using RGB add
1654   //-------------------------------------------------
1655
1656   static void draw_quad_argb32_add(const render_primitive &prim, _PixelType *dstdata, UINT32 pitch, quad_setup_data &setup)
1657   {
1658      const rgb_t *palbase = prim.texture.palette;
1659      INT32 dudx = setup.dudx;
1660      INT32 dvdx = setup.dvdx;
1661      INT32 endx = setup.endx;
1662
1663      // simply can't do this without reading from the dest
1664      if (_NoDestRead)
1665         return;
1666
1667      // fast case: no coloring, no alpha
1668      if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a))
1669      {
1670         // loop over rows
1671         for (INT32 y = setup.starty; y < setup.endy; y++)
1672         {
1673            _PixelType *dest = dstdata + y * pitch + setup.startx;
1674            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
1675            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
1676
1677            // no lookup case
1678            if (palbase == NULL)
1679            {
1680               // loop over cols
1681               for (INT32 x = setup.startx; x < endx; x++)
1682               {
1683                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1684                  UINT32 ta = pix >> 24;
1685                  if (ta != 0)
1686                  {
1687                     UINT32 dpix = _NoDestRead ? 0 : *dest;
1688                     UINT32 r = ((source32_r(pix) * ta) >> 8) + dest_r(dpix);
1689                     UINT32 g = ((source32_g(pix) * ta) >> 8) + dest_g(dpix);
1690                     UINT32 b = ((source32_b(pix) * ta) >> 8) + dest_b(dpix);
1691                     r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
1692                     g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
1693                     b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
1694                     *dest = dest_assemble_rgb(r, g, b);
1695                  }
1696                  dest++;
1697                  curu += dudx;
1698                  curv += dvdx;
1699               }
1700            }
1701
1702            // lookup case
1703            else
1704            {
1705               // loop over cols
1706               for (INT32 x = setup.startx; x < endx; x++)
1707               {
1708                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1709                  UINT32 ta = pix >> 24;
1710                  if (ta != 0)
1711                  {
1712                     UINT32 dpix = _NoDestRead ? 0 : *dest;
1713                     UINT32 r = ((palbase[(pix >> 16) & 0xff] * ta) >> (8 + _SrcShiftR)) + dest_r(dpix);
1714                     UINT32 g = ((palbase[(pix >> 8) & 0xff] * ta) >> (8 + _SrcShiftG)) + dest_g(dpix);
1715                     UINT32 b = ((palbase[(pix >> 0) & 0xff] * ta) >> (8 + _SrcShiftB)) + dest_b(dpix);
1716                     r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
1717                     g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
1718                     b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
1719                     *dest = dest_assemble_rgb(r, g, b);
1720                  }
1721                  dest++;
1722                  curu += dudx;
1723                  curv += dvdx;
1724               }
1725            }
1726         }
1727      }
1728
1729      // alpha and/or coloring case
1730      else
1731      {
1732         UINT32 sr = UINT32(256.0f * prim.color.r);
1733         UINT32 sg = UINT32(256.0f * prim.color.g);
1734         UINT32 sb = UINT32(256.0f * prim.color.b);
1735         UINT32 sa = UINT32(256.0f * prim.color.a);
1736
1737         // clamp R,G,B and inverse A to 0-256 range
1738         if (sr > 0x100) { if (INT32(sr) < 0) sr = 0; else sr = 0x100; }
1739         if (sg > 0x100) { if (INT32(sg) < 0) sg = 0; else sg = 0x100; }
1740         if (sb > 0x100) { if (INT32(sb) < 0) sb = 0; else sb = 0x100; }
1741         if (sa > 0x100) { if (INT32(sa) < 0) sa = 0; else sa = 0x100; }
1742
1743         // loop over rows
1744         for (INT32 y = setup.starty; y < setup.endy; y++)
1745         {
1746            _PixelType *dest = dstdata + y * pitch + setup.startx;
1747            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
1748            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
1749
1750            // no lookup case
1751            if (palbase == NULL)
1752            {
1753               // loop over cols
1754               for (INT32 x = setup.startx; x < endx; x++)
1755               {
1756                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1757                  UINT32 ta = (pix >> 24) * sa;
1758                  if (ta != 0)
1759                  {
1760                     UINT32 dpix = _NoDestRead ? 0 : *dest;
1761                     UINT32 r = ((source32_r(pix) * sr * ta) >> 24) + dest_r(dpix);
1762                     UINT32 g = ((source32_g(pix) * sg * ta) >> 24) + dest_g(dpix);
1763                     UINT32 b = ((source32_b(pix) * sb * ta) >> 24) + dest_b(dpix);
1764                     r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
1765                     g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
1766                     b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
1767                     *dest = dest_assemble_rgb(r, g, b);
1768                  }
1769                  dest++;
1770                  curu += dudx;
1771                  curv += dvdx;
1772               }
1773            }
1774
1775            // lookup case
1776            else
1777            {
1778               // loop over cols
1779               for (INT32 x = setup.startx; x < endx; x++)
1780               {
1781                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1782                  UINT32 ta = (pix >> 24) * sa;
1783                  if (ta != 0)
1784                  {
1785                     UINT32 dpix = _NoDestRead ? 0 : *dest;
1786                     UINT32 r = ((palbase[(pix >> 16) & 0xff] * sr * ta) >> (24 + _SrcShiftR)) + dest_r(dpix);
1787                     UINT32 g = ((palbase[(pix >> 8) & 0xff] * sr * ta) >> (24 + _SrcShiftR)) + dest_g(dpix);
1788                     UINT32 b = ((palbase[(pix >> 0) & 0xff] * sr * ta) >> (24 + _SrcShiftR)) + dest_b(dpix);
1789                     r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
1790                     g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
1791                     b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
1792                     *dest = dest_assemble_rgb(r, g, b);
1793                  }
1794                  dest++;
1795                  curu += dudx;
1796                  curv += dvdx;
1797               }
1798            }
1799         }
1800      }
1801   }
1802
1803
1804   //**************************************************************************
1805   //  CORE QUAD RASTERIZERS
1806   //**************************************************************************
1807
1808   //-------------------------------------------------
1809   //  setup_and_draw_textured_quad - perform setup
1810   //  and then dispatch to a texture-mode-specific
1811   //  drawing routine
1812   //-------------------------------------------------
1813
1814   static void setup_and_draw_textured_quad(const render_primitive &prim, _PixelType *dstdata, INT32 width, INT32 height, UINT32 pitch)
1815   {
1816      assert(prim.bounds.x0 <= prim.bounds.x1);
1817      assert(prim.bounds.y0 <= prim.bounds.y1);
1818
1819      // determine U/V deltas
1820      float fdudx = (prim.texcoords.tr.u - prim.texcoords.tl.u) / (prim.bounds.x1 - prim.bounds.x0);
1821      float fdvdx = (prim.texcoords.tr.v - prim.texcoords.tl.v) / (prim.bounds.x1 - prim.bounds.x0);
1822      float fdudy = (prim.texcoords.bl.u - prim.texcoords.tl.u) / (prim.bounds.y1 - prim.bounds.y0);
1823      float fdvdy = (prim.texcoords.bl.v - prim.texcoords.tl.v) / (prim.bounds.y1 - prim.bounds.y0);
1824
1825      // clamp to integers
1826      quad_setup_data setup;
1827      setup.startx = round_nearest(prim.bounds.x0);
1828      setup.starty = round_nearest(prim.bounds.y0);
1829      setup.endx = round_nearest(prim.bounds.x1);
1830      setup.endy = round_nearest(prim.bounds.y1);
1831
1832      // ensure we fit
1833      if (setup.startx < 0) setup.startx = 0;
1834      if (setup.startx >= width) setup.startx = width;
1835      if (setup.endx < 0) setup.endx = 0;
1836      if (setup.endx >= width) setup.endx = width;
1837      if (setup.starty < 0) setup.starty = 0;
1838      if (setup.starty >= height) setup.starty = height;
1839      if (setup.endy < 0) setup.endy = 0;
1840      if (setup.endy >= height) setup.endy = height;
1841
1842      // compute start and delta U,V coordinates now
1843      setup.dudx = round_nearest(65536.0f * float(prim.texture.width) * fdudx);
1844      setup.dvdx = round_nearest(65536.0f * float(prim.texture.height) * fdvdx);
1845      setup.dudy = round_nearest(65536.0f * float(prim.texture.width) * fdudy);
1846      setup.dvdy = round_nearest(65536.0f * float(prim.texture.height) * fdvdy);
1847      setup.startu = round_nearest(65536.0f * float(prim.texture.width) * prim.texcoords.tl.u);
1848      setup.startv = round_nearest(65536.0f * float(prim.texture.height) * prim.texcoords.tl.v);
1849
1850      // advance U/V to the middle of the first texel
1851      setup.startu += (setup.dudx + setup.dudy) / 2;
1852      setup.startv += (setup.dvdx + setup.dvdy) / 2;
1853
1854      // if we're bilinear filtering, we need to offset u/v by half a texel
1855      if (_BilinearFilter)
1856      {
1857         setup.startu -= 0x8000;
1858         setup.startv -= 0x8000;
1859      }
1860
1861      // render based on the texture coordinates
1862      switch (prim.flags & (PRIMFLAG_TEXFORMAT_MASK | PRIMFLAG_BLENDMODE_MASK))
1863      {
1864         case PRIMFLAG_TEXFORMAT(TEXFORMAT_PALETTE16) | PRIMFLAG_BLENDMODE(BLENDMODE_NONE):
1865         case PRIMFLAG_TEXFORMAT(TEXFORMAT_PALETTE16) | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA):
1866            draw_quad_palette16_none(prim, dstdata, pitch, setup);
1867            break;
1868
1869         case PRIMFLAG_TEXFORMAT(TEXFORMAT_PALETTE16) | PRIMFLAG_BLENDMODE(BLENDMODE_ADD):
1870            draw_quad_palette16_add(prim, dstdata, pitch, setup);
1871            break;
1872
1873         case PRIMFLAG_TEXFORMAT(TEXFORMAT_PALETTEA16) | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA):
1874            draw_quad_palettea16_alpha(prim, dstdata, pitch, setup);
1875            break;
1876
1877         case PRIMFLAG_TEXFORMAT(TEXFORMAT_YUY16) | PRIMFLAG_BLENDMODE(BLENDMODE_NONE):
1878            draw_quad_yuy16_none(prim, dstdata, pitch, setup);
1879            break;
1880
1881         case PRIMFLAG_TEXFORMAT(TEXFORMAT_RGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_NONE):
1882         case PRIMFLAG_TEXFORMAT(TEXFORMAT_RGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA):
1883         case PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_NONE):
1884            draw_quad_rgb32(prim, dstdata, pitch, setup);
1885            break;
1886
1887         case PRIMFLAG_TEXFORMAT(TEXFORMAT_RGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_ADD):
1888            draw_quad_rgb32_add(prim, dstdata, pitch, setup);
1889            break;
1890
1891         case PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA):
1892            draw_quad_argb32_alpha(prim, dstdata, pitch, setup);
1893            break;
1894
1895         case PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_RGB_MULTIPLY):
1896            draw_quad_argb32_multiply(prim, dstdata, pitch, setup);
1897            break;
1898
1899         case PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_ADD):
1900            draw_quad_argb32_add(prim, dstdata, pitch, setup);
1901            break;
1902
1903         default:
1904            fatalerror("Unknown texformat(%d)/blendmode(%d) combo\n", PRIMFLAG_GET_TEXFORMAT(prim.flags), PRIMFLAG_GET_BLENDMODE(prim.flags));
1905            break;
1906      }
1907   }
1908
1909
1910   //**************************************************************************
1911   //  PRIMARY ENTRY POINT
1912   //**************************************************************************
1913
1914   //-------------------------------------------------
1915   //  draw_primitives - draw a series of primitives
1916   //  using a software rasterizer
1917   //-------------------------------------------------
1918
1919public:
1920   static void draw_primitives(const render_primitive_list &primlist, void *dstdata, UINT32 width, UINT32 height, UINT32 pitch)
1921   {
1922      // loop over the list and render each element
1923      for (const render_primitive *prim = primlist.first(); prim != NULL; prim = prim->next())
1924         switch (prim->type)
1925         {
1926            case render_primitive::LINE:
1927               draw_line(*prim, reinterpret_cast<_PixelType *>(dstdata), width, height, pitch);
1928               break;
1929
1930            case render_primitive::QUAD:
1931               if (!prim->texture.base)
1932                  draw_rect(*prim, reinterpret_cast<_PixelType *>(dstdata), width, height, pitch);
1933               else
1934                  setup_and_draw_textured_quad(*prim, reinterpret_cast<_PixelType *>(dstdata), width, height, pitch);
1935               break;
1936
1937            default:
1938               throw emu_fatalerror("Unexpected render_primitive type");
1939         }
1940   }
1941};
trunk/src/emu/rendersw.inc
r0r28728
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles
3/***************************************************************************
4
5    rendersw.inc
6
7    Software-only rasterization system.
8
9***************************************************************************/
10
11
12#include "emucore.h"
13#include "eminline.h"
14#include "video/rgbutil.h"
15#include "render.h"
16
17
18template<typename _PixelType, int _SrcShiftR, int _SrcShiftG, int _SrcShiftB, int _DstShiftR, int _DstShiftG, int _DstShiftB, bool _NoDestRead = false, bool _BilinearFilter = false>
19class software_renderer
20{
21private:
22   // internal structs
23   struct quad_setup_data
24   {
25      INT32           dudx, dvdx, dudy, dvdy;
26      INT32           startu, startv;
27      INT32           startx, starty;
28      INT32           endx, endy;
29   };
30
31   // internal helpers
32   static inline bool is_opaque(float alpha) { return (alpha >= (_NoDestRead ? 0.5f : 1.0f)); }
33   static inline bool is_transparent(float alpha) { return (alpha < (_NoDestRead ? 0.5f : 0.0001f)); }
34   static inline rgb_t apply_intensity(int intensity, rgb_t color) { return color.scale8(intensity); }
35   static inline float round_nearest(float f) { return floor(f + 0.5f); }
36
37   // destination pixels are written based on the values of the template parameters
38   static inline _PixelType dest_assemble_rgb(UINT32 r, UINT32 g, UINT32 b) { return (r << _DstShiftR) | (g << _DstShiftG) | (b << _DstShiftB); }
39   static inline _PixelType dest_rgb_to_pixel(UINT32 r, UINT32 g, UINT32 b) { return dest_assemble_rgb(r >> _SrcShiftR, g >> _SrcShiftG, b >> _SrcShiftB); }
40
41   // source 32-bit pixels are in MAME standardized format
42   static inline UINT32 source32_r(rgb_t pixel) { return (pixel >> (16 + _SrcShiftR)) & (0xff >> _SrcShiftR); }
43   static inline UINT32 source32_g(rgb_t pixel) { return (pixel >> ( 8 + _SrcShiftG)) & (0xff >> _SrcShiftG); }
44   static inline UINT32 source32_b(rgb_t pixel) { return (pixel >> ( 0 + _SrcShiftB)) & (0xff >> _SrcShiftB); }
45
46   // destination pixel masks are based on the template parameters as well
47   static inline UINT32 dest_r(_PixelType pixel) { return (pixel >> _DstShiftR) & (0xff >> _SrcShiftR); }
48   static inline UINT32 dest_g(_PixelType pixel) { return (pixel >> _DstShiftG) & (0xff >> _SrcShiftG); }
49   static inline UINT32 dest_b(_PixelType pixel) { return (pixel >> _DstShiftB) & (0xff >> _SrcShiftB); }
50
51   // generic conversion with special optimization for destinations in the standard format
52   static inline _PixelType source32_to_dest(rgb_t pixel)
53   {
54      if (_SrcShiftR == 0 && _SrcShiftG == 0 && _SrcShiftB == 0 && _DstShiftR == 16 && _DstShiftG == 8 && _DstShiftB == 0)
55         return pixel;
56      else
57         return dest_assemble_rgb(source32_r(pixel), source32_g(pixel), source32_b(pixel));
58   }
59
60
61   //-------------------------------------------------
62   //  ycc_to_rgb - convert YCC to RGB; the YCC pixel
63   //  contains Y in the LSB, Cb << 8, and Cr << 16
64   //  This actually a YCbCr conversion,
65   //  details my be found in chapter 6.4 ff of
66   //  http://softwarecommunity.intel.com/isn/downloads/softwareproducts/pdfs/346495.pdf
67   //  The document also contains the constants below as floats.
68   //-------------------------------------------------
69
70   static inline UINT32 clamp16_shift8(UINT32 x)
71   {
72      return ((INT32(x) < 0) ? 0 : (x > 65535 ? 255: x >> 8));
73   }
74
75   static inline UINT32 ycc_to_rgb(UINT32 ycc)
76   {
77      // original equations:
78      //
79      //  C = Y - 16
80      //  D = Cb - 128
81      //  E = Cr - 128
82      //
83      //  R = clip(( 298 * C           + 409 * E + 128) >> 8)
84      //  G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8)
85      //  B = clip(( 298 * C + 516 * D           + 128) >> 8)
86      //
87      //  R = clip(( 298 * (Y - 16)                    + 409 * (Cr - 128) + 128) >> 8)
88      //  G = clip(( 298 * (Y - 16) - 100 * (Cb - 128) - 208 * (Cr - 128) + 128) >> 8)
89      //  B = clip(( 298 * (Y - 16) + 516 * (Cb - 128)                    + 128) >> 8)
90      //
91      //  R = clip(( 298 * Y - 298 * 16                        + 409 * Cr - 409 * 128 + 128) >> 8)
92      //  G = clip(( 298 * Y - 298 * 16 - 100 * Cb + 100 * 128 - 208 * Cr + 208 * 128 + 128) >> 8)
93      //  B = clip(( 298 * Y - 298 * 16 + 516 * Cb - 516 * 128                        + 128) >> 8)
94      //
95      //  R = clip(( 298 * Y - 298 * 16                        + 409 * Cr - 409 * 128 + 128) >> 8)
96      //  G = clip(( 298 * Y - 298 * 16 - 100 * Cb + 100 * 128 - 208 * Cr + 208 * 128 + 128) >> 8)
97      //  B = clip(( 298 * Y - 298 * 16 + 516 * Cb - 516 * 128                        + 128) >> 8)
98      //
99      //  Now combine constants:
100      //
101      //  R = clip(( 298 * Y            + 409 * Cr - 56992) >> 8)
102      //  G = clip(( 298 * Y - 100 * Cb - 208 * Cr + 34784) >> 8)
103      //  B = clip(( 298 * Y + 516 * Cb            - 70688) >> 8)
104      //
105      //  Define common = 298 * y - 56992. This will save one addition
106      //
107      //  R = clip(( common            + 409 * Cr -     0) >> 8)
108      //  G = clip(( common - 100 * Cb - 208 * Cr + 91776) >> 8)
109      //  B = clip(( common + 516 * Cb            - 13696) >> 8)
110      //
111
112      UINT8 y = ycc;
113      UINT8 cb = ycc >> 8;
114      UINT8 cr = ycc >> 16;
115
116      UINT32 common = 298 * y - 56992;
117      UINT32 r = (common +            409 * cr);
118      UINT32 g = (common - 100 * cb - 208 * cr + 91776);
119      UINT32 b = (common + 516 * cb - 13696);
120
121      // Now clamp and shift back
122      return rgb_t(clamp16_shift8(r), clamp16_shift8(g), clamp16_shift8(b));
123   }
124
125
126   //-------------------------------------------------
127   //  get_texel_palette16 - return a texel from a
128   //  palettized 16bpp source
129   //-------------------------------------------------
130
131   static inline UINT32 get_texel_palette16(const render_texinfo &texture, INT32 curu, INT32 curv)
132   {
133      if (_BilinearFilter)
134      {
135         INT32 u0 = curu >> 16;
136         INT32 u1 = 1;
137         if (u0 < 0) u0 = u1 = 0;
138         else if (u0 + 1 >= texture.width) u0 = texture.width - 1, u1 = 0;
139         INT32 v0 = curv >> 16;
140         INT32 v1 = texture.rowpixels;
141         if (v0 < 0) v0 = v1 = 0;
142         else if (v0 + 1 >= texture.height) v0 = texture.height - 1, v1 = 0;
143
144         const UINT16 *texbase = reinterpret_cast<const UINT16 *>(texture.base);
145         texbase += v0 * texture.rowpixels + u0;
146
147         rgb_t pix00 = texture.palette[texbase[0]];
148         rgb_t pix01 = texture.palette[texbase[u1]];
149         rgb_t pix10 = texture.palette[texbase[v1]];
150         rgb_t pix11 = texture.palette[texbase[u1 + v1]];
151         return rgb_bilinear_filter(pix00, pix01, pix10, pix11, curu >> 8, curv >> 8);
152      }
153      else
154      {
155         const UINT16 *texbase = reinterpret_cast<const UINT16 *>(texture.base) + (curv >> 16) * texture.rowpixels + (curu >> 16);
156         return texture.palette[texbase[0]];
157      }
158   }
159
160
161   //-------------------------------------------------
162   //  get_texel_palette16a - return a texel from a
163   //  palettized 16bpp source with alpha
164   //-------------------------------------------------
165
166   static inline UINT32 get_texel_palette16a(const render_texinfo &texture, INT32 curu, INT32 curv)
167   {
168      if (_BilinearFilter)
169      {
170         INT32 u0 = curu >> 16;
171         INT32 u1 = 1;
172         if (u0 < 0) u0 = u1 = 0;
173         else if (u0 + 1 >= texture.width) u0 = texture.width - 1, u1 = 0;
174         INT32 v0 = curv >> 16;
175         INT32 v1 = texture.rowpixels;
176         if (v0 < 0) v0 = v1 = 0;
177         else if (v0 + 1 >= texture.height) v0 = texture.height - 1, v1 = 0;
178
179         const UINT16 *texbase = reinterpret_cast<const UINT16 *>(texture.base);
180         texbase += v0 * texture.rowpixels + u0;
181
182         rgb_t pix00 = texture.palette[texbase[0]];
183         rgb_t pix01 = texture.palette[texbase[u1]];
184         rgb_t pix10 = texture.palette[texbase[v1]];
185         rgb_t pix11 = texture.palette[texbase[u1 + v1]];
186         return rgba_bilinear_filter(pix00, pix01, pix10, pix11, curu >> 8, curv >> 8);
187      }
188      else
189      {
190         const UINT16 *texbase = reinterpret_cast<const UINT16 *>(texture.base) + (curv >> 16) * texture.rowpixels + (curu >> 16);
191         return texture.palette[texbase[0]];
192      }
193   }
194
195
196   //-------------------------------------------------
197   //  get_texel_yuy16 - return a texel from a 16bpp
198   //  YCbCr source (pixel is returned as Cr-Cb-Y)
199   //-------------------------------------------------
200
201   static inline UINT32 get_texel_yuy16(const render_texinfo &texture, INT32 curu, INT32 curv)
202   {
203      if (_BilinearFilter)
204      {
205         INT32 u0 = curu >> 16;
206         INT32 u1 = 1;
207         if (u0 < 0) u0 = u1 = 0;
208         else if (u0 + 1 >= texture.width) u0 = texture.width - 1, u1 = 0;
209         INT32 v0 = curv >> 16;
210         INT32 v1 = texture.rowpixels;
211         if (v0 < 0) v0 = v1 = 0;
212         else if (v0 + 1 >= texture.height) v0 = texture.height - 1, v1 = 0;
213
214         const UINT16 *texbase = reinterpret_cast<const UINT16 *>(texture.base);
215         texbase += v0 * texture.rowpixels + (u0 & ~1);
216
217         rgb_t pix00, pix01, pix10, pix11;
218         if ((curu & 0x10000) == 0)
219         {
220            rgb_t cbcr = ((texbase[0] & 0xff) << 8) | ((texbase[1] & 0xff) << 16);
221            pix00 = (texbase[0] >> 8) | cbcr;
222            pix01 = (texbase[u1] >> 8) | cbcr;
223            cbcr = ((texbase[v1 + 0] & 0xff) << 8) | ((texbase[v1 + 1] & 0xff) << 16);
224            pix10 = (texbase[v1 + 0] >> 8) | cbcr;
225            pix11 = (texbase[v1 + u1] >> 8) | cbcr;
226         }
227         else
228         {
229            rgb_t cbcr = ((texbase[0] & 0xff) << 8) | ((texbase[1] & 0xff) << 16);
230            pix00 = (texbase[1] >> 8) | cbcr;
231            if (u1 != 0)
232            {
233               cbcr = ((texbase[2] & 0xff) << 8) | ((texbase[3] & 0xff) << 16);
234               pix01 = (texbase[2] >> 8) | cbcr;
235            }
236            else
237               pix01 = pix00;
238            cbcr = ((texbase[v1 + 0] & 0xff) << 8) | ((texbase[v1 + 1] & 0xff) << 16);
239            pix10 = (texbase[v1 + 1] >> 8) | cbcr;
240            if (u1 != 0)
241            {
242               cbcr = ((texbase[v1 + 2] & 0xff) << 8) | ((texbase[v1 + 3] & 0xff) << 16);
243               pix11 = (texbase[v1 + 2] >> 8) | cbcr;
244            }
245            else
246               pix11 = pix10;
247         }
248         return rgb_bilinear_filter(pix00, pix01, pix10, pix11, curu >> 8, curv >> 8);
249      }
250      else
251      {
252         const UINT16 *texbase = reinterpret_cast<const UINT16 *>(texture.base) + (curv >> 16) * texture.rowpixels + (curu >> 17) * 2;
253         return (texbase[(curu >> 16) & 1] >> 8) | ((texbase[0] & 0xff) << 8) | ((texbase[1] & 0xff) << 16);
254      }
255   }
256
257
258   //-------------------------------------------------
259   //  get_texel_rgb32 - return a texel from a 32bpp
260   //  RGB source
261   //-------------------------------------------------
262
263   static inline UINT32 get_texel_rgb32(const render_texinfo &texture, INT32 curu, INT32 curv)
264   {
265      if (_BilinearFilter)
266      {
267         INT32 u0 = curu >> 16;
268         INT32 u1 = 1;
269         if (u0 < 0) u0 = u1 = 0;
270         else if (u0 + 1 >= texture.width) u0 = texture.width - 1, u1 = 0;
271         INT32 v0 = curv >> 16;
272         INT32 v1 = texture.rowpixels;
273         if (v0 < 0) v0 = v1 = 0;
274         else if (v0 + 1 >= texture.height) v0 = texture.height - 1, v1 = 0;
275
276         const UINT32 *texbase = reinterpret_cast<const UINT32 *>(texture.base);
277         texbase += v0 * texture.rowpixels + u0;
278
279         rgb_t pix00 = texbase[0];
280         rgb_t pix01 = texbase[u1];
281         rgb_t pix10 = texbase[v1];
282         rgb_t pix11 = texbase[u1 + v1];
283         return rgb_bilinear_filter(pix00, pix01, pix10, pix11, curu >> 8, curv >> 8);
284      }
285      else
286      {
287         const UINT32 *texbase = reinterpret_cast<const UINT32 *>(texture.base) + (curv >> 16) * texture.rowpixels + (curu >> 16);
288         return texbase[0];
289      }
290   }
291
292
293   //-------------------------------------------------
294   //  get_texel_argb32 - return a texel from a 32bpp
295   //  ARGB source
296   //-------------------------------------------------
297
298   static inline UINT32 get_texel_argb32(const render_texinfo &texture, INT32 curu, INT32 curv)
299   {
300      if (_BilinearFilter)
301      {
302         INT32 u0 = curu >> 16;
303         INT32 u1 = 1;
304         if (u0 < 0) u0 = u1 = 0;
305         else if (u0 + 1 >= texture.width) u0 = texture.width - 1, u1 = 0;
306         INT32 v0 = curv >> 16;
307         INT32 v1 = texture.rowpixels;
308         if (v0 < 0) v0 = v1 = 0;
309         else if (v0 + 1 >= texture.height) v0 = texture.height - 1, v1 = 0;
310
311         const UINT32 *texbase = reinterpret_cast<const UINT32 *>(texture.base);
312         texbase += v0 * texture.rowpixels + u0;
313
314         rgb_t pix00 = texbase[0];
315         rgb_t pix01 = texbase[u1];
316         rgb_t pix10 = texbase[v1];
317         rgb_t pix11 = texbase[u1 + v1];
318         return rgba_bilinear_filter(pix00, pix01, pix10, pix11, curu >> 8, curv >> 8);
319      }
320      else
321      {
322         const UINT32 *texbase = reinterpret_cast<const UINT32 *>(texture.base) + (curv >> 16) * texture.rowpixels + (curu >> 16);
323         return texbase[0];
324      }
325   }
326
327
328   //-------------------------------------------------
329   //  draw_aa_pixel - draw an antialiased pixel
330   //-------------------------------------------------
331
332   static inline void draw_aa_pixel(_PixelType *dstdata, UINT32 pitch, int x, int y, rgb_t col)
333   {
334      _PixelType *dest = dstdata + y * pitch + x;
335      UINT32 dpix = _NoDestRead ? 0 : *dest;
336      UINT32 dr = source32_r(col) + dest_r(dpix);
337      UINT32 dg = source32_g(col) + dest_g(dpix);
338      UINT32 db = source32_b(col) + dest_b(dpix);
339      dr = (dr | -(dr >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
340      dg = (dg | -(dg >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
341      db = (db | -(db >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
342      *dest = dest_assemble_rgb(dr, dg, db);
343   }
344
345
346   //-------------------------------------------------
347   //  draw_line - draw a line or point
348   //-------------------------------------------------
349
350   static void draw_line(const render_primitive &prim, _PixelType *dstdata, INT32 width, INT32 height, UINT32 pitch)
351   {
352      // internal tables
353      static UINT32 s_cosine_table[2049];
354
355      // compute the start/end coordinates
356      int x1 = int(prim.bounds.x0 * 65536.0f);
357      int y1 = int(prim.bounds.y0 * 65536.0f);
358      int x2 = int(prim.bounds.x1 * 65536.0f);
359      int y2 = int(prim.bounds.y1 * 65536.0f);
360
361      // handle color and intensity
362      UINT32 col = rgb_t(int(255.0f * prim.color.r * prim.color.a), int(255.0f * prim.color.g * prim.color.a), int(255.0f * prim.color.b * prim.color.a));
363
364      if (PRIMFLAG_GET_ANTIALIAS(prim.flags))
365      {
366         // build up the cosine table if we haven't yet
367         if (s_cosine_table[0] == 0)
368            for (int entry = 0; entry <= 2048; entry++)
369               s_cosine_table[entry] = int(double(1.0 / cos(atan(double(entry) / 2048.0))) * 0x10000000 + 0.5);
370
371         int beam = prim.width * 65536.0f;
372         if (beam < 0x00010000)
373            beam = 0x00010000;
374
375         // draw an anti-aliased line
376         int dx = abs(x1 - x2);
377         int dy = abs(y1 - y2);
378
379         if (dx >= dy)
380         {
381            int sx = ((x1 <= x2) ? 1 : -1);
382            int sy = (dy == 0) ? 0 : div_32x32_shift(y2 - y1, dx, 16);
383            if (sy < 0)
384               dy--;
385            x1 >>= 16;
386            int xx = x2 >> 16;
387            int bwidth = mul_32x32_hi(beam << 4, s_cosine_table[abs(sy) >> 5]);
388            y1 -= bwidth >> 1; // start back half the diameter
389            for (;;)
390            {
391               if (x1 >= 0 && x1 < width)
392               {
393                  dx = bwidth;    // init diameter of beam
394                  dy = y1 >> 16;
395                  if (dy >= 0 && dy < height)
396                     draw_aa_pixel(dstdata, pitch, x1, dy, apply_intensity(0xff & (~y1 >> 8), col));
397                  dy++;
398                  dx -= 0x10000 - (0xffff & y1); // take off amount plotted
399                  UINT8 a1 = (dx >> 8) & 0xff;   // calc remainder pixel
400                  dx >>= 16;                   // adjust to pixel (solid) count
401                  while (dx--)                 // plot rest of pixels
402                  {
403                     if (dy >= 0 && dy < height)
404                        draw_aa_pixel(dstdata, pitch, x1, dy, col);
405                     dy++;
406                  }
407                  if (dy >= 0 && dy < height)
408                     draw_aa_pixel(dstdata, pitch, x1, dy, apply_intensity(a1,col));
409               }
410               if (x1 == xx) break;
411               x1 += sx;
412               y1 += sy;
413            }
414         }
415         else
416         {
417            int sy = ((y1 <= y2) ? 1: -1);
418            int sx = (dx == 0) ? 0 : div_32x32_shift(x2 - x1, dy, 16);
419            if (sx < 0)
420               dx--;
421            y1 >>= 16;
422            int yy = y2 >> 16;
423            int bwidth = mul_32x32_hi(beam << 4,s_cosine_table[abs(sx) >> 5]);
424            x1 -= bwidth >> 1; // start back half the width
425            for (;;)
426            {
427               if (y1 >= 0 && y1 < height)
428               {
429                  dy = bwidth;    // calc diameter of beam
430                  dx = x1 >> 16;
431                  if (dx >= 0 && dx < width)
432                     draw_aa_pixel(dstdata, pitch, dx, y1, apply_intensity(0xff & (~x1 >> 8), col));
433                  dx++;
434                  dy -= 0x10000 - (0xffff & x1); // take off amount plotted
435                  UINT8 a1 = (dy >> 8) & 0xff;   // remainder pixel
436                  dy >>= 16;                   // adjust to pixel (solid) count
437                  while (dy--)                 // plot rest of pixels
438                  {
439                     if (dx >= 0 && dx < width)
440                        draw_aa_pixel(dstdata, pitch, dx, y1, col);
441                     dx++;
442                  }
443                  if (dx >= 0 && dx < width)
444                     draw_aa_pixel(dstdata, pitch, dx, y1, apply_intensity(a1, col));
445               }
446               if (y1 == yy) break;
447               y1 += sy;
448               x1 += sx;
449            }
450         }
451      }
452      else // use good old Bresenham for non-antialiasing 980317 BW
453      {
454         x1 = (x1 + 0x8000) >> 16;
455         y1 = (y1 + 0x8000) >> 16;
456         x2 = (x2 + 0x8000) >> 16;
457         y2 = (y2 + 0x8000) >> 16;
458
459         int dx = abs(x1 - x2);
460         int dy = abs(y1 - y2);
461         int sx = (x1 <= x2) ? 1 : -1;
462         int sy = (y1 <= y2) ? 1 : -1;
463         int cx = dx / 2;
464         int cy = dy / 2;
465
466         if (dx >= dy)
467         {
468            for (;;)
469            {
470               if (x1 >= 0 && x1 < width && y1 >= 0 && y1 < height)
471                  draw_aa_pixel(dstdata, pitch, x1, y1, col);
472               if (x1 == x2) break;
473               x1 += sx;
474               cx -= dy;
475               if (cx < 0)
476               {
477                  y1 += sy;
478                  cx += dx;
479               }
480            }
481         }
482         else
483         {
484            for (;;)
485            {
486               if (x1 >= 0 && x1 < width && y1 >= 0 && y1 < height)
487                  draw_aa_pixel(dstdata, pitch, x1, y1, col);
488               if (y1 == y2) break;
489               y1 += sy;
490               cy -= dx;
491               if (cy < 0)
492               {
493                  x1 += sx;
494                  cy += dy;
495               }
496            }
497         }
498      }
499   }
500
501
502
503   //**************************************************************************
504   //  RECT RASTERIZERS
505   //**************************************************************************
506
507   //-------------------------------------------------
508   //  draw_rect - draw a solid rectangle
509   //-------------------------------------------------
510
511   static void draw_rect(const render_primitive &prim, _PixelType *dstdata, INT32 width, INT32 height, UINT32 pitch)
512   {
513      render_bounds fpos = prim.bounds;
514      assert(fpos.x0 <= fpos.x1);
515      assert(fpos.y0 <= fpos.y1);
516
517      // clamp to integers
518      INT32 startx = round_nearest(fpos.x0);
519      INT32 starty = round_nearest(fpos.y0);
520      INT32 endx = round_nearest(fpos.x1);
521      INT32 endy = round_nearest(fpos.y1);
522
523      // ensure we fit
524      if (startx < 0) startx = 0;
525      if (startx >= width) startx = width;
526      if (endx < 0) endx = 0;
527      if (endx >= width) endx = width;
528      if (starty < 0) starty = 0;
529      if (starty >= height) starty = height;
530      if (endy < 0) endy = 0;
531      if (endy >= height) endy = height;
532
533      // bail if nothing left
534      if (fpos.x0 > fpos.x1 || fpos.y0 > fpos.y1)
535         return;
536
537      // only support alpha and "none" blendmodes
538      assert(PRIMFLAG_GET_BLENDMODE(prim.flags) == BLENDMODE_NONE ||
539            PRIMFLAG_GET_BLENDMODE(prim.flags) == BLENDMODE_ALPHA);
540
541      // fast case: no alpha
542      if (PRIMFLAG_GET_BLENDMODE(prim.flags) == BLENDMODE_NONE || is_opaque(prim.color.a))
543      {
544         UINT32 r = UINT32(256.0f * prim.color.r);
545         UINT32 g = UINT32(256.0f * prim.color.g);
546         UINT32 b = UINT32(256.0f * prim.color.b);
547         UINT32 pix;
548
549         // clamp R,G,B to 0-256 range
550         if (r > 0xff) { if (INT32(r) < 0) r = 0; else r = 0xff; }
551         if (g > 0xff) { if (INT32(g) < 0) g = 0; else g = 0xff; }
552         if (b > 0xff) { if (INT32(b) < 0) b = 0; else b = 0xff; }
553         pix = dest_rgb_to_pixel(r, g, b);
554
555         // loop over rows
556         for (INT32 y = starty; y < endy; y++)
557         {
558            _PixelType *dest = dstdata + y * pitch + startx;
559
560            // loop over cols
561            for (INT32 x = startx; x < endx; x++)
562               *dest++ = pix;
563         }
564      }
565
566      // alpha and/or coloring case
567      else if (!is_transparent(prim.color.a))
568      {
569         UINT32 rmask = dest_rgb_to_pixel(0xff,0x00,0x00);
570         UINT32 gmask = dest_rgb_to_pixel(0x00,0xff,0x00);
571         UINT32 bmask = dest_rgb_to_pixel(0x00,0x00,0xff);
572         UINT32 r = UINT32(256.0f * prim.color.r * prim.color.a);
573         UINT32 g = UINT32(256.0f * prim.color.g * prim.color.a);
574         UINT32 b = UINT32(256.0f * prim.color.b * prim.color.a);
575         UINT32 inva = UINT32(256.0f * (1.0f - prim.color.a));
576
577         // clamp R,G,B and inverse A to 0-256 range
578         if (r > 0xff) { if (INT32(r) < 0) r = 0; else r = 0xff; }
579         if (g > 0xff) { if (INT32(g) < 0) g = 0; else g = 0xff; }
580         if (b > 0xff) { if (INT32(b) < 0) b = 0; else b = 0xff; }
581         if (inva > 0x100) { if (INT32(inva) < 0) inva = 0; else inva = 0x100; }
582
583         // pre-shift the RGBA pieces
584         r = dest_rgb_to_pixel(r, 0, 0) << 8;
585         g = dest_rgb_to_pixel(0, g, 0) << 8;
586         b = dest_rgb_to_pixel(0, 0, b) << 8;
587
588         // loop over rows
589         for (INT32 y = starty; y < endy; y++)
590         {
591            _PixelType *dest = dstdata + y * pitch + startx;
592
593            // loop over cols
594            for (INT32 x = startx; x < endx; x++)
595            {
596               UINT32 dpix = _NoDestRead ? 0 : *dest;
597               UINT32 dr = (r + ((dpix & rmask) * inva)) & (rmask << 8);
598               UINT32 dg = (g + ((dpix & gmask) * inva)) & (gmask << 8);
599               UINT32 db = (b + ((dpix & bmask) * inva)) & (bmask << 8);
600               *dest++ = (dr | dg | db) >> 8;
601            }
602         }
603      }
604   }
605
606
607   //**************************************************************************
608   //  16-BIT PALETTE RASTERIZERS
609   //**************************************************************************
610
611   //-------------------------------------------------
612   //  draw_quad_palette16_none - perform
613   //  rasterization of a 16bpp palettized texture
614   //-------------------------------------------------
615
616   static void draw_quad_palette16_none(const render_primitive &prim, _PixelType *dstdata, UINT32 pitch, quad_setup_data &setup)
617   {
618      INT32 dudx = setup.dudx;
619      INT32 dvdx = setup.dvdx;
620      INT32 endx = setup.endx;
621
622      // ensure all parameters are valid
623      assert(prim.texture.palette != NULL);
624
625      // fast case: no coloring, no alpha
626      if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a))
627      {
628         // loop over rows
629         for (INT32 y = setup.starty; y < setup.endy; y++)
630         {
631            _PixelType *dest = dstdata + y * pitch + setup.startx;
632            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
633            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
634
635            // loop over cols
636            for (INT32 x = setup.startx; x < endx; x++)
637            {
638               UINT32 pix = get_texel_palette16(prim.texture, curu, curv);
639               *dest++ = source32_to_dest(pix);
640               curu += dudx;
641               curv += dvdx;
642            }
643         }
644      }
645
646      // coloring-only case
647      else if (is_opaque(prim.color.a))
648      {
649         UINT32 sr = UINT32(256.0f * prim.color.r);
650         UINT32 sg = UINT32(256.0f * prim.color.g);
651         UINT32 sb = UINT32(256.0f * prim.color.b);
652
653         // clamp R,G,B to 0-256 range
654         if (sr > 0x100) { if (INT32(sr) < 0) sr = 0; else sr = 0x100; }
655         if (sg > 0x100) { if (INT32(sg) < 0) sg = 0; else sg = 0x100; }
656         if (sb > 0x100) { if (INT32(sb) < 0) sb = 0; else sb = 0x100; }
657
658         // loop over rows
659         for (INT32 y = setup.starty; y < setup.endy; y++)
660         {
661            _PixelType *dest = dstdata + y * pitch + setup.startx;
662            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
663            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
664
665            // loop over cols
666            for (INT32 x = setup.startx; x < endx; x++)
667            {
668               UINT32 pix = get_texel_palette16(prim.texture, curu, curv);
669               UINT32 r = (source32_r(pix) * sr) >> 8;
670               UINT32 g = (source32_g(pix) * sg) >> 8;
671               UINT32 b = (source32_b(pix) * sb) >> 8;
672
673               *dest++ = dest_assemble_rgb(r, g, b);
674               curu += dudx;
675               curv += dvdx;
676            }
677         }
678      }
679
680      // alpha and/or coloring case
681      else if (!is_transparent(prim.color.a))
682      {
683         UINT32 sr = UINT32(256.0f * prim.color.r * prim.color.a);
684         UINT32 sg = UINT32(256.0f * prim.color.g * prim.color.a);
685         UINT32 sb = UINT32(256.0f * prim.color.b * prim.color.a);
686         UINT32 invsa = UINT32(256.0f * (1.0f - prim.color.a));
687
688         // clamp R,G,B and inverse A to 0-256 range
689         if (sr > 0x100) { if (INT32(sr) < 0) sr = 0; else sr = 0x100; }
690         if (sg > 0x100) { if (INT32(sg) < 0) sg = 0; else sg = 0x100; }
691         if (sb > 0x100) { if (INT32(sb) < 0) sb = 0; else sb = 0x100; }
692         if (invsa > 0x100) { if (INT32(invsa) < 0) invsa = 0; else invsa = 0x100; }
693
694         // loop over rows
695         for (INT32 y = setup.starty; y < setup.endy; y++)
696         {
697            _PixelType *dest = dstdata + y * pitch + setup.startx;
698            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
699            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
700
701            // loop over cols
702            for (INT32 x = setup.startx; x < endx; x++)
703            {
704               UINT32 pix = get_texel_palette16(prim.texture, curu, curv);
705               UINT32 dpix = _NoDestRead ? 0 : *dest;
706               UINT32 r = (source32_r(pix) * sr + dest_r(dpix) * invsa) >> 8;
707               UINT32 g = (source32_g(pix) * sg + dest_g(dpix) * invsa) >> 8;
708               UINT32 b = (source32_b(pix) * sb + dest_b(dpix) * invsa) >> 8;
709
710               *dest++ = dest_assemble_rgb(r, g, b);
711               curu += dudx;
712               curv += dvdx;
713            }
714         }
715      }
716   }
717
718
719   //-------------------------------------------------
720   //  draw_quad_palette16_add - perform
721   //  rasterization of a 16bpp palettized texture
722   //-------------------------------------------------
723
724   static void draw_quad_palette16_add(const render_primitive &prim, _PixelType *dstdata, UINT32 pitch, quad_setup_data &setup)
725   {
726      INT32 dudx = setup.dudx;
727      INT32 dvdx = setup.dvdx;
728      INT32 endx = setup.endx;
729
730      // ensure all parameters are valid
731      assert(prim.texture.palette != NULL);
732
733      // fast case: no coloring, no alpha
734      if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a))
735      {
736         // loop over rows
737         for (INT32 y = setup.starty; y < setup.endy; y++)
738         {
739            _PixelType *dest = dstdata + y * pitch + setup.startx;
740            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
741            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
742
743            // loop over cols
744            for (INT32 x = setup.startx; x < endx; x++)
745            {
746               UINT32 pix = get_texel_palette16(prim.texture, curu, curv);
747               if ((pix & 0xffffff) != 0)
748               {
749                  UINT32 dpix = _NoDestRead ? 0 : *dest;
750                  UINT32 r = source32_r(pix) + dest_r(dpix);
751                  UINT32 g = source32_g(pix) + dest_g(dpix);
752                  UINT32 b = source32_b(pix) + dest_b(dpix);
753                  r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
754                  g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
755                  b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
756                  *dest = dest_assemble_rgb(r, g, b);
757               }
758               dest++;
759               curu += dudx;
760               curv += dvdx;
761            }
762         }
763      }
764
765      // alpha and/or coloring case
766      else
767      {
768         UINT32 sr = UINT32(256.0f * prim.color.r * prim.color.a);
769         UINT32 sg = UINT32(256.0f * prim.color.g * prim.color.a);
770         UINT32 sb = UINT32(256.0f * prim.color.b * prim.color.a);
771
772         // clamp R,G,B and inverse A to 0-256 range
773         if (sr > 0x100) { if (INT32(sr) < 0) sr = 0; else sr = 0x100; }
774         if (sg > 0x100) { if (INT32(sg) < 0) sg = 0; else sg = 0x100; }
775         if (sb > 0x100) { if (INT32(sb) < 0) sb = 0; else sb = 0x100; }
776
777         // loop over rows
778         for (INT32 y = setup.starty; y < setup.endy; y++)
779         {
780            _PixelType *dest = dstdata + y * pitch + setup.startx;
781            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
782            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
783
784            // loop over cols
785            for (INT32 x = setup.startx; x < endx; x++)
786            {
787               UINT32 pix = get_texel_palette16(prim.texture, curu, curv);
788               if ((pix & 0xffffff) != 0)
789               {
790                  UINT32 dpix = _NoDestRead ? 0 : *dest;
791                  UINT32 r = ((source32_r(pix) * sr) >> 8) + dest_r(dpix);
792                  UINT32 g = ((source32_g(pix) * sg) >> 8) + dest_g(dpix);
793                  UINT32 b = ((source32_b(pix) * sb) >> 8) + dest_b(dpix);
794                  r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
795                  g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
796                  b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
797                  *dest++ = dest_assemble_rgb(r, g, b);
798                  curu += dudx;
799                  curv += dvdx;
800               }
801            }
802         }
803      }
804   }
805
806
807
808   //**************************************************************************
809   //  16-BIT ALPHA PALETTE RASTERIZERS
810   //**************************************************************************
811
812   //-------------------------------------------------
813   //  draw_quad_palettea16_alpha - perform
814   //  rasterization using standard alpha blending
815   //-------------------------------------------------
816
817   static void draw_quad_palettea16_alpha(const render_primitive &prim, _PixelType *dstdata, UINT32 pitch, quad_setup_data &setup)
818   {
819      INT32 dudx = setup.dudx;
820      INT32 dvdx = setup.dvdx;
821      INT32 endx = setup.endx;
822
823      // ensure all parameters are valid
824      assert(prim.texture.palette != NULL);
825
826      // fast case: no coloring, no alpha
827      if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a))
828      {
829         // loop over rows
830         for (INT32 y = setup.starty; y < setup.endy; y++)
831         {
832            _PixelType *dest = dstdata + y * pitch + setup.startx;
833            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
834            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
835
836            // loop over cols
837            for (INT32 x = setup.startx; x < endx; x++)
838            {
839               UINT32 pix = get_texel_palette16a(prim.texture, curu, curv);
840               UINT32 ta = pix >> 24;
841               if (ta != 0)
842               {
843                  UINT32 dpix = _NoDestRead ? 0 : *dest;
844                  UINT32 invta = 0x100 - ta;
845                  UINT32 r = (source32_r(pix) * ta + dest_r(dpix) * invta) >> 8;
846                  UINT32 g = (source32_g(pix) * ta + dest_g(dpix) * invta) >> 8;
847                  UINT32 b = (source32_b(pix) * ta + dest_b(dpix) * invta) >> 8;
848
849                  *dest = dest_assemble_rgb(r, g, b);
850               }
851               dest++;
852               curu += dudx;
853               curv += dvdx;
854            }
855         }
856      }
857
858      // alpha and/or coloring case
859      else
860      {
861         UINT32 sr = UINT32(256.0f * prim.color.r);
862         UINT32 sg = UINT32(256.0f * prim.color.g);
863         UINT32 sb = UINT32(256.0f * prim.color.b);
864         UINT32 sa = UINT32(256.0f * prim.color.a);
865
866         // clamp R,G,B and inverse A to 0-256 range
867         if (sr > 0x100) { if (INT32(sr) < 0) sr = 0; else sr = 0x100; }
868         if (sg > 0x100) { if (INT32(sg) < 0) sg = 0; else sg = 0x100; }
869         if (sb > 0x100) { if (INT32(sb) < 0) sb = 0; else sb = 0x100; }
870         if (sa > 0x100) { if (INT32(sa) < 0) sa = 0; else sa = 0x100; }
871
872         // loop over rows
873         for (INT32 y = setup.starty; y < setup.endy; y++)
874         {
875            _PixelType *dest = dstdata + y * pitch + setup.startx;
876            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
877            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
878
879            // loop over cols
880            for (INT32 x = setup.startx; x < endx; x++)
881            {
882               UINT32 pix = get_texel_palette16a(prim.texture, curu, curv);
883               UINT32 ta = (pix >> 24) * sa;
884               if (ta != 0)
885               {
886                  UINT32 dpix = _NoDestRead ? 0 : *dest;
887                  UINT32 invsta = (0x10000 - ta) << 8;
888                  UINT32 r = (source32_r(pix) * sr * ta + dest_r(dpix) * invsta) >> 24;
889                  UINT32 g = (source32_g(pix) * sg * ta + dest_g(dpix) * invsta) >> 24;
890                  UINT32 b = (source32_b(pix) * sb * ta + dest_b(dpix) * invsta) >> 24;
891
892                  *dest = dest_assemble_rgb(r, g, b);
893               }
894               dest++;
895               curu += dudx;
896               curv += dvdx;
897            }
898         }
899      }
900   }
901
902
903
904   //**************************************************************************
905   //  16-BIT YUY RASTERIZERS
906   //**************************************************************************
907
908   //-------------------------------------------------
909   //  draw_quad_yuy16_none - perform
910   //  rasterization of a 16bpp YUY image
911   //-------------------------------------------------
912
913   static void draw_quad_yuy16_none(const render_primitive &prim, _PixelType *dstdata, UINT32 pitch, quad_setup_data &setup)
914   {
915      const rgb_t *palbase = prim.texture.palette;
916      INT32 dudx = setup.dudx;
917      INT32 dvdx = setup.dvdx;
918      INT32 endx = setup.endx;
919
920      // fast case: no coloring, no alpha
921      if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a))
922      {
923         // loop over rows
924         for (INT32 y = setup.starty; y < setup.endy; y++)
925         {
926            _PixelType *dest = dstdata + y * pitch + setup.startx;
927            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
928            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
929
930            // no lookup case
931            if (palbase == NULL)
932            {
933               // loop over cols
934               for (INT32 x = setup.startx; x < endx; x++)
935               {
936                  UINT32 pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv));
937                  *dest++ = source32_to_dest(pix);
938                  curu += dudx;
939                  curv += dvdx;
940               }
941            }
942
943            // lookup case
944            else
945            {
946               // loop over cols
947               for (INT32 x = setup.startx; x < endx; x++)
948               {
949                  UINT32 pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv));
950                  *dest++ = source32_to_dest(pix);
951                  curu += dudx;
952                  curv += dvdx;
953               }
954            }
955         }
956      }
957
958      // coloring-only case
959      else if (is_opaque(prim.color.a))
960      {
961         UINT32 sr = UINT32(256.0f * prim.color.r);
962         UINT32 sg = UINT32(256.0f * prim.color.g);
963         UINT32 sb = UINT32(256.0f * prim.color.b);
964
965         // clamp R,G,B to 0-256 range
966         if (sr > 0x100) { if (INT32(sr) < 0) sr = 0; else sr = 0x100; }
967         if (sg > 0x100) { if (INT32(sg) < 0) sg = 0; else sg = 0x100; }
968         if (sb > 0x100) { if (INT32(sb) < 0) sb = 0; else sb = 0x100; }
969
970         // loop over rows
971         for (INT32 y = setup.starty; y < setup.endy; y++)
972         {
973            _PixelType *dest = dstdata + y * pitch + setup.startx;
974            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
975            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
976
977            // no lookup case
978            if (palbase == NULL)
979            {
980               // loop over cols
981               for (INT32 x = setup.startx; x < endx; x++)
982               {
983                  UINT32 pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv));
984                  UINT32 r = (source32_r(pix) * sr) >> 8;
985                  UINT32 g = (source32_g(pix) * sg) >> 8;
986                  UINT32 b = (source32_b(pix) * sb) >> 8;
987
988                  *dest++ = dest_assemble_rgb(r, g, b);
989                  curu += dudx;
990                  curv += dvdx;
991               }
992            }
993
994            // lookup case
995            else
996            {
997               // loop over cols
998               for (INT32 x = setup.startx; x < endx; x++)
999               {
1000                  UINT32 pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv));
1001                  UINT32 r = (source32_r(pix) * sr) >> 8;
1002                  UINT32 g = (source32_g(pix) * sg) >> 8;
1003                  UINT32 b = (source32_b(pix) * sb) >> 8;
1004
1005                  *dest++ = dest_assemble_rgb(r, g, b);
1006                  curu += dudx;
1007                  curv += dvdx;
1008               }
1009            }
1010         }
1011      }
1012
1013      // alpha and/or coloring case
1014      else if (!is_transparent(prim.color.a))
1015      {
1016         UINT32 sr = UINT32(256.0f * prim.color.r * prim.color.a);
1017         UINT32 sg = UINT32(256.0f * prim.color.g * prim.color.a);
1018         UINT32 sb = UINT32(256.0f * prim.color.b * prim.color.a);
1019         UINT32 invsa = UINT32(256.0f * (1.0f - prim.color.a));
1020
1021         // clamp R,G,B and inverse A to 0-256 range
1022         if (sr > 0x100) { if (INT32(sr) < 0) sr = 0; else sr = 0x100; }
1023         if (sg > 0x100) { if (INT32(sg) < 0) sg = 0; else sg = 0x100; }
1024         if (sb > 0x100) { if (INT32(sb) < 0) sb = 0; else sb = 0x100; }
1025         if (invsa > 0x100) { if (INT32(invsa) < 0) invsa = 0; else invsa = 0x100; }
1026
1027         // loop over rows
1028         for (INT32 y = setup.starty; y < setup.endy; y++)
1029         {
1030            _PixelType *dest = dstdata + y * pitch + setup.startx;
1031            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
1032            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
1033
1034            // no lookup case
1035            if (palbase == NULL)
1036            {
1037               // loop over cols
1038               for (INT32 x = setup.startx; x < endx; x++)
1039               {
1040                  UINT32 pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv));
1041                  UINT32 dpix = _NoDestRead ? 0 : *dest;
1042                  UINT32 r = (source32_r(pix) * sr + dest_r(dpix) * invsa) >> 8;
1043                  UINT32 g = (source32_g(pix) * sg + dest_g(dpix) * invsa) >> 8;
1044                  UINT32 b = (source32_b(pix) * sb + dest_b(dpix) * invsa) >> 8;
1045
1046                  *dest++ = dest_assemble_rgb(r, g, b);
1047                  curu += dudx;
1048                  curv += dvdx;
1049               }
1050            }
1051
1052            // lookup case
1053            else
1054            {
1055               // loop over cols
1056               for (INT32 x = setup.startx; x < endx; x++)
1057               {
1058                  UINT32 pix = ycc_to_rgb(get_texel_yuy16(prim.texture, curu, curv));
1059                  UINT32 dpix = _NoDestRead ? 0 : *dest;
1060                  UINT32 r = (source32_r(pix) * sr + dest_r(dpix) * invsa) >> 8;
1061                  UINT32 g = (source32_g(pix) * sg + dest_g(dpix) * invsa) >> 8;
1062                  UINT32 b = (source32_b(pix) * sb + dest_b(dpix) * invsa) >> 8;
1063
1064                  *dest++ = dest_assemble_rgb(r, g, b);
1065                  curu += dudx;
1066                  curv += dvdx;
1067               }
1068            }
1069         }
1070      }
1071   }
1072
1073
1074   //**************************************************************************
1075   //  32-BIT RGB QUAD RASTERIZERS
1076   //**************************************************************************
1077
1078   //-------------------------------------------------
1079   //  draw_quad_rgb32 - perform rasterization of
1080   //  a 32bpp RGB texture
1081   //-------------------------------------------------
1082
1083   static void draw_quad_rgb32(const render_primitive &prim, _PixelType *dstdata, UINT32 pitch, quad_setup_data &setup)
1084   {
1085      const rgb_t *palbase = prim.texture.palette;
1086      INT32 dudx = setup.dudx;
1087      INT32 dvdx = setup.dvdx;
1088      INT32 endx = setup.endx;
1089
1090      // fast case: no coloring, no alpha
1091      if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a))
1092      {
1093         // loop over rows
1094         for (INT32 y = setup.starty; y < setup.endy; y++)
1095         {
1096            _PixelType *dest = dstdata + y * pitch + setup.startx;
1097            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
1098            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
1099
1100            // no lookup case
1101            if (palbase == NULL)
1102            {
1103               // loop over cols
1104               for (INT32 x = setup.startx; x < endx; x++)
1105               {
1106                  UINT32 pix = get_texel_rgb32(prim.texture, curu, curv);
1107                  *dest++ = source32_to_dest(pix);
1108                  curu += dudx;
1109                  curv += dvdx;
1110               }
1111            }
1112
1113            // lookup case
1114            else
1115            {
1116               // loop over cols
1117               for (INT32 x = setup.startx; x < endx; x++)
1118               {
1119                  UINT32 pix = get_texel_rgb32(prim.texture, curu, curv);
1120                  UINT32 r = palbase[(pix >> 16) & 0xff] >> _SrcShiftR;
1121                  UINT32 g = palbase[(pix >> 8) & 0xff] >> _SrcShiftG;
1122                  UINT32 b = palbase[(pix >> 0) & 0xff] >> _SrcShiftB;
1123
1124                  *dest++ = dest_assemble_rgb(r, g, b);
1125                  curu += dudx;
1126                  curv += dvdx;
1127               }
1128            }
1129         }
1130      }
1131
1132      // coloring-only case
1133      else if (is_opaque(prim.color.a))
1134      {
1135         UINT32 sr = UINT32(256.0f * prim.color.r);
1136         UINT32 sg = UINT32(256.0f * prim.color.g);
1137         UINT32 sb = UINT32(256.0f * prim.color.b);
1138
1139         // clamp R,G,B to 0-256 range
1140         if (sr > 0x100) { if (INT32(sr) < 0) sr = 0; else sr = 0x100; }
1141         if (sg > 0x100) { if (INT32(sg) < 0) sg = 0; else sg = 0x100; }
1142         if (sb > 0x100) { if (INT32(sb) < 0) sb = 0; else sb = 0x100; }
1143
1144         // loop over rows
1145         for (INT32 y = setup.starty; y < setup.endy; y++)
1146         {
1147            _PixelType *dest = dstdata + y * pitch + setup.startx;
1148            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
1149            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
1150
1151            // no lookup case
1152            if (palbase == NULL)
1153            {
1154               // loop over cols
1155               for (INT32 x = setup.startx; x < endx; x++)
1156               {
1157                  UINT32 pix = get_texel_rgb32(prim.texture, curu, curv);
1158                  UINT32 r = (source32_r(pix) * sr) >> 8;
1159                  UINT32 g = (source32_g(pix) * sg) >> 8;
1160                  UINT32 b = (source32_b(pix) * sb) >> 8;
1161
1162                  *dest++ = dest_assemble_rgb(r, g, b);
1163                  curu += dudx;
1164                  curv += dvdx;
1165               }
1166            }
1167
1168            // lookup case
1169            else
1170            {
1171               // loop over cols
1172               for (INT32 x = setup.startx; x < endx; x++)
1173               {
1174                  UINT32 pix = get_texel_rgb32(prim.texture, curu, curv);
1175                  UINT32 r = (palbase[(pix >> 16) & 0xff] * sr) >> (8 + _SrcShiftR);
1176                  UINT32 g = (palbase[(pix >> 8) & 0xff] * sg) >> (8 + _SrcShiftG);
1177                  UINT32 b = (palbase[(pix >> 0) & 0xff] * sb) >> (8 + _SrcShiftB);
1178
1179                  *dest++ = dest_assemble_rgb(r, g, b);
1180                  curu += dudx;
1181                  curv += dvdx;
1182               }
1183            }
1184         }
1185      }
1186
1187      // alpha and/or coloring case
1188      else if (!is_transparent(prim.color.a))
1189      {
1190         UINT32 sr = UINT32(256.0f * prim.color.r * prim.color.a);
1191         UINT32 sg = UINT32(256.0f * prim.color.g * prim.color.a);
1192         UINT32 sb = UINT32(256.0f * prim.color.b * prim.color.a);
1193         UINT32 invsa = UINT32(256.0f * (1.0f - prim.color.a));
1194
1195         // clamp R,G,B and inverse A to 0-256 range
1196         if (sr > 0x100) { if (INT32(sr) < 0) sr = 0; else sr = 0x100; }
1197         if (sg > 0x100) { if (INT32(sg) < 0) sg = 0; else sg = 0x100; }
1198         if (sb > 0x100) { if (INT32(sb) < 0) sb = 0; else sb = 0x100; }
1199         if (invsa > 0x100) { if (INT32(invsa) < 0) invsa = 0; else invsa = 0x100; }
1200
1201         // loop over rows
1202         for (INT32 y = setup.starty; y < setup.endy; y++)
1203         {
1204            _PixelType *dest = dstdata + y * pitch + setup.startx;
1205            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
1206            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
1207
1208            // no lookup case
1209            if (palbase == NULL)
1210            {
1211               // loop over cols
1212               for (INT32 x = setup.startx; x < endx; x++)
1213               {
1214                  UINT32 pix = get_texel_rgb32(prim.texture, curu, curv);
1215                  UINT32 dpix = _NoDestRead ? 0 : *dest;
1216                  UINT32 r = (source32_r(pix) * sr + dest_r(dpix) * invsa) >> 8;
1217                  UINT32 g = (source32_g(pix) * sg + dest_g(dpix) * invsa) >> 8;
1218                  UINT32 b = (source32_b(pix) * sb + dest_b(dpix) * invsa) >> 8;
1219
1220                  *dest++ = dest_assemble_rgb(r, g, b);
1221                  curu += dudx;
1222                  curv += dvdx;
1223               }
1224            }
1225
1226            // lookup case
1227            else
1228            {
1229               // loop over cols
1230               for (INT32 x = setup.startx; x < endx; x++)
1231               {
1232                  UINT32 pix = get_texel_rgb32(prim.texture, curu, curv);
1233                  UINT32 dpix = _NoDestRead ? 0 : *dest;
1234                  UINT32 r = ((palbase[(pix >> 16) & 0xff] >> _SrcShiftR) * sr + dest_r(dpix) * invsa) >> 8;
1235                  UINT32 g = ((palbase[(pix >> 8) & 0xff] >> _SrcShiftG) * sg + dest_g(dpix) * invsa) >> 8;
1236                  UINT32 b = ((palbase[(pix >> 0) & 0xff] >> _SrcShiftB) * sb + dest_b(dpix) * invsa) >> 8;
1237
1238                  *dest++ = dest_assemble_rgb(r, g, b);
1239                  curu += dudx;
1240                  curv += dvdx;
1241               }
1242            }
1243         }
1244      }
1245   }
1246
1247
1248   //-------------------------------------------------
1249   //  draw_quad_rgb32_add - perform
1250   //  rasterization by using RGB add
1251   //-------------------------------------------------
1252
1253   static void draw_quad_rgb32_add(const render_primitive &prim, _PixelType *dstdata, UINT32 pitch, quad_setup_data &setup)
1254   {
1255      const rgb_t *palbase = prim.texture.palette;
1256      INT32 dudx = setup.dudx;
1257      INT32 dvdx = setup.dvdx;
1258      INT32 endx = setup.endx;
1259
1260      // simply can't do this without reading from the dest
1261      if (_NoDestRead)
1262         return;
1263
1264      // fast case: no coloring, no alpha
1265      if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a))
1266      {
1267         // loop over rows
1268         for (INT32 y = setup.starty; y < setup.endy; y++)
1269         {
1270            _PixelType *dest = dstdata + y * pitch + setup.startx;
1271            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
1272            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
1273
1274            // no lookup case
1275            if (palbase == NULL)
1276            {
1277               // loop over cols
1278               for (INT32 x = setup.startx; x < endx; x++)
1279               {
1280                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1281                  UINT32 dpix = _NoDestRead ? 0 : *dest;
1282                  UINT32 r = source32_r(pix) + dest_r(dpix);
1283                  UINT32 g = source32_g(pix) + dest_g(dpix);
1284                  UINT32 b = source32_b(pix) + dest_b(dpix);
1285                  r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
1286                  g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
1287                  b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
1288                  *dest++ = dest_assemble_rgb(r, g, b);
1289                  curu += dudx;
1290                  curv += dvdx;
1291               }
1292            }
1293
1294            // lookup case
1295            else
1296            {
1297               // loop over cols
1298               for (INT32 x = setup.startx; x < endx; x++)
1299               {
1300                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1301                  UINT32 dpix = _NoDestRead ? 0 : *dest;
1302                  UINT32 r = (palbase[(pix >> 16) & 0xff] >> _SrcShiftR) + dest_r(dpix);
1303                  UINT32 g = (palbase[(pix >> 8) & 0xff] >> _SrcShiftG) + dest_g(dpix);
1304                  UINT32 b = (palbase[(pix >> 0) & 0xff] >> _SrcShiftB) + dest_b(dpix);
1305                  r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
1306                  g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
1307                  b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
1308                  *dest++ = dest_assemble_rgb(r, g, b);
1309                  curu += dudx;
1310                  curv += dvdx;
1311               }
1312            }
1313         }
1314      }
1315
1316      // alpha and/or coloring case
1317      else
1318      {
1319         UINT32 sr = UINT32(256.0f * prim.color.r);
1320         UINT32 sg = UINT32(256.0f * prim.color.g);
1321         UINT32 sb = UINT32(256.0f * prim.color.b);
1322         UINT32 sa = UINT32(256.0f * prim.color.a);
1323
1324         // clamp R,G,B and inverse A to 0-256 range
1325         if (sr > 0x100) { if (INT32(sr) < 0) sr = 0; else sr = 0x100; }
1326         if (sg > 0x100) { if (INT32(sg) < 0) sg = 0; else sg = 0x100; }
1327         if (sb > 0x100) { if (INT32(sb) < 0) sb = 0; else sb = 0x100; }
1328         if (sa > 0x100) { if (INT32(sa) < 0) sa = 0; else sa = 0x100; }
1329
1330         // loop over rows
1331         for (INT32 y = setup.starty; y < setup.endy; y++)
1332         {
1333            _PixelType *dest = dstdata + y * pitch + setup.startx;
1334            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
1335            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
1336
1337            // no lookup case
1338            if (palbase == NULL)
1339            {
1340               // loop over cols
1341               for (INT32 x = setup.startx; x < endx; x++)
1342               {
1343                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1344                  UINT32 dpix = _NoDestRead ? 0 : *dest;
1345                  UINT32 r = ((source32_r(pix) * sr * sa) >> 16) + dest_r(dpix);
1346                  UINT32 g = ((source32_g(pix) * sg * sa) >> 16) + dest_g(dpix);
1347                  UINT32 b = ((source32_b(pix) * sb * sa) >> 16) + dest_b(dpix);
1348                  r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
1349                  g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
1350                  b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
1351                  *dest++ = dest_assemble_rgb(r, g, b);
1352                  curu += dudx;
1353                  curv += dvdx;
1354               }
1355            }
1356
1357            // lookup case
1358            else
1359            {
1360               // loop over cols
1361               for (INT32 x = setup.startx; x < endx; x++)
1362               {
1363                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1364                  UINT32 dpix = _NoDestRead ? 0 : *dest;
1365                  UINT32 r = ((palbase[(pix >> 16) & 0xff] * sr * sa) >> (16 + _SrcShiftR)) + dest_r(dpix);
1366                  UINT32 g = ((palbase[(pix >> 8) & 0xff] * sr * sa) >> (16 + _SrcShiftR)) + dest_g(dpix);
1367                  UINT32 b = ((palbase[(pix >> 0) & 0xff] * sr * sa) >> (16 + _SrcShiftR)) + dest_b(dpix);
1368                  r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
1369                  g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
1370                  b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
1371                  *dest++ = dest_assemble_rgb(r, g, b);
1372                  curu += dudx;
1373                  curv += dvdx;
1374               }
1375            }
1376         }
1377      }
1378   }
1379
1380
1381
1382   //**************************************************************************
1383   //  32-BIT ARGB QUAD RASTERIZERS
1384   //**************************************************************************
1385
1386   //-------------------------------------------------
1387   //  draw_quad_argb32_alpha - perform
1388   //  rasterization using standard alpha blending
1389   //-------------------------------------------------
1390
1391   static void draw_quad_argb32_alpha(const render_primitive &prim, _PixelType *dstdata, UINT32 pitch, quad_setup_data &setup)
1392   {
1393      const rgb_t *palbase = prim.texture.palette;
1394      INT32 dudx = setup.dudx;
1395      INT32 dvdx = setup.dvdx;
1396      INT32 endx = setup.endx;
1397
1398      // fast case: no coloring, no alpha
1399      if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a))
1400      {
1401         // loop over rows
1402         for (INT32 y = setup.starty; y < setup.endy; y++)
1403         {
1404            _PixelType *dest = dstdata + y * pitch + setup.startx;
1405            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
1406            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
1407
1408            // no lookup case
1409            if (palbase == NULL)
1410            {
1411               // loop over cols
1412               for (INT32 x = setup.startx; x < endx; x++)
1413               {
1414                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1415                  UINT32 ta = pix >> 24;
1416                  if (ta != 0)
1417                  {
1418                     UINT32 dpix = _NoDestRead ? 0 : *dest;
1419                     UINT32 invta = 0x100 - ta;
1420                     UINT32 r = (source32_r(pix) * ta + dest_r(dpix) * invta) >> 8;
1421                     UINT32 g = (source32_g(pix) * ta + dest_g(dpix) * invta) >> 8;
1422                     UINT32 b = (source32_b(pix) * ta + dest_b(dpix) * invta) >> 8;
1423
1424                     *dest = dest_assemble_rgb(r, g, b);
1425                  }
1426                  dest++;
1427                  curu += dudx;
1428                  curv += dvdx;
1429               }
1430            }
1431
1432            // lookup case
1433            else
1434            {
1435               // loop over cols
1436               for (INT32 x = setup.startx; x < endx; x++)
1437               {
1438                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1439                  UINT32 ta = pix >> 24;
1440                  if (ta != 0)
1441                  {
1442                     UINT32 dpix = _NoDestRead ? 0 : *dest;
1443                     UINT32 invta = 0x100 - ta;
1444                     UINT32 r = ((palbase[(pix >> 16) & 0xff] >> _SrcShiftR) * ta + dest_r(dpix) * invta) >> 8;
1445                     UINT32 g = ((palbase[(pix >> 8) & 0xff] >> _SrcShiftG) * ta + dest_g(dpix) * invta) >> 8;
1446                     UINT32 b = ((palbase[(pix >> 0) & 0xff] >> _SrcShiftB) * ta + dest_b(dpix) * invta) >> 8;
1447
1448                     *dest = dest_assemble_rgb(r, g, b);
1449                  }
1450                  dest++;
1451                  curu += dudx;
1452                  curv += dvdx;
1453               }
1454            }
1455         }
1456      }
1457
1458      // alpha and/or coloring case
1459      else
1460      {
1461         UINT32 sr = UINT32(256.0f * prim.color.r);
1462         UINT32 sg = UINT32(256.0f * prim.color.g);
1463         UINT32 sb = UINT32(256.0f * prim.color.b);
1464         UINT32 sa = UINT32(256.0f * prim.color.a);
1465
1466         // clamp R,G,B and inverse A to 0-256 range
1467         if (sr > 0x100) { if (INT32(sr) < 0) sr = 0; else sr = 0x100; }
1468         if (sg > 0x100) { if (INT32(sg) < 0) sg = 0; else sg = 0x100; }
1469         if (sb > 0x100) { if (INT32(sb) < 0) sb = 0; else sb = 0x100; }
1470         if (sa > 0x100) { if (INT32(sa) < 0) sa = 0; else sa = 0x100; }
1471
1472         // loop over rows
1473         for (INT32 y = setup.starty; y < setup.endy; y++)
1474         {
1475            _PixelType *dest = dstdata + y * pitch + setup.startx;
1476            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
1477            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
1478
1479            // no lookup case
1480            if (palbase == NULL)
1481            {
1482               // loop over cols
1483               for (INT32 x = setup.startx; x < endx; x++)
1484               {
1485                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1486                  UINT32 ta = (pix >> 24) * sa;
1487                  if (ta != 0)
1488                  {
1489                     UINT32 dpix = _NoDestRead ? 0 : *dest;
1490                     UINT32 invsta = (0x10000 - ta) << 8;
1491                     UINT32 r = (source32_r(pix) * sr * ta + dest_r(dpix) * invsta) >> 24;
1492                     UINT32 g = (source32_g(pix) * sg * ta + dest_g(dpix) * invsta) >> 24;
1493                     UINT32 b = (source32_b(pix) * sb * ta + dest_b(dpix) * invsta) >> 24;
1494
1495                     *dest = dest_assemble_rgb(r, g, b);
1496                  }
1497                  dest++;
1498                  curu += dudx;
1499                  curv += dvdx;
1500               }
1501            }
1502
1503
1504            // lookup case
1505            else
1506            {
1507               // loop over cols
1508               for (INT32 x = setup.startx; x < endx; x++)
1509               {
1510                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1511                  UINT32 ta = (pix >> 24) * sa;
1512                  if (ta != 0)
1513                  {
1514                     UINT32 dpix = _NoDestRead ? 0 : *dest;
1515                     UINT32 invsta = (0x10000 - ta) << 8;
1516                     UINT32 r = ((palbase[(pix >> 16) & 0xff] >> _SrcShiftR) * sr * ta + dest_r(dpix) * invsta) >> 24;
1517                     UINT32 g = ((palbase[(pix >> 8) & 0xff] >> _SrcShiftG) * sg * ta + dest_g(dpix) * invsta) >> 24;
1518                     UINT32 b = ((palbase[(pix >> 0) & 0xff] >> _SrcShiftB) * sb * ta + dest_b(dpix) * invsta) >> 24;
1519
1520                     *dest = dest_assemble_rgb(r, g, b);
1521                  }
1522                  dest++;
1523                  curu += dudx;
1524                  curv += dvdx;
1525               }
1526            }
1527         }
1528      }
1529   }
1530
1531
1532   //-------------------------------------------------
1533   //  draw_quad_argb32_multiply - perform
1534   //  rasterization using RGB multiply
1535   //-------------------------------------------------
1536
1537   static void draw_quad_argb32_multiply(const render_primitive &prim, _PixelType *dstdata, UINT32 pitch, quad_setup_data &setup)
1538   {
1539      const rgb_t *palbase = prim.texture.palette;
1540      INT32 dudx = setup.dudx;
1541      INT32 dvdx = setup.dvdx;
1542      INT32 endx = setup.endx;
1543
1544      // simply can't do this without reading from the dest
1545      if (_NoDestRead)
1546         return;
1547
1548      // fast case: no coloring, no alpha
1549      if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a))
1550      {
1551         // loop over rows
1552         for (INT32 y = setup.starty; y < setup.endy; y++)
1553         {
1554            _PixelType *dest = dstdata + y * pitch + setup.startx;
1555            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
1556            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
1557
1558            // no lookup case
1559            if (palbase == NULL)
1560            {
1561               // loop over cols
1562               for (INT32 x = setup.startx; x < endx; x++)
1563               {
1564                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1565                  UINT32 dpix = _NoDestRead ? 0 : *dest;
1566                  UINT32 r = (source32_r(pix) * dest_r(dpix)) >> (8 - _SrcShiftR);
1567                  UINT32 g = (source32_g(pix) * dest_g(dpix)) >> (8 - _SrcShiftG);
1568                  UINT32 b = (source32_b(pix) * dest_b(dpix)) >> (8 - _SrcShiftB);
1569
1570                  *dest++ = dest_assemble_rgb(r, g, b);
1571                  curu += dudx;
1572                  curv += dvdx;
1573               }
1574            }
1575            else
1576            {
1577               // loop over cols
1578               for (INT32 x = setup.startx; x < endx; x++)
1579               {
1580                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1581                  UINT32 dpix = _NoDestRead ? 0 : *dest;
1582                  UINT32 r = (palbase[(pix >> 16) & 0xff] * dest_r(dpix)) >> 8;
1583                  UINT32 g = (palbase[(pix >> 8) & 0xff] * dest_g(dpix)) >> 8;
1584                  UINT32 b = (palbase[(pix >> 0) & 0xff] * dest_b(dpix)) >> 8;
1585
1586                  *dest++ = dest_assemble_rgb(r, g, b);
1587                  curu += dudx;
1588                  curv += dvdx;
1589               }
1590            }
1591         }
1592      }
1593
1594      // alpha and/or coloring case
1595      else
1596      {
1597         UINT32 sr = UINT32(256.0f * prim.color.r * prim.color.a);
1598         UINT32 sg = UINT32(256.0f * prim.color.g * prim.color.a);
1599         UINT32 sb = UINT32(256.0f * prim.color.b * prim.color.a);
1600
1601         // clamp R,G,B and inverse A to 0-256 range
1602         if (sr > 0x100) { if (INT32(sr) < 0) sr = 0; else sr = 0x100; }
1603         if (sg > 0x100) { if (INT32(sg) < 0) sg = 0; else sg = 0x100; }
1604         if (sb > 0x100) { if (INT32(sb) < 0) sb = 0; else sb = 0x100; }
1605
1606         // loop over rows
1607         for (INT32 y = setup.starty; y < setup.endy; y++)
1608         {
1609            _PixelType *dest = dstdata + y * pitch + setup.startx;
1610            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
1611            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
1612
1613            // no lookup case
1614            if (palbase == NULL)
1615            {
1616               // loop over cols
1617               for (INT32 x = setup.startx; x < endx; x++)
1618               {
1619                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1620                  UINT32 dpix = _NoDestRead ? 0 : *dest;
1621                  UINT32 r = (source32_r(pix) * sr * dest_r(dpix)) >> (16 - _SrcShiftR);
1622                  UINT32 g = (source32_g(pix) * sg * dest_g(dpix)) >> (16 - _SrcShiftG);
1623                  UINT32 b = (source32_b(pix) * sb * dest_b(dpix)) >> (16 - _SrcShiftB);
1624
1625                  *dest++ = dest_assemble_rgb(r, g, b);
1626                  curu += dudx;
1627                  curv += dvdx;
1628               }
1629            }
1630            else
1631            {
1632               // loop over cols
1633               for (INT32 x = setup.startx; x < endx; x++)
1634               {
1635                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1636                  UINT32 dpix = _NoDestRead ? 0 : *dest;
1637                  UINT32 r = (palbase[(pix >> 16) & 0xff] * sr * dest_r(dpix)) >> 16;
1638                  UINT32 g = (palbase[(pix >> 8) & 0xff] * sg * dest_g(dpix)) >> 16;
1639                  UINT32 b = (palbase[(pix >> 0) & 0xff] * sb * dest_b(dpix)) >> 16;
1640
1641                  *dest++ = dest_assemble_rgb(r, g, b);
1642                  curu += dudx;
1643                  curv += dvdx;
1644               }
1645            }
1646         }
1647      }
1648   }
1649
1650
1651   //-------------------------------------------------
1652   //  draw_quad_argb32_add - perform
1653   //  rasterization by using RGB add
1654   //-------------------------------------------------
1655
1656   static void draw_quad_argb32_add(const render_primitive &prim, _PixelType *dstdata, UINT32 pitch, quad_setup_data &setup)
1657   {
1658      const rgb_t *palbase = prim.texture.palette;
1659      INT32 dudx = setup.dudx;
1660      INT32 dvdx = setup.dvdx;
1661      INT32 endx = setup.endx;
1662
1663      // simply can't do this without reading from the dest
1664      if (_NoDestRead)
1665         return;
1666
1667      // fast case: no coloring, no alpha
1668      if (prim.color.r >= 1.0f && prim.color.g >= 1.0f && prim.color.b >= 1.0f && is_opaque(prim.color.a))
1669      {
1670         // loop over rows
1671         for (INT32 y = setup.starty; y < setup.endy; y++)
1672         {
1673            _PixelType *dest = dstdata + y * pitch + setup.startx;
1674            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
1675            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
1676
1677            // no lookup case
1678            if (palbase == NULL)
1679            {
1680               // loop over cols
1681               for (INT32 x = setup.startx; x < endx; x++)
1682               {
1683                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1684                  UINT32 ta = pix >> 24;
1685                  if (ta != 0)
1686                  {
1687                     UINT32 dpix = _NoDestRead ? 0 : *dest;
1688                     UINT32 r = ((source32_r(pix) * ta) >> 8) + dest_r(dpix);
1689                     UINT32 g = ((source32_g(pix) * ta) >> 8) + dest_g(dpix);
1690                     UINT32 b = ((source32_b(pix) * ta) >> 8) + dest_b(dpix);
1691                     r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
1692                     g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
1693                     b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
1694                     *dest = dest_assemble_rgb(r, g, b);
1695                  }
1696                  dest++;
1697                  curu += dudx;
1698                  curv += dvdx;
1699               }
1700            }
1701
1702            // lookup case
1703            else
1704            {
1705               // loop over cols
1706               for (INT32 x = setup.startx; x < endx; x++)
1707               {
1708                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1709                  UINT32 ta = pix >> 24;
1710                  if (ta != 0)
1711                  {
1712                     UINT32 dpix = _NoDestRead ? 0 : *dest;
1713                     UINT32 r = ((palbase[(pix >> 16) & 0xff] * ta) >> (8 + _SrcShiftR)) + dest_r(dpix);
1714                     UINT32 g = ((palbase[(pix >> 8) & 0xff] * ta) >> (8 + _SrcShiftG)) + dest_g(dpix);
1715                     UINT32 b = ((palbase[(pix >> 0) & 0xff] * ta) >> (8 + _SrcShiftB)) + dest_b(dpix);
1716                     r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
1717                     g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
1718                     b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
1719                     *dest = dest_assemble_rgb(r, g, b);
1720                  }
1721                  dest++;
1722                  curu += dudx;
1723                  curv += dvdx;
1724               }
1725            }
1726         }
1727      }
1728
1729      // alpha and/or coloring case
1730      else
1731      {
1732         UINT32 sr = UINT32(256.0f * prim.color.r);
1733         UINT32 sg = UINT32(256.0f * prim.color.g);
1734         UINT32 sb = UINT32(256.0f * prim.color.b);
1735         UINT32 sa = UINT32(256.0f * prim.color.a);
1736
1737         // clamp R,G,B and inverse A to 0-256 range
1738         if (sr > 0x100) { if (INT32(sr) < 0) sr = 0; else sr = 0x100; }
1739         if (sg > 0x100) { if (INT32(sg) < 0) sg = 0; else sg = 0x100; }
1740         if (sb > 0x100) { if (INT32(sb) < 0) sb = 0; else sb = 0x100; }
1741         if (sa > 0x100) { if (INT32(sa) < 0) sa = 0; else sa = 0x100; }
1742
1743         // loop over rows
1744         for (INT32 y = setup.starty; y < setup.endy; y++)
1745         {
1746            _PixelType *dest = dstdata + y * pitch + setup.startx;
1747            INT32 curu = setup.startu + (y - setup.starty) * setup.dudy;
1748            INT32 curv = setup.startv + (y - setup.starty) * setup.dvdy;
1749
1750            // no lookup case
1751            if (palbase == NULL)
1752            {
1753               // loop over cols
1754               for (INT32 x = setup.startx; x < endx; x++)
1755               {
1756                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1757                  UINT32 ta = (pix >> 24) * sa;
1758                  if (ta != 0)
1759                  {
1760                     UINT32 dpix = _NoDestRead ? 0 : *dest;
1761                     UINT32 r = ((source32_r(pix) * sr * ta) >> 24) + dest_r(dpix);
1762                     UINT32 g = ((source32_g(pix) * sg * ta) >> 24) + dest_g(dpix);
1763                     UINT32 b = ((source32_b(pix) * sb * ta) >> 24) + dest_b(dpix);
1764                     r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
1765                     g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
1766                     b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
1767                     *dest = dest_assemble_rgb(r, g, b);
1768                  }
1769                  dest++;
1770                  curu += dudx;
1771                  curv += dvdx;
1772               }
1773            }
1774
1775            // lookup case
1776            else
1777            {
1778               // loop over cols
1779               for (INT32 x = setup.startx; x < endx; x++)
1780               {
1781                  UINT32 pix = get_texel_argb32(prim.texture, curu, curv);
1782                  UINT32 ta = (pix >> 24) * sa;
1783                  if (ta != 0)
1784                  {
1785                     UINT32 dpix = _NoDestRead ? 0 : *dest;
1786                     UINT32 r = ((palbase[(pix >> 16) & 0xff] * sr * ta) >> (24 + _SrcShiftR)) + dest_r(dpix);
1787                     UINT32 g = ((palbase[(pix >> 8) & 0xff] * sr * ta) >> (24 + _SrcShiftR)) + dest_g(dpix);
1788                     UINT32 b = ((palbase[(pix >> 0) & 0xff] * sr * ta) >> (24 + _SrcShiftR)) + dest_b(dpix);
1789                     r = (r | -(r >> (8 - _SrcShiftR))) & (0xff >> _SrcShiftR);
1790                     g = (g | -(g >> (8 - _SrcShiftG))) & (0xff >> _SrcShiftG);
1791                     b = (b | -(b >> (8 - _SrcShiftB))) & (0xff >> _SrcShiftB);
1792                     *dest = dest_assemble_rgb(r, g, b);
1793                  }
1794                  dest++;
1795                  curu += dudx;
1796                  curv += dvdx;
1797               }
1798            }
1799         }
1800      }
1801   }
1802
1803
1804   //**************************************************************************
1805   //  CORE QUAD RASTERIZERS
1806   //**************************************************************************
1807
1808   //-------------------------------------------------
1809   //  setup_and_draw_textured_quad - perform setup
1810   //  and then dispatch to a texture-mode-specific
1811   //  drawing routine
1812   //-------------------------------------------------
1813
1814   static void setup_and_draw_textured_quad(const render_primitive &prim, _PixelType *dstdata, INT32 width, INT32 height, UINT32 pitch)
1815   {
1816      assert(prim.bounds.x0 <= prim.bounds.x1);
1817      assert(prim.bounds.y0 <= prim.bounds.y1);
1818
1819      // determine U/V deltas
1820      float fdudx = (prim.texcoords.tr.u - prim.texcoords.tl.u) / (prim.bounds.x1 - prim.bounds.x0);
1821      float fdvdx = (prim.texcoords.tr.v - prim.texcoords.tl.v) / (prim.bounds.x1 - prim.bounds.x0);
1822      float fdudy = (prim.texcoords.bl.u - prim.texcoords.tl.u) / (prim.bounds.y1 - prim.bounds.y0);
1823      float fdvdy = (prim.texcoords.bl.v - prim.texcoords.tl.v) / (prim.bounds.y1 - prim.bounds.y0);
1824
1825      // clamp to integers
1826      quad_setup_data setup;
1827      setup.startx = round_nearest(prim.bounds.x0);
1828      setup.starty = round_nearest(prim.bounds.y0);
1829      setup.endx = round_nearest(prim.bounds.x1);
1830      setup.endy = round_nearest(prim.bounds.y1);
1831
1832      // ensure we fit
1833      if (setup.startx < 0) setup.startx = 0;
1834      if (setup.startx >= width) setup.startx = width;
1835      if (setup.endx < 0) setup.endx = 0;
1836      if (setup.endx >= width) setup.endx = width;
1837      if (setup.starty < 0) setup.starty = 0;
1838      if (setup.starty >= height) setup.starty = height;
1839      if (setup.endy < 0) setup.endy = 0;
1840      if (setup.endy >= height) setup.endy = height;
1841
1842      // compute start and delta U,V coordinates now
1843      setup.dudx = round_nearest(65536.0f * float(prim.texture.width) * fdudx);
1844      setup.dvdx = round_nearest(65536.0f * float(prim.texture.height) * fdvdx);
1845      setup.dudy = round_nearest(65536.0f * float(prim.texture.width) * fdudy);
1846      setup.dvdy = round_nearest(65536.0f * float(prim.texture.height) * fdvdy);
1847      setup.startu = round_nearest(65536.0f * float(prim.texture.width) * prim.texcoords.tl.u);
1848      setup.startv = round_nearest(65536.0f * float(prim.texture.height) * prim.texcoords.tl.v);
1849
1850      // advance U/V to the middle of the first texel
1851      setup.startu += (setup.dudx + setup.dudy) / 2;
1852      setup.startv += (setup.dvdx + setup.dvdy) / 2;
1853
1854      // if we're bilinear filtering, we need to offset u/v by half a texel
1855      if (_BilinearFilter)
1856      {
1857         setup.startu -= 0x8000;
1858         setup.startv -= 0x8000;
1859      }
1860
1861      // render based on the texture coordinates
1862      switch (prim.flags & (PRIMFLAG_TEXFORMAT_MASK | PRIMFLAG_BLENDMODE_MASK))
1863      {
1864         case PRIMFLAG_TEXFORMAT(TEXFORMAT_PALETTE16) | PRIMFLAG_BLENDMODE(BLENDMODE_NONE):
1865         case PRIMFLAG_TEXFORMAT(TEXFORMAT_PALETTE16) | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA):
1866            draw_quad_palette16_none(prim, dstdata, pitch, setup);
1867            break;
1868
1869         case PRIMFLAG_TEXFORMAT(TEXFORMAT_PALETTE16) | PRIMFLAG_BLENDMODE(BLENDMODE_ADD):
1870            draw_quad_palette16_add(prim, dstdata, pitch, setup);
1871            break;
1872
1873         case PRIMFLAG_TEXFORMAT(TEXFORMAT_PALETTEA16) | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA):
1874            draw_quad_palettea16_alpha(prim, dstdata, pitch, setup);
1875            break;
1876
1877         case PRIMFLAG_TEXFORMAT(TEXFORMAT_YUY16) | PRIMFLAG_BLENDMODE(BLENDMODE_NONE):
1878            draw_quad_yuy16_none(prim, dstdata, pitch, setup);
1879            break;
1880
1881         case PRIMFLAG_TEXFORMAT(TEXFORMAT_RGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_NONE):
1882         case PRIMFLAG_TEXFORMAT(TEXFORMAT_RGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA):
1883         case PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_NONE):
1884            draw_quad_rgb32(prim, dstdata, pitch, setup);
1885            break;
1886
1887         case PRIMFLAG_TEXFORMAT(TEXFORMAT_RGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_ADD):
1888            draw_quad_rgb32_add(prim, dstdata, pitch, setup);
1889            break;
1890
1891         case PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA):
1892            draw_quad_argb32_alpha(prim, dstdata, pitch, setup);
1893            break;
1894
1895         case PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_RGB_MULTIPLY):
1896            draw_quad_argb32_multiply(prim, dstdata, pitch, setup);
1897            break;
1898
1899         case PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_ADD):
1900            draw_quad_argb32_add(prim, dstdata, pitch, setup);
1901            break;
1902
1903         default:
1904            fatalerror("Unknown texformat(%d)/blendmode(%d) combo\n", PRIMFLAG_GET_TEXFORMAT(prim.flags), PRIMFLAG_GET_BLENDMODE(prim.flags));
1905            break;
1906      }
1907   }
1908
1909
1910   //**************************************************************************
1911   //  PRIMARY ENTRY POINT
1912   //**************************************************************************
1913
1914   //-------------------------------------------------
1915   //  draw_primitives - draw a series of primitives
1916   //  using a software rasterizer
1917   //-------------------------------------------------
1918
1919public:
1920   static void draw_primitives(const render_primitive_list &primlist, void *dstdata, UINT32 width, UINT32 height, UINT32 pitch)
1921   {
1922      // loop over the list and render each element
1923      for (const render_primitive *prim = primlist.first(); prim != NULL; prim = prim->next())
1924         switch (prim->type)
1925         {
1926            case render_primitive::LINE:
1927               draw_line(*prim, reinterpret_cast<_PixelType *>(dstdata), width, height, pitch);
1928               break;
1929
1930            case render_primitive::QUAD:
1931               if (!prim->texture.base)
1932                  draw_rect(*prim, reinterpret_cast<_PixelType *>(dstdata), width, height, pitch);
1933               else
1934                  setup_and_draw_textured_quad(*prim, reinterpret_cast<_PixelType *>(dstdata), width, height, pitch);
1935               break;
1936
1937            default:
1938               throw emu_fatalerror("Unexpected render_primitive type");
1939         }
1940   }
1941};
Property changes on: trunk/src/emu/rendersw.inc
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/emu.mak
r28727r28728
249249
250250$(EMUOBJ)/rendfont.o:   $(EMUOBJ)/uismall.fh
251251
252$(EMUOBJ)/video.o:  $(EMUSRC)/rendersw.c
252$(EMUOBJ)/video.o:  $(EMUSRC)/rendersw.inc
253253
254254#-------------------------------------------------
255255# core layouts
trunk/src/emu/video.c
r28727r28728
1616#include "ui/ui.h"
1717#include "aviio.h"
1818#include "crsshair.h"
19#include "rendersw.c"
19#include "rendersw.inc"
2020#include "output.h"
2121
2222#include "snap.lh"
trunk/src/mess/drivers/cxhumax.c
r28727r28728
823823{
824824}
825825
826/* copy from emu/rendersw.c */
826/* copy from emu/rendersw.inc */
827827/*------------------------------------------------------------------------
828828    ycc_to_rgb - convert YCC to RGB; the YCC pixel
829829    contains Y in the LSB, Cb << 8, and Cr << 16

Previous 199869 Revisions Next


© 1997-2024 The MAME Team