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