sync with tizen_2.2
[sdk/emulator/qemu.git] / gl / mesa / src / gallium / auxiliary / util / u_pstipple.c
1 /**************************************************************************
2  * 
3  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4  * Copyright 2010 VMware, Inc.
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the
9  * "Software"), to deal in the Software without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sub license, and/or sell copies of the Software, and to
12  * permit persons to whom the Software is furnished to do so, subject to
13  * the following conditions:
14  * 
15  * The above copyright notice and this permission notice (including the
16  * next paragraph) shall be included in all copies or substantial portions
17  * of the Software.
18  * 
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
23  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26  * 
27  **************************************************************************/
28
29 /**
30  * Polygon stipple helper module.  Drivers/GPUs which don't support polygon
31  * stipple natively can use this module to simulate it.
32  *
33  * Basically, modify fragment shader to sample the 32x32 stipple pattern
34  * texture and do a fragment kill for the 'off' bits.
35  *
36  * This was originally a 'draw' module stage, but since we don't need
37  * vertex window coords or anything, it can be a stand-alone utility module.
38  *
39  * Authors:  Brian Paul
40  */
41
42
43 #include "pipe/p_context.h"
44 #include "pipe/p_defines.h"
45 #include "pipe/p_shader_tokens.h"
46 #include "util/u_inlines.h"
47
48 #include "util/u_format.h"
49 #include "util/u_memory.h"
50 #include "util/u_pstipple.h"
51 #include "util/u_sampler.h"
52
53 #include "tgsi/tgsi_transform.h"
54 #include "tgsi/tgsi_dump.h"
55 #include "tgsi/tgsi_scan.h"
56
57 /** Approx number of new tokens for instructions in pstip_transform_inst() */
58 #define NUM_NEW_TOKENS 50
59
60
61 static void
62 util_pstipple_update_stipple_texture(struct pipe_context *pipe,
63                                      struct pipe_resource *tex,
64                                      const uint32_t pattern[32])
65 {
66    static const uint bit31 = 1 << 31;
67    struct pipe_transfer *transfer;
68    ubyte *data;
69    int i, j;
70
71    /* map texture memory */
72    transfer = pipe_get_transfer(pipe, tex, 0, 0,
73                                 PIPE_TRANSFER_WRITE, 0, 0, 32, 32);
74    data = pipe->transfer_map(pipe, transfer);
75
76    /*
77     * Load alpha texture.
78     * Note: 0 means keep the fragment, 255 means kill it.
79     * We'll negate the texel value and use KILP which kills if value
80     * is negative.
81     */
82    for (i = 0; i < 32; i++) {
83       for (j = 0; j < 32; j++) {
84          if (pattern[i] & (bit31 >> j)) {
85             /* fragment "on" */
86             data[i * transfer->stride + j] = 0;
87          }
88          else {
89             /* fragment "off" */
90             data[i * transfer->stride + j] = 255;
91          }
92       }
93    }
94
95    /* unmap */
96    pipe->transfer_unmap(pipe, transfer);
97    pipe->transfer_destroy(pipe, transfer);
98 }
99
100
101 /**
102  * Create a 32x32 alpha8 texture that encodes the given stipple pattern.
103  */
104 struct pipe_resource *
105 util_pstipple_create_stipple_texture(struct pipe_context *pipe,
106                                      const uint32_t pattern[32])
107 {
108    struct pipe_screen *screen = pipe->screen;
109    struct pipe_resource templat, *tex;
110
111    memset(&templat, 0, sizeof(templat));
112    templat.target = PIPE_TEXTURE_2D;
113    templat.format = PIPE_FORMAT_A8_UNORM;
114    templat.last_level = 0;
115    templat.width0 = 32;
116    templat.height0 = 32;
117    templat.depth0 = 1;
118    templat.array_size = 1;
119    templat.bind = PIPE_BIND_SAMPLER_VIEW;
120
121    tex = screen->resource_create(screen, &templat);
122
123    if (tex)
124       util_pstipple_update_stipple_texture(pipe, tex, pattern);
125
126    return tex;
127 }
128
129
130 /**
131  * Create sampler view to sample the stipple texture.
132  */
133 struct pipe_sampler_view *
134 util_pstipple_create_sampler_view(struct pipe_context *pipe,
135                                   struct pipe_resource *tex)
136 {
137    struct pipe_sampler_view templat, *sv;
138
139    u_sampler_view_default_template(&templat, tex, tex->format);
140    sv = pipe->create_sampler_view(pipe, tex, &templat);
141
142    return sv;
143 }
144
145
146 /**
147  * Create the sampler CSO that'll be used for stippling.
148  */
149 void *
150 util_pstipple_create_sampler(struct pipe_context *pipe)
151 {
152    struct pipe_sampler_state templat;
153    void *s;
154
155    memset(&templat, 0, sizeof(templat));
156    templat.wrap_s = PIPE_TEX_WRAP_REPEAT;
157    templat.wrap_t = PIPE_TEX_WRAP_REPEAT;
158    templat.wrap_r = PIPE_TEX_WRAP_REPEAT;
159    templat.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
160    templat.min_img_filter = PIPE_TEX_FILTER_NEAREST;
161    templat.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
162    templat.normalized_coords = 1;
163    templat.min_lod = 0.0f;
164    templat.max_lod = 0.0f;
165
166    s = pipe->create_sampler_state(pipe, &templat);
167    return s;
168 }
169
170
171
172 /**
173  * Subclass of tgsi_transform_context, used for transforming the
174  * user's fragment shader to add the extra texture sample and fragment kill
175  * instructions.
176  */
177 struct pstip_transform_context {
178    struct tgsi_transform_context base;
179    struct tgsi_shader_info info;
180    uint tempsUsed;  /**< bitmask */
181    int wincoordInput;
182    int maxInput;
183    uint samplersUsed;  /**< bitfield of samplers used */
184    int freeSampler;  /** an available sampler for the pstipple */
185    int texTemp;  /**< temp registers */
186    int numImmed;
187    boolean firstInstruction;
188    uint coordOrigin;
189 };
190
191
192 /**
193  * TGSI declaration transform callback.
194  * Track samplers used, temps used, inputs used.
195  */
196 static void
197 pstip_transform_decl(struct tgsi_transform_context *ctx,
198                      struct tgsi_full_declaration *decl)
199 {
200    struct pstip_transform_context *pctx =
201       (struct pstip_transform_context *) ctx;
202
203    /* XXX we can use tgsi_shader_info instead of some of this */
204
205    if (decl->Declaration.File == TGSI_FILE_SAMPLER) {
206       uint i;
207       for (i = decl->Range.First; i <= decl->Range.Last; i++) {
208          pctx->samplersUsed |= 1 << i;
209       }
210    }
211    else if (decl->Declaration.File == TGSI_FILE_INPUT) {
212       pctx->maxInput = MAX2(pctx->maxInput, (int) decl->Range.Last);
213       if (decl->Semantic.Name == TGSI_SEMANTIC_POSITION)
214          pctx->wincoordInput = (int) decl->Range.First;
215    }
216    else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) {
217       uint i;
218       for (i = decl->Range.First; i <= decl->Range.Last; i++) {
219          pctx->tempsUsed |= (1 << i);
220       }
221    }
222
223    ctx->emit_declaration(ctx, decl);
224 }
225
226
227 static void
228 pstip_transform_immed(struct tgsi_transform_context *ctx,
229                       struct tgsi_full_immediate *immed)
230 {
231    struct pstip_transform_context *pctx =
232       (struct pstip_transform_context *) ctx;
233    pctx->numImmed++;
234 }
235
236
237 /**
238  * Find the lowest zero bit in the given word, or -1 if bitfield is all ones.
239  */
240 static int
241 free_bit(uint bitfield)
242 {
243    return ffs(~bitfield) - 1;
244 }
245
246
247 /**
248  * TGSI instruction transform callback.
249  * Before the first instruction, insert our new code to sample the
250  * stipple texture (using the fragment coord register) then kill the
251  * fragment if the stipple texture bit is off.
252  *
253  * Insert:
254  *   declare new registers
255  *   MUL texTemp, INPUT[wincoord], 1/32;
256  *   TEX texTemp, texTemp, sampler;
257  *   KIL -texTemp;   # if -texTemp < 0, KILL fragment
258  *   [...original code...]
259  */
260 static void
261 pstip_transform_inst(struct tgsi_transform_context *ctx,
262                      struct tgsi_full_instruction *inst)
263 {
264    struct pstip_transform_context *pctx =
265       (struct pstip_transform_context *) ctx;
266
267    if (pctx->firstInstruction) {
268       /* emit our new declarations before the first instruction */
269
270       struct tgsi_full_declaration decl;
271       struct tgsi_full_instruction newInst;
272       uint i;
273       int wincoordInput;
274
275       /* find free texture sampler */
276       pctx->freeSampler = free_bit(pctx->samplersUsed);
277       if (pctx->freeSampler >= PIPE_MAX_SAMPLERS)
278          pctx->freeSampler = PIPE_MAX_SAMPLERS - 1;
279
280       if (pctx->wincoordInput < 0)
281          wincoordInput = pctx->maxInput + 1;
282       else
283          wincoordInput = pctx->wincoordInput;
284
285       /* find one free temp register */
286       for (i = 0; i < 32; i++) {
287          if ((pctx->tempsUsed & (1 << i)) == 0) {
288             /* found a free temp */
289             if (pctx->texTemp < 0)
290                pctx->texTemp  = i;
291             else
292                break;
293          }
294       }
295       assert(pctx->texTemp >= 0);
296
297       if (pctx->wincoordInput < 0) {
298          /* declare new position input reg */
299          decl = tgsi_default_full_declaration();
300          decl.Declaration.File = TGSI_FILE_INPUT;
301          decl.Declaration.Interpolate = TGSI_INTERPOLATE_LINEAR;
302          decl.Declaration.Semantic = 1;
303          decl.Semantic.Name = TGSI_SEMANTIC_POSITION;
304          decl.Semantic.Index = 0;
305          decl.Range.First = 
306             decl.Range.Last = wincoordInput;
307          ctx->emit_declaration(ctx, &decl);
308       }
309
310       /* declare new sampler */
311       decl = tgsi_default_full_declaration();
312       decl.Declaration.File = TGSI_FILE_SAMPLER;
313       decl.Range.First = 
314       decl.Range.Last = pctx->freeSampler;
315       ctx->emit_declaration(ctx, &decl);
316
317       /* declare new temp regs */
318       decl = tgsi_default_full_declaration();
319       decl.Declaration.File = TGSI_FILE_TEMPORARY;
320       decl.Range.First = 
321       decl.Range.Last = pctx->texTemp;
322       ctx->emit_declaration(ctx, &decl);
323
324       /* emit immediate = {1/32, 1/32, 1, 1}
325        * The index/position of this immediate will be pctx->numImmed
326        */
327       {
328          static const float value[4] = { 1.0/32, 1.0/32, 1.0, 1.0 };
329          struct tgsi_full_immediate immed;
330          uint size = 4;
331          immed = tgsi_default_full_immediate();
332          immed.Immediate.NrTokens = 1 + size; /* one for the token itself */
333          immed.u[0].Float = value[0];
334          immed.u[1].Float = value[1];
335          immed.u[2].Float = value[2];
336          immed.u[3].Float = value[3];
337          ctx->emit_immediate(ctx, &immed);
338       }
339
340       pctx->firstInstruction = FALSE;
341
342
343       /* 
344        * Insert new MUL/TEX/KILP instructions at start of program
345        * Take gl_FragCoord, divide by 32 (stipple size), sample the
346        * texture and kill fragment if needed.
347        *
348        * We'd like to use non-normalized texcoords to index into a RECT
349        * texture, but we can only use REPEAT wrap mode with normalized
350        * texcoords.  Darn.
351        */
352
353       /* XXX invert wincoord if origin isn't lower-left... */
354
355       /* MUL texTemp, INPUT[wincoord], 1/32; */
356       newInst = tgsi_default_full_instruction();
357       newInst.Instruction.Opcode = TGSI_OPCODE_MUL;
358       newInst.Instruction.NumDstRegs = 1;
359       newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
360       newInst.Dst[0].Register.Index = pctx->texTemp;
361       newInst.Instruction.NumSrcRegs = 2;
362       newInst.Src[0].Register.File = TGSI_FILE_INPUT;
363       newInst.Src[0].Register.Index = wincoordInput;
364       newInst.Src[1].Register.File = TGSI_FILE_IMMEDIATE;
365       newInst.Src[1].Register.Index = pctx->numImmed;
366       ctx->emit_instruction(ctx, &newInst);
367
368       /* TEX texTemp, texTemp, sampler; */
369       newInst = tgsi_default_full_instruction();
370       newInst.Instruction.Opcode = TGSI_OPCODE_TEX;
371       newInst.Instruction.NumDstRegs = 1;
372       newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
373       newInst.Dst[0].Register.Index = pctx->texTemp;
374       newInst.Instruction.NumSrcRegs = 2;
375       newInst.Instruction.Texture = TRUE;
376       newInst.Texture.Texture = TGSI_TEXTURE_2D;
377       newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
378       newInst.Src[0].Register.Index = pctx->texTemp;
379       newInst.Src[1].Register.File = TGSI_FILE_SAMPLER;
380       newInst.Src[1].Register.Index = pctx->freeSampler;
381       ctx->emit_instruction(ctx, &newInst);
382
383       /* KIL -texTemp;   # if -texTemp < 0, KILL fragment */
384       newInst = tgsi_default_full_instruction();
385       newInst.Instruction.Opcode = TGSI_OPCODE_KIL;
386       newInst.Instruction.NumDstRegs = 0;
387       newInst.Instruction.NumSrcRegs = 1;
388       newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
389       newInst.Src[0].Register.Index = pctx->texTemp;
390       newInst.Src[0].Register.Negate = 1;
391       ctx->emit_instruction(ctx, &newInst);
392    }
393
394    /* emit this instruction */
395    ctx->emit_instruction(ctx, inst);
396 }
397
398
399 /**
400  * Given a fragment shader, return a new fragment shader which
401  * samples a stipple texture and executes KILL.
402  */
403 struct pipe_shader_state *
404 util_pstipple_create_fragment_shader(struct pipe_context *pipe,
405                                      struct pipe_shader_state *fs,
406                                      unsigned *samplerUnitOut)
407 {
408    struct pipe_shader_state *new_fs;
409    struct pstip_transform_context transform;
410    const uint newLen = tgsi_num_tokens(fs->tokens) + NUM_NEW_TOKENS;
411    unsigned i;
412
413    new_fs = MALLOC(sizeof(*new_fs));
414    if (!new_fs)
415       return NULL;
416
417    new_fs->tokens = tgsi_alloc_tokens(newLen);
418    if (!new_fs->tokens) {
419       FREE(new_fs);
420       return NULL;
421    }
422
423    /* Setup shader transformation info/context.
424     */
425    memset(&transform, 0, sizeof(transform));
426    transform.wincoordInput = -1;
427    transform.maxInput = -1;
428    transform.texTemp = -1;
429    transform.firstInstruction = TRUE;
430    transform.coordOrigin = TGSI_FS_COORD_ORIGIN_UPPER_LEFT;
431    transform.base.transform_instruction = pstip_transform_inst;
432    transform.base.transform_declaration = pstip_transform_decl;
433    transform.base.transform_immediate = pstip_transform_immed;
434
435    tgsi_scan_shader(fs->tokens, &transform.info);
436
437    /* find fragment coordinate origin property */
438    for (i = 0; i < transform.info.num_properties; i++) {
439       if (transform.info.properties[i].name == TGSI_PROPERTY_FS_COORD_ORIGIN)
440          transform.coordOrigin = transform.info.properties[i].data[0];
441    }
442
443    tgsi_transform_shader(fs->tokens,
444                          (struct tgsi_token *) new_fs->tokens,
445                          newLen, &transform.base);
446
447 #if 0 /* DEBUG */
448    tgsi_dump(fs->tokens, 0);
449    tgsi_dump(new_fs->tokens, 0);
450 #endif
451
452    assert(transform.freeSampler < PIPE_MAX_SAMPLERS);
453    *samplerUnitOut = transform.freeSampler;
454
455    return new_fs;
456 }
457