/**
* Called by glUniformMatrix*() functions.
* Note: cols=2, rows=4 ==> array[2] of vec4
*/
extern "C" void
_mesa_uniform_matrix(struct gl_context *ctx, struct gl_shader_program *shProg,
GLuint cols, GLuint rows,
GLint location, GLsizei count,
GLboolean transpose, const GLfloat *values)
{
unsigned loc, offset;
unsigned vectors;
unsigned components;
unsigned elements;
struct gl_uniform_storage *uni;
ASSERT_OUTSIDE_BEGIN_END(ctx);
if (!validate_uniform_parameters(ctx, shProg, location, count,
&loc, &offset, "glUniformMatrix", false))
return;
uni = &shProg->UniformStorage[loc];
if (!uni->type->is_matrix()) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glUniformMatrix(non-matrix uniform)");
return;
}
assert(!uni->type->is_sampler());
vectors = uni->type->matrix_columns;
components = uni->type->vector_elements;
/* Verify that the types are compatible. This is greatly simplified for
* matrices because they can only have a float base type.
*/
if (vectors != cols || components != rows) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glUniformMatrix(matrix size mismatch)");
return;
}
if (ctx->Shader.Flags & GLSL_UNIFORMS) {
log_uniform(values, GLSL_TYPE_FLOAT, components, vectors, count,
bool(transpose), shProg, location, uni);
}
/* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says:
*
* "When loading N elements starting at an arbitrary position k in a
* uniform declared as an array, elements k through k + N - 1 in the
* array will be replaced with the new values. Values for any array
* element that exceeds the highest array element index used, as
* reported by GetActiveUniform, will be ignored by the GL."
*
* Clamp 'count' to a valid value. Note that for non-arrays a count > 1
* will have already generated an error.
*/
if (uni->array_elements != 0) {
if (offset >= uni->array_elements)
return;
count = MIN2(count, (int) (uni->array_elements - offset));
}
FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
/* Store the data in the "actual type" backing storage for the uniform.
*/
elements = components * vectors;
if (!transpose) {
memcpy(&uni->storage[elements * offset], values,
sizeof(uni->storage[0]) * elements * count);
} else {
/* Copy and transpose the matrix.
*/
const float *src = values;
float *dst = &uni->storage[elements * offset].f;
for (int i = 0; i < count; i++) {
for (unsigned r = 0; r < rows; r++) {
for (unsigned c = 0; c < cols; c++) {
dst[(c * components) + r] = src[c + (r * vectors)];
}
}
dst += elements;
src += elements;
}
}
uni->initialized = true;
_mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
}
/**
* Called via ctx->Driver.Uniform().
*/
void
_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
const GLvoid *values, GLenum type)
{
struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
GLint elems, i, k;
GLenum uType;
GLsizei maxCount;
if (!shProg || !shProg->LinkStatus) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
return;
}
if (location == -1)
return; /* The standard specifies this as a no-op */
/* The spec says this is GL_INVALID_OPERATION, although it seems like it
* ought to be GL_INVALID_VALUE
*/
if (location < 0 || location >= (GLint) shProg->Uniforms->NumParameters) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(location)");
return;
}
FLUSH_VERTICES(ctx, _NEW_PROGRAM);
uType = shProg->Uniforms->Parameters[location].DataType;
/*
* If we're setting a sampler, we must use glUniformi1()!
*/
if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
GLint unit;
if (type != GL_INT || count != 1) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glUniform(only glUniform1i can be used "
"to set sampler uniforms)");
return;
}
/* check that the sampler (tex unit index) is legal */
unit = ((GLint *) values)[0];
if (unit >= ctx->Const.MaxTextureImageUnits) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glUniform1(invalid sampler/tex unit index)");
return;
}
}
if (count < 0) {
_mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
return;
}
switch (type) {
case GL_FLOAT:
case GL_INT:
elems = 1;
break;
case GL_FLOAT_VEC2:
case GL_INT_VEC2:
elems = 2;
break;
case GL_FLOAT_VEC3:
case GL_INT_VEC3:
elems = 3;
break;
case GL_FLOAT_VEC4:
case GL_INT_VEC4:
elems = 4;
break;
default:
_mesa_problem(ctx, "Invalid type in _mesa_uniform");
return;
}
/* OpenGL requires types to match exactly, except that one can convert
* float or int array to boolean array.
*/
switch (uType)
{
case GL_BOOL:
case GL_BOOL_VEC2:
case GL_BOOL_VEC3:
case GL_BOOL_VEC4:
if (elems != sizeof_glsl_type(uType)) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count mismatch)");
}
break;
case PROGRAM_SAMPLER:
break;
default:
if (shProg->Uniforms->Parameters[location].Type != PROGRAM_SAMPLER
&& uType != type) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
}
break;
}
//.........这里部分代码省略.........
//.........这里部分代码省略.........
}
}
}
if (uni->type->is_image()) {
for (int i = 0; i < count; i++) {
const int unit = ((GLint *) values)[i];
/* check that the image unit is legal */
if (unit < 0 || unit >= (int)ctx->Const.MaxImageUnits) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glUniform1i(invalid image unit index for uniform %d)",
location);
return;
}
}
}
/* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says:
*
* "When loading N elements starting at an arbitrary position k in a
* uniform declared as an array, elements k through k + N - 1 in the
* array will be replaced with the new values. Values for any array
* element that exceeds the highest array element index used, as
* reported by GetActiveUniform, will be ignored by the GL."
*
* Clamp 'count' to a valid value. Note that for non-arrays a count > 1
* will have already generated an error.
*/
if (uni->array_elements != 0) {
count = MIN2(count, (int) (uni->array_elements - offset));
}
FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
/* Store the data in the "actual type" backing storage for the uniform.
*/
if (!uni->type->is_boolean()) {
memcpy(&uni->storage[size_mul * components * offset], values,
sizeof(uni->storage[0]) * components * count * size_mul);
} else {
const union gl_constant_value *src =
(const union gl_constant_value *) values;
union gl_constant_value *dst = &uni->storage[components * offset];
const unsigned elems = components * count;
for (unsigned i = 0; i < elems; i++) {
if (basicType == GLSL_TYPE_FLOAT) {
dst[i].i = src[i].f != 0.0f ? ctx->Const.UniformBooleanTrue : 0;
} else {
dst[i].i = src[i].i != 0 ? ctx->Const.UniformBooleanTrue : 0;
}
}
}
uni->initialized = true;
_mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
/* If the uniform is a sampler, do the extra magic necessary to propagate
* the changes through.
*/
if (uni->type->is_sampler()) {
bool flushed = false;
for (int i = 0; i < MESA_SHADER_STAGES; i++) {
struct gl_shader *const sh = shProg->_LinkedShaders[i];
/**
* Called by glUniformMatrix*() functions.
* Note: cols=2, rows=4 ==> array[2] of vec4
*/
extern "C" void
_mesa_uniform_matrix(struct gl_context *ctx, struct gl_shader_program *shProg,
GLuint cols, GLuint rows,
GLint location, GLsizei count,
GLboolean transpose,
const GLvoid *values, GLenum type)
{
unsigned offset;
unsigned vectors;
unsigned components;
unsigned elements;
int size_mul;
struct gl_uniform_storage *const uni =
validate_uniform_parameters(ctx, shProg, location, count,
&offset, "glUniformMatrix");
if (uni == NULL)
return;
if (!uni->type->is_matrix()) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glUniformMatrix(non-matrix uniform)");
return;
}
assert(type == GL_FLOAT || type == GL_DOUBLE);
size_mul = type == GL_DOUBLE ? 2 : 1;
assert(!uni->type->is_sampler());
vectors = uni->type->matrix_columns;
components = uni->type->vector_elements;
/* Verify that the types are compatible. This is greatly simplified for
* matrices because they can only have a float base type.
*/
if (vectors != cols || components != rows) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glUniformMatrix(matrix size mismatch)");
return;
}
/* GL_INVALID_VALUE is generated if `transpose' is not GL_FALSE.
* http://www.khronos.org/opengles/sdk/docs/man/xhtml/glUniform.xml
*/
if (transpose) {
if (ctx->API == API_OPENGLES2 && ctx->Version < 30) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glUniformMatrix(matrix transpose is not GL_FALSE)");
return;
}
}
if (unlikely(ctx->_Shader->Flags & GLSL_UNIFORMS)) {
log_uniform(values, uni->type->base_type, components, vectors, count,
bool(transpose), shProg, location, uni);
}
/* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says:
*
* "When loading N elements starting at an arbitrary position k in a
* uniform declared as an array, elements k through k + N - 1 in the
* array will be replaced with the new values. Values for any array
* element that exceeds the highest array element index used, as
* reported by GetActiveUniform, will be ignored by the GL."
*
* Clamp 'count' to a valid value. Note that for non-arrays a count > 1
* will have already generated an error.
*/
if (uni->array_elements != 0) {
count = MIN2(count, (int) (uni->array_elements - offset));
}
FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
/* Store the data in the "actual type" backing storage for the uniform.
*/
elements = components * vectors;
if (!transpose) {
memcpy(&uni->storage[elements * offset], values,
sizeof(uni->storage[0]) * elements * count * size_mul);
} else if (type == GL_FLOAT) {
/* Copy and transpose the matrix.
*/
const float *src = (const float *)values;
float *dst = &uni->storage[elements * offset].f;
for (int i = 0; i < count; i++) {
for (unsigned r = 0; r < rows; r++) {
for (unsigned c = 0; c < cols; c++) {
dst[(c * components) + r] = src[c + (r * vectors)];
}
}
dst += elements;
src += elements;
}
//.........这里部分代码省略.........
/**
* This is called just prior to changing any sampler object state.
*/
static inline void
flush(struct gl_context *ctx)
{
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
}
开发者ID:dumbbell,项目名称:mesa,代码行数:8,代码来源:samplerobj.c
示例13: _mesa_TexGenfv
void GLAPIENTRY
_mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
{
struct gl_texture_unit *texUnit;
struct gl_texgen *texgen;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE))
_mesa_debug(ctx, "glTexGen %s %s %.1f(%s)...\n",
_mesa_lookup_enum_by_nr(coord),
_mesa_lookup_enum_by_nr(pname),
*params,
_mesa_lookup_enum_by_nr((GLenum) (GLint) *params));
if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glTexGen(current unit)");
return;
}
texUnit = _mesa_get_current_tex_unit(ctx);
texgen = get_texgen(ctx, texUnit, coord);
if (!texgen) {
_mesa_error(ctx, GL_INVALID_ENUM, "glTexGen(coord)");
return;
}
switch (pname) {
case GL_TEXTURE_GEN_MODE:
{
GLenum mode = (GLenum) (GLint) params[0];
GLbitfield bit = 0x0;
if (texgen->Mode == mode)
return;
switch (mode) {
case GL_OBJECT_LINEAR:
bit = TEXGEN_OBJ_LINEAR;
break;
case GL_EYE_LINEAR:
bit = TEXGEN_EYE_LINEAR;
break;
case GL_SPHERE_MAP:
if (coord == GL_S || coord == GL_T)
bit = TEXGEN_SPHERE_MAP;
break;
case GL_REFLECTION_MAP_NV:
if (coord != GL_Q)
bit = TEXGEN_REFLECTION_MAP_NV;
break;
case GL_NORMAL_MAP_NV:
if (coord != GL_Q)
bit = TEXGEN_NORMAL_MAP_NV;
break;
default:
; /* nop */
}
if (!bit) {
_mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
return;
}
if (ctx->API != API_OPENGL
&& (bit & (TEXGEN_REFLECTION_MAP_NV | TEXGEN_NORMAL_MAP_NV)) == 0) {
_mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
return;
}
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
texgen->Mode = mode;
texgen->_ModeBit = bit;
}
break;
case GL_OBJECT_PLANE:
{
if (ctx->API != API_OPENGL) {
_mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
return;
}
if (TEST_EQ_4V(texgen->ObjectPlane, params))
return;
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
COPY_4FV(texgen->ObjectPlane, params);
}
break;
case GL_EYE_PLANE:
{
GLfloat tmp[4];
if (ctx->API != API_OPENGL) {
_mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
return;
}
/* Transform plane equation by the inverse modelview matrix */
if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) {
_math_matrix_analyse(ctx->ModelviewMatrixStack.Top);
}
_mesa_transform_vector(tmp, params,
//.........这里部分代码省略.........
请发表评论