030d1121 |
1 | /*************************************************************************** |
2 | * Copyright (C) 2016 PCSX4ALL Team * |
3 | * * |
4 | * This program is free software; you can redistribute it and/or modify * |
5 | * it under the terms of the GNU General Public License as published by * |
6 | * the Free Software Foundation; either version 2 of the License, or * |
7 | * (at your option) any later version. * |
8 | * * |
9 | * This program is distributed in the hope that it will be useful, * |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
12 | * GNU General Public License for more details. * |
13 | * * |
14 | * You should have received a copy of the GNU General Public License * |
15 | * along with this program; if not, write to the * |
16 | * Free Software Foundation, Inc., * |
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. * |
18 | ***************************************************************************/ |
19 | |
20 | #ifndef _OP_DITHER_H_ |
21 | #define _OP_DITHER_H_ |
22 | |
23 | static void SetupDitheringConstants() |
24 | { |
25 | // Initialize Dithering Constants |
26 | // The screen is divided into 8x8 chunks and sub-unitary noise is applied |
27 | // using the following matrix. This ensures that data lost in color |
28 | // quantization will be added back to the image 'by chance' in predictable |
29 | // patterns that are naturally 'smoothed' by your sight when viewed from a |
30 | // certain distance. |
31 | // |
32 | // http://caca.zoy.org/study/index.html |
33 | // |
34 | // Shading colors are encoded in 4.5, and then are quantitized to 5.0, |
35 | // DitherMatrix constants reflect that. |
36 | |
37 | static const u8 DitherMatrix[] = { |
38 | 0, 32, 8, 40, 2, 34, 10, 42, |
39 | 48, 16, 56, 24, 50, 18, 58, 26, |
40 | 12, 44, 4, 36, 14, 46, 6, 38, |
41 | 60, 28, 52, 20, 62, 30, 54, 22, |
42 | 3, 35, 11, 43, 1, 33, 9, 41, |
43 | 51, 19, 59, 27, 49, 17, 57, 25, |
44 | 15, 47, 7, 39, 13, 45, 5, 37, |
45 | 63, 31, 55, 23, 61, 29, 53, 21 |
46 | }; |
47 | |
48 | int i, j; |
49 | for (i = 0; i < 8; i++) |
50 | { |
51 | for (j = 0; j < 8; j++) |
52 | { |
53 | u16 offset = (i << 3) | j; |
54 | |
55 | u32 component = ((DitherMatrix[offset] + 1) << 4) / 65; //[5.5] -> [5] |
56 | |
57 | // XXX - senquack - hack Dec 2016 |
58 | // Until JohnnyF gets the time to work further on dithering, |
59 | // force lower bit of component to 0. This fixes grid pattern |
60 | // affecting quality of dithered image, as well as loss of |
61 | // detail in dark areas. With lower bit unset like this, existing |
62 | // 27-bit accuracy of dithering math is unneeded, could be 24-bit. |
63 | // Is 8x8 matrix overkill as a result, can we use 4x4? |
64 | component &= ~1; |
65 | |
66 | gpu_unai.DitherMatrix[offset] = (component) |
67 | | (component << 10) |
68 | | (component << 20); |
69 | } |
70 | } |
71 | } |
72 | |
73 | //////////////////////////////////////////////////////////////////////////////// |
74 | // Convert padded u32 5.4:5.4:5.4 bgr fixed-pt triplet to final bgr555 color, |
75 | // applying dithering if specified by template parameter. |
76 | // |
77 | // INPUT: |
78 | // 'uSrc24' input: 000bbbbbXXXX0gggggXXXX0rrrrrXXXX |
79 | // ^ bit 31 |
80 | // 'pDst' is a pointer to destination framebuffer pixel, used |
81 | // to determine which DitherMatrix[] entry to apply. |
82 | // RETURNS: |
83 | // u16 output: 0bbbbbgggggrrrrr |
84 | // ^ bit 16 |
85 | // Where 'X' are fixed-pt bits, '0' is zero-padding, and '-' is don't care |
86 | //////////////////////////////////////////////////////////////////////////////// |
87 | template <int DITHER> |
88 | GPU_INLINE u16 gpuColorQuantization24(u32 uSrc24, const u16 *pDst) |
89 | { |
90 | if (DITHER) |
91 | { |
92 | u16 fbpos = (u32)(pDst - gpu_unai.vram); |
93 | u16 offset = ((fbpos & (0x7 << 10)) >> 7) | (fbpos & 0x7); |
94 | |
95 | //clean overflow flags and add |
96 | uSrc24 = (uSrc24 & 0x1FF7FDFF) + gpu_unai.DitherMatrix[offset]; |
97 | |
98 | if (uSrc24 & (1<< 9)) uSrc24 |= (0x1FF ); |
99 | if (uSrc24 & (1<<19)) uSrc24 |= (0x1FF<<10); |
100 | if (uSrc24 & (1<<29)) uSrc24 |= (0x1FF<<20); |
101 | } |
102 | |
103 | return ((uSrc24>> 4) & (0x1F )) |
104 | | ((uSrc24>> 9) & (0x1F<<5 )) |
105 | | ((uSrc24>>14) & (0x1F<<10)); |
106 | } |
107 | |
108 | #endif //_OP_DITHER_H_ |