1 /************************************************************************** 2 * 3 * Copyright 2008 Red Hat Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * 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, sub license, 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 portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 29 #include "main/imports.h" 30 #include "main/macros.h" 31 #include "main/mtypes.h" 32 #include "main/enums.h" 33 #include "main/fbobject.h" 34 #include "main/framebuffer.h" 35 #include "main/renderbuffer.h" 36 #include "main/context.h" 37 #include "swrast/swrast.h" 38 #include "drivers/common/meta.h" 39 40 #include "radeon_common.h" 41 #include "radeon_mipmap_tree.h" 42 43 #define FILE_DEBUG_FLAG RADEON_TEXTURE 44 #define DBG(...) do { \ 45 if (RADEON_DEBUG & FILE_DEBUG_FLAG) \ 46 printf(__VA_ARGS__); \ 47 } while(0) 48 49 static void 50 radeon_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb) 51 { 52 struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); 53 54 radeon_print(RADEON_TEXTURE, RADEON_TRACE, 55 "%s(rb %p, rrb %p) \n", 56 __func__, rb, rrb); 57 58 assert(rrb); 59 60 if (rrb && rrb->bo) { 61 radeon_bo_unref(rrb->bo); 62 } 63 _mesa_delete_renderbuffer(ctx, rb); 64 } 65 66 #if defined(RADEON_R100) 67 static GLuint get_depth_z32(const struct radeon_renderbuffer * rrb, 68 GLint x, GLint y) 69 { 70 GLuint ba, address = 0; 71 72 ba = (y >> 4) * (rrb->pitch >> 6) + (x >> 4); 73 74 address |= (x & 0x7) << 2; 75 address |= (y & 0x3) << 5; 76 address |= (((x & 0x10) >> 2) ^ (y & 0x4)) << 5; 77 address |= (ba & 3) << 8; 78 address |= (y & 0x8) << 7; 79 address |= (((x & 0x8) << 1) ^ (y & 0x10)) << 7; 80 address |= (ba & ~0x3) << 10; 81 return address; 82 } 83 84 static GLuint get_depth_z16(const struct radeon_renderbuffer * rrb, 85 GLint x, GLint y) 86 { 87 GLuint ba, address = 0; /* a[0] = 0 */ 88 89 ba = (y / 16) * (rrb->pitch >> 6) + (x / 32); 90 91 address |= (x & 0x7) << 1; /* a[1..3] = x[0..2] */ 92 address |= (y & 0x7) << 4; /* a[4..6] = y[0..2] */ 93 address |= (x & 0x8) << 4; /* a[7] = x[3] */ 94 address |= (ba & 0x3) << 8; /* a[8..9] = ba[0..1] */ 95 address |= (y & 0x8) << 7; /* a[10] = y[3] */ 96 address |= ((x & 0x10) ^ (y & 0x10)) << 7;/* a[11] = x[4] ^ y[4] */ 97 address |= (ba & ~0x3) << 10; /* a[12..] = ba[2..] */ 98 return address; 99 } 100 #endif 101 102 #if defined(RADEON_R200) 103 static GLuint get_depth_z32(const struct radeon_renderbuffer * rrb, 104 GLint x, GLint y) 105 { 106 GLuint offset; 107 GLuint b; 108 offset = 0; 109 b = (((y & 0x7ff) >> 4) * (rrb->pitch >> 7) + (x >> 5)); 110 offset += (b >> 1) << 12; 111 offset += (((rrb->pitch >> 7) & 0x1) ? (b & 0x1) : ((b & 0x1) ^ ((y >> 4) & 0x1))) << 11; 112 offset += ((y >> 2) & 0x3) << 9; 113 offset += ((x >> 2) & 0x1) << 8; 114 offset += ((x >> 3) & 0x3) << 6; 115 offset += ((y >> 1) & 0x1) << 5; 116 offset += ((x >> 1) & 0x1) << 4; 117 offset += (y & 0x1) << 3; 118 offset += (x & 0x1) << 2; 119 120 return offset; 121 } 122 123 static GLuint get_depth_z16(const struct radeon_renderbuffer *rrb, 124 GLint x, GLint y) 125 { 126 GLuint offset; 127 GLuint b; 128 129 offset = 0; 130 b = (((y >> 4) * (rrb->pitch >> 7) + (x >> 6))); 131 offset += (b >> 1) << 12; 132 offset += (((rrb->pitch >> 7) & 0x1) ? (b & 0x1) : ((b & 0x1) ^ ((y >> 4) & 0x1))) << 11; 133 offset += ((y >> 2) & 0x3) << 9; 134 offset += ((x >> 3) & 0x1) << 8; 135 offset += ((x >> 4) & 0x3) << 6; 136 offset += ((x >> 2) & 0x1) << 5; 137 offset += ((y >> 1) & 0x1) << 4; 138 offset += ((x >> 1) & 0x1) << 3; 139 offset += (y & 0x1) << 2; 140 offset += (x & 0x1) << 1; 141 142 return offset; 143 } 144 #endif 145 146 static void 147 radeon_map_renderbuffer_s8z24(struct gl_context *ctx, 148 struct gl_renderbuffer *rb, 149 GLuint x, GLuint y, GLuint w, GLuint h, 150 GLbitfield mode, 151 GLubyte **out_map, 152 GLint *out_stride) 153 { 154 struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); 155 uint32_t *untiled_s8z24_map, *tiled_s8z24_map; 156 int ret; 157 int y_flip = (rb->Name == 0) ? -1 : 1; 158 int y_bias = (rb->Name == 0) ? (rb->Height - 1) : 0; 159 uint32_t pitch = w * rrb->cpp; 160 161 rrb->map_pitch = pitch; 162 163 rrb->map_buffer = malloc(w * h * 4); 164 ret = radeon_bo_map(rrb->bo, !!(mode & GL_MAP_WRITE_BIT)); 165 assert(!ret); 166 (void) ret; 167 untiled_s8z24_map = rrb->map_buffer; 168 tiled_s8z24_map = rrb->bo->ptr; 169 170 for (uint32_t pix_y = 0; pix_y < h; ++ pix_y) { 171 for (uint32_t pix_x = 0; pix_x < w; ++pix_x) { 172 uint32_t flipped_y = y_flip * (int32_t)(y + pix_y) + y_bias; 173 uint32_t src_offset = get_depth_z32(rrb, x + pix_x, flipped_y); 174 uint32_t dst_offset = pix_y * rrb->map_pitch + pix_x * rrb->cpp; 175 untiled_s8z24_map[dst_offset/4] = tiled_s8z24_map[src_offset/4]; 176 } 177 } 178 179 radeon_bo_unmap(rrb->bo); 180 181 *out_map = rrb->map_buffer; 182 *out_stride = rrb->map_pitch; 183 } 184 185 static void 186 radeon_map_renderbuffer_z16(struct gl_context *ctx, 187 struct gl_renderbuffer *rb, 188 GLuint x, GLuint y, GLuint w, GLuint h, 189 GLbitfield mode, 190 GLubyte **out_map, 191 GLint *out_stride) 192 { 193 struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); 194 uint16_t *untiled_z16_map, *tiled_z16_map; 195 int ret; 196 int y_flip = (rb->Name == 0) ? -1 : 1; 197 int y_bias = (rb->Name == 0) ? (rb->Height - 1) : 0; 198 uint32_t pitch = w * rrb->cpp; 199 200 rrb->map_pitch = pitch; 201 202 rrb->map_buffer = malloc(w * h * 2); 203 ret = radeon_bo_map(rrb->bo, !!(mode & GL_MAP_WRITE_BIT)); 204 assert(!ret); 205 (void) ret; 206 207 untiled_z16_map = rrb->map_buffer; 208 tiled_z16_map = rrb->bo->ptr; 209 210 for (uint32_t pix_y = 0; pix_y < h; ++ pix_y) { 211 for (uint32_t pix_x = 0; pix_x < w; ++pix_x) { 212 uint32_t flipped_y = y_flip * (int32_t)(y + pix_y) + y_bias; 213 uint32_t src_offset = get_depth_z16(rrb, x + pix_x, flipped_y); 214 uint32_t dst_offset = pix_y * rrb->map_pitch + pix_x * rrb->cpp; 215 untiled_z16_map[dst_offset/2] = tiled_z16_map[src_offset/2]; 216 } 217 } 218 219 radeon_bo_unmap(rrb->bo); 220 221 *out_map = rrb->map_buffer; 222 *out_stride = rrb->map_pitch; 223 } 224 225 static void 226 radeon_map_renderbuffer(struct gl_context *ctx, 227 struct gl_renderbuffer *rb, 228 GLuint x, GLuint y, GLuint w, GLuint h, 229 GLbitfield mode, 230 GLubyte **out_map, 231 GLint *out_stride) 232 { 233 struct radeon_context *const rmesa = RADEON_CONTEXT(ctx); 234 struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); 235 GLubyte *map; 236 GLboolean ok; 237 int stride, flip_stride; 238 int ret; 239 int src_x, src_y; 240 241 if (!rrb || !rrb->bo) { 242 *out_map = NULL; 243 *out_stride = 0; 244 return; 245 } 246 247 rrb->map_mode = mode; 248 rrb->map_x = x; 249 rrb->map_y = y; 250 rrb->map_w = w; 251 rrb->map_h = h; 252 rrb->map_pitch = rrb->pitch; 253 254 ok = rmesa->vtbl.check_blit(rb->Format, rrb->pitch / rrb->cpp); 255 if (ok) { 256 if (rb->Name) { 257 src_x = x; 258 src_y = y; 259 } else { 260 src_x = x; 261 src_y = rrb->base.Base.Height - y - h; 262 } 263 264 /* Make a temporary buffer and blit the current contents of the renderbuffer 265 * out to it. This gives us linear access to the buffer, instead of having 266 * to do detiling in software. 267 */ 268 269 rrb->map_pitch = rrb->pitch; 270 271 assert(!rrb->map_bo); 272 rrb->map_bo = radeon_bo_open(rmesa->radeonScreen->bom, 0, 273 rrb->map_pitch * h, 4, 274 RADEON_GEM_DOMAIN_GTT, 0); 275 276 ok = rmesa->vtbl.blit(ctx, rrb->bo, rrb->draw_offset, 277 rb->Format, rrb->pitch / rrb->cpp, 278 rb->Width, rb->Height, 279 src_x, src_y, 280 rrb->map_bo, 0, 281 rb->Format, rrb->map_pitch / rrb->cpp, 282 w, h, 283 0, 0, 284 w, h, 285 GL_FALSE); 286 assert(ok); 287 288 ret = radeon_bo_map(rrb->map_bo, !!(mode & GL_MAP_WRITE_BIT)); 289 assert(!ret); 290 291 map = rrb->map_bo->ptr; 292 293 if (rb->Name) { 294 *out_map = map; 295 *out_stride = rrb->map_pitch; 296 } else { 297 *out_map = map + (h - 1) * rrb->map_pitch; 298 *out_stride = -rrb->map_pitch; 299 } 300 return; 301 } 302 303 /* sw fallback flush stuff */ 304 if (radeon_bo_is_referenced_by_cs(rrb->bo, rmesa->cmdbuf.cs)) { 305 radeon_firevertices(rmesa); 306 } 307 308 if ((rmesa->radeonScreen->chip_flags & RADEON_CHIPSET_DEPTH_ALWAYS_TILED) && !rrb->has_surface) { 309 if (rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT || rb->Format == MESA_FORMAT_Z24_UNORM_X8_UINT) { 310 radeon_map_renderbuffer_s8z24(ctx, rb, x, y, w, h, 311 mode, out_map, out_stride); 312 return; 313 } 314 if (rb->Format == MESA_FORMAT_Z_UNORM16) { 315 radeon_map_renderbuffer_z16(ctx, rb, x, y, w, h, 316 mode, out_map, out_stride); 317 return; 318 } 319 } 320 321 ret = radeon_bo_map(rrb->bo, !!(mode & GL_MAP_WRITE_BIT)); 322 assert(!ret); 323 (void) ret; 324 325 map = rrb->bo->ptr; 326 stride = rrb->map_pitch; 327 328 if (rb->Name == 0) { 329 y = rb->Height - 1 - y; 330 flip_stride = -stride; 331 } else { 332 flip_stride = stride; 333 map += rrb->draw_offset; 334 } 335 336 map += x * rrb->cpp; 337 map += (int)y * stride; 338 339 *out_map = map; 340 *out_stride = flip_stride; 341 } 342 343 static void 344 radeon_unmap_renderbuffer_s8z24(struct gl_context *ctx, 345 struct gl_renderbuffer *rb) 346 { 347 struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); 348 349 if (!rrb->map_buffer) 350 return; 351 352 if (rrb->map_mode & GL_MAP_WRITE_BIT) { 353 uint32_t *untiled_s8z24_map = rrb->map_buffer; 354 uint32_t *tiled_s8z24_map; 355 int y_flip = (rb->Name == 0) ? -1 : 1; 356 int y_bias = (rb->Name == 0) ? (rb->Height - 1) : 0; 357 358 radeon_bo_map(rrb->bo, 1); 359 360 tiled_s8z24_map = rrb->bo->ptr; 361 362 for (uint32_t pix_y = 0; pix_y < rrb->map_h; pix_y++) { 363 for (uint32_t pix_x = 0; pix_x < rrb->map_w; pix_x++) { 364 uint32_t flipped_y = y_flip * (int32_t)(pix_y + rrb->map_y) + y_bias; 365 uint32_t dst_offset = get_depth_z32(rrb, rrb->map_x + pix_x, flipped_y); 366 uint32_t src_offset = pix_y * rrb->map_pitch + pix_x * rrb->cpp; 367 tiled_s8z24_map[dst_offset/4] = untiled_s8z24_map[src_offset/4]; 368 } 369 } 370 radeon_bo_unmap(rrb->bo); 371 } 372 free(rrb->map_buffer); 373 rrb->map_buffer = NULL; 374 } 375 376 static void 377 radeon_unmap_renderbuffer_z16(struct gl_context *ctx, 378 struct gl_renderbuffer *rb) 379 { 380 struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); 381 382 if (!rrb->map_buffer) 383 return; 384 385 if (rrb->map_mode & GL_MAP_WRITE_BIT) { 386 uint16_t *untiled_z16_map = rrb->map_buffer; 387 uint16_t *tiled_z16_map; 388 int y_flip = (rb->Name == 0) ? -1 : 1; 389 int y_bias = (rb->Name == 0) ? (rb->Height - 1) : 0; 390 391 radeon_bo_map(rrb->bo, 1); 392 393 tiled_z16_map = rrb->bo->ptr; 394 395 for (uint32_t pix_y = 0; pix_y < rrb->map_h; pix_y++) { 396 for (uint32_t pix_x = 0; pix_x < rrb->map_w; pix_x++) { 397 uint32_t flipped_y = y_flip * (int32_t)(pix_y + rrb->map_y) + y_bias; 398 uint32_t dst_offset = get_depth_z16(rrb, rrb->map_x + pix_x, flipped_y); 399 uint32_t src_offset = pix_y * rrb->map_pitch + pix_x * rrb->cpp; 400 tiled_z16_map[dst_offset/2] = untiled_z16_map[src_offset/2]; 401 } 402 } 403 radeon_bo_unmap(rrb->bo); 404 } 405 free(rrb->map_buffer); 406 rrb->map_buffer = NULL; 407 } 408 409 410 static void 411 radeon_unmap_renderbuffer(struct gl_context *ctx, 412 struct gl_renderbuffer *rb) 413 { 414 struct radeon_context *const rmesa = RADEON_CONTEXT(ctx); 415 struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); 416 417 if ((rmesa->radeonScreen->chip_flags & RADEON_CHIPSET_DEPTH_ALWAYS_TILED) && !rrb->has_surface) { 418 if (rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT || rb->Format == MESA_FORMAT_Z24_UNORM_X8_UINT) { 419 radeon_unmap_renderbuffer_s8z24(ctx, rb); 420 return; 421 } 422 if (rb->Format == MESA_FORMAT_Z_UNORM16) { 423 radeon_unmap_renderbuffer_z16(ctx, rb); 424 return; 425 } 426 } 427 428 if (!rrb->map_bo) { 429 if (rrb->bo) 430 radeon_bo_unmap(rrb->bo); 431 return; 432 } 433 434 radeon_bo_unmap(rrb->map_bo); 435 436 if (rrb->map_mode & GL_MAP_WRITE_BIT) { 437 GLboolean ok; 438 ok = rmesa->vtbl.blit(ctx, rrb->map_bo, 0, 439 rb->Format, rrb->map_pitch / rrb->cpp, 440 rrb->map_w, rrb->map_h, 441 0, 0, 442 rrb->bo, rrb->draw_offset, 443 rb->Format, rrb->pitch / rrb->cpp, 444 rb->Width, rb->Height, 445 rrb->map_x, rrb->map_y, 446 rrb->map_w, rrb->map_h, 447 GL_FALSE); 448 assert(ok); 449 (void) ok; 450 } 451 452 radeon_bo_unref(rrb->map_bo); 453 rrb->map_bo = NULL; 454 } 455 456 457 /** 458 * Called via glRenderbufferStorageEXT() to set the format and allocate 459 * storage for a user-created renderbuffer. 460 */ 461 static GLboolean 462 radeon_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, 463 GLenum internalFormat, 464 GLuint width, GLuint height) 465 { 466 struct radeon_context *radeon = RADEON_CONTEXT(ctx); 467 struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); 468 uint32_t size, pitch; 469 int cpp; 470 471 radeon_print(RADEON_TEXTURE, RADEON_TRACE, 472 "%s(%p, rb %p) \n", 473 __func__, ctx, rb); 474 475 assert(rb->Name != 0); 476 switch (internalFormat) { 477 case GL_R3_G3_B2: 478 case GL_RGB4: 479 case GL_RGB5: 480 rb->Format = _radeon_texformat_rgb565; 481 cpp = 2; 482 break; 483 case GL_RGB: 484 case GL_RGB8: 485 case GL_RGB10: 486 case GL_RGB12: 487 case GL_RGB16: 488 rb->Format = _radeon_texformat_argb8888; 489 cpp = 4; 490 break; 491 case GL_RGBA: 492 case GL_RGBA2: 493 case GL_RGBA4: 494 case GL_RGB5_A1: 495 case GL_RGBA8: 496 case GL_RGB10_A2: 497 case GL_RGBA12: 498 case GL_RGBA16: 499 rb->Format = _radeon_texformat_argb8888; 500 cpp = 4; 501 break; 502 case GL_STENCIL_INDEX: 503 case GL_STENCIL_INDEX1_EXT: 504 case GL_STENCIL_INDEX4_EXT: 505 case GL_STENCIL_INDEX8_EXT: 506 case GL_STENCIL_INDEX16_EXT: 507 /* alloc a depth+stencil buffer */ 508 rb->Format = MESA_FORMAT_Z24_UNORM_S8_UINT; 509 cpp = 4; 510 break; 511 case GL_DEPTH_COMPONENT16: 512 rb->Format = MESA_FORMAT_Z_UNORM16; 513 cpp = 2; 514 break; 515 case GL_DEPTH_COMPONENT: 516 case GL_DEPTH_COMPONENT24: 517 case GL_DEPTH_COMPONENT32: 518 rb->Format = MESA_FORMAT_Z24_UNORM_X8_UINT; 519 cpp = 4; 520 break; 521 case GL_DEPTH_STENCIL_EXT: 522 case GL_DEPTH24_STENCIL8_EXT: 523 rb->Format = MESA_FORMAT_Z24_UNORM_S8_UINT; 524 cpp = 4; 525 break; 526 default: 527 _mesa_problem(ctx, 528 "Unexpected format in radeon_alloc_renderbuffer_storage"); 529 return GL_FALSE; 530 } 531 532 rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); 533 534 if (ctx->Driver.Flush) 535 ctx->Driver.Flush(ctx); /* +r6/r7 */ 536 537 if (rrb->bo) 538 radeon_bo_unref(rrb->bo); 539 540 pitch = ((cpp * width + 63) & ~63) / cpp; 541 542 if (RADEON_DEBUG & RADEON_MEMORY) 543 fprintf(stderr,"Allocating %d x %d radeon RBO (pitch %d)\n", width, 544 height, pitch); 545 546 size = pitch * height * cpp; 547 rrb->pitch = pitch * cpp; 548 rrb->cpp = cpp; 549 rrb->bo = radeon_bo_open(radeon->radeonScreen->bom, 550 0, 551 size, 552 0, 553 RADEON_GEM_DOMAIN_VRAM, 554 0); 555 rb->Width = width; 556 rb->Height = height; 557 return GL_TRUE; 558 } 559 560 static void 561 radeon_image_target_renderbuffer_storage(struct gl_context *ctx, 562 struct gl_renderbuffer *rb, 563 void *image_handle) 564 { 565 radeonContextPtr radeon = RADEON_CONTEXT(ctx); 566 struct radeon_renderbuffer *rrb; 567 __DRIscreen *screen; 568 __DRIimage *image; 569 570 screen = radeon->radeonScreen->driScreen; 571 image = screen->dri2.image->lookupEGLImage(screen, image_handle, 572 screen->loaderPrivate); 573 if (image == NULL) 574 return; 575 576 rrb = radeon_renderbuffer(rb); 577 578 if (ctx->Driver.Flush) 579 ctx->Driver.Flush(ctx); /* +r6/r7 */ 580 581 if (rrb->bo) 582 radeon_bo_unref(rrb->bo); 583 rrb->bo = image->bo; 584 radeon_bo_ref(rrb->bo); 585 fprintf(stderr, "image->bo: %p, name: %d, rbs: w %d -> p %d\n", image->bo, image->bo->handle, 586 image->width, image->pitch); 587 588 rrb->cpp = image->cpp; 589 rrb->pitch = image->pitch * image->cpp; 590 591 rb->Format = image->format; 592 rb->InternalFormat = image->internal_format; 593 rb->Width = image->width; 594 rb->Height = image->height; 595 rb->Format = image->format; 596 rb->_BaseFormat = _mesa_base_fbo_format(&radeon->glCtx, 597 image->internal_format); 598 rb->NeedsFinishRenderTexture = GL_TRUE; 599 } 600 601 /** 602 * Called for each hardware renderbuffer when a _window_ is resized. 603 * Just update fields. 604 * Not used for user-created renderbuffers! 605 */ 606 static GLboolean 607 radeon_alloc_window_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, 608 GLenum internalFormat, GLuint width, GLuint height) 609 { 610 assert(rb->Name == 0); 611 rb->Width = width; 612 rb->Height = height; 613 rb->InternalFormat = internalFormat; 614 radeon_print(RADEON_TEXTURE, RADEON_TRACE, 615 "%s(%p, rb %p) \n", 616 __func__, ctx, rb); 617 618 619 return GL_TRUE; 620 } 621 622 /** Dummy function for gl_renderbuffer::AllocStorage() */ 623 static GLboolean 624 radeon_nop_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, 625 GLenum internalFormat, GLuint width, GLuint height) 626 { 627 _mesa_problem(ctx, "radeon_op_alloc_storage should never be called."); 628 return GL_FALSE; 629 } 630 631 632 /** 633 * Create a renderbuffer for a window's color, depth and/or stencil buffer. 634 * Not used for user-created renderbuffers. 635 */ 636 struct radeon_renderbuffer * 637 radeon_create_renderbuffer(mesa_format format, __DRIdrawable *driDrawPriv) 638 { 639 struct radeon_renderbuffer *rrb; 640 struct gl_renderbuffer *rb; 641 642 rrb = CALLOC_STRUCT(radeon_renderbuffer); 643 644 radeon_print(RADEON_TEXTURE, RADEON_TRACE, 645 "%s( rrb %p ) \n", 646 __func__, rrb); 647 648 if (!rrb) 649 return NULL; 650 651 rb = &rrb->base.Base; 652 653 _mesa_init_renderbuffer(rb, 0); 654 rb->ClassID = RADEON_RB_CLASS; 655 rb->Format = format; 656 rb->_BaseFormat = _mesa_get_format_base_format(format); 657 rb->InternalFormat = _mesa_get_format_base_format(format); 658 659 rrb->dPriv = driDrawPriv; 660 661 rb->Delete = radeon_delete_renderbuffer; 662 rb->AllocStorage = radeon_alloc_window_storage; 663 664 rrb->bo = NULL; 665 return rrb; 666 } 667 668 static struct gl_renderbuffer * 669 radeon_new_renderbuffer(struct gl_context * ctx, GLuint name) 670 { 671 struct radeon_renderbuffer *rrb; 672 struct gl_renderbuffer *rb; 673 674 675 rrb = CALLOC_STRUCT(radeon_renderbuffer); 676 677 radeon_print(RADEON_TEXTURE, RADEON_TRACE, 678 "%s(%p, rrb %p) \n", 679 __func__, ctx, rrb); 680 681 if (!rrb) 682 return NULL; 683 684 rb = &rrb->base.Base; 685 686 _mesa_init_renderbuffer(rb, name); 687 rb->ClassID = RADEON_RB_CLASS; 688 rb->Delete = radeon_delete_renderbuffer; 689 rb->AllocStorage = radeon_alloc_renderbuffer_storage; 690 691 return rb; 692 } 693 694 static void 695 radeon_bind_framebuffer(struct gl_context * ctx, GLenum target, 696 struct gl_framebuffer *fb, struct gl_framebuffer *fbread) 697 { 698 radeon_print(RADEON_TEXTURE, RADEON_TRACE, 699 "%s(%p, fb %p, target %s) \n", 700 __func__, ctx, fb, 701 _mesa_enum_to_string(target)); 702 703 if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) { 704 radeon_draw_buffer(ctx, fb); 705 } 706 else { 707 /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */ 708 } 709 } 710 711 static void 712 radeon_framebuffer_renderbuffer(struct gl_context * ctx, 713 struct gl_framebuffer *fb, 714 GLenum attachment, struct gl_renderbuffer *rb) 715 { 716 717 if (ctx->Driver.Flush) 718 ctx->Driver.Flush(ctx); /* +r6/r7 */ 719 720 radeon_print(RADEON_TEXTURE, RADEON_TRACE, 721 "%s(%p, fb %p, rb %p) \n", 722 __func__, ctx, fb, rb); 723 724 _mesa_FramebufferRenderbuffer_sw(ctx, fb, attachment, rb); 725 radeon_draw_buffer(ctx, fb); 726 } 727 728 static GLboolean 729 radeon_update_wrapper(struct gl_context *ctx, struct radeon_renderbuffer *rrb, 730 struct gl_texture_image *texImage) 731 { 732 struct gl_renderbuffer *rb = &rrb->base.Base; 733 734 radeon_print(RADEON_TEXTURE, RADEON_TRACE, 735 "%s(%p, rrb %p, texImage %p, texFormat %s) \n", 736 __func__, ctx, rrb, texImage, _mesa_get_format_name(texImage->TexFormat)); 737 738 rrb->cpp = _mesa_get_format_bytes(texImage->TexFormat); 739 rrb->pitch = texImage->Width * rrb->cpp; 740 rb->Format = texImage->TexFormat; 741 rb->InternalFormat = texImage->InternalFormat; 742 rb->_BaseFormat = _mesa_base_fbo_format(ctx, rb->InternalFormat); 743 rb->Width = texImage->Width; 744 rb->Height = texImage->Height; 745 rb->Delete = radeon_delete_renderbuffer; 746 rb->AllocStorage = radeon_nop_alloc_storage; 747 748 return GL_TRUE; 749 } 750 751 static void 752 radeon_render_texture(struct gl_context * ctx, 753 struct gl_framebuffer *fb, 754 struct gl_renderbuffer_attachment *att) 755 { 756 struct gl_renderbuffer *rb = att->Renderbuffer; 757 struct gl_texture_image *newImage = rb->TexImage; 758 struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); 759 radeon_texture_image *radeon_image; 760 GLuint imageOffset; 761 762 radeon_print(RADEON_TEXTURE, RADEON_TRACE, 763 "%s(%p, fb %p, rrb %p, att %p)\n", 764 __func__, ctx, fb, rrb, att); 765 766 (void) fb; 767 768 assert(newImage); 769 770 radeon_image = (radeon_texture_image *)newImage; 771 772 if (!radeon_image->mt) { 773 /* Fallback on drawing to a texture without a miptree. 774 */ 775 _swrast_render_texture(ctx, fb, att); 776 return; 777 } 778 779 if (!radeon_update_wrapper(ctx, rrb, newImage)) { 780 _swrast_render_texture(ctx, fb, att); 781 return; 782 } 783 784 DBG("Begin render texture tex=%u w=%d h=%d refcount=%d\n", 785 att->Texture->Name, newImage->Width, newImage->Height, 786 rb->RefCount); 787 788 /* point the renderbufer's region to the texture image region */ 789 if (rrb->bo != radeon_image->mt->bo) { 790 if (rrb->bo) 791 radeon_bo_unref(rrb->bo); 792 rrb->bo = radeon_image->mt->bo; 793 radeon_bo_ref(rrb->bo); 794 } 795 796 /* compute offset of the particular 2D image within the texture region */ 797 imageOffset = radeon_miptree_image_offset(radeon_image->mt, 798 att->CubeMapFace, 799 att->TextureLevel); 800 801 if (att->Texture->Target == GL_TEXTURE_3D) { 802 imageOffset += radeon_image->mt->levels[att->TextureLevel].rowstride * 803 radeon_image->mt->levels[att->TextureLevel].height * 804 att->Zoffset; 805 } 806 807 /* store that offset in the region, along with the correct pitch for 808 * the image we are rendering to */ 809 rrb->draw_offset = imageOffset; 810 rrb->pitch = radeon_image->mt->levels[att->TextureLevel].rowstride; 811 radeon_image->used_as_render_target = GL_TRUE; 812 813 /* update drawing region, etc */ 814 radeon_draw_buffer(ctx, fb); 815 } 816 817 static void 818 radeon_finish_render_texture(struct gl_context *ctx, struct gl_renderbuffer *rb) 819 { 820 struct gl_texture_image *image = rb->TexImage; 821 radeon_texture_image *radeon_image = (radeon_texture_image *)image; 822 823 if (radeon_image) 824 radeon_image->used_as_render_target = GL_FALSE; 825 826 if (ctx->Driver.Flush) 827 ctx->Driver.Flush(ctx); /* +r6/r7 */ 828 } 829 static void 830 radeon_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) 831 { 832 radeonContextPtr radeon = RADEON_CONTEXT(ctx); 833 mesa_format mesa_format; 834 int i; 835 836 for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) { 837 struct gl_renderbuffer_attachment *att; 838 if (i == -2) { 839 att = &fb->Attachment[BUFFER_DEPTH]; 840 } else if (i == -1) { 841 att = &fb->Attachment[BUFFER_STENCIL]; 842 } else { 843 att = &fb->Attachment[BUFFER_COLOR0 + i]; 844 } 845 846 if (att->Type == GL_TEXTURE) { 847 mesa_format = att->Renderbuffer->TexImage->TexFormat; 848 } else { 849 /* All renderbuffer formats are renderable, but not sampable */ 850 continue; 851 } 852 853 if (!radeon->vtbl.is_format_renderable(mesa_format)){ 854 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED; 855 radeon_print(RADEON_TEXTURE, RADEON_TRACE, 856 "%s: HW doesn't support format %s as output format of attachment %d\n", 857 __func__, _mesa_get_format_name(mesa_format), i); 858 return; 859 } 860 } 861 } 862 863 void radeon_fbo_init(struct radeon_context *radeon) 864 { 865 radeon->glCtx.Driver.NewRenderbuffer = radeon_new_renderbuffer; 866 radeon->glCtx.Driver.MapRenderbuffer = radeon_map_renderbuffer; 867 radeon->glCtx.Driver.UnmapRenderbuffer = radeon_unmap_renderbuffer; 868 radeon->glCtx.Driver.BindFramebuffer = radeon_bind_framebuffer; 869 radeon->glCtx.Driver.FramebufferRenderbuffer = radeon_framebuffer_renderbuffer; 870 radeon->glCtx.Driver.RenderTexture = radeon_render_texture; 871 radeon->glCtx.Driver.FinishRenderTexture = radeon_finish_render_texture; 872 radeon->glCtx.Driver.ValidateFramebuffer = radeon_validate_framebuffer; 873 radeon->glCtx.Driver.BlitFramebuffer = _mesa_meta_and_swrast_BlitFramebuffer; 874 radeon->glCtx.Driver.EGLImageTargetRenderbufferStorage = 875 radeon_image_target_renderbuffer_storage; 876 } 877 878 879 void radeon_renderbuffer_set_bo(struct radeon_renderbuffer *rb, 880 struct radeon_bo *bo) 881 { 882 struct radeon_bo *old; 883 old = rb->bo; 884 rb->bo = bo; 885 radeon_bo_ref(bo); 886 if (old) 887 radeon_bo_unref(old); 888 } 889