• 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/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 
826 
827 static void
st_thread_finish(struct st_context_iface * stctxi)828 st_thread_finish(struct st_context_iface *stctxi)
829 {
830    struct st_context *st = (struct st_context *) stctxi;
831 
832    _mesa_glthread_finish(st->ctx);
833 }
834 
835 
836 static void
st_manager_destroy(struct st_manager * smapi)837 st_manager_destroy(struct st_manager *smapi)
838 {
839    struct st_manager_private *smPriv = smapi->st_manager_private;
840 
841    if (smPriv && smPriv->stfbi_ht) {
842       _mesa_hash_table_destroy(smPriv->stfbi_ht, NULL);
843       simple_mtx_destroy(&smPriv->st_mutex);
844       free(smPriv);
845       smapi->st_manager_private = NULL;
846    }
847 }
848 
849 
850 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)851 st_api_create_context(struct st_api *stapi, struct st_manager *smapi,
852                       const struct st_context_attribs *attribs,
853                       enum st_context_error *error,
854                       struct st_context_iface *shared_stctxi)
855 {
856    struct st_context *shared_ctx = (struct st_context *) shared_stctxi;
857    struct st_context *st;
858    struct pipe_context *pipe;
859    struct gl_config* mode_ptr;
860    struct gl_config mode;
861    gl_api api;
862    bool no_error = false;
863    unsigned ctx_flags = PIPE_CONTEXT_PREFER_THREADED;
864 
865    if (!(stapi->profile_mask & (1 << attribs->profile)))
866       return NULL;
867 
868    switch (attribs->profile) {
869    case ST_PROFILE_DEFAULT:
870       api = API_OPENGL_COMPAT;
871       break;
872    case ST_PROFILE_OPENGL_ES1:
873       api = API_OPENGLES;
874       break;
875    case ST_PROFILE_OPENGL_ES2:
876       api = API_OPENGLES2;
877       break;
878    case ST_PROFILE_OPENGL_CORE:
879       api = API_OPENGL_CORE;
880       break;
881    default:
882       *error = ST_CONTEXT_ERROR_BAD_API;
883       return NULL;
884    }
885 
886    _mesa_initialize();
887 
888    /* Create a hash table for the framebuffer interface objects
889     * if it has not been created for this st manager.
890     */
891    if (smapi->st_manager_private == NULL) {
892       struct st_manager_private *smPriv;
893 
894       smPriv = CALLOC_STRUCT(st_manager_private);
895       simple_mtx_init(&smPriv->st_mutex, mtx_plain);
896       smPriv->stfbi_ht = _mesa_hash_table_create(NULL,
897                                                  st_framebuffer_iface_hash,
898                                                  st_framebuffer_iface_equal);
899       smapi->st_manager_private = smPriv;
900       smapi->destroy = st_manager_destroy;
901    }
902 
903    if (attribs->flags & ST_CONTEXT_FLAG_ROBUST_ACCESS)
904       ctx_flags |= PIPE_CONTEXT_ROBUST_BUFFER_ACCESS;
905 
906    if (attribs->flags & ST_CONTEXT_FLAG_NO_ERROR)
907       no_error = true;
908 
909    if (attribs->flags & ST_CONTEXT_FLAG_LOW_PRIORITY)
910       ctx_flags |= PIPE_CONTEXT_LOW_PRIORITY;
911    else if (attribs->flags & ST_CONTEXT_FLAG_HIGH_PRIORITY)
912       ctx_flags |= PIPE_CONTEXT_HIGH_PRIORITY;
913 
914    if (attribs->flags & ST_CONTEXT_FLAG_RESET_NOTIFICATION_ENABLED)
915       ctx_flags |= PIPE_CONTEXT_LOSE_CONTEXT_ON_RESET;
916 
917    pipe = smapi->screen->context_create(smapi->screen, NULL, ctx_flags);
918    if (!pipe) {
919       *error = ST_CONTEXT_ERROR_NO_MEMORY;
920       return NULL;
921    }
922 
923    st_visual_to_context_mode(&attribs->visual, &mode);
924 
925    if (attribs->visual.no_config)
926       mode_ptr = NULL;
927    else
928       mode_ptr = &mode;
929 
930    st = st_create_context(api, pipe, mode_ptr, shared_ctx,
931                           &attribs->options, no_error);
932    if (!st) {
933       *error = ST_CONTEXT_ERROR_NO_MEMORY;
934       pipe->destroy(pipe);
935       return NULL;
936    }
937 
938    if (attribs->flags & ST_CONTEXT_FLAG_DEBUG) {
939       if (!_mesa_set_debug_state_int(st->ctx, GL_DEBUG_OUTPUT, GL_TRUE)) {
940          *error = ST_CONTEXT_ERROR_NO_MEMORY;
941          return NULL;
942       }
943 
944       st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_DEBUG_BIT;
945    }
946 
947    if (st->ctx->Const.ContextFlags & GL_CONTEXT_FLAG_DEBUG_BIT) {
948       st_update_debug_callback(st);
949    }
950 
951    if (attribs->flags & ST_CONTEXT_FLAG_FORWARD_COMPATIBLE)
952       st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT;
953    if (attribs->flags & ST_CONTEXT_FLAG_ROBUST_ACCESS) {
954       st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB;
955       st->ctx->Const.RobustAccess = GL_TRUE;
956    }
957    if (attribs->flags & ST_CONTEXT_FLAG_RESET_NOTIFICATION_ENABLED) {
958       st->ctx->Const.ResetStrategy = GL_LOSE_CONTEXT_ON_RESET_ARB;
959       st_install_device_reset_callback(st);
960    }
961 
962    if (attribs->flags & ST_CONTEXT_FLAG_RELEASE_NONE)
963        st->ctx->Const.ContextReleaseBehavior = GL_NONE;
964 
965    /* need to perform version check */
966    if (attribs->major > 1 || attribs->minor > 0) {
967       /* Is the actual version less than the requested version?
968        */
969       if (st->ctx->Version < attribs->major * 10U + attribs->minor) {
970          *error = ST_CONTEXT_ERROR_BAD_VERSION;
971          st_destroy_context(st);
972          return NULL;
973       }
974    }
975 
976    st->can_scissor_clear = !!st->pipe->screen->get_param(st->pipe->screen, PIPE_CAP_CLEAR_SCISSORED);
977 
978    st->invalidate_on_gl_viewport =
979       smapi->get_param(smapi, ST_MANAGER_BROKEN_INVALIDATE);
980 
981    st->iface.destroy = st_context_destroy;
982    st->iface.flush = st_context_flush;
983    st->iface.teximage = st_context_teximage;
984    st->iface.copy = st_context_copy;
985    st->iface.share = st_context_share;
986    st->iface.start_thread = st_start_thread;
987    st->iface.thread_finish = st_thread_finish;
988    st->iface.st_context_private = (void *) smapi;
989    st->iface.cso_context = st->cso_context;
990    st->iface.pipe = st->pipe;
991    st->iface.state_manager = smapi;
992 
993    *error = ST_CONTEXT_SUCCESS;
994    return &st->iface;
995 }
996 
997 
998 static struct st_context_iface *
st_api_get_current(struct st_api * stapi)999 st_api_get_current(struct st_api *stapi)
1000 {
1001    GET_CURRENT_CONTEXT(ctx);
1002    struct st_context *st = ctx ? ctx->st : NULL;
1003 
1004    return st ? &st->iface : NULL;
1005 }
1006 
1007 
1008 static struct st_framebuffer *
st_framebuffer_reuse_or_create(struct st_context * st,struct gl_framebuffer * fb,struct st_framebuffer_iface * stfbi)1009 st_framebuffer_reuse_or_create(struct st_context *st,
1010                                struct gl_framebuffer *fb,
1011                                struct st_framebuffer_iface *stfbi)
1012 {
1013    struct st_framebuffer *cur = NULL, *stfb = NULL;
1014 
1015    if (!stfbi)
1016       return NULL;
1017 
1018    /* Check if there is already a framebuffer object for the specified
1019     * framebuffer interface in this context. If there is one, use it.
1020     */
1021    LIST_FOR_EACH_ENTRY(cur, &st->winsys_buffers, head) {
1022       if (cur->iface_ID == stfbi->ID) {
1023          st_framebuffer_reference(&stfb, cur);
1024          break;
1025       }
1026    }
1027 
1028    /* If there is not already a framebuffer object, create one */
1029    if (stfb == NULL) {
1030       cur = st_framebuffer_create(st, stfbi);
1031 
1032       if (cur) {
1033          /* add the referenced framebuffer interface object to
1034           * the framebuffer interface object hash table.
1035           */
1036          if (!st_framebuffer_iface_insert(stfbi->state_manager, stfbi)) {
1037             st_framebuffer_reference(&cur, NULL);
1038             return NULL;
1039          }
1040 
1041          /* add to the context's winsys buffers list */
1042          list_add(&cur->head, &st->winsys_buffers);
1043 
1044          st_framebuffer_reference(&stfb, cur);
1045       }
1046    }
1047 
1048    return stfb;
1049 }
1050 
1051 
1052 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)1053 st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi,
1054                     struct st_framebuffer_iface *stdrawi,
1055                     struct st_framebuffer_iface *streadi)
1056 {
1057    struct st_context *st = (struct st_context *) stctxi;
1058    struct st_framebuffer *stdraw, *stread;
1059    bool ret;
1060 
1061    if (st) {
1062       /* reuse or create the draw fb */
1063       stdraw = st_framebuffer_reuse_or_create(st,
1064             st->ctx->WinSysDrawBuffer, stdrawi);
1065       if (streadi != stdrawi) {
1066          /* do the same for the read fb */
1067          stread = st_framebuffer_reuse_or_create(st,
1068                st->ctx->WinSysReadBuffer, streadi);
1069       }
1070       else {
1071          stread = NULL;
1072          /* reuse the draw fb for the read fb */
1073          if (stdraw)
1074             st_framebuffer_reference(&stread, stdraw);
1075       }
1076 
1077       if (stdraw && stread) {
1078          st_framebuffer_validate(stdraw, st);
1079          if (stread != stdraw)
1080             st_framebuffer_validate(stread, st);
1081 
1082          ret = _mesa_make_current(st->ctx, &stdraw->Base, &stread->Base);
1083 
1084          st->draw_stamp = stdraw->stamp - 1;
1085          st->read_stamp = stread->stamp - 1;
1086          st_context_validate(st, stdraw, stread);
1087       }
1088       else {
1089          struct gl_framebuffer *incomplete = _mesa_get_incomplete_framebuffer();
1090          ret = _mesa_make_current(st->ctx, incomplete, incomplete);
1091       }
1092 
1093       st_framebuffer_reference(&stdraw, NULL);
1094       st_framebuffer_reference(&stread, NULL);
1095 
1096       /* Purge the context's winsys_buffers list in case any
1097        * of the referenced drawables no longer exist.
1098        */
1099       st_framebuffers_purge(st);
1100    }
1101    else {
1102       GET_CURRENT_CONTEXT(ctx);
1103 
1104       if (ctx) {
1105          /* Before releasing the context, release its associated
1106           * winsys buffers first. Then purge the context's winsys buffers list
1107           * to free the resources of any winsys buffers that no longer have
1108           * an existing drawable.
1109           */
1110          ret = _mesa_make_current(ctx, NULL, NULL);
1111          st_framebuffers_purge(ctx->st);
1112       }
1113 
1114       ret = _mesa_make_current(NULL, NULL, NULL);
1115    }
1116 
1117    return ret;
1118 }
1119 
1120 
1121 static void
st_api_destroy(struct st_api * stapi)1122 st_api_destroy(struct st_api *stapi)
1123 {
1124 }
1125 
1126 
1127 /**
1128  * Flush the front buffer if the current context renders to the front buffer.
1129  */
1130 void
st_manager_flush_frontbuffer(struct st_context * st)1131 st_manager_flush_frontbuffer(struct st_context *st)
1132 {
1133    struct st_framebuffer *stfb = st_ws_framebuffer(st->ctx->DrawBuffer);
1134    struct st_renderbuffer *strb = NULL;
1135 
1136    if (!stfb)
1137       return;
1138 
1139    /* If the context uses a doublebuffered visual, but the buffer is
1140     * single-buffered, guess that it's a pbuffer, which doesn't need
1141     * flushing.
1142     */
1143    if (st->ctx->Visual.doubleBufferMode &&
1144        !stfb->Base.Visual.doubleBufferMode)
1145       return;
1146 
1147    strb = st_renderbuffer(stfb->Base.Attachment[BUFFER_FRONT_LEFT].
1148                           Renderbuffer);
1149 
1150    /* Do we have a front color buffer and has it been drawn to since last
1151     * frontbuffer flush?
1152     */
1153    if (strb && strb->defined) {
1154       stfb->iface->flush_front(&st->iface, stfb->iface,
1155                                ST_ATTACHMENT_FRONT_LEFT);
1156       strb->defined = GL_FALSE;
1157 
1158       /* Trigger an update of strb->defined on next draw */
1159       st->dirty |= ST_NEW_FB_STATE;
1160    }
1161 }
1162 
1163 
1164 /**
1165  * Re-validate the framebuffers.
1166  */
1167 void
st_manager_validate_framebuffers(struct st_context * st)1168 st_manager_validate_framebuffers(struct st_context *st)
1169 {
1170    struct st_framebuffer *stdraw = st_ws_framebuffer(st->ctx->DrawBuffer);
1171    struct st_framebuffer *stread = st_ws_framebuffer(st->ctx->ReadBuffer);
1172 
1173    if (stdraw)
1174       st_framebuffer_validate(stdraw, st);
1175    if (stread && stread != stdraw)
1176       st_framebuffer_validate(stread, st);
1177 
1178    st_context_validate(st, stdraw, stread);
1179 }
1180 
1181 
1182 /**
1183  * Flush any outstanding swapbuffers on the current draw framebuffer.
1184  */
1185 void
st_manager_flush_swapbuffers(void)1186 st_manager_flush_swapbuffers(void)
1187 {
1188    GET_CURRENT_CONTEXT(ctx);
1189    struct st_context *st = (ctx) ? ctx->st : NULL;
1190    struct st_framebuffer *stfb;
1191 
1192    if (!st)
1193       return;
1194 
1195    stfb = st_ws_framebuffer(ctx->DrawBuffer);
1196    if (!stfb || !stfb->iface->flush_swapbuffers)
1197       return;
1198 
1199    stfb->iface->flush_swapbuffers(&st->iface, stfb->iface);
1200 }
1201 
1202 
1203 /**
1204  * Add a color renderbuffer on demand.  The FBO must correspond to a window,
1205  * not a user-created FBO.
1206  */
1207 bool
st_manager_add_color_renderbuffer(struct st_context * st,struct gl_framebuffer * fb,gl_buffer_index idx)1208 st_manager_add_color_renderbuffer(struct st_context *st,
1209                                   struct gl_framebuffer *fb,
1210                                   gl_buffer_index idx)
1211 {
1212    struct st_framebuffer *stfb = st_ws_framebuffer(fb);
1213 
1214    /* FBO */
1215    if (!stfb)
1216       return false;
1217 
1218    assert(_mesa_is_winsys_fbo(fb));
1219 
1220    if (stfb->Base.Attachment[idx].Renderbuffer)
1221       return true;
1222 
1223    switch (idx) {
1224    case BUFFER_FRONT_LEFT:
1225    case BUFFER_BACK_LEFT:
1226    case BUFFER_FRONT_RIGHT:
1227    case BUFFER_BACK_RIGHT:
1228       break;
1229    default:
1230       return false;
1231    }
1232 
1233    if (!st_framebuffer_add_renderbuffer(stfb, idx,
1234                                         stfb->Base.Visual.sRGBCapable))
1235       return false;
1236 
1237    st_framebuffer_update_attachments(stfb);
1238 
1239    /*
1240     * Force a call to the frontend manager to validate the
1241     * new renderbuffer. It might be that there is a window system
1242     * renderbuffer available.
1243     */
1244    if (stfb->iface)
1245       stfb->iface_stamp = p_atomic_read(&stfb->iface->stamp) - 1;
1246 
1247    st_invalidate_buffers(st);
1248 
1249    return true;
1250 }
1251 
1252 
1253 static unsigned
get_version(struct pipe_screen * screen,struct st_config_options * options,gl_api api)1254 get_version(struct pipe_screen *screen,
1255             struct st_config_options *options, gl_api api)
1256 {
1257    struct gl_constants consts = {0};
1258    struct gl_extensions extensions = {0};
1259    GLuint version;
1260 
1261    if (_mesa_override_gl_version_contextless(&consts, &api, &version)) {
1262       return version;
1263    }
1264 
1265    _mesa_init_constants(&consts, api);
1266    _mesa_init_extensions(&extensions);
1267 
1268    st_init_limits(screen, &consts, &extensions);
1269    st_init_extensions(screen, &consts, &extensions, options, api);
1270    version = _mesa_get_version(&extensions, &consts, api);
1271    free(consts.SpirVExtensions);
1272    return version;
1273 }
1274 
1275 
1276 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)1277 st_api_query_versions(struct st_api *stapi, struct st_manager *sm,
1278                       struct st_config_options *options,
1279                       int *gl_core_version,
1280                       int *gl_compat_version,
1281                       int *gl_es1_version,
1282                       int *gl_es2_version)
1283 {
1284    *gl_core_version = get_version(sm->screen, options, API_OPENGL_CORE);
1285    *gl_compat_version = get_version(sm->screen, options, API_OPENGL_COMPAT);
1286    *gl_es1_version = get_version(sm->screen, options, API_OPENGLES);
1287    *gl_es2_version = get_version(sm->screen, options, API_OPENGLES2);
1288 }
1289 
1290 
1291 static const struct st_api st_gl_api = {
1292    .name = "Mesa " PACKAGE_VERSION,
1293    .api = ST_API_OPENGL,
1294    .profile_mask = ST_PROFILE_DEFAULT_MASK |
1295                    ST_PROFILE_OPENGL_CORE_MASK |
1296                    ST_PROFILE_OPENGL_ES1_MASK |
1297                    ST_PROFILE_OPENGL_ES2_MASK |
1298                    0,
1299    .feature_mask = ST_API_FEATURE_MS_VISUALS_MASK,
1300    .destroy = st_api_destroy,
1301    .query_versions = st_api_query_versions,
1302    .create_context = st_api_create_context,
1303    .make_current = st_api_make_current,
1304    .get_current = st_api_get_current,
1305    .destroy_drawable = st_api_destroy_drawable,
1306 };
1307 
1308 
1309 struct st_api *
st_gl_api_create(void)1310 st_gl_api_create(void)
1311 {
1312    return (struct st_api *) &st_gl_api;
1313 }
1314