Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 1
/**************************************************************************
2
 *
3
 * Copyright 2011 Lauri Kasanen
4
 * All Rights Reserved.
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the
8
 * "Software"), to deal in the Software without restriction, including
9
 * without limitation the rights to use, copy, modify, merge, publish,
10
 * distribute, sub license, and/or sell copies of the Software, and to
11
 * permit persons to whom the Software is furnished to do so, subject to
12
 * the following conditions:
13
 *
14
 * The above copyright notice and this permission notice (including the
15
 * next paragraph) shall be included in all copies or substantial portions
16
 * of the Software.
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
22
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
 *
26
 **************************************************************************/
27
 
28
#include "postprocess.h"
29
 
30
#include "postprocess/pp_filters.h"
31
#include "util/u_inlines.h"
32
#include "util/u_sampler.h"
33
 
34
#include "tgsi/tgsi_parse.h"
35
 
36
void
37
pp_blit(struct pipe_context *pipe,
38
        struct pipe_resource *src_tex,
39
        int srcX0, int srcY0,
40
        int srcX1, int srcY1,
41
        int srcZ0,
42
        struct pipe_surface *dst,
43
        int dstX0, int dstY0,
44
        int dstX1, int dstY1)
45
{
46
   struct pipe_blit_info blit;
47
 
48
   memset(&blit, 0, sizeof(blit));
49
 
50
   blit.src.resource = src_tex;
51
   blit.src.level = 0;
52
   blit.src.format = src_tex->format;
53
   blit.src.box.x = srcX0;
54
   blit.src.box.y = srcY0;
55
   blit.src.box.z = srcZ0;
56
   blit.src.box.width = srcX1 - srcX0;
57
   blit.src.box.height = srcY1 - srcY0;
58
   blit.src.box.depth = 1;
59
 
60
   blit.dst.resource = dst->texture;
61
   blit.dst.level = dst->u.tex.level;
62
   blit.dst.format = dst->format;
63
   blit.dst.box.x = dstX0;
64
   blit.dst.box.y = dstY0;
65
   blit.dst.box.z = 0;
66
   blit.dst.box.width = dstX1 - dstX0;
67
   blit.dst.box.height = dstY1 - dstY0;
68
   blit.dst.box.depth = 1;
69
 
70
   blit.mask = PIPE_MASK_RGBA;
71
 
72
   pipe->blit(pipe, &blit);
73
}
74
 
75
/**
76
*	Main run function of the PP queue. Called on swapbuffers/flush.
77
*
78
*	Runs all requested filters in order and handles shuffling the temp
79
*	buffers in between.
80
*/
81
void
82
pp_run(struct pp_queue_t *ppq, struct pipe_resource *in,
83
       struct pipe_resource *out, struct pipe_resource *indepth)
84
{
85
   struct pipe_resource *refin = NULL, *refout = NULL;
86
   unsigned int i;
87
   struct cso_context *cso = ppq->p->cso;
88
 
89
   if (ppq->n_filters == 0)
90
      return;
91
 
92
   assert(ppq->pp_queue);
93
   assert(ppq->tmp[0]);
94
 
95
   if (in->width0 != ppq->p->framebuffer.width ||
96
       in->height0 != ppq->p->framebuffer.height) {
97
      pp_debug("Resizing the temp pp buffers\n");
98
      pp_free_fbos(ppq);
99
      pp_init_fbos(ppq, in->width0, in->height0);
100
   }
101
 
102
   if (in == out && ppq->n_filters == 1) {
103
      /* Make a copy of in to tmp[0] in this case. */
104
      unsigned int w = ppq->p->framebuffer.width;
105
      unsigned int h = ppq->p->framebuffer.height;
106
 
107
 
108
      pp_blit(ppq->p->pipe, in, 0, 0,
109
              w, h, 0, ppq->tmps[0],
110
              0, 0, w, h);
111
 
112
      in = ppq->tmp[0];
113
   }
114
 
115
   /* save state (restored below) */
116
   cso_save_blend(cso);
117
   cso_save_depth_stencil_alpha(cso);
118
   cso_save_fragment_shader(cso);
119
   cso_save_framebuffer(cso);
120
   cso_save_geometry_shader(cso);
121
   cso_save_rasterizer(cso);
122
   cso_save_sample_mask(cso);
123
   cso_save_samplers(cso, PIPE_SHADER_FRAGMENT);
124
   cso_save_sampler_views(cso, PIPE_SHADER_FRAGMENT);
125
   cso_save_stencil_ref(cso);
126
   cso_save_stream_outputs(cso);
127
   cso_save_vertex_elements(cso);
128
   cso_save_vertex_shader(cso);
129
   cso_save_viewport(cso);
130
   cso_save_aux_vertex_buffer_slot(cso);
131
   cso_save_constant_buffer_slot0(cso, PIPE_SHADER_VERTEX);
132
   cso_save_constant_buffer_slot0(cso, PIPE_SHADER_FRAGMENT);
133
   cso_save_render_condition(cso);
134
 
135
   /* set default state */
136
   cso_set_sample_mask(cso, ~0);
137
   cso_set_stream_outputs(cso, 0, NULL, 0);
138
   cso_set_geometry_shader_handle(cso, NULL);
139
   cso_set_render_condition(cso, NULL, FALSE, 0);
140
 
141
   // Kept only for this frame.
142
   pipe_resource_reference(&ppq->depth, indepth);
143
   pipe_resource_reference(&refin, in);
144
   pipe_resource_reference(&refout, out);
145
 
146
   switch (ppq->n_filters) {
147
   case 0:
148
      /* Failsafe, but never reached. */
149
      break;
150
   case 1:                     /* No temp buf */
151
      ppq->pp_queue[0] (ppq, in, out, 0);
152
      break;
153
   case 2:                     /* One temp buf */
154
 
155
      ppq->pp_queue[0] (ppq, in, ppq->tmp[0], 0);
156
      ppq->pp_queue[1] (ppq, ppq->tmp[0], out, 1);
157
 
158
      break;
159
   default:                    /* Two temp bufs */
160
      assert(ppq->tmp[1]);
161
      ppq->pp_queue[0] (ppq, in, ppq->tmp[0], 0);
162
 
163
      for (i = 1; i < (ppq->n_filters - 1); i++) {
164
         if (i % 2 == 0)
165
            ppq->pp_queue[i] (ppq, ppq->tmp[1], ppq->tmp[0], i);
166
 
167
         else
168
            ppq->pp_queue[i] (ppq, ppq->tmp[0], ppq->tmp[1], i);
169
      }
170
 
171
      if (i % 2 == 0)
172
         ppq->pp_queue[i] (ppq, ppq->tmp[1], out, i);
173
 
174
      else
175
         ppq->pp_queue[i] (ppq, ppq->tmp[0], out, i);
176
 
177
      break;
178
   }
179
 
180
   /* restore state we changed */
181
   cso_restore_blend(cso);
182
   cso_restore_depth_stencil_alpha(cso);
183
   cso_restore_fragment_shader(cso);
184
   cso_restore_framebuffer(cso);
185
   cso_restore_geometry_shader(cso);
186
   cso_restore_rasterizer(cso);
187
   cso_restore_sample_mask(cso);
188
   cso_restore_samplers(cso, PIPE_SHADER_FRAGMENT);
189
   cso_restore_sampler_views(cso, PIPE_SHADER_FRAGMENT);
190
   cso_restore_stencil_ref(cso);
191
   cso_restore_stream_outputs(cso);
192
   cso_restore_vertex_elements(cso);
193
   cso_restore_vertex_shader(cso);
194
   cso_restore_viewport(cso);
195
   cso_restore_aux_vertex_buffer_slot(cso);
196
   cso_restore_constant_buffer_slot0(cso, PIPE_SHADER_VERTEX);
197
   cso_restore_constant_buffer_slot0(cso, PIPE_SHADER_FRAGMENT);
198
   cso_restore_render_condition(cso);
199
 
200
   pipe_resource_reference(&ppq->depth, NULL);
201
   pipe_resource_reference(&refin, NULL);
202
   pipe_resource_reference(&refout, NULL);
203
}
204
 
205
 
206
/* Utility functions for the filters. You're not forced to use these if */
207
/* your filter is more complicated. */
208
 
209
/** Setup this resource as the filter input. */
210
void
211
pp_filter_setup_in(struct program *p, struct pipe_resource *in)
212
{
213
   struct pipe_sampler_view v_tmp;
214
   u_sampler_view_default_template(&v_tmp, in, in->format);
215
   p->view = p->pipe->create_sampler_view(p->pipe, in, &v_tmp);
216
}
217
 
218
/** Setup this resource as the filter output. */
219
void
220
pp_filter_setup_out(struct program *p, struct pipe_resource *out)
221
{
222
   p->surf.format = out->format;
223
 
224
   p->framebuffer.cbufs[0] = p->pipe->create_surface(p->pipe, out, &p->surf);
225
}
226
 
227
/** Clean up the input and output set with the above. */
228
void
229
pp_filter_end_pass(struct program *p)
230
{
231
   pipe_surface_reference(&p->framebuffer.cbufs[0], NULL);
232
   pipe_sampler_view_reference(&p->view, NULL);
233
}
234
 
235
/**
236
*	Convert the TGSI assembly to a runnable shader.
237
*
238
* We need not care about geometry shaders. All we have is screen quads.
239
*/
240
void *
241
pp_tgsi_to_state(struct pipe_context *pipe, const char *text, bool isvs,
242
                 const char *name)
243
{
244
   struct pipe_shader_state state;
245
   struct tgsi_token *tokens = NULL;
246
   void *ret_state = NULL;
247
 
248
   /*
249
    * Allocate temporary token storage. State creation will duplicate
250
    * tokens so we must free them on exit.
251
    */
252
   tokens = tgsi_alloc_tokens(PP_MAX_TOKENS);
253
 
254
   if (tokens == NULL) {
255
      pp_debug("Failed to allocate temporary token storage.\n");
256
      return NULL;
257
   }
258
 
259
   if (tgsi_text_translate(text, tokens, PP_MAX_TOKENS) == FALSE) {
260
      _debug_printf("pp: Failed to translate a shader for %s\n", name);
261
      return NULL;
262
   }
263
 
264
   state.tokens = tokens;
265
   memset(&state.stream_output, 0, sizeof(state.stream_output));
266
 
267
   if (isvs) {
268
      ret_state = pipe->create_vs_state(pipe, &state);
269
      FREE(tokens);
270
   } else {
271
      ret_state = pipe->create_fs_state(pipe, &state);
272
      FREE(tokens);
273
   }
274
 
275
   return ret_state;
276
}
277
 
278
/** Setup misc state for the filter. */
279
void
280
pp_filter_misc_state(struct program *p)
281
{
282
   cso_set_blend(p->cso, &p->blend);
283
   cso_set_depth_stencil_alpha(p->cso, &p->depthstencil);
284
   cso_set_rasterizer(p->cso, &p->rasterizer);
285
   cso_set_viewport(p->cso, &p->viewport);
286
 
287
   cso_set_vertex_elements(p->cso, 2, p->velem);
288
}
289
 
290
/** Draw with the filter to the set output. */
291
void
292
pp_filter_draw(struct program *p)
293
{
294
   util_draw_vertex_buffer(p->pipe, p->cso, p->vbuf, 0, 0,
295
                           PIPE_PRIM_QUADS, 4, 2);
296
}
297
 
298
/** Set the framebuffer as active. */
299
void
300
pp_filter_set_fb(struct program *p)
301
{
302
   cso_set_framebuffer(p->cso, &p->framebuffer);
303
}
304
 
305
/** Set the framebuffer as active and clear it. */
306
void
307
pp_filter_set_clear_fb(struct program *p)
308
{
309
   cso_set_framebuffer(p->cso, &p->framebuffer);
310
   p->pipe->clear(p->pipe, PIPE_CLEAR_COLOR, &p->clear_color, 0, 0);
311
}