radeon_fbo.c revision c2711cdfb68d92ede740e2cc1fd7d78f604dc201
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_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 free(rrb); 71} 72 73static void 74radeon_map_renderbuffer(struct gl_context *ctx, 75 struct gl_renderbuffer *rb, 76 GLuint x, GLuint y, GLuint w, GLuint h, 77 GLbitfield mode, 78 GLubyte **out_map, 79 GLint *out_stride) 80{ 81 struct radeon_context *const rmesa = RADEON_CONTEXT(ctx); 82 struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); 83 GLubyte *map; 84 GLboolean ok; 85 int stride, ret; 86 87 assert(rrb && rrb->bo); 88 89 /* Make a temporary buffer and blit the current contents of the renderbuffer 90 * out to it. This gives us linear access to the buffer, instead of having 91 * to do detiling in software. 92 */ 93 assert(!rrb->map_bo); 94 rrb->map_bo = radeon_bo_open(rmesa->radeonScreen->bom, 0, 95 rrb->pitch * h, 4, 96 RADEON_GEM_DOMAIN_GTT, 0); 97 rrb->map_mode = mode; 98 rrb->map_x = x; 99 rrb->map_y = y; 100 rrb->map_w = w; 101 rrb->map_h = h; 102 103 ok = rmesa->vtbl.check_blit(rb->Format); 104 assert(ok); 105 106 ok = rmesa->vtbl.blit(ctx, rrb->bo, rrb->draw_offset, 107 rb->Format, rrb->pitch / rrb->cpp, 108 rb->Width, rb->Height, 109 x, y, 110 rrb->map_bo, 0, 111 rb->Format, rrb->pitch / rrb->cpp, 112 w, h, 113 0, 0, 114 w, h, 115 GL_FALSE); 116 assert(ok); 117 118 radeon_bo_wait(rrb->map_bo); 119 ret = radeon_bo_map(rrb->map_bo, !!(mode & GL_MAP_WRITE_BIT)); 120 assert(!ret); 121 122 map = rrb->map_bo->ptr; 123 stride = rrb->pitch; 124 125 if (rb->Name == 0) { 126 map += stride * (rb->Height - 1); 127 stride = -stride; 128 } 129 130 map += x * _mesa_get_format_bytes(rb->Format); 131 map += (int)y * stride; 132 133 *out_map = map; 134 *out_stride = stride; 135} 136 137static void 138radeon_unmap_renderbuffer(struct gl_context *ctx, 139 struct gl_renderbuffer *rb) 140{ 141 struct radeon_context *const rmesa = RADEON_CONTEXT(ctx); 142 struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); 143 GLboolean ok; 144 145 radeon_bo_unmap(rrb->map_bo); 146 147 if (rrb->map_mode & GL_MAP_WRITE_BIT) { 148 ok = rmesa->vtbl.blit(ctx, rrb->map_bo, 0, 149 rb->Format, rrb->pitch / rrb->cpp, 150 rrb->map_w, rrb->map_h, 151 0, 0, 152 rrb->bo, rrb->draw_offset, 153 rb->Format, rrb->pitch / rrb->cpp, 154 rb->Width, rb->Height, 155 rrb->map_x, rrb->map_y, 156 rrb->map_w, rrb->map_h, 157 GL_FALSE); 158 assert(ok); 159 } 160 161 radeon_bo_unref(rrb->map_bo); 162 rrb->map_bo = NULL; 163} 164 165static void * 166radeon_get_pointer(struct gl_context *ctx, struct gl_renderbuffer *rb, 167 GLint x, GLint y) 168{ 169 radeon_print(RADEON_TEXTURE, RADEON_TRACE, 170 "%s(%p, rb %p) \n", 171 __func__, ctx, rb); 172 173 return NULL; 174} 175 176/** 177 * Called via glRenderbufferStorageEXT() to set the format and allocate 178 * storage for a user-created renderbuffer. 179 */ 180static GLboolean 181radeon_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, 182 GLenum internalFormat, 183 GLuint width, GLuint height) 184{ 185 struct radeon_context *radeon = RADEON_CONTEXT(ctx); 186 struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); 187 uint32_t size, pitch; 188 int cpp; 189 190 radeon_print(RADEON_TEXTURE, RADEON_TRACE, 191 "%s(%p, rb %p) \n", 192 __func__, ctx, rb); 193 194 ASSERT(rb->Name != 0); 195 switch (internalFormat) { 196 case GL_R3_G3_B2: 197 case GL_RGB4: 198 case GL_RGB5: 199 rb->Format = _radeon_texformat_rgb565; 200 rb->DataType = GL_UNSIGNED_BYTE; 201 cpp = 2; 202 break; 203 case GL_RGB: 204 case GL_RGB8: 205 case GL_RGB10: 206 case GL_RGB12: 207 case GL_RGB16: 208 rb->Format = _radeon_texformat_argb8888; 209 rb->DataType = GL_UNSIGNED_BYTE; 210 cpp = 4; 211 break; 212 case GL_RGBA: 213 case GL_RGBA2: 214 case GL_RGBA4: 215 case GL_RGB5_A1: 216 case GL_RGBA8: 217 case GL_RGB10_A2: 218 case GL_RGBA12: 219 case GL_RGBA16: 220 rb->Format = _radeon_texformat_argb8888; 221 rb->DataType = GL_UNSIGNED_BYTE; 222 cpp = 4; 223 break; 224 case GL_STENCIL_INDEX: 225 case GL_STENCIL_INDEX1_EXT: 226 case GL_STENCIL_INDEX4_EXT: 227 case GL_STENCIL_INDEX8_EXT: 228 case GL_STENCIL_INDEX16_EXT: 229 /* alloc a depth+stencil buffer */ 230 rb->Format = MESA_FORMAT_S8_Z24; 231 rb->DataType = GL_UNSIGNED_INT_24_8_EXT; 232 cpp = 4; 233 break; 234 case GL_DEPTH_COMPONENT16: 235 rb->Format = MESA_FORMAT_Z16; 236 rb->DataType = GL_UNSIGNED_SHORT; 237 cpp = 2; 238 break; 239 case GL_DEPTH_COMPONENT: 240 case GL_DEPTH_COMPONENT24: 241 case GL_DEPTH_COMPONENT32: 242 rb->Format = MESA_FORMAT_X8_Z24; 243 rb->DataType = GL_UNSIGNED_INT; 244 cpp = 4; 245 break; 246 case GL_DEPTH_STENCIL_EXT: 247 case GL_DEPTH24_STENCIL8_EXT: 248 rb->Format = MESA_FORMAT_S8_Z24; 249 rb->DataType = GL_UNSIGNED_INT_24_8_EXT; 250 cpp = 4; 251 break; 252 default: 253 _mesa_problem(ctx, 254 "Unexpected format in radeon_alloc_renderbuffer_storage"); 255 return GL_FALSE; 256 } 257 258 rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); 259 260 if (ctx->Driver.Flush) 261 ctx->Driver.Flush(ctx); /* +r6/r7 */ 262 263 if (rrb->bo) 264 radeon_bo_unref(rrb->bo); 265 266 pitch = ((cpp * width + 63) & ~63) / cpp; 267 268 if (RADEON_DEBUG & RADEON_MEMORY) 269 fprintf(stderr,"Allocating %d x %d radeon RBO (pitch %d)\n", width, 270 height, pitch); 271 272 size = pitch * height * cpp; 273 rrb->pitch = pitch * cpp; 274 rrb->cpp = cpp; 275 rrb->bo = radeon_bo_open(radeon->radeonScreen->bom, 276 0, 277 size, 278 0, 279 RADEON_GEM_DOMAIN_VRAM, 280 0); 281 rb->Width = width; 282 rb->Height = height; 283 return GL_TRUE; 284} 285 286#if FEATURE_OES_EGL_image 287static void 288radeon_image_target_renderbuffer_storage(struct gl_context *ctx, 289 struct gl_renderbuffer *rb, 290 void *image_handle) 291{ 292 radeonContextPtr radeon = RADEON_CONTEXT(ctx); 293 struct radeon_renderbuffer *rrb; 294 __DRIscreen *screen; 295 __DRIimage *image; 296 297 screen = radeon->radeonScreen->driScreen; 298 image = screen->dri2.image->lookupEGLImage(screen, image_handle, 299 screen->loaderPrivate); 300 if (image == NULL) 301 return; 302 303 rrb = radeon_renderbuffer(rb); 304 305 if (ctx->Driver.Flush) 306 ctx->Driver.Flush(ctx); /* +r6/r7 */ 307 308 if (rrb->bo) 309 radeon_bo_unref(rrb->bo); 310 rrb->bo = image->bo; 311 radeon_bo_ref(rrb->bo); 312 fprintf(stderr, "image->bo: %p, name: %d, rbs: w %d -> p %d\n", image->bo, image->bo->handle, 313 image->width, image->pitch); 314 315 rrb->cpp = image->cpp; 316 rrb->pitch = image->pitch * image->cpp; 317 318 rb->Format = image->format; 319 rb->InternalFormat = image->internal_format; 320 rb->Width = image->width; 321 rb->Height = image->height; 322 rb->Format = image->format; 323 rb->DataType = image->data_type; 324 rb->_BaseFormat = _mesa_base_fbo_format(radeon->glCtx, 325 image->internal_format); 326} 327#endif 328 329/** 330 * Called for each hardware renderbuffer when a _window_ is resized. 331 * Just update fields. 332 * Not used for user-created renderbuffers! 333 */ 334static GLboolean 335radeon_alloc_window_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, 336 GLenum internalFormat, GLuint width, GLuint height) 337{ 338 ASSERT(rb->Name == 0); 339 rb->Width = width; 340 rb->Height = height; 341 rb->InternalFormat = internalFormat; 342 radeon_print(RADEON_TEXTURE, RADEON_TRACE, 343 "%s(%p, rb %p) \n", 344 __func__, ctx, rb); 345 346 347 return GL_TRUE; 348} 349 350 351static void 352radeon_resize_buffers(struct gl_context *ctx, struct gl_framebuffer *fb, 353 GLuint width, GLuint height) 354{ 355 struct radeon_framebuffer *radeon_fb = (struct radeon_framebuffer*)fb; 356 int i; 357 358 radeon_print(RADEON_TEXTURE, RADEON_TRACE, 359 "%s(%p, fb %p) \n", 360 __func__, ctx, fb); 361 362 _mesa_resize_framebuffer(ctx, fb, width, height); 363 364 fb->Initialized = GL_TRUE; /* XXX remove someday */ 365 366 if (fb->Name != 0) { 367 return; 368 } 369 370 /* Make sure all window system renderbuffers are up to date */ 371 for (i = 0; i < 2; i++) { 372 struct gl_renderbuffer *rb = &radeon_fb->color_rb[i]->base; 373 374 /* only resize if size is changing */ 375 if (rb && (rb->Width != width || rb->Height != height)) { 376 rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height); 377 } 378 } 379} 380 381 382/** Dummy function for gl_renderbuffer::AllocStorage() */ 383static GLboolean 384radeon_nop_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, 385 GLenum internalFormat, GLuint width, GLuint height) 386{ 387 _mesa_problem(ctx, "radeon_op_alloc_storage should never be called."); 388 return GL_FALSE; 389} 390 391 392/** 393 * Create a renderbuffer for a window's color, depth and/or stencil buffer. 394 * Not used for user-created renderbuffers. 395 */ 396struct radeon_renderbuffer * 397radeon_create_renderbuffer(gl_format format, __DRIdrawable *driDrawPriv) 398{ 399 struct radeon_renderbuffer *rrb; 400 401 rrb = CALLOC_STRUCT(radeon_renderbuffer); 402 403 radeon_print(RADEON_TEXTURE, RADEON_TRACE, 404 "%s( rrb %p ) \n", 405 __func__, rrb); 406 407 if (!rrb) 408 return NULL; 409 410 _mesa_init_renderbuffer(&rrb->base, 0); 411 rrb->base.ClassID = RADEON_RB_CLASS; 412 413 rrb->base.Format = format; 414 415 switch (format) { 416 case MESA_FORMAT_RGB565: 417 assert(_mesa_little_endian()); 418 rrb->base.DataType = GL_UNSIGNED_BYTE; 419 break; 420 case MESA_FORMAT_RGB565_REV: 421 assert(!_mesa_little_endian()); 422 rrb->base.DataType = GL_UNSIGNED_BYTE; 423 break; 424 case MESA_FORMAT_XRGB8888: 425 assert(_mesa_little_endian()); 426 rrb->base.DataType = GL_UNSIGNED_BYTE; 427 break; 428 case MESA_FORMAT_XRGB8888_REV: 429 assert(!_mesa_little_endian()); 430 rrb->base.DataType = GL_UNSIGNED_BYTE; 431 break; 432 case MESA_FORMAT_ARGB8888: 433 assert(_mesa_little_endian()); 434 rrb->base.DataType = GL_UNSIGNED_BYTE; 435 break; 436 case MESA_FORMAT_ARGB8888_REV: 437 assert(!_mesa_little_endian()); 438 rrb->base.DataType = GL_UNSIGNED_BYTE; 439 break; 440 case MESA_FORMAT_S8: 441 rrb->base.DataType = GL_UNSIGNED_BYTE; 442 break; 443 case MESA_FORMAT_Z16: 444 rrb->base.DataType = GL_UNSIGNED_SHORT; 445 break; 446 case MESA_FORMAT_X8_Z24: 447 rrb->base.DataType = GL_UNSIGNED_INT; 448 break; 449 case MESA_FORMAT_S8_Z24: 450 rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT; 451 break; 452 default: 453 fprintf(stderr, "%s: Unknown format %s\n", 454 __FUNCTION__, _mesa_get_format_name(format)); 455 _mesa_delete_renderbuffer(&rrb->base); 456 return NULL; 457 } 458 rrb->base._BaseFormat = _mesa_get_format_base_format(format); 459 460 rrb->dPriv = driDrawPriv; 461 rrb->base.InternalFormat = _mesa_get_format_base_format(format); 462 463 rrb->base.Delete = radeon_delete_renderbuffer; 464 rrb->base.AllocStorage = radeon_alloc_window_storage; 465 rrb->base.GetPointer = radeon_get_pointer; 466 467 rrb->bo = NULL; 468 return rrb; 469} 470 471static struct gl_renderbuffer * 472radeon_new_renderbuffer(struct gl_context * ctx, GLuint name) 473{ 474 struct radeon_renderbuffer *rrb; 475 476 rrb = CALLOC_STRUCT(radeon_renderbuffer); 477 478 radeon_print(RADEON_TEXTURE, RADEON_TRACE, 479 "%s(%p, rrb %p) \n", 480 __func__, ctx, rrb); 481 482 if (!rrb) 483 return NULL; 484 485 _mesa_init_renderbuffer(&rrb->base, name); 486 rrb->base.ClassID = RADEON_RB_CLASS; 487 488 rrb->base.Delete = radeon_delete_renderbuffer; 489 rrb->base.AllocStorage = radeon_alloc_renderbuffer_storage; 490 rrb->base.GetPointer = radeon_get_pointer; 491 492 return &rrb->base; 493} 494 495static void 496radeon_bind_framebuffer(struct gl_context * ctx, GLenum target, 497 struct gl_framebuffer *fb, struct gl_framebuffer *fbread) 498{ 499 radeon_print(RADEON_TEXTURE, RADEON_TRACE, 500 "%s(%p, fb %p, target %s) \n", 501 __func__, ctx, fb, 502 _mesa_lookup_enum_by_nr(target)); 503 504 if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) { 505 radeon_draw_buffer(ctx, fb); 506 } 507 else { 508 /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */ 509 } 510} 511 512static void 513radeon_framebuffer_renderbuffer(struct gl_context * ctx, 514 struct gl_framebuffer *fb, 515 GLenum attachment, struct gl_renderbuffer *rb) 516{ 517 518 if (ctx->Driver.Flush) 519 ctx->Driver.Flush(ctx); /* +r6/r7 */ 520 521 radeon_print(RADEON_TEXTURE, RADEON_TRACE, 522 "%s(%p, fb %p, rb %p) \n", 523 __func__, ctx, fb, rb); 524 525 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb); 526 radeon_draw_buffer(ctx, fb); 527} 528 529static GLboolean 530radeon_update_wrapper(struct gl_context *ctx, struct radeon_renderbuffer *rrb, 531 struct gl_texture_image *texImage) 532{ 533 radeon_print(RADEON_TEXTURE, RADEON_TRACE, 534 "%s(%p, rrb %p, texImage %p, texFormat %s) \n", 535 __func__, ctx, rrb, texImage, _mesa_get_format_name(texImage->TexFormat)); 536 537 switch (texImage->TexFormat) { 538 case MESA_FORMAT_RGBA8888: 539 case MESA_FORMAT_RGBA8888_REV: 540 case MESA_FORMAT_ARGB8888: 541 case MESA_FORMAT_ARGB8888_REV: 542 case MESA_FORMAT_XRGB8888: 543 case MESA_FORMAT_XRGB8888_REV: 544 case MESA_FORMAT_RGB565: 545 case MESA_FORMAT_RGB565_REV: 546 case MESA_FORMAT_RGBA5551: 547 case MESA_FORMAT_ARGB1555: 548 case MESA_FORMAT_ARGB1555_REV: 549 case MESA_FORMAT_ARGB4444: 550 case MESA_FORMAT_ARGB4444_REV: 551 rrb->base.DataType = GL_UNSIGNED_BYTE; 552 break; 553 case MESA_FORMAT_Z16: 554 rrb->base.DataType = GL_UNSIGNED_SHORT; 555 break; 556 case MESA_FORMAT_X8_Z24: 557 rrb->base.DataType = GL_UNSIGNED_INT; 558 break; 559 case MESA_FORMAT_S8_Z24: 560 rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT; 561 break; 562 default: 563 _mesa_problem(ctx, "Unexpected texture format in radeon_update_wrapper()"); 564 } 565 566 rrb->cpp = _mesa_get_format_bytes(texImage->TexFormat); 567 rrb->pitch = texImage->Width * rrb->cpp; 568 rrb->base.Format = texImage->TexFormat; 569 rrb->base.InternalFormat = texImage->InternalFormat; 570 rrb->base._BaseFormat = _mesa_base_fbo_format(ctx, rrb->base.InternalFormat); 571 rrb->base.Width = texImage->Width; 572 rrb->base.Height = texImage->Height; 573 rrb->base.Delete = radeon_delete_renderbuffer; 574 rrb->base.AllocStorage = radeon_nop_alloc_storage; 575 576 return GL_TRUE; 577} 578 579 580static struct radeon_renderbuffer * 581radeon_wrap_texture(struct gl_context * ctx, struct gl_texture_image *texImage) 582{ 583 const GLuint name = ~0; /* not significant, but distinct for debugging */ 584 struct radeon_renderbuffer *rrb; 585 586 /* make an radeon_renderbuffer to wrap the texture image */ 587 rrb = CALLOC_STRUCT(radeon_renderbuffer); 588 589 radeon_print(RADEON_TEXTURE, RADEON_TRACE, 590 "%s(%p, rrb %p, texImage %p) \n", 591 __func__, ctx, rrb, texImage); 592 593 if (!rrb) { 594 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture"); 595 return NULL; 596 } 597 598 _mesa_init_renderbuffer(&rrb->base, name); 599 rrb->base.ClassID = RADEON_RB_CLASS; 600 601 if (!radeon_update_wrapper(ctx, rrb, texImage)) { 602 free(rrb); 603 return NULL; 604 } 605 606 return rrb; 607 608} 609static void 610radeon_render_texture(struct gl_context * ctx, 611 struct gl_framebuffer *fb, 612 struct gl_renderbuffer_attachment *att) 613{ 614 struct gl_texture_image *newImage 615 = att->Texture->Image[att->CubeMapFace][att->TextureLevel]; 616 struct radeon_renderbuffer *rrb = radeon_renderbuffer(att->Renderbuffer); 617 radeon_texture_image *radeon_image; 618 GLuint imageOffset; 619 620 radeon_print(RADEON_TEXTURE, RADEON_TRACE, 621 "%s(%p, fb %p, rrb %p, att %p)\n", 622 __func__, ctx, fb, rrb, att); 623 624 (void) fb; 625 626 ASSERT(newImage); 627 628 radeon_image = (radeon_texture_image *)newImage; 629 630 if (!radeon_image->mt || newImage->Border != 0) { 631 /* Fallback on drawing to a texture without a miptree. 632 */ 633 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); 634 _swrast_render_texture(ctx, fb, att); 635 return; 636 } 637 else if (!rrb) { 638 rrb = radeon_wrap_texture(ctx, newImage); 639 if (rrb) { 640 /* bind the wrapper to the attachment point */ 641 _mesa_reference_renderbuffer(&att->Renderbuffer, &rrb->base); 642 } 643 else { 644 /* fallback to software rendering */ 645 _swrast_render_texture(ctx, fb, att); 646 return; 647 } 648 } 649 650 if (!radeon_update_wrapper(ctx, rrb, newImage)) { 651 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); 652 _swrast_render_texture(ctx, fb, att); 653 return; 654 } 655 656 DBG("Begin render texture tid %lx tex=%u w=%d h=%d refcount=%d\n", 657 _glthread_GetID(), 658 att->Texture->Name, newImage->Width, newImage->Height, 659 rrb->base.RefCount); 660 661 /* point the renderbufer's region to the texture image region */ 662 if (rrb->bo != radeon_image->mt->bo) { 663 if (rrb->bo) 664 radeon_bo_unref(rrb->bo); 665 rrb->bo = radeon_image->mt->bo; 666 radeon_bo_ref(rrb->bo); 667 } 668 669 /* compute offset of the particular 2D image within the texture region */ 670 imageOffset = radeon_miptree_image_offset(radeon_image->mt, 671 att->CubeMapFace, 672 att->TextureLevel); 673 674 if (att->Texture->Target == GL_TEXTURE_3D) { 675 imageOffset += radeon_image->mt->levels[att->TextureLevel].rowstride * 676 radeon_image->mt->levels[att->TextureLevel].height * 677 att->Zoffset; 678 } 679 680 /* store that offset in the region, along with the correct pitch for 681 * the image we are rendering to */ 682 rrb->draw_offset = imageOffset; 683 rrb->pitch = radeon_image->mt->levels[att->TextureLevel].rowstride; 684 685 /* update drawing region, etc */ 686 radeon_draw_buffer(ctx, fb); 687} 688 689static void 690radeon_finish_render_texture(struct gl_context * ctx, 691 struct gl_renderbuffer_attachment *att) 692{ 693 694} 695static void 696radeon_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) 697{ 698 radeonContextPtr radeon = RADEON_CONTEXT(ctx); 699 gl_format mesa_format; 700 int i; 701 702 for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) { 703 struct gl_renderbuffer_attachment *att; 704 if (i == -2) { 705 att = &fb->Attachment[BUFFER_DEPTH]; 706 } else if (i == -1) { 707 att = &fb->Attachment[BUFFER_STENCIL]; 708 } else { 709 att = &fb->Attachment[BUFFER_COLOR0 + i]; 710 } 711 712 if (att->Type == GL_TEXTURE) { 713 mesa_format = att->Texture->Image[att->CubeMapFace][att->TextureLevel]->TexFormat; 714 } else { 715 /* All renderbuffer formats are renderable, but not sampable */ 716 continue; 717 } 718 719 if (!radeon->vtbl.is_format_renderable(mesa_format)){ 720 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED; 721 radeon_print(RADEON_TEXTURE, RADEON_TRACE, 722 "%s: HW doesn't support format %s as output format of attachment %d\n", 723 __FUNCTION__, _mesa_get_format_name(mesa_format), i); 724 return; 725 } 726 } 727} 728 729void radeon_fbo_init(struct radeon_context *radeon) 730{ 731#if FEATURE_EXT_framebuffer_object 732 radeon->glCtx->Driver.NewFramebuffer = radeon_new_framebuffer; 733 radeon->glCtx->Driver.NewRenderbuffer = radeon_new_renderbuffer; 734 radeon->glCtx->Driver.MapRenderbuffer = radeon_map_renderbuffer; 735 radeon->glCtx->Driver.UnmapRenderbuffer = radeon_unmap_renderbuffer; 736 radeon->glCtx->Driver.BindFramebuffer = radeon_bind_framebuffer; 737 radeon->glCtx->Driver.FramebufferRenderbuffer = radeon_framebuffer_renderbuffer; 738 radeon->glCtx->Driver.RenderTexture = radeon_render_texture; 739 radeon->glCtx->Driver.FinishRenderTexture = radeon_finish_render_texture; 740 radeon->glCtx->Driver.ResizeBuffers = radeon_resize_buffers; 741 radeon->glCtx->Driver.ValidateFramebuffer = radeon_validate_framebuffer; 742#endif 743#if FEATURE_EXT_framebuffer_blit 744 radeon->glCtx->Driver.BlitFramebuffer = _mesa_meta_BlitFramebuffer; 745#endif 746#if FEATURE_OES_EGL_image 747 radeon->glCtx->Driver.EGLImageTargetRenderbufferStorage = 748 radeon_image_target_renderbuffer_storage; 749#endif 750} 751 752 753void radeon_renderbuffer_set_bo(struct radeon_renderbuffer *rb, 754 struct radeon_bo *bo) 755{ 756 struct radeon_bo *old; 757 old = rb->bo; 758 rb->bo = bo; 759 radeon_bo_ref(bo); 760 if (old) 761 radeon_bo_unref(old); 762} 763