aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa/main
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/mesa/main')
-rw-r--r--mesalib/src/mesa/main/api_validate.c10
-rw-r--r--mesalib/src/mesa/main/attrib.c40
-rw-r--r--mesalib/src/mesa/main/config.h5
-rw-r--r--mesalib/src/mesa/main/context.c72
-rw-r--r--mesalib/src/mesa/main/dlist.c1
-rw-r--r--mesalib/src/mesa/main/enable.c36
-rw-r--r--mesalib/src/mesa/main/extensions.c2
-rw-r--r--mesalib/src/mesa/main/fbobject.c2
-rw-r--r--mesalib/src/mesa/main/ff_fragment_shader.cpp8
-rw-r--r--mesalib/src/mesa/main/ffvertex_prog.c2
-rw-r--r--mesalib/src/mesa/main/formats.c12
-rw-r--r--mesalib/src/mesa/main/framebuffer.c86
-rw-r--r--mesalib/src/mesa/main/framebuffer.h5
-rw-r--r--mesalib/src/mesa/main/get.c229
-rw-r--r--mesalib/src/mesa/main/get.h6
-rw-r--r--mesalib/src/mesa/main/get_hash_params.py13
-rw-r--r--mesalib/src/mesa/main/glformats.c130
-rw-r--r--mesalib/src/mesa/main/macros.h2
-rw-r--r--mesalib/src/mesa/main/mtypes.h46
-rw-r--r--mesalib/src/mesa/main/rastpos.c5
-rw-r--r--mesalib/src/mesa/main/scissor.c161
-rw-r--r--mesalib/src/mesa/main/scissor.h10
-rw-r--r--mesalib/src/mesa/main/shaderapi.c62
-rw-r--r--mesalib/src/mesa/main/shaderapi.h3
-rw-r--r--mesalib/src/mesa/main/shaderobj.c4
-rw-r--r--mesalib/src/mesa/main/shared.c4
-rw-r--r--mesalib/src/mesa/main/state.c24
-rw-r--r--mesalib/src/mesa/main/texobj.c8
-rw-r--r--mesalib/src/mesa/main/texstate.c75
-rw-r--r--mesalib/src/mesa/main/texstorage.c40
-rw-r--r--mesalib/src/mesa/main/transformfeedback.c51
-rw-r--r--mesalib/src/mesa/main/viewport.c347
-rw-r--r--mesalib/src/mesa/main/viewport.h21
33 files changed, 1150 insertions, 372 deletions
diff --git a/mesalib/src/mesa/main/api_validate.c b/mesalib/src/mesa/main/api_validate.c
index 96b178905..694558443 100644
--- a/mesalib/src/mesa/main/api_validate.c
+++ b/mesalib/src/mesa/main/api_validate.c
@@ -128,7 +128,7 @@ check_valid_to_render(struct gl_context *ctx, const char *function)
case API_OPENGL_CORE:
{
const struct gl_shader_program *vsProg =
- ctx->Shader.CurrentVertexProgram;
+ ctx->Shader.CurrentProgram[MESA_SHADER_VERTEX];
GLboolean haveVertexShader = (vsProg && vsProg->LinkStatus);
GLboolean haveVertexProgram = ctx->VertexProgram._Enabled;
if (haveVertexShader || haveVertexProgram) {
@@ -269,9 +269,9 @@ _mesa_valid_prim_mode(struct gl_context *ctx, GLenum mode, const char *name)
* TRIANGLES_ADJACENCY_ARB or TRIANGLE_STRIP_ADJACENCY_ARB.
*
*/
- if (ctx->Shader.CurrentGeometryProgram) {
+ if (ctx->Shader.CurrentProgram[MESA_SHADER_GEOMETRY]) {
const GLenum geom_mode =
- ctx->Shader.CurrentGeometryProgram->Geom.InputType;
+ ctx->Shader.CurrentProgram[MESA_SHADER_GEOMETRY]->Geom.InputType;
switch (mode) {
case GL_POINTS:
valid_enum = (geom_mode == GL_POINTS);
@@ -330,8 +330,8 @@ _mesa_valid_prim_mode(struct gl_context *ctx, GLenum mode, const char *name)
if (_mesa_is_xfb_active_and_unpaused(ctx)) {
GLboolean pass = GL_TRUE;
- if(ctx->Shader.CurrentGeometryProgram) {
- switch (ctx->Shader.CurrentGeometryProgram->Geom.OutputType) {
+ if(ctx->Shader.CurrentProgram[MESA_SHADER_GEOMETRY]) {
+ switch (ctx->Shader.CurrentProgram[MESA_SHADER_GEOMETRY]->Geom.OutputType) {
case GL_POINTS:
pass = ctx->TransformFeedback.Mode == GL_POINTS;
break;
diff --git a/mesalib/src/mesa/main/attrib.c b/mesalib/src/mesa/main/attrib.c
index 30c815d67..7b7cf0ef3 100644
--- a/mesalib/src/mesa/main/attrib.c
+++ b/mesalib/src/mesa/main/attrib.c
@@ -112,7 +112,7 @@ struct gl_enable_attrib
GLboolean PolygonSmooth;
GLboolean PolygonStipple;
GLboolean RescaleNormals;
- GLboolean Scissor;
+ GLbitfield Scissor;
GLboolean Stencil;
GLboolean StencilTwoSide; /* GL_EXT_stencil_two_side */
GLboolean MultisampleEnabled; /* GL_ARB_multisample */
@@ -354,7 +354,7 @@ _mesa_PushAttrib(GLbitfield mask)
attr->PolygonSmooth = ctx->Polygon.SmoothFlag;
attr->PolygonStipple = ctx->Polygon.StippleFlag;
attr->RescaleNormals = ctx->Transform.RescaleNormals;
- attr->Scissor = ctx->Scissor.Enabled;
+ attr->Scissor = ctx->Scissor.EnableFlags;
attr->Stencil = ctx->Stencil.Enabled;
attr->StencilTwoSide = ctx->Stencil.TestTwoSide;
attr->MultisampleEnabled = ctx->Multisample.Enabled;
@@ -533,8 +533,9 @@ _mesa_PushAttrib(GLbitfield mask)
if (mask & GL_VIEWPORT_BIT) {
if (!push_attrib(ctx, &head, GL_VIEWPORT_BIT,
- sizeof(struct gl_viewport_attrib),
- (void*)&ctx->Viewport))
+ sizeof(struct gl_viewport_attrib)
+ * ctx->Const.MaxViewports,
+ (void*)&ctx->ViewportArray))
goto end;
}
@@ -658,7 +659,13 @@ pop_enable_group(struct gl_context *ctx, const struct gl_enable_attrib *enable)
GL_POLYGON_SMOOTH);
TEST_AND_UPDATE(ctx->Polygon.StippleFlag, enable->PolygonStipple,
GL_POLYGON_STIPPLE);
- TEST_AND_UPDATE(ctx->Scissor.Enabled, enable->Scissor, GL_SCISSOR_TEST);
+ if (ctx->Scissor.EnableFlags != enable->Scissor) {
+ unsigned i;
+
+ for (i = 0; i < ctx->Const.MaxViewports; i++) {
+ _mesa_set_enablei(ctx, GL_SCISSOR_TEST, i, (enable->Scissor >> i) & 1);
+ }
+ }
TEST_AND_UPDATE(ctx->Stencil.Enabled, enable->Stencil, GL_STENCIL_TEST);
if (ctx->Extensions.EXT_stencil_two_side) {
TEST_AND_UPDATE(ctx->Stencil.TestTwoSide, enable->StencilTwoSide, GL_STENCIL_TEST_TWO_SIDE_EXT);
@@ -1262,11 +1269,19 @@ _mesa_PopAttrib(void)
break;
case GL_SCISSOR_BIT:
{
+ unsigned i;
const struct gl_scissor_attrib *scissor;
scissor = (const struct gl_scissor_attrib *) attr->data;
- _mesa_Scissor(scissor->X, scissor->Y,
- scissor->Width, scissor->Height);
- _mesa_set_enable(ctx, GL_SCISSOR_TEST, scissor->Enabled);
+
+ for (i = 0; i < ctx->Const.MaxViewports; i++) {
+ _mesa_set_scissor(ctx, i,
+ scissor->ScissorArray[i].X,
+ scissor->ScissorArray[i].Y,
+ scissor->ScissorArray[i].Width,
+ scissor->ScissorArray[i].Height);
+ _mesa_set_enablei(ctx, GL_SCISSOR_TEST, i,
+ (scissor->EnableFlags >> i) & 1);
+ }
}
break;
case GL_STENCIL_BUFFER_BIT:
@@ -1342,10 +1357,15 @@ _mesa_PopAttrib(void)
break;
case GL_VIEWPORT_BIT:
{
+ unsigned i;
const struct gl_viewport_attrib *vp;
vp = (const struct gl_viewport_attrib *) attr->data;
- _mesa_Viewport(vp->X, vp->Y, vp->Width, vp->Height);
- _mesa_DepthRange(vp->Near, vp->Far);
+
+ for (i = 0; i < ctx->Const.MaxViewports; i++) {
+ _mesa_set_viewport(ctx, i, vp[i].X, vp[i].Y, vp[i].Width,
+ vp[i].Height);
+ _mesa_set_depth_range(ctx, i, vp[i].Near, vp[i].Far);
+ }
}
break;
case GL_MULTISAMPLE_BIT_ARB:
diff --git a/mesalib/src/mesa/main/config.h b/mesalib/src/mesa/main/config.h
index 1e1cfb6c5..d1f4632d4 100644
--- a/mesalib/src/mesa/main/config.h
+++ b/mesalib/src/mesa/main/config.h
@@ -125,7 +125,7 @@
* Max number of texture image units. Also determines number of texture
* samplers in shaders.
*/
-#define MAX_TEXTURE_IMAGE_UNITS 16
+#define MAX_TEXTURE_IMAGE_UNITS 32
/**
* Larger of MAX_TEXTURE_COORD_UNITS and MAX_TEXTURE_IMAGE_UNITS.
@@ -141,6 +141,9 @@
#define MAX_VIEWPORT_WIDTH 16384
#define MAX_VIEWPORT_HEIGHT 16384
+/** Maximun number of viewports supported with ARB_viewport_array */
+#define MAX_VIEWPORTS 16
+
/** Maxmimum size for CVA. May be overridden by the drivers. */
#define MAX_ARRAY_LOCK_SIZE 3000
diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c
index 4f7bdbdbc..1f8639108 100644
--- a/mesalib/src/mesa/main/context.c
+++ b/mesalib/src/mesa/main/context.c
@@ -587,6 +587,16 @@ _mesa_init_constants(struct gl_context *ctx)
ctx->Const.MaxSpotExponent = 128.0;
ctx->Const.MaxViewportWidth = MAX_VIEWPORT_WIDTH;
ctx->Const.MaxViewportHeight = MAX_VIEWPORT_HEIGHT;
+ ctx->Const.MinMapBufferAlignment = 1;
+
+ /* Driver must override these values if ARB_viewport_array is supported. */
+ ctx->Const.MaxViewports = 1;
+ ctx->Const.ViewportSubpixelBits = 0;
+ ctx->Const.ViewportBounds.Min = 0;
+ ctx->Const.ViewportBounds.Max = 0;
+
+ /* Driver must override if it supports ARB_viewport_array */
+ ctx->Const.MaxViewports = 1;
/** GL_ARB_uniform_buffer_object */
ctx->Const.MaxCombinedUniformBlocks = 36;
@@ -1348,13 +1358,17 @@ _mesa_copy_context( const struct gl_context *src, struct gl_context *dst,
}
if (mask & GL_VIEWPORT_BIT) {
/* Cannot use memcpy, because of pointers in GLmatrix _WindowMap */
- dst->Viewport.X = src->Viewport.X;
- dst->Viewport.Y = src->Viewport.Y;
- dst->Viewport.Width = src->Viewport.Width;
- dst->Viewport.Height = src->Viewport.Height;
- dst->Viewport.Near = src->Viewport.Near;
- dst->Viewport.Far = src->Viewport.Far;
- _math_matrix_copy(&dst->Viewport._WindowMap, &src->Viewport._WindowMap);
+ unsigned i;
+ for (i = 0; i < src->Const.MaxViewports; i++) {
+ dst->ViewportArray[i].X = src->ViewportArray[i].X;
+ dst->ViewportArray[i].Y = src->ViewportArray[i].Y;
+ dst->ViewportArray[i].Width = src->ViewportArray[i].Width;
+ dst->ViewportArray[i].Height = src->ViewportArray[i].Height;
+ dst->ViewportArray[i].Near = src->ViewportArray[i].Near;
+ dst->ViewportArray[i].Far = src->ViewportArray[i].Far;
+ _math_matrix_copy(&dst->ViewportArray[i]._WindowMap,
+ &src->ViewportArray[i]._WindowMap);
+ }
}
/* XXX FIXME: Call callbacks?
@@ -1423,12 +1437,20 @@ void
_mesa_check_init_viewport(struct gl_context *ctx, GLuint width, GLuint height)
{
if (!ctx->ViewportInitialized && width > 0 && height > 0) {
+ unsigned i;
+
/* Note: set flag here, before calling _mesa_set_viewport(), to prevent
* potential infinite recursion.
*/
ctx->ViewportInitialized = GL_TRUE;
- _mesa_set_viewport(ctx, 0, 0, width, height);
- _mesa_set_scissor(ctx, 0, 0, width, height);
+
+ /* Note: ctx->Const.MaxViewports may not have been set by the driver
+ * yet, so just initialize all of them.
+ */
+ for (i = 0; i < MAX_VIEWPORTS; i++) {
+ _mesa_set_viewport(ctx, i, 0, 0, width, height);
+ _mesa_set_scissor(ctx, i, 0, 0, width, height);
+ }
}
}
@@ -1744,10 +1766,10 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *where)
if (ctx->NewState)
_mesa_update_state(ctx);
- if (ctx->Shader.CurrentVertexProgram) {
+ if (ctx->Shader.CurrentProgram[MESA_SHADER_VERTEX]) {
vert_from_glsl_shader = true;
- if (!ctx->Shader.CurrentVertexProgram->LinkStatus) {
+ if (!ctx->Shader.CurrentProgram[MESA_SHADER_VERTEX]->LinkStatus) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"%s(shader not linked)", where);
return GL_FALSE;
@@ -1756,19 +1778,19 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *where)
{
char errMsg[100];
if (!_mesa_validate_shader_program(ctx,
- ctx->Shader.CurrentVertexProgram,
+ ctx->Shader.CurrentProgram[MESA_SHADER_VERTEX],
errMsg)) {
_mesa_warning(ctx, "Shader program %u is invalid: %s",
- ctx->Shader.CurrentVertexProgram->Name, errMsg);
+ ctx->Shader.CurrentProgram[MESA_SHADER_VERTEX]->Name, errMsg);
}
}
#endif
}
- if (ctx->Shader.CurrentGeometryProgram) {
+ if (ctx->Shader.CurrentProgram[MESA_SHADER_GEOMETRY]) {
geom_from_glsl_shader = true;
- if (!ctx->Shader.CurrentGeometryProgram->LinkStatus) {
+ if (!ctx->Shader.CurrentProgram[MESA_SHADER_GEOMETRY]->LinkStatus) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"%s(shader not linked)", where);
return GL_FALSE;
@@ -1777,19 +1799,20 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *where)
{
char errMsg[100];
if (!_mesa_validate_shader_program(ctx,
- ctx->Shader.CurrentGeometryProgram,
+ ctx->Shader.CurrentProgram[MESA_SHADER_GEOMETRY],
errMsg)) {
_mesa_warning(ctx, "Shader program %u is invalid: %s",
- ctx->Shader.CurrentGeometryProgram->Name, errMsg);
+ ctx->Shader.CurrentProgram[MESA_SHADER_GEOMETRY]->Name,
+ errMsg);
}
}
#endif
}
- if (ctx->Shader.CurrentFragmentProgram) {
+ if (ctx->Shader.CurrentProgram[MESA_SHADER_FRAGMENT]) {
frag_from_glsl_shader = true;
- if (!ctx->Shader.CurrentFragmentProgram->LinkStatus) {
+ if (!ctx->Shader.CurrentProgram[MESA_SHADER_FRAGMENT]->LinkStatus) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"%s(shader not linked)", where);
return GL_FALSE;
@@ -1798,10 +1821,11 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *where)
{
char errMsg[100];
if (!_mesa_validate_shader_program(ctx,
- ctx->Shader.CurrentFragmentProgram,
+ ctx->Shader.CurrentProgram[MESA_SHADER_FRAGMENT],
errMsg)) {
_mesa_warning(ctx, "Shader program %u is invalid: %s",
- ctx->Shader.CurrentFragmentProgram->Name, errMsg);
+ ctx->Shader.CurrentProgram[MESA_SHADER_FRAGMENT]->Name,
+ errMsg);
}
}
#endif
@@ -1851,13 +1875,9 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *where)
#ifdef DEBUG
if (ctx->Shader.Flags & GLSL_LOG) {
- struct gl_shader_program *shProg[MESA_SHADER_STAGES];
+ struct gl_shader_program **shProg = ctx->Shader.CurrentProgram;
gl_shader_stage i;
- shProg[MESA_SHADER_VERTEX] = ctx->Shader.CurrentVertexProgram;
- shProg[MESA_SHADER_GEOMETRY] = ctx->Shader.CurrentGeometryProgram;
- shProg[MESA_SHADER_FRAGMENT] = ctx->Shader.CurrentFragmentProgram;
-
for (i = 0; i < MESA_SHADER_STAGES; i++) {
if (shProg[i] == NULL || shProg[i]->_Used
|| shProg[i]->_LinkedShaders[i] == NULL)
diff --git a/mesalib/src/mesa/main/dlist.c b/mesalib/src/mesa/main/dlist.c
index cb40ff4db..08943c9f9 100644
--- a/mesalib/src/mesa/main/dlist.c
+++ b/mesalib/src/mesa/main/dlist.c
@@ -767,6 +767,7 @@ _mesa_delete_list(struct gl_context *ctx, struct gl_display_list *dlist)
break;
case OPCODE_PIXEL_MAP:
free(get_pointer(&n[3]));
+ n += InstSize[n[0].opcode];
break;
case OPCODE_CONTINUE:
diff --git a/mesalib/src/mesa/main/enable.c b/mesalib/src/mesa/main/enable.c
index fca306890..640db8490 100644
--- a/mesalib/src/mesa/main/enable.c
+++ b/mesalib/src/mesa/main/enable.c
@@ -659,10 +659,15 @@ _mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state)
ctx->Transform.RescaleNormals = state;
break;
case GL_SCISSOR_TEST:
- if (ctx->Scissor.Enabled == state)
- return;
- FLUSH_VERTICES(ctx, _NEW_SCISSOR);
- ctx->Scissor.Enabled = state;
+ {
+ /* Must expand glEnable to all scissors */
+ GLbitfield newEnabled =
+ state * ((1 << ctx->Const.MaxViewports) - 1);
+ if (newEnabled != ctx->Scissor.EnableFlags) {
+ FLUSH_VERTICES(ctx, _NEW_SCISSOR);
+ ctx->Scissor.EnableFlags = newEnabled;
+ }
+ }
break;
case GL_STENCIL_TEST:
if (ctx->Stencil.Enabled == state)
@@ -1076,6 +1081,20 @@ _mesa_set_enablei(struct gl_context *ctx, GLenum cap,
ctx->Color.BlendEnabled &= ~(1 << index);
}
break;
+ case GL_SCISSOR_TEST:
+ if (index >= ctx->Const.MaxViewports) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%u)",
+ state ? "glEnablei" : "glDisablei", index);
+ return;
+ }
+ if (((ctx->Scissor.EnableFlags >> index) & 1) != state) {
+ FLUSH_VERTICES(ctx, _NEW_SCISSOR);
+ if (state)
+ ctx->Scissor.EnableFlags |= (1 << index);
+ else
+ ctx->Scissor.EnableFlags &= ~(1 << index);
+ }
+ break;
default:
goto invalid_enum_error;
}
@@ -1117,6 +1136,13 @@ _mesa_IsEnabledi( GLenum cap, GLuint index )
return GL_FALSE;
}
return (ctx->Color.BlendEnabled >> index) & 1;
+ case GL_SCISSOR_TEST:
+ if (index >= ctx->Const.MaxViewports) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glIsEnabledIndexed(index=%u)",
+ index);
+ return GL_FALSE;
+ }
+ return (ctx->Scissor.EnableFlags >> index) & 1;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glIsEnabledIndexed(cap=%s)",
_mesa_lookup_enum_by_nr(cap));
@@ -1349,7 +1375,7 @@ _mesa_IsEnabled( GLenum cap )
goto invalid_enum_error;
return ctx->Transform.RescaleNormals;
case GL_SCISSOR_TEST:
- return ctx->Scissor.Enabled;
+ return ctx->Scissor.EnableFlags & 1; /* return state for index 0 */
case GL_STENCIL_TEST:
return ctx->Stencil.Enabled;
case GL_TEXTURE_1D:
diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c
index 2e0ccc3b6..0676f1e3d 100644
--- a/mesalib/src/mesa/main/extensions.c
+++ b/mesalib/src/mesa/main/extensions.c
@@ -80,6 +80,7 @@ static const struct extension extension_table[] = {
/* ARB Extensions */
{ "GL_ARB_ES2_compatibility", o(ARB_ES2_compatibility), GL, 2009 },
{ "GL_ARB_ES3_compatibility", o(ARB_ES3_compatibility), GL, 2012 },
+ { "GL_ARB_arrays_of_arrays", o(ARB_arrays_of_arrays), GL, 2012 },
{ "GL_ARB_base_instance", o(ARB_base_instance), GL, 2011 },
{ "GL_ARB_blend_func_extended", o(ARB_blend_func_extended), GL, 2009 },
{ "GL_ARB_clear_buffer_object", o(dummy_true), GL, 2012 },
@@ -176,6 +177,7 @@ static const struct extension extension_table[] = {
{ "GL_ARB_vertex_shader", o(ARB_vertex_shader), GL, 2002 },
{ "GL_ARB_vertex_type_10f_11f_11f_rev", o(ARB_vertex_type_10f_11f_11f_rev), GL, 2013 },
{ "GL_ARB_vertex_type_2_10_10_10_rev", o(ARB_vertex_type_2_10_10_10_rev), GL, 2009 },
+ { "GL_ARB_viewport_array", o(ARB_viewport_array), GLC, 2010 },
{ "GL_ARB_window_pos", o(dummy_true), GLL, 2001 },
/* EXT extensions */
{ "GL_EXT_abgr", o(dummy_true), GL, 1995 },
diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c
index dc7184ad4..943f40bd9 100644
--- a/mesalib/src/mesa/main/fbobject.c
+++ b/mesalib/src/mesa/main/fbobject.c
@@ -880,7 +880,7 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx,
/* Covers max_layer_count, is_layered, and layer_tex_target */
bool layer_info_valid = false;
GLuint max_layer_count = 0, att_layer_count;
- bool is_layered;
+ bool is_layered = false;
GLenum layer_tex_target = 0;
assert(_mesa_is_user_fbo(fb));
diff --git a/mesalib/src/mesa/main/ff_fragment_shader.cpp b/mesalib/src/mesa/main/ff_fragment_shader.cpp
index 8523edf41..cad67aa85 100644
--- a/mesalib/src/mesa/main/ff_fragment_shader.cpp
+++ b/mesalib/src/mesa/main/ff_fragment_shader.cpp
@@ -317,9 +317,9 @@ static GLbitfield get_fp_input_mask( struct gl_context *ctx )
{
/* _NEW_PROGRAM */
const GLboolean vertexShader =
- (ctx->Shader.CurrentVertexProgram &&
- ctx->Shader.CurrentVertexProgram->LinkStatus &&
- ctx->Shader.CurrentVertexProgram->_LinkedShaders[MESA_SHADER_VERTEX]);
+ (ctx->Shader.CurrentProgram[MESA_SHADER_VERTEX] &&
+ ctx->Shader.CurrentProgram[MESA_SHADER_VERTEX]->LinkStatus &&
+ ctx->Shader.CurrentProgram[MESA_SHADER_VERTEX]->_LinkedShaders[MESA_SHADER_VERTEX]);
const GLboolean vertexProgram = ctx->VertexProgram._Enabled;
GLbitfield fp_inputs = 0x0;
@@ -383,7 +383,7 @@ static GLbitfield get_fp_input_mask( struct gl_context *ctx )
* validation (see additional comments in state.c).
*/
if (vertexShader)
- vprog = ctx->Shader.CurrentVertexProgram->_LinkedShaders[MESA_SHADER_VERTEX]->Program;
+ vprog = ctx->Shader.CurrentProgram[MESA_SHADER_VERTEX]->_LinkedShaders[MESA_SHADER_VERTEX]->Program;
else
vprog = &ctx->VertexProgram.Current->Base;
diff --git a/mesalib/src/mesa/main/ffvertex_prog.c b/mesalib/src/mesa/main/ffvertex_prog.c
index aec2b2dbc..4d71c55ee 100644
--- a/mesalib/src/mesa/main/ffvertex_prog.c
+++ b/mesalib/src/mesa/main/ffvertex_prog.c
@@ -1676,7 +1676,7 @@ _mesa_get_fixed_func_vertex_program(struct gl_context *ctx)
return NULL;
create_new_program( &key, prog,
- ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX].PreferDP4,
+ ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX].OptimizeForAOS,
ctx->Const.Program[MESA_SHADER_VERTEX].MaxTemps );
#if 0
diff --git a/mesalib/src/mesa/main/formats.c b/mesalib/src/mesa/main/formats.c
index 1246c4d92..7bde1f1a8 100644
--- a/mesalib/src/mesa/main/formats.c
+++ b/mesalib/src/mesa/main/formats.c
@@ -2032,6 +2032,9 @@ _mesa_get_format_color_encoding(gl_format format)
case MESA_FORMAT_SRGBA_DXT3:
case MESA_FORMAT_SRGBA_DXT5:
case MESA_FORMAT_XBGR8888_SRGB:
+ case MESA_FORMAT_ETC2_SRGB8:
+ case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC:
+ case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
return GL_SRGB;
default:
return GL_LINEAR;
@@ -2077,6 +2080,15 @@ _mesa_get_srgb_format_linear(gl_format format)
case MESA_FORMAT_XBGR8888_SRGB:
format = MESA_FORMAT_RGBX8888_REV;
break;
+ case MESA_FORMAT_ETC2_SRGB8:
+ format = MESA_FORMAT_ETC2_RGB8;
+ break;
+ case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC:
+ format = MESA_FORMAT_ETC2_RGBA8_EAC;
+ break;
+ case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
+ format = MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1;
+ break;
default:
break;
}
diff --git a/mesalib/src/mesa/main/framebuffer.c b/mesalib/src/mesa/main/framebuffer.c
index 2fad45880..bd8f4933f 100644
--- a/mesalib/src/mesa/main/framebuffer.c
+++ b/mesalib/src/mesa/main/framebuffer.c
@@ -357,6 +357,56 @@ update_framebuffer_size(struct gl_context *ctx, struct gl_framebuffer *fb)
/**
+ * Calculate the inclusive bounding box for the scissor of a specific viewport
+ *
+ * \param ctx GL context.
+ * \param buffer Framebuffer to be checked against
+ * \param idx Index of the desired viewport
+ * \param bbox Bounding box for the scissored viewport. Stored as xmin,
+ * xmax, ymin, ymax.
+ *
+ * \warning This function assumes that the framebuffer dimensions are up to
+ * date (e.g., update_framebuffer_size has been recently called on \c buffer).
+ *
+ * \sa _mesa_clip_to_region
+ */
+void
+_mesa_scissor_bounding_box(const struct gl_context *ctx,
+ const struct gl_framebuffer *buffer,
+ unsigned idx, int *bbox)
+{
+ bbox[0] = 0;
+ bbox[2] = 0;
+ bbox[1] = buffer->Width;
+ bbox[3] = buffer->Height;
+
+ if (ctx->Scissor.EnableFlags & (1u << idx)) {
+ if (ctx->Scissor.ScissorArray[idx].X > bbox[0]) {
+ bbox[0] = ctx->Scissor.ScissorArray[idx].X;
+ }
+ if (ctx->Scissor.ScissorArray[idx].Y > bbox[2]) {
+ bbox[2] = ctx->Scissor.ScissorArray[idx].Y;
+ }
+ if (ctx->Scissor.ScissorArray[idx].X + ctx->Scissor.ScissorArray[idx].Width < bbox[1]) {
+ bbox[1] = ctx->Scissor.ScissorArray[idx].X + ctx->Scissor.ScissorArray[idx].Width;
+ }
+ if (ctx->Scissor.ScissorArray[idx].Y + ctx->Scissor.ScissorArray[idx].Height < bbox[3]) {
+ bbox[3] = ctx->Scissor.ScissorArray[idx].Y + ctx->Scissor.ScissorArray[idx].Height;
+ }
+ /* finally, check for empty region */
+ if (bbox[0] > bbox[1]) {
+ bbox[0] = bbox[1];
+ }
+ if (bbox[2] > bbox[3]) {
+ bbox[2] = bbox[3];
+ }
+ }
+
+ ASSERT(bbox[0] <= bbox[1]);
+ ASSERT(bbox[2] <= bbox[3]);
+}
+
+/**
* Update the context's current drawing buffer's Xmin, Xmax, Ymin, Ymax fields.
* These values are computed from the buffer's width and height and
* the scissor box, if it's enabled.
@@ -366,6 +416,7 @@ void
_mesa_update_draw_buffer_bounds(struct gl_context *ctx)
{
struct gl_framebuffer *buffer = ctx->DrawBuffer;
+ int bbox[4];
if (!buffer)
return;
@@ -375,35 +426,12 @@ _mesa_update_draw_buffer_bounds(struct gl_context *ctx)
update_framebuffer_size(ctx, buffer);
}
- buffer->_Xmin = 0;
- buffer->_Ymin = 0;
- buffer->_Xmax = buffer->Width;
- buffer->_Ymax = buffer->Height;
-
- if (ctx->Scissor.Enabled) {
- if (ctx->Scissor.X > buffer->_Xmin) {
- buffer->_Xmin = ctx->Scissor.X;
- }
- if (ctx->Scissor.Y > buffer->_Ymin) {
- buffer->_Ymin = ctx->Scissor.Y;
- }
- if (ctx->Scissor.X + ctx->Scissor.Width < buffer->_Xmax) {
- buffer->_Xmax = ctx->Scissor.X + ctx->Scissor.Width;
- }
- if (ctx->Scissor.Y + ctx->Scissor.Height < buffer->_Ymax) {
- buffer->_Ymax = ctx->Scissor.Y + ctx->Scissor.Height;
- }
- /* finally, check for empty region */
- if (buffer->_Xmin > buffer->_Xmax) {
- buffer->_Xmin = buffer->_Xmax;
- }
- if (buffer->_Ymin > buffer->_Ymax) {
- buffer->_Ymin = buffer->_Ymax;
- }
- }
-
- ASSERT(buffer->_Xmin <= buffer->_Xmax);
- ASSERT(buffer->_Ymin <= buffer->_Ymax);
+ /* Default to the first scissor as that's always valid */
+ _mesa_scissor_bounding_box(ctx, buffer, 0, bbox);
+ buffer->_Xmin = bbox[0];
+ buffer->_Ymin = bbox[2];
+ buffer->_Xmax = bbox[1];
+ buffer->_Ymax = bbox[3];
}
diff --git a/mesalib/src/mesa/main/framebuffer.h b/mesalib/src/mesa/main/framebuffer.h
index 264566477..a4274216e 100644
--- a/mesalib/src/mesa/main/framebuffer.h
+++ b/mesalib/src/mesa/main/framebuffer.h
@@ -71,6 +71,11 @@ _mesa_resize_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
extern void
_mesa_resizebuffers( struct gl_context *ctx );
+extern void
+_mesa_scissor_bounding_box(const struct gl_context *ctx,
+ const struct gl_framebuffer *buffer,
+ unsigned idx, int *bbox);
+
extern void
_mesa_update_draw_buffer_bounds(struct gl_context *ctx);
diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c
index b13f9a3db..16dce5b65 100644
--- a/mesalib/src/mesa/main/get.c
+++ b/mesalib/src/mesa/main/get.c
@@ -113,6 +113,7 @@ enum value_type {
TYPE_FLOATN_3,
TYPE_FLOATN_4,
TYPE_DOUBLEN,
+ TYPE_DOUBLEN_2,
TYPE_MATRIX,
TYPE_MATRIX_T,
TYPE_CONST
@@ -162,6 +163,7 @@ struct value_desc {
union value {
GLfloat value_float;
GLfloat value_float_4[4];
+ GLdouble value_double_2[2];
GLmatrix *value_matrix;
GLint value_int;
GLint value_int_4[4];
@@ -389,6 +391,7 @@ EXTRA_EXT(ARB_texture_gather);
EXTRA_EXT(ARB_shader_atomic_counters);
EXTRA_EXT(ARB_draw_indirect);
EXTRA_EXT(ARB_shader_image_load_store);
+EXTRA_EXT(ARB_viewport_array);
static const int
extra_ARB_color_buffer_float_or_glcore[] = {
@@ -665,10 +668,14 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu
break;
case GL_SCISSOR_BOX:
- v->value_int_4[0] = ctx->Scissor.X;
- v->value_int_4[1] = ctx->Scissor.Y;
- v->value_int_4[2] = ctx->Scissor.Width;
- v->value_int_4[3] = ctx->Scissor.Height;
+ v->value_int_4[0] = ctx->Scissor.ScissorArray[0].X;
+ v->value_int_4[1] = ctx->Scissor.ScissorArray[0].Y;
+ v->value_int_4[2] = ctx->Scissor.ScissorArray[0].Width;
+ v->value_int_4[3] = ctx->Scissor.ScissorArray[0].Height;
+ break;
+
+ case GL_SCISSOR_TEST:
+ v->value_bool = ctx->Scissor.EnableFlags & 1;
break;
case GL_LIST_INDEX:
@@ -685,10 +692,15 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu
break;
case GL_VIEWPORT:
- v->value_int_4[0] = ctx->Viewport.X;
- v->value_int_4[1] = ctx->Viewport.Y;
- v->value_int_4[2] = ctx->Viewport.Width;
- v->value_int_4[3] = ctx->Viewport.Height;
+ v->value_float_4[0] = ctx->ViewportArray[0].X;
+ v->value_float_4[1] = ctx->ViewportArray[0].Y;
+ v->value_float_4[2] = ctx->ViewportArray[0].Width;
+ v->value_float_4[3] = ctx->ViewportArray[0].Height;
+ break;
+
+ case GL_DEPTH_RANGE:
+ v->value_double_2[0] = ctx->ViewportArray[0].Near;
+ v->value_double_2[1] = ctx->ViewportArray[0].Far;
break;
case GL_ACTIVE_STENCIL_FACE_EXT:
@@ -1235,6 +1247,8 @@ _mesa_GetBooleanv(GLenum pname, GLboolean *params)
params[0] = FLOAT_TO_BOOLEAN(((GLfloat *) p)[0]);
break;
+ case TYPE_DOUBLEN_2:
+ params[1] = FLOAT_TO_BOOLEAN(((GLdouble *) p)[1]);
case TYPE_DOUBLEN:
params[0] = FLOAT_TO_BOOLEAN(((GLdouble *) p)[0]);
break;
@@ -1321,6 +1335,8 @@ _mesa_GetFloatv(GLenum pname, GLfloat *params)
params[0] = ((GLfloat *) p)[0];
break;
+ case TYPE_DOUBLEN_2:
+ params[1] = (GLfloat) (((GLdouble *) p)[1]);
case TYPE_DOUBLEN:
params[0] = (GLfloat) (((GLdouble *) p)[0]);
break;
@@ -1413,6 +1429,8 @@ _mesa_GetIntegerv(GLenum pname, GLint *params)
params[0] = FLOAT_TO_INT(((GLfloat *) p)[0]);
break;
+ case TYPE_DOUBLEN_2:
+ params[1] = FLOAT_TO_INT(((GLdouble *) p)[1]);
case TYPE_DOUBLEN:
params[0] = FLOAT_TO_INT(((GLdouble *) p)[0]);
break;
@@ -1505,6 +1523,8 @@ _mesa_GetInteger64v(GLenum pname, GLint64 *params)
params[0] = FLOAT_TO_INT64(((GLfloat *) p)[0]);
break;
+ case TYPE_DOUBLEN_2:
+ params[1] = FLOAT_TO_INT64(((GLdouble *) p)[1]);
case TYPE_DOUBLEN:
params[0] = FLOAT_TO_INT64(((GLdouble *) p)[0]);
break;
@@ -1591,6 +1611,8 @@ _mesa_GetDoublev(GLenum pname, GLdouble *params)
params[0] = ((GLfloat *) p)[0];
break;
+ case TYPE_DOUBLEN_2:
+ params[1] = ((GLdouble *) p)[1];
case TYPE_DOUBLEN:
params[0] = ((GLdouble *) p)[0];
break;
@@ -1719,6 +1741,31 @@ find_value_indexed(const char *func, GLenum pname, GLuint index, union value *v)
v->value_int_4[3] = ctx->Color.ColorMask[index][ACOMP] ? 1 : 0;
return TYPE_INT_4;
+ case GL_SCISSOR_BOX:
+ if (index >= ctx->Const.MaxViewports)
+ goto invalid_value;
+ v->value_int_4[0] = ctx->Scissor.ScissorArray[index].X;
+ v->value_int_4[1] = ctx->Scissor.ScissorArray[index].Y;
+ v->value_int_4[2] = ctx->Scissor.ScissorArray[index].Width;
+ v->value_int_4[3] = ctx->Scissor.ScissorArray[index].Height;
+ return TYPE_INT_4;
+
+ case GL_VIEWPORT:
+ if (index >= ctx->Const.MaxViewports)
+ goto invalid_value;
+ v->value_float_4[0] = ctx->ViewportArray[index].X;
+ v->value_float_4[1] = ctx->ViewportArray[index].Y;
+ v->value_float_4[2] = ctx->ViewportArray[index].Width;
+ v->value_float_4[3] = ctx->ViewportArray[index].Height;
+ return TYPE_FLOAT_4;
+
+ case GL_DEPTH_RANGE:
+ if (index >= ctx->Const.MaxViewports)
+ goto invalid_value;
+ v->value_double_2[0] = ctx->ViewportArray[index].Near;
+ v->value_double_2[1] = ctx->ViewportArray[index].Far;
+ return TYPE_DOUBLEN_2;
+
case GL_TRANSFORM_FEEDBACK_BUFFER_START:
if (index >= ctx->Const.MaxTransformFeedbackBuffers)
goto invalid_value;
@@ -1927,6 +1974,26 @@ _mesa_GetIntegeri_v( GLenum pname, GLuint index, GLint *params )
find_value_indexed("glGetIntegeri_v", pname, index, &v);
switch (type) {
+ case TYPE_FLOAT_4:
+ case TYPE_FLOATN_4:
+ params[3] = IROUND(v.value_float_4[3]);
+ case TYPE_FLOAT_3:
+ case TYPE_FLOATN_3:
+ params[2] = IROUND(v.value_float_4[2]);
+ case TYPE_FLOAT_2:
+ case TYPE_FLOATN_2:
+ params[1] = IROUND(v.value_float_4[1]);
+ case TYPE_FLOAT:
+ case TYPE_FLOATN:
+ params[0] = IROUND(v.value_float_4[0]);
+ break;
+
+ case TYPE_DOUBLEN_2:
+ params[1] = IROUND(v.value_double_2[1]);
+ case TYPE_DOUBLEN:
+ params[0] = IROUND(v.value_double_2[0]);
+ break;
+
case TYPE_INT:
params[0] = v.value_int;
break;
@@ -1970,6 +2037,150 @@ _mesa_GetInteger64i_v( GLenum pname, GLuint index, GLint64 *params )
}
void GLAPIENTRY
+_mesa_GetFloati_v(GLenum pname, GLuint index, GLfloat *params)
+{
+ int i;
+ GLmatrix *m;
+ union value v;
+ enum value_type type =
+ find_value_indexed("glGetFloati_v", pname, index, &v);
+
+ switch (type) {
+ case TYPE_FLOAT_4:
+ case TYPE_FLOATN_4:
+ params[3] = v.value_float_4[3];
+ case TYPE_FLOAT_3:
+ case TYPE_FLOATN_3:
+ params[2] = v.value_float_4[2];
+ case TYPE_FLOAT_2:
+ case TYPE_FLOATN_2:
+ params[1] = v.value_float_4[1];
+ case TYPE_FLOAT:
+ case TYPE_FLOATN:
+ params[0] = v.value_float_4[0];
+ break;
+
+ case TYPE_DOUBLEN_2:
+ params[1] = (GLfloat) v.value_double_2[1];
+ case TYPE_DOUBLEN:
+ params[0] = (GLfloat) v.value_double_2[0];
+ break;
+
+ case TYPE_INT_4:
+ params[3] = (GLfloat) v.value_int_4[3];
+ case TYPE_INT_3:
+ params[2] = (GLfloat) v.value_int_4[2];
+ case TYPE_INT_2:
+ case TYPE_ENUM_2:
+ params[1] = (GLfloat) v.value_int_4[1];
+ case TYPE_INT:
+ case TYPE_ENUM:
+ params[0] = (GLfloat) v.value_int_4[0];
+ break;
+
+ case TYPE_INT_N:
+ for (i = 0; i < v.value_int_n.n; i++)
+ params[i] = INT_TO_FLOAT(v.value_int_n.ints[i]);
+ break;
+
+ case TYPE_INT64:
+ params[0] = (GLfloat) v.value_int64;
+ break;
+
+ case TYPE_BOOLEAN:
+ params[0] = BOOLEAN_TO_FLOAT(v.value_bool);
+ break;
+
+ case TYPE_MATRIX:
+ m = *(GLmatrix **) &v;
+ for (i = 0; i < 16; i++)
+ params[i] = m->m[i];
+ break;
+
+ case TYPE_MATRIX_T:
+ m = *(GLmatrix **) &v;
+ for (i = 0; i < 16; i++)
+ params[i] = m->m[transpose[i]];
+ break;
+
+ default:
+ ;
+ }
+}
+
+void GLAPIENTRY
+_mesa_GetDoublei_v(GLenum pname, GLuint index, GLdouble *params)
+{
+ int i;
+ GLmatrix *m;
+ union value v;
+ enum value_type type =
+ find_value_indexed("glGetDoublei_v", pname, index, &v);
+
+ switch (type) {
+ case TYPE_FLOAT_4:
+ case TYPE_FLOATN_4:
+ params[3] = (GLdouble) v.value_float_4[3];
+ case TYPE_FLOAT_3:
+ case TYPE_FLOATN_3:
+ params[2] = (GLdouble) v.value_float_4[2];
+ case TYPE_FLOAT_2:
+ case TYPE_FLOATN_2:
+ params[1] = (GLdouble) v.value_float_4[1];
+ case TYPE_FLOAT:
+ case TYPE_FLOATN:
+ params[0] = (GLdouble) v.value_float_4[0];
+ break;
+
+ case TYPE_DOUBLEN_2:
+ params[1] = v.value_double_2[1];
+ case TYPE_DOUBLEN:
+ params[0] = v.value_double_2[0];
+ break;
+
+ case TYPE_INT_4:
+ params[3] = (GLdouble) v.value_int_4[3];
+ case TYPE_INT_3:
+ params[2] = (GLdouble) v.value_int_4[2];
+ case TYPE_INT_2:
+ case TYPE_ENUM_2:
+ params[1] = (GLdouble) v.value_int_4[1];
+ case TYPE_INT:
+ case TYPE_ENUM:
+ params[0] = (GLdouble) v.value_int_4[0];
+ break;
+
+ case TYPE_INT_N:
+ for (i = 0; i < v.value_int_n.n; i++)
+ params[i] = (GLdouble) INT_TO_FLOAT(v.value_int_n.ints[i]);
+ break;
+
+ case TYPE_INT64:
+ params[0] = (GLdouble) v.value_int64;
+ break;
+
+ case TYPE_BOOLEAN:
+ params[0] = (GLdouble) BOOLEAN_TO_FLOAT(v.value_bool);
+ break;
+
+ case TYPE_MATRIX:
+ m = *(GLmatrix **) &v;
+ for (i = 0; i < 16; i++)
+ params[i] = (GLdouble) m->m[i];
+ break;
+
+ case TYPE_MATRIX_T:
+ m = *(GLmatrix **) &v;
+ for (i = 0; i < 16; i++)
+ params[i] = (GLdouble) m->m[transpose[i]];
+ break;
+
+ default:
+ ;
+ }
+}
+
+void GLAPIENTRY
_mesa_GetFixedv(GLenum pname, GLfixed *params)
{
const struct value_desc *d;
@@ -2000,6 +2211,8 @@ _mesa_GetFixedv(GLenum pname, GLfixed *params)
params[0] = FLOAT_TO_FIXED(((GLfloat *) p)[0]);
break;
+ case TYPE_DOUBLEN_2:
+ params[1] = FLOAT_TO_FIXED(((GLdouble *) p)[1]);
case TYPE_DOUBLEN:
params[0] = FLOAT_TO_FIXED(((GLdouble *) p)[0]);
break;
diff --git a/mesalib/src/mesa/main/get.h b/mesalib/src/mesa/main/get.h
index 0f72508a7..ce97cc586 100644
--- a/mesalib/src/mesa/main/get.h
+++ b/mesalib/src/mesa/main/get.h
@@ -65,6 +65,12 @@ _mesa_GetInteger64i_v( GLenum pname, GLuint index, GLint64 *params );
extern void GLAPIENTRY
_mesa_GetPointerv( GLenum pname, GLvoid **params );
+extern void GLAPIENTRY
+_mesa_GetFloati_v(GLenum target, GLuint index, GLfloat *data);
+
+extern void GLAPIENTRY
+_mesa_GetDoublei_v(GLenum target, GLuint index, GLdouble *data);
+
extern const GLubyte * GLAPIENTRY
_mesa_GetString( GLenum name );
diff --git a/mesalib/src/mesa/main/get_hash_params.py b/mesalib/src/mesa/main/get_hash_params.py
index bc2bbafa8..b45e1430b 100644
--- a/mesalib/src/mesa/main/get_hash_params.py
+++ b/mesalib/src/mesa/main/get_hash_params.py
@@ -11,7 +11,7 @@ descriptor=[
[ "DEPTH_BITS", "BUFFER_INT(Visual.depthBits), extra_new_buffers" ],
[ "DEPTH_CLEAR_VALUE", "CONTEXT_FIELD(Depth.Clear, TYPE_DOUBLEN), NO_EXTRA" ],
[ "DEPTH_FUNC", "CONTEXT_ENUM(Depth.Func), NO_EXTRA" ],
- [ "DEPTH_RANGE", "CONTEXT_FIELD(Viewport.Near, TYPE_FLOATN_2), NO_EXTRA" ],
+ [ "DEPTH_RANGE", "LOC_CUSTOM, TYPE_DOUBLEN_2, 0, NO_EXTRA" ],
[ "DEPTH_TEST", "CONTEXT_BOOL(Depth.Test), NO_EXTRA" ],
[ "DEPTH_WRITEMASK", "CONTEXT_BOOL(Depth.Mask), NO_EXTRA" ],
[ "DITHER", "CONTEXT_BOOL(Color.DitherFlag), NO_EXTRA" ],
@@ -30,7 +30,7 @@ descriptor=[
[ "POLYGON_OFFSET_FILL", "CONTEXT_BOOL(Polygon.OffsetFill), NO_EXTRA" ],
[ "RED_BITS", "BUFFER_INT(Visual.redBits), extra_new_buffers" ],
[ "SCISSOR_BOX", "LOC_CUSTOM, TYPE_INT_4, 0, NO_EXTRA" ],
- [ "SCISSOR_TEST", "CONTEXT_BOOL(Scissor.Enabled), NO_EXTRA" ],
+ [ "SCISSOR_TEST", "LOC_CUSTOM, TYPE_BOOLEAN, NO_OFFSET, NO_EXTRA" ],
[ "STENCIL_BITS", "BUFFER_INT(Visual.stencilBits), extra_new_buffers" ],
[ "STENCIL_CLEAR_VALUE", "CONTEXT_INT(Stencil.Clear), NO_EXTRA" ],
[ "STENCIL_FAIL", "LOC_CUSTOM, TYPE_ENUM, NO_OFFSET, NO_EXTRA" ],
@@ -44,7 +44,7 @@ descriptor=[
[ "SUBPIXEL_BITS", "CONTEXT_INT(Const.SubPixelBits), NO_EXTRA" ],
[ "TEXTURE_BINDING_2D", "LOC_CUSTOM, TYPE_INT, TEXTURE_2D_INDEX, NO_EXTRA" ],
[ "UNPACK_ALIGNMENT", "CONTEXT_INT(Unpack.Alignment), NO_EXTRA" ],
- [ "VIEWPORT", "LOC_CUSTOM, TYPE_INT_4, 0, NO_EXTRA" ],
+ [ "VIEWPORT", "LOC_CUSTOM, TYPE_FLOAT_4, 0, NO_EXTRA" ],
# GL_ARB_multitexture
[ "ACTIVE_TEXTURE", "LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA" ],
@@ -759,6 +759,13 @@ descriptor=[
[ "TEXTURE_BUFFER_OFFSET_ALIGNMENT", "CONTEXT_INT(Const.TextureBufferOffsetAlignment), extra_ARB_texture_buffer_range" ],
# GL_ARB_draw_indirect
[ "DRAW_INDIRECT_BUFFER_BINDING", "LOC_CUSTOM, TYPE_INT, 0, extra_ARB_draw_indirect" ],
+
+# GL_ARB_viewport_array
+ [ "MAX_VIEWPORTS", "CONTEXT_INT(Const.MaxViewports), extra_ARB_viewport_array" ],
+ [ "VIEWPORT_SUBPIXEL_BITS", "CONTEXT_INT(Const.ViewportSubpixelBits), extra_ARB_viewport_array" ],
+ [ "VIEWPORT_BOUNDS_RANGE", "CONTEXT_FLOAT2(Const.ViewportBounds), extra_ARB_viewport_array" ],
+ [ "LAYER_PROVOKING_VERTEX", "CONTEXT_ENUM(Light.ProvokingVertex), extra_ARB_viewport_array" ],
+ [ "VIEWPORT_INDEX_PROVOKING_VERTEX", "CONTEXT_ENUM(Light.ProvokingVertex), extra_ARB_viewport_array" ],
]}
]
diff --git a/mesalib/src/mesa/main/glformats.c b/mesalib/src/mesa/main/glformats.c
index bec7a9bbb..7d4a31057 100644
--- a/mesalib/src/mesa/main/glformats.c
+++ b/mesalib/src/mesa/main/glformats.c
@@ -1136,76 +1136,60 @@ GLenum
_mesa_get_nongeneric_internalformat(GLenum format)
{
switch (format) {
- /* GL 1.1 formats. */
- case 4:
- case GL_RGBA:
- return GL_RGBA8;
-
- case 3:
- case GL_RGB:
- return GL_RGB8;
-
- case 2:
- case GL_LUMINANCE_ALPHA:
- return GL_LUMINANCE8_ALPHA8;
-
- case 1:
- case GL_LUMINANCE:
- return GL_LUMINANCE8;
-
- case GL_ALPHA:
- return GL_ALPHA8;
-
- case GL_INTENSITY:
- return GL_INTENSITY8;
-
- /* GL_ARB_texture_rg */
- case GL_RED:
- return GL_R8;
-
- case GL_RG:
- return GL_RG8;
-
- /* GL_EXT_texture_sRGB */
- case GL_SRGB:
- return GL_SRGB8;
-
- case GL_SRGB_ALPHA:
- return GL_SRGB8_ALPHA8;
-
- case GL_SLUMINANCE:
- return GL_SLUMINANCE8;
-
- case GL_SLUMINANCE_ALPHA:
- return GL_SLUMINANCE8_ALPHA8;
-
- /* GL_EXT_texture_snorm */
- case GL_RGBA_SNORM:
- return GL_RGBA8_SNORM;
-
- case GL_RGB_SNORM:
- return GL_RGB8_SNORM;
-
- case GL_RG_SNORM:
- return GL_RG8_SNORM;
-
- case GL_RED_SNORM:
- return GL_R8_SNORM;
-
- case GL_LUMINANCE_ALPHA_SNORM:
- return GL_LUMINANCE8_ALPHA8_SNORM;
-
- case GL_LUMINANCE_SNORM:
- return GL_LUMINANCE8_SNORM;
+ /* GL 1.1 formats. */
+ case 4:
+ case GL_RGBA:
+ return GL_RGBA8;
+ case 3:
+ case GL_RGB:
+ return GL_RGB8;
+ case 2:
+ case GL_LUMINANCE_ALPHA:
+ return GL_LUMINANCE8_ALPHA8;
+ case 1:
+ case GL_LUMINANCE:
+ return GL_LUMINANCE8;
+ case GL_ALPHA:
+ return GL_ALPHA8;
+ case GL_INTENSITY:
+ return GL_INTENSITY8;
- case GL_ALPHA_SNORM:
- return GL_ALPHA8_SNORM;
+ /* GL_ARB_texture_rg */
+ case GL_RED:
+ return GL_R8;
+ case GL_RG:
+ return GL_RG8;
- case GL_INTENSITY_SNORM:
- return GL_INTENSITY8_SNORM;
+ /* GL_EXT_texture_sRGB */
+ case GL_SRGB:
+ return GL_SRGB8;
+ case GL_SRGB_ALPHA:
+ return GL_SRGB8_ALPHA8;
+ case GL_SLUMINANCE:
+ return GL_SLUMINANCE8;
+ case GL_SLUMINANCE_ALPHA:
+ return GL_SLUMINANCE8_ALPHA8;
+
+ /* GL_EXT_texture_snorm */
+ case GL_RGBA_SNORM:
+ return GL_RGBA8_SNORM;
+ case GL_RGB_SNORM:
+ return GL_RGB8_SNORM;
+ case GL_RG_SNORM:
+ return GL_RG8_SNORM;
+ case GL_RED_SNORM:
+ return GL_R8_SNORM;
+ case GL_LUMINANCE_ALPHA_SNORM:
+ return GL_LUMINANCE8_ALPHA8_SNORM;
+ case GL_LUMINANCE_SNORM:
+ return GL_LUMINANCE8_SNORM;
+ case GL_ALPHA_SNORM:
+ return GL_ALPHA8_SNORM;
+ case GL_INTENSITY_SNORM:
+ return GL_INTENSITY8_SNORM;
- default:
- return format;
+ default:
+ return format;
}
}
@@ -1219,22 +1203,20 @@ _mesa_get_linear_internalformat(GLenum format)
switch (format) {
case GL_SRGB:
return GL_RGB;
-
case GL_SRGB_ALPHA:
return GL_RGBA;
-
case GL_SRGB8:
return GL_RGB8;
-
case GL_SRGB8_ALPHA8:
return GL_RGBA8;
-
- case GL_SLUMINANCE:
+ case GL_SLUMINANCE8:
return GL_LUMINANCE8;
-
+ case GL_SLUMINANCE:
+ return GL_LUMINANCE;
case GL_SLUMINANCE_ALPHA:
+ return GL_LUMINANCE_ALPHA;
+ case GL_SLUMINANCE8_ALPHA8:
return GL_LUMINANCE8_ALPHA8;
-
default:
return format;
}
diff --git a/mesalib/src/mesa/main/macros.h b/mesalib/src/mesa/main/macros.h
index 379f75663..dafeaa372 100644
--- a/mesalib/src/mesa/main/macros.h
+++ b/mesalib/src/mesa/main/macros.h
@@ -809,5 +809,7 @@ DIFFERENT_SIGNS(GLfloat x, GLfloat y)
/* Compute the size of an array */
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
+/* Stringify */
+#define STRINGIFY(x) #x
#endif
diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h
index 33df682cf..9ab2de026 100644
--- a/mesalib/src/mesa/main/mtypes.h
+++ b/mesalib/src/mesa/main/mtypes.h
@@ -235,6 +235,7 @@ typedef enum
VARYING_SLOT_CLIP_DIST1,
VARYING_SLOT_PRIMITIVE_ID, /* Does not appear in VS */
VARYING_SLOT_LAYER, /* Appears as VS or GS output */
+ VARYING_SLOT_VIEWPORT, /* Appears as VS or GS output */
VARYING_SLOT_FACE, /* FS only */
VARYING_SLOT_PNTC, /* FS only */
VARYING_SLOT_VAR0, /* First generic varying slot */
@@ -270,6 +271,7 @@ typedef enum
#define VARYING_BIT_CLIP_DIST1 BITFIELD64_BIT(VARYING_SLOT_CLIP_DIST1)
#define VARYING_BIT_PRIMITIVE_ID BITFIELD64_BIT(VARYING_SLOT_PRIMITIVE_ID)
#define VARYING_BIT_LAYER BITFIELD64_BIT(VARYING_SLOT_LAYER)
+#define VARYING_BIT_VIEWPORT BITFIELD64_BIT(VARYING_SLOT_VIEWPORT)
#define VARYING_BIT_FACE BITFIELD64_BIT(VARYING_SLOT_FACE)
#define VARYING_BIT_PNTC BITFIELD64_BIT(VARYING_SLOT_PNTC)
#define VARYING_BIT_VAR(V) BITFIELD64_BIT(VARYING_SLOT_VAR0 + (V))
@@ -1009,12 +1011,16 @@ struct gl_polygon_attrib
/**
* Scissor attributes (GL_SCISSOR_BIT).
*/
-struct gl_scissor_attrib
+struct gl_scissor_rect
{
- GLboolean Enabled; /**< Scissor test enabled? */
GLint X, Y; /**< Lower left corner of box */
GLsizei Width, Height; /**< Size of box */
};
+struct gl_scissor_attrib
+{
+ GLbitfield EnableFlags; /**< Scissor test enabled? */
+ struct gl_scissor_rect ScissorArray[MAX_VIEWPORTS];
+};
/**
@@ -1428,9 +1434,9 @@ struct gl_transform_attrib
*/
struct gl_viewport_attrib
{
- GLint X, Y; /**< position */
- GLsizei Width, Height; /**< size */
- GLfloat Near, Far; /**< Depth buffer range */
+ GLfloat X, Y; /**< position */
+ GLfloat Width, Height; /**< size */
+ GLdouble Near, Far; /**< Depth buffer range */
GLmatrix _WindowMap; /**< Mapping transformation as a matrix. */
};
@@ -1809,7 +1815,9 @@ struct gl_transform_feedback_object
/**
* The shader program active when BeginTransformFeedback() was called.
- * When active and unpaused, this equals ctx->Shader.CurrentVertexProgram.
+ * When active and unpaused, this equals ctx->Shader.CurrentProgram[stage],
+ * where stage is the pipeline stage that is the source of data for
+ * transform feedback.
*/
struct gl_shader_program *shader_program;
@@ -2708,9 +2716,7 @@ struct gl_shader_state
* GL_EXT_separate_shader_objects is not supported, each of these must point
* to \c NULL or to the same program.
*/
- struct gl_shader_program *CurrentVertexProgram;
- struct gl_shader_program *CurrentGeometryProgram;
- struct gl_shader_program *CurrentFragmentProgram;
+ struct gl_shader_program *CurrentProgram[MESA_SHADER_STAGES];
struct gl_shader_program *_CurrentFragmentProgram;
@@ -2754,10 +2760,13 @@ struct gl_shader_compiler_options
GLuint MaxUnrollIterations;
/**
- * Prefer DP4 instructions (rather than MUL/MAD) for matrix * vector
- * operations, such as position transformation.
+ * Optimize code for array of structures backends.
+ *
+ * This is a proxy for:
+ * - preferring DP4 instructions (rather than MUL/MAD) for
+ * matrix * vector operations, such as position transformation.
*/
- GLboolean PreferDP4;
+ GLboolean OptimizeForAOS;
struct gl_sl_pragmas DefaultPragmas; /**< Default #pragma settings */
};
@@ -3166,6 +3175,12 @@ struct gl_constants
GLfloat MaxSpotExponent; /**< GL_NV_light_max_exponent */
GLuint MaxViewportWidth, MaxViewportHeight;
+ GLuint MaxViewports; /**< GL_ARB_viewport_array */
+ GLuint ViewportSubpixelBits; /**< GL_ARB_viewport_array */
+ struct {
+ GLfloat Min;
+ GLfloat Max;
+ } ViewportBounds; /**< GL_ARB_viewport_array */
struct gl_program_constants Program[MESA_SHADER_STAGES];
GLuint MaxProgramMatrices;
@@ -3366,6 +3381,7 @@ struct gl_extensions
GLboolean ANGLE_texture_compression_dxt;
GLboolean ARB_ES2_compatibility;
GLboolean ARB_ES3_compatibility;
+ GLboolean ARB_arrays_of_arrays;
GLboolean ARB_base_instance;
GLboolean ARB_blend_func_extended;
GLboolean ARB_color_buffer_float;
@@ -3434,6 +3450,7 @@ struct gl_extensions
GLboolean ARB_vertex_shader;
GLboolean ARB_vertex_type_10f_11f_11f_rev;
GLboolean ARB_vertex_type_2_10_10_10_rev;
+ GLboolean ARB_viewport_array;
GLboolean EXT_blend_color;
GLboolean EXT_blend_equation_separate;
GLboolean EXT_blend_func_separate;
@@ -3764,6 +3781,9 @@ struct gl_driver_flags
/** gl_context::TransformFeedback::CurrentObject */
GLbitfield NewTransformFeedback;
+ /** gl_context::TransformFeedback::CurrentObject::shader_program */
+ GLbitfield NewTransformFeedbackProg;
+
/** gl_context::RasterDiscard */
GLbitfield NewRasterizerDiscard;
@@ -3972,7 +3992,7 @@ struct gl_context
struct gl_stencil_attrib Stencil; /**< Stencil buffer attributes */
struct gl_texture_attrib Texture; /**< Texture attributes */
struct gl_transform_attrib Transform; /**< Transformation attributes */
- struct gl_viewport_attrib Viewport; /**< Viewport attributes */
+ struct gl_viewport_attrib ViewportArray[MAX_VIEWPORTS]; /**< Viewport attributes */
/*@}*/
/** \name Client attribute stack */
diff --git a/mesalib/src/mesa/main/rastpos.c b/mesalib/src/mesa/main/rastpos.c
index 1acdb8b53..a9a6ceec0 100644
--- a/mesalib/src/mesa/main/rastpos.c
+++ b/mesalib/src/mesa/main/rastpos.c
@@ -227,8 +227,9 @@ window_pos3f(GLfloat x, GLfloat y, GLfloat z)
FLUSH_VERTICES(ctx, 0);
FLUSH_CURRENT(ctx, 0);
- z2 = CLAMP(z, 0.0F, 1.0F) * (ctx->Viewport.Far - ctx->Viewport.Near)
- + ctx->Viewport.Near;
+ z2 = CLAMP(z, 0.0F, 1.0F)
+ * (ctx->ViewportArray[0].Far - ctx->ViewportArray[0].Near)
+ + ctx->ViewportArray[0].Near;
/* set raster position */
ctx->Current.RasterPos[0] = x;
diff --git a/mesalib/src/mesa/main/scissor.c b/mesalib/src/mesa/main/scissor.c
index ac86bd591..14c8e8a6c 100644
--- a/mesalib/src/mesa/main/scissor.c
+++ b/mesalib/src/mesa/main/scissor.c
@@ -30,11 +30,37 @@
/**
+ * Set scissor rectangle data directly in ScissorArray
+ *
+ * This is an internal function that performs no error checking on the
+ * supplied data. It also does \b not call \c dd_function_table::Scissor.
+ *
+ * \sa _mesa_set_scissor
+ */
+static void
+set_scissor_no_notify(struct gl_context *ctx, unsigned idx,
+ GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ if (x == ctx->Scissor.ScissorArray[idx].X &&
+ y == ctx->Scissor.ScissorArray[idx].Y &&
+ width == ctx->Scissor.ScissorArray[idx].Width &&
+ height == ctx->Scissor.ScissorArray[idx].Height)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_SCISSOR);
+ ctx->Scissor.ScissorArray[idx].X = x;
+ ctx->Scissor.ScissorArray[idx].Y = y;
+ ctx->Scissor.ScissorArray[idx].Width = width;
+ ctx->Scissor.ScissorArray[idx].Height = height;
+}
+
+/**
* Called via glScissor
*/
void GLAPIENTRY
_mesa_Scissor( GLint x, GLint y, GLsizei width, GLsizei height )
{
+ unsigned i;
GET_CURRENT_CONTEXT(ctx);
if (MESA_VERBOSE & VERBOSE_API)
@@ -45,7 +71,23 @@ _mesa_Scissor( GLint x, GLint y, GLsizei width, GLsizei height )
return;
}
- _mesa_set_scissor(ctx, x, y, width, height);
+ /* The GL_ARB_viewport_array spec says:
+ *
+ * "Scissor sets the scissor rectangle for all viewports to the same
+ * values and is equivalent (assuming no errors are generated) to:
+ *
+ * for (uint i = 0; i < MAX_VIEWPORTS; i++) {
+ * ScissorIndexed(i, left, bottom, width, height);
+ * }"
+ *
+ * Set the scissor rectangle for all of the viewports supported by the
+ * implementation, but only signal the driver once at the end.
+ */
+ for (i = 0; i < ctx->Const.MaxViewports; i++)
+ set_scissor_no_notify(ctx, i, x, y, width, height);
+
+ if (ctx->Driver.Scissor)
+ ctx->Driver.Scissor(ctx);
}
@@ -63,25 +105,108 @@ _mesa_Scissor( GLint x, GLint y, GLsizei width, GLsizei height )
* the dd_function_table::Scissor callback.
*/
void
-_mesa_set_scissor(struct gl_context *ctx,
+_mesa_set_scissor(struct gl_context *ctx, unsigned idx,
GLint x, GLint y, GLsizei width, GLsizei height)
{
- if (x == ctx->Scissor.X &&
- y == ctx->Scissor.Y &&
- width == ctx->Scissor.Width &&
- height == ctx->Scissor.Height)
+ set_scissor_no_notify(ctx, idx, x, y, width, height);
+
+ if (ctx->Driver.Scissor)
+ ctx->Driver.Scissor(ctx);
+}
+
+/**
+ * Define count scissor boxes starting at index.
+ *
+ * \param index index of first scissor records to set
+ * \param count number of scissor records to set
+ * \param x, y pointer to array of struct gl_scissor_rects
+ *
+ * \sa glScissorArrayv().
+ *
+ * Verifies the parameters and call set_scissor_no_notify to do the work.
+ */
+void GLAPIENTRY
+_mesa_ScissorArrayv(GLuint first, GLsizei count, const GLint *v)
+{
+ int i;
+ struct gl_scissor_rect *p = (struct gl_scissor_rect *) v;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if ((first + count) > ctx->Const.MaxViewports) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glScissorArrayv: first (%d) + count (%d) >= MaxViewports (%d)",
+ first, count, ctx->Const.MaxViewports);
return;
+ }
- FLUSH_VERTICES(ctx, _NEW_SCISSOR);
- ctx->Scissor.X = x;
- ctx->Scissor.Y = y;
- ctx->Scissor.Width = width;
- ctx->Scissor.Height = height;
+ /* Verify width & height */
+ for (i = 0; i < count; i++) {
+ if (p[i].Width < 0 || p[i].Height < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glScissorArrayv: index (%d) width or height < 0 (%d, %d)",
+ i, p[i].Width, p[i].Height);
+ }
+ }
+
+ for (i = 0; i < count; i++)
+ set_scissor_no_notify(ctx, i + first,
+ p[i].X, p[i].Y, p[i].Width, p[i].Height);
if (ctx->Driver.Scissor)
ctx->Driver.Scissor(ctx);
}
+/**
+ * Define the scissor box.
+ *
+ * \param index index of scissor records to set
+ * \param x, y coordinates of the scissor box lower-left corner.
+ * \param width width of the scissor box.
+ * \param height height of the scissor box.
+ *
+ * Verifies the parameters call set_scissor_no_notify to do the work.
+ */
+static void
+ScissorIndexed(GLuint index, GLint left, GLint bottom,
+ GLsizei width, GLsizei height, const char *function)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "%s(%d, %d, %d, %d, %d)\n",
+ function, index, left, bottom, width, height);
+
+ if (index >= ctx->Const.MaxViewports) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s: index (%d) >= MaxViewports (%d)",
+ function, index, ctx->Const.MaxViewports);
+ return;
+ }
+
+ if (width < 0 || height < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s: index (%d) width or height < 0 (%d, %d)",
+ function, index, width, height);
+ }
+
+ set_scissor_no_notify(ctx, index, left, bottom, width, height);
+
+ if (ctx->Driver.Scissor)
+ ctx->Driver.Scissor(ctx);
+}
+
+void GLAPIENTRY
+_mesa_ScissorIndexed(GLuint index, GLint left, GLint bottom,
+ GLsizei width, GLsizei height)
+{
+ ScissorIndexed(index, left, bottom, width, height, "glScissorIndexd");
+}
+
+void GLAPIENTRY
+_mesa_ScissorIndexedv(GLuint index, const GLint *v)
+{
+ ScissorIndexed(index, v[0], v[1], v[2], v[3], "glScissorIndexdv");
+}
/**
* Initialize the context's scissor state.
@@ -90,10 +215,14 @@ _mesa_set_scissor(struct gl_context *ctx,
void
_mesa_init_scissor(struct gl_context *ctx)
{
+ unsigned i;
+
/* Scissor group */
- ctx->Scissor.Enabled = GL_FALSE;
- ctx->Scissor.X = 0;
- ctx->Scissor.Y = 0;
- ctx->Scissor.Width = 0;
- ctx->Scissor.Height = 0;
+ ctx->Scissor.EnableFlags = 0;
+
+ /* Note: ctx->Const.MaxViewports may not have been set by the driver yet,
+ * so just initialize all of them.
+ */
+ for (i = 0; i < MAX_VIEWPORTS; i++)
+ set_scissor_no_notify(ctx, i, 0, 0, 0, 0);
}
diff --git a/mesalib/src/mesa/main/scissor.h b/mesalib/src/mesa/main/scissor.h
index 0d7e2010a..5f9a9945a 100644
--- a/mesalib/src/mesa/main/scissor.h
+++ b/mesalib/src/mesa/main/scissor.h
@@ -34,9 +34,17 @@ struct gl_context;
extern void GLAPIENTRY
_mesa_Scissor( GLint x, GLint y, GLsizei width, GLsizei height );
+extern void GLAPIENTRY
+_mesa_ScissorArrayv(GLuint first, GLsizei count, const GLint * v);
+
+extern void GLAPIENTRY
+_mesa_ScissorIndexed(GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+
+extern void GLAPIENTRY
+_mesa_ScissorIndexedv(GLuint index, const GLint * v);
extern void
-_mesa_set_scissor(struct gl_context *ctx,
+_mesa_set_scissor(struct gl_context *ctx, unsigned idx,
GLint x, GLint y, GLsizei width, GLsizei height);
diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c
index 6042fa896..61ac0e35a 100644
--- a/mesalib/src/mesa/main/shaderapi.c
+++ b/mesalib/src/mesa/main/shaderapi.c
@@ -130,11 +130,11 @@ _mesa_init_shader_state(struct gl_context *ctx)
void
_mesa_free_shader_state(struct gl_context *ctx)
{
- _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentVertexProgram, NULL);
- _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentGeometryProgram,
- NULL);
- _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentFragmentProgram,
- NULL);
+ int i;
+ for (i = 0; i < MESA_SHADER_STAGES; i++) {
+ _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram[i],
+ NULL);
+ }
_mesa_reference_shader_program(ctx, &ctx->Shader._CurrentFragmentProgram,
NULL);
_mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, NULL);
@@ -171,16 +171,23 @@ _mesa_copy_string(GLchar *dst, GLsizei maxLength,
* \param type Shader target
*
*/
-static bool
-validate_shader_target(const struct gl_context *ctx, GLenum type)
-{
+bool
+_mesa_validate_shader_target(const struct gl_context *ctx, GLenum type)
+{
+ /* Note: when building built-in GLSL functions, this function may be
+ * invoked with ctx == NULL. In that case, we can only validate that it's
+ * a shader target we recognize, not that it's supported in the current
+ * context. But that's fine--we don't need any further validation than
+ * that when building built-in GLSL functions.
+ */
+
switch (type) {
case GL_FRAGMENT_SHADER:
- return ctx->Extensions.ARB_fragment_shader;
+ return ctx == NULL || ctx->Extensions.ARB_fragment_shader;
case GL_VERTEX_SHADER:
- return ctx->Extensions.ARB_vertex_shader;
+ return ctx == NULL || ctx->Extensions.ARB_vertex_shader;
case GL_GEOMETRY_SHADER_ARB:
- return _mesa_has_geometry_shaders(ctx);
+ return ctx == NULL || _mesa_has_geometry_shaders(ctx);
default:
return false;
}
@@ -273,7 +280,7 @@ create_shader(struct gl_context *ctx, GLenum type)
struct gl_shader *sh;
GLuint name;
- if (!validate_shader_target(ctx, type)) {
+ if (!_mesa_validate_shader_target(ctx, type)) {
_mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
return 0;
}
@@ -939,32 +946,11 @@ use_shader_program(struct gl_context *ctx, GLenum type,
struct gl_shader_program *shProg)
{
struct gl_shader_program **target;
+ gl_shader_stage stage = _mesa_shader_enum_to_shader_stage(type);
- switch (type) {
- case GL_VERTEX_SHADER:
- target = &ctx->Shader.CurrentVertexProgram;
- if ((shProg == NULL)
- || (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL)) {
- shProg = NULL;
- }
- break;
- case GL_GEOMETRY_SHADER_ARB:
- target = &ctx->Shader.CurrentGeometryProgram;
- if ((shProg == NULL)
- || (shProg->_LinkedShaders[MESA_SHADER_GEOMETRY] == NULL)) {
- shProg = NULL;
- }
- break;
- case GL_FRAGMENT_SHADER:
- target = &ctx->Shader.CurrentFragmentProgram;
- if ((shProg == NULL)
- || (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)) {
- shProg = NULL;
- }
- break;
- default:
- return;
- }
+ target = &ctx->Shader.CurrentProgram[stage];
+ if ((shProg == NULL) || (shProg->_LinkedShaders[stage] == NULL))
+ shProg = NULL;
if (*target != shProg) {
FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
@@ -1739,7 +1725,7 @@ _mesa_UseShaderProgramEXT(GLenum type, GLuint program)
GET_CURRENT_CONTEXT(ctx);
struct gl_shader_program *shProg = NULL;
- if (!validate_shader_target(ctx, type)) {
+ if (!_mesa_validate_shader_target(ctx, type)) {
_mesa_error(ctx, GL_INVALID_ENUM, "glUseShaderProgramEXT(type)");
return;
}
diff --git a/mesalib/src/mesa/main/shaderapi.h b/mesalib/src/mesa/main/shaderapi.h
index 4822e32c2..10f810caf 100644
--- a/mesalib/src/mesa/main/shaderapi.h
+++ b/mesalib/src/mesa/main/shaderapi.h
@@ -215,6 +215,9 @@ _mesa_copy_linked_program_data(gl_shader_stage type,
const struct gl_shader_program *src,
struct gl_program *dst);
+extern bool
+_mesa_validate_shader_target(const struct gl_context *ctx, GLenum type);
+
#ifdef __cplusplus
}
diff --git a/mesalib/src/mesa/main/shaderobj.c b/mesalib/src/mesa/main/shaderobj.c
index dc81bbc77..4f4bb69a8 100644
--- a/mesalib/src/mesa/main/shaderobj.c
+++ b/mesalib/src/mesa/main/shaderobj.c
@@ -34,6 +34,7 @@
#include "main/context.h"
#include "main/hash.h"
#include "main/mtypes.h"
+#include "main/shaderapi.h"
#include "main/shaderobj.h"
#include "main/uniforms.h"
#include "program/program.h"
@@ -105,8 +106,7 @@ struct gl_shader *
_mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type)
{
struct gl_shader *shader;
- assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER ||
- type == GL_GEOMETRY_SHADER_ARB);
+ assert(_mesa_validate_shader_target(ctx, type));
shader = rzalloc(NULL, struct gl_shader);
if (shader) {
shader->Type = type;
diff --git a/mesalib/src/mesa/main/shared.c b/mesalib/src/mesa/main/shared.c
index 2f73cf3ca..c11c7f9e9 100644
--- a/mesalib/src/mesa/main/shared.c
+++ b/mesalib/src/mesa/main/shared.c
@@ -38,6 +38,7 @@
#include "dlist.h"
#include "samplerobj.h"
#include "set.h"
+#include "shaderapi.h"
#include "shaderobj.h"
#include "syncobj.h"
@@ -218,8 +219,7 @@ delete_shader_cb(GLuint id, void *data, void *userData)
{
struct gl_context *ctx = (struct gl_context *) userData;
struct gl_shader *sh = (struct gl_shader *) data;
- if (sh->Type == GL_FRAGMENT_SHADER || sh->Type == GL_VERTEX_SHADER ||
- sh->Type == GL_GEOMETRY_SHADER) {
+ if (_mesa_validate_shader_target(ctx, sh->Type)) {
ctx->Driver.DeleteShader(ctx, sh);
}
else {
diff --git a/mesalib/src/mesa/main/state.c b/mesalib/src/mesa/main/state.c
index 33070b7e0..bdebbc141 100644
--- a/mesalib/src/mesa/main/state.c
+++ b/mesalib/src/mesa/main/state.c
@@ -94,9 +94,12 @@ update_program_enables(struct gl_context *ctx)
static GLbitfield
update_program(struct gl_context *ctx)
{
- const struct gl_shader_program *vsProg = ctx->Shader.CurrentVertexProgram;
- const struct gl_shader_program *gsProg = ctx->Shader.CurrentGeometryProgram;
- struct gl_shader_program *fsProg = ctx->Shader.CurrentFragmentProgram;
+ const struct gl_shader_program *vsProg =
+ ctx->Shader.CurrentProgram[MESA_SHADER_VERTEX];
+ const struct gl_shader_program *gsProg =
+ ctx->Shader.CurrentProgram[MESA_SHADER_GEOMETRY];
+ struct gl_shader_program *fsProg =
+ ctx->Shader.CurrentProgram[MESA_SHADER_FRAGMENT];
const struct gl_vertex_program *prevVP = ctx->VertexProgram._Current;
const struct gl_fragment_program *prevFP = ctx->FragmentProgram._Current;
const struct gl_geometry_program *prevGP = ctx->GeometryProgram._Current;
@@ -269,6 +272,7 @@ static void
update_viewport_matrix(struct gl_context *ctx)
{
const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF;
+ unsigned i;
ASSERT(depthMax > 0);
@@ -276,11 +280,13 @@ update_viewport_matrix(struct gl_context *ctx)
* and should be maintained elsewhere if at all.
* NOTE: RasterPos uses this.
*/
- _math_matrix_viewport(&ctx->Viewport._WindowMap,
- ctx->Viewport.X, ctx->Viewport.Y,
- ctx->Viewport.Width, ctx->Viewport.Height,
- ctx->Viewport.Near, ctx->Viewport.Far,
- depthMax);
+ for (i = 0; i < ctx->Const.MaxViewports; i++) {
+ _math_matrix_viewport(&ctx->ViewportArray[i]._WindowMap,
+ ctx->ViewportArray[i].X, ctx->ViewportArray[i].Y,
+ ctx->ViewportArray[i].Width, ctx->ViewportArray[i].Height,
+ ctx->ViewportArray[i].Near, ctx->ViewportArray[i].Far,
+ depthMax);
+ }
}
@@ -304,7 +310,7 @@ update_multisample(struct gl_context *ctx)
static void
update_twoside(struct gl_context *ctx)
{
- if (ctx->Shader.CurrentVertexProgram ||
+ if (ctx->Shader.CurrentProgram[MESA_SHADER_VERTEX] ||
ctx->VertexProgram._Enabled) {
ctx->VertexProgram._TwoSideEnabled = ctx->VertexProgram.TwoSideEnabled;
} else {
diff --git a/mesalib/src/mesa/main/texobj.c b/mesalib/src/mesa/main/texobj.c
index 3c64c4376..5d516c55f 100644
--- a/mesalib/src/mesa/main/texobj.c
+++ b/mesalib/src/mesa/main/texobj.c
@@ -1104,10 +1104,10 @@ unbind_texobj_from_texunits(struct gl_context *ctx,
* and unbind it if that's the case.
*/
static void
-unbind_texobj_from_imgunits(struct gl_context *ctx,
- struct gl_texture_object *texObj)
+unbind_texobj_from_image_units(struct gl_context *ctx,
+ struct gl_texture_object *texObj)
{
- int i;
+ GLuint i;
for (i = 0; i < ctx->Const.MaxImageUnits; i++) {
struct gl_image_unit *unit = &ctx->ImageUnits[i];
@@ -1169,7 +1169,7 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *textures)
* image unit. If so, unbind it.
* See section 3.9.X of GL_ARB_shader_image_load_store.
*/
- unbind_texobj_from_imgunits(ctx, delObj);
+ unbind_texobj_from_image_units(ctx, delObj);
_mesa_unlock_texture(ctx, delObj);
diff --git a/mesalib/src/mesa/main/texstate.c b/mesalib/src/mesa/main/texstate.c
index 7720965a8..08725f601 100644
--- a/mesalib/src/mesa/main/texstate.c
+++ b/mesalib/src/mesa/main/texstate.c
@@ -527,27 +527,20 @@ static void
update_texture_state( struct gl_context *ctx )
{
GLuint unit;
- struct gl_program *fprog = NULL;
- struct gl_program *vprog = NULL;
- struct gl_program *gprog = NULL;
+ struct gl_program *prog[MESA_SHADER_STAGES];
GLbitfield enabledFragUnits = 0x0;
-
- if (ctx->Shader.CurrentVertexProgram &&
- ctx->Shader.CurrentVertexProgram->LinkStatus) {
- vprog = ctx->Shader.CurrentVertexProgram->_LinkedShaders[MESA_SHADER_VERTEX]->Program;
- }
-
- if (ctx->Shader.CurrentGeometryProgram &&
- ctx->Shader.CurrentGeometryProgram->LinkStatus) {
- gprog = ctx->Shader.CurrentGeometryProgram->_LinkedShaders[MESA_SHADER_GEOMETRY]->Program;
- }
-
- if (ctx->Shader.CurrentFragmentProgram &&
- ctx->Shader.CurrentFragmentProgram->LinkStatus) {
- fprog = ctx->Shader.CurrentFragmentProgram->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program;
- }
- else if (ctx->FragmentProgram._Enabled) {
- fprog = &ctx->FragmentProgram.Current->Base;
+ int i;
+
+ for (i = 0; i < MESA_SHADER_STAGES; i++) {
+ if (ctx->Shader.CurrentProgram[i] &&
+ ctx->Shader.CurrentProgram[i]->LinkStatus) {
+ prog[i] = ctx->Shader.CurrentProgram[i]->_LinkedShaders[i]->Program;
+ } else {
+ if (i == MESA_SHADER_FRAGMENT && ctx->FragmentProgram._Enabled)
+ prog[i] = &ctx->FragmentProgram.Current->Base;
+ else
+ prog[i] = NULL;
+ }
}
/* TODO: only set this if there are actual changes */
@@ -563,9 +556,7 @@ update_texture_state( struct gl_context *ctx )
*/
for (unit = 0; unit < ctx->Const.MaxCombinedTextureImageUnits; unit++) {
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
- GLbitfield enabledVertTargets = 0x0;
- GLbitfield enabledFragTargets = 0x0;
- GLbitfield enabledGeomTargets = 0x0;
+ GLbitfield enabledTargetsByStage[MESA_SHADER_STAGES];
GLbitfield enabledTargets = 0x0;
GLuint texIndex;
@@ -575,25 +566,16 @@ update_texture_state( struct gl_context *ctx )
* by a fragment program/program. When multiple flags are set, we'll
* settle on the one with highest priority (see below).
*/
- if (vprog) {
- enabledVertTargets |= vprog->TexturesUsed[unit];
+ for (i = 0; i < MESA_SHADER_STAGES; i++) {
+ if (prog[i])
+ enabledTargetsByStage[i] = prog[i]->TexturesUsed[unit];
+ else if (i == MESA_SHADER_FRAGMENT)
+ enabledTargetsByStage[i] = texUnit->Enabled;
+ else
+ enabledTargetsByStage[i] = 0;
+ enabledTargets |= enabledTargetsByStage[i];
}
- if (gprog) {
- enabledGeomTargets |= gprog->TexturesUsed[unit];
- }
-
- if (fprog) {
- enabledFragTargets |= fprog->TexturesUsed[unit];
- }
- else {
- /* fixed-function fragment program */
- enabledFragTargets |= texUnit->Enabled;
- }
-
- enabledTargets = enabledVertTargets | enabledFragTargets |
- enabledGeomTargets;
-
texUnit->_ReallyEnabled = 0x0;
if (enabledTargets == 0x0) {
@@ -625,7 +607,7 @@ update_texture_state( struct gl_context *ctx )
}
if (!texUnit->_ReallyEnabled) {
- if (fprog) {
+ if (prog[MESA_SHADER_FRAGMENT]) {
/* If we get here it means the shader is expecting a texture
* object, but there isn't one (or it's incomplete). Use the
* fallback texture.
@@ -655,25 +637,26 @@ update_texture_state( struct gl_context *ctx )
ctx->Texture._EnabledUnits |= (1 << unit);
- if (enabledFragTargets)
+ if (enabledTargetsByStage[MESA_SHADER_FRAGMENT])
enabledFragUnits |= (1 << unit);
- if (!fprog)
+ if (!prog[MESA_SHADER_FRAGMENT])
update_tex_combine(ctx, texUnit);
}
/* Determine which texture coordinate sets are actually needed */
- if (fprog) {
+ if (prog[MESA_SHADER_FRAGMENT]) {
const GLuint coordMask = (1 << MAX_TEXTURE_COORD_UNITS) - 1;
ctx->Texture._EnabledCoordUnits
- = (fprog->InputsRead >> VARYING_SLOT_TEX0) & coordMask;
+ = (prog[MESA_SHADER_FRAGMENT]->InputsRead >> VARYING_SLOT_TEX0) &
+ coordMask;
}
else {
ctx->Texture._EnabledCoordUnits = enabledFragUnits;
}
- if (!fprog || !vprog)
+ if (!prog[MESA_SHADER_FRAGMENT] || !prog[MESA_SHADER_VERTEX])
update_texgen(ctx);
_mesa_validate_image_units(ctx);
diff --git a/mesalib/src/mesa/main/texstorage.c b/mesalib/src/mesa/main/texstorage.c
index 5062fdb4f..22208572f 100644
--- a/mesalib/src/mesa/main/texstorage.c
+++ b/mesalib/src/mesa/main/texstorage.c
@@ -244,6 +244,10 @@ _mesa_alloc_texture_storage(struct gl_context *ctx,
int face;
int level;
+ (void) width;
+ (void) height;
+ (void) depth;
+
for (face = 0; face < numFaces; face++) {
for (level = 0; level < levels; level++) {
struct gl_texture_image *const texImage = texObj->Image[face][level];
@@ -460,7 +464,16 @@ _mesa_TextureStorage1DEXT(GLuint texture, GLenum target, GLsizei levels,
GLenum internalformat,
GLsizei width)
{
- /* no-op */
+ GET_CURRENT_CONTEXT(ctx);
+
+ (void) texture;
+ (void) target;
+ (void) levels;
+ (void) internalformat;
+ (void) width;
+
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureStorage1DEXT not supported");
}
@@ -469,7 +482,17 @@ _mesa_TextureStorage2DEXT(GLuint texture, GLenum target, GLsizei levels,
GLenum internalformat,
GLsizei width, GLsizei height)
{
- /* no-op */
+ GET_CURRENT_CONTEXT(ctx);
+
+ (void) texture;
+ (void) target;
+ (void) levels;
+ (void) internalformat;
+ (void) width;
+ (void) height;
+
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureStorage2DEXT not supported");
}
@@ -479,5 +502,16 @@ _mesa_TextureStorage3DEXT(GLuint texture, GLenum target, GLsizei levels,
GLenum internalformat,
GLsizei width, GLsizei height, GLsizei depth)
{
- /* no-op */
+ GET_CURRENT_CONTEXT(ctx);
+
+ (void) texture;
+ (void) target;
+ (void) levels;
+ (void) internalformat;
+ (void) width;
+ (void) height;
+ (void) depth;
+
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureStorage3DEXT not supported");
}
diff --git a/mesalib/src/mesa/main/transformfeedback.c b/mesalib/src/mesa/main/transformfeedback.c
index 76d213b16..6b9565ca3 100644
--- a/mesalib/src/mesa/main/transformfeedback.c
+++ b/mesalib/src/mesa/main/transformfeedback.c
@@ -24,7 +24,7 @@
/*
- * Vertex transform feedback support.
+ * Transform feedback support.
*
* Authors:
* Brian Paul
@@ -376,24 +376,48 @@ _mesa_compute_max_transform_feedback_vertices(
**/
+/**
+ * Figure out which stage of the pipeline is the source of transform feedback
+ * data given the current context state, and return its gl_shader_program.
+ *
+ * If no active program can generate transform feedback data (i.e. no vertex
+ * shader is active), returns NULL.
+ */
+static struct gl_shader_program *
+get_xfb_source(struct gl_context *ctx)
+{
+ int i;
+ for (i = MESA_SHADER_GEOMETRY; i >= MESA_SHADER_VERTEX; i--) {
+ if (ctx->Shader.CurrentProgram[i] != NULL)
+ return ctx->Shader.CurrentProgram[i];
+ }
+ return NULL;
+}
+
+
void GLAPIENTRY
_mesa_BeginTransformFeedback(GLenum mode)
{
struct gl_transform_feedback_object *obj;
- struct gl_transform_feedback_info *info;
+ struct gl_transform_feedback_info *info = NULL;
+ struct gl_shader_program *source;
GLuint i;
unsigned vertices_per_prim;
GET_CURRENT_CONTEXT(ctx);
obj = ctx->TransformFeedback.CurrentObject;
- if (ctx->Shader.CurrentVertexProgram == NULL) {
+ /* Figure out what pipeline stage is the source of data for transform
+ * feedback.
+ */
+ source = get_xfb_source(ctx);
+ if (source == NULL) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glBeginTransformFeedback(no program active)");
return;
}
- info = &ctx->Shader.CurrentVertexProgram->LinkedTransformFeedback;
+ info = &source->LinkedTransformFeedback;
if (info->NumOutputs == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION,
@@ -451,7 +475,10 @@ _mesa_BeginTransformFeedback(GLenum mode)
obj->GlesRemainingPrims = max_vertices / vertices_per_prim;
}
- obj->shader_program = ctx->Shader.CurrentVertexProgram;
+ if (obj->shader_program != source) {
+ ctx->NewDriverState |= ctx->DriverFlags.NewTransformFeedbackProg;
+ obj->shader_program = source;
+ }
assert(ctx->Driver.BeginTransformFeedback);
ctx->Driver.BeginTransformFeedback(ctx, mode, obj);
@@ -518,7 +545,7 @@ bind_buffer_range(struct gl_context *ctx, GLuint index,
/**
- * Specify a buffer object to receive vertex shader results. Plus,
+ * Specify a buffer object to receive transform feedback results. Plus,
* specify the starting offset to place the results, and max size.
* Called from the glBindBufferRange() function.
*/
@@ -562,7 +589,7 @@ _mesa_bind_buffer_range_transform_feedback(struct gl_context *ctx,
/**
- * Specify a buffer object to receive vertex shader results.
+ * Specify a buffer object to receive transform feedback results.
* As above, but start at offset = 0.
* Called from the glBindBufferBase() function.
*/
@@ -591,7 +618,7 @@ _mesa_bind_buffer_base_transform_feedback(struct gl_context *ctx,
/**
- * Specify a buffer object to receive vertex shader results, plus the
+ * Specify a buffer object to receive transform feedback results, plus the
* offset in the buffer to start placing results.
* This function is part of GL_EXT_transform_feedback, but not GL3.
*/
@@ -646,7 +673,7 @@ _mesa_BindBufferOffsetEXT(GLenum target, GLuint index, GLuint buffer,
/**
- * This function specifies the vertex shader outputs to be written
+ * This function specifies the transform feedback outputs to be written
* to the feedback buffer(s), and in what order.
*/
void GLAPIENTRY
@@ -756,7 +783,7 @@ _mesa_TransformFeedbackVaryings(GLuint program, GLsizei count,
/**
- * Get info about the vertex shader's outputs which are to be written
+ * Get info about the transform feedback outputs which are to be written
* to the feedback buffer(s).
*/
void GLAPIENTRY
@@ -993,9 +1020,9 @@ _mesa_ResumeTransformFeedback(void)
* the program object being used by the current transform feedback object
* is not active."
*/
- if (obj->shader_program != ctx->Shader.CurrentVertexProgram) {
+ if (obj->shader_program != get_xfb_source(ctx)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glResumeTransformFeedback(wrong vertex program bound)");
+ "glResumeTransformFeedback(wrong program bound)");
return;
}
diff --git a/mesalib/src/mesa/main/viewport.c b/mesalib/src/mesa/main/viewport.c
index 3aaab2d46..6545bf68a 100644
--- a/mesalib/src/mesa/main/viewport.c
+++ b/mesalib/src/mesa/main/viewport.c
@@ -34,6 +34,60 @@
#include "mtypes.h"
#include "viewport.h"
+static void
+set_viewport_no_notify(struct gl_context *ctx, unsigned idx,
+ GLfloat x, GLfloat y,
+ GLfloat width, GLfloat height)
+{
+ /* clamp width and height to the implementation dependent range */
+ width = MIN2(width, (GLfloat) ctx->Const.MaxViewportWidth);
+ height = MIN2(height, (GLfloat) ctx->Const.MaxViewportHeight);
+
+ /* The GL_ARB_viewport_array spec says:
+ *
+ * "The location of the viewport's bottom-left corner, given by (x,y),
+ * are clamped to be within the implementation-dependent viewport
+ * bounds range. The viewport bounds range [min, max] tuple may be
+ * determined by calling GetFloatv with the symbolic constant
+ * VIEWPORT_BOUNDS_RANGE (see section 6.1)."
+ */
+ if (ctx->Extensions.ARB_viewport_array) {
+ x = CLAMP(x,
+ ctx->Const.ViewportBounds.Min, ctx->Const.ViewportBounds.Max);
+ y = CLAMP(y,
+ ctx->Const.ViewportBounds.Min, ctx->Const.ViewportBounds.Max);
+ }
+
+ ctx->ViewportArray[idx].X = x;
+ ctx->ViewportArray[idx].Width = width;
+ ctx->ViewportArray[idx].Y = y;
+ ctx->ViewportArray[idx].Height = height;
+ ctx->NewState |= _NEW_VIEWPORT;
+
+#if 1
+ /* XXX remove this someday. Currently the DRI drivers rely on
+ * the WindowMap matrix being up to date in the driver's Viewport
+ * and DepthRange functions.
+ */
+ _math_matrix_viewport(&ctx->ViewportArray[idx]._WindowMap,
+ ctx->ViewportArray[idx].X,
+ ctx->ViewportArray[idx].Y,
+ ctx->ViewportArray[idx].Width,
+ ctx->ViewportArray[idx].Height,
+ ctx->ViewportArray[idx].Near,
+ ctx->ViewportArray[idx].Far,
+ ctx->DrawBuffer->_DepthMaxF);
+#endif
+}
+
+struct gl_viewport_inputs {
+ GLfloat X, Y; /**< position */
+ GLfloat Width, Height; /**< size */
+};
+
+struct gl_depthrange_inputs {
+ GLdouble Near, Far; /**< Depth buffer range */
+};
/**
* Set the viewport.
@@ -45,9 +99,39 @@
void GLAPIENTRY
_mesa_Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
{
+ unsigned i;
GET_CURRENT_CONTEXT(ctx);
FLUSH_VERTICES(ctx, 0);
- _mesa_set_viewport(ctx, x, y, width, height);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glViewport %d %d %d %d\n", x, y, width, height);
+
+ if (width < 0 || height < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glViewport(%d, %d, %d, %d)", x, y, width, height);
+ return;
+ }
+
+ /* The GL_ARB_viewport_array spec says:
+ *
+ * "Viewport sets the parameters for all viewports to the same values
+ * and is equivalent (assuming no errors are generated) to:
+ *
+ * for (uint i = 0; i < MAX_VIEWPORTS; i++)
+ * ViewportIndexedf(i, 1, (float)x, (float)y, (float)w, (float)h);"
+ *
+ * Set all of the viewports supported by the implementation, but only
+ * signal the driver once at the end.
+ */
+ for (i = 0; i < ctx->Const.MaxViewports; i++)
+ set_viewport_no_notify(ctx, i, x, y, width, height);
+
+ if (ctx->Driver.Viewport) {
+ /* Many drivers will use this call to check for window size changes
+ * and reallocate the z/stencil/accum/etc buffers if needed.
+ */
+ ctx->Driver.Viewport(ctx);
+ }
}
@@ -56,31 +140,114 @@ _mesa_Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
* matrix). Usually called from _mesa_Viewport().
*
* \param ctx GL context.
+ * \param idx Index of the viewport to be updated.
* \param x, y coordinates of the lower left corner of the viewport rectangle.
* \param width width of the viewport rectangle.
* \param height height of the viewport rectangle.
*/
void
-_mesa_set_viewport(struct gl_context *ctx, GLint x, GLint y,
- GLsizei width, GLsizei height)
+_mesa_set_viewport(struct gl_context *ctx, unsigned idx, GLfloat x, GLfloat y,
+ GLfloat width, GLfloat height)
{
+ set_viewport_no_notify(ctx, idx, x, y, width, height);
+
+ if (ctx->Driver.Viewport) {
+ /* Many drivers will use this call to check for window size changes
+ * and reallocate the z/stencil/accum/etc buffers if needed.
+ */
+ ctx->Driver.Viewport(ctx);
+ }
+}
+
+void GLAPIENTRY
+_mesa_ViewportArrayv(GLuint first, GLsizei count, const GLfloat *v)
+{
+ int i;
+ const struct gl_viewport_inputs *const p = (struct gl_viewport_inputs *) v;
+ GET_CURRENT_CONTEXT(ctx);
+
if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glViewport %d %d %d %d\n", x, y, width, height);
+ _mesa_debug(ctx, "glViewportArrayv %d %d\n", first, count);
- if (width < 0 || height < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glViewport(%d, %d, %d, %d)", x, y, width, height);
+ if ((first + count) > ctx->Const.MaxViewports) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glViewportArrayv: first (%d) + count (%d) > MaxViewports "
+ "(%d)",
+ first, count, ctx->Const.MaxViewports);
return;
}
- /* clamp width and height to the implementation dependent range */
- width = MIN2(width, (GLsizei) ctx->Const.MaxViewportWidth);
- height = MIN2(height, (GLsizei) ctx->Const.MaxViewportHeight);
+ /* Verify width & height */
+ for (i = 0; i < count; i++) {
+ if (p[i].Width < 0 || p[i].Height < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glViewportArrayv: index (%d) width or height < 0 "
+ "(%f, %f)",
+ i + first, p[i].Width, p[i].Height);
+ return;
+ }
+ }
+
+ for (i = 0; i < count; i++)
+ set_viewport_no_notify(ctx, i + first,
+ p[i].X, p[i].Y,
+ p[i].Width, p[i].Height);
+
+ if (ctx->Driver.Viewport)
+ ctx->Driver.Viewport(ctx);
+}
- ctx->Viewport.X = x;
- ctx->Viewport.Width = width;
- ctx->Viewport.Y = y;
- ctx->Viewport.Height = height;
+static void
+ViewportIndexedf(GLuint index, GLfloat x, GLfloat y,
+ GLfloat w, GLfloat h, const char *function)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "%s(%d, %f, %f, %f, %f)\n",
+ function, index, x, y, w, h);
+
+ if (index >= ctx->Const.MaxViewports) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s: index (%d) >= MaxViewports (%d)",
+ function, index, ctx->Const.MaxViewports);
+ return;
+ }
+
+ /* Verify width & height */
+ if (w < 0 || h < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s: index (%d) width or height < 0 (%f, %f)",
+ function, index, w, h);
+ return;
+ }
+
+ _mesa_set_viewport(ctx, index, x, y, w, h);
+}
+
+void GLAPIENTRY
+_mesa_ViewportIndexedf(GLuint index, GLfloat x, GLfloat y,
+ GLfloat w, GLfloat h)
+{
+ ViewportIndexedf(index, x, y, w, h, "glViewportIndexedf");
+}
+
+void GLAPIENTRY
+_mesa_ViewportIndexedfv(GLuint index, const GLfloat *v)
+{
+ ViewportIndexedf(index, v[0], v[1], v[2], v[3], "glViewportIndexedfv");
+}
+
+static void
+set_depth_range_no_notify(struct gl_context *ctx, unsigned idx,
+ GLclampd nearval, GLclampd farval)
+{
+ if (ctx->ViewportArray[idx].Near == nearval &&
+ ctx->ViewportArray[idx].Far == farval)
+ return;
+
+ ctx->ViewportArray[idx].Near = CLAMP(nearval, 0.0, 1.0);
+ ctx->ViewportArray[idx].Far = CLAMP(farval, 0.0, 1.0);
ctx->NewState |= _NEW_VIEWPORT;
#if 1
@@ -88,21 +255,26 @@ _mesa_set_viewport(struct gl_context *ctx, GLint x, GLint y,
* the WindowMap matrix being up to date in the driver's Viewport
* and DepthRange functions.
*/
- _math_matrix_viewport(&ctx->Viewport._WindowMap,
- ctx->Viewport.X, ctx->Viewport.Y,
- ctx->Viewport.Width, ctx->Viewport.Height,
- ctx->Viewport.Near, ctx->Viewport.Far,
+ _math_matrix_viewport(&ctx->ViewportArray[idx]._WindowMap,
+ ctx->ViewportArray[idx].X,
+ ctx->ViewportArray[idx].Y,
+ ctx->ViewportArray[idx].Width,
+ ctx->ViewportArray[idx].Height,
+ ctx->ViewportArray[idx].Near,
+ ctx->ViewportArray[idx].Far,
ctx->DrawBuffer->_DepthMaxF);
#endif
-
- if (ctx->Driver.Viewport) {
- /* Many drivers will use this call to check for window size changes
- * and reallocate the z/stencil/accum/etc buffers if needed.
- */
- ctx->Driver.Viewport(ctx);
- }
}
+void
+_mesa_set_depth_range(struct gl_context *ctx, unsigned idx,
+ GLclampd nearval, GLclampd farval)
+{
+ set_depth_range_no_notify(ctx, idx, nearval, farval);
+
+ if (ctx->Driver.DepthRange)
+ ctx->Driver.DepthRange(ctx);
+}
/**
* Called by glDepthRange
@@ -115,6 +287,7 @@ _mesa_set_viewport(struct gl_context *ctx, GLint x, GLint y,
void GLAPIENTRY
_mesa_DepthRange(GLclampd nearval, GLclampd farval)
{
+ unsigned i;
GET_CURRENT_CONTEXT(ctx);
FLUSH_VERTICES(ctx, 0);
@@ -122,25 +295,19 @@ _mesa_DepthRange(GLclampd nearval, GLclampd farval)
if (MESA_VERBOSE&VERBOSE_API)
_mesa_debug(ctx, "glDepthRange %f %f\n", nearval, farval);
- if (ctx->Viewport.Near == nearval &&
- ctx->Viewport.Far == farval)
- return;
-
- ctx->Viewport.Near = (GLfloat) CLAMP(nearval, 0.0, 1.0);
- ctx->Viewport.Far = (GLfloat) CLAMP(farval, 0.0, 1.0);
- ctx->NewState |= _NEW_VIEWPORT;
-
-#if 1
- /* XXX remove this someday. Currently the DRI drivers rely on
- * the WindowMap matrix being up to date in the driver's Viewport
- * and DepthRange functions.
+ /* The GL_ARB_viewport_array spec says:
+ *
+ * "DepthRange sets the depth range for all viewports to the same
+ * values and is equivalent (assuming no errors are generated) to:
+ *
+ * for (uint i = 0; i < MAX_VIEWPORTS; i++)
+ * DepthRangeIndexed(i, n, f);"
+ *
+ * Set the depth range for all of the viewports supported by the
+ * implementation, but only signal the driver once at the end.
*/
- _math_matrix_viewport(&ctx->Viewport._WindowMap,
- ctx->Viewport.X, ctx->Viewport.Y,
- ctx->Viewport.Width, ctx->Viewport.Height,
- ctx->Viewport.Near, ctx->Viewport.Far,
- ctx->DrawBuffer->_DepthMaxF);
-#endif
+ for (i = 0; i < ctx->Const.MaxViewports; i++)
+ set_depth_range_no_notify(ctx, i, nearval, farval);
if (ctx->Driver.DepthRange) {
ctx->Driver.DepthRange(ctx);
@@ -153,6 +320,67 @@ _mesa_DepthRangef(GLclampf nearval, GLclampf farval)
_mesa_DepthRange(nearval, farval);
}
+/**
+ * Update a range DepthRange values
+ *
+ * \param first starting array index
+ * \param count count of DepthRange items to update
+ * \param v pointer to memory containing
+ * GLclampd near and far clip-plane values
+ */
+void GLAPIENTRY
+_mesa_DepthRangeArrayv(GLuint first, GLsizei count, const GLclampd *v)
+{
+ int i;
+ const struct gl_depthrange_inputs *const p =
+ (struct gl_depthrange_inputs *) v;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glDepthRangeArrayv %d %d\n", first, count);
+
+ if ((first + count) > ctx->Const.MaxViewports) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glDepthRangev: first (%d) + count (%d) >= MaxViewports (%d)",
+ first, count, ctx->Const.MaxViewports);
+ return;
+ }
+
+ for (i = 0; i < count; i++)
+ set_depth_range_no_notify(ctx, i + first, p[i].Near, p[i].Far);
+
+ if (ctx->Driver.DepthRange)
+ ctx->Driver.DepthRange(ctx);
+}
+
+/**
+ * Update a single DepthRange
+ *
+ * \param index array index to update
+ * \param nearval specifies the Z buffer value which should correspond to
+ * the near clip plane
+ * \param farval specifies the Z buffer value which should correspond to
+ * the far clip plane
+ */
+void GLAPIENTRY
+_mesa_DepthRangeIndexed(GLuint index, GLclampd nearval, GLclampd farval)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glDepthRangeIndexed(%d, %f, %f)\n",
+ index, nearval, farval);
+
+ if (index >= ctx->Const.MaxViewports) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glDepthRangeIndexed: index (%d) >= MaxViewports (%d)",
+ index, ctx->Const.MaxViewports);
+ return;
+ }
+
+ _mesa_set_depth_range(ctx, index, nearval, farval);
+}
+
/**
* Initialize the context viewport attribute group.
* \param ctx the GL context.
@@ -160,18 +388,24 @@ _mesa_DepthRangef(GLclampf nearval, GLclampf farval)
void _mesa_init_viewport(struct gl_context *ctx)
{
GLfloat depthMax = 65535.0F; /* sorf of arbitrary */
+ unsigned i;
- /* Viewport group */
- ctx->Viewport.X = 0;
- ctx->Viewport.Y = 0;
- ctx->Viewport.Width = 0;
- ctx->Viewport.Height = 0;
- ctx->Viewport.Near = 0.0;
- ctx->Viewport.Far = 1.0;
- _math_matrix_ctr(&ctx->Viewport._WindowMap);
-
- _math_matrix_viewport(&ctx->Viewport._WindowMap, 0, 0, 0, 0,
- 0.0F, 1.0F, depthMax);
+ /* Note: ctx->Const.MaxViewports may not have been set by the driver yet,
+ * so just initialize all of them.
+ */
+ for (i = 0; i < MAX_VIEWPORTS; i++) {
+ /* Viewport group */
+ ctx->ViewportArray[i].X = 0;
+ ctx->ViewportArray[i].Y = 0;
+ ctx->ViewportArray[i].Width = 0;
+ ctx->ViewportArray[i].Height = 0;
+ ctx->ViewportArray[i].Near = 0.0;
+ ctx->ViewportArray[i].Far = 1.0;
+ _math_matrix_ctr(&ctx->ViewportArray[i]._WindowMap);
+
+ _math_matrix_viewport(&ctx->ViewportArray[i]._WindowMap, 0, 0, 0, 0,
+ 0.0F, 1.0F, depthMax);
+ }
}
@@ -181,6 +415,9 @@ void _mesa_init_viewport(struct gl_context *ctx)
*/
void _mesa_free_viewport_data(struct gl_context *ctx)
{
- _math_matrix_dtr(&ctx->Viewport._WindowMap);
+ unsigned i;
+
+ for (i = 0; i < MAX_VIEWPORTS; i++)
+ _math_matrix_dtr(&ctx->ViewportArray[i]._WindowMap);
}
diff --git a/mesalib/src/mesa/main/viewport.h b/mesalib/src/mesa/main/viewport.h
index ffa3a729c..f2311c02b 100644
--- a/mesalib/src/mesa/main/viewport.h
+++ b/mesalib/src/mesa/main/viewport.h
@@ -34,10 +34,18 @@ struct gl_context;
extern void GLAPIENTRY
_mesa_Viewport(GLint x, GLint y, GLsizei width, GLsizei height);
+extern void GLAPIENTRY
+_mesa_ViewportArrayv(GLuint first, GLsizei count, const GLfloat * v);
+
+extern void GLAPIENTRY
+_mesa_ViewportIndexedf(GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+
+extern void GLAPIENTRY
+_mesa_ViewportIndexedfv(GLuint index, const GLfloat * v);
extern void
-_mesa_set_viewport(struct gl_context *ctx, GLint x, GLint y,
- GLsizei width, GLsizei height);
+_mesa_set_viewport(struct gl_context *ctx, unsigned idx, GLfloat x, GLfloat y,
+ GLfloat width, GLfloat height);
extern void GLAPIENTRY
@@ -46,6 +54,15 @@ _mesa_DepthRange(GLclampd nearval, GLclampd farval);
extern void GLAPIENTRY
_mesa_DepthRangef(GLclampf nearval, GLclampf farval);
+extern void GLAPIENTRY
+_mesa_DepthRangeArrayv(GLuint first, GLsizei count, const GLclampd * v);
+
+extern void GLAPIENTRY
+_mesa_DepthRangeIndexed(GLuint index, GLclampd n, GLclampd f);
+
+extern void
+_mesa_set_depth_range(struct gl_context *ctx, unsigned idx,
+ GLclampd nearval, GLclampd farval);
extern void
_mesa_init_viewport(struct gl_context *ctx);