Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 1
/**************************************************************************
2
 *
3
 * Copyright 2007 VMware, Inc.
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 VMWARE AND/OR ITS SUPPLIERS 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 "sp_context.h"
29
#include "sp_state.h"
30
#include "sp_fs.h"
31
#include "sp_texture.h"
32
 
33
#include "pipe/p_defines.h"
34
#include "util/u_memory.h"
35
#include "util/u_inlines.h"
36
#include "util/u_pstipple.h"
37
#include "draw/draw_context.h"
38
#include "draw/draw_vs.h"
39
#include "draw/draw_gs.h"
40
#include "tgsi/tgsi_dump.h"
41
#include "tgsi/tgsi_scan.h"
42
#include "tgsi/tgsi_parse.h"
43
 
44
 
45
/**
46
 * Create a new fragment shader variant.
47
 */
48
static struct sp_fragment_shader_variant *
49
create_fs_variant(struct softpipe_context *softpipe,
50
                  struct sp_fragment_shader *fs,
51
                  const struct sp_fragment_shader_variant_key *key)
52
{
53
   struct sp_fragment_shader_variant *var;
54
   struct pipe_shader_state *curfs = &fs->shader;
55
 
56
   /* codegen, create variant object */
57
   var = softpipe_create_fs_variant_exec(softpipe);
58
 
59
   if (var) {
60
      var->key = *key;
61
 
62
#if DO_PSTIPPLE_IN_HELPER_MODULE
63
      if (key->polygon_stipple) {
64
         /* get new shader that implements polygon stippling */
65
         var->tokens =
66
            util_pstipple_create_fragment_shader(curfs->tokens,
67
                                                 &var->stipple_sampler_unit, 0);
68
      }
69
      else
70
#endif
71
      {
72
         var->tokens = tgsi_dup_tokens(curfs->tokens);
73
         var->stipple_sampler_unit = 0;
74
      }
75
 
76
      tgsi_scan_shader(var->tokens, &var->info);
77
 
78
      /* See comments elsewhere about draw fragment shaders */
79
#if 0
80
      /* draw's fs state */
81
      var->draw_shader = draw_create_fragment_shader(softpipe->draw,
82
                                                     &fs->shader);
83
      if (!var->draw_shader) {
84
         var->delete(var);
85
         FREE((void *) var->tokens);
86
         return NULL;
87
      }
88
#endif
89
 
90
      /* insert variant into linked list */
91
      var->next = fs->variants;
92
      fs->variants = var;
93
   }
94
 
95
   return var;
96
}
97
 
98
 
99
struct sp_fragment_shader_variant *
100
softpipe_find_fs_variant(struct softpipe_context *sp,
101
                         struct sp_fragment_shader *fs,
102
                         const struct sp_fragment_shader_variant_key *key)
103
{
104
   struct sp_fragment_shader_variant *var;
105
 
106
   for (var = fs->variants; var; var = var->next) {
107
      if (memcmp(&var->key, key, sizeof(*key)) == 0) {
108
         /* found it */
109
         return var;
110
      }
111
   }
112
 
113
   return create_fs_variant(sp, fs, key);
114
}
115
 
116
 
117
static void *
118
softpipe_create_fs_state(struct pipe_context *pipe,
119
                         const struct pipe_shader_state *templ)
120
{
121
   struct softpipe_context *softpipe = softpipe_context(pipe);
122
   struct sp_fragment_shader *state = CALLOC_STRUCT(sp_fragment_shader);
123
 
124
   /* debug */
125
   if (softpipe->dump_fs)
126
      tgsi_dump(templ->tokens, 0);
127
 
128
   /* we need to keep a local copy of the tokens */
129
   state->shader.tokens = tgsi_dup_tokens(templ->tokens);
130
 
131
   /* draw's fs state */
132
   state->draw_shader = draw_create_fragment_shader(softpipe->draw,
133
                                                    &state->shader);
134
   if (!state->draw_shader) {
135
      tgsi_free_tokens(state->shader.tokens);
136
      FREE(state);
137
      return NULL;
138
   }
139
 
140
   return state;
141
}
142
 
143
 
144
static void
145
softpipe_bind_fs_state(struct pipe_context *pipe, void *fs)
146
{
147
   struct softpipe_context *softpipe = softpipe_context(pipe);
148
   struct sp_fragment_shader *state = (struct sp_fragment_shader *) fs;
149
 
150
   if (softpipe->fs == fs)
151
      return;
152
 
153
   draw_flush(softpipe->draw);
154
 
155
   softpipe->fs = fs;
156
 
157
   /* This depends on the current fragment shader and must always be
158
    * re-validated before use.
159
    */
160
   softpipe->fs_variant = NULL;
161
 
162
   if (state)
163
      draw_bind_fragment_shader(softpipe->draw,
164
                                state->draw_shader);
165
   else
166
      draw_bind_fragment_shader(softpipe->draw, NULL);
167
 
168
   softpipe->dirty |= SP_NEW_FS;
169
}
170
 
171
 
172
static void
173
softpipe_delete_fs_state(struct pipe_context *pipe, void *fs)
174
{
175
   struct softpipe_context *softpipe = softpipe_context(pipe);
176
   struct sp_fragment_shader *state = fs;
177
   struct sp_fragment_shader_variant *var, *next_var;
178
 
179
   assert(fs != softpipe->fs);
180
 
181
   /* delete variants */
182
   for (var = state->variants; var; var = next_var) {
183
      next_var = var->next;
184
 
185
      assert(var != softpipe->fs_variant);
186
 
187
      /* See comments elsewhere about draw fragment shaders */
188
#if 0
189
      draw_delete_fragment_shader(softpipe->draw, var->draw_shader);
190
#endif
191
 
192
      var->delete(var, softpipe->fs_machine);
193
   }
194
 
195
   draw_delete_fragment_shader(softpipe->draw, state->draw_shader);
196
 
197
   tgsi_free_tokens(state->shader.tokens);
198
   FREE(state);
199
}
200
 
201
 
202
static void *
203
softpipe_create_vs_state(struct pipe_context *pipe,
204
                         const struct pipe_shader_state *templ)
205
{
206
   struct softpipe_context *softpipe = softpipe_context(pipe);
207
   struct sp_vertex_shader *state;
208
 
209
   state = CALLOC_STRUCT(sp_vertex_shader);
210
   if (state == NULL )
211
      goto fail;
212
 
213
   /* copy shader tokens, the ones passed in will go away.
214
    */
215
   state->shader.tokens = tgsi_dup_tokens(templ->tokens);
216
   if (state->shader.tokens == NULL)
217
      goto fail;
218
 
219
   state->draw_data = draw_create_vertex_shader(softpipe->draw, templ);
220
   if (state->draw_data == NULL)
221
      goto fail;
222
 
223
   state->max_sampler = state->draw_data->info.file_max[TGSI_FILE_SAMPLER];
224
 
225
   return state;
226
 
227
fail:
228
   if (state) {
229
      tgsi_free_tokens(state->shader.tokens);
230
      FREE( state->draw_data );
231
      FREE( state );
232
   }
233
   return NULL;
234
}
235
 
236
 
237
static void
238
softpipe_bind_vs_state(struct pipe_context *pipe, void *vs)
239
{
240
   struct softpipe_context *softpipe = softpipe_context(pipe);
241
 
242
   softpipe->vs = (struct sp_vertex_shader *) vs;
243
 
244
   draw_bind_vertex_shader(softpipe->draw,
245
                           (softpipe->vs ? softpipe->vs->draw_data : NULL));
246
 
247
   softpipe->dirty |= SP_NEW_VS;
248
}
249
 
250
 
251
static void
252
softpipe_delete_vs_state(struct pipe_context *pipe, void *vs)
253
{
254
   struct softpipe_context *softpipe = softpipe_context(pipe);
255
 
256
   struct sp_vertex_shader *state = (struct sp_vertex_shader *) vs;
257
 
258
   draw_delete_vertex_shader(softpipe->draw, state->draw_data);
259
   tgsi_free_tokens(state->shader.tokens);
260
   FREE( state );
261
}
262
 
263
 
264
static void *
265
softpipe_create_gs_state(struct pipe_context *pipe,
266
                         const struct pipe_shader_state *templ)
267
{
268
   struct softpipe_context *softpipe = softpipe_context(pipe);
269
   struct sp_geometry_shader *state;
270
 
271
   state = CALLOC_STRUCT(sp_geometry_shader);
272
   if (state == NULL )
273
      goto fail;
274
 
275
   state->shader = *templ;
276
 
277
   if (templ->tokens) {
278
      /* debug */
279
      if (softpipe->dump_gs)
280
         tgsi_dump(templ->tokens, 0);
281
 
282
      /* copy shader tokens, the ones passed in will go away.
283
       */
284
      state->shader.tokens = tgsi_dup_tokens(templ->tokens);
285
      if (state->shader.tokens == NULL)
286
         goto fail;
287
 
288
      state->draw_data = draw_create_geometry_shader(softpipe->draw, templ);
289
      if (state->draw_data == NULL)
290
         goto fail;
291
 
292
      state->max_sampler = state->draw_data->info.file_max[TGSI_FILE_SAMPLER];
293
   }
294
 
295
   return state;
296
 
297
fail:
298
   if (state) {
299
      tgsi_free_tokens(state->shader.tokens);
300
      FREE( state->draw_data );
301
      FREE( state );
302
   }
303
   return NULL;
304
}
305
 
306
 
307
static void
308
softpipe_bind_gs_state(struct pipe_context *pipe, void *gs)
309
{
310
   struct softpipe_context *softpipe = softpipe_context(pipe);
311
 
312
   softpipe->gs = (struct sp_geometry_shader *)gs;
313
 
314
   draw_bind_geometry_shader(softpipe->draw,
315
                             (softpipe->gs ? softpipe->gs->draw_data : NULL));
316
 
317
   softpipe->dirty |= SP_NEW_GS;
318
}
319
 
320
 
321
static void
322
softpipe_delete_gs_state(struct pipe_context *pipe, void *gs)
323
{
324
   struct softpipe_context *softpipe = softpipe_context(pipe);
325
 
326
   struct sp_geometry_shader *state =
327
      (struct sp_geometry_shader *)gs;
328
 
329
   draw_delete_geometry_shader(softpipe->draw,
330
                               (state) ? state->draw_data : 0);
331
 
332
   tgsi_free_tokens(state->shader.tokens);
333
   FREE(state);
334
}
335
 
336
 
337
static void
338
softpipe_set_constant_buffer(struct pipe_context *pipe,
339
                             uint shader, uint index,
340
                             struct pipe_constant_buffer *cb)
341
{
342
   struct softpipe_context *softpipe = softpipe_context(pipe);
343
   struct pipe_resource *constants = cb ? cb->buffer : NULL;
344
   unsigned size;
345
   const void *data;
346
 
347
   assert(shader < PIPE_SHADER_TYPES);
348
 
349
   if (cb && cb->user_buffer) {
350
      constants = softpipe_user_buffer_create(pipe->screen,
351
                                              (void *) cb->user_buffer,
352
                                              cb->buffer_size,
353
                                              PIPE_BIND_CONSTANT_BUFFER);
354
   }
355
 
356
   size = cb ? cb->buffer_size : 0;
357
   data = constants ? softpipe_resource_data(constants) : NULL;
358
   if (data)
359
      data = (const char *) data + cb->buffer_offset;
360
 
361
   draw_flush(softpipe->draw);
362
 
363
   /* note: reference counting */
364
   pipe_resource_reference(&softpipe->constants[shader][index], constants);
365
 
366
   if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) {
367
      draw_set_mapped_constant_buffer(softpipe->draw, shader, index, data, size);
368
   }
369
 
370
   softpipe->mapped_constants[shader][index] = data;
371
   softpipe->const_buffer_size[shader][index] = size;
372
 
373
   softpipe->dirty |= SP_NEW_CONSTANTS;
374
 
375
   if (cb && cb->user_buffer) {
376
      pipe_resource_reference(&constants, NULL);
377
   }
378
}
379
 
380
 
381
void
382
softpipe_init_shader_funcs(struct pipe_context *pipe)
383
{
384
   pipe->create_fs_state = softpipe_create_fs_state;
385
   pipe->bind_fs_state   = softpipe_bind_fs_state;
386
   pipe->delete_fs_state = softpipe_delete_fs_state;
387
 
388
   pipe->create_vs_state = softpipe_create_vs_state;
389
   pipe->bind_vs_state   = softpipe_bind_vs_state;
390
   pipe->delete_vs_state = softpipe_delete_vs_state;
391
 
392
   pipe->create_gs_state = softpipe_create_gs_state;
393
   pipe->bind_gs_state   = softpipe_bind_gs_state;
394
   pipe->delete_gs_state = softpipe_delete_gs_state;
395
 
396
   pipe->set_constant_buffer = softpipe_set_constant_buffer;
397
}