1 /* $Id: fb.c,v 1.5 2007/08/25 21:05:30 fredette Exp $ */
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>
37 _TME_RCSID("$Id: fb.c,v 1.5 2007/08/25 21:05:30 fredette Exp $");
38 
39 /* includes: */
40 #include <tme/generic/fb.h>
41 
42 /* include the automatically-generated translation functions: */
43 #include "fb-xlat-auto.c"
44 
45 /* macros: */
46 #define TME_FB_COLORSET_DIRECT_COLOR	(1)
47 #define TME_FB_COLORSET_PSEUDO_COLOR	(2)
48 
49 /* this returns the best translation function: */
50 const struct tme_fb_xlat *
tme_fb_xlat_best(const struct tme_fb_xlat * xlat_user)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);
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);
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);
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);
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
tme_fb_xlat_is_optimal(const struct tme_fb_xlat * xlat)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
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
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
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 	  );
144 }
145 
146 /* this returns the number of bytes required for a source framebuffer
147    scanline: */
148 static unsigned long
_tme_fb_xlat_src_bypl(const struct tme_fb_connection * src)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
_tme_fb_xlat_src_bypb_real(const struct tme_fb_connection * src)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
_tme_fb_xlat_src_bypb(const struct tme_fb_connection * src)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
tme_fb_xlat_redraw(struct tme_fb_connection * src)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
tme_fb_xlat_alloc_src(struct tme_fb_connection * src)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 
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
_tme_fb_xlat_colors_get_set(const struct tme_fb_connection * src,unsigned int scale,struct tme_fb_connection * dst,struct tme_fb_color ** _colors,int get)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;
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;
265   struct tme_fb_color *colors;
266   tme_uint32_t *pixels;
267   tme_uint32_t invert_mask;
268   tme_uint32_t colorset;
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;
330     colorset = TME_FB_COLORSET_NONE;
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;
348     colorset = TME_FB_COLORSET_NONE;
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;
377       dst->tme_fb_connection_map_pixel_count = 0;
378       return (TME_FB_COLORSET_NONE);
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;
390     colorset = TME_FB_COLORSET_DIRECT_COLOR;
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;
414       dst->tme_fb_connection_map_pixel_count = color_count;
415       return (colorset);
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;
464     colorset = TME_FB_COLORSET_PSEUDO_COLOR;
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 
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 
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 
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 
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: */
580       colors[color_i].tme_fb_color_pixel = color_j;
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;
588     dst->tme_fb_connection_map_pixel_count = color_count;
589     return (colorset);
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
tme_fb_xlat_colors_get(const struct tme_fb_connection * src,unsigned int scale,struct tme_fb_connection * dst,struct tme_fb_color ** _colors)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
tme_fb_xlat_colors_set(const struct tme_fb_connection * src,unsigned int scale,struct tme_fb_connection * dst,struct tme_fb_color * colors)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 
628 /* this scores a framebuffer connection: */
629 int
tme_fb_connection_score(struct tme_connection * conn,unsigned int * _score)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 
648