1/**********************************************************
2 * Copyright 2008-2009 VMware, Inc.  All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 **********************************************************/
25
26#include "draw/draw_context.h"
27#include "draw/draw_vbuf.h"
28#include "util/u_inlines.h"
29#include "pipe/p_state.h"
30
31#include "svga_context.h"
32#include "svga_swtnl.h"
33#include "svga_state.h"
34#include "svga_tgsi.h"
35#include "svga_swtnl_private.h"
36
37
38#define SVGA_POINT_ADJ_X -0.375
39#define SVGA_POINT_ADJ_Y -0.5
40
41#define SVGA_LINE_ADJ_X -0.5
42#define SVGA_LINE_ADJ_Y -0.5
43
44#define SVGA_TRIANGLE_ADJ_X -0.375
45#define SVGA_TRIANGLE_ADJ_Y -0.5
46
47
48static void set_draw_viewport( struct svga_context *svga )
49{
50   struct pipe_viewport_state vp = svga->curr.viewport;
51   float adjx = 0;
52   float adjy = 0;
53
54   switch (svga->curr.reduced_prim) {
55   case PIPE_PRIM_POINTS:
56      adjx = SVGA_POINT_ADJ_X;
57      adjy = SVGA_POINT_ADJ_Y;
58      break;
59   case PIPE_PRIM_LINES:
60      /* XXX: This is to compensate for the fact that wide lines are
61       * going to be drawn with triangles, but we're not catching all
62       * cases where that will happen.
63       */
64      if (svga->curr.rast->need_pipeline & SVGA_PIPELINE_FLAG_LINES)
65      {
66         adjx = SVGA_LINE_ADJ_X + 0.175;
67         adjy = SVGA_LINE_ADJ_Y - 0.175;
68      }
69      else {
70         adjx = SVGA_LINE_ADJ_X;
71         adjy = SVGA_LINE_ADJ_Y;
72      }
73      break;
74   case PIPE_PRIM_TRIANGLES:
75      adjx += SVGA_TRIANGLE_ADJ_X;
76      adjy += SVGA_TRIANGLE_ADJ_Y;
77      break;
78   }
79
80   vp.translate[0] += adjx;
81   vp.translate[1] += adjy;
82
83   draw_set_viewport_state(svga->swtnl.draw, &vp);
84}
85
86static enum pipe_error
87update_swtnl_draw( struct svga_context *svga,
88                   unsigned dirty )
89{
90   draw_flush( svga->swtnl.draw );
91
92   if (dirty & SVGA_NEW_VS)
93      draw_bind_vertex_shader(svga->swtnl.draw,
94                              svga->curr.vs->draw_shader);
95
96   if (dirty & SVGA_NEW_FS)
97      draw_bind_fragment_shader(svga->swtnl.draw,
98                                svga->curr.fs->draw_shader);
99
100   if (dirty & SVGA_NEW_VBUFFER)
101      draw_set_vertex_buffers(svga->swtnl.draw,
102                              svga->curr.num_vertex_buffers,
103                              svga->curr.vb);
104
105   if (dirty & SVGA_NEW_VELEMENT)
106      draw_set_vertex_elements(svga->swtnl.draw,
107                               svga->curr.velems->count,
108                               svga->curr.velems->velem );
109
110   if (dirty & SVGA_NEW_CLIP)
111      draw_set_clip_state(svga->swtnl.draw,
112                          &svga->curr.clip);
113
114   if (dirty & (SVGA_NEW_VIEWPORT |
115                SVGA_NEW_REDUCED_PRIMITIVE |
116                SVGA_NEW_RAST))
117      set_draw_viewport( svga );
118
119   if (dirty & SVGA_NEW_RAST)
120      draw_set_rasterizer_state(svga->swtnl.draw,
121                                &svga->curr.rast->templ,
122                                (void *) svga->curr.rast);
123
124   if (dirty & SVGA_NEW_FRAME_BUFFER)
125      draw_set_mrd(svga->swtnl.draw,
126                   svga->curr.depthscale);
127
128   return 0;
129}
130
131
132struct svga_tracked_state svga_update_swtnl_draw =
133{
134   "update draw module state",
135   (SVGA_NEW_VS |
136    SVGA_NEW_VBUFFER |
137    SVGA_NEW_VELEMENT |
138    SVGA_NEW_CLIP |
139    SVGA_NEW_VIEWPORT |
140    SVGA_NEW_RAST |
141    SVGA_NEW_FRAME_BUFFER |
142    SVGA_NEW_REDUCED_PRIMITIVE),
143   update_swtnl_draw
144};
145
146
147enum pipe_error
148svga_swtnl_update_vdecl( struct svga_context *svga )
149{
150   struct svga_vbuf_render *svga_render = svga_vbuf_render(svga->swtnl.backend);
151   struct draw_context *draw = svga->swtnl.draw;
152   struct vertex_info *vinfo = &svga_render->vertex_info;
153   SVGA3dVertexDecl vdecl[PIPE_MAX_ATTRIBS];
154   const enum interp_mode colorInterp =
155      svga->curr.rast->templ.flatshade ? INTERP_CONSTANT : INTERP_LINEAR;
156   struct svga_fragment_shader *fs = svga->curr.fs;
157   int offset = 0;
158   int nr_decls = 0;
159   int src, i;
160
161   memset(vinfo, 0, sizeof(*vinfo));
162   memset(vdecl, 0, sizeof(vdecl));
163
164   /* always add position */
165   src = draw_find_shader_output(draw, TGSI_SEMANTIC_POSITION, 0);
166   draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_LINEAR, src);
167   vinfo->attrib[0].emit = EMIT_4F;
168   vdecl[0].array.offset = offset;
169   vdecl[0].identity.type = SVGA3D_DECLTYPE_FLOAT4;
170   vdecl[0].identity.usage = SVGA3D_DECLUSAGE_POSITIONT;
171   vdecl[0].identity.usageIndex = 0;
172   offset += 16;
173   nr_decls++;
174
175   for (i = 0; i < fs->base.info.num_inputs; i++) {
176      const unsigned sem_name = fs->base.info.input_semantic_name[i];
177      const unsigned sem_index = fs->base.info.input_semantic_index[i];
178
179      src = draw_find_shader_output(draw, sem_name, sem_index);
180
181      vdecl[nr_decls].array.offset = offset;
182      vdecl[nr_decls].identity.usageIndex = sem_index;
183
184      switch (sem_name) {
185      case TGSI_SEMANTIC_COLOR:
186         draw_emit_vertex_attr(vinfo, EMIT_4F, colorInterp, src);
187         vdecl[nr_decls].identity.usage = SVGA3D_DECLUSAGE_COLOR;
188         vdecl[nr_decls].identity.type = SVGA3D_DECLTYPE_FLOAT4;
189         offset += 16;
190         nr_decls++;
191         break;
192      case TGSI_SEMANTIC_GENERIC:
193         draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, src);
194         vdecl[nr_decls].identity.usage = SVGA3D_DECLUSAGE_TEXCOORD;
195         vdecl[nr_decls].identity.type = SVGA3D_DECLTYPE_FLOAT4;
196         vdecl[nr_decls].identity.usageIndex =
197            svga_remap_generic_index(fs->generic_remap_table, sem_index);
198         offset += 16;
199         nr_decls++;
200         break;
201      case TGSI_SEMANTIC_FOG:
202         draw_emit_vertex_attr(vinfo, EMIT_1F, INTERP_PERSPECTIVE, src);
203         vdecl[nr_decls].identity.usage = SVGA3D_DECLUSAGE_TEXCOORD;
204         vdecl[nr_decls].identity.type = SVGA3D_DECLTYPE_FLOAT1;
205         assert(vdecl[nr_decls].identity.usageIndex == 0);
206         offset += 4;
207         nr_decls++;
208         break;
209      case TGSI_SEMANTIC_POSITION:
210         /* generated internally, not a vertex shader output */
211         break;
212      default:
213         assert(0);
214      }
215   }
216
217   draw_compute_vertex_size(vinfo);
218
219   svga_render->vdecl_count = nr_decls;
220   for (i = 0; i < svga_render->vdecl_count; i++)
221      vdecl[i].array.stride = offset;
222
223   if (memcmp(svga_render->vdecl, vdecl, sizeof(vdecl)) == 0)
224      return 0;
225
226   memcpy(svga_render->vdecl, vdecl, sizeof(vdecl));
227   svga->swtnl.new_vdecl = TRUE;
228
229   return 0;
230}
231
232
233static enum pipe_error
234update_swtnl_vdecl( struct svga_context *svga,
235                    unsigned dirty )
236{
237   return svga_swtnl_update_vdecl( svga );
238}
239
240
241struct svga_tracked_state svga_update_swtnl_vdecl =
242{
243   "update draw module vdecl",
244   (SVGA_NEW_VS |
245    SVGA_NEW_FS),
246   update_swtnl_vdecl
247};
248