Annotation of tme/generic/fb.c, revision 1.1.1.3

1.1.1.3 ! root        1: /* $Id: fb.c,v 1.5 2007/08/25 21:05:30 fredette Exp $ */
1.1       root        2: 
                      3: /* generic/fb.c - generic framebuffer implementation support: */
                      4: 
                      5: /*
                      6:  * Copyright (c) 2003 Matt Fredette
                      7:  * All rights reserved.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. All advertising materials mentioning features or use of this software
                     18:  *    must display the following acknowledgement:
                     19:  *      This product includes software developed by Matt Fredette.
                     20:  * 4. The name of the author may not be used to endorse or promote products
                     21:  *    derived from this software without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     25:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     26:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
                     27:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     28:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     29:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     31:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
                     32:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     33:  * POSSIBILITY OF SUCH DAMAGE.
                     34:  */
                     35: 
                     36: #include <tme/common.h>
1.1.1.3 ! root       37: _TME_RCSID("$Id: fb.c,v 1.5 2007/08/25 21:05:30 fredette Exp $");
1.1       root       38: 
                     39: /* includes: */
                     40: #include <tme/generic/fb.h>
                     41: 
                     42: /* include the automatically-generated translation functions: */
                     43: #include "fb-xlat-auto.c"
                     44: 
1.1.1.3 ! root       45: /* macros: */
        !            46: #define TME_FB_COLORSET_DIRECT_COLOR   (1)
        !            47: #define TME_FB_COLORSET_PSEUDO_COLOR   (2)
        !            48: 
1.1       root       49: /* this returns the best translation function: */
                     50: const struct tme_fb_xlat *
                     51: tme_fb_xlat_best(const struct tme_fb_xlat *xlat_user)
                     52: {
                     53:   unsigned int xlat_i;
                     54:   const struct tme_fb_xlat *xlat;
                     55:   const struct tme_fb_xlat *xlat_best;
                     56:   unsigned int xlat_best_score, xlat_score;
                     57: 
                     58:   /* loop over the xlats: */
                     59:   xlat_best = NULL;
                     60:   xlat_best_score = 0;
                     61:   for (xlat_i = 0;
                     62:        xlat_i < TME_ARRAY_ELS(tme_fb_xlats);
                     63:        xlat_i++) {
                     64: 
                     65:     /* get this xlat: */
                     66:     xlat = &tme_fb_xlats[xlat_i];
                     67:     xlat_score = 0;
                     68: 
                     69:     /* if this xlat only works for a particular value of the given
                     70:        member, and the user's value is different, we cannot use this
                     71:        xlat.  otherwise, increase this xlat's score: */
                     72: #define TME_FB_XLAT_SCORE(score, member, specific)     \
                     73: if ((xlat->member specific)                            \
                     74:     && (xlat->member != xlat_user->member)) {          \
                     75:   continue;                                            \
                     76: }                                                      \
                     77: if (xlat->member specific)                             \
                     78:   xlat_score += score
                     79: 
                     80:     TME_FB_XLAT_SCORE(100, tme_fb_xlat_width, != 0);
                     81:     TME_FB_XLAT_SCORE(100, tme_fb_xlat_height, != 0);
                     82:     TME_FB_XLAT_SCORE(  0, tme_fb_xlat_scale, || TRUE);
                     83:     TME_FB_XLAT_SCORE(100, tme_fb_xlat_src_depth, != 0);
                     84:     TME_FB_XLAT_SCORE(100, tme_fb_xlat_src_bits_per_pixel, != 0);
                     85:     TME_FB_XLAT_SCORE(100, tme_fb_xlat_src_skipx, >= 0);
                     86:     TME_FB_XLAT_SCORE(100, tme_fb_xlat_src_scanline_pad, != 0);
                     87:     TME_FB_XLAT_SCORE(  0, tme_fb_xlat_src_order, || TRUE);
1.1.1.2   root       88:     TME_FB_XLAT_SCORE(100, tme_fb_xlat_src_class, != TME_FB_XLAT_CLASS_ANY);
                     89:     TME_FB_XLAT_SCORE(100, tme_fb_xlat_src_map, != TME_FB_XLAT_MAP_ANY);
                     90:     TME_FB_XLAT_SCORE(100, tme_fb_xlat_src_map_bits, != 0);
                     91:     TME_FB_XLAT_SCORE(100, tme_fb_xlat_src_mask_g, != TME_FB_XLAT_MASK_ANY);
                     92:     TME_FB_XLAT_SCORE(100, tme_fb_xlat_src_mask_r, != TME_FB_XLAT_MASK_ANY);
                     93:     TME_FB_XLAT_SCORE(100, tme_fb_xlat_src_mask_b, != TME_FB_XLAT_MASK_ANY);
1.1       root       94:     TME_FB_XLAT_SCORE(100, tme_fb_xlat_dst_depth, != 0);
                     95:     TME_FB_XLAT_SCORE(100, tme_fb_xlat_dst_bits_per_pixel, != 0);
                     96:     TME_FB_XLAT_SCORE(100, tme_fb_xlat_dst_skipx, >= 0);
                     97:     TME_FB_XLAT_SCORE(100, tme_fb_xlat_dst_scanline_pad, != 0);
                     98:     TME_FB_XLAT_SCORE(  0, tme_fb_xlat_dst_order, || TRUE);
1.1.1.2   root       99:     TME_FB_XLAT_SCORE(100, tme_fb_xlat_dst_map, != TME_FB_XLAT_MAP_ANY);
                    100:     TME_FB_XLAT_SCORE(100, tme_fb_xlat_dst_mask_g, != TME_FB_XLAT_MASK_ANY);
                    101:     TME_FB_XLAT_SCORE(100, tme_fb_xlat_dst_mask_r, != TME_FB_XLAT_MASK_ANY);
                    102:     TME_FB_XLAT_SCORE(100, tme_fb_xlat_dst_mask_b, != TME_FB_XLAT_MASK_ANY);
1.1       root      103: 
                    104: #undef TME_FB_XLAT_SCORE
                    105: 
                    106:     /* update the best xlat: */
                    107:     if (xlat_best == NULL
                    108:        || xlat_best_score < xlat_score) {
                    109:       xlat_best = xlat;
                    110:       xlat_best_score = xlat_score;
                    111:     }
                    112:   }
                    113: 
                    114:   /* return the best xlat: */
                    115:   assert (xlat_best != NULL);
                    116:   return (xlat_best);
                    117: }
                    118: 
                    119: /* this returns nonzero iff the translation function is optimal: */
                    120: int
                    121: tme_fb_xlat_is_optimal(const struct tme_fb_xlat *xlat)
                    122: {
                    123:   return (xlat->tme_fb_xlat_width != 0
                    124:          && xlat->tme_fb_xlat_height != 0
                    125:          && xlat->tme_fb_xlat_src_depth != 0
                    126:          && xlat->tme_fb_xlat_src_bits_per_pixel != 0
                    127:          && xlat->tme_fb_xlat_src_skipx >= 0
                    128:          && xlat->tme_fb_xlat_src_scanline_pad != 0
1.1.1.2   root      129:          && xlat->tme_fb_xlat_src_class != TME_FB_XLAT_CLASS_ANY
                    130:          && xlat->tme_fb_xlat_src_map != TME_FB_XLAT_MAP_ANY
                    131:          && xlat->tme_fb_xlat_src_map_bits != 0
                    132:          && xlat->tme_fb_xlat_src_mask_g != TME_FB_XLAT_MASK_ANY
                    133:          && xlat->tme_fb_xlat_src_mask_r != TME_FB_XLAT_MASK_ANY
                    134:          && xlat->tme_fb_xlat_src_mask_b != TME_FB_XLAT_MASK_ANY
1.1       root      135:          && xlat->tme_fb_xlat_dst_depth != 0
                    136:          && xlat->tme_fb_xlat_dst_bits_per_pixel != 0
                    137:          && xlat->tme_fb_xlat_dst_skipx >= 0
1.1.1.2   root      138:          && xlat->tme_fb_xlat_dst_scanline_pad != 0
                    139:          && xlat->tme_fb_xlat_dst_map != TME_FB_XLAT_MAP_ANY
                    140:          && xlat->tme_fb_xlat_dst_mask_g != TME_FB_XLAT_MASK_ANY
                    141:          && xlat->tme_fb_xlat_dst_mask_r != TME_FB_XLAT_MASK_ANY
                    142:          && xlat->tme_fb_xlat_dst_mask_b != TME_FB_XLAT_MASK_ANY
                    143:          );
1.1       root      144: }
                    145: 
                    146: /* this returns the number of bytes required for a source framebuffer
                    147:    scanline: */
                    148: static unsigned long
                    149: _tme_fb_xlat_src_bypl(const struct tme_fb_connection *src)
                    150: {
                    151:   /* NB that this definition must match the one in the
                    152:      automatically-generated xlat functions: */
                    153:   const unsigned long src_bypl
                    154:     = (((((src->tme_fb_connection_skipx
                    155:           + src->tme_fb_connection_width)
                    156:          * src->tme_fb_connection_bits_per_pixel)
                    157:         + (src->tme_fb_connection_scanline_pad - 1))
                    158:        & -src->tme_fb_connection_scanline_pad)
                    159:        / 8);
                    160:   return (src_bypl);
                    161: }
                    162: 
                    163: /* this returns the number of bytes required for a source framebuffer: */
                    164: static unsigned long
                    165: _tme_fb_xlat_src_bypb_real(const struct tme_fb_connection *src)
                    166: {
                    167:   /* NB that these definitions must match those in the
                    168:      automatically-generated xlat functions: */
                    169:   const unsigned long src_bypl
                    170:     = _tme_fb_xlat_src_bypl(src);
                    171:   const unsigned long src_bypb_real
                    172:     = (((src->tme_fb_connection_height * src_bypl) + 3) & -4);
                    173:   return (src_bypb_real);
                    174: }
                    175: 
                    176: /* this returns the number of bytes allocated for a source framebuffer.
                    177:    this includes the guard regions that are needed to guarantee that
                    178:    the translation function main loop terminates: */
                    179: static unsigned long
                    180: _tme_fb_xlat_src_bypb(const struct tme_fb_connection *src)
                    181: {
                    182:   /* NB that this definition must match the one in the
                    183:      automatically-generated xlat functions: */
                    184:   const unsigned long src_bypl
                    185:     = _tme_fb_xlat_src_bypl(src);
                    186:   const unsigned long src_bypb_real
                    187:     = _tme_fb_xlat_src_bypb_real(src);
                    188:   const unsigned long src_bypb
                    189:     = ((src_bypb_real + (src_bypl * 2)) & -4);
                    190:   return (src_bypb);
                    191: }
                    192: 
                    193: /* this forces the next translation to retranslate the entire buffer: */
                    194: void
                    195: tme_fb_xlat_redraw(struct tme_fb_connection *src)
                    196: {
                    197:   const tme_uint32_t *src_user;
                    198:   tme_uint32_t *src_back;
                    199:   unsigned int count32;
                    200: 
                    201:   src_user
                    202:     = ((const tme_uint32_t *) 
                    203:        src->tme_fb_connection_buffer);
                    204:   src_back
                    205:     = ((tme_uint32_t *) 
                    206:        (src->tme_fb_connection_buffer
                    207:        + _tme_fb_xlat_src_bypb(src)));
                    208:   for (count32 = _tme_fb_xlat_src_bypb_real(src) / sizeof(tme_uint32_t);
                    209:        count32-- > 0; ) {
                    210:     *(src_back++) = ~(*(src_user++));
                    211:   }
                    212: }
                    213: 
                    214: /* this allocates memory for a source framebuffer: */
                    215: int
                    216: tme_fb_xlat_alloc_src(struct tme_fb_connection *src)
                    217: {
                    218: 
                    219:   /* allocate the buffer.  remember, this is really two buffers - the
                    220:      first half is the real, current framebuffer, and the second half
                    221:      holds the last frame that was translated: */
                    222:   src->tme_fb_connection_buffer
                    223:     = tme_new0(tme_uint8_t,
                    224:               _tme_fb_xlat_src_bypb(src) * 2);
                    225: 
                    226:   /* force the next translation to do a complete redraw: */
                    227:   tme_fb_xlat_redraw(src);
                    228:   
                    229:   return (TME_OK);
                    230: }
                    231: 
1.1.1.2   root      232: /* this internal function gets or sets the needed colors on a
                    233:    destination framebuffer connection that is using the common
                    234:    translation functions: */
                    235: static tme_uint32_t
                    236: _tme_fb_xlat_colors_get_set(const struct tme_fb_connection *src,
                    237:                            unsigned int scale,
                    238:                            struct tme_fb_connection *dst,
                    239:                            struct tme_fb_color **_colors,
                    240:                            int get)
                    241: {
                    242:   tme_uint32_t src_mask;
                    243:   tme_uint32_t src_mask_g;
                    244:   tme_uint32_t src_mask_r;
                    245:   tme_uint32_t src_mask_b;
                    246:   tme_uint32_t src_shift_g;
                    247:   tme_uint32_t src_shift_r;
                    248:   tme_uint32_t src_shift_b;
                    249:   const void *src_map_g;
                    250:   const void *src_map_r;
                    251:   const void *src_map_b;
                    252:   tme_uint32_t value_g;
                    253:   tme_uint32_t value_r;
                    254:   tme_uint32_t value_b;
                    255:   tme_uint32_t src_max_g;
                    256:   tme_uint32_t src_max_r;
                    257:   tme_uint32_t src_max_b;
                    258:   tme_uint32_t color_count;
                    259:   tme_uint32_t color_i;
1.1.1.3 ! root      260:   tme_uint32_t color_j;
        !           261:   int compress_colors;
        !           262:   unsigned int dst_depth_g;
        !           263:   unsigned int dst_depth_r;
        !           264:   unsigned int dst_depth_b;
1.1.1.2   root      265:   struct tme_fb_color *colors;
                    266:   tme_uint32_t *pixels;
                    267:   tme_uint32_t invert_mask;
1.1.1.3 ! root      268:   tme_uint32_t colorset;
1.1.1.2   root      269: 
                    270:   /* get how to decompose source pixels into subfields.  if source
                    271:      pixels have no subfields, act as if all of the subfields are the
                    272:      entire source pixel: */
                    273:   src_mask = (0xffffffff >> (32 - src->tme_fb_connection_depth));
                    274:   src_mask_g = src->tme_fb_connection_mask_g;
                    275:   src_mask_r = src->tme_fb_connection_mask_r;
                    276:   src_mask_b = src->tme_fb_connection_mask_b;
                    277:   if (src_mask_g == 0) {
                    278:     src_mask_g = src_mask;
                    279:     src_mask_r = src_mask;
                    280:     src_mask_b = src_mask;
                    281:   }
                    282: 
                    283:   /* if source intensities are index mapped, their common maximum is
                    284:      the mask of the mapping size range in bits: */
                    285:   src_map_g = src->tme_fb_connection_map_g;
                    286:   src_map_r = src->tme_fb_connection_map_r;
                    287:   src_map_b = src->tme_fb_connection_map_b;
                    288:   if (src_map_g != NULL) {
                    289:     src_max_g = (0xffffffff >> (32 - src->tme_fb_connection_map_bits));
                    290:     src_max_r = src_max_g;
                    291:     src_max_b = src_max_g;
                    292:   }
                    293: 
                    294:   /* otherwise, source intensities are linearly mapped, and each
                    295:      primary's maximum intensity is the base mask of its subfield: */
                    296:   else {
                    297:     src_max_g = TME_FB_XLAT_MAP_BASE_MASK(src_mask_g);
                    298:     src_max_r = TME_FB_XLAT_MAP_BASE_MASK(src_mask_r);
                    299:     src_max_b = TME_FB_XLAT_MAP_BASE_MASK(src_mask_b);
                    300:   }
                    301: 
                    302:   /* the source intensity maximums must be greater than zero, and not
                    303:      larger than 16 bits: */
                    304:   assert (src_max_g > 0 && src_max_g <= 0xffff);
                    305:   assert (src_max_r > 0 && src_max_r <= 0xffff);
                    306:   assert (src_max_b > 0 && src_max_b <= 0xffff);
                    307: 
                    308:   /* get any inversion mask: */
                    309:   invert_mask = (src->tme_fb_connection_inverted ? 0xffff : 0);
                    310: 
                    311:   /* if we're halving, the intensity maximums are four times what they
                    312:      would be otherwise, because the intensities from four pixels are
                    313:      added together: */
                    314:   if (scale == TME_FB_XLAT_SCALE_HALF) {
                    315:     src_max_g *= 4;
                    316:     src_max_r *= 4;
                    317:     src_max_b *= 4;
                    318:   }
                    319: 
                    320:   /* if we're not halving, and either the source pixel mask is less
                    321:      than the maximum index mask or source pixels have no subfields,
                    322:      we will index map source pixels directly to destination
                    323:      pixels: */
                    324:   if (scale != TME_FB_XLAT_SCALE_HALF
                    325:       && (src_mask <= TME_FB_XLAT_MAP_INDEX_MASK_MAX
                    326:          || src_mask_g == src_mask)) {
                    327: 
                    328:     /* we will allocate as many colors as we have source pixels: */
                    329:     color_count = src_mask + 1;
1.1.1.3 ! root      330:     colorset = TME_FB_COLORSET_NONE;
1.1.1.2   root      331:   }
                    332:   
                    333:   /* otherwise, either we're halving, or source pixels are too big to
                    334:      map directly and they have subfields.  the translation code will 
                    335:      decompose pixels into intensities: */
                    336: 
                    337:   /* if the source class is monochrome, we only have to deal with
                    338:      the green primary: */
                    339:   else if (src->tme_fb_connection_class == TME_FB_XLAT_CLASS_MONOCHROME) {
                    340: 
                    341:     /* the translation function will index map green intensity values
                    342:        directly into pixels.  we may need to scale the intensities so
                    343:        they can be indexed: */
                    344:     for (; src_max_g > TME_FB_XLAT_MAP_INDEX_MASK_MAX; src_max_g >>= 1);
                    345: 
                    346:     /* allocate colors for src_max_g intensities: */
                    347:     color_count = src_max_g + 1;
1.1.1.3 ! root      348:     colorset = TME_FB_COLORSET_NONE;
1.1.1.2   root      349:     src_mask_g = TME_FB_XLAT_MAP_INDEX_MASK_MAX;
                    350:     src_map_g = NULL;
                    351:     src_mask_r = src_mask_g;
                    352:     src_mask_b = src_mask_g;
                    353:     src_map_r = src_map_g;
                    354:     src_map_b = src_map_g;
                    355:     src_max_r = src_max_g;
                    356:     src_max_b = src_max_g;
                    357:   }
                    358: 
                    359:   /* otherwise, we have to deal with all three primaries: */
                    360: 
                    361:   /* if the destination is color and has subfields: */
                    362:   else if (dst->tme_fb_connection_class == TME_FB_XLAT_CLASS_COLOR
                    363:           && dst->tme_fb_connection_mask_g != 0) {
                    364:        
                    365:     /* if the destination maps intensities linearly, we don't need to
                    366:        allocate colors at all: */
                    367:     if (dst->tme_fb_connection_map_g == NULL) {
                    368: 
                    369:       /* however, we can't do this yet with a source framebuffer that
                    370:         is inverted: */
                    371:       if (src->tme_fb_connection_inverted) {
                    372:        abort();
                    373:       }
                    374:          
                    375:       /* nothing to do */
                    376:       *_colors = NULL;
1.1.1.3 ! root      377:       dst->tme_fb_connection_map_pixel_count = 0;
        !           378:       return (TME_FB_COLORSET_NONE);
1.1.1.2   root      379:     }
                    380: 
                    381:     /* otherwise, the translation function will index map the
                    382:        intensity values into subfield values.  we may need to scale
                    383:        the intensities so they can be indexed: */
                    384:     for (; src_max_g > TME_FB_XLAT_MAP_INDEX_MASK_MAX; src_max_g >>= 1);
                    385:     for (; src_max_r > TME_FB_XLAT_MAP_INDEX_MASK_MAX; src_max_r >>= 1);
                    386:     for (; src_max_b > TME_FB_XLAT_MAP_INDEX_MASK_MAX; src_max_b >>= 1);
                    387: 
                    388:     /* size the color array: */
                    389:     color_count = src_max_g + 1 + src_max_r + 1 + src_max_b + 1;
1.1.1.3 ! root      390:     colorset = TME_FB_COLORSET_DIRECT_COLOR;
1.1.1.2   root      391: 
                    392:     /* if we're getting the needed colors: */
                    393:     if (get) {
                    394: 
                    395:       /* allocate the color array: */
                    396:       colors = tme_new0(struct tme_fb_color, color_count);
                    397: 
                    398:       /* make the colors to allocate from all of the different
                    399:         primary intensities: */
                    400:       color_i = 0;
                    401: #define _TME_FB_XLAT_INDEX_COLORS(value, max, primary)         \
                    402:   do {                                                         \
                    403:     for (value = 0; value <= (max); value++, color_i++) {      \
                    404:       colors[color_i].primary = ((0xffff * value) / (max)) ^ invert_mask;\
                    405:     }                                                          \
                    406:   } while (/* CONSTCOND */ 0)
                    407:       _TME_FB_XLAT_INDEX_COLORS(value_g, src_max_g, tme_fb_color_value_g);
                    408:       _TME_FB_XLAT_INDEX_COLORS(value_r, src_max_r, tme_fb_color_value_r);
                    409:       _TME_FB_XLAT_INDEX_COLORS(value_b, src_max_b, tme_fb_color_value_b);
                    410: #undef _TME_FB_XLAT_INDEX_COLORS
                    411: 
                    412:       /* return the needed colors: */
                    413:       *_colors = colors;
1.1.1.3 ! root      414:       dst->tme_fb_connection_map_pixel_count = color_count;
        !           415:       return (colorset);
1.1.1.2   root      416:     }
                    417: 
                    418:     /* set up the intensity index maps: */
                    419:     colors = *_colors;
                    420:     color_i = 0;
                    421: #define __TME_FB_XLAT_INDEX_SUBFIELDS(value, max, primary_mask, primary_shift, primary_map, type)\
                    422:   do {                                                                                 \
                    423:     dst->primary_map = tme_new(type, (max) + 1);                                       \
                    424:     for (value = 0; value <= (max); value++, color_i++) {                              \
                    425:       ((type *) dst->primary_map)[value]                                               \
                    426:        = ((colors[color_i].tme_fb_color_pixel                                          \
                    427:            & dst->primary_mask)                                                        \
                    428:           >> primary_shift);                                                           \
                    429:     }                                                                                  \
                    430:   } while (/* CONSTCOND */  0)
                    431: #define _TME_FB_XLAT_INDEX_SUBFIELDS(value, max, primary_mask, primary_shift, primary_map)\
                    432:   do {                                                                                 \
                    433:     for (primary_shift = 0;                                                            \
                    434:         ((dst->primary_mask >> primary_shift) & 1) == 0;                               \
                    435:         primary_shift++);                                                              \
                    436:     if (TME_FB_XLAT_MAP_BASE_MASK(dst->primary_mask) <= 0xff) {                        \
                    437:       __TME_FB_XLAT_INDEX_SUBFIELDS(value, max, primary_mask, primary_shift, primary_map, tme_uint8_t);\
                    438:     }                                                                                  \
                    439:     else {                                                                             \
                    440:       __TME_FB_XLAT_INDEX_SUBFIELDS(value, max, primary_mask, primary_shift, primary_map, tme_uint16_t);\
                    441:     }                                                                                  \
                    442:   } while (/* CONSTCOND */ 0)
                    443:     _TME_FB_XLAT_INDEX_SUBFIELDS(value_g, src_max_g, tme_fb_connection_mask_g, src_shift_g, tme_fb_connection_map_g);
                    444:     _TME_FB_XLAT_INDEX_SUBFIELDS(value_r, src_max_r, tme_fb_connection_mask_r, src_shift_r, tme_fb_connection_map_r);
                    445:     _TME_FB_XLAT_INDEX_SUBFIELDS(value_b, src_max_b, tme_fb_connection_mask_b, src_shift_b, tme_fb_connection_map_b);
                    446: #undef _TME_FB_XLAT_INDEX_SUBFIELDS
                    447: #undef __TME_FB_XLAT_INDEX_SUBFIELDS
                    448:   }
                    449: 
                    450:   /* otherwise, the destination is either not color or it doesn't
                    451:      have subfields.  we need to allocate colors to map fake
                    452:      source pixels: */
                    453:   else {
                    454:     src_mask_g = TME_FB_XLAT_MASK_DEFAULT_G;
                    455:     src_mask_r = TME_FB_XLAT_MASK_DEFAULT_R;
                    456:     src_mask_b = TME_FB_XLAT_MASK_DEFAULT_B;
                    457:     src_map_g = NULL;
                    458:     src_map_r = NULL;
                    459:     src_map_b = NULL;
                    460:     src_max_g = TME_FB_XLAT_MAP_BASE_MASK(src_mask_g);
                    461:     src_max_r = TME_FB_XLAT_MAP_BASE_MASK(src_mask_r);
                    462:     src_max_b = TME_FB_XLAT_MAP_BASE_MASK(src_mask_b);
                    463:     color_count = (src_mask_g | src_mask_r | src_mask_b) + 1;
1.1.1.3 ! root      464:     colorset = TME_FB_COLORSET_PSEUDO_COLOR;
1.1.1.2   root      465:   }
                    466: 
                    467:   /* if we get here, we're allocating colors from source pixel values
                    468:      (or possibly fake source pixel values): */
                    469: 
                    470:   /* if we're getting the needed colors: */
                    471:   if (get) {
                    472: 
1.1.1.3 ! root      473:     /* if the number of colors we need is clearly more than the
        !           474:        destination's depth can possibly handle, and the destination is
        !           475:        either monochrome or is color with no pixel subfields, asking
        !           476:        for this huge number of distinct colors will probably get us a
        !           477:        poorly representative subset.
        !           478:        
        !           479:        in general, we can't help this.  but in the specific case of
        !           480:        source pixels that directly map to intensity(s), we can remove
        !           481:        some of the less significant bits of the source pixel subfield
        !           482:        mask(s), so that we only ask to allocate as many distinct
        !           483:        colors as the destination's depth can handle: */
        !           484:     compress_colors
        !           485:       = ((color_count >> dst->tme_fb_connection_depth) > 0
        !           486:         && (dst->tme_fb_connection_class == TME_FB_XLAT_CLASS_MONOCHROME
        !           487:             || dst->tme_fb_connection_mask_g == 0)
        !           488:         && src_map_g == NULL);
        !           489:     if (compress_colors) {
        !           490: 
        !           491:       /* get the depth for each primary: */
        !           492:       if (src->tme_fb_connection_class == TME_FB_XLAT_CLASS_MONOCHROME) {
        !           493:        dst_depth_g = dst->tme_fb_connection_depth;
        !           494:        dst_depth_r = 0;
        !           495:        dst_depth_b = 0;
        !           496:       }
        !           497:       else {
        !           498:        dst_depth_r = dst->tme_fb_connection_depth;
        !           499:        dst_depth_g = (dst_depth_r + 2) / 3;
        !           500:        dst_depth_r -= dst_depth_g;
        !           501:        dst_depth_b = (dst_depth_r + 1) / 2;
        !           502:        dst_depth_r -= dst_depth_b;
        !           503:       }
        !           504: 
        !           505:       /* remove some of the less significant bits in the subfield
        !           506:          masks and recalculate the source intensity maximums: */
        !           507: #define _TME_FB_XLAT_LIMIT_MASK(src_mask_i, src_max_i, dst_depth_i)            \
        !           508:   do {                                                                         \
        !           509:     src_mask_i ^= (src_mask_i & (src_mask_i >> dst_depth_i));                  \
        !           510:     src_max_i = (src_mask_i ? TME_FB_XLAT_MAP_BASE_MASK(src_mask_i) : 1);      \
        !           511:   } while (/* CONSTCOND */ 0)
        !           512:       _TME_FB_XLAT_LIMIT_MASK(src_mask_g, src_max_g, dst_depth_g);
        !           513:       _TME_FB_XLAT_LIMIT_MASK(src_mask_r, src_max_r, dst_depth_r);
        !           514:       _TME_FB_XLAT_LIMIT_MASK(src_mask_b, src_max_b, dst_depth_b);
        !           515: #undef _TME_FB_XLAT_LIMIT_MASK
        !           516:     }
        !           517: 
1.1.1.2   root      518:     /* make shift counts for the subfields and shift their trailing zeroes off: */
                    519:     for (src_shift_g = 0; (src_mask_g & 1) == 0; src_shift_g++, src_mask_g >>= 1);
                    520:     for (src_shift_r = 0; (src_mask_r & 1) == 0; src_shift_r++, src_mask_r >>= 1);
                    521:     for (src_shift_b = 0; (src_mask_b & 1) == 0; src_shift_b++, src_mask_b >>= 1);
                    522: 
                    523:     /* allocate the color array: */
                    524:     colors = tme_new0(struct tme_fb_color, color_count);
                    525: 
                    526:     /* loop over the source pixels: */
                    527:     for (color_i = 0;
                    528:         color_i < color_count;
                    529:         color_i++) {
                    530:       
                    531:       /* get the raw primary values: */
                    532:       value_g = (color_i >> src_shift_g) & src_mask_g;
                    533:       value_r = (color_i >> src_shift_r) & src_mask_r;
                    534:       value_b = (color_i >> src_shift_b) & src_mask_b;
                    535: 
1.1.1.3 ! root      536:       /* we give a distinct pixel value for each distinct color we ask
        !           537:         for, since we may ask for a lot of duplicates.  this isn't
        !           538:         really a pixel value at all, anywhere - it only serves to
        !           539:         group duplicate colors together in the color array: */
        !           540:       if (compress_colors) {
        !           541:        color_j = value_g;
        !           542:        color_j = (color_j * (src_mask_r + 1)) + value_r;
        !           543:        color_j = (color_j * (src_mask_b + 1)) + value_b;
        !           544:       }
        !           545:       else {
        !           546:        color_j = color_i;
        !           547:       }
        !           548: 
1.1.1.2   root      549:       /* if the primaries are index mapped, turn the raw primary
                    550:         values into intensities: */
                    551:       if (src_map_g != NULL) {
                    552: 
                    553:        /* if intensities are stored as 8 bits: */
                    554:        if (src_max_g <= 0xff) {
                    555:          value_g = ((const tme_uint8_t *) src_map_g)[value_g];
                    556:          value_r = ((const tme_uint8_t *) src_map_r)[value_r];
                    557:          value_b = ((const tme_uint8_t *) src_map_b)[value_b];
                    558:        }
                    559: 
                    560:        /* otherwise, intensities are stored as 16 bits: */
                    561:        else {
                    562:          value_g = ((const tme_uint16_t *) src_map_g)[value_g];
                    563:          value_r = ((const tme_uint16_t *) src_map_r)[value_r];
                    564:          value_b = ((const tme_uint16_t *) src_map_b)[value_b];
                    565:        }
                    566:       }
                    567: 
                    568:       /* scale the intensities to 16 bits and possibly invert them: */
                    569:       value_g = ((0xffff * value_g) / src_max_g) ^ invert_mask;
                    570:       value_r = ((0xffff * value_r) / src_max_r) ^ invert_mask;
                    571:       value_b = ((0xffff * value_b) / src_max_b) ^ invert_mask;
                    572: 
                    573:       /* if the source class is monochrome, use only the green primary: */
                    574:       if (src->tme_fb_connection_class == TME_FB_XLAT_CLASS_MONOCHROME) {
                    575:        value_r = value_g;
                    576:        value_b = value_g;
                    577:       }
                    578: 
                    579:       /* allocate this color: */
1.1.1.3 ! root      580:       colors[color_i].tme_fb_color_pixel = color_j;
1.1.1.2   root      581:       colors[color_i].tme_fb_color_value_g = value_g;
                    582:       colors[color_i].tme_fb_color_value_r = value_r;
                    583:       colors[color_i].tme_fb_color_value_b = value_b;
                    584:     }
                    585: 
                    586:     /* return the needed colors: */
                    587:     *_colors = colors;
1.1.1.3 ! root      588:     dst->tme_fb_connection_map_pixel_count = color_count;
        !           589:     return (colorset);
1.1.1.2   root      590:   }
                    591: 
                    592:   /* otherwise, take in the allocated colors: */
                    593:   colors = *_colors;
                    594:   pixels = tme_new(tme_uint32_t, color_count);
                    595:   for (color_i = 0;
                    596:        color_i < color_count;
                    597:        color_i++) {
                    598:     pixels[color_i] = colors[color_i].tme_fb_color_pixel;
                    599:   }
                    600:   dst->tme_fb_connection_map_pixel = pixels;
                    601:   dst->tme_fb_connection_map_pixel_count = color_count;
                    602:   tme_free(colors);
                    603:   return (0);
                    604: }
                    605: 
                    606: /* this gets the needed colors on a destination framebuffer connection
                    607:    that is using the common translation functions: */
                    608: tme_uint32_t
                    609: tme_fb_xlat_colors_get(const struct tme_fb_connection *src,
                    610:                       unsigned int scale,
                    611:                       struct tme_fb_connection *dst,
                    612:                       struct tme_fb_color **_colors)
                    613: {
                    614:   return (_tme_fb_xlat_colors_get_set(src, scale, dst, _colors, TRUE));
                    615: }
                    616: 
                    617: /* this sets the needed colors on a destination framebuffer connection
                    618:    that is using the common translation functions: */
                    619: void
                    620: tme_fb_xlat_colors_set(const struct tme_fb_connection *src,
                    621:                       unsigned int scale,
                    622:                       struct tme_fb_connection *dst,
                    623:                       struct tme_fb_color *colors)
                    624: {
                    625:   _tme_fb_xlat_colors_get_set(src, scale, dst, &colors, FALSE);
                    626: }
                    627: 
1.1       root      628: /* this scores a framebuffer connection: */
                    629: int
                    630: tme_fb_connection_score(struct tme_connection *conn, unsigned int *_score)
                    631: {
                    632:   struct tme_fb_connection *conn_fb;
                    633:   struct tme_fb_connection *conn_fb_other;
                    634: 
                    635:   /* both sides must be Ethernet connections: */
                    636:   assert(conn->tme_connection_type == TME_CONNECTION_FRAMEBUFFER);
                    637:   assert(conn->tme_connection_other->tme_connection_type == TME_CONNECTION_FRAMEBUFFER);
                    638: 
                    639:   /* one side must be a real display and the other side must be a
                    640:      framebuffer emulator: */
                    641:   conn_fb = (struct tme_fb_connection *) conn;
                    642:   conn_fb_other = (struct tme_fb_connection *) conn->tme_connection_other;
                    643:   *_score = ((conn_fb->tme_fb_connection_mode_change != NULL)
                    644:             != (conn_fb_other->tme_fb_connection_mode_change != NULL));
                    645:   return (TME_OK);
                    646: }
                    647: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.