mesa: Make metaops use program refcounts instead of names.
Fixes failure on restoring state when the program was active but deleted, and the name no longer exists. Bug #31194
This commit is contained in:
@@ -52,6 +52,7 @@
|
|||||||
#include "main/readpix.h"
|
#include "main/readpix.h"
|
||||||
#include "main/scissor.h"
|
#include "main/scissor.h"
|
||||||
#include "main/shaderapi.h"
|
#include "main/shaderapi.h"
|
||||||
|
#include "main/shaderobj.h"
|
||||||
#include "main/state.h"
|
#include "main/state.h"
|
||||||
#include "main/stencil.h"
|
#include "main/stencil.h"
|
||||||
#include "main/texobj.h"
|
#include "main/texobj.h"
|
||||||
@@ -143,10 +144,10 @@ struct save_state
|
|||||||
struct gl_vertex_program *VertexProgram;
|
struct gl_vertex_program *VertexProgram;
|
||||||
GLboolean FragmentProgramEnabled;
|
GLboolean FragmentProgramEnabled;
|
||||||
struct gl_fragment_program *FragmentProgram;
|
struct gl_fragment_program *FragmentProgram;
|
||||||
GLuint VertexShader;
|
struct gl_shader_program *VertexShader;
|
||||||
GLuint GeometryShader;
|
struct gl_shader_program *GeometryShader;
|
||||||
GLuint FragmentShader;
|
struct gl_shader_program *FragmentShader;
|
||||||
GLuint ActiveShader;
|
struct gl_shader_program *ActiveShader;
|
||||||
|
|
||||||
/** META_STENCIL_TEST */
|
/** META_STENCIL_TEST */
|
||||||
struct gl_stencil_attrib Stencil;
|
struct gl_stencil_attrib Stencil;
|
||||||
@@ -436,14 +437,14 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->Extensions.ARB_shader_objects) {
|
if (ctx->Extensions.ARB_shader_objects) {
|
||||||
save->VertexShader = ctx->Shader.CurrentVertexProgram ?
|
_mesa_reference_shader_program(ctx, &save->VertexShader,
|
||||||
ctx->Shader.CurrentVertexProgram->Name : 0;
|
ctx->Shader.CurrentVertexProgram);
|
||||||
save->GeometryShader = ctx->Shader.CurrentGeometryProgram ?
|
_mesa_reference_shader_program(ctx, &save->GeometryShader,
|
||||||
ctx->Shader.CurrentGeometryProgram->Name : 0;
|
ctx->Shader.CurrentGeometryProgram);
|
||||||
save->FragmentShader = ctx->Shader.CurrentFragmentProgram ?
|
_mesa_reference_shader_program(ctx, &save->FragmentShader,
|
||||||
ctx->Shader.CurrentFragmentProgram->Name : 0;
|
ctx->Shader.CurrentFragmentProgram);
|
||||||
save->ActiveShader = ctx->Shader.ActiveProgram ?
|
_mesa_reference_shader_program(ctx, &save->ActiveShader,
|
||||||
ctx->Shader.ActiveProgram->Name : 0;
|
ctx->Shader.CurrentFragmentProgram);
|
||||||
|
|
||||||
_mesa_UseProgramObjectARB(0);
|
_mesa_UseProgramObjectARB(0);
|
||||||
}
|
}
|
||||||
@@ -675,16 +676,18 @@ _mesa_meta_end(struct gl_context *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->Extensions.ARB_vertex_shader)
|
if (ctx->Extensions.ARB_vertex_shader)
|
||||||
_mesa_UseShaderProgramEXT(GL_VERTEX_SHADER, save->VertexShader);
|
_mesa_use_shader_program(ctx, GL_VERTEX_SHADER, save->VertexShader);
|
||||||
|
|
||||||
if (ctx->Extensions.ARB_geometry_shader4)
|
if (ctx->Extensions.ARB_geometry_shader4)
|
||||||
_mesa_UseShaderProgramEXT(GL_GEOMETRY_SHADER_ARB,
|
_mesa_use_shader_program(ctx, GL_GEOMETRY_SHADER_ARB,
|
||||||
save->GeometryShader);
|
save->GeometryShader);
|
||||||
|
|
||||||
if (ctx->Extensions.ARB_fragment_shader)
|
if (ctx->Extensions.ARB_fragment_shader)
|
||||||
_mesa_UseShaderProgramEXT(GL_FRAGMENT_SHADER, save->FragmentShader);
|
_mesa_use_shader_program(ctx, GL_FRAGMENT_SHADER,
|
||||||
|
save->FragmentShader);
|
||||||
|
|
||||||
_mesa_ActiveProgramEXT(save->ActiveShader);
|
_mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram,
|
||||||
|
save->ActiveShader);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state & META_STENCIL_TEST) {
|
if (state & META_STENCIL_TEST) {
|
||||||
|
@@ -936,9 +936,9 @@ print_shader_info(const struct gl_shader_program *shProg)
|
|||||||
/**
|
/**
|
||||||
* Use the named shader program for subsequent glUniform calls
|
* Use the named shader program for subsequent glUniform calls
|
||||||
*/
|
*/
|
||||||
static void
|
void
|
||||||
active_program(struct gl_context *ctx, struct gl_shader_program *shProg,
|
_mesa_active_program(struct gl_context *ctx, struct gl_shader_program *shProg,
|
||||||
const char *caller)
|
const char *caller)
|
||||||
{
|
{
|
||||||
if ((shProg != NULL) && !shProg->LinkStatus) {
|
if ((shProg != NULL) && !shProg->LinkStatus) {
|
||||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||||
@@ -1003,45 +1003,16 @@ use_shader_program(struct gl_context *ctx, GLenum type,
|
|||||||
* Use the named shader program for subsequent rendering.
|
* Use the named shader program for subsequent rendering.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
_mesa_use_program(struct gl_context *ctx, GLuint program)
|
_mesa_use_program(struct gl_context *ctx, struct gl_shader_program *shProg)
|
||||||
{
|
{
|
||||||
struct gl_shader_program *shProg;
|
|
||||||
struct gl_transform_feedback_object *obj =
|
|
||||||
ctx->TransformFeedback.CurrentObject;
|
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
|
||||||
if (obj->Active) {
|
|
||||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
|
||||||
"glUseProgram(transform feedback active)");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (program) {
|
|
||||||
shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
|
|
||||||
if (!shProg) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!shProg->LinkStatus) {
|
|
||||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
|
||||||
"glUseProgram(program %u not linked)", program);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* debug code */
|
|
||||||
if (ctx->Shader.Flags & GLSL_USE_PROG) {
|
|
||||||
print_shader_info(shProg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
shProg = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
changed = use_shader_program(ctx, GL_VERTEX_SHADER, shProg);
|
changed = use_shader_program(ctx, GL_VERTEX_SHADER, shProg);
|
||||||
changed = use_shader_program(ctx, GL_GEOMETRY_SHADER_ARB, shProg)
|
changed = use_shader_program(ctx, GL_GEOMETRY_SHADER_ARB, shProg)
|
||||||
|| changed;
|
|| changed;
|
||||||
changed = use_shader_program(ctx, GL_FRAGMENT_SHADER, shProg)
|
changed = use_shader_program(ctx, GL_FRAGMENT_SHADER, shProg)
|
||||||
|| changed;
|
|| changed;
|
||||||
active_program(ctx, shProg, "glUseProgram");
|
_mesa_active_program(ctx, shProg, "glUseProgram");
|
||||||
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
|
FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
|
||||||
@@ -1614,8 +1585,39 @@ void GLAPIENTRY
|
|||||||
_mesa_UseProgramObjectARB(GLhandleARB program)
|
_mesa_UseProgramObjectARB(GLhandleARB program)
|
||||||
{
|
{
|
||||||
GET_CURRENT_CONTEXT(ctx);
|
GET_CURRENT_CONTEXT(ctx);
|
||||||
|
struct gl_shader_program *shProg;
|
||||||
|
struct gl_transform_feedback_object *obj =
|
||||||
|
ctx->TransformFeedback.CurrentObject;
|
||||||
|
|
||||||
FLUSH_VERTICES(ctx, _NEW_PROGRAM);
|
FLUSH_VERTICES(ctx, _NEW_PROGRAM);
|
||||||
_mesa_use_program(ctx, program);
|
|
||||||
|
if (obj->Active) {
|
||||||
|
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||||
|
"glUseProgram(transform feedback active)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (program) {
|
||||||
|
shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
|
||||||
|
if (!shProg) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!shProg->LinkStatus) {
|
||||||
|
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||||
|
"glUseProgram(program %u not linked)", program);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* debug code */
|
||||||
|
if (ctx->Shader.Flags & GLSL_USE_PROG) {
|
||||||
|
print_shader_info(shProg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
shProg = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
_mesa_use_program(ctx, shProg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1731,12 +1733,25 @@ _mesa_ProgramParameteriARB(GLuint program, GLenum pname,
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
_mesa_use_shader_program(struct gl_context *ctx, GLenum type,
|
||||||
|
struct gl_shader_program *shProg)
|
||||||
|
{
|
||||||
|
bool changed;
|
||||||
|
|
||||||
|
changed = use_shader_program(ctx, type, shProg);
|
||||||
|
if (changed)
|
||||||
|
FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
|
||||||
|
|
||||||
|
if (ctx->Driver.UseProgram)
|
||||||
|
ctx->Driver.UseProgram(ctx, shProg);
|
||||||
|
}
|
||||||
|
|
||||||
void GLAPIENTRY
|
void GLAPIENTRY
|
||||||
_mesa_UseShaderProgramEXT(GLenum type, GLuint program)
|
_mesa_UseShaderProgramEXT(GLenum type, GLuint program)
|
||||||
{
|
{
|
||||||
GET_CURRENT_CONTEXT(ctx);
|
GET_CURRENT_CONTEXT(ctx);
|
||||||
struct gl_shader_program *shProg = NULL;
|
struct gl_shader_program *shProg = NULL;
|
||||||
bool changed = false;
|
|
||||||
|
|
||||||
if (!validate_shader_target(ctx, type)) {
|
if (!validate_shader_target(ctx, type)) {
|
||||||
_mesa_error(ctx, GL_INVALID_ENUM, "glUseShaderProgramEXT(type)");
|
_mesa_error(ctx, GL_INVALID_ENUM, "glUseShaderProgramEXT(type)");
|
||||||
@@ -1762,13 +1777,7 @@ _mesa_UseShaderProgramEXT(GLenum type, GLuint program)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
changed = use_shader_program(ctx, type, shProg);
|
_mesa_use_shader_program(ctx, type, shProg);
|
||||||
if (changed)
|
|
||||||
FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
|
|
||||||
|
|
||||||
if (ctx->Driver.UseProgram)
|
|
||||||
ctx->Driver.UseProgram(ctx, shProg);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLAPIENTRY
|
void GLAPIENTRY
|
||||||
@@ -1779,7 +1788,7 @@ _mesa_ActiveProgramEXT(GLuint program)
|
|||||||
? _mesa_lookup_shader_program_err(ctx, program, "glActiveProgramEXT")
|
? _mesa_lookup_shader_program_err(ctx, program, "glActiveProgramEXT")
|
||||||
: NULL;
|
: NULL;
|
||||||
|
|
||||||
active_program(ctx, shProg, "glActiveProgramEXT");
|
_mesa_active_program(ctx, shProg, "glActiveProgramEXT");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -39,8 +39,11 @@ _mesa_copy_string(GLchar *dst, GLsizei maxLength,
|
|||||||
GLsizei *length, const GLchar *src);
|
GLsizei *length, const GLchar *src);
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
_mesa_use_program(struct gl_context *ctx, GLuint program);
|
_mesa_use_program(struct gl_context *ctx, struct gl_shader_program *shProg);
|
||||||
|
|
||||||
|
extern void
|
||||||
|
_mesa_active_program(struct gl_context *ctx, struct gl_shader_program *shProg,
|
||||||
|
const char *caller);
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
_mesa_init_shader_dispatch(struct _glapi_table *exec);
|
_mesa_init_shader_dispatch(struct _glapi_table *exec);
|
||||||
@@ -172,6 +175,9 @@ _mesa_ShaderBinary(GLint n, const GLuint *shaders, GLenum binaryformat,
|
|||||||
extern void GLAPIENTRY
|
extern void GLAPIENTRY
|
||||||
_mesa_ProgramParameteriARB(GLuint program, GLenum pname,
|
_mesa_ProgramParameteriARB(GLuint program, GLenum pname,
|
||||||
GLint value);
|
GLint value);
|
||||||
|
void
|
||||||
|
_mesa_use_shader_program(struct gl_context *ctx, GLenum type,
|
||||||
|
struct gl_shader_program *shProg);
|
||||||
|
|
||||||
extern void GLAPIENTRY
|
extern void GLAPIENTRY
|
||||||
_mesa_UseShaderProgramEXT(GLenum type, GLuint program);
|
_mesa_UseShaderProgramEXT(GLenum type, GLuint program);
|
||||||
|
Reference in New Issue
Block a user