1/* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 2010 LunarG Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: 25 * Chia-I Wu <olv@lunarg.com> 26 */ 27 28#include "main/mtypes.h" 29#include "main/extensions.h" 30#include "main/context.h" 31#include "main/debug_output.h" 32#include "main/framebuffer.h" 33#include "main/glthread.h" 34#include "main/texobj.h" 35#include "main/teximage.h" 36#include "main/texstate.h" 37#include "main/errors.h" 38#include "main/framebuffer.h" 39#include "main/fbobject.h" 40#include "main/renderbuffer.h" 41#include "main/version.h" 42#include "util/hash_table.h" 43#include "st_texture.h" 44 45#include "st_context.h" 46#include "st_debug.h" 47#include "st_extensions.h" 48#include "st_format.h" 49#include "st_cb_bitmap.h" 50#include "st_cb_flush.h" 51#include "st_manager.h" 52#include "st_sampler_view.h" 53#include "st_util.h" 54 55#include "state_tracker/st_gl_api.h" 56 57#include "pipe/p_context.h" 58#include "pipe/p_screen.h" 59#include "util/format/u_format.h" 60#include "util/u_helpers.h" 61#include "util/u_pointer.h" 62#include "util/u_inlines.h" 63#include "util/u_atomic.h" 64#include "util/u_surface.h" 65#include "util/list.h" 66#include "util/u_memory.h" 67 68struct hash_table; 69struct st_manager_private 70{ 71 struct hash_table *stfbi_ht; /* framebuffer iface objects hash table */ 72 simple_mtx_t st_mutex; 73}; 74 75/** 76 * Cast wrapper to convert a struct gl_framebuffer to an gl_framebuffer. 77 * Return NULL if the struct gl_framebuffer is a user-created framebuffer. 78 * We'll only return non-null for window system framebuffers. 79 * Note that this function may fail. 80 */ 81static inline struct gl_framebuffer * 82st_ws_framebuffer(struct gl_framebuffer *fb) 83{ 84 /* FBO cannot be casted. See st_new_framebuffer */ 85 if (fb && _mesa_is_winsys_fbo(fb) && 86 fb != _mesa_get_incomplete_framebuffer()) 87 return fb; 88 return NULL; 89} 90 91/** 92 * Map an attachment to a buffer index. 93 */ 94static inline gl_buffer_index 95attachment_to_buffer_index(enum st_attachment_type statt) 96{ 97 gl_buffer_index index; 98 99 switch (statt) { 100 case ST_ATTACHMENT_FRONT_LEFT: 101 index = BUFFER_FRONT_LEFT; 102 break; 103 case ST_ATTACHMENT_BACK_LEFT: 104 index = BUFFER_BACK_LEFT; 105 break; 106 case ST_ATTACHMENT_FRONT_RIGHT: 107 index = BUFFER_FRONT_RIGHT; 108 break; 109 case ST_ATTACHMENT_BACK_RIGHT: 110 index = BUFFER_BACK_RIGHT; 111 break; 112 case ST_ATTACHMENT_DEPTH_STENCIL: 113 index = BUFFER_DEPTH; 114 break; 115 case ST_ATTACHMENT_ACCUM: 116 index = BUFFER_ACCUM; 117 break; 118 default: 119 index = BUFFER_COUNT; 120 break; 121 } 122 123 return index; 124} 125 126 127/** 128 * Map a buffer index to an attachment. 129 */ 130static inline enum st_attachment_type 131buffer_index_to_attachment(gl_buffer_index index) 132{ 133 enum st_attachment_type statt; 134 135 switch (index) { 136 case BUFFER_FRONT_LEFT: 137 statt = ST_ATTACHMENT_FRONT_LEFT; 138 break; 139 case BUFFER_BACK_LEFT: 140 statt = ST_ATTACHMENT_BACK_LEFT; 141 break; 142 case BUFFER_FRONT_RIGHT: 143 statt = ST_ATTACHMENT_FRONT_RIGHT; 144 break; 145 case BUFFER_BACK_RIGHT: 146 statt = ST_ATTACHMENT_BACK_RIGHT; 147 break; 148 case BUFFER_DEPTH: 149 statt = ST_ATTACHMENT_DEPTH_STENCIL; 150 break; 151 case BUFFER_ACCUM: 152 statt = ST_ATTACHMENT_ACCUM; 153 break; 154 default: 155 statt = ST_ATTACHMENT_INVALID; 156 break; 157 } 158 159 return statt; 160} 161 162 163/** 164 * Make sure a context picks up the latest cached state of the 165 * drawables it binds to. 166 */ 167static void 168st_context_validate(struct st_context *st, 169 struct gl_framebuffer *stdraw, 170 struct gl_framebuffer *stread) 171{ 172 if (stdraw && stdraw->stamp != st->draw_stamp) { 173 st->dirty |= ST_NEW_FRAMEBUFFER; 174 _mesa_resize_framebuffer(st->ctx, stdraw, 175 stdraw->Width, 176 stdraw->Height); 177 st->draw_stamp = stdraw->stamp; 178 } 179 180 if (stread && stread->stamp != st->read_stamp) { 181 if (stread != stdraw) { 182 st->dirty |= ST_NEW_FRAMEBUFFER; 183 _mesa_resize_framebuffer(st->ctx, stread, 184 stread->Width, 185 stread->Height); 186 } 187 st->read_stamp = stread->stamp; 188 } 189} 190 191 192void 193st_set_ws_renderbuffer_surface(struct gl_renderbuffer *rb, 194 struct pipe_surface *surf) 195{ 196 pipe_surface_reference(&rb->surface_srgb, NULL); 197 pipe_surface_reference(&rb->surface_linear, NULL); 198 199 if (util_format_is_srgb(surf->format)) 200 pipe_surface_reference(&rb->surface_srgb, surf); 201 else 202 pipe_surface_reference(&rb->surface_linear, surf); 203 204 rb->surface = surf; /* just assign, don't ref */ 205 pipe_resource_reference(&rb->texture, surf->texture); 206 207 rb->Width = surf->width; 208 rb->Height = surf->height; 209} 210 211 212/** 213 * Validate a framebuffer to make sure up-to-date pipe_textures are used. 214 * The context is only used for creating pipe surfaces and for calling 215 * _mesa_resize_framebuffer(). 216 * (That should probably be rethought, since those surfaces become 217 * drawable state, not context state, and can be freed by another pipe 218 * context). 219 */ 220static void 221st_framebuffer_validate(struct gl_framebuffer *stfb, 222 struct st_context *st) 223{ 224 struct pipe_resource *textures[ST_ATTACHMENT_COUNT]; 225 uint width, height; 226 unsigned i; 227 bool changed = false; 228 int32_t new_stamp; 229 230 new_stamp = p_atomic_read(&stfb->iface->stamp); 231 if (stfb->iface_stamp == new_stamp) 232 return; 233 234 memset(textures, 0, stfb->num_statts * sizeof(textures[0])); 235 236 /* validate the fb */ 237 do { 238 if (!stfb->iface->validate(&st->iface, stfb->iface, stfb->statts, 239 stfb->num_statts, textures)) 240 return; 241 242 stfb->iface_stamp = new_stamp; 243 new_stamp = p_atomic_read(&stfb->iface->stamp); 244 } while(stfb->iface_stamp != new_stamp); 245 246 width = stfb->Width; 247 height = stfb->Height; 248 249 for (i = 0; i < stfb->num_statts; i++) { 250 struct gl_renderbuffer *rb; 251 struct pipe_surface *ps, surf_tmpl; 252 gl_buffer_index idx; 253 254 if (!textures[i]) 255 continue; 256 257 idx = attachment_to_buffer_index(stfb->statts[i]); 258 if (idx >= BUFFER_COUNT) { 259 pipe_resource_reference(&textures[i], NULL); 260 continue; 261 } 262 263 rb = stfb->Attachment[idx].Renderbuffer; 264 assert(rb); 265 if (rb->texture == textures[i] && 266 rb->Width == textures[i]->width0 && 267 rb->Height == textures[i]->height0) { 268 pipe_resource_reference(&textures[i], NULL); 269 continue; 270 } 271 272 u_surface_default_template(&surf_tmpl, textures[i]); 273 ps = st->pipe->create_surface(st->pipe, textures[i], &surf_tmpl); 274 if (ps) { 275 st_set_ws_renderbuffer_surface(rb, ps); 276 pipe_surface_reference(&ps, NULL); 277 278 changed = true; 279 280 width = rb->Width; 281 height = rb->Height; 282 } 283 284 pipe_resource_reference(&textures[i], NULL); 285 } 286 287 if (changed) { 288 ++stfb->stamp; 289 _mesa_resize_framebuffer(st->ctx, stfb, width, height); 290 } 291} 292 293 294/** 295 * Update the attachments to validate by looping the existing renderbuffers. 296 */ 297static void 298st_framebuffer_update_attachments(struct gl_framebuffer *stfb) 299{ 300 gl_buffer_index idx; 301 302 stfb->num_statts = 0; 303 304 for (enum st_attachment_type i = 0; i < ST_ATTACHMENT_COUNT; i++) 305 stfb->statts[i] = ST_ATTACHMENT_INVALID; 306 307 for (idx = 0; idx < BUFFER_COUNT; idx++) { 308 struct gl_renderbuffer *rb; 309 enum st_attachment_type statt; 310 311 rb = stfb->Attachment[idx].Renderbuffer; 312 if (!rb || rb->software) 313 continue; 314 315 statt = buffer_index_to_attachment(idx); 316 if (statt != ST_ATTACHMENT_INVALID && 317 st_visual_have_buffers(stfb->iface->visual, 1 << statt)) 318 stfb->statts[stfb->num_statts++] = statt; 319 } 320 stfb->stamp++; 321} 322 323/** 324 * Allocate a renderbuffer for an on-screen window (not a user-created 325 * renderbuffer). The window system code determines the format. 326 */ 327static struct gl_renderbuffer * 328st_new_renderbuffer_fb(enum pipe_format format, unsigned samples, boolean sw) 329{ 330 struct gl_renderbuffer *rb; 331 332 rb = CALLOC_STRUCT(gl_renderbuffer); 333 if (!rb) { 334 _mesa_error(NULL, GL_OUT_OF_MEMORY, "creating renderbuffer"); 335 return NULL; 336 } 337 338 _mesa_init_renderbuffer(rb, 0); 339 rb->ClassID = 0x4242; /* just a unique value */ 340 rb->NumSamples = samples; 341 rb->NumStorageSamples = samples; 342 rb->Format = st_pipe_format_to_mesa_format(format); 343 rb->_BaseFormat = _mesa_get_format_base_format(rb->Format); 344 rb->software = sw; 345 346 switch (format) { 347 case PIPE_FORMAT_B10G10R10A2_UNORM: 348 case PIPE_FORMAT_R10G10B10A2_UNORM: 349 rb->InternalFormat = GL_RGB10_A2; 350 break; 351 case PIPE_FORMAT_R10G10B10X2_UNORM: 352 case PIPE_FORMAT_B10G10R10X2_UNORM: 353 rb->InternalFormat = GL_RGB10; 354 break; 355 case PIPE_FORMAT_R8G8B8A8_UNORM: 356 case PIPE_FORMAT_B8G8R8A8_UNORM: 357 case PIPE_FORMAT_A8R8G8B8_UNORM: 358 rb->InternalFormat = GL_RGBA8; 359 break; 360 case PIPE_FORMAT_R8G8B8X8_UNORM: 361 case PIPE_FORMAT_B8G8R8X8_UNORM: 362 case PIPE_FORMAT_X8R8G8B8_UNORM: 363 case PIPE_FORMAT_R8G8B8_UNORM: 364 rb->InternalFormat = GL_RGB8; 365 break; 366 case PIPE_FORMAT_R8G8B8A8_SRGB: 367 case PIPE_FORMAT_B8G8R8A8_SRGB: 368 case PIPE_FORMAT_A8R8G8B8_SRGB: 369 rb->InternalFormat = GL_SRGB8_ALPHA8; 370 break; 371 case PIPE_FORMAT_R8G8B8X8_SRGB: 372 case PIPE_FORMAT_B8G8R8X8_SRGB: 373 case PIPE_FORMAT_X8R8G8B8_SRGB: 374 rb->InternalFormat = GL_SRGB8; 375 break; 376 case PIPE_FORMAT_B5G5R5A1_UNORM: 377 rb->InternalFormat = GL_RGB5_A1; 378 break; 379 case PIPE_FORMAT_B4G4R4A4_UNORM: 380 rb->InternalFormat = GL_RGBA4; 381 break; 382 case PIPE_FORMAT_B5G6R5_UNORM: 383 rb->InternalFormat = GL_RGB565; 384 break; 385 case PIPE_FORMAT_Z16_UNORM: 386 rb->InternalFormat = GL_DEPTH_COMPONENT16; 387 break; 388 case PIPE_FORMAT_Z32_UNORM: 389 rb->InternalFormat = GL_DEPTH_COMPONENT32; 390 break; 391 case PIPE_FORMAT_Z24_UNORM_S8_UINT: 392 case PIPE_FORMAT_S8_UINT_Z24_UNORM: 393 rb->InternalFormat = GL_DEPTH24_STENCIL8_EXT; 394 break; 395 case PIPE_FORMAT_Z24X8_UNORM: 396 case PIPE_FORMAT_X8Z24_UNORM: 397 rb->InternalFormat = GL_DEPTH_COMPONENT24; 398 break; 399 case PIPE_FORMAT_S8_UINT: 400 rb->InternalFormat = GL_STENCIL_INDEX8_EXT; 401 break; 402 case PIPE_FORMAT_R16G16B16A16_SNORM: 403 /* accum buffer */ 404 rb->InternalFormat = GL_RGBA16_SNORM; 405 break; 406 case PIPE_FORMAT_R16G16B16A16_UNORM: 407 rb->InternalFormat = GL_RGBA16; 408 break; 409 case PIPE_FORMAT_R16G16B16_UNORM: 410 rb->InternalFormat = GL_RGB16; 411 break; 412 case PIPE_FORMAT_R8_UNORM: 413 rb->InternalFormat = GL_R8; 414 break; 415 case PIPE_FORMAT_R8G8_UNORM: 416 rb->InternalFormat = GL_RG8; 417 break; 418 case PIPE_FORMAT_R16_UNORM: 419 rb->InternalFormat = GL_R16; 420 break; 421 case PIPE_FORMAT_R16G16_UNORM: 422 rb->InternalFormat = GL_RG16; 423 break; 424 case PIPE_FORMAT_R32G32B32A32_FLOAT: 425 rb->InternalFormat = GL_RGBA32F; 426 break; 427 case PIPE_FORMAT_R32G32B32X32_FLOAT: 428 case PIPE_FORMAT_R32G32B32_FLOAT: 429 rb->InternalFormat = GL_RGB32F; 430 break; 431 case PIPE_FORMAT_R16G16B16A16_FLOAT: 432 rb->InternalFormat = GL_RGBA16F; 433 break; 434 case PIPE_FORMAT_R16G16B16X16_FLOAT: 435 rb->InternalFormat = GL_RGB16F; 436 break; 437 default: 438 _mesa_problem(NULL, 439 "Unexpected format %s in st_new_renderbuffer_fb", 440 util_format_name(format)); 441 FREE(rb); 442 return NULL; 443 } 444 445 rb->surface = NULL; 446 447 return rb; 448} 449 450/** 451 * Add a renderbuffer to the framebuffer. The framebuffer is one that 452 * corresponds to a window and is not a user-created FBO. 453 */ 454static bool 455st_framebuffer_add_renderbuffer(struct gl_framebuffer *stfb, 456 gl_buffer_index idx, bool prefer_srgb) 457{ 458 struct gl_renderbuffer *rb; 459 enum pipe_format format; 460 bool sw; 461 462 assert(_mesa_is_winsys_fbo(stfb)); 463 464 /* do not distinguish depth/stencil buffers */ 465 if (idx == BUFFER_STENCIL) 466 idx = BUFFER_DEPTH; 467 468 switch (idx) { 469 case BUFFER_DEPTH: 470 format = stfb->iface->visual->depth_stencil_format; 471 sw = false; 472 break; 473 case BUFFER_ACCUM: 474 format = stfb->iface->visual->accum_format; 475 sw = true; 476 break; 477 default: 478 format = stfb->iface->visual->color_format; 479 if (prefer_srgb) 480 format = util_format_srgb(format); 481 sw = false; 482 break; 483 } 484 485 if (format == PIPE_FORMAT_NONE) 486 return false; 487 488 rb = st_new_renderbuffer_fb(format, stfb->iface->visual->samples, sw); 489 if (!rb) 490 return false; 491 492 if (idx != BUFFER_DEPTH) { 493 _mesa_attach_and_own_rb(stfb, idx, rb); 494 return true; 495 } 496 497 bool rb_ownership_taken = false; 498 if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 0)) { 499 _mesa_attach_and_own_rb(stfb, BUFFER_DEPTH, rb); 500 rb_ownership_taken = true; 501 } 502 503 if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 1)) { 504 if (rb_ownership_taken) 505 _mesa_attach_and_reference_rb(stfb, BUFFER_STENCIL, rb); 506 else 507 _mesa_attach_and_own_rb(stfb, BUFFER_STENCIL, rb); 508 } 509 510 return true; 511} 512 513 514/** 515 * Intialize a struct gl_config from a visual. 516 */ 517static void 518st_visual_to_context_mode(const struct st_visual *visual, 519 struct gl_config *mode) 520{ 521 memset(mode, 0, sizeof(*mode)); 522 523 if (st_visual_have_buffers(visual, ST_ATTACHMENT_BACK_LEFT_MASK)) 524 mode->doubleBufferMode = GL_TRUE; 525 526 if (st_visual_have_buffers(visual, 527 ST_ATTACHMENT_FRONT_RIGHT_MASK | ST_ATTACHMENT_BACK_RIGHT_MASK)) 528 mode->stereoMode = GL_TRUE; 529 530 if (visual->color_format != PIPE_FORMAT_NONE) { 531 mode->redBits = 532 util_format_get_component_bits(visual->color_format, 533 UTIL_FORMAT_COLORSPACE_RGB, 0); 534 mode->greenBits = 535 util_format_get_component_bits(visual->color_format, 536 UTIL_FORMAT_COLORSPACE_RGB, 1); 537 mode->blueBits = 538 util_format_get_component_bits(visual->color_format, 539 UTIL_FORMAT_COLORSPACE_RGB, 2); 540 mode->alphaBits = 541 util_format_get_component_bits(visual->color_format, 542 UTIL_FORMAT_COLORSPACE_RGB, 3); 543 544 mode->rgbBits = mode->redBits + 545 mode->greenBits + mode->blueBits + mode->alphaBits; 546 mode->sRGBCapable = util_format_is_srgb(visual->color_format); 547 } 548 549 if (visual->depth_stencil_format != PIPE_FORMAT_NONE) { 550 mode->depthBits = 551 util_format_get_component_bits(visual->depth_stencil_format, 552 UTIL_FORMAT_COLORSPACE_ZS, 0); 553 mode->stencilBits = 554 util_format_get_component_bits(visual->depth_stencil_format, 555 UTIL_FORMAT_COLORSPACE_ZS, 1); 556 } 557 558 if (visual->accum_format != PIPE_FORMAT_NONE) { 559 mode->accumRedBits = 560 util_format_get_component_bits(visual->accum_format, 561 UTIL_FORMAT_COLORSPACE_RGB, 0); 562 mode->accumGreenBits = 563 util_format_get_component_bits(visual->accum_format, 564 UTIL_FORMAT_COLORSPACE_RGB, 1); 565 mode->accumBlueBits = 566 util_format_get_component_bits(visual->accum_format, 567 UTIL_FORMAT_COLORSPACE_RGB, 2); 568 mode->accumAlphaBits = 569 util_format_get_component_bits(visual->accum_format, 570 UTIL_FORMAT_COLORSPACE_RGB, 3); 571 } 572 573 if (visual->samples > 1) { 574 mode->samples = visual->samples; 575 } 576} 577 578 579/** 580 * Create a framebuffer from a manager interface. 581 */ 582static struct gl_framebuffer * 583st_framebuffer_create(struct st_context *st, 584 struct st_framebuffer_iface *stfbi) 585{ 586 struct gl_framebuffer *stfb; 587 struct gl_config mode; 588 gl_buffer_index idx; 589 bool prefer_srgb = false; 590 591 if (!stfbi) 592 return NULL; 593 594 stfb = CALLOC_STRUCT(gl_framebuffer); 595 if (!stfb) 596 return NULL; 597 598 st_visual_to_context_mode(stfbi->visual, &mode); 599 600 /* 601 * For desktop GL, sRGB framebuffer write is controlled by both the 602 * capability of the framebuffer and GL_FRAMEBUFFER_SRGB. We should 603 * advertise the capability when the pipe driver (and core Mesa) supports 604 * it so that applications can enable sRGB write when they want to. 605 * 606 * This is not to be confused with GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB. When 607 * the attribute is GLX_TRUE, it tells the st manager to pick a color 608 * format such that util_format_srgb(visual->color_format) can be supported 609 * by the pipe driver. We still need to advertise the capability here. 610 * 611 * For GLES, however, sRGB framebuffer write is initially only controlled 612 * by the capability of the framebuffer, with GL_EXT_sRGB_write_control 613 * control is given back to the applications, but GL_FRAMEBUFFER_SRGB is 614 * still enabled by default since this is the behaviour when 615 * EXT_sRGB_write_control is not available. Since GL_EXT_sRGB_write_control 616 * brings GLES on par with desktop GLs EXT_framebuffer_sRGB, in mesa this 617 * is also expressed by using the same extension flag 618 */ 619 if (_mesa_has_EXT_framebuffer_sRGB(st->ctx)) { 620 struct pipe_screen *screen = st->screen; 621 const enum pipe_format srgb_format = 622 util_format_srgb(stfbi->visual->color_format); 623 624 if (srgb_format != PIPE_FORMAT_NONE && 625 st_pipe_format_to_mesa_format(srgb_format) != MESA_FORMAT_NONE && 626 screen->is_format_supported(screen, srgb_format, 627 PIPE_TEXTURE_2D, stfbi->visual->samples, 628 stfbi->visual->samples, 629 (PIPE_BIND_DISPLAY_TARGET | 630 PIPE_BIND_RENDER_TARGET))) { 631 mode.sRGBCapable = GL_TRUE; 632 /* Since GL_FRAMEBUFFER_SRGB is enabled by default on GLES we must not 633 * create renderbuffers with an sRGB format derived from the 634 * visual->color_format, but we still want sRGB for desktop GL. 635 */ 636 prefer_srgb = _mesa_is_desktop_gl(st->ctx); 637 } 638 } 639 640 _mesa_initialize_window_framebuffer(stfb, &mode); 641 642 stfb->iface = stfbi; 643 stfb->iface_ID = stfbi->ID; 644 stfb->iface_stamp = p_atomic_read(&stfbi->stamp) - 1; 645 646 /* add the color buffer */ 647 idx = stfb->_ColorDrawBufferIndexes[0]; 648 if (!st_framebuffer_add_renderbuffer(stfb, idx, prefer_srgb)) { 649 FREE(stfb); 650 return NULL; 651 } 652 653 st_framebuffer_add_renderbuffer(stfb, BUFFER_DEPTH, false); 654 st_framebuffer_add_renderbuffer(stfb, BUFFER_ACCUM, false); 655 656 stfb->stamp = 0; 657 st_framebuffer_update_attachments(stfb); 658 659 return stfb; 660} 661 662 663static uint32_t 664st_framebuffer_iface_hash(const void *key) 665{ 666 return (uintptr_t)key; 667} 668 669 670static bool 671st_framebuffer_iface_equal(const void *a, const void *b) 672{ 673 return (struct st_framebuffer_iface *)a == (struct st_framebuffer_iface *)b; 674} 675 676 677static bool 678st_framebuffer_iface_lookup(struct st_manager *smapi, 679 const struct st_framebuffer_iface *stfbi) 680{ 681 struct st_manager_private *smPriv = 682 (struct st_manager_private *)smapi->st_manager_private; 683 struct hash_entry *entry; 684 685 assert(smPriv); 686 assert(smPriv->stfbi_ht); 687 688 simple_mtx_lock(&smPriv->st_mutex); 689 entry = _mesa_hash_table_search(smPriv->stfbi_ht, stfbi); 690 simple_mtx_unlock(&smPriv->st_mutex); 691 692 return entry != NULL; 693} 694 695 696static bool 697st_framebuffer_iface_insert(struct st_manager *smapi, 698 struct st_framebuffer_iface *stfbi) 699{ 700 struct st_manager_private *smPriv = 701 (struct st_manager_private *)smapi->st_manager_private; 702 struct hash_entry *entry; 703 704 assert(smPriv); 705 assert(smPriv->stfbi_ht); 706 707 simple_mtx_lock(&smPriv->st_mutex); 708 entry = _mesa_hash_table_insert(smPriv->stfbi_ht, stfbi, stfbi); 709 simple_mtx_unlock(&smPriv->st_mutex); 710 711 return entry != NULL; 712} 713 714 715static void 716st_framebuffer_iface_remove(struct st_manager *smapi, 717 struct st_framebuffer_iface *stfbi) 718{ 719 struct st_manager_private *smPriv = 720 (struct st_manager_private *)smapi->st_manager_private; 721 struct hash_entry *entry; 722 723 if (!smPriv || !smPriv->stfbi_ht) 724 return; 725 726 simple_mtx_lock(&smPriv->st_mutex); 727 entry = _mesa_hash_table_search(smPriv->stfbi_ht, stfbi); 728 if (!entry) 729 goto unlock; 730 731 _mesa_hash_table_remove(smPriv->stfbi_ht, entry); 732 733unlock: 734 simple_mtx_unlock(&smPriv->st_mutex); 735} 736 737 738/** 739 * The framebuffer interface object is no longer valid. 740 * Remove the object from the framebuffer interface hash table. 741 */ 742static void 743st_api_destroy_drawable(struct st_api *stapi, 744 struct st_framebuffer_iface *stfbi) 745{ 746 if (!stfbi) 747 return; 748 749 st_framebuffer_iface_remove(stfbi->state_manager, stfbi); 750} 751 752 753/** 754 * Purge the winsys buffers list to remove any references to 755 * non-existing framebuffer interface objects. 756 */ 757static void 758st_framebuffers_purge(struct st_context *st) 759{ 760 struct st_context_iface *st_iface = &st->iface; 761 struct st_manager *smapi = st_iface->state_manager; 762 struct gl_framebuffer *stfb, *next; 763 764 assert(smapi); 765 766 LIST_FOR_EACH_ENTRY_SAFE_REV(stfb, next, &st->winsys_buffers, head) { 767 struct st_framebuffer_iface *stfbi = stfb->iface; 768 769 assert(stfbi); 770 771 /** 772 * If the corresponding framebuffer interface object no longer exists, 773 * remove the framebuffer object from the context's winsys buffers list, 774 * and unreference the framebuffer object, so its resources can be 775 * deleted. 776 */ 777 if (!st_framebuffer_iface_lookup(smapi, stfbi)) { 778 list_del(&stfb->head); 779 _mesa_reference_framebuffer(&stfb, NULL); 780 } 781 } 782} 783 784 785static void 786st_context_flush(struct st_context_iface *stctxi, unsigned flags, 787 struct pipe_fence_handle **fence, 788 void (*before_flush_cb) (void*), 789 void* args) 790{ 791 struct st_context *st = (struct st_context *) stctxi; 792 unsigned pipe_flags = 0; 793 794 if (flags & ST_FLUSH_END_OF_FRAME) 795 pipe_flags |= PIPE_FLUSH_END_OF_FRAME; 796 if (flags & ST_FLUSH_FENCE_FD) 797 pipe_flags |= PIPE_FLUSH_FENCE_FD; 798 799 /* We can do these in any order because FLUSH_VERTICES will also flush 800 * the bitmap cache if there are any unflushed vertices. 801 */ 802 st_flush_bitmap_cache(st); 803 FLUSH_VERTICES(st->ctx, 0, 0); 804 805 /* Notify the caller that we're ready to flush */ 806 if (before_flush_cb) 807 before_flush_cb(args); 808 st_flush(st, fence, pipe_flags); 809 810 if ((flags & ST_FLUSH_WAIT) && fence && *fence) { 811 st->screen->fence_finish(st->screen, NULL, *fence, 812 PIPE_TIMEOUT_INFINITE); 813 st->screen->fence_reference(st->screen, fence, NULL); 814 } 815 816 if (flags & ST_FLUSH_FRONT) 817 st_manager_flush_frontbuffer(st); 818 819 /* DRI3 changes the framebuffer after SwapBuffers, but we need to invoke 820 * st_manager_validate_framebuffers to notice that. 821 * 822 * Set gfx_shaders_may_be_dirty to invoke st_validate_state in the next 823 * draw call, which will invoke st_manager_validate_framebuffers, but it 824 * won't dirty states if there is no change. 825 */ 826 if (flags & ST_FLUSH_END_OF_FRAME) 827 st->gfx_shaders_may_be_dirty = true; 828} 829 830static bool 831st_context_teximage(struct st_context_iface *stctxi, 832 enum st_texture_type tex_type, 833 int level, enum pipe_format pipe_format, 834 struct pipe_resource *tex, bool mipmap) 835{ 836 struct st_context *st = (struct st_context *) stctxi; 837 struct gl_context *ctx = st->ctx; 838 struct gl_texture_object *texObj; 839 struct gl_texture_image *texImage; 840 GLenum internalFormat; 841 GLuint width, height, depth; 842 GLenum target; 843 844 switch (tex_type) { 845 case ST_TEXTURE_1D: 846 target = GL_TEXTURE_1D; 847 break; 848 case ST_TEXTURE_2D: 849 target = GL_TEXTURE_2D; 850 break; 851 case ST_TEXTURE_3D: 852 target = GL_TEXTURE_3D; 853 break; 854 case ST_TEXTURE_RECT: 855 target = GL_TEXTURE_RECTANGLE_ARB; 856 break; 857 default: 858 return FALSE; 859 } 860 861 texObj = _mesa_get_current_tex_object(ctx, target); 862 863 _mesa_lock_texture(ctx, texObj); 864 865 /* switch to surface based */ 866 if (!texObj->surface_based) { 867 _mesa_clear_texture_object(ctx, texObj, NULL); 868 texObj->surface_based = GL_TRUE; 869 } 870 871 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 872 if (tex) { 873 mesa_format texFormat = st_pipe_format_to_mesa_format(pipe_format); 874 875 if (util_format_has_alpha(tex->format)) 876 internalFormat = GL_RGBA; 877 else 878 internalFormat = GL_RGB; 879 880 _mesa_init_teximage_fields(ctx, texImage, 881 tex->width0, tex->height0, 1, 0, 882 internalFormat, texFormat); 883 884 width = tex->width0; 885 height = tex->height0; 886 depth = tex->depth0; 887 888 /* grow the image size until we hit level = 0 */ 889 while (level > 0) { 890 if (width != 1) 891 width <<= 1; 892 if (height != 1) 893 height <<= 1; 894 if (depth != 1) 895 depth <<= 1; 896 level--; 897 } 898 } 899 else { 900 _mesa_clear_texture_image(ctx, texImage); 901 width = height = depth = 0; 902 } 903 904 pipe_resource_reference(&texObj->pt, tex); 905 st_texture_release_all_sampler_views(st, texObj); 906 pipe_resource_reference(&texImage->pt, tex); 907 texObj->surface_format = pipe_format; 908 909 texObj->needs_validation = true; 910 911 _mesa_dirty_texobj(ctx, texObj); 912 _mesa_unlock_texture(ctx, texObj); 913 914 return true; 915} 916 917 918static void 919st_context_copy(struct st_context_iface *stctxi, 920 struct st_context_iface *stsrci, unsigned mask) 921{ 922 struct st_context *st = (struct st_context *) stctxi; 923 struct st_context *src = (struct st_context *) stsrci; 924 925 _mesa_copy_context(src->ctx, st->ctx, mask); 926} 927 928 929static bool 930st_context_share(struct st_context_iface *stctxi, 931 struct st_context_iface *stsrci) 932{ 933 struct st_context *st = (struct st_context *) stctxi; 934 struct st_context *src = (struct st_context *) stsrci; 935 936 return _mesa_share_state(st->ctx, src->ctx); 937} 938 939 940static void 941st_context_destroy(struct st_context_iface *stctxi) 942{ 943 struct st_context *st = (struct st_context *) stctxi; 944 st_destroy_context(st); 945} 946 947 948static void 949st_start_thread(struct st_context_iface *stctxi) 950{ 951 struct st_context *st = (struct st_context *) stctxi; 952 953 _mesa_glthread_init(st->ctx); 954} 955 956 957static void 958st_thread_finish(struct st_context_iface *stctxi) 959{ 960 struct st_context *st = (struct st_context *) stctxi; 961 962 _mesa_glthread_finish(st->ctx); 963} 964 965 966static void 967st_context_invalidate_state(struct st_context_iface *stctxi, 968 unsigned flags) 969{ 970 struct st_context *st = (struct st_context *) stctxi; 971 972 if (flags & ST_INVALIDATE_FS_SAMPLER_VIEWS) 973 st->dirty |= ST_NEW_FS_SAMPLER_VIEWS; 974 if (flags & ST_INVALIDATE_FS_CONSTBUF0) 975 st->dirty |= ST_NEW_FS_CONSTANTS; 976 if (flags & ST_INVALIDATE_VS_CONSTBUF0) 977 st->dirty |= ST_NEW_VS_CONSTANTS; 978 if (flags & ST_INVALIDATE_VERTEX_BUFFERS) { 979 st->ctx->Array.NewVertexElements = true; 980 st->dirty |= ST_NEW_VERTEX_ARRAYS; 981 } 982} 983 984 985static void 986st_manager_destroy(struct st_manager *smapi) 987{ 988 struct st_manager_private *smPriv = smapi->st_manager_private; 989 990 if (smPriv && smPriv->stfbi_ht) { 991 _mesa_hash_table_destroy(smPriv->stfbi_ht, NULL); 992 simple_mtx_destroy(&smPriv->st_mutex); 993 FREE(smPriv); 994 smapi->st_manager_private = NULL; 995 } 996} 997 998 999static struct st_context_iface * 1000st_api_create_context(struct st_api *stapi, struct st_manager *smapi, 1001 const struct st_context_attribs *attribs, 1002 enum st_context_error *error, 1003 struct st_context_iface *shared_stctxi) 1004{ 1005 struct st_context *shared_ctx = (struct st_context *) shared_stctxi; 1006 struct st_context *st; 1007 struct pipe_context *pipe; 1008 struct gl_config mode, *mode_ptr = &mode; 1009 gl_api api; 1010 bool no_error = false; 1011 unsigned ctx_flags = PIPE_CONTEXT_PREFER_THREADED; 1012 1013 if (!(stapi->profile_mask & (1 << attribs->profile))) 1014 return NULL; 1015 1016 switch (attribs->profile) { 1017 case ST_PROFILE_DEFAULT: 1018 api = API_OPENGL_COMPAT; 1019 break; 1020 case ST_PROFILE_OPENGL_ES1: 1021 api = API_OPENGLES; 1022 break; 1023 case ST_PROFILE_OPENGL_ES2: 1024 api = API_OPENGLES2; 1025 break; 1026 case ST_PROFILE_OPENGL_CORE: 1027 api = API_OPENGL_CORE; 1028 break; 1029 default: 1030 *error = ST_CONTEXT_ERROR_BAD_API; 1031 return NULL; 1032 } 1033 1034 _mesa_initialize(attribs->options.mesa_extension_override); 1035 1036 /* Create a hash table for the framebuffer interface objects 1037 * if it has not been created for this st manager. 1038 */ 1039 if (smapi->st_manager_private == NULL) { 1040 struct st_manager_private *smPriv; 1041 1042 smPriv = CALLOC_STRUCT(st_manager_private); 1043 simple_mtx_init(&smPriv->st_mutex, mtx_plain); 1044 smPriv->stfbi_ht = _mesa_hash_table_create(NULL, 1045 st_framebuffer_iface_hash, 1046 st_framebuffer_iface_equal); 1047 smapi->st_manager_private = smPriv; 1048 smapi->destroy = st_manager_destroy; 1049 } 1050 1051 if (attribs->flags & ST_CONTEXT_FLAG_ROBUST_ACCESS) 1052 ctx_flags |= PIPE_CONTEXT_ROBUST_BUFFER_ACCESS; 1053 1054 if (attribs->flags & ST_CONTEXT_FLAG_NO_ERROR) 1055 no_error = true; 1056 1057 if (attribs->flags & ST_CONTEXT_FLAG_LOW_PRIORITY) 1058 ctx_flags |= PIPE_CONTEXT_LOW_PRIORITY; 1059 else if (attribs->flags & ST_CONTEXT_FLAG_HIGH_PRIORITY) 1060 ctx_flags |= PIPE_CONTEXT_HIGH_PRIORITY; 1061 1062 if (attribs->flags & ST_CONTEXT_FLAG_RESET_NOTIFICATION_ENABLED) 1063 ctx_flags |= PIPE_CONTEXT_LOSE_CONTEXT_ON_RESET; 1064 1065 pipe = smapi->screen->context_create(smapi->screen, NULL, ctx_flags); 1066 if (!pipe) { 1067 *error = ST_CONTEXT_ERROR_NO_MEMORY; 1068 return NULL; 1069 } 1070 1071 st_visual_to_context_mode(&attribs->visual, &mode); 1072 if (attribs->visual.color_format == PIPE_FORMAT_NONE) 1073 mode_ptr = NULL; 1074 st = st_create_context(api, pipe, mode_ptr, shared_ctx, 1075 &attribs->options, no_error, 1076 !!smapi->validate_egl_image); 1077 if (!st) { 1078 *error = ST_CONTEXT_ERROR_NO_MEMORY; 1079 pipe->destroy(pipe); 1080 return NULL; 1081 } 1082 1083 if (attribs->flags & ST_CONTEXT_FLAG_DEBUG) { 1084 if (!_mesa_set_debug_state_int(st->ctx, GL_DEBUG_OUTPUT, GL_TRUE)) { 1085 *error = ST_CONTEXT_ERROR_NO_MEMORY; 1086 return NULL; 1087 } 1088 1089 st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_DEBUG_BIT; 1090 } 1091 1092 if (st->ctx->Const.ContextFlags & GL_CONTEXT_FLAG_DEBUG_BIT) { 1093 _mesa_update_debug_callback(st->ctx); 1094 } 1095 1096 if (attribs->flags & ST_CONTEXT_FLAG_FORWARD_COMPATIBLE) 1097 st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT; 1098 if (attribs->flags & ST_CONTEXT_FLAG_ROBUST_ACCESS) { 1099 st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB; 1100 st->ctx->Const.RobustAccess = GL_TRUE; 1101 } 1102 if (attribs->flags & ST_CONTEXT_FLAG_RESET_NOTIFICATION_ENABLED) { 1103 st->ctx->Const.ResetStrategy = GL_LOSE_CONTEXT_ON_RESET_ARB; 1104 st_install_device_reset_callback(st); 1105 } 1106 1107 if (attribs->flags & ST_CONTEXT_FLAG_RELEASE_NONE) 1108 st->ctx->Const.ContextReleaseBehavior = GL_NONE; 1109 1110 /* need to perform version check */ 1111 if (attribs->major > 1 || attribs->minor > 0) { 1112 /* Is the actual version less than the requested version? 1113 */ 1114 if (st->ctx->Version < attribs->major * 10U + attribs->minor) { 1115 *error = ST_CONTEXT_ERROR_BAD_VERSION; 1116 st_destroy_context(st); 1117 return NULL; 1118 } 1119 } 1120 1121 st->can_scissor_clear = !!st->screen->get_param(st->screen, PIPE_CAP_CLEAR_SCISSORED); 1122 1123 st->ctx->invalidate_on_gl_viewport = 1124 smapi->get_param(smapi, ST_MANAGER_BROKEN_INVALIDATE); 1125 1126 st->iface.destroy = st_context_destroy; 1127 st->iface.flush = st_context_flush; 1128 st->iface.teximage = st_context_teximage; 1129 st->iface.copy = st_context_copy; 1130 st->iface.share = st_context_share; 1131 st->iface.start_thread = st_start_thread; 1132 st->iface.thread_finish = st_thread_finish; 1133 st->iface.invalidate_state = st_context_invalidate_state; 1134 st->iface.st_context_private = (void *) smapi; 1135 st->iface.cso_context = st->cso_context; 1136 st->iface.pipe = st->pipe; 1137 st->iface.state_manager = smapi; 1138 1139 if (st->ctx->IntelBlackholeRender && 1140 st->screen->get_param(st->screen, PIPE_CAP_FRONTEND_NOOP)) 1141 st->pipe->set_frontend_noop(st->pipe, st->ctx->IntelBlackholeRender); 1142 1143 *error = ST_CONTEXT_SUCCESS; 1144 return &st->iface; 1145} 1146 1147 1148static struct st_context_iface * 1149st_api_get_current(struct st_api *stapi) 1150{ 1151 GET_CURRENT_CONTEXT(ctx); 1152 struct st_context *st = ctx ? ctx->st : NULL; 1153 1154 return st ? &st->iface : NULL; 1155} 1156 1157 1158static struct gl_framebuffer * 1159st_framebuffer_reuse_or_create(struct st_context *st, 1160 struct gl_framebuffer *fb, 1161 struct st_framebuffer_iface *stfbi) 1162{ 1163 struct gl_framebuffer *cur = NULL, *stfb = NULL; 1164 1165 if (!stfbi) 1166 return NULL; 1167 1168 /* Check if there is already a framebuffer object for the specified 1169 * framebuffer interface in this context. If there is one, use it. 1170 */ 1171 LIST_FOR_EACH_ENTRY(cur, &st->winsys_buffers, head) { 1172 if (cur->iface_ID == stfbi->ID) { 1173 _mesa_reference_framebuffer(&stfb, cur); 1174 break; 1175 } 1176 } 1177 1178 /* If there is not already a framebuffer object, create one */ 1179 if (stfb == NULL) { 1180 cur = st_framebuffer_create(st, stfbi); 1181 1182 if (cur) { 1183 /* add the referenced framebuffer interface object to 1184 * the framebuffer interface object hash table. 1185 */ 1186 if (!st_framebuffer_iface_insert(stfbi->state_manager, stfbi)) { 1187 _mesa_reference_framebuffer(&cur, NULL); 1188 return NULL; 1189 } 1190 1191 /* add to the context's winsys buffers list */ 1192 list_add(&cur->head, &st->winsys_buffers); 1193 1194 _mesa_reference_framebuffer(&stfb, cur); 1195 } 1196 } 1197 1198 return stfb; 1199} 1200 1201 1202static bool 1203st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi, 1204 struct st_framebuffer_iface *stdrawi, 1205 struct st_framebuffer_iface *streadi) 1206{ 1207 struct st_context *st = (struct st_context *) stctxi; 1208 struct gl_framebuffer *stdraw, *stread; 1209 bool ret; 1210 1211 if (st) { 1212 /* reuse or create the draw fb */ 1213 stdraw = st_framebuffer_reuse_or_create(st, 1214 st->ctx->WinSysDrawBuffer, stdrawi); 1215 if (streadi != stdrawi) { 1216 /* do the same for the read fb */ 1217 stread = st_framebuffer_reuse_or_create(st, 1218 st->ctx->WinSysReadBuffer, streadi); 1219 } 1220 else { 1221 stread = NULL; 1222 /* reuse the draw fb for the read fb */ 1223 if (stdraw) 1224 _mesa_reference_framebuffer(&stread, stdraw); 1225 } 1226 1227 /* If framebuffers were asked for, we'd better have allocated them */ 1228 if ((stdrawi && !stdraw) || (streadi && !stread)) 1229 return false; 1230 1231 if (stdraw && stread) { 1232 st_framebuffer_validate(stdraw, st); 1233 if (stread != stdraw) 1234 st_framebuffer_validate(stread, st); 1235 1236 ret = _mesa_make_current(st->ctx, stdraw, stread); 1237 1238 st->draw_stamp = stdraw->stamp - 1; 1239 st->read_stamp = stread->stamp - 1; 1240 st_context_validate(st, stdraw, stread); 1241 } 1242 else { 1243 struct gl_framebuffer *incomplete = _mesa_get_incomplete_framebuffer(); 1244 ret = _mesa_make_current(st->ctx, incomplete, incomplete); 1245 } 1246 1247 _mesa_reference_framebuffer(&stdraw, NULL); 1248 _mesa_reference_framebuffer(&stread, NULL); 1249 1250 /* Purge the context's winsys_buffers list in case any 1251 * of the referenced drawables no longer exist. 1252 */ 1253 st_framebuffers_purge(st); 1254 } 1255 else { 1256 GET_CURRENT_CONTEXT(ctx); 1257 1258 if (ctx) { 1259 /* Before releasing the context, release its associated 1260 * winsys buffers first. Then purge the context's winsys buffers list 1261 * to free the resources of any winsys buffers that no longer have 1262 * an existing drawable. 1263 */ 1264 ret = _mesa_make_current(ctx, NULL, NULL); 1265 st_framebuffers_purge(ctx->st); 1266 } 1267 1268 ret = _mesa_make_current(NULL, NULL, NULL); 1269 } 1270 1271 return ret; 1272} 1273 1274 1275static void 1276st_api_destroy(struct st_api *stapi) 1277{ 1278} 1279 1280 1281/** 1282 * Flush the front buffer if the current context renders to the front buffer. 1283 */ 1284void 1285st_manager_flush_frontbuffer(struct st_context *st) 1286{ 1287 struct gl_framebuffer *stfb = st_ws_framebuffer(st->ctx->DrawBuffer); 1288 struct gl_renderbuffer *rb = NULL; 1289 1290 if (!stfb) 1291 return; 1292 1293 /* If the context uses a doublebuffered visual, but the buffer is 1294 * single-buffered, guess that it's a pbuffer, which doesn't need 1295 * flushing. 1296 */ 1297 if (st->ctx->Visual.doubleBufferMode && 1298 !stfb->Visual.doubleBufferMode) 1299 return; 1300 1301 /* Check front buffer used at the GL API level. */ 1302 enum st_attachment_type statt = ST_ATTACHMENT_FRONT_LEFT; 1303 rb = stfb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer; 1304 if (!rb) { 1305 /* Check back buffer redirected by EGL_KHR_mutable_render_buffer. */ 1306 statt = ST_ATTACHMENT_BACK_LEFT; 1307 rb = stfb->Attachment[BUFFER_BACK_LEFT].Renderbuffer; 1308 } 1309 1310 /* Do we have a front color buffer and has it been drawn to since last 1311 * frontbuffer flush? 1312 */ 1313 if (rb && rb->defined && 1314 stfb->iface->flush_front(&st->iface, stfb->iface, statt)) { 1315 rb->defined = GL_FALSE; 1316 1317 /* Trigger an update of rb->defined on next draw */ 1318 st->dirty |= ST_NEW_FB_STATE; 1319 } 1320} 1321 1322 1323/** 1324 * Re-validate the framebuffers. 1325 */ 1326void 1327st_manager_validate_framebuffers(struct st_context *st) 1328{ 1329 struct gl_framebuffer *stdraw = st_ws_framebuffer(st->ctx->DrawBuffer); 1330 struct gl_framebuffer *stread = st_ws_framebuffer(st->ctx->ReadBuffer); 1331 1332 if (stdraw) 1333 st_framebuffer_validate(stdraw, st); 1334 if (stread && stread != stdraw) 1335 st_framebuffer_validate(stread, st); 1336 1337 st_context_validate(st, stdraw, stread); 1338} 1339 1340 1341/** 1342 * Flush any outstanding swapbuffers on the current draw framebuffer. 1343 */ 1344void 1345st_manager_flush_swapbuffers(void) 1346{ 1347 GET_CURRENT_CONTEXT(ctx); 1348 struct st_context *st = (ctx) ? ctx->st : NULL; 1349 struct gl_framebuffer *stfb; 1350 1351 if (!st) 1352 return; 1353 1354 stfb = st_ws_framebuffer(ctx->DrawBuffer); 1355 if (!stfb || !stfb->iface->flush_swapbuffers) 1356 return; 1357 1358 stfb->iface->flush_swapbuffers(&st->iface, stfb->iface); 1359} 1360 1361 1362/** 1363 * Add a color renderbuffer on demand. The FBO must correspond to a window, 1364 * not a user-created FBO. 1365 */ 1366bool 1367st_manager_add_color_renderbuffer(struct gl_context *ctx, 1368 struct gl_framebuffer *fb, 1369 gl_buffer_index idx) 1370{ 1371 struct gl_framebuffer *stfb = st_ws_framebuffer(fb); 1372 1373 /* FBO */ 1374 if (!stfb) 1375 return false; 1376 1377 assert(_mesa_is_winsys_fbo(fb)); 1378 1379 if (stfb->Attachment[idx].Renderbuffer) 1380 return true; 1381 1382 switch (idx) { 1383 case BUFFER_FRONT_LEFT: 1384 case BUFFER_BACK_LEFT: 1385 case BUFFER_FRONT_RIGHT: 1386 case BUFFER_BACK_RIGHT: 1387 break; 1388 default: 1389 return false; 1390 } 1391 1392 if (!st_framebuffer_add_renderbuffer(stfb, idx, 1393 stfb->Visual.sRGBCapable)) 1394 return false; 1395 1396 st_framebuffer_update_attachments(stfb); 1397 1398 /* 1399 * Force a call to the frontend manager to validate the 1400 * new renderbuffer. It might be that there is a window system 1401 * renderbuffer available. 1402 */ 1403 if (stfb->iface) 1404 stfb->iface_stamp = p_atomic_read(&stfb->iface->stamp) - 1; 1405 1406 st_invalidate_buffers(st_context(ctx)); 1407 1408 return true; 1409} 1410 1411 1412static unsigned 1413get_version(struct pipe_screen *screen, 1414 struct st_config_options *options, gl_api api) 1415{ 1416 struct gl_constants consts = {0}; 1417 struct gl_extensions extensions = {0}; 1418 GLuint version; 1419 1420 if (_mesa_override_gl_version_contextless(&consts, &api, &version)) { 1421 return version; 1422 } 1423 1424 _mesa_init_constants(&consts, api); 1425 _mesa_init_extensions(&extensions); 1426 1427 st_init_limits(screen, &consts, &extensions); 1428 st_init_extensions(screen, &consts, &extensions, options, api); 1429 version = _mesa_get_version(&extensions, &consts, api); 1430 free(consts.SpirVExtensions); 1431 return version; 1432} 1433 1434 1435static void 1436st_api_query_versions(struct st_api *stapi, struct st_manager *sm, 1437 struct st_config_options *options, 1438 int *gl_core_version, 1439 int *gl_compat_version, 1440 int *gl_es1_version, 1441 int *gl_es2_version) 1442{ 1443 *gl_core_version = get_version(sm->screen, options, API_OPENGL_CORE); 1444 *gl_compat_version = get_version(sm->screen, options, API_OPENGL_COMPAT); 1445 *gl_es1_version = get_version(sm->screen, options, API_OPENGLES); 1446 *gl_es2_version = get_version(sm->screen, options, API_OPENGLES2); 1447} 1448 1449 1450static const struct st_api st_gl_api = { 1451 .name = "Mesa " PACKAGE_VERSION, 1452 .api = ST_API_OPENGL, 1453 .profile_mask = ST_PROFILE_DEFAULT_MASK | 1454 ST_PROFILE_OPENGL_CORE_MASK | 1455 ST_PROFILE_OPENGL_ES1_MASK | 1456 ST_PROFILE_OPENGL_ES2_MASK | 1457 0, 1458 .feature_mask = ST_API_FEATURE_MS_VISUALS_MASK, 1459 .destroy = st_api_destroy, 1460 .query_versions = st_api_query_versions, 1461 .create_context = st_api_create_context, 1462 .make_current = st_api_make_current, 1463 .get_current = st_api_get_current, 1464 .destroy_drawable = st_api_destroy_drawable, 1465}; 1466 1467 1468struct st_api * 1469st_gl_api_create(void) 1470{ 1471 return (struct st_api *) &st_gl_api; 1472} 1473 1474void 1475st_manager_invalidate_drawables(struct gl_context *ctx) 1476{ 1477 struct gl_framebuffer *stdraw; 1478 struct gl_framebuffer *stread; 1479 1480 /* 1481 * Normally we'd want the frontend manager to mark the drawables 1482 * invalid only when needed. This will force the frontend manager 1483 * to revalidate the drawable, rather than just update the context with 1484 * the latest cached drawable info. 1485 */ 1486 1487 stdraw = st_ws_framebuffer(ctx->DrawBuffer); 1488 stread = st_ws_framebuffer(ctx->ReadBuffer); 1489 1490 if (stdraw) 1491 stdraw->iface_stamp = p_atomic_read(&stdraw->iface->stamp) - 1; 1492 if (stread && stread != stdraw) 1493 stread->iface_stamp = p_atomic_read(&stread->iface->stamp) - 1; 1494} 1495