1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 2010 LunarG Inc. 5848b8605Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the "Software"), 8848b8605Smrg * to deal in the Software without restriction, including without limitation 9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 11848b8605Smrg * Software is furnished to do so, subject to the following conditions: 12848b8605Smrg * 13848b8605Smrg * The above copyright notice and this permission notice shall be included 14848b8605Smrg * in all copies or substantial portions of the Software. 15848b8605Smrg * 16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17848b8605Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20848b8605Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21848b8605Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22848b8605Smrg * DEALINGS IN THE SOFTWARE. 23848b8605Smrg * 24848b8605Smrg * Authors: 25848b8605Smrg * Chia-I Wu <olv@lunarg.com> 26848b8605Smrg */ 27848b8605Smrg 28848b8605Smrg#include "main/mtypes.h" 29848b8605Smrg#include "main/extensions.h" 30848b8605Smrg#include "main/context.h" 31b8e80941Smrg#include "main/debug_output.h" 32b8e80941Smrg#include "main/glthread.h" 33848b8605Smrg#include "main/texobj.h" 34848b8605Smrg#include "main/teximage.h" 35848b8605Smrg#include "main/texstate.h" 36848b8605Smrg#include "main/errors.h" 37848b8605Smrg#include "main/framebuffer.h" 38848b8605Smrg#include "main/fbobject.h" 39848b8605Smrg#include "main/renderbuffer.h" 40848b8605Smrg#include "main/version.h" 41b8e80941Smrg#include "util/hash_table.h" 42848b8605Smrg#include "st_texture.h" 43848b8605Smrg 44848b8605Smrg#include "st_context.h" 45b8e80941Smrg#include "st_debug.h" 46848b8605Smrg#include "st_extensions.h" 47848b8605Smrg#include "st_format.h" 48b8e80941Smrg#include "st_cb_bitmap.h" 49848b8605Smrg#include "st_cb_fbo.h" 50848b8605Smrg#include "st_cb_flush.h" 51848b8605Smrg#include "st_manager.h" 52b8e80941Smrg#include "st_sampler_view.h" 53848b8605Smrg 54848b8605Smrg#include "state_tracker/st_gl_api.h" 55848b8605Smrg 56848b8605Smrg#include "pipe/p_context.h" 57848b8605Smrg#include "pipe/p_screen.h" 58848b8605Smrg#include "util/u_format.h" 59b8e80941Smrg#include "util/u_helpers.h" 60848b8605Smrg#include "util/u_pointer.h" 61848b8605Smrg#include "util/u_inlines.h" 62848b8605Smrg#include "util/u_atomic.h" 63848b8605Smrg#include "util/u_surface.h" 64b8e80941Smrg#include "util/list.h" 65848b8605Smrg 66b8e80941Smrgstruct hash_table; 67b8e80941Smrgstruct st_manager_private 68848b8605Smrg{ 69b8e80941Smrg struct hash_table *stfbi_ht; /* framebuffer iface objects hash table */ 70b8e80941Smrg mtx_t st_mutex; 71b8e80941Smrg}; 72b8e80941Smrg 73848b8605Smrg 74848b8605Smrg/** 75848b8605Smrg * Map an attachment to a buffer index. 76848b8605Smrg */ 77b8e80941Smrgstatic inline gl_buffer_index 78848b8605Smrgattachment_to_buffer_index(enum st_attachment_type statt) 79848b8605Smrg{ 80848b8605Smrg gl_buffer_index index; 81848b8605Smrg 82848b8605Smrg switch (statt) { 83848b8605Smrg case ST_ATTACHMENT_FRONT_LEFT: 84848b8605Smrg index = BUFFER_FRONT_LEFT; 85848b8605Smrg break; 86848b8605Smrg case ST_ATTACHMENT_BACK_LEFT: 87848b8605Smrg index = BUFFER_BACK_LEFT; 88848b8605Smrg break; 89848b8605Smrg case ST_ATTACHMENT_FRONT_RIGHT: 90848b8605Smrg index = BUFFER_FRONT_RIGHT; 91848b8605Smrg break; 92848b8605Smrg case ST_ATTACHMENT_BACK_RIGHT: 93848b8605Smrg index = BUFFER_BACK_RIGHT; 94848b8605Smrg break; 95848b8605Smrg case ST_ATTACHMENT_DEPTH_STENCIL: 96848b8605Smrg index = BUFFER_DEPTH; 97848b8605Smrg break; 98848b8605Smrg case ST_ATTACHMENT_ACCUM: 99848b8605Smrg index = BUFFER_ACCUM; 100848b8605Smrg break; 101848b8605Smrg case ST_ATTACHMENT_SAMPLE: 102848b8605Smrg default: 103848b8605Smrg index = BUFFER_COUNT; 104848b8605Smrg break; 105848b8605Smrg } 106848b8605Smrg 107848b8605Smrg return index; 108848b8605Smrg} 109848b8605Smrg 110b8e80941Smrg 111848b8605Smrg/** 112848b8605Smrg * Map a buffer index to an attachment. 113848b8605Smrg */ 114b8e80941Smrgstatic inline enum st_attachment_type 115848b8605Smrgbuffer_index_to_attachment(gl_buffer_index index) 116848b8605Smrg{ 117848b8605Smrg enum st_attachment_type statt; 118848b8605Smrg 119848b8605Smrg switch (index) { 120848b8605Smrg case BUFFER_FRONT_LEFT: 121848b8605Smrg statt = ST_ATTACHMENT_FRONT_LEFT; 122848b8605Smrg break; 123848b8605Smrg case BUFFER_BACK_LEFT: 124848b8605Smrg statt = ST_ATTACHMENT_BACK_LEFT; 125848b8605Smrg break; 126848b8605Smrg case BUFFER_FRONT_RIGHT: 127848b8605Smrg statt = ST_ATTACHMENT_FRONT_RIGHT; 128848b8605Smrg break; 129848b8605Smrg case BUFFER_BACK_RIGHT: 130848b8605Smrg statt = ST_ATTACHMENT_BACK_RIGHT; 131848b8605Smrg break; 132848b8605Smrg case BUFFER_DEPTH: 133848b8605Smrg statt = ST_ATTACHMENT_DEPTH_STENCIL; 134848b8605Smrg break; 135848b8605Smrg case BUFFER_ACCUM: 136848b8605Smrg statt = ST_ATTACHMENT_ACCUM; 137848b8605Smrg break; 138848b8605Smrg default: 139848b8605Smrg statt = ST_ATTACHMENT_INVALID; 140848b8605Smrg break; 141848b8605Smrg } 142848b8605Smrg 143848b8605Smrg return statt; 144848b8605Smrg} 145848b8605Smrg 146b8e80941Smrg 147848b8605Smrg/** 148848b8605Smrg * Make sure a context picks up the latest cached state of the 149848b8605Smrg * drawables it binds to. 150848b8605Smrg */ 151848b8605Smrgstatic void 152848b8605Smrgst_context_validate(struct st_context *st, 153848b8605Smrg struct st_framebuffer *stdraw, 154848b8605Smrg struct st_framebuffer *stread) 155848b8605Smrg{ 156848b8605Smrg if (stdraw && stdraw->stamp != st->draw_stamp) { 157b8e80941Smrg st->dirty |= ST_NEW_FRAMEBUFFER; 158848b8605Smrg _mesa_resize_framebuffer(st->ctx, &stdraw->Base, 159848b8605Smrg stdraw->Base.Width, 160848b8605Smrg stdraw->Base.Height); 161848b8605Smrg st->draw_stamp = stdraw->stamp; 162848b8605Smrg } 163848b8605Smrg 164848b8605Smrg if (stread && stread->stamp != st->read_stamp) { 165848b8605Smrg if (stread != stdraw) { 166b8e80941Smrg st->dirty |= ST_NEW_FRAMEBUFFER; 167848b8605Smrg _mesa_resize_framebuffer(st->ctx, &stread->Base, 168848b8605Smrg stread->Base.Width, 169848b8605Smrg stread->Base.Height); 170848b8605Smrg } 171848b8605Smrg st->read_stamp = stread->stamp; 172848b8605Smrg } 173848b8605Smrg} 174848b8605Smrg 175b8e80941Smrg 176b8e80941Smrgvoid 177b8e80941Smrgst_set_ws_renderbuffer_surface(struct st_renderbuffer *strb, 178b8e80941Smrg struct pipe_surface *surf) 179b8e80941Smrg{ 180b8e80941Smrg pipe_surface_reference(&strb->surface_srgb, NULL); 181b8e80941Smrg pipe_surface_reference(&strb->surface_linear, NULL); 182b8e80941Smrg 183b8e80941Smrg if (util_format_is_srgb(surf->format)) 184b8e80941Smrg pipe_surface_reference(&strb->surface_srgb, surf); 185b8e80941Smrg else 186b8e80941Smrg pipe_surface_reference(&strb->surface_linear, surf); 187b8e80941Smrg 188b8e80941Smrg strb->surface = surf; /* just assign, don't ref */ 189b8e80941Smrg pipe_resource_reference(&strb->texture, surf->texture); 190b8e80941Smrg 191b8e80941Smrg strb->Base.Width = surf->width; 192b8e80941Smrg strb->Base.Height = surf->height; 193b8e80941Smrg} 194b8e80941Smrg 195b8e80941Smrg 196848b8605Smrg/** 197848b8605Smrg * Validate a framebuffer to make sure up-to-date pipe_textures are used. 198848b8605Smrg * The context is only used for creating pipe surfaces and for calling 199848b8605Smrg * _mesa_resize_framebuffer(). 200848b8605Smrg * (That should probably be rethought, since those surfaces become 201848b8605Smrg * drawable state, not context state, and can be freed by another pipe 202848b8605Smrg * context). 203848b8605Smrg */ 204848b8605Smrgstatic void 205848b8605Smrgst_framebuffer_validate(struct st_framebuffer *stfb, 206848b8605Smrg struct st_context *st) 207848b8605Smrg{ 208848b8605Smrg struct pipe_resource *textures[ST_ATTACHMENT_COUNT]; 209848b8605Smrg uint width, height; 210848b8605Smrg unsigned i; 211848b8605Smrg boolean changed = FALSE; 212848b8605Smrg int32_t new_stamp; 213848b8605Smrg 214848b8605Smrg new_stamp = p_atomic_read(&stfb->iface->stamp); 215848b8605Smrg if (stfb->iface_stamp == new_stamp) 216848b8605Smrg return; 217848b8605Smrg 218b8e80941Smrg memset(textures, 0, stfb->num_statts * sizeof(textures[0])); 219b8e80941Smrg 220848b8605Smrg /* validate the fb */ 221848b8605Smrg do { 222848b8605Smrg if (!stfb->iface->validate(&st->iface, stfb->iface, stfb->statts, 223b8e80941Smrg stfb->num_statts, textures)) 224b8e80941Smrg return; 225848b8605Smrg 226848b8605Smrg stfb->iface_stamp = new_stamp; 227848b8605Smrg new_stamp = p_atomic_read(&stfb->iface->stamp); 228848b8605Smrg } while(stfb->iface_stamp != new_stamp); 229848b8605Smrg 230848b8605Smrg width = stfb->Base.Width; 231848b8605Smrg height = stfb->Base.Height; 232848b8605Smrg 233848b8605Smrg for (i = 0; i < stfb->num_statts; i++) { 234848b8605Smrg struct st_renderbuffer *strb; 235848b8605Smrg struct pipe_surface *ps, surf_tmpl; 236848b8605Smrg gl_buffer_index idx; 237848b8605Smrg 238848b8605Smrg if (!textures[i]) 239848b8605Smrg continue; 240848b8605Smrg 241848b8605Smrg idx = attachment_to_buffer_index(stfb->statts[i]); 242848b8605Smrg if (idx >= BUFFER_COUNT) { 243848b8605Smrg pipe_resource_reference(&textures[i], NULL); 244848b8605Smrg continue; 245848b8605Smrg } 246848b8605Smrg 247848b8605Smrg strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer); 248848b8605Smrg assert(strb); 249848b8605Smrg if (strb->texture == textures[i]) { 250848b8605Smrg pipe_resource_reference(&textures[i], NULL); 251848b8605Smrg continue; 252848b8605Smrg } 253848b8605Smrg 254848b8605Smrg u_surface_default_template(&surf_tmpl, textures[i]); 255848b8605Smrg ps = st->pipe->create_surface(st->pipe, textures[i], &surf_tmpl); 256848b8605Smrg if (ps) { 257b8e80941Smrg st_set_ws_renderbuffer_surface(strb, ps); 258848b8605Smrg pipe_surface_reference(&ps, NULL); 259848b8605Smrg 260848b8605Smrg changed = TRUE; 261848b8605Smrg 262848b8605Smrg width = strb->Base.Width; 263848b8605Smrg height = strb->Base.Height; 264848b8605Smrg } 265848b8605Smrg 266848b8605Smrg pipe_resource_reference(&textures[i], NULL); 267848b8605Smrg } 268848b8605Smrg 269848b8605Smrg if (changed) { 270848b8605Smrg ++stfb->stamp; 271848b8605Smrg _mesa_resize_framebuffer(st->ctx, &stfb->Base, width, height); 272848b8605Smrg } 273848b8605Smrg} 274848b8605Smrg 275b8e80941Smrg 276848b8605Smrg/** 277848b8605Smrg * Update the attachments to validate by looping the existing renderbuffers. 278848b8605Smrg */ 279848b8605Smrgstatic void 280848b8605Smrgst_framebuffer_update_attachments(struct st_framebuffer *stfb) 281848b8605Smrg{ 282848b8605Smrg gl_buffer_index idx; 283848b8605Smrg 284848b8605Smrg stfb->num_statts = 0; 285848b8605Smrg for (idx = 0; idx < BUFFER_COUNT; idx++) { 286848b8605Smrg struct st_renderbuffer *strb; 287848b8605Smrg enum st_attachment_type statt; 288848b8605Smrg 289848b8605Smrg strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer); 290848b8605Smrg if (!strb || strb->software) 291848b8605Smrg continue; 292848b8605Smrg 293848b8605Smrg statt = buffer_index_to_attachment(idx); 294848b8605Smrg if (statt != ST_ATTACHMENT_INVALID && 295848b8605Smrg st_visual_have_buffers(stfb->iface->visual, 1 << statt)) 296848b8605Smrg stfb->statts[stfb->num_statts++] = statt; 297848b8605Smrg } 298848b8605Smrg stfb->stamp++; 299848b8605Smrg} 300848b8605Smrg 301b8e80941Smrg 302848b8605Smrg/** 303b8e80941Smrg * Add a renderbuffer to the framebuffer. The framebuffer is one that 304b8e80941Smrg * corresponds to a window and is not a user-created FBO. 305848b8605Smrg */ 306848b8605Smrgstatic boolean 307848b8605Smrgst_framebuffer_add_renderbuffer(struct st_framebuffer *stfb, 308b8e80941Smrg gl_buffer_index idx, bool prefer_srgb) 309848b8605Smrg{ 310848b8605Smrg struct gl_renderbuffer *rb; 311848b8605Smrg enum pipe_format format; 312848b8605Smrg boolean sw; 313848b8605Smrg 314b8e80941Smrg assert(_mesa_is_winsys_fbo(&stfb->Base)); 315848b8605Smrg 316848b8605Smrg /* do not distinguish depth/stencil buffers */ 317848b8605Smrg if (idx == BUFFER_STENCIL) 318848b8605Smrg idx = BUFFER_DEPTH; 319848b8605Smrg 320848b8605Smrg switch (idx) { 321848b8605Smrg case BUFFER_DEPTH: 322848b8605Smrg format = stfb->iface->visual->depth_stencil_format; 323848b8605Smrg sw = FALSE; 324848b8605Smrg break; 325848b8605Smrg case BUFFER_ACCUM: 326848b8605Smrg format = stfb->iface->visual->accum_format; 327848b8605Smrg sw = TRUE; 328848b8605Smrg break; 329848b8605Smrg default: 330848b8605Smrg format = stfb->iface->visual->color_format; 331b8e80941Smrg if (prefer_srgb) 332848b8605Smrg format = util_format_srgb(format); 333848b8605Smrg sw = FALSE; 334848b8605Smrg break; 335848b8605Smrg } 336848b8605Smrg 337848b8605Smrg if (format == PIPE_FORMAT_NONE) 338848b8605Smrg return FALSE; 339848b8605Smrg 340848b8605Smrg rb = st_new_renderbuffer_fb(format, stfb->iface->visual->samples, sw); 341848b8605Smrg if (!rb) 342848b8605Smrg return FALSE; 343848b8605Smrg 344848b8605Smrg if (idx != BUFFER_DEPTH) { 345b8e80941Smrg _mesa_attach_and_own_rb(&stfb->Base, idx, rb); 346b8e80941Smrg return TRUE; 347848b8605Smrg } 348b8e80941Smrg 349b8e80941Smrg bool rb_ownership_taken = false; 350b8e80941Smrg if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 0)) { 351b8e80941Smrg _mesa_attach_and_own_rb(&stfb->Base, BUFFER_DEPTH, rb); 352b8e80941Smrg rb_ownership_taken = true; 353b8e80941Smrg } 354b8e80941Smrg 355b8e80941Smrg if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 1)) { 356b8e80941Smrg if (rb_ownership_taken) 357b8e80941Smrg _mesa_attach_and_reference_rb(&stfb->Base, BUFFER_STENCIL, rb); 358b8e80941Smrg else 359b8e80941Smrg _mesa_attach_and_own_rb(&stfb->Base, BUFFER_STENCIL, rb); 360848b8605Smrg } 361848b8605Smrg 362848b8605Smrg return TRUE; 363848b8605Smrg} 364848b8605Smrg 365b8e80941Smrg 366848b8605Smrg/** 367848b8605Smrg * Intialize a struct gl_config from a visual. 368848b8605Smrg */ 369848b8605Smrgstatic void 370848b8605Smrgst_visual_to_context_mode(const struct st_visual *visual, 371848b8605Smrg struct gl_config *mode) 372848b8605Smrg{ 373848b8605Smrg memset(mode, 0, sizeof(*mode)); 374848b8605Smrg 375848b8605Smrg if (st_visual_have_buffers(visual, ST_ATTACHMENT_BACK_LEFT_MASK)) 376848b8605Smrg mode->doubleBufferMode = GL_TRUE; 377b8e80941Smrg 378848b8605Smrg if (st_visual_have_buffers(visual, 379848b8605Smrg ST_ATTACHMENT_FRONT_RIGHT_MASK | ST_ATTACHMENT_BACK_RIGHT_MASK)) 380848b8605Smrg mode->stereoMode = GL_TRUE; 381848b8605Smrg 382848b8605Smrg if (visual->color_format != PIPE_FORMAT_NONE) { 383848b8605Smrg mode->rgbMode = GL_TRUE; 384848b8605Smrg 385848b8605Smrg mode->redBits = 386848b8605Smrg util_format_get_component_bits(visual->color_format, 387848b8605Smrg UTIL_FORMAT_COLORSPACE_RGB, 0); 388848b8605Smrg mode->greenBits = 389848b8605Smrg util_format_get_component_bits(visual->color_format, 390848b8605Smrg UTIL_FORMAT_COLORSPACE_RGB, 1); 391848b8605Smrg mode->blueBits = 392848b8605Smrg util_format_get_component_bits(visual->color_format, 393848b8605Smrg UTIL_FORMAT_COLORSPACE_RGB, 2); 394848b8605Smrg mode->alphaBits = 395848b8605Smrg util_format_get_component_bits(visual->color_format, 396848b8605Smrg UTIL_FORMAT_COLORSPACE_RGB, 3); 397848b8605Smrg 398848b8605Smrg mode->rgbBits = mode->redBits + 399848b8605Smrg mode->greenBits + mode->blueBits + mode->alphaBits; 400b8e80941Smrg mode->sRGBCapable = util_format_is_srgb(visual->color_format); 401848b8605Smrg } 402848b8605Smrg 403848b8605Smrg if (visual->depth_stencil_format != PIPE_FORMAT_NONE) { 404848b8605Smrg mode->depthBits = 405848b8605Smrg util_format_get_component_bits(visual->depth_stencil_format, 406848b8605Smrg UTIL_FORMAT_COLORSPACE_ZS, 0); 407848b8605Smrg mode->stencilBits = 408848b8605Smrg util_format_get_component_bits(visual->depth_stencil_format, 409848b8605Smrg UTIL_FORMAT_COLORSPACE_ZS, 1); 410848b8605Smrg 411848b8605Smrg mode->haveDepthBuffer = mode->depthBits > 0; 412848b8605Smrg mode->haveStencilBuffer = mode->stencilBits > 0; 413848b8605Smrg } 414848b8605Smrg 415848b8605Smrg if (visual->accum_format != PIPE_FORMAT_NONE) { 416848b8605Smrg mode->haveAccumBuffer = GL_TRUE; 417848b8605Smrg 418848b8605Smrg mode->accumRedBits = 419848b8605Smrg util_format_get_component_bits(visual->accum_format, 420848b8605Smrg UTIL_FORMAT_COLORSPACE_RGB, 0); 421848b8605Smrg mode->accumGreenBits = 422848b8605Smrg util_format_get_component_bits(visual->accum_format, 423848b8605Smrg UTIL_FORMAT_COLORSPACE_RGB, 1); 424848b8605Smrg mode->accumBlueBits = 425848b8605Smrg util_format_get_component_bits(visual->accum_format, 426848b8605Smrg UTIL_FORMAT_COLORSPACE_RGB, 2); 427848b8605Smrg mode->accumAlphaBits = 428848b8605Smrg util_format_get_component_bits(visual->accum_format, 429848b8605Smrg UTIL_FORMAT_COLORSPACE_RGB, 3); 430848b8605Smrg } 431848b8605Smrg 432848b8605Smrg if (visual->samples > 1) { 433848b8605Smrg mode->sampleBuffers = 1; 434848b8605Smrg mode->samples = visual->samples; 435848b8605Smrg } 436848b8605Smrg} 437848b8605Smrg 438b8e80941Smrg 439848b8605Smrg/** 440848b8605Smrg * Create a framebuffer from a manager interface. 441848b8605Smrg */ 442848b8605Smrgstatic struct st_framebuffer * 443848b8605Smrgst_framebuffer_create(struct st_context *st, 444848b8605Smrg struct st_framebuffer_iface *stfbi) 445848b8605Smrg{ 446848b8605Smrg struct st_framebuffer *stfb; 447848b8605Smrg struct gl_config mode; 448848b8605Smrg gl_buffer_index idx; 449b8e80941Smrg bool prefer_srgb = false; 450848b8605Smrg 451848b8605Smrg if (!stfbi) 452848b8605Smrg return NULL; 453848b8605Smrg 454848b8605Smrg stfb = CALLOC_STRUCT(st_framebuffer); 455848b8605Smrg if (!stfb) 456848b8605Smrg return NULL; 457848b8605Smrg 458848b8605Smrg st_visual_to_context_mode(stfbi->visual, &mode); 459848b8605Smrg 460848b8605Smrg /* 461848b8605Smrg * For desktop GL, sRGB framebuffer write is controlled by both the 462848b8605Smrg * capability of the framebuffer and GL_FRAMEBUFFER_SRGB. We should 463848b8605Smrg * advertise the capability when the pipe driver (and core Mesa) supports 464848b8605Smrg * it so that applications can enable sRGB write when they want to. 465848b8605Smrg * 466848b8605Smrg * This is not to be confused with GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB. When 467848b8605Smrg * the attribute is GLX_TRUE, it tells the st manager to pick a color 468848b8605Smrg * format such that util_format_srgb(visual->color_format) can be supported 469848b8605Smrg * by the pipe driver. We still need to advertise the capability here. 470848b8605Smrg * 471b8e80941Smrg * For GLES, however, sRGB framebuffer write is initially only controlled 472b8e80941Smrg * by the capability of the framebuffer, with GL_EXT_sRGB_write_control 473b8e80941Smrg * control is given back to the applications, but GL_FRAMEBUFFER_SRGB is 474b8e80941Smrg * still enabled by default since this is the behaviour when 475b8e80941Smrg * EXT_sRGB_write_control is not available. Since GL_EXT_sRGB_write_control 476b8e80941Smrg * brings GLES on par with desktop GLs EXT_framebuffer_sRGB, in mesa this 477b8e80941Smrg * is also expressed by using the same extension flag 478848b8605Smrg */ 479b8e80941Smrg if (_mesa_has_EXT_framebuffer_sRGB(st->ctx)) { 480848b8605Smrg struct pipe_screen *screen = st->pipe->screen; 481848b8605Smrg const enum pipe_format srgb_format = 482848b8605Smrg util_format_srgb(stfbi->visual->color_format); 483848b8605Smrg 484848b8605Smrg if (srgb_format != PIPE_FORMAT_NONE && 485848b8605Smrg st_pipe_format_to_mesa_format(srgb_format) != MESA_FORMAT_NONE && 486848b8605Smrg screen->is_format_supported(screen, srgb_format, 487848b8605Smrg PIPE_TEXTURE_2D, stfbi->visual->samples, 488b8e80941Smrg stfbi->visual->samples, 489b8e80941Smrg (PIPE_BIND_DISPLAY_TARGET | 490b8e80941Smrg PIPE_BIND_RENDER_TARGET))) { 491848b8605Smrg mode.sRGBCapable = GL_TRUE; 492b8e80941Smrg /* Since GL_FRAMEBUFFER_SRGB is enabled by default on GLES we must not 493b8e80941Smrg * create renderbuffers with an sRGB format derived from the 494b8e80941Smrg * visual->color_format, but we still want sRGB for desktop GL. 495b8e80941Smrg */ 496b8e80941Smrg prefer_srgb = _mesa_is_desktop_gl(st->ctx); 497b8e80941Smrg } 498848b8605Smrg } 499848b8605Smrg 500848b8605Smrg _mesa_initialize_window_framebuffer(&stfb->Base, &mode); 501848b8605Smrg 502848b8605Smrg stfb->iface = stfbi; 503b8e80941Smrg stfb->iface_ID = stfbi->ID; 504848b8605Smrg stfb->iface_stamp = p_atomic_read(&stfbi->stamp) - 1; 505848b8605Smrg 506848b8605Smrg /* add the color buffer */ 507848b8605Smrg idx = stfb->Base._ColorDrawBufferIndexes[0]; 508b8e80941Smrg if (!st_framebuffer_add_renderbuffer(stfb, idx, prefer_srgb)) { 509848b8605Smrg free(stfb); 510848b8605Smrg return NULL; 511848b8605Smrg } 512848b8605Smrg 513b8e80941Smrg st_framebuffer_add_renderbuffer(stfb, BUFFER_DEPTH, false); 514b8e80941Smrg st_framebuffer_add_renderbuffer(stfb, BUFFER_ACCUM, false); 515848b8605Smrg 516848b8605Smrg stfb->stamp = 0; 517848b8605Smrg st_framebuffer_update_attachments(stfb); 518848b8605Smrg 519848b8605Smrg return stfb; 520848b8605Smrg} 521848b8605Smrg 522b8e80941Smrg 523848b8605Smrg/** 524848b8605Smrg * Reference a framebuffer. 525848b8605Smrg */ 526b8e80941Smrgvoid 527848b8605Smrgst_framebuffer_reference(struct st_framebuffer **ptr, 528848b8605Smrg struct st_framebuffer *stfb) 529848b8605Smrg{ 530848b8605Smrg struct gl_framebuffer *fb = &stfb->Base; 531848b8605Smrg _mesa_reference_framebuffer((struct gl_framebuffer **) ptr, fb); 532848b8605Smrg} 533848b8605Smrg 534b8e80941Smrg 535b8e80941Smrgstatic uint32_t 536b8e80941Smrgst_framebuffer_iface_hash(const void *key) 537b8e80941Smrg{ 538b8e80941Smrg return (uintptr_t)key; 539b8e80941Smrg} 540b8e80941Smrg 541b8e80941Smrg 542b8e80941Smrgstatic bool 543b8e80941Smrgst_framebuffer_iface_equal(const void *a, const void *b) 544b8e80941Smrg{ 545b8e80941Smrg return (struct st_framebuffer_iface *)a == (struct st_framebuffer_iface *)b; 546b8e80941Smrg} 547b8e80941Smrg 548b8e80941Smrg 549b8e80941Smrgstatic boolean 550b8e80941Smrgst_framebuffer_iface_lookup(struct st_manager *smapi, 551b8e80941Smrg const struct st_framebuffer_iface *stfbi) 552b8e80941Smrg{ 553b8e80941Smrg struct st_manager_private *smPriv = 554b8e80941Smrg (struct st_manager_private *)smapi->st_manager_private; 555b8e80941Smrg struct hash_entry *entry; 556b8e80941Smrg 557b8e80941Smrg assert(smPriv); 558b8e80941Smrg assert(smPriv->stfbi_ht); 559b8e80941Smrg 560b8e80941Smrg mtx_lock(&smPriv->st_mutex); 561b8e80941Smrg entry = _mesa_hash_table_search(smPriv->stfbi_ht, stfbi); 562b8e80941Smrg mtx_unlock(&smPriv->st_mutex); 563b8e80941Smrg 564b8e80941Smrg return entry != NULL; 565b8e80941Smrg} 566b8e80941Smrg 567b8e80941Smrg 568b8e80941Smrgstatic boolean 569b8e80941Smrgst_framebuffer_iface_insert(struct st_manager *smapi, 570b8e80941Smrg struct st_framebuffer_iface *stfbi) 571b8e80941Smrg{ 572b8e80941Smrg struct st_manager_private *smPriv = 573b8e80941Smrg (struct st_manager_private *)smapi->st_manager_private; 574b8e80941Smrg struct hash_entry *entry; 575b8e80941Smrg 576b8e80941Smrg assert(smPriv); 577b8e80941Smrg assert(smPriv->stfbi_ht); 578b8e80941Smrg 579b8e80941Smrg mtx_lock(&smPriv->st_mutex); 580b8e80941Smrg entry = _mesa_hash_table_insert(smPriv->stfbi_ht, stfbi, stfbi); 581b8e80941Smrg mtx_unlock(&smPriv->st_mutex); 582b8e80941Smrg 583b8e80941Smrg return entry != NULL; 584b8e80941Smrg} 585b8e80941Smrg 586b8e80941Smrg 587b8e80941Smrgstatic void 588b8e80941Smrgst_framebuffer_iface_remove(struct st_manager *smapi, 589b8e80941Smrg struct st_framebuffer_iface *stfbi) 590b8e80941Smrg{ 591b8e80941Smrg struct st_manager_private *smPriv = 592b8e80941Smrg (struct st_manager_private *)smapi->st_manager_private; 593b8e80941Smrg struct hash_entry *entry; 594b8e80941Smrg 595b8e80941Smrg if (!smPriv || !smPriv->stfbi_ht) 596b8e80941Smrg return; 597b8e80941Smrg 598b8e80941Smrg mtx_lock(&smPriv->st_mutex); 599b8e80941Smrg entry = _mesa_hash_table_search(smPriv->stfbi_ht, stfbi); 600b8e80941Smrg if (!entry) 601b8e80941Smrg goto unlock; 602b8e80941Smrg 603b8e80941Smrg _mesa_hash_table_remove(smPriv->stfbi_ht, entry); 604b8e80941Smrg 605b8e80941Smrgunlock: 606b8e80941Smrg mtx_unlock(&smPriv->st_mutex); 607b8e80941Smrg} 608b8e80941Smrg 609b8e80941Smrg 610b8e80941Smrg/** 611b8e80941Smrg * The framebuffer interface object is no longer valid. 612b8e80941Smrg * Remove the object from the framebuffer interface hash table. 613b8e80941Smrg */ 614b8e80941Smrgstatic void 615b8e80941Smrgst_api_destroy_drawable(struct st_api *stapi, 616b8e80941Smrg struct st_framebuffer_iface *stfbi) 617b8e80941Smrg{ 618b8e80941Smrg if (!stfbi) 619b8e80941Smrg return; 620b8e80941Smrg 621b8e80941Smrg st_framebuffer_iface_remove(stfbi->state_manager, stfbi); 622b8e80941Smrg} 623b8e80941Smrg 624b8e80941Smrg 625b8e80941Smrg/** 626b8e80941Smrg * Purge the winsys buffers list to remove any references to 627b8e80941Smrg * non-existing framebuffer interface objects. 628b8e80941Smrg */ 629b8e80941Smrgstatic void 630b8e80941Smrgst_framebuffers_purge(struct st_context *st) 631b8e80941Smrg{ 632b8e80941Smrg struct st_context_iface *st_iface = &st->iface; 633b8e80941Smrg struct st_manager *smapi = st_iface->state_manager; 634b8e80941Smrg struct st_framebuffer *stfb, *next; 635b8e80941Smrg 636b8e80941Smrg assert(smapi); 637b8e80941Smrg 638b8e80941Smrg LIST_FOR_EACH_ENTRY_SAFE_REV(stfb, next, &st->winsys_buffers, head) { 639b8e80941Smrg struct st_framebuffer_iface *stfbi = stfb->iface; 640b8e80941Smrg 641b8e80941Smrg assert(stfbi); 642b8e80941Smrg 643b8e80941Smrg /** 644b8e80941Smrg * If the corresponding framebuffer interface object no longer exists, 645b8e80941Smrg * remove the framebuffer object from the context's winsys buffers list, 646b8e80941Smrg * and unreference the framebuffer object, so its resources can be 647b8e80941Smrg * deleted. 648b8e80941Smrg */ 649b8e80941Smrg if (!st_framebuffer_iface_lookup(smapi, stfbi)) { 650b8e80941Smrg LIST_DEL(&stfb->head); 651b8e80941Smrg st_framebuffer_reference(&stfb, NULL); 652b8e80941Smrg } 653b8e80941Smrg } 654b8e80941Smrg} 655b8e80941Smrg 656b8e80941Smrg 657848b8605Smrgstatic void 658848b8605Smrgst_context_flush(struct st_context_iface *stctxi, unsigned flags, 659848b8605Smrg struct pipe_fence_handle **fence) 660848b8605Smrg{ 661848b8605Smrg struct st_context *st = (struct st_context *) stctxi; 662848b8605Smrg unsigned pipe_flags = 0; 663848b8605Smrg 664b8e80941Smrg if (flags & ST_FLUSH_END_OF_FRAME) 665848b8605Smrg pipe_flags |= PIPE_FLUSH_END_OF_FRAME; 666b8e80941Smrg if (flags & ST_FLUSH_FENCE_FD) 667b8e80941Smrg pipe_flags |= PIPE_FLUSH_FENCE_FD; 668848b8605Smrg 669b8e80941Smrg FLUSH_VERTICES(st->ctx, 0); 670b8e80941Smrg FLUSH_CURRENT(st->ctx, 0); 671848b8605Smrg st_flush(st, fence, pipe_flags); 672b8e80941Smrg 673b8e80941Smrg if ((flags & ST_FLUSH_WAIT) && fence && *fence) { 674b8e80941Smrg st->pipe->screen->fence_finish(st->pipe->screen, NULL, *fence, 675b8e80941Smrg PIPE_TIMEOUT_INFINITE); 676b8e80941Smrg st->pipe->screen->fence_reference(st->pipe->screen, fence, NULL); 677b8e80941Smrg } 678b8e80941Smrg 679848b8605Smrg if (flags & ST_FLUSH_FRONT) 680848b8605Smrg st_manager_flush_frontbuffer(st); 681b8e80941Smrg 682b8e80941Smrg /* DRI3 changes the framebuffer after SwapBuffers, but we need to invoke 683b8e80941Smrg * st_manager_validate_framebuffers to notice that. 684b8e80941Smrg * 685b8e80941Smrg * Set gfx_shaders_may_be_dirty to invoke st_validate_state in the next 686b8e80941Smrg * draw call, which will invoke st_manager_validate_framebuffers, but it 687b8e80941Smrg * won't dirty states if there is no change. 688b8e80941Smrg */ 689b8e80941Smrg if (flags & ST_FLUSH_END_OF_FRAME) 690b8e80941Smrg st->gfx_shaders_may_be_dirty = true; 691848b8605Smrg} 692848b8605Smrg 693848b8605Smrgstatic boolean 694848b8605Smrgst_context_teximage(struct st_context_iface *stctxi, 695848b8605Smrg enum st_texture_type tex_type, 696848b8605Smrg int level, enum pipe_format pipe_format, 697848b8605Smrg struct pipe_resource *tex, boolean mipmap) 698848b8605Smrg{ 699848b8605Smrg struct st_context *st = (struct st_context *) stctxi; 700848b8605Smrg struct gl_context *ctx = st->ctx; 701848b8605Smrg struct gl_texture_object *texObj; 702848b8605Smrg struct gl_texture_image *texImage; 703848b8605Smrg struct st_texture_object *stObj; 704848b8605Smrg struct st_texture_image *stImage; 705848b8605Smrg GLenum internalFormat; 706848b8605Smrg GLuint width, height, depth; 707848b8605Smrg GLenum target; 708848b8605Smrg 709848b8605Smrg switch (tex_type) { 710848b8605Smrg case ST_TEXTURE_1D: 711848b8605Smrg target = GL_TEXTURE_1D; 712848b8605Smrg break; 713848b8605Smrg case ST_TEXTURE_2D: 714848b8605Smrg target = GL_TEXTURE_2D; 715848b8605Smrg break; 716848b8605Smrg case ST_TEXTURE_3D: 717848b8605Smrg target = GL_TEXTURE_3D; 718848b8605Smrg break; 719848b8605Smrg case ST_TEXTURE_RECT: 720848b8605Smrg target = GL_TEXTURE_RECTANGLE_ARB; 721848b8605Smrg break; 722848b8605Smrg default: 723848b8605Smrg return FALSE; 724848b8605Smrg } 725848b8605Smrg 726848b8605Smrg texObj = _mesa_get_current_tex_object(ctx, target); 727848b8605Smrg 728848b8605Smrg _mesa_lock_texture(ctx, texObj); 729848b8605Smrg 730848b8605Smrg stObj = st_texture_object(texObj); 731848b8605Smrg /* switch to surface based */ 732848b8605Smrg if (!stObj->surface_based) { 733b8e80941Smrg _mesa_clear_texture_object(ctx, texObj, NULL); 734848b8605Smrg stObj->surface_based = GL_TRUE; 735848b8605Smrg } 736848b8605Smrg 737848b8605Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 738848b8605Smrg stImage = st_texture_image(texImage); 739848b8605Smrg if (tex) { 740848b8605Smrg mesa_format texFormat = st_pipe_format_to_mesa_format(pipe_format); 741848b8605Smrg 742848b8605Smrg if (util_format_has_alpha(tex->format)) 743848b8605Smrg internalFormat = GL_RGBA; 744848b8605Smrg else 745848b8605Smrg internalFormat = GL_RGB; 746848b8605Smrg 747848b8605Smrg _mesa_init_teximage_fields(ctx, texImage, 748848b8605Smrg tex->width0, tex->height0, 1, 0, 749848b8605Smrg internalFormat, texFormat); 750848b8605Smrg 751848b8605Smrg width = tex->width0; 752848b8605Smrg height = tex->height0; 753848b8605Smrg depth = tex->depth0; 754848b8605Smrg 755848b8605Smrg /* grow the image size until we hit level = 0 */ 756848b8605Smrg while (level > 0) { 757848b8605Smrg if (width != 1) 758848b8605Smrg width <<= 1; 759848b8605Smrg if (height != 1) 760848b8605Smrg height <<= 1; 761848b8605Smrg if (depth != 1) 762848b8605Smrg depth <<= 1; 763848b8605Smrg level--; 764848b8605Smrg } 765848b8605Smrg } 766848b8605Smrg else { 767848b8605Smrg _mesa_clear_texture_image(ctx, texImage); 768848b8605Smrg width = height = depth = 0; 769848b8605Smrg } 770848b8605Smrg 771b8e80941Smrg pipe_resource_reference(&stObj->pt, tex); 772b8e80941Smrg st_texture_release_all_sampler_views(st, stObj); 773848b8605Smrg pipe_resource_reference(&stImage->pt, tex); 774848b8605Smrg stObj->surface_format = pipe_format; 775848b8605Smrg 776b8e80941Smrg stObj->needs_validation = true; 777b8e80941Smrg 778848b8605Smrg _mesa_dirty_texobj(ctx, texObj); 779848b8605Smrg _mesa_unlock_texture(ctx, texObj); 780b8e80941Smrg 781848b8605Smrg return TRUE; 782848b8605Smrg} 783848b8605Smrg 784b8e80941Smrg 785848b8605Smrgstatic void 786848b8605Smrgst_context_copy(struct st_context_iface *stctxi, 787848b8605Smrg struct st_context_iface *stsrci, unsigned mask) 788848b8605Smrg{ 789848b8605Smrg struct st_context *st = (struct st_context *) stctxi; 790848b8605Smrg struct st_context *src = (struct st_context *) stsrci; 791848b8605Smrg 792848b8605Smrg _mesa_copy_context(src->ctx, st->ctx, mask); 793848b8605Smrg} 794848b8605Smrg 795b8e80941Smrg 796848b8605Smrgstatic boolean 797848b8605Smrgst_context_share(struct st_context_iface *stctxi, 798848b8605Smrg struct st_context_iface *stsrci) 799848b8605Smrg{ 800848b8605Smrg struct st_context *st = (struct st_context *) stctxi; 801848b8605Smrg struct st_context *src = (struct st_context *) stsrci; 802848b8605Smrg 803848b8605Smrg return _mesa_share_state(st->ctx, src->ctx); 804848b8605Smrg} 805848b8605Smrg 806b8e80941Smrg 807848b8605Smrgstatic void 808848b8605Smrgst_context_destroy(struct st_context_iface *stctxi) 809848b8605Smrg{ 810848b8605Smrg struct st_context *st = (struct st_context *) stctxi; 811848b8605Smrg st_destroy_context(st); 812848b8605Smrg} 813848b8605Smrg 814b8e80941Smrg 815b8e80941Smrgstatic void 816b8e80941Smrgst_start_thread(struct st_context_iface *stctxi) 817b8e80941Smrg{ 818b8e80941Smrg struct st_context *st = (struct st_context *) stctxi; 819b8e80941Smrg 820b8e80941Smrg _mesa_glthread_init(st->ctx); 821b8e80941Smrg 822b8e80941Smrg /* Pin all driver threads to one L3 cache for optimal performance 823b8e80941Smrg * on AMD Zen. This is only done if glthread is enabled. 824b8e80941Smrg * 825b8e80941Smrg * If glthread is disabled, st_draw.c re-pins driver threads regularly 826b8e80941Smrg * based on the location of the app thread. 827b8e80941Smrg */ 828b8e80941Smrg struct glthread_state *glthread = st->ctx->GLThread; 829b8e80941Smrg if (glthread && st->pipe->set_context_param) { 830b8e80941Smrg util_pin_driver_threads_to_random_L3(st->pipe, &glthread->queue.threads[0]); 831b8e80941Smrg } 832b8e80941Smrg} 833b8e80941Smrg 834b8e80941Smrg 835b8e80941Smrgstatic void 836b8e80941Smrgst_thread_finish(struct st_context_iface *stctxi) 837b8e80941Smrg{ 838b8e80941Smrg struct st_context *st = (struct st_context *) stctxi; 839b8e80941Smrg 840b8e80941Smrg _mesa_glthread_finish(st->ctx); 841b8e80941Smrg} 842b8e80941Smrg 843b8e80941Smrg 844b8e80941Smrgstatic void 845b8e80941Smrgst_manager_destroy(struct st_manager *smapi) 846b8e80941Smrg{ 847b8e80941Smrg struct st_manager_private *smPriv = smapi->st_manager_private; 848b8e80941Smrg 849b8e80941Smrg if (smPriv && smPriv->stfbi_ht) { 850b8e80941Smrg _mesa_hash_table_destroy(smPriv->stfbi_ht, NULL); 851b8e80941Smrg mtx_destroy(&smPriv->st_mutex); 852b8e80941Smrg free(smPriv); 853b8e80941Smrg smapi->st_manager_private = NULL; 854b8e80941Smrg } 855b8e80941Smrg} 856b8e80941Smrg 857b8e80941Smrg 858848b8605Smrgstatic struct st_context_iface * 859848b8605Smrgst_api_create_context(struct st_api *stapi, struct st_manager *smapi, 860848b8605Smrg const struct st_context_attribs *attribs, 861848b8605Smrg enum st_context_error *error, 862848b8605Smrg struct st_context_iface *shared_stctxi) 863848b8605Smrg{ 864848b8605Smrg struct st_context *shared_ctx = (struct st_context *) shared_stctxi; 865848b8605Smrg struct st_context *st; 866848b8605Smrg struct pipe_context *pipe; 867b8e80941Smrg struct gl_config* mode_ptr; 868848b8605Smrg struct gl_config mode; 869848b8605Smrg gl_api api; 870b8e80941Smrg bool no_error = false; 871b8e80941Smrg unsigned ctx_flags = PIPE_CONTEXT_PREFER_THREADED; 872848b8605Smrg 873848b8605Smrg if (!(stapi->profile_mask & (1 << attribs->profile))) 874848b8605Smrg return NULL; 875848b8605Smrg 876848b8605Smrg switch (attribs->profile) { 877848b8605Smrg case ST_PROFILE_DEFAULT: 878848b8605Smrg api = API_OPENGL_COMPAT; 879848b8605Smrg break; 880848b8605Smrg case ST_PROFILE_OPENGL_ES1: 881848b8605Smrg api = API_OPENGLES; 882848b8605Smrg break; 883848b8605Smrg case ST_PROFILE_OPENGL_ES2: 884848b8605Smrg api = API_OPENGLES2; 885848b8605Smrg break; 886848b8605Smrg case ST_PROFILE_OPENGL_CORE: 887848b8605Smrg api = API_OPENGL_CORE; 888848b8605Smrg break; 889848b8605Smrg default: 890848b8605Smrg *error = ST_CONTEXT_ERROR_BAD_API; 891848b8605Smrg return NULL; 892848b8605Smrg } 893848b8605Smrg 894b8e80941Smrg /* Create a hash table for the framebuffer interface objects 895b8e80941Smrg * if it has not been created for this st manager. 896b8e80941Smrg */ 897b8e80941Smrg if (smapi->st_manager_private == NULL) { 898b8e80941Smrg struct st_manager_private *smPriv; 899b8e80941Smrg 900b8e80941Smrg smPriv = CALLOC_STRUCT(st_manager_private); 901b8e80941Smrg mtx_init(&smPriv->st_mutex, mtx_plain); 902b8e80941Smrg smPriv->stfbi_ht = _mesa_hash_table_create(NULL, 903b8e80941Smrg st_framebuffer_iface_hash, 904b8e80941Smrg st_framebuffer_iface_equal); 905b8e80941Smrg smapi->st_manager_private = smPriv; 906b8e80941Smrg smapi->destroy = st_manager_destroy; 907b8e80941Smrg } 908b8e80941Smrg 909b8e80941Smrg if (attribs->flags & ST_CONTEXT_FLAG_ROBUST_ACCESS) 910b8e80941Smrg ctx_flags |= PIPE_CONTEXT_ROBUST_BUFFER_ACCESS; 911b8e80941Smrg 912b8e80941Smrg if (attribs->flags & ST_CONTEXT_FLAG_NO_ERROR) 913b8e80941Smrg no_error = true; 914b8e80941Smrg 915b8e80941Smrg if (attribs->flags & ST_CONTEXT_FLAG_LOW_PRIORITY) 916b8e80941Smrg ctx_flags |= PIPE_CONTEXT_LOW_PRIORITY; 917b8e80941Smrg else if (attribs->flags & ST_CONTEXT_FLAG_HIGH_PRIORITY) 918b8e80941Smrg ctx_flags |= PIPE_CONTEXT_HIGH_PRIORITY; 919b8e80941Smrg 920b8e80941Smrg if (attribs->flags & ST_CONTEXT_FLAG_RESET_NOTIFICATION_ENABLED) 921b8e80941Smrg ctx_flags |= PIPE_CONTEXT_LOSE_CONTEXT_ON_RESET; 922b8e80941Smrg 923b8e80941Smrg pipe = smapi->screen->context_create(smapi->screen, NULL, ctx_flags); 924848b8605Smrg if (!pipe) { 925848b8605Smrg *error = ST_CONTEXT_ERROR_NO_MEMORY; 926848b8605Smrg return NULL; 927848b8605Smrg } 928848b8605Smrg 929848b8605Smrg st_visual_to_context_mode(&attribs->visual, &mode); 930b8e80941Smrg 931b8e80941Smrg if (attribs->visual.no_config) 932b8e80941Smrg mode_ptr = NULL; 933b8e80941Smrg else 934b8e80941Smrg mode_ptr = &mode; 935b8e80941Smrg 936b8e80941Smrg st = st_create_context(api, pipe, mode_ptr, shared_ctx, 937b8e80941Smrg &attribs->options, no_error); 938848b8605Smrg if (!st) { 939848b8605Smrg *error = ST_CONTEXT_ERROR_NO_MEMORY; 940848b8605Smrg pipe->destroy(pipe); 941848b8605Smrg return NULL; 942848b8605Smrg } 943848b8605Smrg 944b8e80941Smrg if (attribs->flags & ST_CONTEXT_FLAG_DEBUG) { 945848b8605Smrg if (!_mesa_set_debug_state_int(st->ctx, GL_DEBUG_OUTPUT, GL_TRUE)) { 946848b8605Smrg *error = ST_CONTEXT_ERROR_NO_MEMORY; 947848b8605Smrg return NULL; 948848b8605Smrg } 949b8e80941Smrg 950848b8605Smrg st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_DEBUG_BIT; 951848b8605Smrg } 952848b8605Smrg 953b8e80941Smrg if (st->ctx->Const.ContextFlags & GL_CONTEXT_FLAG_DEBUG_BIT) { 954b8e80941Smrg st_update_debug_callback(st); 955b8e80941Smrg } 956b8e80941Smrg 957848b8605Smrg if (attribs->flags & ST_CONTEXT_FLAG_FORWARD_COMPATIBLE) 958848b8605Smrg st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT; 959b8e80941Smrg if (attribs->flags & ST_CONTEXT_FLAG_ROBUST_ACCESS) { 960b8e80941Smrg st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB; 961b8e80941Smrg st->ctx->Const.RobustAccess = GL_TRUE; 962b8e80941Smrg } 963b8e80941Smrg if (attribs->flags & ST_CONTEXT_FLAG_RESET_NOTIFICATION_ENABLED) { 964b8e80941Smrg st->ctx->Const.ResetStrategy = GL_LOSE_CONTEXT_ON_RESET_ARB; 965b8e80941Smrg st_install_device_reset_callback(st); 966b8e80941Smrg } 967b8e80941Smrg 968b8e80941Smrg if (attribs->flags & ST_CONTEXT_FLAG_RELEASE_NONE) 969b8e80941Smrg st->ctx->Const.ContextReleaseBehavior = GL_NONE; 970848b8605Smrg 971848b8605Smrg /* need to perform version check */ 972848b8605Smrg if (attribs->major > 1 || attribs->minor > 0) { 973848b8605Smrg /* Is the actual version less than the requested version? 974848b8605Smrg */ 975b8e80941Smrg if (st->ctx->Version < attribs->major * 10U + attribs->minor) { 976b8e80941Smrg *error = ST_CONTEXT_ERROR_BAD_VERSION; 977848b8605Smrg st_destroy_context(st); 978848b8605Smrg return NULL; 979848b8605Smrg } 980848b8605Smrg } 981848b8605Smrg 982848b8605Smrg st->invalidate_on_gl_viewport = 983848b8605Smrg smapi->get_param(smapi, ST_MANAGER_BROKEN_INVALIDATE); 984848b8605Smrg 985848b8605Smrg st->iface.destroy = st_context_destroy; 986848b8605Smrg st->iface.flush = st_context_flush; 987848b8605Smrg st->iface.teximage = st_context_teximage; 988848b8605Smrg st->iface.copy = st_context_copy; 989848b8605Smrg st->iface.share = st_context_share; 990b8e80941Smrg st->iface.start_thread = st_start_thread; 991b8e80941Smrg st->iface.thread_finish = st_thread_finish; 992848b8605Smrg st->iface.st_context_private = (void *) smapi; 993848b8605Smrg st->iface.cso_context = st->cso_context; 994848b8605Smrg st->iface.pipe = st->pipe; 995b8e80941Smrg st->iface.state_manager = smapi; 996848b8605Smrg 997848b8605Smrg *error = ST_CONTEXT_SUCCESS; 998848b8605Smrg return &st->iface; 999848b8605Smrg} 1000848b8605Smrg 1001b8e80941Smrg 1002848b8605Smrgstatic struct st_context_iface * 1003848b8605Smrgst_api_get_current(struct st_api *stapi) 1004848b8605Smrg{ 1005848b8605Smrg GET_CURRENT_CONTEXT(ctx); 1006b8e80941Smrg struct st_context *st = ctx ? ctx->st : NULL; 1007848b8605Smrg 1008b8e80941Smrg return st ? &st->iface : NULL; 1009848b8605Smrg} 1010848b8605Smrg 1011b8e80941Smrg 1012848b8605Smrgstatic struct st_framebuffer * 1013848b8605Smrgst_framebuffer_reuse_or_create(struct st_context *st, 1014848b8605Smrg struct gl_framebuffer *fb, 1015848b8605Smrg struct st_framebuffer_iface *stfbi) 1016848b8605Smrg{ 1017b8e80941Smrg struct st_framebuffer *cur = NULL, *stfb = NULL; 1018b8e80941Smrg 1019b8e80941Smrg if (!stfbi) 1020b8e80941Smrg return NULL; 1021848b8605Smrg 1022b8e80941Smrg /* Check if there is already a framebuffer object for the specified 1023b8e80941Smrg * framebuffer interface in this context. If there is one, use it. 1024b8e80941Smrg */ 1025b8e80941Smrg LIST_FOR_EACH_ENTRY(cur, &st->winsys_buffers, head) { 1026b8e80941Smrg if (cur->iface_ID == stfbi->ID) { 1027b8e80941Smrg st_framebuffer_reference(&stfb, cur); 1028b8e80941Smrg break; 1029b8e80941Smrg } 1030848b8605Smrg } 1031b8e80941Smrg 1032b8e80941Smrg /* If there is not already a framebuffer object, create one */ 1033b8e80941Smrg if (stfb == NULL) { 1034b8e80941Smrg cur = st_framebuffer_create(st, stfbi); 1035b8e80941Smrg 1036b8e80941Smrg if (cur) { 1037b8e80941Smrg /* add the referenced framebuffer interface object to 1038b8e80941Smrg * the framebuffer interface object hash table. 1039b8e80941Smrg */ 1040b8e80941Smrg if (!st_framebuffer_iface_insert(stfbi->state_manager, stfbi)) { 1041b8e80941Smrg st_framebuffer_reference(&cur, NULL); 1042b8e80941Smrg return NULL; 1043b8e80941Smrg } 1044b8e80941Smrg 1045b8e80941Smrg /* add to the context's winsys buffers list */ 1046b8e80941Smrg LIST_ADD(&cur->head, &st->winsys_buffers); 1047b8e80941Smrg 1048b8e80941Smrg st_framebuffer_reference(&stfb, cur); 1049b8e80941Smrg } 1050848b8605Smrg } 1051848b8605Smrg 1052848b8605Smrg return stfb; 1053848b8605Smrg} 1054848b8605Smrg 1055b8e80941Smrg 1056848b8605Smrgstatic boolean 1057848b8605Smrgst_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi, 1058848b8605Smrg struct st_framebuffer_iface *stdrawi, 1059848b8605Smrg struct st_framebuffer_iface *streadi) 1060848b8605Smrg{ 1061848b8605Smrg struct st_context *st = (struct st_context *) stctxi; 1062848b8605Smrg struct st_framebuffer *stdraw, *stread; 1063848b8605Smrg boolean ret; 1064848b8605Smrg 1065848b8605Smrg if (st) { 1066848b8605Smrg /* reuse or create the draw fb */ 1067848b8605Smrg stdraw = st_framebuffer_reuse_or_create(st, 1068848b8605Smrg st->ctx->WinSysDrawBuffer, stdrawi); 1069848b8605Smrg if (streadi != stdrawi) { 1070848b8605Smrg /* do the same for the read fb */ 1071848b8605Smrg stread = st_framebuffer_reuse_or_create(st, 1072848b8605Smrg st->ctx->WinSysReadBuffer, streadi); 1073848b8605Smrg } 1074848b8605Smrg else { 1075848b8605Smrg stread = NULL; 1076848b8605Smrg /* reuse the draw fb for the read fb */ 1077848b8605Smrg if (stdraw) 1078848b8605Smrg st_framebuffer_reference(&stread, stdraw); 1079848b8605Smrg } 1080848b8605Smrg 1081848b8605Smrg if (stdraw && stread) { 1082848b8605Smrg st_framebuffer_validate(stdraw, st); 1083848b8605Smrg if (stread != stdraw) 1084848b8605Smrg st_framebuffer_validate(stread, st); 1085848b8605Smrg 1086848b8605Smrg ret = _mesa_make_current(st->ctx, &stdraw->Base, &stread->Base); 1087848b8605Smrg 1088848b8605Smrg st->draw_stamp = stdraw->stamp - 1; 1089848b8605Smrg st->read_stamp = stread->stamp - 1; 1090848b8605Smrg st_context_validate(st, stdraw, stread); 1091848b8605Smrg } 1092848b8605Smrg else { 1093848b8605Smrg struct gl_framebuffer *incomplete = _mesa_get_incomplete_framebuffer(); 1094848b8605Smrg ret = _mesa_make_current(st->ctx, incomplete, incomplete); 1095848b8605Smrg } 1096848b8605Smrg 1097848b8605Smrg st_framebuffer_reference(&stdraw, NULL); 1098848b8605Smrg st_framebuffer_reference(&stread, NULL); 1099b8e80941Smrg 1100b8e80941Smrg /* Purge the context's winsys_buffers list in case any 1101b8e80941Smrg * of the referenced drawables no longer exist. 1102b8e80941Smrg */ 1103b8e80941Smrg st_framebuffers_purge(st); 1104848b8605Smrg } 1105848b8605Smrg else { 1106b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 1107b8e80941Smrg 1108b8e80941Smrg if (ctx) { 1109b8e80941Smrg /* Before releasing the context, release its associated 1110b8e80941Smrg * winsys buffers first. Then purge the context's winsys buffers list 1111b8e80941Smrg * to free the resources of any winsys buffers that no longer have 1112b8e80941Smrg * an existing drawable. 1113b8e80941Smrg */ 1114b8e80941Smrg ret = _mesa_make_current(ctx, NULL, NULL); 1115b8e80941Smrg st_framebuffers_purge(ctx->st); 1116b8e80941Smrg } 1117b8e80941Smrg 1118848b8605Smrg ret = _mesa_make_current(NULL, NULL, NULL); 1119848b8605Smrg } 1120848b8605Smrg 1121848b8605Smrg return ret; 1122848b8605Smrg} 1123848b8605Smrg 1124848b8605Smrg 1125848b8605Smrgstatic void 1126848b8605Smrgst_api_destroy(struct st_api *stapi) 1127848b8605Smrg{ 1128848b8605Smrg} 1129848b8605Smrg 1130b8e80941Smrg 1131848b8605Smrg/** 1132848b8605Smrg * Flush the front buffer if the current context renders to the front buffer. 1133848b8605Smrg */ 1134848b8605Smrgvoid 1135848b8605Smrgst_manager_flush_frontbuffer(struct st_context *st) 1136848b8605Smrg{ 1137848b8605Smrg struct st_framebuffer *stfb = st_ws_framebuffer(st->ctx->DrawBuffer); 1138848b8605Smrg struct st_renderbuffer *strb = NULL; 1139848b8605Smrg 1140b8e80941Smrg if (!stfb) 1141848b8605Smrg return; 1142848b8605Smrg 1143b8e80941Smrg /* If the context uses a doublebuffered visual, but the buffer is 1144b8e80941Smrg * single-buffered, guess that it's a pbuffer, which doesn't need 1145b8e80941Smrg * flushing. 1146b8e80941Smrg */ 1147b8e80941Smrg if (st->ctx->Visual.doubleBufferMode && 1148b8e80941Smrg !stfb->Base.Visual.doubleBufferMode) 1149b8e80941Smrg return; 1150848b8605Smrg 1151b8e80941Smrg strb = st_renderbuffer(stfb->Base.Attachment[BUFFER_FRONT_LEFT]. 1152b8e80941Smrg Renderbuffer); 1153848b8605Smrg 1154b8e80941Smrg /* Do we have a front color buffer and has it been drawn to since last 1155b8e80941Smrg * frontbuffer flush? 1156b8e80941Smrg */ 1157b8e80941Smrg if (strb && strb->defined) { 1158b8e80941Smrg stfb->iface->flush_front(&st->iface, stfb->iface, 1159b8e80941Smrg ST_ATTACHMENT_FRONT_LEFT); 1160b8e80941Smrg strb->defined = GL_FALSE; 1161848b8605Smrg 1162b8e80941Smrg /* Trigger an update of strb->defined on next draw */ 1163b8e80941Smrg st->dirty |= ST_NEW_FB_STATE; 1164b8e80941Smrg } 1165848b8605Smrg} 1166848b8605Smrg 1167b8e80941Smrg 1168848b8605Smrg/** 1169848b8605Smrg * Re-validate the framebuffers. 1170848b8605Smrg */ 1171848b8605Smrgvoid 1172848b8605Smrgst_manager_validate_framebuffers(struct st_context *st) 1173848b8605Smrg{ 1174848b8605Smrg struct st_framebuffer *stdraw = st_ws_framebuffer(st->ctx->DrawBuffer); 1175848b8605Smrg struct st_framebuffer *stread = st_ws_framebuffer(st->ctx->ReadBuffer); 1176848b8605Smrg 1177848b8605Smrg if (stdraw) 1178848b8605Smrg st_framebuffer_validate(stdraw, st); 1179848b8605Smrg if (stread && stread != stdraw) 1180848b8605Smrg st_framebuffer_validate(stread, st); 1181848b8605Smrg 1182848b8605Smrg st_context_validate(st, stdraw, stread); 1183848b8605Smrg} 1184848b8605Smrg 1185b8e80941Smrg 1186b8e80941Smrg/** 1187b8e80941Smrg * Flush any outstanding swapbuffers on the current draw framebuffer. 1188b8e80941Smrg */ 1189b8e80941Smrgvoid 1190b8e80941Smrgst_manager_flush_swapbuffers(void) 1191b8e80941Smrg{ 1192b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 1193b8e80941Smrg struct st_context *st = (ctx) ? ctx->st : NULL; 1194b8e80941Smrg struct st_framebuffer *stfb; 1195b8e80941Smrg 1196b8e80941Smrg if (!st) 1197b8e80941Smrg return; 1198b8e80941Smrg 1199b8e80941Smrg stfb = st_ws_framebuffer(ctx->DrawBuffer); 1200b8e80941Smrg if (!stfb || !stfb->iface->flush_swapbuffers) 1201b8e80941Smrg return; 1202b8e80941Smrg 1203b8e80941Smrg stfb->iface->flush_swapbuffers(&st->iface, stfb->iface); 1204b8e80941Smrg} 1205b8e80941Smrg 1206b8e80941Smrg 1207848b8605Smrg/** 1208b8e80941Smrg * Add a color renderbuffer on demand. The FBO must correspond to a window, 1209b8e80941Smrg * not a user-created FBO. 1210848b8605Smrg */ 1211848b8605Smrgboolean 1212848b8605Smrgst_manager_add_color_renderbuffer(struct st_context *st, 1213848b8605Smrg struct gl_framebuffer *fb, 1214848b8605Smrg gl_buffer_index idx) 1215848b8605Smrg{ 1216848b8605Smrg struct st_framebuffer *stfb = st_ws_framebuffer(fb); 1217848b8605Smrg 1218848b8605Smrg /* FBO */ 1219848b8605Smrg if (!stfb) 1220848b8605Smrg return FALSE; 1221848b8605Smrg 1222b8e80941Smrg assert(_mesa_is_winsys_fbo(fb)); 1223b8e80941Smrg 1224848b8605Smrg if (stfb->Base.Attachment[idx].Renderbuffer) 1225848b8605Smrg return TRUE; 1226848b8605Smrg 1227848b8605Smrg switch (idx) { 1228848b8605Smrg case BUFFER_FRONT_LEFT: 1229848b8605Smrg case BUFFER_BACK_LEFT: 1230848b8605Smrg case BUFFER_FRONT_RIGHT: 1231848b8605Smrg case BUFFER_BACK_RIGHT: 1232848b8605Smrg break; 1233848b8605Smrg default: 1234848b8605Smrg return FALSE; 1235848b8605Smrg } 1236848b8605Smrg 1237b8e80941Smrg if (!st_framebuffer_add_renderbuffer(stfb, idx, 1238b8e80941Smrg stfb->Base.Visual.sRGBCapable)) 1239848b8605Smrg return FALSE; 1240848b8605Smrg 1241848b8605Smrg st_framebuffer_update_attachments(stfb); 1242848b8605Smrg 1243848b8605Smrg /* 1244848b8605Smrg * Force a call to the state tracker manager to validate the 1245848b8605Smrg * new renderbuffer. It might be that there is a window system 1246848b8605Smrg * renderbuffer available. 1247848b8605Smrg */ 1248b8e80941Smrg if (stfb->iface) 1249848b8605Smrg stfb->iface_stamp = p_atomic_read(&stfb->iface->stamp) - 1; 1250848b8605Smrg 1251b8e80941Smrg st_invalidate_buffers(st); 1252848b8605Smrg 1253848b8605Smrg return TRUE; 1254848b8605Smrg} 1255848b8605Smrg 1256b8e80941Smrg 1257b8e80941Smrgstatic unsigned 1258b8e80941Smrgget_version(struct pipe_screen *screen, 1259b8e80941Smrg struct st_config_options *options, gl_api api) 1260848b8605Smrg{ 1261848b8605Smrg struct gl_constants consts = {0}; 1262848b8605Smrg struct gl_extensions extensions = {0}; 1263848b8605Smrg GLuint version; 1264848b8605Smrg 1265b8e80941Smrg if (_mesa_override_gl_version_contextless(&consts, &api, &version)) { 1266848b8605Smrg return version; 1267848b8605Smrg } 1268848b8605Smrg 1269848b8605Smrg _mesa_init_constants(&consts, api); 1270848b8605Smrg _mesa_init_extensions(&extensions); 1271848b8605Smrg 1272848b8605Smrg st_init_limits(screen, &consts, &extensions); 1273b8e80941Smrg st_init_extensions(screen, &consts, &extensions, options, api); 1274848b8605Smrg 1275848b8605Smrg return _mesa_get_version(&extensions, &consts, api); 1276848b8605Smrg} 1277848b8605Smrg 1278b8e80941Smrg 1279848b8605Smrgstatic void 1280848b8605Smrgst_api_query_versions(struct st_api *stapi, struct st_manager *sm, 1281848b8605Smrg struct st_config_options *options, 1282848b8605Smrg int *gl_core_version, 1283848b8605Smrg int *gl_compat_version, 1284848b8605Smrg int *gl_es1_version, 1285848b8605Smrg int *gl_es2_version) 1286848b8605Smrg{ 1287848b8605Smrg *gl_core_version = get_version(sm->screen, options, API_OPENGL_CORE); 1288848b8605Smrg *gl_compat_version = get_version(sm->screen, options, API_OPENGL_COMPAT); 1289848b8605Smrg *gl_es1_version = get_version(sm->screen, options, API_OPENGLES); 1290848b8605Smrg *gl_es2_version = get_version(sm->screen, options, API_OPENGLES2); 1291848b8605Smrg} 1292848b8605Smrg 1293b8e80941Smrg 1294848b8605Smrgstatic const struct st_api st_gl_api = { 1295b8e80941Smrg .name = "Mesa " PACKAGE_VERSION, 1296b8e80941Smrg .api = ST_API_OPENGL, 1297b8e80941Smrg .profile_mask = ST_PROFILE_DEFAULT_MASK | 1298b8e80941Smrg ST_PROFILE_OPENGL_CORE_MASK | 1299b8e80941Smrg ST_PROFILE_OPENGL_ES1_MASK | 1300b8e80941Smrg ST_PROFILE_OPENGL_ES2_MASK | 1301b8e80941Smrg 0, 1302b8e80941Smrg .feature_mask = ST_API_FEATURE_MS_VISUALS_MASK, 1303b8e80941Smrg .destroy = st_api_destroy, 1304b8e80941Smrg .query_versions = st_api_query_versions, 1305b8e80941Smrg .create_context = st_api_create_context, 1306b8e80941Smrg .make_current = st_api_make_current, 1307b8e80941Smrg .get_current = st_api_get_current, 1308b8e80941Smrg .destroy_drawable = st_api_destroy_drawable, 1309848b8605Smrg}; 1310848b8605Smrg 1311b8e80941Smrg 1312848b8605Smrgstruct st_api * 1313848b8605Smrgst_gl_api_create(void) 1314848b8605Smrg{ 1315848b8605Smrg return (struct st_api *) &st_gl_api; 1316848b8605Smrg} 1317