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