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