vc4: Initial skeleton driver import.
[mesa.git] / src / gallium / drivers / vc4 / vc4_draw.c
1 /*
2 * Copyright (c) 2014 Scott Mansell
3 * Copyright © 2014 Broadcom
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 */
24
25 #include <stdio.h>
26
27 #include "vc4_context.h"
28 #include "vc4_resource.h"
29
30 static struct vc4_bo *
31 get_vbo(struct vc4_context *vc4, uint32_t width, uint32_t height)
32 {
33 struct {
34 uint16_t x, y;
35 float z, rhw, r, g, b;
36 } verts[] = {
37 {
38 // Vertex: Top, red
39 (-(int)width / 3) << 4, // X in 12.4 fixed point
40 (-(int)height / 3) << 4, // Y in 12.4 fixed point
41 1.0f, // Z
42 1.0f, // 1/W
43 1.0f, // Varying 0 (Red)
44 0.0f, // Varying 1 (Green)
45 0.0f, // Varying 2 (Blue)
46 },
47 {
48 // Vertex: bottom left, Green
49 (width / 3) << 4, // X in 12.4 fixed point
50 (-(int)height / 3) << 4, // Y in 12.4 fixed point
51 1.0f, // Z
52 1.0f, // 1/W
53 0.0f, // Varying 0 (Red)
54 1.0f, // Varying 1 (Green)
55 0.0f, // Varying 2 (Blue)
56 },
57
58 {
59 // Vertex: bottom right, Blue
60 (width / 3) << 4, // X in 12.4 fixed point
61 (height / 3) << 4, // Y in 12.4 fixed point
62 1.0f, // Z
63 1.0f, // 1/W
64 0.0f, // Varying 0 (Red)
65 0.0f, // Varying 1 (Green)
66 1.0f, // Varying 2 (Blue)
67 },
68 };
69
70 return vc4_bo_alloc_mem(vc4->screen, verts, sizeof(verts), "verts");
71 }
72 static struct vc4_bo *
73 get_ibo(struct vc4_context *vc4)
74 {
75 static const uint8_t indices[] = { 0, 1, 2 };
76
77 return vc4_bo_alloc_mem(vc4->screen, indices, sizeof(indices), "indices");
78 }
79
80 static void
81 vc4_rcl_tile_calls(struct vc4_context *vc4,
82 uint32_t xtiles, uint32_t ytiles,
83 struct vc4_bo *tile_alloc)
84 {
85 for (int x = 0; x < xtiles; x++) {
86 for (int y = 0; y < ytiles; y++) {
87 cl_u8(&vc4->rcl, VC4_PACKET_TILE_COORDINATES);
88 cl_u8(&vc4->rcl, x);
89 cl_u8(&vc4->rcl, y);
90
91 cl_start_reloc(&vc4->rcl, 1);
92 cl_u8(&vc4->rcl, VC4_PACKET_BRANCH_TO_SUB_LIST);
93 cl_reloc(vc4, &vc4->rcl, tile_alloc,
94 (y * xtiles + x) * 32);
95
96 if (x == xtiles - 1 && y == ytiles - 1) {
97 cl_u8(&vc4->rcl,
98 VC4_PACKET_STORE_MS_TILE_BUFFER_AND_EOF);
99 } else {
100 cl_u8(&vc4->rcl,
101 VC4_PACKET_STORE_MS_TILE_BUFFER);
102 }
103 }
104 }
105 }
106
107 static void
108 vc4_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
109 {
110 struct vc4_context *vc4 = vc4_context(pctx);
111 uint32_t width = vc4->framebuffer.width;
112 uint32_t height = vc4->framebuffer.height;
113 uint32_t tilew = align(width, 64) / 64;
114 uint32_t tileh = align(height, 64) / 64;
115 struct vc4_bo *tile_alloc = vc4_bo_alloc(vc4->screen,
116 32 * tilew * tileh, "tilea");
117 struct vc4_bo *tile_state = vc4_bo_alloc(vc4->screen,
118 48 * tilew * tileh, "tilestate");
119 struct vc4_bo *ibo = get_ibo(vc4);
120
121 struct vc4_bo *fs_uniform = vc4_bo_alloc(vc4->screen, 0x1000, "fsu");
122 struct vc4_bo *vbo = get_vbo(vc4, width, height);
123
124 vc4->needs_flush = true;
125
126 // Tile state data is 48 bytes per tile, I think it can be thrown away
127 // as soon as binning is finished.
128 cl_start_reloc(&vc4->bcl, 2);
129 cl_u8(&vc4->bcl, VC4_PACKET_TILE_BINNING_MODE_CONFIG);
130 cl_reloc(vc4, &vc4->bcl, tile_alloc, 0);
131 cl_u32(&vc4->bcl, 0x8000); /* tile allocation memory size */
132 cl_reloc(vc4, &vc4->bcl, tile_state, 0);
133 cl_u8(&vc4->bcl, tilew);
134 cl_u8(&vc4->bcl, tileh);
135 cl_u8(&vc4->bcl, VC4_BIN_CONFIG_AUTO_INIT_TSDA);
136
137 cl_u8(&vc4->bcl, VC4_PACKET_START_TILE_BINNING);
138
139 cl_u8(&vc4->bcl, VC4_PACKET_PRIMITIVE_LIST_FORMAT);
140 cl_u8(&vc4->bcl, 0x32); // 16 bit triangle
141
142 vc4_emit_state(pctx);
143
144 /* the actual draw call. */
145 cl_u8(&vc4->bcl, VC4_PACKET_NV_SHADER_STATE);
146 #ifndef USE_VC4_SIMULATOR
147 cl_u32(&vc4->bcl, 0); /* offset into shader_rec */
148 #else
149 cl_u32(&vc4->bcl, simpenrose_hw_addr(vc4->shader_rec.next));
150 #endif
151
152 cl_start_reloc(&vc4->bcl, 1);
153 cl_u8(&vc4->bcl, VC4_PACKET_GL_INDEXED_PRIMITIVE);
154 cl_u8(&vc4->bcl, 0x04); // 8bit index, trinagles
155 cl_u32(&vc4->bcl, 3); // Length
156 cl_reloc(vc4, &vc4->bcl, ibo, 0);
157 cl_u32(&vc4->bcl, 2); // Maximum index
158
159 cl_u8(&vc4->bcl, VC4_PACKET_FLUSH_ALL);
160 cl_u8(&vc4->bcl, VC4_PACKET_NOP);
161 cl_u8(&vc4->bcl, VC4_PACKET_HALT);
162
163 // Shader Record
164 cl_start_shader_reloc(&vc4->shader_rec, 3);
165
166 cl_u8(&vc4->shader_rec, 0);
167 cl_u8(&vc4->shader_rec, 6*4); // stride
168 cl_u8(&vc4->shader_rec, 0xcc); // num uniforms (not used)
169 cl_u8(&vc4->shader_rec, 3); // num varyings
170 cl_reloc(vc4, &vc4->shader_rec, vc4->prog.fs->bo, 0);
171 cl_reloc(vc4, &vc4->shader_rec, fs_uniform, 0);
172 cl_reloc(vc4, &vc4->shader_rec, vbo, 0);
173
174 vc4->shader_rec_count++;
175
176 cl_u8(&vc4->rcl, VC4_PACKET_CLEAR_COLORS);
177 cl_u32(&vc4->rcl, 0xff000000); // Opaque Black
178 cl_u32(&vc4->rcl, 0xff000000); // 32 bit clear colours need to be repeated twice
179 cl_u32(&vc4->rcl, 0);
180 cl_u8(&vc4->rcl, 0);
181
182 struct vc4_surface *csurf = vc4_surface(vc4->framebuffer.cbufs[0]);
183 struct vc4_resource *ctex = vc4_resource(csurf->base.texture);
184
185 cl_start_reloc(&vc4->rcl, 1);
186 cl_u8(&vc4->rcl, VC4_PACKET_TILE_RENDERING_MODE_CONFIG);
187 cl_reloc(vc4, &vc4->rcl, ctex->bo, csurf->offset);
188 cl_u16(&vc4->rcl, width);
189 cl_u16(&vc4->rcl, height);
190 cl_u8(&vc4->rcl, (VC4_RENDER_CONFIG_MEMORY_FORMAT_LINEAR |
191 VC4_RENDER_CONFIG_FORMAT_RGBA8888));
192 cl_u8(&vc4->rcl, 0);
193
194 // Do a store of the first tile to force the tile buffer to be cleared
195 /* XXX: I think these two packets may be unnecessary. */
196 cl_u8(&vc4->rcl, VC4_PACKET_TILE_COORDINATES);
197 cl_u8(&vc4->rcl, 0);
198 cl_u8(&vc4->rcl, 0);
199
200 cl_u8(&vc4->rcl, VC4_PACKET_STORE_TILE_BUFFER_GENERAL);
201 cl_u16(&vc4->rcl, 0); // Store nothing (just clear)
202 cl_u32(&vc4->rcl, 0); // no address is needed
203
204 vc4_rcl_tile_calls(vc4, tilew, tileh, tile_alloc);
205
206 vc4_flush(pctx);
207 }
208
209 static void
210 vc4_clear(struct pipe_context *pctx, unsigned buffers,
211 const union pipe_color_union *color, double depth, unsigned stencil)
212 {
213 struct vc4_context *vc4 = vc4_context(pctx);
214
215 vc4->needs_flush = true;
216 }
217
218 static void
219 vc4_clear_render_target(struct pipe_context *pctx, struct pipe_surface *ps,
220 const union pipe_color_union *color,
221 unsigned x, unsigned y, unsigned w, unsigned h)
222 {
223 fprintf(stderr, "unimpl: clear RT\n");
224 }
225
226 static void
227 vc4_clear_depth_stencil(struct pipe_context *pctx, struct pipe_surface *ps,
228 unsigned buffers, double depth, unsigned stencil,
229 unsigned x, unsigned y, unsigned w, unsigned h)
230 {
231 fprintf(stderr, "unimpl: clear DS\n");
232 }
233
234 void
235 vc4_draw_init(struct pipe_context *pctx)
236 {
237 pctx->draw_vbo = vc4_draw_vbo;
238 pctx->clear = vc4_clear;
239 pctx->clear_render_target = vc4_clear_render_target;
240 pctx->clear_depth_stencil = vc4_clear_depth_stencil;
241 }