1 /* 2 * Copyright (C) 2009 Maciej Cencora <m.cencora (at) 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 "r200_context.h" 30 #include "r200_blit.h" 31 32 static inline uint32_t cmdpacket0(struct radeon_screen *rscrn, 33 int reg, int count) 34 { 35 if (count) 36 return CP_PACKET0(reg, count - 1); 37 return CP_PACKET2; 38 } 39 40 /* common formats supported as both textures and render targets */ 41 unsigned r200_check_blit(gl_format mesa_format, uint32_t dst_pitch) 42 { 43 /* XXX others? BE/LE? */ 44 switch (mesa_format) { 45 case MESA_FORMAT_ARGB8888: 46 case MESA_FORMAT_XRGB8888: 47 case MESA_FORMAT_RGB565: 48 case MESA_FORMAT_ARGB4444: 49 case MESA_FORMAT_ARGB1555: 50 case MESA_FORMAT_A8: 51 case MESA_FORMAT_L8: 52 case MESA_FORMAT_I8: 53 /* swizzled */ 54 case MESA_FORMAT_RGBA8888: 55 case MESA_FORMAT_RGBA8888_REV: 56 break; 57 default: 58 return 0; 59 } 60 61 /* Rendering to small buffer doesn't work. 62 * Looks like a hw limitation. 63 */ 64 if (dst_pitch < 32) 65 return 0; 66 67 /* ??? */ 68 if (_mesa_get_format_bits(mesa_format, GL_DEPTH_BITS) > 0) 69 return 0; 70 71 return 1; 72 } 73 74 static inline void emit_vtx_state(struct r200_context *r200) 75 { 76 BATCH_LOCALS(&r200->radeon); 77 78 BEGIN_BATCH(14); 79 if (r200->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) { 80 OUT_BATCH_REGVAL(R200_SE_VAP_CNTL_STATUS, 0); 81 } else { 82 OUT_BATCH_REGVAL(R200_SE_VAP_CNTL_STATUS, RADEON_TCL_BYPASS); 83 } 84 OUT_BATCH_REGVAL(R200_SE_VAP_CNTL, (R200_VAP_FORCE_W_TO_ONE | 85 (9 << R200_VAP_VF_MAX_VTX_NUM__SHIFT))); 86 OUT_BATCH_REGVAL(R200_SE_VTX_STATE_CNTL, 0); 87 OUT_BATCH_REGVAL(R200_SE_VTE_CNTL, 0); 88 OUT_BATCH_REGVAL(R200_SE_VTX_FMT_0, R200_VTX_XY); 89 OUT_BATCH_REGVAL(R200_SE_VTX_FMT_1, (2 << R200_VTX_TEX0_COMP_CNT_SHIFT)); 90 OUT_BATCH_REGVAL(RADEON_SE_CNTL, (RADEON_DIFFUSE_SHADE_GOURAUD | 91 RADEON_BFACE_SOLID | 92 RADEON_FFACE_SOLID | 93 RADEON_VTX_PIX_CENTER_OGL | 94 RADEON_ROUND_MODE_ROUND | 95 RADEON_ROUND_PREC_4TH_PIX)); 96 END_BATCH(); 97 } 98 99 static void inline emit_tx_setup(struct r200_context *r200, 100 gl_format src_mesa_format, 101 gl_format dst_mesa_format, 102 struct radeon_bo *bo, 103 intptr_t offset, 104 unsigned width, 105 unsigned height, 106 unsigned pitch) 107 { 108 uint32_t txformat = R200_TXFORMAT_NON_POWER2; 109 BATCH_LOCALS(&r200->radeon); 110 111 assert(width <= 2048); 112 assert(height <= 2048); 113 assert(offset % 32 == 0); 114 115 /* XXX others? BE/LE? */ 116 switch (src_mesa_format) { 117 case MESA_FORMAT_ARGB8888: 118 txformat |= R200_TXFORMAT_ARGB8888 | R200_TXFORMAT_ALPHA_IN_MAP; 119 break; 120 case MESA_FORMAT_RGBA8888: 121 txformat |= R200_TXFORMAT_RGBA8888 | R200_TXFORMAT_ALPHA_IN_MAP; 122 break; 123 case MESA_FORMAT_RGBA8888_REV: 124 txformat |= R200_TXFORMAT_ABGR8888 | R200_TXFORMAT_ALPHA_IN_MAP; 125 break; 126 case MESA_FORMAT_XRGB8888: 127 txformat |= R200_TXFORMAT_ARGB8888; 128 break; 129 case MESA_FORMAT_RGB565: 130 txformat |= R200_TXFORMAT_RGB565; 131 break; 132 case MESA_FORMAT_ARGB4444: 133 txformat |= R200_TXFORMAT_ARGB4444 | R200_TXFORMAT_ALPHA_IN_MAP; 134 break; 135 case MESA_FORMAT_ARGB1555: 136 txformat |= R200_TXFORMAT_ARGB1555 | R200_TXFORMAT_ALPHA_IN_MAP; 137 break; 138 case MESA_FORMAT_A8: 139 case MESA_FORMAT_I8: 140 txformat |= R200_TXFORMAT_I8 | R200_TXFORMAT_ALPHA_IN_MAP; 141 break; 142 case MESA_FORMAT_L8: 143 txformat |= R200_TXFORMAT_I8; 144 break; 145 case MESA_FORMAT_AL88: 146 txformat |= R200_TXFORMAT_AI88 | R200_TXFORMAT_ALPHA_IN_MAP; 147 break; 148 default: 149 break; 150 } 151 152 if (bo->flags & RADEON_BO_FLAGS_MACRO_TILE) 153 offset |= R200_TXO_MACRO_TILE; 154 if (bo->flags & RADEON_BO_FLAGS_MICRO_TILE) 155 offset |= R200_TXO_MICRO_TILE; 156 157 switch (dst_mesa_format) { 158 case MESA_FORMAT_ARGB8888: 159 case MESA_FORMAT_XRGB8888: 160 case MESA_FORMAT_RGB565: 161 case MESA_FORMAT_ARGB4444: 162 case MESA_FORMAT_ARGB1555: 163 case MESA_FORMAT_A8: 164 case MESA_FORMAT_L8: 165 case MESA_FORMAT_I8: 166 default: 167 /* no swizzle required */ 168 BEGIN_BATCH(10); 169 OUT_BATCH_REGVAL(RADEON_PP_CNTL, (RADEON_TEX_0_ENABLE | 170 RADEON_TEX_BLEND_0_ENABLE)); 171 OUT_BATCH_REGVAL(R200_PP_TXCBLEND_0, (R200_TXC_ARG_A_ZERO | 172 R200_TXC_ARG_B_ZERO | 173 R200_TXC_ARG_C_R0_COLOR | 174 R200_TXC_OP_MADD)); 175 OUT_BATCH_REGVAL(R200_PP_TXCBLEND2_0, (R200_TXC_CLAMP_0_1 | 176 R200_TXC_OUTPUT_REG_R0)); 177 OUT_BATCH_REGVAL(R200_PP_TXABLEND_0, (R200_TXA_ARG_A_ZERO | 178 R200_TXA_ARG_B_ZERO | 179 R200_TXA_ARG_C_R0_ALPHA | 180 R200_TXA_OP_MADD)); 181 OUT_BATCH_REGVAL(R200_PP_TXABLEND2_0, (R200_TXA_CLAMP_0_1 | 182 R200_TXA_OUTPUT_REG_R0)); 183 END_BATCH(); 184 break; 185 case MESA_FORMAT_RGBA8888: 186 BEGIN_BATCH(10); 187 OUT_BATCH_REGVAL(RADEON_PP_CNTL, (RADEON_TEX_0_ENABLE | 188 RADEON_TEX_BLEND_0_ENABLE)); 189 OUT_BATCH_REGVAL(R200_PP_TXCBLEND_0, (R200_TXC_ARG_A_ZERO | 190 R200_TXC_ARG_B_ZERO | 191 R200_TXC_ARG_C_R0_COLOR | 192 R200_TXC_OP_MADD)); 193 OUT_BATCH_REGVAL(R200_PP_TXCBLEND2_0, (R200_TXC_CLAMP_0_1 | 194 R200_TXC_OUTPUT_ROTATE_GBA | 195 R200_TXC_OUTPUT_REG_R0)); 196 OUT_BATCH_REGVAL(R200_PP_TXABLEND_0, (R200_TXA_ARG_A_ZERO | 197 R200_TXA_ARG_B_ZERO | 198 R200_TXA_ARG_C_R0_ALPHA | 199 R200_TXA_OP_MADD)); 200 OUT_BATCH_REGVAL(R200_PP_TXABLEND2_0, (R200_TXA_CLAMP_0_1 | 201 (R200_TXA_REPL_RED << R200_TXA_REPL_ARG_C_SHIFT) | 202 R200_TXA_OUTPUT_REG_R0)); 203 END_BATCH(); 204 break; 205 case MESA_FORMAT_RGBA8888_REV: 206 BEGIN_BATCH(34); 207 OUT_BATCH_REGVAL(RADEON_PP_CNTL, (RADEON_TEX_0_ENABLE | 208 RADEON_TEX_BLEND_0_ENABLE | 209 RADEON_TEX_BLEND_1_ENABLE | 210 RADEON_TEX_BLEND_2_ENABLE | 211 RADEON_TEX_BLEND_3_ENABLE)); 212 /* r1.r = r0.b */ 213 OUT_BATCH_REGVAL(R200_PP_TXCBLEND_0, (R200_TXC_ARG_A_ZERO | 214 R200_TXC_ARG_B_ZERO | 215 R200_TXC_ARG_C_R0_COLOR | 216 R200_TXC_OP_MADD)); 217 OUT_BATCH_REGVAL(R200_PP_TXCBLEND2_0, (R200_TXC_CLAMP_0_1 | 218 R200_TXC_OUTPUT_MASK_R | 219 (R200_TXC_REPL_BLUE << R200_TXC_REPL_ARG_C_SHIFT) | 220 R200_TXC_OUTPUT_REG_R1)); 221 /* r1.a = r0.a */ 222 OUT_BATCH_REGVAL(R200_PP_TXABLEND_0, (R200_TXA_ARG_A_ZERO | 223 R200_TXA_ARG_B_ZERO | 224 R200_TXA_ARG_C_R0_ALPHA | 225 R200_TXA_OP_MADD)); 226 OUT_BATCH_REGVAL(R200_PP_TXABLEND2_0, (R200_TXA_CLAMP_0_1 | 227 R200_TXA_OUTPUT_REG_R1)); 228 /* r1.g = r0.g */ 229 OUT_BATCH_REGVAL(R200_PP_TXCBLEND_1, (R200_TXC_ARG_A_ZERO | 230 R200_TXC_ARG_B_ZERO | 231 R200_TXC_ARG_C_R0_COLOR | 232 R200_TXC_OP_MADD)); 233 OUT_BATCH_REGVAL(R200_PP_TXCBLEND2_1, (R200_TXC_CLAMP_0_1 | 234 R200_TXC_OUTPUT_MASK_G | 235 (R200_TXC_REPL_GREEN << R200_TXC_REPL_ARG_C_SHIFT) | 236 R200_TXC_OUTPUT_REG_R1)); 237 /* r1.a = r0.a */ 238 OUT_BATCH_REGVAL(R200_PP_TXABLEND_1, (R200_TXA_ARG_A_ZERO | 239 R200_TXA_ARG_B_ZERO | 240 R200_TXA_ARG_C_R0_ALPHA | 241 R200_TXA_OP_MADD)); 242 OUT_BATCH_REGVAL(R200_PP_TXABLEND2_1, (R200_TXA_CLAMP_0_1 | 243 R200_TXA_OUTPUT_REG_R1)); 244 /* r1.b = r0.r */ 245 OUT_BATCH_REGVAL(R200_PP_TXCBLEND_2, (R200_TXC_ARG_A_ZERO | 246 R200_TXC_ARG_B_ZERO | 247 R200_TXC_ARG_C_R0_COLOR | 248 R200_TXC_OP_MADD)); 249 OUT_BATCH_REGVAL(R200_PP_TXCBLEND2_2, (R200_TXC_CLAMP_0_1 | 250 R200_TXC_OUTPUT_MASK_B | 251 (R200_TXC_REPL_RED << R200_TXC_REPL_ARG_C_SHIFT) | 252 R200_TXC_OUTPUT_REG_R1)); 253 /* r1.a = r0.a */ 254 OUT_BATCH_REGVAL(R200_PP_TXABLEND_2, (R200_TXA_ARG_A_ZERO | 255 R200_TXA_ARG_B_ZERO | 256 R200_TXA_ARG_C_R0_ALPHA | 257 R200_TXA_OP_MADD)); 258 OUT_BATCH_REGVAL(R200_PP_TXABLEND2_2, (R200_TXA_CLAMP_0_1 | 259 R200_TXA_OUTPUT_REG_R1)); 260 /* r0.rgb = r1.rgb */ 261 OUT_BATCH_REGVAL(R200_PP_TXCBLEND_3, (R200_TXC_ARG_A_ZERO | 262 R200_TXC_ARG_B_ZERO | 263 R200_TXC_ARG_C_R1_COLOR | 264 R200_TXC_OP_MADD)); 265 OUT_BATCH_REGVAL(R200_PP_TXCBLEND2_3, (R200_TXC_CLAMP_0_1 | 266 R200_TXC_OUTPUT_REG_R0)); 267 /* r0.a = r1.a */ 268 OUT_BATCH_REGVAL(R200_PP_TXABLEND_3, (R200_TXA_ARG_A_ZERO | 269 R200_TXA_ARG_B_ZERO | 270 R200_TXA_ARG_C_R1_ALPHA | 271 R200_TXA_OP_MADD)); 272 OUT_BATCH_REGVAL(R200_PP_TXABLEND2_3, (R200_TXA_CLAMP_0_1 | 273 R200_TXA_OUTPUT_REG_R0)); 274 END_BATCH(); 275 break; 276 } 277 278 BEGIN_BATCH(18); 279 OUT_BATCH_REGVAL(R200_PP_CNTL_X, 0); 280 OUT_BATCH_REGVAL(R200_PP_TXMULTI_CTL_0, 0); 281 OUT_BATCH_REGVAL(R200_PP_TXFILTER_0, (R200_CLAMP_S_CLAMP_LAST | 282 R200_CLAMP_T_CLAMP_LAST | 283 R200_MAG_FILTER_NEAREST | 284 R200_MIN_FILTER_NEAREST)); 285 OUT_BATCH_REGVAL(R200_PP_TXFORMAT_0, txformat); 286 OUT_BATCH_REGVAL(R200_PP_TXFORMAT_X_0, 0); 287 OUT_BATCH_REGVAL(R200_PP_TXSIZE_0, ((width - 1) | 288 ((height - 1) << RADEON_TEX_VSIZE_SHIFT))); 289 OUT_BATCH_REGVAL(R200_PP_TXPITCH_0, pitch * _mesa_get_format_bytes(src_mesa_format) - 32); 290 291 OUT_BATCH_REGSEQ(R200_PP_TXOFFSET_0, 1); 292 OUT_BATCH_RELOC(offset, bo, offset, RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0); 293 294 END_BATCH(); 295 } 296 297 static inline void emit_cb_setup(struct r200_context *r200, 298 struct radeon_bo *bo, 299 intptr_t offset, 300 gl_format mesa_format, 301 unsigned pitch, 302 unsigned width, 303 unsigned height) 304 { 305 uint32_t dst_pitch = pitch; 306 uint32_t dst_format = 0; 307 BATCH_LOCALS(&r200->radeon); 308 309 /* XXX others? BE/LE? */ 310 switch (mesa_format) { 311 case MESA_FORMAT_ARGB8888: 312 case MESA_FORMAT_XRGB8888: 313 case MESA_FORMAT_RGBA8888: 314 case MESA_FORMAT_RGBA8888_REV: 315 dst_format = RADEON_COLOR_FORMAT_ARGB8888; 316 break; 317 case MESA_FORMAT_RGB565: 318 dst_format = RADEON_COLOR_FORMAT_RGB565; 319 break; 320 case MESA_FORMAT_ARGB4444: 321 dst_format = RADEON_COLOR_FORMAT_ARGB4444; 322 break; 323 case MESA_FORMAT_ARGB1555: 324 dst_format = RADEON_COLOR_FORMAT_ARGB1555; 325 break; 326 case MESA_FORMAT_A8: 327 case MESA_FORMAT_L8: 328 case MESA_FORMAT_I8: 329 dst_format = RADEON_COLOR_FORMAT_RGB8; 330 break; 331 default: 332 break; 333 } 334 335 if (bo->flags & RADEON_BO_FLAGS_MACRO_TILE) 336 dst_pitch |= R200_COLOR_TILE_ENABLE; 337 if (bo->flags & RADEON_BO_FLAGS_MICRO_TILE) 338 dst_pitch |= R200_COLOR_MICROTILE_ENABLE; 339 340 BEGIN_BATCH_NO_AUTOSTATE(22); 341 OUT_BATCH_REGVAL(R200_RE_AUX_SCISSOR_CNTL, 0); 342 OUT_BATCH_REGVAL(R200_RE_CNTL, 0); 343 OUT_BATCH_REGVAL(RADEON_RE_TOP_LEFT, 0); 344 OUT_BATCH_REGVAL(RADEON_RE_WIDTH_HEIGHT, (((width - 1) << RADEON_RE_WIDTH_SHIFT) | 345 ((height - 1) << RADEON_RE_HEIGHT_SHIFT))); 346 OUT_BATCH_REGVAL(RADEON_RB3D_PLANEMASK, 0xffffffff); 347 OUT_BATCH_REGVAL(RADEON_RB3D_BLENDCNTL, RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ZERO); 348 OUT_BATCH_REGVAL(RADEON_RB3D_CNTL, dst_format); 349 350 OUT_BATCH_REGSEQ(RADEON_RB3D_COLOROFFSET, 1); 351 OUT_BATCH_RELOC(offset, bo, offset, 0, RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0); 352 OUT_BATCH_REGSEQ(RADEON_RB3D_COLORPITCH, 1); 353 OUT_BATCH_RELOC(dst_pitch, bo, dst_pitch, 0, RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0); 354 355 END_BATCH(); 356 } 357 358 static GLboolean validate_buffers(struct r200_context *r200, 359 struct radeon_bo *src_bo, 360 struct radeon_bo *dst_bo) 361 { 362 int ret; 363 364 radeon_cs_space_reset_bos(r200->radeon.cmdbuf.cs); 365 366 ret = radeon_cs_space_check_with_bo(r200->radeon.cmdbuf.cs, 367 src_bo, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 0); 368 if (ret) 369 return GL_FALSE; 370 371 ret = radeon_cs_space_check_with_bo(r200->radeon.cmdbuf.cs, 372 dst_bo, 0, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT); 373 if (ret) 374 return GL_FALSE; 375 376 return GL_TRUE; 377 } 378 379 /** 380 * Calculate texcoords for given image region. 381 * Output values are [minx, maxx, miny, maxy] 382 */ 383 static inline void calc_tex_coords(float img_width, float img_height, 384 float x, float y, 385 float reg_width, float reg_height, 386 unsigned flip_y, float *buf) 387 { 388 buf[0] = x / img_width; 389 buf[1] = buf[0] + reg_width / img_width; 390 buf[2] = y / img_height; 391 buf[3] = buf[2] + reg_height / img_height; 392 if (flip_y) 393 { 394 buf[2] = 1.0 - buf[2]; 395 buf[3] = 1.0 - buf[3]; 396 } 397 } 398 399 static inline void emit_draw_packet(struct r200_context *r200, 400 unsigned src_width, unsigned src_height, 401 unsigned src_x_offset, unsigned src_y_offset, 402 unsigned dst_x_offset, unsigned dst_y_offset, 403 unsigned reg_width, unsigned reg_height, 404 unsigned flip_y) 405 { 406 float texcoords[4]; 407 float verts[12]; 408 BATCH_LOCALS(&r200->radeon); 409 410 calc_tex_coords(src_width, src_height, 411 src_x_offset, src_y_offset, 412 reg_width, reg_height, 413 flip_y, texcoords); 414 415 verts[0] = dst_x_offset; 416 verts[1] = dst_y_offset + reg_height; 417 verts[2] = texcoords[0]; 418 verts[3] = texcoords[3]; 419 420 verts[4] = dst_x_offset + reg_width; 421 verts[5] = dst_y_offset + reg_height; 422 verts[6] = texcoords[1]; 423 verts[7] = texcoords[3]; 424 425 verts[8] = dst_x_offset + reg_width; 426 verts[9] = dst_y_offset; 427 verts[10] = texcoords[1]; 428 verts[11] = texcoords[2]; 429 430 BEGIN_BATCH(14); 431 OUT_BATCH(R200_CP_CMD_3D_DRAW_IMMD_2 | (12 << 16)); 432 OUT_BATCH(RADEON_CP_VC_CNTL_PRIM_WALK_RING | 433 RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST | 434 (3 << 16)); 435 OUT_BATCH_TABLE(verts, 12); 436 END_BATCH(); 437 } 438 439 /** 440 * Copy a region of [@a width x @a height] pixels from source buffer 441 * to destination buffer. 442 * @param[in] r200 r200 context 443 * @param[in] src_bo source radeon buffer object 444 * @param[in] src_offset offset of the source image in the @a src_bo 445 * @param[in] src_mesaformat source image format 446 * @param[in] src_pitch aligned source image width 447 * @param[in] src_width source image width 448 * @param[in] src_height source image height 449 * @param[in] src_x_offset x offset in the source image 450 * @param[in] src_y_offset y offset in the source image 451 * @param[in] dst_bo destination radeon buffer object 452 * @param[in] dst_offset offset of the destination image in the @a dst_bo 453 * @param[in] dst_mesaformat destination image format 454 * @param[in] dst_pitch aligned destination image width 455 * @param[in] dst_width destination image width 456 * @param[in] dst_height destination image height 457 * @param[in] dst_x_offset x offset in the destination image 458 * @param[in] dst_y_offset y offset in the destination image 459 * @param[in] width region width 460 * @param[in] height region height 461 * @param[in] flip_y set if y coords of the source image need to be flipped 462 */ 463 unsigned r200_blit(struct gl_context *ctx, 464 struct radeon_bo *src_bo, 465 intptr_t src_offset, 466 gl_format src_mesaformat, 467 unsigned src_pitch, 468 unsigned src_width, 469 unsigned src_height, 470 unsigned src_x_offset, 471 unsigned src_y_offset, 472 struct radeon_bo *dst_bo, 473 intptr_t dst_offset, 474 gl_format dst_mesaformat, 475 unsigned dst_pitch, 476 unsigned dst_width, 477 unsigned dst_height, 478 unsigned dst_x_offset, 479 unsigned dst_y_offset, 480 unsigned reg_width, 481 unsigned reg_height, 482 unsigned flip_y) 483 { 484 struct r200_context *r200 = R200_CONTEXT(ctx); 485 486 if (!r200_check_blit(dst_mesaformat, dst_pitch)) 487 return GL_FALSE; 488 489 /* Make sure that colorbuffer has even width - hw limitation */ 490 if (dst_pitch % 2 > 0) 491 ++dst_pitch; 492 493 /* Need to clamp the region size to make sure 494 * we don't read outside of the source buffer 495 * or write outside of the destination buffer. 496 */ 497 if (reg_width + src_x_offset > src_width) 498 reg_width = src_width - src_x_offset; 499 if (reg_height + src_y_offset > src_height) 500 reg_height = src_height - src_y_offset; 501 if (reg_width + dst_x_offset > dst_width) 502 reg_width = dst_width - dst_x_offset; 503 if (reg_height + dst_y_offset > dst_height) 504 reg_height = dst_height - dst_y_offset; 505 506 if (src_bo == dst_bo) { 507 return GL_FALSE; 508 } 509 510 if (src_offset % 32 || dst_offset % 32) { 511 return GL_FALSE; 512 } 513 514 if (0) { 515 fprintf(stderr, "src: size [%d x %d], pitch %d, " 516 "offset [%d x %d], format %s, bo %p\n", 517 src_width, src_height, src_pitch, 518 src_x_offset, src_y_offset, 519 _mesa_get_format_name(src_mesaformat), 520 src_bo); 521 fprintf(stderr, "dst: pitch %d, offset[%d x %d], format %s, bo %p\n", 522 dst_pitch, dst_x_offset, dst_y_offset, 523 _mesa_get_format_name(dst_mesaformat), dst_bo); 524 fprintf(stderr, "region: %d x %d\n", reg_width, reg_height); 525 } 526 527 /* Flush is needed to make sure that source buffer has correct data */ 528 radeonFlush(r200->radeon.glCtx); 529 530 rcommonEnsureCmdBufSpace(&r200->radeon, 102, __FUNCTION__); 531 532 if (!validate_buffers(r200, src_bo, dst_bo)) 533 return GL_FALSE; 534 535 /* 14 */ 536 emit_vtx_state(r200); 537 /* 52 */ 538 emit_tx_setup(r200, src_mesaformat, dst_mesaformat, src_bo, src_offset, src_width, src_height, src_pitch); 539 /* 22 */ 540 emit_cb_setup(r200, dst_bo, dst_offset, dst_mesaformat, dst_pitch, dst_width, dst_height); 541 /* 14 */ 542 emit_draw_packet(r200, src_width, src_height, 543 src_x_offset, src_y_offset, 544 dst_x_offset, dst_y_offset, 545 reg_width, reg_height, 546 flip_y); 547 548 radeonFlush(ctx); 549 550 return GL_TRUE; 551 } 552