radeon_fbo.c revision 8a600836766716df684f2ab1eeafdcbec4b0f019
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/mtypes.h" 32#include "main/fbobject.h" 33#include "main/framebuffer.h" 34#include "main/renderbuffer.h" 35#include "main/context.h" 36#include "main/texformat.h" 37#include "main/texrender.h" 38 39#include "radeon_common.h" 40#include "radeon_mipmap_tree.h" 41 42#define FILE_DEBUG_FLAG DEBUG_TEXTURE 43#define DBG(...) do { \ 44 if (RADEON_DEBUG & FILE_DEBUG_FLAG) \ 45 _mesa_printf(__VA_ARGS__); \ 46} while(0) 47 48static struct gl_framebuffer * 49radeon_new_framebuffer(GLcontext *ctx, GLuint name) 50{ 51 return _mesa_new_framebuffer(ctx, name); 52} 53 54static void 55radeon_delete_renderbuffer(struct gl_renderbuffer *rb) 56{ 57 GET_CURRENT_CONTEXT(ctx); 58 struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); 59 60 ASSERT(rrb); 61 62 if (rrb && rrb->bo) { 63 radeon_bo_unref(rrb->bo); 64 } 65 66 67 _mesa_free(rrb); 68} 69 70static void * 71radeon_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb, 72 GLint x, GLint y) 73{ 74 return NULL; 75} 76 77/** 78 * Called via glRenderbufferStorageEXT() to set the format and allocate 79 * storage for a user-created renderbuffer. 80 */ 81static GLboolean 82radeon_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb, 83 GLenum internalFormat, 84 GLuint width, GLuint height) 85{ 86 struct radeon_context *radeon = RADEON_CONTEXT(ctx); 87 struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); 88 GLboolean software_buffer = GL_FALSE; 89 int cpp; 90 91 ASSERT(rb->Name != 0); 92 switch (internalFormat) { 93 case GL_R3_G3_B2: 94 case GL_RGB4: 95 case GL_RGB5: 96 rb->_ActualFormat = GL_RGB5; 97 rb->DataType = GL_UNSIGNED_BYTE; 98 rb->RedBits = 5; 99 rb->GreenBits = 6; 100 rb->BlueBits = 5; 101 cpp = 2; 102 break; 103 case GL_RGB: 104 case GL_RGB8: 105 case GL_RGB10: 106 case GL_RGB12: 107 case GL_RGB16: 108 rb->_ActualFormat = GL_RGB8; 109 rb->DataType = GL_UNSIGNED_BYTE; 110 rb->RedBits = 8; 111 rb->GreenBits = 8; 112 rb->BlueBits = 8; 113 rb->AlphaBits = 0; 114 cpp = 4; 115 break; 116 case GL_RGBA: 117 case GL_RGBA2: 118 case GL_RGBA4: 119 case GL_RGB5_A1: 120 case GL_RGBA8: 121 case GL_RGB10_A2: 122 case GL_RGBA12: 123 case GL_RGBA16: 124 rb->_ActualFormat = GL_RGBA8; 125 rb->DataType = GL_UNSIGNED_BYTE; 126 rb->RedBits = 8; 127 rb->GreenBits = 8; 128 rb->BlueBits = 8; 129 rb->AlphaBits = 8; 130 cpp = 4; 131 break; 132 case GL_STENCIL_INDEX: 133 case GL_STENCIL_INDEX1_EXT: 134 case GL_STENCIL_INDEX4_EXT: 135 case GL_STENCIL_INDEX8_EXT: 136 case GL_STENCIL_INDEX16_EXT: 137 /* alloc a depth+stencil buffer */ 138 rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT; 139 rb->DataType = GL_UNSIGNED_INT_24_8_EXT; 140 rb->StencilBits = 8; 141 cpp = 4; 142 break; 143 case GL_DEPTH_COMPONENT16: 144 rb->_ActualFormat = GL_DEPTH_COMPONENT16; 145 rb->DataType = GL_UNSIGNED_SHORT; 146 rb->DepthBits = 16; 147 cpp = 2; 148 break; 149 case GL_DEPTH_COMPONENT: 150 case GL_DEPTH_COMPONENT24: 151 case GL_DEPTH_COMPONENT32: 152 rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT; 153 rb->DataType = GL_UNSIGNED_INT_24_8_EXT; 154 rb->DepthBits = 24; 155 cpp = 4; 156 break; 157 case GL_DEPTH_STENCIL_EXT: 158 case GL_DEPTH24_STENCIL8_EXT: 159 rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT; 160 rb->DataType = GL_UNSIGNED_INT_24_8_EXT; 161 rb->DepthBits = 24; 162 rb->StencilBits = 8; 163 cpp = 4; 164 break; 165 default: 166 _mesa_problem(ctx, 167 "Unexpected format in intel_alloc_renderbuffer_storage"); 168 return GL_FALSE; 169 } 170 171 radeonFlush(ctx); 172 173 if (rrb->bo) 174 radeon_bo_unref(rrb->bo); 175 176 177 if (software_buffer) { 178 return _mesa_soft_renderbuffer_storage(ctx, rb, internalFormat, 179 width, height); 180 } 181 else { 182 /* TODO Alloc a BO */ 183 uint32_t size = width * height * cpp; 184 185 rrb->pitch = width * cpp; 186 rrb->cpp = cpp; 187 rrb->bo = radeon_bo_open(radeon->radeonScreen->bom, 188 0, 189 size, 190 0, 191 RADEON_GEM_DOMAIN_VRAM, 192 0); 193 // rrb->bo = radeon_bo_open(); 194 rb->Width = width; 195 rb->Height = height; 196 return GL_TRUE; 197 } 198 199} 200 201 202/** 203 * Called for each hardware renderbuffer when a _window_ is resized. 204 * Just update fields. 205 * Not used for user-created renderbuffers! 206 */ 207static GLboolean 208radeon_alloc_window_storage(GLcontext * ctx, struct gl_renderbuffer *rb, 209 GLenum internalFormat, GLuint width, GLuint height) 210{ 211 ASSERT(rb->Name == 0); 212 rb->Width = width; 213 rb->Height = height; 214 rb->_ActualFormat = internalFormat; 215 216 return GL_TRUE; 217} 218 219 220static void 221radeon_resize_buffers(GLcontext *ctx, struct gl_framebuffer *fb, 222 GLuint width, GLuint height) 223{ 224 struct radeon_framebuffer *radeon_fb = (struct radeon_framebuffer*)fb; 225 int i; 226 227 _mesa_resize_framebuffer(ctx, fb, width, height); 228 229 fb->Initialized = GL_TRUE; /* XXX remove someday */ 230 231 if (fb->Name != 0) { 232 return; 233 } 234 235 /* Make sure all window system renderbuffers are up to date */ 236 for (i = 0; i < 2; i++) { 237 struct gl_renderbuffer *rb = &radeon_fb->color_rb[i]->base; 238 239 /* only resize if size is changing */ 240 if (rb && (rb->Width != width || rb->Height != height)) { 241 rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height); 242 } 243 } 244} 245 246 247/** Dummy function for gl_renderbuffer::AllocStorage() */ 248static GLboolean 249radeon_nop_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb, 250 GLenum internalFormat, GLuint width, GLuint height) 251{ 252 _mesa_problem(ctx, "radeon_op_alloc_storage should never be called."); 253 return GL_FALSE; 254} 255 256struct gl_renderbuffer * 257radeon_create_renderbuffer(GLenum format, __DRIdrawablePrivate *driDrawPriv) 258{ 259 struct radeon_renderbuffer *rrb; 260 261 rrb = CALLOC_STRUCT(radeon_renderbuffer); 262 if (!rrb) 263 return NULL; 264 265 _mesa_init_renderbuffer(&rrb->base, 0); 266 rrb->base.ClassID = RADEON_RB_CLASS; 267 268 /* XXX format junk */ 269 switch (format) { 270 case GL_RGB5: 271 rrb->base._ActualFormat = GL_RGB5; 272 rrb->base._BaseFormat = GL_RGBA; 273 rrb->base.RedBits = 5; 274 rrb->base.GreenBits = 6; 275 rrb->base.BlueBits = 5; 276 rrb->base.DataType = GL_UNSIGNED_BYTE; 277 break; 278 case GL_RGBA8: 279 rrb->base._ActualFormat = GL_RGBA8; 280 rrb->base._BaseFormat = GL_RGBA; 281 rrb->base.RedBits = 8; 282 rrb->base.GreenBits = 8; 283 rrb->base.BlueBits = 8; 284 rrb->base.AlphaBits = 8; 285 rrb->base.DataType = GL_UNSIGNED_BYTE; 286 break; 287 case GL_STENCIL_INDEX8_EXT: 288 rrb->base._ActualFormat = GL_STENCIL_INDEX8_EXT; 289 rrb->base._BaseFormat = GL_STENCIL_INDEX; 290 rrb->base.StencilBits = 8; 291 rrb->base.DataType = GL_UNSIGNED_BYTE; 292 break; 293 case GL_DEPTH_COMPONENT16: 294 rrb->base._ActualFormat = GL_DEPTH_COMPONENT16; 295 rrb->base._BaseFormat = GL_DEPTH_COMPONENT; 296 rrb->base.DepthBits = 16; 297 rrb->base.DataType = GL_UNSIGNED_SHORT; 298 break; 299 case GL_DEPTH_COMPONENT24: 300 rrb->base._ActualFormat = GL_DEPTH24_STENCIL8_EXT; 301 rrb->base._BaseFormat = GL_DEPTH_COMPONENT; 302 rrb->base.DepthBits = 24; 303 rrb->base.DataType = GL_UNSIGNED_INT; 304 break; 305 case GL_DEPTH24_STENCIL8_EXT: 306 rrb->base._ActualFormat = GL_DEPTH24_STENCIL8_EXT; 307 rrb->base._BaseFormat = GL_DEPTH_STENCIL_EXT; 308 rrb->base.DepthBits = 24; 309 rrb->base.StencilBits = 8; 310 rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT; 311 break; 312 default: 313 fprintf(stderr, "%s: Unknown format 0x%04x\n", __FUNCTION__, format); 314 _mesa_delete_renderbuffer(&rrb->base); 315 return NULL; 316 } 317 318 rrb->dPriv = driDrawPriv; 319 rrb->base.InternalFormat = format; 320 321 rrb->base.Delete = radeon_delete_renderbuffer; 322 rrb->base.AllocStorage = radeon_alloc_window_storage; 323 rrb->base.GetPointer = radeon_get_pointer; 324 325 rrb->bo = NULL; 326 return &rrb->base; 327} 328 329static struct gl_renderbuffer * 330radeon_new_renderbuffer(GLcontext * ctx, GLuint name) 331{ 332 struct radeon_renderbuffer *rrb; 333 334 rrb = CALLOC_STRUCT(radeon_renderbuffer); 335 if (!rrb) 336 return NULL; 337 338 _mesa_init_renderbuffer(&rrb->base, name); 339 rrb->base.ClassID = RADEON_RB_CLASS; 340 341 rrb->base.Delete = radeon_delete_renderbuffer; 342 rrb->base.AllocStorage = radeon_alloc_renderbuffer_storage; 343 rrb->base.GetPointer = radeon_get_pointer; 344 345 return &rrb->base; 346} 347 348static void 349radeon_bind_framebuffer(GLcontext * ctx, GLenum target, 350 struct gl_framebuffer *fb, struct gl_framebuffer *fbread) 351{ 352 if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) { 353 radeon_draw_buffer(ctx, fb); 354 } 355 else { 356 /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */ 357 } 358} 359 360static void 361radeon_framebuffer_renderbuffer(GLcontext * ctx, 362 struct gl_framebuffer *fb, 363 GLenum attachment, struct gl_renderbuffer *rb) 364{ 365 366 radeonFlush(ctx); 367 368 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb); 369 radeon_draw_buffer(ctx, fb); 370} 371 372 373static GLboolean 374radeon_update_wrapper(GLcontext *ctx, struct radeon_renderbuffer *rrb, 375 struct gl_texture_image *texImage) 376{ 377 if (texImage->TexFormat == &_mesa_texformat_argb8888) { 378 rrb->base._ActualFormat = GL_RGBA8; 379 rrb->base._BaseFormat = GL_RGBA; 380 rrb->base.DataType = GL_UNSIGNED_BYTE; 381 DBG("Render to RGBA8 texture OK\n"); 382 } 383 else if (texImage->TexFormat == &_mesa_texformat_rgb565) { 384 rrb->base._ActualFormat = GL_RGB5; 385 rrb->base._BaseFormat = GL_RGB; 386 rrb->base.DataType = GL_UNSIGNED_SHORT; 387 DBG("Render to RGB5 texture OK\n"); 388 } 389 else if (texImage->TexFormat == &_mesa_texformat_z16) { 390 rrb->base._ActualFormat = GL_DEPTH_COMPONENT16; 391 rrb->base._BaseFormat = GL_DEPTH_COMPONENT; 392 rrb->base.DataType = GL_UNSIGNED_SHORT; 393 DBG("Render to DEPTH16 texture OK\n"); 394 } 395 else if (texImage->TexFormat == &_mesa_texformat_s8_z24) { 396 rrb->base._ActualFormat = GL_DEPTH24_STENCIL8_EXT; 397 rrb->base._BaseFormat = GL_DEPTH_STENCIL_EXT; 398 rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT; 399 DBG("Render to DEPTH_STENCIL texture OK\n"); 400 } 401 else { 402 DBG("Render to texture BAD FORMAT %d\n", 403 texImage->TexFormat->MesaFormat); 404 return GL_FALSE; 405 } 406 407 rrb->base.InternalFormat = rrb->base._ActualFormat; 408 rrb->base.Width = texImage->Width; 409 rrb->base.Height = texImage->Height; 410 rrb->base.RedBits = texImage->TexFormat->RedBits; 411 rrb->base.GreenBits = texImage->TexFormat->GreenBits; 412 rrb->base.BlueBits = texImage->TexFormat->BlueBits; 413 rrb->base.AlphaBits = texImage->TexFormat->AlphaBits; 414 rrb->base.DepthBits = texImage->TexFormat->DepthBits; 415 416 rrb->base.Delete = radeon_delete_renderbuffer; 417 rrb->base.AllocStorage = radeon_nop_alloc_storage; 418 419 return GL_TRUE; 420} 421 422 423static struct radeon_renderbuffer * 424radeon_wrap_texture(GLcontext * ctx, struct gl_texture_image *texImage) 425{ 426 const GLuint name = ~0; /* not significant, but distinct for debugging */ 427 struct radeon_renderbuffer *rrb; 428 429 /* make an radeon_renderbuffer to wrap the texture image */ 430 rrb = CALLOC_STRUCT(radeon_renderbuffer); 431 if (!rrb) { 432 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture"); 433 return NULL; 434 } 435 436 _mesa_init_renderbuffer(&rrb->base, name); 437 rrb->base.ClassID = RADEON_RB_CLASS; 438 439 if (!radeon_update_wrapper(ctx, rrb, texImage)) { 440 _mesa_free(rrb); 441 return NULL; 442 } 443 444 return rrb; 445 446} 447static void 448radeon_render_texture(GLcontext * ctx, 449 struct gl_framebuffer *fb, 450 struct gl_renderbuffer_attachment *att) 451{ 452 struct gl_texture_image *newImage 453 = att->Texture->Image[att->CubeMapFace][att->TextureLevel]; 454 struct radeon_renderbuffer *rrb = radeon_renderbuffer(att->Renderbuffer); 455 radeon_texture_image *radeon_image; 456 GLuint imageOffset; 457 458 (void) fb; 459 460 ASSERT(newImage); 461 462 if (newImage->Border != 0) { 463 /* Fallback on drawing to a texture with a border, which won't have a 464 * miptree. 465 */ 466 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); 467 _mesa_render_texture(ctx, fb, att); 468 return; 469 } 470 else if (!rrb) { 471 rrb = radeon_wrap_texture(ctx, newImage); 472 if (rrb) { 473 /* bind the wrapper to the attachment point */ 474 _mesa_reference_renderbuffer(&att->Renderbuffer, &rrb->base); 475 } 476 else { 477 /* fallback to software rendering */ 478 _mesa_render_texture(ctx, fb, att); 479 return; 480 } 481 } 482 483 if (!radeon_update_wrapper(ctx, rrb, newImage)) { 484 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); 485 _mesa_render_texture(ctx, fb, att); 486 return; 487 } 488 489 DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n", 490 _glthread_GetID(), 491 att->Texture->Name, newImage->Width, newImage->Height, 492 rrb->base.RefCount); 493 494 /* point the renderbufer's region to the texture image region */ 495 radeon_image = (radeon_texture_image *)newImage; 496 if (rrb->bo != radeon_image->mt->bo) { 497 if (rrb->bo) 498 radeon_bo_unref(rrb->bo); 499 rrb->bo = radeon_image->mt->bo; 500 radeon_bo_ref(rrb->bo); 501 } 502 503#if 0 504 /* compute offset of the particular 2D image within the texture region */ 505 imageOffset = radeon_miptree_image_offset(radeon_image->mt, 506 att->CubeMapFace, 507 att->TextureLevel); 508 509 if (att->Texture->Target == GL_TEXTURE_3D) { 510 const GLuint *offsets = radeon_miptree_depth_offsets(radeon_image->mt, 511 att->TextureLevel); 512 imageOffset += offsets[att->Zoffset]; 513 } 514 515 /* store that offset in the region */ 516 radeon_image->mt->draw_offset = imageOffset; 517#endif 518 /* update drawing region, etc */ 519 radeon_draw_buffer(ctx, fb); 520} 521 522static void 523radeon_finish_render_texture(GLcontext * ctx, 524 struct gl_renderbuffer_attachment *att) 525{ 526 527} 528static void 529radeon_validate_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb) 530{ 531} 532 533static void 534radeon_blit_framebuffer(GLcontext *ctx, 535 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 536 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, 537 GLbitfield mask, GLenum filter) 538{ 539} 540 541void radeon_fbo_init(struct radeon_context *radeon) 542{ 543 radeon->glCtx->Driver.NewFramebuffer = radeon_new_framebuffer; 544 radeon->glCtx->Driver.NewRenderbuffer = radeon_new_renderbuffer; 545 radeon->glCtx->Driver.BindFramebuffer = radeon_bind_framebuffer; 546 radeon->glCtx->Driver.FramebufferRenderbuffer = radeon_framebuffer_renderbuffer; 547 radeon->glCtx->Driver.RenderTexture = radeon_render_texture; 548 radeon->glCtx->Driver.FinishRenderTexture = radeon_finish_render_texture; 549 radeon->glCtx->Driver.ResizeBuffers = radeon_resize_buffers; 550 radeon->glCtx->Driver.ValidateFramebuffer = radeon_validate_framebuffer; 551 radeon->glCtx->Driver.BlitFramebuffer = radeon_blit_framebuffer; 552} 553 554 555 556