Squashed commit of the following:
[profile/ivi/mesa.git] / src / gallium / drivers / svga / svga_draw.c
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 "pipe/p_compiler.h"
27 #include "util/u_inlines.h"
28 #include "pipe/p_defines.h"
29 #include "util/u_memory.h"
30 #include "util/u_math.h"
31
32 #include "svga_context.h"
33 #include "svga_draw.h"
34 #include "svga_draw_private.h"
35 #include "svga_debug.h"
36 #include "svga_screen.h"
37 #include "svga_resource_buffer.h"
38 #include "svga_resource_texture.h"
39 #include "svga_surface.h"
40 #include "svga_winsys.h"
41 #include "svga_cmd.h"
42
43
44 struct svga_hwtnl *svga_hwtnl_create( struct svga_context *svga,
45                                       struct u_upload_mgr *upload_ib,
46                                       struct svga_winsys_context *swc )
47 {
48    struct svga_hwtnl *hwtnl = CALLOC_STRUCT(svga_hwtnl);
49    if (hwtnl == NULL)
50       goto fail;
51
52    hwtnl->svga = svga;
53    hwtnl->upload_ib = upload_ib;
54    
55    hwtnl->cmd.swc = swc;
56
57    return hwtnl;
58
59 fail:
60    return NULL;
61 }
62
63 void svga_hwtnl_destroy( struct svga_hwtnl *hwtnl )
64 {
65    int i, j;
66
67    for (i = 0; i < PIPE_PRIM_MAX; i++) {
68       for (j = 0; j < IDX_CACHE_MAX; j++) {
69          pipe_resource_reference( &hwtnl->index_cache[i][j].buffer,
70                                 NULL );
71       }
72    }
73
74    for (i = 0; i < hwtnl->cmd.vdecl_count; i++)
75       pipe_resource_reference(&hwtnl->cmd.vdecl_vb[i], NULL);
76
77    for (i = 0; i < hwtnl->cmd.prim_count; i++)
78       pipe_resource_reference(&hwtnl->cmd.prim_ib[i], NULL);
79       
80
81    FREE(hwtnl);
82 }
83
84
85 void svga_hwtnl_set_flatshade( struct svga_hwtnl *hwtnl,
86                                boolean flatshade,
87                                boolean flatshade_first )
88 {
89    hwtnl->hw_pv = PV_FIRST;
90    hwtnl->api_pv = (flatshade && !flatshade_first) ? PV_LAST : PV_FIRST;
91 }                               
92
93 void svga_hwtnl_set_unfilled( struct svga_hwtnl *hwtnl,
94                               unsigned mode )
95 {
96    hwtnl->api_fillmode = mode;
97 }                               
98
99 void svga_hwtnl_reset_vdecl( struct svga_hwtnl *hwtnl,
100                              unsigned count )
101 {
102    unsigned i;
103
104    assert(hwtnl->cmd.prim_count == 0);
105
106    for (i = count; i < hwtnl->cmd.vdecl_count; i++) {
107       pipe_resource_reference(&hwtnl->cmd.vdecl_vb[i],
108                             NULL);
109    }
110
111    hwtnl->cmd.vdecl_count = count;
112 }
113
114
115 void svga_hwtnl_vdecl( struct svga_hwtnl *hwtnl,
116                        unsigned i,
117                        const SVGA3dVertexDecl *decl,
118                        struct pipe_resource *vb)
119 {
120    assert(hwtnl->cmd.prim_count == 0);
121
122    assert( i < hwtnl->cmd.vdecl_count );
123
124    hwtnl->cmd.vdecl[i] = *decl;
125
126    pipe_resource_reference(&hwtnl->cmd.vdecl_vb[i], vb);   
127 }
128
129
130
131 enum pipe_error
132 svga_hwtnl_flush( struct svga_hwtnl *hwtnl )
133 {
134    struct svga_winsys_context *swc = hwtnl->cmd.swc;
135    struct svga_context *svga = hwtnl->svga;
136    enum pipe_error ret;
137
138    if (hwtnl->cmd.prim_count) {
139       struct svga_winsys_surface *vb_handle[SVGA3D_INPUTREG_MAX];
140       struct svga_winsys_surface *ib_handle[QSZ];
141       struct svga_winsys_surface *handle;
142       SVGA3dVertexDecl *vdecl;
143       SVGA3dPrimitiveRange *prim;
144       unsigned i;
145
146       for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
147          handle = svga_buffer_handle(svga, hwtnl->cmd.vdecl_vb[i]);
148          if (handle == NULL)
149             return PIPE_ERROR_OUT_OF_MEMORY;
150
151          vb_handle[i] = handle;
152       }
153
154       for (i = 0; i < hwtnl->cmd.prim_count; i++) {
155          if (hwtnl->cmd.prim_ib[i]) {
156             handle = svga_buffer_handle(svga, hwtnl->cmd.prim_ib[i]);
157             if (handle == NULL)
158                return PIPE_ERROR_OUT_OF_MEMORY;
159          }
160          else
161             handle = NULL;
162
163          ib_handle[i] = handle;
164       }
165
166       SVGA_DBG(DEBUG_DMA, "draw to sid %p, %d prims\n",
167                svga->curr.framebuffer.cbufs[0] ?
168                svga_surface(svga->curr.framebuffer.cbufs[0])->handle : NULL,
169                hwtnl->cmd.prim_count);
170
171       ret = SVGA3D_BeginDrawPrimitives(swc, 
172                                        &vdecl, 
173                                        hwtnl->cmd.vdecl_count, 
174                                        &prim, 
175                                        hwtnl->cmd.prim_count);
176       if (ret != PIPE_OK) 
177          return ret;
178
179       
180       memcpy( vdecl,
181               hwtnl->cmd.vdecl,
182               hwtnl->cmd.vdecl_count * sizeof hwtnl->cmd.vdecl[0]);
183
184       for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
185          /* Given rangeHint is considered to be relative to indexBias, and 
186           * indexBias varies per primitive, we cannot accurately supply an 
187           * rangeHint when emitting more than one primitive per draw command.
188           */
189          if (hwtnl->cmd.prim_count == 1) {
190             vdecl[i].rangeHint.first = hwtnl->cmd.min_index[0];
191             vdecl[i].rangeHint.last = hwtnl->cmd.max_index[0] + 1;
192          }
193          else {
194             vdecl[i].rangeHint.first = 0;
195             vdecl[i].rangeHint.last = 0;
196          }
197
198          swc->surface_relocation(swc,
199                                  &vdecl[i].array.surfaceId,
200                                  vb_handle[i],
201                                  SVGA_RELOC_READ);
202       }
203
204       memcpy( prim,
205               hwtnl->cmd.prim,
206               hwtnl->cmd.prim_count * sizeof hwtnl->cmd.prim[0]);
207
208       for (i = 0; i < hwtnl->cmd.prim_count; i++) {
209          swc->surface_relocation(swc,
210                                  &prim[i].indexArray.surfaceId,
211                                  ib_handle[i],
212                                  SVGA_RELOC_READ);
213          pipe_resource_reference(&hwtnl->cmd.prim_ib[i], NULL);
214       }
215       
216       SVGA_FIFOCommitAll( swc );
217       hwtnl->cmd.prim_count = 0;
218    }
219
220    return PIPE_OK;
221 }
222
223
224
225
226
227 /***********************************************************************
228  * Internal functions:
229  */
230
231 enum pipe_error svga_hwtnl_prim( struct svga_hwtnl *hwtnl,
232                                  const SVGA3dPrimitiveRange *range,
233                                  unsigned min_index,
234                                  unsigned max_index,
235                                  struct pipe_resource *ib )
236 {
237    int ret = PIPE_OK;
238
239 #ifdef DEBUG
240    {
241       unsigned i;
242       for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
243          struct pipe_resource *vb = hwtnl->cmd.vdecl_vb[i];
244          unsigned size = vb ? vb->width0 : 0;
245          unsigned offset = hwtnl->cmd.vdecl[i].array.offset;
246          unsigned stride = hwtnl->cmd.vdecl[i].array.stride;
247          unsigned index_bias = range->indexBias;
248          unsigned width;
249
250          assert(vb);
251          assert(size);
252          assert(offset < size);
253          assert(index_bias >= 0);
254          assert(min_index <= max_index);
255          assert(offset + index_bias*stride < size);
256          if (min_index != ~0) {
257             assert(offset + (index_bias + min_index) * stride < size);
258          }
259
260          switch (hwtnl->cmd.vdecl[i].identity.type) {
261          case SVGA3D_DECLTYPE_FLOAT1:
262             width = 4;
263             break;
264          case SVGA3D_DECLTYPE_FLOAT2:
265             width = 4*2;
266             break;
267          case SVGA3D_DECLTYPE_FLOAT3:
268             width = 4*3;
269             break;
270          case SVGA3D_DECLTYPE_FLOAT4:
271             width = 4*4;
272             break;
273          case SVGA3D_DECLTYPE_D3DCOLOR:
274             width = 4;
275             break;
276          case SVGA3D_DECLTYPE_UBYTE4:
277             width = 1*4;
278             break;
279          case SVGA3D_DECLTYPE_SHORT2:
280             width = 2*2;
281             break;
282          case SVGA3D_DECLTYPE_SHORT4:
283             width = 2*4;
284             break;
285          case SVGA3D_DECLTYPE_UBYTE4N:
286             width = 1*4;
287             break;
288          case SVGA3D_DECLTYPE_SHORT2N:
289             width = 2*2;
290             break;
291          case SVGA3D_DECLTYPE_SHORT4N:
292             width = 2*4;
293             break;
294          case SVGA3D_DECLTYPE_USHORT2N:
295             width = 2*2;
296             break;
297          case SVGA3D_DECLTYPE_USHORT4N:
298             width = 2*4;
299             break;
300          case SVGA3D_DECLTYPE_UDEC3:
301             width = 4;
302             break;
303          case SVGA3D_DECLTYPE_DEC3N:
304             width = 4;
305             break;
306          case SVGA3D_DECLTYPE_FLOAT16_2:
307             width = 2*2;
308             break;
309          case SVGA3D_DECLTYPE_FLOAT16_4:
310             width = 2*4;
311             break;
312          default:
313             assert(0);
314             width = 0;
315             break;
316          }
317
318          assert(!stride || width <= stride);
319          if (max_index != ~0) {
320             assert(offset + (index_bias + max_index) * stride + width <= size);
321          }
322       }
323
324       assert(range->indexWidth == range->indexArray.stride);
325
326       if(ib) {
327          unsigned size = ib->width0;
328          unsigned offset = range->indexArray.offset;
329          unsigned stride = range->indexArray.stride;
330          unsigned count;
331
332          assert(size);
333          assert(offset < size);
334          assert(stride);
335
336          switch (range->primType) {
337          case SVGA3D_PRIMITIVE_POINTLIST:
338             count = range->primitiveCount;
339             break;
340          case SVGA3D_PRIMITIVE_LINELIST:
341             count = range->primitiveCount * 2;
342             break;
343          case SVGA3D_PRIMITIVE_LINESTRIP:
344             count = range->primitiveCount + 1;
345             break;
346          case SVGA3D_PRIMITIVE_TRIANGLELIST:
347             count = range->primitiveCount * 3;
348             break;
349          case SVGA3D_PRIMITIVE_TRIANGLESTRIP:
350             count = range->primitiveCount + 2;
351             break;
352          case SVGA3D_PRIMITIVE_TRIANGLEFAN:
353             count = range->primitiveCount + 2;
354             break;
355          default:
356             assert(0);
357             count = 0;
358             break;
359          }
360
361          assert(offset + count*stride <= size);
362       }
363    }
364 #endif
365
366    if (hwtnl->cmd.prim_count+1 >= QSZ) {
367       ret = svga_hwtnl_flush( hwtnl );
368       if (ret != PIPE_OK)
369          return ret;
370    }
371    
372    /* min/max indices are relative to bias */
373    hwtnl->cmd.min_index[hwtnl->cmd.prim_count] = min_index;
374    hwtnl->cmd.max_index[hwtnl->cmd.prim_count] = max_index;
375
376    hwtnl->cmd.prim[hwtnl->cmd.prim_count] = *range;
377
378    pipe_resource_reference(&hwtnl->cmd.prim_ib[hwtnl->cmd.prim_count], ib);
379    hwtnl->cmd.prim_count++;
380
381    return ret;
382 }