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