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