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