1 /* RetroArch - A frontend for libretro.
2 * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
3 * Copyright (C) 2011-2017 - Daniel De Matteis
4 *
5 * RetroArch is free software: you can redistribute it and/or modify it under the terms
6 * of the GNU General Public License as published by the Free Software Found-
7 * ation, either version 3 of the License, or (at your option) any later version.
8 *
9 * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along with RetroArch.
14 * If not, see <http://www.gnu.org/licenses/>.
15 */
16
17 /* Useless filter, just nice as a reference for other filters. */
18
19 #include "softfilter.h"
20 #include <stdlib.h>
21
22 #ifdef RARCH_INTERNAL
23 #define softfilter_get_implementation darken_get_implementation
24 #define softfilter_thread_data darken_softfilter_thread_data
25 #define filter_data darken_filter_data
26 #endif
27
28 struct softfilter_thread_data
29 {
30 void *out_data;
31 const void *in_data;
32 size_t out_pitch;
33 size_t in_pitch;
34 unsigned colfmt;
35 unsigned width;
36 unsigned height;
37 int first;
38 int last;
39 };
40
41 struct filter_data
42 {
43 unsigned threads;
44 struct softfilter_thread_data *workers;
45 unsigned in_fmt;
46 };
47
darken_input_fmts(void)48 static unsigned darken_input_fmts(void)
49 {
50 return SOFTFILTER_FMT_XRGB8888 | SOFTFILTER_FMT_RGB565;
51 }
52
darken_output_fmts(unsigned input_fmts)53 static unsigned darken_output_fmts(unsigned input_fmts)
54 {
55 return input_fmts;
56 }
57
darken_threads(void * data)58 static unsigned darken_threads(void *data)
59 {
60 struct filter_data *filt = (struct filter_data*)data;
61 return filt->threads;
62 }
63
darken_create(const struct softfilter_config * config,unsigned in_fmt,unsigned out_fmt,unsigned max_width,unsigned max_height,unsigned threads,softfilter_simd_mask_t simd,void * userdata)64 static void *darken_create(const struct softfilter_config *config,
65 unsigned in_fmt, unsigned out_fmt,
66 unsigned max_width, unsigned max_height,
67 unsigned threads, softfilter_simd_mask_t simd, void *userdata)
68 {
69 struct filter_data *filt = (struct filter_data*)calloc(1, sizeof(*filt));
70 (void)simd;
71 (void)config;
72 (void)userdata;
73 if (!filt)
74 return NULL;
75 filt->workers = (struct softfilter_thread_data*)
76 calloc(threads, sizeof(struct softfilter_thread_data));
77 filt->threads = threads;
78 filt->in_fmt = in_fmt;
79 if (!filt->workers)
80 {
81 free(filt);
82 return NULL;
83 }
84 return filt;
85 }
86
darken_output(void * data,unsigned * out_width,unsigned * out_height,unsigned width,unsigned height)87 static void darken_output(void *data, unsigned *out_width, unsigned *out_height,
88 unsigned width, unsigned height)
89 {
90 *out_width = width;
91 *out_height = height;
92 }
93
darken_destroy(void * data)94 static void darken_destroy(void *data)
95 {
96 struct filter_data *filt = (struct filter_data*)data;
97
98 if (!filt)
99 return;
100
101 free(filt->workers);
102 free(filt);
103 }
104
darken_work_cb_xrgb8888(void * data,void * thread_data)105 static void darken_work_cb_xrgb8888(void *data, void *thread_data)
106 {
107 struct softfilter_thread_data *thr =
108 (struct softfilter_thread_data*)thread_data;
109 const uint32_t *input = (const uint32_t*)thr->in_data;
110 uint32_t *output = (uint32_t*)thr->out_data;
111 unsigned width = thr->width;
112 unsigned height = thr->height;
113
114 unsigned x, y;
115 for (y = 0; y < height;
116 y++, input += thr->in_pitch >> 2, output += thr->out_pitch >> 2)
117 for (x = 0; x < width; x++)
118 output[x] = (input[x] >> 2) & (0x3f * 0x01010101);
119 }
120
darken_work_cb_rgb565(void * data,void * thread_data)121 static void darken_work_cb_rgb565(void *data, void *thread_data)
122 {
123 struct softfilter_thread_data *thr =
124 (struct softfilter_thread_data*)thread_data;
125 const uint16_t *input = (const uint16_t*)thr->in_data;
126 uint16_t *output = (uint16_t*)thr->out_data;
127 unsigned width = thr->width;
128 unsigned height = thr->height;
129
130 unsigned x, y;
131 for (y = 0; y < height;
132 y++, input += thr->in_pitch >> 1, output += thr->out_pitch >> 1)
133 for (x = 0; x < width; x++)
134 output[x] = (input[x] >> 2) & ((0x7 << 0) | (0xf << 5) | (0x7 << 11));
135 }
136
darken_packets(void * data,struct softfilter_work_packet * packets,void * output,size_t output_stride,const void * input,unsigned width,unsigned height,size_t input_stride)137 static void darken_packets(void *data,
138 struct softfilter_work_packet *packets,
139 void *output, size_t output_stride,
140 const void *input, unsigned width, unsigned height, size_t input_stride)
141 {
142 unsigned i;
143 struct filter_data *filt = (struct filter_data*)data;
144 for (i = 0; i < filt->threads; i++)
145 {
146 struct softfilter_thread_data *thr =
147 (struct softfilter_thread_data*)&filt->workers[i];
148 unsigned y_start = (height * i) / filt->threads;
149 unsigned y_end = (height * (i + 1)) / filt->threads;
150 thr->out_data = (uint8_t*)output + y_start * output_stride;
151 thr->in_data = (const uint8_t*)input + y_start * input_stride;
152 thr->out_pitch = output_stride;
153 thr->in_pitch = input_stride;
154 thr->width = width;
155 thr->height = y_end - y_start;
156
157 if (filt->in_fmt == SOFTFILTER_FMT_XRGB8888)
158 packets[i].work = darken_work_cb_xrgb8888;
159 else if (filt->in_fmt == SOFTFILTER_FMT_RGB565)
160 packets[i].work = darken_work_cb_rgb565;
161 packets[i].thread_data = thr;
162 }
163 }
164
165 static const struct softfilter_implementation darken = {
166 darken_input_fmts,
167 darken_output_fmts,
168
169 darken_create,
170 darken_destroy,
171
172 darken_threads,
173 darken_output,
174 darken_packets,
175 SOFTFILTER_API_VERSION,
176 "Darken",
177 "darken",
178 };
179
softfilter_get_implementation(softfilter_simd_mask_t simd)180 const struct softfilter_implementation *softfilter_get_implementation(
181 softfilter_simd_mask_t simd)
182 {
183 (void)simd;
184 return &darken;
185 }
186
187 #ifdef RARCH_INTERNAL
188 #undef softfilter_get_implementation
189 #undef softfilter_thread_data
190 #undef filter_data
191 #endif
192