aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src')
-rw-r--r--mesalib/src/gallium/auxiliary/hud/hud_context.c3
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_blit.c3
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_format_pack.py122
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_format_parse.py211
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_format_table.py44
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_math.h31
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_pack_color.h38
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_surface.c2
-rw-r--r--mesalib/src/glsl/glsl_types.h2
-rw-r--r--mesalib/src/glsl/lower_instructions.cpp4
-rw-r--r--mesalib/src/mapi/Makefile.sources1
-rw-r--r--mesalib/src/mesa/drivers/common/meta.c4
-rw-r--r--mesalib/src/mesa/drivers/dri/common/SConscript1
-rwxr-xr-x[-rw-r--r--]mesalib/src/mesa/drivers/dri/common/dri_util.c7
-rw-r--r--mesalib/src/mesa/drivers/dri/common/dri_util.h8
-rw-r--r--mesalib/src/mesa/drivers/dri/common/megadriver_stub.c7
-rw-r--r--mesalib/src/mesa/drivers/dri/swrast/swrast.c8
-rw-r--r--mesalib/src/mesa/main/enable.c35
-rw-r--r--mesalib/src/mesa/main/errors.c1175
-rw-r--r--mesalib/src/mesa/main/errors.h10
-rw-r--r--mesalib/src/mesa/main/ff_fragment_shader.cpp19
-rw-r--r--mesalib/src/mesa/main/ffvertex_prog.c4
-rw-r--r--mesalib/src/mesa/main/get.c16
-rw-r--r--mesalib/src/mesa/main/getstring.c17
-rw-r--r--mesalib/src/mesa/main/mtypes.h50
-rw-r--r--mesalib/src/mesa/main/texobj.c4
-rw-r--r--mesalib/src/mesa/main/texparam.c4
-rw-r--r--mesalib/src/mesa/main/texstate.c297
-rw-r--r--mesalib/src/mesa/state_tracker/st_atom.c1
-rw-r--r--mesalib/src/mesa/state_tracker/st_atom.h1
-rw-r--r--mesalib/src/mesa/state_tracker/st_atom_framebuffer.c15
-rw-r--r--mesalib/src/mesa/state_tracker/st_atom_msaa.c23
-rw-r--r--mesalib/src/mesa/state_tracker/st_atom_pixeltransfer.c2
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_clear.c3
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_drawtex.c6
-rw-r--r--mesalib/src/mesa/state_tracker/st_extensions.c3
-rw-r--r--mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp91
-rw-r--r--mesalib/src/mesa/state_tracker/st_manager.c11
-rw-r--r--mesalib/src/mesa/state_tracker/st_program.c21
-rw-r--r--mesalib/src/mesa/swrast/s_context.c8
-rw-r--r--mesalib/src/mesa/swrast/s_texcombine.c10
-rw-r--r--mesalib/src/mesa/swrast/s_texture.c66
-rw-r--r--mesalib/src/mesa/swrast/s_triangle.c4
-rw-r--r--mesalib/src/mesa/swrast_setup/ss_context.c3
44 files changed, 1386 insertions, 1009 deletions
diff --git a/mesalib/src/gallium/auxiliary/hud/hud_context.c b/mesalib/src/gallium/auxiliary/hud/hud_context.c
index ccf020bed..b6e018423 100644
--- a/mesalib/src/gallium/auxiliary/hud/hud_context.c
+++ b/mesalib/src/gallium/auxiliary/hud/hud_context.c
@@ -412,6 +412,7 @@ hud_draw(struct hud_context *hud, struct pipe_resource *tex)
cso_save_framebuffer(cso);
cso_save_sample_mask(cso);
+ cso_save_min_samples(cso);
cso_save_blend(cso);
cso_save_depth_stencil_alpha(cso);
cso_save_fragment_shader(cso);
@@ -450,6 +451,7 @@ hud_draw(struct hud_context *hud, struct pipe_resource *tex)
cso_set_framebuffer(cso, &fb);
cso_set_sample_mask(cso, ~0);
+ cso_set_min_samples(cso, 1);
cso_set_blend(cso, &hud->alpha_blend);
cso_set_depth_stencil_alpha(cso, &hud->dsa);
cso_set_rasterizer(cso, &hud->rasterizer);
@@ -538,6 +540,7 @@ hud_draw(struct hud_context *hud, struct pipe_resource *tex)
/* restore states */
cso_restore_framebuffer(cso);
cso_restore_sample_mask(cso);
+ cso_restore_min_samples(cso);
cso_restore_blend(cso);
cso_restore_depth_stencil_alpha(cso);
cso_restore_fragment_shader(cso);
diff --git a/mesalib/src/gallium/auxiliary/util/u_blit.c b/mesalib/src/gallium/auxiliary/util/u_blit.c
index 4b25b93dd..f69b4b1ab 100644
--- a/mesalib/src/gallium/auxiliary/util/u_blit.c
+++ b/mesalib/src/gallium/auxiliary/util/u_blit.c
@@ -520,6 +520,7 @@ util_blit_pixels_tex(struct blit_state *ctx,
cso_save_depth_stencil_alpha(ctx->cso);
cso_save_rasterizer(ctx->cso);
cso_save_sample_mask(ctx->cso);
+ cso_save_min_samples(ctx->cso);
cso_save_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
cso_save_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
cso_save_stream_outputs(ctx->cso);
@@ -535,6 +536,7 @@ util_blit_pixels_tex(struct blit_state *ctx,
cso_set_blend(ctx->cso, &ctx->blend_write_color);
cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_keep_depthstencil);
cso_set_sample_mask(ctx->cso, ~0);
+ cso_set_min_samples(ctx->cso, 1);
cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
cso_set_stream_outputs(ctx->cso, 0, NULL, NULL);
@@ -597,6 +599,7 @@ util_blit_pixels_tex(struct blit_state *ctx,
cso_restore_depth_stencil_alpha(ctx->cso);
cso_restore_rasterizer(ctx->cso);
cso_restore_sample_mask(ctx->cso);
+ cso_restore_min_samples(ctx->cso);
cso_restore_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
cso_restore_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
cso_restore_viewport(ctx->cso);
diff --git a/mesalib/src/gallium/auxiliary/util/u_format_pack.py b/mesalib/src/gallium/auxiliary/util/u_format_pack.py
index 8072fdb13..f9496de6c 100644
--- a/mesalib/src/gallium/auxiliary/util/u_format_pack.py
+++ b/mesalib/src/gallium/auxiliary/util/u_format_pack.py
@@ -40,24 +40,33 @@
from u_format_parse import *
+def inv_swizzles(swizzles):
+ '''Return an array[4] of inverse swizzle terms'''
+ '''Only pick the first matching value to avoid l8 getting blue and i8 getting alpha'''
+ inv_swizzle = [None]*4
+ for i in range(4):
+ swizzle = swizzles[i]
+ if swizzle < 4 and inv_swizzle[swizzle] == None:
+ inv_swizzle[swizzle] = i
+ return inv_swizzle
+
+def print_channels(format, func):
+ if format.nr_channels() <= 1:
+ func(format.le_channels, format.le_swizzles)
+ else:
+ print '#ifdef PIPE_ARCH_BIG_ENDIAN'
+ func(format.be_channels, format.be_swizzles)
+ print '#else'
+ func(format.le_channels, format.le_swizzles)
+ print '#endif'
+
def generate_format_type(format):
'''Generate a structure that describes the format.'''
assert format.layout == PLAIN
- print 'union util_format_%s {' % format.short_name()
-
- if format.block_size() in (8, 16, 32, 64):
- print ' uint%u_t value;' % (format.block_size(),)
-
- use_bitfields = False
- for channel in format.channels:
- if channel.size % 8 or not is_pot(channel.size):
- use_bitfields = True
-
- print ' struct {'
- for channel in format.channels:
- if use_bitfields:
+ def generate_bitfields(channels, swizzles):
+ for channel in channels:
if channel.type == VOID:
if channel.size:
print ' unsigned %s:%u;' % (channel.name, channel.size)
@@ -74,7 +83,9 @@ def generate_format_type(format):
print ' unsigned %s:%u;' % (channel.name, channel.size)
else:
assert 0
- else:
+
+ def generate_full_fields(channels, swizzles):
+ for channel in channels:
assert channel.size % 8 == 0 and is_pot(channel.size)
if channel.type == VOID:
if channel.size:
@@ -94,6 +105,22 @@ def generate_format_type(format):
assert 0
else:
assert 0
+
+ print 'union util_format_%s {' % format.short_name()
+
+ if format.block_size() in (8, 16, 32, 64):
+ print ' uint%u_t value;' % (format.block_size(),)
+
+ use_bitfields = False
+ for channel in format.le_channels:
+ if channel.size % 8 or not is_pot(channel.size):
+ use_bitfields = True
+
+ print ' struct {'
+ if use_bitfields:
+ print_channels(format, generate_bitfields)
+ else:
+ print_channels(format, generate_full_fields)
print ' } chan;'
print '};'
print
@@ -109,7 +136,7 @@ def is_format_supported(format):
return False
for i in range(4):
- channel = format.channels[i]
+ channel = format.le_channels[i]
if channel.type not in (VOID, UNSIGNED, SIGNED, FLOAT, FIXED):
return False
if channel.type == FLOAT and channel.size not in (16, 32, 64):
@@ -117,27 +144,6 @@ def is_format_supported(format):
return True
-def is_format_pure_unsigned(format):
- for i in range(4):
- channel = format.channels[i]
- if channel.type not in (VOID, UNSIGNED):
- return False
- if channel.type == UNSIGNED and channel.pure == False:
- return False
-
- return True
-
-
-def is_format_pure_signed(format):
- for i in range(4):
- channel = format.channels[i]
- if channel.type not in (VOID, SIGNED):
- return False
- if channel.type == SIGNED and channel.pure == False:
- return False
-
- return True
-
def native_type(format):
'''Get the native appropriate for a format.'''
@@ -152,7 +158,7 @@ def native_type(format):
return 'uint%u_t' % format.block_size()
else:
# For array pixel formats return the integer type that matches the color channel
- channel = format.channels[0]
+ channel = format.array_element()
if channel.type in (UNSIGNED, VOID):
return 'uint%u_t' % channel.size
elif channel.type in (SIGNED, FIXED):
@@ -410,13 +416,13 @@ def generate_unpack_kernel(format, dst_channel, dst_native_type):
src_native_type = native_type(format)
- if format.is_bitmask():
+ def unpack_from_bitmask(channels, swizzles):
depth = format.block_size()
print ' uint%u_t value = *(const uint%u_t *)src;' % (depth, depth)
# Declare the intermediate variables
for i in range(format.nr_channels()):
- src_channel = format.channels[i]
+ src_channel = channels[i]
if src_channel.type == UNSIGNED:
print ' uint%u_t %s;' % (depth, src_channel.name)
elif src_channel.type == SIGNED:
@@ -424,7 +430,7 @@ def generate_unpack_kernel(format, dst_channel, dst_native_type):
# Compute the intermediate unshifted values
for i in range(format.nr_channels()):
- src_channel = format.channels[i]
+ src_channel = channels[i]
value = 'value'
shift = src_channel.shift
if src_channel.type == UNSIGNED:
@@ -451,9 +457,9 @@ def generate_unpack_kernel(format, dst_channel, dst_native_type):
# Convert, swizzle, and store final values
for i in range(4):
- swizzle = format.swizzles[i]
+ swizzle = swizzles[i]
if swizzle < 4:
- src_channel = format.channels[swizzle]
+ src_channel = channels[swizzle]
src_colorspace = format.colorspace
if src_colorspace == SRGB and i == 3:
# Alpha channel is linear
@@ -473,14 +479,14 @@ def generate_unpack_kernel(format, dst_channel, dst_native_type):
assert False
print ' dst[%u] = %s; /* %s */' % (i, value, 'rgba'[i])
- else:
+ def unpack_from_union(channels, swizzles):
print ' union util_format_%s pixel;' % format.short_name()
print ' memcpy(&pixel, src, sizeof pixel);'
for i in range(4):
- swizzle = format.swizzles[i]
+ swizzle = swizzles[i]
if swizzle < 4:
- src_channel = format.channels[swizzle]
+ src_channel = channels[swizzle]
src_colorspace = format.colorspace
if src_colorspace == SRGB and i == 3:
# Alpha channel is linear
@@ -500,6 +506,11 @@ def generate_unpack_kernel(format, dst_channel, dst_native_type):
assert False
print ' dst[%u] = %s; /* %s */' % (i, value, 'rgba'[i])
+ if format.is_bitmask():
+ print_channels(format, unpack_from_bitmask)
+ else:
+ print_channels(format, unpack_from_union)
+
def generate_pack_kernel(format, src_channel, src_native_type):
@@ -510,14 +521,14 @@ def generate_pack_kernel(format, src_channel, src_native_type):
assert format.layout == PLAIN
- inv_swizzle = format.inv_swizzles()
+ def pack_into_bitmask(channels, swizzles):
+ inv_swizzle = inv_swizzles(swizzles)
- if format.is_bitmask():
depth = format.block_size()
print ' uint%u_t value = 0;' % depth
for i in range(4):
- dst_channel = format.channels[i]
+ dst_channel = channels[i]
shift = dst_channel.shift
if inv_swizzle[i] is not None:
value ='src[%u]' % inv_swizzle[i]
@@ -544,11 +555,13 @@ def generate_pack_kernel(format, src_channel, src_native_type):
print ' *(uint%u_t *)dst = value;' % depth
- else:
+ def pack_into_union(channels, swizzles):
+ inv_swizzle = inv_swizzles(swizzles)
+
print ' union util_format_%s pixel;' % format.short_name()
for i in range(4):
- dst_channel = format.channels[i]
+ dst_channel = channels[i]
width = dst_channel.size
if inv_swizzle[i] is None:
continue
@@ -565,6 +578,11 @@ def generate_pack_kernel(format, src_channel, src_native_type):
print ' memcpy(dst, &pixel, sizeof pixel);'
+ if format.is_bitmask():
+ print_channels(format, pack_into_bitmask)
+ else:
+ print_channels(format, pack_into_union)
+
def generate_format_unpack(format, dst_channel, dst_native_type, dst_suffix):
'''Generate the function to unpack pixels from a particular format'''
@@ -662,7 +680,7 @@ def generate(formats):
if is_format_supported(format):
generate_format_type(format)
- if is_format_pure_unsigned(format):
+ if format.is_pure_unsigned():
native_type = 'unsigned'
suffix = 'unsigned'
channel = Channel(UNSIGNED, False, True, 32)
@@ -676,7 +694,7 @@ def generate(formats):
suffix = 'signed'
generate_format_unpack(format, channel, native_type, suffix)
generate_format_pack(format, channel, native_type, suffix)
- elif is_format_pure_signed(format):
+ elif format.is_pure_signed():
native_type = 'int'
suffix = 'signed'
channel = Channel(SIGNED, False, True, 32)
diff --git a/mesalib/src/gallium/auxiliary/util/u_format_parse.py b/mesalib/src/gallium/auxiliary/util/u_format_parse.py
index e202099b9..15cc6d4fe 100644
--- a/mesalib/src/gallium/auxiliary/util/u_format_parse.py
+++ b/mesalib/src/gallium/auxiliary/util/u_format_parse.py
@@ -30,8 +30,6 @@
'''
-import sys
-
VOID, UNSIGNED, SIGNED, FIXED, FLOAT = range(5)
SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W, SWIZZLE_0, SWIZZLE_1, SWIZZLE_NONE, = range(7)
@@ -44,9 +42,6 @@ YUV = 'yuv'
ZS = 'zs'
-# Not cross-compiler friendly
-is_big_endian = sys.byteorder == 'big'
-
def is_pot(x):
return (x & (x - 1)) == 0
@@ -109,13 +104,15 @@ class Channel:
class Format:
'''Describe a pixel format.'''
- def __init__(self, name, layout, block_width, block_height, channels, swizzles, colorspace):
+ def __init__(self, name, layout, block_width, block_height, le_channels, le_swizzles, be_channels, be_swizzles, colorspace):
self.name = name
self.layout = layout
self.block_width = block_width
self.block_height = block_height
- self.channels = channels
- self.swizzles = swizzles
+ self.le_channels = le_channels
+ self.le_swizzles = le_swizzles
+ self.be_channels = be_channels
+ self.be_swizzles = be_swizzles
self.name = name
self.colorspace = colorspace
@@ -134,42 +131,45 @@ class Format:
def block_size(self):
size = 0
- for channel in self.channels:
+ for channel in self.le_channels:
size += channel.size
return size
def nr_channels(self):
nr_channels = 0
- for channel in self.channels:
+ for channel in self.le_channels:
if channel.size:
nr_channels += 1
return nr_channels
- def is_array(self):
+ def array_element(self):
if self.layout != PLAIN:
- return False
- ref_channel = self.channels[0]
+ return None
+ ref_channel = self.le_channels[0]
if ref_channel.type == VOID:
- ref_channel = self.channels[1]
- for channel in self.channels:
+ ref_channel = self.le_channels[1]
+ for channel in self.le_channels:
if channel.size and (channel.size != ref_channel.size or channel.size % 8):
- return False
+ return None
if channel.type != VOID:
if channel.type != ref_channel.type:
- return False
+ return None
if channel.norm != ref_channel.norm:
- return False
+ return None
if channel.pure != ref_channel.pure:
- return False
- return True
+ return None
+ return ref_channel
+
+ def is_array(self):
+ return self.array_element() != None
def is_mixed(self):
if self.layout != PLAIN:
return False
- ref_channel = self.channels[0]
+ ref_channel = self.le_channels[0]
if ref_channel.type == VOID:
- ref_channel = self.channels[1]
- for channel in self.channels[1:]:
+ ref_channel = self.le_channels[1]
+ for channel in self.le_channels[1:]:
if channel.type != VOID:
if channel.type != ref_channel.type:
return True
@@ -185,7 +185,7 @@ class Format:
def is_int(self):
if self.layout != PLAIN:
return False
- for channel in self.channels:
+ for channel in self.le_channels:
if channel.type not in (VOID, UNSIGNED, SIGNED):
return False
return True
@@ -193,7 +193,7 @@ class Format:
def is_float(self):
if self.layout != PLAIN:
return False
- for channel in self.channels:
+ for channel in self.le_channels:
if channel.type not in (VOID, FLOAT):
return False
return True
@@ -203,20 +203,43 @@ class Format:
return False
if self.block_size() not in (8, 16, 32):
return False
- for channel in self.channels:
+ for channel in self.le_channels:
if channel.type not in (VOID, UNSIGNED, SIGNED):
return False
return True
- def inv_swizzles(self):
- '''Return an array[4] of inverse swizzle terms'''
- '''Only pick the first matching value to avoid l8 getting blue and i8 getting alpha'''
- inv_swizzle = [None]*4
- for i in range(4):
- swizzle = self.swizzles[i]
- if swizzle < 4 and inv_swizzle[swizzle] == None:
- inv_swizzle[swizzle] = i
- return inv_swizzle
+ def is_pure_color(self):
+ if self.layout != PLAIN or self.colorspace == ZS:
+ return False
+ pures = [channel.pure
+ for channel in self.le_channels
+ if channel.type != VOID]
+ for x in pures:
+ assert x == pures[0]
+ return pures[0]
+
+ def channel_type(self):
+ types = [channel.type
+ for channel in self.le_channels
+ if channel.type != VOID]
+ for x in types:
+ assert x == types[0]
+ return types[0]
+
+ def is_pure_signed(self):
+ return self.is_pure_color() and self.channel_type() == SIGNED
+
+ def is_pure_unsigned(self):
+ return self.is_pure_color() and self.channel_type() == UNSIGNED
+
+ def has_channel(self, id):
+ return self.le_swizzles[id] != SWIZZLE_NONE
+
+ def has_depth(self):
+ return self.colorspace == ZS and self.has_channel(0)
+
+ def has_stencil(self):
+ return self.colorspace == ZS and self.has_channel(1)
def stride(self):
return self.block_size()/8
@@ -241,6 +264,54 @@ _swizzle_parse_map = {
'_': SWIZZLE_NONE,
}
+def _parse_channels(fields, layout, colorspace, swizzles):
+ if layout == PLAIN:
+ names = ['']*4
+ if colorspace in (RGB, SRGB):
+ for i in range(4):
+ swizzle = swizzles[i]
+ if swizzle < 4:
+ names[swizzle] += 'rgba'[i]
+ elif colorspace == ZS:
+ for i in range(4):
+ swizzle = swizzles[i]
+ if swizzle < 4:
+ names[swizzle] += 'zs'[i]
+ else:
+ assert False
+ for i in range(4):
+ if names[i] == '':
+ names[i] = 'x'
+ else:
+ names = ['x', 'y', 'z', 'w']
+
+ channels = []
+ for i in range(0, 4):
+ field = fields[i]
+ if field:
+ type = _type_parse_map[field[0]]
+ if field[1] == 'n':
+ norm = True
+ pure = False
+ size = int(field[2:])
+ elif field[1] == 'p':
+ pure = True
+ norm = False
+ size = int(field[2:])
+ else:
+ norm = False
+ pure = False
+ size = int(field[1:])
+ else:
+ type = VOID
+ norm = False
+ pure = False
+ size = 0
+ channel = Channel(type, norm, pure, size, names[i])
+ channels.append(channel)
+
+ return channels
+
def parse(filename):
'''Parse the format descrition in CSV format in terms of the
Channel and Format classes above.'''
@@ -263,61 +334,27 @@ def parse(filename):
name = fields[0]
layout = fields[1]
block_width, block_height = map(int, fields[2:4])
-
- swizzles = [_swizzle_parse_map[swizzle] for swizzle in fields[8]]
colorspace = fields[9]
-
- if layout == PLAIN:
- names = ['']*4
- if colorspace in (RGB, SRGB):
- for i in range(4):
- swizzle = swizzles[i]
- if swizzle < 4:
- names[swizzle] += 'rgba'[i]
- elif colorspace == ZS:
- for i in range(4):
- swizzle = swizzles[i]
- if swizzle < 4:
- names[swizzle] += 'zs'[i]
- else:
- assert False
- for i in range(4):
- if names[i] == '':
- names[i] = 'x'
- else:
- names = ['x', 'y', 'z', 'w']
-
- channels = []
- for i in range(0, 4):
- field = fields[4 + i]
- if field:
- type = _type_parse_map[field[0]]
- if field[1] == 'n':
- norm = True
- pure = False
- size = int(field[2:])
- elif field[1] == 'p':
- pure = True
- norm = False
- size = int(field[2:])
- else:
- norm = False
- pure = False
- size = int(field[1:])
- else:
- type = VOID
- norm = False
- pure = False
- size = 0
- channel = Channel(type, norm, pure, size, names[i])
- channels.append(channel)
- shift = 0
- for channel in channels[3::-1] if is_big_endian else channels:
- channel.shift = shift
- shift += channel.size
+ le_swizzles = [_swizzle_parse_map[swizzle] for swizzle in fields[8]]
+ le_channels = _parse_channels(fields[4:8], layout, colorspace, le_swizzles)
+
+ be_swizzles = [_swizzle_parse_map[swizzle] for swizzle in fields[8]]
+ be_channels = _parse_channels(fields[4:8], layout, colorspace, be_swizzles)
+
+ le_shift = 0
+ for channel in le_channels:
+ channel.shift = le_shift
+ le_shift += channel.size
+
+ be_shift = 0
+ for channel in be_channels[3::-1]:
+ channel.shift = be_shift
+ be_shift += channel.size
+
+ assert le_shift == be_shift
- format = Format(name, layout, block_width, block_height, channels, swizzles, colorspace)
+ format = Format(name, layout, block_width, block_height, le_channels, le_swizzles, be_channels, be_swizzles, colorspace)
formats.append(format)
return formats
diff --git a/mesalib/src/gallium/auxiliary/util/u_format_table.py b/mesalib/src/gallium/auxiliary/util/u_format_table.py
index 9d44cf391..81fd3996f 100644
--- a/mesalib/src/gallium/auxiliary/util/u_format_table.py
+++ b/mesalib/src/gallium/auxiliary/util/u_format_table.py
@@ -94,21 +94,10 @@ def write_format_table(formats):
u_format_pack.generate(formats)
- for format in formats:
- print 'const struct util_format_description'
- print 'util_format_%s_description = {' % (format.short_name(),)
- print " %s," % (format.name,)
- print " \"%s\"," % (format.name,)
- print " \"%s\"," % (format.short_name(),)
- print " {%u, %u, %u},\t/* block */" % (format.block_width, format.block_height, format.block_size())
- print " %s," % (layout_map(format.layout),)
- print " %u,\t/* nr_channels */" % (format.nr_channels(),)
- print " %s,\t/* is_array */" % (bool_map(format.is_array()),)
- print " %s,\t/* is_bitmask */" % (bool_map(format.is_bitmask()),)
- print " %s,\t/* is_mixed */" % (bool_map(format.is_mixed()),)
+ def do_channel_array(channels, swizzles):
print " {"
for i in range(4):
- channel = format.channels[i]
+ channel = channels[i]
if i < 3:
sep = ","
else:
@@ -118,9 +107,11 @@ def write_format_table(formats):
else:
print " {0, 0, 0, 0, 0}%s" % (sep,)
print " },"
+
+ def do_swizzle_array(channels, swizzles):
print " {"
for i in range(4):
- swizzle = format.swizzles[i]
+ swizzle = swizzles[i]
if i < 3:
sep = ","
else:
@@ -131,8 +122,23 @@ def write_format_table(formats):
comment = 'ignored'
print " %s%s\t/* %s */" % (swizzle_map[swizzle], sep, comment)
print " },"
+
+ for format in formats:
+ print 'const struct util_format_description'
+ print 'util_format_%s_description = {' % (format.short_name(),)
+ print " %s," % (format.name,)
+ print " \"%s\"," % (format.name,)
+ print " \"%s\"," % (format.short_name(),)
+ print " {%u, %u, %u},\t/* block */" % (format.block_width, format.block_height, format.block_size())
+ print " %s," % (layout_map(format.layout),)
+ print " %u,\t/* nr_channels */" % (format.nr_channels(),)
+ print " %s,\t/* is_array */" % (bool_map(format.is_array()),)
+ print " %s,\t/* is_bitmask */" % (bool_map(format.is_bitmask()),)
+ print " %s,\t/* is_mixed */" % (bool_map(format.is_mixed()),)
+ u_format_pack.print_channels(format, do_channel_array)
+ u_format_pack.print_channels(format, do_swizzle_array)
print " %s," % (colorspace_map(format.colorspace),)
- if format.colorspace != ZS and format.channels[0].pure == False:
+ if format.colorspace != ZS and not format.is_pure_color():
print " &util_format_%s_unpack_rgba_8unorm," % format.short_name()
print " &util_format_%s_pack_rgba_8unorm," % format.short_name()
if format.layout == 's3tc' or format.layout == 'rgtc':
@@ -149,7 +155,7 @@ def write_format_table(formats):
print " NULL, /* unpack_rgba_float */"
print " NULL, /* pack_rgba_float */"
print " NULL, /* fetch_rgba_float */"
- if format.colorspace == ZS and format.swizzles[0] != SWIZZLE_NONE:
+ if format.has_depth():
print " &util_format_%s_unpack_z_32unorm," % format.short_name()
print " &util_format_%s_pack_z_32unorm," % format.short_name()
print " &util_format_%s_unpack_z_float," % format.short_name()
@@ -159,20 +165,20 @@ def write_format_table(formats):
print " NULL, /* pack_z_32unorm */"
print " NULL, /* unpack_z_float */"
print " NULL, /* pack_z_float */"
- if format.colorspace == ZS and format.swizzles[1] != SWIZZLE_NONE:
+ if format.has_stencil():
print " &util_format_%s_unpack_s_8uint," % format.short_name()
print " &util_format_%s_pack_s_8uint," % format.short_name()
else:
print " NULL, /* unpack_s_8uint */"
print " NULL, /* pack_s_8uint */"
- if format.colorspace != ZS and format.channels[0].pure == True and format.channels[0].type == UNSIGNED:
+ if format.is_pure_unsigned():
print " &util_format_%s_unpack_unsigned, /* unpack_rgba_uint */" % format.short_name()
print " &util_format_%s_pack_unsigned, /* pack_rgba_uint */" % format.short_name()
print " &util_format_%s_unpack_signed, /* unpack_rgba_sint */" % format.short_name()
print " &util_format_%s_pack_signed, /* pack_rgba_sint */" % format.short_name()
print " &util_format_%s_fetch_unsigned, /* fetch_rgba_uint */" % format.short_name()
print " NULL /* fetch_rgba_sint */"
- elif format.colorspace != ZS and format.channels[0].pure == True and format.channels[0].type == SIGNED:
+ elif format.is_pure_signed():
print " &util_format_%s_unpack_unsigned, /* unpack_rgba_uint */" % format.short_name()
print " &util_format_%s_pack_unsigned, /* pack_rgba_uint */" % format.short_name()
print " &util_format_%s_unpack_signed, /* unpack_rgba_sint */" % format.short_name()
diff --git a/mesalib/src/gallium/auxiliary/util/u_math.h b/mesalib/src/gallium/auxiliary/util/u_math.h
index ec03e4e58..a60e1830a 100644
--- a/mesalib/src/gallium/auxiliary/util/u_math.h
+++ b/mesalib/src/gallium/auxiliary/util/u_math.h
@@ -567,6 +567,22 @@ static INLINE unsigned util_last_bit(unsigned u)
#endif
}
+/**
+ * Find last bit in a word that does not match the sign bit. The least
+ * significant bit is 1.
+ * Return 0 if no bits are set.
+ */
+static INLINE unsigned util_last_bit_signed(int i)
+{
+#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 407)
+ return 31 - __builtin_clrsb(i);
+#else
+ if (i >= 0)
+ return util_last_bit(i);
+ else
+ return util_last_bit(~(unsigned)i);
+#endif
+}
/* Destructively loop over all of the bits in a mask as in:
*
@@ -715,6 +731,21 @@ util_bitcount(unsigned n)
#endif
}
+/**
+ * Reverse bits in n
+ * Algorithm taken from:
+ * http://stackoverflow.com/questions/9144800/c-reverse-bits-in-unsigned-integer
+ */
+static INLINE unsigned
+util_bitreverse(unsigned n)
+{
+ n = ((n >> 1) & 0x55555555u) | ((n & 0x55555555u) << 1);
+ n = ((n >> 2) & 0x33333333u) | ((n & 0x33333333u) << 2);
+ n = ((n >> 4) & 0x0f0f0f0fu) | ((n & 0x0f0f0f0fu) << 4);
+ n = ((n >> 8) & 0x00ff00ffu) | ((n & 0x00ff00ffu) << 8);
+ n = ((n >> 16) & 0xffffu) | ((n & 0xffffu) << 16);
+ return n;
+}
/**
* Convert from little endian to CPU byte order.
diff --git a/mesalib/src/gallium/auxiliary/util/u_pack_color.h b/mesalib/src/gallium/auxiliary/util/u_pack_color.h
index 166c68b57..e0c9018f8 100644
--- a/mesalib/src/gallium/auxiliary/util/u_pack_color.h
+++ b/mesalib/src/gallium/auxiliary/util/u_pack_color.h
@@ -51,7 +51,7 @@
union util_color {
ubyte ub;
ushort us;
- uint ui;
+ uint ui[4];
ushort h[4]; /* half float */
float f[4];
double d[4];
@@ -67,32 +67,32 @@ util_pack_color_ub(ubyte r, ubyte g, ubyte b, ubyte a,
switch (format) {
case PIPE_FORMAT_ABGR8888_UNORM:
{
- uc->ui = (r << 24) | (g << 16) | (b << 8) | a;
+ uc->ui[0] = (r << 24) | (g << 16) | (b << 8) | a;
}
return;
case PIPE_FORMAT_XBGR8888_UNORM:
{
- uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff;
+ uc->ui[0] = (r << 24) | (g << 16) | (b << 8) | 0xff;
}
return;
case PIPE_FORMAT_BGRA8888_UNORM:
{
- uc->ui = (a << 24) | (r << 16) | (g << 8) | b;
+ uc->ui[0] = (a << 24) | (r << 16) | (g << 8) | b;
}
return;
case PIPE_FORMAT_BGRX8888_UNORM:
{
- uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b;
+ uc->ui[0] = (0xff << 24) | (r << 16) | (g << 8) | b;
}
return;
case PIPE_FORMAT_ARGB8888_UNORM:
{
- uc->ui = (b << 24) | (g << 16) | (r << 8) | a;
+ uc->ui[0] = (b << 24) | (g << 16) | (r << 8) | a;
}
return;
case PIPE_FORMAT_XRGB8888_UNORM:
{
- uc->ui = (b << 24) | (g << 16) | (r << 8) | 0xff;
+ uc->ui[0] = (b << 24) | (g << 16) | (r << 8) | 0xff;
}
return;
case PIPE_FORMAT_B5G6R5_UNORM:
@@ -168,7 +168,7 @@ util_unpack_color_ub(enum pipe_format format, union util_color *uc,
switch (format) {
case PIPE_FORMAT_ABGR8888_UNORM:
{
- uint p = uc->ui;
+ uint p = uc->ui[0];
*r = (ubyte) ((p >> 24) & 0xff);
*g = (ubyte) ((p >> 16) & 0xff);
*b = (ubyte) ((p >> 8) & 0xff);
@@ -177,7 +177,7 @@ util_unpack_color_ub(enum pipe_format format, union util_color *uc,
return;
case PIPE_FORMAT_XBGR8888_UNORM:
{
- uint p = uc->ui;
+ uint p = uc->ui[0];
*r = (ubyte) ((p >> 24) & 0xff);
*g = (ubyte) ((p >> 16) & 0xff);
*b = (ubyte) ((p >> 8) & 0xff);
@@ -186,7 +186,7 @@ util_unpack_color_ub(enum pipe_format format, union util_color *uc,
return;
case PIPE_FORMAT_BGRA8888_UNORM:
{
- uint p = uc->ui;
+ uint p = uc->ui[0];
*r = (ubyte) ((p >> 16) & 0xff);
*g = (ubyte) ((p >> 8) & 0xff);
*b = (ubyte) ((p >> 0) & 0xff);
@@ -195,7 +195,7 @@ util_unpack_color_ub(enum pipe_format format, union util_color *uc,
return;
case PIPE_FORMAT_BGRX8888_UNORM:
{
- uint p = uc->ui;
+ uint p = uc->ui[0];
*r = (ubyte) ((p >> 16) & 0xff);
*g = (ubyte) ((p >> 8) & 0xff);
*b = (ubyte) ((p >> 0) & 0xff);
@@ -204,7 +204,7 @@ util_unpack_color_ub(enum pipe_format format, union util_color *uc,
return;
case PIPE_FORMAT_ARGB8888_UNORM:
{
- uint p = uc->ui;
+ uint p = uc->ui[0];
*r = (ubyte) ((p >> 8) & 0xff);
*g = (ubyte) ((p >> 16) & 0xff);
*b = (ubyte) ((p >> 24) & 0xff);
@@ -213,7 +213,7 @@ util_unpack_color_ub(enum pipe_format format, union util_color *uc,
return;
case PIPE_FORMAT_XRGB8888_UNORM:
{
- uint p = uc->ui;
+ uint p = uc->ui[0];
*r = (ubyte) ((p >> 8) & 0xff);
*g = (ubyte) ((p >> 16) & 0xff);
*b = (ubyte) ((p >> 24) & 0xff);
@@ -352,32 +352,32 @@ util_pack_color(const float rgba[4], enum pipe_format format, union util_color *
switch (format) {
case PIPE_FORMAT_ABGR8888_UNORM:
{
- uc->ui = (r << 24) | (g << 16) | (b << 8) | a;
+ uc->ui[0] = (r << 24) | (g << 16) | (b << 8) | a;
}
return;
case PIPE_FORMAT_XBGR8888_UNORM:
{
- uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff;
+ uc->ui[0] = (r << 24) | (g << 16) | (b << 8) | 0xff;
}
return;
case PIPE_FORMAT_BGRA8888_UNORM:
{
- uc->ui = (a << 24) | (r << 16) | (g << 8) | b;
+ uc->ui[0] = (a << 24) | (r << 16) | (g << 8) | b;
}
return;
case PIPE_FORMAT_BGRX8888_UNORM:
{
- uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b;
+ uc->ui[0] = (0xff << 24) | (r << 16) | (g << 8) | b;
}
return;
case PIPE_FORMAT_ARGB8888_UNORM:
{
- uc->ui = (b << 24) | (g << 16) | (r << 8) | a;
+ uc->ui[0] = (b << 24) | (g << 16) | (r << 8) | a;
}
return;
case PIPE_FORMAT_XRGB8888_UNORM:
{
- uc->ui = (b << 24) | (g << 16) | (r << 8) | 0xff;
+ uc->ui[0] = (b << 24) | (g << 16) | (r << 8) | 0xff;
}
return;
case PIPE_FORMAT_B5G6R5_UNORM:
diff --git a/mesalib/src/gallium/auxiliary/util/u_surface.c b/mesalib/src/gallium/auxiliary/util/u_surface.c
index 07997d2ad..654b5bbc5 100644
--- a/mesalib/src/gallium/auxiliary/util/u_surface.c
+++ b/mesalib/src/gallium/auxiliary/util/u_surface.c
@@ -196,7 +196,7 @@ util_fill_rect(ubyte * dst,
for (i = 0; i < height; i++) {
uint32_t *row = (uint32_t *)dst;
for (j = 0; j < width; j++)
- *row++ = uc->ui;
+ *row++ = uc->ui[0];
dst += dst_stride;
}
break;
diff --git a/mesalib/src/glsl/glsl_types.h b/mesalib/src/glsl/glsl_types.h
index ae3829f30..dca5492ac 100644
--- a/mesalib/src/glsl/glsl_types.h
+++ b/mesalib/src/glsl/glsl_types.h
@@ -180,7 +180,7 @@ struct glsl_type {
/**@}*/
/**
- * For numeric and boolean derrived types returns the basic scalar type
+ * For numeric and boolean derived types returns the basic scalar type
*
* If the type is a numeric or boolean scalar, vector, or matrix type,
* this function gets the scalar type of the individual components. For
diff --git a/mesalib/src/glsl/lower_instructions.cpp b/mesalib/src/glsl/lower_instructions.cpp
index 01ea0f01f..49316d002 100644
--- a/mesalib/src/glsl/lower_instructions.cpp
+++ b/mesalib/src/glsl/lower_instructions.cpp
@@ -359,8 +359,8 @@ lower_instructions_visitor::ldexp_to_arith(ir_expression *ir)
ir_constant *sign_mask = new(ir) ir_constant(0x80000000u, vec_elem);
- ir_constant *exp_shift = new(ir) ir_constant(23u, vec_elem);
- ir_constant *exp_width = new(ir) ir_constant(8u, vec_elem);
+ ir_constant *exp_shift = new(ir) ir_constant(23);
+ ir_constant *exp_width = new(ir) ir_constant(8);
/* Temporary variables */
ir_variable *x = new(ir) ir_variable(ir->type, "x", ir_var_temporary);
diff --git a/mesalib/src/mapi/Makefile.sources b/mesalib/src/mapi/Makefile.sources
index 37ca4842c..4ce1afb23 100644
--- a/mesalib/src/mapi/Makefile.sources
+++ b/mesalib/src/mapi/Makefile.sources
@@ -32,6 +32,7 @@ MAPI_BRIDGE_FILES = \
$(TOP)/src/mapi/mapi_tmp.h
MAPI_FILES = \
+ $(TOP)/src/mapi/entry.c \
$(TOP)/src/mapi/mapi.c \
$(TOP)/src/mapi/mapi.h \
$(TOP)/src/mapi/stub.c \
diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c
index ac27abba6..ab86f9c96 100644
--- a/mesalib/src/mesa/drivers/common/meta.c
+++ b/mesalib/src/mesa/drivers/common/meta.c
@@ -2328,7 +2328,7 @@ _mesa_meta_Bitmap(struct gl_context *ctx,
if (ctx->_ImageTransferState ||
ctx->FragmentProgram._Enabled ||
ctx->Fog.Enabled ||
- ctx->Texture._EnabledUnits ||
+ ctx->Texture._MaxEnabledTexImageUnit != -1 ||
width > tex->MaxSize ||
height > tex->MaxSize) {
_swrast_Bitmap(ctx, x, y, width, height, unpack, bitmap1);
@@ -3265,7 +3265,7 @@ _mesa_meta_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
GLfloat s, t, s1, t1;
GLuint tw, th;
- if (!ctx->Texture.Unit[i]._ReallyEnabled) {
+ if (!ctx->Texture.Unit[i]._Current) {
GLuint j;
for (j = 0; j < 4; j++) {
verts[j].st[i][0] = 0.0f;
diff --git a/mesalib/src/mesa/drivers/dri/common/SConscript b/mesalib/src/mesa/drivers/dri/common/SConscript
index 8b15532e3..41f6356c3 100644
--- a/mesalib/src/mesa/drivers/dri/common/SConscript
+++ b/mesalib/src/mesa/drivers/dri/common/SConscript
@@ -30,6 +30,7 @@ drienv.Replace(CPPPATH = [
driswenv = drienv.Clone()
driswenv.Append(CPPDEFINES = [
'__NOT_HAVE_DRM_H',
+ 'HAVE_DLADDR',
])
drienv.PkgUseModules('DRM')
diff --git a/mesalib/src/mesa/drivers/dri/common/dri_util.c b/mesalib/src/mesa/drivers/dri/common/dri_util.c
index 78cfcf536..bb07a9541 100644..100755
--- a/mesalib/src/mesa/drivers/dri/common/dri_util.c
+++ b/mesalib/src/mesa/drivers/dri/common/dri_util.c
@@ -453,10 +453,7 @@ driContextSetFlags(struct gl_context *ctx, uint32_t flags)
if ((flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0)
ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT;
if ((flags & __DRI_CTX_FLAG_DEBUG) != 0) {
- struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
- if (debug) {
- debug->DebugOutput = GL_TRUE;
- }
+ _mesa_set_debug_state_int(ctx, GL_DEBUG_OUTPUT, GL_TRUE);
ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_DEBUG_BIT;
}
}
@@ -782,7 +779,7 @@ const __DRIswrastExtension driSWRastExtension = {
};
const __DRI2configQueryExtension dri2ConfigQueryExtension = {
- /*.base =*/ { __DRI2_CONFIG_QUERY, __DRI2_CONFIG_QUERY_VERSION },
+ /*.base =*/ { __DRI2_CONFIG_QUERY, 1 },
/*.configQueryb =*/ dri2ConfigQueryb,
/*.configQueryi =*/ dri2ConfigQueryi,
diff --git a/mesalib/src/mesa/drivers/dri/common/dri_util.h b/mesalib/src/mesa/drivers/dri/common/dri_util.h
index a37a0bbbc..1138bf106 100644
--- a/mesalib/src/mesa/drivers/dri/common/dri_util.h
+++ b/mesalib/src/mesa/drivers/dri/common/dri_util.h
@@ -174,13 +174,13 @@ struct __DRIscreenRec {
struct {
/* Flag to indicate that this is a DRI2 screen. Many of the above
* fields will not be valid or initializaed in that case. */
- __DRIdri2LoaderExtension *loader;
- __DRIimageLookupExtension *image;
- __DRIuseInvalidateExtension *useInvalidate;
+ const __DRIdri2LoaderExtension *loader;
+ const __DRIimageLookupExtension *image;
+ const __DRIuseInvalidateExtension *useInvalidate;
} dri2;
struct {
- __DRIimageLoaderExtension *loader;
+ const __DRIimageLoaderExtension *loader;
} image;
driOptionCache optionInfo;
diff --git a/mesalib/src/mesa/drivers/dri/common/megadriver_stub.c b/mesalib/src/mesa/drivers/dri/common/megadriver_stub.c
index 4c3cc6776..f0c8878a8 100644
--- a/mesalib/src/mesa/drivers/dri/common/megadriver_stub.c
+++ b/mesalib/src/mesa/drivers/dri/common/megadriver_stub.c
@@ -28,10 +28,9 @@
/* We need GNU extensions to dlfcn.h in order to provide backward
* compatibility for the older DRI driver loader mechanism. (dladdr,
- * Dl_info, and RTLD_DEFAULT are only defined when _GNU_SOURCE is
- * defined.)
+ * Dl_info, and RTLD_DEFAULT)
*/
-#ifdef RTLD_DEFAULT
+#if defined(RTLD_DEFAULT) && defined(HAVE_DLADDR)
#define MEGADRIVER_STUB_MAX_EXTENSIONS 10
#define LIB_PATH_SUFFIX "_dri.so"
@@ -148,7 +147,7 @@ megadriver_stub_init(void)
}
}
-#endif /* RTLD_DEFAULT */
+#endif /* RTLD_DEFAULT && HAVE_DLADDR */
static const
__DRIconfig **stub_error_init_screen(__DRIscreen *psp)
diff --git a/mesalib/src/mesa/drivers/dri/swrast/swrast.c b/mesalib/src/mesa/drivers/dri/swrast/swrast.c
index 3d19a52dc..b9a5d71ef 100644
--- a/mesalib/src/mesa/drivers/dri/swrast/swrast.c
+++ b/mesalib/src/mesa/drivers/dri/swrast/swrast.c
@@ -115,9 +115,11 @@ static void swrastSetTexBuffer(__DRIcontext *pDRICtx, GLint target,
}
static const __DRItexBufferExtension swrastTexBufferExtension = {
- { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION },
- swrastSetTexBuffer,
- swrastSetTexBuffer2,
+ .base = { __DRI_TEX_BUFFER, 3 },
+
+ .setTexBuffer = swrastSetTexBuffer,
+ .setTexBuffer2 = swrastSetTexBuffer2,
+ .releaseTexBuffer = NULL,
};
static const __DRIextension *dri_screen_extensions[] = {
diff --git a/mesalib/src/mesa/main/enable.c b/mesalib/src/mesa/main/enable.c
index edd4751e1..0f3bcf0a9 100644
--- a/mesalib/src/mesa/main/enable.c
+++ b/mesalib/src/mesa/main/enable.c
@@ -368,26 +368,11 @@ _mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state)
ctx->Depth.Test = state;
break;
case GL_DEBUG_OUTPUT:
- if (!_mesa_is_desktop_gl(ctx)) {
- goto invalid_enum_error;
- }
- else {
- struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
- if (debug) {
- debug->DebugOutput = state;
- }
- }
- break;
case GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB:
- if (!_mesa_is_desktop_gl(ctx)) {
+ if (!_mesa_is_desktop_gl(ctx))
goto invalid_enum_error;
- }
- else {
- struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
- if (debug) {
- debug->SyncOutput = state;
- }
- }
+ else
+ _mesa_set_debug_state_int(ctx, cap, state);
break;
case GL_DITHER:
if (ctx->Color.DitherFlag == state)
@@ -1239,21 +1224,11 @@ _mesa_IsEnabled( GLenum cap )
case GL_CULL_FACE:
return ctx->Polygon.CullFlag;
case GL_DEBUG_OUTPUT:
- if (!_mesa_is_desktop_gl(ctx))
- goto invalid_enum_error;
- if (ctx->Debug) {
- return ctx->Debug->DebugOutput;
- } else {
- return GL_FALSE;
- }
case GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB:
if (!_mesa_is_desktop_gl(ctx))
goto invalid_enum_error;
- if (ctx->Debug) {
- return ctx->Debug->SyncOutput;
- } else {
- return GL_FALSE;
- }
+ else
+ return (GLboolean) _mesa_get_debug_state_int(ctx, cap);
case GL_DEPTH_TEST:
return ctx->Depth.Test;
case GL_DITHER:
diff --git a/mesalib/src/mesa/main/errors.c b/mesalib/src/mesa/main/errors.c
index d80fda0db..30a867298 100644
--- a/mesalib/src/mesa/main/errors.c
+++ b/mesalib/src/mesa/main/errors.c
@@ -41,10 +41,63 @@
static mtx_t DynamicIDMutex = _MTX_INITIALIZER_NP;
static GLuint NextDynamicID = 1;
-struct gl_debug_severity
+/**
+ * A namespace element.
+ */
+struct gl_debug_element
{
struct simple_node link;
+
GLuint ID;
+ /* at which severity levels (mesa_debug_severity) is the message enabled */
+ GLbitfield State;
+};
+
+struct gl_debug_namespace
+{
+ struct simple_node Elements;
+ GLbitfield DefaultState;
+};
+
+struct gl_debug_group {
+ struct gl_debug_namespace Namespaces[MESA_DEBUG_SOURCE_COUNT][MESA_DEBUG_TYPE_COUNT];
+};
+
+/**
+ * An error, warning, or other piece of debug information for an application
+ * to consume via GL_ARB_debug_output/GL_KHR_debug.
+ */
+struct gl_debug_message
+{
+ enum mesa_debug_source source;
+ enum mesa_debug_type type;
+ GLuint id;
+ enum mesa_debug_severity severity;
+ GLsizei length;
+ GLcharARB *message;
+};
+
+/**
+ * Debug message log. It works like a ring buffer.
+ */
+struct gl_debug_log {
+ struct gl_debug_message Messages[MAX_DEBUG_LOGGED_MESSAGES];
+ GLint NextMessage;
+ GLint NumMessages;
+};
+
+struct gl_debug_state
+{
+ GLDEBUGPROC Callback;
+ const void *CallbackData;
+ GLboolean SyncOutput;
+ GLboolean DebugOutput;
+
+ struct gl_debug_group *Groups[MAX_DEBUG_GROUP_STACK_DEPTH];
+ struct gl_debug_message GroupMessages[MAX_DEBUG_GROUP_STACK_DEPTH];
+ GLint GroupStackDepth;
+
+ struct gl_debug_log Log;
};
static char out_of_memory[] = "Debugging error: out of memory";
@@ -139,235 +192,399 @@ debug_get_id(GLuint *id)
}
}
+static void
+debug_message_clear(struct gl_debug_message *msg)
+{
+ if (msg->message != (char*)out_of_memory)
+ free(msg->message);
+ msg->message = NULL;
+ msg->length = 0;
+}
+
+static void
+debug_message_store(struct gl_debug_message *msg,
+ enum mesa_debug_source source,
+ enum mesa_debug_type type, GLuint id,
+ enum mesa_debug_severity severity,
+ GLsizei len, const char *buf)
+{
+ assert(!msg->message && !msg->length);
+
+ msg->message = malloc(len+1);
+ if (msg->message) {
+ (void) strncpy(msg->message, buf, (size_t)len);
+ msg->message[len] = '\0';
+
+ msg->length = len+1;
+ msg->source = source;
+ msg->type = type;
+ msg->id = id;
+ msg->severity = severity;
+ } else {
+ static GLuint oom_msg_id = 0;
+ debug_get_id(&oom_msg_id);
+
+ /* malloc failed! */
+ msg->message = out_of_memory;
+ msg->length = strlen(out_of_memory)+1;
+ msg->source = MESA_DEBUG_SOURCE_OTHER;
+ msg->type = MESA_DEBUG_TYPE_ERROR;
+ msg->id = oom_msg_id;
+ msg->severity = MESA_DEBUG_SEVERITY_HIGH;
+ }
+}
+
+static void
+debug_namespace_init(struct gl_debug_namespace *ns)
+{
+ make_empty_list(&ns->Elements);
-/*
- * We store a bitfield in the hash table, with five possible values total.
- *
- * The ENABLED_BIT's purpose is self-explanatory.
- *
- * The FOUND_BIT is needed to differentiate the value of DISABLED from
- * the value returned by HashTableLookup() when it can't find the given key.
- *
- * The KNOWN_SEVERITY bit is a bit complicated:
- *
- * A client may call Control() with an array of IDs, then call Control()
- * on all message IDs of a certain severity, then Insert() one of the
- * previously specified IDs, giving us a known severity level, then call
- * Control() on all message IDs of a certain severity level again.
- *
- * After the first call, those IDs will have a FOUND_BIT, but will not
- * exist in any severity-specific list, so the second call will not
- * impact them. This is undesirable but unavoidable given the API:
- * The only entrypoint that gives a severity for a client-defined ID
- * is the Insert() call.
- *
- * For the sake of Control(), we want to maintain the invariant
- * that an ID will either appear in none of the three severity lists,
- * or appear once, to minimize pointless duplication and potential surprises.
- *
- * Because Insert() is the only place that will learn an ID's severity,
- * it should insert an ID into the appropriate list, but only if the ID
- * doesn't exist in it or any other list yet. Because searching all three
- * lists at O(n) is needlessly expensive, we store KNOWN_SEVERITY.
- */
-enum {
- FOUND_BIT = 1 << 0,
- ENABLED_BIT = 1 << 1,
- KNOWN_SEVERITY = 1 << 2,
-
- /* HashTable reserves zero as a return value meaning 'not found' */
- NOT_FOUND = 0,
- DISABLED = FOUND_BIT,
- ENABLED = ENABLED_BIT | FOUND_BIT
-};
+ /* Enable all the messages with severity HIGH or MEDIUM by default */
+ ns->DefaultState = (1 << MESA_DEBUG_SEVERITY_HIGH) |
+ (1 << MESA_DEBUG_SEVERITY_MEDIUM);
+}
+
+static void
+debug_namespace_clear(struct gl_debug_namespace *ns)
+{
+ struct simple_node *node, *tmp;
+
+ foreach_s(node, tmp, &ns->Elements)
+ free(node);
+}
+
+static bool
+debug_namespace_copy(struct gl_debug_namespace *dst,
+ const struct gl_debug_namespace *src)
+{
+ struct simple_node *node;
+
+ dst->DefaultState = src->DefaultState;
+ make_empty_list(&dst->Elements);
+ foreach(node, &src->Elements) {
+ const struct gl_debug_element *elem =
+ (const struct gl_debug_element *) node;
+ struct gl_debug_element *copy;
+
+ copy = malloc(sizeof(*copy));
+ if (!copy) {
+ debug_namespace_clear(dst);
+ return false;
+ }
+
+ copy->ID = elem->ID;
+ copy->State = elem->State;
+ insert_at_tail(&dst->Elements, &copy->link);
+ }
+
+ return true;
+}
/**
- * Return debug state for the context. The debug state will be allocated
- * and initialized upon the first call.
+ * Set the state of \p id in the namespace.
*/
-struct gl_debug_state *
-_mesa_get_debug_state(struct gl_context *ctx)
+static bool
+debug_namespace_set(struct gl_debug_namespace *ns,
+ GLuint id, bool enabled)
{
- if (!ctx->Debug) {
- ctx->Debug = CALLOC_STRUCT(gl_debug_state);
- if (!ctx->Debug) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "allocating debug state");
+ const uint32_t state = (enabled) ?
+ ((1 << MESA_DEBUG_SEVERITY_COUNT) - 1) : 0;
+ struct gl_debug_element *elem = NULL;
+ struct simple_node *node;
+
+ /* find the element */
+ foreach(node, &ns->Elements) {
+ struct gl_debug_element *tmp = (struct gl_debug_element *) node;
+ if (tmp->ID == id) {
+ elem = tmp;
+ break;
}
- else {
- struct gl_debug_state *debug = ctx->Debug;
- int s, t, sev;
-
- /* Enable all the messages with severity HIGH or MEDIUM by default. */
- memset(debug->Defaults[0][MESA_DEBUG_SEVERITY_HIGH], GL_TRUE,
- sizeof debug->Defaults[0][MESA_DEBUG_SEVERITY_HIGH]);
- memset(debug->Defaults[0][MESA_DEBUG_SEVERITY_MEDIUM], GL_TRUE,
- sizeof debug->Defaults[0][MESA_DEBUG_SEVERITY_MEDIUM]);
- memset(debug->Defaults[0][MESA_DEBUG_SEVERITY_LOW], GL_FALSE,
- sizeof debug->Defaults[0][MESA_DEBUG_SEVERITY_LOW]);
-
- /* Initialize state for filtering known debug messages. */
- for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) {
- for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) {
- debug->Namespaces[0][s][t].IDs = _mesa_NewHashTable();
- assert(debug->Namespaces[0][s][t].IDs);
-
- for (sev = 0; sev < MESA_DEBUG_SEVERITY_COUNT; sev++) {
- make_empty_list(&debug->Namespaces[0][s][t].Severity[sev]);
- }
- }
- }
+ }
+
+ /* we do not need the element if it has the default state */
+ if (ns->DefaultState == state) {
+ if (elem) {
+ remove_from_list(&elem->link);
+ free(elem);
}
+ return true;
}
- return ctx->Debug;
+ if (!elem) {
+ elem = malloc(sizeof(*elem));
+ if (!elem)
+ return false;
+
+ elem->ID = id;
+ insert_at_tail(&ns->Elements, &elem->link);
+ }
+
+ elem->State = state;
+
+ return true;
}
+/**
+ * Set the default state of the namespace for \p severity. When \p severity
+ * is MESA_DEBUG_SEVERITY_COUNT, the default values for all severities are
+ * updated.
+ */
+static void
+debug_namespace_set_all(struct gl_debug_namespace *ns,
+ enum mesa_debug_severity severity,
+ bool enabled)
+{
+ struct simple_node *node, *tmp;
+ uint32_t mask, val;
+
+ /* set all elements to the same state */
+ if (severity == MESA_DEBUG_SEVERITY_COUNT) {
+ ns->DefaultState = (enabled) ? ((1 << severity) - 1) : 0;
+ debug_namespace_clear(ns);
+ make_empty_list(&ns->Elements);
+ return;
+ }
+
+ mask = 1 << severity;
+ val = (enabled) ? mask : 0;
+ ns->DefaultState = (ns->DefaultState & ~mask) | val;
+
+ foreach_s(node, tmp, &ns->Elements) {
+ struct gl_debug_element *elem = (struct gl_debug_element *) node;
+
+ elem->State = (elem->State & ~mask) | val;
+ if (elem->State == ns->DefaultState) {
+ remove_from_list(node);
+ free(node);
+ }
+ }
+}
/**
- * Returns the state of the given message source/type/ID tuple.
+ * Get the state of \p id in the namespace.
*/
-static GLboolean
-should_log(struct gl_context *ctx,
- enum mesa_debug_source source,
- enum mesa_debug_type type,
- GLuint id,
- enum mesa_debug_severity severity)
+static bool
+debug_namespace_get(const struct gl_debug_namespace *ns, GLuint id,
+ enum mesa_debug_severity severity)
{
- struct gl_debug_state *debug;
- uintptr_t state = 0;
+ struct simple_node *node;
+ uint32_t state;
- if (!ctx->Debug) {
- /* no debug state set so far */
- return GL_FALSE;
+ state = ns->DefaultState;
+ foreach(node, &ns->Elements) {
+ struct gl_debug_element *elem = (struct gl_debug_element *) node;
+
+ if (elem->ID == id) {
+ state = elem->State;
+ break;
+ }
}
- debug = _mesa_get_debug_state(ctx);
- if (debug) {
- const GLint gstack = debug->GroupStackDepth;
- struct gl_debug_namespace *nspace =
- &debug->Namespaces[gstack][source][type];
+ return (state & (1 << severity));
+}
- if (!debug->DebugOutput)
- return GL_FALSE;
+/**
+ * Allocate and initialize context debug state.
+ */
+static struct gl_debug_state *
+debug_create(void)
+{
+ struct gl_debug_state *debug;
+ int s, t;
- /* In addition to not being able to store zero as a value, HashTable also
- * can't use zero as a key.
- */
- if (id)
- state = (uintptr_t)_mesa_HashLookup(nspace->IDs, id);
- else
- state = nspace->ZeroID;
+ debug = CALLOC_STRUCT(gl_debug_state);
+ if (!debug)
+ return NULL;
- /* Only do this once for each ID. This makes sure the ID exists in,
- * at most, one list, and does not pointlessly appear multiple times.
- */
- if (!(state & KNOWN_SEVERITY)) {
- struct gl_debug_severity *entry;
-
- if (state == NOT_FOUND) {
- if (debug->Defaults[gstack][severity][source][type])
- state = ENABLED;
- else
- state = DISABLED;
- }
+ debug->Groups[0] = malloc(sizeof(*debug->Groups[0]));
+ if (!debug->Groups[0]) {
+ free(debug);
+ return NULL;
+ }
+
+ /* Initialize state for filtering known debug messages. */
+ for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) {
+ for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++)
+ debug_namespace_init(&debug->Groups[0]->Namespaces[s][t]);
+ }
+
+ return debug;
+}
- entry = malloc(sizeof *entry);
- if (!entry)
- goto out;
+/**
+ * Return true if the top debug group points to the group below it.
+ */
+static bool
+debug_is_group_read_only(const struct gl_debug_state *debug)
+{
+ const GLint gstack = debug->GroupStackDepth;
+ return (gstack > 0 && debug->Groups[gstack] == debug->Groups[gstack - 1]);
+}
+
+/**
+ * Make the top debug group writable.
+ */
+static bool
+debug_make_group_writable(struct gl_debug_state *debug)
+{
+ const GLint gstack = debug->GroupStackDepth;
+ const struct gl_debug_group *src = debug->Groups[gstack];
+ struct gl_debug_group *dst;
+ int s, t;
- state |= KNOWN_SEVERITY;
+ if (!debug_is_group_read_only(debug))
+ return true;
- if (id)
- _mesa_HashInsert(nspace->IDs, id, (void*)state);
- else
- nspace->ZeroID = state;
+ dst = malloc(sizeof(*dst));
+ if (!dst)
+ return false;
- entry->ID = id;
- insert_at_tail(&nspace->Severity[severity], &entry->link);
+ for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) {
+ for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) {
+ if (!debug_namespace_copy(&dst->Namespaces[s][t],
+ &src->Namespaces[s][t])) {
+ /* error path! */
+ for (t = t - 1; t >= 0; t--)
+ debug_namespace_clear(&dst->Namespaces[s][t]);
+ for (s = s - 1; s >= 0; s--) {
+ for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++)
+ debug_namespace_clear(&dst->Namespaces[s][t]);
+ }
+ free(dst);
+ return false;
+ }
}
}
-out:
- return !!(state & ENABLED_BIT);
-}
+ debug->Groups[gstack] = dst;
+
+ return true;
+}
/**
- * Sets the state of the given message source/type/ID tuple.
+ * Free the top debug group.
*/
static void
-set_message_state(struct gl_context *ctx,
- enum mesa_debug_source source,
- enum mesa_debug_type type,
- GLuint id, GLboolean enabled)
+debug_clear_group(struct gl_debug_state *debug)
{
- struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
+ const GLint gstack = debug->GroupStackDepth;
- if (debug) {
- GLint gstack = debug->GroupStackDepth;
- struct gl_debug_namespace *nspace =
- &debug->Namespaces[gstack][source][type];
- uintptr_t state;
+ if (!debug_is_group_read_only(debug)) {
+ struct gl_debug_group *grp = debug->Groups[gstack];
+ int s, t;
- /* In addition to not being able to store zero as a value, HashTable also
- * can't use zero as a key.
- */
- if (id)
- state = (uintptr_t)_mesa_HashLookup(nspace->IDs, id);
- else
- state = nspace->ZeroID;
-
- if (state == NOT_FOUND)
- state = enabled ? ENABLED : DISABLED;
- else {
- if (enabled)
- state |= ENABLED_BIT;
- else
- state &= ~ENABLED_BIT;
+ for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) {
+ for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++)
+ debug_namespace_clear(&grp->Namespaces[s][t]);
}
- if (id)
- _mesa_HashInsert(nspace->IDs, id, (void*)state);
- else
- nspace->ZeroID = state;
+ free(grp);
}
+
+ debug->Groups[gstack] = NULL;
}
+/**
+ * Loop through debug group stack tearing down states for
+ * filtering debug messages. Then free debug output state.
+ */
+static void
+debug_destroy(struct gl_debug_state *debug)
+{
+ while (debug->GroupStackDepth > 0) {
+ debug_clear_group(debug);
+ debug->GroupStackDepth--;
+ }
+ debug_clear_group(debug);
+ free(debug);
+}
+
+/**
+ * Sets the state of the given message source/type/ID tuple.
+ */
static void
-store_message_details(struct gl_debug_msg *emptySlot,
- enum mesa_debug_source source,
- enum mesa_debug_type type, GLuint id,
- enum mesa_debug_severity severity, GLint len,
- const char *buf)
+debug_set_message_enable(struct gl_debug_state *debug,
+ enum mesa_debug_source source,
+ enum mesa_debug_type type,
+ GLuint id, GLboolean enabled)
{
- assert(!emptySlot->message && !emptySlot->length);
-
- emptySlot->message = malloc(len+1);
- if (emptySlot->message) {
- (void) strncpy(emptySlot->message, buf, (size_t)len);
- emptySlot->message[len] = '\0';
-
- emptySlot->length = len+1;
- emptySlot->source = source;
- emptySlot->type = type;
- emptySlot->id = id;
- emptySlot->severity = severity;
+ const GLint gstack = debug->GroupStackDepth;
+ struct gl_debug_namespace *ns;
+
+ debug_make_group_writable(debug);
+ ns = &debug->Groups[gstack]->Namespaces[source][type];
+
+ debug_namespace_set(ns, id, enabled);
+}
+
+/*
+ * Set the state of all message IDs found in the given intersection of
+ * 'source', 'type', and 'severity'. The _COUNT enum can be used for
+ * GL_DONT_CARE (include all messages in the class).
+ *
+ * This requires both setting the state of all previously seen message
+ * IDs in the hash table, and setting the default state for all
+ * applicable combinations of source/type/severity, so that all the
+ * yet-unknown message IDs that may be used in the future will be
+ * impacted as if they were already known.
+ */
+static void
+debug_set_message_enable_all(struct gl_debug_state *debug,
+ enum mesa_debug_source source,
+ enum mesa_debug_type type,
+ enum mesa_debug_severity severity,
+ GLboolean enabled)
+{
+ const GLint gstack = debug->GroupStackDepth;
+ int s, t, smax, tmax;
+
+ if (source == MESA_DEBUG_SOURCE_COUNT) {
+ source = 0;
+ smax = MESA_DEBUG_SOURCE_COUNT;
} else {
- static GLuint oom_msg_id = 0;
- debug_get_id(&oom_msg_id);
+ smax = source+1;
+ }
- /* malloc failed! */
- emptySlot->message = out_of_memory;
- emptySlot->length = strlen(out_of_memory)+1;
- emptySlot->source = MESA_DEBUG_SOURCE_OTHER;
- emptySlot->type = MESA_DEBUG_TYPE_ERROR;
- emptySlot->id = oom_msg_id;
- emptySlot->severity = MESA_DEBUG_SEVERITY_HIGH;
+ if (type == MESA_DEBUG_TYPE_COUNT) {
+ type = 0;
+ tmax = MESA_DEBUG_TYPE_COUNT;
+ } else {
+ tmax = type+1;
+ }
+
+ debug_make_group_writable(debug);
+
+ for (s = source; s < smax; s++) {
+ for (t = type; t < tmax; t++) {
+ struct gl_debug_namespace *nspace =
+ &debug->Groups[gstack]->Namespaces[s][t];
+ debug_namespace_set_all(nspace, severity, enabled);
+ }
}
}
+/**
+ * Returns if the given message source/type/ID tuple is enabled.
+ */
+static bool
+debug_is_message_enabled(const struct gl_debug_state *debug,
+ enum mesa_debug_source source,
+ enum mesa_debug_type type,
+ GLuint id,
+ enum mesa_debug_severity severity)
+{
+ const GLint gstack = debug->GroupStackDepth;
+ struct gl_debug_group *grp = debug->Groups[gstack];
+ struct gl_debug_namespace *nspace = &grp->Namespaces[source][type];
+
+ if (!debug->DebugOutput)
+ return false;
+
+ return debug_namespace_get(nspace, id, severity);
+}
/**
* 'buf' is not necessarily a null-terminated string. When logging, copy
@@ -376,108 +593,229 @@ store_message_details(struct gl_debug_msg *emptySlot,
* the null terminator this time.
*/
static void
-log_msg(struct gl_context *ctx, enum mesa_debug_source source,
- enum mesa_debug_type type, GLuint id,
- enum mesa_debug_severity severity, GLint len, const char *buf)
+debug_log_message(struct gl_debug_state *debug,
+ enum mesa_debug_source source,
+ enum mesa_debug_type type, GLuint id,
+ enum mesa_debug_severity severity,
+ GLsizei len, const char *buf)
{
- struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
+ struct gl_debug_log *log = &debug->Log;
GLint nextEmpty;
- struct gl_debug_msg *emptySlot;
-
- if (!debug)
- return;
+ struct gl_debug_message *emptySlot;
assert(len >= 0 && len < MAX_DEBUG_MESSAGE_LENGTH);
- if (!should_log(ctx, source, type, id, severity))
+ if (log->NumMessages == MAX_DEBUG_LOGGED_MESSAGES)
return;
- if (debug->Callback) {
- GLenum gl_type = debug_type_enums[type];
- GLenum gl_severity = debug_severity_enums[severity];
+ nextEmpty = (log->NextMessage + log->NumMessages)
+ % MAX_DEBUG_LOGGED_MESSAGES;
+ emptySlot = &log->Messages[nextEmpty];
- debug->Callback(debug_source_enums[source], gl_type, id, gl_severity,
- len, buf, debug->CallbackData);
- return;
- }
+ debug_message_store(emptySlot, source, type,
+ id, severity, len, buf);
- if (debug->NumMessages == MAX_DEBUG_LOGGED_MESSAGES)
- return;
+ log->NumMessages++;
+}
+
+/**
+ * Return the oldest debug message out of the log.
+ */
+static const struct gl_debug_message *
+debug_fetch_message(const struct gl_debug_state *debug)
+{
+ const struct gl_debug_log *log = &debug->Log;
+
+ return (log->NumMessages) ? &log->Messages[log->NextMessage] : NULL;
+}
+
+/**
+ * Delete the oldest debug messages out of the log.
+ */
+static void
+debug_delete_messages(struct gl_debug_state *debug, unsigned count)
+{
+ struct gl_debug_log *log = &debug->Log;
- nextEmpty = (debug->NextMsg + debug->NumMessages)
- % MAX_DEBUG_LOGGED_MESSAGES;
- emptySlot = &debug->Log[nextEmpty];
+ if (count > log->NumMessages)
+ count = log->NumMessages;
- store_message_details(emptySlot, source, type, id, severity, len, buf);
+ while (count--) {
+ struct gl_debug_message *msg = &log->Messages[log->NextMessage];
- if (debug->NumMessages == 0)
- debug->NextMsgLength = debug->Log[debug->NextMsg].length;
+ debug_message_clear(msg);
- debug->NumMessages++;
+ log->NumMessages--;
+ log->NextMessage++;
+ log->NextMessage %= MAX_DEBUG_LOGGED_MESSAGES;
+ }
+}
+
+static struct gl_debug_message *
+debug_get_group_message(struct gl_debug_state *debug)
+{
+ return &debug->GroupMessages[debug->GroupStackDepth];
+}
+
+static void
+debug_push_group(struct gl_debug_state *debug)
+{
+ const GLint gstack = debug->GroupStackDepth;
+
+ /* just point to the previous stack */
+ debug->Groups[gstack + 1] = debug->Groups[gstack];
+ debug->GroupStackDepth++;
+}
+
+static void
+debug_pop_group(struct gl_debug_state *debug)
+{
+ debug_clear_group(debug);
+ debug->GroupStackDepth--;
}
/**
- * Pop the oldest debug message out of the log.
- * Writes the message string, including the null terminator, into 'buf',
- * using up to 'bufSize' bytes. If 'bufSize' is too small, or
- * if 'buf' is NULL, nothing is written.
- *
- * Returns the number of bytes written on success, or when 'buf' is NULL,
- * the number that would have been written. A return value of 0
- * indicates failure.
+ * Return debug state for the context. The debug state will be allocated
+ * and initialized upon the first call.
*/
-static GLsizei
-get_msg(struct gl_context *ctx, GLenum *source, GLenum *type,
- GLuint *id, GLenum *severity, GLsizei bufSize, char *buf)
+static struct gl_debug_state *
+_mesa_get_debug_state(struct gl_context *ctx)
+{
+ if (!ctx->Debug) {
+ ctx->Debug = debug_create();
+ if (!ctx->Debug) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "allocating debug state");
+ }
+ }
+
+ return ctx->Debug;
+}
+
+/**
+ * Set the integer debug state specified by \p pname. This can be called from
+ * _mesa_set_enable for example.
+ */
+bool
+_mesa_set_debug_state_int(struct gl_context *ctx, GLenum pname, GLint val)
{
struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
- struct gl_debug_msg *msg;
- GLsizei length;
- if (!debug || debug->NumMessages == 0)
- return 0;
+ if (!debug)
+ return false;
- msg = &debug->Log[debug->NextMsg];
- length = msg->length;
+ switch (pname) {
+ case GL_DEBUG_OUTPUT:
+ debug->DebugOutput = (val != 0);
+ break;
+ case GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB:
+ debug->SyncOutput = (val != 0);
+ break;
+ default:
+ assert(!"unknown debug output param");
+ break;
+ }
- assert(length > 0 && length == debug->NextMsgLength);
+ return true;
+}
- if (bufSize < length && buf != NULL)
+/**
+ * Query the integer debug state specified by \p pname. This can be called
+ * _mesa_GetIntegerv for example.
+ */
+GLint
+_mesa_get_debug_state_int(struct gl_context *ctx, GLenum pname)
+{
+ struct gl_debug_state *debug;
+ GLint val;
+
+ debug = ctx->Debug;
+ if (!debug)
return 0;
- if (severity) {
- *severity = debug_severity_enums[msg->severity];
+ switch (pname) {
+ case GL_DEBUG_OUTPUT:
+ val = debug->DebugOutput;
+ break;
+ case GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB:
+ val = debug->SyncOutput;
+ break;
+ case GL_DEBUG_LOGGED_MESSAGES:
+ val = debug->Log.NumMessages;
+ break;
+ case GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH:
+ val = (debug->Log.NumMessages) ?
+ debug->Log.Messages[debug->Log.NextMessage].length : 0;
+ break;
+ case GL_DEBUG_GROUP_STACK_DEPTH:
+ val = debug->GroupStackDepth;
+ break;
+ default:
+ assert(!"unknown debug output param");
+ val = 0;
+ break;
}
- if (source) {
- *source = debug_source_enums[msg->source];
- }
+ return val;
+}
- if (type) {
- *type = debug_type_enums[msg->type];
- }
+/**
+ * Query the pointer debug state specified by \p pname. This can be called
+ * _mesa_GetPointerv for example.
+ */
+void *
+_mesa_get_debug_state_ptr(struct gl_context *ctx, GLenum pname)
+{
+ struct gl_debug_state *debug;
+ void *val;
- if (id) {
- *id = msg->id;
- }
+ debug = ctx->Debug;
+ if (!debug)
+ return NULL;
- if (buf) {
- assert(msg->message[length-1] == '\0');
- (void) strncpy(buf, msg->message, (size_t)length);
+ switch (pname) {
+ case GL_DEBUG_CALLBACK_FUNCTION_ARB:
+ val = (void *) debug->Callback;
+ break;
+ case GL_DEBUG_CALLBACK_USER_PARAM_ARB:
+ val = (void *) debug->CallbackData;
+ break;
+ default:
+ assert(!"unknown debug output param");
+ val = NULL;
+ break;
}
- if (msg->message != (char*)out_of_memory)
- free(msg->message);
- msg->message = NULL;
- msg->length = 0;
+ return val;
+}
- debug->NumMessages--;
- debug->NextMsg++;
- debug->NextMsg %= MAX_DEBUG_LOGGED_MESSAGES;
- debug->NextMsgLength = debug->Log[debug->NextMsg].length;
- return length;
+/**
+ * Log a client or driver debug message.
+ */
+static void
+log_msg(struct gl_context *ctx, enum mesa_debug_source source,
+ enum mesa_debug_type type, GLuint id,
+ enum mesa_debug_severity severity, GLint len, const char *buf)
+{
+ struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
+
+ if (!debug)
+ return;
+
+ if (!debug_is_message_enabled(debug, source, type, id, severity))
+ return;
+
+ if (debug->Callback) {
+ GLenum gl_type = debug_type_enums[type];
+ GLenum gl_severity = debug_severity_enums[severity];
+
+ debug->Callback(debug_source_enums[source], gl_type, id, gl_severity,
+ len, buf, debug->CallbackData);
+ return;
+ }
+
+ debug_log_message(debug, source, type, id, severity, len, buf);
}
@@ -560,172 +898,18 @@ error:
}
-/**
- * Set the state of all message IDs found in the given intersection of
- * 'source', 'type', and 'severity'. The _COUNT enum can be used for
- * GL_DONT_CARE (include all messages in the class).
- *
- * This requires both setting the state of all previously seen message
- * IDs in the hash table, and setting the default state for all
- * applicable combinations of source/type/severity, so that all the
- * yet-unknown message IDs that may be used in the future will be
- * impacted as if they were already known.
- */
-static void
-control_messages(struct gl_context *ctx,
- enum mesa_debug_source source,
- enum mesa_debug_type type,
- enum mesa_debug_severity severity,
- GLboolean enabled)
-{
- struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
- int s, t, sev, smax, tmax, sevmax;
- const GLint gstack = debug ? debug->GroupStackDepth : 0;
-
- if (!debug)
- return;
-
- if (source == MESA_DEBUG_SOURCE_COUNT) {
- source = 0;
- smax = MESA_DEBUG_SOURCE_COUNT;
- } else {
- smax = source+1;
- }
-
- if (type == MESA_DEBUG_TYPE_COUNT) {
- type = 0;
- tmax = MESA_DEBUG_TYPE_COUNT;
- } else {
- tmax = type+1;
- }
-
- if (severity == MESA_DEBUG_SEVERITY_COUNT) {
- severity = 0;
- sevmax = MESA_DEBUG_SEVERITY_COUNT;
- } else {
- sevmax = severity+1;
- }
-
- for (sev = severity; sev < sevmax; sev++) {
- for (s = source; s < smax; s++) {
- for (t = type; t < tmax; t++) {
- struct simple_node *node;
- struct gl_debug_severity *entry;
-
- /* change the default for IDs we've never seen before. */
- debug->Defaults[gstack][sev][s][t] = enabled;
-
- /* Now change the state of IDs we *have* seen... */
- foreach(node, &debug->Namespaces[gstack][s][t].Severity[sev]) {
- entry = (struct gl_debug_severity *)node;
- set_message_state(ctx, s, t, entry->ID, enabled);
- }
- }
- }
- }
-}
-
-
-/**
- * Debugging-message namespaces with the source APPLICATION or THIRD_PARTY
- * require special handling, since the IDs in them are controlled by clients,
- * not the OpenGL implementation.
- *
- * 'count' is the length of the array 'ids'. If 'count' is nonzero, all
- * the given IDs in the namespace defined by 'esource' and 'etype'
- * will be affected.
- *
- * If 'count' is zero, this sets the state of all IDs that match
- * the combination of 'esource', 'etype', and 'eseverity'.
- */
-static void
-control_app_messages(struct gl_context *ctx, GLenum esource, GLenum etype,
- GLenum eseverity, GLsizei count, const GLuint *ids,
- GLboolean enabled)
-{
- GLsizei i;
- enum mesa_debug_source source = gl_enum_to_debug_source(esource);
- enum mesa_debug_type type = gl_enum_to_debug_type(etype);
- enum mesa_debug_severity severity = gl_enum_to_debug_severity(eseverity);
-
- for (i = 0; i < count; i++)
- set_message_state(ctx, source, type, ids[i], enabled);
-
- if (count)
- return;
-
- control_messages(ctx, source, type, severity, enabled);
-}
-
-
-/**
- * This is a generic message insert function.
- * Validation of source, type and severity parameters should be done
- * before calling this funtion.
- */
-static void
-message_insert(GLenum source, GLenum type, GLuint id,
- GLenum severity, GLint length, const GLchar *buf,
- const char *callerstr)
+static GLboolean
+validate_length(struct gl_context *ctx, const char *callerstr, GLsizei length)
{
- GET_CURRENT_CONTEXT(ctx);
-
- if (length < 0)
- length = strlen(buf);
-
if (length >= MAX_DEBUG_MESSAGE_LENGTH) {
_mesa_error(ctx, GL_INVALID_VALUE,
"%s(length=%d, which is not less than "
"GL_MAX_DEBUG_MESSAGE_LENGTH=%d)", callerstr, length,
MAX_DEBUG_MESSAGE_LENGTH);
- return;
+ return GL_FALSE;
}
- log_msg(ctx,
- gl_enum_to_debug_source(source),
- gl_enum_to_debug_type(type), id,
- gl_enum_to_debug_severity(severity), length, buf);
-}
-
-
-static void
-do_nothing(GLuint key, void *data, void *userData)
-{
-}
-
-
-/**
- * Free context state pertaining to error/debug state for the given stack
- * depth.
- */
-static void
-free_errors_data(struct gl_context *ctx, GLint gstack)
-{
- struct gl_debug_state *debug = ctx->Debug;
- enum mesa_debug_type t;
- enum mesa_debug_source s;
- enum mesa_debug_severity sev;
-
- assert(debug);
-
- /* Tear down state for filtering debug messages. */
- for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) {
- for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) {
- _mesa_HashDeleteAll(debug->Namespaces[gstack][s][t].IDs,
- do_nothing, NULL);
- _mesa_DeleteHashTable(debug->Namespaces[gstack][s][t].IDs);
- for (sev = 0; sev < MESA_DEBUG_SEVERITY_COUNT; sev++) {
- struct simple_node *node, *tmp;
- struct gl_debug_severity *entry;
-
- foreach_s(node, tmp,
- &debug->Namespaces[gstack][s][t].Severity[sev]) {
- entry = (struct gl_debug_severity *)node;
- free(entry);
- }
- }
- }
- }
+ return GL_TRUE;
}
@@ -741,7 +925,15 @@ _mesa_DebugMessageInsert(GLenum source, GLenum type, GLuint id,
if (!validate_params(ctx, INSERT, callerstr, source, type, severity))
return; /* GL_INVALID_ENUM */
- message_insert(source, type, id, severity, length, buf, callerstr);
+ if (length < 0)
+ length = strlen(buf);
+ if (!validate_length(ctx, callerstr, length))
+ return; /* GL_INVALID_VALUE */
+
+ log_msg(ctx, gl_enum_to_debug_source(source),
+ gl_enum_to_debug_type(type), id,
+ gl_enum_to_debug_severity(severity),
+ length, buf);
}
@@ -751,6 +943,7 @@ _mesa_GetDebugMessageLog(GLuint count, GLsizei logSize, GLenum *sources,
GLsizei *lengths, GLchar *messageLog)
{
GET_CURRENT_CONTEXT(ctx);
+ struct gl_debug_state *debug;
GLuint ret;
if (!messageLog)
@@ -763,29 +956,39 @@ _mesa_GetDebugMessageLog(GLuint count, GLsizei logSize, GLenum *sources,
return 0;
}
+ debug = _mesa_get_debug_state(ctx);
+ if (!debug)
+ return 0;
+
for (ret = 0; ret < count; ret++) {
- GLsizei written = get_msg(ctx, sources, types, ids, severities,
- logSize, messageLog);
- if (!written)
+ const struct gl_debug_message *msg = debug_fetch_message(debug);
+
+ if (!msg)
+ break;
+
+ if (logSize < msg->length && messageLog != NULL)
break;
if (messageLog) {
- messageLog += written;
- logSize -= written;
- }
- if (lengths) {
- *lengths = written;
- lengths++;
+ assert(msg->message[msg->length-1] == '\0');
+ (void) strncpy(messageLog, msg->message, (size_t)msg->length);
+
+ messageLog += msg->length;
+ logSize -= msg->length;
}
+ if (lengths)
+ *lengths++ = msg->length;
if (severities)
- severities++;
+ *severities++ = debug_severity_enums[msg->severity];
if (sources)
- sources++;
+ *sources++ = debug_source_enums[msg->source];
if (types)
- types++;
+ *types++ = debug_type_enums[msg->type];
if (ids)
- ids++;
+ *ids++ = msg->id;
+
+ debug_delete_messages(debug, 1);
}
return ret;
@@ -797,9 +1000,12 @@ _mesa_DebugMessageControl(GLenum gl_source, GLenum gl_type,
GLenum gl_severity, GLsizei count,
const GLuint *ids, GLboolean enabled)
{
- const char *callerstr = "glDebugMessageControl";
-
GET_CURRENT_CONTEXT(ctx);
+ enum mesa_debug_source source = gl_enum_to_debug_source(gl_source);
+ enum mesa_debug_type type = gl_enum_to_debug_type(gl_type);
+ enum mesa_debug_severity severity = gl_enum_to_debug_severity(gl_severity);
+ const char *callerstr = "glDebugMessageControl";
+ struct gl_debug_state *debug;
if (count < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
@@ -821,8 +1027,18 @@ _mesa_DebugMessageControl(GLenum gl_source, GLenum gl_type,
return;
}
- control_app_messages(ctx, gl_source, gl_type, gl_severity,
- count, ids, enabled);
+ debug = _mesa_get_debug_state(ctx);
+ if (!debug)
+ return;
+
+ if (count) {
+ GLsizei i;
+ for (i = 0; i < count; i++)
+ debug_set_message_enable(debug, source, type, ids[i], enabled);
+ }
+ else {
+ debug_set_message_enable_all(debug, source, type, severity, enabled);
+ }
}
@@ -845,10 +1061,7 @@ _mesa_PushDebugGroup(GLenum source, GLuint id, GLsizei length,
GET_CURRENT_CONTEXT(ctx);
struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
const char *callerstr = "glPushDebugGroup";
- int s, t, sev;
- GLint prevStackDepth;
- GLint currStackDepth;
- struct gl_debug_msg *emptySlot;
+ struct gl_debug_message *emptySlot;
if (!debug)
return;
@@ -868,55 +1081,26 @@ _mesa_PushDebugGroup(GLenum source, GLuint id, GLsizei length,
return;
}
- message_insert(source, GL_DEBUG_TYPE_PUSH_GROUP, id,
- GL_DEBUG_SEVERITY_NOTIFICATION, length,
- message, callerstr);
+ if (length < 0)
+ length = strlen(message);
+ if (!validate_length(ctx, callerstr, length))
+ return; /* GL_INVALID_VALUE */
- prevStackDepth = debug->GroupStackDepth;
- debug->GroupStackDepth++;
- currStackDepth = debug->GroupStackDepth;
+ log_msg(ctx, gl_enum_to_debug_source(source),
+ MESA_DEBUG_TYPE_PUSH_GROUP, id,
+ MESA_DEBUG_SEVERITY_NOTIFICATION, length,
+ message);
/* pop reuses the message details from push so we store this */
- if (length < 0)
- length = strlen(message);
- emptySlot = &debug->DebugGroupMsgs[debug->GroupStackDepth];
- store_message_details(emptySlot, gl_enum_to_debug_source(source),
- gl_enum_to_debug_type(GL_DEBUG_TYPE_PUSH_GROUP),
- id,
- gl_enum_to_debug_severity(GL_DEBUG_SEVERITY_NOTIFICATION),
- length, message);
-
- /* inherit the control volume of the debug group previously residing on
- * the top of the debug group stack
- */
- for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) {
- for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) {
- /* copy id settings */
- debug->Namespaces[currStackDepth][s][t].IDs =
- _mesa_HashClone(debug->Namespaces[prevStackDepth][s][t].IDs);
-
- for (sev = 0; sev < MESA_DEBUG_SEVERITY_COUNT; sev++) {
- struct gl_debug_severity *entry, *prevEntry;
- struct simple_node *node;
-
- /* copy default settings for unknown ids */
- debug->Defaults[currStackDepth][sev][s][t] =
- debug->Defaults[prevStackDepth][sev][s][t];
-
- /* copy known id severity settings */
- make_empty_list(&debug->Namespaces[currStackDepth][s][t].Severity[sev]);
- foreach(node, &debug->Namespaces[prevStackDepth][s][t].Severity[sev]) {
- prevEntry = (struct gl_debug_severity *)node;
- entry = malloc(sizeof *entry);
- if (!entry)
- return;
-
- entry->ID = prevEntry->ID;
- insert_at_tail(&debug->Namespaces[currStackDepth][s][t].Severity[sev], &entry->link);
- }
- }
- }
- }
+ emptySlot = debug_get_group_message(debug);
+ debug_message_store(emptySlot,
+ gl_enum_to_debug_source(source),
+ gl_enum_to_debug_type(GL_DEBUG_TYPE_PUSH_GROUP),
+ id,
+ gl_enum_to_debug_severity(GL_DEBUG_SEVERITY_NOTIFICATION),
+ length, message);
+
+ debug_push_group(debug);
}
@@ -926,8 +1110,7 @@ _mesa_PopDebugGroup(void)
GET_CURRENT_CONTEXT(ctx);
struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
const char *callerstr = "glPopDebugGroup";
- struct gl_debug_msg *gdmessage;
- GLint prevStackDepth;
+ struct gl_debug_message *gdmessage;
if (!debug)
return;
@@ -937,26 +1120,16 @@ _mesa_PopDebugGroup(void)
return;
}
- prevStackDepth = debug->GroupStackDepth;
- debug->GroupStackDepth--;
+ debug_pop_group(debug);
- gdmessage = &debug->DebugGroupMsgs[prevStackDepth];
- /* using log_msg() directly here as verification of parameters
- * already done in push
- */
+ gdmessage = debug_get_group_message(debug);
log_msg(ctx, gdmessage->source,
gl_enum_to_debug_type(GL_DEBUG_TYPE_POP_GROUP),
gdmessage->id,
gl_enum_to_debug_severity(GL_DEBUG_SEVERITY_NOTIFICATION),
gdmessage->length, gdmessage->message);
- if (gdmessage->message != (char*)out_of_memory)
- free(gdmessage->message);
- gdmessage->message = NULL;
- gdmessage->length = 0;
-
- /* free popped debug group data */
- free_errors_data(ctx, prevStackDepth);
+ debug_message_clear(gdmessage);
}
@@ -967,20 +1140,11 @@ _mesa_init_errors(struct gl_context *ctx)
}
-/**
- * Loop through debug group stack tearing down states for
- * filtering debug messages. Then free debug output state.
- */
void
_mesa_free_errors_data(struct gl_context *ctx)
{
if (ctx->Debug) {
- GLint i;
-
- for (i = 0; i <= ctx->Debug->GroupStackDepth; i++) {
- free_errors_data(ctx, i);
- }
- free(ctx->Debug);
+ debug_destroy(ctx->Debug);
/* set to NULL just in case it is used before context is completely gone. */
ctx->Debug = NULL;
}
@@ -1198,11 +1362,16 @@ _mesa_error( struct gl_context *ctx, GLenum error, const char *fmtString, ... )
debug_get_id(&error_msg_id);
do_output = should_output(ctx, error, fmtString);
- do_log = should_log(ctx,
- MESA_DEBUG_SOURCE_API,
- MESA_DEBUG_TYPE_ERROR,
- error_msg_id,
- MESA_DEBUG_SEVERITY_HIGH);
+ if (ctx->Debug) {
+ do_log = debug_is_message_enabled(ctx->Debug,
+ MESA_DEBUG_SOURCE_API,
+ MESA_DEBUG_TYPE_ERROR,
+ error_msg_id,
+ MESA_DEBUG_SEVERITY_HIGH);
+ }
+ else {
+ do_log = GL_FALSE;
+ }
if (do_output || do_log) {
char s[MAX_DEBUG_MESSAGE_LENGTH], s2[MAX_DEBUG_MESSAGE_LENGTH];
diff --git a/mesalib/src/mesa/main/errors.h b/mesalib/src/mesa/main/errors.h
index e0706e5b9..06d0b21fc 100644
--- a/mesalib/src/mesa/main/errors.h
+++ b/mesalib/src/mesa/main/errors.h
@@ -83,8 +83,14 @@ _mesa_gl_debug(struct gl_context *ctx,
} \
} while (0)
-struct gl_debug_state *
-_mesa_get_debug_state(struct gl_context *ctx);
+bool
+_mesa_set_debug_state_int(struct gl_context *ctx, GLenum pname, GLint val);
+
+GLint
+_mesa_get_debug_state_int(struct gl_context *ctx, GLenum pname);
+
+void *
+_mesa_get_debug_state_ptr(struct gl_context *ctx, GLenum pname);
extern void
_mesa_shader_debug(struct gl_context *ctx, GLenum type, GLuint *id,
diff --git a/mesalib/src/mesa/main/ff_fragment_shader.cpp b/mesalib/src/mesa/main/ff_fragment_shader.cpp
index 66c18fa16..605f3713e 100644
--- a/mesalib/src/mesa/main/ff_fragment_shader.cpp
+++ b/mesalib/src/mesa/main/ff_fragment_shader.cpp
@@ -42,6 +42,7 @@ extern "C" {
#include "program/prog_statevars.h"
#include "program/programopt.h"
#include "texenvprogram.h"
+#include "texobj.h"
}
#include "main/uniforms.h"
#include "../glsl/glsl_types.h"
@@ -290,18 +291,6 @@ need_saturate( GLuint mode )
}
}
-
-
-/**
- * Translate TEXTURE_x_BIT to TEXTURE_x_INDEX.
- */
-static GLuint translate_tex_src_bit( GLbitfield bit )
-{
- ASSERT(bit);
- return ffs(bit) - 1;
-}
-
-
#define VERT_BIT_TEX_ANY (0xff << VERT_ATTRIB_TEX0)
/**
@@ -430,7 +419,7 @@ static GLuint make_state_key( struct gl_context *ctx, struct state_key *key )
const struct gl_sampler_object *samp;
GLenum format;
- if (!texUnit->_ReallyEnabled || !texUnit->Enabled)
+ if (!texUnit->_Current || !texUnit->Enabled)
continue;
samp = _mesa_get_samplerobj(ctx, i);
@@ -441,8 +430,8 @@ static GLuint make_state_key( struct gl_context *ctx, struct state_key *key )
key->nr_enabled_units = i + 1;
inputs_referenced |= VARYING_BIT_TEX(i);
- key->unit[i].source_index =
- translate_tex_src_bit(texUnit->_ReallyEnabled);
+ key->unit[i].source_index = _mesa_tex_target_to_index(ctx,
+ texObj->Target);
key->unit[i].shadow =
((samp->CompareMode == GL_COMPARE_R_TO_TEXTURE) &&
diff --git a/mesalib/src/mesa/main/ffvertex_prog.c b/mesalib/src/mesa/main/ffvertex_prog.c
index c5583c965..728cf968b 100644
--- a/mesalib/src/mesa/main/ffvertex_prog.c
+++ b/mesalib/src/mesa/main/ffvertex_prog.c
@@ -233,13 +233,13 @@ static void make_state_key( struct gl_context *ctx, struct state_key *key )
if (ctx->Texture._TexGenEnabled ||
ctx->Texture._TexMatEnabled ||
- ctx->Texture._EnabledUnits)
+ ctx->Texture._MaxEnabledTexImageUnit != -1)
key->texture_enabled_global = 1;
for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) {
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
- if (texUnit->_ReallyEnabled)
+ if (texUnit->_Current)
key->unit[i].texunit_really_enabled = 1;
if (ctx->Point.PointSprite)
diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c
index 6d9579008..fe35ff3ef 100644
--- a/mesalib/src/mesa/main/get.c
+++ b/mesalib/src/mesa/main/get.c
@@ -989,24 +989,10 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu
break;
/* GL_KHR_DEBUG */
case GL_DEBUG_LOGGED_MESSAGES:
- {
- struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
- v->value_int = debug ? debug->NumMessages : 0;
- }
- break;
case GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH:
- {
- struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
- v->value_int = debug ? debug->NextMsgLength : 0;
- }
- break;
case GL_DEBUG_GROUP_STACK_DEPTH:
- {
- struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
- v->value_int = debug ? debug->GroupStackDepth : 0;
- }
+ v->value_int = _mesa_get_debug_state_int(ctx, d->pname);
break;
-
/* GL_ARB_shader_atomic_counters */
case GL_ATOMIC_COUNTER_BUFFER_BINDING:
v->value_int = ctx->AtomicBuffer->Name;
diff --git a/mesalib/src/mesa/main/getstring.c b/mesalib/src/mesa/main/getstring.c
index b0bd3190b..431d60b03 100644
--- a/mesalib/src/mesa/main/getstring.c
+++ b/mesalib/src/mesa/main/getstring.c
@@ -253,22 +253,11 @@ _mesa_GetPointerv( GLenum pname, GLvoid **params )
*params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_POINT_SIZE].Ptr;
break;
case GL_DEBUG_CALLBACK_FUNCTION_ARB:
- if (!_mesa_is_desktop_gl(ctx)) {
- goto invalid_pname;
- }
- else {
- struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
- *params = debug ? (void *) debug->Callback : NULL;
- }
- break;
case GL_DEBUG_CALLBACK_USER_PARAM_ARB:
- if (!_mesa_is_desktop_gl(ctx)) {
+ if (!_mesa_is_desktop_gl(ctx))
goto invalid_pname;
- }
- else {
- struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
- *params = debug ? (void *) debug->CallbackData : NULL;
- }
+ else
+ *params = _mesa_get_debug_state_ptr(ctx, pname);
break;
default:
goto invalid_pname;
diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h
index 66943836c..5fbfffe98 100644
--- a/mesalib/src/mesa/main/mtypes.h
+++ b/mesalib/src/mesa/main/mtypes.h
@@ -76,6 +76,7 @@ struct gl_list_extensions;
struct gl_meta_state;
struct gl_program_cache;
struct gl_texture_object;
+struct gl_debug_state;
struct gl_context;
struct st_context;
struct gl_uniform_storage;
@@ -1085,7 +1086,6 @@ typedef enum
/**
* Bit flags for each type of texture object
- * Used for Texture.Unit[]._ReallyEnabled flags.
*/
/*@{*/
#define TEXTURE_2D_MULTISAMPLE_BIT (1 << TEXTURE_2D_MULTISAMPLE_INDEX)
@@ -1327,7 +1327,6 @@ struct gl_texgen
struct gl_texture_unit
{
GLbitfield Enabled; /**< bitmask of TEXTURE_*_BIT flags */
- GLbitfield _ReallyEnabled; /**< 0 or exactly one of TEXTURE_*_BIT flags */
GLenum EnvMode; /**< GL_MODULATE, GL_DECAL, GL_BLEND, etc. */
GLclampf EnvColor[4];
@@ -1388,9 +1387,6 @@ struct gl_texture_attrib
/** GL_ARB_seamless_cubemap */
GLboolean CubeMapSeamless;
- /** Texture units/samplers used by vertex or fragment texturing */
- GLbitfield _EnabledUnits;
-
/** Texture coord units/sets used for fragment texturing */
GLbitfield _EnabledCoordUnits;
@@ -1403,8 +1399,11 @@ struct gl_texture_attrib
/** Bitwise-OR of all Texture.Unit[i]._GenFlags */
GLbitfield _GenFlags;
- /** Upper bound on _ReallyEnabled texunits. */
+ /** Largest index of a texture unit with _Current != NULL. */
GLint _MaxEnabledTexImageUnit;
+
+ /** Largest index + 1 of texture units that have had any CurrentTex set. */
+ GLint NumCurrentTexUsed;
};
@@ -3822,45 +3821,6 @@ enum mesa_debug_severity {
/** @} */
/**
- * An error, warning, or other piece of debug information for an application
- * to consume via GL_ARB_debug_output/GL_KHR_debug.
- */
-struct gl_debug_msg
-{
- enum mesa_debug_source source;
- enum mesa_debug_type type;
- GLuint id;
- enum mesa_debug_severity severity;
- GLsizei length;
- GLcharARB *message;
-};
-
-struct gl_debug_namespace
-{
- struct _mesa_HashTable *IDs;
- unsigned ZeroID; /* a HashTable won't take zero, so store its state here */
- /** lists of IDs in the hash table at each severity */
- struct simple_node Severity[MESA_DEBUG_SEVERITY_COUNT];
-};
-
-struct gl_debug_state
-{
- GLDEBUGPROC Callback;
- const void *CallbackData;
- GLboolean SyncOutput;
- GLboolean DebugOutput;
- GLboolean Defaults[MAX_DEBUG_GROUP_STACK_DEPTH][MESA_DEBUG_SEVERITY_COUNT][MESA_DEBUG_SOURCE_COUNT][MESA_DEBUG_TYPE_COUNT];
- struct gl_debug_namespace Namespaces[MAX_DEBUG_GROUP_STACK_DEPTH][MESA_DEBUG_SOURCE_COUNT][MESA_DEBUG_TYPE_COUNT];
- struct gl_debug_msg Log[MAX_DEBUG_LOGGED_MESSAGES];
- struct gl_debug_msg DebugGroupMsgs[MAX_DEBUG_GROUP_STACK_DEPTH];
- GLint GroupStackDepth;
- GLint NumMessages;
- GLint NextMsg;
- GLint NextMsgLength; /* redundant, but copied here from Log[NextMsg].length
- for the sake of the offsetof() code in get.c */
-};
-
-/**
* Enum for the OpenGL APIs we know about and may support.
*
* NOTE: This must match the api_enum table in
diff --git a/mesalib/src/mesa/main/texobj.c b/mesalib/src/mesa/main/texobj.c
index 918dd59ed..85246c8ab 100644
--- a/mesalib/src/mesa/main/texobj.c
+++ b/mesalib/src/mesa/main/texobj.c
@@ -1094,7 +1094,7 @@ unbind_texobj_from_texunits(struct gl_context *ctx,
{
GLuint u, tex;
- for (u = 0; u < Elements(ctx->Texture.Unit); u++) {
+ for (u = 0; u < ctx->Texture.NumCurrentTexUsed; u++) {
struct gl_texture_unit *unit = &ctx->Texture.Unit[u];
for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
if (texObj == unit->CurrentTex[tex]) {
@@ -1353,6 +1353,8 @@ _mesa_BindTexture( GLenum target, GLuint texName )
* count hits zero.
*/
_mesa_reference_texobj(&texUnit->CurrentTex[targetIndex], newTexObj);
+ ctx->Texture.NumCurrentTexUsed = MAX2(ctx->Texture.NumCurrentTexUsed,
+ ctx->Texture.CurrentUnit + 1);
ASSERT(texUnit->CurrentTex[targetIndex]);
/* Pass BindTexture call to device driver */
diff --git a/mesalib/src/mesa/main/texparam.c b/mesalib/src/mesa/main/texparam.c
index 40790ff0e..dc17ea584 100644
--- a/mesalib/src/mesa/main/texparam.c
+++ b/mesalib/src/mesa/main/texparam.c
@@ -485,7 +485,7 @@ set_tex_parameteri(struct gl_context *ctx,
const GLuint comp = pname - GL_TEXTURE_SWIZZLE_R_EXT;
const GLint swz = comp_to_swizzle(params[0]);
if (swz < 0) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
+ _mesa_error(ctx, GL_INVALID_ENUM,
"glTexParameter(swizzle 0x%x)", params[0]);
return GL_FALSE;
}
@@ -510,7 +510,7 @@ set_tex_parameteri(struct gl_context *ctx,
set_swizzle_component(&texObj->_Swizzle, comp, swz);
}
else {
- _mesa_error(ctx, GL_INVALID_OPERATION,
+ _mesa_error(ctx, GL_INVALID_ENUM,
"glTexParameter(swizzle 0x%x)", params[comp]);
return GL_FALSE;
}
diff --git a/mesalib/src/mesa/main/texstate.c b/mesalib/src/mesa/main/texstate.c
index b68920ce1..91b290691 100644
--- a/mesalib/src/mesa/main/texstate.c
+++ b/mesalib/src/mesa/main/texstate.c
@@ -40,7 +40,7 @@
#include "teximage.h"
#include "texstate.h"
#include "mtypes.h"
-
+#include "bitset.h"
/**
@@ -108,6 +108,10 @@ _mesa_copy_texture_state( const struct gl_context *src, struct gl_context *dst )
for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
_mesa_reference_texobj(&dst->Texture.Unit[u].CurrentTex[tex],
src->Texture.Unit[u].CurrentTex[tex]);
+ if (src->Texture.Unit[u].CurrentTex[tex]) {
+ dst->Texture.NumCurrentTexUsed =
+ MAX2(dst->Texture.NumCurrentTexUsed, u + 1);
+ }
}
_mesa_unlock_context_textures(dst);
}
@@ -371,7 +375,7 @@ update_texture_matrices( struct gl_context *ctx )
if (_math_matrix_is_dirty(ctx->TextureMatrixStack[u].Top)) {
_math_matrix_analyse( ctx->TextureMatrixStack[u].Top );
- if (ctx->Texture.Unit[u]._ReallyEnabled &&
+ if (ctx->Texture.Unit[u]._Current &&
ctx->TextureMatrixStack[u].Top->type != MATRIX_IDENTITY)
ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(u);
}
@@ -515,83 +519,151 @@ update_texgen(struct gl_context *ctx)
}
}
-/**
- * \note This routine refers to derived texture matrix values to
- * compute the ENABLE_TEXMAT flags, but is only called on
- * _NEW_TEXTURE. On changes to _NEW_TEXTURE_MATRIX, the ENABLE_TEXMAT
- * flags are updated by _mesa_update_texture_matrices, above.
- *
- * \param ctx GL context.
- */
+static struct gl_texture_object *
+update_single_program_texture(struct gl_context *ctx, struct gl_program *prog,
+ int s)
+{
+ gl_texture_index target_index;
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_sampler_object *sampler;
+ int unit;
+
+ if (!(prog->SamplersUsed & (1 << s)))
+ return NULL;
+
+ unit = prog->SamplerUnits[s];
+ texUnit = &ctx->Texture.Unit[unit];
+
+ /* Note: If more than one bit was set in TexturesUsed[unit], then we should
+ * have had the draw call rejected already. From the GL 4.4 specification,
+ * section 7.10 ("Samplers"):
+ *
+ * "It is not allowed to have variables of different sampler types
+ * pointing to the same texture image unit within a program
+ * object. This situation can only be detected at the next rendering
+ * command issued which triggers shader invocations, and an
+ * INVALID_OPERATION error will then be generated."
+ */
+ target_index = ffs(prog->TexturesUsed[unit]) - 1;
+ texObj = texUnit->CurrentTex[target_index];
+
+ sampler = texUnit->Sampler ?
+ texUnit->Sampler : &texObj->Sampler;
+
+ if (likely(texObj)) {
+ if (_mesa_is_texture_complete(texObj, sampler))
+ return texObj;
+
+ _mesa_test_texobj_completeness(ctx, texObj);
+ if (_mesa_is_texture_complete(texObj, sampler))
+ return texObj;
+ }
+
+ /* If we've reached this point, we didn't find a complete texture of the
+ * shader's target. From the GL 4.4 core specification, section 11.1.3.5
+ * ("Texture Access"):
+ *
+ * "If a sampler is used in a shader and the sampler’s associated
+ * texture is not complete, as defined in section 8.17, (0, 0, 0, 1)
+ * will be returned for a non-shadow sampler and 0 for a shadow
+ * sampler."
+ *
+ * Mesa implements this by creating a hidden texture object with a pixel of
+ * that value.
+ */
+ texObj = _mesa_get_fallback_texture(ctx, target_index);
+ assert(texObj);
+
+ return texObj;
+}
+
static void
-update_texture_state( struct gl_context *ctx )
+update_program_texture_state(struct gl_context *ctx, struct gl_program **prog,
+ BITSET_WORD *enabled_texture_units)
{
- GLuint unit;
- struct gl_program *prog[MESA_SHADER_STAGES];
- GLbitfield enabledFragUnits = 0x0;
int i;
for (i = 0; i < MESA_SHADER_STAGES; i++) {
- if (ctx->_Shader->CurrentProgram[i] &&
- ctx->_Shader->CurrentProgram[i]->LinkStatus) {
- prog[i] = ctx->_Shader->CurrentProgram[i]->_LinkedShaders[i]->Program;
- } else {
- if (i == MESA_SHADER_FRAGMENT && ctx->FragmentProgram._Enabled)
- prog[i] = &ctx->FragmentProgram.Current->Base;
- else
- prog[i] = NULL;
+ int s;
+
+ if (!prog[i])
+ continue;
+
+ /* We can't only do the shifting trick as the loop condition because if
+ * sampler 31 is active, the next iteration tries to shift by 32, which is
+ * undefined.
+ */
+ for (s = 0; s < MAX_SAMPLERS && (1 << s) <= prog[i]->SamplersUsed; s++) {
+ struct gl_texture_object *texObj;
+
+ texObj = update_single_program_texture(ctx, prog[i], s);
+ if (texObj) {
+ int unit = prog[i]->SamplerUnits[s];
+ _mesa_reference_texobj(&ctx->Texture.Unit[unit]._Current, texObj);
+ BITSET_SET(enabled_texture_units, unit);
+ ctx->Texture._MaxEnabledTexImageUnit =
+ MAX2(ctx->Texture._MaxEnabledTexImageUnit, (int)unit);
+ }
}
}
- /* TODO: only set this if there are actual changes */
- ctx->NewState |= _NEW_TEXTURE;
+ if (prog[MESA_SHADER_FRAGMENT]) {
+ const GLuint coordMask = (1 << MAX_TEXTURE_COORD_UNITS) - 1;
+ ctx->Texture._EnabledCoordUnits |=
+ (prog[MESA_SHADER_FRAGMENT]->InputsRead >> VARYING_SLOT_TEX0) &
+ coordMask;
+ }
+}
- ctx->Texture._EnabledUnits = 0x0;
- ctx->Texture._GenFlags = 0x0;
- ctx->Texture._TexMatEnabled = 0x0;
- ctx->Texture._TexGenEnabled = 0x0;
- ctx->Texture._MaxEnabledTexImageUnit = -1;
+static void
+update_ff_texture_state(struct gl_context *ctx,
+ BITSET_WORD *enabled_texture_units)
+{
+ int unit;
- /*
- * Update texture unit state.
- */
- for (unit = 0; unit < ctx->Const.MaxCombinedTextureImageUnits; unit++) {
+ for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
- GLbitfield enabledTargetsByStage[MESA_SHADER_STAGES];
- GLbitfield enabledTargets = 0x0;
GLuint texIndex;
- /* Get the bitmask of texture target enables.
- * enableBits will be a mask of the TEXTURE_*_BIT flags indicating
- * which texture targets are enabled (fixed function) or referenced
- * by a fragment program/program. When multiple flags are set, we'll
- * settle on the one with highest priority (see below).
- */
- for (i = 0; i < MESA_SHADER_STAGES; i++) {
- if (prog[i])
- enabledTargetsByStage[i] = prog[i]->TexturesUsed[unit];
- else if (i == MESA_SHADER_FRAGMENT)
- enabledTargetsByStage[i] = texUnit->Enabled;
- else
- enabledTargetsByStage[i] = 0;
- enabledTargets |= enabledTargetsByStage[i];
- }
-
- texUnit->_ReallyEnabled = 0x0;
+ if (texUnit->Enabled == 0x0)
+ continue;
- if (enabledTargets == 0x0) {
- /* neither vertex nor fragment processing uses this unit */
+ /* If a shader already dictated what texture target was used for this
+ * unit, just go along with it.
+ */
+ if (BITSET_TEST(enabled_texture_units, unit))
continue;
- }
- /* Look for the highest priority texture target that's enabled (or used
- * by the vert/frag shaders) and "complete". That's the one we'll use
- * for texturing.
+ /* From the GL 4.4 compat specification, section 16.2 ("Texture Application"):
+ *
+ * "Texturing is enabled or disabled using the generic Enable and
+ * Disable commands, respectively, with the symbolic constants
+ * TEXTURE_1D, TEXTURE_2D, TEXTURE_RECTANGLE, TEXTURE_3D, or
+ * TEXTURE_CUBE_MAP to enable the one-, two-, rectangular,
+ * three-dimensional, or cube map texture, respectively. If more
+ * than one of these textures is enabled, the first one enabled
+ * from the following list is used:
+ *
+ * • cube map texture
+ * • three-dimensional texture
+ * • rectangular texture
+ * • two-dimensional texture
+ * • one-dimensional texture"
*
* Note that the TEXTURE_x_INDEX values are in high to low priority.
+ * Also:
+ *
+ * "If a texture unit is disabled or has an invalid or incomplete
+ * texture (as defined in section 8.17) bound to it, then blending
+ * is disabled for that texture unit. If the texture environment
+ * for a given enabled texture unit references a disabled texture
+ * unit, or an invalid or incomplete texture that is bound to
+ * another unit, then the results of texture blending are
+ * undefined."
*/
for (texIndex = 0; texIndex < NUM_TEXTURE_TARGETS; texIndex++) {
- if (enabledTargets & (1 << texIndex)) {
+ if (texUnit->Enabled & (1 << texIndex)) {
struct gl_texture_object *texObj = texUnit->CurrentTex[texIndex];
struct gl_sampler_object *sampler = texUnit->Sampler ?
texUnit->Sampler : &texObj->Sampler;
@@ -600,62 +672,84 @@ update_texture_state( struct gl_context *ctx )
_mesa_test_texobj_completeness(ctx, texObj);
}
if (_mesa_is_texture_complete(texObj, sampler)) {
- texUnit->_ReallyEnabled = 1 << texIndex;
_mesa_reference_texobj(&texUnit->_Current, texObj);
break;
}
}
}
- if (!texUnit->_ReallyEnabled) {
- if (prog[MESA_SHADER_FRAGMENT]) {
- /* If we get here it means the shader is expecting a texture
- * object, but there isn't one (or it's incomplete). Use the
- * fallback texture.
- */
- struct gl_texture_object *texObj;
- gl_texture_index texTarget;
-
- texTarget = (gl_texture_index) (ffs(enabledTargets) - 1);
- texObj = _mesa_get_fallback_texture(ctx, texTarget);
-
- assert(texObj);
- if (!texObj) {
- /* invalid fallback texture: don't enable the texture unit */
- continue;
- }
-
- _mesa_reference_texobj(&texUnit->_Current, texObj);
- texUnit->_ReallyEnabled = 1 << texTarget;
- }
- else {
- /* fixed-function: texture unit is really disabled */
- continue;
- }
- }
+ if (texIndex == NUM_TEXTURE_TARGETS)
+ continue;
/* if we get here, we know this texture unit is enabled */
+ BITSET_SET(enabled_texture_units, unit);
+ ctx->Texture._MaxEnabledTexImageUnit =
+ MAX2(ctx->Texture._MaxEnabledTexImageUnit, (int)unit);
- ctx->Texture._EnabledUnits |= (1 << unit);
- ctx->Texture._MaxEnabledTexImageUnit = unit;
+ ctx->Texture._EnabledCoordUnits |= 1 << unit;
- if (enabledTargetsByStage[MESA_SHADER_FRAGMENT])
- enabledFragUnits |= (1 << unit);
+ update_tex_combine(ctx, texUnit);
+ }
+}
+
+/**
+ * \note This routine refers to derived texture matrix values to
+ * compute the ENABLE_TEXMAT flags, but is only called on
+ * _NEW_TEXTURE. On changes to _NEW_TEXTURE_MATRIX, the ENABLE_TEXMAT
+ * flags are updated by _mesa_update_texture_matrices, above.
+ *
+ * \param ctx GL context.
+ */
+static void
+update_texture_state( struct gl_context *ctx )
+{
+ struct gl_program *prog[MESA_SHADER_STAGES];
+ int i;
+ int old_max_unit = ctx->Texture._MaxEnabledTexImageUnit;
+ BITSET_DECLARE(enabled_texture_units, MAX_COMBINED_TEXTURE_IMAGE_UNITS);
- if (!prog[MESA_SHADER_FRAGMENT])
- update_tex_combine(ctx, texUnit);
+ for (i = 0; i < MESA_SHADER_STAGES; i++) {
+ if (ctx->_Shader->CurrentProgram[i] &&
+ ctx->_Shader->CurrentProgram[i]->LinkStatus) {
+ prog[i] = ctx->_Shader->CurrentProgram[i]->_LinkedShaders[i]->Program;
+ } else {
+ if (i == MESA_SHADER_FRAGMENT && ctx->FragmentProgram._Enabled)
+ prog[i] = &ctx->FragmentProgram.Current->Base;
+ else
+ prog[i] = NULL;
+ }
}
+ /* TODO: only set this if there are actual changes */
+ ctx->NewState |= _NEW_TEXTURE;
- /* Determine which texture coordinate sets are actually needed */
- if (prog[MESA_SHADER_FRAGMENT]) {
- const GLuint coordMask = (1 << MAX_TEXTURE_COORD_UNITS) - 1;
- ctx->Texture._EnabledCoordUnits
- = (prog[MESA_SHADER_FRAGMENT]->InputsRead >> VARYING_SLOT_TEX0) &
- coordMask;
+ ctx->Texture._GenFlags = 0x0;
+ ctx->Texture._TexMatEnabled = 0x0;
+ ctx->Texture._TexGenEnabled = 0x0;
+ ctx->Texture._MaxEnabledTexImageUnit = -1;
+ ctx->Texture._EnabledCoordUnits = 0x0;
+
+ memset(&enabled_texture_units, 0, sizeof(enabled_texture_units));
+
+ /* First, walk over our programs pulling in all the textures for them.
+ * Programs dictate specific texture targets to be enabled, and for a draw
+ * call to be valid they can't conflict about which texture targets are
+ * used.
+ */
+ update_program_texture_state(ctx, prog, enabled_texture_units);
+
+ /* Also pull in any textures necessary for fixed function fragment shading.
+ */
+ if (!prog[MESA_SHADER_FRAGMENT])
+ update_ff_texture_state(ctx, enabled_texture_units);
+
+ /* Now, clear out the _Current of any disabled texture units. */
+ for (i = 0; i <= ctx->Texture._MaxEnabledTexImageUnit; i++) {
+ if (!BITSET_TEST(enabled_texture_units, i))
+ _mesa_reference_texobj(&ctx->Texture.Unit[i]._Current, NULL);
}
- else {
- ctx->Texture._EnabledCoordUnits = enabledFragUnits;
+ for (i = ctx->Texture._MaxEnabledTexImageUnit + 1; i <= old_max_unit; i++) {
+ _mesa_reference_texobj(&ctx->Texture.Unit[i]._Current, NULL);
}
if (!prog[MESA_SHADER_FRAGMENT] || !prog[MESA_SHADER_VERTEX])
@@ -796,7 +890,6 @@ _mesa_init_texture(struct gl_context *ctx)
/* Texture group */
ctx->Texture.CurrentUnit = 0; /* multitexture */
- ctx->Texture._EnabledUnits = 0x0;
/* Appendix F.2 of the OpenGL ES 3.0 spec says:
*
@@ -824,6 +917,8 @@ _mesa_init_texture(struct gl_context *ctx)
_mesa_reference_buffer_object(ctx, &ctx->Texture.BufferObject,
ctx->Shared->NullBufferObj);
+ ctx->Texture.NumCurrentTexUsed = 0;
+
return GL_TRUE;
}
diff --git a/mesalib/src/mesa/state_tracker/st_atom.c b/mesalib/src/mesa/state_tracker/st_atom.c
index 99e9df26b..625ea2965 100644
--- a/mesalib/src/mesa/state_tracker/st_atom.c
+++ b/mesalib/src/mesa/state_tracker/st_atom.c
@@ -61,6 +61,7 @@ static const struct st_tracked_state *atoms[] =
&st_update_sampler, /* depends on update_*_texture for swizzle */
&st_update_framebuffer,
&st_update_msaa,
+ &st_update_sample_shading,
&st_update_vs_constants,
&st_update_gs_constants,
&st_update_fs_constants,
diff --git a/mesalib/src/mesa/state_tracker/st_atom.h b/mesalib/src/mesa/state_tracker/st_atom.h
index 60d89d75f..c50111d50 100644
--- a/mesalib/src/mesa/state_tracker/st_atom.h
+++ b/mesalib/src/mesa/state_tracker/st_atom.h
@@ -59,6 +59,7 @@ extern const struct st_tracked_state st_update_viewport;
extern const struct st_tracked_state st_update_scissor;
extern const struct st_tracked_state st_update_blend;
extern const struct st_tracked_state st_update_msaa;
+extern const struct st_tracked_state st_update_sample_shading;
extern const struct st_tracked_state st_update_sampler;
extern const struct st_tracked_state st_update_fragment_texture;
extern const struct st_tracked_state st_update_vertex_texture;
diff --git a/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c b/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c
index a17417c35..b195c55b3 100644
--- a/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c
+++ b/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c
@@ -113,6 +113,12 @@ update_framebuffer_state( struct st_context *st )
pipe_surface_reference(&framebuffer->cbufs[i], NULL);
}
+ /* Remove trailing GL_NONE draw buffers. */
+ while (framebuffer->nr_cbufs &&
+ !framebuffer->cbufs[framebuffer->nr_cbufs-1]) {
+ framebuffer->nr_cbufs--;
+ }
+
/*
* Depth/Stencil renderbuffer/surface.
*/
@@ -147,11 +153,10 @@ update_framebuffer_state( struct st_context *st )
}
#endif
- /* _mesa_test_framebuffer_completeness refuses framebuffers with no
- * attachments, so this should never happen.
- */
- assert(framebuffer->width != UINT_MAX);
- assert(framebuffer->height != UINT_MAX);
+ if (framebuffer->width == UINT_MAX)
+ framebuffer->width = 0;
+ if (framebuffer->height == UINT_MAX)
+ framebuffer->height = 0;
cso_set_framebuffer(st->cso_context, framebuffer);
}
diff --git a/mesalib/src/mesa/state_tracker/st_atom_msaa.c b/mesalib/src/mesa/state_tracker/st_atom_msaa.c
index 2f3a42e02..703cb5e75 100644
--- a/mesalib/src/mesa/state_tracker/st_atom_msaa.c
+++ b/mesalib/src/mesa/state_tracker/st_atom_msaa.c
@@ -27,8 +27,10 @@
#include "st_context.h"
+#include "pipe/p_screen.h"
#include "pipe/p_context.h"
#include "st_atom.h"
+#include "st_program.h"
#include "cso_cache/cso_context.h"
#include "util/u_framebuffer.h"
@@ -70,6 +72,18 @@ static void update_sample_mask( struct st_context *st )
}
}
+static void update_sample_shading( struct st_context *st )
+{
+ if (!st->fp)
+ return;
+
+ if (!st->ctx->Extensions.ARB_sample_shading)
+ return;
+
+ cso_set_min_samples(
+ st->cso_context,
+ _mesa_get_min_invocations_per_fragment(st->ctx, &st->fp->Base, false));
+}
const struct st_tracked_state st_update_msaa = {
"st_update_msaa", /* name */
@@ -79,3 +93,12 @@ const struct st_tracked_state st_update_msaa = {
},
update_sample_mask /* update */
};
+
+const struct st_tracked_state st_update_sample_shading = {
+ "st_update_sample_shading", /* name */
+ { /* dirty */
+ (_NEW_MULTISAMPLE | _NEW_PROGRAM | _NEW_BUFFERS), /* mesa */
+ ST_NEW_FRAGMENT_PROGRAM | ST_NEW_FRAMEBUFFER, /* st */
+ },
+ update_sample_shading /* update */
+};
diff --git a/mesalib/src/mesa/state_tracker/st_atom_pixeltransfer.c b/mesalib/src/mesa/state_tracker/st_atom_pixeltransfer.c
index 306eeb153..a04163cc1 100644
--- a/mesalib/src/mesa/state_tracker/st_atom_pixeltransfer.c
+++ b/mesalib/src/mesa/state_tracker/st_atom_pixeltransfer.c
@@ -121,7 +121,7 @@ load_color_map_texture(struct gl_context *ctx, struct pipe_resource *pt)
rgba[2] = ctx->PixelMaps.BtoB.Map[j * bSize / texSize];
rgba[3] = ctx->PixelMaps.AtoA.Map[i * aSize / texSize];
util_pack_color(rgba, pt->format, &uc);
- *(dest + k) = uc.ui;
+ *(dest + k) = uc.ui[0];
}
}
diff --git a/mesalib/src/mesa/state_tracker/st_cb_clear.c b/mesalib/src/mesa/state_tracker/st_cb_clear.c
index fcd7e1382..371f7fcda 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_clear.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_clear.c
@@ -240,6 +240,7 @@ clear_with_quad(struct gl_context *ctx, unsigned clear_buffers)
cso_save_depth_stencil_alpha(st->cso_context);
cso_save_rasterizer(st->cso_context);
cso_save_sample_mask(st->cso_context);
+ cso_save_min_samples(st->cso_context);
cso_save_viewport(st->cso_context);
cso_save_fragment_shader(st->cso_context);
cso_save_stream_outputs(st->cso_context);
@@ -309,6 +310,7 @@ clear_with_quad(struct gl_context *ctx, unsigned clear_buffers)
cso_set_vertex_elements(st->cso_context, 2, st->velems_util_draw);
cso_set_stream_outputs(st->cso_context, 0, NULL, NULL);
cso_set_sample_mask(st->cso_context, ~0);
+ cso_set_min_samples(st->cso_context, 1);
cso_set_rasterizer(st->cso_context, &st->clear.raster);
/* viewport state: viewport matching window dims */
@@ -348,6 +350,7 @@ clear_with_quad(struct gl_context *ctx, unsigned clear_buffers)
cso_restore_depth_stencil_alpha(st->cso_context);
cso_restore_rasterizer(st->cso_context);
cso_restore_sample_mask(st->cso_context);
+ cso_restore_min_samples(st->cso_context);
cso_restore_viewport(st->cso_context);
cso_restore_fragment_shader(st->cso_context);
cso_restore_vertex_shader(st->cso_context);
diff --git a/mesalib/src/mesa/state_tracker/st_cb_drawtex.c b/mesalib/src/mesa/state_tracker/st_cb_drawtex.c
index b0a44fd90..f997e6b00 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_drawtex.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_drawtex.c
@@ -123,7 +123,8 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
/* determine how many enabled sets of texcoords */
numTexCoords = 0;
for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
- if (ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_2D_BIT) {
+ if (ctx->Texture.Unit[i]._Current &&
+ ctx->Texture.Unit[i]._Current->Target == GL_TEXTURE_2D) {
numTexCoords++;
}
}
@@ -192,7 +193,8 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
/* texcoords */
for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
- if (ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_2D_BIT) {
+ if (ctx->Texture.Unit[i]._Current &&
+ ctx->Texture.Unit[i]._Current->Target == GL_TEXTURE_2D) {
struct gl_texture_object *obj = ctx->Texture.Unit[i]._Current;
struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
const GLfloat wt = (GLfloat) img->Width;
diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c
index 70726886e..a245fdf18 100644
--- a/mesalib/src/mesa/state_tracker/st_extensions.c
+++ b/mesalib/src/mesa/state_tracker/st_extensions.c
@@ -425,7 +425,8 @@ void st_init_extensions(struct st_context *st)
{ o(OES_standard_derivatives), PIPE_CAP_SM3 },
{ o(ARB_texture_cube_map_array), PIPE_CAP_CUBE_MAP_ARRAY },
{ o(ARB_texture_multisample), PIPE_CAP_TEXTURE_MULTISAMPLE },
- { o(ARB_texture_query_lod), PIPE_CAP_TEXTURE_QUERY_LOD }
+ { o(ARB_texture_query_lod), PIPE_CAP_TEXTURE_QUERY_LOD },
+ { o(ARB_sample_shading), PIPE_CAP_SAMPLE_SHADING },
};
/* Required: render target and sampler support */
diff --git a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index 15b5279b8..d1c3856b5 100644
--- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -241,7 +241,7 @@ public:
unsigned op;
st_dst_reg dst;
- st_src_reg src[3];
+ st_src_reg src[4];
/** Pointer to the ir source this tree came from for debugging */
ir_instruction *ir;
GLboolean cond_update;
@@ -411,7 +411,12 @@ public:
glsl_to_tgsi_instruction *emit(ir_instruction *ir, unsigned op,
st_dst_reg dst,
st_src_reg src0, st_src_reg src1, st_src_reg src2);
-
+
+ glsl_to_tgsi_instruction *emit(ir_instruction *ir, unsigned op,
+ st_dst_reg dst,
+ st_src_reg src0, st_src_reg src1,
+ st_src_reg src2, st_src_reg src3);
+
unsigned get_opcode(ir_instruction *ir, unsigned op,
st_dst_reg dst,
st_src_reg src0, st_src_reg src1);
@@ -524,8 +529,9 @@ num_inst_src_regs(unsigned opcode)
glsl_to_tgsi_instruction *
glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op,
- st_dst_reg dst,
- st_src_reg src0, st_src_reg src1, st_src_reg src2)
+ st_dst_reg dst,
+ st_src_reg src0, st_src_reg src1,
+ st_src_reg src2, st_src_reg src3)
{
glsl_to_tgsi_instruction *inst = new(mem_ctx) glsl_to_tgsi_instruction();
int num_reladdr = 0, i;
@@ -540,7 +546,9 @@ glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op,
num_reladdr += src0.reladdr != NULL || src0.reladdr2 != NULL;
num_reladdr += src1.reladdr != NULL || src1.reladdr2 != NULL;
num_reladdr += src2.reladdr != NULL || src2.reladdr2 != NULL;
+ num_reladdr += src3.reladdr != NULL || src3.reladdr2 != NULL;
+ reladdr_to_temp(ir, &src3, &num_reladdr);
reladdr_to_temp(ir, &src2, &num_reladdr);
reladdr_to_temp(ir, &src1, &num_reladdr);
reladdr_to_temp(ir, &src0, &num_reladdr);
@@ -556,6 +564,7 @@ glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op,
inst->src[0] = src0;
inst->src[1] = src1;
inst->src[2] = src2;
+ inst->src[3] = src3;
inst->ir = ir;
inst->dead_mask = 0;
@@ -577,7 +586,7 @@ glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op,
}
}
else {
- for (i=0; i<3; i++) {
+ for (i=0; i<4; i++) {
if(inst->src[i].reladdr) {
switch(inst->src[i].file) {
case PROGRAM_STATE_VAR:
@@ -600,12 +609,19 @@ glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op,
return inst;
}
+glsl_to_tgsi_instruction *
+glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op,
+ st_dst_reg dst, st_src_reg src0,
+ st_src_reg src1, st_src_reg src2)
+{
+ return emit(ir, op, dst, src0, src1, src2, undef_src);
+}
glsl_to_tgsi_instruction *
glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op,
st_dst_reg dst, st_src_reg src0, st_src_reg src1)
{
- return emit(ir, op, dst, src0, src1, undef_src);
+ return emit(ir, op, dst, src0, src1, undef_src, undef_src);
}
glsl_to_tgsi_instruction *
@@ -613,13 +629,13 @@ glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op,
st_dst_reg dst, st_src_reg src0)
{
assert(dst.writemask != 0);
- return emit(ir, op, dst, src0, undef_src, undef_src);
+ return emit(ir, op, dst, src0, undef_src, undef_src, undef_src);
}
glsl_to_tgsi_instruction *
glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op)
{
- return emit(ir, op, undef_dst, undef_src, undef_src, undef_src);
+ return emit(ir, op, undef_dst, undef_src, undef_src, undef_src, undef_src);
}
/**
@@ -690,7 +706,10 @@ glsl_to_tgsi_visitor::get_opcode(ir_instruction *ir, unsigned op,
case2fi(SSG, ISSG);
case3(ABS, IABS, IABS);
-
+
+ case2iu(IBFE, UBFE);
+ case2iu(IMSB, UMSB);
+ case2iu(IMUL_HI, UMUL_HI);
default: break;
}
@@ -1934,6 +1953,33 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
emit(ir, TGSI_OPCODE_CMP, result_dst, op[0], op[1], op[2]);
}
break;
+ case ir_triop_bitfield_extract:
+ emit(ir, TGSI_OPCODE_IBFE, result_dst, op[0], op[1], op[2]);
+ break;
+ case ir_quadop_bitfield_insert:
+ emit(ir, TGSI_OPCODE_BFI, result_dst, op[0], op[1], op[2], op[3]);
+ break;
+ case ir_unop_bitfield_reverse:
+ emit(ir, TGSI_OPCODE_BREV, result_dst, op[0]);
+ break;
+ case ir_unop_bit_count:
+ emit(ir, TGSI_OPCODE_POPC, result_dst, op[0]);
+ break;
+ case ir_unop_find_msb:
+ emit(ir, TGSI_OPCODE_IMSB, result_dst, op[0]);
+ break;
+ case ir_unop_find_lsb:
+ emit(ir, TGSI_OPCODE_LSB, result_dst, op[0]);
+ break;
+ case ir_binop_imul_high:
+ emit(ir, TGSI_OPCODE_IMUL_HI, result_dst, op[0], op[1]);
+ break;
+ case ir_triop_fma:
+ /* NOTE: Perhaps there should be a special opcode that enforces fused
+ * mul-add. Just use MAD for now.
+ */
+ emit(ir, TGSI_OPCODE_MAD, result_dst, op[0], op[1], op[2]);
+ break;
case ir_unop_pack_snorm_2x16:
case ir_unop_pack_unorm_2x16:
case ir_unop_pack_half_2x16:
@@ -1947,22 +1993,14 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
case ir_unop_unpack_snorm_4x8:
case ir_unop_unpack_unorm_4x8:
case ir_binop_pack_half_2x16_split:
- case ir_unop_bitfield_reverse:
- case ir_unop_bit_count:
- case ir_unop_find_msb:
- case ir_unop_find_lsb:
case ir_binop_bfm:
- case ir_triop_fma:
case ir_triop_bfi:
- case ir_triop_bitfield_extract:
- case ir_quadop_bitfield_insert:
case ir_quadop_vector:
case ir_binop_vector_extract:
case ir_triop_vector_insert:
case ir_binop_ldexp:
case ir_binop_carry:
case ir_binop_borrow:
- case ir_binop_imul_high:
/* This operation is not supported, or should have already been handled.
*/
assert(!"Invalid ir opcode in glsl_to_tgsi_visitor::visit()");
@@ -4163,7 +4201,11 @@ struct st_translate {
static unsigned mesa_sysval_to_semantic[SYSTEM_VALUE_MAX] = {
TGSI_SEMANTIC_FACE,
TGSI_SEMANTIC_VERTEXID,
- TGSI_SEMANTIC_INSTANCEID
+ TGSI_SEMANTIC_INSTANCEID,
+ TGSI_SEMANTIC_SAMPLEID,
+ TGSI_SEMANTIC_SAMPLEPOS,
+ TGSI_SEMANTIC_SAMPLEMASK,
+ TGSI_SEMANTIC_INVOCATIONID,
};
/**
@@ -4381,7 +4423,8 @@ translate_dst(struct st_translate *t,
break;
case TGSI_PROCESSOR_FRAGMENT:
- if (dst_reg->index >= FRAG_RESULT_COLOR) {
+ if (dst_reg->index == FRAG_RESULT_COLOR ||
+ dst_reg->index >= FRAG_RESULT_DATA0) {
dst = ureg_saturate(dst);
}
break;
@@ -4876,6 +4919,15 @@ st_translate_program(
TGSI_SEMANTIC_COLOR,
outputSemanticIndex[i]);
break;
+ case TGSI_SEMANTIC_SAMPLEMASK:
+ t->outputs[i] = ureg_DECL_output(ureg,
+ TGSI_SEMANTIC_SAMPLEMASK,
+ outputSemanticIndex[i]);
+ /* TODO: If we ever support more than 32 samples, this will have
+ * to become an array.
+ */
+ t->outputs[i] = ureg_writemask(t->outputs[i], TGSI_WRITEMASK_X);
+ break;
default:
assert(!"fragment shader outputs must be POSITION/STENCIL/COLOR");
ret = PIPE_ERROR_BAD_INPUT;
@@ -5343,6 +5395,7 @@ st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
DIV_TO_MUL_RCP |
EXP_TO_EXP2 |
LOG_TO_LOG2 |
+ LDEXP_TO_ARITH |
(options->EmitNoPow ? POW_TO_EXP2 : 0) |
(!ctx->Const.NativeIntegers ? INT_DIV_TO_MUL_RCP : 0));
diff --git a/mesalib/src/mesa/state_tracker/st_manager.c b/mesalib/src/mesa/state_tracker/st_manager.c
index 314d34232..706af7fd1 100644
--- a/mesalib/src/mesa/state_tracker/st_manager.c
+++ b/mesalib/src/mesa/state_tracker/st_manager.c
@@ -183,8 +183,13 @@ st_framebuffer_validate(struct st_framebuffer *stfb,
uint width, height;
unsigned i;
boolean changed = FALSE;
- int32_t new_stamp = p_atomic_read(&stfb->iface->stamp);
+ int32_t new_stamp;
+ /* Check for incomplete framebuffers (e.g. EGL_KHR_surfaceless_context) */
+ if (!stfb->iface)
+ return;
+
+ new_stamp = p_atomic_read(&stfb->iface->stamp);
if (stfb->iface_stamp == new_stamp)
return;
@@ -663,13 +668,11 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi,
}
if (attribs->flags & ST_CONTEXT_FLAG_DEBUG){
- struct gl_debug_state *debug = _mesa_get_debug_state(st->ctx);
- if (!debug) {
+ if (!_mesa_set_debug_state_int(st->ctx, GL_DEBUG_OUTPUT, GL_TRUE)) {
*error = ST_CONTEXT_ERROR_NO_MEMORY;
return NULL;
}
st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_DEBUG_BIT;
- debug->DebugOutput = GL_TRUE;
}
if (attribs->flags & ST_CONTEXT_FLAG_FORWARD_COMPATIBLE)
diff --git a/mesalib/src/mesa/state_tracker/st_program.c b/mesalib/src/mesa/state_tracker/st_program.c
index 2f0ec32f5..f9887a2c4 100644
--- a/mesalib/src/mesa/state_tracker/st_program.c
+++ b/mesalib/src/mesa/state_tracker/st_program.c
@@ -682,6 +682,7 @@ st_translate_fragment_program(struct st_context *st,
/* handle remaining outputs (color) */
for (attr = 0; attr < FRAG_RESULT_MAX; attr++) {
if (outputsWritten & BITFIELD64_BIT(attr)) {
+ int semantic = TGSI_SEMANTIC_COLOR;
switch (attr) {
case FRAG_RESULT_DEPTH:
case FRAG_RESULT_STENCIL:
@@ -689,17 +690,21 @@ st_translate_fragment_program(struct st_context *st,
assert(0);
break;
case FRAG_RESULT_COLOR:
- write_all = GL_TRUE; /* fallthrough */
- default:
- assert(attr == FRAG_RESULT_COLOR ||
- (FRAG_RESULT_DATA0 <= attr && attr < FRAG_RESULT_MAX));
- fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_COLOR;
- fs_output_semantic_index[fs_num_outputs] = numColors;
- outputMapping[attr] = fs_num_outputs;
- numColors++;
+ write_all = GL_TRUE;
+ break;
+ case FRAG_RESULT_SAMPLE_MASK:
+ semantic = TGSI_SEMANTIC_SAMPLEMASK;
break;
}
+ assert(attr == FRAG_RESULT_COLOR ||
+ attr == FRAG_RESULT_SAMPLE_MASK ||
+ (FRAG_RESULT_DATA0 <= attr && attr < FRAG_RESULT_MAX));
+ fs_output_semantic_name[fs_num_outputs] = semantic;
+ fs_output_semantic_index[fs_num_outputs] = numColors;
+ outputMapping[attr] = fs_num_outputs;
+ numColors++;
+
fs_num_outputs++;
}
}
diff --git a/mesalib/src/mesa/swrast/s_context.c b/mesalib/src/mesa/swrast/s_context.c
index 07485006c..ad11aa2c1 100644
--- a/mesalib/src/mesa/swrast/s_context.c
+++ b/mesalib/src/mesa/swrast/s_context.c
@@ -73,7 +73,7 @@ _swrast_update_rasterflags( struct gl_context *ctx )
}
}
if (ctx->Color.ColorLogicOpEnabled) rasterMask |= LOGIC_OP_BIT;
- if (ctx->Texture._EnabledUnits) rasterMask |= TEXTURE_BIT;
+ if (ctx->Texture._MaxEnabledTexImageUnit >= 0) rasterMask |= TEXTURE_BIT;
if ( ctx->ViewportArray[0].X < 0
|| ctx->ViewportArray[0].X + ctx->ViewportArray[0].Width > (GLfloat) ctx->DrawBuffer->Width
|| ctx->ViewportArray[0].Y < 0
@@ -286,7 +286,7 @@ _swrast_update_specular_vertex_add(struct gl_context *ctx)
ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR);
swrast->SpecularVertexAdd = (separateSpecular
- && ctx->Texture._EnabledUnits == 0x0
+ && ctx->Texture._MaxEnabledTexImageUnit == -1
&& !_swrast_use_fragment_program(ctx)
&& !ctx->ATIFragmentShader._Enabled);
}
@@ -523,7 +523,7 @@ _swrast_update_active_attribs(struct gl_context *ctx)
if (swrast->_FogEnabled)
attribsMask |= VARYING_BIT_FOGC;
- attribsMask |= (ctx->Texture._EnabledUnits << VARYING_SLOT_TEX0);
+ attribsMask |= (ctx->Texture._EnabledCoordUnits << VARYING_SLOT_TEX0);
}
swrast->_ActiveAttribMask = attribsMask;
@@ -923,7 +923,7 @@ _swrast_print_vertex( struct gl_context *ctx, const SWvertex *v )
v->attrib[VARYING_SLOT_POS][3]);
for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
- if (ctx->Texture.Unit[i]._ReallyEnabled)
+ if (ctx->Texture.Unit[i]._Current)
_mesa_debug(ctx, "texcoord[%d] %f %f %f %f\n", i,
v->attrib[VARYING_SLOT_TEX0 + i][0],
v->attrib[VARYING_SLOT_TEX0 + i][1],
diff --git a/mesalib/src/mesa/swrast/s_texcombine.c b/mesalib/src/mesa/swrast/s_texcombine.c
index 32d7c0944..c1a152aa8 100644
--- a/mesalib/src/mesa/swrast/s_texcombine.c
+++ b/mesalib/src/mesa/swrast/s_texcombine.c
@@ -189,7 +189,7 @@ texture_combine( struct gl_context *ctx, GLuint unit,
{
const GLuint srcUnit = srcRGB - GL_TEXTURE0;
ASSERT(srcUnit < ctx->Const.MaxTextureUnits);
- if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled)
+ if (!ctx->Texture.Unit[srcUnit]._Current)
goto end;
argRGB[term] = get_texel_array(swrast, srcUnit);
}
@@ -279,7 +279,7 @@ texture_combine( struct gl_context *ctx, GLuint unit,
{
const GLuint srcUnit = srcA - GL_TEXTURE0;
ASSERT(srcUnit < ctx->Const.MaxTextureUnits);
- if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled)
+ if (!ctx->Texture.Unit[srcUnit]._Current)
goto end;
argA[term] = get_texel_array(swrast, srcUnit);
}
@@ -657,7 +657,7 @@ _swrast_texture_span( struct gl_context *ctx, SWspan *span )
for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
- if (texUnit->_ReallyEnabled &&
+ if (texUnit->_Current &&
texUnit->_CurrentCombine->ModeRGB == GL_BUMP_ENVMAP_ATI) {
const GLfloat (*texcoords)[4] = (const GLfloat (*)[4])
span->array->attribs[VARYING_SLOT_TEX0 + unit];
@@ -723,7 +723,7 @@ _swrast_texture_span( struct gl_context *ctx, SWspan *span )
*/
for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
- if (texUnit->_ReallyEnabled &&
+ if (texUnit->_Current &&
texUnit->_CurrentCombine->ModeRGB != GL_BUMP_ENVMAP_ATI) {
const GLfloat (*texcoords)[4] = (const GLfloat (*)[4])
span->array->attribs[VARYING_SLOT_TEX0 + unit];
@@ -787,7 +787,7 @@ _swrast_texture_span( struct gl_context *ctx, SWspan *span )
* We modify the span->color.rgba values.
*/
for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
- if (ctx->Texture.Unit[unit]._ReallyEnabled)
+ if (ctx->Texture.Unit[unit]._Current)
texture_combine(ctx, unit, primary_rgba, swrast->TexelBuffer, span);
}
diff --git a/mesalib/src/mesa/swrast/s_texture.c b/mesalib/src/mesa/swrast/s_texture.c
index c08a4e9d1..9ccd0e347 100644
--- a/mesalib/src/mesa/swrast/s_texture.c
+++ b/mesalib/src/mesa/swrast/s_texture.c
@@ -177,8 +177,8 @@ _swrast_free_texture_image_buffer(struct gl_context *ctx,
* Error checking for debugging only.
*/
static void
-_mesa_check_map_teximage(struct gl_texture_image *texImage,
- GLuint slice, GLuint x, GLuint y, GLuint w, GLuint h)
+check_map_teximage(const struct gl_texture_image *texImage,
+ GLuint slice, GLuint x, GLuint y, GLuint w, GLuint h)
{
if (texImage->TexObject->Target == GL_TEXTURE_1D)
@@ -216,7 +216,16 @@ _swrast_map_teximage(struct gl_context *ctx,
GLint stride, texelSize;
GLuint bw, bh;
- _mesa_check_map_teximage(texImage, slice, x, y, w, h);
+ check_map_teximage(texImage, slice, x, y, w, h);
+
+ if (!swImage->Buffer) {
+ /* Either glTexImage was called with a NULL <pixels> argument or
+ * we ran out of memory when allocating texture memory,
+ */
+ *mapOut = NULL;
+ *rowStrideOut = 0;
+ return;
+ }
texelSize = _mesa_get_format_bytes(texImage->TexFormat);
stride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width);
@@ -225,12 +234,6 @@ _swrast_map_teximage(struct gl_context *ctx,
assert(x % bw == 0);
assert(y % bh == 0);
- if (!swImage->Buffer) {
- /* probably ran out of memory when allocating tex mem */
- *mapOut = NULL;
- return;
- }
-
/* This function can only be used with a swrast-allocated buffer, in which
* case ImageSlices is populated with pointers into Buffer.
*/
@@ -266,7 +269,7 @@ _swrast_map_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
for (level = texObj->BaseLevel; level < MAX_TEXTURE_LEVELS; level++) {
struct gl_texture_image *texImage = texObj->Image[face][level];
struct swrast_texture_image *swImage = swrast_texture_image(texImage);
- unsigned int i;
+ unsigned int i, slices;
if (!texImage)
continue;
@@ -279,7 +282,16 @@ _swrast_map_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
continue;
}
- for (i = 0; i < texture_slices(texImage); i++) {
+ if (!swImage->ImageSlices) {
+ swImage->ImageSlices =
+ calloc(texture_slices(texImage), sizeof(void *));
+ if (!swImage->ImageSlices)
+ continue;
+ }
+
+ slices = texture_slices(texImage);
+
+ for (i = 0; i < slices; i++) {
GLubyte *map;
GLint rowStride;
@@ -317,7 +329,7 @@ _swrast_unmap_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
for (level = texObj->BaseLevel; level < MAX_TEXTURE_LEVELS; level++) {
struct gl_texture_image *texImage = texObj->Image[face][level];
struct swrast_texture_image *swImage = swrast_texture_image(texImage);
- unsigned int i;
+ unsigned int i, slices;
if (!texImage)
continue;
@@ -325,7 +337,12 @@ _swrast_unmap_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
if (swImage->Buffer)
return;
- for (i = 0; i < texture_slices(texImage); i++) {
+ if (!swImage->ImageSlices)
+ continue;
+
+ slices = texture_slices(texImage);
+
+ for (i = 0; i < slices; i++) {
if (swImage->ImageSlices[i]) {
ctx->Driver.UnmapTextureImage(ctx, texImage, i);
swImage->ImageSlices[i] = NULL;
@@ -342,16 +359,13 @@ _swrast_unmap_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
void
_swrast_map_textures(struct gl_context *ctx)
{
- GLbitfield enabledUnits = ctx->Texture._EnabledUnits;
+ int unit;
- /* loop over enabled texture units */
- while (enabledUnits) {
- GLuint unit = ffs(enabledUnits) - 1;
+ for (unit = 0; unit <= ctx->Texture._MaxEnabledTexImageUnit; unit++) {
struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
-
- _swrast_map_texture(ctx, texObj);
- enabledUnits &= ~(1 << unit);
+ if (texObj)
+ _swrast_map_texture(ctx, texObj);
}
}
@@ -362,15 +376,11 @@ _swrast_map_textures(struct gl_context *ctx)
void
_swrast_unmap_textures(struct gl_context *ctx)
{
- GLbitfield enabledUnits = ctx->Texture._EnabledUnits;
-
- /* loop over enabled texture units */
- while (enabledUnits) {
- GLuint unit = ffs(enabledUnits) - 1;
+ int unit;
+ for (unit = 0; unit <= ctx->Texture._MaxEnabledTexImageUnit; unit++) {
struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
-
- _swrast_unmap_texture(ctx, texObj);
- enabledUnits &= ~(1 << unit);
+ if (texObj)
+ _swrast_unmap_texture(ctx, texObj);
}
}
diff --git a/mesalib/src/mesa/swrast/s_triangle.c b/mesalib/src/mesa/swrast/s_triangle.c
index 00383fb84..164906643 100644
--- a/mesalib/src/mesa/swrast/s_triangle.c
+++ b/mesalib/src/mesa/swrast/s_triangle.c
@@ -1071,8 +1071,8 @@ _swrast_choose_triangle( struct gl_context *ctx )
if (ctx->Texture._EnabledCoordUnits == 0x1
&& !_swrast_use_fragment_program(ctx)
&& !ctx->ATIFragmentShader._Enabled
- && ctx->Texture._EnabledUnits == 0x1
- && ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT
+ && ctx->Texture._MaxEnabledTexImageUnit == 0
+ && ctx->Texture.Unit[0]._Current->Target == GL_TEXTURE_2D
&& samp->WrapS == GL_REPEAT
&& samp->WrapT == GL_REPEAT
&& texObj2D->_Swizzle == SWIZZLE_NOOP
diff --git a/mesalib/src/mesa/swrast_setup/ss_context.c b/mesalib/src/mesa/swrast_setup/ss_context.c
index 12a47358f..0b3b9e4df 100644
--- a/mesalib/src/mesa/swrast_setup/ss_context.c
+++ b/mesalib/src/mesa/swrast_setup/ss_context.c
@@ -287,7 +287,8 @@ _swsetup_Translate( struct gl_context *ctx, const void *vertex, SWvertex *dest )
_tnl_get_attr( ctx, vertex, _TNL_ATTRIB_COLOR0,
dest->attrib[VARYING_SLOT_COL0] );
- UNCLAMPED_FLOAT_TO_RGBA_CHAN( dest->color, tmp );
+
+ UNCLAMPED_FLOAT_TO_RGBA_CHAN(dest->color, dest->attrib[VARYING_SLOT_COL0]);
_tnl_get_attr( ctx, vertex, _TNL_ATTRIB_COLOR1,
dest->attrib[VARYING_SLOT_COL1]);