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