1/************************************************************************** 2 * 3 * Copyright 2007 VMware, 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/** 30 * Framebuffer/renderbuffer functions. 31 * 32 * \author Brian Paul 33 */ 34 35 36#include "main/imports.h" 37#include "main/context.h" 38#include "main/fbobject.h" 39#include "main/framebuffer.h" 40#include "main/glformats.h" 41#include "main/macros.h" 42#include "main/renderbuffer.h" 43#include "main/state.h" 44 45#include "pipe/p_context.h" 46#include "pipe/p_defines.h" 47#include "pipe/p_screen.h" 48#include "st_atom.h" 49#include "st_context.h" 50#include "st_cb_fbo.h" 51#include "st_cb_flush.h" 52#include "st_cb_texture.h" 53#include "st_format.h" 54#include "st_texture.h" 55#include "st_manager.h" 56 57#include "util/u_format.h" 58#include "util/u_inlines.h" 59#include "util/u_surface.h" 60 61 62static GLboolean 63st_renderbuffer_alloc_sw_storage(struct gl_context * ctx, 64 struct gl_renderbuffer *rb, 65 GLenum internalFormat, 66 GLuint width, GLuint height) 67{ 68 struct st_context *st = st_context(ctx); 69 struct st_renderbuffer *strb = st_renderbuffer(rb); 70 enum pipe_format format; 71 size_t size; 72 73 free(strb->data); 74 strb->data = NULL; 75 76 if (internalFormat == GL_RGBA16_SNORM) { 77 /* Special case for software accum buffers. Otherwise, if the 78 * call to st_choose_renderbuffer_format() fails (because the 79 * driver doesn't support signed 16-bit/channel colors) we'd 80 * just return without allocating the software accum buffer. 81 */ 82 format = PIPE_FORMAT_R16G16B16A16_SNORM; 83 } 84 else { 85 format = st_choose_renderbuffer_format(st, internalFormat, 0); 86 87 /* Not setting gl_renderbuffer::Format here will cause 88 * FRAMEBUFFER_UNSUPPORTED and ValidateFramebuffer will not be called. 89 */ 90 if (format == PIPE_FORMAT_NONE) { 91 return GL_TRUE; 92 } 93 } 94 95 strb->Base.Format = st_pipe_format_to_mesa_format(format); 96 97 size = _mesa_format_image_size(strb->Base.Format, width, height, 1); 98 strb->data = malloc(size); 99 return strb->data != NULL; 100} 101 102 103/** 104 * gl_renderbuffer::AllocStorage() 105 * This is called to allocate the original drawing surface, and 106 * during window resize. 107 */ 108static GLboolean 109st_renderbuffer_alloc_storage(struct gl_context * ctx, 110 struct gl_renderbuffer *rb, 111 GLenum internalFormat, 112 GLuint width, GLuint height) 113{ 114 struct st_context *st = st_context(ctx); 115 struct pipe_context *pipe = st->pipe; 116 struct pipe_screen *screen = st->pipe->screen; 117 struct st_renderbuffer *strb = st_renderbuffer(rb); 118 enum pipe_format format = PIPE_FORMAT_NONE; 119 struct pipe_surface surf_tmpl; 120 struct pipe_resource templ; 121 122 /* init renderbuffer fields */ 123 strb->Base.Width = width; 124 strb->Base.Height = height; 125 strb->Base._BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); 126 strb->defined = GL_FALSE; /* undefined contents now */ 127 128 if (strb->software) { 129 return st_renderbuffer_alloc_sw_storage(ctx, rb, internalFormat, 130 width, height); 131 } 132 133 /* Free the old surface and texture 134 */ 135 pipe_surface_reference( &strb->surface, NULL ); 136 pipe_resource_reference( &strb->texture, NULL ); 137 138 /* If an sRGB framebuffer is unsupported, sRGB formats behave like linear 139 * formats. 140 */ 141 if (!ctx->Extensions.EXT_framebuffer_sRGB) { 142 internalFormat = _mesa_get_linear_internalformat(internalFormat); 143 } 144 145 /* Handle multisample renderbuffers first. 146 * 147 * From ARB_framebuffer_object: 148 * If <samples> is zero, then RENDERBUFFER_SAMPLES is set to zero. 149 * Otherwise <samples> represents a request for a desired minimum 150 * number of samples. Since different implementations may support 151 * different sample counts for multisampled rendering, the actual 152 * number of samples allocated for the renderbuffer image is 153 * implementation dependent. However, the resulting value for 154 * RENDERBUFFER_SAMPLES is guaranteed to be greater than or equal 155 * to <samples> and no more than the next larger sample count supported 156 * by the implementation. 157 * 158 * So let's find the supported number of samples closest to NumSamples. 159 * (NumSamples == 1) is treated the same as (NumSamples == 0). 160 */ 161 if (rb->NumSamples > 1) { 162 unsigned i; 163 164 for (i = rb->NumSamples; i <= ctx->Const.MaxSamples; i++) { 165 format = st_choose_renderbuffer_format(st, internalFormat, i); 166 167 if (format != PIPE_FORMAT_NONE) { 168 rb->NumSamples = i; 169 break; 170 } 171 } 172 } else { 173 format = st_choose_renderbuffer_format(st, internalFormat, 0); 174 } 175 176 /* Not setting gl_renderbuffer::Format here will cause 177 * FRAMEBUFFER_UNSUPPORTED and ValidateFramebuffer will not be called. 178 */ 179 if (format == PIPE_FORMAT_NONE) { 180 return GL_TRUE; 181 } 182 183 strb->Base.Format = st_pipe_format_to_mesa_format(format); 184 185 if (width == 0 || height == 0) { 186 /* if size is zero, nothing to allocate */ 187 return GL_TRUE; 188 } 189 190 /* Setup new texture template. 191 */ 192 memset(&templ, 0, sizeof(templ)); 193 templ.target = st->internal_target; 194 templ.format = format; 195 templ.width0 = width; 196 templ.height0 = height; 197 templ.depth0 = 1; 198 templ.array_size = 1; 199 templ.nr_samples = rb->NumSamples; 200 if (util_format_is_depth_or_stencil(format)) { 201 templ.bind = PIPE_BIND_DEPTH_STENCIL; 202 } 203 else if (strb->Base.Name != 0) { 204 /* this is a user-created renderbuffer */ 205 templ.bind = PIPE_BIND_RENDER_TARGET; 206 } 207 else { 208 /* this is a window-system buffer */ 209 templ.bind = (PIPE_BIND_DISPLAY_TARGET | 210 PIPE_BIND_RENDER_TARGET); 211 } 212 213 strb->texture = screen->resource_create(screen, &templ); 214 215 if (!strb->texture) 216 return FALSE; 217 218 u_surface_default_template(&surf_tmpl, strb->texture); 219 strb->surface = pipe->create_surface(pipe, 220 strb->texture, 221 &surf_tmpl); 222 if (strb->surface) { 223 assert(strb->surface->texture); 224 assert(strb->surface->format); 225 assert(strb->surface->width == width); 226 assert(strb->surface->height == height); 227 } 228 229 return strb->surface != NULL; 230} 231 232 233/** 234 * gl_renderbuffer::Delete() 235 */ 236static void 237st_renderbuffer_delete(struct gl_context *ctx, struct gl_renderbuffer *rb) 238{ 239 struct st_renderbuffer *strb = st_renderbuffer(rb); 240 if (ctx) { 241 struct st_context *st = st_context(ctx); 242 pipe_surface_release(st->pipe, &strb->surface); 243 } 244 pipe_resource_reference(&strb->texture, NULL); 245 free(strb->data); 246 _mesa_delete_renderbuffer(ctx, rb); 247} 248 249 250/** 251 * Called via ctx->Driver.NewRenderbuffer() 252 */ 253static struct gl_renderbuffer * 254st_new_renderbuffer(struct gl_context *ctx, GLuint name) 255{ 256 struct st_renderbuffer *strb = ST_CALLOC_STRUCT(st_renderbuffer); 257 if (strb) { 258 assert(name != 0); 259 _mesa_init_renderbuffer(&strb->Base, name); 260 strb->Base.Delete = st_renderbuffer_delete; 261 strb->Base.AllocStorage = st_renderbuffer_alloc_storage; 262 return &strb->Base; 263 } 264 return NULL; 265} 266 267 268/** 269 * Allocate a renderbuffer for an on-screen window (not a user-created 270 * renderbuffer). The window system code determines the format. 271 */ 272struct gl_renderbuffer * 273st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw) 274{ 275 struct st_renderbuffer *strb; 276 277 strb = ST_CALLOC_STRUCT(st_renderbuffer); 278 if (!strb) { 279 _mesa_error(NULL, GL_OUT_OF_MEMORY, "creating renderbuffer"); 280 return NULL; 281 } 282 283 _mesa_init_renderbuffer(&strb->Base, 0); 284 strb->Base.ClassID = 0x4242; /* just a unique value */ 285 strb->Base.NumSamples = samples; 286 strb->Base.Format = st_pipe_format_to_mesa_format(format); 287 strb->Base._BaseFormat = _mesa_get_format_base_format(strb->Base.Format); 288 strb->software = sw; 289 290 switch (format) { 291 case PIPE_FORMAT_R8G8B8A8_UNORM: 292 case PIPE_FORMAT_B8G8R8A8_UNORM: 293 case PIPE_FORMAT_A8R8G8B8_UNORM: 294 strb->Base.InternalFormat = GL_RGBA8; 295 break; 296 case PIPE_FORMAT_R8G8B8X8_UNORM: 297 case PIPE_FORMAT_B8G8R8X8_UNORM: 298 case PIPE_FORMAT_X8R8G8B8_UNORM: 299 strb->Base.InternalFormat = GL_RGB8; 300 break; 301 case PIPE_FORMAT_R8G8B8A8_SRGB: 302 case PIPE_FORMAT_B8G8R8A8_SRGB: 303 case PIPE_FORMAT_A8R8G8B8_SRGB: 304 strb->Base.InternalFormat = GL_SRGB8_ALPHA8; 305 break; 306 case PIPE_FORMAT_R8G8B8X8_SRGB: 307 case PIPE_FORMAT_B8G8R8X8_SRGB: 308 case PIPE_FORMAT_X8R8G8B8_SRGB: 309 strb->Base.InternalFormat = GL_SRGB8; 310 break; 311 case PIPE_FORMAT_B5G5R5A1_UNORM: 312 strb->Base.InternalFormat = GL_RGB5_A1; 313 break; 314 case PIPE_FORMAT_B4G4R4A4_UNORM: 315 strb->Base.InternalFormat = GL_RGBA4; 316 break; 317 case PIPE_FORMAT_B5G6R5_UNORM: 318 strb->Base.InternalFormat = GL_RGB565; 319 break; 320 case PIPE_FORMAT_Z16_UNORM: 321 strb->Base.InternalFormat = GL_DEPTH_COMPONENT16; 322 break; 323 case PIPE_FORMAT_Z32_UNORM: 324 strb->Base.InternalFormat = GL_DEPTH_COMPONENT32; 325 break; 326 case PIPE_FORMAT_Z24_UNORM_S8_UINT: 327 case PIPE_FORMAT_S8_UINT_Z24_UNORM: 328 strb->Base.InternalFormat = GL_DEPTH24_STENCIL8_EXT; 329 break; 330 case PIPE_FORMAT_Z24X8_UNORM: 331 case PIPE_FORMAT_X8Z24_UNORM: 332 strb->Base.InternalFormat = GL_DEPTH_COMPONENT24; 333 break; 334 case PIPE_FORMAT_S8_UINT: 335 strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT; 336 break; 337 case PIPE_FORMAT_R16G16B16A16_SNORM: 338 /* accum buffer */ 339 strb->Base.InternalFormat = GL_RGBA16_SNORM; 340 break; 341 case PIPE_FORMAT_R16G16B16A16_UNORM: 342 strb->Base.InternalFormat = GL_RGBA16; 343 break; 344 case PIPE_FORMAT_R8_UNORM: 345 strb->Base.InternalFormat = GL_R8; 346 break; 347 case PIPE_FORMAT_R8G8_UNORM: 348 strb->Base.InternalFormat = GL_RG8; 349 break; 350 case PIPE_FORMAT_R16_UNORM: 351 strb->Base.InternalFormat = GL_R16; 352 break; 353 case PIPE_FORMAT_R16G16_UNORM: 354 strb->Base.InternalFormat = GL_RG16; 355 break; 356 case PIPE_FORMAT_R32G32B32A32_FLOAT: 357 strb->Base.InternalFormat = GL_RGBA32F; 358 break; 359 case PIPE_FORMAT_R16G16B16A16_FLOAT: 360 strb->Base.InternalFormat = GL_RGBA16F; 361 break; 362 default: 363 _mesa_problem(NULL, 364 "Unexpected format %s in st_new_renderbuffer_fb", 365 util_format_name(format)); 366 free(strb); 367 return NULL; 368 } 369 370 /* st-specific methods */ 371 strb->Base.Delete = st_renderbuffer_delete; 372 strb->Base.AllocStorage = st_renderbuffer_alloc_storage; 373 374 /* surface is allocated in st_renderbuffer_alloc_storage() */ 375 strb->surface = NULL; 376 377 return &strb->Base; 378} 379 380 381/** 382 * Create or update the pipe_surface of a FBO renderbuffer. 383 * This is usually called after st_finalize_texture. 384 */ 385void 386st_update_renderbuffer_surface(struct st_context *st, 387 struct st_renderbuffer *strb) 388{ 389 struct pipe_context *pipe = st->pipe; 390 struct pipe_resource *resource = strb->texture; 391 struct st_texture_object *stTexObj = NULL; 392 unsigned rtt_width = strb->Base.Width; 393 unsigned rtt_height = strb->Base.Height; 394 unsigned rtt_depth = strb->Base.Depth; 395 /* 396 * For winsys fbo, it is possible that the renderbuffer is sRGB-capable but 397 * the format of strb->texture is linear (because we have no control over 398 * the format). Check strb->Base.Format instead of strb->texture->format 399 * to determine if the rb is sRGB-capable. 400 */ 401 boolean enable_srgb = (st->ctx->Color.sRGBEnabled && 402 _mesa_get_format_color_encoding(strb->Base.Format) == GL_SRGB); 403 enum pipe_format format = resource->format; 404 405 if (strb->is_rtt) { 406 stTexObj = st_texture_object(strb->Base.TexImage->TexObject); 407 if (stTexObj->surface_based) 408 format = stTexObj->surface_format; 409 } 410 411 format = (enable_srgb) ? 412 util_format_srgb(format) : 413 util_format_linear(format); 414 415 unsigned first_layer, last_layer, level; 416 417 if (resource->target == PIPE_TEXTURE_1D_ARRAY) { 418 rtt_depth = rtt_height; 419 rtt_height = 1; 420 } 421 422 /* find matching mipmap level size */ 423 for (level = 0; level <= resource->last_level; level++) { 424 if (u_minify(resource->width0, level) == rtt_width && 425 u_minify(resource->height0, level) == rtt_height && 426 (resource->target != PIPE_TEXTURE_3D || 427 u_minify(resource->depth0, level) == rtt_depth)) { 428 break; 429 } 430 } 431 assert(level <= resource->last_level); 432 433 /* determine the layer bounds */ 434 if (strb->rtt_layered) { 435 first_layer = 0; 436 last_layer = util_max_layer(strb->texture, level); 437 } 438 else { 439 first_layer = 440 last_layer = strb->rtt_face + strb->rtt_slice; 441 } 442 443 /* Adjust for texture views */ 444 if (strb->is_rtt && resource->array_size > 1 && 445 stTexObj->base.Immutable) { 446 struct gl_texture_object *tex = &stTexObj->base; 447 first_layer += tex->MinLayer; 448 if (!strb->rtt_layered) 449 last_layer += tex->MinLayer; 450 else 451 last_layer = MIN2(first_layer + tex->NumLayers - 1, last_layer); 452 } 453 454 if (!strb->surface || 455 strb->surface->texture->nr_samples != strb->Base.NumSamples || 456 strb->surface->format != format || 457 strb->surface->texture != resource || 458 strb->surface->width != rtt_width || 459 strb->surface->height != rtt_height || 460 strb->surface->u.tex.level != level || 461 strb->surface->u.tex.first_layer != first_layer || 462 strb->surface->u.tex.last_layer != last_layer) { 463 /* create a new pipe_surface */ 464 struct pipe_surface surf_tmpl; 465 memset(&surf_tmpl, 0, sizeof(surf_tmpl)); 466 surf_tmpl.format = format; 467 surf_tmpl.u.tex.level = level; 468 surf_tmpl.u.tex.first_layer = first_layer; 469 surf_tmpl.u.tex.last_layer = last_layer; 470 471 pipe_surface_release(pipe, &strb->surface); 472 473 strb->surface = pipe->create_surface(pipe, resource, &surf_tmpl); 474 } 475} 476 477/** 478 * Called by ctx->Driver.RenderTexture 479 */ 480static void 481st_render_texture(struct gl_context *ctx, 482 struct gl_framebuffer *fb, 483 struct gl_renderbuffer_attachment *att) 484{ 485 struct st_context *st = st_context(ctx); 486 struct pipe_context *pipe = st->pipe; 487 struct gl_renderbuffer *rb = att->Renderbuffer; 488 struct st_renderbuffer *strb = st_renderbuffer(rb); 489 struct pipe_resource *pt; 490 491 if (!st_finalize_texture(ctx, pipe, att->Texture, att->CubeMapFace)) 492 return; 493 494 pt = st_get_texobj_resource(att->Texture); 495 assert(pt); 496 497 /* point renderbuffer at texobject */ 498 strb->is_rtt = TRUE; 499 strb->rtt_face = att->CubeMapFace; 500 strb->rtt_slice = att->Zoffset; 501 strb->rtt_layered = att->Layered; 502 pipe_resource_reference(&strb->texture, pt); 503 504 st_update_renderbuffer_surface(st, strb); 505 506 /* Invalidate buffer state so that the pipe's framebuffer state 507 * gets updated. 508 * That's where the new renderbuffer (which we just created) gets 509 * passed to the pipe as a (color/depth) render target. 510 */ 511 st_invalidate_state(ctx, _NEW_BUFFERS); 512 513 514 /* Need to trigger a call to update_framebuffer() since we just 515 * attached a new renderbuffer. 516 */ 517 ctx->NewState |= _NEW_BUFFERS; 518} 519 520 521/** 522 * Called via ctx->Driver.FinishRenderTexture. 523 */ 524static void 525st_finish_render_texture(struct gl_context *ctx, struct gl_renderbuffer *rb) 526{ 527 struct st_renderbuffer *strb = st_renderbuffer(rb); 528 529 if (!strb) 530 return; 531 532 strb->is_rtt = FALSE; 533 534 /* restore previous framebuffer state */ 535 st_invalidate_state(ctx, _NEW_BUFFERS); 536} 537 538 539/** Debug helper */ 540static void 541st_fbo_invalid(const char *reason) 542{ 543 if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) { 544 _mesa_debug(NULL, "Invalid FBO: %s\n", reason); 545 } 546} 547 548 549/** 550 * Validate a renderbuffer attachment for a particular set of bindings. 551 */ 552static GLboolean 553st_validate_attachment(struct gl_context *ctx, 554 struct pipe_screen *screen, 555 const struct gl_renderbuffer_attachment *att, 556 unsigned bindings) 557{ 558 const struct st_texture_object *stObj = st_texture_object(att->Texture); 559 enum pipe_format format; 560 mesa_format texFormat; 561 GLboolean valid; 562 563 /* Sanity check: we must be binding the surface as a (color) render target 564 * or depth/stencil target. 565 */ 566 assert(bindings == PIPE_BIND_RENDER_TARGET || 567 bindings == PIPE_BIND_DEPTH_STENCIL); 568 569 /* Only validate texture attachments for now, since 570 * st_renderbuffer_alloc_storage makes sure that 571 * the format is supported. 572 */ 573 if (att->Type != GL_TEXTURE) 574 return GL_TRUE; 575 576 if (!stObj || !stObj->pt) 577 return GL_FALSE; 578 579 format = stObj->pt->format; 580 texFormat = att->Renderbuffer->TexImage->TexFormat; 581 582 /* If the encoding is sRGB and sRGB rendering cannot be enabled, 583 * check for linear format support instead. 584 * Later when we create a surface, we change the format to a linear one. */ 585 if (!ctx->Extensions.EXT_framebuffer_sRGB && 586 _mesa_get_format_color_encoding(texFormat) == GL_SRGB) { 587 const mesa_format linearFormat = _mesa_get_srgb_format_linear(texFormat); 588 format = st_mesa_format_to_pipe_format(st_context(ctx), linearFormat); 589 } 590 591 valid = screen->is_format_supported(screen, format, 592 PIPE_TEXTURE_2D, 593 stObj->pt->nr_samples, bindings); 594 if (!valid) { 595 st_fbo_invalid("Invalid format"); 596 } 597 598 return valid; 599} 600 601 602/** 603 * Check that the framebuffer configuration is valid in terms of what 604 * the driver can support. 605 * 606 * For Gallium we only supports combined Z+stencil, not separate buffers. 607 */ 608static void 609st_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) 610{ 611 struct st_context *st = st_context(ctx); 612 struct pipe_screen *screen = st->pipe->screen; 613 const struct gl_renderbuffer_attachment *depth = 614 &fb->Attachment[BUFFER_DEPTH]; 615 const struct gl_renderbuffer_attachment *stencil = 616 &fb->Attachment[BUFFER_STENCIL]; 617 GLuint i; 618 enum pipe_format first_format = PIPE_FORMAT_NONE; 619 boolean mixed_formats = 620 screen->get_param(screen, PIPE_CAP_MIXED_COLORBUFFER_FORMATS) != 0; 621 622 if (depth->Type && stencil->Type && depth->Type != stencil->Type) { 623 st_fbo_invalid("Different Depth/Stencil buffer formats"); 624 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; 625 return; 626 } 627 if (depth->Type == GL_RENDERBUFFER_EXT && 628 stencil->Type == GL_RENDERBUFFER_EXT && 629 depth->Renderbuffer != stencil->Renderbuffer) { 630 st_fbo_invalid("Separate Depth/Stencil buffers"); 631 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; 632 return; 633 } 634 if (depth->Type == GL_TEXTURE && 635 stencil->Type == GL_TEXTURE && 636 depth->Texture != stencil->Texture) { 637 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; 638 st_fbo_invalid("Different Depth/Stencil textures"); 639 return; 640 } 641 642 if (!st_validate_attachment(ctx, 643 screen, 644 depth, 645 PIPE_BIND_DEPTH_STENCIL)) { 646 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; 647 st_fbo_invalid("Invalid depth attachment"); 648 return; 649 } 650 if (!st_validate_attachment(ctx, 651 screen, 652 stencil, 653 PIPE_BIND_DEPTH_STENCIL)) { 654 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; 655 st_fbo_invalid("Invalid stencil attachment"); 656 return; 657 } 658 for (i = 0; i < ctx->Const.MaxColorAttachments; i++) { 659 struct gl_renderbuffer_attachment *att = 660 &fb->Attachment[BUFFER_COLOR0 + i]; 661 enum pipe_format format; 662 663 if (!st_validate_attachment(ctx, 664 screen, 665 att, 666 PIPE_BIND_RENDER_TARGET)) { 667 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; 668 st_fbo_invalid("Invalid color attachment"); 669 return; 670 } 671 672 if (!mixed_formats) { 673 /* Disallow mixed formats. */ 674 if (att->Type != GL_NONE) { 675 format = st_renderbuffer(att->Renderbuffer)->surface->format; 676 } else { 677 continue; 678 } 679 680 if (first_format == PIPE_FORMAT_NONE) { 681 first_format = format; 682 } else if (format != first_format) { 683 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; 684 st_fbo_invalid("Mixed color formats"); 685 return; 686 } 687 } 688 } 689} 690 691 692/** 693 * Called via glDrawBuffer. 694 */ 695static void 696st_DrawBuffers(struct gl_context *ctx, GLsizei count, const GLenum *buffers) 697{ 698 struct st_context *st = st_context(ctx); 699 struct gl_framebuffer *fb = ctx->DrawBuffer; 700 GLuint i; 701 702 (void) count; 703 (void) buffers; 704 705 /* add the renderbuffers on demand */ 706 for (i = 0; i < fb->_NumColorDrawBuffers; i++) { 707 GLint idx = fb->_ColorDrawBufferIndexes[i]; 708 709 if (idx >= 0) { 710 st_manager_add_color_renderbuffer(st, fb, idx); 711 } 712 } 713} 714 715 716/** 717 * Called via glReadBuffer. 718 */ 719static void 720st_ReadBuffer(struct gl_context *ctx, GLenum buffer) 721{ 722 struct st_context *st = st_context(ctx); 723 struct gl_framebuffer *fb = ctx->ReadBuffer; 724 725 (void) buffer; 726 727 /* Check if we need to allocate a front color buffer. 728 * Front buffers are often allocated on demand (other color buffers are 729 * always allocated in advance). 730 */ 731 if ((fb->_ColorReadBufferIndex == BUFFER_FRONT_LEFT || 732 fb->_ColorReadBufferIndex == BUFFER_FRONT_RIGHT) && 733 fb->Attachment[fb->_ColorReadBufferIndex].Type == GL_NONE) { 734 /* add the buffer */ 735 st_manager_add_color_renderbuffer(st, fb, fb->_ColorReadBufferIndex); 736 _mesa_update_state(ctx); 737 st_validate_state(st, ST_PIPELINE_RENDER); 738 } 739} 740 741 742 743/** 744 * Called via ctx->Driver.MapRenderbuffer. 745 */ 746static void 747st_MapRenderbuffer(struct gl_context *ctx, 748 struct gl_renderbuffer *rb, 749 GLuint x, GLuint y, GLuint w, GLuint h, 750 GLbitfield mode, 751 GLubyte **mapOut, GLint *rowStrideOut) 752{ 753 struct st_context *st = st_context(ctx); 754 struct st_renderbuffer *strb = st_renderbuffer(rb); 755 struct pipe_context *pipe = st->pipe; 756 const GLboolean invert = rb->Name == 0; 757 unsigned usage; 758 GLuint y2; 759 GLubyte *map; 760 761 if (strb->software) { 762 /* software-allocated renderbuffer (probably an accum buffer) */ 763 if (strb->data) { 764 GLint bpp = _mesa_get_format_bytes(strb->Base.Format); 765 GLint stride = _mesa_format_row_stride(strb->Base.Format, 766 strb->Base.Width); 767 *mapOut = (GLubyte *) strb->data + y * stride + x * bpp; 768 *rowStrideOut = stride; 769 } 770 else { 771 *mapOut = NULL; 772 *rowStrideOut = 0; 773 } 774 return; 775 } 776 777 usage = 0x0; 778 if (mode & GL_MAP_READ_BIT) 779 usage |= PIPE_TRANSFER_READ; 780 if (mode & GL_MAP_WRITE_BIT) 781 usage |= PIPE_TRANSFER_WRITE; 782 if (mode & GL_MAP_INVALIDATE_RANGE_BIT) 783 usage |= PIPE_TRANSFER_DISCARD_RANGE; 784 785 /* Note: y=0=bottom of buffer while y2=0=top of buffer. 786 * 'invert' will be true for window-system buffers and false for 787 * user-allocated renderbuffers and textures. 788 */ 789 if (invert) 790 y2 = strb->Base.Height - y - h; 791 else 792 y2 = y; 793 794 map = pipe_transfer_map(pipe, 795 strb->texture, 796 strb->surface->u.tex.level, 797 strb->surface->u.tex.first_layer, 798 usage, x, y2, w, h, &strb->transfer); 799 if (map) { 800 if (invert) { 801 *rowStrideOut = -(int) strb->transfer->stride; 802 map += (h - 1) * strb->transfer->stride; 803 } 804 else { 805 *rowStrideOut = strb->transfer->stride; 806 } 807 *mapOut = map; 808 } 809 else { 810 *mapOut = NULL; 811 *rowStrideOut = 0; 812 } 813} 814 815 816/** 817 * Called via ctx->Driver.UnmapRenderbuffer. 818 */ 819static void 820st_UnmapRenderbuffer(struct gl_context *ctx, 821 struct gl_renderbuffer *rb) 822{ 823 struct st_context *st = st_context(ctx); 824 struct st_renderbuffer *strb = st_renderbuffer(rb); 825 struct pipe_context *pipe = st->pipe; 826 827 if (strb->software) { 828 /* software-allocated renderbuffer (probably an accum buffer) */ 829 return; 830 } 831 832 pipe_transfer_unmap(pipe, strb->transfer); 833 strb->transfer = NULL; 834} 835 836 837 838void st_init_fbo_functions(struct dd_function_table *functions) 839{ 840 functions->NewFramebuffer = _mesa_new_framebuffer; 841 functions->NewRenderbuffer = st_new_renderbuffer; 842 functions->FramebufferRenderbuffer = _mesa_FramebufferRenderbuffer_sw; 843 functions->RenderTexture = st_render_texture; 844 functions->FinishRenderTexture = st_finish_render_texture; 845 functions->ValidateFramebuffer = st_validate_framebuffer; 846 847 functions->DrawBuffers = st_DrawBuffers; 848 functions->ReadBuffer = st_ReadBuffer; 849 850 functions->MapRenderbuffer = st_MapRenderbuffer; 851 functions->UnmapRenderbuffer = st_UnmapRenderbuffer; 852} 853 854 855