1a9ffcceee9214342dab2085a35452acaa41003c5Christian König/**************************************************************************
2a9ffcceee9214342dab2085a35452acaa41003c5Christian König *
3a9ffcceee9214342dab2085a35452acaa41003c5Christian König * Copyright 2012 Christian König.
4a9ffcceee9214342dab2085a35452acaa41003c5Christian König * All Rights Reserved.
5a9ffcceee9214342dab2085a35452acaa41003c5Christian König *
6a9ffcceee9214342dab2085a35452acaa41003c5Christian König * Permission is hereby granted, free of charge, to any person obtaining a
7a9ffcceee9214342dab2085a35452acaa41003c5Christian König * copy of this software and associated documentation files (the
8a9ffcceee9214342dab2085a35452acaa41003c5Christian König * "Software"), to deal in the Software without restriction, including
9a9ffcceee9214342dab2085a35452acaa41003c5Christian König * without limitation the rights to use, copy, modify, merge, publish,
10a9ffcceee9214342dab2085a35452acaa41003c5Christian König * distribute, sub license, and/or sell copies of the Software, and to
11a9ffcceee9214342dab2085a35452acaa41003c5Christian König * permit persons to whom the Software is furnished to do so, subject to
12a9ffcceee9214342dab2085a35452acaa41003c5Christian König * the following conditions:
13a9ffcceee9214342dab2085a35452acaa41003c5Christian König *
14a9ffcceee9214342dab2085a35452acaa41003c5Christian König * The above copyright notice and this permission notice (including the
15a9ffcceee9214342dab2085a35452acaa41003c5Christian König * next paragraph) shall be included in all copies or substantial portions
16a9ffcceee9214342dab2085a35452acaa41003c5Christian König * of the Software.
17a9ffcceee9214342dab2085a35452acaa41003c5Christian König *
18a9ffcceee9214342dab2085a35452acaa41003c5Christian König * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19a9ffcceee9214342dab2085a35452acaa41003c5Christian König * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20a9ffcceee9214342dab2085a35452acaa41003c5Christian König * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21877128505431adaf817dc8069172ebe4a1cdf5d8José Fonseca * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22a9ffcceee9214342dab2085a35452acaa41003c5Christian König * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23a9ffcceee9214342dab2085a35452acaa41003c5Christian König * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24a9ffcceee9214342dab2085a35452acaa41003c5Christian König * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25a9ffcceee9214342dab2085a35452acaa41003c5Christian König *
26a9ffcceee9214342dab2085a35452acaa41003c5Christian König **************************************************************************/
27a9ffcceee9214342dab2085a35452acaa41003c5Christian König
28a9ffcceee9214342dab2085a35452acaa41003c5Christian König#include "pipe/p_context.h"
29a9ffcceee9214342dab2085a35452acaa41003c5Christian König
30a9ffcceee9214342dab2085a35452acaa41003c5Christian König#include "tgsi/tgsi_ureg.h"
31a9ffcceee9214342dab2085a35452acaa41003c5Christian König
32a9ffcceee9214342dab2085a35452acaa41003c5Christian König#include "util/u_draw.h"
33a9ffcceee9214342dab2085a35452acaa41003c5Christian König#include "util/u_memory.h"
34a9ffcceee9214342dab2085a35452acaa41003c5Christian König#include "util/u_math.h"
35a9ffcceee9214342dab2085a35452acaa41003c5Christian König
36a9ffcceee9214342dab2085a35452acaa41003c5Christian König#include "vl_types.h"
37a9ffcceee9214342dab2085a35452acaa41003c5Christian König#include "vl_vertex_buffers.h"
38a9ffcceee9214342dab2085a35452acaa41003c5Christian König#include "vl_median_filter.h"
39a9ffcceee9214342dab2085a35452acaa41003c5Christian König
40a9ffcceee9214342dab2085a35452acaa41003c5Christian Königenum VS_OUTPUT
41a9ffcceee9214342dab2085a35452acaa41003c5Christian König{
4295594bae47d8b3302be188e6f0be2d69c5507bb3Christian König   VS_O_VPOS = 0,
4395594bae47d8b3302be188e6f0be2d69c5507bb3Christian König   VS_O_VTEX = 0
44a9ffcceee9214342dab2085a35452acaa41003c5Christian König};
45a9ffcceee9214342dab2085a35452acaa41003c5Christian König
46a9ffcceee9214342dab2085a35452acaa41003c5Christian Königstatic void *
47a9ffcceee9214342dab2085a35452acaa41003c5Christian Königcreate_vert_shader(struct vl_median_filter *filter)
48a9ffcceee9214342dab2085a35452acaa41003c5Christian König{
49a9ffcceee9214342dab2085a35452acaa41003c5Christian König   struct ureg_program *shader;
50a9ffcceee9214342dab2085a35452acaa41003c5Christian König   struct ureg_src i_vpos;
51a9ffcceee9214342dab2085a35452acaa41003c5Christian König   struct ureg_dst o_vpos, o_vtex;
52a9ffcceee9214342dab2085a35452acaa41003c5Christian König
53af249a7da9bf2621ab836d5074ef692677b11bbfMarek Olšák   shader = ureg_create(PIPE_SHADER_VERTEX);
54a9ffcceee9214342dab2085a35452acaa41003c5Christian König   if (!shader)
55a9ffcceee9214342dab2085a35452acaa41003c5Christian König      return NULL;
56a9ffcceee9214342dab2085a35452acaa41003c5Christian König
57a9ffcceee9214342dab2085a35452acaa41003c5Christian König   i_vpos = ureg_DECL_vs_input(shader, 0);
58a9ffcceee9214342dab2085a35452acaa41003c5Christian König   o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS);
59a9ffcceee9214342dab2085a35452acaa41003c5Christian König   o_vtex = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX);
60a9ffcceee9214342dab2085a35452acaa41003c5Christian König
61a9ffcceee9214342dab2085a35452acaa41003c5Christian König   ureg_MOV(shader, o_vpos, i_vpos);
62a9ffcceee9214342dab2085a35452acaa41003c5Christian König   ureg_MOV(shader, o_vtex, i_vpos);
63a9ffcceee9214342dab2085a35452acaa41003c5Christian König
64a9ffcceee9214342dab2085a35452acaa41003c5Christian König   ureg_END(shader);
65a9ffcceee9214342dab2085a35452acaa41003c5Christian König
66a9ffcceee9214342dab2085a35452acaa41003c5Christian König   return ureg_create_shader_and_destroy(shader, filter->pipe);
67a9ffcceee9214342dab2085a35452acaa41003c5Christian König}
68a9ffcceee9214342dab2085a35452acaa41003c5Christian König
69a9ffcceee9214342dab2085a35452acaa41003c5Christian Königstatic inline bool
70a9ffcceee9214342dab2085a35452acaa41003c5Christian Königis_vec_zero(struct vertex2f v)
71a9ffcceee9214342dab2085a35452acaa41003c5Christian König{
72a9ffcceee9214342dab2085a35452acaa41003c5Christian König   return v.x == 0.0f && v.y == 0.0f;
73a9ffcceee9214342dab2085a35452acaa41003c5Christian König}
74a9ffcceee9214342dab2085a35452acaa41003c5Christian König
75a9ffcceee9214342dab2085a35452acaa41003c5Christian Königstatic void *
76a9ffcceee9214342dab2085a35452acaa41003c5Christian Königcreate_frag_shader(struct vl_median_filter *filter,
77a9ffcceee9214342dab2085a35452acaa41003c5Christian König                   struct vertex2f *offsets,
78a9ffcceee9214342dab2085a35452acaa41003c5Christian König                   unsigned num_offsets)
79a9ffcceee9214342dab2085a35452acaa41003c5Christian König{
80a9ffcceee9214342dab2085a35452acaa41003c5Christian König   struct pipe_screen *screen = filter->pipe->screen;
81a9ffcceee9214342dab2085a35452acaa41003c5Christian König   struct ureg_program *shader;
82a9ffcceee9214342dab2085a35452acaa41003c5Christian König   struct ureg_src i_vtex;
83a9ffcceee9214342dab2085a35452acaa41003c5Christian König   struct ureg_src sampler;
84a9ffcceee9214342dab2085a35452acaa41003c5Christian König   struct ureg_dst *t_array = MALLOC(sizeof(struct ureg_dst) * num_offsets);
8520be2867096b984823e4b18939fc855b377c5c95Christian König   struct ureg_dst o_fragment;
86a9ffcceee9214342dab2085a35452acaa41003c5Christian König   const unsigned median = num_offsets >> 1;
871fb4179f927442354f93dfc8494f0236e50af838Jan Vesely   unsigned i, j;
88a9ffcceee9214342dab2085a35452acaa41003c5Christian König
89a9ffcceee9214342dab2085a35452acaa41003c5Christian König   assert(num_offsets & 1); /* we need an odd number of offsets */
90a9ffcceee9214342dab2085a35452acaa41003c5Christian König   if (!(num_offsets & 1)) { /* yeah, we REALLY need an odd number of offsets!!! */
91a9ffcceee9214342dab2085a35452acaa41003c5Christian König      FREE(t_array);
92a9ffcceee9214342dab2085a35452acaa41003c5Christian König      return NULL;
93a9ffcceee9214342dab2085a35452acaa41003c5Christian König   }
94a9ffcceee9214342dab2085a35452acaa41003c5Christian König
95a9ffcceee9214342dab2085a35452acaa41003c5Christian König   if (num_offsets > screen->get_shader_param(
96af249a7da9bf2621ab836d5074ef692677b11bbfMarek Olšák      screen, PIPE_SHADER_FRAGMENT, PIPE_SHADER_CAP_MAX_TEMPS)) {
97a9ffcceee9214342dab2085a35452acaa41003c5Christian König
98a9ffcceee9214342dab2085a35452acaa41003c5Christian König      FREE(t_array);
99a9ffcceee9214342dab2085a35452acaa41003c5Christian König      return NULL;
100a9ffcceee9214342dab2085a35452acaa41003c5Christian König   }
101a9ffcceee9214342dab2085a35452acaa41003c5Christian König
102af249a7da9bf2621ab836d5074ef692677b11bbfMarek Olšák   shader = ureg_create(PIPE_SHADER_FRAGMENT);
103a9ffcceee9214342dab2085a35452acaa41003c5Christian König   if (!shader) {
104a9ffcceee9214342dab2085a35452acaa41003c5Christian König      FREE(t_array);
105a9ffcceee9214342dab2085a35452acaa41003c5Christian König      return NULL;
106a9ffcceee9214342dab2085a35452acaa41003c5Christian König   }
107a9ffcceee9214342dab2085a35452acaa41003c5Christian König
108a9ffcceee9214342dab2085a35452acaa41003c5Christian König   i_vtex = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX, TGSI_INTERPOLATE_LINEAR);
109a9ffcceee9214342dab2085a35452acaa41003c5Christian König   sampler = ureg_DECL_sampler(shader, 0);
110a9ffcceee9214342dab2085a35452acaa41003c5Christian König
11120be2867096b984823e4b18939fc855b377c5c95Christian König   for (i = 0; i < num_offsets; ++i)
11220be2867096b984823e4b18939fc855b377c5c95Christian König      t_array[i] = ureg_DECL_temporary(shader);
11320be2867096b984823e4b18939fc855b377c5c95Christian König   o_fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
114a9ffcceee9214342dab2085a35452acaa41003c5Christian König
115a9ffcceee9214342dab2085a35452acaa41003c5Christian König   /*
116a9ffcceee9214342dab2085a35452acaa41003c5Christian König    * t_array[0..*] = vtex + offset[0..*]
117a9ffcceee9214342dab2085a35452acaa41003c5Christian König    * t_array[0..*] = tex(t_array[0..*], sampler)
118a9ffcceee9214342dab2085a35452acaa41003c5Christian König    * result = partial_bubblesort(t_array)[mid]
119a9ffcceee9214342dab2085a35452acaa41003c5Christian König    */
120a9ffcceee9214342dab2085a35452acaa41003c5Christian König
121a9ffcceee9214342dab2085a35452acaa41003c5Christian König   for (i = 0; i < num_offsets; ++i) {
122a9ffcceee9214342dab2085a35452acaa41003c5Christian König      if (!is_vec_zero(offsets[i])) {
123a9ffcceee9214342dab2085a35452acaa41003c5Christian König         ureg_ADD(shader, ureg_writemask(t_array[i], TGSI_WRITEMASK_XY),
124a9ffcceee9214342dab2085a35452acaa41003c5Christian König                  i_vtex, ureg_imm2f(shader, offsets[i].x, offsets[i].y));
125a9ffcceee9214342dab2085a35452acaa41003c5Christian König         ureg_MOV(shader, ureg_writemask(t_array[i], TGSI_WRITEMASK_ZW),
126a9ffcceee9214342dab2085a35452acaa41003c5Christian König                  ureg_imm1f(shader, 0.0f));
127a9ffcceee9214342dab2085a35452acaa41003c5Christian König      }
128a9ffcceee9214342dab2085a35452acaa41003c5Christian König   }
129a9ffcceee9214342dab2085a35452acaa41003c5Christian König
130a9ffcceee9214342dab2085a35452acaa41003c5Christian König   for (i = 0; i < num_offsets; ++i) {
131a9ffcceee9214342dab2085a35452acaa41003c5Christian König      struct ureg_src src = is_vec_zero(offsets[i]) ? i_vtex : ureg_src(t_array[i]);
132a9ffcceee9214342dab2085a35452acaa41003c5Christian König      ureg_TEX(shader, t_array[i], TGSI_TEXTURE_2D, src, sampler);
133a9ffcceee9214342dab2085a35452acaa41003c5Christian König   }
134a9ffcceee9214342dab2085a35452acaa41003c5Christian König
135a9ffcceee9214342dab2085a35452acaa41003c5Christian König   // TODO: Couldn't this be improved even more?
136a9ffcceee9214342dab2085a35452acaa41003c5Christian König   for (i = 0; i <= median; ++i) {
137a9ffcceee9214342dab2085a35452acaa41003c5Christian König      for (j = 1; j < (num_offsets - i - 1); ++j) {
138a9ffcceee9214342dab2085a35452acaa41003c5Christian König         struct ureg_dst tmp = ureg_DECL_temporary(shader);
139a9ffcceee9214342dab2085a35452acaa41003c5Christian König         ureg_MOV(shader, tmp, ureg_src(t_array[j]));
140a9ffcceee9214342dab2085a35452acaa41003c5Christian König         ureg_MAX(shader, t_array[j], ureg_src(t_array[j]), ureg_src(t_array[j - 1]));
141a9ffcceee9214342dab2085a35452acaa41003c5Christian König         ureg_MIN(shader, t_array[j - 1], ureg_src(tmp), ureg_src(t_array[j - 1]));
142a9ffcceee9214342dab2085a35452acaa41003c5Christian König         ureg_release_temporary(shader, tmp);
143a9ffcceee9214342dab2085a35452acaa41003c5Christian König      }
144a9ffcceee9214342dab2085a35452acaa41003c5Christian König      if (i == median)
145a9ffcceee9214342dab2085a35452acaa41003c5Christian König         ureg_MAX(shader, t_array[j], ureg_src(t_array[j]), ureg_src(t_array[j - 1]));
146a9ffcceee9214342dab2085a35452acaa41003c5Christian König      else
147a9ffcceee9214342dab2085a35452acaa41003c5Christian König         ureg_MIN(shader, t_array[j - 1], ureg_src(t_array[j]), ureg_src(t_array[j - 1]));
148a9ffcceee9214342dab2085a35452acaa41003c5Christian König   }
14920be2867096b984823e4b18939fc855b377c5c95Christian König   ureg_MOV(shader, o_fragment, ureg_src(t_array[median]));
150a9ffcceee9214342dab2085a35452acaa41003c5Christian König
151a9ffcceee9214342dab2085a35452acaa41003c5Christian König   ureg_END(shader);
152a9ffcceee9214342dab2085a35452acaa41003c5Christian König
153a9ffcceee9214342dab2085a35452acaa41003c5Christian König   FREE(t_array);
154a9ffcceee9214342dab2085a35452acaa41003c5Christian König   return ureg_create_shader_and_destroy(shader, filter->pipe);
155a9ffcceee9214342dab2085a35452acaa41003c5Christian König}
156a9ffcceee9214342dab2085a35452acaa41003c5Christian König
157a9ffcceee9214342dab2085a35452acaa41003c5Christian Königstatic void
158a9ffcceee9214342dab2085a35452acaa41003c5Christian Königgenerate_offsets(enum vl_median_filter_shape shape, unsigned size,
159a9ffcceee9214342dab2085a35452acaa41003c5Christian König                 struct vertex2f **offsets, unsigned *num_offsets)
160a9ffcceee9214342dab2085a35452acaa41003c5Christian König{
1611fb4179f927442354f93dfc8494f0236e50af838Jan Vesely   unsigned i = 0;
1621fb4179f927442354f93dfc8494f0236e50af838Jan Vesely   int half_size;
163a9ffcceee9214342dab2085a35452acaa41003c5Christian König   struct vertex2f v;
164a9ffcceee9214342dab2085a35452acaa41003c5Christian König
165a9ffcceee9214342dab2085a35452acaa41003c5Christian König   assert(offsets && num_offsets);
166a9ffcceee9214342dab2085a35452acaa41003c5Christian König
167a9ffcceee9214342dab2085a35452acaa41003c5Christian König   /* size needs to be odd */
168553e8203879d163e6fe2f3a8f6b80a44749514c1Christian König   size = align(size + 1, 2) - 1;
169a9ffcceee9214342dab2085a35452acaa41003c5Christian König   half_size = size >> 1;
170a9ffcceee9214342dab2085a35452acaa41003c5Christian König
171a9ffcceee9214342dab2085a35452acaa41003c5Christian König   switch(shape) {
172a9ffcceee9214342dab2085a35452acaa41003c5Christian König   case VL_MEDIAN_FILTER_BOX:
173a9ffcceee9214342dab2085a35452acaa41003c5Christian König      *num_offsets = size*size;
174a9ffcceee9214342dab2085a35452acaa41003c5Christian König      break;
175a9ffcceee9214342dab2085a35452acaa41003c5Christian König
176a9ffcceee9214342dab2085a35452acaa41003c5Christian König   case VL_MEDIAN_FILTER_CROSS:
177a9ffcceee9214342dab2085a35452acaa41003c5Christian König   case VL_MEDIAN_FILTER_X:
178a9ffcceee9214342dab2085a35452acaa41003c5Christian König      *num_offsets = size + size - 1;
179a9ffcceee9214342dab2085a35452acaa41003c5Christian König      break;
180a9ffcceee9214342dab2085a35452acaa41003c5Christian König
181a9ffcceee9214342dab2085a35452acaa41003c5Christian König   case VL_MEDIAN_FILTER_HORIZONTAL:
182a9ffcceee9214342dab2085a35452acaa41003c5Christian König   case VL_MEDIAN_FILTER_VERTICAL:
183a9ffcceee9214342dab2085a35452acaa41003c5Christian König      *num_offsets = size;
184a9ffcceee9214342dab2085a35452acaa41003c5Christian König      break;
185a9ffcceee9214342dab2085a35452acaa41003c5Christian König
186a9ffcceee9214342dab2085a35452acaa41003c5Christian König   default:
187a9ffcceee9214342dab2085a35452acaa41003c5Christian König      *num_offsets = 0;
188a9ffcceee9214342dab2085a35452acaa41003c5Christian König      return;
189a9ffcceee9214342dab2085a35452acaa41003c5Christian König   }
190a9ffcceee9214342dab2085a35452acaa41003c5Christian König
191a9ffcceee9214342dab2085a35452acaa41003c5Christian König   *offsets = MALLOC(sizeof(struct vertex2f) * *num_offsets);
192a9ffcceee9214342dab2085a35452acaa41003c5Christian König   if (!*offsets)
193a9ffcceee9214342dab2085a35452acaa41003c5Christian König      return;
194a9ffcceee9214342dab2085a35452acaa41003c5Christian König
195a9ffcceee9214342dab2085a35452acaa41003c5Christian König   switch(shape) {
196a9ffcceee9214342dab2085a35452acaa41003c5Christian König   case VL_MEDIAN_FILTER_BOX:
197a9ffcceee9214342dab2085a35452acaa41003c5Christian König      for (v.x = -half_size; v.x <= half_size; ++v.x)
198a9ffcceee9214342dab2085a35452acaa41003c5Christian König         for (v.y = -half_size; v.y <= half_size; ++v.y)
199a9ffcceee9214342dab2085a35452acaa41003c5Christian König            (*offsets)[i++] = v;
200a9ffcceee9214342dab2085a35452acaa41003c5Christian König      break;
201a9ffcceee9214342dab2085a35452acaa41003c5Christian König
202a9ffcceee9214342dab2085a35452acaa41003c5Christian König   case VL_MEDIAN_FILTER_CROSS:
203a9ffcceee9214342dab2085a35452acaa41003c5Christian König      v.y = 0.0f;
204a9ffcceee9214342dab2085a35452acaa41003c5Christian König      for (v.x = -half_size; v.x <= half_size; ++v.x)
205a9ffcceee9214342dab2085a35452acaa41003c5Christian König         (*offsets)[i++] = v;
206a9ffcceee9214342dab2085a35452acaa41003c5Christian König
207a9ffcceee9214342dab2085a35452acaa41003c5Christian König      v.x = 0.0f;
208a9ffcceee9214342dab2085a35452acaa41003c5Christian König      for (v.y = -half_size; v.y <= half_size; ++v.y)
209a9ffcceee9214342dab2085a35452acaa41003c5Christian König         if (v.y != 0.0f)
210a9ffcceee9214342dab2085a35452acaa41003c5Christian König            (*offsets)[i++] = v;
211a9ffcceee9214342dab2085a35452acaa41003c5Christian König      break;
212a9ffcceee9214342dab2085a35452acaa41003c5Christian König
213a9ffcceee9214342dab2085a35452acaa41003c5Christian König   case VL_MEDIAN_FILTER_X:
214a9ffcceee9214342dab2085a35452acaa41003c5Christian König      for (v.x = v.y = -half_size; v.x <= half_size; ++v.x, ++v.y)
215a9ffcceee9214342dab2085a35452acaa41003c5Christian König         (*offsets)[i++] = v;
216a9ffcceee9214342dab2085a35452acaa41003c5Christian König
217a9ffcceee9214342dab2085a35452acaa41003c5Christian König      for (v.x = -half_size, v.y = half_size; v.x <= half_size; ++v.x, --v.y)
218a9ffcceee9214342dab2085a35452acaa41003c5Christian König         if (v.y != 0.0f)
219a9ffcceee9214342dab2085a35452acaa41003c5Christian König            (*offsets)[i++] = v;
220a9ffcceee9214342dab2085a35452acaa41003c5Christian König      break;
221a9ffcceee9214342dab2085a35452acaa41003c5Christian König
222a9ffcceee9214342dab2085a35452acaa41003c5Christian König   case VL_MEDIAN_FILTER_HORIZONTAL:
223a9ffcceee9214342dab2085a35452acaa41003c5Christian König      v.y = 0.0f;
224a9ffcceee9214342dab2085a35452acaa41003c5Christian König      for (v.x = -half_size; v.x <= half_size; ++v.x)
225a9ffcceee9214342dab2085a35452acaa41003c5Christian König         (*offsets)[i++] = v;
226a9ffcceee9214342dab2085a35452acaa41003c5Christian König      break;
227a9ffcceee9214342dab2085a35452acaa41003c5Christian König
228a9ffcceee9214342dab2085a35452acaa41003c5Christian König   case VL_MEDIAN_FILTER_VERTICAL:
229a9ffcceee9214342dab2085a35452acaa41003c5Christian König      v.x = 0.0f;
230a9ffcceee9214342dab2085a35452acaa41003c5Christian König      for (v.y = -half_size; v.y <= half_size; ++v.y)
231a9ffcceee9214342dab2085a35452acaa41003c5Christian König         (*offsets)[i++] = v;
232a9ffcceee9214342dab2085a35452acaa41003c5Christian König      break;
233a9ffcceee9214342dab2085a35452acaa41003c5Christian König   }
234a9ffcceee9214342dab2085a35452acaa41003c5Christian König
235a9ffcceee9214342dab2085a35452acaa41003c5Christian König   assert(i == *num_offsets);
236a9ffcceee9214342dab2085a35452acaa41003c5Christian König}
237a9ffcceee9214342dab2085a35452acaa41003c5Christian König
238a9ffcceee9214342dab2085a35452acaa41003c5Christian Königbool
239a9ffcceee9214342dab2085a35452acaa41003c5Christian Königvl_median_filter_init(struct vl_median_filter *filter, struct pipe_context *pipe,
240a9ffcceee9214342dab2085a35452acaa41003c5Christian König                      unsigned width, unsigned height, unsigned size,
241a9ffcceee9214342dab2085a35452acaa41003c5Christian König                      enum vl_median_filter_shape shape)
242a9ffcceee9214342dab2085a35452acaa41003c5Christian König{
243a9ffcceee9214342dab2085a35452acaa41003c5Christian König   struct pipe_rasterizer_state rs_state;
244a9ffcceee9214342dab2085a35452acaa41003c5Christian König   struct pipe_blend_state blend;
245a9ffcceee9214342dab2085a35452acaa41003c5Christian König   struct pipe_sampler_state sampler;
246a9ffcceee9214342dab2085a35452acaa41003c5Christian König   struct vertex2f *offsets = NULL;
247a9ffcceee9214342dab2085a35452acaa41003c5Christian König   struct pipe_vertex_element ve;
248a9ffcceee9214342dab2085a35452acaa41003c5Christian König   unsigned i, num_offsets = 0;
249a9ffcceee9214342dab2085a35452acaa41003c5Christian König
250a9ffcceee9214342dab2085a35452acaa41003c5Christian König   assert(filter && pipe);
251a9ffcceee9214342dab2085a35452acaa41003c5Christian König   assert(width && height);
252553e8203879d163e6fe2f3a8f6b80a44749514c1Christian König   assert(size > 1 && size < 20);
253a9ffcceee9214342dab2085a35452acaa41003c5Christian König
254a9ffcceee9214342dab2085a35452acaa41003c5Christian König   memset(filter, 0, sizeof(*filter));
255a9ffcceee9214342dab2085a35452acaa41003c5Christian König   filter->pipe = pipe;
256a9ffcceee9214342dab2085a35452acaa41003c5Christian König
257a9ffcceee9214342dab2085a35452acaa41003c5Christian König   memset(&rs_state, 0, sizeof(rs_state));
2582737abb44efebfa10ac84b183c20fc5818d1514eJosé Fonseca   rs_state.half_pixel_center = true;
2592737abb44efebfa10ac84b183c20fc5818d1514eJosé Fonseca   rs_state.bottom_edge_rule = true;
260a9ffcceee9214342dab2085a35452acaa41003c5Christian König   rs_state.depth_clip = 1;
261a9ffcceee9214342dab2085a35452acaa41003c5Christian König   filter->rs_state = pipe->create_rasterizer_state(pipe, &rs_state);
262a9ffcceee9214342dab2085a35452acaa41003c5Christian König   if (!filter->rs_state)
263a9ffcceee9214342dab2085a35452acaa41003c5Christian König      goto error_rs_state;
264a9ffcceee9214342dab2085a35452acaa41003c5Christian König
265a9ffcceee9214342dab2085a35452acaa41003c5Christian König   memset(&blend, 0, sizeof blend);
266a9ffcceee9214342dab2085a35452acaa41003c5Christian König   blend.rt[0].rgb_func = PIPE_BLEND_ADD;
267a9ffcceee9214342dab2085a35452acaa41003c5Christian König   blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
268a9ffcceee9214342dab2085a35452acaa41003c5Christian König   blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
269a9ffcceee9214342dab2085a35452acaa41003c5Christian König   blend.rt[0].alpha_func = PIPE_BLEND_ADD;
270a9ffcceee9214342dab2085a35452acaa41003c5Christian König   blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
271a9ffcceee9214342dab2085a35452acaa41003c5Christian König   blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
272a9ffcceee9214342dab2085a35452acaa41003c5Christian König   blend.logicop_func = PIPE_LOGICOP_CLEAR;
273a9ffcceee9214342dab2085a35452acaa41003c5Christian König   blend.rt[0].colormask = PIPE_MASK_RGBA;
274a9ffcceee9214342dab2085a35452acaa41003c5Christian König   filter->blend = pipe->create_blend_state(pipe, &blend);
275a9ffcceee9214342dab2085a35452acaa41003c5Christian König   if (!filter->blend)
276a9ffcceee9214342dab2085a35452acaa41003c5Christian König      goto error_blend;
277a9ffcceee9214342dab2085a35452acaa41003c5Christian König
278a9ffcceee9214342dab2085a35452acaa41003c5Christian König   memset(&sampler, 0, sizeof(sampler));
279a9ffcceee9214342dab2085a35452acaa41003c5Christian König   sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
280a9ffcceee9214342dab2085a35452acaa41003c5Christian König   sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
281a9ffcceee9214342dab2085a35452acaa41003c5Christian König   sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
282a9ffcceee9214342dab2085a35452acaa41003c5Christian König   sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
283a9ffcceee9214342dab2085a35452acaa41003c5Christian König   sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
284a9ffcceee9214342dab2085a35452acaa41003c5Christian König   sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
285a9ffcceee9214342dab2085a35452acaa41003c5Christian König   sampler.compare_mode = PIPE_TEX_COMPARE_NONE;
286a9ffcceee9214342dab2085a35452acaa41003c5Christian König   sampler.compare_func = PIPE_FUNC_ALWAYS;
287a9ffcceee9214342dab2085a35452acaa41003c5Christian König   sampler.normalized_coords = 1;
288a9ffcceee9214342dab2085a35452acaa41003c5Christian König   filter->sampler = pipe->create_sampler_state(pipe, &sampler);
289a9ffcceee9214342dab2085a35452acaa41003c5Christian König   if (!filter->sampler)
290a9ffcceee9214342dab2085a35452acaa41003c5Christian König      goto error_sampler;
291a9ffcceee9214342dab2085a35452acaa41003c5Christian König
292a9ffcceee9214342dab2085a35452acaa41003c5Christian König   filter->quad = vl_vb_upload_quads(pipe);
293a9ffcceee9214342dab2085a35452acaa41003c5Christian König   if(!filter->quad.buffer)
294a9ffcceee9214342dab2085a35452acaa41003c5Christian König      goto error_quad;
295a9ffcceee9214342dab2085a35452acaa41003c5Christian König
296a9ffcceee9214342dab2085a35452acaa41003c5Christian König   memset(&ve, 0, sizeof(ve));
297a9ffcceee9214342dab2085a35452acaa41003c5Christian König   ve.src_offset = 0;
298a9ffcceee9214342dab2085a35452acaa41003c5Christian König   ve.instance_divisor = 0;
299a9ffcceee9214342dab2085a35452acaa41003c5Christian König   ve.vertex_buffer_index = 0;
300a9ffcceee9214342dab2085a35452acaa41003c5Christian König   ve.src_format = PIPE_FORMAT_R32G32_FLOAT;
301a9ffcceee9214342dab2085a35452acaa41003c5Christian König   filter->ves = pipe->create_vertex_elements_state(pipe, 1, &ve);
302a9ffcceee9214342dab2085a35452acaa41003c5Christian König   if (!filter->ves)
303a9ffcceee9214342dab2085a35452acaa41003c5Christian König      goto error_ves;
304a9ffcceee9214342dab2085a35452acaa41003c5Christian König
305a9ffcceee9214342dab2085a35452acaa41003c5Christian König   generate_offsets(shape, size, &offsets, &num_offsets);
306a9ffcceee9214342dab2085a35452acaa41003c5Christian König   if (!offsets)
307a9ffcceee9214342dab2085a35452acaa41003c5Christian König      goto error_offsets;
308a9ffcceee9214342dab2085a35452acaa41003c5Christian König
309a9ffcceee9214342dab2085a35452acaa41003c5Christian König   for (i = 0; i < num_offsets; ++i) {
310a9ffcceee9214342dab2085a35452acaa41003c5Christian König      offsets[i].x /= width;
311a9ffcceee9214342dab2085a35452acaa41003c5Christian König      offsets[i].y /= height;
312a9ffcceee9214342dab2085a35452acaa41003c5Christian König   }
313a9ffcceee9214342dab2085a35452acaa41003c5Christian König
314a9ffcceee9214342dab2085a35452acaa41003c5Christian König   filter->vs = create_vert_shader(filter);
315a9ffcceee9214342dab2085a35452acaa41003c5Christian König   if (!filter->vs)
316a9ffcceee9214342dab2085a35452acaa41003c5Christian König      goto error_vs;
317a9ffcceee9214342dab2085a35452acaa41003c5Christian König
318a9ffcceee9214342dab2085a35452acaa41003c5Christian König   filter->fs = create_frag_shader(filter, offsets, num_offsets);
319a9ffcceee9214342dab2085a35452acaa41003c5Christian König   if (!filter->fs)
320a9ffcceee9214342dab2085a35452acaa41003c5Christian König      goto error_fs;
321a9ffcceee9214342dab2085a35452acaa41003c5Christian König
322a9ffcceee9214342dab2085a35452acaa41003c5Christian König   FREE(offsets);
323a9ffcceee9214342dab2085a35452acaa41003c5Christian König   return true;
324a9ffcceee9214342dab2085a35452acaa41003c5Christian König
325a9ffcceee9214342dab2085a35452acaa41003c5Christian Königerror_fs:
326a9ffcceee9214342dab2085a35452acaa41003c5Christian König   pipe->delete_vs_state(pipe, filter->vs);
327a9ffcceee9214342dab2085a35452acaa41003c5Christian König
328a9ffcceee9214342dab2085a35452acaa41003c5Christian Königerror_vs:
329a9ffcceee9214342dab2085a35452acaa41003c5Christian König   FREE(offsets);
330a9ffcceee9214342dab2085a35452acaa41003c5Christian König
331a9ffcceee9214342dab2085a35452acaa41003c5Christian Königerror_offsets:
332a9ffcceee9214342dab2085a35452acaa41003c5Christian König   pipe->delete_vertex_elements_state(pipe, filter->ves);
333a9ffcceee9214342dab2085a35452acaa41003c5Christian König
334a9ffcceee9214342dab2085a35452acaa41003c5Christian Königerror_ves:
335a9ffcceee9214342dab2085a35452acaa41003c5Christian König   pipe_resource_reference(&filter->quad.buffer, NULL);
336a9ffcceee9214342dab2085a35452acaa41003c5Christian König
337a9ffcceee9214342dab2085a35452acaa41003c5Christian Königerror_quad:
338a9ffcceee9214342dab2085a35452acaa41003c5Christian König   pipe->delete_sampler_state(pipe, filter->sampler);
339a9ffcceee9214342dab2085a35452acaa41003c5Christian König
340a9ffcceee9214342dab2085a35452acaa41003c5Christian Königerror_sampler:
341a9ffcceee9214342dab2085a35452acaa41003c5Christian König   pipe->delete_blend_state(pipe, filter->blend);
342a9ffcceee9214342dab2085a35452acaa41003c5Christian König
343a9ffcceee9214342dab2085a35452acaa41003c5Christian Königerror_blend:
344a9ffcceee9214342dab2085a35452acaa41003c5Christian König   pipe->delete_rasterizer_state(pipe, filter->rs_state);
345a9ffcceee9214342dab2085a35452acaa41003c5Christian König
346a9ffcceee9214342dab2085a35452acaa41003c5Christian Königerror_rs_state:
347a9ffcceee9214342dab2085a35452acaa41003c5Christian König   return false;
348a9ffcceee9214342dab2085a35452acaa41003c5Christian König}
349a9ffcceee9214342dab2085a35452acaa41003c5Christian König
350a9ffcceee9214342dab2085a35452acaa41003c5Christian Königvoid
351a9ffcceee9214342dab2085a35452acaa41003c5Christian Königvl_median_filter_cleanup(struct vl_median_filter *filter)
352a9ffcceee9214342dab2085a35452acaa41003c5Christian König{
353a9ffcceee9214342dab2085a35452acaa41003c5Christian König   assert(filter);
354a9ffcceee9214342dab2085a35452acaa41003c5Christian König
355a9ffcceee9214342dab2085a35452acaa41003c5Christian König   filter->pipe->delete_sampler_state(filter->pipe, filter->sampler);
356a9ffcceee9214342dab2085a35452acaa41003c5Christian König   filter->pipe->delete_blend_state(filter->pipe, filter->blend);
357a9ffcceee9214342dab2085a35452acaa41003c5Christian König   filter->pipe->delete_rasterizer_state(filter->pipe, filter->rs_state);
358a9ffcceee9214342dab2085a35452acaa41003c5Christian König   filter->pipe->delete_vertex_elements_state(filter->pipe, filter->ves);
359a9ffcceee9214342dab2085a35452acaa41003c5Christian König   pipe_resource_reference(&filter->quad.buffer, NULL);
360a9ffcceee9214342dab2085a35452acaa41003c5Christian König
361a9ffcceee9214342dab2085a35452acaa41003c5Christian König   filter->pipe->delete_vs_state(filter->pipe, filter->vs);
362a9ffcceee9214342dab2085a35452acaa41003c5Christian König   filter->pipe->delete_fs_state(filter->pipe, filter->fs);
363a9ffcceee9214342dab2085a35452acaa41003c5Christian König}
364a9ffcceee9214342dab2085a35452acaa41003c5Christian König
365a9ffcceee9214342dab2085a35452acaa41003c5Christian Königvoid
366a9ffcceee9214342dab2085a35452acaa41003c5Christian Königvl_median_filter_render(struct vl_median_filter *filter,
367a9ffcceee9214342dab2085a35452acaa41003c5Christian König                        struct pipe_sampler_view *src,
368a9ffcceee9214342dab2085a35452acaa41003c5Christian König                        struct pipe_surface *dst)
369a9ffcceee9214342dab2085a35452acaa41003c5Christian König{
370a9ffcceee9214342dab2085a35452acaa41003c5Christian König   struct pipe_viewport_state viewport;
371a9ffcceee9214342dab2085a35452acaa41003c5Christian König   struct pipe_framebuffer_state fb_state;
372a9ffcceee9214342dab2085a35452acaa41003c5Christian König
373a9ffcceee9214342dab2085a35452acaa41003c5Christian König   assert(filter && src && dst);
374a9ffcceee9214342dab2085a35452acaa41003c5Christian König
375a9ffcceee9214342dab2085a35452acaa41003c5Christian König   memset(&viewport, 0, sizeof(viewport));
376a9ffcceee9214342dab2085a35452acaa41003c5Christian König   viewport.scale[0] = dst->width;
377a9ffcceee9214342dab2085a35452acaa41003c5Christian König   viewport.scale[1] = dst->height;
378a9ffcceee9214342dab2085a35452acaa41003c5Christian König   viewport.scale[2] = 1;
379a9ffcceee9214342dab2085a35452acaa41003c5Christian König
380a9ffcceee9214342dab2085a35452acaa41003c5Christian König   memset(&fb_state, 0, sizeof(fb_state));
381a9ffcceee9214342dab2085a35452acaa41003c5Christian König   fb_state.width = dst->width;
382a9ffcceee9214342dab2085a35452acaa41003c5Christian König   fb_state.height = dst->height;
383a9ffcceee9214342dab2085a35452acaa41003c5Christian König   fb_state.nr_cbufs = 1;
384a9ffcceee9214342dab2085a35452acaa41003c5Christian König   fb_state.cbufs[0] = dst;
385a9ffcceee9214342dab2085a35452acaa41003c5Christian König
386a9ffcceee9214342dab2085a35452acaa41003c5Christian König   filter->pipe->bind_rasterizer_state(filter->pipe, filter->rs_state);
387a9ffcceee9214342dab2085a35452acaa41003c5Christian König   filter->pipe->bind_blend_state(filter->pipe, filter->blend);
388d0520d5bf6fb8dec8434d6b68dd014227a1bdaa3Brian Paul   filter->pipe->bind_sampler_states(filter->pipe, PIPE_SHADER_FRAGMENT,
389d0520d5bf6fb8dec8434d6b68dd014227a1bdaa3Brian Paul                                     0, 1, &filter->sampler);
390a3ed98f7aa85636579a5696bf036ec13e5c9104aBrian Paul   filter->pipe->set_sampler_views(filter->pipe, PIPE_SHADER_FRAGMENT,
391a3ed98f7aa85636579a5696bf036ec13e5c9104aBrian Paul                                   0, 1, &src);
392a9ffcceee9214342dab2085a35452acaa41003c5Christian König   filter->pipe->bind_vs_state(filter->pipe, filter->vs);
393a9ffcceee9214342dab2085a35452acaa41003c5Christian König   filter->pipe->bind_fs_state(filter->pipe, filter->fs);
394a9ffcceee9214342dab2085a35452acaa41003c5Christian König   filter->pipe->set_framebuffer_state(filter->pipe, &fb_state);
395eaabb4ead07ae043ecc789024028e225ebd0f318Zack Rusin   filter->pipe->set_viewport_states(filter->pipe, 0, 1, &viewport);
396e73bf3b805de78299f1a652668ba4e6eab9bac94Marek Olšák   filter->pipe->set_vertex_buffers(filter->pipe, 0, 1, &filter->quad);
397a9ffcceee9214342dab2085a35452acaa41003c5Christian König   filter->pipe->bind_vertex_elements_state(filter->pipe, filter->ves);
398a9ffcceee9214342dab2085a35452acaa41003c5Christian König
399a9ffcceee9214342dab2085a35452acaa41003c5Christian König   util_draw_arrays(filter->pipe, PIPE_PRIM_QUADS, 0, 4);
400a9ffcceee9214342dab2085a35452acaa41003c5Christian König}
401