6a066a63730530474dde996266ed36e32fbb36f7
[mesa.git] / src / gallium / drivers / freedreno / a2xx / fd2_gmem.c
1 /*
2 * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors:
24 * Rob Clark <robclark@freedesktop.org>
25 */
26
27 #include "pipe/p_state.h"
28 #include "util/u_string.h"
29 #include "util/u_memory.h"
30 #include "util/u_inlines.h"
31
32 #include "freedreno_draw.h"
33 #include "freedreno_state.h"
34 #include "freedreno_resource.h"
35
36 #include "fd2_gmem.h"
37 #include "fd2_context.h"
38 #include "fd2_emit.h"
39 #include "fd2_program.h"
40 #include "fd2_util.h"
41 #include "fd2_zsa.h"
42 #include "instr-a2xx.h"
43
44 static uint32_t fmt2swap(enum pipe_format format)
45 {
46 switch (format) {
47 case PIPE_FORMAT_B8G8R8A8_UNORM:
48 case PIPE_FORMAT_B8G8R8X8_UNORM:
49 case PIPE_FORMAT_B5G6R5_UNORM:
50 case PIPE_FORMAT_B5G5R5A1_UNORM:
51 case PIPE_FORMAT_B5G5R5X1_UNORM:
52 case PIPE_FORMAT_B4G4R4A4_UNORM:
53 case PIPE_FORMAT_B4G4R4X4_UNORM:
54 /* TODO probably some more.. */
55 return 1;
56 default:
57 return 0;
58 }
59 }
60
61 /* transfer from gmem to system memory (ie. normal RAM) */
62
63 static void
64 emit_gmem2mem_surf(struct fd_batch *batch, uint32_t base,
65 struct pipe_surface *psurf)
66 {
67 struct fd_ringbuffer *ring = batch->gmem;
68 struct fd_resource *rsc = fd_resource(psurf->texture);
69 uint32_t swap = fmt2swap(psurf->format);
70 struct fd_resource_slice *slice =
71 fd_resource_slice(rsc, psurf->u.tex.level);
72 uint32_t offset =
73 fd_resource_offset(rsc, psurf->u.tex.level, psurf->u.tex.first_layer);
74
75 assert((slice->pitch & 31) == 0);
76 assert((offset & 0xfff) == 0);
77
78 if (!rsc->valid)
79 return;
80
81 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
82 OUT_RING(ring, CP_REG(REG_A2XX_RB_COLOR_INFO));
83 OUT_RING(ring, A2XX_RB_COLOR_INFO_SWAP(swap) |
84 A2XX_RB_COLOR_INFO_BASE(base) |
85 A2XX_RB_COLOR_INFO_FORMAT(fd2_pipe2color(psurf->format)));
86
87 OUT_PKT3(ring, CP_SET_CONSTANT, 5);
88 OUT_RING(ring, CP_REG(REG_A2XX_RB_COPY_CONTROL));
89 OUT_RING(ring, 0x00000000); /* RB_COPY_CONTROL */
90 OUT_RELOCW(ring, rsc->bo, offset, 0, 0); /* RB_COPY_DEST_BASE */
91 OUT_RING(ring, slice->pitch >> 5); /* RB_COPY_DEST_PITCH */
92 OUT_RING(ring, /* RB_COPY_DEST_INFO */
93 A2XX_RB_COPY_DEST_INFO_FORMAT(fd2_pipe2color(psurf->format)) |
94 A2XX_RB_COPY_DEST_INFO_LINEAR |
95 A2XX_RB_COPY_DEST_INFO_SWAP(swap) |
96 A2XX_RB_COPY_DEST_INFO_WRITE_RED |
97 A2XX_RB_COPY_DEST_INFO_WRITE_GREEN |
98 A2XX_RB_COPY_DEST_INFO_WRITE_BLUE |
99 A2XX_RB_COPY_DEST_INFO_WRITE_ALPHA);
100
101 if (!is_a20x(batch->ctx->screen)) {
102 OUT_WFI (ring);
103
104 OUT_PKT3(ring, CP_SET_CONSTANT, 3);
105 OUT_RING(ring, CP_REG(REG_A2XX_VGT_MAX_VTX_INDX));
106 OUT_RING(ring, 3); /* VGT_MAX_VTX_INDX */
107 OUT_RING(ring, 0); /* VGT_MIN_VTX_INDX */
108 }
109
110 fd_draw(batch, ring, DI_PT_RECTLIST, IGNORE_VISIBILITY,
111 DI_SRC_SEL_AUTO_INDEX, 3, 0, INDEX_SIZE_IGN, 0, 0, NULL);
112 }
113
114 static void
115 fd2_emit_tile_gmem2mem(struct fd_batch *batch, struct fd_tile *tile)
116 {
117 struct fd_context *ctx = batch->ctx;
118 struct fd2_context *fd2_ctx = fd2_context(ctx);
119 struct fd_gmem_stateobj *gmem = &ctx->gmem;
120 struct fd_ringbuffer *ring = batch->gmem;
121 struct pipe_framebuffer_state *pfb = &batch->framebuffer;
122
123 fd2_emit_vertex_bufs(ring, 0x9c, (struct fd2_vertex_buf[]) {
124 { .prsc = fd2_ctx->solid_vertexbuf, .size = 36 },
125 }, 1);
126
127 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
128 OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_WINDOW_OFFSET));
129 OUT_RING(ring, 0x00000000); /* PA_SC_WINDOW_OFFSET */
130
131 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
132 OUT_RING(ring, CP_REG(REG_A2XX_VGT_INDX_OFFSET));
133 OUT_RING(ring, 0);
134
135 if (!is_a20x(ctx->screen)) {
136 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
137 OUT_RING(ring, CP_REG(REG_A2XX_VGT_VERTEX_REUSE_BLOCK_CNTL));
138 OUT_RING(ring, 0x0000028f);
139 }
140
141 fd2_program_emit(ctx, ring, &ctx->solid_prog);
142
143 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
144 OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_AA_MASK));
145 OUT_RING(ring, 0x0000ffff);
146
147 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
148 OUT_RING(ring, CP_REG(REG_A2XX_RB_DEPTHCONTROL));
149 OUT_RING(ring, A2XX_RB_DEPTHCONTROL_EARLY_Z_ENABLE);
150
151 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
152 OUT_RING(ring, CP_REG(REG_A2XX_PA_SU_SC_MODE_CNTL));
153 OUT_RING(ring, A2XX_PA_SU_SC_MODE_CNTL_PROVOKING_VTX_LAST | /* PA_SU_SC_MODE_CNTL */
154 A2XX_PA_SU_SC_MODE_CNTL_FRONT_PTYPE(PC_DRAW_TRIANGLES) |
155 A2XX_PA_SU_SC_MODE_CNTL_BACK_PTYPE(PC_DRAW_TRIANGLES));
156
157 OUT_PKT3(ring, CP_SET_CONSTANT, 3);
158 OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_WINDOW_SCISSOR_TL));
159 OUT_RING(ring, xy2d(0, 0)); /* PA_SC_WINDOW_SCISSOR_TL */
160 OUT_RING(ring, xy2d(pfb->width, pfb->height)); /* PA_SC_WINDOW_SCISSOR_BR */
161
162 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
163 OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_CLIP_CNTL));
164 OUT_RING(ring, 0x00000000);
165
166 OUT_PKT3(ring, CP_SET_CONSTANT, 5);
167 OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_VPORT_XSCALE));
168 OUT_RING(ring, fui((float) tile->bin_w / 2.0)); /* XSCALE */
169 OUT_RING(ring, fui((float) tile->bin_w / 2.0)); /* XOFFSET */
170 OUT_RING(ring, fui((float) tile->bin_h / 2.0)); /* YSCALE */
171 OUT_RING(ring, fui((float) tile->bin_h / 2.0)); /* YOFFSET */
172
173 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
174 OUT_RING(ring, CP_REG(REG_A2XX_RB_MODECONTROL));
175 OUT_RING(ring, A2XX_RB_MODECONTROL_EDRAM_MODE(EDRAM_COPY));
176
177 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
178 OUT_RING(ring, CP_REG(REG_A2XX_RB_COPY_DEST_OFFSET));
179 OUT_RING(ring, A2XX_RB_COPY_DEST_OFFSET_X(tile->xoff) |
180 A2XX_RB_COPY_DEST_OFFSET_Y(tile->yoff));
181
182 if (batch->resolve & (FD_BUFFER_DEPTH | FD_BUFFER_STENCIL))
183 emit_gmem2mem_surf(batch, gmem->zsbuf_base[0], pfb->zsbuf);
184
185 if (batch->resolve & FD_BUFFER_COLOR)
186 emit_gmem2mem_surf(batch, gmem->cbuf_base[0], pfb->cbufs[0]);
187
188 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
189 OUT_RING(ring, CP_REG(REG_A2XX_RB_MODECONTROL));
190 OUT_RING(ring, A2XX_RB_MODECONTROL_EDRAM_MODE(COLOR_DEPTH));
191
192 if (!is_a20x(ctx->screen)) {
193 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
194 OUT_RING(ring, CP_REG(REG_A2XX_VGT_VERTEX_REUSE_BLOCK_CNTL));
195 OUT_RING(ring, 0x0000003b);
196 }
197 }
198
199 /* transfer from system memory to gmem */
200
201 static void
202 emit_mem2gmem_surf(struct fd_batch *batch, uint32_t base,
203 struct pipe_surface *psurf)
204 {
205 struct fd_ringbuffer *ring = batch->gmem;
206 struct fd_resource *rsc = fd_resource(psurf->texture);
207 struct fd_resource_slice *slice =
208 fd_resource_slice(rsc, psurf->u.tex.level);
209 uint32_t offset =
210 fd_resource_offset(rsc, psurf->u.tex.level, psurf->u.tex.first_layer);
211 uint32_t swiz;
212
213 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
214 OUT_RING(ring, CP_REG(REG_A2XX_RB_COLOR_INFO));
215 OUT_RING(ring, A2XX_RB_COLOR_INFO_SWAP(fmt2swap(psurf->format)) |
216 A2XX_RB_COLOR_INFO_BASE(base) |
217 A2XX_RB_COLOR_INFO_FORMAT(fd2_pipe2color(psurf->format)));
218
219 swiz = fd2_tex_swiz(psurf->format, PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y,
220 PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W);
221
222 /* emit fb as a texture: */
223 OUT_PKT3(ring, CP_SET_CONSTANT, 7);
224 OUT_RING(ring, 0x00010000);
225 OUT_RING(ring, A2XX_SQ_TEX_0_CLAMP_X(SQ_TEX_WRAP) |
226 A2XX_SQ_TEX_0_CLAMP_Y(SQ_TEX_WRAP) |
227 A2XX_SQ_TEX_0_CLAMP_Z(SQ_TEX_WRAP) |
228 A2XX_SQ_TEX_0_PITCH(slice->pitch));
229 OUT_RELOC(ring, rsc->bo, offset,
230 fd2_pipe2surface(psurf->format) |
231 A2XX_SQ_TEX_1_CLAMP_POLICY(SQ_TEX_CLAMP_POLICY_OGL), 0);
232 OUT_RING(ring, A2XX_SQ_TEX_2_WIDTH(psurf->width - 1) |
233 A2XX_SQ_TEX_2_HEIGHT(psurf->height - 1));
234 OUT_RING(ring, A2XX_SQ_TEX_3_MIP_FILTER(SQ_TEX_FILTER_BASEMAP) |
235 swiz |
236 A2XX_SQ_TEX_3_XY_MAG_FILTER(SQ_TEX_FILTER_POINT) |
237 A2XX_SQ_TEX_3_XY_MIN_FILTER(SQ_TEX_FILTER_POINT));
238 OUT_RING(ring, 0x00000000);
239 OUT_RING(ring, A2XX_SQ_TEX_5_DIMENSION(SQ_TEX_DIMENSION_2D));
240
241 if (!is_a20x(batch->ctx->screen)) {
242 OUT_PKT3(ring, CP_SET_CONSTANT, 3);
243 OUT_RING(ring, CP_REG(REG_A2XX_VGT_MAX_VTX_INDX));
244 OUT_RING(ring, 3); /* VGT_MAX_VTX_INDX */
245 OUT_RING(ring, 0); /* VGT_MIN_VTX_INDX */
246 }
247
248 fd_draw(batch, ring, DI_PT_RECTLIST, IGNORE_VISIBILITY,
249 DI_SRC_SEL_AUTO_INDEX, 3, 0, INDEX_SIZE_IGN, 0, 0, NULL);
250 }
251
252 static void
253 fd2_emit_tile_mem2gmem(struct fd_batch *batch, struct fd_tile *tile)
254 {
255 struct fd_context *ctx = batch->ctx;
256 struct fd2_context *fd2_ctx = fd2_context(ctx);
257 struct fd_gmem_stateobj *gmem = &ctx->gmem;
258 struct fd_ringbuffer *ring = batch->gmem;
259 struct pipe_framebuffer_state *pfb = &batch->framebuffer;
260 unsigned bin_w = tile->bin_w;
261 unsigned bin_h = tile->bin_h;
262 float x0, y0, x1, y1;
263
264 fd2_emit_vertex_bufs(ring, 0x9c, (struct fd2_vertex_buf[]) {
265 { .prsc = fd2_ctx->solid_vertexbuf, .size = 36, },
266 { .prsc = fd2_ctx->solid_vertexbuf, .size = 24, .offset = 36 },
267 }, 2);
268
269 /* write texture coordinates to vertexbuf: */
270 x0 = ((float)tile->xoff) / ((float)pfb->width);
271 x1 = ((float)tile->xoff + bin_w) / ((float)pfb->width);
272 y0 = ((float)tile->yoff) / ((float)pfb->height);
273 y1 = ((float)tile->yoff + bin_h) / ((float)pfb->height);
274 OUT_PKT3(ring, CP_MEM_WRITE, 9);
275 OUT_RELOC(ring, fd_resource(fd2_ctx->solid_vertexbuf)->bo, 0x60, 0, 0);
276 OUT_RING(ring, fui(x0));
277 OUT_RING(ring, fui(y0));
278 OUT_RING(ring, fui(x1));
279 OUT_RING(ring, fui(y0));
280 OUT_RING(ring, fui(x0));
281 OUT_RING(ring, fui(y1));
282 OUT_RING(ring, fui(x1));
283 OUT_RING(ring, fui(y1));
284
285 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
286 OUT_RING(ring, CP_REG(REG_A2XX_VGT_INDX_OFFSET));
287 OUT_RING(ring, 0);
288
289 fd2_program_emit(ctx, ring, &ctx->blit_prog[0]);
290
291 OUT_PKT0(ring, REG_A2XX_TC_CNTL_STATUS, 1);
292 OUT_RING(ring, A2XX_TC_CNTL_STATUS_L2_INVALIDATE);
293
294 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
295 OUT_RING(ring, CP_REG(REG_A2XX_RB_DEPTHCONTROL));
296 OUT_RING(ring, A2XX_RB_DEPTHCONTROL_EARLY_Z_ENABLE);
297
298 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
299 OUT_RING(ring, CP_REG(REG_A2XX_PA_SU_SC_MODE_CNTL));
300 OUT_RING(ring, A2XX_PA_SU_SC_MODE_CNTL_PROVOKING_VTX_LAST |
301 A2XX_PA_SU_SC_MODE_CNTL_FRONT_PTYPE(PC_DRAW_TRIANGLES) |
302 A2XX_PA_SU_SC_MODE_CNTL_BACK_PTYPE(PC_DRAW_TRIANGLES));
303
304 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
305 OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_AA_MASK));
306 OUT_RING(ring, 0x0000ffff);
307
308 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
309 OUT_RING(ring, CP_REG(REG_A2XX_RB_COLORCONTROL));
310 OUT_RING(ring, A2XX_RB_COLORCONTROL_ALPHA_FUNC(PIPE_FUNC_ALWAYS) |
311 A2XX_RB_COLORCONTROL_BLEND_DISABLE |
312 A2XX_RB_COLORCONTROL_ROP_CODE(12) |
313 A2XX_RB_COLORCONTROL_DITHER_MODE(DITHER_DISABLE) |
314 A2XX_RB_COLORCONTROL_DITHER_TYPE(DITHER_PIXEL));
315
316 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
317 OUT_RING(ring, CP_REG(REG_A2XX_RB_BLEND_CONTROL));
318 OUT_RING(ring, A2XX_RB_BLEND_CONTROL_COLOR_SRCBLEND(FACTOR_ONE) |
319 A2XX_RB_BLEND_CONTROL_COLOR_COMB_FCN(BLEND2_DST_PLUS_SRC) |
320 A2XX_RB_BLEND_CONTROL_COLOR_DESTBLEND(FACTOR_ZERO) |
321 A2XX_RB_BLEND_CONTROL_ALPHA_SRCBLEND(FACTOR_ONE) |
322 A2XX_RB_BLEND_CONTROL_ALPHA_COMB_FCN(BLEND2_DST_PLUS_SRC) |
323 A2XX_RB_BLEND_CONTROL_ALPHA_DESTBLEND(FACTOR_ZERO));
324
325 OUT_PKT3(ring, CP_SET_CONSTANT, 3);
326 OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_WINDOW_SCISSOR_TL));
327 OUT_RING(ring, A2XX_PA_SC_WINDOW_OFFSET_DISABLE |
328 xy2d(0,0)); /* PA_SC_WINDOW_SCISSOR_TL */
329 OUT_RING(ring, xy2d(bin_w, bin_h)); /* PA_SC_WINDOW_SCISSOR_BR */
330
331 OUT_PKT3(ring, CP_SET_CONSTANT, 5);
332 OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_VPORT_XSCALE));
333 OUT_RING(ring, fui((float)bin_w/2.0)); /* PA_CL_VPORT_XSCALE */
334 OUT_RING(ring, fui((float)bin_w/2.0)); /* PA_CL_VPORT_XOFFSET */
335 OUT_RING(ring, fui(-(float)bin_h/2.0)); /* PA_CL_VPORT_YSCALE */
336 OUT_RING(ring, fui((float)bin_h/2.0)); /* PA_CL_VPORT_YOFFSET */
337
338 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
339 OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_VTE_CNTL));
340 OUT_RING(ring, A2XX_PA_CL_VTE_CNTL_VTX_XY_FMT |
341 A2XX_PA_CL_VTE_CNTL_VTX_Z_FMT | // XXX check this???
342 A2XX_PA_CL_VTE_CNTL_VPORT_X_SCALE_ENA |
343 A2XX_PA_CL_VTE_CNTL_VPORT_X_OFFSET_ENA |
344 A2XX_PA_CL_VTE_CNTL_VPORT_Y_SCALE_ENA |
345 A2XX_PA_CL_VTE_CNTL_VPORT_Y_OFFSET_ENA);
346
347 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
348 OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_CLIP_CNTL));
349 OUT_RING(ring, 0x00000000);
350
351 if (fd_gmem_needs_restore(batch, tile, FD_BUFFER_DEPTH | FD_BUFFER_STENCIL))
352 emit_mem2gmem_surf(batch, gmem->zsbuf_base[0], pfb->zsbuf);
353
354 if (fd_gmem_needs_restore(batch, tile, FD_BUFFER_COLOR))
355 emit_mem2gmem_surf(batch, gmem->cbuf_base[0], pfb->cbufs[0]);
356
357 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
358 OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_VTE_CNTL));
359 OUT_RING(ring, A2XX_PA_CL_VTE_CNTL_VTX_W0_FMT |
360 A2XX_PA_CL_VTE_CNTL_VPORT_X_SCALE_ENA |
361 A2XX_PA_CL_VTE_CNTL_VPORT_X_OFFSET_ENA |
362 A2XX_PA_CL_VTE_CNTL_VPORT_Y_SCALE_ENA |
363 A2XX_PA_CL_VTE_CNTL_VPORT_Y_OFFSET_ENA |
364 A2XX_PA_CL_VTE_CNTL_VPORT_Z_SCALE_ENA |
365 A2XX_PA_CL_VTE_CNTL_VPORT_Z_OFFSET_ENA);
366
367 /* TODO blob driver seems to toss in a CACHE_FLUSH after each DRAW_INDX.. */
368 }
369
370 static void
371 patch_draws(struct fd_batch *batch, enum pc_di_vis_cull_mode vismode)
372 {
373 unsigned i;
374
375 if (!is_a20x(batch->ctx->screen)) {
376 /* identical to a3xx */
377 for (i = 0; i < fd_patch_num_elements(&batch->draw_patches); i++) {
378 struct fd_cs_patch *patch = fd_patch_element(&batch->draw_patches, i);
379 *patch->cs = patch->val | DRAW(0, 0, 0, vismode, 0);
380 }
381 util_dynarray_resize(&batch->draw_patches, 0);
382 return;
383 }
384
385 if (vismode == USE_VISIBILITY)
386 return;
387
388 for (i = 0; i < batch->draw_patches.size / sizeof(uint32_t*); i++) {
389 uint32_t *ptr = *util_dynarray_element(&batch->draw_patches, uint32_t*, i);
390 unsigned cnt = ptr[0] >> 16 & 0xfff; /* 5 with idx buffer, 3 without */
391
392 /* convert CP_DRAW_INDX_BIN to a CP_DRAW_INDX
393 * replace first two DWORDS with NOP and move the rest down
394 * (we don't want to have to move the idx buffer reloc)
395 */
396 ptr[0] = CP_TYPE3_PKT | (CP_NOP << 8);
397 ptr[1] = 0x00000000;
398
399 ptr[4] = ptr[2] & ~(1 << 14 | 1 << 15); /* remove cull_enable bits */
400 ptr[2] = CP_TYPE3_PKT | ((cnt-2) << 16) | (CP_DRAW_INDX << 8);
401 ptr[3] = 0x00000000;
402 }
403 }
404
405 static void
406 fd2_emit_sysmem_prep(struct fd_batch *batch)
407 {
408 struct fd_context *ctx = batch->ctx;
409 struct fd_ringbuffer *ring = batch->gmem;
410 struct pipe_framebuffer_state *pfb = &batch->framebuffer;
411 struct pipe_surface *psurf = pfb->cbufs[0];
412
413 if (!psurf)
414 return;
415
416 struct fd_resource *rsc = fd_resource(psurf->texture);
417 struct fd_resource_slice *slice =
418 fd_resource_slice(rsc, psurf->u.tex.level);
419 uint32_t offset =
420 fd_resource_offset(rsc, psurf->u.tex.level, psurf->u.tex.first_layer);
421
422 assert((slice->pitch & 31) == 0);
423 assert((offset & 0xfff) == 0);
424
425 fd2_emit_restore(ctx, ring);
426
427 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
428 OUT_RING(ring, CP_REG(REG_A2XX_RB_SURFACE_INFO));
429 OUT_RING(ring, A2XX_RB_SURFACE_INFO_SURFACE_PITCH(slice->pitch));
430
431 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
432 OUT_RING(ring, CP_REG(REG_A2XX_RB_COLOR_INFO));
433 OUT_RELOCW(ring, rsc->bo, offset, A2XX_RB_COLOR_INFO_LINEAR |
434 A2XX_RB_COLOR_INFO_SWAP(fmt2swap(psurf->format)) |
435 A2XX_RB_COLOR_INFO_FORMAT(fd2_pipe2color(psurf->format)), 0);
436
437 OUT_PKT3(ring, CP_SET_CONSTANT, 3);
438 OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_SCREEN_SCISSOR_TL));
439 OUT_RING(ring, A2XX_PA_SC_SCREEN_SCISSOR_TL_WINDOW_OFFSET_DISABLE);
440 OUT_RING(ring, A2XX_PA_SC_SCREEN_SCISSOR_BR_X(pfb->width) |
441 A2XX_PA_SC_SCREEN_SCISSOR_BR_Y(pfb->height));
442
443 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
444 OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_WINDOW_OFFSET));
445 OUT_RING(ring, A2XX_PA_SC_WINDOW_OFFSET_X(0) |
446 A2XX_PA_SC_WINDOW_OFFSET_Y(0));
447
448 patch_draws(batch, IGNORE_VISIBILITY);
449 util_dynarray_resize(&batch->draw_patches, 0);
450 util_dynarray_resize(&batch->shader_patches, 0);
451 }
452
453 /* before first tile */
454 static void
455 fd2_emit_tile_init(struct fd_batch *batch)
456 {
457 struct fd_context *ctx = batch->ctx;
458 struct fd_ringbuffer *ring = batch->gmem;
459 struct pipe_framebuffer_state *pfb = &batch->framebuffer;
460 struct fd_gmem_stateobj *gmem = &ctx->gmem;
461 enum pipe_format format = pipe_surface_format(pfb->cbufs[0]);
462 uint32_t reg;
463
464 fd2_emit_restore(ctx, ring);
465
466 OUT_PKT3(ring, CP_SET_CONSTANT, 4);
467 OUT_RING(ring, CP_REG(REG_A2XX_RB_SURFACE_INFO));
468 OUT_RING(ring, gmem->bin_w); /* RB_SURFACE_INFO */
469 OUT_RING(ring, A2XX_RB_COLOR_INFO_SWAP(fmt2swap(format)) |
470 A2XX_RB_COLOR_INFO_FORMAT(fd2_pipe2color(format)));
471 reg = A2XX_RB_DEPTH_INFO_DEPTH_BASE(gmem->zsbuf_base[0]);
472 if (pfb->zsbuf)
473 reg |= A2XX_RB_DEPTH_INFO_DEPTH_FORMAT(fd_pipe2depth(pfb->zsbuf->format));
474 OUT_RING(ring, reg); /* RB_DEPTH_INFO */
475
476 /* set to zero, for some reason hardware doesn't like certain values */
477 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
478 OUT_RING(ring, CP_REG(REG_A2XX_VGT_CURRENT_BIN_ID_MIN));
479 OUT_RING(ring, 0);
480
481 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
482 OUT_RING(ring, CP_REG(REG_A2XX_VGT_CURRENT_BIN_ID_MAX));
483 OUT_RING(ring, 0);
484
485 if (is_a20x(ctx->screen) && fd_binning_enabled && gmem->num_vsc_pipes) {
486 /* patch out unneeded memory exports by changing EXEC CF to EXEC_END
487 *
488 * in the shader compiler, we guarantee that the shader ends with
489 * a specific pattern of ALLOC/EXEC CF pairs for the hw binning exports
490 *
491 * the since patches point only to dwords and CFs are 1.5 dwords
492 * the patch is aligned and might point to a ALLOC CF
493 */
494 for (int i = 0; i < batch->shader_patches.size / sizeof(void*); i++) {
495 instr_cf_t *cf =
496 *util_dynarray_element(&batch->shader_patches, instr_cf_t*, i);
497 if (cf->opc == ALLOC)
498 cf++;
499 assert(cf->opc == EXEC);
500 assert(cf[ctx->screen->num_vsc_pipes*2-2].opc == EXEC_END);
501 cf[2*(gmem->num_vsc_pipes-1)].opc = EXEC_END;
502 }
503
504 patch_draws(batch, USE_VISIBILITY);
505
506 /* initialize shader constants for the binning memexport */
507 OUT_PKT3(ring, CP_SET_CONSTANT, 1 + gmem->num_vsc_pipes * 4);
508 OUT_RING(ring, 0x0000000C);
509
510 for (int i = 0; i < gmem->num_vsc_pipes; i++) {
511 struct fd_vsc_pipe *pipe = &ctx->vsc_pipe[i];
512
513 /* XXX we know how large this needs to be..
514 * should do some sort of realloc
515 * it should be ctx->batch->num_vertices bytes large
516 * with this size it will break with more than 256k vertices..
517 */
518 if (!pipe->bo) {
519 pipe->bo = fd_bo_new(ctx->dev, 0x40000,
520 DRM_FREEDRENO_GEM_TYPE_KMEM, "vsc_pipe[%u]", i);
521 }
522
523 /* memory export address (export32):
524 * .x: (base_address >> 2) | 0x40000000 (?)
525 * .y: index (float) - set by shader
526 * .z: 0x4B00D000 (?)
527 * .w: 0x4B000000 (?) | max_index (?)
528 */
529 OUT_RELOCW(ring, pipe->bo, 0, 0x40000000, -2);
530 OUT_RING(ring, 0x00000000);
531 OUT_RING(ring, 0x4B00D000);
532 OUT_RING(ring, 0x4B000000 | 0x40000);
533 }
534
535 OUT_PKT3(ring, CP_SET_CONSTANT, 1 + gmem->num_vsc_pipes * 8);
536 OUT_RING(ring, 0x0000018C);
537
538 for (int i = 0; i < gmem->num_vsc_pipes; i++) {
539 struct fd_vsc_pipe *pipe = &ctx->vsc_pipe[i];
540 float off_x, off_y, mul_x, mul_y;
541
542 /* const to tranform from [-1,1] to bin coordinates for this pipe
543 * for x/y, [0,256/2040] = 0, [256/2040,512/2040] = 1, etc
544 * 8 possible values on x/y axis,
545 * to clip at binning stage: only use center 6x6
546 * TODO: set the z parameters too so that hw binning
547 * can clip primitives in Z too
548 */
549
550 mul_x = 1.0f / (float) (gmem->bin_w * 8);
551 mul_y = 1.0f / (float) (gmem->bin_h * 8);
552 off_x = -pipe->x * (1.0/8.0f) + 0.125f - mul_x * gmem->minx;
553 off_y = -pipe->y * (1.0/8.0f) + 0.125f - mul_y * gmem->miny;
554
555 OUT_RING(ring, fui(off_x * (256.0f/255.0f)));
556 OUT_RING(ring, fui(off_y * (256.0f/255.0f)));
557 OUT_RING(ring, 0x3f000000);
558 OUT_RING(ring, fui(0.0f));
559
560 OUT_RING(ring, fui(mul_x * (256.0f/255.0f)));
561 OUT_RING(ring, fui(mul_y * (256.0f/255.0f)));
562 OUT_RING(ring, fui(0.0f));
563 OUT_RING(ring, fui(0.0f));
564 }
565
566 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
567 OUT_RING(ring, CP_REG(REG_A2XX_VGT_VERTEX_REUSE_BLOCK_CNTL));
568 OUT_RING(ring, 0);
569
570 ctx->emit_ib(ring, batch->binning);
571
572 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
573 OUT_RING(ring, CP_REG(REG_A2XX_VGT_VERTEX_REUSE_BLOCK_CNTL));
574 OUT_RING(ring, 0x00000002);
575 } else {
576 patch_draws(batch, IGNORE_VISIBILITY);
577 }
578
579 util_dynarray_resize(&batch->draw_patches, 0);
580 util_dynarray_resize(&batch->shader_patches, 0);
581 }
582
583 /* before mem2gmem */
584 static void
585 fd2_emit_tile_prep(struct fd_batch *batch, struct fd_tile *tile)
586 {
587 struct fd_ringbuffer *ring = batch->gmem;
588 struct pipe_framebuffer_state *pfb = &batch->framebuffer;
589 enum pipe_format format = pipe_surface_format(pfb->cbufs[0]);
590
591 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
592 OUT_RING(ring, CP_REG(REG_A2XX_RB_COLOR_INFO));
593 OUT_RING(ring, A2XX_RB_COLOR_INFO_SWAP(1) | /* RB_COLOR_INFO */
594 A2XX_RB_COLOR_INFO_FORMAT(fd2_pipe2color(format)));
595
596 /* setup screen scissor for current tile (same for mem2gmem): */
597 OUT_PKT3(ring, CP_SET_CONSTANT, 3);
598 OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_SCREEN_SCISSOR_TL));
599 OUT_RING(ring, A2XX_PA_SC_SCREEN_SCISSOR_TL_X(0) |
600 A2XX_PA_SC_SCREEN_SCISSOR_TL_Y(0));
601 OUT_RING(ring, A2XX_PA_SC_SCREEN_SCISSOR_BR_X(tile->bin_w) |
602 A2XX_PA_SC_SCREEN_SCISSOR_BR_Y(tile->bin_h));
603 }
604
605 /* before IB to rendering cmds: */
606 static void
607 fd2_emit_tile_renderprep(struct fd_batch *batch, struct fd_tile *tile)
608 {
609 struct fd_context *ctx = batch->ctx;
610 struct fd_ringbuffer *ring = batch->gmem;
611 struct pipe_framebuffer_state *pfb = &batch->framebuffer;
612 enum pipe_format format = pipe_surface_format(pfb->cbufs[0]);
613
614 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
615 OUT_RING(ring, CP_REG(REG_A2XX_RB_COLOR_INFO));
616 OUT_RING(ring, A2XX_RB_COLOR_INFO_SWAP(fmt2swap(format)) |
617 A2XX_RB_COLOR_INFO_FORMAT(fd2_pipe2color(format)));
618
619 /* setup window scissor and offset for current tile (different
620 * from mem2gmem):
621 */
622 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
623 OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_WINDOW_OFFSET));
624 OUT_RING(ring, A2XX_PA_SC_WINDOW_OFFSET_X(-tile->xoff) |
625 A2XX_PA_SC_WINDOW_OFFSET_Y(-tile->yoff));
626
627 /* tile offset for gl_FragCoord on a20x (C64 in fragment shader) */
628 if (is_a20x(batch->ctx->screen)) {
629 OUT_PKT3(ring, CP_SET_CONSTANT, 5);
630 OUT_RING(ring, 0x00000580);
631 OUT_RING(ring, fui(tile->xoff));
632 OUT_RING(ring, fui(tile->yoff));
633 OUT_RING(ring, fui(0.0f));
634 OUT_RING(ring, fui(0.0f));
635 }
636
637 if (is_a20x(ctx->screen) && fd_binning_enabled) {
638 struct fd_vsc_pipe *pipe = &ctx->vsc_pipe[tile->p];
639
640 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
641 OUT_RING(ring, CP_REG(REG_A2XX_VGT_CURRENT_BIN_ID_MIN));
642 OUT_RING(ring, tile->n);
643
644 OUT_PKT3(ring, CP_SET_CONSTANT, 2);
645 OUT_RING(ring, CP_REG(REG_A2XX_VGT_CURRENT_BIN_ID_MAX));
646 OUT_RING(ring, tile->n);
647
648 /* TODO only emit this when tile->p changes */
649 OUT_PKT3(ring, CP_SET_DRAW_INIT_FLAGS, 1);
650 OUT_RELOC(ring, pipe->bo, 0, 0, 0);
651 }
652 }
653
654 void
655 fd2_gmem_init(struct pipe_context *pctx)
656 {
657 struct fd_context *ctx = fd_context(pctx);
658
659 ctx->emit_sysmem_prep = fd2_emit_sysmem_prep;
660 ctx->emit_tile_init = fd2_emit_tile_init;
661 ctx->emit_tile_prep = fd2_emit_tile_prep;
662 ctx->emit_tile_mem2gmem = fd2_emit_tile_mem2gmem;
663 ctx->emit_tile_renderprep = fd2_emit_tile_renderprep;
664 ctx->emit_tile_gmem2mem = fd2_emit_tile_gmem2mem;
665 }