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