r300/compiler: Move declaration before code.
[mesa.git] / src / mesa / drivers / dri / r300 / r300_blit.c
1 /*
2 * Copyright (C) 2009 Maciej Cencora <m.cencora@gmail.com>
3 *
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 */
27
28 #include "radeon_common.h"
29 #include "r300_context.h"
30
31 #include "r300_blit.h"
32 #include "r300_cmdbuf.h"
33 #include "r300_emit.h"
34 #include "r300_tex.h"
35 #include "compiler/radeon_compiler.h"
36 #include "compiler/radeon_opcodes.h"
37
38 static void vp_ins_outs(struct r300_vertex_program_compiler *c)
39 {
40 c->code->inputs[VERT_ATTRIB_POS] = 0;
41 c->code->inputs[VERT_ATTRIB_TEX0] = 1;
42 c->code->outputs[VERT_RESULT_HPOS] = 0;
43 c->code->outputs[VERT_RESULT_TEX0] = 1;
44 }
45
46 static void fp_allocate_hw_inputs(
47 struct r300_fragment_program_compiler * c,
48 void (*allocate)(void * data, unsigned input, unsigned hwreg),
49 void * mydata)
50 {
51 allocate(mydata, FRAG_ATTRIB_TEX0, 0);
52 }
53
54 static void create_vertex_program(struct r300_context *r300)
55 {
56 struct r300_vertex_program_compiler compiler;
57 struct rc_instruction *inst;
58
59 memset(&compiler, 0, sizeof(compiler));
60 rc_init(&compiler.Base);
61
62 inst = rc_insert_new_instruction(&compiler.Base, compiler.Base.Program.Instructions.Prev);
63 inst->U.I.Opcode = RC_OPCODE_MOV;
64 inst->U.I.DstReg.File = RC_FILE_OUTPUT;
65 inst->U.I.DstReg.Index = VERT_RESULT_HPOS;
66 inst->U.I.DstReg.RelAddr = 0;
67 inst->U.I.DstReg.WriteMask = RC_MASK_XYZW;
68 inst->U.I.SrcReg[0].Abs = 0;
69 inst->U.I.SrcReg[0].File = RC_FILE_INPUT;
70 inst->U.I.SrcReg[0].Index = VERT_ATTRIB_POS;
71 inst->U.I.SrcReg[0].Negate = 0;
72 inst->U.I.SrcReg[0].RelAddr = 0;
73 inst->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZW;
74
75 inst = rc_insert_new_instruction(&compiler.Base, compiler.Base.Program.Instructions.Prev);
76 inst->U.I.Opcode = RC_OPCODE_MOV;
77 inst->U.I.DstReg.File = RC_FILE_OUTPUT;
78 inst->U.I.DstReg.Index = VERT_RESULT_TEX0;
79 inst->U.I.DstReg.RelAddr = 0;
80 inst->U.I.DstReg.WriteMask = RC_MASK_XYZW;
81 inst->U.I.SrcReg[0].Abs = 0;
82 inst->U.I.SrcReg[0].File = RC_FILE_INPUT;
83 inst->U.I.SrcReg[0].Index = VERT_ATTRIB_TEX0;
84 inst->U.I.SrcReg[0].Negate = 0;
85 inst->U.I.SrcReg[0].RelAddr = 0;
86 inst->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZW;
87
88 compiler.Base.Program.InputsRead = (1 << VERT_ATTRIB_POS) | (1 << VERT_ATTRIB_TEX0);
89 compiler.RequiredOutputs = compiler.Base.Program.OutputsWritten = (1 << VERT_RESULT_HPOS) | (1 << VERT_RESULT_TEX0);
90 compiler.SetHwInputOutput = vp_ins_outs;
91 compiler.code = &r300->blit.vp_code;
92 compiler.Base.is_r500 = r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515;
93 compiler.Base.disable_optimizations = 0;
94 compiler.Base.has_half_swizzles = 0;
95 compiler.Base.max_temp_regs = 32;
96 compiler.Base.max_constants = 256;
97 compiler.Base.max_alu_insts = compiler.Base.is_r500 ? 1024 : 256;
98
99 r3xx_compile_vertex_program(&compiler);
100 }
101
102 static void create_fragment_program(struct r300_context *r300)
103 {
104 struct r300_fragment_program_compiler compiler;
105 struct rc_instruction *inst;
106
107 memset(&compiler, 0, sizeof(struct r300_fragment_program_compiler));
108 rc_init(&compiler.Base);
109
110 inst = rc_insert_new_instruction(&compiler.Base, compiler.Base.Program.Instructions.Prev);
111 inst->U.I.Opcode = RC_OPCODE_TEX;
112 inst->U.I.TexSrcTarget = RC_TEXTURE_2D;
113 inst->U.I.TexSrcUnit = 0;
114 inst->U.I.DstReg.File = RC_FILE_OUTPUT;
115 inst->U.I.DstReg.Index = FRAG_RESULT_COLOR;
116 inst->U.I.DstReg.WriteMask = RC_MASK_XYZW;
117 inst->U.I.SrcReg[0].Abs = 0;
118 inst->U.I.SrcReg[0].File = RC_FILE_INPUT;
119 inst->U.I.SrcReg[0].Index = FRAG_ATTRIB_TEX0;
120 inst->U.I.SrcReg[0].Negate = 0;
121 inst->U.I.SrcReg[0].RelAddr = 0;
122 inst->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZW;
123
124 compiler.Base.Program.InputsRead = (1 << FRAG_ATTRIB_TEX0);
125 compiler.OutputColor[0] = FRAG_RESULT_COLOR;
126 compiler.OutputDepth = FRAG_RESULT_DEPTH;
127 compiler.enable_shadow_ambient = GL_TRUE;
128 compiler.Base.is_r500 = (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515);
129 compiler.Base.disable_optimizations = 0;
130 compiler.Base.has_half_swizzles = 1;
131 compiler.Base.max_temp_regs = (compiler.Base.is_r500) ? 128 : 32;
132 compiler.Base.max_constants = compiler.Base.is_r500 ? 256 : 32;
133 compiler.Base.max_alu_insts = compiler.Base.is_r500 ? 512 : 64;
134 compiler.code = &r300->blit.fp_code;
135 compiler.AllocateHwInputs = fp_allocate_hw_inputs;
136
137 r3xx_compile_fragment_program(&compiler);
138 }
139
140 void r300_blit_init(struct r300_context *r300)
141 {
142 if (r300->options.hw_tcl_enabled)
143 create_vertex_program(r300);
144 create_fragment_program(r300);
145 }
146
147 static void r300_emit_tx_setup(struct r300_context *r300,
148 gl_format mesa_format,
149 struct radeon_bo *bo,
150 intptr_t offset,
151 unsigned width,
152 unsigned height,
153 unsigned pitch)
154 {
155 int is_r500 = r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515;
156 BATCH_LOCALS(&r300->radeon);
157
158 assert(is_r500 ? width <= 4096 : width <= 2048);
159 assert(is_r500 ? height <= 4096 : height <= 2048);
160 assert(r300TranslateTexFormat(mesa_format) >= 0);
161 assert(offset % 32 == 0);
162
163 BEGIN_BATCH(17);
164 OUT_BATCH_REGVAL(R300_TX_FILTER0_0,
165 (R300_TX_CLAMP_TO_EDGE << R300_TX_WRAP_S_SHIFT) |
166 (R300_TX_CLAMP_TO_EDGE << R300_TX_WRAP_T_SHIFT) |
167 (R300_TX_CLAMP_TO_EDGE << R300_TX_WRAP_R_SHIFT) |
168 R300_TX_MIN_FILTER_MIP_NONE |
169 R300_TX_MIN_FILTER_NEAREST |
170 R300_TX_MAG_FILTER_NEAREST |
171 (0 << 28));
172 OUT_BATCH_REGVAL(R300_TX_FILTER1_0, 0);
173 OUT_BATCH_REGVAL(R300_TX_SIZE_0,
174 (((width - 1) & 0x7ff) << R300_TX_WIDTHMASK_SHIFT) |
175 (((height - 1) & 0x7ff) << R300_TX_HEIGHTMASK_SHIFT) |
176 (0 << R300_TX_DEPTHMASK_SHIFT) |
177 (0 << R300_TX_MAX_MIP_LEVEL_SHIFT) |
178 R300_TX_SIZE_TXPITCH_EN);
179
180 OUT_BATCH_REGVAL(R300_TX_FORMAT_0, r300TranslateTexFormat(mesa_format));
181 OUT_BATCH_REGVAL(R300_TX_FORMAT2_0,
182 (pitch - 1) |
183 (is_r500 && width > 2048 ? R500_TXWIDTH_BIT11 : 0) |
184 (is_r500 && height > 2048 ? R500_TXHEIGHT_BIT11 : 0));
185 OUT_BATCH_REGSEQ(R300_TX_OFFSET_0, 1);
186 OUT_BATCH_RELOC(0, bo, offset, RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
187
188 OUT_BATCH_REGSEQ(R300_TX_INVALTAGS, 2);
189 OUT_BATCH(0);
190 OUT_BATCH(1);
191
192 END_BATCH();
193 }
194
195 #define EASY_US_FORMAT(FMT, C0, C1, C2, C3, SIGN) \
196 (FMT | R500_C0_SEL_##C0 | R500_C1_SEL_##C1 | \
197 R500_C2_SEL_##C2 | R500_C3_SEL_##C3 | R500_OUT_SIGN(SIGN))
198
199 static uint32_t mesa_format_to_us_format(gl_format mesa_format)
200 {
201 switch(mesa_format)
202 {
203 case MESA_FORMAT_RGBA8888: // x
204 return EASY_US_FORMAT(R500_OUT_FMT_C4_8, A, B, G, R, 0);
205 case MESA_FORMAT_RGB565: // x
206 case MESA_FORMAT_ARGB1555: // x
207 case MESA_FORMAT_RGBA8888_REV: // x
208 return EASY_US_FORMAT(R500_OUT_FMT_C4_8, R, G, B, A, 0);
209 case MESA_FORMAT_ARGB8888: // x
210 return EASY_US_FORMAT(R500_OUT_FMT_C4_8, B, G, R, A, 0);
211 case MESA_FORMAT_ARGB8888_REV:
212 return EASY_US_FORMAT(R500_OUT_FMT_C4_8, A, R, G, B, 0);
213 case MESA_FORMAT_XRGB8888:
214 return EASY_US_FORMAT(R500_OUT_FMT_C4_8, A, R, G, B, 0);
215
216 case MESA_FORMAT_RGB332:
217 return EASY_US_FORMAT(R500_OUT_FMT_C_3_3_2, A, R, G, B, 0);
218
219 case MESA_FORMAT_RGBA_FLOAT32:
220 return EASY_US_FORMAT(R500_OUT_FMT_C4_32_FP, R, G, B, A, 0);
221 case MESA_FORMAT_RGBA_FLOAT16:
222 return EASY_US_FORMAT(R500_OUT_FMT_C4_16_FP, R, G, B, A, 0);
223 case MESA_FORMAT_ALPHA_FLOAT32:
224 return EASY_US_FORMAT(R500_OUT_FMT_C_32_FP, A, A, A, A, 0);
225 case MESA_FORMAT_ALPHA_FLOAT16:
226 return EASY_US_FORMAT(R500_OUT_FMT_C_16_FP, A, A, A, A, 0);
227
228 case MESA_FORMAT_SIGNED_RGBA8888:
229 return EASY_US_FORMAT(R500_OUT_FMT_C4_8, R, G, B, A, 0xf);
230 case MESA_FORMAT_SIGNED_RGBA8888_REV:
231 return EASY_US_FORMAT(R500_OUT_FMT_C4_8, A, B, G, R, 0xf);
232 case MESA_FORMAT_SIGNED_RGBA_16:
233 return EASY_US_FORMAT(R500_OUT_FMT_C4_16, R, G, B, A, 0xf);
234
235 default:
236 fprintf(stderr, "Unsupported format %s for US output\n", _mesa_get_format_name(mesa_format));
237 assert(0);
238 return 0;
239 }
240 }
241 #undef EASY_US_FORMAT
242
243 static void r500_emit_fp_setup(struct r300_context *r300,
244 struct r500_fragment_program_code *fp,
245 gl_format dst_format)
246 {
247 r500_emit_fp(r300, (uint32_t *)fp->inst, (fp->inst_end + 1) * 6, 0, 0, 0);
248 BATCH_LOCALS(&r300->radeon);
249
250 BEGIN_BATCH(10);
251 OUT_BATCH_REGSEQ(R500_US_CODE_ADDR, 3);
252 OUT_BATCH(R500_US_CODE_START_ADDR(0) | R500_US_CODE_END_ADDR(fp->inst_end));
253 OUT_BATCH(R500_US_CODE_RANGE_ADDR(0) | R500_US_CODE_RANGE_SIZE(fp->inst_end));
254 OUT_BATCH(0);
255 OUT_BATCH_REGVAL(R500_US_CONFIG, 0);
256 OUT_BATCH_REGVAL(R500_US_OUT_FMT_0, mesa_format_to_us_format(dst_format));
257 OUT_BATCH_REGVAL(R500_US_PIXSIZE, fp->max_temp_idx);
258 END_BATCH();
259 }
260
261 static void r500_emit_rs_setup(struct r300_context *r300)
262 {
263 BATCH_LOCALS(&r300->radeon);
264
265 BEGIN_BATCH(7);
266 OUT_BATCH_REGSEQ(R300_RS_COUNT, 2);
267 OUT_BATCH((4 << R300_IT_COUNT_SHIFT) | R300_HIRES_EN);
268 OUT_BATCH(0);
269 OUT_BATCH_REGVAL(R500_RS_INST_0,
270 (0 << R500_RS_INST_TEX_ID_SHIFT) |
271 (0 << R500_RS_INST_TEX_ADDR_SHIFT) |
272 R500_RS_INST_TEX_CN_WRITE |
273 R500_RS_INST_COL_CN_NO_WRITE);
274 OUT_BATCH_REGVAL(R500_RS_IP_0,
275 (0 << R500_RS_IP_TEX_PTR_S_SHIFT) |
276 (1 << R500_RS_IP_TEX_PTR_T_SHIFT) |
277 (2 << R500_RS_IP_TEX_PTR_R_SHIFT) |
278 (3 << R500_RS_IP_TEX_PTR_Q_SHIFT));
279 END_BATCH();
280 }
281
282 static void r300_emit_fp_setup(struct r300_context *r300,
283 struct r300_fragment_program_code *code,
284 gl_format dst_format)
285 {
286 unsigned i;
287 BATCH_LOCALS(&r300->radeon);
288
289 BEGIN_BATCH((code->alu.length + 1) * 4 + code->tex.length + 1 + 11);
290
291 OUT_BATCH_REGSEQ(R300_US_ALU_RGB_INST_0, code->alu.length);
292 for (i = 0; i < code->alu.length; i++) {
293 OUT_BATCH(code->alu.inst[i].rgb_inst);
294 }
295 OUT_BATCH_REGSEQ(R300_US_ALU_RGB_ADDR_0, code->alu.length);
296 for (i = 0; i < code->alu.length; i++) {
297 OUT_BATCH(code->alu.inst[i].rgb_addr);
298 }
299 OUT_BATCH_REGSEQ(R300_US_ALU_ALPHA_INST_0, code->alu.length);
300 for (i = 0; i < code->alu.length; i++) {
301 OUT_BATCH(code->alu.inst[i].alpha_inst);
302 }
303 OUT_BATCH_REGSEQ(R300_US_ALU_ALPHA_ADDR_0, code->alu.length);
304 for (i = 0; i < code->alu.length; i++) {
305 OUT_BATCH(code->alu.inst[i].alpha_addr);
306 }
307
308 OUT_BATCH_REGSEQ(R300_US_TEX_INST_0, code->tex.length);
309 OUT_BATCH_TABLE(code->tex.inst, code->tex.length);
310
311 OUT_BATCH_REGSEQ(R300_US_CONFIG, 3);
312 OUT_BATCH(R300_PFS_CNTL_FIRST_NODE_HAS_TEX);
313 OUT_BATCH(code->pixsize);
314 OUT_BATCH(code->code_offset);
315 OUT_BATCH_REGSEQ(R300_US_CODE_ADDR_0, 4);
316 OUT_BATCH_TABLE(code->code_addr, 4);
317 OUT_BATCH_REGVAL(R500_US_OUT_FMT_0, mesa_format_to_us_format(dst_format));
318 END_BATCH();
319 }
320
321 static void r300_emit_rs_setup(struct r300_context *r300)
322 {
323 BATCH_LOCALS(&r300->radeon);
324
325 BEGIN_BATCH(7);
326 OUT_BATCH_REGSEQ(R300_RS_COUNT, 2);
327 OUT_BATCH((4 << R300_IT_COUNT_SHIFT) | R300_HIRES_EN);
328 OUT_BATCH(0);
329 OUT_BATCH_REGVAL(R300_RS_INST_0,
330 R300_RS_INST_TEX_ID(0) |
331 R300_RS_INST_TEX_ADDR(0) |
332 R300_RS_INST_TEX_CN_WRITE);
333 OUT_BATCH_REGVAL(R300_RS_IP_0,
334 R300_RS_TEX_PTR(0) |
335 R300_RS_SEL_S(R300_RS_SEL_C0) |
336 R300_RS_SEL_T(R300_RS_SEL_C1) |
337 R300_RS_SEL_R(R300_RS_SEL_K0) |
338 R300_RS_SEL_Q(R300_RS_SEL_K1));
339 END_BATCH();
340 }
341
342 static void emit_pvs_setup(struct r300_context *r300,
343 uint32_t *vp_code,
344 unsigned vp_len)
345 {
346 BATCH_LOCALS(&r300->radeon);
347
348 r300_emit_vpu(r300, vp_code, vp_len * 4, R300_PVS_CODE_START);
349
350 BEGIN_BATCH(4);
351 OUT_BATCH_REGSEQ(R300_VAP_PVS_CODE_CNTL_0, 3);
352 OUT_BATCH((0 << R300_PVS_FIRST_INST_SHIFT) |
353 ((vp_len - 1) << R300_PVS_XYZW_VALID_INST_SHIFT) |
354 ((vp_len - 1)<< R300_PVS_LAST_INST_SHIFT));
355 OUT_BATCH(0);
356 OUT_BATCH((vp_len - 1) << R300_PVS_LAST_VTX_SRC_INST_SHIFT);
357 END_BATCH();
358 }
359
360 static void emit_vap_setup(struct r300_context *r300)
361 {
362 int tex_offset;
363 BATCH_LOCALS(&r300->radeon);
364
365 if (r300->options.hw_tcl_enabled)
366 tex_offset = 1;
367 else
368 tex_offset = 6;
369
370 BEGIN_BATCH(12);
371 OUT_BATCH_REGSEQ(R300_SE_VTE_CNTL, 2);
372 OUT_BATCH(R300_VTX_XY_FMT | R300_VTX_Z_FMT);
373 OUT_BATCH(4);
374
375 OUT_BATCH_REGVAL(R300_VAP_PSC_SGN_NORM_CNTL, 0xaaaaaaaa);
376 OUT_BATCH_REGVAL(R300_VAP_PROG_STREAM_CNTL_0,
377 ((R300_DATA_TYPE_FLOAT_2 | (0 << R300_DST_VEC_LOC_SHIFT)) << 0) |
378 (((tex_offset << R300_DST_VEC_LOC_SHIFT) | R300_DATA_TYPE_FLOAT_2 | R300_LAST_VEC) << 16));
379 OUT_BATCH_REGVAL(R300_VAP_PROG_STREAM_CNTL_EXT_0,
380 ((((R300_SWIZZLE_SELECT_X << R300_SWIZZLE_SELECT_X_SHIFT) |
381 (R300_SWIZZLE_SELECT_Y << R300_SWIZZLE_SELECT_Y_SHIFT) |
382 (R300_SWIZZLE_SELECT_FP_ZERO << R300_SWIZZLE_SELECT_Z_SHIFT) |
383 (R300_SWIZZLE_SELECT_FP_ONE << R300_SWIZZLE_SELECT_W_SHIFT) |
384 (0xf << R300_WRITE_ENA_SHIFT) ) << 0) |
385 (((R300_SWIZZLE_SELECT_X << R300_SWIZZLE_SELECT_X_SHIFT) |
386 (R300_SWIZZLE_SELECT_Y << R300_SWIZZLE_SELECT_Y_SHIFT) |
387 (R300_SWIZZLE_SELECT_FP_ZERO << R300_SWIZZLE_SELECT_Z_SHIFT) |
388 (R300_SWIZZLE_SELECT_FP_ONE << R300_SWIZZLE_SELECT_W_SHIFT) |
389 (0xf << R300_WRITE_ENA_SHIFT) ) << 16) ) );
390 OUT_BATCH_REGSEQ(R300_VAP_OUTPUT_VTX_FMT_0, 2);
391 OUT_BATCH(R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT);
392 OUT_BATCH(R300_VAP_OUTPUT_VTX_FMT_1__4_COMPONENTS);
393 END_BATCH();
394 }
395
396 static GLboolean validate_buffers(struct r300_context *r300,
397 struct radeon_bo *src_bo,
398 struct radeon_bo *dst_bo)
399 {
400 int ret;
401
402 radeon_cs_space_reset_bos(r300->radeon.cmdbuf.cs);
403
404 ret = radeon_cs_space_check_with_bo(r300->radeon.cmdbuf.cs,
405 src_bo, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 0);
406 if (ret)
407 return GL_FALSE;
408
409 ret = radeon_cs_space_check_with_bo(r300->radeon.cmdbuf.cs,
410 dst_bo, 0, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT);
411 if (ret)
412 return GL_FALSE;
413
414 return GL_TRUE;
415 }
416
417 /**
418 * Calculate texcoords for given image region.
419 * Output values are [minx, maxx, miny, maxy]
420 */
421 static void calc_tex_coords(float img_width, float img_height,
422 float x, float y,
423 float reg_width, float reg_height,
424 unsigned flip_y, float *buf)
425 {
426 buf[0] = x / img_width;
427 buf[1] = buf[0] + reg_width / img_width;
428 buf[2] = y / img_height;
429 buf[3] = buf[2] + reg_height / img_height;
430 if (flip_y)
431 {
432 buf[2] = 1.0 - buf[2];
433 buf[3] = 1.0 - buf[3];
434 }
435 }
436
437 static void emit_draw_packet(struct r300_context *r300,
438 unsigned src_width, unsigned src_height,
439 unsigned src_x_offset, unsigned src_y_offset,
440 unsigned dst_x_offset, unsigned dst_y_offset,
441 unsigned reg_width, unsigned reg_height,
442 unsigned flip_y)
443 {
444 float texcoords[4];
445
446 calc_tex_coords(src_width, src_height,
447 src_x_offset, src_y_offset,
448 reg_width, reg_height,
449 flip_y, texcoords);
450
451 float verts[] = { dst_x_offset, dst_y_offset,
452 texcoords[0], texcoords[2],
453 dst_x_offset, dst_y_offset + reg_height,
454 texcoords[0], texcoords[3],
455 dst_x_offset + reg_width, dst_y_offset + reg_height,
456 texcoords[1], texcoords[3],
457 dst_x_offset + reg_width, dst_y_offset,
458 texcoords[1], texcoords[2] };
459
460 BATCH_LOCALS(&r300->radeon);
461
462 BEGIN_BATCH(19);
463 OUT_BATCH_PACKET3(R300_PACKET3_3D_DRAW_IMMD_2, 16);
464 OUT_BATCH(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED |
465 (4 << 16) | R300_VAP_VF_CNTL__PRIM_QUADS);
466 OUT_BATCH_TABLE(verts, 16);
467 END_BATCH();
468 }
469
470 static void other_stuff(struct r300_context *r300)
471 {
472 BATCH_LOCALS(&r300->radeon);
473
474 BEGIN_BATCH(13);
475 OUT_BATCH_REGVAL(R300_GA_POLY_MODE,
476 R300_GA_POLY_MODE_FRONT_PTYPE_TRI | R300_GA_POLY_MODE_BACK_PTYPE_TRI);
477 OUT_BATCH_REGVAL(R300_SU_CULL_MODE, R300_FRONT_FACE_CCW);
478 OUT_BATCH_REGVAL(R300_FG_FOG_BLEND, 0);
479 OUT_BATCH_REGVAL(R300_FG_ALPHA_FUNC, 0);
480 OUT_BATCH_REGSEQ(R300_RB3D_CBLEND, 2);
481 OUT_BATCH(0x0);
482 OUT_BATCH(0x0);
483 OUT_BATCH_REGVAL(R300_ZB_CNTL, 0);
484 END_BATCH();
485 if (r300->options.hw_tcl_enabled) {
486 BEGIN_BATCH(2);
487 OUT_BATCH_REGVAL(R300_VAP_CLIP_CNTL, R300_CLIP_DISABLE);
488 END_BATCH();
489 }
490 }
491
492 static void emit_cb_setup(struct r300_context *r300,
493 struct radeon_bo *bo,
494 intptr_t offset,
495 gl_format mesa_format,
496 unsigned pitch,
497 unsigned width,
498 unsigned height)
499 {
500 BATCH_LOCALS(&r300->radeon);
501
502 unsigned x1, y1, x2, y2;
503 x1 = 0;
504 y1 = 0;
505 x2 = width - 1;
506 y2 = height - 1;
507
508 if (r300->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV515) {
509 x1 += R300_SCISSORS_OFFSET;
510 y1 += R300_SCISSORS_OFFSET;
511 x2 += R300_SCISSORS_OFFSET;
512 y2 += R300_SCISSORS_OFFSET;
513 }
514
515 r300_emit_cb_setup(r300, bo, offset, mesa_format,
516 _mesa_get_format_bytes(mesa_format),
517 _mesa_format_row_stride(mesa_format, pitch));
518
519 BEGIN_BATCH_NO_AUTOSTATE(5);
520 OUT_BATCH_REGSEQ(R300_SC_SCISSORS_TL, 2);
521 OUT_BATCH((x1 << R300_SCISSORS_X_SHIFT)|(y1 << R300_SCISSORS_Y_SHIFT));
522 OUT_BATCH((x2 << R300_SCISSORS_X_SHIFT)|(y2 << R300_SCISSORS_Y_SHIFT));
523 OUT_BATCH_REGVAL(R300_RB3D_CCTL, 0);
524 END_BATCH();
525 }
526
527 unsigned r300_check_blit(gl_format dst_format)
528 {
529 switch (dst_format) {
530 case MESA_FORMAT_RGB565:
531 case MESA_FORMAT_ARGB1555:
532 case MESA_FORMAT_RGBA8888:
533 case MESA_FORMAT_RGBA8888_REV:
534 case MESA_FORMAT_ARGB8888:
535 case MESA_FORMAT_ARGB8888_REV:
536 case MESA_FORMAT_XRGB8888:
537 break;
538 default:
539 return 0;
540 }
541
542 if (_mesa_get_format_bits(dst_format, GL_DEPTH_BITS) > 0)
543 return 0;
544
545 return 1;
546 }
547
548 /**
549 * Copy a region of [@a width x @a height] pixels from source buffer
550 * to destination buffer.
551 * @param[in] r300 r300 context
552 * @param[in] src_bo source radeon buffer object
553 * @param[in] src_offset offset of the source image in the @a src_bo
554 * @param[in] src_mesaformat source image format
555 * @param[in] src_pitch aligned source image width
556 * @param[in] src_width source image width
557 * @param[in] src_height source image height
558 * @param[in] src_x_offset x offset in the source image
559 * @param[in] src_y_offset y offset in the source image
560 * @param[in] dst_bo destination radeon buffer object
561 * @param[in] dst_offset offset of the destination image in the @a dst_bo
562 * @param[in] dst_mesaformat destination image format
563 * @param[in] dst_pitch aligned destination image width
564 * @param[in] dst_width destination image width
565 * @param[in] dst_height destination image height
566 * @param[in] dst_x_offset x offset in the destination image
567 * @param[in] dst_y_offset y offset in the destination image
568 * @param[in] width region width
569 * @param[in] height region height
570 * @param[in] flip_y set if y coords of the source image need to be flipped
571 */
572 unsigned r300_blit(GLcontext *ctx,
573 struct radeon_bo *src_bo,
574 intptr_t src_offset,
575 gl_format src_mesaformat,
576 unsigned src_pitch,
577 unsigned src_width,
578 unsigned src_height,
579 unsigned src_x_offset,
580 unsigned src_y_offset,
581 struct radeon_bo *dst_bo,
582 intptr_t dst_offset,
583 gl_format dst_mesaformat,
584 unsigned dst_pitch,
585 unsigned dst_width,
586 unsigned dst_height,
587 unsigned dst_x_offset,
588 unsigned dst_y_offset,
589 unsigned reg_width,
590 unsigned reg_height,
591 unsigned flip_y)
592 {
593 r300ContextPtr r300 = R300_CONTEXT(ctx);
594
595 if (!r300_check_blit(dst_mesaformat))
596 return 0;
597
598 /* Make sure that colorbuffer has even width - hw limitation */
599 if (dst_pitch % 2 > 0)
600 ++dst_pitch;
601
602 /* Need to clamp the region size to make sure
603 * we don't read outside of the source buffer
604 * or write outside of the destination buffer.
605 */
606 if (reg_width + src_x_offset > src_width)
607 reg_width = src_width - src_x_offset;
608 if (reg_height + src_y_offset > src_height)
609 reg_height = src_height - src_y_offset;
610 if (reg_width + dst_x_offset > dst_width)
611 reg_width = dst_width - dst_x_offset;
612 if (reg_height + dst_y_offset > dst_height)
613 reg_height = dst_height - dst_y_offset;
614
615 if (src_bo == dst_bo) {
616 return 0;
617 }
618
619 if (src_offset % 32 || dst_offset % 32) {
620 return GL_FALSE;
621 }
622
623 if (0) {
624 fprintf(stderr, "src: size [%d x %d], pitch %d, "
625 "offset [%d x %d], format %s, bo %p\n",
626 src_width, src_height, src_pitch,
627 src_x_offset, src_y_offset,
628 _mesa_get_format_name(src_mesaformat),
629 src_bo);
630 fprintf(stderr, "dst: pitch %d, offset[%d x %d], format %s, bo %p\n",
631 dst_pitch, dst_x_offset, dst_y_offset,
632 _mesa_get_format_name(dst_mesaformat), dst_bo);
633 fprintf(stderr, "region: %d x %d\n", reg_width, reg_height);
634 }
635
636 /* Flush is needed to make sure that source buffer has correct data */
637 radeonFlush(r300->radeon.glCtx);
638
639 if (!validate_buffers(r300, src_bo, dst_bo))
640 return 0;
641
642 rcommonEnsureCmdBufSpace(&r300->radeon, 200, __FUNCTION__);
643
644 other_stuff(r300);
645
646 r300_emit_tx_setup(r300, src_mesaformat, src_bo, src_offset, src_width, src_height, src_pitch);
647
648 if (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) {
649 r500_emit_fp_setup(r300, &r300->blit.fp_code.code.r500, dst_mesaformat);
650 r500_emit_rs_setup(r300);
651 } else {
652 r300_emit_fp_setup(r300, &r300->blit.fp_code.code.r300, dst_mesaformat);
653 r300_emit_rs_setup(r300);
654 }
655
656 if (r300->options.hw_tcl_enabled)
657 emit_pvs_setup(r300, r300->blit.vp_code.body.d, 2);
658
659 emit_vap_setup(r300);
660
661 emit_cb_setup(r300, dst_bo, dst_offset, dst_mesaformat, dst_pitch, dst_width, dst_height);
662
663 emit_draw_packet(r300, src_width, src_height,
664 src_x_offset, src_y_offset,
665 dst_x_offset, dst_y_offset,
666 reg_width, reg_height,
667 flip_y);
668
669 r300EmitCacheFlush(r300);
670
671 radeonFlush(r300->radeon.glCtx);
672
673 return 1;
674 }