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/buffers.c2
-rw-r--r--mesalib/src/mesa/main/condrender.c23
-rw-r--r--mesalib/src/mesa/main/context.c204
-rw-r--r--mesalib/src/mesa/main/context.h3
-rw-r--r--mesalib/src/mesa/main/copyimage.c8
-rw-r--r--mesalib/src/mesa/main/extensions.c15
-rw-r--r--mesalib/src/mesa/main/extensions.h2
-rw-r--r--mesalib/src/mesa/main/ff_fragment_shader.cpp2
-rw-r--r--mesalib/src/mesa/main/ffvertex_prog.c2
-rw-r--r--mesalib/src/mesa/main/format_info.py7
-rw-r--r--mesalib/src/mesa/main/formats.c45
-rw-r--r--mesalib/src/mesa/main/formats.csv6
-rw-r--r--mesalib/src/mesa/main/formats.h9
-rw-r--r--mesalib/src/mesa/main/glformats.c10
-rw-r--r--mesalib/src/mesa/main/mipmap.c13
-rw-r--r--mesalib/src/mesa/main/mtypes.h7
-rw-r--r--mesalib/src/mesa/main/pixelstore.c42
-rw-r--r--mesalib/src/mesa/main/pixelstore.h8
-rw-r--r--mesalib/src/mesa/main/shaderapi.c4
-rw-r--r--mesalib/src/mesa/main/shared.c2
-rw-r--r--mesalib/src/mesa/main/texcompress.c34
-rw-r--r--mesalib/src/mesa/main/texcompress_bptc.c1649
-rw-r--r--mesalib/src/mesa/main/texcompress_bptc.h44
-rw-r--r--mesalib/src/mesa/main/texformat.c8
-rw-r--r--mesalib/src/mesa/main/texgetimage.c9
-rw-r--r--mesalib/src/mesa/main/teximage.c64
-rw-r--r--mesalib/src/mesa/main/teximage.h6
-rw-r--r--mesalib/src/mesa/main/texparam.c6
-rw-r--r--mesalib/src/mesa/main/texstore.c40
-rw-r--r--mesalib/src/mesa/main/texstore.h9
-rw-r--r--mesalib/src/mesa/main/uniform_query.cpp4
-rw-r--r--mesalib/src/mesa/main/varray.c4
-rw-r--r--mesalib/src/mesa/main/varray.h4
-rw-r--r--mesalib/src/mesa/main/version.c308
-rw-r--r--mesalib/src/mesa/main/version.h11
35 files changed, 2282 insertions, 332 deletions
diff --git a/mesalib/src/mesa/main/buffers.c b/mesalib/src/mesa/main/buffers.c
index 140cf6e82..8a0852c42 100644
--- a/mesalib/src/mesa/main/buffers.c
+++ b/mesalib/src/mesa/main/buffers.c
@@ -498,7 +498,7 @@ _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers,
* (ex: glDrawBuffer(GL_FRONT_AND_BACK)).
* Otherwise, destMask[x] can only have one bit set.
*/
- if (_mesa_bitcount(destMask[0]) > 1) {
+ if (n > 0 && _mesa_bitcount(destMask[0]) > 1) {
GLuint count = 0, destMask0 = destMask[0];
while (destMask0) {
GLint bufIndex = ffs(destMask0) - 1;
diff --git a/mesalib/src/mesa/main/condrender.c b/mesalib/src/mesa/main/condrender.c
index 0ad1e5c2a..75f9d74bc 100644
--- a/mesalib/src/mesa/main/condrender.c
+++ b/mesalib/src/mesa/main/condrender.c
@@ -77,8 +77,14 @@ _mesa_BeginConditionalRender(GLuint queryId, GLenum mode)
case GL_QUERY_NO_WAIT:
case GL_QUERY_BY_REGION_WAIT:
case GL_QUERY_BY_REGION_NO_WAIT:
- /* OK */
- break;
+ break; /* OK */
+ case GL_QUERY_WAIT_INVERTED:
+ case GL_QUERY_NO_WAIT_INVERTED:
+ case GL_QUERY_BY_REGION_WAIT_INVERTED:
+ case GL_QUERY_BY_REGION_NO_WAIT_INVERTED:
+ if (ctx->Extensions.ARB_conditional_render_inverted)
+ break; /* OK */
+ /* fallthrough - invalid */
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glBeginConditionalRender(mode=%s)",
_mesa_lookup_enum_by_nr(mode));
@@ -156,12 +162,25 @@ _mesa_check_conditional_render(struct gl_context *ctx)
ctx->Driver.WaitQuery(ctx, q);
}
return q->Result > 0;
+ case GL_QUERY_BY_REGION_WAIT_INVERTED:
+ /* fall-through */
+ case GL_QUERY_WAIT_INVERTED:
+ if (!q->Ready) {
+ ctx->Driver.WaitQuery(ctx, q);
+ }
+ return q->Result == 0;
case GL_QUERY_BY_REGION_NO_WAIT:
/* fall-through */
case GL_QUERY_NO_WAIT:
if (!q->Ready)
ctx->Driver.CheckQuery(ctx, q);
return q->Ready ? (q->Result > 0) : GL_TRUE;
+ case GL_QUERY_BY_REGION_NO_WAIT_INVERTED:
+ /* fall-through */
+ case GL_QUERY_NO_WAIT_INVERTED:
+ if (!q->Ready)
+ ctx->Driver.CheckQuery(ctx, q);
+ return q->Ready ? (q->Result == 0) : GL_TRUE;
default:
_mesa_problem(ctx, "Bad cond render mode %s in "
" _mesa_check_conditional_render()",
diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c
index 50aae8bf6..232084267 100644
--- a/mesalib/src/mesa/main/context.c
+++ b/mesalib/src/mesa/main/context.c
@@ -464,7 +464,7 @@ _mesa_init_current(struct gl_context *ctx)
* Important: drivers should override these with actual limits.
*/
static void
-init_program_limits(struct gl_context *ctx, gl_shader_stage stage,
+init_program_limits(struct gl_constants *consts, gl_shader_stage stage,
struct gl_program_constants *prog)
{
prog->MaxInstructions = MAX_PROGRAM_INSTRUCTIONS;
@@ -546,7 +546,7 @@ init_program_limits(struct gl_context *ctx, gl_shader_stage stage,
prog->MaxUniformBlocks = 12;
prog->MaxCombinedUniformComponents = (prog->MaxUniformComponents +
- ctx->Const.MaxUniformBlockSize / 4 *
+ consts->MaxUniformBlockSize / 4 *
prog->MaxUniformBlocks);
prog->MaxAtomicBuffers = 0;
@@ -559,161 +559,161 @@ init_program_limits(struct gl_context *ctx, gl_shader_stage stage,
* Use defaults from config.h. The device drivers will often override
* some of these values (such as number of texture units).
*/
-static void
-_mesa_init_constants(struct gl_context *ctx)
+void
+_mesa_init_constants(struct gl_constants *consts, gl_api api)
{
int i;
- assert(ctx);
+ assert(consts);
/* Constants, may be overriden (usually only reduced) by device drivers */
- ctx->Const.MaxTextureMbytes = MAX_TEXTURE_MBYTES;
- ctx->Const.MaxTextureLevels = MAX_TEXTURE_LEVELS;
- ctx->Const.Max3DTextureLevels = MAX_3D_TEXTURE_LEVELS;
- ctx->Const.MaxCubeTextureLevels = MAX_CUBE_TEXTURE_LEVELS;
- ctx->Const.MaxTextureRectSize = MAX_TEXTURE_RECT_SIZE;
- ctx->Const.MaxArrayTextureLayers = MAX_ARRAY_TEXTURE_LAYERS;
- ctx->Const.MaxTextureCoordUnits = MAX_TEXTURE_COORD_UNITS;
- ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
- ctx->Const.MaxTextureUnits = MIN2(ctx->Const.MaxTextureCoordUnits,
- ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits);
- ctx->Const.MaxTextureMaxAnisotropy = MAX_TEXTURE_MAX_ANISOTROPY;
- ctx->Const.MaxTextureLodBias = MAX_TEXTURE_LOD_BIAS;
- ctx->Const.MaxTextureBufferSize = 65536;
- ctx->Const.TextureBufferOffsetAlignment = 1;
- ctx->Const.MaxArrayLockSize = MAX_ARRAY_LOCK_SIZE;
- ctx->Const.SubPixelBits = SUB_PIXEL_BITS;
- ctx->Const.MinPointSize = MIN_POINT_SIZE;
- ctx->Const.MaxPointSize = MAX_POINT_SIZE;
- ctx->Const.MinPointSizeAA = MIN_POINT_SIZE;
- ctx->Const.MaxPointSizeAA = MAX_POINT_SIZE;
- ctx->Const.PointSizeGranularity = (GLfloat) POINT_SIZE_GRANULARITY;
- ctx->Const.MinLineWidth = MIN_LINE_WIDTH;
- ctx->Const.MaxLineWidth = MAX_LINE_WIDTH;
- ctx->Const.MinLineWidthAA = MIN_LINE_WIDTH;
- ctx->Const.MaxLineWidthAA = MAX_LINE_WIDTH;
- ctx->Const.LineWidthGranularity = (GLfloat) LINE_WIDTH_GRANULARITY;
- ctx->Const.MaxClipPlanes = 6;
- ctx->Const.MaxLights = MAX_LIGHTS;
- ctx->Const.MaxShininess = 128.0;
- ctx->Const.MaxSpotExponent = 128.0;
- ctx->Const.MaxViewportWidth = MAX_VIEWPORT_WIDTH;
- ctx->Const.MaxViewportHeight = MAX_VIEWPORT_HEIGHT;
- ctx->Const.MinMapBufferAlignment = 64;
+ consts->MaxTextureMbytes = MAX_TEXTURE_MBYTES;
+ consts->MaxTextureLevels = MAX_TEXTURE_LEVELS;
+ consts->Max3DTextureLevels = MAX_3D_TEXTURE_LEVELS;
+ consts->MaxCubeTextureLevels = MAX_CUBE_TEXTURE_LEVELS;
+ consts->MaxTextureRectSize = MAX_TEXTURE_RECT_SIZE;
+ consts->MaxArrayTextureLayers = MAX_ARRAY_TEXTURE_LAYERS;
+ consts->MaxTextureCoordUnits = MAX_TEXTURE_COORD_UNITS;
+ consts->Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
+ consts->MaxTextureUnits = MIN2(consts->MaxTextureCoordUnits,
+ consts->Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits);
+ consts->MaxTextureMaxAnisotropy = MAX_TEXTURE_MAX_ANISOTROPY;
+ consts->MaxTextureLodBias = MAX_TEXTURE_LOD_BIAS;
+ consts->MaxTextureBufferSize = 65536;
+ consts->TextureBufferOffsetAlignment = 1;
+ consts->MaxArrayLockSize = MAX_ARRAY_LOCK_SIZE;
+ consts->SubPixelBits = SUB_PIXEL_BITS;
+ consts->MinPointSize = MIN_POINT_SIZE;
+ consts->MaxPointSize = MAX_POINT_SIZE;
+ consts->MinPointSizeAA = MIN_POINT_SIZE;
+ consts->MaxPointSizeAA = MAX_POINT_SIZE;
+ consts->PointSizeGranularity = (GLfloat) POINT_SIZE_GRANULARITY;
+ consts->MinLineWidth = MIN_LINE_WIDTH;
+ consts->MaxLineWidth = MAX_LINE_WIDTH;
+ consts->MinLineWidthAA = MIN_LINE_WIDTH;
+ consts->MaxLineWidthAA = MAX_LINE_WIDTH;
+ consts->LineWidthGranularity = (GLfloat) LINE_WIDTH_GRANULARITY;
+ consts->MaxClipPlanes = 6;
+ consts->MaxLights = MAX_LIGHTS;
+ consts->MaxShininess = 128.0;
+ consts->MaxSpotExponent = 128.0;
+ consts->MaxViewportWidth = MAX_VIEWPORT_WIDTH;
+ consts->MaxViewportHeight = MAX_VIEWPORT_HEIGHT;
+ consts->MinMapBufferAlignment = 64;
/* 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;
+ consts->MaxViewports = 1;
+ consts->ViewportSubpixelBits = 0;
+ consts->ViewportBounds.Min = 0;
+ consts->ViewportBounds.Max = 0;
/** GL_ARB_uniform_buffer_object */
- ctx->Const.MaxCombinedUniformBlocks = 36;
- ctx->Const.MaxUniformBufferBindings = 36;
- ctx->Const.MaxUniformBlockSize = 16384;
- ctx->Const.UniformBufferOffsetAlignment = 1;
+ consts->MaxCombinedUniformBlocks = 36;
+ consts->MaxUniformBufferBindings = 36;
+ consts->MaxUniformBlockSize = 16384;
+ consts->UniformBufferOffsetAlignment = 1;
/* GL_ARB_explicit_uniform_location, GL_MAX_UNIFORM_LOCATIONS */
- ctx->Const.MaxUserAssignableUniformLocations =
+ consts->MaxUserAssignableUniformLocations =
4 * MESA_SHADER_STAGES * MAX_UNIFORMS;
for (i = 0; i < MESA_SHADER_STAGES; i++)
- init_program_limits(ctx, i, &ctx->Const.Program[i]);
+ init_program_limits(consts, i, &consts->Program[i]);
- ctx->Const.MaxProgramMatrices = MAX_PROGRAM_MATRICES;
- ctx->Const.MaxProgramMatrixStackDepth = MAX_PROGRAM_MATRIX_STACK_DEPTH;
+ consts->MaxProgramMatrices = MAX_PROGRAM_MATRICES;
+ consts->MaxProgramMatrixStackDepth = MAX_PROGRAM_MATRIX_STACK_DEPTH;
/* CheckArrayBounds is overriden by drivers/x11 for X server */
- ctx->Const.CheckArrayBounds = GL_FALSE;
+ consts->CheckArrayBounds = GL_FALSE;
/* GL_ARB_draw_buffers */
- ctx->Const.MaxDrawBuffers = MAX_DRAW_BUFFERS;
+ consts->MaxDrawBuffers = MAX_DRAW_BUFFERS;
- ctx->Const.MaxColorAttachments = MAX_COLOR_ATTACHMENTS;
- ctx->Const.MaxRenderbufferSize = MAX_RENDERBUFFER_SIZE;
+ consts->MaxColorAttachments = MAX_COLOR_ATTACHMENTS;
+ consts->MaxRenderbufferSize = MAX_RENDERBUFFER_SIZE;
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
- ctx->Const.MaxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS;
- ctx->Const.MaxVarying = 16; /* old limit not to break tnl and swrast */
- ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
- ctx->Const.MaxGeometryOutputVertices = MAX_GEOMETRY_OUTPUT_VERTICES;
- ctx->Const.MaxGeometryTotalOutputComponents = MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS;
+ consts->Program[MESA_SHADER_VERTEX].MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
+ consts->MaxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS;
+ consts->MaxVarying = 16; /* old limit not to break tnl and swrast */
+ consts->Program[MESA_SHADER_GEOMETRY].MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
+ consts->MaxGeometryOutputVertices = MAX_GEOMETRY_OUTPUT_VERTICES;
+ consts->MaxGeometryTotalOutputComponents = MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS;
/* Shading language version */
- if (_mesa_is_desktop_gl(ctx)) {
- ctx->Const.GLSLVersion = 120;
- _mesa_override_glsl_version(ctx);
+ if (api == API_OPENGL_COMPAT || api == API_OPENGL_CORE) {
+ consts->GLSLVersion = 120;
+ _mesa_override_glsl_version(consts);
}
- else if (ctx->API == API_OPENGLES2) {
- ctx->Const.GLSLVersion = 100;
+ else if (api == API_OPENGLES2) {
+ consts->GLSLVersion = 100;
}
- else if (ctx->API == API_OPENGLES) {
- ctx->Const.GLSLVersion = 0; /* GLSL not supported */
+ else if (api == API_OPENGLES) {
+ consts->GLSLVersion = 0; /* GLSL not supported */
}
/* GL_ARB_framebuffer_object */
- ctx->Const.MaxSamples = 0;
+ consts->MaxSamples = 0;
/* GL_ARB_sync */
- ctx->Const.MaxServerWaitTimeout = 0x1fff7fffffffULL;
+ consts->MaxServerWaitTimeout = 0x1fff7fffffffULL;
/* GL_EXT_provoking_vertex */
- ctx->Const.QuadsFollowProvokingVertexConvention = GL_TRUE;
+ consts->QuadsFollowProvokingVertexConvention = GL_TRUE;
/* GL_EXT_transform_feedback */
- ctx->Const.MaxTransformFeedbackBuffers = MAX_FEEDBACK_BUFFERS;
- ctx->Const.MaxTransformFeedbackSeparateComponents = 4 * MAX_FEEDBACK_ATTRIBS;
- ctx->Const.MaxTransformFeedbackInterleavedComponents = 4 * MAX_FEEDBACK_ATTRIBS;
- ctx->Const.MaxVertexStreams = 1;
+ consts->MaxTransformFeedbackBuffers = MAX_FEEDBACK_BUFFERS;
+ consts->MaxTransformFeedbackSeparateComponents = 4 * MAX_FEEDBACK_ATTRIBS;
+ consts->MaxTransformFeedbackInterleavedComponents = 4 * MAX_FEEDBACK_ATTRIBS;
+ consts->MaxVertexStreams = 1;
/* GL 3.2 */
- ctx->Const.ProfileMask = ctx->API == API_OPENGL_CORE
+ consts->ProfileMask = api == API_OPENGL_CORE
? GL_CONTEXT_CORE_PROFILE_BIT
: GL_CONTEXT_COMPATIBILITY_PROFILE_BIT;
/** GL_EXT_gpu_shader4 */
- ctx->Const.MinProgramTexelOffset = -8;
- ctx->Const.MaxProgramTexelOffset = 7;
+ consts->MinProgramTexelOffset = -8;
+ consts->MaxProgramTexelOffset = 7;
/* GL_ARB_texture_gather */
- ctx->Const.MinProgramTextureGatherOffset = -8;
- ctx->Const.MaxProgramTextureGatherOffset = 7;
+ consts->MinProgramTextureGatherOffset = -8;
+ consts->MaxProgramTextureGatherOffset = 7;
/* GL_ARB_robustness */
- ctx->Const.ResetStrategy = GL_NO_RESET_NOTIFICATION_ARB;
+ consts->ResetStrategy = GL_NO_RESET_NOTIFICATION_ARB;
/* PrimitiveRestart */
- ctx->Const.PrimitiveRestartInSoftware = GL_FALSE;
+ consts->PrimitiveRestartInSoftware = GL_FALSE;
/* ES 3.0 or ARB_ES3_compatibility */
- ctx->Const.MaxElementIndex = 0xffffffffu;
+ consts->MaxElementIndex = 0xffffffffu;
/* GL_ARB_texture_multisample */
- ctx->Const.MaxColorTextureSamples = 1;
- ctx->Const.MaxDepthTextureSamples = 1;
- ctx->Const.MaxIntegerSamples = 1;
+ consts->MaxColorTextureSamples = 1;
+ consts->MaxDepthTextureSamples = 1;
+ consts->MaxIntegerSamples = 1;
/* GL_ARB_shader_atomic_counters */
- ctx->Const.MaxAtomicBufferBindings = MAX_COMBINED_ATOMIC_BUFFERS;
- ctx->Const.MaxAtomicBufferSize = MAX_ATOMIC_COUNTERS * ATOMIC_COUNTER_SIZE;
- ctx->Const.MaxCombinedAtomicBuffers = MAX_COMBINED_ATOMIC_BUFFERS;
- ctx->Const.MaxCombinedAtomicCounters = MAX_ATOMIC_COUNTERS;
+ consts->MaxAtomicBufferBindings = MAX_COMBINED_ATOMIC_BUFFERS;
+ consts->MaxAtomicBufferSize = MAX_ATOMIC_COUNTERS * ATOMIC_COUNTER_SIZE;
+ consts->MaxCombinedAtomicBuffers = MAX_COMBINED_ATOMIC_BUFFERS;
+ consts->MaxCombinedAtomicCounters = MAX_ATOMIC_COUNTERS;
/* GL_ARB_vertex_attrib_binding */
- ctx->Const.MaxVertexAttribRelativeOffset = 2047;
- ctx->Const.MaxVertexAttribBindings = MAX_VERTEX_GENERIC_ATTRIBS;
+ consts->MaxVertexAttribRelativeOffset = 2047;
+ consts->MaxVertexAttribBindings = MAX_VERTEX_GENERIC_ATTRIBS;
/* GL_ARB_compute_shader */
- ctx->Const.MaxComputeWorkGroupCount[0] = 65535;
- ctx->Const.MaxComputeWorkGroupCount[1] = 65535;
- ctx->Const.MaxComputeWorkGroupCount[2] = 65535;
- ctx->Const.MaxComputeWorkGroupSize[0] = 1024;
- ctx->Const.MaxComputeWorkGroupSize[1] = 1024;
- ctx->Const.MaxComputeWorkGroupSize[2] = 64;
- ctx->Const.MaxComputeWorkGroupInvocations = 1024;
+ consts->MaxComputeWorkGroupCount[0] = 65535;
+ consts->MaxComputeWorkGroupCount[1] = 65535;
+ consts->MaxComputeWorkGroupCount[2] = 65535;
+ consts->MaxComputeWorkGroupSize[0] = 1024;
+ consts->MaxComputeWorkGroupSize[1] = 1024;
+ consts->MaxComputeWorkGroupSize[2] = 64;
+ consts->MaxComputeWorkGroupInvocations = 1024;
/** GL_ARB_gpu_shader5 */
- ctx->Const.MinFragmentInterpolationOffset = MIN_FRAGMENT_INTERPOLATION_OFFSET;
- ctx->Const.MaxFragmentInterpolationOffset = MAX_FRAGMENT_INTERPOLATION_OFFSET;
+ consts->MinFragmentInterpolationOffset = MIN_FRAGMENT_INTERPOLATION_OFFSET;
+ consts->MaxFragmentInterpolationOffset = MAX_FRAGMENT_INTERPOLATION_OFFSET;
}
@@ -790,10 +790,10 @@ init_attrib_groups(struct gl_context *ctx)
assert(ctx);
/* Constants */
- _mesa_init_constants( ctx );
+ _mesa_init_constants(&ctx->Const, ctx->API);
/* Extensions */
- _mesa_init_extensions( ctx );
+ _mesa_init_extensions(&ctx->Extensions);
/* Attribute Groups */
_mesa_init_accum( ctx );
diff --git a/mesalib/src/mesa/main/context.h b/mesalib/src/mesa/main/context.h
index 792ab4cd5..d902ea76e 100644
--- a/mesalib/src/mesa/main/context.h
+++ b/mesalib/src/mesa/main/context.h
@@ -144,6 +144,9 @@ _mesa_get_current_context(void);
/*@}*/
extern void
+_mesa_init_constants(struct gl_constants *consts, gl_api api);
+
+extern void
_mesa_init_get_hash(struct gl_context *ctx);
extern void
diff --git a/mesalib/src/mesa/main/copyimage.c b/mesalib/src/mesa/main/copyimage.c
index dcbc83de6..df7d7c272 100644
--- a/mesalib/src/mesa/main/copyimage.c
+++ b/mesalib/src/mesa/main/copyimage.c
@@ -277,6 +277,12 @@ _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel,
dstX, dstY, dstZ,
srcWidth, srcHeight, srcWidth);
+ if (!ctx->Extensions.ARB_copy_image) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyImageSubData(extension not available)");
+ return;
+ }
+
if (!prepare_target(ctx, srcName, &srcTarget, srcLevel,
&srcTexObj, &srcTexImage, &tmpTexNames[0], "src"))
goto cleanup;
@@ -328,7 +334,7 @@ _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel,
srcTexImage->InternalFormat,
dstTexImage->InternalFormat)) {
} else {
- return; /* Error loged by _mesa_texture_view_compatible_format */
+ return; /* Error logged by _mesa_texture_view_compatible_format */
}
for (i = 0; i < srcDepth; ++i) {
diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c
index d60838a1c..553c01e34 100644
--- a/mesalib/src/mesa/main/extensions.c
+++ b/mesalib/src/mesa/main/extensions.c
@@ -94,6 +94,7 @@ static const struct extension extension_table[] = {
{ "GL_ARB_color_buffer_float", o(ARB_color_buffer_float), GL, 2004 },
{ "GL_ARB_compressed_texture_pixel_storage", o(dummy_true), GL, 2011 },
{ "GL_ARB_compute_shader", o(ARB_compute_shader), GL, 2012 },
+ { "GL_ARB_conditional_render_inverted", o(ARB_conditional_render_inverted), GL, 2014 },
{ "GL_ARB_copy_buffer", o(dummy_true), GL, 2008 },
{ "GL_ARB_copy_image", o(ARB_copy_image), GL, 2012 },
{ "GL_ARB_conservative_depth", o(ARB_conservative_depth), GL, 2011 },
@@ -101,6 +102,7 @@ static const struct extension extension_table[] = {
{ "GL_ARB_depth_buffer_float", o(ARB_depth_buffer_float), GL, 2008 },
{ "GL_ARB_depth_clamp", o(ARB_depth_clamp), GL, 2003 },
{ "GL_ARB_depth_texture", o(ARB_depth_texture), GLL, 2001 },
+ { "GL_ARB_derivative_control", o(ARB_derivative_control), GL, 2014 },
{ "GL_ARB_draw_buffers", o(dummy_true), GL, 2002 },
{ "GL_ARB_draw_buffers_blend", o(ARB_draw_buffers_blend), GL, 2009 },
{ "GL_ARB_draw_elements_base_vertex", o(ARB_draw_elements_base_vertex), GL, 2009 },
@@ -116,7 +118,7 @@ static const struct extension extension_table[] = {
{ "GL_ARB_framebuffer_object", o(ARB_framebuffer_object), GL, 2005 },
{ "GL_ARB_framebuffer_sRGB", o(EXT_framebuffer_sRGB), GL, 1998 },
{ "GL_ARB_get_program_binary", o(dummy_true), GL, 2010 },
- { "GL_ARB_gpu_shader5", o(ARB_gpu_shader5), GL, 2010 },
+ { "GL_ARB_gpu_shader5", o(ARB_gpu_shader5), GLC, 2010 },
{ "GL_ARB_half_float_pixel", o(dummy_true), GL, 2003 },
{ "GL_ARB_half_float_vertex", o(ARB_half_float_vertex), GL, 2008 },
{ "GL_ARB_instanced_arrays", o(ARB_instanced_arrays), GL, 2008 },
@@ -152,11 +154,13 @@ static const struct extension extension_table[] = {
{ "GL_ARB_shadow", o(ARB_shadow), GLL, 2001 },
{ "GL_ARB_stencil_texturing", o(ARB_stencil_texturing), GL, 2012 },
{ "GL_ARB_sync", o(ARB_sync), GL, 2003 },
+ { "GL_ARB_texture_barrier", o(NV_texture_barrier), GL, 2014 },
{ "GL_ARB_texture_border_clamp", o(ARB_texture_border_clamp), GLL, 2000 },
{ "GL_ARB_texture_buffer_object", o(ARB_texture_buffer_object), GLC, 2008 },
{ "GL_ARB_texture_buffer_object_rgb32", o(ARB_texture_buffer_object_rgb32), GLC, 2009 },
{ "GL_ARB_texture_buffer_range", o(ARB_texture_buffer_range), GLC, 2012 },
{ "GL_ARB_texture_compression", o(dummy_true), GLL, 2000 },
+ { "GL_ARB_texture_compression_bptc", o(ARB_texture_compression_bptc), GL, 2010 },
{ "GL_ARB_texture_compression_rgtc", o(ARB_texture_compression_rgtc), GL, 2004 },
{ "GL_ARB_texture_cube_map", o(ARB_texture_cube_map), GLL, 1999 },
{ "GL_ARB_texture_cube_map_array", o(ARB_texture_cube_map_array), GL, 2009 },
@@ -449,6 +453,7 @@ _mesa_enable_sw_extensions(struct gl_context *ctx)
ctx->Extensions.ARB_point_sprite = GL_TRUE;
ctx->Extensions.ARB_shadow = GL_TRUE;
ctx->Extensions.ARB_texture_border_clamp = GL_TRUE;
+ ctx->Extensions.ARB_texture_compression_bptc = GL_TRUE;
ctx->Extensions.ARB_texture_cube_map = GL_TRUE;
ctx->Extensions.ARB_texture_env_combine = GL_TRUE;
ctx->Extensions.ARB_texture_env_crossbar = GL_TRUE;
@@ -667,9 +672,9 @@ _mesa_one_time_init_extension_overrides(void)
* Note: Sets gl_extensions.dummy_true to true.
*/
void
-_mesa_init_extensions( struct gl_context *ctx )
+_mesa_init_extensions(struct gl_extensions *extensions)
{
- GLboolean *base = (GLboolean *) &ctx->Extensions;
+ GLboolean *base = (GLboolean *) extensions;
GLboolean *sentinel = base + o(extension_sentinel);
GLboolean *i;
@@ -678,8 +683,8 @@ _mesa_init_extensions( struct gl_context *ctx )
*i = GL_FALSE;
/* Then, selectively turn default extensions on. */
- ctx->Extensions.dummy_true = GL_TRUE;
- ctx->Extensions.EXT_texture3D = GL_TRUE;
+ extensions->dummy_true = GL_TRUE;
+ extensions->EXT_texture3D = GL_TRUE;
}
diff --git a/mesalib/src/mesa/main/extensions.h b/mesalib/src/mesa/main/extensions.h
index 3a404d2e0..595512a5d 100644
--- a/mesalib/src/mesa/main/extensions.h
+++ b/mesalib/src/mesa/main/extensions.h
@@ -45,7 +45,7 @@ extern void _mesa_enable_sw_extensions(struct gl_context *ctx);
extern void _mesa_one_time_init_extension_overrides(void);
-extern void _mesa_init_extensions(struct gl_context *ctx);
+extern void _mesa_init_extensions(struct gl_extensions *extentions);
extern GLubyte *_mesa_make_extension_string(struct gl_context *ctx);
diff --git a/mesalib/src/mesa/main/ff_fragment_shader.cpp b/mesalib/src/mesa/main/ff_fragment_shader.cpp
index 8758b5e9d..9bb706cc5 100644
--- a/mesalib/src/mesa/main/ff_fragment_shader.cpp
+++ b/mesalib/src/mesa/main/ff_fragment_shader.cpp
@@ -1252,7 +1252,7 @@ create_new_program(struct gl_context *ctx, struct state_key *key)
validate_ir_tree(p.shader->ir);
const struct gl_shader_compiler_options *options =
- &ctx->ShaderCompilerOptions[MESA_SHADER_FRAGMENT];
+ &ctx->Const.ShaderCompilerOptions[MESA_SHADER_FRAGMENT];
while (do_common_optimization(p.shader->ir, false, false, options,
ctx->Const.NativeIntegers))
diff --git a/mesalib/src/mesa/main/ffvertex_prog.c b/mesalib/src/mesa/main/ffvertex_prog.c
index 728cf968b..d5afc3d81 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].OptimizeForAOS,
+ ctx->Const.ShaderCompilerOptions[MESA_SHADER_VERTEX].OptimizeForAOS,
ctx->Const.Program[MESA_SHADER_VERTEX].MaxTemps );
#if 0
diff --git a/mesalib/src/mesa/main/format_info.py b/mesalib/src/mesa/main/format_info.py
index 448bd0055..7424fe0cd 100644
--- a/mesalib/src/mesa/main/format_info.py
+++ b/mesalib/src/mesa/main/format_info.py
@@ -62,7 +62,9 @@ def get_gl_base_format(fmat):
def get_gl_data_type(fmat):
if fmat.is_compressed():
- if 'SIGNED' in fmat.name or 'SNORM' in fmat.name:
+ if 'FLOAT' in fmat.name:
+ return 'GL_FLOAT'
+ elif 'SIGNED' in fmat.name or 'SNORM' in fmat.name:
return 'GL_SIGNED_NORMALIZED'
else:
return 'GL_UNSIGNED_NORMALIZED'
@@ -125,6 +127,9 @@ def get_channel_bits(fmat, chan_name):
bits = 11 if fmat.name.endswith('11_EAC') else 8
return bits if fmat.has_channel(chan_name) else 0
+ elif fmat.layout == 'bptc':
+ bits = 16 if fmat.name.endswith('_FLOAT') else 8
+ return bits if fmat.has_channel(chan_name) else 0
else:
assert False
else:
diff --git a/mesalib/src/mesa/main/formats.c b/mesalib/src/mesa/main/formats.c
index f03425e41..db22a45c4 100644
--- a/mesalib/src/mesa/main/formats.c
+++ b/mesalib/src/mesa/main/formats.c
@@ -369,6 +369,7 @@ _mesa_get_format_color_encoding(mesa_format format)
case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC:
case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
case MESA_FORMAT_B8G8R8X8_SRGB:
+ case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
return GL_SRGB;
default:
return GL_LINEAR;
@@ -377,6 +378,31 @@ _mesa_get_format_color_encoding(mesa_format format)
/**
+ * Return TRUE if format is an ETC2 compressed format specified
+ * by GL_ARB_ES3_compatibility.
+ */
+bool
+_mesa_is_format_etc2(mesa_format format)
+{
+ switch (format) {
+ case MESA_FORMAT_ETC2_RGB8:
+ case MESA_FORMAT_ETC2_SRGB8:
+ case MESA_FORMAT_ETC2_RGBA8_EAC:
+ case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC:
+ case MESA_FORMAT_ETC2_R11_EAC:
+ case MESA_FORMAT_ETC2_RG11_EAC:
+ case MESA_FORMAT_ETC2_SIGNED_R11_EAC:
+ case MESA_FORMAT_ETC2_SIGNED_RG11_EAC:
+ case MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1:
+ case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
* For an sRGB format, return the corresponding linear color space format.
* For non-sRGB formats, return the format as-is.
*/
@@ -426,6 +452,9 @@ _mesa_get_srgb_format_linear(mesa_format format)
case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
format = MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1;
break;
+ case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
+ format = MESA_FORMAT_BPTC_RGBA_UNORM;
+ break;
case MESA_FORMAT_B8G8R8X8_SRGB:
format = MESA_FORMAT_B8G8R8X8_UNORM;
break;
@@ -491,6 +520,12 @@ _mesa_get_uncompressed_format(mesa_format format)
case MESA_FORMAT_ETC2_RG11_EAC:
case MESA_FORMAT_ETC2_SIGNED_RG11_EAC:
return MESA_FORMAT_R16G16_UNORM;
+ case MESA_FORMAT_BPTC_RGBA_UNORM:
+ case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
+ return MESA_FORMAT_A8B8G8R8_UNORM;
+ case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT:
+ case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT:
+ return MESA_FORMAT_RGB_FLOAT32;
default:
#ifdef DEBUG
assert(!_mesa_is_format_compressed(format));
@@ -968,6 +1003,10 @@ _mesa_format_to_type_and_comps(mesa_format format,
case MESA_FORMAT_ETC2_SIGNED_RG11_EAC:
case MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1:
case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
+ case MESA_FORMAT_BPTC_RGBA_UNORM:
+ case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
+ case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT:
+ case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT:
/* XXX generate error instead? */
*datatype = GL_UNSIGNED_BYTE;
*comps = 0;
@@ -1524,6 +1563,12 @@ _mesa_format_matches_format_and_type(mesa_format mesa_format,
case MESA_FORMAT_RGBA_DXT5:
return GL_FALSE;
+ case MESA_FORMAT_BPTC_RGBA_UNORM:
+ case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
+ case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT:
+ case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT:
+ return GL_FALSE;
+
case MESA_FORMAT_RGBA_FLOAT32:
return format == GL_RGBA && type == GL_FLOAT && !swapBytes;
case MESA_FORMAT_RGBA_FLOAT16:
diff --git a/mesalib/src/mesa/main/formats.csv b/mesalib/src/mesa/main/formats.csv
index eade6facd..4d542b7c6 100644
--- a/mesalib/src/mesa/main/formats.csv
+++ b/mesalib/src/mesa/main/formats.csv
@@ -280,3 +280,9 @@ MESA_FORMAT_ETC2_SIGNED_R11_EAC , etc2 , 4, 4, x64 , , ,
MESA_FORMAT_ETC2_SIGNED_RG11_EAC , etc2 , 4, 4, x128, , , , xy01, rgb
MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1 , etc2 , 4, 4, x64 , , , , xyzw, rgb
MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1, etc2 , 4, 4, x64 , , , , xyzw, srgb
+
+# BPTC compressed formats
+MESA_FORMAT_BPTC_RGBA_UNORM , bptc , 4, 4, x128, , , , xyzw, rgb
+MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM , bptc , 4, 4, x128, , , , xyzw, srgb
+MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT , bptc , 4, 4, x128, , , , xyz1, rgb
+MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT , bptc , 4, 4, x128, , , , xyz1, rgb
diff --git a/mesalib/src/mesa/main/formats.h b/mesalib/src/mesa/main/formats.h
index 457c8abf8..d6253bf86 100644
--- a/mesalib/src/mesa/main/formats.h
+++ b/mesalib/src/mesa/main/formats.h
@@ -427,6 +427,12 @@ typedef enum
MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1,
MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1,
+ /* BPTC compressed formats */
+ MESA_FORMAT_BPTC_RGBA_UNORM,
+ MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM,
+ MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT,
+ MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT,
+
MESA_FORMAT_COUNT
} mesa_format;
@@ -476,6 +482,9 @@ _mesa_is_format_signed(mesa_format format);
extern GLboolean
_mesa_is_format_integer(mesa_format format);
+extern bool
+_mesa_is_format_etc2(mesa_format format);
+
extern GLenum
_mesa_get_format_color_encoding(mesa_format format);
diff --git a/mesalib/src/mesa/main/glformats.c b/mesalib/src/mesa/main/glformats.c
index 0fb25ba0f..00478f989 100644
--- a/mesalib/src/mesa/main/glformats.c
+++ b/mesalib/src/mesa/main/glformats.c
@@ -787,6 +787,10 @@ _mesa_is_color_format(GLenum format)
case GL_COMPRESSED_SIGNED_RG11_EAC:
case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ case GL_COMPRESSED_RGBA_BPTC_UNORM:
+ case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
+ case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
+ case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
/* generic integer formats */
case GL_RED_INTEGER_EXT:
case GL_GREEN_INTEGER_EXT:
@@ -1040,6 +1044,12 @@ _mesa_is_compressed_format(struct gl_context *ctx, GLenum format)
case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
return _mesa_is_gles3(ctx) || ctx->Extensions.ARB_ES3_compatibility;
+ case GL_COMPRESSED_RGBA_BPTC_UNORM:
+ case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
+ case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
+ case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
+ return _mesa_is_desktop_gl(ctx) &&
+ ctx->Extensions.ARB_texture_compression_bptc;
case GL_PALETTE4_RGB8_OES:
case GL_PALETTE4_RGBA8_OES:
case GL_PALETTE4_R5_G6_B5_OES:
diff --git a/mesalib/src/mesa/main/mipmap.c b/mesalib/src/mesa/main/mipmap.c
index cc109cc52..fdaa68282 100644
--- a/mesalib/src/mesa/main/mipmap.c
+++ b/mesalib/src/mesa/main/mipmap.c
@@ -2038,12 +2038,15 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
components = _mesa_format_num_components(temp_format);
- /* Revisit this if we get compressed formats with >8 bits per component */
- if (_mesa_get_format_datatype(srcImage->TexFormat)
- == GL_SIGNED_NORMALIZED) {
+ switch (_mesa_get_format_datatype(srcImage->TexFormat)) {
+ case GL_FLOAT:
+ temp_datatype = GL_FLOAT;
+ break;
+ case GL_SIGNED_NORMALIZED:
+ /* Revisit this if we get compressed formats with >8 bits per component */
temp_datatype = GL_BYTE;
- }
- else {
+ break;
+ default:
temp_datatype = GL_UNSIGNED_BYTE;
}
diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h
index e141ac658..cb2a4df4f 100644
--- a/mesalib/src/mesa/main/mtypes.h
+++ b/mesalib/src/mesa/main/mtypes.h
@@ -3529,6 +3529,8 @@ struct gl_constants
GLfloat MaxFragmentInterpolationOffset;
GLboolean FakeSWMSAA;
+
+ struct gl_shader_compiler_options ShaderCompilerOptions[MESA_SHADER_STAGES];
};
@@ -3551,11 +3553,13 @@ struct gl_extensions
GLboolean ARB_clear_texture;
GLboolean ARB_color_buffer_float;
GLboolean ARB_compute_shader;
+ GLboolean ARB_conditional_render_inverted;
GLboolean ARB_conservative_depth;
GLboolean ARB_copy_image;
GLboolean ARB_depth_buffer_float;
GLboolean ARB_depth_clamp;
GLboolean ARB_depth_texture;
+ GLboolean ARB_derivative_control;
GLboolean ARB_draw_buffers_blend;
GLboolean ARB_draw_elements_base_vertex;
GLboolean ARB_draw_indirect;
@@ -3593,6 +3597,7 @@ struct gl_extensions
GLboolean ARB_texture_buffer_object;
GLboolean ARB_texture_buffer_object_rgb32;
GLboolean ARB_texture_buffer_range;
+ GLboolean ARB_texture_compression_bptc;
GLboolean ARB_texture_compression_rgtc;
GLboolean ARB_texture_cube_map;
GLboolean ARB_texture_cube_map_array;
@@ -4172,8 +4177,6 @@ struct gl_context
*/
struct gl_pipeline_object *_Shader;
- struct gl_shader_compiler_options ShaderCompilerOptions[MESA_SHADER_STAGES];
-
struct gl_query_state Query; /**< occlusion, timer queries */
struct gl_transform_feedback_state TransformFeedback;
diff --git a/mesalib/src/mesa/main/pixelstore.c b/mesalib/src/mesa/main/pixelstore.c
index 05f6583a4..fc815337b 100644
--- a/mesalib/src/mesa/main/pixelstore.c
+++ b/mesalib/src/mesa/main/pixelstore.c
@@ -284,3 +284,45 @@ _mesa_init_pixelstore( struct gl_context *ctx )
_mesa_reference_buffer_object(ctx, &ctx->DefaultPacking.BufferObj,
ctx->Shared->NullBufferObj);
}
+
+
+/**
+ * Check if the given compressed pixel storage parameters are legal.
+ * Record a GL error if illegal.
+ * \return true if legal, false if illegal
+ */
+bool
+_mesa_compressed_pixel_storage_error_check(
+ struct gl_context *ctx,
+ GLint dimensions,
+ const struct gl_pixelstore_attrib *packing,
+ const char *caller)
+{
+ if (!_mesa_is_desktop_gl(ctx) || !packing->CompressedBlockSize)
+ return true;
+
+ if (packing->CompressedBlockWidth &&
+ packing->SkipPixels % packing->CompressedBlockWidth) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(skip-pixels %% block-width)", caller);
+ return false;
+ }
+
+ if (dimensions > 1 &&
+ packing->CompressedBlockHeight &&
+ packing->SkipRows % packing->CompressedBlockHeight) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(skip-rows %% block-height)", caller);
+ return false;
+ }
+
+ if (dimensions > 2 &&
+ packing->CompressedBlockDepth &&
+ packing->SkipImages % packing->CompressedBlockDepth) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(skip-images %% block-depth)", caller);
+ return false;
+ }
+
+ return true;
+}
diff --git a/mesalib/src/mesa/main/pixelstore.h b/mesalib/src/mesa/main/pixelstore.h
index 1b5347daf..68384548a 100644
--- a/mesalib/src/mesa/main/pixelstore.h
+++ b/mesalib/src/mesa/main/pixelstore.h
@@ -49,4 +49,12 @@ extern void
_mesa_init_pixelstore( struct gl_context *ctx );
+extern bool
+_mesa_compressed_pixel_storage_error_check(
+ struct gl_context *ctx,
+ GLint dimensions,
+ const struct gl_pixelstore_attrib *packing,
+ const char *caller);
+
+
#endif
diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c
index b4a5e7050..620cab3cc 100644
--- a/mesalib/src/mesa/main/shaderapi.c
+++ b/mesalib/src/mesa/main/shaderapi.c
@@ -119,7 +119,7 @@ _mesa_init_shader_state(struct gl_context *ctx)
options.DefaultPragmas.Optimize = GL_TRUE;
for (sh = 0; sh < MESA_SHADER_STAGES; ++sh)
- memcpy(&ctx->ShaderCompilerOptions[sh], &options, sizeof(options));
+ memcpy(&ctx->Const.ShaderCompilerOptions[sh], &options, sizeof(options));
ctx->Shader.Flags = _mesa_get_shader_flags();
@@ -826,7 +826,7 @@ compile_shader(struct gl_context *ctx, GLuint shaderObj)
if (!sh)
return;
- options = &ctx->ShaderCompilerOptions[sh->Stage];
+ options = &ctx->Const.ShaderCompilerOptions[sh->Stage];
/* set default pragma state for shader */
sh->Pragmas = options->DefaultPragmas;
diff --git a/mesalib/src/mesa/main/shared.c b/mesalib/src/mesa/main/shared.c
index 0189dd296..7ef932ff0 100644
--- a/mesalib/src/mesa/main/shared.c
+++ b/mesalib/src/mesa/main/shared.c
@@ -113,7 +113,7 @@ _mesa_alloc_shared_state(struct gl_context *ctx)
assert(shared->DefaultTex[TEXTURE_1D_INDEX]->RefCount == 1);
/* Mutex and timestamp for texobj state validation */
- mtx_init(&shared->TexMutex, mtx_plain);
+ mtx_init(&shared->TexMutex, mtx_recursive);
shared->TextureStateStamp = 0;
shared->FrameBuffers = _mesa_NewHashTable();
diff --git a/mesalib/src/mesa/main/texcompress.c b/mesalib/src/mesa/main/texcompress.c
index 9dbfe9ffe..b4efeee3b 100644
--- a/mesalib/src/mesa/main/texcompress.c
+++ b/mesalib/src/mesa/main/texcompress.c
@@ -42,6 +42,7 @@
#include "texcompress_rgtc.h"
#include "texcompress_s3tc.h"
#include "texcompress_etc.h"
+#include "texcompress_bptc.h"
/**
@@ -92,6 +93,8 @@ _mesa_gl_compressed_format_base_format(GLenum format)
case GL_COMPRESSED_RGB:
case GL_COMPRESSED_SRGB:
+ case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB:
+ case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB:
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGB_FXT1_3DFX:
case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
@@ -104,8 +107,6 @@ _mesa_gl_compressed_format_base_format(GLenum format)
case GL_COMPRESSED_SRGB_ALPHA:
case GL_COMPRESSED_RGBA_BPTC_UNORM_ARB:
case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB:
- case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB:
- case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB:
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
@@ -235,6 +236,12 @@ _mesa_gl_compressed_format_base_format(GLenum format)
* GL_EXT_texture_compression_latc. At the very least, Catalyst 11.6 does not
* expose the 3dc formats through this mechanism.
*
+ * The spec for GL_ARB_texture_compression_bptc doesn't mention whether it
+ * should be included in GL_COMPRESSED_TEXTURE_FORMATS. However as it takes a
+ * very long time to compress the textures in this format it's probably not
+ * very useful as a general format where the GL will have to compress it on
+ * the fly.
+ *
* \param ctx the GL context
* \param formats the resulting format list (may be NULL).
*
@@ -434,6 +441,15 @@ _mesa_glenum_to_compressed_format(GLenum format)
case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
return MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1;
+ case GL_COMPRESSED_RGBA_BPTC_UNORM:
+ return MESA_FORMAT_BPTC_RGBA_UNORM;
+ case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
+ return MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM;
+ case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
+ return MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT;
+ case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
+ return MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT;
+
default:
return MESA_FORMAT_NONE;
}
@@ -515,6 +531,15 @@ _mesa_compressed_format_to_glenum(struct gl_context *ctx, mesa_format mesaFormat
case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
return GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2;
+ case MESA_FORMAT_BPTC_RGBA_UNORM:
+ return GL_COMPRESSED_RGBA_BPTC_UNORM;
+ case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
+ return GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM;
+ case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT:
+ return GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT;
+ case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT:
+ return GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT;
+
default:
_mesa_problem(ctx, "Unexpected mesa texture format in"
" _mesa_compressed_format_to_glenum()");
@@ -586,6 +611,11 @@ _mesa_get_compressed_fetch_func(mesa_format format)
return _mesa_get_compressed_rgtc_func(format);
case MESA_FORMAT_ETC1_RGB8:
return _mesa_get_etc_fetch_func(format);
+ case MESA_FORMAT_BPTC_RGBA_UNORM:
+ case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
+ case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT:
+ case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT:
+ return _mesa_get_bptc_fetch_func(format);
default:
return NULL;
}
diff --git a/mesalib/src/mesa/main/texcompress_bptc.c b/mesalib/src/mesa/main/texcompress_bptc.c
new file mode 100644
index 000000000..9204f123e
--- /dev/null
+++ b/mesalib/src/mesa/main/texcompress_bptc.c
@@ -0,0 +1,1649 @@
+/*
+ * Copyright (C) 2014 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file texcompress_bptc.c
+ * GL_ARB_texture_compression_bptc support.
+ */
+
+#include <stdbool.h>
+#include "texcompress.h"
+#include "texcompress_bptc.h"
+#include "util/format_srgb.h"
+#include "texstore.h"
+#include "macros.h"
+#include "image.h"
+
+#define BLOCK_SIZE 4
+#define N_PARTITIONS 64
+#define BLOCK_BYTES 16
+
+struct bptc_unorm_mode {
+ int n_subsets;
+ int n_partition_bits;
+ bool has_rotation_bits;
+ bool has_index_selection_bit;
+ int n_color_bits;
+ int n_alpha_bits;
+ bool has_endpoint_pbits;
+ bool has_shared_pbits;
+ int n_index_bits;
+ int n_secondary_index_bits;
+};
+
+struct bptc_float_bitfield {
+ int8_t endpoint;
+ uint8_t component;
+ uint8_t offset;
+ uint8_t n_bits;
+ bool reverse;
+};
+
+struct bptc_float_mode {
+ bool reserved;
+ bool transformed_endpoints;
+ int n_partition_bits;
+ int n_endpoint_bits;
+ int n_index_bits;
+ int n_delta_bits[3];
+ struct bptc_float_bitfield bitfields[24];
+};
+
+struct bit_writer {
+ uint8_t buf;
+ int pos;
+ uint8_t *dst;
+};
+
+static const struct bptc_unorm_mode
+bptc_unorm_modes[] = {
+ /* 0 */ { 3, 4, false, false, 4, 0, true, false, 3, 0 },
+ /* 1 */ { 2, 6, false, false, 6, 0, false, true, 3, 0 },
+ /* 2 */ { 3, 6, false, false, 5, 0, false, false, 2, 0 },
+ /* 3 */ { 2, 6, false, false, 7, 0, true, false, 2, 0 },
+ /* 4 */ { 1, 0, true, true, 5, 6, false, false, 2, 3 },
+ /* 5 */ { 1, 0, true, false, 7, 8, false, false, 2, 2 },
+ /* 6 */ { 1, 0, false, false, 7, 7, true, false, 4, 0 },
+ /* 7 */ { 2, 6, false, false, 5, 5, true, false, 2, 0 }
+};
+
+static const struct bptc_float_mode
+bptc_float_modes[] = {
+ /* 00 */
+ { false, true, 5, 10, 3, { 5, 5, 5 },
+ { { 2, 1, 4, 1, false }, { 2, 2, 4, 1, false }, { 3, 2, 4, 1, false },
+ { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
+ { 1, 0, 0, 5, false }, { 3, 1, 4, 1, false }, { 2, 1, 0, 4, false },
+ { 1, 1, 0, 5, false }, { 3, 2, 0, 1, false }, { 3, 1, 0, 4, false },
+ { 1, 2, 0, 5, false }, { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false },
+ { 2, 0, 0, 5, false }, { 3, 2, 2, 1, false }, { 3, 0, 0, 5, false },
+ { 3, 2, 3, 1, false },
+ { -1 } }
+ },
+ /* 01 */
+ { false, true, 5, 7, 3, { 6, 6, 6 },
+ { { 2, 1, 5, 1, false }, { 3, 1, 4, 1, false }, { 3, 1, 5, 1, false },
+ { 0, 0, 0, 7, false }, { 3, 2, 0, 1, false }, { 3, 2, 1, 1, false },
+ { 2, 2, 4, 1, false }, { 0, 1, 0, 7, false }, { 2, 2, 5, 1, false },
+ { 3, 2, 2, 1, false }, { 2, 1, 4, 1, false }, { 0, 2, 0, 7, false },
+ { 3, 2, 3, 1, false }, { 3, 2, 5, 1, false }, { 3, 2, 4, 1, false },
+ { 1, 0, 0, 6, false }, { 2, 1, 0, 4, false }, { 1, 1, 0, 6, false },
+ { 3, 1, 0, 4, false }, { 1, 2, 0, 6, false }, { 2, 2, 0, 4, false },
+ { 2, 0, 0, 6, false },
+ { 3, 0, 0, 6, false },
+ { -1 } }
+ },
+ /* 00010 */
+ { false, true, 5, 11, 3, { 5, 4, 4 },
+ { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
+ { 1, 0, 0, 5, false }, { 0, 0, 10, 1, false }, { 2, 1, 0, 4, false },
+ { 1, 1, 0, 4, false }, { 0, 1, 10, 1, false }, { 3, 2, 0, 1, false },
+ { 3, 1, 0, 4, false }, { 1, 2, 0, 4, false }, { 0, 2, 10, 1, false },
+ { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 5, false },
+ { 3, 2, 2, 1, false }, { 3, 0, 0, 5, false }, { 3, 2, 3, 1, false },
+ { -1 } }
+ },
+ /* 00011 */
+ { false, false, 0, 10, 4, { 10, 10, 10 },
+ { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
+ { 1, 0, 0, 10, false }, { 1, 1, 0, 10, false }, { 1, 2, 0, 10, false },
+ { -1 } }
+ },
+ /* 00110 */
+ { false, true, 5, 11, 3, { 4, 5, 4 },
+ { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
+ { 1, 0, 0, 4, false }, { 0, 0, 10, 1, false }, { 3, 1, 4, 1, false },
+ { 2, 1, 0, 4, false }, { 1, 1, 0, 5, false }, { 0, 1, 10, 1, false },
+ { 3, 1, 0, 4, false }, { 1, 2, 0, 4, false }, { 0, 2, 10, 1, false },
+ { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 4, false },
+ { 3, 2, 0, 1, false }, { 3, 2, 2, 1, false }, { 3, 0, 0, 4, false },
+ { 2, 1, 4, 1, false }, { 3, 2, 3, 1, false },
+ { -1 } }
+ },
+ /* 00111 */
+ { false, true, 0, 11, 4, { 9, 9, 9 },
+ { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
+ { 1, 0, 0, 9, false }, { 0, 0, 10, 1, false }, { 1, 1, 0, 9, false },
+ { 0, 1, 10, 1, false }, { 1, 2, 0, 9, false }, { 0, 2, 10, 1, false },
+ { -1 } }
+ },
+ /* 01010 */
+ { false, true, 5, 11, 3, { 4, 4, 5 },
+ { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
+ { 1, 0, 0, 4, false }, { 0, 0, 10, 1, false }, { 2, 2, 4, 1, false },
+ { 2, 1, 0, 4, false }, { 1, 1, 0, 4, false }, { 0, 1, 10, 1, false },
+ { 3, 2, 0, 1, false }, { 3, 1, 0, 4, false }, { 1, 2, 0, 5, false },
+ { 0, 2, 10, 1, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 4, false },
+ { 3, 2, 1, 1, false }, { 3, 2, 2, 1, false }, { 3, 0, 0, 4, false },
+ { 3, 2, 4, 1, false }, { 3, 2, 3, 1, false },
+ { -1 } }
+ },
+ /* 01011 */
+ { false, true, 0, 12, 4, { 8, 8, 8 },
+ { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
+ { 1, 0, 0, 8, false }, { 0, 0, 10, 2, true }, { 1, 1, 0, 8, false },
+ { 0, 1, 10, 2, true }, { 1, 2, 0, 8, false }, { 0, 2, 10, 2, true },
+ { -1 } }
+ },
+ /* 01110 */
+ { false, true, 5, 9, 3, { 5, 5, 5 },
+ { { 0, 0, 0, 9, false }, { 2, 2, 4, 1, false }, { 0, 1, 0, 9, false },
+ { 2, 1, 4, 1, false }, { 0, 2, 0, 9, false }, { 3, 2, 4, 1, false },
+ { 1, 0, 0, 5, false }, { 3, 1, 4, 1, false }, { 2, 1, 0, 4, false },
+ { 1, 1, 0, 5, false }, { 3, 2, 0, 1, false }, { 3, 1, 0, 4, false },
+ { 1, 2, 0, 5, false }, { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false },
+ { 2, 0, 0, 5, false }, { 3, 2, 2, 1, false }, { 3, 0, 0, 5, false },
+ { 3, 2, 3, 1, false },
+ { -1 } }
+ },
+ /* 01111 */
+ { false, true, 0, 16, 4, { 4, 4, 4 },
+ { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
+ { 1, 0, 0, 4, false }, { 0, 0, 10, 6, true }, { 1, 1, 0, 4, false },
+ { 0, 1, 10, 6, true }, { 1, 2, 0, 4, false }, { 0, 2, 10, 6, true },
+ { -1 } }
+ },
+ /* 10010 */
+ { false, true, 5, 8, 3, { 6, 5, 5 },
+ { { 0, 0, 0, 8, false }, { 3, 1, 4, 1, false }, { 2, 2, 4, 1, false },
+ { 0, 1, 0, 8, false }, { 3, 2, 2, 1, false }, { 2, 1, 4, 1, false },
+ { 0, 2, 0, 8, false }, { 3, 2, 3, 1, false }, { 3, 2, 4, 1, false },
+ { 1, 0, 0, 6, false }, { 2, 1, 0, 4, false }, { 1, 1, 0, 5, false },
+ { 3, 2, 0, 1, false }, { 3, 1, 0, 4, false }, { 1, 2, 0, 5, false },
+ { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 6, false },
+ { 3, 0, 0, 6, false },
+ { -1 } }
+ },
+ /* 10011 */
+ { true /* reserved */ },
+ /* 10110 */
+ { false, true, 5, 8, 3, { 5, 6, 5 },
+ { { 0, 0, 0, 8, false }, { 3, 2, 0, 1, false }, { 2, 2, 4, 1, false },
+ { 0, 1, 0, 8, false }, { 2, 1, 5, 1, false }, { 2, 1, 4, 1, false },
+ { 0, 2, 0, 8, false }, { 3, 1, 5, 1, false }, { 3, 2, 4, 1, false },
+ { 1, 0, 0, 5, false }, { 3, 1, 4, 1, false }, { 2, 1, 0, 4, false },
+ { 1, 1, 0, 6, false }, { 3, 1, 0, 4, false }, { 1, 2, 0, 5, false },
+ { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 5, false },
+ { 3, 2, 2, 1, false }, { 3, 0, 0, 5, false }, { 3, 2, 3, 1, false },
+ { -1 } }
+ },
+ /* 10111 */
+ { true /* reserved */ },
+ /* 11010 */
+ { false, true, 5, 8, 3, { 5, 5, 6 },
+ { { 0, 0, 0, 8, false }, { 3, 2, 1, 1, false }, { 2, 2, 4, 1, false },
+ { 0, 1, 0, 8, false }, { 2, 2, 5, 1, false }, { 2, 1, 4, 1, false },
+ { 0, 2, 0, 8, false }, { 3, 2, 5, 1, false }, { 3, 2, 4, 1, false },
+ { 1, 0, 0, 5, false }, { 3, 1, 4, 1, false }, { 2, 1, 0, 4, false },
+ { 1, 1, 0, 5, false }, { 3, 2, 0, 1, false }, { 3, 1, 0, 4, false },
+ { 1, 2, 0, 6, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 5, false },
+ { 3, 2, 2, 1, false }, { 3, 0, 0, 5, false }, { 3, 2, 3, 1, false },
+ { -1 } }
+ },
+ /* 11011 */
+ { true /* reserved */ },
+ /* 11110 */
+ { false, false, 5, 6, 3, { 6, 6, 6 },
+ { { 0, 0, 0, 6, false }, { 3, 1, 4, 1, false }, { 3, 2, 0, 1, false },
+ { 3, 2, 1, 1, false }, { 2, 2, 4, 1, false }, { 0, 1, 0, 6, false },
+ { 2, 1, 5, 1, false }, { 2, 2, 5, 1, false }, { 3, 2, 2, 1, false },
+ { 2, 1, 4, 1, false }, { 0, 2, 0, 6, false }, { 3, 1, 5, 1, false },
+ { 3, 2, 3, 1, false }, { 3, 2, 5, 1, false }, { 3, 2, 4, 1, false },
+ { 1, 0, 0, 6, false }, { 2, 1, 0, 4, false }, { 1, 1, 0, 6, false },
+ { 3, 1, 0, 4, false }, { 1, 2, 0, 6, false }, { 2, 2, 0, 4, false },
+ { 2, 0, 0, 6, false }, { 3, 0, 0, 6, false },
+ { -1 } }
+ },
+ /* 11111 */
+ { true /* reserved */ },
+};
+
+/* This partition table is used when the mode has two subsets. Each
+ * partition is represented by a 32-bit value which gives 2 bits per texel
+ * within the block. The value of the two bits represents which subset to use
+ * (0 or 1).
+ */
+static const uint32_t
+partition_table1[N_PARTITIONS] = {
+ 0x50505050U, 0x40404040U, 0x54545454U, 0x54505040U,
+ 0x50404000U, 0x55545450U, 0x55545040U, 0x54504000U,
+ 0x50400000U, 0x55555450U, 0x55544000U, 0x54400000U,
+ 0x55555440U, 0x55550000U, 0x55555500U, 0x55000000U,
+ 0x55150100U, 0x00004054U, 0x15010000U, 0x00405054U,
+ 0x00004050U, 0x15050100U, 0x05010000U, 0x40505054U,
+ 0x00404050U, 0x05010100U, 0x14141414U, 0x05141450U,
+ 0x01155440U, 0x00555500U, 0x15014054U, 0x05414150U,
+ 0x44444444U, 0x55005500U, 0x11441144U, 0x05055050U,
+ 0x05500550U, 0x11114444U, 0x41144114U, 0x44111144U,
+ 0x15055054U, 0x01055040U, 0x05041050U, 0x05455150U,
+ 0x14414114U, 0x50050550U, 0x41411414U, 0x00141400U,
+ 0x00041504U, 0x00105410U, 0x10541000U, 0x04150400U,
+ 0x50410514U, 0x41051450U, 0x05415014U, 0x14054150U,
+ 0x41050514U, 0x41505014U, 0x40011554U, 0x54150140U,
+ 0x50505500U, 0x00555050U, 0x15151010U, 0x54540404U,
+};
+
+/* This partition table is used when the mode has three subsets. In this case
+ * the values can be 0, 1 or 2.
+ */
+static const uint32_t
+partition_table2[N_PARTITIONS] = {
+ 0xaa685050U, 0x6a5a5040U, 0x5a5a4200U, 0x5450a0a8U,
+ 0xa5a50000U, 0xa0a05050U, 0x5555a0a0U, 0x5a5a5050U,
+ 0xaa550000U, 0xaa555500U, 0xaaaa5500U, 0x90909090U,
+ 0x94949494U, 0xa4a4a4a4U, 0xa9a59450U, 0x2a0a4250U,
+ 0xa5945040U, 0x0a425054U, 0xa5a5a500U, 0x55a0a0a0U,
+ 0xa8a85454U, 0x6a6a4040U, 0xa4a45000U, 0x1a1a0500U,
+ 0x0050a4a4U, 0xaaa59090U, 0x14696914U, 0x69691400U,
+ 0xa08585a0U, 0xaa821414U, 0x50a4a450U, 0x6a5a0200U,
+ 0xa9a58000U, 0x5090a0a8U, 0xa8a09050U, 0x24242424U,
+ 0x00aa5500U, 0x24924924U, 0x24499224U, 0x50a50a50U,
+ 0x500aa550U, 0xaaaa4444U, 0x66660000U, 0xa5a0a5a0U,
+ 0x50a050a0U, 0x69286928U, 0x44aaaa44U, 0x66666600U,
+ 0xaa444444U, 0x54a854a8U, 0x95809580U, 0x96969600U,
+ 0xa85454a8U, 0x80959580U, 0xaa141414U, 0x96960000U,
+ 0xaaaa1414U, 0xa05050a0U, 0xa0a5a5a0U, 0x96000000U,
+ 0x40804080U, 0xa9a8a9a8U, 0xaaaaaa44U, 0x2a4a5254U
+};
+
+static const uint8_t
+anchor_indices[][N_PARTITIONS] = {
+ /* Anchor index values for the second subset of two-subset partitioning */
+ {
+ 0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,
+ 0xf,0x2,0x8,0x2,0x2,0x8,0x8,0xf,0x2,0x8,0x2,0x2,0x8,0x8,0x2,0x2,
+ 0xf,0xf,0x6,0x8,0x2,0x8,0xf,0xf,0x2,0x8,0x2,0x2,0x2,0xf,0xf,0x6,
+ 0x6,0x2,0x6,0x8,0xf,0xf,0x2,0x2,0xf,0xf,0xf,0xf,0xf,0x2,0x2,0xf
+ },
+
+ /* Anchor index values for the second subset of three-subset partitioning */
+ {
+ 0x3,0x3,0xf,0xf,0x8,0x3,0xf,0xf,0x8,0x8,0x6,0x6,0x6,0x5,0x3,0x3,
+ 0x3,0x3,0x8,0xf,0x3,0x3,0x6,0xa,0x5,0x8,0x8,0x6,0x8,0x5,0xf,0xf,
+ 0x8,0xf,0x3,0x5,0x6,0xa,0x8,0xf,0xf,0x3,0xf,0x5,0xf,0xf,0xf,0xf,
+ 0x3,0xf,0x5,0x5,0x5,0x8,0x5,0xa,0x5,0xa,0x8,0xd,0xf,0xc,0x3,0x3
+ },
+
+ /* Anchor index values for the third subset of three-subset
+ * partitioning
+ */
+ {
+ 0xf,0x8,0x8,0x3,0xf,0xf,0x3,0x8,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x8,
+ 0xf,0x8,0xf,0x3,0xf,0x8,0xf,0x8,0x3,0xf,0x6,0xa,0xf,0xf,0xa,0x8,
+ 0xf,0x3,0xf,0xa,0xa,0x8,0x9,0xa,0x6,0xf,0x8,0xf,0x3,0x6,0x6,0x8,
+ 0xf,0x3,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x3,0xf,0xf,0x8
+ }
+};
+
+static int
+extract_bits(const uint8_t *block,
+ int offset,
+ int n_bits)
+{
+ int byte_index = offset / 8;
+ int bit_index = offset % 8;
+ int n_bits_in_byte = MIN2(n_bits, 8 - bit_index);
+ int result = 0;
+ int bit = 0;
+
+ while (true) {
+ result |= ((block[byte_index] >> bit_index) &
+ ((1 << n_bits_in_byte) - 1)) << bit;
+
+ n_bits -= n_bits_in_byte;
+
+ if (n_bits <= 0)
+ return result;
+
+ bit += n_bits_in_byte;
+ byte_index++;
+ bit_index = 0;
+ n_bits_in_byte = MIN2(n_bits, 8);
+ }
+}
+
+static uint8_t
+expand_component(uint8_t byte,
+ int n_bits)
+{
+ /* Expands a n-bit quantity into a byte by copying the most-significant
+ * bits into the unused least-significant bits.
+ */
+ return byte << (8 - n_bits) | (byte >> (2 * n_bits - 8));
+}
+
+static int
+extract_unorm_endpoints(const struct bptc_unorm_mode *mode,
+ const uint8_t *block,
+ int bit_offset,
+ uint8_t endpoints[][4])
+{
+ int component;
+ int subset;
+ int endpoint;
+ int pbit;
+ int n_components;
+
+ /* Extract each color component */
+ for (component = 0; component < 3; component++) {
+ for (subset = 0; subset < mode->n_subsets; subset++) {
+ for (endpoint = 0; endpoint < 2; endpoint++) {
+ endpoints[subset * 2 + endpoint][component] =
+ extract_bits(block, bit_offset, mode->n_color_bits);
+ bit_offset += mode->n_color_bits;
+ }
+ }
+ }
+
+ /* Extract the alpha values */
+ if (mode->n_alpha_bits > 0) {
+ for (subset = 0; subset < mode->n_subsets; subset++) {
+ for (endpoint = 0; endpoint < 2; endpoint++) {
+ endpoints[subset * 2 + endpoint][3] =
+ extract_bits(block, bit_offset, mode->n_alpha_bits);
+ bit_offset += mode->n_alpha_bits;
+ }
+ }
+
+ n_components = 4;
+ } else {
+ for (subset = 0; subset < mode->n_subsets; subset++)
+ for (endpoint = 0; endpoint < 2; endpoint++)
+ endpoints[subset * 2 + endpoint][3] = 255;
+
+ n_components = 3;
+ }
+
+ /* Add in the p-bits */
+ if (mode->has_endpoint_pbits) {
+ for (subset = 0; subset < mode->n_subsets; subset++) {
+ for (endpoint = 0; endpoint < 2; endpoint++) {
+ pbit = extract_bits(block, bit_offset, 1);
+ bit_offset += 1;
+
+ for (component = 0; component < n_components; component++) {
+ endpoints[subset * 2 + endpoint][component] <<= 1;
+ endpoints[subset * 2 + endpoint][component] |= pbit;
+ }
+ }
+ }
+ } else if (mode->has_shared_pbits) {
+ for (subset = 0; subset < mode->n_subsets; subset++) {
+ pbit = extract_bits(block, bit_offset, 1);
+ bit_offset += 1;
+
+ for (endpoint = 0; endpoint < 2; endpoint++) {
+ for (component = 0; component < n_components; component++) {
+ endpoints[subset * 2 + endpoint][component] <<= 1;
+ endpoints[subset * 2 + endpoint][component] |= pbit;
+ }
+ }
+ }
+ }
+
+ /* Expand the n-bit values to a byte */
+ for (subset = 0; subset < mode->n_subsets; subset++) {
+ for (endpoint = 0; endpoint < 2; endpoint++) {
+ for (component = 0; component < 3; component++) {
+ endpoints[subset * 2 + endpoint][component] =
+ expand_component(endpoints[subset * 2 + endpoint][component],
+ mode->n_color_bits +
+ mode->has_endpoint_pbits +
+ mode->has_shared_pbits);
+ }
+
+ if (mode->n_alpha_bits > 0) {
+ endpoints[subset * 2 + endpoint][3] =
+ expand_component(endpoints[subset * 2 + endpoint][3],
+ mode->n_alpha_bits +
+ mode->has_endpoint_pbits +
+ mode->has_shared_pbits);
+ }
+ }
+ }
+
+ return bit_offset;
+}
+
+static bool
+is_anchor(int n_subsets,
+ int partition_num,
+ int texel)
+{
+ if (texel == 0)
+ return true;
+
+ switch (n_subsets) {
+ case 1:
+ return false;
+ case 2:
+ return anchor_indices[0][partition_num] == texel;
+ case 3:
+ return (anchor_indices[1][partition_num] == texel ||
+ anchor_indices[2][partition_num] == texel);
+ default:
+ assert(false);
+ return false;
+ }
+}
+
+static int
+count_anchors_before_texel(int n_subsets,
+ int partition_num,
+ int texel)
+{
+ int count = 1;
+
+ if (texel == 0)
+ return 0;
+
+ switch (n_subsets) {
+ case 1:
+ break;
+ case 2:
+ if (texel > anchor_indices[0][partition_num])
+ count++;
+ break;
+ case 3:
+ if (texel > anchor_indices[1][partition_num])
+ count++;
+ if (texel > anchor_indices[2][partition_num])
+ count++;
+ break;
+ default:
+ assert(false);
+ return 0;
+ }
+
+ return count;
+}
+
+static int32_t
+interpolate(int32_t a, int32_t b,
+ int index,
+ int index_bits)
+{
+ static const uint8_t weights2[] = { 0, 21, 43, 64 };
+ static const uint8_t weights3[] = { 0, 9, 18, 27, 37, 46, 55, 64 };
+ static const uint8_t weights4[] =
+ { 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 };
+ static const uint8_t *weights[] = {
+ NULL, NULL, weights2, weights3, weights4
+ };
+ int weight;
+
+ weight = weights[index_bits][index];
+
+ return ((64 - weight) * a + weight * b + 32) >> 6;
+}
+
+static void
+apply_rotation(int rotation,
+ uint8_t *result)
+{
+ uint8_t t;
+
+ if (rotation == 0)
+ return;
+
+ rotation--;
+
+ t = result[rotation];
+ result[rotation] = result[3];
+ result[3] = t;
+}
+
+static void
+fetch_rgba_unorm_from_block(const uint8_t *block,
+ uint8_t *result,
+ int texel)
+{
+ int mode_num = ffs(block[0]);
+ const struct bptc_unorm_mode *mode;
+ int bit_offset, secondary_bit_offset;
+ int partition_num;
+ int subset_num;
+ int rotation;
+ int index_selection;
+ int index_bits;
+ int indices[2];
+ int index;
+ int anchors_before_texel;
+ bool anchor;
+ uint8_t endpoints[3 * 2][4];
+ uint32_t subsets;
+ int component;
+
+ if (mode_num == 0) {
+ /* According to the spec this mode is reserved and shouldn't be used. */
+ memset(result, 0, 3);
+ result[3] = 0xff;
+ return;
+ }
+
+ mode = bptc_unorm_modes + mode_num - 1;
+ bit_offset = mode_num;
+
+ partition_num = extract_bits(block, bit_offset, mode->n_partition_bits);
+ bit_offset += mode->n_partition_bits;
+
+ switch (mode->n_subsets) {
+ case 1:
+ subsets = 0;
+ break;
+ case 2:
+ subsets = partition_table1[partition_num];
+ break;
+ case 3:
+ subsets = partition_table2[partition_num];
+ break;
+ default:
+ assert(false);
+ return;
+ }
+
+ if (mode->has_rotation_bits) {
+ rotation = extract_bits(block, bit_offset, 2);
+ bit_offset += 2;
+ } else {
+ rotation = 0;
+ }
+
+ if (mode->has_index_selection_bit) {
+ index_selection = extract_bits(block, bit_offset, 1);
+ bit_offset++;
+ } else {
+ index_selection = 0;
+ }
+
+ bit_offset = extract_unorm_endpoints(mode, block, bit_offset, endpoints);
+
+ anchors_before_texel = count_anchors_before_texel(mode->n_subsets,
+ partition_num, texel);
+
+ /* Calculate the offset to the secondary index */
+ secondary_bit_offset = (bit_offset +
+ BLOCK_SIZE * BLOCK_SIZE * mode->n_index_bits -
+ mode->n_subsets +
+ mode->n_secondary_index_bits * texel -
+ anchors_before_texel);
+
+ /* Calculate the offset to the primary index for this texel */
+ bit_offset += mode->n_index_bits * texel - anchors_before_texel;
+
+ subset_num = (subsets >> (texel * 2)) & 3;
+
+ anchor = is_anchor(mode->n_subsets, partition_num, texel);
+
+ index_bits = mode->n_index_bits;
+ if (anchor)
+ index_bits--;
+ indices[0] = extract_bits(block, bit_offset, index_bits);
+
+ if (mode->n_secondary_index_bits) {
+ index_bits = mode->n_secondary_index_bits;
+ if (anchor)
+ index_bits--;
+ indices[1] = extract_bits(block, secondary_bit_offset, index_bits);
+ }
+
+ index = indices[index_selection];
+ index_bits = (index_selection ?
+ mode->n_secondary_index_bits :
+ mode->n_index_bits);
+
+ for (component = 0; component < 3; component++)
+ result[component] = interpolate(endpoints[subset_num * 2][component],
+ endpoints[subset_num * 2 + 1][component],
+ index,
+ index_bits);
+
+ /* Alpha uses the opposite index from the color components */
+ if (mode->n_secondary_index_bits && !index_selection) {
+ index = indices[1];
+ index_bits = mode->n_secondary_index_bits;
+ } else {
+ index = indices[0];
+ index_bits = mode->n_index_bits;
+ }
+
+ result[3] = interpolate(endpoints[subset_num * 2][3],
+ endpoints[subset_num * 2 + 1][3],
+ index,
+ index_bits);
+
+ apply_rotation(rotation, result);
+}
+
+static void
+fetch_bptc_rgba_unorm_bytes(const GLubyte *map,
+ GLint rowStride, GLint i, GLint j,
+ GLubyte *texel)
+{
+ const GLubyte *block;
+
+ block = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16;
+
+ fetch_rgba_unorm_from_block(block, texel, (i % 4) + (j % 4) * 4);
+}
+
+static void
+fetch_bptc_rgba_unorm(const GLubyte *map,
+ GLint rowStride, GLint i, GLint j,
+ GLfloat *texel)
+{
+ GLubyte texel_bytes[4];
+
+ fetch_bptc_rgba_unorm_bytes(map, rowStride, i, j, texel_bytes);
+
+ texel[RCOMP] = UBYTE_TO_FLOAT(texel_bytes[0]);
+ texel[GCOMP] = UBYTE_TO_FLOAT(texel_bytes[1]);
+ texel[BCOMP] = UBYTE_TO_FLOAT(texel_bytes[2]);
+ texel[ACOMP] = UBYTE_TO_FLOAT(texel_bytes[3]);
+}
+
+static void
+fetch_bptc_srgb_alpha_unorm(const GLubyte *map,
+ GLint rowStride, GLint i, GLint j,
+ GLfloat *texel)
+{
+ GLubyte texel_bytes[4];
+
+ fetch_bptc_rgba_unorm_bytes(map, rowStride, i, j, texel_bytes);
+
+ texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[0]);
+ texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[1]);
+ texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[2]);
+ texel[ACOMP] = UBYTE_TO_FLOAT(texel_bytes[3]);
+}
+
+static int32_t
+sign_extend(int32_t value,
+ int n_bits)
+{
+ if ((value & (1 << (n_bits - 1)))) {
+ value |= (~(int32_t) 0) << n_bits;
+ }
+
+ return value;
+}
+
+static int
+signed_unquantize(int value, int n_endpoint_bits)
+{
+ bool sign;
+
+ if (n_endpoint_bits >= 16)
+ return value;
+
+ if (value == 0)
+ return 0;
+
+ sign = false;
+
+ if (value < 0) {
+ sign = true;
+ value = -value;
+ }
+
+ if (value >= (1 << (n_endpoint_bits - 1)) - 1)
+ value = 0x7fff;
+ else
+ value = ((value << 15) + 0x4000) >> (n_endpoint_bits - 1);
+
+ if (sign)
+ value = -value;
+
+ return value;
+}
+
+static int
+unsigned_unquantize(int value, int n_endpoint_bits)
+{
+ if (n_endpoint_bits >= 15)
+ return value;
+
+ if (value == 0)
+ return 0;
+
+ if (value == (1 << n_endpoint_bits) - 1)
+ return 0xffff;
+
+ return ((value << 15) + 0x4000) >> (n_endpoint_bits - 1);
+}
+
+static int
+extract_float_endpoints(const struct bptc_float_mode *mode,
+ const uint8_t *block,
+ int bit_offset,
+ int32_t endpoints[][3],
+ bool is_signed)
+{
+ const struct bptc_float_bitfield *bitfield;
+ int endpoint, component;
+ int n_endpoints;
+ int value;
+ int i;
+
+ if (mode->n_partition_bits)
+ n_endpoints = 4;
+ else
+ n_endpoints = 2;
+
+ memset(endpoints, 0, sizeof endpoints[0][0] * n_endpoints * 3);
+
+ for (bitfield = mode->bitfields; bitfield->endpoint != -1; bitfield++) {
+ value = extract_bits(block, bit_offset, bitfield->n_bits);
+ bit_offset += bitfield->n_bits;
+
+ if (bitfield->reverse) {
+ for (i = 0; i < bitfield->n_bits; i++) {
+ if (value & (1 << i))
+ endpoints[bitfield->endpoint][bitfield->component] |=
+ 1 << ((bitfield->n_bits - 1 - i) + bitfield->offset);
+ }
+ } else {
+ endpoints[bitfield->endpoint][bitfield->component] |=
+ value << bitfield->offset;
+ }
+ }
+
+ if (mode->transformed_endpoints) {
+ /* The endpoints are specified as signed offsets from e0 */
+ for (endpoint = 1; endpoint < n_endpoints; endpoint++) {
+ for (component = 0; component < 3; component++) {
+ value = sign_extend(endpoints[endpoint][component],
+ mode->n_delta_bits[component]);
+ endpoints[endpoint][component] =
+ ((endpoints[0][component] + value) &
+ ((1 << mode->n_endpoint_bits) - 1));
+ }
+ }
+ }
+
+ if (is_signed) {
+ for (endpoint = 0; endpoint < n_endpoints; endpoint++) {
+ for (component = 0; component < 3; component++) {
+ value = sign_extend(endpoints[endpoint][component],
+ mode->n_endpoint_bits);
+ endpoints[endpoint][component] =
+ signed_unquantize(value, mode->n_endpoint_bits);
+ }
+ }
+ } else {
+ for (endpoint = 0; endpoint < n_endpoints; endpoint++) {
+ for (component = 0; component < 3; component++) {
+ endpoints[endpoint][component] =
+ unsigned_unquantize(endpoints[endpoint][component],
+ mode->n_endpoint_bits);
+ }
+ }
+ }
+
+ return bit_offset;
+}
+
+static int32_t
+finish_unsigned_unquantize(int32_t value)
+{
+ return value * 31 / 64;
+}
+
+static int32_t
+finish_signed_unquantize(int32_t value)
+{
+ if (value < 0)
+ return (-value * 31 / 32) | 0x8000;
+ else
+ return value * 31 / 32;
+}
+
+static void
+fetch_rgb_float_from_block(const uint8_t *block,
+ float *result,
+ int texel,
+ bool is_signed)
+{
+ int mode_num;
+ const struct bptc_float_mode *mode;
+ int bit_offset;
+ int partition_num;
+ int subset_num;
+ int index_bits;
+ int index;
+ int anchors_before_texel;
+ int32_t endpoints[2 * 2][3];
+ uint32_t subsets;
+ int n_subsets;
+ int component;
+ int32_t value;
+
+ if (block[0] & 0x2) {
+ mode_num = (((block[0] >> 1) & 0xe) | (block[0] & 1)) + 2;
+ bit_offset = 5;
+ } else {
+ mode_num = block[0] & 3;
+ bit_offset = 2;
+ }
+
+ mode = bptc_float_modes + mode_num;
+
+ if (mode->reserved) {
+ memset(result, 0, sizeof result[0] * 3);
+ result[3] = 1.0f;
+ return;
+ }
+
+ bit_offset = extract_float_endpoints(mode, block, bit_offset,
+ endpoints, is_signed);
+
+ if (mode->n_partition_bits) {
+ partition_num = extract_bits(block, bit_offset, mode->n_partition_bits);
+ bit_offset += mode->n_partition_bits;
+
+ subsets = partition_table1[partition_num];
+ n_subsets = 2;
+ } else {
+ partition_num = 0;
+ subsets = 0;
+ n_subsets = 1;
+ }
+
+ anchors_before_texel =
+ count_anchors_before_texel(n_subsets, partition_num, texel);
+
+ /* Calculate the offset to the primary index for this texel */
+ bit_offset += mode->n_index_bits * texel - anchors_before_texel;
+
+ subset_num = (subsets >> (texel * 2)) & 3;
+
+ index_bits = mode->n_index_bits;
+ if (is_anchor(n_subsets, partition_num, texel))
+ index_bits--;
+ index = extract_bits(block, bit_offset, index_bits);
+
+ for (component = 0; component < 3; component++) {
+ value = interpolate(endpoints[subset_num * 2][component],
+ endpoints[subset_num * 2 + 1][component],
+ index,
+ mode->n_index_bits);
+
+ if (is_signed)
+ value = finish_signed_unquantize(value);
+ else
+ value = finish_unsigned_unquantize(value);
+
+ result[component] = _mesa_half_to_float(value);
+ }
+
+ result[3] = 1.0f;
+}
+
+static void
+fetch_bptc_rgb_float(const GLubyte *map,
+ GLint rowStride, GLint i, GLint j,
+ GLfloat *texel,
+ bool is_signed)
+{
+ const GLubyte *block;
+
+ block = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16;
+
+ fetch_rgb_float_from_block(block, texel, (i % 4) + (j % 4) * 4, is_signed);
+}
+
+static void
+fetch_bptc_rgb_signed_float(const GLubyte *map,
+ GLint rowStride, GLint i, GLint j,
+ GLfloat *texel)
+{
+ fetch_bptc_rgb_float(map, rowStride, i, j, texel, true);
+}
+
+static void
+fetch_bptc_rgb_unsigned_float(const GLubyte *map,
+ GLint rowStride, GLint i, GLint j,
+ GLfloat *texel)
+{
+ fetch_bptc_rgb_float(map, rowStride, i, j, texel, false);
+}
+
+compressed_fetch_func
+_mesa_get_bptc_fetch_func(mesa_format format)
+{
+ switch (format) {
+ case MESA_FORMAT_BPTC_RGBA_UNORM:
+ return fetch_bptc_rgba_unorm;
+ case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
+ return fetch_bptc_srgb_alpha_unorm;
+ case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT:
+ return fetch_bptc_rgb_signed_float;
+ case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT:
+ return fetch_bptc_rgb_unsigned_float;
+ default:
+ return NULL;
+ }
+}
+
+static void
+write_bits(struct bit_writer *writer, int n_bits, int value)
+{
+ do {
+ if (n_bits + writer->pos >= 8) {
+ *(writer->dst++) = writer->buf | (value << writer->pos);
+ writer->buf = 0;
+ value >>= (8 - writer->pos);
+ n_bits -= (8 - writer->pos);
+ writer->pos = 0;
+ } else {
+ writer->buf |= value << writer->pos;
+ writer->pos += n_bits;
+ break;
+ }
+ } while (n_bits > 0);
+}
+
+static void
+get_average_luminance_alpha_unorm(int width, int height,
+ const uint8_t *src, int src_rowstride,
+ int *average_luminance, int *average_alpha)
+{
+ int luminance_sum = 0, alpha_sum = 0;
+ int y, x;
+
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+ luminance_sum += src[0] + src[1] + src[2];
+ alpha_sum += src[3];
+ src += 4;
+ }
+ src += src_rowstride - width * 4;
+ }
+
+ *average_luminance = luminance_sum / (width * height);
+ *average_alpha = alpha_sum / (width * height);
+}
+
+static void
+get_rgba_endpoints_unorm(int width, int height,
+ const uint8_t *src, int src_rowstride,
+ int average_luminance, int average_alpha,
+ uint8_t endpoints[][4])
+{
+ int endpoint_luminances[2];
+ int midpoint;
+ int sums[2][4];
+ int endpoint;
+ int luminance;
+ uint8_t temp[3];
+ const uint8_t *p = src;
+ int rgb_left_endpoint_count = 0;
+ int alpha_left_endpoint_count = 0;
+ int y, x, i;
+
+ memset(sums, 0, sizeof sums);
+
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+ luminance = p[0] + p[1] + p[2];
+ if (luminance < average_luminance) {
+ endpoint = 0;
+ rgb_left_endpoint_count++;
+ } else {
+ endpoint = 1;
+ }
+ for (i = 0; i < 3; i++)
+ sums[endpoint][i] += p[i];
+
+ if (p[2] < average_alpha) {
+ endpoint = 0;
+ alpha_left_endpoint_count++;
+ } else {
+ endpoint = 1;
+ }
+ sums[endpoint][3] += p[3];
+
+ p += 4;
+ }
+
+ p += src_rowstride - width * 4;
+ }
+
+ if (rgb_left_endpoint_count == 0 ||
+ rgb_left_endpoint_count == width * height) {
+ for (i = 0; i < 3; i++)
+ endpoints[0][i] = endpoints[1][i] =
+ (sums[0][i] + sums[1][i]) / (width * height);
+ } else {
+ for (i = 0; i < 3; i++) {
+ endpoints[0][i] = sums[0][i] / rgb_left_endpoint_count;
+ endpoints[1][i] = (sums[1][i] /
+ (width * height - rgb_left_endpoint_count));
+ }
+ }
+
+ if (alpha_left_endpoint_count == 0 ||
+ alpha_left_endpoint_count == width * height) {
+ endpoints[0][3] = endpoints[1][3] =
+ (sums[0][3] + sums[1][3]) / (width * height);
+ } else {
+ endpoints[0][3] = sums[0][3] / alpha_left_endpoint_count;
+ endpoints[1][3] = (sums[1][3] /
+ (width * height - alpha_left_endpoint_count));
+ }
+
+ /* We may need to swap the endpoints to ensure the most-significant bit of
+ * the first index is zero */
+
+ for (endpoint = 0; endpoint < 2; endpoint++) {
+ endpoint_luminances[endpoint] =
+ endpoints[endpoint][0] +
+ endpoints[endpoint][1] +
+ endpoints[endpoint][2];
+ }
+ midpoint = (endpoint_luminances[0] + endpoint_luminances[1]) / 2;
+
+ if ((src[0] + src[1] + src[2] <= midpoint) !=
+ (endpoint_luminances[0] <= midpoint)) {
+ memcpy(temp, endpoints[0], 3);
+ memcpy(endpoints[0], endpoints[1], 3);
+ memcpy(endpoints[1], temp, 3);
+ }
+
+ /* Same for the alpha endpoints */
+
+ midpoint = (endpoints[0][3] + endpoints[1][3]) / 2;
+
+ if ((src[3] <= midpoint) != (endpoints[0][3] <= midpoint)) {
+ temp[0] = endpoints[0][3];
+ endpoints[0][3] = endpoints[1][3];
+ endpoints[1][3] = temp[0];
+ }
+}
+
+static void
+write_rgb_indices_unorm(struct bit_writer *writer,
+ int src_width, int src_height,
+ const uint8_t *src, int src_rowstride,
+ uint8_t endpoints[][4])
+{
+ int luminance;
+ int endpoint_luminances[2];
+ int endpoint;
+ int index;
+ int y, x;
+
+ for (endpoint = 0; endpoint < 2; endpoint++) {
+ endpoint_luminances[endpoint] =
+ endpoints[endpoint][0] +
+ endpoints[endpoint][1] +
+ endpoints[endpoint][2];
+ }
+
+ /* If the endpoints have the same luminance then we'll just use index 0 for
+ * all of the texels */
+ if (endpoint_luminances[0] == endpoint_luminances[1]) {
+ write_bits(writer, BLOCK_SIZE * BLOCK_SIZE * 2 - 1, 0);
+ return;
+ }
+
+ for (y = 0; y < src_height; y++) {
+ for (x = 0; x < src_width; x++) {
+ luminance = src[0] + src[1] + src[2];
+
+ index = ((luminance - endpoint_luminances[0]) * 3 /
+ (endpoint_luminances[1] - endpoint_luminances[0]));
+ if (index < 0)
+ index = 0;
+ else if (index > 3)
+ index = 3;
+
+ assert(x != 0 || y != 0 || index < 2);
+
+ write_bits(writer, (x == 0 && y == 0) ? 1 : 2, index);
+
+ src += 4;
+ }
+
+ /* Pad the indices out to the block size */
+ if (src_width < BLOCK_SIZE)
+ write_bits(writer, 2 * (BLOCK_SIZE - src_width), 0);
+
+ src += src_rowstride - src_width * 4;
+ }
+
+ /* Pad the indices out to the block size */
+ if (src_height < BLOCK_SIZE)
+ write_bits(writer, 2 * BLOCK_SIZE * (BLOCK_SIZE - src_height), 0);
+}
+
+static void
+write_alpha_indices_unorm(struct bit_writer *writer,
+ int src_width, int src_height,
+ const uint8_t *src, int src_rowstride,
+ uint8_t endpoints[][4])
+{
+ int index;
+ int y, x;
+
+ /* If the endpoints have the same alpha then we'll just use index 0 for
+ * all of the texels */
+ if (endpoints[0][3] == endpoints[1][3]) {
+ write_bits(writer, BLOCK_SIZE * BLOCK_SIZE * 3 - 1, 0);
+ return;
+ }
+
+ for (y = 0; y < src_height; y++) {
+ for (x = 0; x < src_width; x++) {
+ index = (((int) src[3] - (int) endpoints[0][3]) * 7 /
+ ((int) endpoints[1][3] - endpoints[0][3]));
+ if (index < 0)
+ index = 0;
+ else if (index > 7)
+ index = 7;
+
+ assert(x != 0 || y != 0 || index < 4);
+
+ /* The first index has one less bit */
+ write_bits(writer, (x == 0 && y == 0) ? 2 : 3, index);
+
+ src += 4;
+ }
+
+ /* Pad the indices out to the block size */
+ if (src_width < BLOCK_SIZE)
+ write_bits(writer, 3 * (BLOCK_SIZE - src_width), 0);
+
+ src += src_rowstride - src_width * 4;
+ }
+
+ /* Pad the indices out to the block size */
+ if (src_height < BLOCK_SIZE)
+ write_bits(writer, 3 * BLOCK_SIZE * (BLOCK_SIZE - src_height), 0);
+}
+
+static void
+compress_rgba_unorm_block(int src_width, int src_height,
+ const uint8_t *src, int src_rowstride,
+ uint8_t *dst)
+{
+ int average_luminance, average_alpha;
+ uint8_t endpoints[2][4];
+ struct bit_writer writer;
+ int component, endpoint;
+
+ get_average_luminance_alpha_unorm(src_width, src_height, src, src_rowstride,
+ &average_luminance, &average_alpha);
+ get_rgba_endpoints_unorm(src_width, src_height, src, src_rowstride,
+ average_luminance, average_alpha,
+ endpoints);
+
+ writer.dst = dst;
+ writer.pos = 0;
+ writer.buf = 0;
+
+ write_bits(&writer, 5, 0x10); /* mode 4 */
+ write_bits(&writer, 2, 0); /* rotation 0 */
+ write_bits(&writer, 1, 0); /* index selection bit */
+
+ /* Write the color endpoints */
+ for (component = 0; component < 3; component++)
+ for (endpoint = 0; endpoint < 2; endpoint++)
+ write_bits(&writer, 5, endpoints[endpoint][component] >> 3);
+
+ /* Write the alpha endpoints */
+ for (endpoint = 0; endpoint < 2; endpoint++)
+ write_bits(&writer, 6, endpoints[endpoint][3] >> 2);
+
+ write_rgb_indices_unorm(&writer,
+ src_width, src_height,
+ src, src_rowstride,
+ endpoints);
+ write_alpha_indices_unorm(&writer,
+ src_width, src_height,
+ src, src_rowstride,
+ endpoints);
+}
+
+static void
+compress_rgba_unorm(int width, int height,
+ const uint8_t *src, int src_rowstride,
+ uint8_t *dst, int dst_rowstride)
+{
+ int dst_row_diff;
+ int y, x;
+
+ if (dst_rowstride >= width * 4)
+ dst_row_diff = dst_rowstride - ((width + 3) & ~3) * 4;
+ else
+ dst_row_diff = 0;
+
+ for (y = 0; y < height; y += BLOCK_SIZE) {
+ for (x = 0; x < width; x += BLOCK_SIZE) {
+ compress_rgba_unorm_block(MIN2(width - x, BLOCK_SIZE),
+ MIN2(height - y, BLOCK_SIZE),
+ src + x * 4 + y * src_rowstride,
+ src_rowstride,
+ dst);
+ dst += BLOCK_BYTES;
+ }
+ dst += dst_row_diff;
+ }
+}
+
+GLboolean
+_mesa_texstore_bptc_rgba_unorm(TEXSTORE_PARAMS)
+{
+ const GLubyte *pixels;
+ const GLubyte *tempImage = NULL;
+ GLenum baseFormat;
+ int rowstride;
+
+ if (srcFormat != GL_RGBA ||
+ srcType != GL_UNSIGNED_BYTE ||
+ ctx->_ImageTransferState ||
+ srcPacking->SwapBytes) {
+ /* convert image to RGBA/ubyte */
+ baseFormat = _mesa_get_format_base_format(dstFormat);
+ tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
+ baseInternalFormat,
+ baseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ if (!tempImage)
+ return GL_FALSE; /* out of memory */
+
+ pixels = tempImage;
+ rowstride = srcWidth * 4;
+ } else {
+ pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
+ srcFormat, srcType, 0, 0);
+ rowstride = _mesa_image_row_stride(srcPacking, srcWidth,
+ srcFormat, srcType);
+ }
+
+ compress_rgba_unorm(srcWidth, srcHeight,
+ pixels, rowstride,
+ dstSlices[0], dstRowStride);
+
+ free((void *) tempImage);
+
+ return GL_TRUE;
+}
+
+static float
+get_average_luminance_float(int width, int height,
+ const float *src, int src_rowstride)
+{
+ float luminance_sum = 0;
+ int y, x;
+
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+ luminance_sum += src[0] + src[1] + src[2];
+ src += 3;
+ }
+ src += (src_rowstride - width * 3 * sizeof (float)) / sizeof (float);
+ }
+
+ return luminance_sum / (width * height);
+}
+
+static float
+clamp_value(float value, bool is_signed)
+{
+ if (value > 65504.0f)
+ return 65504.0f;
+
+ if (is_signed) {
+ if (value < -65504.0f)
+ return -65504.0f;
+ else
+ return value;
+ }
+
+ if (value < 0.0f)
+ return 0.0f;
+
+ return value;
+}
+
+static void
+get_endpoints_float(int width, int height,
+ const float *src, int src_rowstride,
+ float average_luminance, float endpoints[][3],
+ bool is_signed)
+{
+ float endpoint_luminances[2];
+ float midpoint;
+ float sums[2][3];
+ int endpoint, component;
+ float luminance;
+ float temp[3];
+ const float *p = src;
+ int left_endpoint_count = 0;
+ int y, x, i;
+
+ memset(sums, 0, sizeof sums);
+
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+ luminance = p[0] + p[1] + p[2];
+ if (luminance < average_luminance) {
+ endpoint = 0;
+ left_endpoint_count++;
+ } else {
+ endpoint = 1;
+ }
+ for (i = 0; i < 3; i++)
+ sums[endpoint][i] += p[i];
+
+ p += 3;
+ }
+
+ p += (src_rowstride - width * 3 * sizeof (float)) / sizeof (float);
+ }
+
+ if (left_endpoint_count == 0 ||
+ left_endpoint_count == width * height) {
+ for (i = 0; i < 3; i++)
+ endpoints[0][i] = endpoints[1][i] =
+ (sums[0][i] + sums[1][i]) / (width * height);
+ } else {
+ for (i = 0; i < 3; i++) {
+ endpoints[0][i] = sums[0][i] / left_endpoint_count;
+ endpoints[1][i] = sums[1][i] / (width * height - left_endpoint_count);
+ }
+ }
+
+ /* Clamp the endpoints to the range of a half float and strip out
+ * infinities */
+ for (endpoint = 0; endpoint < 2; endpoint++) {
+ for (component = 0; component < 3; component++) {
+ endpoints[endpoint][component] =
+ clamp_value(endpoints[endpoint][component], is_signed);
+ }
+ }
+
+ /* We may need to swap the endpoints to ensure the most-significant bit of
+ * the first index is zero */
+
+ for (endpoint = 0; endpoint < 2; endpoint++) {
+ endpoint_luminances[endpoint] =
+ endpoints[endpoint][0] +
+ endpoints[endpoint][1] +
+ endpoints[endpoint][2];
+ }
+ midpoint = (endpoint_luminances[0] + endpoint_luminances[1]) / 2.0f;
+
+ if ((src[0] + src[1] + src[2] <= midpoint) !=
+ (endpoint_luminances[0] <= midpoint)) {
+ memcpy(temp, endpoints[0], sizeof temp);
+ memcpy(endpoints[0], endpoints[1], sizeof temp);
+ memcpy(endpoints[1], temp, sizeof temp);
+ }
+}
+
+static void
+write_rgb_indices_float(struct bit_writer *writer,
+ int src_width, int src_height,
+ const float *src, int src_rowstride,
+ float endpoints[][3])
+{
+ float luminance;
+ float endpoint_luminances[2];
+ int endpoint;
+ int index;
+ int y, x;
+
+ for (endpoint = 0; endpoint < 2; endpoint++) {
+ endpoint_luminances[endpoint] =
+ endpoints[endpoint][0] +
+ endpoints[endpoint][1] +
+ endpoints[endpoint][2];
+ }
+
+ /* If the endpoints have the same luminance then we'll just use index 0 for
+ * all of the texels */
+ if (endpoint_luminances[0] == endpoint_luminances[1]) {
+ write_bits(writer, BLOCK_SIZE * BLOCK_SIZE * 4 - 1, 0);
+ return;
+ }
+
+ for (y = 0; y < src_height; y++) {
+ for (x = 0; x < src_width; x++) {
+ luminance = src[0] + src[1] + src[2];
+
+ index = ((luminance - endpoint_luminances[0]) * 15 /
+ (endpoint_luminances[1] - endpoint_luminances[0]));
+ if (index < 0)
+ index = 0;
+ else if (index > 15)
+ index = 15;
+
+ assert(x != 0 || y != 0 || index < 8);
+
+ write_bits(writer, (x == 0 && y == 0) ? 3 : 4, index);
+
+ src += 3;
+ }
+
+ /* Pad the indices out to the block size */
+ if (src_width < BLOCK_SIZE)
+ write_bits(writer, 4 * (BLOCK_SIZE - src_width), 0);
+
+ src += (src_rowstride - src_width * 3 * sizeof (float)) / sizeof (float);
+ }
+
+ /* Pad the indices out to the block size */
+ if (src_height < BLOCK_SIZE)
+ write_bits(writer, 4 * BLOCK_SIZE * (BLOCK_SIZE - src_height), 0);
+}
+
+static int
+get_endpoint_value(float value, bool is_signed)
+{
+ bool sign = false;
+ int half;
+
+ if (is_signed) {
+ half = _mesa_float_to_half(value);
+
+ if (half & 0x8000) {
+ half &= 0x7fff;
+ sign = true;
+ }
+
+ half = (32 * half / 31) >> 6;
+
+ if (sign)
+ half = -half & ((1 << 10) - 1);
+
+ return half;
+ } else {
+ if (value <= 0.0f)
+ return 0;
+
+ half = _mesa_float_to_half(value);
+
+ return (64 * half / 31) >> 6;
+ }
+}
+
+static void
+compress_rgb_float_block(int src_width, int src_height,
+ const float *src, int src_rowstride,
+ uint8_t *dst,
+ bool is_signed)
+{
+ float average_luminance;
+ float endpoints[2][3];
+ struct bit_writer writer;
+ int component, endpoint;
+ int endpoint_value;
+
+ average_luminance =
+ get_average_luminance_float(src_width, src_height, src, src_rowstride);
+ get_endpoints_float(src_width, src_height, src, src_rowstride,
+ average_luminance, endpoints, is_signed);
+
+ writer.dst = dst;
+ writer.pos = 0;
+ writer.buf = 0;
+
+ write_bits(&writer, 5, 3); /* mode 3 */
+
+ /* Write the endpoints */
+ for (endpoint = 0; endpoint < 2; endpoint++) {
+ for (component = 0; component < 3; component++) {
+ endpoint_value =
+ get_endpoint_value(endpoints[endpoint][component], is_signed);
+ write_bits(&writer, 10, endpoint_value);
+ }
+ }
+
+ write_rgb_indices_float(&writer,
+ src_width, src_height,
+ src, src_rowstride,
+ endpoints);
+}
+
+static void
+compress_rgb_float(int width, int height,
+ const float *src, int src_rowstride,
+ uint8_t *dst, int dst_rowstride,
+ bool is_signed)
+{
+ int dst_row_diff;
+ int y, x;
+
+ if (dst_rowstride >= width * 4)
+ dst_row_diff = dst_rowstride - ((width + 3) & ~3) * 4;
+ else
+ dst_row_diff = 0;
+
+ for (y = 0; y < height; y += BLOCK_SIZE) {
+ for (x = 0; x < width; x += BLOCK_SIZE) {
+ compress_rgb_float_block(MIN2(width - x, BLOCK_SIZE),
+ MIN2(height - y, BLOCK_SIZE),
+ src + x * 3 +
+ y * src_rowstride / sizeof (float),
+ src_rowstride,
+ dst,
+ is_signed);
+ dst += BLOCK_BYTES;
+ }
+ dst += dst_row_diff;
+ }
+}
+
+static GLboolean
+texstore_bptc_rgb_float(TEXSTORE_PARAMS,
+ bool is_signed)
+{
+ const float *pixels;
+ const float *tempImage = NULL;
+ GLenum baseFormat;
+ int rowstride;
+
+ if (srcFormat != GL_RGB ||
+ srcType != GL_FLOAT ||
+ ctx->_ImageTransferState ||
+ srcPacking->SwapBytes) {
+ /* convert image to RGB/float */
+ baseFormat = _mesa_get_format_base_format(dstFormat);
+ tempImage = _mesa_make_temp_float_image(ctx, dims,
+ baseInternalFormat,
+ baseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking,
+ ctx->_ImageTransferState);
+ if (!tempImage)
+ return GL_FALSE; /* out of memory */
+
+ pixels = tempImage;
+ rowstride = srcWidth * sizeof(float) * 3;
+ } else {
+ pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
+ srcFormat, srcType, 0, 0);
+ rowstride = _mesa_image_row_stride(srcPacking, srcWidth,
+ srcFormat, srcType);
+ }
+
+ compress_rgb_float(srcWidth, srcHeight,
+ pixels, rowstride,
+ dstSlices[0], dstRowStride,
+ is_signed);
+
+ free((void *) tempImage);
+
+ return GL_TRUE;
+}
+
+GLboolean
+_mesa_texstore_bptc_rgb_signed_float(TEXSTORE_PARAMS)
+{
+ ASSERT(dstFormat == MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT);
+
+ return texstore_bptc_rgb_float(ctx, dims, baseInternalFormat,
+ dstFormat, dstRowStride, dstSlices,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType,
+ srcAddr, srcPacking,
+ true /* signed */);
+}
+
+GLboolean
+_mesa_texstore_bptc_rgb_unsigned_float(TEXSTORE_PARAMS)
+{
+ ASSERT(dstFormat == MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT);
+
+ return texstore_bptc_rgb_float(ctx, dims, baseInternalFormat,
+ dstFormat, dstRowStride, dstSlices,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType,
+ srcAddr, srcPacking,
+ false /* unsigned */);
+}
diff --git a/mesalib/src/mesa/main/texcompress_bptc.h b/mesalib/src/mesa/main/texcompress_bptc.h
new file mode 100644
index 000000000..814548e2b
--- /dev/null
+++ b/mesalib/src/mesa/main/texcompress_bptc.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2014 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef TEXCOMPRESS_BPTC_H
+#define TEXCOMPRESS_BPTC_H
+
+#include <inttypes.h>
+#include "glheader.h"
+#include "texcompress.h"
+#include "texstore.h"
+
+GLboolean
+_mesa_texstore_bptc_rgba_unorm(TEXSTORE_PARAMS);
+
+GLboolean
+_mesa_texstore_bptc_rgb_signed_float(TEXSTORE_PARAMS);
+
+GLboolean
+_mesa_texstore_bptc_rgb_unsigned_float(TEXSTORE_PARAMS);
+
+compressed_fetch_func
+_mesa_get_bptc_fetch_func(mesa_format format);
+
+#endif
diff --git a/mesalib/src/mesa/main/texformat.c b/mesalib/src/mesa/main/texformat.c
index c61a74859..6d3b80556 100644
--- a/mesalib/src/mesa/main/texformat.c
+++ b/mesalib/src/mesa/main/texformat.c
@@ -345,6 +345,14 @@ _mesa_choose_tex_format(struct gl_context *ctx, GLenum target,
return MESA_FORMAT_SRGBA_DXT3;
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
return MESA_FORMAT_SRGBA_DXT5;
+ case GL_COMPRESSED_RGBA_BPTC_UNORM:
+ return MESA_FORMAT_BPTC_RGBA_UNORM;
+ case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
+ return MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM;
+ case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
+ return MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT;
+ case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
+ return MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT;
case GL_ALPHA16F_ARB:
RETURN_IF_SUPPORTED(MESA_FORMAT_A_FLOAT16);
diff --git a/mesalib/src/mesa/main/texgetimage.c b/mesalib/src/mesa/main/texgetimage.c
index f1e09c986..2c54e4a35 100644
--- a/mesalib/src/mesa/main/texgetimage.c
+++ b/mesalib/src/mesa/main/texgetimage.c
@@ -40,6 +40,7 @@
#include "mtypes.h"
#include "pack.h"
#include "pbo.h"
+#include "pixelstore.h"
#include "texcompress.h"
#include "texgetimage.h"
#include "teximage.h"
@@ -693,7 +694,7 @@ _mesa_get_compressed_teximage(struct gl_context *ctx,
GLuint i, slice;
GLubyte *dest;
- _mesa_compute_compressed_pixelstore(dimensions, texImage,
+ _mesa_compute_compressed_pixelstore(dimensions, texImage->TexFormat,
texImage->Width, texImage->Height,
texImage->Depth,
&ctx->Pack,
@@ -1008,9 +1009,9 @@ getcompressedteximage_error_check(struct gl_context *ctx, GLenum target,
/* Check for invalid pixel storage modes */
dimensions = _mesa_get_texture_dimensions(texImage->TexObject->Target);
- if (!_mesa_compressed_texture_pixel_storage_error_check(ctx, dimensions,
- &ctx->Pack,
- "glGetCompressedTexImageARB")) {
+ if (!_mesa_compressed_pixel_storage_error_check(ctx, dimensions,
+ &ctx->Pack,
+ "glGetCompressedTexImageARB")) {
return GL_TRUE;
}
diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c
index bb050b188..647d28ab3 100644
--- a/mesalib/src/mesa/main/teximage.c
+++ b/mesalib/src/mesa/main/teximage.c
@@ -41,6 +41,7 @@
#include "imports.h"
#include "macros.h"
#include "multisample.h"
+#include "pixelstore.h"
#include "state.h"
#include "texcompress.h"
#include "texcompress_cpal.h"
@@ -520,6 +521,20 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat )
}
}
+ if (_mesa_is_desktop_gl(ctx) &&
+ ctx->Extensions.ARB_texture_compression_bptc) {
+ switch (internalFormat) {
+ case GL_COMPRESSED_RGBA_BPTC_UNORM:
+ case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
+ return GL_RGBA;
+ case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
+ case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
+ return GL_RGB;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
if (ctx->API == API_OPENGLES) {
switch (internalFormat) {
case GL_PALETTE4_RGB8_OES:
@@ -2250,36 +2265,6 @@ texture_error_check( struct gl_context *ctx,
}
-bool
-_mesa_compressed_texture_pixel_storage_error_check(struct gl_context *ctx,
- GLint dimensions,
- struct gl_pixelstore_attrib *packing,
- const char *caller)
-{
- if (!_mesa_is_desktop_gl(ctx) || !packing->CompressedBlockSize)
- return true;
-
- if (packing->CompressedBlockWidth && packing->SkipPixels % packing->CompressedBlockWidth) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "%s(skip-pixels %% block-width)", caller);
- return false;
- }
-
- if (dimensions > 1 && packing->CompressedBlockHeight && packing->SkipRows % packing->CompressedBlockHeight) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "%s(skip-rows %% block-height)", caller);
- return false;
- }
-
- if (dimensions > 2 && packing->CompressedBlockDepth && packing->SkipImages % packing->CompressedBlockDepth) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "%s(skip-images %% block-depth)", caller);
- return false;
- }
-
- return true;
-}
-
/**
* Error checking for glCompressedTexImage[123]D().
* Note that the width, height and depth values are not fully error checked
@@ -2389,9 +2374,9 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
}
/* Check for invalid pixel storage modes */
- if (!_mesa_compressed_texture_pixel_storage_error_check(ctx, dimensions,
- &ctx->Unpack,
- "glCompressedTexImage")) {
+ if (!_mesa_compressed_pixel_storage_error_check(ctx, dimensions,
+ &ctx->Unpack,
+ "glCompressedTexImage")) {
return GL_FALSE;
}
@@ -4197,9 +4182,9 @@ out:
/**
* Error checking for glCompressedTexSubImage[123]D().
- * \return error code or GL_NO_ERROR.
+ * \return GL_TRUE if error, GL_FALSE if no error
*/
-static GLenum
+static GLboolean
compressed_subtexture_error_check(struct gl_context *ctx, GLint dims,
GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
@@ -4258,13 +4243,12 @@ compressed_subtexture_error_check(struct gl_context *ctx, GLint dims,
}
/* Check for invalid pixel storage modes */
- if (!_mesa_compressed_texture_pixel_storage_error_check(ctx, dims,
- &ctx->Unpack,
- "glCompressedTexSubImage")) {
- return GL_FALSE;
+ if (!_mesa_compressed_pixel_storage_error_check(ctx, dims,
+ &ctx->Unpack,
+ "glCompressedTexSubImage")) {
+ return GL_TRUE;
}
-
expectedSize = compressed_tex_size(width, height, depth, format);
if (expectedSize != imageSize) {
_mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage%uD(size=%d)",
diff --git a/mesalib/src/mesa/main/teximage.h b/mesalib/src/mesa/main/teximage.h
index 52bfa7816..4b27381a0 100644
--- a/mesalib/src/mesa/main/teximage.h
+++ b/mesalib/src/mesa/main/teximage.h
@@ -339,12 +339,6 @@ _mesa_TexStorage3DMultisample(GLenum target, GLsizei samples,
GLsizei height, GLsizei depth,
GLboolean fixedsamplelocations);
-bool
-_mesa_compressed_texture_pixel_storage_error_check(struct gl_context *ctx,
- GLint dimensions,
- struct gl_pixelstore_attrib *packing,
- const char *caller);
-
/*@}*/
#ifdef __cplusplus
diff --git a/mesalib/src/mesa/main/texparam.c b/mesalib/src/mesa/main/texparam.c
index 30dd0b9b3..e40fb249e 100644
--- a/mesalib/src/mesa/main/texparam.c
+++ b/mesalib/src/mesa/main/texparam.c
@@ -1384,7 +1384,7 @@ _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
if (!obj)
return;
- _mesa_lock_texture(ctx, obj);
+ _mesa_lock_context_textures(ctx);
switch (pname) {
case GL_TEXTURE_MAG_FILTER:
*params = ENUM_TO_FLOAT(obj->Sampler.MagFilter);
@@ -1591,11 +1591,11 @@ _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
}
/* no error if we get here */
- _mesa_unlock_texture(ctx, obj);
+ _mesa_unlock_context_textures(ctx);
return;
invalid_pname:
- _mesa_unlock_texture(ctx, obj);
+ _mesa_unlock_context_textures(ctx);
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(pname=0x%x)", pname);
}
diff --git a/mesalib/src/mesa/main/texstore.c b/mesalib/src/mesa/main/texstore.c
index 0e036d9eb..d2aba8ba1 100644
--- a/mesalib/src/mesa/main/texstore.c
+++ b/mesalib/src/mesa/main/texstore.c
@@ -68,6 +68,7 @@
#include "texcompress_rgtc.h"
#include "texcompress_s3tc.h"
#include "texcompress_etc.h"
+#include "texcompress_bptc.h"
#include "teximage.h"
#include "texstore.h"
#include "enums.h"
@@ -1426,6 +1427,15 @@ texstore_compressed(TEXSTORE_PARAMS)
table[MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1] =
_mesa_texstore_etc2_srgb8_punchthrough_alpha1;
+ table[MESA_FORMAT_BPTC_RGBA_UNORM] =
+ _mesa_texstore_bptc_rgba_unorm;
+ table[MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM] =
+ _mesa_texstore_bptc_rgba_unorm;
+ table[MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT] =
+ _mesa_texstore_bptc_rgb_signed_float;
+ table[MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT] =
+ _mesa_texstore_bptc_rgb_unsigned_float;
+
initialized = GL_TRUE;
}
@@ -1485,6 +1495,12 @@ texstore_swizzle(TEXSTORE_PARAMS)
if (!is_array)
return GL_FALSE;
+ if (srcFormat == GL_COLOR_INDEX)
+ return GL_FALSE;
+
+ if (_mesa_texstore_needs_transfer_ops(ctx, baseInternalFormat, dstFormat))
+ return GL_FALSE;
+
switch (srcType) {
case GL_FLOAT:
case GL_UNSIGNED_BYTE:
@@ -2175,14 +2191,23 @@ _mesa_store_compressed_teximage(struct gl_context *ctx, GLuint dims,
}
+/**
+ * Compute compressed_pixelstore parameters for copying compressed
+ * texture data.
+ * \param dims number of texture image dimensions: 1, 2 or 3
+ * \param texFormat the compressed texture format
+ * \param width, height, depth size of image to copy
+ * \param packing pixelstore parameters describing user-space image packing
+ * \param store returns the compressed_pixelstore parameters
+ */
void
-_mesa_compute_compressed_pixelstore(GLuint dims, struct gl_texture_image *texImage,
- GLsizei width, GLsizei height, GLsizei depth,
- const struct gl_pixelstore_attrib *packing,
- struct compressed_pixelstore *store)
+_mesa_compute_compressed_pixelstore(GLuint dims, mesa_format texFormat,
+ GLsizei width, GLsizei height,
+ GLsizei depth,
+ const struct gl_pixelstore_attrib *packing,
+ struct compressed_pixelstore *store)
{
GLuint bw, bh;
- const mesa_format texFormat = texImage->TexFormat;
_mesa_get_format_block_size(texFormat, &bw, &bh);
@@ -2252,8 +2277,9 @@ _mesa_store_compressed_texsubimage(struct gl_context *ctx, GLuint dims,
return;
}
- _mesa_compute_compressed_pixelstore(dims, texImage, width, height, depth,
- &ctx->Unpack, &store);
+ _mesa_compute_compressed_pixelstore(dims, texImage->TexFormat,
+ width, height, depth,
+ &ctx->Unpack, &store);
/* get pointer to src pixels (may be in a pbo which we'll map here) */
data = _mesa_validate_pbo_compressed_teximage(ctx, dims, imageSize, data,
diff --git a/mesalib/src/mesa/main/texstore.h b/mesalib/src/mesa/main/texstore.h
index dd1e1d015..4c41d1fcd 100644
--- a/mesalib/src/mesa/main/texstore.h
+++ b/mesalib/src/mesa/main/texstore.h
@@ -150,10 +150,11 @@ struct compressed_pixelstore {
extern void
-_mesa_compute_compressed_pixelstore(GLuint dims, struct gl_texture_image *texImage,
- GLsizei width, GLsizei height, GLsizei depth,
- const struct gl_pixelstore_attrib *packing,
- struct compressed_pixelstore *store);
+_mesa_compute_compressed_pixelstore(GLuint dims, mesa_format texFormat,
+ GLsizei width, GLsizei height,
+ GLsizei depth,
+ const struct gl_pixelstore_attrib *packing,
+ struct compressed_pixelstore *store);
#endif
diff --git a/mesalib/src/mesa/main/uniform_query.cpp b/mesalib/src/mesa/main/uniform_query.cpp
index 7e630e65b..4cd2bca01 100644
--- a/mesalib/src/mesa/main/uniform_query.cpp
+++ b/mesalib/src/mesa/main/uniform_query.cpp
@@ -799,9 +799,9 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
for (i = 0; i < elems; i++) {
if (basicType == GLSL_TYPE_FLOAT) {
- dst[i].i = src[i].f != 0.0f ? 1 : 0;
+ dst[i].i = src[i].f != 0.0f ? ctx->Const.UniformBooleanTrue : 0;
} else {
- dst[i].i = src[i].i != 0 ? 1 : 0;
+ dst[i].i = src[i].i != 0 ? ctx->Const.UniformBooleanTrue : 0;
}
}
}
diff --git a/mesalib/src/mesa/main/varray.c b/mesalib/src/mesa/main/varray.c
index 230fb30cb..5d3cc2a70 100644
--- a/mesalib/src/mesa/main/varray.c
+++ b/mesalib/src/mesa/main/varray.c
@@ -1553,14 +1553,14 @@ _mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers,
*/
if (offsets[i] < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glBindVertexBuffer(offsets[%u]=%" PRId64 " < 0)",
+ "glBindVertexBuffers(offsets[%u]=%" PRId64 " < 0)",
i, (int64_t) offsets[i]);
continue;
}
if (strides[i] < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glBindVertexBuffer(strides[%u]=%d < 0)",
+ "glBindVertexBuffers(strides[%u]=%d < 0)",
i, strides[i]);
continue;
}
diff --git a/mesalib/src/mesa/main/varray.h b/mesalib/src/mesa/main/varray.h
index f94ebac99..d5d8b363d 100644
--- a/mesalib/src/mesa/main/varray.h
+++ b/mesalib/src/mesa/main/varray.h
@@ -272,6 +272,10 @@ extern void GLAPIENTRY
_mesa_DrawArrays(GLenum mode, GLint first, GLsizei count);
extern void GLAPIENTRY
+_mesa_DrawArraysInstanced(GLenum mode, GLint first, GLsizei count,
+ GLsizei primcount);
+
+extern void GLAPIENTRY
_mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
const GLvoid *indices);
diff --git a/mesalib/src/mesa/main/version.c b/mesalib/src/mesa/main/version.c
index b3ae3f5e8..126032740 100644
--- a/mesalib/src/mesa/main/version.c
+++ b/mesalib/src/mesa/main/version.c
@@ -124,8 +124,9 @@ create_version_string(struct gl_context *ctx, const char *prefix)
* 3.1: select a Core profile with GL version 3.1
* 3.1FC: select a Core+Forward Compatible profile with GL version 3.1
*/
-void
-_mesa_override_gl_version(struct gl_context *ctx)
+bool
+_mesa_override_gl_version_contextless(struct gl_constants *consts,
+ gl_api *apiOut, GLuint *versionOut)
{
int version;
GLboolean fwd_context;
@@ -133,15 +134,25 @@ _mesa_override_gl_version(struct gl_context *ctx)
get_gl_override(&version, &fwd_context);
if (version > 0) {
- ctx->Version = version;
+ *versionOut = version;
if (version >= 30 && fwd_context) {
- ctx->API = API_OPENGL_CORE;
- ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT;
+ *apiOut = API_OPENGL_CORE;
+ consts->ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT;
} else if (version >= 31) {
- ctx->API = API_OPENGL_CORE;
+ *apiOut = API_OPENGL_CORE;
} else {
- ctx->API = API_OPENGL_COMPAT;
+ *apiOut = API_OPENGL_COMPAT;
}
+ return GL_TRUE;
+ }
+ return GL_FALSE;
+}
+
+void
+_mesa_override_gl_version(struct gl_context *ctx)
+{
+ if (_mesa_override_gl_version_contextless(&ctx->Const, &ctx->API,
+ &ctx->Version)) {
create_version_string(ctx, "");
}
}
@@ -168,7 +179,7 @@ _mesa_get_gl_version_override(void)
* MESA_GLSL_VERSION_OVERRIDE are integers, such as "130".
*/
void
-_mesa_override_glsl_version(struct gl_context *ctx)
+_mesa_override_glsl_version(struct gl_constants *consts)
{
const char *env_var = "MESA_GLSL_VERSION_OVERRIDE";
const char *version;
@@ -179,7 +190,7 @@ _mesa_override_glsl_version(struct gl_context *ctx)
return;
}
- n = sscanf(version, "%u", &ctx->Const.GLSLVersion);
+ n = sscanf(version, "%u", &consts->GLSLVersion);
if (n != 1) {
fprintf(stderr, "error: invalid value for %s: %s\n", env_var, version);
return;
@@ -189,31 +200,32 @@ _mesa_override_glsl_version(struct gl_context *ctx)
/**
* Examine enabled GL extensions to determine GL version.
*/
-static void
-compute_version(struct gl_context *ctx)
+static GLuint
+compute_version(const struct gl_extensions *extensions,
+ const struct gl_constants *consts, gl_api api)
{
- GLuint major, minor;
+ GLuint major, minor, version;
- const GLboolean ver_1_3 = (ctx->Extensions.ARB_texture_border_clamp &&
- ctx->Extensions.ARB_texture_cube_map &&
- ctx->Extensions.ARB_texture_env_combine &&
- ctx->Extensions.ARB_texture_env_dot3);
+ const GLboolean ver_1_3 = (extensions->ARB_texture_border_clamp &&
+ extensions->ARB_texture_cube_map &&
+ extensions->ARB_texture_env_combine &&
+ extensions->ARB_texture_env_dot3);
const GLboolean ver_1_4 = (ver_1_3 &&
- ctx->Extensions.ARB_depth_texture &&
- ctx->Extensions.ARB_shadow &&
- ctx->Extensions.ARB_texture_env_crossbar &&
- ctx->Extensions.EXT_blend_color &&
- ctx->Extensions.EXT_blend_func_separate &&
- ctx->Extensions.EXT_blend_minmax &&
- ctx->Extensions.EXT_point_parameters);
+ extensions->ARB_depth_texture &&
+ extensions->ARB_shadow &&
+ extensions->ARB_texture_env_crossbar &&
+ extensions->EXT_blend_color &&
+ extensions->EXT_blend_func_separate &&
+ extensions->EXT_blend_minmax &&
+ extensions->EXT_point_parameters);
const GLboolean ver_1_5 = (ver_1_4 &&
- ctx->Extensions.ARB_occlusion_query);
+ extensions->ARB_occlusion_query);
const GLboolean ver_2_0 = (ver_1_5 &&
- ctx->Extensions.ARB_point_sprite &&
- ctx->Extensions.ARB_vertex_shader &&
- ctx->Extensions.ARB_fragment_shader &&
- ctx->Extensions.ARB_texture_non_power_of_two &&
- ctx->Extensions.EXT_blend_equation_separate &&
+ extensions->ARB_point_sprite &&
+ extensions->ARB_vertex_shader &&
+ extensions->ARB_fragment_shader &&
+ extensions->ARB_texture_non_power_of_two &&
+ extensions->EXT_blend_equation_separate &&
/* Technically, 2.0 requires the functionality
* of the EXT version. Enable 2.0 if either
@@ -221,61 +233,61 @@ compute_version(struct gl_context *ctx)
* driver that only exposes the ATI extension
* will fallback to software when necessary.
*/
- (ctx->Extensions.EXT_stencil_two_side
- || ctx->Extensions.ATI_separate_stencil));
+ (extensions->EXT_stencil_two_side
+ || extensions->ATI_separate_stencil));
const GLboolean ver_2_1 = (ver_2_0 &&
- ctx->Extensions.EXT_pixel_buffer_object &&
- ctx->Extensions.EXT_texture_sRGB);
+ extensions->EXT_pixel_buffer_object &&
+ extensions->EXT_texture_sRGB);
const GLboolean ver_3_0 = (ver_2_1 &&
- ctx->Const.GLSLVersion >= 130 &&
- (ctx->Const.MaxSamples >= 4 || ctx->Const.FakeSWMSAA) &&
- (ctx->API == API_OPENGL_CORE ||
- ctx->Extensions.ARB_color_buffer_float) &&
- ctx->Extensions.ARB_depth_buffer_float &&
- ctx->Extensions.ARB_half_float_vertex &&
- ctx->Extensions.ARB_map_buffer_range &&
- ctx->Extensions.ARB_shader_texture_lod &&
- ctx->Extensions.ARB_texture_float &&
- ctx->Extensions.ARB_texture_rg &&
- ctx->Extensions.ARB_texture_compression_rgtc &&
- ctx->Extensions.EXT_draw_buffers2 &&
- ctx->Extensions.ARB_framebuffer_object &&
- ctx->Extensions.EXT_framebuffer_sRGB &&
- ctx->Extensions.EXT_packed_float &&
- ctx->Extensions.EXT_texture_array &&
- ctx->Extensions.EXT_texture_shared_exponent &&
- ctx->Extensions.EXT_transform_feedback &&
- ctx->Extensions.NV_conditional_render);
+ consts->GLSLVersion >= 130 &&
+ (consts->MaxSamples >= 4 || consts->FakeSWMSAA) &&
+ (api == API_OPENGL_CORE ||
+ extensions->ARB_color_buffer_float) &&
+ extensions->ARB_depth_buffer_float &&
+ extensions->ARB_half_float_vertex &&
+ extensions->ARB_map_buffer_range &&
+ extensions->ARB_shader_texture_lod &&
+ extensions->ARB_texture_float &&
+ extensions->ARB_texture_rg &&
+ extensions->ARB_texture_compression_rgtc &&
+ extensions->EXT_draw_buffers2 &&
+ extensions->ARB_framebuffer_object &&
+ extensions->EXT_framebuffer_sRGB &&
+ extensions->EXT_packed_float &&
+ extensions->EXT_texture_array &&
+ extensions->EXT_texture_shared_exponent &&
+ extensions->EXT_transform_feedback &&
+ extensions->NV_conditional_render);
const GLboolean ver_3_1 = (ver_3_0 &&
- ctx->Const.GLSLVersion >= 140 &&
- ctx->Extensions.ARB_draw_instanced &&
- ctx->Extensions.ARB_texture_buffer_object &&
- ctx->Extensions.ARB_uniform_buffer_object &&
- ctx->Extensions.EXT_texture_snorm &&
- ctx->Extensions.NV_primitive_restart &&
- ctx->Extensions.NV_texture_rectangle &&
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits >= 16);
+ consts->GLSLVersion >= 140 &&
+ extensions->ARB_draw_instanced &&
+ extensions->ARB_texture_buffer_object &&
+ extensions->ARB_uniform_buffer_object &&
+ extensions->EXT_texture_snorm &&
+ extensions->NV_primitive_restart &&
+ extensions->NV_texture_rectangle &&
+ consts->Program[MESA_SHADER_VERTEX].MaxTextureImageUnits >= 16);
const GLboolean ver_3_2 = (ver_3_1 &&
- ctx->Const.GLSLVersion >= 150 &&
- ctx->Extensions.ARB_depth_clamp &&
- ctx->Extensions.ARB_draw_elements_base_vertex &&
- ctx->Extensions.ARB_fragment_coord_conventions &&
- ctx->Extensions.EXT_provoking_vertex &&
- ctx->Extensions.ARB_seamless_cube_map &&
- ctx->Extensions.ARB_sync &&
- ctx->Extensions.ARB_texture_multisample &&
- ctx->Extensions.EXT_vertex_array_bgra);
+ consts->GLSLVersion >= 150 &&
+ extensions->ARB_depth_clamp &&
+ extensions->ARB_draw_elements_base_vertex &&
+ extensions->ARB_fragment_coord_conventions &&
+ extensions->EXT_provoking_vertex &&
+ extensions->ARB_seamless_cube_map &&
+ extensions->ARB_sync &&
+ extensions->ARB_texture_multisample &&
+ extensions->EXT_vertex_array_bgra);
const GLboolean ver_3_3 = (ver_3_2 &&
- ctx->Const.GLSLVersion >= 330 &&
- ctx->Extensions.ARB_blend_func_extended &&
- ctx->Extensions.ARB_explicit_attrib_location &&
- ctx->Extensions.ARB_instanced_arrays &&
- ctx->Extensions.ARB_occlusion_query2 &&
- ctx->Extensions.ARB_shader_bit_encoding &&
- ctx->Extensions.ARB_texture_rgb10_a2ui &&
- ctx->Extensions.ARB_timer_query &&
- ctx->Extensions.ARB_vertex_type_2_10_10_10_rev &&
- ctx->Extensions.EXT_texture_swizzle);
+ consts->GLSLVersion >= 330 &&
+ extensions->ARB_blend_func_extended &&
+ extensions->ARB_explicit_attrib_location &&
+ extensions->ARB_instanced_arrays &&
+ extensions->ARB_occlusion_query2 &&
+ extensions->ARB_shader_bit_encoding &&
+ extensions->ARB_texture_rgb10_a2ui &&
+ extensions->ARB_timer_query &&
+ extensions->ARB_vertex_type_2_10_10_10_rev &&
+ extensions->EXT_texture_swizzle);
/* ARB_sampler_objects is always enabled in mesa */
if (ver_3_3) {
@@ -319,74 +331,95 @@ compute_version(struct gl_context *ctx)
minor = 2;
}
- ctx->Version = major * 10 + minor;
+ version = major * 10 + minor;
- create_version_string(ctx, "");
+ if (api == API_OPENGL_CORE && version < 31)
+ return 0;
+
+ return version;
}
-static void
-compute_version_es1(struct gl_context *ctx)
+static GLuint
+compute_version_es1(const struct gl_extensions *extensions)
{
/* OpenGL ES 1.0 is derived from OpenGL 1.3 */
- const GLboolean ver_1_0 = (ctx->Extensions.ARB_texture_env_combine &&
- ctx->Extensions.ARB_texture_env_dot3);
+ const GLboolean ver_1_0 = (extensions->ARB_texture_env_combine &&
+ extensions->ARB_texture_env_dot3);
/* OpenGL ES 1.1 is derived from OpenGL 1.5 */
const GLboolean ver_1_1 = (ver_1_0 &&
- ctx->Extensions.EXT_point_parameters);
+ extensions->EXT_point_parameters);
if (ver_1_1) {
- ctx->Version = 11;
+ return 11;
} else if (ver_1_0) {
- ctx->Version = 10;
+ return 10;
} else {
- _mesa_problem(ctx, "Incomplete OpenGL ES 1.0 support.");
+ return 0;
}
-
- create_version_string(ctx, "OpenGL ES-CM ");
}
-static void
-compute_version_es2(struct gl_context *ctx)
+static GLuint
+compute_version_es2(const struct gl_extensions *extensions)
{
/* OpenGL ES 2.0 is derived from OpenGL 2.0 */
- const GLboolean ver_2_0 = (ctx->Extensions.ARB_texture_cube_map &&
- ctx->Extensions.EXT_blend_color &&
- ctx->Extensions.EXT_blend_func_separate &&
- ctx->Extensions.EXT_blend_minmax &&
- ctx->Extensions.ARB_vertex_shader &&
- ctx->Extensions.ARB_fragment_shader &&
- ctx->Extensions.ARB_texture_non_power_of_two &&
- ctx->Extensions.EXT_blend_equation_separate);
+ const GLboolean ver_2_0 = (extensions->ARB_texture_cube_map &&
+ extensions->EXT_blend_color &&
+ extensions->EXT_blend_func_separate &&
+ extensions->EXT_blend_minmax &&
+ extensions->ARB_vertex_shader &&
+ extensions->ARB_fragment_shader &&
+ extensions->ARB_texture_non_power_of_two &&
+ extensions->EXT_blend_equation_separate);
/* FINISHME: This list isn't quite right. */
- const GLboolean ver_3_0 = (ctx->Extensions.ARB_half_float_vertex &&
- ctx->Extensions.ARB_internalformat_query &&
- ctx->Extensions.ARB_map_buffer_range &&
- ctx->Extensions.ARB_shader_texture_lod &&
- ctx->Extensions.ARB_texture_float &&
- ctx->Extensions.ARB_texture_rg &&
- ctx->Extensions.ARB_texture_compression_rgtc &&
- ctx->Extensions.EXT_draw_buffers2 &&
- /* ctx->Extensions.ARB_framebuffer_object && */
- ctx->Extensions.EXT_framebuffer_sRGB &&
- ctx->Extensions.EXT_packed_float &&
- ctx->Extensions.EXT_texture_array &&
- ctx->Extensions.EXT_texture_shared_exponent &&
- ctx->Extensions.EXT_transform_feedback &&
- ctx->Extensions.NV_conditional_render &&
- ctx->Extensions.ARB_draw_instanced &&
- ctx->Extensions.ARB_uniform_buffer_object &&
- ctx->Extensions.EXT_texture_snorm &&
- ctx->Extensions.NV_primitive_restart &&
- ctx->Extensions.OES_depth_texture_cube_map);
+ const GLboolean ver_3_0 = (extensions->ARB_half_float_vertex &&
+ extensions->ARB_internalformat_query &&
+ extensions->ARB_map_buffer_range &&
+ extensions->ARB_shader_texture_lod &&
+ extensions->ARB_texture_float &&
+ extensions->ARB_texture_rg &&
+ extensions->ARB_texture_compression_rgtc &&
+ extensions->EXT_draw_buffers2 &&
+ /* extensions->ARB_framebuffer_object && */
+ extensions->EXT_framebuffer_sRGB &&
+ extensions->EXT_packed_float &&
+ extensions->EXT_texture_array &&
+ extensions->EXT_texture_shared_exponent &&
+ extensions->EXT_transform_feedback &&
+ extensions->NV_conditional_render &&
+ extensions->ARB_draw_instanced &&
+ extensions->ARB_uniform_buffer_object &&
+ extensions->EXT_texture_snorm &&
+ extensions->NV_primitive_restart &&
+ extensions->OES_depth_texture_cube_map);
if (ver_3_0) {
- ctx->Version = 30;
+ return 30;
} else if (ver_2_0) {
- ctx->Version = 20;
+ return 20;
} else {
- _mesa_problem(ctx, "Incomplete OpenGL ES 2.0 support.");
+ return 0;
}
+}
- create_version_string(ctx, "OpenGL ES ");
+GLuint
+_mesa_get_version(const struct gl_extensions *extensions,
+ struct gl_constants *consts, gl_api api)
+{
+ switch (api) {
+ case API_OPENGL_COMPAT:
+ /* Disable GLSL 1.40 and later for legacy contexts.
+ * This disallows creation of the GL 3.1 compatibility context. */
+ if (consts->GLSLVersion > 130) {
+ consts->GLSLVersion = 130;
+ }
+ /* fall through */
+ case API_OPENGL_CORE:
+ return compute_version(extensions, consts, api);
+ case API_OPENGLES:
+ return compute_version_es1(extensions);
+ case API_OPENGLES2:
+ return compute_version_es2(extensions);
+ }
+ return 0;
}
/**
@@ -400,23 +433,28 @@ _mesa_compute_version(struct gl_context *ctx)
if (ctx->Version)
return;
+ ctx->Version = _mesa_get_version(&ctx->Extensions, &ctx->Const, ctx->API);
+
switch (ctx->API) {
case API_OPENGL_COMPAT:
- /* Disable GLSL 1.40 and later for legacy contexts.
- * This disallows creation of the GL 3.1 compatibility context. */
- if (ctx->Const.GLSLVersion > 130) {
- ctx->Const.GLSLVersion = 130;
- }
- /* fall through */
case API_OPENGL_CORE:
- compute_version(ctx);
+ create_version_string(ctx, "");
break;
+
case API_OPENGLES:
- compute_version_es1(ctx);
+ if (!ctx->Version) {
+ _mesa_problem(ctx, "Incomplete OpenGL ES 1.0 support.");
+ return;
+ }
+ create_version_string(ctx, "OpenGL ES-CM ");
break;
+
case API_OPENGLES2:
- compute_version_es2(ctx);
+ if (!ctx->Version) {
+ _mesa_problem(ctx, "Incomplete OpenGL ES 2.0 support.");
+ return;
+ }
+ create_version_string(ctx, "OpenGL ES ");
break;
}
-
}
diff --git a/mesalib/src/mesa/main/version.h b/mesalib/src/mesa/main/version.h
index c78f87a2b..450a0e31d 100644
--- a/mesalib/src/mesa/main/version.h
+++ b/mesalib/src/mesa/main/version.h
@@ -27,18 +27,25 @@
#ifndef VERSION_H
#define VERSION_H
+#include "mtypes.h"
-struct gl_context;
+extern GLuint
+_mesa_get_version(const struct gl_extensions *extensions,
+ struct gl_constants *consts, gl_api api);
extern void
_mesa_compute_version(struct gl_context *ctx);
+extern bool
+_mesa_override_gl_version_contextless(struct gl_constants *consts,
+ gl_api *apiOut, GLuint *versionOut);
+
extern void
_mesa_override_gl_version(struct gl_context *ctx);
extern void
-_mesa_override_glsl_version(struct gl_context *ctx);
+_mesa_override_glsl_version(struct gl_constants *consts);
extern int
_mesa_get_gl_version_override(void);