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