1 // license:BSD-3-Clause
2 // copyright-holders:Ryan Holtz
3 #if 0
4 static inline void video_filter16(int *out_r, int *out_g, int *out_b, uint16_t* vbuff, uint8_t* hbuff, const uint32_t hres);
5 static inline void divot_filter16(uint8_t* r, uint8_t* g, uint8_t* b, uint16_t* fbuff, uint32_t fbuff_index);
6 static inline void restore_filter16(int32_t* r, int32_t* g, int32_t* b, uint16_t* fbuff, uint32_t fbuff_index, uint32_t hres);
7 static inline void divot_filter16_buffer(int32_t* r, int32_t* g, int32_t* b, color_t* vibuffer);
8 static inline void restore_filter16_buffer(int32_t* r, int32_t* g, int32_t* b, color_t* vibuff, uint32_t hres);
9 static inline void restore_two(color_t* filtered, color_t* neighbour);
10 static inline void video_max(uint32_t* Pixels, uint8_t* max, uint32_t* enb);
11 static inline uint32_t ge_two(uint32_t enb);
12 
13 static inline void video_filter16(int *out_r, int *out_g, int *out_b, uint16_t* vbuff, uint8_t* hbuff, const uint32_t hres)
14 {
15 	color_t penumax, penumin, max, min;
16 	uint16_t pix = *vbuff;
17 	const uint8_t centercvg = (*hbuff & 3) + ((pix & 1) << 2) + 1;
18 	uint32_t numoffull = 1;
19 	uint32_t cvg;
20 	uint32_t backr[7], backg[7], backb[7];
21 	uint32_t invr[7], invg[7], invb[7];
22 	int32_t coeff;
23 	int32_t leftup = -hres - 2;
24 	int32_t leftdown = hres - 2;
25 	int32_t toleft = -2;
26 	uint32_t colr, colg, colb;
27 	uint32_t enb;
28 	uint32_t r = ((pix >> 8) & 0xf8) | (pix >> 13);
29 	uint32_t g = ((pix >> 3) & 0xf8) | ((pix >>  8) & 0x07);
30 	uint32_t b = ((pix << 2) & 0xf8) | ((pix >>  3) & 0x07);
31 
32 	*out_r = *out_g = *out_b = 0;
33 
34 	backr[0] = r;
35 	backg[0] = g;
36 	backb[0] = b;
37 	invr[0] = ~r;
38 	invg[0] = ~g;
39 	invb[0] = ~b;
40 
41 	if (centercvg == 8)
42 	{
43 		*out_r = r;
44 		*out_g = g;
45 		*out_b = b;
46 		return;
47 	}
48 
49 	for(int i = 0; i < 5; i++)
50 	{
51 		pix = vbuff[leftup ^ WORD_ADDR_XOR];
52 		cvg = hbuff[leftup ^ BYTE_ADDR_XOR] & 3;
53 		if(i & 1)
54 		{
55 			if (cvg == 3 && (pix & 1))
56 			{
57 				backr[numoffull] = ((pix >> 8) & 0xf8) | (pix >> 13);
58 				backg[numoffull] = ((pix >> 3) & 0xf8) | ((pix >>  8) & 0x07);
59 				backb[numoffull] = ((pix << 2) & 0xf8) | ((pix >>  3) & 0x07);
60 				invr[numoffull] = ~backr[numoffull];
61 				invg[numoffull] = ~backg[numoffull];
62 				invb[numoffull] = ~backb[numoffull];
63 			}
64 			else
65 			{
66 				backr[numoffull] = invr[numoffull] = 0;
67 				backg[numoffull] = invg[numoffull] = 0;
68 				backb[numoffull] = invb[numoffull] = 0;
69 			}
70 			numoffull++;
71 		}
72 		leftup++;
73 	}
74 
75 	for(int i = 0; i < 5; i++)
76 	{
77 		pix = vbuff[leftdown ^ WORD_ADDR_XOR];
78 		cvg = hbuff[leftdown ^ BYTE_ADDR_XOR] & 3;
79 		if (i&1)
80 		{
81 			if (cvg == 3 && (pix & 1))
82 			{
83 				backr[numoffull] = ((pix >> 8) & 0xf8) | (pix >> 13);
84 				backg[numoffull] = ((pix >> 3) & 0xf8) | ((pix >>  8) & 0x07);
85 				backb[numoffull] = ((pix << 2) & 0xf8) | ((pix >>  3) & 0x07);
86 				invr[numoffull] = ~backr[numoffull];
87 				invg[numoffull] = ~backg[numoffull];
88 				invb[numoffull] = ~backb[numoffull];
89 			}
90 			else
91 			{
92 				backr[numoffull] = invr[numoffull] = 0;
93 				backg[numoffull] = invg[numoffull] = 0;
94 				backb[numoffull] = invb[numoffull] = 0;
95 			}
96 			numoffull++;
97 		}
98 		leftdown++;
99 	}
100 
101 	for(int i = 0; i < 5; i++)
102 	{
103 		pix = vbuff[toleft ^ WORD_ADDR_XOR];
104 		cvg = hbuff[toleft ^ BYTE_ADDR_XOR] & 3;
105 		if (!(i&3))
106 		{
107 			if (cvg == 3 && (pix & 1))
108 			{
109 				backr[numoffull] = ((pix >> 8) & 0xf8) | (pix >> 13);
110 				backg[numoffull] = ((pix >> 3) & 0xf8) | ((pix >>  8) & 0x07);
111 				backb[numoffull] = ((pix << 2) & 0xf8) | ((pix >>  3) & 0x07);
112 				invr[numoffull] = ~backr[numoffull];
113 				invg[numoffull] = ~backg[numoffull];
114 				invb[numoffull] = ~backb[numoffull];
115 			}
116 			else
117 			{
118 				backr[numoffull] = invr[numoffull] = 0;
119 				backg[numoffull] = invg[numoffull] = 0;
120 				backb[numoffull] = invb[numoffull] = 0;
121 			}
122 			numoffull++;
123 		}
124 		toleft++;
125 	}
126 
127 	video_max(&backr[0], &max.i.r, &enb);
128 	for(int i = 1; i < 7; i++)
129 	{
130 		if (!((enb >> i) & 1))
131 		{
132 			backr[i] = 0;
133 		}
134 	}
135 	video_max(&backg[0], &max.i.g, &enb);
136 	for (int i = 1; i < 7; i++)
137 	{
138 		if (!((enb >> i) & 1))
139 		{
140 			backg[i] = 0;
141 		}
142 	}
143 	video_max(&backb[0], &max.i.b, &enb);
144 	for (int i = 1; i < 7; i++)
145 	{
146 		if (!((enb >> i) & 1))
147 		{
148 			backb[i] = 0;
149 		}
150 	}
151 	video_max(&invr[0], &min.i.r, &enb);
152 	for (int i = 1; i < 7; i++)
153 	{
154 		if (!((enb >> i) & 1))
155 		{
156 			backr[i] = 0;
157 		}
158 	}
159 	video_max(&invg[0], &min.i.g, &enb);
160 	for (int i = 1; i < 7; i++)
161 	{
162 		if (!((enb >> i) & 1))
163 		{
164 			backg[i] = 0;
165 		}
166 	}
167 	video_max(&invb[0], &min.i.b, &enb);
168 	for (int i = 1; i < 7; i++)
169 	{
170 		if (!((enb >> i) & 1))
171 		{
172 			backb[i] = 0;
173 		}
174 	}
175 
176 	video_max(&backr[0], &penumax.i.r, &enb);
177 	penumax.i.r = ge_two(enb) ? max.i.r : penumax.i.r;
178 
179 	video_max(&backg[0], &penumax.i.g, &enb);
180 	penumax.i.g = ge_two(enb) ? max.i.g : penumax.i.g;
181 
182 	video_max(&backb[0], &penumax.i.b, &enb);
183 	penumax.i.b = ge_two(enb) ? max.i.b : penumax.i.b;
184 
185 	video_max(&invr[0], &penumin.i.r, &enb);
186 	penumin.i.r = ge_two(enb) ? min.i.r : penumin.i.r;
187 
188 	video_max(&invg[0], &penumin.i.g, &enb);
189 	penumin.i.g = ge_two(enb) ? min.i.g : penumin.i.g;
190 
191 	video_max(&invb[0], &penumin.i.b, &enb);
192 	penumin.i.b = ge_two(enb) ? min.i.b : penumin.i.b;
193 
194 	penumin.i.r = ~penumin.i.r;
195 	penumin.i.g = ~penumin.i.g;
196 	penumin.i.b = ~penumin.i.b;
197 
198 	colr = (uint32_t)penumin.i.r + (uint32_t)penumax.i.r - (r << 1);
199 	colg = (uint32_t)penumin.i.g + (uint32_t)penumax.i.g - (g << 1);
200 	colb = (uint32_t)penumin.i.b + (uint32_t)penumax.i.b - (b << 1);
201 	coeff = 8 - centercvg;
202 	colr = (((colr * coeff) + 4) >> 3) + r;
203 	colg = (((colg * coeff) + 4) >> 3) + g;
204 	colb = (((colb * coeff) + 4) >> 3) + b;
205 
206 	*out_r = colr & 0xff;
207 	*out_g = colg & 0xff;
208 	*out_b = colb & 0xff;
209 	return;
210 }
211 
212 // This needs to be fixed for endianness.
213 static inline void divot_filter16(uint8_t* r, uint8_t* g, uint8_t* b, uint16_t* fbuff, uint32_t fbuff_index)
214 {
215 	uint8_t leftr, leftg, leftb, rightr, rightg, rightb;
216 	uint16_t leftpix, rightpix;
217 	uint16_t* next, *prev;
218 	uint32_t Lsw = fbuff_index & 1;
219 	next = (Lsw) ? (uint16_t*)(fbuff - 1) : (uint16_t*)(fbuff + 3);
220 	prev = (Lsw) ? (uint16_t*)(fbuff - 3) : (uint16_t*)(fbuff + 1);
221 	leftpix = *prev;
222 	rightpix = *next;
223 
224 	//leftpix = *(fbuff - 1); //for BE targets
225 	//rightpix = *(fbuff + 1);
226 
227 	leftr = ((leftpix >> 8) & 0xf8) | (leftpix >> 13);
228 	leftg = ((leftpix >> 3) & 0xf8) | ((leftpix >>  8) & 0x07);
229 	leftb = ((leftpix << 2) & 0xf8) | ((leftpix >>  3) & 0x07);
230 	rightr = ((rightpix >> 8) & 0xf8) | (rightpix >> 13);
231 	rightg = ((rightpix >> 3) & 0xf8) | ((rightpix >>  8) & 0x07);
232 	rightb = ((rightpix << 2) & 0xf8) | ((rightpix >>  3) & 0x07);
233 	if ((leftr >= *r && rightr >= leftr) || (leftr >= rightr && *r >= leftr))
234 	{
235 		*r = leftr; //left = median value
236 	}
237 	if ((rightr >= *r && leftr >= rightr) || (rightr >= leftr && *r >= rightr))
238 	{
239 		*r = rightr; //right = median, else *r itself is median
240 	}
241 	if ((leftg >= *g && rightg >= leftg) || (leftg >= rightg && *g >= leftg))
242 	{
243 		*g = leftg;
244 	}
245 	if ((rightg >= *g && leftg >= rightg) || (rightg >= leftg && *g >= rightg))
246 	{
247 		*g = rightg;
248 	}
249 	if ((leftb >= *b && rightb >= leftb) || (leftb >= rightb && *b >= leftb))
250 	{
251 		*b = leftb;
252 	}
253 	if ((rightb >= *b && leftb >= rightb) || (rightb >= leftb && *b >= rightb))
254 	{
255 		*b = rightb;
256 	}
257 }
258 
259 static inline void divot_filter16_buffer(int* r, int* g, int* b, color_t* vibuffer)
260 {
261 	color_t leftpix = vibuffer[-1];
262 	color_t rightpix = vibuffer[1];
263 	color_t filtered = *vibuffer;
264 
265 	*r = filtered.i.r;
266 	*g = filtered.i.g;
267 	*b = filtered.i.b;
268 	uint32_t leftr = leftpix.i.r;
269 	uint32_t leftg = leftpix.i.g;
270 	uint32_t leftb = leftpix.i.b;
271 	uint32_t rightr = rightpix.i.r;
272 	uint32_t rightg = rightpix.i.g;
273 	uint32_t rightb = rightpix.i.b;
274 
275 	if ((leftr >= *r && rightr >= leftr) || (leftr >= rightr && *r >= leftr))
276 	{
277 		*r = leftr; //left = median value
278 	}
279 	if ((rightr >= *r && leftr >= rightr) || (rightr >= leftr && *r >= rightr))
280 	{
281 		*r = rightr; //right = median, else *r itself is median
282 	}
283 	if ((leftg >= *g && rightg >= leftg) || (leftg >= rightg && *g >= leftg))
284 	{
285 		*g = leftg;
286 	}
287 	if ((rightg >= *g && leftg >= rightg) || (rightg >= leftg && *g >= rightg))
288 	{
289 		*g = rightg;
290 	}
291 	if ((leftb >= *b && rightb >= leftb) || (leftb >= rightb && *b >= leftb))
292 	{
293 		*b = leftb;
294 	}
295 	if ((rightb >= *b && leftb >= rightb) || (rightb >= leftb && *b >= rightb))
296 	{
297 		*b = rightb;
298 	}
299 
300 	filtered.i.r = *r;
301 	filtered.i.g = *g;
302 	filtered.i.b = *b;
303 }
304 
305 // Fix me.
306 static inline void restore_filter16(int* r, int* g, int* b, uint16_t* fbuff, uint32_t fbuff_index, uint32_t hres)
307 {
308 	int32_t leftuppix = -hres - 1;
309 	int32_t leftdownpix = hres - 1;
310 	int32_t toleftpix = -1;
311 	uint8_t tempr, tempg, tempb;
312 	uint16_t pix;
313 	int i;
314 
315 	uint8_t r5 = *r;
316 	uint8_t g5 = *g;
317 	uint8_t b5 = *b;
318 	r5 &= ~7;
319 	g5 &= ~7;
320 	b5 &= ~7;
321 
322 	for (i = 0; i < 3; i++)
323 	{
324 		pix = fbuff[leftuppix ^ 1];
325 		tempr = ((pix >> 8) & 0xf8) | (pix >> 13);
326 		tempg = ((pix >> 3) & 0xf8) | ((pix >>  8) & 0x07);
327 		tempb = ((pix << 2) & 0xf8) | ((pix >>  3) & 0x07);
328 		tempr &= ~7;
329 		tempg &= ~7;
330 		tempb &= ~7;
331 		if (tempr > r5)
332 		{
333 			*r += 1;
334 		}
335 		if (tempr < r5)
336 		{
337 			*r -= 1;
338 		}
339 		if (tempg > g5)
340 		{
341 			*g += 1;
342 		}
343 		if (tempg < g5)
344 		{
345 			*g -= 1;
346 		}
347 		if (tempb > b5)
348 		{
349 			*b += 1;
350 		}
351 		if (tempb < b5)
352 		{
353 			*b -= 1;
354 		}
355 		leftuppix++;
356 	}
357 
358 	for (i = 0; i < 3; i++)
359 	{
360 		pix = fbuff[leftdownpix ^ 1];
361 		tempr = ((pix >> 8) & 0xf8) | (pix >> 13);
362 		tempg = ((pix >> 3) & 0xf8) | ((pix >>  8) & 0x07);
363 		tempb = ((pix << 2) & 0xf8) | ((pix >>  3) & 0x07);
364 		tempr &= ~7;
365 		tempg &= ~7;
366 		tempb &= ~7;
367 		if (tempr > r5)
368 		{
369 			*r += 1;
370 		}
371 		if (tempr < r5)
372 		{
373 			*r -= 1;
374 		}
375 		if (tempg > g5)
376 		{
377 			*g += 1;
378 		}
379 		if (tempg < g5)
380 		{
381 			*g -= 1;
382 		}
383 		if (tempb > b5)
384 		{
385 			*b += 1;
386 		}
387 		if (tempb < b5)
388 		{
389 			*b -= 1;
390 		}
391 		leftdownpix++;
392 	}
393 	for(i = 0; i < 3; i++)
394 	{
395 		if (!(i & 1))
396 		{
397 			pix = fbuff[toleftpix ^ 1];
398 			tempr = ((pix >> 8) & 0xf8) | (pix >> 13);
399 			tempg = ((pix >> 3) & 0xf8) | ((pix >>  8) & 0x07);
400 			tempb = ((pix << 2) & 0xf8) | ((pix >>  3) & 0x07);
401 			tempr &= ~7;
402 			tempg &= ~7;
403 			tempb &= ~7;
404 			if (tempr > r5)
405 			{
406 				*r += 1;
407 			}
408 			if (tempr < r5)
409 			{
410 				*r -= 1;
411 			}
412 			if (tempg > g5)
413 			{
414 				*g += 1;
415 			}
416 			if (tempg < g5)
417 			{
418 				*g -= 1;
419 			}
420 			if (tempb > b5)
421 			{
422 				*b += 1;
423 			}
424 			if (tempb < b5)
425 			{
426 				*b -= 1;
427 			}
428 		}
429 		toleftpix++;
430 	}
431 }
432 
433 static inline void restore_filter16_buffer(int32_t* r, int32_t* g, int32_t* b, color_t* vibuff, uint32_t hres)
434 {
435 	color_t filtered;
436 	color_t leftuppix, leftdownpix, leftpix;
437 	color_t rightuppix, rightdownpix, rightpix;
438 	color_t uppix, downpix;
439 	int32_t ihres = (int32_t)hres; //can't apply unary minus to unsigned
440 
441 	leftuppix = vibuff[-ihres - 1];
442 	leftdownpix = vibuff[ihres - 1];
443 	leftpix = vibuff[-1];
444 
445 	rightuppix = vibuff[-ihres + 1];
446 	rightdownpix = vibuff[ihres + 1];
447 	rightpix = vibuff[1];
448 
449 	uppix = vibuff[-ihres];
450 	downpix = vibuff[ihres];
451 	filtered = *vibuff;
452 
453 	restore_two(&filtered, &leftuppix);
454 	restore_two(&filtered, &uppix);
455 	restore_two(&filtered, &rightuppix);
456 
457 	restore_two(&filtered, &leftpix);
458 	restore_two(&filtered, &rightpix);
459 
460 	restore_two(&filtered, &leftdownpix);
461 	restore_two(&filtered, &downpix);
462 	restore_two(&filtered, &rightdownpix);
463 
464 	*r = filtered.i.r;
465 	*g = filtered.i.g;
466 	*b = filtered.i.b;
467 
468 	if(*r < 0) *r = 0;
469 	else if(*r > 255) *r = 255;
470 	if(*g < 0) *g = 0;
471 	else if(*g > 255) *g = 255;
472 	if(*b < 0) *b = 0;
473 	else if(*b > 255) *b = 255;
474 }
475 
476 // This is wrong, only the 5 upper bits are compared.
477 static inline void restore_two(color_t* filtered, color_t* neighbour)
478 {
479 	if (neighbour->i.r > filtered->i.r)
480 	{
481 		filtered->i.r += 1;
482 	}
483 	if (neighbour->i.r < filtered->i.r)
484 	{
485 		filtered->i.r -= 1;
486 	}
487 	if (neighbour->i.g > filtered->i.g)
488 	{
489 		filtered->i.g += 1;
490 	}
491 	if (neighbour->i.g < filtered->i.g)
492 	{
493 		filtered->i.g -= 1;
494 	}
495 	if (neighbour->i.b > filtered->i.b)
496 	{
497 		filtered->i.b += 1;
498 	}
499 	if (neighbour->i.b < filtered->i.b)
500 	{
501 		filtered->i.b -= 1;
502 	}
503 }
504 
505 static inline void video_max(uint32_t* Pixels, uint8_t* max, uint32_t* enb)
506 {
507 	int i;
508 	int pos = 0;
509 	*enb = 0;
510 	for(i = 0; i < 7; i++)
511 	{
512 		if (Pixels[i] > Pixels[pos])
513 		{
514 			*enb += (1 << i);
515 			pos = i;
516 		}
517 		else if (Pixels[i] < Pixels[pos])
518 		{
519 			*enb += (1 << i);
520 		}
521 		else
522 		{
523 			pos = i;
524 		}
525 	}
526 	*max = Pixels[pos];
527 }
528 
529 static inline uint32_t ge_two(uint32_t enb)
530 {
531 	if(enb & 1)
532 	{
533 		if(enb & 2)
534 			return 1;
535 		if(enb & 4)
536 			return 1;
537 		if(enb & 8)
538 			return 1;
539 		if(enb & 16)
540 			return 1;
541 		if(enb & 32)
542 			return 1;
543 		if(enb & 64)
544 			return 1;
545 		if(enb & 128)
546 			return 1;
547 		return 0;
548 	}
549 	else if(enb & 2)
550 	{
551 		if(enb & 4)
552 			return 1;
553 		if(enb & 8)
554 			return 1;
555 		if(enb & 16)
556 			return 1;
557 		if(enb & 32)
558 			return 1;
559 		if(enb & 64)
560 			return 1;
561 		if(enb & 128)
562 			return 1;
563 		return 0;
564 	}
565 	else if(enb & 4)
566 	{
567 		if(enb & 8)
568 			return 1;
569 		if(enb & 16)
570 			return 1;
571 		if(enb & 32)
572 			return 1;
573 		if(enb & 64)
574 			return 1;
575 		if(enb & 128)
576 			return 1;
577 		return 0;
578 	}
579 	else if(enb & 8)
580 	{
581 		if(enb & 16)
582 			return 1;
583 		if(enb & 32)
584 			return 1;
585 		if(enb & 64)
586 			return 1;
587 		if(enb & 128)
588 			return 1;
589 		return 0;
590 	}
591 	else if(enb & 16)
592 	{
593 		if(enb & 32)
594 			return 1;
595 		if(enb & 64)
596 			return 1;
597 		if(enb & 128)
598 			return 1;
599 		return 0;
600 	}
601 	else if(enb & 32)
602 	{
603 		if(enb & 64)
604 			return 1;
605 		if(enb & 128)
606 			return 1;
607 		return 0;
608 	}
609 	else if(enb & 64)
610 	{
611 		if(enb & 128)
612 			return 1;
613 		return 0;
614 	}
615 	return 0;
616 }
617 #endif
618