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