r300: Zero-initialize register for NV_vertex_program
[mesa.git] / src / gallium / drivers / r300 / r300_surface.c
1 /*
2 * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
3 * Joakim Sindholt <opensource@zhasha.com>
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 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the 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 NON-INFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 * USE OR OTHER DEALINGS IN THE SOFTWARE. */
23
24 #include "r300_surface.h"
25
26 static void r300_surface_setup(struct r300_context* r300,
27 struct r300_texture* dest,
28 unsigned x, unsigned y,
29 unsigned w, unsigned h)
30 {
31 struct r300_capabilities* caps = r300_screen(r300->context.screen)->caps;
32 unsigned pixpitch = dest->stride / dest->tex.block.size;
33 CS_LOCALS(r300);
34
35 r300_emit_blend_state(r300, &blend_clear_state);
36 r300_emit_blend_color_state(r300, &blend_color_clear_state);
37 r300_emit_dsa_state(r300, &dsa_clear_state);
38 r300_emit_rs_state(r300, &rs_clear_state);
39
40 BEGIN_CS(26);
41
42 /* Viewport setup */
43 OUT_CS_REG_SEQ(R300_SE_VPORT_XSCALE, 6);
44 OUT_CS_32F((float)w);
45 OUT_CS_32F((float)x);
46 OUT_CS_32F((float)h);
47 OUT_CS_32F((float)y);
48 OUT_CS_32F(1.0);
49 OUT_CS_32F(0.0);
50
51 OUT_CS_REG(R300_VAP_VTE_CNTL, R300_VPORT_X_SCALE_ENA |
52 R300_VPORT_X_OFFSET_ENA |
53 R300_VPORT_Y_SCALE_ENA |
54 R300_VPORT_Y_OFFSET_ENA |
55 R300_VTX_XY_FMT | R300_VTX_Z_FMT);
56
57 /* Pixel scissors. */
58 OUT_CS_REG_SEQ(R300_SC_SCISSORS_TL, 2);
59 if (caps->is_r500) {
60 OUT_CS((x << R300_SCISSORS_X_SHIFT) | (y << R300_SCISSORS_Y_SHIFT));
61 OUT_CS(((w - 1) << R300_SCISSORS_X_SHIFT) | ((h - 1) << R300_SCISSORS_Y_SHIFT));
62 } else {
63 /* Non-R500 chipsets have an offset of 1440 in their scissors. */
64 OUT_CS(((x + 1440) << R300_SCISSORS_X_SHIFT) |
65 ((y + 1440) << R300_SCISSORS_Y_SHIFT));
66 OUT_CS((((w - 1) + 1440) << R300_SCISSORS_X_SHIFT) |
67 (((h - 1) + 1440) << R300_SCISSORS_Y_SHIFT));
68 }
69
70 /* Flush colorbuffer and blend caches. */
71 OUT_CS_REG(R300_RB3D_DSTCACHE_CTLSTAT,
72 R300_RB3D_DSTCACHE_CTLSTAT_DC_FLUSH_FLUSH_DIRTY_3D |
73 R300_RB3D_DSTCACHE_CTLSTAT_DC_FINISH_SIGNAL);
74 OUT_CS_REG(R300_ZB_ZCACHE_CTLSTAT,
75 R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE |
76 R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE);
77
78 /* Setup colorbuffer. */
79 OUT_CS_REG_SEQ(R300_RB3D_COLOROFFSET0, 1);
80 OUT_CS_RELOC(dest->buffer, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0);
81 OUT_CS_REG_SEQ(R300_RB3D_COLORPITCH0, 1);
82 OUT_CS_RELOC(dest->buffer, pixpitch |
83 r300_translate_colorformat(dest->tex.format), 0,
84 RADEON_GEM_DOMAIN_VRAM, 0);
85 OUT_CS_REG(RB3D_COLOR_CHANNEL_MASK, 0xf);
86
87 END_CS;
88 }
89
90 /* Provides pipe_context's "surface_fill". Commonly used for clearing
91 * buffers. */
92 static void r300_surface_fill(struct pipe_context* pipe,
93 struct pipe_surface* dest,
94 unsigned x, unsigned y,
95 unsigned w, unsigned h,
96 unsigned color)
97 {
98 int i;
99 float r, g, b, a, depth;
100 struct r300_context* r300 = r300_context(pipe);
101 struct r300_capabilities* caps = r300_screen(pipe->screen)->caps;
102 struct r300_texture* tex = (struct r300_texture*)dest->texture;
103 unsigned pixpitch = tex->stride / tex->tex.block.size;
104 boolean invalid = FALSE;
105 CS_LOCALS(r300);
106
107 a = (float)((color >> 24) & 0xff) / 255.0f;
108 r = (float)((color >> 16) & 0xff) / 255.0f;
109 g = (float)((color >> 8) & 0xff) / 255.0f;
110 b = (float)((color >> 0) & 0xff) / 255.0f;
111 debug_printf("r300: Filling surface %p at (%d,%d),"
112 " dimensions %dx%d (pixel pitch %d), color 0x%x\n",
113 dest, x, y, w, h, pixpitch, color);
114
115 /* Fallback? */
116 if (FALSE) {
117 fallback:
118 debug_printf("r300: Falling back on surface clear...");
119 util_surface_fill(pipe, dest, x, y, w, h, color);
120 return;
121 }
122
123 /* Make sure our target BO is okay. */
124 validate:
125 if (!r300->winsys->add_buffer(r300->winsys, tex->buffer,
126 0, RADEON_GEM_DOMAIN_VRAM)) {
127 r300->context.flush(&r300->context, 0, NULL);
128 goto validate;
129 }
130 if (!r300->winsys->validate(r300->winsys)) {
131 r300->context.flush(&r300->context, 0, NULL);
132 if (invalid) {
133 debug_printf("r300: Stuck in validation loop, gonna fallback.");
134 goto fallback;
135 }
136 invalid = TRUE;
137 goto validate;
138 }
139
140 r300_surface_setup(r300, tex, x, y, w, h);
141
142 /* Vertex shader setup */
143 if (caps->has_tcl) {
144 r300_emit_vertex_program_code(r300, &r300_passthrough_vertex_shader, 0);
145 } else {
146 BEGIN_CS(4);
147 OUT_CS_REG(R300_VAP_CNTL_STATUS,
148 #ifdef PIPE_ARCH_BIG_ENDIAN
149 R300_VC_32BIT_SWAP |
150 #endif
151 R300_VAP_TCL_BYPASS);
152 OUT_CS_REG(R300_VAP_CNTL, R300_PVS_NUM_SLOTS(5) |
153 R300_PVS_NUM_CNTLRS(5) |
154 R300_PVS_NUM_FPUS(caps->num_vert_fpus) |
155 R300_PVS_VF_MAX_VTX_NUM(12));
156 END_CS;
157 }
158
159 /* Fragment shader setup */
160 if (caps->is_r500) {
161 r500_emit_fragment_program_code(r300, &r5xx_passthrough_fragment_shader, 0);
162 r300_emit_rs_block_state(r300, &r5xx_rs_block_clear_state);
163 } else {
164 r300_emit_fragment_program_code(r300, &r3xx_passthrough_fragment_shader, 0);
165 r300_emit_rs_block_state(r300, &r3xx_rs_block_clear_state);
166 }
167
168 BEGIN_CS(26);
169
170 /* VAP stream control, mapping from input memory to PVS/RS memory */
171 if (caps->has_tcl) {
172 OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_0,
173 (R300_DATA_TYPE_FLOAT_4 << R300_DATA_TYPE_0_SHIFT) |
174 ((R300_LAST_VEC | (1 << R300_DST_VEC_LOC_SHIFT) |
175 R300_DATA_TYPE_FLOAT_4) << R300_DATA_TYPE_1_SHIFT));
176 } else {
177 OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_0,
178 (R300_DATA_TYPE_FLOAT_4 << R300_DATA_TYPE_0_SHIFT) |
179 ((R300_LAST_VEC | (2 << R300_DST_VEC_LOC_SHIFT) |
180 R300_DATA_TYPE_FLOAT_4) << R300_DATA_TYPE_1_SHIFT));
181 }
182 OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_EXT_0,
183 (R300_VAP_SWIZZLE_XYZW << R300_SWIZZLE0_SHIFT) |
184 (R300_VAP_SWIZZLE_XYZW << R300_SWIZZLE1_SHIFT));
185
186 /* VAP format controls */
187 OUT_CS_REG(R300_VAP_OUTPUT_VTX_FMT_0,
188 R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT |
189 R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT);
190 OUT_CS_REG(R300_VAP_OUTPUT_VTX_FMT_1, 0x0);
191
192 /* Disable textures */
193 OUT_CS_REG(R300_TX_ENABLE, 0x0);
194
195 /* The size of the point we're about to draw, in sixths of pixels */
196 OUT_CS_REG(R300_GA_POINT_SIZE,
197 ((h * 6) & R300_POINTSIZE_Y_MASK) |
198 ((w * 6) << R300_POINTSIZE_X_SHIFT));
199
200 /* Vertex size. */
201 OUT_CS_REG(R300_VAP_VTX_SIZE, 0x8);
202
203 /* Packet3 with our point vertex */
204 OUT_CS_PKT3(R200_3D_DRAW_IMMD_2, 8);
205 OUT_CS(R300_PRIM_TYPE_POINT | R300_PRIM_WALK_RING |
206 (1 << R300_PRIM_NUM_VERTICES_SHIFT));
207 /* Position */
208 OUT_CS_32F(0.5);
209 OUT_CS_32F(0.5);
210 OUT_CS_32F(1.0);
211 OUT_CS_32F(1.0);
212 /* Color */
213 OUT_CS_32F(r);
214 OUT_CS_32F(g);
215 OUT_CS_32F(b);
216 OUT_CS_32F(a);
217
218 OUT_CS_REG(R300_RB3D_DSTCACHE_CTLSTAT, 0xA);
219
220 END_CS;
221
222 r300->dirty_hw++;
223 }
224
225 static void r300_surface_copy(struct pipe_context* pipe,
226 struct pipe_surface* dest,
227 unsigned destx, unsigned desty,
228 struct pipe_surface* src,
229 unsigned srcx, unsigned srcy,
230 unsigned w, unsigned h)
231 {
232 struct r300_context* r300 = r300_context(pipe);
233 struct r300_capabilities* caps = r300_screen(pipe->screen)->caps;
234 struct r300_texture* srctex = (struct r300_texture*)src->texture;
235 struct r300_texture* desttex = (struct r300_texture*)dest->texture;
236 unsigned pixpitch = srctex->stride / srctex->tex.block.size;
237 boolean invalid = FALSE;
238 float fsrcx = srcx, fsrcy = srcy, fdestx = destx, fdesty = desty;
239 CS_LOCALS(r300);
240
241 debug_printf("r300: Copying surface %p at (%d,%d) to %p at (%d, %d),"
242 " dimensions %dx%d (pixel pitch %d)\n",
243 src, srcx, srcy, dest, destx, desty, w, h, pixpitch);
244
245 if ((srctex->buffer == desttex->buffer) &&
246 ((destx < srcx + w) || (srcx < destx + w)) &&
247 ((desty < srcy + h) || (srcy < desty + h))) {
248 fallback:
249 debug_printf("r300: Falling back on surface_copy\n");
250 util_surface_copy(pipe, FALSE, dest, destx, desty, src,
251 srcx, srcy, w, h);
252 }
253
254 /* Add our target BOs to the list. */
255 validate:
256 if (!r300->winsys->add_buffer(r300->winsys, srctex->buffer,
257 RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0)) {
258 r300->context.flush(&r300->context, 0, NULL);
259 goto validate;
260 }
261 if (!r300->winsys->add_buffer(r300->winsys, desttex->buffer,
262 0, RADEON_GEM_DOMAIN_VRAM)) {
263 r300->context.flush(&r300->context, 0, NULL);
264 goto validate;
265 }
266 if (!r300->winsys->validate(r300->winsys)) {
267 r300->context.flush(&r300->context, 0, NULL);
268 if (invalid) {
269 debug_printf("r300: Stuck in validation loop, gonna fallback.");
270 goto fallback;
271 }
272 invalid = TRUE;
273 goto validate;
274 }
275
276 r300_surface_setup(r300, desttex, destx, desty, w, h);
277
278 /* Setup the texture. */
279 r300_emit_texture(r300, &r300_sampler_copy_state, srctex, 0);
280
281 /* Flush and enable. */
282 r300_flush_textures(r300);
283
284 /* Vertex shader setup */
285 if (caps->has_tcl) {
286 r300_emit_vertex_program_code(r300, &r300_passthrough_vertex_shader, 0);
287 } else {
288 BEGIN_CS(4);
289 OUT_CS_REG(R300_VAP_CNTL_STATUS,
290 #ifdef PIPE_ARCH_BIG_ENDIAN
291 R300_VC_32BIT_SWAP |
292 #endif
293 R300_VAP_TCL_BYPASS);
294 OUT_CS_REG(R300_VAP_CNTL, R300_PVS_NUM_SLOTS(5) |
295 R300_PVS_NUM_CNTLRS(5) |
296 R300_PVS_NUM_FPUS(caps->num_vert_fpus) |
297 R300_PVS_VF_MAX_VTX_NUM(12));
298 END_CS;
299 }
300
301 /* Fragment shader setup */
302 if (caps->is_r500) {
303 r500_emit_fragment_program_code(r300, &r5xx_texture_fragment_shader, 0);
304 r300_emit_rs_block_state(r300, &r5xx_rs_block_copy_state);
305 } else {
306 r300_emit_fragment_program_code(r300, &r3xx_texture_fragment_shader, 0);
307 r300_emit_rs_block_state(r300, &r3xx_rs_block_copy_state);
308 }
309
310 BEGIN_CS(30);
311 /* VAP stream control, mapping from input memory to PVS/RS memory */
312 if (caps->has_tcl) {
313 OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_0,
314 (R300_DATA_TYPE_FLOAT_2 << R300_DATA_TYPE_0_SHIFT) |
315 ((R300_LAST_VEC | (1 << R300_DST_VEC_LOC_SHIFT) |
316 R300_DATA_TYPE_FLOAT_2) << R300_DATA_TYPE_1_SHIFT));
317 } else {
318 OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_0,
319 (R300_DATA_TYPE_FLOAT_2 << R300_DATA_TYPE_0_SHIFT) |
320 ((R300_LAST_VEC | (6 << R300_DST_VEC_LOC_SHIFT) |
321 R300_DATA_TYPE_FLOAT_2) << R300_DATA_TYPE_1_SHIFT));
322 }
323 OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_EXT_0,
324 (R300_VAP_SWIZZLE_XYZW << R300_SWIZZLE0_SHIFT) |
325 (R300_VAP_SWIZZLE_XYZW << R300_SWIZZLE1_SHIFT));
326
327 /* VAP format controls */
328 OUT_CS_REG(R300_VAP_OUTPUT_VTX_FMT_0,
329 R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT);
330 /* Two components of texture 0 */
331 OUT_CS_REG(R300_VAP_OUTPUT_VTX_FMT_1, 0x2);
332
333 /* Vertex size. */
334 OUT_CS_REG(R300_VAP_VTX_SIZE, 0x4);
335
336 /* Packet3 with our texcoords */
337 OUT_CS_PKT3(R200_3D_DRAW_IMMD_2, 16);
338 OUT_CS(R300_PRIM_TYPE_QUADS | R300_PRIM_WALK_RING |
339 (4 << R300_PRIM_NUM_VERTICES_SHIFT));
340 /* (x , y ) */
341 OUT_CS_32F(fdestx / dest->width);
342 OUT_CS_32F(fdesty / dest->height);
343 OUT_CS_32F(fsrcx / src->width);
344 OUT_CS_32F(fsrcy / src->height);
345 /* (x , y + h) */
346 OUT_CS_32F(fdestx / dest->width);
347 OUT_CS_32F((fdesty + h) / dest->height);
348 OUT_CS_32F(fsrcx / src->width);
349 OUT_CS_32F((fsrcy + h) / src->height);
350 /* (x + w, y + h) */
351 OUT_CS_32F((fdestx + w) / dest->width);
352 OUT_CS_32F((fdesty + h) / dest->height);
353 OUT_CS_32F((fsrcx + w) / src->width);
354 OUT_CS_32F((fsrcy + h) / src->height);
355 /* (x + w, y ) */
356 OUT_CS_32F((fdestx + w) / dest->width);
357 OUT_CS_32F(fdesty / dest->height);
358 OUT_CS_32F((fsrcx + w) / src->width);
359 OUT_CS_32F(fsrcy / src->height);
360
361 OUT_CS_REG(R300_RB3D_DSTCACHE_CTLSTAT, 0xA);
362
363 END_CS;
364
365 r300->dirty_hw++;
366 }
367
368 void r300_init_surface_functions(struct r300_context* r300)
369 {
370 r300->context.surface_fill = r300_surface_fill;
371 r300->context.surface_copy = r300_surface_copy;
372 }