2 * Copyright (C) 2009 Maciej Cencora <m.cencora@gmail.com>
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:
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.
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.
28 #include "radeon_common.h"
29 #include "r300_context.h"
31 #include "r300_blit.h"
32 #include "r300_cmdbuf.h"
33 #include "r300_emit.h"
35 #include "compiler/radeon_compiler.h"
36 #include "compiler/radeon_opcodes.h"
38 static void vp_ins_outs(struct r300_vertex_program_compiler
*c
)
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;
46 static void fp_allocate_hw_inputs(
47 struct r300_fragment_program_compiler
* c
,
48 void (*allocate
)(void * data
, unsigned input
, unsigned hwreg
),
51 allocate(mydata
, FRAG_ATTRIB_TEX0
, 0);
54 static void create_vertex_program(struct r300_context
*r300
)
56 struct r300_vertex_program_compiler compiler
;
57 struct rc_instruction
*inst
;
59 rc_init(&compiler
.Base
);
61 inst
= rc_insert_new_instruction(&compiler
.Base
, compiler
.Base
.Program
.Instructions
.Prev
);
62 inst
->U
.I
.Opcode
= RC_OPCODE_MOV
;
63 inst
->U
.I
.DstReg
.File
= RC_FILE_OUTPUT
;
64 inst
->U
.I
.DstReg
.Index
= VERT_RESULT_HPOS
;
65 inst
->U
.I
.DstReg
.RelAddr
= 0;
66 inst
->U
.I
.DstReg
.WriteMask
= RC_MASK_XYZW
;
67 inst
->U
.I
.SrcReg
[0].Abs
= 0;
68 inst
->U
.I
.SrcReg
[0].File
= RC_FILE_INPUT
;
69 inst
->U
.I
.SrcReg
[0].Index
= VERT_ATTRIB_POS
;
70 inst
->U
.I
.SrcReg
[0].Negate
= 0;
71 inst
->U
.I
.SrcReg
[0].RelAddr
= 0;
72 inst
->U
.I
.SrcReg
[0].Swizzle
= RC_SWIZZLE_XYZW
;
74 inst
= rc_insert_new_instruction(&compiler
.Base
, compiler
.Base
.Program
.Instructions
.Prev
);
75 inst
->U
.I
.Opcode
= RC_OPCODE_MOV
;
76 inst
->U
.I
.DstReg
.File
= RC_FILE_OUTPUT
;
77 inst
->U
.I
.DstReg
.Index
= VERT_RESULT_TEX0
;
78 inst
->U
.I
.DstReg
.RelAddr
= 0;
79 inst
->U
.I
.DstReg
.WriteMask
= RC_MASK_XYZW
;
80 inst
->U
.I
.SrcReg
[0].Abs
= 0;
81 inst
->U
.I
.SrcReg
[0].File
= RC_FILE_INPUT
;
82 inst
->U
.I
.SrcReg
[0].Index
= VERT_ATTRIB_TEX0
;
83 inst
->U
.I
.SrcReg
[0].Negate
= 0;
84 inst
->U
.I
.SrcReg
[0].RelAddr
= 0;
85 inst
->U
.I
.SrcReg
[0].Swizzle
= RC_SWIZZLE_XYZW
;
87 compiler
.Base
.Program
.InputsRead
= (1 << VERT_ATTRIB_POS
) | (1 << VERT_ATTRIB_TEX0
);
88 compiler
.RequiredOutputs
= compiler
.Base
.Program
.OutputsWritten
= (1 << VERT_RESULT_HPOS
) | (1 << VERT_RESULT_TEX0
);
89 compiler
.SetHwInputOutput
= vp_ins_outs
;
90 compiler
.code
= &r300
->blit
.vp_code
;
92 r3xx_compile_vertex_program(&compiler
);
95 static void create_fragment_program(struct r300_context
*r300
)
97 struct r300_fragment_program_compiler compiler
;
98 struct rc_instruction
*inst
;
100 memset(&compiler
, 0, sizeof(struct r300_fragment_program_compiler
));
101 rc_init(&compiler
.Base
);
103 inst
= rc_insert_new_instruction(&compiler
.Base
, compiler
.Base
.Program
.Instructions
.Prev
);
104 inst
->U
.I
.Opcode
= RC_OPCODE_TEX
;
105 inst
->U
.I
.TexSrcTarget
= RC_TEXTURE_2D
;
106 inst
->U
.I
.TexSrcUnit
= 0;
107 inst
->U
.I
.DstReg
.File
= RC_FILE_OUTPUT
;
108 inst
->U
.I
.DstReg
.Index
= FRAG_RESULT_COLOR
;
109 inst
->U
.I
.DstReg
.WriteMask
= RC_MASK_XYZW
;
110 inst
->U
.I
.SrcReg
[0].Abs
= 0;
111 inst
->U
.I
.SrcReg
[0].File
= RC_FILE_INPUT
;
112 inst
->U
.I
.SrcReg
[0].Index
= FRAG_ATTRIB_TEX0
;
113 inst
->U
.I
.SrcReg
[0].Negate
= 0;
114 inst
->U
.I
.SrcReg
[0].RelAddr
= 0;
115 inst
->U
.I
.SrcReg
[0].Swizzle
= RC_SWIZZLE_XYZW
;
117 compiler
.Base
.Program
.InputsRead
= (1 << FRAG_ATTRIB_TEX0
);
118 compiler
.OutputColor
[0] = FRAG_RESULT_COLOR
;
119 compiler
.OutputDepth
= FRAG_RESULT_DEPTH
;
120 compiler
.enable_shadow_ambient
= GL_TRUE
;
121 compiler
.is_r500
= (r300
->radeon
.radeonScreen
->chip_family
>= CHIP_FAMILY_RV515
);
122 compiler
.max_temp_regs
= (compiler
.is_r500
) ? 128 : 32;
123 compiler
.code
= &r300
->blit
.fp_code
;
124 compiler
.AllocateHwInputs
= fp_allocate_hw_inputs
;
126 r3xx_compile_fragment_program(&compiler
);
129 void r300_blit_init(struct r300_context
*r300
)
131 if (r300
->options
.hw_tcl_enabled
)
132 create_vertex_program(r300
);
133 create_fragment_program(r300
);
136 static void r300_emit_tx_setup(struct r300_context
*r300
,
137 gl_format mesa_format
,
138 struct radeon_bo
*bo
,
144 BATCH_LOCALS(&r300
->radeon
);
146 assert(width
<= 2048);
147 assert(height
<= 2048);
148 assert(r300TranslateTexFormat(mesa_format
) >= 0);
149 assert(offset
% 32 == 0);
152 OUT_BATCH_REGVAL(R300_TX_FILTER0_0
,
153 (R300_TX_CLAMP_TO_EDGE
<< R300_TX_WRAP_S_SHIFT
) |
154 (R300_TX_CLAMP_TO_EDGE
<< R300_TX_WRAP_T_SHIFT
) |
155 (R300_TX_CLAMP_TO_EDGE
<< R300_TX_WRAP_R_SHIFT
) |
156 R300_TX_MIN_FILTER_MIP_NONE
|
157 R300_TX_MIN_FILTER_NEAREST
|
158 R300_TX_MAG_FILTER_NEAREST
|
160 OUT_BATCH_REGVAL(R300_TX_FILTER1_0
, 0);
161 OUT_BATCH_REGVAL(R300_TX_SIZE_0
,
162 ((width
-1) << R300_TX_WIDTHMASK_SHIFT
) |
163 ((height
-1) << R300_TX_HEIGHTMASK_SHIFT
) |
164 (0 << R300_TX_DEPTHMASK_SHIFT
) |
165 (0 << R300_TX_MAX_MIP_LEVEL_SHIFT
) |
166 R300_TX_SIZE_TXPITCH_EN
);
168 OUT_BATCH_REGVAL(R300_TX_FORMAT_0
, r300TranslateTexFormat(mesa_format
));
169 OUT_BATCH_REGVAL(R300_TX_FORMAT2_0
, pitch
- 1);
170 OUT_BATCH_REGSEQ(R300_TX_OFFSET_0
, 1);
171 OUT_BATCH_RELOC(0, bo
, offset
, RADEON_GEM_DOMAIN_GTT
|RADEON_GEM_DOMAIN_VRAM
, 0, 0);
173 OUT_BATCH_REGSEQ(R300_TX_INVALTAGS
, 2);
180 #define EASY_US_FORMAT(FMT, C0, C1, C2, C3, SIGN) \
181 (FMT | R500_C0_SEL_##C0 | R500_C1_SEL_##C1 | \
182 R500_C2_SEL_##C2 | R500_C3_SEL_##C3 | R500_OUT_SIGN(SIGN))
184 static uint32_t mesa_format_to_us_format(gl_format mesa_format
)
188 case MESA_FORMAT_RGBA8888
: // x
189 return EASY_US_FORMAT(R500_OUT_FMT_C4_8
, A
, B
, G
, R
, 0);
190 case MESA_FORMAT_RGB565
: // x
191 case MESA_FORMAT_ARGB1555
: // x
192 case MESA_FORMAT_RGBA8888_REV
: // x
193 return EASY_US_FORMAT(R500_OUT_FMT_C4_8
, R
, G
, B
, A
, 0);
194 case MESA_FORMAT_ARGB8888
: // x
195 return EASY_US_FORMAT(R500_OUT_FMT_C4_8
, B
, G
, R
, A
, 0);
196 case MESA_FORMAT_ARGB8888_REV
:
197 return EASY_US_FORMAT(R500_OUT_FMT_C4_8
, A
, R
, G
, B
, 0);
198 case MESA_FORMAT_XRGB8888
:
199 return EASY_US_FORMAT(R500_OUT_FMT_C4_8
, A
, R
, G
, B
, 0);
201 case MESA_FORMAT_RGB332
:
202 return EASY_US_FORMAT(R500_OUT_FMT_C_3_3_2
, A
, R
, G
, B
, 0);
204 case MESA_FORMAT_RGBA_FLOAT32
:
205 return EASY_US_FORMAT(R500_OUT_FMT_C4_32_FP
, R
, G
, B
, A
, 0);
206 case MESA_FORMAT_RGBA_FLOAT16
:
207 return EASY_US_FORMAT(R500_OUT_FMT_C4_16_FP
, R
, G
, B
, A
, 0);
208 case MESA_FORMAT_ALPHA_FLOAT32
:
209 return EASY_US_FORMAT(R500_OUT_FMT_C_32_FP
, A
, A
, A
, A
, 0);
210 case MESA_FORMAT_ALPHA_FLOAT16
:
211 return EASY_US_FORMAT(R500_OUT_FMT_C_16_FP
, A
, A
, A
, A
, 0);
213 case MESA_FORMAT_SIGNED_RGBA8888
:
214 return EASY_US_FORMAT(R500_OUT_FMT_C4_8
, R
, G
, B
, A
, 0xf);
215 case MESA_FORMAT_SIGNED_RGBA8888_REV
:
216 return EASY_US_FORMAT(R500_OUT_FMT_C4_8
, A
, B
, G
, R
, 0xf);
217 case MESA_FORMAT_SIGNED_RGBA_16
:
218 return EASY_US_FORMAT(R500_OUT_FMT_C4_16
, R
, G
, B
, A
, 0xf);
221 fprintf(stderr
, "Unsupported format %s for US output\n", _mesa_get_format_name(mesa_format
));
226 #undef EASY_US_FORMAT
228 static void r500_emit_fp_setup(struct r300_context
*r300
,
229 struct r500_fragment_program_code
*fp
,
230 gl_format dst_format
)
232 r500_emit_fp(r300
, (uint32_t *)fp
->inst
, (fp
->inst_end
+ 1) * 6, 0, 0, 0);
233 BATCH_LOCALS(&r300
->radeon
);
236 OUT_BATCH_REGSEQ(R500_US_CODE_ADDR
, 3);
237 OUT_BATCH(R500_US_CODE_START_ADDR(0) | R500_US_CODE_END_ADDR(fp
->inst_end
));
238 OUT_BATCH(R500_US_CODE_RANGE_ADDR(0) | R500_US_CODE_RANGE_SIZE(fp
->inst_end
));
240 OUT_BATCH_REGVAL(R500_US_CONFIG
, 0);
241 OUT_BATCH_REGVAL(R500_US_OUT_FMT_0
, mesa_format_to_us_format(dst_format
));
242 OUT_BATCH_REGVAL(R500_US_PIXSIZE
, fp
->max_temp_idx
);
246 static void r500_emit_rs_setup(struct r300_context
*r300
)
248 BATCH_LOCALS(&r300
->radeon
);
251 OUT_BATCH_REGSEQ(R300_RS_COUNT
, 2);
252 OUT_BATCH((4 << R300_IT_COUNT_SHIFT
) | R300_HIRES_EN
);
254 OUT_BATCH_REGVAL(R500_RS_INST_0
,
255 (0 << R500_RS_INST_TEX_ID_SHIFT
) |
256 (0 << R500_RS_INST_TEX_ADDR_SHIFT
) |
257 R500_RS_INST_TEX_CN_WRITE
|
258 R500_RS_INST_COL_CN_NO_WRITE
);
259 OUT_BATCH_REGVAL(R500_RS_IP_0
,
260 (0 << R500_RS_IP_TEX_PTR_S_SHIFT
) |
261 (1 << R500_RS_IP_TEX_PTR_T_SHIFT
) |
262 (2 << R500_RS_IP_TEX_PTR_R_SHIFT
) |
263 (3 << R500_RS_IP_TEX_PTR_Q_SHIFT
));
267 static void r300_emit_fp_setup(struct r300_context
*r300
,
268 struct r300_fragment_program_code
*code
,
269 gl_format dst_format
)
272 BATCH_LOCALS(&r300
->radeon
);
274 BEGIN_BATCH((code
->alu
.length
+ 1) * 4 + code
->tex
.length
+ 1 + 11);
276 OUT_BATCH_REGSEQ(R300_US_ALU_RGB_INST_0
, code
->alu
.length
);
277 for (i
= 0; i
< code
->alu
.length
; i
++) {
278 OUT_BATCH(code
->alu
.inst
[i
].rgb_inst
);
280 OUT_BATCH_REGSEQ(R300_US_ALU_RGB_ADDR_0
, code
->alu
.length
);
281 for (i
= 0; i
< code
->alu
.length
; i
++) {
282 OUT_BATCH(code
->alu
.inst
[i
].rgb_addr
);
284 OUT_BATCH_REGSEQ(R300_US_ALU_ALPHA_INST_0
, code
->alu
.length
);
285 for (i
= 0; i
< code
->alu
.length
; i
++) {
286 OUT_BATCH(code
->alu
.inst
[i
].alpha_inst
);
288 OUT_BATCH_REGSEQ(R300_US_ALU_ALPHA_ADDR_0
, code
->alu
.length
);
289 for (i
= 0; i
< code
->alu
.length
; i
++) {
290 OUT_BATCH(code
->alu
.inst
[i
].alpha_addr
);
293 OUT_BATCH_REGSEQ(R300_US_TEX_INST_0
, code
->tex
.length
);
294 OUT_BATCH_TABLE(code
->tex
.inst
, code
->tex
.length
);
296 OUT_BATCH_REGSEQ(R300_US_CONFIG
, 3);
297 OUT_BATCH(R300_PFS_CNTL_FIRST_NODE_HAS_TEX
);
298 OUT_BATCH(code
->pixsize
);
299 OUT_BATCH(code
->code_offset
);
300 OUT_BATCH_REGSEQ(R300_US_CODE_ADDR_0
, 4);
301 OUT_BATCH_TABLE(code
->code_addr
, 4);
302 OUT_BATCH_REGVAL(R500_US_OUT_FMT_0
, mesa_format_to_us_format(dst_format
));
306 static void r300_emit_rs_setup(struct r300_context
*r300
)
308 BATCH_LOCALS(&r300
->radeon
);
311 OUT_BATCH_REGSEQ(R300_RS_COUNT
, 2);
312 OUT_BATCH((4 << R300_IT_COUNT_SHIFT
) | R300_HIRES_EN
);
314 OUT_BATCH_REGVAL(R300_RS_INST_0
,
315 R300_RS_INST_TEX_ID(0) |
316 R300_RS_INST_TEX_ADDR(0) |
317 R300_RS_INST_TEX_CN_WRITE
);
318 OUT_BATCH_REGVAL(R300_RS_IP_0
,
320 R300_RS_SEL_S(R300_RS_SEL_C0
) |
321 R300_RS_SEL_T(R300_RS_SEL_C1
) |
322 R300_RS_SEL_R(R300_RS_SEL_K0
) |
323 R300_RS_SEL_Q(R300_RS_SEL_K1
));
327 static void emit_pvs_setup(struct r300_context
*r300
,
331 BATCH_LOCALS(&r300
->radeon
);
333 r300_emit_vpu(r300
, vp_code
, vp_len
* 4, R300_PVS_CODE_START
);
336 OUT_BATCH_REGSEQ(R300_VAP_PVS_CODE_CNTL_0
, 3);
337 OUT_BATCH((0 << R300_PVS_FIRST_INST_SHIFT
) |
338 ((vp_len
- 1) << R300_PVS_XYZW_VALID_INST_SHIFT
) |
339 ((vp_len
- 1)<< R300_PVS_LAST_INST_SHIFT
));
341 OUT_BATCH((vp_len
- 1) << R300_PVS_LAST_VTX_SRC_INST_SHIFT
);
345 static void emit_vap_setup(struct r300_context
*r300
)
348 BATCH_LOCALS(&r300
->radeon
);
350 if (r300
->options
.hw_tcl_enabled
)
356 OUT_BATCH_REGSEQ(R300_SE_VTE_CNTL
, 2);
357 OUT_BATCH(R300_VTX_XY_FMT
| R300_VTX_Z_FMT
);
360 OUT_BATCH_REGVAL(R300_VAP_PSC_SGN_NORM_CNTL
, 0xaaaaaaaa);
361 OUT_BATCH_REGVAL(R300_VAP_PROG_STREAM_CNTL_0
,
362 ((R300_DATA_TYPE_FLOAT_2
| (0 << R300_DST_VEC_LOC_SHIFT
)) << 0) |
363 (((tex_offset
<< R300_DST_VEC_LOC_SHIFT
) | R300_DATA_TYPE_FLOAT_2
| R300_LAST_VEC
) << 16));
364 OUT_BATCH_REGVAL(R300_VAP_PROG_STREAM_CNTL_EXT_0
,
365 ((((R300_SWIZZLE_SELECT_X
<< R300_SWIZZLE_SELECT_X_SHIFT
) |
366 (R300_SWIZZLE_SELECT_Y
<< R300_SWIZZLE_SELECT_Y_SHIFT
) |
367 (R300_SWIZZLE_SELECT_FP_ZERO
<< R300_SWIZZLE_SELECT_Z_SHIFT
) |
368 (R300_SWIZZLE_SELECT_FP_ONE
<< R300_SWIZZLE_SELECT_W_SHIFT
) |
369 (0xf << R300_WRITE_ENA_SHIFT
) ) << 0) |
370 (((R300_SWIZZLE_SELECT_X
<< R300_SWIZZLE_SELECT_X_SHIFT
) |
371 (R300_SWIZZLE_SELECT_Y
<< R300_SWIZZLE_SELECT_Y_SHIFT
) |
372 (R300_SWIZZLE_SELECT_FP_ZERO
<< R300_SWIZZLE_SELECT_Z_SHIFT
) |
373 (R300_SWIZZLE_SELECT_FP_ONE
<< R300_SWIZZLE_SELECT_W_SHIFT
) |
374 (0xf << R300_WRITE_ENA_SHIFT
) ) << 16) ) );
375 OUT_BATCH_REGSEQ(R300_VAP_OUTPUT_VTX_FMT_0
, 2);
376 OUT_BATCH(R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT
);
377 OUT_BATCH(R300_VAP_OUTPUT_VTX_FMT_1__4_COMPONENTS
);
381 static GLboolean
validate_buffers(struct r300_context
*r300
,
382 struct radeon_bo
*src_bo
,
383 struct radeon_bo
*dst_bo
)
387 radeon_cs_space_reset_bos(r300
->radeon
.cmdbuf
.cs
);
389 ret
= radeon_cs_space_check_with_bo(r300
->radeon
.cmdbuf
.cs
,
390 src_bo
, RADEON_GEM_DOMAIN_VRAM
| RADEON_GEM_DOMAIN_GTT
, 0);
394 ret
= radeon_cs_space_check_with_bo(r300
->radeon
.cmdbuf
.cs
,
395 dst_bo
, 0, RADEON_GEM_DOMAIN_VRAM
| RADEON_GEM_DOMAIN_GTT
);
403 * Calculate texcoords for given image region.
404 * Output values are [minx, maxx, miny, maxy]
406 static void calc_tex_coords(float img_width
, float img_height
,
408 float reg_width
, float reg_height
,
409 unsigned flip_y
, float *buf
)
411 buf
[0] = x
/ img_width
;
412 buf
[1] = buf
[0] + reg_width
/ img_width
;
413 buf
[2] = y
/ img_height
;
414 buf
[3] = buf
[2] + reg_height
/ img_height
;
417 buf
[2] = 1.0 - buf
[2];
418 buf
[3] = 1.0 - buf
[3];
422 static void emit_draw_packet(struct r300_context
*r300
,
423 unsigned src_width
, unsigned src_height
,
424 unsigned src_x_offset
, unsigned src_y_offset
,
425 unsigned dst_x_offset
, unsigned dst_y_offset
,
426 unsigned reg_width
, unsigned reg_height
,
431 calc_tex_coords(src_width
, src_height
,
432 src_x_offset
, src_y_offset
,
433 reg_width
, reg_height
,
436 float verts
[] = { dst_x_offset
, dst_y_offset
,
437 texcoords
[0], texcoords
[2],
438 dst_x_offset
, dst_y_offset
+ reg_height
,
439 texcoords
[0], texcoords
[3],
440 dst_x_offset
+ reg_width
, dst_y_offset
+ reg_height
,
441 texcoords
[1], texcoords
[3],
442 dst_x_offset
+ reg_width
, dst_y_offset
,
443 texcoords
[1], texcoords
[2] };
445 BATCH_LOCALS(&r300
->radeon
);
448 OUT_BATCH_PACKET3(R300_PACKET3_3D_DRAW_IMMD_2
, 16);
449 OUT_BATCH(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED
|
450 (4 << 16) | R300_VAP_VF_CNTL__PRIM_QUADS
);
451 OUT_BATCH_TABLE(verts
, 16);
455 static void other_stuff(struct r300_context
*r300
)
457 BATCH_LOCALS(&r300
->radeon
);
460 OUT_BATCH_REGVAL(R300_GA_POLY_MODE
,
461 R300_GA_POLY_MODE_FRONT_PTYPE_TRI
| R300_GA_POLY_MODE_BACK_PTYPE_TRI
);
462 OUT_BATCH_REGVAL(R300_SU_CULL_MODE
, R300_FRONT_FACE_CCW
);
463 OUT_BATCH_REGVAL(R300_FG_FOG_BLEND
, 0);
464 OUT_BATCH_REGVAL(R300_FG_ALPHA_FUNC
, 0);
465 OUT_BATCH_REGSEQ(R300_RB3D_CBLEND
, 2);
468 OUT_BATCH_REGVAL(R300_ZB_CNTL
, 0);
470 if (r300
->options
.hw_tcl_enabled
) {
472 OUT_BATCH_REGVAL(R300_VAP_CLIP_CNTL
, R300_CLIP_DISABLE
);
477 static void emit_cb_setup(struct r300_context
*r300
,
478 struct radeon_bo
*bo
,
480 gl_format mesa_format
,
485 BATCH_LOCALS(&r300
->radeon
);
487 unsigned x1
, y1
, x2
, y2
;
493 if (r300
->radeon
.radeonScreen
->chip_family
< CHIP_FAMILY_RV515
) {
494 x1
+= R300_SCISSORS_OFFSET
;
495 y1
+= R300_SCISSORS_OFFSET
;
496 x2
+= R300_SCISSORS_OFFSET
;
497 y2
+= R300_SCISSORS_OFFSET
;
500 r300_emit_cb_setup(r300
, bo
, offset
, mesa_format
,
501 _mesa_get_format_bytes(mesa_format
),
502 _mesa_format_row_stride(mesa_format
, pitch
));
504 BEGIN_BATCH_NO_AUTOSTATE(5);
505 OUT_BATCH_REGSEQ(R300_SC_SCISSORS_TL
, 2);
506 OUT_BATCH((x1
<< R300_SCISSORS_X_SHIFT
)|(y1
<< R300_SCISSORS_Y_SHIFT
));
507 OUT_BATCH((x2
<< R300_SCISSORS_X_SHIFT
)|(y2
<< R300_SCISSORS_Y_SHIFT
));
508 OUT_BATCH_REGVAL(R300_RB3D_CCTL
, 0);
512 unsigned r300_check_blit(gl_format dst_format
)
514 switch (dst_format
) {
515 case MESA_FORMAT_RGB565
:
516 case MESA_FORMAT_ARGB1555
:
517 case MESA_FORMAT_RGBA8888
:
518 case MESA_FORMAT_RGBA8888_REV
:
519 case MESA_FORMAT_ARGB8888
:
520 case MESA_FORMAT_ARGB8888_REV
:
521 case MESA_FORMAT_XRGB8888
:
527 if (_mesa_get_format_bits(dst_format
, GL_DEPTH_BITS
) > 0)
534 * Copy a region of [@a width x @a height] pixels from source buffer
535 * to destination buffer.
536 * @param[in] r300 r300 context
537 * @param[in] src_bo source radeon buffer object
538 * @param[in] src_offset offset of the source image in the @a src_bo
539 * @param[in] src_mesaformat source image format
540 * @param[in] src_pitch aligned source image width
541 * @param[in] src_width source image width
542 * @param[in] src_height source image height
543 * @param[in] src_x_offset x offset in the source image
544 * @param[in] src_y_offset y offset in the source image
545 * @param[in] dst_bo destination radeon buffer object
546 * @param[in] dst_offset offset of the destination image in the @a dst_bo
547 * @param[in] dst_mesaformat destination image format
548 * @param[in] dst_pitch aligned destination image width
549 * @param[in] dst_width destination image width
550 * @param[in] dst_height destination image height
551 * @param[in] dst_x_offset x offset in the destination image
552 * @param[in] dst_y_offset y offset in the destination image
553 * @param[in] width region width
554 * @param[in] height region height
555 * @param[in] flip_y set if y coords of the source image need to be flipped
557 unsigned r300_blit(GLcontext
*ctx
,
558 struct radeon_bo
*src_bo
,
560 gl_format src_mesaformat
,
564 unsigned src_x_offset
,
565 unsigned src_y_offset
,
566 struct radeon_bo
*dst_bo
,
568 gl_format dst_mesaformat
,
572 unsigned dst_x_offset
,
573 unsigned dst_y_offset
,
578 r300ContextPtr r300
= R300_CONTEXT(ctx
);
580 if (!r300_check_blit(dst_mesaformat
))
583 /* Make sure that colorbuffer has even width - hw limitation */
584 if (dst_pitch
% 2 > 0)
587 /* Need to clamp the region size to make sure
588 * we don't read outside of the source buffer
589 * or write outside of the destination buffer.
591 if (reg_width
+ src_x_offset
> src_width
)
592 reg_width
= src_width
- src_x_offset
;
593 if (reg_height
+ src_y_offset
> src_height
)
594 reg_height
= src_height
- src_y_offset
;
595 if (reg_width
+ dst_x_offset
> dst_width
)
596 reg_width
= dst_width
- dst_x_offset
;
597 if (reg_height
+ dst_y_offset
> dst_height
)
598 reg_height
= dst_height
- dst_y_offset
;
600 if (src_bo
== dst_bo
) {
604 if (src_offset
% 32 || dst_offset
% 32) {
609 fprintf(stderr
, "src: size [%d x %d], pitch %d, "
610 "offset [%d x %d], format %s, bo %p\n",
611 src_width
, src_height
, src_pitch
,
612 src_x_offset
, src_y_offset
,
613 _mesa_get_format_name(src_mesaformat
),
615 fprintf(stderr
, "dst: pitch %d, offset[%d x %d], format %s, bo %p\n",
616 dst_pitch
, dst_x_offset
, dst_y_offset
,
617 _mesa_get_format_name(dst_mesaformat
), dst_bo
);
618 fprintf(stderr
, "region: %d x %d\n", reg_width
, reg_height
);
621 /* Flush is needed to make sure that source buffer has correct data */
622 radeonFlush(r300
->radeon
.glCtx
);
624 if (!validate_buffers(r300
, src_bo
, dst_bo
))
627 rcommonEnsureCmdBufSpace(&r300
->radeon
, 200, __FUNCTION__
);
631 r300_emit_tx_setup(r300
, src_mesaformat
, src_bo
, src_offset
, src_width
, src_height
, src_pitch
);
633 if (r300
->radeon
.radeonScreen
->chip_family
>= CHIP_FAMILY_RV515
) {
634 r500_emit_fp_setup(r300
, &r300
->blit
.fp_code
.code
.r500
, dst_mesaformat
);
635 r500_emit_rs_setup(r300
);
637 r300_emit_fp_setup(r300
, &r300
->blit
.fp_code
.code
.r300
, dst_mesaformat
);
638 r300_emit_rs_setup(r300
);
641 if (r300
->options
.hw_tcl_enabled
)
642 emit_pvs_setup(r300
, r300
->blit
.vp_code
.body
.d
, 2);
644 emit_vap_setup(r300
);
646 emit_cb_setup(r300
, dst_bo
, dst_offset
, dst_mesaformat
, dst_pitch
, dst_width
, dst_height
);
648 emit_draw_packet(r300
, src_width
, src_height
,
649 src_x_offset
, src_y_offset
,
650 dst_x_offset
, dst_y_offset
,
651 reg_width
, reg_height
,
654 r300EmitCacheFlush(r300
);
656 radeonFlush(r300
->radeon
.glCtx
);