freedreno/ir3: consider instruction neighbors in cp
[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 if (svga->rebind.vs) {
217 ret = svga_reemit_vs_bindings(svga);
218 if (ret != PIPE_OK) {
219 return ret;
220 }
221 }
222
223 if (svga->rebind.fs) {
224 ret = svga_reemit_fs_bindings(svga);
225 if (ret != PIPE_OK) {
226 return ret;
227 }
228 }
229
230 SVGA_DBG(DEBUG_DMA, "draw to sid %p, %d prims\n",
231 svga->curr.framebuffer.cbufs[0] ?
232 svga_surface(svga->curr.framebuffer.cbufs[0])->handle : NULL,
233 hwtnl->cmd.prim_count);
234
235 ret = SVGA3D_BeginDrawPrimitives(swc, &vdecl, hwtnl->cmd.vdecl_count,
236 &prim, hwtnl->cmd.prim_count);
237 if (ret != PIPE_OK)
238 return ret;
239
240 memcpy(vdecl, hwtnl->cmd.vdecl,
241 hwtnl->cmd.vdecl_count * sizeof hwtnl->cmd.vdecl[0]);
242
243 for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
244 /* Given rangeHint is considered to be relative to indexBias, and
245 * indexBias varies per primitive, we cannot accurately supply an
246 * rangeHint when emitting more than one primitive per draw command.
247 */
248 if (hwtnl->cmd.prim_count == 1) {
249 vdecl[i].rangeHint.first = hwtnl->cmd.min_index[0];
250 vdecl[i].rangeHint.last = hwtnl->cmd.max_index[0] + 1;
251 }
252 else {
253 vdecl[i].rangeHint.first = 0;
254 vdecl[i].rangeHint.last = 0;
255 }
256
257 swc->surface_relocation(swc, &vdecl[i].array.surfaceId, NULL,
258 vb_handle[i], SVGA_RELOC_READ);
259 }
260
261 memcpy(prim, hwtnl->cmd.prim,
262 hwtnl->cmd.prim_count * sizeof hwtnl->cmd.prim[0]);
263
264 for (i = 0; i < hwtnl->cmd.prim_count; i++) {
265 swc->surface_relocation(swc, &prim[i].indexArray.surfaceId, NULL,
266 ib_handle[i], SVGA_RELOC_READ);
267 pipe_resource_reference(&hwtnl->cmd.prim_ib[i], NULL);
268 }
269
270 SVGA_FIFOCommitAll(swc);
271 hwtnl->cmd.prim_count = 0;
272 }
273
274 return PIPE_OK;
275 }
276
277
278 void
279 svga_hwtnl_set_index_bias(struct svga_hwtnl *hwtnl, int index_bias)
280 {
281 hwtnl->index_bias = index_bias;
282 }
283
284
285
286 /***********************************************************************
287 * Internal functions:
288 */
289
290 /**
291 * For debugging only.
292 */
293 static void
294 check_draw_params(struct svga_hwtnl *hwtnl,
295 const SVGA3dPrimitiveRange *range,
296 unsigned min_index, unsigned max_index,
297 struct pipe_resource *ib)
298 {
299 unsigned i;
300
301 for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
302 struct pipe_resource *vb = hwtnl->cmd.vdecl_vb[i];
303 unsigned size = vb ? vb->width0 : 0;
304 unsigned offset = hwtnl->cmd.vdecl[i].array.offset;
305 unsigned stride = hwtnl->cmd.vdecl[i].array.stride;
306 int index_bias = (int) range->indexBias + hwtnl->index_bias;
307 unsigned width;
308
309 assert(vb);
310 assert(size);
311 assert(offset < size);
312 assert(min_index <= max_index);
313
314 switch (hwtnl->cmd.vdecl[i].identity.type) {
315 case SVGA3D_DECLTYPE_FLOAT1:
316 width = 4;
317 break;
318 case SVGA3D_DECLTYPE_FLOAT2:
319 width = 4 * 2;
320 break;
321 case SVGA3D_DECLTYPE_FLOAT3:
322 width = 4 * 3;
323 break;
324 case SVGA3D_DECLTYPE_FLOAT4:
325 width = 4 * 4;
326 break;
327 case SVGA3D_DECLTYPE_D3DCOLOR:
328 width = 4;
329 break;
330 case SVGA3D_DECLTYPE_UBYTE4:
331 width = 1 * 4;
332 break;
333 case SVGA3D_DECLTYPE_SHORT2:
334 width = 2 * 2;
335 break;
336 case SVGA3D_DECLTYPE_SHORT4:
337 width = 2 * 4;
338 break;
339 case SVGA3D_DECLTYPE_UBYTE4N:
340 width = 1 * 4;
341 break;
342 case SVGA3D_DECLTYPE_SHORT2N:
343 width = 2 * 2;
344 break;
345 case SVGA3D_DECLTYPE_SHORT4N:
346 width = 2 * 4;
347 break;
348 case SVGA3D_DECLTYPE_USHORT2N:
349 width = 2 * 2;
350 break;
351 case SVGA3D_DECLTYPE_USHORT4N:
352 width = 2 * 4;
353 break;
354 case SVGA3D_DECLTYPE_UDEC3:
355 width = 4;
356 break;
357 case SVGA3D_DECLTYPE_DEC3N:
358 width = 4;
359 break;
360 case SVGA3D_DECLTYPE_FLOAT16_2:
361 width = 2 * 2;
362 break;
363 case SVGA3D_DECLTYPE_FLOAT16_4:
364 width = 2 * 4;
365 break;
366 default:
367 assert(0);
368 width = 0;
369 break;
370 }
371
372 if (index_bias >= 0) {
373 assert(offset + index_bias * stride + width <= size);
374 }
375
376 /*
377 * min_index/max_index are merely conservative guesses, so we can't
378 * make buffer overflow detection based on their values.
379 */
380 }
381
382 assert(range->indexWidth == range->indexArray.stride);
383
384 if (ib) {
385 unsigned size = ib->width0;
386 unsigned offset = range->indexArray.offset;
387 unsigned stride = range->indexArray.stride;
388 unsigned count;
389
390 assert(size);
391 assert(offset < size);
392 assert(stride);
393
394 switch (range->primType) {
395 case SVGA3D_PRIMITIVE_POINTLIST:
396 count = range->primitiveCount;
397 break;
398 case SVGA3D_PRIMITIVE_LINELIST:
399 count = range->primitiveCount * 2;
400 break;
401 case SVGA3D_PRIMITIVE_LINESTRIP:
402 count = range->primitiveCount + 1;
403 break;
404 case SVGA3D_PRIMITIVE_TRIANGLELIST:
405 count = range->primitiveCount * 3;
406 break;
407 case SVGA3D_PRIMITIVE_TRIANGLESTRIP:
408 count = range->primitiveCount + 2;
409 break;
410 case SVGA3D_PRIMITIVE_TRIANGLEFAN:
411 count = range->primitiveCount + 2;
412 break;
413 default:
414 assert(0);
415 count = 0;
416 break;
417 }
418
419 assert(offset + count * stride <= size);
420 }
421 }
422
423
424 enum pipe_error
425 svga_hwtnl_prim(struct svga_hwtnl *hwtnl,
426 const SVGA3dPrimitiveRange * range,
427 unsigned min_index,
428 unsigned max_index, struct pipe_resource *ib)
429 {
430 enum pipe_error ret = PIPE_OK;
431
432 #ifdef DEBUG
433 check_draw_params(hwtnl, range, min_index, max_index, ib);
434 #endif
435
436 if (hwtnl->cmd.prim_count + 1 >= QSZ) {
437 ret = svga_hwtnl_flush(hwtnl);
438 if (ret != PIPE_OK)
439 return ret;
440 }
441
442 /* min/max indices are relative to bias */
443 hwtnl->cmd.min_index[hwtnl->cmd.prim_count] = min_index;
444 hwtnl->cmd.max_index[hwtnl->cmd.prim_count] = max_index;
445
446 hwtnl->cmd.prim[hwtnl->cmd.prim_count] = *range;
447 hwtnl->cmd.prim[hwtnl->cmd.prim_count].indexBias += hwtnl->index_bias;
448
449 pipe_resource_reference(&hwtnl->cmd.prim_ib[hwtnl->cmd.prim_count], ib);
450 hwtnl->cmd.prim_count++;
451
452 return ret;
453 }