1 /**********************************************************
2 * Copyright 2008-2009 VMware, Inc. All rights reserved.
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:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
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
24 **********************************************************/
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"
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"
46 svga_hwtnl_create(struct svga_context *svga)
48 struct svga_hwtnl *hwtnl = CALLOC_STRUCT(svga_hwtnl);
54 hwtnl->cmd.swc = svga->swc;
64 svga_hwtnl_destroy(struct svga_hwtnl *hwtnl)
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);
74 for (i = 0; i < hwtnl->cmd.vdecl_count; i++)
75 pipe_resource_reference(&hwtnl->cmd.vdecl_vb[i], NULL);
77 for (i = 0; i < hwtnl->cmd.prim_count; i++)
78 pipe_resource_reference(&hwtnl->cmd.prim_ib[i], NULL);
85 svga_hwtnl_set_flatshade(struct svga_hwtnl *hwtnl,
86 boolean flatshade, boolean flatshade_first)
88 hwtnl->hw_pv = PV_FIRST;
89 hwtnl->api_pv = (flatshade && !flatshade_first) ? PV_LAST : PV_FIRST;
94 svga_hwtnl_set_unfilled(struct svga_hwtnl *hwtnl, unsigned mode)
96 hwtnl->api_fillmode = mode;
101 svga_hwtnl_reset_vdecl(struct svga_hwtnl *hwtnl, unsigned count)
105 assert(hwtnl->cmd.prim_count == 0);
107 for (i = count; i < hwtnl->cmd.vdecl_count; i++) {
108 pipe_resource_reference(&hwtnl->cmd.vdecl_vb[i], NULL);
111 hwtnl->cmd.vdecl_count = count;
116 svga_hwtnl_vdecl(struct svga_hwtnl *hwtnl,
118 const SVGA3dVertexDecl * decl, struct pipe_resource *vb)
120 assert(hwtnl->cmd.prim_count == 0);
122 assert(i < hwtnl->cmd.vdecl_count);
124 hwtnl->cmd.vdecl[i] = *decl;
126 pipe_resource_reference(&hwtnl->cmd.vdecl_vb[i], vb);
131 * Determine whether the specified buffer is referred in the primitive queue,
132 * for which no commands have been written yet.
135 svga_hwtnl_is_buffer_referred(struct svga_hwtnl *hwtnl,
136 struct pipe_resource *buffer)
140 if (svga_buffer_is_user_buffer(buffer)) {
144 if (!hwtnl->cmd.prim_count) {
148 for (i = 0; i < hwtnl->cmd.vdecl_count; ++i) {
149 if (hwtnl->cmd.vdecl_vb[i] == buffer) {
154 for (i = 0; i < hwtnl->cmd.prim_count; ++i) {
155 if (hwtnl->cmd.prim_ib[i] == buffer) {
165 svga_hwtnl_flush(struct svga_hwtnl *hwtnl)
167 struct svga_winsys_context *swc = hwtnl->cmd.swc;
168 struct svga_context *svga = hwtnl->svga;
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;
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]);
183 return PIPE_ERROR_OUT_OF_MEMORY;
185 vb_handle[i] = handle;
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]);
193 return PIPE_ERROR_OUT_OF_MEMORY;
199 ib_handle[i] = handle;
202 if (svga->rebind.rendertargets) {
203 ret = svga_reemit_framebuffer_bindings(svga);
204 if (ret != PIPE_OK) {
209 if (svga->rebind.texture_samplers) {
210 ret = svga_reemit_tss_bindings(svga);
211 if (ret != PIPE_OK) {
216 if (svga->rebind.vs) {
217 ret = svga_reemit_vs_bindings(svga);
218 if (ret != PIPE_OK) {
223 if (svga->rebind.fs) {
224 ret = svga_reemit_fs_bindings(svga);
225 if (ret != PIPE_OK) {
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);
235 ret = SVGA3D_BeginDrawPrimitives(swc, &vdecl, hwtnl->cmd.vdecl_count,
236 &prim, hwtnl->cmd.prim_count);
240 memcpy(vdecl, hwtnl->cmd.vdecl,
241 hwtnl->cmd.vdecl_count * sizeof hwtnl->cmd.vdecl[0]);
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.
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;
253 vdecl[i].rangeHint.first = 0;
254 vdecl[i].rangeHint.last = 0;
257 swc->surface_relocation(swc, &vdecl[i].array.surfaceId, NULL,
258 vb_handle[i], SVGA_RELOC_READ);
261 memcpy(prim, hwtnl->cmd.prim,
262 hwtnl->cmd.prim_count * sizeof hwtnl->cmd.prim[0]);
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);
270 SVGA_FIFOCommitAll(swc);
271 hwtnl->cmd.prim_count = 0;
279 svga_hwtnl_set_index_bias(struct svga_hwtnl *hwtnl, int index_bias)
281 hwtnl->index_bias = index_bias;
286 /***********************************************************************
287 * Internal functions:
291 svga_hwtnl_prim(struct svga_hwtnl *hwtnl,
292 const SVGA3dPrimitiveRange * range,
294 unsigned max_index, struct pipe_resource *ib)
296 enum pipe_error ret = PIPE_OK;
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;
311 assert(offset < size);
312 assert(min_index <= max_index);
314 switch (hwtnl->cmd.vdecl[i].identity.type) {
315 case SVGA3D_DECLTYPE_FLOAT1:
318 case SVGA3D_DECLTYPE_FLOAT2:
321 case SVGA3D_DECLTYPE_FLOAT3:
324 case SVGA3D_DECLTYPE_FLOAT4:
327 case SVGA3D_DECLTYPE_D3DCOLOR:
330 case SVGA3D_DECLTYPE_UBYTE4:
333 case SVGA3D_DECLTYPE_SHORT2:
336 case SVGA3D_DECLTYPE_SHORT4:
339 case SVGA3D_DECLTYPE_UBYTE4N:
342 case SVGA3D_DECLTYPE_SHORT2N:
345 case SVGA3D_DECLTYPE_SHORT4N:
348 case SVGA3D_DECLTYPE_USHORT2N:
351 case SVGA3D_DECLTYPE_USHORT4N:
354 case SVGA3D_DECLTYPE_UDEC3:
357 case SVGA3D_DECLTYPE_DEC3N:
360 case SVGA3D_DECLTYPE_FLOAT16_2:
363 case SVGA3D_DECLTYPE_FLOAT16_4:
372 if (index_bias >= 0) {
373 assert(offset + index_bias * stride + width <= size);
377 * min_index/max_index are merely conservative guesses, so we can't
378 * make buffer overflow detection based on their values.
382 assert(range->indexWidth == range->indexArray.stride);
385 unsigned size = ib->width0;
386 unsigned offset = range->indexArray.offset;
387 unsigned stride = range->indexArray.stride;
391 assert(offset < size);
394 switch (range->primType) {
395 case SVGA3D_PRIMITIVE_POINTLIST:
396 count = range->primitiveCount;
398 case SVGA3D_PRIMITIVE_LINELIST:
399 count = range->primitiveCount * 2;
401 case SVGA3D_PRIMITIVE_LINESTRIP:
402 count = range->primitiveCount + 1;
404 case SVGA3D_PRIMITIVE_TRIANGLELIST:
405 count = range->primitiveCount * 3;
407 case SVGA3D_PRIMITIVE_TRIANGLESTRIP:
408 count = range->primitiveCount + 2;
410 case SVGA3D_PRIMITIVE_TRIANGLEFAN:
411 count = range->primitiveCount + 2;
419 assert(offset + count * stride <= size);
424 if (hwtnl->cmd.prim_count + 1 >= QSZ) {
425 ret = svga_hwtnl_flush(hwtnl);
430 /* min/max indices are relative to bias */
431 hwtnl->cmd.min_index[hwtnl->cmd.prim_count] = min_index;
432 hwtnl->cmd.max_index[hwtnl->cmd.prim_count] = max_index;
434 hwtnl->cmd.prim[hwtnl->cmd.prim_count] = *range;
435 hwtnl->cmd.prim[hwtnl->cmd.prim_count].indexBias += hwtnl->index_bias;
437 pipe_resource_reference(&hwtnl->cmd.prim_ib[hwtnl->cmd.prim_count], ib);
438 hwtnl->cmd.prim_count++;