1 /* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
4 * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * Rob Clark <robclark@freedesktop.org>
29 #include "pipe/p_state.h"
30 #include "util/u_string.h"
31 #include "util/u_memory.h"
32 #include "util/u_prim.h"
34 #include "freedreno_vbo.h"
35 #include "freedreno_context.h"
36 #include "freedreno_state.h"
37 #include "freedreno_zsa.h"
38 #include "freedreno_resource.h"
39 #include "freedreno_util.h"
43 fd_vertex_state_create(struct pipe_context
*pctx
, unsigned num_elements
,
44 const struct pipe_vertex_element
*elements
)
46 struct fd_vertex_stateobj
*so
= CALLOC_STRUCT(fd_vertex_stateobj
);
51 memcpy(so
->pipe
, elements
, sizeof(*elements
) * num_elements
);
52 so
->num_elements
= num_elements
;
58 fd_vertex_state_delete(struct pipe_context
*pctx
, void *hwcso
)
64 fd_vertex_state_bind(struct pipe_context
*pctx
, void *hwcso
)
66 struct fd_context
*ctx
= fd_context(pctx
);
68 ctx
->dirty
|= FD_DIRTY_VTXSTATE
;
72 emit_cacheflush(struct fd_ringbuffer
*ring
)
76 for (i
= 0; i
< 12; i
++) {
77 OUT_PKT3(ring
, CP_EVENT_WRITE
, 1);
78 OUT_RING(ring
, CACHE_FLUSH
);
82 static enum pc_di_primtype
83 mode2primtype(unsigned mode
)
86 case PIPE_PRIM_POINTS
: return DI_PT_POINTLIST
;
87 case PIPE_PRIM_LINES
: return DI_PT_LINELIST
;
88 case PIPE_PRIM_LINE_STRIP
: return DI_PT_LINESTRIP
;
89 case PIPE_PRIM_TRIANGLES
: return DI_PT_TRILIST
;
90 case PIPE_PRIM_TRIANGLE_STRIP
: return DI_PT_TRISTRIP
;
91 case PIPE_PRIM_TRIANGLE_FAN
: return DI_PT_TRIFAN
;
92 case PIPE_PRIM_QUADS
: return DI_PT_QUADLIST
;
93 case PIPE_PRIM_QUAD_STRIP
: return DI_PT_QUADSTRIP
;
94 case PIPE_PRIM_POLYGON
: return DI_PT_POLYGON
;
96 DBG("unsupported mode: (%s) %d", u_prim_name(mode
), mode
);
101 static enum pc_di_index_size
102 size2indextype(unsigned index_size
)
104 switch (index_size
) {
105 case 1: return INDEX_SIZE_8_BIT
;
106 case 2: return INDEX_SIZE_16_BIT
;
107 case 4: return INDEX_SIZE_32_BIT
;
109 DBG("unsupported index size: %d", index_size
);
111 return INDEX_SIZE_IGN
;
115 emit_vertexbufs(struct fd_context
*ctx
, unsigned count
)
117 struct fd_vertex_stateobj
*vtx
= ctx
->vtx
;
118 struct fd_vertexbuf_stateobj
*vertexbuf
= &ctx
->vertexbuf
;
119 struct fd_vertex_buf bufs
[PIPE_MAX_ATTRIBS
];
122 if (!vtx
->num_elements
)
125 for (i
= 0; i
< vtx
->num_elements
; i
++) {
126 struct pipe_vertex_element
*elem
= &vtx
->pipe
[i
];
127 struct pipe_vertex_buffer
*vb
=
128 &vertexbuf
->vb
[elem
->vertex_buffer_index
];
129 bufs
[i
].offset
= vb
->buffer_offset
;
130 bufs
[i
].size
= count
* vb
->stride
;
131 bufs
[i
].prsc
= vb
->buffer
;
134 // NOTE I believe the 0x78 (or 0x9c in solid_vp) relates to the
135 // CONST(20,0) (or CONST(26,0) in soliv_vp)
137 fd_emit_vertex_bufs(ctx
->ring
, 0x78, bufs
, vtx
->num_elements
);
141 fd_draw_vbo(struct pipe_context
*pctx
, const struct pipe_draw_info
*info
)
143 struct fd_context
*ctx
= fd_context(pctx
);
144 struct pipe_framebuffer_state
*fb
= &ctx
->framebuffer
;
145 struct fd_ringbuffer
*ring
= ctx
->ring
;
146 struct fd_bo
*idx_bo
= NULL
;
147 enum pc_di_index_size idx_type
= INDEX_SIZE_IGN
;
148 enum pc_di_src_sel src_sel
;
149 uint32_t idx_size
, idx_offset
;
152 /* if we supported transform feedback, we'd have to disable this: */
153 if (((ctx
->scissor
.maxx
- ctx
->scissor
.minx
) *
154 (ctx
->scissor
.maxy
- ctx
->scissor
.miny
)) == 0) {
158 ctx
->needs_flush
= true;
161 struct pipe_index_buffer
*idx
= &ctx
->indexbuf
;
163 assert(!idx
->user_buffer
);
165 idx_bo
= fd_resource(idx
->buffer
)->bo
;
166 idx_type
= size2indextype(idx
->index_size
);
167 idx_size
= idx
->index_size
* info
->count
;
168 idx_offset
= idx
->offset
;
169 src_sel
= DI_SRC_SEL_DMA
;
172 idx_type
= INDEX_SIZE_IGN
;
175 src_sel
= DI_SRC_SEL_AUTO_INDEX
;
178 fd_resource(fb
->cbufs
[0]->texture
)->dirty
= true;
180 /* figure out the buffers we need: */
181 buffers
= FD_BUFFER_COLOR
;
182 if (fd_depth_enabled(ctx
->zsa
)) {
183 buffers
|= FD_BUFFER_DEPTH
;
184 fd_resource(fb
->zsbuf
->texture
)->dirty
= true;
186 if (fd_stencil_enabled(ctx
->zsa
)) {
187 buffers
|= FD_BUFFER_STENCIL
;
188 fd_resource(fb
->zsbuf
->texture
)->dirty
= true;
191 /* any buffers that haven't been cleared, we need to restore: */
192 ctx
->restore
|= buffers
& (FD_BUFFER_ALL
& ~ctx
->cleared
);
193 /* and any buffers used, need to be resolved: */
194 ctx
->resolve
|= buffers
;
196 if (ctx
->dirty
& FD_DIRTY_VTXBUF
)
197 emit_vertexbufs(ctx
, info
->count
);
199 fd_state_emit(pctx
, ctx
->dirty
);
201 OUT_PKT3(ring
, CP_SET_CONSTANT
, 2);
202 OUT_RING(ring
, CP_REG(REG_A2XX_VGT_INDX_OFFSET
));
203 OUT_RING(ring
, info
->start
);
205 OUT_PKT3(ring
, CP_SET_CONSTANT
, 2);
206 OUT_RING(ring
, CP_REG(REG_A2XX_VGT_VERTEX_REUSE_BLOCK_CNTL
));
207 OUT_RING(ring
, 0x0000003b);
209 OUT_PKT0(ring
, REG_A2XX_TC_CNTL_STATUS
, 1);
210 OUT_RING(ring
, A2XX_TC_CNTL_STATUS_L2_INVALIDATE
);
212 OUT_PKT3(ring
, CP_WAIT_FOR_IDLE
, 1);
213 OUT_RING(ring
, 0x0000000);
215 OUT_PKT3(ring
, CP_DRAW_INDX
, info
->indexed
? 5 : 3);
216 OUT_RING(ring
, 0x00000000); /* viz query info. */
217 OUT_RING(ring
, DRAW(mode2primtype(info
->mode
),
218 src_sel
, idx_type
, IGNORE_VISIBILITY
));
219 OUT_RING(ring
, info
->count
); /* NumIndices */
221 OUT_RELOC(ring
, idx_bo
, idx_offset
, 0);
222 OUT_RING (ring
, idx_size
);
225 OUT_PKT3(ring
, CP_SET_CONSTANT
, 2);
226 OUT_RING(ring
, CP_REG(REG_A2XX_UNKNOWN_2010
));
227 OUT_RING(ring
, 0x00000000);
229 emit_cacheflush(ring
);
233 fd_vbo_init(struct pipe_context
*pctx
)
235 pctx
->create_vertex_elements_state
= fd_vertex_state_create
;
236 pctx
->delete_vertex_elements_state
= fd_vertex_state_delete
;
237 pctx
->bind_vertex_elements_state
= fd_vertex_state_bind
;
238 pctx
->draw_vbo
= fd_draw_vbo
;