draw_pipe_aaline.c revision 4f25420bdd834e81a3e22733304efc5261c2998a
14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/**************************************************************************
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * All Rights Reserved.
54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *
64e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Permission is hereby granted, free of charge, to any person obtaining a
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * copy of this software and associated documentation files (the
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * "Software"), to deal in the Software without restriction, including
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * without limitation the rights to use, copy, modify, merge, publish,
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * distribute, sub license, and/or sell copies of the Software, and to
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * permit persons to whom the Software is furnished to do so, subject to
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the following conditions:
134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *
144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * The above copyright notice and this permission notice (including the
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * next paragraph) shall be included in all copies or substantial portions
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * of the Software.
174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) **************************************************************************/
274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * AA line stage:  AA lines are converted to texture mapped triangles.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Authors:  Brian Paul
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "pipe/p_inlines.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "pipe/p_context.h"
374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "pipe/p_defines.h"
38#include "pipe/p_shader_tokens.h"
39#include "util/u_math.h"
40#include "util/u_memory.h"
41
42#include "tgsi/tgsi_transform.h"
43#include "tgsi/tgsi_dump.h"
44
45#include "draw_context.h"
46#include "draw_private.h"
47#include "draw_pipe.h"
48
49
50/**
51 * Max texture level for the alpha texture used for antialiasing
52 */
53#define MAX_TEXTURE_LEVEL  5   /* 32 x 32 */
54
55
56/**
57 * Subclass of pipe_shader_state to carry extra fragment shader info.
58 */
59struct aaline_fragment_shader
60{
61   struct pipe_shader_state state;
62   void *driver_fs;
63   void *aaline_fs;
64   void *aapoint_fs; /* not yet */
65   void *sprite_fs; /* not yet */
66   uint sampler_unit;
67   int generic_attrib;  /**< texcoord/generic used for texture */
68};
69
70
71/**
72 * Subclass of draw_stage
73 */
74struct aaline_stage
75{
76   struct draw_stage stage;
77
78   float half_line_width;
79
80   /** For AA lines, this is the vertex attrib slot for the new texcoords */
81   uint tex_slot;
82   /** position, not necessarily output zero */
83   uint pos_slot;
84
85   void *sampler_cso;
86   struct pipe_texture *texture;
87   uint num_samplers;
88   uint num_textures;
89
90
91   /*
92    * Currently bound state
93    */
94   struct aaline_fragment_shader *fs;
95   struct {
96      void *sampler[PIPE_MAX_SAMPLERS];
97      struct pipe_texture *texture[PIPE_MAX_SAMPLERS];
98   } state;
99
100   /*
101    * Driver interface/override functions
102    */
103   void * (*driver_create_fs_state)(struct pipe_context *,
104                                    const struct pipe_shader_state *);
105   void (*driver_bind_fs_state)(struct pipe_context *, void *);
106   void (*driver_delete_fs_state)(struct pipe_context *, void *);
107
108   void (*driver_bind_sampler_states)(struct pipe_context *, unsigned,
109                                      void **);
110   void (*driver_set_sampler_textures)(struct pipe_context *, unsigned,
111                                       struct pipe_texture **);
112
113   struct pipe_context *pipe;
114};
115
116
117
118/**
119 * Subclass of tgsi_transform_context, used for transforming the
120 * user's fragment shader to add the special AA instructions.
121 */
122struct aa_transform_context {
123   struct tgsi_transform_context base;
124   uint tempsUsed;  /**< bitmask */
125   int colorOutput; /**< which output is the primary color */
126   uint samplersUsed;  /**< bitfield of samplers used */
127   int freeSampler;  /** an available sampler for the pstipple */
128   int maxInput, maxGeneric;  /**< max input index found */
129   int colorTemp, texTemp;  /**< temp registers */
130   boolean firstInstruction;
131};
132
133
134/**
135 * TGSI declaration transform callback.
136 * Look for a free sampler, a free input attrib, and two free temp regs.
137 */
138static void
139aa_transform_decl(struct tgsi_transform_context *ctx,
140                  struct tgsi_full_declaration *decl)
141{
142   struct aa_transform_context *aactx = (struct aa_transform_context *) ctx;
143
144   if (decl->Declaration.File == TGSI_FILE_OUTPUT &&
145       decl->Semantic.SemanticName == TGSI_SEMANTIC_COLOR &&
146       decl->Semantic.SemanticIndex == 0) {
147      aactx->colorOutput = decl->DeclarationRange.First;
148   }
149   else if (decl->Declaration.File == TGSI_FILE_SAMPLER) {
150      uint i;
151      for (i = decl->DeclarationRange.First;
152           i <= decl->DeclarationRange.Last; i++) {
153         aactx->samplersUsed |= 1 << i;
154      }
155   }
156   else if (decl->Declaration.File == TGSI_FILE_INPUT) {
157      if ((int) decl->DeclarationRange.Last > aactx->maxInput)
158         aactx->maxInput = decl->DeclarationRange.Last;
159      if (decl->Semantic.SemanticName == TGSI_SEMANTIC_GENERIC &&
160           (int) decl->Semantic.SemanticIndex > aactx->maxGeneric) {
161         aactx->maxGeneric = decl->Semantic.SemanticIndex;
162      }
163   }
164   else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) {
165      uint i;
166      for (i = decl->DeclarationRange.First;
167           i <= decl->DeclarationRange.Last; i++) {
168         aactx->tempsUsed |= (1 << i);
169      }
170   }
171
172   ctx->emit_declaration(ctx, decl);
173}
174
175
176/**
177 * Find the lowest zero bit in the given word, or -1 if bitfield is all ones.
178 */
179static int
180free_bit(uint bitfield)
181{
182   int i;
183   for (i = 0; i < 32; i++) {
184      if ((bitfield & (1 << i)) == 0)
185         return i;
186   }
187   return -1;
188}
189
190
191/**
192 * TGSI instruction transform callback.
193 * Replace writes to result.color w/ a temp reg.
194 * Upon END instruction, insert texture sampling code for antialiasing.
195 */
196static void
197aa_transform_inst(struct tgsi_transform_context *ctx,
198                  struct tgsi_full_instruction *inst)
199{
200   struct aa_transform_context *aactx = (struct aa_transform_context *) ctx;
201
202   if (aactx->firstInstruction) {
203      /* emit our new declarations before the first instruction */
204
205      struct tgsi_full_declaration decl;
206      uint i;
207
208      /* find free sampler */
209      aactx->freeSampler = free_bit(aactx->samplersUsed);
210      if (aactx->freeSampler >= PIPE_MAX_SAMPLERS)
211         aactx->freeSampler = PIPE_MAX_SAMPLERS - 1;
212
213      /* find two free temp regs */
214      for (i = 0; i < 32; i++) {
215         if ((aactx->tempsUsed & (1 << i)) == 0) {
216            /* found a free temp */
217            if (aactx->colorTemp < 0)
218               aactx->colorTemp  = i;
219            else if (aactx->texTemp < 0)
220               aactx->texTemp  = i;
221            else
222               break;
223         }
224      }
225      assert(aactx->colorTemp >= 0);
226      assert(aactx->texTemp >= 0);
227
228      /* declare new generic input/texcoord */
229      decl = tgsi_default_full_declaration();
230      decl.Declaration.File = TGSI_FILE_INPUT;
231      /* XXX this could be linear... */
232      decl.Declaration.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE;
233      decl.Declaration.Semantic = 1;
234      decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC;
235      decl.Semantic.SemanticIndex = aactx->maxGeneric + 1;
236      decl.DeclarationRange.First =
237      decl.DeclarationRange.Last = aactx->maxInput + 1;
238      ctx->emit_declaration(ctx, &decl);
239
240      /* declare new sampler */
241      decl = tgsi_default_full_declaration();
242      decl.Declaration.File = TGSI_FILE_SAMPLER;
243      decl.DeclarationRange.First =
244      decl.DeclarationRange.Last = aactx->freeSampler;
245      ctx->emit_declaration(ctx, &decl);
246
247      /* declare new temp regs */
248      decl = tgsi_default_full_declaration();
249      decl.Declaration.File = TGSI_FILE_TEMPORARY;
250      decl.DeclarationRange.First =
251      decl.DeclarationRange.Last = aactx->texTemp;
252      ctx->emit_declaration(ctx, &decl);
253
254      decl = tgsi_default_full_declaration();
255      decl.Declaration.File = TGSI_FILE_TEMPORARY;
256      decl.DeclarationRange.First =
257      decl.DeclarationRange.Last = aactx->colorTemp;
258      ctx->emit_declaration(ctx, &decl);
259
260      aactx->firstInstruction = FALSE;
261   }
262
263   if (inst->Instruction.Opcode == TGSI_OPCODE_END &&
264       aactx->colorOutput != -1) {
265      struct tgsi_full_instruction newInst;
266
267      /* TEX */
268      newInst = tgsi_default_full_instruction();
269      newInst.Instruction.Opcode = TGSI_OPCODE_TEX;
270      newInst.Instruction.NumDstRegs = 1;
271      newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
272      newInst.FullDstRegisters[0].DstRegister.Index = aactx->texTemp;
273      newInst.Instruction.NumSrcRegs = 2;
274      newInst.InstructionExtTexture.Texture = TGSI_TEXTURE_2D;
275      newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
276      newInst.FullSrcRegisters[0].SrcRegister.Index = aactx->maxInput + 1;
277      newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
278      newInst.FullSrcRegisters[1].SrcRegister.Index = aactx->freeSampler;
279
280      ctx->emit_instruction(ctx, &newInst);
281
282      /* MOV rgb */
283      newInst = tgsi_default_full_instruction();
284      newInst.Instruction.Opcode = TGSI_OPCODE_MOV;
285      newInst.Instruction.NumDstRegs = 1;
286      newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
287      newInst.FullDstRegisters[0].DstRegister.Index = aactx->colorOutput;
288      newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_XYZ;
289      newInst.Instruction.NumSrcRegs = 1;
290      newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
291      newInst.FullSrcRegisters[0].SrcRegister.Index = aactx->colorTemp;
292      ctx->emit_instruction(ctx, &newInst);
293
294      /* MUL alpha */
295      newInst = tgsi_default_full_instruction();
296      newInst.Instruction.Opcode = TGSI_OPCODE_MUL;
297      newInst.Instruction.NumDstRegs = 1;
298      newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
299      newInst.FullDstRegisters[0].DstRegister.Index = aactx->colorOutput;
300      newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_W;
301      newInst.Instruction.NumSrcRegs = 2;
302      newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
303      newInst.FullSrcRegisters[0].SrcRegister.Index = aactx->colorTemp;
304      newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_TEMPORARY;
305      newInst.FullSrcRegisters[1].SrcRegister.Index = aactx->texTemp;
306      ctx->emit_instruction(ctx, &newInst);
307
308      /* END */
309      newInst = tgsi_default_full_instruction();
310      newInst.Instruction.Opcode = TGSI_OPCODE_END;
311      newInst.Instruction.NumDstRegs = 0;
312      newInst.Instruction.NumSrcRegs = 0;
313      ctx->emit_instruction(ctx, &newInst);
314   }
315   else {
316      /* Not an END instruction.
317       * Look for writes to result.color and replace with colorTemp reg.
318       */
319      uint i;
320
321      for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
322         struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i];
323         if (dst->DstRegister.File == TGSI_FILE_OUTPUT &&
324             dst->DstRegister.Index == aactx->colorOutput) {
325            dst->DstRegister.File = TGSI_FILE_TEMPORARY;
326            dst->DstRegister.Index = aactx->colorTemp;
327         }
328      }
329
330      ctx->emit_instruction(ctx, inst);
331   }
332}
333
334
335/**
336 * Generate the frag shader we'll use for drawing AA lines.
337 * This will be the user's shader plus some texture/modulate instructions.
338 */
339static boolean
340generate_aaline_fs(struct aaline_stage *aaline)
341{
342   const struct pipe_shader_state *orig_fs = &aaline->fs->state;
343   struct pipe_shader_state aaline_fs;
344   struct aa_transform_context transform;
345
346#define MAX 1000
347
348   aaline_fs = *orig_fs; /* copy to init */
349   aaline_fs.tokens = MALLOC(sizeof(struct tgsi_token) * MAX);
350   if (aaline_fs.tokens == NULL)
351      return FALSE;
352
353   memset(&transform, 0, sizeof(transform));
354   transform.colorOutput = -1;
355   transform.maxInput = -1;
356   transform.maxGeneric = -1;
357   transform.colorTemp = -1;
358   transform.texTemp = -1;
359   transform.firstInstruction = TRUE;
360   transform.base.transform_instruction = aa_transform_inst;
361   transform.base.transform_declaration = aa_transform_decl;
362
363   tgsi_transform_shader(orig_fs->tokens,
364                         (struct tgsi_token *) aaline_fs.tokens,
365                         MAX, &transform.base);
366
367#if 0 /* DEBUG */
368   tgsi_dump(orig_fs->tokens, 0);
369   tgsi_dump(aaline_fs.tokens, 0);
370#endif
371
372   aaline->fs->sampler_unit = transform.freeSampler;
373
374   aaline->fs->aaline_fs
375      = aaline->driver_create_fs_state(aaline->pipe, &aaline_fs);
376   if (aaline->fs->aaline_fs == NULL)
377      return FALSE;
378
379   aaline->fs->generic_attrib = transform.maxGeneric + 1;
380   return TRUE;
381}
382
383
384/**
385 * Create the texture map we'll use for antialiasing the lines.
386 */
387static boolean
388aaline_create_texture(struct aaline_stage *aaline)
389{
390   struct pipe_context *pipe = aaline->pipe;
391   struct pipe_screen *screen = pipe->screen;
392   struct pipe_texture texTemp;
393   uint level;
394
395   memset(&texTemp, 0, sizeof(texTemp));
396   texTemp.target = PIPE_TEXTURE_2D;
397   texTemp.format = PIPE_FORMAT_A8_UNORM; /* XXX verify supported by driver! */
398   texTemp.last_level = MAX_TEXTURE_LEVEL;
399   texTemp.width[0] = 1 << MAX_TEXTURE_LEVEL;
400   texTemp.height[0] = 1 << MAX_TEXTURE_LEVEL;
401   texTemp.depth[0] = 1;
402   pf_get_block(texTemp.format, &texTemp.block);
403
404   aaline->texture = screen->texture_create(screen, &texTemp);
405   if (!aaline->texture)
406      return FALSE;
407
408   /* Fill in mipmap images.
409    * Basically each level is solid opaque, except for the outermost
410    * texels which are zero.  Special case the 1x1 and 2x2 levels.
411    */
412   for (level = 0; level <= MAX_TEXTURE_LEVEL; level++) {
413      struct pipe_surface *surface;
414      const uint size = aaline->texture->width[level];
415      ubyte *data;
416      uint i, j;
417
418      assert(aaline->texture->width[level] == aaline->texture->height[level]);
419
420      /* This texture is new, no need to flush.
421       */
422      surface = screen->get_tex_surface(screen, aaline->texture, 0, level, 0,
423                                        PIPE_BUFFER_USAGE_CPU_WRITE);
424      data = screen->surface_map(screen, surface, PIPE_BUFFER_USAGE_CPU_WRITE);
425      if (data == NULL)
426         return FALSE;
427
428      for (i = 0; i < size; i++) {
429         for (j = 0; j < size; j++) {
430            ubyte d;
431            if (size == 1) {
432               d = 255;
433            }
434            else if (size == 2) {
435               d = 200; /* tuneable */
436            }
437            else if (i == 0 || j == 0 || i == size - 1 || j == size - 1) {
438               d = 0;
439            }
440            else {
441               d = 255;
442            }
443            data[i * surface->stride + j] = d;
444         }
445      }
446
447      /* unmap */
448      screen->surface_unmap(screen, surface);
449      screen->tex_surface_release(screen, &surface);
450   }
451   return TRUE;
452}
453
454
455/**
456 * Create the sampler CSO that'll be used for antialiasing.
457 * By using a mipmapped texture, we don't have to generate a different
458 * texture image for each line size.
459 */
460static boolean
461aaline_create_sampler(struct aaline_stage *aaline)
462{
463   struct pipe_sampler_state sampler;
464   struct pipe_context *pipe = aaline->pipe;
465
466   memset(&sampler, 0, sizeof(sampler));
467   sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
468   sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
469   sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
470   sampler.min_mip_filter = PIPE_TEX_MIPFILTER_LINEAR;
471   sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
472   sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
473   sampler.normalized_coords = 1;
474   sampler.min_lod = 0.0f;
475   sampler.max_lod = MAX_TEXTURE_LEVEL;
476
477   aaline->sampler_cso = pipe->create_sampler_state(pipe, &sampler);
478   if (aaline->sampler_cso == NULL)
479      return FALSE;
480
481   return TRUE;
482}
483
484
485/**
486 * When we're about to draw our first AA line in a batch, this function is
487 * called to tell the driver to bind our modified fragment shader.
488 */
489static boolean
490bind_aaline_fragment_shader(struct aaline_stage *aaline)
491{
492   struct draw_context *draw = aaline->stage.draw;
493
494   if (!aaline->fs->aaline_fs &&
495       !generate_aaline_fs(aaline))
496      return FALSE;
497
498   draw->suspend_flushing = TRUE;
499   aaline->driver_bind_fs_state(aaline->pipe, aaline->fs->aaline_fs);
500   draw->suspend_flushing = FALSE;
501
502   return TRUE;
503}
504
505
506
507static INLINE struct aaline_stage *
508aaline_stage( struct draw_stage *stage )
509{
510   return (struct aaline_stage *) stage;
511}
512
513
514/**
515 * Draw a wide line by drawing a quad, using geometry which will
516 * fullfill GL's antialiased line requirements.
517 */
518static void
519aaline_line(struct draw_stage *stage, struct prim_header *header)
520{
521   const struct aaline_stage *aaline = aaline_stage(stage);
522   const float half_width = aaline->half_line_width;
523   struct prim_header tri;
524   struct vertex_header *v[8];
525   uint texPos = aaline->tex_slot;
526   uint posPos = aaline->pos_slot;
527   float *pos, *tex;
528   float dx = header->v[1]->data[posPos][0] - header->v[0]->data[posPos][0];
529   float dy = header->v[1]->data[posPos][1] - header->v[0]->data[posPos][1];
530   double a = atan2(dy, dx);
531   float c_a = (float) cos(a), s_a = (float) sin(a);
532   uint i;
533
534   /* XXX the ends of lines aren't quite perfect yet, but probably passable */
535   dx = 0.5F * half_width;
536   dy = half_width;
537
538   /* allocate/dup new verts */
539   for (i = 0; i < 8; i++) {
540      v[i] = dup_vert(stage, header->v[i/4], i);
541   }
542
543   /*
544    * Quad strip for line from v0 to v1 (*=endpoints):
545    *
546    *  1   3                     5   7
547    *  +---+---------------------+---+
548    *  |                             |
549    *  | *v0                     v1* |
550    *  |                             |
551    *  +---+---------------------+---+
552    *  0   2                     4   6
553    */
554
555   /* new verts */
556   pos = v[0]->data[posPos];
557   pos[0] += (-dx * c_a -  dy * s_a);
558   pos[1] += (-dx * s_a +  dy * c_a);
559
560   pos = v[1]->data[posPos];
561   pos[0] += (-dx * c_a - -dy * s_a);
562   pos[1] += (-dx * s_a + -dy * c_a);
563
564   pos = v[2]->data[posPos];
565   pos[0] += ( dx * c_a -  dy * s_a);
566   pos[1] += ( dx * s_a +  dy * c_a);
567
568   pos = v[3]->data[posPos];
569   pos[0] += ( dx * c_a - -dy * s_a);
570   pos[1] += ( dx * s_a + -dy * c_a);
571
572   pos = v[4]->data[posPos];
573   pos[0] += (-dx * c_a -  dy * s_a);
574   pos[1] += (-dx * s_a +  dy * c_a);
575
576   pos = v[5]->data[posPos];
577   pos[0] += (-dx * c_a - -dy * s_a);
578   pos[1] += (-dx * s_a + -dy * c_a);
579
580   pos = v[6]->data[posPos];
581   pos[0] += ( dx * c_a -  dy * s_a);
582   pos[1] += ( dx * s_a +  dy * c_a);
583
584   pos = v[7]->data[posPos];
585   pos[0] += ( dx * c_a - -dy * s_a);
586   pos[1] += ( dx * s_a + -dy * c_a);
587
588   /* new texcoords */
589   tex = v[0]->data[texPos];
590   ASSIGN_4V(tex, 0, 0, 0, 1);
591
592   tex = v[1]->data[texPos];
593   ASSIGN_4V(tex, 0, 1, 0, 1);
594
595   tex = v[2]->data[texPos];
596   ASSIGN_4V(tex, .5, 0, 0, 1);
597
598   tex = v[3]->data[texPos];
599   ASSIGN_4V(tex, .5, 1, 0, 1);
600
601   tex = v[4]->data[texPos];
602   ASSIGN_4V(tex, .5, 0, 0, 1);
603
604   tex = v[5]->data[texPos];
605   ASSIGN_4V(tex, .5, 1, 0, 1);
606
607   tex = v[6]->data[texPos];
608   ASSIGN_4V(tex, 1, 0, 0, 1);
609
610   tex = v[7]->data[texPos];
611   ASSIGN_4V(tex, 1, 1, 0, 1);
612
613   /* emit 6 tris for the quad strip */
614   tri.v[0] = v[2];  tri.v[1] = v[1];  tri.v[2] = v[0];
615   stage->next->tri( stage->next, &tri );
616
617   tri.v[0] = v[3];  tri.v[1] = v[1];  tri.v[2] = v[2];
618   stage->next->tri( stage->next, &tri );
619
620   tri.v[0] = v[4];  tri.v[1] = v[3];  tri.v[2] = v[2];
621   stage->next->tri( stage->next, &tri );
622
623   tri.v[0] = v[5];  tri.v[1] = v[3];  tri.v[2] = v[4];
624   stage->next->tri( stage->next, &tri );
625
626   tri.v[0] = v[6];  tri.v[1] = v[5];  tri.v[2] = v[4];
627   stage->next->tri( stage->next, &tri );
628
629   tri.v[0] = v[7];  tri.v[1] = v[5];  tri.v[2] = v[6];
630   stage->next->tri( stage->next, &tri );
631}
632
633
634static void
635aaline_first_line(struct draw_stage *stage, struct prim_header *header)
636{
637   auto struct aaline_stage *aaline = aaline_stage(stage);
638   struct draw_context *draw = stage->draw;
639   struct pipe_context *pipe = aaline->pipe;
640   uint num_samplers;
641
642   assert(draw->rasterizer->line_smooth);
643
644   if (draw->rasterizer->line_width <= 3.0)
645      aaline->half_line_width = 1.5f;
646   else
647      aaline->half_line_width = 0.5f * draw->rasterizer->line_width;
648
649   /*
650    * Bind (generate) our fragprog, sampler and texture
651    */
652   if (!bind_aaline_fragment_shader(aaline)) {
653      stage->line = draw_pipe_passthrough_line;
654      stage->line(stage, header);
655      return;
656   }
657
658   /* update vertex attrib info */
659   aaline->tex_slot = draw->vs.num_vs_outputs;
660   aaline->pos_slot = draw->vs.position_output;
661
662   /* advertise the extra post-transformed vertex attribute */
663   draw->extra_vp_outputs.semantic_name = TGSI_SEMANTIC_GENERIC;
664   draw->extra_vp_outputs.semantic_index = aaline->fs->generic_attrib;
665   draw->extra_vp_outputs.slot = aaline->tex_slot;
666
667   /* how many samplers? */
668   /* we'll use sampler/texture[pstip->sampler_unit] for the stipple */
669   num_samplers = MAX2(aaline->num_textures, aaline->num_samplers);
670   num_samplers = MAX2(num_samplers, aaline->fs->sampler_unit + 1);
671
672   aaline->state.sampler[aaline->fs->sampler_unit] = aaline->sampler_cso;
673   pipe_texture_reference(&aaline->state.texture[aaline->fs->sampler_unit],
674                          aaline->texture);
675
676   draw->suspend_flushing = TRUE;
677   aaline->driver_bind_sampler_states(pipe, num_samplers, aaline->state.sampler);
678   aaline->driver_set_sampler_textures(pipe, num_samplers, aaline->state.texture);
679   draw->suspend_flushing = FALSE;
680
681   /* now really draw first line */
682   stage->line = aaline_line;
683   stage->line(stage, header);
684}
685
686
687static void
688aaline_flush(struct draw_stage *stage, unsigned flags)
689{
690   struct draw_context *draw = stage->draw;
691   struct aaline_stage *aaline = aaline_stage(stage);
692   struct pipe_context *pipe = aaline->pipe;
693
694   stage->line = aaline_first_line;
695   stage->next->flush( stage->next, flags );
696
697   /* restore original frag shader, texture, sampler state */
698   draw->suspend_flushing = TRUE;
699   aaline->driver_bind_fs_state(pipe, aaline->fs->driver_fs);
700   aaline->driver_bind_sampler_states(pipe, aaline->num_samplers,
701                                      aaline->state.sampler);
702   aaline->driver_set_sampler_textures(pipe, aaline->num_textures,
703                                       aaline->state.texture);
704   draw->suspend_flushing = FALSE;
705
706   draw->extra_vp_outputs.slot = 0;
707}
708
709
710static void
711aaline_reset_stipple_counter(struct draw_stage *stage)
712{
713   stage->next->reset_stipple_counter( stage->next );
714}
715
716
717static void
718aaline_destroy(struct draw_stage *stage)
719{
720   struct aaline_stage *aaline = aaline_stage(stage);
721   uint i;
722
723   for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
724      pipe_texture_reference(&aaline->state.texture[i], NULL);
725   }
726
727   if (aaline->sampler_cso)
728      aaline->pipe->delete_sampler_state(aaline->pipe, aaline->sampler_cso);
729
730   if (aaline->texture)
731      pipe_texture_release(&aaline->texture);
732
733   draw_free_temp_verts( stage );
734
735   FREE( stage );
736}
737
738
739static struct aaline_stage *
740draw_aaline_stage(struct draw_context *draw)
741{
742   struct aaline_stage *aaline = CALLOC_STRUCT(aaline_stage);
743   if (aaline == NULL)
744      return NULL;
745
746   if (!draw_alloc_temp_verts( &aaline->stage, 8 ))
747      goto fail;
748
749   aaline->stage.draw = draw;
750   aaline->stage.next = NULL;
751   aaline->stage.point = draw_pipe_passthrough_point;
752   aaline->stage.line = aaline_first_line;
753   aaline->stage.tri = draw_pipe_passthrough_tri;
754   aaline->stage.flush = aaline_flush;
755   aaline->stage.reset_stipple_counter = aaline_reset_stipple_counter;
756   aaline->stage.destroy = aaline_destroy;
757
758   return aaline;
759
760 fail:
761   if (aaline)
762      aaline_destroy(&aaline->stage);
763
764   return NULL;
765}
766
767
768static struct aaline_stage *
769aaline_stage_from_pipe(struct pipe_context *pipe)
770{
771   struct draw_context *draw = (struct draw_context *) pipe->draw;
772   return aaline_stage(draw->pipeline.aaline);
773}
774
775
776/**
777 * This function overrides the driver's create_fs_state() function and
778 * will typically be called by the state tracker.
779 */
780static void *
781aaline_create_fs_state(struct pipe_context *pipe,
782                       const struct pipe_shader_state *fs)
783{
784   struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
785   struct aaline_fragment_shader *aafs = CALLOC_STRUCT(aaline_fragment_shader);
786   if (aafs == NULL)
787      return NULL;
788
789   aafs->state = *fs;
790
791   /* pass-through */
792   aafs->driver_fs = aaline->driver_create_fs_state(aaline->pipe, fs);
793
794   return aafs;
795}
796
797
798static void
799aaline_bind_fs_state(struct pipe_context *pipe, void *fs)
800{
801   struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
802   struct aaline_fragment_shader *aafs = (struct aaline_fragment_shader *) fs;
803
804   /* save current */
805   aaline->fs = aafs;
806   /* pass-through */
807   aaline->driver_bind_fs_state(aaline->pipe,
808                                (aafs ? aafs->driver_fs : NULL));
809}
810
811
812static void
813aaline_delete_fs_state(struct pipe_context *pipe, void *fs)
814{
815   struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
816   struct aaline_fragment_shader *aafs = (struct aaline_fragment_shader *) fs;
817   /* pass-through */
818   aaline->driver_delete_fs_state(aaline->pipe, aafs->driver_fs);
819   FREE(aafs);
820}
821
822
823static void
824aaline_bind_sampler_states(struct pipe_context *pipe,
825                           unsigned num, void **sampler)
826{
827   struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
828
829   /* save current */
830   memcpy(aaline->state.sampler, sampler, num * sizeof(void *));
831   aaline->num_samplers = num;
832
833   /* pass-through */
834   aaline->driver_bind_sampler_states(aaline->pipe, num, sampler);
835}
836
837
838static void
839aaline_set_sampler_textures(struct pipe_context *pipe,
840                            unsigned num, struct pipe_texture **texture)
841{
842   struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
843   uint i;
844
845   /* save current */
846   for (i = 0; i < num; i++) {
847      pipe_texture_reference(&aaline->state.texture[i], texture[i]);
848   }
849   for ( ; i < PIPE_MAX_SAMPLERS; i++) {
850      pipe_texture_reference(&aaline->state.texture[i], NULL);
851   }
852   aaline->num_textures = num;
853
854   /* pass-through */
855   aaline->driver_set_sampler_textures(aaline->pipe, num, texture);
856}
857
858
859/**
860 * Called by drivers that want to install this AA line prim stage
861 * into the draw module's pipeline.  This will not be used if the
862 * hardware has native support for AA lines.
863 */
864boolean
865draw_install_aaline_stage(struct draw_context *draw, struct pipe_context *pipe)
866{
867   struct aaline_stage *aaline;
868
869   pipe->draw = (void *) draw;
870
871   /*
872    * Create / install AA line drawing / prim stage
873    */
874   aaline = draw_aaline_stage( draw );
875   if (!aaline)
876      goto fail;
877
878   aaline->pipe = pipe;
879
880   /* create special texture, sampler state */
881   if (!aaline_create_texture(aaline))
882      goto fail;
883
884   if (!aaline_create_sampler(aaline))
885      goto fail;
886
887   /* save original driver functions */
888   aaline->driver_create_fs_state = pipe->create_fs_state;
889   aaline->driver_bind_fs_state = pipe->bind_fs_state;
890   aaline->driver_delete_fs_state = pipe->delete_fs_state;
891
892   aaline->driver_bind_sampler_states = pipe->bind_sampler_states;
893   aaline->driver_set_sampler_textures = pipe->set_sampler_textures;
894
895   /* override the driver's functions */
896   pipe->create_fs_state = aaline_create_fs_state;
897   pipe->bind_fs_state = aaline_bind_fs_state;
898   pipe->delete_fs_state = aaline_delete_fs_state;
899
900   pipe->bind_sampler_states = aaline_bind_sampler_states;
901   pipe->set_sampler_textures = aaline_set_sampler_textures;
902
903   /* Install once everything is known to be OK:
904    */
905   draw->pipeline.aaline = &aaline->stage;
906
907   return TRUE;
908
909 fail:
910   if (aaline)
911      aaline->stage.destroy( &aaline->stage );
912
913   return FALSE;
914}
915