13464ebd5Sriastradh/* 23464ebd5Sriastradh * Mesa 3-D graphics library 33464ebd5Sriastradh * 43464ebd5Sriastradh * Copyright (C) 2010 LunarG Inc. 53464ebd5Sriastradh * 63464ebd5Sriastradh * Permission is hereby granted, free of charge, to any person obtaining a 73464ebd5Sriastradh * copy of this software and associated documentation files (the "Software"), 83464ebd5Sriastradh * to deal in the Software without restriction, including without limitation 93464ebd5Sriastradh * the rights to use, copy, modify, merge, publish, distribute, sublicense, 103464ebd5Sriastradh * and/or sell copies of the Software, and to permit persons to whom the 113464ebd5Sriastradh * Software is furnished to do so, subject to the following conditions: 123464ebd5Sriastradh * 133464ebd5Sriastradh * The above copyright notice and this permission notice shall be included 143464ebd5Sriastradh * in all copies or substantial portions of the Software. 153464ebd5Sriastradh * 163464ebd5Sriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 173464ebd5Sriastradh * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 183464ebd5Sriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 193464ebd5Sriastradh * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 203464ebd5Sriastradh * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 213464ebd5Sriastradh * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 223464ebd5Sriastradh * DEALINGS IN THE SOFTWARE. 233464ebd5Sriastradh * 243464ebd5Sriastradh * Authors: 253464ebd5Sriastradh * Chia-I Wu <olv@lunarg.com> 263464ebd5Sriastradh */ 273464ebd5Sriastradh 283464ebd5Sriastradh#include "main/mtypes.h" 29af69d88dSmrg#include "main/extensions.h" 303464ebd5Sriastradh#include "main/context.h" 3101e04c3fSmrg#include "main/debug_output.h" 3201e04c3fSmrg#include "main/glthread.h" 333464ebd5Sriastradh#include "main/texobj.h" 343464ebd5Sriastradh#include "main/teximage.h" 353464ebd5Sriastradh#include "main/texstate.h" 36af69d88dSmrg#include "main/errors.h" 373464ebd5Sriastradh#include "main/framebuffer.h" 383464ebd5Sriastradh#include "main/fbobject.h" 393464ebd5Sriastradh#include "main/renderbuffer.h" 403464ebd5Sriastradh#include "main/version.h" 4101e04c3fSmrg#include "util/hash_table.h" 423464ebd5Sriastradh#include "st_texture.h" 433464ebd5Sriastradh 443464ebd5Sriastradh#include "st_context.h" 4501e04c3fSmrg#include "st_debug.h" 46af69d88dSmrg#include "st_extensions.h" 473464ebd5Sriastradh#include "st_format.h" 4801e04c3fSmrg#include "st_cb_bitmap.h" 493464ebd5Sriastradh#include "st_cb_fbo.h" 503464ebd5Sriastradh#include "st_cb_flush.h" 513464ebd5Sriastradh#include "st_manager.h" 5201e04c3fSmrg#include "st_sampler_view.h" 533464ebd5Sriastradh 54af69d88dSmrg#include "state_tracker/st_gl_api.h" 55af69d88dSmrg 56af69d88dSmrg#include "pipe/p_context.h" 57af69d88dSmrg#include "pipe/p_screen.h" 587ec681f3Smrg#include "util/format/u_format.h" 5901e04c3fSmrg#include "util/u_helpers.h" 60af69d88dSmrg#include "util/u_pointer.h" 61af69d88dSmrg#include "util/u_inlines.h" 62af69d88dSmrg#include "util/u_atomic.h" 63af69d88dSmrg#include "util/u_surface.h" 6401e04c3fSmrg#include "util/list.h" 657ec681f3Smrg#include "util/u_memory.h" 66af69d88dSmrg 6701e04c3fSmrgstruct hash_table; 6801e04c3fSmrgstruct st_manager_private 693464ebd5Sriastradh{ 7001e04c3fSmrg struct hash_table *stfbi_ht; /* framebuffer iface objects hash table */ 717ec681f3Smrg simple_mtx_t st_mutex; 7201e04c3fSmrg}; 7301e04c3fSmrg 743464ebd5Sriastradh 753464ebd5Sriastradh/** 763464ebd5Sriastradh * Map an attachment to a buffer index. 773464ebd5Sriastradh */ 7801e04c3fSmrgstatic inline gl_buffer_index 793464ebd5Sriastradhattachment_to_buffer_index(enum st_attachment_type statt) 803464ebd5Sriastradh{ 813464ebd5Sriastradh gl_buffer_index index; 823464ebd5Sriastradh 833464ebd5Sriastradh switch (statt) { 843464ebd5Sriastradh case ST_ATTACHMENT_FRONT_LEFT: 853464ebd5Sriastradh index = BUFFER_FRONT_LEFT; 863464ebd5Sriastradh break; 873464ebd5Sriastradh case ST_ATTACHMENT_BACK_LEFT: 883464ebd5Sriastradh index = BUFFER_BACK_LEFT; 893464ebd5Sriastradh break; 903464ebd5Sriastradh case ST_ATTACHMENT_FRONT_RIGHT: 913464ebd5Sriastradh index = BUFFER_FRONT_RIGHT; 923464ebd5Sriastradh break; 933464ebd5Sriastradh case ST_ATTACHMENT_BACK_RIGHT: 943464ebd5Sriastradh index = BUFFER_BACK_RIGHT; 953464ebd5Sriastradh break; 963464ebd5Sriastradh case ST_ATTACHMENT_DEPTH_STENCIL: 973464ebd5Sriastradh index = BUFFER_DEPTH; 983464ebd5Sriastradh break; 993464ebd5Sriastradh case ST_ATTACHMENT_ACCUM: 1003464ebd5Sriastradh index = BUFFER_ACCUM; 1013464ebd5Sriastradh break; 1023464ebd5Sriastradh default: 1033464ebd5Sriastradh index = BUFFER_COUNT; 1043464ebd5Sriastradh break; 1053464ebd5Sriastradh } 1063464ebd5Sriastradh 1073464ebd5Sriastradh return index; 1083464ebd5Sriastradh} 1093464ebd5Sriastradh 11001e04c3fSmrg 1113464ebd5Sriastradh/** 1123464ebd5Sriastradh * Map a buffer index to an attachment. 1133464ebd5Sriastradh */ 11401e04c3fSmrgstatic inline enum st_attachment_type 1153464ebd5Sriastradhbuffer_index_to_attachment(gl_buffer_index index) 1163464ebd5Sriastradh{ 1173464ebd5Sriastradh enum st_attachment_type statt; 1183464ebd5Sriastradh 1193464ebd5Sriastradh switch (index) { 1203464ebd5Sriastradh case BUFFER_FRONT_LEFT: 1213464ebd5Sriastradh statt = ST_ATTACHMENT_FRONT_LEFT; 1223464ebd5Sriastradh break; 1233464ebd5Sriastradh case BUFFER_BACK_LEFT: 1243464ebd5Sriastradh statt = ST_ATTACHMENT_BACK_LEFT; 1253464ebd5Sriastradh break; 1263464ebd5Sriastradh case BUFFER_FRONT_RIGHT: 1273464ebd5Sriastradh statt = ST_ATTACHMENT_FRONT_RIGHT; 1283464ebd5Sriastradh break; 1293464ebd5Sriastradh case BUFFER_BACK_RIGHT: 1303464ebd5Sriastradh statt = ST_ATTACHMENT_BACK_RIGHT; 1313464ebd5Sriastradh break; 1323464ebd5Sriastradh case BUFFER_DEPTH: 1333464ebd5Sriastradh statt = ST_ATTACHMENT_DEPTH_STENCIL; 1343464ebd5Sriastradh break; 1353464ebd5Sriastradh case BUFFER_ACCUM: 1363464ebd5Sriastradh statt = ST_ATTACHMENT_ACCUM; 1373464ebd5Sriastradh break; 1383464ebd5Sriastradh default: 1393464ebd5Sriastradh statt = ST_ATTACHMENT_INVALID; 1403464ebd5Sriastradh break; 1413464ebd5Sriastradh } 1423464ebd5Sriastradh 1433464ebd5Sriastradh return statt; 1443464ebd5Sriastradh} 1453464ebd5Sriastradh 14601e04c3fSmrg 147af69d88dSmrg/** 148af69d88dSmrg * Make sure a context picks up the latest cached state of the 149af69d88dSmrg * drawables it binds to. 150af69d88dSmrg */ 151af69d88dSmrgstatic void 152af69d88dSmrgst_context_validate(struct st_context *st, 153af69d88dSmrg struct st_framebuffer *stdraw, 154af69d88dSmrg struct st_framebuffer *stread) 155af69d88dSmrg{ 156af69d88dSmrg if (stdraw && stdraw->stamp != st->draw_stamp) { 15701e04c3fSmrg st->dirty |= ST_NEW_FRAMEBUFFER; 158af69d88dSmrg _mesa_resize_framebuffer(st->ctx, &stdraw->Base, 159af69d88dSmrg stdraw->Base.Width, 160af69d88dSmrg stdraw->Base.Height); 161af69d88dSmrg st->draw_stamp = stdraw->stamp; 162af69d88dSmrg } 163af69d88dSmrg 164af69d88dSmrg if (stread && stread->stamp != st->read_stamp) { 165af69d88dSmrg if (stread != stdraw) { 16601e04c3fSmrg st->dirty |= ST_NEW_FRAMEBUFFER; 167af69d88dSmrg _mesa_resize_framebuffer(st->ctx, &stread->Base, 168af69d88dSmrg stread->Base.Width, 169af69d88dSmrg stread->Base.Height); 170af69d88dSmrg } 171af69d88dSmrg st->read_stamp = stread->stamp; 172af69d88dSmrg } 173af69d88dSmrg} 174af69d88dSmrg 17501e04c3fSmrg 176b9abf16eSmayavoid 177b9abf16eSmayast_set_ws_renderbuffer_surface(struct st_renderbuffer *strb, 178b9abf16eSmaya struct pipe_surface *surf) 179b9abf16eSmaya{ 180b9abf16eSmaya pipe_surface_reference(&strb->surface_srgb, NULL); 181b9abf16eSmaya pipe_surface_reference(&strb->surface_linear, NULL); 182b9abf16eSmaya 183b9abf16eSmaya if (util_format_is_srgb(surf->format)) 184b9abf16eSmaya pipe_surface_reference(&strb->surface_srgb, surf); 185b9abf16eSmaya else 186b9abf16eSmaya pipe_surface_reference(&strb->surface_linear, surf); 187b9abf16eSmaya 188b9abf16eSmaya strb->surface = surf; /* just assign, don't ref */ 189b9abf16eSmaya pipe_resource_reference(&strb->texture, surf->texture); 190b9abf16eSmaya 191b9abf16eSmaya strb->Base.Width = surf->width; 192b9abf16eSmaya strb->Base.Height = surf->height; 193b9abf16eSmaya} 194b9abf16eSmaya 195b9abf16eSmaya 1963464ebd5Sriastradh/** 1973464ebd5Sriastradh * Validate a framebuffer to make sure up-to-date pipe_textures are used. 198af69d88dSmrg * The context is only used for creating pipe surfaces and for calling 199af69d88dSmrg * _mesa_resize_framebuffer(). 200af69d88dSmrg * (That should probably be rethought, since those surfaces become 201af69d88dSmrg * drawable state, not context state, and can be freed by another pipe 202af69d88dSmrg * context). 2033464ebd5Sriastradh */ 2043464ebd5Sriastradhstatic void 205af69d88dSmrgst_framebuffer_validate(struct st_framebuffer *stfb, 206af69d88dSmrg struct st_context *st) 2073464ebd5Sriastradh{ 2083464ebd5Sriastradh struct pipe_resource *textures[ST_ATTACHMENT_COUNT]; 2093464ebd5Sriastradh uint width, height; 2103464ebd5Sriastradh unsigned i; 2117ec681f3Smrg bool changed = false; 212af69d88dSmrg int32_t new_stamp; 2133464ebd5Sriastradh 214af69d88dSmrg new_stamp = p_atomic_read(&stfb->iface->stamp); 215af69d88dSmrg if (stfb->iface_stamp == new_stamp) 2163464ebd5Sriastradh return; 2173464ebd5Sriastradh 21801e04c3fSmrg memset(textures, 0, stfb->num_statts * sizeof(textures[0])); 21901e04c3fSmrg 220af69d88dSmrg /* validate the fb */ 221af69d88dSmrg do { 222af69d88dSmrg if (!stfb->iface->validate(&st->iface, stfb->iface, stfb->statts, 22301e04c3fSmrg stfb->num_statts, textures)) 22401e04c3fSmrg return; 225af69d88dSmrg 226af69d88dSmrg stfb->iface_stamp = new_stamp; 227af69d88dSmrg new_stamp = p_atomic_read(&stfb->iface->stamp); 228af69d88dSmrg } while(stfb->iface_stamp != new_stamp); 229af69d88dSmrg 2303464ebd5Sriastradh width = stfb->Base.Width; 2313464ebd5Sriastradh height = stfb->Base.Height; 2323464ebd5Sriastradh 2333464ebd5Sriastradh for (i = 0; i < stfb->num_statts; i++) { 2343464ebd5Sriastradh struct st_renderbuffer *strb; 2353464ebd5Sriastradh struct pipe_surface *ps, surf_tmpl; 2363464ebd5Sriastradh gl_buffer_index idx; 2373464ebd5Sriastradh 2383464ebd5Sriastradh if (!textures[i]) 2393464ebd5Sriastradh continue; 2403464ebd5Sriastradh 2413464ebd5Sriastradh idx = attachment_to_buffer_index(stfb->statts[i]); 2423464ebd5Sriastradh if (idx >= BUFFER_COUNT) { 2433464ebd5Sriastradh pipe_resource_reference(&textures[i], NULL); 2443464ebd5Sriastradh continue; 2453464ebd5Sriastradh } 2463464ebd5Sriastradh 2473464ebd5Sriastradh strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer); 2483464ebd5Sriastradh assert(strb); 2493464ebd5Sriastradh if (strb->texture == textures[i]) { 2503464ebd5Sriastradh pipe_resource_reference(&textures[i], NULL); 2513464ebd5Sriastradh continue; 2523464ebd5Sriastradh } 2533464ebd5Sriastradh 254af69d88dSmrg u_surface_default_template(&surf_tmpl, textures[i]); 255af69d88dSmrg ps = st->pipe->create_surface(st->pipe, textures[i], &surf_tmpl); 2563464ebd5Sriastradh if (ps) { 257b9abf16eSmaya st_set_ws_renderbuffer_surface(strb, ps); 2583464ebd5Sriastradh pipe_surface_reference(&ps, NULL); 2593464ebd5Sriastradh 2607ec681f3Smrg changed = true; 2613464ebd5Sriastradh 2623464ebd5Sriastradh width = strb->Base.Width; 2633464ebd5Sriastradh height = strb->Base.Height; 2643464ebd5Sriastradh } 2653464ebd5Sriastradh 2663464ebd5Sriastradh pipe_resource_reference(&textures[i], NULL); 2673464ebd5Sriastradh } 2683464ebd5Sriastradh 2693464ebd5Sriastradh if (changed) { 270af69d88dSmrg ++stfb->stamp; 2713464ebd5Sriastradh _mesa_resize_framebuffer(st->ctx, &stfb->Base, width, height); 2723464ebd5Sriastradh } 2733464ebd5Sriastradh} 2743464ebd5Sriastradh 27501e04c3fSmrg 2763464ebd5Sriastradh/** 2773464ebd5Sriastradh * Update the attachments to validate by looping the existing renderbuffers. 2783464ebd5Sriastradh */ 2793464ebd5Sriastradhstatic void 2803464ebd5Sriastradhst_framebuffer_update_attachments(struct st_framebuffer *stfb) 2813464ebd5Sriastradh{ 2823464ebd5Sriastradh gl_buffer_index idx; 2833464ebd5Sriastradh 2843464ebd5Sriastradh stfb->num_statts = 0; 2857ec681f3Smrg 2867ec681f3Smrg for (enum st_attachment_type i = 0; i < ST_ATTACHMENT_COUNT; i++) 2877ec681f3Smrg stfb->statts[i] = ST_ATTACHMENT_INVALID; 2887ec681f3Smrg 2893464ebd5Sriastradh for (idx = 0; idx < BUFFER_COUNT; idx++) { 2903464ebd5Sriastradh struct st_renderbuffer *strb; 2913464ebd5Sriastradh enum st_attachment_type statt; 2923464ebd5Sriastradh 2933464ebd5Sriastradh strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer); 2943464ebd5Sriastradh if (!strb || strb->software) 2953464ebd5Sriastradh continue; 2963464ebd5Sriastradh 2973464ebd5Sriastradh statt = buffer_index_to_attachment(idx); 2983464ebd5Sriastradh if (statt != ST_ATTACHMENT_INVALID && 2993464ebd5Sriastradh st_visual_have_buffers(stfb->iface->visual, 1 << statt)) 3003464ebd5Sriastradh stfb->statts[stfb->num_statts++] = statt; 3013464ebd5Sriastradh } 302af69d88dSmrg stfb->stamp++; 3033464ebd5Sriastradh} 3043464ebd5Sriastradh 30501e04c3fSmrg 3063464ebd5Sriastradh/** 30701e04c3fSmrg * Add a renderbuffer to the framebuffer. The framebuffer is one that 30801e04c3fSmrg * corresponds to a window and is not a user-created FBO. 3093464ebd5Sriastradh */ 3107ec681f3Smrgstatic bool 3113464ebd5Sriastradhst_framebuffer_add_renderbuffer(struct st_framebuffer *stfb, 312b9abf16eSmaya gl_buffer_index idx, bool prefer_srgb) 3133464ebd5Sriastradh{ 3143464ebd5Sriastradh struct gl_renderbuffer *rb; 3153464ebd5Sriastradh enum pipe_format format; 3167ec681f3Smrg bool sw; 3173464ebd5Sriastradh 31801e04c3fSmrg assert(_mesa_is_winsys_fbo(&stfb->Base)); 3193464ebd5Sriastradh 3203464ebd5Sriastradh /* do not distinguish depth/stencil buffers */ 3213464ebd5Sriastradh if (idx == BUFFER_STENCIL) 3223464ebd5Sriastradh idx = BUFFER_DEPTH; 3233464ebd5Sriastradh 3243464ebd5Sriastradh switch (idx) { 3253464ebd5Sriastradh case BUFFER_DEPTH: 3263464ebd5Sriastradh format = stfb->iface->visual->depth_stencil_format; 3277ec681f3Smrg sw = false; 3283464ebd5Sriastradh break; 3293464ebd5Sriastradh case BUFFER_ACCUM: 3303464ebd5Sriastradh format = stfb->iface->visual->accum_format; 3317ec681f3Smrg sw = true; 3323464ebd5Sriastradh break; 3333464ebd5Sriastradh default: 3343464ebd5Sriastradh format = stfb->iface->visual->color_format; 335b9abf16eSmaya if (prefer_srgb) 336af69d88dSmrg format = util_format_srgb(format); 3377ec681f3Smrg sw = false; 3383464ebd5Sriastradh break; 3393464ebd5Sriastradh } 3403464ebd5Sriastradh 3413464ebd5Sriastradh if (format == PIPE_FORMAT_NONE) 3427ec681f3Smrg return false; 3433464ebd5Sriastradh 344af69d88dSmrg rb = st_new_renderbuffer_fb(format, stfb->iface->visual->samples, sw); 3453464ebd5Sriastradh if (!rb) 3467ec681f3Smrg return false; 3473464ebd5Sriastradh 3483464ebd5Sriastradh if (idx != BUFFER_DEPTH) { 34901e04c3fSmrg _mesa_attach_and_own_rb(&stfb->Base, idx, rb); 3507ec681f3Smrg return true; 3513464ebd5Sriastradh } 35201e04c3fSmrg 35301e04c3fSmrg bool rb_ownership_taken = false; 35401e04c3fSmrg if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 0)) { 35501e04c3fSmrg _mesa_attach_and_own_rb(&stfb->Base, BUFFER_DEPTH, rb); 35601e04c3fSmrg rb_ownership_taken = true; 35701e04c3fSmrg } 35801e04c3fSmrg 35901e04c3fSmrg if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 1)) { 36001e04c3fSmrg if (rb_ownership_taken) 36101e04c3fSmrg _mesa_attach_and_reference_rb(&stfb->Base, BUFFER_STENCIL, rb); 36201e04c3fSmrg else 36301e04c3fSmrg _mesa_attach_and_own_rb(&stfb->Base, BUFFER_STENCIL, rb); 3643464ebd5Sriastradh } 3653464ebd5Sriastradh 3667ec681f3Smrg return true; 3673464ebd5Sriastradh} 3683464ebd5Sriastradh 36901e04c3fSmrg 3703464ebd5Sriastradh/** 3713464ebd5Sriastradh * Intialize a struct gl_config from a visual. 3723464ebd5Sriastradh */ 3733464ebd5Sriastradhstatic void 3743464ebd5Sriastradhst_visual_to_context_mode(const struct st_visual *visual, 3753464ebd5Sriastradh struct gl_config *mode) 3763464ebd5Sriastradh{ 3773464ebd5Sriastradh memset(mode, 0, sizeof(*mode)); 3783464ebd5Sriastradh 3793464ebd5Sriastradh if (st_visual_have_buffers(visual, ST_ATTACHMENT_BACK_LEFT_MASK)) 3803464ebd5Sriastradh mode->doubleBufferMode = GL_TRUE; 38101e04c3fSmrg 3823464ebd5Sriastradh if (st_visual_have_buffers(visual, 3833464ebd5Sriastradh ST_ATTACHMENT_FRONT_RIGHT_MASK | ST_ATTACHMENT_BACK_RIGHT_MASK)) 3843464ebd5Sriastradh mode->stereoMode = GL_TRUE; 3853464ebd5Sriastradh 3863464ebd5Sriastradh if (visual->color_format != PIPE_FORMAT_NONE) { 3873464ebd5Sriastradh mode->redBits = 3883464ebd5Sriastradh util_format_get_component_bits(visual->color_format, 3893464ebd5Sriastradh UTIL_FORMAT_COLORSPACE_RGB, 0); 3903464ebd5Sriastradh mode->greenBits = 3913464ebd5Sriastradh util_format_get_component_bits(visual->color_format, 3923464ebd5Sriastradh UTIL_FORMAT_COLORSPACE_RGB, 1); 3933464ebd5Sriastradh mode->blueBits = 3943464ebd5Sriastradh util_format_get_component_bits(visual->color_format, 3953464ebd5Sriastradh UTIL_FORMAT_COLORSPACE_RGB, 2); 3963464ebd5Sriastradh mode->alphaBits = 3973464ebd5Sriastradh util_format_get_component_bits(visual->color_format, 3983464ebd5Sriastradh UTIL_FORMAT_COLORSPACE_RGB, 3); 3993464ebd5Sriastradh 4003464ebd5Sriastradh mode->rgbBits = mode->redBits + 4013464ebd5Sriastradh mode->greenBits + mode->blueBits + mode->alphaBits; 40201e04c3fSmrg mode->sRGBCapable = util_format_is_srgb(visual->color_format); 4033464ebd5Sriastradh } 4043464ebd5Sriastradh 4053464ebd5Sriastradh if (visual->depth_stencil_format != PIPE_FORMAT_NONE) { 4063464ebd5Sriastradh mode->depthBits = 4073464ebd5Sriastradh util_format_get_component_bits(visual->depth_stencil_format, 4083464ebd5Sriastradh UTIL_FORMAT_COLORSPACE_ZS, 0); 4093464ebd5Sriastradh mode->stencilBits = 4103464ebd5Sriastradh util_format_get_component_bits(visual->depth_stencil_format, 4113464ebd5Sriastradh UTIL_FORMAT_COLORSPACE_ZS, 1); 4123464ebd5Sriastradh } 4133464ebd5Sriastradh 4143464ebd5Sriastradh if (visual->accum_format != PIPE_FORMAT_NONE) { 4153464ebd5Sriastradh mode->accumRedBits = 4163464ebd5Sriastradh util_format_get_component_bits(visual->accum_format, 4173464ebd5Sriastradh UTIL_FORMAT_COLORSPACE_RGB, 0); 4183464ebd5Sriastradh mode->accumGreenBits = 4193464ebd5Sriastradh util_format_get_component_bits(visual->accum_format, 4203464ebd5Sriastradh UTIL_FORMAT_COLORSPACE_RGB, 1); 4213464ebd5Sriastradh mode->accumBlueBits = 4223464ebd5Sriastradh util_format_get_component_bits(visual->accum_format, 4233464ebd5Sriastradh UTIL_FORMAT_COLORSPACE_RGB, 2); 4243464ebd5Sriastradh mode->accumAlphaBits = 4253464ebd5Sriastradh util_format_get_component_bits(visual->accum_format, 4263464ebd5Sriastradh UTIL_FORMAT_COLORSPACE_RGB, 3); 4273464ebd5Sriastradh } 4283464ebd5Sriastradh 429af69d88dSmrg if (visual->samples > 1) { 4303464ebd5Sriastradh mode->samples = visual->samples; 4313464ebd5Sriastradh } 4323464ebd5Sriastradh} 4333464ebd5Sriastradh 43401e04c3fSmrg 4353464ebd5Sriastradh/** 4363464ebd5Sriastradh * Create a framebuffer from a manager interface. 4373464ebd5Sriastradh */ 4383464ebd5Sriastradhstatic struct st_framebuffer * 439af69d88dSmrgst_framebuffer_create(struct st_context *st, 440af69d88dSmrg struct st_framebuffer_iface *stfbi) 4413464ebd5Sriastradh{ 4423464ebd5Sriastradh struct st_framebuffer *stfb; 4433464ebd5Sriastradh struct gl_config mode; 4443464ebd5Sriastradh gl_buffer_index idx; 445b9abf16eSmaya bool prefer_srgb = false; 4463464ebd5Sriastradh 4473464ebd5Sriastradh if (!stfbi) 4483464ebd5Sriastradh return NULL; 4493464ebd5Sriastradh 4503464ebd5Sriastradh stfb = CALLOC_STRUCT(st_framebuffer); 4513464ebd5Sriastradh if (!stfb) 4523464ebd5Sriastradh return NULL; 4533464ebd5Sriastradh 4543464ebd5Sriastradh st_visual_to_context_mode(stfbi->visual, &mode); 4553464ebd5Sriastradh 456af69d88dSmrg /* 457af69d88dSmrg * For desktop GL, sRGB framebuffer write is controlled by both the 458af69d88dSmrg * capability of the framebuffer and GL_FRAMEBUFFER_SRGB. We should 459af69d88dSmrg * advertise the capability when the pipe driver (and core Mesa) supports 460af69d88dSmrg * it so that applications can enable sRGB write when they want to. 461af69d88dSmrg * 462af69d88dSmrg * This is not to be confused with GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB. When 463af69d88dSmrg * the attribute is GLX_TRUE, it tells the st manager to pick a color 464af69d88dSmrg * format such that util_format_srgb(visual->color_format) can be supported 465af69d88dSmrg * by the pipe driver. We still need to advertise the capability here. 466af69d88dSmrg * 467b9abf16eSmaya * For GLES, however, sRGB framebuffer write is initially only controlled 468b9abf16eSmaya * by the capability of the framebuffer, with GL_EXT_sRGB_write_control 469b9abf16eSmaya * control is given back to the applications, but GL_FRAMEBUFFER_SRGB is 470b9abf16eSmaya * still enabled by default since this is the behaviour when 471b9abf16eSmaya * EXT_sRGB_write_control is not available. Since GL_EXT_sRGB_write_control 472b9abf16eSmaya * brings GLES on par with desktop GLs EXT_framebuffer_sRGB, in mesa this 473b9abf16eSmaya * is also expressed by using the same extension flag 474af69d88dSmrg */ 475b9abf16eSmaya if (_mesa_has_EXT_framebuffer_sRGB(st->ctx)) { 4767ec681f3Smrg struct pipe_screen *screen = st->screen; 477af69d88dSmrg const enum pipe_format srgb_format = 478af69d88dSmrg util_format_srgb(stfbi->visual->color_format); 479af69d88dSmrg 480af69d88dSmrg if (srgb_format != PIPE_FORMAT_NONE && 481af69d88dSmrg st_pipe_format_to_mesa_format(srgb_format) != MESA_FORMAT_NONE && 482af69d88dSmrg screen->is_format_supported(screen, srgb_format, 483af69d88dSmrg PIPE_TEXTURE_2D, stfbi->visual->samples, 48401e04c3fSmrg stfbi->visual->samples, 48501e04c3fSmrg (PIPE_BIND_DISPLAY_TARGET | 486b9abf16eSmaya PIPE_BIND_RENDER_TARGET))) { 487af69d88dSmrg mode.sRGBCapable = GL_TRUE; 488b9abf16eSmaya /* Since GL_FRAMEBUFFER_SRGB is enabled by default on GLES we must not 489b9abf16eSmaya * create renderbuffers with an sRGB format derived from the 490b9abf16eSmaya * visual->color_format, but we still want sRGB for desktop GL. 491b9abf16eSmaya */ 492b9abf16eSmaya prefer_srgb = _mesa_is_desktop_gl(st->ctx); 493b9abf16eSmaya } 494af69d88dSmrg } 495af69d88dSmrg 496af69d88dSmrg _mesa_initialize_window_framebuffer(&stfb->Base, &mode); 4973464ebd5Sriastradh 4983464ebd5Sriastradh stfb->iface = stfbi; 49901e04c3fSmrg stfb->iface_ID = stfbi->ID; 500af69d88dSmrg stfb->iface_stamp = p_atomic_read(&stfbi->stamp) - 1; 5013464ebd5Sriastradh 5023464ebd5Sriastradh /* add the color buffer */ 5033464ebd5Sriastradh idx = stfb->Base._ColorDrawBufferIndexes[0]; 504b9abf16eSmaya if (!st_framebuffer_add_renderbuffer(stfb, idx, prefer_srgb)) { 505af69d88dSmrg free(stfb); 5063464ebd5Sriastradh return NULL; 5073464ebd5Sriastradh } 5083464ebd5Sriastradh 509b9abf16eSmaya st_framebuffer_add_renderbuffer(stfb, BUFFER_DEPTH, false); 510b9abf16eSmaya st_framebuffer_add_renderbuffer(stfb, BUFFER_ACCUM, false); 5113464ebd5Sriastradh 512af69d88dSmrg stfb->stamp = 0; 5133464ebd5Sriastradh st_framebuffer_update_attachments(stfb); 5143464ebd5Sriastradh 5153464ebd5Sriastradh return stfb; 5163464ebd5Sriastradh} 5173464ebd5Sriastradh 51801e04c3fSmrg 5193464ebd5Sriastradh/** 5203464ebd5Sriastradh * Reference a framebuffer. 5213464ebd5Sriastradh */ 52201e04c3fSmrgvoid 5233464ebd5Sriastradhst_framebuffer_reference(struct st_framebuffer **ptr, 5243464ebd5Sriastradh struct st_framebuffer *stfb) 5253464ebd5Sriastradh{ 5267ec681f3Smrg struct gl_framebuffer *fb = stfb ? &stfb->Base : NULL; 5273464ebd5Sriastradh _mesa_reference_framebuffer((struct gl_framebuffer **) ptr, fb); 5283464ebd5Sriastradh} 5293464ebd5Sriastradh 53001e04c3fSmrg 53101e04c3fSmrgstatic uint32_t 53201e04c3fSmrgst_framebuffer_iface_hash(const void *key) 53301e04c3fSmrg{ 53401e04c3fSmrg return (uintptr_t)key; 53501e04c3fSmrg} 53601e04c3fSmrg 53701e04c3fSmrg 53801e04c3fSmrgstatic bool 53901e04c3fSmrgst_framebuffer_iface_equal(const void *a, const void *b) 54001e04c3fSmrg{ 54101e04c3fSmrg return (struct st_framebuffer_iface *)a == (struct st_framebuffer_iface *)b; 54201e04c3fSmrg} 54301e04c3fSmrg 54401e04c3fSmrg 5457ec681f3Smrgstatic bool 54601e04c3fSmrgst_framebuffer_iface_lookup(struct st_manager *smapi, 54701e04c3fSmrg const struct st_framebuffer_iface *stfbi) 54801e04c3fSmrg{ 54901e04c3fSmrg struct st_manager_private *smPriv = 55001e04c3fSmrg (struct st_manager_private *)smapi->st_manager_private; 55101e04c3fSmrg struct hash_entry *entry; 55201e04c3fSmrg 55301e04c3fSmrg assert(smPriv); 55401e04c3fSmrg assert(smPriv->stfbi_ht); 55501e04c3fSmrg 5567ec681f3Smrg simple_mtx_lock(&smPriv->st_mutex); 55701e04c3fSmrg entry = _mesa_hash_table_search(smPriv->stfbi_ht, stfbi); 5587ec681f3Smrg simple_mtx_unlock(&smPriv->st_mutex); 55901e04c3fSmrg 56001e04c3fSmrg return entry != NULL; 56101e04c3fSmrg} 56201e04c3fSmrg 56301e04c3fSmrg 5647ec681f3Smrgstatic bool 56501e04c3fSmrgst_framebuffer_iface_insert(struct st_manager *smapi, 56601e04c3fSmrg struct st_framebuffer_iface *stfbi) 56701e04c3fSmrg{ 56801e04c3fSmrg struct st_manager_private *smPriv = 56901e04c3fSmrg (struct st_manager_private *)smapi->st_manager_private; 57001e04c3fSmrg struct hash_entry *entry; 57101e04c3fSmrg 57201e04c3fSmrg assert(smPriv); 57301e04c3fSmrg assert(smPriv->stfbi_ht); 57401e04c3fSmrg 5757ec681f3Smrg simple_mtx_lock(&smPriv->st_mutex); 57601e04c3fSmrg entry = _mesa_hash_table_insert(smPriv->stfbi_ht, stfbi, stfbi); 5777ec681f3Smrg simple_mtx_unlock(&smPriv->st_mutex); 57801e04c3fSmrg 57901e04c3fSmrg return entry != NULL; 58001e04c3fSmrg} 58101e04c3fSmrg 58201e04c3fSmrg 58301e04c3fSmrgstatic void 58401e04c3fSmrgst_framebuffer_iface_remove(struct st_manager *smapi, 58501e04c3fSmrg struct st_framebuffer_iface *stfbi) 58601e04c3fSmrg{ 58701e04c3fSmrg struct st_manager_private *smPriv = 58801e04c3fSmrg (struct st_manager_private *)smapi->st_manager_private; 58901e04c3fSmrg struct hash_entry *entry; 59001e04c3fSmrg 59101e04c3fSmrg if (!smPriv || !smPriv->stfbi_ht) 59201e04c3fSmrg return; 59301e04c3fSmrg 5947ec681f3Smrg simple_mtx_lock(&smPriv->st_mutex); 59501e04c3fSmrg entry = _mesa_hash_table_search(smPriv->stfbi_ht, stfbi); 59601e04c3fSmrg if (!entry) 59701e04c3fSmrg goto unlock; 59801e04c3fSmrg 59901e04c3fSmrg _mesa_hash_table_remove(smPriv->stfbi_ht, entry); 60001e04c3fSmrg 60101e04c3fSmrgunlock: 6027ec681f3Smrg simple_mtx_unlock(&smPriv->st_mutex); 60301e04c3fSmrg} 60401e04c3fSmrg 60501e04c3fSmrg 60601e04c3fSmrg/** 60701e04c3fSmrg * The framebuffer interface object is no longer valid. 60801e04c3fSmrg * Remove the object from the framebuffer interface hash table. 60901e04c3fSmrg */ 61001e04c3fSmrgstatic void 61101e04c3fSmrgst_api_destroy_drawable(struct st_api *stapi, 61201e04c3fSmrg struct st_framebuffer_iface *stfbi) 61301e04c3fSmrg{ 61401e04c3fSmrg if (!stfbi) 61501e04c3fSmrg return; 61601e04c3fSmrg 61701e04c3fSmrg st_framebuffer_iface_remove(stfbi->state_manager, stfbi); 61801e04c3fSmrg} 61901e04c3fSmrg 62001e04c3fSmrg 62101e04c3fSmrg/** 62201e04c3fSmrg * Purge the winsys buffers list to remove any references to 62301e04c3fSmrg * non-existing framebuffer interface objects. 62401e04c3fSmrg */ 62501e04c3fSmrgstatic void 62601e04c3fSmrgst_framebuffers_purge(struct st_context *st) 62701e04c3fSmrg{ 62801e04c3fSmrg struct st_context_iface *st_iface = &st->iface; 62901e04c3fSmrg struct st_manager *smapi = st_iface->state_manager; 63001e04c3fSmrg struct st_framebuffer *stfb, *next; 63101e04c3fSmrg 63201e04c3fSmrg assert(smapi); 63301e04c3fSmrg 63401e04c3fSmrg LIST_FOR_EACH_ENTRY_SAFE_REV(stfb, next, &st->winsys_buffers, head) { 63501e04c3fSmrg struct st_framebuffer_iface *stfbi = stfb->iface; 63601e04c3fSmrg 63701e04c3fSmrg assert(stfbi); 63801e04c3fSmrg 63901e04c3fSmrg /** 64001e04c3fSmrg * If the corresponding framebuffer interface object no longer exists, 64101e04c3fSmrg * remove the framebuffer object from the context's winsys buffers list, 64201e04c3fSmrg * and unreference the framebuffer object, so its resources can be 64301e04c3fSmrg * deleted. 64401e04c3fSmrg */ 64501e04c3fSmrg if (!st_framebuffer_iface_lookup(smapi, stfbi)) { 6467ec681f3Smrg list_del(&stfb->head); 64701e04c3fSmrg st_framebuffer_reference(&stfb, NULL); 64801e04c3fSmrg } 64901e04c3fSmrg } 65001e04c3fSmrg} 65101e04c3fSmrg 65201e04c3fSmrg 6533464ebd5Sriastradhstatic void 654af69d88dSmrgst_context_flush(struct st_context_iface *stctxi, unsigned flags, 6557ec681f3Smrg struct pipe_fence_handle **fence, 6567ec681f3Smrg void (*before_flush_cb) (void*), 6577ec681f3Smrg void* args) 6583464ebd5Sriastradh{ 6593464ebd5Sriastradh struct st_context *st = (struct st_context *) stctxi; 660af69d88dSmrg unsigned pipe_flags = 0; 6613464ebd5Sriastradh 66201e04c3fSmrg if (flags & ST_FLUSH_END_OF_FRAME) 663af69d88dSmrg pipe_flags |= PIPE_FLUSH_END_OF_FRAME; 66401e04c3fSmrg if (flags & ST_FLUSH_FENCE_FD) 66501e04c3fSmrg pipe_flags |= PIPE_FLUSH_FENCE_FD; 6663464ebd5Sriastradh 6677ec681f3Smrg /* We can do these in any order because FLUSH_VERTICES will also flush 6687ec681f3Smrg * the bitmap cache if there are any unflushed vertices. 6697ec681f3Smrg */ 6707ec681f3Smrg st_flush_bitmap_cache(st); 6717ec681f3Smrg FLUSH_VERTICES(st->ctx, 0, 0); 6727ec681f3Smrg 6737ec681f3Smrg /* Notify the caller that we're ready to flush */ 6747ec681f3Smrg if (before_flush_cb) 6757ec681f3Smrg before_flush_cb(args); 676af69d88dSmrg st_flush(st, fence, pipe_flags); 67701e04c3fSmrg 67801e04c3fSmrg if ((flags & ST_FLUSH_WAIT) && fence && *fence) { 6797ec681f3Smrg st->screen->fence_finish(st->screen, NULL, *fence, 68001e04c3fSmrg PIPE_TIMEOUT_INFINITE); 6817ec681f3Smrg st->screen->fence_reference(st->screen, fence, NULL); 68201e04c3fSmrg } 68301e04c3fSmrg 6843464ebd5Sriastradh if (flags & ST_FLUSH_FRONT) 6853464ebd5Sriastradh st_manager_flush_frontbuffer(st); 68601e04c3fSmrg 68701e04c3fSmrg /* DRI3 changes the framebuffer after SwapBuffers, but we need to invoke 68801e04c3fSmrg * st_manager_validate_framebuffers to notice that. 68901e04c3fSmrg * 69001e04c3fSmrg * Set gfx_shaders_may_be_dirty to invoke st_validate_state in the next 69101e04c3fSmrg * draw call, which will invoke st_manager_validate_framebuffers, but it 69201e04c3fSmrg * won't dirty states if there is no change. 69301e04c3fSmrg */ 69401e04c3fSmrg if (flags & ST_FLUSH_END_OF_FRAME) 69501e04c3fSmrg st->gfx_shaders_may_be_dirty = true; 6963464ebd5Sriastradh} 6973464ebd5Sriastradh 6987ec681f3Smrgstatic bool 6993464ebd5Sriastradhst_context_teximage(struct st_context_iface *stctxi, 700af69d88dSmrg enum st_texture_type tex_type, 701af69d88dSmrg int level, enum pipe_format pipe_format, 7027ec681f3Smrg struct pipe_resource *tex, bool mipmap) 7033464ebd5Sriastradh{ 7043464ebd5Sriastradh struct st_context *st = (struct st_context *) stctxi; 7053464ebd5Sriastradh struct gl_context *ctx = st->ctx; 7063464ebd5Sriastradh struct gl_texture_object *texObj; 7073464ebd5Sriastradh struct gl_texture_image *texImage; 7083464ebd5Sriastradh struct st_texture_object *stObj; 7093464ebd5Sriastradh struct st_texture_image *stImage; 7103464ebd5Sriastradh GLenum internalFormat; 7113464ebd5Sriastradh GLuint width, height, depth; 712af69d88dSmrg GLenum target; 7133464ebd5Sriastradh 714af69d88dSmrg switch (tex_type) { 7153464ebd5Sriastradh case ST_TEXTURE_1D: 7163464ebd5Sriastradh target = GL_TEXTURE_1D; 7173464ebd5Sriastradh break; 7183464ebd5Sriastradh case ST_TEXTURE_2D: 7193464ebd5Sriastradh target = GL_TEXTURE_2D; 7203464ebd5Sriastradh break; 7213464ebd5Sriastradh case ST_TEXTURE_3D: 7223464ebd5Sriastradh target = GL_TEXTURE_3D; 7233464ebd5Sriastradh break; 7243464ebd5Sriastradh case ST_TEXTURE_RECT: 7253464ebd5Sriastradh target = GL_TEXTURE_RECTANGLE_ARB; 7263464ebd5Sriastradh break; 7273464ebd5Sriastradh default: 7283464ebd5Sriastradh return FALSE; 7293464ebd5Sriastradh } 7303464ebd5Sriastradh 731af69d88dSmrg texObj = _mesa_get_current_tex_object(ctx, target); 732af69d88dSmrg 7333464ebd5Sriastradh _mesa_lock_texture(ctx, texObj); 7343464ebd5Sriastradh 7353464ebd5Sriastradh stObj = st_texture_object(texObj); 7363464ebd5Sriastradh /* switch to surface based */ 7373464ebd5Sriastradh if (!stObj->surface_based) { 73801e04c3fSmrg _mesa_clear_texture_object(ctx, texObj, NULL); 7393464ebd5Sriastradh stObj->surface_based = GL_TRUE; 7403464ebd5Sriastradh } 7413464ebd5Sriastradh 7423464ebd5Sriastradh texImage = _mesa_get_tex_image(ctx, texObj, target, level); 7433464ebd5Sriastradh stImage = st_texture_image(texImage); 7443464ebd5Sriastradh if (tex) { 745af69d88dSmrg mesa_format texFormat = st_pipe_format_to_mesa_format(pipe_format); 746af69d88dSmrg 747af69d88dSmrg if (util_format_has_alpha(tex->format)) 7483464ebd5Sriastradh internalFormat = GL_RGBA; 7493464ebd5Sriastradh else 7503464ebd5Sriastradh internalFormat = GL_RGB; 7513464ebd5Sriastradh 752af69d88dSmrg _mesa_init_teximage_fields(ctx, texImage, 7533464ebd5Sriastradh tex->width0, tex->height0, 1, 0, 7543464ebd5Sriastradh internalFormat, texFormat); 7553464ebd5Sriastradh 7563464ebd5Sriastradh width = tex->width0; 7573464ebd5Sriastradh height = tex->height0; 7583464ebd5Sriastradh depth = tex->depth0; 7593464ebd5Sriastradh 7603464ebd5Sriastradh /* grow the image size until we hit level = 0 */ 7613464ebd5Sriastradh while (level > 0) { 7623464ebd5Sriastradh if (width != 1) 7633464ebd5Sriastradh width <<= 1; 7643464ebd5Sriastradh if (height != 1) 7653464ebd5Sriastradh height <<= 1; 7663464ebd5Sriastradh if (depth != 1) 7673464ebd5Sriastradh depth <<= 1; 7683464ebd5Sriastradh level--; 7693464ebd5Sriastradh } 7703464ebd5Sriastradh } 7713464ebd5Sriastradh else { 7723464ebd5Sriastradh _mesa_clear_texture_image(ctx, texImage); 7733464ebd5Sriastradh width = height = depth = 0; 7743464ebd5Sriastradh } 7753464ebd5Sriastradh 77601e04c3fSmrg pipe_resource_reference(&stObj->pt, tex); 77701e04c3fSmrg st_texture_release_all_sampler_views(st, stObj); 7783464ebd5Sriastradh pipe_resource_reference(&stImage->pt, tex); 779af69d88dSmrg stObj->surface_format = pipe_format; 7803464ebd5Sriastradh 78101e04c3fSmrg stObj->needs_validation = true; 78201e04c3fSmrg 783af69d88dSmrg _mesa_dirty_texobj(ctx, texObj); 7843464ebd5Sriastradh _mesa_unlock_texture(ctx, texObj); 78501e04c3fSmrg 7867ec681f3Smrg return true; 7873464ebd5Sriastradh} 7883464ebd5Sriastradh 78901e04c3fSmrg 7903464ebd5Sriastradhstatic void 7913464ebd5Sriastradhst_context_copy(struct st_context_iface *stctxi, 7923464ebd5Sriastradh struct st_context_iface *stsrci, unsigned mask) 7933464ebd5Sriastradh{ 7943464ebd5Sriastradh struct st_context *st = (struct st_context *) stctxi; 7953464ebd5Sriastradh struct st_context *src = (struct st_context *) stsrci; 7963464ebd5Sriastradh 7973464ebd5Sriastradh _mesa_copy_context(src->ctx, st->ctx, mask); 7983464ebd5Sriastradh} 7993464ebd5Sriastradh 80001e04c3fSmrg 8017ec681f3Smrgstatic bool 8023464ebd5Sriastradhst_context_share(struct st_context_iface *stctxi, 8033464ebd5Sriastradh struct st_context_iface *stsrci) 8043464ebd5Sriastradh{ 8053464ebd5Sriastradh struct st_context *st = (struct st_context *) stctxi; 8063464ebd5Sriastradh struct st_context *src = (struct st_context *) stsrci; 8073464ebd5Sriastradh 8083464ebd5Sriastradh return _mesa_share_state(st->ctx, src->ctx); 8093464ebd5Sriastradh} 8103464ebd5Sriastradh 81101e04c3fSmrg 8123464ebd5Sriastradhstatic void 8133464ebd5Sriastradhst_context_destroy(struct st_context_iface *stctxi) 8143464ebd5Sriastradh{ 8153464ebd5Sriastradh struct st_context *st = (struct st_context *) stctxi; 8163464ebd5Sriastradh st_destroy_context(st); 8173464ebd5Sriastradh} 8183464ebd5Sriastradh 81901e04c3fSmrg 82001e04c3fSmrgstatic void 82101e04c3fSmrgst_start_thread(struct st_context_iface *stctxi) 82201e04c3fSmrg{ 82301e04c3fSmrg struct st_context *st = (struct st_context *) stctxi; 82401e04c3fSmrg 82501e04c3fSmrg _mesa_glthread_init(st->ctx); 82601e04c3fSmrg} 82701e04c3fSmrg 82801e04c3fSmrg 82901e04c3fSmrgstatic void 83001e04c3fSmrgst_thread_finish(struct st_context_iface *stctxi) 83101e04c3fSmrg{ 83201e04c3fSmrg struct st_context *st = (struct st_context *) stctxi; 83301e04c3fSmrg 83401e04c3fSmrg _mesa_glthread_finish(st->ctx); 83501e04c3fSmrg} 83601e04c3fSmrg 83701e04c3fSmrg 8387ec681f3Smrgstatic void 8397ec681f3Smrgst_context_invalidate_state(struct st_context_iface *stctxi, 8407ec681f3Smrg unsigned flags) 8417ec681f3Smrg{ 8427ec681f3Smrg struct st_context *st = (struct st_context *) stctxi; 8437ec681f3Smrg 8447ec681f3Smrg if (flags & ST_INVALIDATE_FS_SAMPLER_VIEWS) 8457ec681f3Smrg st->dirty |= ST_NEW_FS_SAMPLER_VIEWS; 8467ec681f3Smrg if (flags & ST_INVALIDATE_FS_CONSTBUF0) 8477ec681f3Smrg st->dirty |= ST_NEW_FS_CONSTANTS; 8487ec681f3Smrg if (flags & ST_INVALIDATE_VS_CONSTBUF0) 8497ec681f3Smrg st->dirty |= ST_NEW_VS_CONSTANTS; 8507ec681f3Smrg if (flags & ST_INVALIDATE_VERTEX_BUFFERS) 8517ec681f3Smrg st->dirty |= ST_NEW_VERTEX_ARRAYS; 8527ec681f3Smrg} 8537ec681f3Smrg 8547ec681f3Smrg 85501e04c3fSmrgstatic void 85601e04c3fSmrgst_manager_destroy(struct st_manager *smapi) 85701e04c3fSmrg{ 85801e04c3fSmrg struct st_manager_private *smPriv = smapi->st_manager_private; 85901e04c3fSmrg 86001e04c3fSmrg if (smPriv && smPriv->stfbi_ht) { 86101e04c3fSmrg _mesa_hash_table_destroy(smPriv->stfbi_ht, NULL); 8627ec681f3Smrg simple_mtx_destroy(&smPriv->st_mutex); 86301e04c3fSmrg free(smPriv); 86401e04c3fSmrg smapi->st_manager_private = NULL; 86501e04c3fSmrg } 86601e04c3fSmrg} 86701e04c3fSmrg 86801e04c3fSmrg 8693464ebd5Sriastradhstatic struct st_context_iface * 8703464ebd5Sriastradhst_api_create_context(struct st_api *stapi, struct st_manager *smapi, 8713464ebd5Sriastradh const struct st_context_attribs *attribs, 872af69d88dSmrg enum st_context_error *error, 8733464ebd5Sriastradh struct st_context_iface *shared_stctxi) 8743464ebd5Sriastradh{ 8753464ebd5Sriastradh struct st_context *shared_ctx = (struct st_context *) shared_stctxi; 8763464ebd5Sriastradh struct st_context *st; 8773464ebd5Sriastradh struct pipe_context *pipe; 8787ec681f3Smrg struct gl_config mode, *mode_ptr = &mode; 8793464ebd5Sriastradh gl_api api; 88001e04c3fSmrg bool no_error = false; 88101e04c3fSmrg unsigned ctx_flags = PIPE_CONTEXT_PREFER_THREADED; 8823464ebd5Sriastradh 8833464ebd5Sriastradh if (!(stapi->profile_mask & (1 << attribs->profile))) 8843464ebd5Sriastradh return NULL; 8853464ebd5Sriastradh 8863464ebd5Sriastradh switch (attribs->profile) { 8873464ebd5Sriastradh case ST_PROFILE_DEFAULT: 888af69d88dSmrg api = API_OPENGL_COMPAT; 8893464ebd5Sriastradh break; 8903464ebd5Sriastradh case ST_PROFILE_OPENGL_ES1: 8913464ebd5Sriastradh api = API_OPENGLES; 8923464ebd5Sriastradh break; 8933464ebd5Sriastradh case ST_PROFILE_OPENGL_ES2: 8943464ebd5Sriastradh api = API_OPENGLES2; 8953464ebd5Sriastradh break; 8963464ebd5Sriastradh case ST_PROFILE_OPENGL_CORE: 897af69d88dSmrg api = API_OPENGL_CORE; 898af69d88dSmrg break; 8993464ebd5Sriastradh default: 900af69d88dSmrg *error = ST_CONTEXT_ERROR_BAD_API; 9013464ebd5Sriastradh return NULL; 9023464ebd5Sriastradh } 9033464ebd5Sriastradh 9047ec681f3Smrg _mesa_initialize(); 9057ec681f3Smrg 90601e04c3fSmrg /* Create a hash table for the framebuffer interface objects 90701e04c3fSmrg * if it has not been created for this st manager. 90801e04c3fSmrg */ 90901e04c3fSmrg if (smapi->st_manager_private == NULL) { 91001e04c3fSmrg struct st_manager_private *smPriv; 91101e04c3fSmrg 91201e04c3fSmrg smPriv = CALLOC_STRUCT(st_manager_private); 9137ec681f3Smrg simple_mtx_init(&smPriv->st_mutex, mtx_plain); 91401e04c3fSmrg smPriv->stfbi_ht = _mesa_hash_table_create(NULL, 91501e04c3fSmrg st_framebuffer_iface_hash, 91601e04c3fSmrg st_framebuffer_iface_equal); 91701e04c3fSmrg smapi->st_manager_private = smPriv; 91801e04c3fSmrg smapi->destroy = st_manager_destroy; 91901e04c3fSmrg } 92001e04c3fSmrg 92101e04c3fSmrg if (attribs->flags & ST_CONTEXT_FLAG_ROBUST_ACCESS) 92201e04c3fSmrg ctx_flags |= PIPE_CONTEXT_ROBUST_BUFFER_ACCESS; 92301e04c3fSmrg 92401e04c3fSmrg if (attribs->flags & ST_CONTEXT_FLAG_NO_ERROR) 92501e04c3fSmrg no_error = true; 92601e04c3fSmrg 92701e04c3fSmrg if (attribs->flags & ST_CONTEXT_FLAG_LOW_PRIORITY) 92801e04c3fSmrg ctx_flags |= PIPE_CONTEXT_LOW_PRIORITY; 92901e04c3fSmrg else if (attribs->flags & ST_CONTEXT_FLAG_HIGH_PRIORITY) 93001e04c3fSmrg ctx_flags |= PIPE_CONTEXT_HIGH_PRIORITY; 93101e04c3fSmrg 932b9abf16eSmaya if (attribs->flags & ST_CONTEXT_FLAG_RESET_NOTIFICATION_ENABLED) 933b9abf16eSmaya ctx_flags |= PIPE_CONTEXT_LOSE_CONTEXT_ON_RESET; 934b9abf16eSmaya 93501e04c3fSmrg pipe = smapi->screen->context_create(smapi->screen, NULL, ctx_flags); 936af69d88dSmrg if (!pipe) { 937af69d88dSmrg *error = ST_CONTEXT_ERROR_NO_MEMORY; 9383464ebd5Sriastradh return NULL; 939af69d88dSmrg } 9403464ebd5Sriastradh 9413464ebd5Sriastradh st_visual_to_context_mode(&attribs->visual, &mode); 9427ec681f3Smrg if (attribs->visual.color_format == PIPE_FORMAT_NONE) 94301e04c3fSmrg mode_ptr = NULL; 94401e04c3fSmrg st = st_create_context(api, pipe, mode_ptr, shared_ctx, 9457ec681f3Smrg &attribs->options, no_error, 9467ec681f3Smrg !!smapi->validate_egl_image); 9473464ebd5Sriastradh if (!st) { 948af69d88dSmrg *error = ST_CONTEXT_ERROR_NO_MEMORY; 9493464ebd5Sriastradh pipe->destroy(pipe); 9503464ebd5Sriastradh return NULL; 9513464ebd5Sriastradh } 9523464ebd5Sriastradh 95301e04c3fSmrg if (attribs->flags & ST_CONTEXT_FLAG_DEBUG) { 954af69d88dSmrg if (!_mesa_set_debug_state_int(st->ctx, GL_DEBUG_OUTPUT, GL_TRUE)) { 955af69d88dSmrg *error = ST_CONTEXT_ERROR_NO_MEMORY; 956af69d88dSmrg return NULL; 957af69d88dSmrg } 95801e04c3fSmrg 959af69d88dSmrg st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_DEBUG_BIT; 960af69d88dSmrg } 961af69d88dSmrg 96201e04c3fSmrg if (st->ctx->Const.ContextFlags & GL_CONTEXT_FLAG_DEBUG_BIT) { 96301e04c3fSmrg st_update_debug_callback(st); 96401e04c3fSmrg } 96501e04c3fSmrg 966af69d88dSmrg if (attribs->flags & ST_CONTEXT_FLAG_FORWARD_COMPATIBLE) 967af69d88dSmrg st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT; 96801e04c3fSmrg if (attribs->flags & ST_CONTEXT_FLAG_ROBUST_ACCESS) { 96901e04c3fSmrg st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB; 97001e04c3fSmrg st->ctx->Const.RobustAccess = GL_TRUE; 97101e04c3fSmrg } 97201e04c3fSmrg if (attribs->flags & ST_CONTEXT_FLAG_RESET_NOTIFICATION_ENABLED) { 97301e04c3fSmrg st->ctx->Const.ResetStrategy = GL_LOSE_CONTEXT_ON_RESET_ARB; 97401e04c3fSmrg st_install_device_reset_callback(st); 97501e04c3fSmrg } 97601e04c3fSmrg 97701e04c3fSmrg if (attribs->flags & ST_CONTEXT_FLAG_RELEASE_NONE) 97801e04c3fSmrg st->ctx->Const.ContextReleaseBehavior = GL_NONE; 979af69d88dSmrg 9803464ebd5Sriastradh /* need to perform version check */ 9813464ebd5Sriastradh if (attribs->major > 1 || attribs->minor > 0) { 982af69d88dSmrg /* Is the actual version less than the requested version? 983af69d88dSmrg */ 98401e04c3fSmrg if (st->ctx->Version < attribs->major * 10U + attribs->minor) { 98501e04c3fSmrg *error = ST_CONTEXT_ERROR_BAD_VERSION; 9863464ebd5Sriastradh st_destroy_context(st); 9873464ebd5Sriastradh return NULL; 9883464ebd5Sriastradh } 9893464ebd5Sriastradh } 9903464ebd5Sriastradh 9917ec681f3Smrg st->can_scissor_clear = !!st->screen->get_param(st->screen, PIPE_CAP_CLEAR_SCISSORED); 9927ec681f3Smrg 9933464ebd5Sriastradh st->invalidate_on_gl_viewport = 9943464ebd5Sriastradh smapi->get_param(smapi, ST_MANAGER_BROKEN_INVALIDATE); 9953464ebd5Sriastradh 9963464ebd5Sriastradh st->iface.destroy = st_context_destroy; 9973464ebd5Sriastradh st->iface.flush = st_context_flush; 9983464ebd5Sriastradh st->iface.teximage = st_context_teximage; 9993464ebd5Sriastradh st->iface.copy = st_context_copy; 10003464ebd5Sriastradh st->iface.share = st_context_share; 100101e04c3fSmrg st->iface.start_thread = st_start_thread; 100201e04c3fSmrg st->iface.thread_finish = st_thread_finish; 10037ec681f3Smrg st->iface.invalidate_state = st_context_invalidate_state; 10043464ebd5Sriastradh st->iface.st_context_private = (void *) smapi; 1005af69d88dSmrg st->iface.cso_context = st->cso_context; 1006af69d88dSmrg st->iface.pipe = st->pipe; 100701e04c3fSmrg st->iface.state_manager = smapi; 10083464ebd5Sriastradh 10097ec681f3Smrg if (st->ctx->IntelBlackholeRender && 10107ec681f3Smrg st->screen->get_param(st->screen, PIPE_CAP_FRONTEND_NOOP)) 10117ec681f3Smrg st->pipe->set_frontend_noop(st->pipe, st->ctx->IntelBlackholeRender); 10127ec681f3Smrg 1013af69d88dSmrg *error = ST_CONTEXT_SUCCESS; 10143464ebd5Sriastradh return &st->iface; 10153464ebd5Sriastradh} 10163464ebd5Sriastradh 101701e04c3fSmrg 10183464ebd5Sriastradhstatic struct st_context_iface * 10193464ebd5Sriastradhst_api_get_current(struct st_api *stapi) 10203464ebd5Sriastradh{ 10213464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 102201e04c3fSmrg struct st_context *st = ctx ? ctx->st : NULL; 10233464ebd5Sriastradh 102401e04c3fSmrg return st ? &st->iface : NULL; 10253464ebd5Sriastradh} 10263464ebd5Sriastradh 102701e04c3fSmrg 10283464ebd5Sriastradhstatic struct st_framebuffer * 1029af69d88dSmrgst_framebuffer_reuse_or_create(struct st_context *st, 1030af69d88dSmrg struct gl_framebuffer *fb, 10313464ebd5Sriastradh struct st_framebuffer_iface *stfbi) 10323464ebd5Sriastradh{ 103301e04c3fSmrg struct st_framebuffer *cur = NULL, *stfb = NULL; 103401e04c3fSmrg 103501e04c3fSmrg if (!stfbi) 103601e04c3fSmrg return NULL; 10373464ebd5Sriastradh 103801e04c3fSmrg /* Check if there is already a framebuffer object for the specified 103901e04c3fSmrg * framebuffer interface in this context. If there is one, use it. 104001e04c3fSmrg */ 104101e04c3fSmrg LIST_FOR_EACH_ENTRY(cur, &st->winsys_buffers, head) { 104201e04c3fSmrg if (cur->iface_ID == stfbi->ID) { 104301e04c3fSmrg st_framebuffer_reference(&stfb, cur); 104401e04c3fSmrg break; 104501e04c3fSmrg } 10463464ebd5Sriastradh } 104701e04c3fSmrg 104801e04c3fSmrg /* If there is not already a framebuffer object, create one */ 104901e04c3fSmrg if (stfb == NULL) { 105001e04c3fSmrg cur = st_framebuffer_create(st, stfbi); 105101e04c3fSmrg 105201e04c3fSmrg if (cur) { 105301e04c3fSmrg /* add the referenced framebuffer interface object to 105401e04c3fSmrg * the framebuffer interface object hash table. 105501e04c3fSmrg */ 105601e04c3fSmrg if (!st_framebuffer_iface_insert(stfbi->state_manager, stfbi)) { 105701e04c3fSmrg st_framebuffer_reference(&cur, NULL); 105801e04c3fSmrg return NULL; 105901e04c3fSmrg } 106001e04c3fSmrg 106101e04c3fSmrg /* add to the context's winsys buffers list */ 10627ec681f3Smrg list_add(&cur->head, &st->winsys_buffers); 106301e04c3fSmrg 106401e04c3fSmrg st_framebuffer_reference(&stfb, cur); 106501e04c3fSmrg } 10663464ebd5Sriastradh } 10673464ebd5Sriastradh 10683464ebd5Sriastradh return stfb; 10693464ebd5Sriastradh} 10703464ebd5Sriastradh 107101e04c3fSmrg 10727ec681f3Smrgstatic bool 10733464ebd5Sriastradhst_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi, 10743464ebd5Sriastradh struct st_framebuffer_iface *stdrawi, 10753464ebd5Sriastradh struct st_framebuffer_iface *streadi) 10763464ebd5Sriastradh{ 10773464ebd5Sriastradh struct st_context *st = (struct st_context *) stctxi; 10783464ebd5Sriastradh struct st_framebuffer *stdraw, *stread; 10797ec681f3Smrg bool ret; 10803464ebd5Sriastradh 10813464ebd5Sriastradh if (st) { 10823464ebd5Sriastradh /* reuse or create the draw fb */ 1083af69d88dSmrg stdraw = st_framebuffer_reuse_or_create(st, 1084af69d88dSmrg st->ctx->WinSysDrawBuffer, stdrawi); 10853464ebd5Sriastradh if (streadi != stdrawi) { 10863464ebd5Sriastradh /* do the same for the read fb */ 1087af69d88dSmrg stread = st_framebuffer_reuse_or_create(st, 1088af69d88dSmrg st->ctx->WinSysReadBuffer, streadi); 10893464ebd5Sriastradh } 10903464ebd5Sriastradh else { 10913464ebd5Sriastradh stread = NULL; 10923464ebd5Sriastradh /* reuse the draw fb for the read fb */ 10933464ebd5Sriastradh if (stdraw) 10943464ebd5Sriastradh st_framebuffer_reference(&stread, stdraw); 10953464ebd5Sriastradh } 10963464ebd5Sriastradh 10977ec681f3Smrg /* If framebuffers were asked for, we'd better have allocated them */ 10987ec681f3Smrg if ((stdrawi && !stdraw) || (streadi && !stread)) 10997ec681f3Smrg return false; 11007ec681f3Smrg 11013464ebd5Sriastradh if (stdraw && stread) { 11023464ebd5Sriastradh st_framebuffer_validate(stdraw, st); 11033464ebd5Sriastradh if (stread != stdraw) 11043464ebd5Sriastradh st_framebuffer_validate(stread, st); 11053464ebd5Sriastradh 11063464ebd5Sriastradh ret = _mesa_make_current(st->ctx, &stdraw->Base, &stread->Base); 1107af69d88dSmrg 1108af69d88dSmrg st->draw_stamp = stdraw->stamp - 1; 1109af69d88dSmrg st->read_stamp = stread->stamp - 1; 1110af69d88dSmrg st_context_validate(st, stdraw, stread); 11113464ebd5Sriastradh } 11123464ebd5Sriastradh else { 11133464ebd5Sriastradh struct gl_framebuffer *incomplete = _mesa_get_incomplete_framebuffer(); 11143464ebd5Sriastradh ret = _mesa_make_current(st->ctx, incomplete, incomplete); 11153464ebd5Sriastradh } 11163464ebd5Sriastradh 11173464ebd5Sriastradh st_framebuffer_reference(&stdraw, NULL); 11183464ebd5Sriastradh st_framebuffer_reference(&stread, NULL); 111901e04c3fSmrg 112001e04c3fSmrg /* Purge the context's winsys_buffers list in case any 112101e04c3fSmrg * of the referenced drawables no longer exist. 112201e04c3fSmrg */ 112301e04c3fSmrg st_framebuffers_purge(st); 11243464ebd5Sriastradh } 11253464ebd5Sriastradh else { 112601e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 112701e04c3fSmrg 1128b9abf16eSmaya if (ctx) { 1129b9abf16eSmaya /* Before releasing the context, release its associated 1130b9abf16eSmaya * winsys buffers first. Then purge the context's winsys buffers list 1131b9abf16eSmaya * to free the resources of any winsys buffers that no longer have 1132b9abf16eSmaya * an existing drawable. 1133b9abf16eSmaya */ 1134b9abf16eSmaya ret = _mesa_make_current(ctx, NULL, NULL); 113501e04c3fSmrg st_framebuffers_purge(ctx->st); 1136b9abf16eSmaya } 1137b9abf16eSmaya 1138b9abf16eSmaya ret = _mesa_make_current(NULL, NULL, NULL); 11393464ebd5Sriastradh } 11403464ebd5Sriastradh 11413464ebd5Sriastradh return ret; 11423464ebd5Sriastradh} 11433464ebd5Sriastradh 11443464ebd5Sriastradh 11453464ebd5Sriastradhstatic void 11463464ebd5Sriastradhst_api_destroy(struct st_api *stapi) 11473464ebd5Sriastradh{ 11483464ebd5Sriastradh} 11493464ebd5Sriastradh 115001e04c3fSmrg 11513464ebd5Sriastradh/** 11523464ebd5Sriastradh * Flush the front buffer if the current context renders to the front buffer. 11533464ebd5Sriastradh */ 11543464ebd5Sriastradhvoid 11553464ebd5Sriastradhst_manager_flush_frontbuffer(struct st_context *st) 11563464ebd5Sriastradh{ 11573464ebd5Sriastradh struct st_framebuffer *stfb = st_ws_framebuffer(st->ctx->DrawBuffer); 11583464ebd5Sriastradh struct st_renderbuffer *strb = NULL; 11593464ebd5Sriastradh 1160b9abf16eSmaya if (!stfb) 1161b9abf16eSmaya return; 1162b9abf16eSmaya 1163b9abf16eSmaya /* If the context uses a doublebuffered visual, but the buffer is 1164b9abf16eSmaya * single-buffered, guess that it's a pbuffer, which doesn't need 1165b9abf16eSmaya * flushing. 1166b9abf16eSmaya */ 1167b9abf16eSmaya if (st->ctx->Visual.doubleBufferMode && 1168b9abf16eSmaya !stfb->Base.Visual.doubleBufferMode) 1169b9abf16eSmaya return; 1170b9abf16eSmaya 11717ec681f3Smrg /* Check front buffer used at the GL API level. */ 11727ec681f3Smrg enum st_attachment_type statt = ST_ATTACHMENT_FRONT_LEFT; 1173b9abf16eSmaya strb = st_renderbuffer(stfb->Base.Attachment[BUFFER_FRONT_LEFT]. 1174b9abf16eSmaya Renderbuffer); 11757ec681f3Smrg if (!strb) { 11767ec681f3Smrg /* Check back buffer redirected by EGL_KHR_mutable_render_buffer. */ 11777ec681f3Smrg statt = ST_ATTACHMENT_BACK_LEFT; 11787ec681f3Smrg strb = st_renderbuffer(stfb->Base.Attachment[BUFFER_BACK_LEFT]. 11797ec681f3Smrg Renderbuffer); 11807ec681f3Smrg } 11813464ebd5Sriastradh 118201e04c3fSmrg /* Do we have a front color buffer and has it been drawn to since last 118301e04c3fSmrg * frontbuffer flush? 118401e04c3fSmrg */ 11857ec681f3Smrg if (strb && strb->defined && 11867ec681f3Smrg stfb->iface->flush_front(&st->iface, stfb->iface, statt)) { 118701e04c3fSmrg strb->defined = GL_FALSE; 11883464ebd5Sriastradh 118901e04c3fSmrg /* Trigger an update of strb->defined on next draw */ 119001e04c3fSmrg st->dirty |= ST_NEW_FB_STATE; 119101e04c3fSmrg } 11923464ebd5Sriastradh} 11933464ebd5Sriastradh 119401e04c3fSmrg 11953464ebd5Sriastradh/** 11963464ebd5Sriastradh * Re-validate the framebuffers. 11973464ebd5Sriastradh */ 11983464ebd5Sriastradhvoid 11993464ebd5Sriastradhst_manager_validate_framebuffers(struct st_context *st) 12003464ebd5Sriastradh{ 12013464ebd5Sriastradh struct st_framebuffer *stdraw = st_ws_framebuffer(st->ctx->DrawBuffer); 12023464ebd5Sriastradh struct st_framebuffer *stread = st_ws_framebuffer(st->ctx->ReadBuffer); 12033464ebd5Sriastradh 12043464ebd5Sriastradh if (stdraw) 12053464ebd5Sriastradh st_framebuffer_validate(stdraw, st); 12063464ebd5Sriastradh if (stread && stread != stdraw) 12073464ebd5Sriastradh st_framebuffer_validate(stread, st); 1208af69d88dSmrg 1209af69d88dSmrg st_context_validate(st, stdraw, stread); 12103464ebd5Sriastradh} 12113464ebd5Sriastradh 121201e04c3fSmrg 121301e04c3fSmrg/** 121401e04c3fSmrg * Flush any outstanding swapbuffers on the current draw framebuffer. 121501e04c3fSmrg */ 121601e04c3fSmrgvoid 121701e04c3fSmrgst_manager_flush_swapbuffers(void) 121801e04c3fSmrg{ 121901e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 122001e04c3fSmrg struct st_context *st = (ctx) ? ctx->st : NULL; 122101e04c3fSmrg struct st_framebuffer *stfb; 122201e04c3fSmrg 122301e04c3fSmrg if (!st) 122401e04c3fSmrg return; 122501e04c3fSmrg 122601e04c3fSmrg stfb = st_ws_framebuffer(ctx->DrawBuffer); 122701e04c3fSmrg if (!stfb || !stfb->iface->flush_swapbuffers) 122801e04c3fSmrg return; 122901e04c3fSmrg 123001e04c3fSmrg stfb->iface->flush_swapbuffers(&st->iface, stfb->iface); 123101e04c3fSmrg} 123201e04c3fSmrg 123301e04c3fSmrg 12343464ebd5Sriastradh/** 123501e04c3fSmrg * Add a color renderbuffer on demand. The FBO must correspond to a window, 123601e04c3fSmrg * not a user-created FBO. 12373464ebd5Sriastradh */ 12387ec681f3Smrgbool 12393464ebd5Sriastradhst_manager_add_color_renderbuffer(struct st_context *st, 12403464ebd5Sriastradh struct gl_framebuffer *fb, 12413464ebd5Sriastradh gl_buffer_index idx) 12423464ebd5Sriastradh{ 12433464ebd5Sriastradh struct st_framebuffer *stfb = st_ws_framebuffer(fb); 12443464ebd5Sriastradh 12453464ebd5Sriastradh /* FBO */ 12463464ebd5Sriastradh if (!stfb) 12477ec681f3Smrg return false; 12483464ebd5Sriastradh 124901e04c3fSmrg assert(_mesa_is_winsys_fbo(fb)); 125001e04c3fSmrg 12513464ebd5Sriastradh if (stfb->Base.Attachment[idx].Renderbuffer) 12527ec681f3Smrg return true; 12533464ebd5Sriastradh 12543464ebd5Sriastradh switch (idx) { 12553464ebd5Sriastradh case BUFFER_FRONT_LEFT: 12563464ebd5Sriastradh case BUFFER_BACK_LEFT: 12573464ebd5Sriastradh case BUFFER_FRONT_RIGHT: 12583464ebd5Sriastradh case BUFFER_BACK_RIGHT: 12593464ebd5Sriastradh break; 12603464ebd5Sriastradh default: 12617ec681f3Smrg return false; 12623464ebd5Sriastradh } 12633464ebd5Sriastradh 1264b9abf16eSmaya if (!st_framebuffer_add_renderbuffer(stfb, idx, 1265b9abf16eSmaya stfb->Base.Visual.sRGBCapable)) 12667ec681f3Smrg return false; 12673464ebd5Sriastradh 12683464ebd5Sriastradh st_framebuffer_update_attachments(stfb); 1269af69d88dSmrg 1270af69d88dSmrg /* 12717ec681f3Smrg * Force a call to the frontend manager to validate the 1272af69d88dSmrg * new renderbuffer. It might be that there is a window system 1273af69d88dSmrg * renderbuffer available. 1274af69d88dSmrg */ 127501e04c3fSmrg if (stfb->iface) 1276af69d88dSmrg stfb->iface_stamp = p_atomic_read(&stfb->iface->stamp) - 1; 1277af69d88dSmrg 127801e04c3fSmrg st_invalidate_buffers(st); 12793464ebd5Sriastradh 12807ec681f3Smrg return true; 12813464ebd5Sriastradh} 12823464ebd5Sriastradh 128301e04c3fSmrg 128401e04c3fSmrgstatic unsigned 128501e04c3fSmrgget_version(struct pipe_screen *screen, 128601e04c3fSmrg struct st_config_options *options, gl_api api) 1287af69d88dSmrg{ 1288af69d88dSmrg struct gl_constants consts = {0}; 1289af69d88dSmrg struct gl_extensions extensions = {0}; 1290af69d88dSmrg GLuint version; 1291af69d88dSmrg 129201e04c3fSmrg if (_mesa_override_gl_version_contextless(&consts, &api, &version)) { 1293af69d88dSmrg return version; 1294af69d88dSmrg } 1295af69d88dSmrg 1296af69d88dSmrg _mesa_init_constants(&consts, api); 1297af69d88dSmrg _mesa_init_extensions(&extensions); 1298af69d88dSmrg 1299b9abf16eSmaya st_init_limits(screen, &consts, &extensions); 130001e04c3fSmrg st_init_extensions(screen, &consts, &extensions, options, api); 13017ec681f3Smrg version = _mesa_get_version(&extensions, &consts, api); 13027ec681f3Smrg free(consts.SpirVExtensions); 13037ec681f3Smrg return version; 1304af69d88dSmrg} 1305af69d88dSmrg 130601e04c3fSmrg 1307af69d88dSmrgstatic void 1308af69d88dSmrgst_api_query_versions(struct st_api *stapi, struct st_manager *sm, 1309af69d88dSmrg struct st_config_options *options, 1310af69d88dSmrg int *gl_core_version, 1311af69d88dSmrg int *gl_compat_version, 1312af69d88dSmrg int *gl_es1_version, 1313af69d88dSmrg int *gl_es2_version) 1314af69d88dSmrg{ 1315af69d88dSmrg *gl_core_version = get_version(sm->screen, options, API_OPENGL_CORE); 1316af69d88dSmrg *gl_compat_version = get_version(sm->screen, options, API_OPENGL_COMPAT); 1317af69d88dSmrg *gl_es1_version = get_version(sm->screen, options, API_OPENGLES); 1318af69d88dSmrg *gl_es2_version = get_version(sm->screen, options, API_OPENGLES2); 1319af69d88dSmrg} 1320af69d88dSmrg 132101e04c3fSmrg 13223464ebd5Sriastradhstatic const struct st_api st_gl_api = { 132301e04c3fSmrg .name = "Mesa " PACKAGE_VERSION, 132401e04c3fSmrg .api = ST_API_OPENGL, 132501e04c3fSmrg .profile_mask = ST_PROFILE_DEFAULT_MASK | 132601e04c3fSmrg ST_PROFILE_OPENGL_CORE_MASK | 132701e04c3fSmrg ST_PROFILE_OPENGL_ES1_MASK | 132801e04c3fSmrg ST_PROFILE_OPENGL_ES2_MASK | 132901e04c3fSmrg 0, 133001e04c3fSmrg .feature_mask = ST_API_FEATURE_MS_VISUALS_MASK, 133101e04c3fSmrg .destroy = st_api_destroy, 133201e04c3fSmrg .query_versions = st_api_query_versions, 133301e04c3fSmrg .create_context = st_api_create_context, 133401e04c3fSmrg .make_current = st_api_make_current, 133501e04c3fSmrg .get_current = st_api_get_current, 133601e04c3fSmrg .destroy_drawable = st_api_destroy_drawable, 13373464ebd5Sriastradh}; 13383464ebd5Sriastradh 133901e04c3fSmrg 13403464ebd5Sriastradhstruct st_api * 13413464ebd5Sriastradhst_gl_api_create(void) 13423464ebd5Sriastradh{ 13433464ebd5Sriastradh return (struct st_api *) &st_gl_api; 13443464ebd5Sriastradh} 1345