xref: /aosp_15_r20/external/mesa3d/src/mesa/main/pipelineobj.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Mesa 3-D graphics library
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Copyright © 2013 Gregory Hainaut <[email protected]>
5*61046927SAndroid Build Coastguard Worker  *
6*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
7*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
8*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
9*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
11*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
12*61046927SAndroid Build Coastguard Worker  *
13*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
14*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
15*61046927SAndroid Build Coastguard Worker  * Software.
16*61046927SAndroid Build Coastguard Worker  *
17*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22*61046927SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23*61046927SAndroid Build Coastguard Worker  * IN THE SOFTWARE.
24*61046927SAndroid Build Coastguard Worker  */
25*61046927SAndroid Build Coastguard Worker 
26*61046927SAndroid Build Coastguard Worker /**
27*61046927SAndroid Build Coastguard Worker  * \file pipelineobj.c
28*61046927SAndroid Build Coastguard Worker  * \author Hainaut Gregory <[email protected]>
29*61046927SAndroid Build Coastguard Worker  *
30*61046927SAndroid Build Coastguard Worker  * Implementation of pipeline object related API functions. Based on
31*61046927SAndroid Build Coastguard Worker  * GL_ARB_separate_shader_objects extension.
32*61046927SAndroid Build Coastguard Worker  */
33*61046927SAndroid Build Coastguard Worker 
34*61046927SAndroid Build Coastguard Worker #include <stdbool.h>
35*61046927SAndroid Build Coastguard Worker #include "util/glheader.h"
36*61046927SAndroid Build Coastguard Worker #include "main/context.h"
37*61046927SAndroid Build Coastguard Worker #include "main/draw_validate.h"
38*61046927SAndroid Build Coastguard Worker #include "main/enums.h"
39*61046927SAndroid Build Coastguard Worker #include "main/hash.h"
40*61046927SAndroid Build Coastguard Worker #include "main/mtypes.h"
41*61046927SAndroid Build Coastguard Worker #include "main/pipelineobj.h"
42*61046927SAndroid Build Coastguard Worker #include "main/shaderapi.h"
43*61046927SAndroid Build Coastguard Worker #include "main/shaderobj.h"
44*61046927SAndroid Build Coastguard Worker #include "main/state.h"
45*61046927SAndroid Build Coastguard Worker #include "main/transformfeedback.h"
46*61046927SAndroid Build Coastguard Worker #include "main/uniforms.h"
47*61046927SAndroid Build Coastguard Worker #include "compiler/glsl/glsl_parser_extras.h"
48*61046927SAndroid Build Coastguard Worker #include "compiler/glsl/ir_uniform.h"
49*61046927SAndroid Build Coastguard Worker #include "program/program.h"
50*61046927SAndroid Build Coastguard Worker #include "program/prog_parameter.h"
51*61046927SAndroid Build Coastguard Worker #include "util/ralloc.h"
52*61046927SAndroid Build Coastguard Worker #include "util/bitscan.h"
53*61046927SAndroid Build Coastguard Worker #include "api_exec_decl.h"
54*61046927SAndroid Build Coastguard Worker 
55*61046927SAndroid Build Coastguard Worker /**
56*61046927SAndroid Build Coastguard Worker  * Delete a pipeline object.
57*61046927SAndroid Build Coastguard Worker  */
58*61046927SAndroid Build Coastguard Worker void
_mesa_delete_pipeline_object(struct gl_context * ctx,struct gl_pipeline_object * obj)59*61046927SAndroid Build Coastguard Worker _mesa_delete_pipeline_object(struct gl_context *ctx,
60*61046927SAndroid Build Coastguard Worker                              struct gl_pipeline_object *obj)
61*61046927SAndroid Build Coastguard Worker {
62*61046927SAndroid Build Coastguard Worker    unsigned i;
63*61046927SAndroid Build Coastguard Worker 
64*61046927SAndroid Build Coastguard Worker    for (i = 0; i < MESA_SHADER_STAGES; i++) {
65*61046927SAndroid Build Coastguard Worker       _mesa_reference_program(ctx, &obj->CurrentProgram[i], NULL);
66*61046927SAndroid Build Coastguard Worker       _mesa_reference_shader_program(ctx, &obj->ReferencedPrograms[i], NULL);
67*61046927SAndroid Build Coastguard Worker    }
68*61046927SAndroid Build Coastguard Worker 
69*61046927SAndroid Build Coastguard Worker    _mesa_reference_shader_program(ctx, &obj->ActiveProgram, NULL);
70*61046927SAndroid Build Coastguard Worker    free(obj->Label);
71*61046927SAndroid Build Coastguard Worker    ralloc_free(obj);
72*61046927SAndroid Build Coastguard Worker }
73*61046927SAndroid Build Coastguard Worker 
74*61046927SAndroid Build Coastguard Worker /**
75*61046927SAndroid Build Coastguard Worker  * Allocate and initialize a new pipeline object.
76*61046927SAndroid Build Coastguard Worker  */
77*61046927SAndroid Build Coastguard Worker static struct gl_pipeline_object *
_mesa_new_pipeline_object(struct gl_context * ctx,GLuint name)78*61046927SAndroid Build Coastguard Worker _mesa_new_pipeline_object(struct gl_context *ctx, GLuint name)
79*61046927SAndroid Build Coastguard Worker {
80*61046927SAndroid Build Coastguard Worker    struct gl_pipeline_object *obj = rzalloc(NULL, struct gl_pipeline_object);
81*61046927SAndroid Build Coastguard Worker    if (obj) {
82*61046927SAndroid Build Coastguard Worker       obj->Name = name;
83*61046927SAndroid Build Coastguard Worker       obj->RefCount = 1;
84*61046927SAndroid Build Coastguard Worker       obj->Flags = _mesa_get_shader_flags();
85*61046927SAndroid Build Coastguard Worker       obj->InfoLog = NULL;
86*61046927SAndroid Build Coastguard Worker    }
87*61046927SAndroid Build Coastguard Worker 
88*61046927SAndroid Build Coastguard Worker    return obj;
89*61046927SAndroid Build Coastguard Worker }
90*61046927SAndroid Build Coastguard Worker 
91*61046927SAndroid Build Coastguard Worker /**
92*61046927SAndroid Build Coastguard Worker  * Initialize pipeline object state for given context.
93*61046927SAndroid Build Coastguard Worker  */
94*61046927SAndroid Build Coastguard Worker void
_mesa_init_pipeline(struct gl_context * ctx)95*61046927SAndroid Build Coastguard Worker _mesa_init_pipeline(struct gl_context *ctx)
96*61046927SAndroid Build Coastguard Worker {
97*61046927SAndroid Build Coastguard Worker    _mesa_InitHashTable(&ctx->Pipeline.Objects);
98*61046927SAndroid Build Coastguard Worker 
99*61046927SAndroid Build Coastguard Worker    ctx->Pipeline.Current = NULL;
100*61046927SAndroid Build Coastguard Worker 
101*61046927SAndroid Build Coastguard Worker    /* Install a default Pipeline */
102*61046927SAndroid Build Coastguard Worker    ctx->Pipeline.Default = _mesa_new_pipeline_object(ctx, 0);
103*61046927SAndroid Build Coastguard Worker    _mesa_reference_pipeline_object(ctx, &ctx->_Shader, ctx->Pipeline.Default);
104*61046927SAndroid Build Coastguard Worker }
105*61046927SAndroid Build Coastguard Worker 
106*61046927SAndroid Build Coastguard Worker 
107*61046927SAndroid Build Coastguard Worker /**
108*61046927SAndroid Build Coastguard Worker  * Callback for deleting a pipeline object.  Called by _mesa_DeleteHashTable().
109*61046927SAndroid Build Coastguard Worker  */
110*61046927SAndroid Build Coastguard Worker static void
delete_pipelineobj_cb(void * data,void * userData)111*61046927SAndroid Build Coastguard Worker delete_pipelineobj_cb(void *data, void *userData)
112*61046927SAndroid Build Coastguard Worker {
113*61046927SAndroid Build Coastguard Worker    struct gl_pipeline_object *obj = (struct gl_pipeline_object *) data;
114*61046927SAndroid Build Coastguard Worker    struct gl_context *ctx = (struct gl_context *) userData;
115*61046927SAndroid Build Coastguard Worker    _mesa_delete_pipeline_object(ctx, obj);
116*61046927SAndroid Build Coastguard Worker }
117*61046927SAndroid Build Coastguard Worker 
118*61046927SAndroid Build Coastguard Worker 
119*61046927SAndroid Build Coastguard Worker /**
120*61046927SAndroid Build Coastguard Worker  * Free pipeline state for given context.
121*61046927SAndroid Build Coastguard Worker  */
122*61046927SAndroid Build Coastguard Worker void
_mesa_free_pipeline_data(struct gl_context * ctx)123*61046927SAndroid Build Coastguard Worker _mesa_free_pipeline_data(struct gl_context *ctx)
124*61046927SAndroid Build Coastguard Worker {
125*61046927SAndroid Build Coastguard Worker    _mesa_reference_pipeline_object(ctx, &ctx->_Shader, NULL);
126*61046927SAndroid Build Coastguard Worker    _mesa_DeinitHashTable(&ctx->Pipeline.Objects, delete_pipelineobj_cb, ctx);
127*61046927SAndroid Build Coastguard Worker    _mesa_delete_pipeline_object(ctx, ctx->Pipeline.Default);
128*61046927SAndroid Build Coastguard Worker }
129*61046927SAndroid Build Coastguard Worker 
130*61046927SAndroid Build Coastguard Worker /**
131*61046927SAndroid Build Coastguard Worker  * Look up the pipeline object for the given ID.
132*61046927SAndroid Build Coastguard Worker  *
133*61046927SAndroid Build Coastguard Worker  * \returns
134*61046927SAndroid Build Coastguard Worker  * Either a pointer to the pipeline object with the specified ID or \c NULL for
135*61046927SAndroid Build Coastguard Worker  * a non-existent ID.  The spec defines ID 0 as being technically
136*61046927SAndroid Build Coastguard Worker  * non-existent.
137*61046927SAndroid Build Coastguard Worker  */
138*61046927SAndroid Build Coastguard Worker struct gl_pipeline_object *
_mesa_lookup_pipeline_object(struct gl_context * ctx,GLuint id)139*61046927SAndroid Build Coastguard Worker _mesa_lookup_pipeline_object(struct gl_context *ctx, GLuint id)
140*61046927SAndroid Build Coastguard Worker {
141*61046927SAndroid Build Coastguard Worker    if (id == 0)
142*61046927SAndroid Build Coastguard Worker       return NULL;
143*61046927SAndroid Build Coastguard Worker    else
144*61046927SAndroid Build Coastguard Worker       return (struct gl_pipeline_object *)
145*61046927SAndroid Build Coastguard Worker          _mesa_HashLookupLocked(&ctx->Pipeline.Objects, id);
146*61046927SAndroid Build Coastguard Worker }
147*61046927SAndroid Build Coastguard Worker 
148*61046927SAndroid Build Coastguard Worker /**
149*61046927SAndroid Build Coastguard Worker  * Add the given pipeline object to the pipeline object pool.
150*61046927SAndroid Build Coastguard Worker  */
151*61046927SAndroid Build Coastguard Worker static void
save_pipeline_object(struct gl_context * ctx,struct gl_pipeline_object * obj)152*61046927SAndroid Build Coastguard Worker save_pipeline_object(struct gl_context *ctx, struct gl_pipeline_object *obj)
153*61046927SAndroid Build Coastguard Worker {
154*61046927SAndroid Build Coastguard Worker    if (obj->Name > 0) {
155*61046927SAndroid Build Coastguard Worker       _mesa_HashInsertLocked(&ctx->Pipeline.Objects, obj->Name, obj);
156*61046927SAndroid Build Coastguard Worker    }
157*61046927SAndroid Build Coastguard Worker }
158*61046927SAndroid Build Coastguard Worker 
159*61046927SAndroid Build Coastguard Worker /**
160*61046927SAndroid Build Coastguard Worker  * Remove the given pipeline object from the pipeline object pool.
161*61046927SAndroid Build Coastguard Worker  * Do not deallocate the pipeline object though.
162*61046927SAndroid Build Coastguard Worker  */
163*61046927SAndroid Build Coastguard Worker static void
remove_pipeline_object(struct gl_context * ctx,struct gl_pipeline_object * obj)164*61046927SAndroid Build Coastguard Worker remove_pipeline_object(struct gl_context *ctx, struct gl_pipeline_object *obj)
165*61046927SAndroid Build Coastguard Worker {
166*61046927SAndroid Build Coastguard Worker    if (obj->Name > 0) {
167*61046927SAndroid Build Coastguard Worker       _mesa_HashRemoveLocked(&ctx->Pipeline.Objects, obj->Name);
168*61046927SAndroid Build Coastguard Worker    }
169*61046927SAndroid Build Coastguard Worker }
170*61046927SAndroid Build Coastguard Worker 
171*61046927SAndroid Build Coastguard Worker /**
172*61046927SAndroid Build Coastguard Worker  * Set ptr to obj w/ reference counting.
173*61046927SAndroid Build Coastguard Worker  * Note: this should only be called from the _mesa_reference_pipeline_object()
174*61046927SAndroid Build Coastguard Worker  * inline function.
175*61046927SAndroid Build Coastguard Worker  */
176*61046927SAndroid Build Coastguard Worker void
_mesa_reference_pipeline_object_(struct gl_context * ctx,struct gl_pipeline_object ** ptr,struct gl_pipeline_object * obj)177*61046927SAndroid Build Coastguard Worker _mesa_reference_pipeline_object_(struct gl_context *ctx,
178*61046927SAndroid Build Coastguard Worker                                  struct gl_pipeline_object **ptr,
179*61046927SAndroid Build Coastguard Worker                                  struct gl_pipeline_object *obj)
180*61046927SAndroid Build Coastguard Worker {
181*61046927SAndroid Build Coastguard Worker    assert(*ptr != obj);
182*61046927SAndroid Build Coastguard Worker 
183*61046927SAndroid Build Coastguard Worker    if (*ptr) {
184*61046927SAndroid Build Coastguard Worker       /* Unreference the old pipeline object */
185*61046927SAndroid Build Coastguard Worker       struct gl_pipeline_object *oldObj = *ptr;
186*61046927SAndroid Build Coastguard Worker 
187*61046927SAndroid Build Coastguard Worker       assert(oldObj->RefCount > 0);
188*61046927SAndroid Build Coastguard Worker       oldObj->RefCount--;
189*61046927SAndroid Build Coastguard Worker 
190*61046927SAndroid Build Coastguard Worker       if (oldObj->RefCount == 0) {
191*61046927SAndroid Build Coastguard Worker          _mesa_delete_pipeline_object(ctx, oldObj);
192*61046927SAndroid Build Coastguard Worker       }
193*61046927SAndroid Build Coastguard Worker 
194*61046927SAndroid Build Coastguard Worker       *ptr = NULL;
195*61046927SAndroid Build Coastguard Worker    }
196*61046927SAndroid Build Coastguard Worker    assert(!*ptr);
197*61046927SAndroid Build Coastguard Worker 
198*61046927SAndroid Build Coastguard Worker    if (obj) {
199*61046927SAndroid Build Coastguard Worker       /* reference new pipeline object */
200*61046927SAndroid Build Coastguard Worker       assert(obj->RefCount > 0);
201*61046927SAndroid Build Coastguard Worker 
202*61046927SAndroid Build Coastguard Worker       obj->RefCount++;
203*61046927SAndroid Build Coastguard Worker       *ptr = obj;
204*61046927SAndroid Build Coastguard Worker    }
205*61046927SAndroid Build Coastguard Worker }
206*61046927SAndroid Build Coastguard Worker 
207*61046927SAndroid Build Coastguard Worker static void
use_program_stage(struct gl_context * ctx,GLenum type,struct gl_shader_program * shProg,struct gl_pipeline_object * pipe)208*61046927SAndroid Build Coastguard Worker use_program_stage(struct gl_context *ctx, GLenum type,
209*61046927SAndroid Build Coastguard Worker                   struct gl_shader_program *shProg,
210*61046927SAndroid Build Coastguard Worker                   struct gl_pipeline_object *pipe) {
211*61046927SAndroid Build Coastguard Worker    gl_shader_stage stage = _mesa_shader_enum_to_shader_stage(type);
212*61046927SAndroid Build Coastguard Worker    struct gl_program *prog = NULL;
213*61046927SAndroid Build Coastguard Worker    if (shProg && shProg->_LinkedShaders[stage])
214*61046927SAndroid Build Coastguard Worker       prog = shProg->_LinkedShaders[stage]->Program;
215*61046927SAndroid Build Coastguard Worker 
216*61046927SAndroid Build Coastguard Worker    _mesa_use_program(ctx, stage, shProg, prog, pipe);
217*61046927SAndroid Build Coastguard Worker }
218*61046927SAndroid Build Coastguard Worker 
219*61046927SAndroid Build Coastguard Worker static void
use_program_stages(struct gl_context * ctx,struct gl_shader_program * shProg,GLbitfield stages,struct gl_pipeline_object * pipe)220*61046927SAndroid Build Coastguard Worker use_program_stages(struct gl_context *ctx, struct gl_shader_program *shProg,
221*61046927SAndroid Build Coastguard Worker                    GLbitfield stages, struct gl_pipeline_object *pipe) {
222*61046927SAndroid Build Coastguard Worker 
223*61046927SAndroid Build Coastguard Worker    /* Enable individual stages from the program as requested by the
224*61046927SAndroid Build Coastguard Worker     * application.  If there is no shader for a requested stage in the
225*61046927SAndroid Build Coastguard Worker     * program, _mesa_use_shader_program will enable fixed-function processing
226*61046927SAndroid Build Coastguard Worker     * as dictated by the spec.
227*61046927SAndroid Build Coastguard Worker     *
228*61046927SAndroid Build Coastguard Worker     * Section 2.11.4 (Program Pipeline Objects) of the OpenGL 4.1 spec
229*61046927SAndroid Build Coastguard Worker     * says:
230*61046927SAndroid Build Coastguard Worker     *
231*61046927SAndroid Build Coastguard Worker     *     "If UseProgramStages is called with program set to zero or with a
232*61046927SAndroid Build Coastguard Worker     *     program object that contains no executable code for the given
233*61046927SAndroid Build Coastguard Worker     *     stages, it is as if the pipeline object has no programmable stage
234*61046927SAndroid Build Coastguard Worker     *     configured for the indicated shader stages."
235*61046927SAndroid Build Coastguard Worker     */
236*61046927SAndroid Build Coastguard Worker    if ((stages & GL_VERTEX_SHADER_BIT) != 0)
237*61046927SAndroid Build Coastguard Worker       use_program_stage(ctx, GL_VERTEX_SHADER, shProg, pipe);
238*61046927SAndroid Build Coastguard Worker 
239*61046927SAndroid Build Coastguard Worker    if ((stages & GL_FRAGMENT_SHADER_BIT) != 0)
240*61046927SAndroid Build Coastguard Worker       use_program_stage(ctx, GL_FRAGMENT_SHADER, shProg, pipe);
241*61046927SAndroid Build Coastguard Worker 
242*61046927SAndroid Build Coastguard Worker    if ((stages & GL_GEOMETRY_SHADER_BIT) != 0)
243*61046927SAndroid Build Coastguard Worker       use_program_stage(ctx, GL_GEOMETRY_SHADER, shProg, pipe);
244*61046927SAndroid Build Coastguard Worker 
245*61046927SAndroid Build Coastguard Worker    if ((stages & GL_TESS_CONTROL_SHADER_BIT) != 0)
246*61046927SAndroid Build Coastguard Worker       use_program_stage(ctx, GL_TESS_CONTROL_SHADER, shProg, pipe);
247*61046927SAndroid Build Coastguard Worker 
248*61046927SAndroid Build Coastguard Worker    if ((stages & GL_TESS_EVALUATION_SHADER_BIT) != 0)
249*61046927SAndroid Build Coastguard Worker       use_program_stage(ctx, GL_TESS_EVALUATION_SHADER, shProg, pipe);
250*61046927SAndroid Build Coastguard Worker 
251*61046927SAndroid Build Coastguard Worker    if ((stages & GL_COMPUTE_SHADER_BIT) != 0)
252*61046927SAndroid Build Coastguard Worker       use_program_stage(ctx, GL_COMPUTE_SHADER, shProg, pipe);
253*61046927SAndroid Build Coastguard Worker 
254*61046927SAndroid Build Coastguard Worker    pipe->Validated = pipe->UserValidated = false;
255*61046927SAndroid Build Coastguard Worker 
256*61046927SAndroid Build Coastguard Worker    if (pipe == ctx->_Shader)
257*61046927SAndroid Build Coastguard Worker       _mesa_update_valid_to_render_state(ctx);
258*61046927SAndroid Build Coastguard Worker }
259*61046927SAndroid Build Coastguard Worker 
260*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_UseProgramStages_no_error(GLuint pipeline,GLbitfield stages,GLuint prog)261*61046927SAndroid Build Coastguard Worker _mesa_UseProgramStages_no_error(GLuint pipeline, GLbitfield stages,
262*61046927SAndroid Build Coastguard Worker                                 GLuint prog)
263*61046927SAndroid Build Coastguard Worker {
264*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
265*61046927SAndroid Build Coastguard Worker 
266*61046927SAndroid Build Coastguard Worker    struct gl_pipeline_object *pipe =
267*61046927SAndroid Build Coastguard Worker       _mesa_lookup_pipeline_object(ctx, pipeline);
268*61046927SAndroid Build Coastguard Worker    struct gl_shader_program *shProg = NULL;
269*61046927SAndroid Build Coastguard Worker 
270*61046927SAndroid Build Coastguard Worker    if (prog)
271*61046927SAndroid Build Coastguard Worker       shProg = _mesa_lookup_shader_program(ctx, prog);
272*61046927SAndroid Build Coastguard Worker 
273*61046927SAndroid Build Coastguard Worker    /* Object is created by any Pipeline call but glGenProgramPipelines,
274*61046927SAndroid Build Coastguard Worker     * glIsProgramPipeline and GetProgramPipelineInfoLog
275*61046927SAndroid Build Coastguard Worker     */
276*61046927SAndroid Build Coastguard Worker    pipe->EverBound = GL_TRUE;
277*61046927SAndroid Build Coastguard Worker 
278*61046927SAndroid Build Coastguard Worker    use_program_stages(ctx, shProg, stages, pipe);
279*61046927SAndroid Build Coastguard Worker }
280*61046927SAndroid Build Coastguard Worker 
281*61046927SAndroid Build Coastguard Worker /**
282*61046927SAndroid Build Coastguard Worker  * Bound program to severals stages of the pipeline
283*61046927SAndroid Build Coastguard Worker  */
284*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_UseProgramStages(GLuint pipeline,GLbitfield stages,GLuint program)285*61046927SAndroid Build Coastguard Worker _mesa_UseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program)
286*61046927SAndroid Build Coastguard Worker {
287*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
288*61046927SAndroid Build Coastguard Worker 
289*61046927SAndroid Build Coastguard Worker    struct gl_pipeline_object *pipe = _mesa_lookup_pipeline_object(ctx, pipeline);
290*61046927SAndroid Build Coastguard Worker    struct gl_shader_program *shProg = NULL;
291*61046927SAndroid Build Coastguard Worker    GLbitfield any_valid_stages;
292*61046927SAndroid Build Coastguard Worker 
293*61046927SAndroid Build Coastguard Worker    if (MESA_VERBOSE & VERBOSE_API)
294*61046927SAndroid Build Coastguard Worker       _mesa_debug(ctx, "glUseProgramStages(%u, 0x%x, %u)\n",
295*61046927SAndroid Build Coastguard Worker                   pipeline, stages, program);
296*61046927SAndroid Build Coastguard Worker 
297*61046927SAndroid Build Coastguard Worker    if (!pipe) {
298*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_OPERATION, "glUseProgramStages(pipeline)");
299*61046927SAndroid Build Coastguard Worker       return;
300*61046927SAndroid Build Coastguard Worker    }
301*61046927SAndroid Build Coastguard Worker 
302*61046927SAndroid Build Coastguard Worker    /* Object is created by any Pipeline call but glGenProgramPipelines,
303*61046927SAndroid Build Coastguard Worker     * glIsProgramPipeline and GetProgramPipelineInfoLog
304*61046927SAndroid Build Coastguard Worker     */
305*61046927SAndroid Build Coastguard Worker    pipe->EverBound = GL_TRUE;
306*61046927SAndroid Build Coastguard Worker 
307*61046927SAndroid Build Coastguard Worker    /* Section 2.11.4 (Program Pipeline Objects) of the OpenGL 4.1 spec says:
308*61046927SAndroid Build Coastguard Worker     *
309*61046927SAndroid Build Coastguard Worker     *     "If stages is not the special value ALL_SHADER_BITS, and has a bit
310*61046927SAndroid Build Coastguard Worker     *     set that is not recognized, the error INVALID_VALUE is generated."
311*61046927SAndroid Build Coastguard Worker     */
312*61046927SAndroid Build Coastguard Worker    any_valid_stages = GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT;
313*61046927SAndroid Build Coastguard Worker    if (_mesa_has_geometry_shaders(ctx))
314*61046927SAndroid Build Coastguard Worker       any_valid_stages |= GL_GEOMETRY_SHADER_BIT;
315*61046927SAndroid Build Coastguard Worker    if (_mesa_has_tessellation(ctx))
316*61046927SAndroid Build Coastguard Worker       any_valid_stages |= GL_TESS_CONTROL_SHADER_BIT |
317*61046927SAndroid Build Coastguard Worker                           GL_TESS_EVALUATION_SHADER_BIT;
318*61046927SAndroid Build Coastguard Worker    if (_mesa_has_compute_shaders(ctx))
319*61046927SAndroid Build Coastguard Worker       any_valid_stages |= GL_COMPUTE_SHADER_BIT;
320*61046927SAndroid Build Coastguard Worker 
321*61046927SAndroid Build Coastguard Worker    if (stages != GL_ALL_SHADER_BITS && (stages & ~any_valid_stages) != 0) {
322*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_VALUE, "glUseProgramStages(Stages)");
323*61046927SAndroid Build Coastguard Worker       return;
324*61046927SAndroid Build Coastguard Worker    }
325*61046927SAndroid Build Coastguard Worker 
326*61046927SAndroid Build Coastguard Worker    /* Section 2.17.2 (Transform Feedback Primitive Capture) of the OpenGL 4.1
327*61046927SAndroid Build Coastguard Worker     * spec says:
328*61046927SAndroid Build Coastguard Worker     *
329*61046927SAndroid Build Coastguard Worker     *     "The error INVALID_OPERATION is generated:
330*61046927SAndroid Build Coastguard Worker     *
331*61046927SAndroid Build Coastguard Worker     *      ...
332*61046927SAndroid Build Coastguard Worker     *
333*61046927SAndroid Build Coastguard Worker     *         - by UseProgramStages if the program pipeline object it refers
334*61046927SAndroid Build Coastguard Worker     *           to is current and the current transform feedback object is
335*61046927SAndroid Build Coastguard Worker     *           active and not paused;
336*61046927SAndroid Build Coastguard Worker     */
337*61046927SAndroid Build Coastguard Worker    if (ctx->_Shader == pipe) {
338*61046927SAndroid Build Coastguard Worker       if (_mesa_is_xfb_active_and_unpaused(ctx)) {
339*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_INVALID_OPERATION,
340*61046927SAndroid Build Coastguard Worker                "glUseProgramStages(transform feedback active)");
341*61046927SAndroid Build Coastguard Worker          return;
342*61046927SAndroid Build Coastguard Worker       }
343*61046927SAndroid Build Coastguard Worker    }
344*61046927SAndroid Build Coastguard Worker 
345*61046927SAndroid Build Coastguard Worker    if (program) {
346*61046927SAndroid Build Coastguard Worker       shProg = _mesa_lookup_shader_program_err(ctx, program,
347*61046927SAndroid Build Coastguard Worker                                                "glUseProgramStages");
348*61046927SAndroid Build Coastguard Worker       if (shProg == NULL)
349*61046927SAndroid Build Coastguard Worker          return;
350*61046927SAndroid Build Coastguard Worker 
351*61046927SAndroid Build Coastguard Worker       /* Section 2.11.4 (Program Pipeline Objects) of the OpenGL 4.1 spec
352*61046927SAndroid Build Coastguard Worker        * says:
353*61046927SAndroid Build Coastguard Worker        *
354*61046927SAndroid Build Coastguard Worker        *     "If the program object named by program was linked without the
355*61046927SAndroid Build Coastguard Worker        *     PROGRAM_SEPARABLE parameter set, or was not linked successfully,
356*61046927SAndroid Build Coastguard Worker        *     the error INVALID_OPERATION is generated and the corresponding
357*61046927SAndroid Build Coastguard Worker        *     shader stages in the pipeline program pipeline object are not
358*61046927SAndroid Build Coastguard Worker        *     modified."
359*61046927SAndroid Build Coastguard Worker        */
360*61046927SAndroid Build Coastguard Worker       if (!shProg->data->LinkStatus) {
361*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_INVALID_OPERATION,
362*61046927SAndroid Build Coastguard Worker                      "glUseProgramStages(program not linked)");
363*61046927SAndroid Build Coastguard Worker          return;
364*61046927SAndroid Build Coastguard Worker       }
365*61046927SAndroid Build Coastguard Worker 
366*61046927SAndroid Build Coastguard Worker       if (!shProg->SeparateShader) {
367*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_INVALID_OPERATION,
368*61046927SAndroid Build Coastguard Worker                      "glUseProgramStages(program wasn't linked with the "
369*61046927SAndroid Build Coastguard Worker                      "PROGRAM_SEPARABLE flag)");
370*61046927SAndroid Build Coastguard Worker          return;
371*61046927SAndroid Build Coastguard Worker       }
372*61046927SAndroid Build Coastguard Worker    }
373*61046927SAndroid Build Coastguard Worker 
374*61046927SAndroid Build Coastguard Worker    use_program_stages(ctx, shProg, stages, pipe);
375*61046927SAndroid Build Coastguard Worker }
376*61046927SAndroid Build Coastguard Worker 
377*61046927SAndroid Build Coastguard Worker static ALWAYS_INLINE void
active_shader_program(struct gl_context * ctx,GLuint pipeline,GLuint program,bool no_error)378*61046927SAndroid Build Coastguard Worker active_shader_program(struct gl_context *ctx, GLuint pipeline, GLuint program,
379*61046927SAndroid Build Coastguard Worker                       bool no_error)
380*61046927SAndroid Build Coastguard Worker {
381*61046927SAndroid Build Coastguard Worker    struct gl_shader_program *shProg = NULL;
382*61046927SAndroid Build Coastguard Worker    struct gl_pipeline_object *pipe = _mesa_lookup_pipeline_object(ctx, pipeline);
383*61046927SAndroid Build Coastguard Worker 
384*61046927SAndroid Build Coastguard Worker    if (program) {
385*61046927SAndroid Build Coastguard Worker       if (no_error) {
386*61046927SAndroid Build Coastguard Worker          shProg = _mesa_lookup_shader_program(ctx, program);
387*61046927SAndroid Build Coastguard Worker       } else {
388*61046927SAndroid Build Coastguard Worker          shProg = _mesa_lookup_shader_program_err(ctx, program,
389*61046927SAndroid Build Coastguard Worker                                                   "glActiveShaderProgram(program)");
390*61046927SAndroid Build Coastguard Worker          if (shProg == NULL)
391*61046927SAndroid Build Coastguard Worker             return;
392*61046927SAndroid Build Coastguard Worker       }
393*61046927SAndroid Build Coastguard Worker    }
394*61046927SAndroid Build Coastguard Worker 
395*61046927SAndroid Build Coastguard Worker    if (!no_error && !pipe) {
396*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_OPERATION, "glActiveShaderProgram(pipeline)");
397*61046927SAndroid Build Coastguard Worker       return;
398*61046927SAndroid Build Coastguard Worker    }
399*61046927SAndroid Build Coastguard Worker 
400*61046927SAndroid Build Coastguard Worker    /* Object is created by any Pipeline call but glGenProgramPipelines,
401*61046927SAndroid Build Coastguard Worker     * glIsProgramPipeline and GetProgramPipelineInfoLog
402*61046927SAndroid Build Coastguard Worker     */
403*61046927SAndroid Build Coastguard Worker    pipe->EverBound = GL_TRUE;
404*61046927SAndroid Build Coastguard Worker 
405*61046927SAndroid Build Coastguard Worker    if (!no_error && shProg != NULL && !shProg->data->LinkStatus) {
406*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_OPERATION,
407*61046927SAndroid Build Coastguard Worker             "glActiveShaderProgram(program %u not linked)", shProg->Name);
408*61046927SAndroid Build Coastguard Worker       return;
409*61046927SAndroid Build Coastguard Worker    }
410*61046927SAndroid Build Coastguard Worker 
411*61046927SAndroid Build Coastguard Worker    _mesa_reference_shader_program(ctx, &pipe->ActiveProgram, shProg);
412*61046927SAndroid Build Coastguard Worker    if (pipe == ctx->_Shader)
413*61046927SAndroid Build Coastguard Worker       _mesa_update_valid_to_render_state(ctx);
414*61046927SAndroid Build Coastguard Worker }
415*61046927SAndroid Build Coastguard Worker 
416*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_ActiveShaderProgram_no_error(GLuint pipeline,GLuint program)417*61046927SAndroid Build Coastguard Worker _mesa_ActiveShaderProgram_no_error(GLuint pipeline, GLuint program)
418*61046927SAndroid Build Coastguard Worker {
419*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
420*61046927SAndroid Build Coastguard Worker    active_shader_program(ctx, pipeline, program, true);
421*61046927SAndroid Build Coastguard Worker }
422*61046927SAndroid Build Coastguard Worker 
423*61046927SAndroid Build Coastguard Worker /**
424*61046927SAndroid Build Coastguard Worker  * Use the named shader program for subsequent glUniform calls (if pipeline
425*61046927SAndroid Build Coastguard Worker  * bound)
426*61046927SAndroid Build Coastguard Worker  */
427*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_ActiveShaderProgram(GLuint pipeline,GLuint program)428*61046927SAndroid Build Coastguard Worker _mesa_ActiveShaderProgram(GLuint pipeline, GLuint program)
429*61046927SAndroid Build Coastguard Worker {
430*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
431*61046927SAndroid Build Coastguard Worker 
432*61046927SAndroid Build Coastguard Worker    if (MESA_VERBOSE & VERBOSE_API)
433*61046927SAndroid Build Coastguard Worker       _mesa_debug(ctx, "glActiveShaderProgram(%u, %u)\n", pipeline, program);
434*61046927SAndroid Build Coastguard Worker 
435*61046927SAndroid Build Coastguard Worker    active_shader_program(ctx, pipeline, program, false);
436*61046927SAndroid Build Coastguard Worker }
437*61046927SAndroid Build Coastguard Worker 
438*61046927SAndroid Build Coastguard Worker static ALWAYS_INLINE void
bind_program_pipeline(struct gl_context * ctx,GLuint pipeline,bool no_error)439*61046927SAndroid Build Coastguard Worker bind_program_pipeline(struct gl_context *ctx, GLuint pipeline, bool no_error)
440*61046927SAndroid Build Coastguard Worker {
441*61046927SAndroid Build Coastguard Worker    struct gl_pipeline_object *newObj = NULL;
442*61046927SAndroid Build Coastguard Worker 
443*61046927SAndroid Build Coastguard Worker    if (MESA_VERBOSE & VERBOSE_API)
444*61046927SAndroid Build Coastguard Worker       _mesa_debug(ctx, "glBindProgramPipeline(%u)\n", pipeline);
445*61046927SAndroid Build Coastguard Worker 
446*61046927SAndroid Build Coastguard Worker    /* Rebinding the same pipeline object: no change.
447*61046927SAndroid Build Coastguard Worker     */
448*61046927SAndroid Build Coastguard Worker    if (ctx->_Shader->Name == pipeline)
449*61046927SAndroid Build Coastguard Worker       return;
450*61046927SAndroid Build Coastguard Worker 
451*61046927SAndroid Build Coastguard Worker    /* Section 2.17.2 (Transform Feedback Primitive Capture) of the OpenGL 4.1
452*61046927SAndroid Build Coastguard Worker     * spec says:
453*61046927SAndroid Build Coastguard Worker     *
454*61046927SAndroid Build Coastguard Worker     *     "The error INVALID_OPERATION is generated:
455*61046927SAndroid Build Coastguard Worker     *
456*61046927SAndroid Build Coastguard Worker     *      ...
457*61046927SAndroid Build Coastguard Worker     *
458*61046927SAndroid Build Coastguard Worker     *         - by BindProgramPipeline if the current transform feedback
459*61046927SAndroid Build Coastguard Worker     *           object is active and not paused;
460*61046927SAndroid Build Coastguard Worker     */
461*61046927SAndroid Build Coastguard Worker    if (!no_error && _mesa_is_xfb_active_and_unpaused(ctx)) {
462*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_OPERATION,
463*61046927SAndroid Build Coastguard Worker             "glBindProgramPipeline(transform feedback active)");
464*61046927SAndroid Build Coastguard Worker       return;
465*61046927SAndroid Build Coastguard Worker    }
466*61046927SAndroid Build Coastguard Worker 
467*61046927SAndroid Build Coastguard Worker    /* Get pointer to new pipeline object (newObj)
468*61046927SAndroid Build Coastguard Worker     */
469*61046927SAndroid Build Coastguard Worker    if (pipeline) {
470*61046927SAndroid Build Coastguard Worker       /* non-default pipeline object */
471*61046927SAndroid Build Coastguard Worker       newObj = _mesa_lookup_pipeline_object(ctx, pipeline);
472*61046927SAndroid Build Coastguard Worker       if (!no_error && !newObj) {
473*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_INVALID_OPERATION,
474*61046927SAndroid Build Coastguard Worker                      "glBindProgramPipeline(non-gen name)");
475*61046927SAndroid Build Coastguard Worker          return;
476*61046927SAndroid Build Coastguard Worker       }
477*61046927SAndroid Build Coastguard Worker 
478*61046927SAndroid Build Coastguard Worker       /* Object is created by any Pipeline call but glGenProgramPipelines,
479*61046927SAndroid Build Coastguard Worker        * glIsProgramPipeline and GetProgramPipelineInfoLog
480*61046927SAndroid Build Coastguard Worker        */
481*61046927SAndroid Build Coastguard Worker       newObj->EverBound = GL_TRUE;
482*61046927SAndroid Build Coastguard Worker    }
483*61046927SAndroid Build Coastguard Worker 
484*61046927SAndroid Build Coastguard Worker    _mesa_bind_pipeline(ctx, newObj);
485*61046927SAndroid Build Coastguard Worker }
486*61046927SAndroid Build Coastguard Worker 
487*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_BindProgramPipeline_no_error(GLuint pipeline)488*61046927SAndroid Build Coastguard Worker _mesa_BindProgramPipeline_no_error(GLuint pipeline)
489*61046927SAndroid Build Coastguard Worker {
490*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
491*61046927SAndroid Build Coastguard Worker    bind_program_pipeline(ctx, pipeline, true);
492*61046927SAndroid Build Coastguard Worker }
493*61046927SAndroid Build Coastguard Worker 
494*61046927SAndroid Build Coastguard Worker /**
495*61046927SAndroid Build Coastguard Worker  * Make program of the pipeline current
496*61046927SAndroid Build Coastguard Worker  */
497*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_BindProgramPipeline(GLuint pipeline)498*61046927SAndroid Build Coastguard Worker _mesa_BindProgramPipeline(GLuint pipeline)
499*61046927SAndroid Build Coastguard Worker {
500*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
501*61046927SAndroid Build Coastguard Worker    bind_program_pipeline(ctx, pipeline, false);
502*61046927SAndroid Build Coastguard Worker }
503*61046927SAndroid Build Coastguard Worker 
504*61046927SAndroid Build Coastguard Worker void
_mesa_bind_pipeline(struct gl_context * ctx,struct gl_pipeline_object * pipe)505*61046927SAndroid Build Coastguard Worker _mesa_bind_pipeline(struct gl_context *ctx,
506*61046927SAndroid Build Coastguard Worker                     struct gl_pipeline_object *pipe)
507*61046927SAndroid Build Coastguard Worker {
508*61046927SAndroid Build Coastguard Worker    int i;
509*61046927SAndroid Build Coastguard Worker    /* First bind the Pipeline to pipeline binding point */
510*61046927SAndroid Build Coastguard Worker    _mesa_reference_pipeline_object(ctx, &ctx->Pipeline.Current, pipe);
511*61046927SAndroid Build Coastguard Worker 
512*61046927SAndroid Build Coastguard Worker    /* Section 2.11.3 (Program Objects) of the OpenGL 4.1 spec says:
513*61046927SAndroid Build Coastguard Worker     *
514*61046927SAndroid Build Coastguard Worker     *     "If there is a current program object established by UseProgram,
515*61046927SAndroid Build Coastguard Worker     *     that program is considered current for all stages. Otherwise, if
516*61046927SAndroid Build Coastguard Worker     *     there is a bound program pipeline object (see section 2.11.4), the
517*61046927SAndroid Build Coastguard Worker     *     program bound to the appropriate stage of the pipeline object is
518*61046927SAndroid Build Coastguard Worker     *     considered current."
519*61046927SAndroid Build Coastguard Worker     */
520*61046927SAndroid Build Coastguard Worker    if (&ctx->Shader != ctx->_Shader) {
521*61046927SAndroid Build Coastguard Worker       FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS, 0);
522*61046927SAndroid Build Coastguard Worker 
523*61046927SAndroid Build Coastguard Worker       if (pipe != NULL) {
524*61046927SAndroid Build Coastguard Worker          /* Bound the pipeline to the current program and
525*61046927SAndroid Build Coastguard Worker           * restore the pipeline state
526*61046927SAndroid Build Coastguard Worker           */
527*61046927SAndroid Build Coastguard Worker          _mesa_reference_pipeline_object(ctx, &ctx->_Shader, pipe);
528*61046927SAndroid Build Coastguard Worker       } else {
529*61046927SAndroid Build Coastguard Worker          /* Unbind the pipeline */
530*61046927SAndroid Build Coastguard Worker          _mesa_reference_pipeline_object(ctx, &ctx->_Shader,
531*61046927SAndroid Build Coastguard Worker                                          ctx->Pipeline.Default);
532*61046927SAndroid Build Coastguard Worker       }
533*61046927SAndroid Build Coastguard Worker 
534*61046927SAndroid Build Coastguard Worker       for (i = 0; i < MESA_SHADER_STAGES; i++) {
535*61046927SAndroid Build Coastguard Worker          struct gl_program *prog = ctx->_Shader->CurrentProgram[i];
536*61046927SAndroid Build Coastguard Worker          if (prog) {
537*61046927SAndroid Build Coastguard Worker             _mesa_program_init_subroutine_defaults(ctx, prog);
538*61046927SAndroid Build Coastguard Worker          }
539*61046927SAndroid Build Coastguard Worker       }
540*61046927SAndroid Build Coastguard Worker 
541*61046927SAndroid Build Coastguard Worker       _mesa_update_vertex_processing_mode(ctx);
542*61046927SAndroid Build Coastguard Worker       _mesa_update_allow_draw_out_of_order(ctx);
543*61046927SAndroid Build Coastguard Worker       _mesa_update_valid_to_render_state(ctx);
544*61046927SAndroid Build Coastguard Worker    }
545*61046927SAndroid Build Coastguard Worker }
546*61046927SAndroid Build Coastguard Worker 
547*61046927SAndroid Build Coastguard Worker /**
548*61046927SAndroid Build Coastguard Worker  * Delete a set of pipeline objects.
549*61046927SAndroid Build Coastguard Worker  *
550*61046927SAndroid Build Coastguard Worker  * \param n      Number of pipeline objects to delete.
551*61046927SAndroid Build Coastguard Worker  * \param ids    pipeline of \c n pipeline object IDs.
552*61046927SAndroid Build Coastguard Worker  */
553*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_DeleteProgramPipelines(GLsizei n,const GLuint * pipelines)554*61046927SAndroid Build Coastguard Worker _mesa_DeleteProgramPipelines(GLsizei n, const GLuint *pipelines)
555*61046927SAndroid Build Coastguard Worker {
556*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
557*61046927SAndroid Build Coastguard Worker    GLsizei i;
558*61046927SAndroid Build Coastguard Worker 
559*61046927SAndroid Build Coastguard Worker    if (MESA_VERBOSE & VERBOSE_API)
560*61046927SAndroid Build Coastguard Worker       _mesa_debug(ctx, "glDeleteProgramPipelines(%d, %p)\n", n, pipelines);
561*61046927SAndroid Build Coastguard Worker 
562*61046927SAndroid Build Coastguard Worker    if (n < 0) {
563*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteProgramPipelines(n<0)");
564*61046927SAndroid Build Coastguard Worker       return;
565*61046927SAndroid Build Coastguard Worker    }
566*61046927SAndroid Build Coastguard Worker 
567*61046927SAndroid Build Coastguard Worker    for (i = 0; i < n; i++) {
568*61046927SAndroid Build Coastguard Worker       struct gl_pipeline_object *obj =
569*61046927SAndroid Build Coastguard Worker          _mesa_lookup_pipeline_object(ctx, pipelines[i]);
570*61046927SAndroid Build Coastguard Worker 
571*61046927SAndroid Build Coastguard Worker       if (obj) {
572*61046927SAndroid Build Coastguard Worker          assert(obj->Name == pipelines[i]);
573*61046927SAndroid Build Coastguard Worker 
574*61046927SAndroid Build Coastguard Worker          /* If the pipeline object is currently bound, the spec says "If an
575*61046927SAndroid Build Coastguard Worker           * object that is currently bound is deleted, the binding for that
576*61046927SAndroid Build Coastguard Worker           * object reverts to zero and no program pipeline object becomes
577*61046927SAndroid Build Coastguard Worker           * current."
578*61046927SAndroid Build Coastguard Worker           */
579*61046927SAndroid Build Coastguard Worker          if (obj == ctx->Pipeline.Current) {
580*61046927SAndroid Build Coastguard Worker             _mesa_BindProgramPipeline(0);
581*61046927SAndroid Build Coastguard Worker          }
582*61046927SAndroid Build Coastguard Worker 
583*61046927SAndroid Build Coastguard Worker          /* The ID is immediately freed for re-use */
584*61046927SAndroid Build Coastguard Worker          remove_pipeline_object(ctx, obj);
585*61046927SAndroid Build Coastguard Worker 
586*61046927SAndroid Build Coastguard Worker          /* Unreference the pipeline object.
587*61046927SAndroid Build Coastguard Worker           * If refcount hits zero, the object will be deleted.
588*61046927SAndroid Build Coastguard Worker           */
589*61046927SAndroid Build Coastguard Worker          _mesa_reference_pipeline_object(ctx, &obj, NULL);
590*61046927SAndroid Build Coastguard Worker       }
591*61046927SAndroid Build Coastguard Worker    }
592*61046927SAndroid Build Coastguard Worker }
593*61046927SAndroid Build Coastguard Worker 
594*61046927SAndroid Build Coastguard Worker /**
595*61046927SAndroid Build Coastguard Worker  * Generate a set of unique pipeline object IDs and store them in \c pipelines.
596*61046927SAndroid Build Coastguard Worker  * \param n       Number of IDs to generate.
597*61046927SAndroid Build Coastguard Worker  * \param pipelines  pipeline of \c n locations to store the IDs.
598*61046927SAndroid Build Coastguard Worker  */
599*61046927SAndroid Build Coastguard Worker static void
create_program_pipelines(struct gl_context * ctx,GLsizei n,GLuint * pipelines,bool dsa)600*61046927SAndroid Build Coastguard Worker create_program_pipelines(struct gl_context *ctx, GLsizei n, GLuint *pipelines,
601*61046927SAndroid Build Coastguard Worker                          bool dsa)
602*61046927SAndroid Build Coastguard Worker {
603*61046927SAndroid Build Coastguard Worker    const char *func = dsa ? "glCreateProgramPipelines" : "glGenProgramPipelines";
604*61046927SAndroid Build Coastguard Worker    GLint i;
605*61046927SAndroid Build Coastguard Worker 
606*61046927SAndroid Build Coastguard Worker    if (!pipelines)
607*61046927SAndroid Build Coastguard Worker       return;
608*61046927SAndroid Build Coastguard Worker 
609*61046927SAndroid Build Coastguard Worker    _mesa_HashFindFreeKeys(&ctx->Pipeline.Objects, pipelines, n);
610*61046927SAndroid Build Coastguard Worker 
611*61046927SAndroid Build Coastguard Worker    for (i = 0; i < n; i++) {
612*61046927SAndroid Build Coastguard Worker       struct gl_pipeline_object *obj;
613*61046927SAndroid Build Coastguard Worker 
614*61046927SAndroid Build Coastguard Worker       obj = _mesa_new_pipeline_object(ctx, pipelines[i]);
615*61046927SAndroid Build Coastguard Worker       if (!obj) {
616*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
617*61046927SAndroid Build Coastguard Worker          return;
618*61046927SAndroid Build Coastguard Worker       }
619*61046927SAndroid Build Coastguard Worker 
620*61046927SAndroid Build Coastguard Worker       if (dsa) {
621*61046927SAndroid Build Coastguard Worker          /* make dsa-allocated objects behave like program objects */
622*61046927SAndroid Build Coastguard Worker          obj->EverBound = GL_TRUE;
623*61046927SAndroid Build Coastguard Worker       }
624*61046927SAndroid Build Coastguard Worker 
625*61046927SAndroid Build Coastguard Worker       save_pipeline_object(ctx, obj);
626*61046927SAndroid Build Coastguard Worker    }
627*61046927SAndroid Build Coastguard Worker }
628*61046927SAndroid Build Coastguard Worker 
629*61046927SAndroid Build Coastguard Worker static void
create_program_pipelines_err(struct gl_context * ctx,GLsizei n,GLuint * pipelines,bool dsa)630*61046927SAndroid Build Coastguard Worker create_program_pipelines_err(struct gl_context *ctx, GLsizei n,
631*61046927SAndroid Build Coastguard Worker                              GLuint *pipelines, bool dsa)
632*61046927SAndroid Build Coastguard Worker {
633*61046927SAndroid Build Coastguard Worker    const char *func = dsa ? "glCreateProgramPipelines" : "glGenProgramPipelines";
634*61046927SAndroid Build Coastguard Worker 
635*61046927SAndroid Build Coastguard Worker    if (n < 0) {
636*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_VALUE, "%s (n < 0)", func);
637*61046927SAndroid Build Coastguard Worker       return;
638*61046927SAndroid Build Coastguard Worker    }
639*61046927SAndroid Build Coastguard Worker 
640*61046927SAndroid Build Coastguard Worker    create_program_pipelines(ctx, n, pipelines, dsa);
641*61046927SAndroid Build Coastguard Worker }
642*61046927SAndroid Build Coastguard Worker 
643*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_GenProgramPipelines_no_error(GLsizei n,GLuint * pipelines)644*61046927SAndroid Build Coastguard Worker _mesa_GenProgramPipelines_no_error(GLsizei n, GLuint *pipelines)
645*61046927SAndroid Build Coastguard Worker {
646*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
647*61046927SAndroid Build Coastguard Worker    create_program_pipelines(ctx, n, pipelines, false);
648*61046927SAndroid Build Coastguard Worker }
649*61046927SAndroid Build Coastguard Worker 
650*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_GenProgramPipelines(GLsizei n,GLuint * pipelines)651*61046927SAndroid Build Coastguard Worker _mesa_GenProgramPipelines(GLsizei n, GLuint *pipelines)
652*61046927SAndroid Build Coastguard Worker {
653*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
654*61046927SAndroid Build Coastguard Worker 
655*61046927SAndroid Build Coastguard Worker    if (MESA_VERBOSE & VERBOSE_API)
656*61046927SAndroid Build Coastguard Worker       _mesa_debug(ctx, "glGenProgramPipelines(%d, %p)\n", n, pipelines);
657*61046927SAndroid Build Coastguard Worker 
658*61046927SAndroid Build Coastguard Worker    create_program_pipelines_err(ctx, n, pipelines, false);
659*61046927SAndroid Build Coastguard Worker }
660*61046927SAndroid Build Coastguard Worker 
661*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_CreateProgramPipelines_no_error(GLsizei n,GLuint * pipelines)662*61046927SAndroid Build Coastguard Worker _mesa_CreateProgramPipelines_no_error(GLsizei n, GLuint *pipelines)
663*61046927SAndroid Build Coastguard Worker {
664*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
665*61046927SAndroid Build Coastguard Worker    create_program_pipelines(ctx, n, pipelines, true);
666*61046927SAndroid Build Coastguard Worker }
667*61046927SAndroid Build Coastguard Worker 
668*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_CreateProgramPipelines(GLsizei n,GLuint * pipelines)669*61046927SAndroid Build Coastguard Worker _mesa_CreateProgramPipelines(GLsizei n, GLuint *pipelines)
670*61046927SAndroid Build Coastguard Worker {
671*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
672*61046927SAndroid Build Coastguard Worker 
673*61046927SAndroid Build Coastguard Worker    if (MESA_VERBOSE & VERBOSE_API)
674*61046927SAndroid Build Coastguard Worker       _mesa_debug(ctx, "glCreateProgramPipelines(%d, %p)\n", n, pipelines);
675*61046927SAndroid Build Coastguard Worker 
676*61046927SAndroid Build Coastguard Worker    create_program_pipelines_err(ctx, n, pipelines, true);
677*61046927SAndroid Build Coastguard Worker }
678*61046927SAndroid Build Coastguard Worker 
679*61046927SAndroid Build Coastguard Worker /**
680*61046927SAndroid Build Coastguard Worker  * Determine if ID is the name of an pipeline object.
681*61046927SAndroid Build Coastguard Worker  *
682*61046927SAndroid Build Coastguard Worker  * \param id  ID of the potential pipeline object.
683*61046927SAndroid Build Coastguard Worker  * \return  \c GL_TRUE if \c id is the name of a pipeline object,
684*61046927SAndroid Build Coastguard Worker  *          \c GL_FALSE otherwise.
685*61046927SAndroid Build Coastguard Worker  */
686*61046927SAndroid Build Coastguard Worker GLboolean GLAPIENTRY
_mesa_IsProgramPipeline(GLuint pipeline)687*61046927SAndroid Build Coastguard Worker _mesa_IsProgramPipeline(GLuint pipeline)
688*61046927SAndroid Build Coastguard Worker {
689*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
690*61046927SAndroid Build Coastguard Worker 
691*61046927SAndroid Build Coastguard Worker    if (MESA_VERBOSE & VERBOSE_API)
692*61046927SAndroid Build Coastguard Worker       _mesa_debug(ctx, "glIsProgramPipeline(%u)\n", pipeline);
693*61046927SAndroid Build Coastguard Worker 
694*61046927SAndroid Build Coastguard Worker    struct gl_pipeline_object *obj = _mesa_lookup_pipeline_object(ctx, pipeline);
695*61046927SAndroid Build Coastguard Worker    if (obj == NULL)
696*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
697*61046927SAndroid Build Coastguard Worker 
698*61046927SAndroid Build Coastguard Worker    return obj->EverBound;
699*61046927SAndroid Build Coastguard Worker }
700*61046927SAndroid Build Coastguard Worker 
701*61046927SAndroid Build Coastguard Worker /**
702*61046927SAndroid Build Coastguard Worker  * glGetProgramPipelineiv() - get pipeline shader state.
703*61046927SAndroid Build Coastguard Worker  */
704*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_GetProgramPipelineiv(GLuint pipeline,GLenum pname,GLint * params)705*61046927SAndroid Build Coastguard Worker _mesa_GetProgramPipelineiv(GLuint pipeline, GLenum pname, GLint *params)
706*61046927SAndroid Build Coastguard Worker {
707*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
708*61046927SAndroid Build Coastguard Worker    struct gl_pipeline_object *pipe = _mesa_lookup_pipeline_object(ctx, pipeline);
709*61046927SAndroid Build Coastguard Worker 
710*61046927SAndroid Build Coastguard Worker    if (MESA_VERBOSE & VERBOSE_API)
711*61046927SAndroid Build Coastguard Worker       _mesa_debug(ctx, "glGetProgramPipelineiv(%u, %d, %p)\n",
712*61046927SAndroid Build Coastguard Worker                   pipeline, pname, params);
713*61046927SAndroid Build Coastguard Worker 
714*61046927SAndroid Build Coastguard Worker    /* Are geometry shaders available in this context?
715*61046927SAndroid Build Coastguard Worker     */
716*61046927SAndroid Build Coastguard Worker    const bool has_gs = _mesa_has_geometry_shaders(ctx);
717*61046927SAndroid Build Coastguard Worker    const bool has_tess = _mesa_has_tessellation(ctx);
718*61046927SAndroid Build Coastguard Worker 
719*61046927SAndroid Build Coastguard Worker    if (!pipe) {
720*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_OPERATION,
721*61046927SAndroid Build Coastguard Worker                   "glGetProgramPipelineiv(pipeline)");
722*61046927SAndroid Build Coastguard Worker       return;
723*61046927SAndroid Build Coastguard Worker    }
724*61046927SAndroid Build Coastguard Worker 
725*61046927SAndroid Build Coastguard Worker    /* Object is created by any Pipeline call but glGenProgramPipelines,
726*61046927SAndroid Build Coastguard Worker     * glIsProgramPipeline and GetProgramPipelineInfoLog
727*61046927SAndroid Build Coastguard Worker     */
728*61046927SAndroid Build Coastguard Worker    pipe->EverBound = GL_TRUE;
729*61046927SAndroid Build Coastguard Worker 
730*61046927SAndroid Build Coastguard Worker    switch (pname) {
731*61046927SAndroid Build Coastguard Worker    case GL_ACTIVE_PROGRAM:
732*61046927SAndroid Build Coastguard Worker       *params = pipe->ActiveProgram ? pipe->ActiveProgram->Name : 0;
733*61046927SAndroid Build Coastguard Worker       return;
734*61046927SAndroid Build Coastguard Worker    case GL_INFO_LOG_LENGTH:
735*61046927SAndroid Build Coastguard Worker       *params = (pipe->InfoLog && pipe->InfoLog[0] != '\0') ?
736*61046927SAndroid Build Coastguard Worker          strlen(pipe->InfoLog) + 1 : 0;
737*61046927SAndroid Build Coastguard Worker       return;
738*61046927SAndroid Build Coastguard Worker    case GL_VALIDATE_STATUS:
739*61046927SAndroid Build Coastguard Worker       *params = pipe->UserValidated;
740*61046927SAndroid Build Coastguard Worker       return;
741*61046927SAndroid Build Coastguard Worker    case GL_VERTEX_SHADER:
742*61046927SAndroid Build Coastguard Worker       *params = pipe->CurrentProgram[MESA_SHADER_VERTEX]
743*61046927SAndroid Build Coastguard Worker          ? pipe->CurrentProgram[MESA_SHADER_VERTEX]->Id : 0;
744*61046927SAndroid Build Coastguard Worker       return;
745*61046927SAndroid Build Coastguard Worker    case GL_TESS_EVALUATION_SHADER:
746*61046927SAndroid Build Coastguard Worker       if (!has_tess)
747*61046927SAndroid Build Coastguard Worker          break;
748*61046927SAndroid Build Coastguard Worker       *params = pipe->CurrentProgram[MESA_SHADER_TESS_EVAL]
749*61046927SAndroid Build Coastguard Worker          ? pipe->CurrentProgram[MESA_SHADER_TESS_EVAL]->Id : 0;
750*61046927SAndroid Build Coastguard Worker       return;
751*61046927SAndroid Build Coastguard Worker    case GL_TESS_CONTROL_SHADER:
752*61046927SAndroid Build Coastguard Worker       if (!has_tess)
753*61046927SAndroid Build Coastguard Worker          break;
754*61046927SAndroid Build Coastguard Worker       *params = pipe->CurrentProgram[MESA_SHADER_TESS_CTRL]
755*61046927SAndroid Build Coastguard Worker          ? pipe->CurrentProgram[MESA_SHADER_TESS_CTRL]->Id : 0;
756*61046927SAndroid Build Coastguard Worker       return;
757*61046927SAndroid Build Coastguard Worker    case GL_GEOMETRY_SHADER:
758*61046927SAndroid Build Coastguard Worker       if (!has_gs)
759*61046927SAndroid Build Coastguard Worker          break;
760*61046927SAndroid Build Coastguard Worker       *params = pipe->CurrentProgram[MESA_SHADER_GEOMETRY]
761*61046927SAndroid Build Coastguard Worker          ? pipe->CurrentProgram[MESA_SHADER_GEOMETRY]->Id : 0;
762*61046927SAndroid Build Coastguard Worker       return;
763*61046927SAndroid Build Coastguard Worker    case GL_FRAGMENT_SHADER:
764*61046927SAndroid Build Coastguard Worker       *params = pipe->CurrentProgram[MESA_SHADER_FRAGMENT]
765*61046927SAndroid Build Coastguard Worker          ? pipe->CurrentProgram[MESA_SHADER_FRAGMENT]->Id : 0;
766*61046927SAndroid Build Coastguard Worker       return;
767*61046927SAndroid Build Coastguard Worker    case GL_COMPUTE_SHADER:
768*61046927SAndroid Build Coastguard Worker       if (!_mesa_has_compute_shaders(ctx))
769*61046927SAndroid Build Coastguard Worker          break;
770*61046927SAndroid Build Coastguard Worker       *params = pipe->CurrentProgram[MESA_SHADER_COMPUTE]
771*61046927SAndroid Build Coastguard Worker          ? pipe->CurrentProgram[MESA_SHADER_COMPUTE]->Id : 0;
772*61046927SAndroid Build Coastguard Worker       return;
773*61046927SAndroid Build Coastguard Worker    default:
774*61046927SAndroid Build Coastguard Worker       break;
775*61046927SAndroid Build Coastguard Worker    }
776*61046927SAndroid Build Coastguard Worker 
777*61046927SAndroid Build Coastguard Worker    _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramPipelineiv(pname=%s)",
778*61046927SAndroid Build Coastguard Worker                _mesa_enum_to_string(pname));
779*61046927SAndroid Build Coastguard Worker }
780*61046927SAndroid Build Coastguard Worker 
781*61046927SAndroid Build Coastguard Worker /**
782*61046927SAndroid Build Coastguard Worker  * Determines whether every stage in a linked program is active in the
783*61046927SAndroid Build Coastguard Worker  * specified pipeline.
784*61046927SAndroid Build Coastguard Worker  */
785*61046927SAndroid Build Coastguard Worker static bool
program_stages_all_active(struct gl_pipeline_object * pipe,const struct gl_program * prog)786*61046927SAndroid Build Coastguard Worker program_stages_all_active(struct gl_pipeline_object *pipe,
787*61046927SAndroid Build Coastguard Worker                           const struct gl_program *prog)
788*61046927SAndroid Build Coastguard Worker {
789*61046927SAndroid Build Coastguard Worker    bool status = true;
790*61046927SAndroid Build Coastguard Worker 
791*61046927SAndroid Build Coastguard Worker    if (!prog)
792*61046927SAndroid Build Coastguard Worker       return true;
793*61046927SAndroid Build Coastguard Worker 
794*61046927SAndroid Build Coastguard Worker    unsigned mask = prog->sh.data->linked_stages;
795*61046927SAndroid Build Coastguard Worker    while (mask) {
796*61046927SAndroid Build Coastguard Worker       const int i = u_bit_scan(&mask);
797*61046927SAndroid Build Coastguard Worker       if (pipe->CurrentProgram[i]) {
798*61046927SAndroid Build Coastguard Worker          if (prog->Id != pipe->CurrentProgram[i]->Id) {
799*61046927SAndroid Build Coastguard Worker             status = false;
800*61046927SAndroid Build Coastguard Worker          }
801*61046927SAndroid Build Coastguard Worker       } else {
802*61046927SAndroid Build Coastguard Worker          status = false;
803*61046927SAndroid Build Coastguard Worker       }
804*61046927SAndroid Build Coastguard Worker    }
805*61046927SAndroid Build Coastguard Worker 
806*61046927SAndroid Build Coastguard Worker    if (!status) {
807*61046927SAndroid Build Coastguard Worker       pipe->InfoLog = ralloc_asprintf(pipe,
808*61046927SAndroid Build Coastguard Worker                                       "Program %d is not active for all "
809*61046927SAndroid Build Coastguard Worker                                       "shaders that was linked",
810*61046927SAndroid Build Coastguard Worker                                       prog->Id);
811*61046927SAndroid Build Coastguard Worker    }
812*61046927SAndroid Build Coastguard Worker 
813*61046927SAndroid Build Coastguard Worker    return status;
814*61046927SAndroid Build Coastguard Worker }
815*61046927SAndroid Build Coastguard Worker 
816*61046927SAndroid Build Coastguard Worker static bool
program_stages_interleaved_illegally(const struct gl_pipeline_object * pipe)817*61046927SAndroid Build Coastguard Worker program_stages_interleaved_illegally(const struct gl_pipeline_object *pipe)
818*61046927SAndroid Build Coastguard Worker {
819*61046927SAndroid Build Coastguard Worker    unsigned prev_linked_stages = 0;
820*61046927SAndroid Build Coastguard Worker 
821*61046927SAndroid Build Coastguard Worker    /* Look for programs bound to stages: A -> B -> A, with any intervening
822*61046927SAndroid Build Coastguard Worker     * sequence of unrelated programs or empty stages.
823*61046927SAndroid Build Coastguard Worker     */
824*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
825*61046927SAndroid Build Coastguard Worker       struct gl_program *cur = pipe->CurrentProgram[i];
826*61046927SAndroid Build Coastguard Worker 
827*61046927SAndroid Build Coastguard Worker       /* Empty stages anywhere in the pipe are OK.  Also we can be confident
828*61046927SAndroid Build Coastguard Worker        * that if the linked_stages mask matches we are looking at the same
829*61046927SAndroid Build Coastguard Worker        * linked program because a previous validation call to
830*61046927SAndroid Build Coastguard Worker        * program_stages_all_active() will have already failed if two different
831*61046927SAndroid Build Coastguard Worker        * programs with the sames stages linked are not active for all linked
832*61046927SAndroid Build Coastguard Worker        * stages.
833*61046927SAndroid Build Coastguard Worker        */
834*61046927SAndroid Build Coastguard Worker       if (!cur || cur->sh.data->linked_stages == prev_linked_stages)
835*61046927SAndroid Build Coastguard Worker          continue;
836*61046927SAndroid Build Coastguard Worker 
837*61046927SAndroid Build Coastguard Worker       if (prev_linked_stages) {
838*61046927SAndroid Build Coastguard Worker          /* We've seen an A -> B transition; look at the rest of the pipe
839*61046927SAndroid Build Coastguard Worker           * to see if we ever see A again.
840*61046927SAndroid Build Coastguard Worker           */
841*61046927SAndroid Build Coastguard Worker          if (prev_linked_stages >> (i + 1))
842*61046927SAndroid Build Coastguard Worker             return true;
843*61046927SAndroid Build Coastguard Worker       }
844*61046927SAndroid Build Coastguard Worker 
845*61046927SAndroid Build Coastguard Worker       prev_linked_stages = cur->sh.data->linked_stages;
846*61046927SAndroid Build Coastguard Worker    }
847*61046927SAndroid Build Coastguard Worker 
848*61046927SAndroid Build Coastguard Worker    return false;
849*61046927SAndroid Build Coastguard Worker }
850*61046927SAndroid Build Coastguard Worker 
851*61046927SAndroid Build Coastguard Worker extern GLboolean
_mesa_validate_program_pipeline(struct gl_context * ctx,struct gl_pipeline_object * pipe)852*61046927SAndroid Build Coastguard Worker _mesa_validate_program_pipeline(struct gl_context* ctx,
853*61046927SAndroid Build Coastguard Worker                                 struct gl_pipeline_object *pipe)
854*61046927SAndroid Build Coastguard Worker {
855*61046927SAndroid Build Coastguard Worker    unsigned i;
856*61046927SAndroid Build Coastguard Worker    bool program_empty = true;
857*61046927SAndroid Build Coastguard Worker 
858*61046927SAndroid Build Coastguard Worker    pipe->Validated = GL_FALSE;
859*61046927SAndroid Build Coastguard Worker 
860*61046927SAndroid Build Coastguard Worker    /* Release and reset the info log.
861*61046927SAndroid Build Coastguard Worker     */
862*61046927SAndroid Build Coastguard Worker    if (pipe->InfoLog != NULL)
863*61046927SAndroid Build Coastguard Worker       ralloc_free(pipe->InfoLog);
864*61046927SAndroid Build Coastguard Worker 
865*61046927SAndroid Build Coastguard Worker    pipe->InfoLog = NULL;
866*61046927SAndroid Build Coastguard Worker 
867*61046927SAndroid Build Coastguard Worker    /* Section 2.11.11 (Shader Execution), subheading "Validation," of the
868*61046927SAndroid Build Coastguard Worker     * OpenGL 4.1 spec says:
869*61046927SAndroid Build Coastguard Worker     *
870*61046927SAndroid Build Coastguard Worker     *     "[INVALID_OPERATION] is generated by any command that transfers
871*61046927SAndroid Build Coastguard Worker     *     vertices to the GL if:
872*61046927SAndroid Build Coastguard Worker     *
873*61046927SAndroid Build Coastguard Worker     *         - A program object is active for at least one, but not all of
874*61046927SAndroid Build Coastguard Worker     *           the shader stages that were present when the program was
875*61046927SAndroid Build Coastguard Worker     *           linked."
876*61046927SAndroid Build Coastguard Worker     *
877*61046927SAndroid Build Coastguard Worker     * For each possible program stage, verify that the program bound to that
878*61046927SAndroid Build Coastguard Worker     * stage has all of its stages active.  In other words, if the program
879*61046927SAndroid Build Coastguard Worker     * bound to the vertex stage also has a fragment shader, the fragment
880*61046927SAndroid Build Coastguard Worker     * shader must also be bound to the fragment stage.
881*61046927SAndroid Build Coastguard Worker     */
882*61046927SAndroid Build Coastguard Worker    for (i = 0; i < MESA_SHADER_STAGES; i++) {
883*61046927SAndroid Build Coastguard Worker       if (!program_stages_all_active(pipe, pipe->CurrentProgram[i])) {
884*61046927SAndroid Build Coastguard Worker          return GL_FALSE;
885*61046927SAndroid Build Coastguard Worker       }
886*61046927SAndroid Build Coastguard Worker    }
887*61046927SAndroid Build Coastguard Worker 
888*61046927SAndroid Build Coastguard Worker    /* Section 2.11.11 (Shader Execution), subheading "Validation," of the
889*61046927SAndroid Build Coastguard Worker     * OpenGL 4.1 spec says:
890*61046927SAndroid Build Coastguard Worker     *
891*61046927SAndroid Build Coastguard Worker     *     "[INVALID_OPERATION] is generated by any command that transfers
892*61046927SAndroid Build Coastguard Worker     *     vertices to the GL if:
893*61046927SAndroid Build Coastguard Worker     *
894*61046927SAndroid Build Coastguard Worker     *         ...
895*61046927SAndroid Build Coastguard Worker     *
896*61046927SAndroid Build Coastguard Worker     *         - One program object is active for at least two shader stages
897*61046927SAndroid Build Coastguard Worker     *           and a second program is active for a shader stage between two
898*61046927SAndroid Build Coastguard Worker     *           stages for which the first program was active."
899*61046927SAndroid Build Coastguard Worker     */
900*61046927SAndroid Build Coastguard Worker    if (program_stages_interleaved_illegally(pipe)) {
901*61046927SAndroid Build Coastguard Worker       pipe->InfoLog =
902*61046927SAndroid Build Coastguard Worker          ralloc_strdup(pipe,
903*61046927SAndroid Build Coastguard Worker                        "Program is active for multiple shader stages with an "
904*61046927SAndroid Build Coastguard Worker                        "intervening stage provided by another program");
905*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
906*61046927SAndroid Build Coastguard Worker    }
907*61046927SAndroid Build Coastguard Worker 
908*61046927SAndroid Build Coastguard Worker    /* Section 2.11.11 (Shader Execution), subheading "Validation," of the
909*61046927SAndroid Build Coastguard Worker     * OpenGL 4.1 spec says:
910*61046927SAndroid Build Coastguard Worker     *
911*61046927SAndroid Build Coastguard Worker     *     "[INVALID_OPERATION] is generated by any command that transfers
912*61046927SAndroid Build Coastguard Worker     *     vertices to the GL if:
913*61046927SAndroid Build Coastguard Worker     *
914*61046927SAndroid Build Coastguard Worker     *         ...
915*61046927SAndroid Build Coastguard Worker     *
916*61046927SAndroid Build Coastguard Worker     *         - There is an active program for tessellation control,
917*61046927SAndroid Build Coastguard Worker     *           tessellation evaluation, or geometry stages with corresponding
918*61046927SAndroid Build Coastguard Worker     *           executable shader, but there is no active program with
919*61046927SAndroid Build Coastguard Worker     *           executable vertex shader."
920*61046927SAndroid Build Coastguard Worker     */
921*61046927SAndroid Build Coastguard Worker    if (!pipe->CurrentProgram[MESA_SHADER_VERTEX]
922*61046927SAndroid Build Coastguard Worker        && (pipe->CurrentProgram[MESA_SHADER_GEOMETRY] ||
923*61046927SAndroid Build Coastguard Worker            pipe->CurrentProgram[MESA_SHADER_TESS_CTRL] ||
924*61046927SAndroid Build Coastguard Worker            pipe->CurrentProgram[MESA_SHADER_TESS_EVAL])) {
925*61046927SAndroid Build Coastguard Worker       pipe->InfoLog = ralloc_strdup(pipe, "Program lacks a vertex shader");
926*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
927*61046927SAndroid Build Coastguard Worker    }
928*61046927SAndroid Build Coastguard Worker 
929*61046927SAndroid Build Coastguard Worker    /* Section 2.11.11 (Shader Execution), subheading "Validation," of the
930*61046927SAndroid Build Coastguard Worker     * OpenGL 4.1 spec says:
931*61046927SAndroid Build Coastguard Worker     *
932*61046927SAndroid Build Coastguard Worker     *     "[INVALID_OPERATION] is generated by any command that transfers
933*61046927SAndroid Build Coastguard Worker     *     vertices to the GL if:
934*61046927SAndroid Build Coastguard Worker     *
935*61046927SAndroid Build Coastguard Worker     *         ...
936*61046927SAndroid Build Coastguard Worker     *
937*61046927SAndroid Build Coastguard Worker     *         - There is no current program object specified by UseProgram,
938*61046927SAndroid Build Coastguard Worker     *           there is a current program pipeline object, and the current
939*61046927SAndroid Build Coastguard Worker     *           program for any shader stage has been relinked since being
940*61046927SAndroid Build Coastguard Worker     *           applied to the pipeline object via UseProgramStages with the
941*61046927SAndroid Build Coastguard Worker     *           PROGRAM_SEPARABLE parameter set to FALSE.
942*61046927SAndroid Build Coastguard Worker     */
943*61046927SAndroid Build Coastguard Worker    for (i = 0; i < MESA_SHADER_STAGES; i++) {
944*61046927SAndroid Build Coastguard Worker       if (pipe->CurrentProgram[i] &&
945*61046927SAndroid Build Coastguard Worker           !pipe->CurrentProgram[i]->info.separate_shader) {
946*61046927SAndroid Build Coastguard Worker          pipe->InfoLog = ralloc_asprintf(pipe,
947*61046927SAndroid Build Coastguard Worker                                          "Program %d was relinked without "
948*61046927SAndroid Build Coastguard Worker                                          "PROGRAM_SEPARABLE state",
949*61046927SAndroid Build Coastguard Worker                                          pipe->CurrentProgram[i]->Id);
950*61046927SAndroid Build Coastguard Worker          return GL_FALSE;
951*61046927SAndroid Build Coastguard Worker       }
952*61046927SAndroid Build Coastguard Worker    }
953*61046927SAndroid Build Coastguard Worker 
954*61046927SAndroid Build Coastguard Worker    /* Section 11.1.3.11 (Validation) of the OpenGL 4.5 spec says:
955*61046927SAndroid Build Coastguard Worker     *
956*61046927SAndroid Build Coastguard Worker     *    "An INVALID_OPERATION error is generated by any command that trans-
957*61046927SAndroid Build Coastguard Worker     *    fers vertices to the GL or launches compute work if the current set
958*61046927SAndroid Build Coastguard Worker     *    of active program objects cannot be executed, for reasons including:
959*61046927SAndroid Build Coastguard Worker     *
960*61046927SAndroid Build Coastguard Worker     *       ...
961*61046927SAndroid Build Coastguard Worker     *
962*61046927SAndroid Build Coastguard Worker     *       - There is no current program object specified by UseProgram,
963*61046927SAndroid Build Coastguard Worker     *         there is a current program pipeline object, and that object is
964*61046927SAndroid Build Coastguard Worker     *         empty (no executable code is installed for any stage).
965*61046927SAndroid Build Coastguard Worker     */
966*61046927SAndroid Build Coastguard Worker    for (i = 0; i < MESA_SHADER_STAGES; i++) {
967*61046927SAndroid Build Coastguard Worker       if (pipe->CurrentProgram[i]) {
968*61046927SAndroid Build Coastguard Worker          program_empty = false;
969*61046927SAndroid Build Coastguard Worker          break;
970*61046927SAndroid Build Coastguard Worker       }
971*61046927SAndroid Build Coastguard Worker    }
972*61046927SAndroid Build Coastguard Worker 
973*61046927SAndroid Build Coastguard Worker    if (program_empty) {
974*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
975*61046927SAndroid Build Coastguard Worker    }
976*61046927SAndroid Build Coastguard Worker 
977*61046927SAndroid Build Coastguard Worker    /* Section 2.11.11 (Shader Execution), subheading "Validation," of the
978*61046927SAndroid Build Coastguard Worker     * OpenGL 4.1 spec says:
979*61046927SAndroid Build Coastguard Worker     *
980*61046927SAndroid Build Coastguard Worker     *     "[INVALID_OPERATION] is generated by any command that transfers
981*61046927SAndroid Build Coastguard Worker     *     vertices to the GL if:
982*61046927SAndroid Build Coastguard Worker     *
983*61046927SAndroid Build Coastguard Worker     *         ...
984*61046927SAndroid Build Coastguard Worker     *
985*61046927SAndroid Build Coastguard Worker     *         - Any two active samplers in the current program object are of
986*61046927SAndroid Build Coastguard Worker     *           different types, but refer to the same texture image unit.
987*61046927SAndroid Build Coastguard Worker     *
988*61046927SAndroid Build Coastguard Worker     *         - The number of active samplers in the program exceeds the
989*61046927SAndroid Build Coastguard Worker     *           maximum number of texture image units allowed."
990*61046927SAndroid Build Coastguard Worker     */
991*61046927SAndroid Build Coastguard Worker    if (!_mesa_sampler_uniforms_pipeline_are_valid(pipe))
992*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
993*61046927SAndroid Build Coastguard Worker 
994*61046927SAndroid Build Coastguard Worker    /* Validate inputs against outputs, this cannot be done during linking
995*61046927SAndroid Build Coastguard Worker     * since programs have been linked separately from each other.
996*61046927SAndroid Build Coastguard Worker     *
997*61046927SAndroid Build Coastguard Worker     * Section 11.1.3.11 (Validation) of the OpenGL 4.5 Core Profile spec says:
998*61046927SAndroid Build Coastguard Worker     *
999*61046927SAndroid Build Coastguard Worker     *     "Separable program objects may have validation failures that cannot be
1000*61046927SAndroid Build Coastguard Worker     *     detected without the complete program pipeline. Mismatched interfaces,
1001*61046927SAndroid Build Coastguard Worker     *     improper usage of program objects together, and the same
1002*61046927SAndroid Build Coastguard Worker     *     state-dependent failures can result in validation errors for such
1003*61046927SAndroid Build Coastguard Worker     *     program objects."
1004*61046927SAndroid Build Coastguard Worker     *
1005*61046927SAndroid Build Coastguard Worker     * OpenGL ES 3.1 specification has the same text.
1006*61046927SAndroid Build Coastguard Worker     *
1007*61046927SAndroid Build Coastguard Worker     * Section 11.1.3.11 (Validation) of the OpenGL ES spec also says:
1008*61046927SAndroid Build Coastguard Worker     *
1009*61046927SAndroid Build Coastguard Worker     *    An INVALID_OPERATION error is generated by any command that transfers
1010*61046927SAndroid Build Coastguard Worker     *    vertices to the GL or launches compute work if the current set of
1011*61046927SAndroid Build Coastguard Worker     *    active program objects cannot be executed, for reasons including:
1012*61046927SAndroid Build Coastguard Worker     *
1013*61046927SAndroid Build Coastguard Worker     *    * The current program pipeline object contains a shader interface
1014*61046927SAndroid Build Coastguard Worker     *      that doesn't have an exact match (see section 7.4.1)
1015*61046927SAndroid Build Coastguard Worker     *
1016*61046927SAndroid Build Coastguard Worker     * Based on this, only perform the most-strict checking on ES or when the
1017*61046927SAndroid Build Coastguard Worker     * application has created a debug context.
1018*61046927SAndroid Build Coastguard Worker     */
1019*61046927SAndroid Build Coastguard Worker    if ((_mesa_is_gles(ctx) || (ctx->Const.ContextFlags & GL_CONTEXT_FLAG_DEBUG_BIT)) &&
1020*61046927SAndroid Build Coastguard Worker        !_mesa_validate_pipeline_io(pipe)) {
1021*61046927SAndroid Build Coastguard Worker       if (_mesa_is_gles(ctx))
1022*61046927SAndroid Build Coastguard Worker          return GL_FALSE;
1023*61046927SAndroid Build Coastguard Worker 
1024*61046927SAndroid Build Coastguard Worker       static GLuint msg_id = 0;
1025*61046927SAndroid Build Coastguard Worker 
1026*61046927SAndroid Build Coastguard Worker       _mesa_gl_debugf(ctx, &msg_id,
1027*61046927SAndroid Build Coastguard Worker                       MESA_DEBUG_SOURCE_API,
1028*61046927SAndroid Build Coastguard Worker                       MESA_DEBUG_TYPE_PORTABILITY,
1029*61046927SAndroid Build Coastguard Worker                       MESA_DEBUG_SEVERITY_MEDIUM,
1030*61046927SAndroid Build Coastguard Worker                       "glValidateProgramPipeline: pipeline %u does not meet "
1031*61046927SAndroid Build Coastguard Worker                       "strict OpenGL ES 3.1 requirements and may not be "
1032*61046927SAndroid Build Coastguard Worker                       "portable across desktop hardware\n",
1033*61046927SAndroid Build Coastguard Worker                       pipe->Name);
1034*61046927SAndroid Build Coastguard Worker    }
1035*61046927SAndroid Build Coastguard Worker 
1036*61046927SAndroid Build Coastguard Worker    pipe->Validated = GL_TRUE;
1037*61046927SAndroid Build Coastguard Worker    return GL_TRUE;
1038*61046927SAndroid Build Coastguard Worker }
1039*61046927SAndroid Build Coastguard Worker 
1040*61046927SAndroid Build Coastguard Worker /**
1041*61046927SAndroid Build Coastguard Worker  * Check compatibility of pipeline's program
1042*61046927SAndroid Build Coastguard Worker  */
1043*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_ValidateProgramPipeline(GLuint pipeline)1044*61046927SAndroid Build Coastguard Worker _mesa_ValidateProgramPipeline(GLuint pipeline)
1045*61046927SAndroid Build Coastguard Worker {
1046*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
1047*61046927SAndroid Build Coastguard Worker 
1048*61046927SAndroid Build Coastguard Worker    if (MESA_VERBOSE & VERBOSE_API)
1049*61046927SAndroid Build Coastguard Worker       _mesa_debug(ctx, "glValidateProgramPipeline(%u)\n", pipeline);
1050*61046927SAndroid Build Coastguard Worker 
1051*61046927SAndroid Build Coastguard Worker    struct gl_pipeline_object *pipe = _mesa_lookup_pipeline_object(ctx, pipeline);
1052*61046927SAndroid Build Coastguard Worker 
1053*61046927SAndroid Build Coastguard Worker    if (!pipe) {
1054*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_OPERATION,
1055*61046927SAndroid Build Coastguard Worker                   "glValidateProgramPipeline(pipeline)");
1056*61046927SAndroid Build Coastguard Worker       return;
1057*61046927SAndroid Build Coastguard Worker    }
1058*61046927SAndroid Build Coastguard Worker 
1059*61046927SAndroid Build Coastguard Worker    _mesa_validate_program_pipeline(ctx, pipe);
1060*61046927SAndroid Build Coastguard Worker    pipe->UserValidated = pipe->Validated;
1061*61046927SAndroid Build Coastguard Worker }
1062*61046927SAndroid Build Coastguard Worker 
1063*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_GetProgramPipelineInfoLog(GLuint pipeline,GLsizei bufSize,GLsizei * length,GLchar * infoLog)1064*61046927SAndroid Build Coastguard Worker _mesa_GetProgramPipelineInfoLog(GLuint pipeline, GLsizei bufSize,
1065*61046927SAndroid Build Coastguard Worker                                 GLsizei *length, GLchar *infoLog)
1066*61046927SAndroid Build Coastguard Worker {
1067*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
1068*61046927SAndroid Build Coastguard Worker 
1069*61046927SAndroid Build Coastguard Worker    if (MESA_VERBOSE & VERBOSE_API)
1070*61046927SAndroid Build Coastguard Worker       _mesa_debug(ctx, "glGetProgramPipelineInfoLog(%u, %d, %p, %p)\n",
1071*61046927SAndroid Build Coastguard Worker                   pipeline, bufSize, length, infoLog);
1072*61046927SAndroid Build Coastguard Worker 
1073*61046927SAndroid Build Coastguard Worker    struct gl_pipeline_object *pipe = _mesa_lookup_pipeline_object(ctx, pipeline);
1074*61046927SAndroid Build Coastguard Worker 
1075*61046927SAndroid Build Coastguard Worker    if (!pipe) {
1076*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_VALUE,
1077*61046927SAndroid Build Coastguard Worker                   "glGetProgramPipelineInfoLog(pipeline)");
1078*61046927SAndroid Build Coastguard Worker       return;
1079*61046927SAndroid Build Coastguard Worker    }
1080*61046927SAndroid Build Coastguard Worker 
1081*61046927SAndroid Build Coastguard Worker    if (bufSize < 0) {
1082*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_VALUE,
1083*61046927SAndroid Build Coastguard Worker                   "glGetProgramPipelineInfoLog(bufSize)");
1084*61046927SAndroid Build Coastguard Worker       return;
1085*61046927SAndroid Build Coastguard Worker    }
1086*61046927SAndroid Build Coastguard Worker 
1087*61046927SAndroid Build Coastguard Worker    _mesa_copy_string(infoLog, bufSize, length, pipe->InfoLog);
1088*61046927SAndroid Build Coastguard Worker }
1089