Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / workbench / hidds / graphics / convertpixels.c
blobd148c433db970739b596d37e0d30886aabe73045
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <string.h>
8 #include <hidd/graphics.h>
9 #include "graphics_intern.h"
11 #define DEBUG 0
12 #include <aros/debug.h>
14 /****************************************************************************************/
16 #warning "Does not yet handle SwapPixelBytes flag of HIDDT_PixelFormat structure!"
18 /****************************************************************************************/
20 #define SHIFT_PIX(pix, shift) \
21 (( (shift) < 0) ? (pix) >> (-shift) : (pix) << (shift) )
24 #define GETPIX32(s, pix) \
25 do { pix = *(ULONG *)s; s = (UBYTE *)s + 4; } while (0)
27 #if AROS_BIG_ENDIAN
28 #define GETPIX24(s, pix) \
29 do \
30 { \
31 pix = (((UBYTE *)s)[0] << 16) | \
32 (((UBYTE *)s)[1] << 8) | \
33 ((UBYTE *)s)[2]; \
34 s = (UBYTE *)s + 3; \
35 } while (0);
37 #else
38 #define GETPIX24(s, pix) \
39 do \
40 { \
41 pix = (((UBYTE *)s)[2] << 16) | \
42 (((UBYTE *)s)[1] << 8) | \
43 ((UBYTE *)s)[0]; \
44 s = (UBYTE *)s + 3; \
45 } while (0);
47 #endif
49 #define GETPIX16(s, pix) \
50 do { pix = *(UWORD *)s; s = (UBYTE *)s + 2; } while (0)
51 #define GETPIX16OE(s, pix) \
52 do { pix = AROS_SWAP_BYTES_WORD(*(UWORD *)s); s = (UBYTE *)s + 2; } while (0)
55 #define GETPIX8(s, pix) \
56 do { pix = *(BYTE *)s; s = (UBYTE *)s + 1; } while (0)
58 #define GET_TRUE_PIX(s, pix, pf) \
59 switch ((pf)->bytes_per_pixel) { \
60 case 4: GETPIX32(s, pix); break; \
61 case 3: GETPIX24(s, pix); break; \
62 case 2: if ((pf)->flags & vHidd_PixFmt_SwapPixelBytes_Flag) \
63 GETPIX16OE(s, pix); \
64 else \
65 GETPIX16(s, pix); \
66 break; \
67 default: D(bug("RUBBISH BYTES PER PIXEL IN GET_TRUE_PIX()\n")); break; \
71 #define GET_PAL_PIX(s, pix, pf, lut) \
72 switch (pf->bytes_per_pixel) { \
73 case 4: GETPIX32(s, pix); break; \
74 case 3: GETPIX24(s, pix); break; \
75 case 2: GETPIX16(s, pix); break; \
76 case 1: GETPIX8 (s, pix); break; \
77 default: D(bug("RUBBISH BYTES PER PIXEL IN GET_PAL_PIX()\n")); break; \
78 } \
79 pix = lut[pix];
81 #define PUTPIX32(d, pix) \
82 do { *(ULONG *)d = pix; d = (UBYTE *)d + 4; } while (0)
84 #if AROS_BIG_ENDIAN
85 #define PUTPIX24(d, pix) \
86 do \
87 { \
88 ((UBYTE *)d)[0] = (UBYTE)((pix >> 16) & 0x000000FF); \
89 ((UBYTE *)d)[1] = (UBYTE)((pix >> 8 ) & 0x000000FF); \
90 ((UBYTE *)d)[2] = (UBYTE)( pix & 0x000000FF); \
91 d = (UBYTE *)d + 3; \
92 } while (0)
93 #else
94 #define PUTPIX24(d, pix) \
95 do \
96 { \
97 ((UBYTE *)d)[2] = (UBYTE)((pix >> 16) & 0x000000FF); \
98 ((UBYTE *)d)[1] = (UBYTE)((pix >> 8 ) & 0x000000FF); \
99 ((UBYTE *)d)[0] = (UBYTE)( pix & 0x000000FF); \
100 d = (UBYTE *)d + 3; \
101 } while (0)
103 #endif
105 #define PUTPIX16(d, pix) \
106 do { *(UWORD *)d = pix; d = (UBYTE *)d + 2; } while (0)
108 #define PUTPIX16OE(d, pix) \
109 do { *(UWORD *)d = AROS_SWAP_BYTES_WORD(pix); d = (UBYTE *)d + 2; } while (0)
111 #define PUT_TRUE_PIX(d, pix, pf) \
112 switch (pf->bytes_per_pixel) { \
113 case 4: PUTPIX32(d, pix); break; \
114 case 3: PUTPIX24(d, pix); break; \
115 case 2: if ((pf)->flags & vHidd_PixFmt_SwapPixelBytes_Flag) \
116 PUTPIX16OE(d, pix); \
117 else \
118 PUTPIX16(d, pix); \
119 break; \
120 default: D(bug("RUBBISH BYTES PER PIXEL IN PUT_TRUE_PIX()\n")); break; \
127 #define INIT_VARS() \
128 UBYTE *src = *msg->srcPixels; \
129 UBYTE *dst = *msg->dstBuf; \
131 #define INIT_FMTVARS() \
132 HIDDT_PixelFormat *srcfmt = msg->srcPixFmt; \
133 HIDDT_PixelFormat *dstfmt = msg->dstPixFmt;
135 /****************************************************************************************/
137 static VOID true_to_true(OOP_Class *cl, OOP_Object *o,
138 struct pHidd_BitMap_ConvertPixels *msg)
140 LONG alpha_diff, red_diff, green_diff, blue_diff;
142 INIT_VARS()
143 INIT_FMTVARS()
145 LONG x, y;
148 alpha_diff = srcfmt->alpha_shift - dstfmt->alpha_shift;
149 red_diff = srcfmt->red_shift - dstfmt->red_shift;
150 green_diff = srcfmt->green_shift - dstfmt->green_shift;
151 blue_diff = srcfmt->blue_shift - dstfmt->blue_shift;
154 #if 0
155 bug("true_to_true()\n: src = %x dest = %x srcfmt = %d %d %d %d [%d] destfmt = %d %d %d %d [%d]\n",
156 src, dst, srcfmt->alpha_shift, srcfmt->red_shift, srcfmt->green_shift, srcfmt->blue_shift, srcfmt->bytes_per_pixel,
157 dstfmt->alpha_shift, dstfmt->red_shift, dstfmt->green_shift, dstfmt->blue_shift, dstfmt->bytes_per_pixel);
159 bug("srcmasks = %p %p %p %p\n",
160 srcfmt->alpha_mask,
161 srcfmt->red_mask,
162 srcfmt->green_mask,
163 srcfmt->blue_mask);
164 bug("destmasks = %p %p %p %p diffs = %d %d %d %d\n",
165 dstfmt->alpha_mask,
166 dstfmt->red_mask,
167 dstfmt->green_mask,
168 dstfmt->blue_mask,
169 alpha_diff,
170 red_diff,
171 green_diff,
172 blue_diff);
173 #endif
174 for (y = 0; y < msg->height; y ++)
176 UBYTE * s = src;
177 UBYTE * d = dst;
179 for (x = 0; x < msg->width; x ++)
181 /* Get the source pixel */
182 HIDDT_Pixel srcpix = 0, dstpix;
184 GET_TRUE_PIX(s, srcpix, srcfmt);
186 dstpix = (SHIFT_PIX(srcpix & srcfmt->alpha_mask, alpha_diff) & dstfmt->alpha_mask)
187 | (SHIFT_PIX(srcpix & srcfmt->red_mask , red_diff) & dstfmt->red_mask)
188 | (SHIFT_PIX(srcpix & srcfmt->green_mask, green_diff) & dstfmt->green_mask)
189 | (SHIFT_PIX(srcpix & srcfmt->blue_mask , blue_diff) & dstfmt->blue_mask);
191 #if 0
192 bug("[ %p, %p, %p, %p ] "
193 , srcpix
194 , srcpix & srcfmt->blue_mask
195 , SHIFT_PIX(srcpix & srcfmt->blue_mask, blue_diff)
196 , SHIFT_PIX(srcpix & srcfmt->blue_mask, blue_diff) & dstfmt->blue_mask);
198 #endif
200 // bug("[ %p => %p ] \n", srcpix, dstpix);
201 /* Write the pixel to the destination buffer */
202 PUT_TRUE_PIX(d, dstpix, dstfmt);
204 } /* for (x) */
206 src += msg->srcMod;
207 dst += msg->dstMod;
209 } /* for (y) */
211 *msg->srcPixels = src;
212 *msg->dstBuf = dst;
215 /****************************************************************************************/
217 static VOID true_to_pal(OOP_Class *cl, OOP_Object *o,
218 struct pHidd_BitMap_ConvertPixels *msg)
220 D(bug("BitMap::ConvertPixels() : Truecolor to palette conversion not implemented yet\n"));
223 static VOID pal_to_true(OOP_Class *cl, OOP_Object *o,
224 struct pHidd_BitMap_ConvertPixels *msg)
226 HIDDT_Pixel *lut;
228 INIT_VARS()
229 INIT_FMTVARS()
231 LONG x, y;
233 lut = msg->pixlut->pixels;
235 for (y = 0; y < msg->height; y ++)
237 APTR s = src;
238 APTR d = dst;
240 for (x = 0; x < msg->width; x ++)
242 ULONG srcpix = 0;
244 GET_PAL_PIX(s, srcpix, srcfmt, lut);
246 /* We now have a pixel in Native32 format. Put it back */
247 PUT_TRUE_PIX(d, srcpix, dstfmt);
251 src += msg->srcMod;
252 dst += msg->dstMod;
256 *msg->srcPixels = src;
257 *msg->dstBuf = dst;
260 /****************************************************************************************/
262 static VOID pal_to_pal(OOP_Class *cl, OOP_Object *o,
263 struct pHidd_BitMap_ConvertPixels *msg)
265 HIDDT_PixelFormat *spf, *dpf;
267 spf = msg->srcPixFmt;
268 dpf = msg->dstPixFmt;
271 if ( spf->clut_shift == dpf->clut_shift
272 && spf->clut_mask == dpf->clut_mask )
274 /* This one is rather easy, just copy the data */
277 else
279 /* Convert pixel-by pixel */
283 return;
286 /****************************************************************************************/
288 static void native32_to_native(OOP_Class *cl, OOP_Object *o,
289 struct pHidd_BitMap_ConvertPixels *msg)
291 INIT_VARS()
292 HIDDT_PixelFormat *dstfmt = msg->dstPixFmt;
293 LONG x, y;
295 D(bug("SRC: Native32, DST: Native, height=%d, width=%d, bytes per pixel: %d, srcmod: %d, dstmod: %d, depth: %d\n"
296 , msg->height, msg->width, dstfmt->bytes_per_pixel, msg->srcMod, msg->dstMod, dstfmt->depth));
298 for ( y = 0; y < msg->height; y ++)
300 UBYTE *d = dst;
301 UBYTE *s = src;
303 for (x = 0; x < msg->width; x ++)
306 switch (dstfmt->bytes_per_pixel)
308 case 4:
309 *(ULONG *)d = (ULONG)*((HIDDT_Pixel *)s);
310 d += 4; s += sizeof(HIDDT_Pixel);
311 break;
313 case 3:
315 HIDDT_Pixel dstpix;
317 dstpix = *((HIDDT_Pixel *)s);
319 d[0] = (UBYTE)((dstpix >> 16) & 0x000000FF);
320 d[1] = (UBYTE)((dstpix >> 8) & 0x000000FF);
321 d[2] = (UBYTE)(dstpix & 0x000000FF);
323 d += 3; s += sizeof(HIDDT_Pixel);
324 break;
327 case 2:
328 *((UWORD *)d) = (UWORD)(*((HIDDT_Pixel *)s));
329 d += 2; s += sizeof(HIDDT_Pixel);
330 break;
332 case 1:
333 *d = (UBYTE)*((HIDDT_Pixel *)s);
334 d += 1; s += sizeof(HIDDT_Pixel);
335 break;
337 #if 0
338 case 0:
339 if (dstfmt->depth == 1)
341 UBYTE mask;
343 mask = XCOORD_TO_MASK(x);
344 d = ((UBYTE *)dst) + XCOORD_TO_BYTEIDX(x);
345 if (*((HIDDT_Pixel *)s) ++) {
346 *((UBYTE *)d) |= mask;
347 } else {
348 *((UBYTE *)d) &= ~mask;
351 break;
352 #endif
354 } /* switch() */
356 } /* for (x) */
358 src += msg->srcMod;
359 dst += msg->dstMod;
363 *msg->srcPixels = src;
364 *msg->dstBuf = dst;
367 /****************************************************************************************/
369 static VOID quick_copy(OOP_Class *cl, OOP_Object *o,
370 struct pHidd_BitMap_ConvertPixels *msg)
372 /* Just do a simple memcpy() of the pixels */
373 INIT_VARS()
374 HIDDT_PixelFormat *srcfmt = msg->srcPixFmt;
375 ULONG bpl = msg->width * srcfmt->bytes_per_pixel;
377 #warning This does not work well for formats with bytes_per_pixel < 1
379 if (msg->srcMod == bpl && msg->dstMod == bpl)
381 memcpy(dst, src, bpl * msg->height);
383 else
385 ULONG i;
386 ULONG copy_width;
388 copy_width = msg->width * srcfmt->bytes_per_pixel;
390 for (i = 0; i < msg->height; i ++)
392 memcpy(dst, src, copy_width);
393 src += msg->srcMod;
394 dst += msg->dstMod;
398 *msg->srcPixels = src;
399 *msg->dstBuf = dst;
403 /****************************************************************************************/
405 #warning Discuss this design decision:
407 /* Should we pass HIDDT_PixelFormat * or HIDDT_StdPixFmt ?
408 The first is more flexible for the user, as he will not only be restricted
409 to standard pixek formats. However the user will have to convert
410 from HIDDT_StdPixFmt to HIDDT_PixelFormat manually.
412 In the latter case this conversion will be done inside the method below.
413 This means that we can call an internal function directly
414 to do the conversion and save two method calls.
417 /****************************************************************************************/
419 VOID BM__Hidd_BitMap__ConvertPixels(OOP_Class *cl, OOP_Object *o,
420 struct pHidd_BitMap_ConvertPixels *msg)
422 /* For now we assume truecolor */
423 HIDDT_PixelFormat *srcfmt, *dstfmt;
425 //bug("bitmap_convertpixels()\n");
427 srcfmt = msg->srcPixFmt;
428 dstfmt = msg->dstPixFmt;
431 /* bug("ConvertPixels: src=%d, dst=%d\n"
432 , srcfmt->stdpixfmt, dstfmt->stdpixfmt);
435 /* Check if source and dest are the same format */
436 if (srcfmt->stdpixfmt == dstfmt->stdpixfmt)
438 quick_copy(cl, o, msg);
439 return;
443 if ( srcfmt->stdpixfmt == vHidd_StdPixFmt_Native32
444 && dstfmt->stdpixfmt == vHidd_StdPixFmt_Native )
447 native32_to_native(cl, o, msg);
448 return;
451 switch (HIDD_PF_COLMODEL(srcfmt))
453 case vHidd_ColorModel_TrueColor:
454 switch (HIDD_PF_COLMODEL(dstfmt))
456 case vHidd_ColorModel_TrueColor:
457 if ((srcfmt->stdpixfmt >= FIRST_RGB_STDPIXFMT) &&
458 (dstfmt->stdpixfmt >= FIRST_RGB_STDPIXFMT) &&
459 (srcfmt->stdpixfmt <= LAST_RGB_STDPIXFMT) &&
460 (dstfmt->stdpixfmt <= LAST_RGB_STDPIXFMT))
462 HIDDT_RGBConversionFunction f;
464 ObtainSemaphoreShared(&CSD(cl)->rgbconvertfuncs_sem);
466 f = CSD(cl)->rgbconvertfuncs[srcfmt->stdpixfmt - FIRST_RGB_STDPIXFMT]
467 [dstfmt->stdpixfmt - FIRST_RGB_STDPIXFMT];
469 if (f)
471 if ((*f)(*msg->srcPixels, msg->srcMod, srcfmt->stdpixfmt,
472 *msg->dstBuf, msg->dstMod, dstfmt->stdpixfmt,
473 msg->width, msg->height))
475 *msg->srcPixels += (msg->srcMod * msg->height);
476 *msg->dstBuf += (msg->dstMod * msg->height);
478 ReleaseSemaphore(&CSD(cl)->rgbconvertfuncs_sem);
479 break;
484 ReleaseSemaphore(&CSD(cl)->rgbconvertfuncs_sem);
488 true_to_true(cl, o, msg);
489 break;
492 case vHidd_ColorModel_Palette:
493 case vHidd_ColorModel_StaticPalette:
494 true_to_pal(cl, o, msg);
495 break;
498 break;
500 case vHidd_ColorModel_Palette:
501 case vHidd_ColorModel_StaticPalette:
502 switch (HIDD_PF_COLMODEL(dstfmt))
504 case vHidd_ColorModel_TrueColor:
505 pal_to_true(cl, o, msg);
506 break;
508 case vHidd_ColorModel_Palette:
509 case vHidd_ColorModel_StaticPalette:
510 pal_to_pal(cl,o, msg);
511 break;
514 break;
517 return;
520 /****************************************************************************************/