1/*
2 * Copyright © 2011 Marek Olšák <maraeo@gmail.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24/**
25 * \file barrier.c
26 * Implementation of various pipeline barrier entry points.
27 *
28 * \author Marek Olšák <maraeo@gmail.com>
29 */
30
31#include "context.h"
32#include "barrier.h"
33
34
35static void
36_mesa_texture_barrier(struct gl_context *ctx)
37{
38   /* no-op */
39}
40
41void
42_mesa_init_barrier_functions(struct dd_function_table *driver)
43{
44   driver->TextureBarrier = _mesa_texture_barrier;
45}
46
47void GLAPIENTRY
48_mesa_TextureBarrierNV(void)
49{
50   GET_CURRENT_CONTEXT(ctx);
51
52   if (!ctx->Extensions.NV_texture_barrier) {
53      _mesa_error(ctx, GL_INVALID_OPERATION,
54                  "glTextureBarrier(not supported)");
55      return;
56   }
57
58   ctx->Driver.TextureBarrier(ctx);
59}
60
61void GLAPIENTRY
62_mesa_MemoryBarrier(GLbitfield barriers)
63{
64   GET_CURRENT_CONTEXT(ctx);
65
66   if (ctx->Driver.MemoryBarrier)
67      ctx->Driver.MemoryBarrier(ctx, barriers);
68}
69
70static ALWAYS_INLINE void
71memory_barrier_by_region(struct gl_context *ctx, GLbitfield barriers,
72                         bool no_error)
73{
74   GLbitfield all_allowed_bits = GL_ATOMIC_COUNTER_BARRIER_BIT |
75                                 GL_FRAMEBUFFER_BARRIER_BIT |
76                                 GL_SHADER_IMAGE_ACCESS_BARRIER_BIT |
77                                 GL_SHADER_STORAGE_BARRIER_BIT |
78                                 GL_TEXTURE_FETCH_BARRIER_BIT |
79                                 GL_UNIFORM_BARRIER_BIT;
80
81   if (ctx->Driver.MemoryBarrier) {
82      /* From section 7.11.2 of the OpenGL ES 3.1 specification:
83       *
84       *    "When barriers is ALL_BARRIER_BITS, shader memory accesses will be
85       *     synchronized relative to all these barrier bits, but not to other
86       *     barrier bits specific to MemoryBarrier."
87       *
88       * That is, if barriers is the special value GL_ALL_BARRIER_BITS, then all
89       * barriers allowed by glMemoryBarrierByRegion should be activated."
90       */
91      if (barriers == GL_ALL_BARRIER_BITS) {
92         ctx->Driver.MemoryBarrier(ctx, all_allowed_bits);
93         return;
94      }
95
96      /* From section 7.11.2 of the OpenGL ES 3.1 specification:
97       *
98       *    "An INVALID_VALUE error is generated if barriers is not the special
99       *     value ALL_BARRIER_BITS, and has any bits set other than those
100       *     described above."
101       */
102      if (!no_error && (barriers & ~all_allowed_bits) != 0) {
103         _mesa_error(ctx, GL_INVALID_VALUE,
104                     "glMemoryBarrierByRegion(unsupported barrier bit");
105      }
106
107      ctx->Driver.MemoryBarrier(ctx, barriers);
108   }
109}
110
111void GLAPIENTRY
112_mesa_MemoryBarrierByRegion_no_error(GLbitfield barriers)
113{
114   GET_CURRENT_CONTEXT(ctx);
115   memory_barrier_by_region(ctx, barriers, true);
116}
117
118void GLAPIENTRY
119_mesa_MemoryBarrierByRegion(GLbitfield barriers)
120{
121   GET_CURRENT_CONTEXT(ctx);
122   memory_barrier_by_region(ctx, barriers, false);
123}
124
125void GLAPIENTRY
126_mesa_BlendBarrier(void)
127{
128   GET_CURRENT_CONTEXT(ctx);
129
130   if (!ctx->Extensions.KHR_blend_equation_advanced) {
131      _mesa_error(ctx, GL_INVALID_OPERATION,
132                  "glBlendBarrier(not supported)");
133      return;
134   }
135
136   ctx->Driver.FramebufferFetchBarrier(ctx);
137}
138
139void GLAPIENTRY
140_mesa_FramebufferFetchBarrierEXT(void)
141{
142   GET_CURRENT_CONTEXT(ctx);
143
144   if (!ctx->Extensions.EXT_shader_framebuffer_fetch_non_coherent) {
145      _mesa_error(ctx, GL_INVALID_OPERATION,
146                  "glFramebufferFetchBarrierEXT(not supported)");
147      return;
148   }
149
150   ctx->Driver.FramebufferFetchBarrier(ctx);
151}
152