From 91e91b72f07f4e61db17ee86c6933a7217f0e25c Mon Sep 17 00:00:00 2001 From: marha Date: Fri, 22 Jul 2011 08:22:17 +0200 Subject: mesa git update 22 July 2011 --- mesalib/Makefile | 16 +- mesalib/configure.ac | 13 +- mesalib/src/gallium/auxiliary/util/u_pstipple.c | 891 ++++++++++---------- mesalib/src/gallium/auxiliary/util/u_vbuf_mgr.c | 10 + mesalib/src/glsl/Makefile | 1 + mesalib/src/glsl/SConscript | 1 + mesalib/src/glsl/ast_function.cpp | 6 +- mesalib/src/glsl/ast_to_hir.cpp | 37 + mesalib/src/glsl/glsl_types.cpp | 16 + mesalib/src/glsl/glsl_types.h | 962 +++++++++++----------- mesalib/src/glsl/ir.cpp | 17 +- mesalib/src/glsl/ir.h | 30 + mesalib/src/glsl/ir_function_detect_recursion.cpp | 371 +++++++++ mesalib/src/glsl/linker.cpp | 6 +- mesalib/src/glsl/s_expression.cpp | 64 +- mesalib/src/glsl/s_expression.h | 2 +- mesalib/src/mesa/drivers/common/driverfuncs.c | 2 - mesalib/src/mesa/drivers/common/meta.c | 273 +++--- mesalib/src/mesa/drivers/common/meta.h | 229 +++-- mesalib/src/mesa/main/dd.h | 69 +- mesalib/src/mesa/main/fbobject.c | 23 +- mesalib/src/mesa/main/teximage.c | 49 +- mesalib/src/mesa/main/texstore.c | 9 +- mesalib/src/mesa/state_tracker/st_cb_texture.c | 83 -- mesalib/src/mesa/state_tracker/st_manager.c | 2 +- 25 files changed, 1809 insertions(+), 1373 deletions(-) create mode 100644 mesalib/src/glsl/ir_function_detect_recursion.cpp (limited to 'mesalib') diff --git a/mesalib/Makefile b/mesalib/Makefile index b0a2d8065..817f3d370 100644 --- a/mesalib/Makefile +++ b/mesalib/Makefile @@ -203,12 +203,6 @@ EXTRA_FILES = \ IGNORE_FILES = \ -x autogen.sh -DEPEND_FILES = \ - src/mesa/depend \ - src/glx/depend \ - src/glw/depend \ - src/glu/sgi/depend - parsers: configure -@touch $(TOP)/configs/current @@ -231,15 +225,9 @@ AUTOCONF = autoconf AC_FLAGS = aclocal.m4: configure.ac acinclude.m4 $(ACLOCAL) $(ACLOCAL_FLAGS) -configure: rm_depend configure.ac aclocal.m4 acinclude.m4 +configure: configure.ac aclocal.m4 acinclude.m4 $(AUTOCONF) $(AC_FLAGS) -rm_depend: - @for dep in $(DEPEND_FILES) ; do \ - rm -f $$dep ; \ - touch $$dep ; \ - done - manifest.txt: .git ( \ ls -1 $(EXTRA_FILES) ; \ @@ -269,4 +257,4 @@ md5: $(ARCHIVES) @-md5sum $(PACKAGE_NAME).tar.bz2 @-md5sum $(PACKAGE_NAME).zip -.PHONY: tarballs rm_depend md5 +.PHONY: tarballs md5 diff --git a/mesalib/configure.ac b/mesalib/configure.ac index 5c76c2865..86ba87b39 100644 --- a/mesalib/configure.ac +++ b/mesalib/configure.ac @@ -1073,11 +1073,6 @@ AC_SUBST([MESA_MODULES]) AC_SUBST([HAVE_XF86VIDMODE]) -PKG_CHECK_MODULES([LIBDRM_RADEON], - [libdrm_radeon >= $LIBDRM_RADEON_REQUIRED], - HAVE_LIBDRM_RADEON=yes, - HAVE_LIBDRM_RADEON=no) - dnl dnl More GLX setup dnl @@ -1270,6 +1265,11 @@ esac case $DRI_DIRS in *radeon*|*r200*|*r300*|*r600*) + PKG_CHECK_MODULES([LIBDRM_RADEON], + [libdrm_radeon >= $LIBDRM_RADEON_REQUIRED], + HAVE_LIBDRM_RADEON=yes, + HAVE_LIBDRM_RADEON=no) + if test "x$HAVE_LIBDRM_RADEON" = xyes; then RADEON_CFLAGS="-DHAVE_LIBDRM_RADEON=1 $LIBDRM_RADEON_CFLAGS" RADEON_LDFLAGS=$LIBDRM_RADEON_LIBS @@ -1906,6 +1906,7 @@ if test "x$with_gallium_drivers" != x; then gallium_check_st "svga/drm" "dri-vmwgfx" "xorg-vmwgfx" "xa-vmwgfx" ;; xi915) + PKG_CHECK_MODULES([INTEL], [libdrm_intel >= $LIBDRM_INTEL_REQUIRED]) GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS i915 softpipe" if test "x$MESA_LLVM" = x1; then GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS llvmpipe" @@ -1914,6 +1915,7 @@ if test "x$with_gallium_drivers" != x; then gallium_check_st "i915/drm" "dri-i915" "xorg-i915" ;; xi965) + PKG_CHECK_MODULES([INTEL], [libdrm_intel >= $LIBDRM_INTEL_REQUIRED]) GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS i965 softpipe" if test "x$MESA_LLVM" = x1; then GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS llvmpipe" @@ -1930,6 +1932,7 @@ if test "x$with_gallium_drivers" != x; then gallium_check_st "r600/drm" "dri-r600" "" "" "xvmc-r600" "vdpau-r600" "va-r600" ;; xnouveau) + PKG_CHECK_MODULES([NOUVEAU], [libdrm_nouveau >= $LIBDRM_NOUVEAU_REQUIRED]) GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS nouveau nvfx nv50 nvc0" gallium_check_st "nouveau/drm" "dri-nouveau" "xorg-nouveau" "" "xvmc-nouveau" ;; diff --git a/mesalib/src/gallium/auxiliary/util/u_pstipple.c b/mesalib/src/gallium/auxiliary/util/u_pstipple.c index 27f72e967..ac0df8c1a 100644 --- a/mesalib/src/gallium/auxiliary/util/u_pstipple.c +++ b/mesalib/src/gallium/auxiliary/util/u_pstipple.c @@ -1,434 +1,457 @@ -/************************************************************************** - * - * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. - * Copyright 2010 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * Polygon stipple helper module. Drivers/GPUs which don't support polygon - * stipple natively can use this module to simulate it. - * - * Basically, modify fragment shader to sample the 32x32 stipple pattern - * texture and do a fragment kill for the 'off' bits. - * - * This was originally a 'draw' module stage, but since we don't need - * vertex window coords or anything, it can be a stand-alone utility module. - * - * Authors: Brian Paul - */ - - -#include "pipe/p_context.h" -#include "pipe/p_defines.h" -#include "pipe/p_shader_tokens.h" -#include "util/u_inlines.h" - -#include "util/u_format.h" -#include "util/u_memory.h" -#include "util/u_pstipple.h" -#include "util/u_sampler.h" - -#include "tgsi/tgsi_transform.h" -#include "tgsi/tgsi_dump.h" - -/** Approx number of new tokens for instructions in pstip_transform_inst() */ -#define NUM_NEW_TOKENS 50 - - -static void -util_pstipple_update_stipple_texture(struct pipe_context *pipe, - struct pipe_resource *tex, - const uint32_t pattern[32]) -{ - static const uint bit31 = 1 << 31; - struct pipe_transfer *transfer; - ubyte *data; - int i, j; - - /* map texture memory */ - transfer = pipe_get_transfer(pipe, tex, 0, 0, - PIPE_TRANSFER_WRITE, 0, 0, 32, 32); - data = pipe->transfer_map(pipe, transfer); - - /* - * Load alpha texture. - * Note: 0 means keep the fragment, 255 means kill it. - * We'll negate the texel value and use KILP which kills if value - * is negative. - */ - for (i = 0; i < 32; i++) { - for (j = 0; j < 32; j++) { - if (pattern[i] & (bit31 >> j)) { - /* fragment "on" */ - data[i * transfer->stride + j] = 0; - } - else { - /* fragment "off" */ - data[i * transfer->stride + j] = 255; - } - } - } - - /* unmap */ - pipe->transfer_unmap(pipe, transfer); - pipe->transfer_destroy(pipe, transfer); -} - - -/** - * Create a 32x32 alpha8 texture that encodes the given stipple pattern. - */ -struct pipe_resource * -util_pstipple_create_stipple_texture(struct pipe_context *pipe, - const uint32_t pattern[32]) -{ - struct pipe_screen *screen = pipe->screen; - struct pipe_resource templat, *tex; - - memset(&templat, 0, sizeof(templat)); - templat.target = PIPE_TEXTURE_2D; - templat.format = PIPE_FORMAT_A8_UNORM; - templat.last_level = 0; - templat.width0 = 32; - templat.height0 = 32; - templat.depth0 = 1; - templat.array_size = 1; - templat.bind = PIPE_BIND_SAMPLER_VIEW; - - tex = screen->resource_create(screen, &templat); - - if (tex) - util_pstipple_update_stipple_texture(pipe, tex, pattern); - - return tex; -} - - -/** - * Create sampler view to sample the stipple texture. - */ -struct pipe_sampler_view * -util_pstipple_create_sampler_view(struct pipe_context *pipe, - struct pipe_resource *tex) -{ - struct pipe_sampler_view templat, *sv; - - u_sampler_view_default_template(&templat, tex, tex->format); - sv = pipe->create_sampler_view(pipe, tex, &templat); - - return sv; -} - - -/** - * Create the sampler CSO that'll be used for stippling. - */ -void * -util_pstipple_create_sampler(struct pipe_context *pipe) -{ - struct pipe_sampler_state templat; - void *s; - - memset(&templat, 0, sizeof(templat)); - templat.wrap_s = PIPE_TEX_WRAP_REPEAT; - templat.wrap_t = PIPE_TEX_WRAP_REPEAT; - templat.wrap_r = PIPE_TEX_WRAP_REPEAT; - templat.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; - templat.min_img_filter = PIPE_TEX_FILTER_NEAREST; - templat.mag_img_filter = PIPE_TEX_FILTER_NEAREST; - templat.normalized_coords = 1; - templat.min_lod = 0.0f; - templat.max_lod = 0.0f; - - s = pipe->create_sampler_state(pipe, &templat); - return s; -} - - - -/** - * Subclass of tgsi_transform_context, used for transforming the - * user's fragment shader to add the extra texture sample and fragment kill - * instructions. - */ -struct pstip_transform_context { - struct tgsi_transform_context base; - uint tempsUsed; /**< bitmask */ - int wincoordInput; - int maxInput; - uint samplersUsed; /**< bitfield of samplers used */ - int freeSampler; /** an available sampler for the pstipple */ - int texTemp; /**< temp registers */ - int numImmed; - boolean firstInstruction; -}; - - -/** - * TGSI declaration transform callback. - * Look for a free sampler, a free input attrib, and two free temp regs. - */ -static void -pstip_transform_decl(struct tgsi_transform_context *ctx, - struct tgsi_full_declaration *decl) -{ - struct pstip_transform_context *pctx = - (struct pstip_transform_context *) ctx; - - if (decl->Declaration.File == TGSI_FILE_SAMPLER) { - uint i; - for (i = decl->Range.First; - i <= decl->Range.Last; i++) { - pctx->samplersUsed |= 1 << i; - } - } - else if (decl->Declaration.File == TGSI_FILE_INPUT) { - pctx->maxInput = MAX2(pctx->maxInput, (int) decl->Range.Last); - if (decl->Semantic.Name == TGSI_SEMANTIC_POSITION) - pctx->wincoordInput = (int) decl->Range.First; - } - else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) { - uint i; - for (i = decl->Range.First; - i <= decl->Range.Last; i++) { - pctx->tempsUsed |= (1 << i); - } - } - - ctx->emit_declaration(ctx, decl); -} - - -static void -pstip_transform_immed(struct tgsi_transform_context *ctx, - struct tgsi_full_immediate *immed) -{ - struct pstip_transform_context *pctx = - (struct pstip_transform_context *) ctx; - pctx->numImmed++; -} - - -/** - * Find the lowest zero bit in the given word, or -1 if bitfield is all ones. - */ -static int -free_bit(uint bitfield) -{ - return ffs(~bitfield) - 1; -} - - -/** - * TGSI instruction transform callback. - * Replace writes to result.color w/ a temp reg. - * Upon END instruction, insert texture sampling code for antialiasing. - */ -static void -pstip_transform_inst(struct tgsi_transform_context *ctx, - struct tgsi_full_instruction *inst) -{ - struct pstip_transform_context *pctx = - (struct pstip_transform_context *) ctx; - - if (pctx->firstInstruction) { - /* emit our new declarations before the first instruction */ - - struct tgsi_full_declaration decl; - struct tgsi_full_instruction newInst; - uint i; - int wincoordInput; - - /* find free sampler */ - pctx->freeSampler = free_bit(pctx->samplersUsed); - if (pctx->freeSampler >= PIPE_MAX_SAMPLERS) - pctx->freeSampler = PIPE_MAX_SAMPLERS - 1; - - if (pctx->wincoordInput < 0) - wincoordInput = pctx->maxInput + 1; - else - wincoordInput = pctx->wincoordInput; - - /* find one free temp reg */ - for (i = 0; i < 32; i++) { - if ((pctx->tempsUsed & (1 << i)) == 0) { - /* found a free temp */ - if (pctx->texTemp < 0) - pctx->texTemp = i; - else - break; - } - } - assert(pctx->texTemp >= 0); - - if (pctx->wincoordInput < 0) { - /* declare new position input reg */ - decl = tgsi_default_full_declaration(); - decl.Declaration.File = TGSI_FILE_INPUT; - decl.Declaration.Interpolate = TGSI_INTERPOLATE_LINEAR; - decl.Declaration.Semantic = 1; - decl.Semantic.Name = TGSI_SEMANTIC_POSITION; - decl.Semantic.Index = 0; - decl.Range.First = - decl.Range.Last = wincoordInput; - ctx->emit_declaration(ctx, &decl); - } - - /* declare new sampler */ - decl = tgsi_default_full_declaration(); - decl.Declaration.File = TGSI_FILE_SAMPLER; - decl.Range.First = - decl.Range.Last = pctx->freeSampler; - ctx->emit_declaration(ctx, &decl); - - /* declare new temp regs */ - decl = tgsi_default_full_declaration(); - decl.Declaration.File = TGSI_FILE_TEMPORARY; - decl.Range.First = - decl.Range.Last = pctx->texTemp; - ctx->emit_declaration(ctx, &decl); - - /* emit immediate = {1/32, 1/32, 1, 1} - * The index/position of this immediate will be pctx->numImmed - */ - { - static const float value[4] = { 1.0/32, 1.0/32, 1.0, 1.0 }; - struct tgsi_full_immediate immed; - uint size = 4; - immed = tgsi_default_full_immediate(); - immed.Immediate.NrTokens = 1 + size; /* one for the token itself */ - immed.u[0].Float = value[0]; - immed.u[1].Float = value[1]; - immed.u[2].Float = value[2]; - immed.u[3].Float = value[3]; - ctx->emit_immediate(ctx, &immed); - } - - pctx->firstInstruction = FALSE; - - - /* - * Insert new MUL/TEX/KILP instructions at start of program - * Take gl_FragCoord, divide by 32 (stipple size), sample the - * texture and kill fragment if needed. - * - * We'd like to use non-normalized texcoords to index into a RECT - * texture, but we can only use REPEAT wrap mode with normalized - * texcoords. Darn. - */ - - /* XXX invert wincoord if origin isn't lower-left... */ - - /* MUL texTemp, INPUT[wincoord], 1/32; */ - newInst = tgsi_default_full_instruction(); - newInst.Instruction.Opcode = TGSI_OPCODE_MUL; - newInst.Instruction.NumDstRegs = 1; - newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; - newInst.Dst[0].Register.Index = pctx->texTemp; - newInst.Instruction.NumSrcRegs = 2; - newInst.Src[0].Register.File = TGSI_FILE_INPUT; - newInst.Src[0].Register.Index = wincoordInput; - newInst.Src[1].Register.File = TGSI_FILE_IMMEDIATE; - newInst.Src[1].Register.Index = pctx->numImmed; - ctx->emit_instruction(ctx, &newInst); - - /* TEX texTemp, texTemp, sampler; */ - newInst = tgsi_default_full_instruction(); - newInst.Instruction.Opcode = TGSI_OPCODE_TEX; - newInst.Instruction.NumDstRegs = 1; - newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; - newInst.Dst[0].Register.Index = pctx->texTemp; - newInst.Instruction.NumSrcRegs = 2; - newInst.Instruction.Texture = TRUE; - newInst.Texture.Texture = TGSI_TEXTURE_2D; - newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY; - newInst.Src[0].Register.Index = pctx->texTemp; - newInst.Src[1].Register.File = TGSI_FILE_SAMPLER; - newInst.Src[1].Register.Index = pctx->freeSampler; - ctx->emit_instruction(ctx, &newInst); - - /* KIL -texTemp; # if -texTemp < 0, KILL fragment */ - newInst = tgsi_default_full_instruction(); - newInst.Instruction.Opcode = TGSI_OPCODE_KIL; - newInst.Instruction.NumDstRegs = 0; - newInst.Instruction.NumSrcRegs = 1; - newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY; - newInst.Src[0].Register.Index = pctx->texTemp; - newInst.Src[0].Register.Negate = 1; - ctx->emit_instruction(ctx, &newInst); - } - - /* emit this instruction */ - ctx->emit_instruction(ctx, inst); -} - - -/** - * Given a fragment shader, return a new fragment shader which - * samples a stipple texture and executes KILL. - */ -struct pipe_shader_state * -util_pstipple_create_fragment_shader(struct pipe_context *pipe, - struct pipe_shader_state *fs, - unsigned *samplerUnitOut) -{ - struct pipe_shader_state *new_fs; - struct pstip_transform_context transform; - const uint newLen = tgsi_num_tokens(fs->tokens) + NUM_NEW_TOKENS; - - new_fs = MALLOC(sizeof(*new_fs)); - if (!new_fs) - return NULL; - - new_fs->tokens = tgsi_alloc_tokens(newLen); - if (!new_fs->tokens) { - FREE(new_fs); - return NULL; - } - - memset(&transform, 0, sizeof(transform)); - transform.wincoordInput = -1; - transform.maxInput = -1; - transform.texTemp = -1; - transform.firstInstruction = TRUE; - transform.base.transform_instruction = pstip_transform_inst; - transform.base.transform_declaration = pstip_transform_decl; - transform.base.transform_immediate = pstip_transform_immed; - - tgsi_transform_shader(fs->tokens, - (struct tgsi_token *) new_fs->tokens, - newLen, &transform.base); - -#if 0 /* DEBUG */ - tgsi_dump(fs->tokens, 0); - tgsi_dump(pstip_fs.tokens, 0); -#endif - - assert(transform.freeSampler < PIPE_MAX_SAMPLERS); - *samplerUnitOut = transform.freeSampler; - - return new_fs; -} - +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2010 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * Polygon stipple helper module. Drivers/GPUs which don't support polygon + * stipple natively can use this module to simulate it. + * + * Basically, modify fragment shader to sample the 32x32 stipple pattern + * texture and do a fragment kill for the 'off' bits. + * + * This was originally a 'draw' module stage, but since we don't need + * vertex window coords or anything, it can be a stand-alone utility module. + * + * Authors: Brian Paul + */ + + +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_shader_tokens.h" +#include "util/u_inlines.h" + +#include "util/u_format.h" +#include "util/u_memory.h" +#include "util/u_pstipple.h" +#include "util/u_sampler.h" + +#include "tgsi/tgsi_transform.h" +#include "tgsi/tgsi_dump.h" +#include "tgsi/tgsi_scan.h" + +/** Approx number of new tokens for instructions in pstip_transform_inst() */ +#define NUM_NEW_TOKENS 50 + + +static void +util_pstipple_update_stipple_texture(struct pipe_context *pipe, + struct pipe_resource *tex, + const uint32_t pattern[32]) +{ + static const uint bit31 = 1 << 31; + struct pipe_transfer *transfer; + ubyte *data; + int i, j; + + /* map texture memory */ + transfer = pipe_get_transfer(pipe, tex, 0, 0, + PIPE_TRANSFER_WRITE, 0, 0, 32, 32); + data = pipe->transfer_map(pipe, transfer); + + /* + * Load alpha texture. + * Note: 0 means keep the fragment, 255 means kill it. + * We'll negate the texel value and use KILP which kills if value + * is negative. + */ + for (i = 0; i < 32; i++) { + for (j = 0; j < 32; j++) { + if (pattern[i] & (bit31 >> j)) { + /* fragment "on" */ + data[i * transfer->stride + j] = 0; + } + else { + /* fragment "off" */ + data[i * transfer->stride + j] = 255; + } + } + } + + /* unmap */ + pipe->transfer_unmap(pipe, transfer); + pipe->transfer_destroy(pipe, transfer); +} + + +/** + * Create a 32x32 alpha8 texture that encodes the given stipple pattern. + */ +struct pipe_resource * +util_pstipple_create_stipple_texture(struct pipe_context *pipe, + const uint32_t pattern[32]) +{ + struct pipe_screen *screen = pipe->screen; + struct pipe_resource templat, *tex; + + memset(&templat, 0, sizeof(templat)); + templat.target = PIPE_TEXTURE_2D; + templat.format = PIPE_FORMAT_A8_UNORM; + templat.last_level = 0; + templat.width0 = 32; + templat.height0 = 32; + templat.depth0 = 1; + templat.array_size = 1; + templat.bind = PIPE_BIND_SAMPLER_VIEW; + + tex = screen->resource_create(screen, &templat); + + if (tex) + util_pstipple_update_stipple_texture(pipe, tex, pattern); + + return tex; +} + + +/** + * Create sampler view to sample the stipple texture. + */ +struct pipe_sampler_view * +util_pstipple_create_sampler_view(struct pipe_context *pipe, + struct pipe_resource *tex) +{ + struct pipe_sampler_view templat, *sv; + + u_sampler_view_default_template(&templat, tex, tex->format); + sv = pipe->create_sampler_view(pipe, tex, &templat); + + return sv; +} + + +/** + * Create the sampler CSO that'll be used for stippling. + */ +void * +util_pstipple_create_sampler(struct pipe_context *pipe) +{ + struct pipe_sampler_state templat; + void *s; + + memset(&templat, 0, sizeof(templat)); + templat.wrap_s = PIPE_TEX_WRAP_REPEAT; + templat.wrap_t = PIPE_TEX_WRAP_REPEAT; + templat.wrap_r = PIPE_TEX_WRAP_REPEAT; + templat.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; + templat.min_img_filter = PIPE_TEX_FILTER_NEAREST; + templat.mag_img_filter = PIPE_TEX_FILTER_NEAREST; + templat.normalized_coords = 1; + templat.min_lod = 0.0f; + templat.max_lod = 0.0f; + + s = pipe->create_sampler_state(pipe, &templat); + return s; +} + + + +/** + * Subclass of tgsi_transform_context, used for transforming the + * user's fragment shader to add the extra texture sample and fragment kill + * instructions. + */ +struct pstip_transform_context { + struct tgsi_transform_context base; + struct tgsi_shader_info info; + uint tempsUsed; /**< bitmask */ + int wincoordInput; + int maxInput; + uint samplersUsed; /**< bitfield of samplers used */ + int freeSampler; /** an available sampler for the pstipple */ + int texTemp; /**< temp registers */ + int numImmed; + boolean firstInstruction; + uint coordOrigin; +}; + + +/** + * TGSI declaration transform callback. + * Track samplers used, temps used, inputs used. + */ +static void +pstip_transform_decl(struct tgsi_transform_context *ctx, + struct tgsi_full_declaration *decl) +{ + struct pstip_transform_context *pctx = + (struct pstip_transform_context *) ctx; + + /* XXX we can use tgsi_shader_info instead of some of this */ + + if (decl->Declaration.File == TGSI_FILE_SAMPLER) { + uint i; + for (i = decl->Range.First; i <= decl->Range.Last; i++) { + pctx->samplersUsed |= 1 << i; + } + } + else if (decl->Declaration.File == TGSI_FILE_INPUT) { + pctx->maxInput = MAX2(pctx->maxInput, (int) decl->Range.Last); + if (decl->Semantic.Name == TGSI_SEMANTIC_POSITION) + pctx->wincoordInput = (int) decl->Range.First; + } + else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) { + uint i; + for (i = decl->Range.First; i <= decl->Range.Last; i++) { + pctx->tempsUsed |= (1 << i); + } + } + + ctx->emit_declaration(ctx, decl); +} + + +static void +pstip_transform_immed(struct tgsi_transform_context *ctx, + struct tgsi_full_immediate *immed) +{ + struct pstip_transform_context *pctx = + (struct pstip_transform_context *) ctx; + pctx->numImmed++; +} + + +/** + * Find the lowest zero bit in the given word, or -1 if bitfield is all ones. + */ +static int +free_bit(uint bitfield) +{ + return ffs(~bitfield) - 1; +} + + +/** + * TGSI instruction transform callback. + * Before the first instruction, insert our new code to sample the + * stipple texture (using the fragment coord register) then kill the + * fragment if the stipple texture bit is off. + * + * Insert: + * declare new registers + * MUL texTemp, INPUT[wincoord], 1/32; + * TEX texTemp, texTemp, sampler; + * KIL -texTemp; # if -texTemp < 0, KILL fragment + * [...original code...] + */ +static void +pstip_transform_inst(struct tgsi_transform_context *ctx, + struct tgsi_full_instruction *inst) +{ + struct pstip_transform_context *pctx = + (struct pstip_transform_context *) ctx; + + if (pctx->firstInstruction) { + /* emit our new declarations before the first instruction */ + + struct tgsi_full_declaration decl; + struct tgsi_full_instruction newInst; + uint i; + int wincoordInput; + + /* find free texture sampler */ + pctx->freeSampler = free_bit(pctx->samplersUsed); + if (pctx->freeSampler >= PIPE_MAX_SAMPLERS) + pctx->freeSampler = PIPE_MAX_SAMPLERS - 1; + + if (pctx->wincoordInput < 0) + wincoordInput = pctx->maxInput + 1; + else + wincoordInput = pctx->wincoordInput; + + /* find one free temp register */ + for (i = 0; i < 32; i++) { + if ((pctx->tempsUsed & (1 << i)) == 0) { + /* found a free temp */ + if (pctx->texTemp < 0) + pctx->texTemp = i; + else + break; + } + } + assert(pctx->texTemp >= 0); + + if (pctx->wincoordInput < 0) { + /* declare new position input reg */ + decl = tgsi_default_full_declaration(); + decl.Declaration.File = TGSI_FILE_INPUT; + decl.Declaration.Interpolate = TGSI_INTERPOLATE_LINEAR; + decl.Declaration.Semantic = 1; + decl.Semantic.Name = TGSI_SEMANTIC_POSITION; + decl.Semantic.Index = 0; + decl.Range.First = + decl.Range.Last = wincoordInput; + ctx->emit_declaration(ctx, &decl); + } + + /* declare new sampler */ + decl = tgsi_default_full_declaration(); + decl.Declaration.File = TGSI_FILE_SAMPLER; + decl.Range.First = + decl.Range.Last = pctx->freeSampler; + ctx->emit_declaration(ctx, &decl); + + /* declare new temp regs */ + decl = tgsi_default_full_declaration(); + decl.Declaration.File = TGSI_FILE_TEMPORARY; + decl.Range.First = + decl.Range.Last = pctx->texTemp; + ctx->emit_declaration(ctx, &decl); + + /* emit immediate = {1/32, 1/32, 1, 1} + * The index/position of this immediate will be pctx->numImmed + */ + { + static const float value[4] = { 1.0/32, 1.0/32, 1.0, 1.0 }; + struct tgsi_full_immediate immed; + uint size = 4; + immed = tgsi_default_full_immediate(); + immed.Immediate.NrTokens = 1 + size; /* one for the token itself */ + immed.u[0].Float = value[0]; + immed.u[1].Float = value[1]; + immed.u[2].Float = value[2]; + immed.u[3].Float = value[3]; + ctx->emit_immediate(ctx, &immed); + } + + pctx->firstInstruction = FALSE; + + + /* + * Insert new MUL/TEX/KILP instructions at start of program + * Take gl_FragCoord, divide by 32 (stipple size), sample the + * texture and kill fragment if needed. + * + * We'd like to use non-normalized texcoords to index into a RECT + * texture, but we can only use REPEAT wrap mode with normalized + * texcoords. Darn. + */ + + /* XXX invert wincoord if origin isn't lower-left... */ + + /* MUL texTemp, INPUT[wincoord], 1/32; */ + newInst = tgsi_default_full_instruction(); + newInst.Instruction.Opcode = TGSI_OPCODE_MUL; + newInst.Instruction.NumDstRegs = 1; + newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; + newInst.Dst[0].Register.Index = pctx->texTemp; + newInst.Instruction.NumSrcRegs = 2; + newInst.Src[0].Register.File = TGSI_FILE_INPUT; + newInst.Src[0].Register.Index = wincoordInput; + newInst.Src[1].Register.File = TGSI_FILE_IMMEDIATE; + newInst.Src[1].Register.Index = pctx->numImmed; + ctx->emit_instruction(ctx, &newInst); + + /* TEX texTemp, texTemp, sampler; */ + newInst = tgsi_default_full_instruction(); + newInst.Instruction.Opcode = TGSI_OPCODE_TEX; + newInst.Instruction.NumDstRegs = 1; + newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; + newInst.Dst[0].Register.Index = pctx->texTemp; + newInst.Instruction.NumSrcRegs = 2; + newInst.Instruction.Texture = TRUE; + newInst.Texture.Texture = TGSI_TEXTURE_2D; + newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY; + newInst.Src[0].Register.Index = pctx->texTemp; + newInst.Src[1].Register.File = TGSI_FILE_SAMPLER; + newInst.Src[1].Register.Index = pctx->freeSampler; + ctx->emit_instruction(ctx, &newInst); + + /* KIL -texTemp; # if -texTemp < 0, KILL fragment */ + newInst = tgsi_default_full_instruction(); + newInst.Instruction.Opcode = TGSI_OPCODE_KIL; + newInst.Instruction.NumDstRegs = 0; + newInst.Instruction.NumSrcRegs = 1; + newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY; + newInst.Src[0].Register.Index = pctx->texTemp; + newInst.Src[0].Register.Negate = 1; + ctx->emit_instruction(ctx, &newInst); + } + + /* emit this instruction */ + ctx->emit_instruction(ctx, inst); +} + + +/** + * Given a fragment shader, return a new fragment shader which + * samples a stipple texture and executes KILL. + */ +struct pipe_shader_state * +util_pstipple_create_fragment_shader(struct pipe_context *pipe, + struct pipe_shader_state *fs, + unsigned *samplerUnitOut) +{ + struct pipe_shader_state *new_fs; + struct pstip_transform_context transform; + const uint newLen = tgsi_num_tokens(fs->tokens) + NUM_NEW_TOKENS; + unsigned i; + + new_fs = MALLOC(sizeof(*new_fs)); + if (!new_fs) + return NULL; + + new_fs->tokens = tgsi_alloc_tokens(newLen); + if (!new_fs->tokens) { + FREE(new_fs); + return NULL; + } + + /* Setup shader transformation info/context. + */ + memset(&transform, 0, sizeof(transform)); + transform.wincoordInput = -1; + transform.maxInput = -1; + transform.texTemp = -1; + transform.firstInstruction = TRUE; + transform.coordOrigin = TGSI_FS_COORD_ORIGIN_UPPER_LEFT; + transform.base.transform_instruction = pstip_transform_inst; + transform.base.transform_declaration = pstip_transform_decl; + transform.base.transform_immediate = pstip_transform_immed; + + tgsi_scan_shader(fs->tokens, &transform.info); + + /* find fragment coordinate origin property */ + for (i = 0; i < transform.info.num_properties; i++) { + if (transform.info.properties[i].name == TGSI_PROPERTY_FS_COORD_ORIGIN) + transform.coordOrigin = transform.info.properties[i].data[0]; + } + + tgsi_transform_shader(fs->tokens, + (struct tgsi_token *) new_fs->tokens, + newLen, &transform.base); + +#if 0 /* DEBUG */ + tgsi_dump(fs->tokens, 0); + tgsi_dump(new_fs->tokens, 0); +#endif + + assert(transform.freeSampler < PIPE_MAX_SAMPLERS); + *samplerUnitOut = transform.freeSampler; + + return new_fs; +} + diff --git a/mesalib/src/gallium/auxiliary/util/u_vbuf_mgr.c b/mesalib/src/gallium/auxiliary/util/u_vbuf_mgr.c index 374fc336b..19eb689cf 100644 --- a/mesalib/src/gallium/auxiliary/util/u_vbuf_mgr.c +++ b/mesalib/src/gallium/auxiliary/util/u_vbuf_mgr.c @@ -79,6 +79,8 @@ struct u_vbuf_mgr_priv { void *saved_ve, *fallback_ve; boolean ve_binding_lock; + unsigned saved_buffer_offset[PIPE_MAX_ATTRIBS]; + boolean any_user_vbs; boolean incompatible_vb_layout; }; @@ -488,6 +490,7 @@ void u_vbuf_mgr_set_vertex_buffers(struct u_vbuf_mgr *mgrb, pipe_resource_reference(&mgr->b.vertex_buffer[i].buffer, vb->buffer); pipe_resource_reference(&mgr->b.real_vertex_buffer[i], NULL); + mgr->saved_buffer_offset[i] = vb->buffer_offset; if (!vb->buffer) { continue; @@ -647,6 +650,13 @@ u_vbuf_mgr_draw_begin(struct u_vbuf_mgr *mgrb, void u_vbuf_mgr_draw_end(struct u_vbuf_mgr *mgrb) { struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb; + unsigned i; + + /* buffer offsets were modified in u_vbuf_upload_buffers */ + if (mgr->any_user_vbs) { + for (i = 0; i < mgr->b.nr_vertex_buffers; i++) + mgr->b.vertex_buffer[i].buffer_offset = mgr->saved_buffer_offset[i]; + } if (mgr->fallback_ve) { u_vbuf_translate_end(mgr); diff --git a/mesalib/src/glsl/Makefile b/mesalib/src/glsl/Makefile index e0776c1b5..d1422c2a4 100644 --- a/mesalib/src/glsl/Makefile +++ b/mesalib/src/glsl/Makefile @@ -39,6 +39,7 @@ CXX_SOURCES = \ ir.cpp \ ir_expression_flattening.cpp \ ir_function_can_inline.cpp \ + ir_function_detect_recursion.cpp \ ir_function.cpp \ ir_hierarchical_visitor.cpp \ ir_hv_accept.cpp \ diff --git a/mesalib/src/glsl/SConscript b/mesalib/src/glsl/SConscript index 1441cc74b..ea104abb8 100644 --- a/mesalib/src/glsl/SConscript +++ b/mesalib/src/glsl/SConscript @@ -50,6 +50,7 @@ glsl_sources = [ 'ir.cpp', 'ir_expression_flattening.cpp', 'ir_function_can_inline.cpp', + 'ir_function_detect_recursion.cpp', 'ir_function.cpp', 'ir_hierarchical_visitor.cpp', 'ir_hv_accept.cpp', diff --git a/mesalib/src/glsl/ast_function.cpp b/mesalib/src/glsl/ast_function.cpp index 60a2c617f..bdb73f487 100644 --- a/mesalib/src/glsl/ast_function.cpp +++ b/mesalib/src/glsl/ast_function.cpp @@ -62,8 +62,10 @@ process_parameters(exec_list *instructions, exec_list *actual_parameters, * * \param return_type Return type of the function. May be \c NULL. * \param name Name of the function. - * \param parameters Parameter list for the function. This may be either a - * formal or actual parameter list. Only the type is used. + * \param parameters List of \c ir_instruction nodes representing the + * parameter list for the function. This may be either a + * formal (\c ir_variable) or actual (\c ir_rvalue) + * parameter list. Only the type is used. * * \return * A ralloced string representing the prototype of the function. diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp index 2e54e8c22..c0524bf0b 100644 --- a/mesalib/src/glsl/ast_to_hir.cpp +++ b/mesalib/src/glsl/ast_to_hir.cpp @@ -83,6 +83,8 @@ _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) foreach_list_typed (ast_node, ast, link, & state->translation_unit) ast->hir(instructions, state); + + detect_recursion_unlinked(state, instructions); } @@ -2704,6 +2706,17 @@ ast_declarator_list::hir(exec_list *instructions, : "and integer"); } + /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec: + * + * "[Sampler types] can only be declared as function + * parameters or uniform variables (see Section 4.3.5 + * "Uniform")". + */ + if (var_type->contains_sampler() && + !this->type->qualifier.flags.q.uniform) { + _mesa_glsl_error(&loc, state, "samplers must be declared uniform"); + } + /* Process the initializer and add its instructions to a temporary * list. This list will be added to the instruction stream (below) after * the declaration is added. This is done because in some cases (such as @@ -2864,6 +2877,18 @@ ast_parameter_declarator::hir(exec_list *instructions, */ apply_type_qualifier_to_variable(& this->type->qualifier, var, state, & loc); + /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec: + * + * "Samplers cannot be treated as l-values; hence cannot be used + * as out or inout function parameters, nor can they be assigned + * into." + */ + if ((var->mode == ir_var_inout || var->mode == ir_var_out) + && type->contains_sampler()) { + _mesa_glsl_error(&loc, state, "out and inout parameters cannot contain samplers"); + type = glsl_type::error_type; + } + instructions->push_tail(var); /* Parameter declarations do not have r-values. @@ -2992,6 +3017,18 @@ ast_function::hir(exec_list *instructions, "function `%s' return type has qualifiers", name); } + /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec: + * + * "[Sampler types] can only be declared as function parameters + * or uniform variables (see Section 4.3.5 "Uniform")". + */ + if (return_type->contains_sampler()) { + YYLTYPE loc = this->get_location(); + _mesa_glsl_error(&loc, state, + "function `%s' return type can't contain a sampler", + name); + } + /* Verify that this function's signature either doesn't match a previously * seen signature for a function with the same name, or, if a match is found, * that the previously seen signature does not have an associated definition. diff --git a/mesalib/src/glsl/glsl_types.cpp b/mesalib/src/glsl/glsl_types.cpp index 78d10bd93..a5e21bbb9 100644 --- a/mesalib/src/glsl/glsl_types.cpp +++ b/mesalib/src/glsl/glsl_types.cpp @@ -111,6 +111,22 @@ add_types_to_symbol_table(glsl_symbol_table *symtab, } } +bool +glsl_type::contains_sampler() const +{ + if (this->is_array()) { + return this->fields.array->contains_sampler(); + } else if (this->is_record()) { + for (unsigned int i = 0; i < this->length; i++) { + if (this->fields.structure[i].type->contains_sampler()) + return true; + } + return false; + } else { + return this->is_sampler(); + } +} + void glsl_type::generate_100ES_types(glsl_symbol_table *symtab) { diff --git a/mesalib/src/glsl/glsl_types.h b/mesalib/src/glsl/glsl_types.h index e4c84c953..87f57e7c7 100644 --- a/mesalib/src/glsl/glsl_types.h +++ b/mesalib/src/glsl/glsl_types.h @@ -1,478 +1,484 @@ -/* -*- c++ -*- */ -/* - * Copyright © 2009 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#pragma once -#ifndef GLSL_TYPES_H -#define GLSL_TYPES_H - -#include -#include - -extern "C" { -#include "GL/gl.h" -} - -#include "ralloc.h" - -struct _mesa_glsl_parse_state; -struct glsl_symbol_table; - -extern "C" void -_mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state); - -extern "C" void -_mesa_glsl_release_types(void); - -enum glsl_base_type { - GLSL_TYPE_UINT = 0, - GLSL_TYPE_INT, - GLSL_TYPE_FLOAT, - GLSL_TYPE_BOOL, - GLSL_TYPE_SAMPLER, - GLSL_TYPE_STRUCT, - GLSL_TYPE_ARRAY, - GLSL_TYPE_VOID, - GLSL_TYPE_ERROR -}; - -enum glsl_sampler_dim { - GLSL_SAMPLER_DIM_1D = 0, - GLSL_SAMPLER_DIM_2D, - GLSL_SAMPLER_DIM_3D, - GLSL_SAMPLER_DIM_CUBE, - GLSL_SAMPLER_DIM_RECT, - GLSL_SAMPLER_DIM_BUF -}; - - -struct glsl_type { - GLenum gl_type; - glsl_base_type base_type; - - unsigned sampler_dimensionality:3; /**< \see glsl_sampler_dim */ - unsigned sampler_shadow:1; - unsigned sampler_array:1; - unsigned sampler_type:2; /**< Type of data returned using this sampler. - * only \c GLSL_TYPE_FLOAT, \c GLSL_TYPE_INT, - * and \c GLSL_TYPE_UINT are valid. - */ - - /* Callers of this ralloc-based new need not call delete. It's - * easier to just ralloc_free 'mem_ctx' (or any of its ancestors). */ - static void* operator new(size_t size) - { - if (glsl_type::mem_ctx == NULL) { - glsl_type::mem_ctx = ralloc_context(NULL); - assert(glsl_type::mem_ctx != NULL); - } - - void *type; - - type = ralloc_size(glsl_type::mem_ctx, size); - assert(type != NULL); - - return type; - } - - /* If the user *does* call delete, that's OK, we will just - * ralloc_free in that case. */ - static void operator delete(void *type) - { - ralloc_free(type); - } - - /** - * \name Vector and matrix element counts - * - * For scalars, each of these values will be 1. For non-numeric types - * these will be 0. - */ - /*@{*/ - unsigned vector_elements:3; /**< 1, 2, 3, or 4 vector elements. */ - unsigned matrix_columns:3; /**< 1, 2, 3, or 4 matrix columns. */ - /*@}*/ - - /** - * Name of the data type - * - * This may be \c NULL for anonymous structures, for arrays, or for - * function types. - */ - const char *name; - - /** - * For \c GLSL_TYPE_ARRAY, this is the length of the array. For - * \c GLSL_TYPE_STRUCT, it is the number of elements in the structure and - * the number of values pointed to by \c fields.structure (below). - */ - unsigned length; - - /** - * Subtype of composite data types. - */ - union { - const struct glsl_type *array; /**< Type of array elements. */ - const struct glsl_type *parameters; /**< Parameters to function. */ - struct glsl_struct_field *structure; /**< List of struct fields. */ - } fields; - - - /** - * \name Pointers to various public type singletons - */ - /*@{*/ - static const glsl_type *const error_type; - static const glsl_type *const void_type; - static const glsl_type *const int_type; - static const glsl_type *const ivec4_type; - static const glsl_type *const uint_type; - static const glsl_type *const uvec2_type; - static const glsl_type *const uvec3_type; - static const glsl_type *const uvec4_type; - static const glsl_type *const float_type; - static const glsl_type *const vec2_type; - static const glsl_type *const vec3_type; - static const glsl_type *const vec4_type; - static const glsl_type *const bool_type; - static const glsl_type *const mat2_type; - static const glsl_type *const mat2x3_type; - static const glsl_type *const mat2x4_type; - static const glsl_type *const mat3x2_type; - static const glsl_type *const mat3_type; - static const glsl_type *const mat3x4_type; - static const glsl_type *const mat4x2_type; - static const glsl_type *const mat4x3_type; - static const glsl_type *const mat4_type; - /*@}*/ - - - /** - * For numeric and boolean derrived 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 - * all other types, including arrays of numeric or boolean types, the - * error type is returned. - */ - const glsl_type *get_base_type() const; - - /** - * Query the type of elements in an array - * - * \return - * Pointer to the type of elements in the array for array types, or \c NULL - * for non-array types. - */ - const glsl_type *element_type() const - { - return is_array() ? fields.array : NULL; - } - - /** - * Get the instance of a built-in scalar, vector, or matrix type - */ - static const glsl_type *get_instance(unsigned base_type, unsigned rows, - unsigned columns); - - /** - * Get the instance of an array type - */ - static const glsl_type *get_array_instance(const glsl_type *base, - unsigned elements); - - /** - * Get the instance of a record type - */ - static const glsl_type *get_record_instance(const glsl_struct_field *fields, - unsigned num_fields, - const char *name); - - /** - * Query the total number of scalars that make up a scalar, vector or matrix - */ - unsigned components() const - { - return vector_elements * matrix_columns; - } - - /** - * Calculate the number of components slots required to hold this type - * - * This is used to determine how many uniform or varying locations a type - * might occupy. - */ - unsigned component_slots() const; - - - /** - * Query whether or not a type is a scalar (non-vector and non-matrix). - */ - bool is_scalar() const - { - return (vector_elements == 1) - && (base_type >= GLSL_TYPE_UINT) - && (base_type <= GLSL_TYPE_BOOL); - } - - /** - * Query whether or not a type is a vector - */ - bool is_vector() const - { - return (vector_elements > 1) - && (matrix_columns == 1) - && (base_type >= GLSL_TYPE_UINT) - && (base_type <= GLSL_TYPE_BOOL); - } - - /** - * Query whether or not a type is a matrix - */ - bool is_matrix() const - { - /* GLSL only has float matrices. */ - return (matrix_columns > 1) && (base_type == GLSL_TYPE_FLOAT); - } - - /** - * Query whether or not a type is a non-array numeric type - */ - bool is_numeric() const - { - return (base_type >= GLSL_TYPE_UINT) && (base_type <= GLSL_TYPE_FLOAT); - } - - /** - * Query whether or not a type is an integral type - */ - bool is_integer() const - { - return (base_type == GLSL_TYPE_UINT) || (base_type == GLSL_TYPE_INT); - } - - /** - * Query whether or not a type is a float type - */ - bool is_float() const - { - return base_type == GLSL_TYPE_FLOAT; - } - - /** - * Query whether or not a type is a non-array boolean type - */ - bool is_boolean() const - { - return base_type == GLSL_TYPE_BOOL; - } - - /** - * Query whether or not a type is a sampler - */ - bool is_sampler() const - { - return base_type == GLSL_TYPE_SAMPLER; - } - - /** - * Query whether or not a type is an array - */ - bool is_array() const - { - return base_type == GLSL_TYPE_ARRAY; - } - - /** - * Query whether or not a type is a record - */ - bool is_record() const - { - return base_type == GLSL_TYPE_STRUCT; - } - - /** - * Query whether or not a type is the void type singleton. - */ - bool is_void() const - { - return base_type == GLSL_TYPE_VOID; - } - - /** - * Query whether or not a type is the error type singleton. - */ - bool is_error() const - { - return base_type == GLSL_TYPE_ERROR; - } - - /** - * Query the full type of a matrix row - * - * \return - * If the type is not a matrix, \c glsl_type::error_type is returned. - * Otherwise a type matching the rows of the matrix is returned. - */ - const glsl_type *row_type() const - { - return is_matrix() - ? get_instance(base_type, matrix_columns, 1) - : error_type; - } - - /** - * Query the full type of a matrix column - * - * \return - * If the type is not a matrix, \c glsl_type::error_type is returned. - * Otherwise a type matching the columns of the matrix is returned. - */ - const glsl_type *column_type() const - { - return is_matrix() - ? get_instance(base_type, vector_elements, 1) - : error_type; - } - - - /** - * Get the type of a structure field - * - * \return - * Pointer to the type of the named field. If the type is not a structure - * or the named field does not exist, \c glsl_type::error_type is returned. - */ - const glsl_type *field_type(const char *name) const; - - - /** - * Get the location of a filed within a record type - */ - int field_index(const char *name) const; - - - /** - * Query the number of elements in an array type - * - * \return - * The number of elements in the array for array types or -1 for non-array - * types. If the number of elements in the array has not yet been declared, - * zero is returned. - */ - int array_size() const - { - return is_array() ? length : -1; - } - -private: - /** - * ralloc context for all glsl_type allocations - * - * Set on the first call to \c glsl_type::new. - */ - static void *mem_ctx; - - void init_ralloc_type_ctx(void); - - /** Constructor for vector and matrix types */ - glsl_type(GLenum gl_type, - glsl_base_type base_type, unsigned vector_elements, - unsigned matrix_columns, const char *name); - - /** Constructor for sampler types */ - glsl_type(GLenum gl_type, - enum glsl_sampler_dim dim, bool shadow, bool array, - unsigned type, const char *name); - - /** Constructor for record types */ - glsl_type(const glsl_struct_field *fields, unsigned num_fields, - const char *name); - - /** Constructor for array types */ - glsl_type(const glsl_type *array, unsigned length); - - /** Hash table containing the known array types. */ - static struct hash_table *array_types; - - /** Hash table containing the known record types. */ - static struct hash_table *record_types; - - static int record_key_compare(const void *a, const void *b); - static unsigned record_key_hash(const void *key); - - /** - * \name Pointers to various type singletons - */ - /*@{*/ - static const glsl_type _error_type; - static const glsl_type _void_type; - static const glsl_type _sampler3D_type; - static const glsl_type builtin_core_types[]; - static const glsl_type builtin_structure_types[]; - static const glsl_type builtin_110_deprecated_structure_types[]; - static const glsl_type builtin_110_types[]; - static const glsl_type builtin_120_types[]; - static const glsl_type builtin_130_types[]; - static const glsl_type builtin_ARB_texture_rectangle_types[]; - static const glsl_type builtin_EXT_texture_array_types[]; - static const glsl_type builtin_EXT_texture_buffer_object_types[]; - /*@}*/ - - /** - * \name Methods to populate a symbol table with built-in types. - * - * \internal - * This is one of the truely annoying things about C++. Methods that are - * completely internal and private to a type still have to be advertised to - * the world in a public header file. - */ - /*@{*/ - static void generate_100ES_types(glsl_symbol_table *); - static void generate_110_types(glsl_symbol_table *); - static void generate_120_types(glsl_symbol_table *); - static void generate_130_types(glsl_symbol_table *); - static void generate_ARB_texture_rectangle_types(glsl_symbol_table *, bool); - static void generate_EXT_texture_array_types(glsl_symbol_table *, bool); - static void generate_OES_texture_3D_types(glsl_symbol_table *, bool); - /*@}*/ - - /** - * \name Friend functions. - * - * These functions are friends because they must have C linkage and the - * need to call various private methods or access various private static - * data. - */ - /*@{*/ - friend void _mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *); - friend void _mesa_glsl_release_types(void); - /*@}*/ -}; - -struct glsl_struct_field { - const struct glsl_type *type; - const char *name; -}; - -#endif /* GLSL_TYPES_H */ +/* -*- c++ -*- */ +/* + * Copyright © 2009 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#pragma once +#ifndef GLSL_TYPES_H +#define GLSL_TYPES_H + +#include +#include + +extern "C" { +#include "GL/gl.h" +} + +#include "ralloc.h" + +struct _mesa_glsl_parse_state; +struct glsl_symbol_table; + +extern "C" void +_mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state); + +extern "C" void +_mesa_glsl_release_types(void); + +enum glsl_base_type { + GLSL_TYPE_UINT = 0, + GLSL_TYPE_INT, + GLSL_TYPE_FLOAT, + GLSL_TYPE_BOOL, + GLSL_TYPE_SAMPLER, + GLSL_TYPE_STRUCT, + GLSL_TYPE_ARRAY, + GLSL_TYPE_VOID, + GLSL_TYPE_ERROR +}; + +enum glsl_sampler_dim { + GLSL_SAMPLER_DIM_1D = 0, + GLSL_SAMPLER_DIM_2D, + GLSL_SAMPLER_DIM_3D, + GLSL_SAMPLER_DIM_CUBE, + GLSL_SAMPLER_DIM_RECT, + GLSL_SAMPLER_DIM_BUF +}; + + +struct glsl_type { + GLenum gl_type; + glsl_base_type base_type; + + unsigned sampler_dimensionality:3; /**< \see glsl_sampler_dim */ + unsigned sampler_shadow:1; + unsigned sampler_array:1; + unsigned sampler_type:2; /**< Type of data returned using this sampler. + * only \c GLSL_TYPE_FLOAT, \c GLSL_TYPE_INT, + * and \c GLSL_TYPE_UINT are valid. + */ + + /* Callers of this ralloc-based new need not call delete. It's + * easier to just ralloc_free 'mem_ctx' (or any of its ancestors). */ + static void* operator new(size_t size) + { + if (glsl_type::mem_ctx == NULL) { + glsl_type::mem_ctx = ralloc_context(NULL); + assert(glsl_type::mem_ctx != NULL); + } + + void *type; + + type = ralloc_size(glsl_type::mem_ctx, size); + assert(type != NULL); + + return type; + } + + /* If the user *does* call delete, that's OK, we will just + * ralloc_free in that case. */ + static void operator delete(void *type) + { + ralloc_free(type); + } + + /** + * \name Vector and matrix element counts + * + * For scalars, each of these values will be 1. For non-numeric types + * these will be 0. + */ + /*@{*/ + unsigned vector_elements:3; /**< 1, 2, 3, or 4 vector elements. */ + unsigned matrix_columns:3; /**< 1, 2, 3, or 4 matrix columns. */ + /*@}*/ + + /** + * Name of the data type + * + * This may be \c NULL for anonymous structures, for arrays, or for + * function types. + */ + const char *name; + + /** + * For \c GLSL_TYPE_ARRAY, this is the length of the array. For + * \c GLSL_TYPE_STRUCT, it is the number of elements in the structure and + * the number of values pointed to by \c fields.structure (below). + */ + unsigned length; + + /** + * Subtype of composite data types. + */ + union { + const struct glsl_type *array; /**< Type of array elements. */ + const struct glsl_type *parameters; /**< Parameters to function. */ + struct glsl_struct_field *structure; /**< List of struct fields. */ + } fields; + + + /** + * \name Pointers to various public type singletons + */ + /*@{*/ + static const glsl_type *const error_type; + static const glsl_type *const void_type; + static const glsl_type *const int_type; + static const glsl_type *const ivec4_type; + static const glsl_type *const uint_type; + static const glsl_type *const uvec2_type; + static const glsl_type *const uvec3_type; + static const glsl_type *const uvec4_type; + static const glsl_type *const float_type; + static const glsl_type *const vec2_type; + static const glsl_type *const vec3_type; + static const glsl_type *const vec4_type; + static const glsl_type *const bool_type; + static const glsl_type *const mat2_type; + static const glsl_type *const mat2x3_type; + static const glsl_type *const mat2x4_type; + static const glsl_type *const mat3x2_type; + static const glsl_type *const mat3_type; + static const glsl_type *const mat3x4_type; + static const glsl_type *const mat4x2_type; + static const glsl_type *const mat4x3_type; + static const glsl_type *const mat4_type; + /*@}*/ + + + /** + * For numeric and boolean derrived 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 + * all other types, including arrays of numeric or boolean types, the + * error type is returned. + */ + const glsl_type *get_base_type() const; + + /** + * Query the type of elements in an array + * + * \return + * Pointer to the type of elements in the array for array types, or \c NULL + * for non-array types. + */ + const glsl_type *element_type() const + { + return is_array() ? fields.array : NULL; + } + + /** + * Get the instance of a built-in scalar, vector, or matrix type + */ + static const glsl_type *get_instance(unsigned base_type, unsigned rows, + unsigned columns); + + /** + * Get the instance of an array type + */ + static const glsl_type *get_array_instance(const glsl_type *base, + unsigned elements); + + /** + * Get the instance of a record type + */ + static const glsl_type *get_record_instance(const glsl_struct_field *fields, + unsigned num_fields, + const char *name); + + /** + * Query the total number of scalars that make up a scalar, vector or matrix + */ + unsigned components() const + { + return vector_elements * matrix_columns; + } + + /** + * Calculate the number of components slots required to hold this type + * + * This is used to determine how many uniform or varying locations a type + * might occupy. + */ + unsigned component_slots() const; + + + /** + * Query whether or not a type is a scalar (non-vector and non-matrix). + */ + bool is_scalar() const + { + return (vector_elements == 1) + && (base_type >= GLSL_TYPE_UINT) + && (base_type <= GLSL_TYPE_BOOL); + } + + /** + * Query whether or not a type is a vector + */ + bool is_vector() const + { + return (vector_elements > 1) + && (matrix_columns == 1) + && (base_type >= GLSL_TYPE_UINT) + && (base_type <= GLSL_TYPE_BOOL); + } + + /** + * Query whether or not a type is a matrix + */ + bool is_matrix() const + { + /* GLSL only has float matrices. */ + return (matrix_columns > 1) && (base_type == GLSL_TYPE_FLOAT); + } + + /** + * Query whether or not a type is a non-array numeric type + */ + bool is_numeric() const + { + return (base_type >= GLSL_TYPE_UINT) && (base_type <= GLSL_TYPE_FLOAT); + } + + /** + * Query whether or not a type is an integral type + */ + bool is_integer() const + { + return (base_type == GLSL_TYPE_UINT) || (base_type == GLSL_TYPE_INT); + } + + /** + * Query whether or not a type is a float type + */ + bool is_float() const + { + return base_type == GLSL_TYPE_FLOAT; + } + + /** + * Query whether or not a type is a non-array boolean type + */ + bool is_boolean() const + { + return base_type == GLSL_TYPE_BOOL; + } + + /** + * Query whether or not a type is a sampler + */ + bool is_sampler() const + { + return base_type == GLSL_TYPE_SAMPLER; + } + + /** + * Query whether or not type is a sampler, or for struct and array + * types, contains a sampler. + */ + bool contains_sampler() const; + + /** + * Query whether or not a type is an array + */ + bool is_array() const + { + return base_type == GLSL_TYPE_ARRAY; + } + + /** + * Query whether or not a type is a record + */ + bool is_record() const + { + return base_type == GLSL_TYPE_STRUCT; + } + + /** + * Query whether or not a type is the void type singleton. + */ + bool is_void() const + { + return base_type == GLSL_TYPE_VOID; + } + + /** + * Query whether or not a type is the error type singleton. + */ + bool is_error() const + { + return base_type == GLSL_TYPE_ERROR; + } + + /** + * Query the full type of a matrix row + * + * \return + * If the type is not a matrix, \c glsl_type::error_type is returned. + * Otherwise a type matching the rows of the matrix is returned. + */ + const glsl_type *row_type() const + { + return is_matrix() + ? get_instance(base_type, matrix_columns, 1) + : error_type; + } + + /** + * Query the full type of a matrix column + * + * \return + * If the type is not a matrix, \c glsl_type::error_type is returned. + * Otherwise a type matching the columns of the matrix is returned. + */ + const glsl_type *column_type() const + { + return is_matrix() + ? get_instance(base_type, vector_elements, 1) + : error_type; + } + + + /** + * Get the type of a structure field + * + * \return + * Pointer to the type of the named field. If the type is not a structure + * or the named field does not exist, \c glsl_type::error_type is returned. + */ + const glsl_type *field_type(const char *name) const; + + + /** + * Get the location of a filed within a record type + */ + int field_index(const char *name) const; + + + /** + * Query the number of elements in an array type + * + * \return + * The number of elements in the array for array types or -1 for non-array + * types. If the number of elements in the array has not yet been declared, + * zero is returned. + */ + int array_size() const + { + return is_array() ? length : -1; + } + +private: + /** + * ralloc context for all glsl_type allocations + * + * Set on the first call to \c glsl_type::new. + */ + static void *mem_ctx; + + void init_ralloc_type_ctx(void); + + /** Constructor for vector and matrix types */ + glsl_type(GLenum gl_type, + glsl_base_type base_type, unsigned vector_elements, + unsigned matrix_columns, const char *name); + + /** Constructor for sampler types */ + glsl_type(GLenum gl_type, + enum glsl_sampler_dim dim, bool shadow, bool array, + unsigned type, const char *name); + + /** Constructor for record types */ + glsl_type(const glsl_struct_field *fields, unsigned num_fields, + const char *name); + + /** Constructor for array types */ + glsl_type(const glsl_type *array, unsigned length); + + /** Hash table containing the known array types. */ + static struct hash_table *array_types; + + /** Hash table containing the known record types. */ + static struct hash_table *record_types; + + static int record_key_compare(const void *a, const void *b); + static unsigned record_key_hash(const void *key); + + /** + * \name Pointers to various type singletons + */ + /*@{*/ + static const glsl_type _error_type; + static const glsl_type _void_type; + static const glsl_type _sampler3D_type; + static const glsl_type builtin_core_types[]; + static const glsl_type builtin_structure_types[]; + static const glsl_type builtin_110_deprecated_structure_types[]; + static const glsl_type builtin_110_types[]; + static const glsl_type builtin_120_types[]; + static const glsl_type builtin_130_types[]; + static const glsl_type builtin_ARB_texture_rectangle_types[]; + static const glsl_type builtin_EXT_texture_array_types[]; + static const glsl_type builtin_EXT_texture_buffer_object_types[]; + /*@}*/ + + /** + * \name Methods to populate a symbol table with built-in types. + * + * \internal + * This is one of the truely annoying things about C++. Methods that are + * completely internal and private to a type still have to be advertised to + * the world in a public header file. + */ + /*@{*/ + static void generate_100ES_types(glsl_symbol_table *); + static void generate_110_types(glsl_symbol_table *); + static void generate_120_types(glsl_symbol_table *); + static void generate_130_types(glsl_symbol_table *); + static void generate_ARB_texture_rectangle_types(glsl_symbol_table *, bool); + static void generate_EXT_texture_array_types(glsl_symbol_table *, bool); + static void generate_OES_texture_3D_types(glsl_symbol_table *, bool); + /*@}*/ + + /** + * \name Friend functions. + * + * These functions are friends because they must have C linkage and the + * need to call various private methods or access various private static + * data. + */ + /*@{*/ + friend void _mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *); + friend void _mesa_glsl_release_types(void); + /*@}*/ +}; + +struct glsl_struct_field { + const struct glsl_type *type; + const char *name; +}; + +#endif /* GLSL_TYPES_H */ diff --git a/mesalib/src/glsl/ir.cpp b/mesalib/src/glsl/ir.cpp index 95689dc10..827fe8e17 100644 --- a/mesalib/src/glsl/ir.cpp +++ b/mesalib/src/glsl/ir.cpp @@ -1095,21 +1095,6 @@ ir_dereference_record::ir_dereference_record(ir_variable *var, ? this->record->type->field_type(field) : glsl_type::error_type; } -bool type_contains_sampler(const glsl_type *type) -{ - if (type->is_array()) { - return type_contains_sampler(type->fields.array); - } else if (type->is_record()) { - for (unsigned int i = 0; i < type->length; i++) { - if (type_contains_sampler(type->fields.structure[i].type)) - return true; - } - return false; - } else { - return type->is_sampler(); - } -} - bool ir_dereference::is_lvalue() { @@ -1129,7 +1114,7 @@ ir_dereference::is_lvalue() * as out or inout function parameters, nor can they be * assigned into." */ - if (type_contains_sampler(this->type)) + if (this->type->contains_sampler()) return false; return true; diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h index 80ad3dd29..50a9d6e19 100644 --- a/mesalib/src/glsl/ir.h +++ b/mesalib/src/glsl/ir.h @@ -1635,6 +1635,32 @@ visit_exec_list(exec_list *list, ir_visitor *visitor); */ void validate_ir_tree(exec_list *instructions); +struct _mesa_glsl_parse_state; +struct gl_shader_program; + +/** + * Detect whether an unlinked shader contains static recursion + * + * If the list of instructions is determined to contain static recursion, + * \c _mesa_glsl_error will be called to emit error messages for each function + * that is in the recursion cycle. + */ +void +detect_recursion_unlinked(struct _mesa_glsl_parse_state *state, + exec_list *instructions); + +/** + * Detect whether a linked shader contains static recursion + * + * If the list of instructions is determined to contain static recursion, + * \c link_error_printf will be called to emit error messages for each function + * that is in the recursion cycle. In addition, + * \c gl_shader_program::LinkStatus will be set to false. + */ +void +detect_recursion_linked(struct gl_shader_program *prog, + exec_list *instructions); + /** * Make a clone of each IR instruction in a list * @@ -1669,4 +1695,8 @@ ir_has_call(ir_instruction *ir); extern void do_set_program_inouts(exec_list *instructions, struct gl_program *prog); +extern char * +prototype_string(const glsl_type *return_type, const char *name, + exec_list *parameters); + #endif /* IR_H */ diff --git a/mesalib/src/glsl/ir_function_detect_recursion.cpp b/mesalib/src/glsl/ir_function_detect_recursion.cpp new file mode 100644 index 000000000..44a1cd0b9 --- /dev/null +++ b/mesalib/src/glsl/ir_function_detect_recursion.cpp @@ -0,0 +1,371 @@ +/* + * Copyright © 2011 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * \file ir_function_detect_recursion.cpp + * Determine whether a shader contains static recursion. + * + * Consider the (possibly disjoint) graph of function calls in a shader. If a + * program contains recursion, this graph will contain a cycle. If a function + * is part of a cycle, it will have a caller and it will have a callee (it + * calls another function). + * + * To detect recursion, the function call graph is constructed. The graph is + * repeatedly reduced by removing any function that either has no callees + * (leaf functions) or has no caller. Eventually the only functions that + * remain will be the functions in the cycles. + * + * The GLSL spec is a bit wishy-washy about recursion. + * + * From page 39 (page 45 of the PDF) of the GLSL 1.10 spec: + * + * "Behavior is undefined if recursion is used. Recursion means having any + * function appearing more than once at any one time in the run-time stack + * of function calls. That is, a function may not call itself either + * directly or indirectly. Compilers may give diagnostic messages when + * this is detectable at compile time, but not all such cases can be + * detected at compile time." + * + * From page 79 (page 85 of the PDF): + * + * "22) Should recursion be supported? + * + * DISCUSSION: Probably not necessary, but another example of limiting + * the language based on how it would directly map to hardware. One + * thought is that recursion would benefit ray tracing shaders. On the + * other hand, many recursion operations can also be implemented with the + * user managing the recursion through arrays. RenderMan doesn't support + * recursion. This could be added at a later date, if it proved to be + * necessary. + * + * RESOLVED on September 10, 2002: Implementations are not required to + * support recursion. + * + * CLOSED on September 10, 2002." + * + * From page 79 (page 85 of the PDF): + * + * "56) Is it an error for an implementation to support recursion if the + * specification says recursion is not supported? + * + * ADDED on September 10, 2002. + * + * DISCUSSION: This issues is related to Issue (22). If we say that + * recursion (or some other piece of functionality) is not supported, is + * it an error for an implementation to support it? Perhaps the + * specification should remain silent on these kind of things so that they + * could be gracefully added later as an extension or as part of the + * standard. + * + * RESOLUTION: Languages, in general, have programs that are not + * well-formed in ways a compiler cannot detect. Portability is only + * ensured for well-formed programs. Detecting recursion is an example of + * this. The language will say a well-formed program may not recurse, but + * compilers are not forced to detect that recursion may happen. + * + * CLOSED: November 29, 2002." + * + * In GLSL 1.10 the behavior of recursion is undefined. Compilers don't have + * to reject shaders (at compile-time or link-time) that contain recursion. + * Instead they could work, or crash, or kill a kitten. + * + * From page 44 (page 50 of the PDF) of the GLSL 1.20 spec: + * + * "Recursion is not allowed, not even statically. Static recursion is + * present if the static function call graph of the program contains + * cycles." + * + * This langauge clears things up a bit, but it still leaves a lot of + * questions unanswered. + * + * - Is the error generated at compile-time or link-time? + * + * - Is it an error to have a recursive function that is never statically + * called by main or any function called directly or indirectly by main? + * Technically speaking, such a function is not in the "static function + * call graph of the program" at all. + * + * \bug + * If a shader has multiple cycles, this algorithm may erroneously complain + * about functions that aren't in any cycle, but are in the part of the call + * tree that connects them. For example, if the call graph consists of a + * cycle between A and B, and a cycle between D and E, and B also calls C + * which calls D, then this algorithm will report C as a function which "has + * static recursion" even though it is not part of any cycle. + * + * A better algorithm for cycle detection that doesn't have this drawback can + * be found here: + * + * http://en.wikipedia.org/wiki/Tarjan%E2%80%99s_strongly_connected_components_algorithm + * + * \author Ian Romanick + */ +#include "main/core.h" +#include "ir.h" +#include "glsl_parser_extras.h" +#include "linker.h" +#include "program/hash_table.h" + +struct call_node : public exec_node { + class function *func; +}; + +class function { +public: + function(ir_function_signature *sig) + : sig(sig) + { + /* empty */ + } + + + /* Callers of this ralloc-based new need not call delete. It's + * easier to just ralloc_free 'ctx' (or any of its ancestors). */ + static void* operator new(size_t size, void *ctx) + { + void *node; + + node = ralloc_size(ctx, size); + assert(node != NULL); + + return node; + } + + /* If the user *does* call delete, that's OK, we will just + * ralloc_free in that case. */ + static void operator delete(void *node) + { + ralloc_free(node); + } + + ir_function_signature *sig; + + /** List of functions called by this function. */ + exec_list callees; + + /** List of functions that call this function. */ + exec_list callers; +}; + +class has_recursion_visitor : public ir_hierarchical_visitor { +public: + has_recursion_visitor() + : current(NULL) + { + this->mem_ctx = ralloc_context(NULL); + this->function_hash = hash_table_ctor(0, hash_table_pointer_hash, + hash_table_pointer_compare); + } + + ~has_recursion_visitor() + { + hash_table_dtor(this->function_hash); + ralloc_free(this->mem_ctx); + } + + function *get_function(ir_function_signature *sig) + { + function *f = (function *) hash_table_find(this->function_hash, sig); + if (f == NULL) { + f = new(mem_ctx) function(sig); + hash_table_insert(this->function_hash, f, sig); + } + + return f; + } + + virtual ir_visitor_status visit_enter(ir_function_signature *sig) + { + this->current = this->get_function(sig); + return visit_continue; + } + + virtual ir_visitor_status visit_leave(ir_function_signature *sig) + { + (void) sig; + this->current = NULL; + return visit_continue; + } + + virtual ir_visitor_status visit_enter(ir_call *call) + { + /* At global scope this->current will be NULL. Since there is no way to + * call global scope, it can never be part of a cycle. Don't bother + * adding calls from global scope to the graph. + */ + if (this->current == NULL) + return visit_continue; + + function *const target = this->get_function(call->get_callee()); + + /* Create a link from the caller to the callee. + */ + call_node *node = new(mem_ctx) call_node; + node->func = target; + this->current->callees.push_tail(node); + + /* Create a link from the callee to the caller. + */ + node = new(mem_ctx) call_node; + node->func = this->current; + target->callers.push_tail(node); + return visit_continue; + } + + function *current; + struct hash_table *function_hash; + void *mem_ctx; + bool progress; +}; + +static void +destroy_links(exec_list *list, function *f) +{ + foreach_list_safe(node, list) { + struct call_node *n = (struct call_node *) node; + + /* If this is the right function, remove it. Note that the loop cannot + * terminate now. There can be multiple links to a function if it is + * either called multiple times or calls multiple times. + */ + if (n->func == f) + n->remove(); + } +} + + +/** + * Remove a function if it has either no in or no out links + */ +static void +remove_unlinked_functions(const void *key, void *data, void *closure) +{ + has_recursion_visitor *visitor = (has_recursion_visitor *) closure; + function *f = (function *) data; + + if (f->callers.is_empty() || f->callees.is_empty()) { + while (!f->callers.is_empty()) { + struct call_node *n = (struct call_node *) f->callers.pop_head(); + destroy_links(& n->func->callees, f); + } + + while (!f->callees.is_empty()) { + struct call_node *n = (struct call_node *) f->callees.pop_head(); + destroy_links(& n->func->callers, f); + } + + hash_table_remove(visitor->function_hash, key); + visitor->progress = true; + } +} + + +static void +emit_errors_unlinked(const void *key, void *data, void *closure) +{ + struct _mesa_glsl_parse_state *state = + (struct _mesa_glsl_parse_state *) closure; + function *f = (function *) data; + YYLTYPE loc; + + char *proto = prototype_string(f->sig->return_type, + f->sig->function_name(), + &f->sig->parameters); + + memset(&loc, 0, sizeof(loc)); + _mesa_glsl_error(&loc, state, + "function `%s' has static recursion.", + proto); + ralloc_free(proto); +} + + +static void +emit_errors_linked(const void *key, void *data, void *closure) +{ + struct gl_shader_program *prog = + (struct gl_shader_program *) closure; + function *f = (function *) data; + + char *proto = prototype_string(f->sig->return_type, + f->sig->function_name(), + &f->sig->parameters); + + linker_error_printf(prog, + "function `%s' has static recursion.\n", + proto); + ralloc_free(proto); + prog->LinkStatus = false; +} + + +void +detect_recursion_unlinked(struct _mesa_glsl_parse_state *state, + exec_list *instructions) +{ + has_recursion_visitor v; + + /* Collect all of the information about which functions call which other + * functions. + */ + v.run(instructions); + + /* Remove from the set all of the functions that either have no caller or + * call no other functions. Repeat until no functions are removed. + */ + do { + v.progress = false; + hash_table_call_foreach(v.function_hash, remove_unlinked_functions, & v); + } while (v.progress); + + + /* At this point any functions still in the hash must be part of a cycle. + */ + hash_table_call_foreach(v.function_hash, emit_errors_unlinked, state); +} + + +void +detect_recursion_linked(struct gl_shader_program *prog, + exec_list *instructions) +{ + has_recursion_visitor v; + + /* Collect all of the information about which functions call which other + * functions. + */ + v.run(instructions); + + /* Remove from the set all of the functions that either have no caller or + * call no other functions. Repeat until no functions are removed. + */ + do { + v.progress = false; + hash_table_call_foreach(v.function_hash, remove_unlinked_functions, & v); + } while (v.progress); + + + /* At this point any functions still in the hash must be part of a cycle. + */ + hash_table_call_foreach(v.function_hash, emit_errors_linked, prog); +} diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index 34b64837a..fe570b6cc 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -1343,7 +1343,7 @@ assign_attribute_or_color_locations(gl_shader_program *prog, foreach_list(node, sh->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if ((var == NULL) || (var->mode != direction)) + if ((var == NULL) || (var->mode != (unsigned) direction)) continue; if (var->explicit_location) { @@ -1702,6 +1702,10 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) if (prog->_LinkedShaders[i] == NULL) continue; + detect_recursion_linked(prog, prog->_LinkedShaders[i]->ir); + if (!prog->LinkStatus) + goto done; + while (do_common_optimization(prog->_LinkedShaders[i]->ir, true, 32)) ; } diff --git a/mesalib/src/glsl/s_expression.cpp b/mesalib/src/glsl/s_expression.cpp index a922a50d3..e704a3be2 100644 --- a/mesalib/src/glsl/s_expression.cpp +++ b/mesalib/src/glsl/s_expression.cpp @@ -25,10 +25,13 @@ #include #include "s_expression.h" -s_symbol::s_symbol(const char *tmp, size_t n) +s_symbol::s_symbol(const char *str, size_t n) { - this->str = ralloc_strndup (this, tmp, n); - assert(this->str != NULL); + /* Assume the given string is already nul-terminated and in memory that + * will live as long as this node. + */ + assert(str[n] == '\0'); + this->str = str; } s_list::s_list() @@ -36,22 +39,26 @@ s_list::s_list() } static void -skip_whitespace(const char *& src) +skip_whitespace(const char *&src, char *&symbol_buffer) { - src += strspn(src, " \v\t\r\n"); + size_t n = strspn(src, " \v\t\r\n"); + src += n; + symbol_buffer += n; /* Also skip Scheme-style comments: semi-colon 'til end of line */ if (src[0] == ';') { - src += strcspn(src, "\n"); - skip_whitespace(src); + n = strcspn(src, "\n"); + src += n; + symbol_buffer += n; + skip_whitespace(src, symbol_buffer); } } static s_expression * -read_atom(void *ctx, const char *& src) +read_atom(void *ctx, const char *&src, char *&symbol_buffer) { s_expression *expr = NULL; - skip_whitespace(src); + skip_whitespace(src, symbol_buffer); size_t n = strcspn(src, "( \v\t\r\n);"); if (n == 0) @@ -70,44 +77,65 @@ read_atom(void *ctx, const char *& src) expr = new(ctx) s_int(i); } else { // Not a number; return a symbol. - expr = new(ctx) s_symbol(src, n); + symbol_buffer[n] = '\0'; + expr = new(ctx) s_symbol(symbol_buffer, n); } src += n; + symbol_buffer += n; return expr; } -s_expression * -s_expression::read_expression(void *ctx, const char *&src) +static s_expression * +__read_expression(void *ctx, const char *&src, char *&symbol_buffer) { - assert(src != NULL); - - s_expression *atom = read_atom(ctx, src); + s_expression *atom = read_atom(ctx, src, symbol_buffer); if (atom != NULL) return atom; - skip_whitespace(src); + skip_whitespace(src, symbol_buffer); if (src[0] == '(') { ++src; + ++symbol_buffer; s_list *list = new(ctx) s_list; s_expression *expr; - while ((expr = read_expression(ctx, src)) != NULL) { + while ((expr = __read_expression(ctx, src, symbol_buffer)) != NULL) { list->subexpressions.push_tail(expr); } - skip_whitespace(src); + skip_whitespace(src, symbol_buffer); if (src[0] != ')') { printf("Unclosed expression (check your parenthesis).\n"); return NULL; } ++src; + ++symbol_buffer; return list; } return NULL; } +s_expression * +s_expression::read_expression(void *ctx, const char *&src) +{ + assert(src != NULL); + + /* When we encounter a Symbol, we need to save a nul-terminated copy of + * the string. However, ralloc_strndup'ing every individual Symbol is + * extremely expensive. We could avoid this by simply overwriting the + * next character (guaranteed to be whitespace, parens, or semicolon) with + * a nul-byte. But overwriting non-whitespace would mess up parsing. + * + * So, just copy the whole buffer ahead of time. Walk both, leaving the + * original source string unmodified, and altering the copy to contain the + * necessary nul-bytes whenever we encounter a symbol. + */ + char *symbol_buffer = ralloc_strdup(ctx, src); + return __read_expression(ctx, src, symbol_buffer); +} + void s_int::print() { printf("%d", this->val); diff --git a/mesalib/src/glsl/s_expression.h b/mesalib/src/glsl/s_expression.h index c9dc676b3..642af19b4 100644 --- a/mesalib/src/glsl/s_expression.h +++ b/mesalib/src/glsl/s_expression.h @@ -129,7 +129,7 @@ public: void print(); private: - char *str; + const char *str; }; /* Lists of expressions: (expr1 ... exprN) */ diff --git a/mesalib/src/mesa/drivers/common/driverfuncs.c b/mesalib/src/mesa/drivers/common/driverfuncs.c index 8ab129dd7..76630264b 100644 --- a/mesalib/src/mesa/drivers/common/driverfuncs.c +++ b/mesalib/src/mesa/drivers/common/driverfuncs.c @@ -95,8 +95,6 @@ _mesa_init_driver_functions(struct dd_function_table *driver) driver->TexSubImage2D = _mesa_store_texsubimage2d; driver->TexSubImage3D = _mesa_store_texsubimage3d; driver->GetTexImage = _mesa_get_teximage; - driver->CopyTexImage1D = _mesa_meta_CopyTexImage1D; - driver->CopyTexImage2D = _mesa_meta_CopyTexImage2D; driver->CopyTexSubImage1D = _mesa_meta_CopyTexSubImage1D; driver->CopyTexSubImage2D = _mesa_meta_CopyTexSubImage2D; driver->CopyTexSubImage3D = _mesa_meta_CopyTexSubImage3D; diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c index 0e58aeca3..fa78674e4 100644 --- a/mesalib/src/mesa/drivers/common/meta.c +++ b/mesalib/src/mesa/drivers/common/meta.c @@ -62,6 +62,7 @@ #include "main/teximage.h" #include "main/texparam.h" #include "main/texstate.h" +#include "main/uniforms.h" #include "main/varray.h" #include "main/viewport.h" #include "program/program.h" @@ -235,6 +236,8 @@ struct clear_state { GLuint ArrayObj; GLuint VBO; + GLuint ShaderProg; + GLint ColorLocation; }; @@ -1589,10 +1592,165 @@ _mesa_meta_Clear(struct gl_context *ctx, GLbitfield buffers) _mesa_meta_end(ctx); } +static void +meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) +{ + const char *vs_source = + "attribute vec4 position;\n" + "void main()\n" + "{\n" + " gl_Position = position;\n" + "}\n"; + const char *fs_source = + "uniform vec4 color;\n" + "void main()\n" + "{\n" + " gl_FragColor = color;\n" + "}\n"; + GLuint vs, fs; + + if (clear->ArrayObj != 0) + return; + + /* create vertex array object */ + _mesa_GenVertexArrays(1, &clear->ArrayObj); + _mesa_BindVertexArray(clear->ArrayObj); + + /* create vertex array buffer */ + _mesa_GenBuffersARB(1, &clear->VBO); + _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO); + + /* setup vertex arrays */ + _mesa_VertexAttribPointerARB(0, 3, GL_FLOAT, GL_FALSE, 0, (void *)0); + _mesa_EnableVertexAttribArrayARB(0); + + vs = _mesa_CreateShaderObjectARB(GL_VERTEX_SHADER); + _mesa_ShaderSourceARB(vs, 1, &vs_source, NULL); + _mesa_CompileShaderARB(vs); + + fs = _mesa_CreateShaderObjectARB(GL_FRAGMENT_SHADER); + _mesa_ShaderSourceARB(fs, 1, &fs_source, NULL); + _mesa_CompileShaderARB(fs); + + clear->ShaderProg = _mesa_CreateProgramObjectARB(); + _mesa_AttachShader(clear->ShaderProg, fs); + _mesa_AttachShader(clear->ShaderProg, vs); + _mesa_BindAttribLocationARB(clear->ShaderProg, 0, "position"); + _mesa_LinkProgramARB(clear->ShaderProg); + + clear->ColorLocation = _mesa_GetUniformLocationARB(clear->ShaderProg, + "color"); +} + +/** + * Meta implementation of ctx->Driver.Clear() in terms of polygon rendering. + */ +void +_mesa_meta_glsl_Clear(struct gl_context *ctx, GLbitfield buffers) +{ + struct clear_state *clear = &ctx->Meta->Clear; + GLbitfield metaSave; + const GLuint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1; + struct gl_framebuffer *fb = ctx->DrawBuffer; + const float x0 = ((float)fb->_Xmin / fb->Width) * 2.0f - 1.0f; + const float y0 = ((float)fb->_Ymin / fb->Height) * 2.0f - 1.0f; + const float x1 = ((float)fb->_Xmax / fb->Width) * 2.0f - 1.0f; + const float y1 = ((float)fb->_Ymax / fb->Height) * 2.0f - 1.0f; + const float z = -invert_z(ctx->Depth.Clear); + struct vertex { + GLfloat x, y, z; + } verts[4]; + + metaSave = (META_ALPHA_TEST | + META_BLEND | + META_DEPTH_TEST | + META_RASTERIZATION | + META_SHADER | + META_STENCIL_TEST | + META_VERTEX | + META_VIEWPORT | + META_CLAMP_FRAGMENT_COLOR); + + if (!(buffers & BUFFER_BITS_COLOR)) { + /* We'll use colormask to disable color writes. Otherwise, + * respect color mask + */ + metaSave |= META_COLOR_MASK; + } + + _mesa_meta_begin(ctx, metaSave); + + meta_glsl_clear_init(ctx, clear); + + _mesa_UseProgramObjectARB(clear->ShaderProg); + _mesa_Uniform4fvARB(clear->ColorLocation, 1, + ctx->Color.ClearColorUnclamped); + + _mesa_BindVertexArray(clear->ArrayObj); + _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO); + + /* GL_COLOR_BUFFER_BIT */ + if (buffers & BUFFER_BITS_COLOR) { + /* leave colormask, glDrawBuffer state as-is */ + + /* Clears never have the color clamped. */ + _mesa_ClampColorARB(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE); + } + else { + ASSERT(metaSave & META_COLOR_MASK); + _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + } + + /* GL_DEPTH_BUFFER_BIT */ + if (buffers & BUFFER_BIT_DEPTH) { + _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE); + _mesa_DepthFunc(GL_ALWAYS); + _mesa_DepthMask(GL_TRUE); + } + else { + assert(!ctx->Depth.Test); + } + + /* GL_STENCIL_BUFFER_BIT */ + if (buffers & BUFFER_BIT_STENCIL) { + _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_TRUE); + _mesa_StencilOpSeparate(GL_FRONT_AND_BACK, + GL_REPLACE, GL_REPLACE, GL_REPLACE); + _mesa_StencilFuncSeparate(GL_FRONT_AND_BACK, GL_ALWAYS, + ctx->Stencil.Clear & stencilMax, + ctx->Stencil.WriteMask[0]); + } + else { + assert(!ctx->Stencil.Enabled); + } + + /* vertex positions */ + verts[0].x = x0; + verts[0].y = y0; + verts[0].z = z; + verts[1].x = x1; + verts[1].y = y0; + verts[1].z = z; + verts[2].x = x1; + verts[2].y = y1; + verts[2].z = z; + verts[3].x = x0; + verts[3].y = y1; + verts[3].z = z; + + /* upload new vertex data */ + _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), verts, + GL_DYNAMIC_DRAW_ARB); + + /* draw quad */ + _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); + + _mesa_meta_end(ctx); +} /** * Meta implementation of ctx->Driver.CopyPixels() in terms - * of texture mapping and polygon rendering. + * of texture mapping and polygon rendering and GLSL shaders. */ void _mesa_meta_CopyPixels(struct gl_context *ctx, GLint srcX, GLint srcY, @@ -2677,119 +2835,6 @@ get_temp_image_type(struct gl_context *ctx, GLenum baseFormat) } -/** - * Helper for _mesa_meta_CopyTexImage1/2D() functions. - * Have to be careful with locking and meta state for pixel transfer. - */ -static void -copy_tex_image(struct gl_context *ctx, GLuint dims, GLenum target, GLint level, - GLenum internalFormat, GLint x, GLint y, - GLsizei width, GLsizei height, GLint border) -{ - struct gl_texture_object *texObj; - struct gl_texture_image *texImage; - GLenum format, type; - GLint bpp; - void *buf; - struct gl_renderbuffer *read_rb = ctx->ReadBuffer->_ColorReadBuffer; - - texObj = _mesa_get_current_tex_object(ctx, target); - texImage = _mesa_get_tex_image(ctx, texObj, target, level); - - /* Choose format/type for temporary image buffer */ - format = _mesa_base_tex_format(ctx, internalFormat); - - if (format == GL_LUMINANCE && - _mesa_get_format_base_format(read_rb->Format) != GL_LUMINANCE) { - /* The glReadPixels() path will convert RGB to luminance by - * summing R+G+B. glCopyTexImage() is supposed to behave as - * glCopyPixels, which doesn't do that change, and instead - * leaves it up to glTexImage which converts RGB to luminance by - * just taking the R channel. To avoid glReadPixels() trashing - * our data, use RGBA for our temporary image. - */ - format = GL_RGBA; - } - - type = get_temp_image_type(ctx, format); - bpp = _mesa_bytes_per_pixel(format, type); - if (bpp <= 0) { - _mesa_problem(ctx, "Bad bpp in meta copy_tex_image()"); - return; - } - - /* - * Alloc image buffer (XXX could use a PBO) - */ - buf = malloc(width * height * bpp); - if (!buf) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage%uD", dims); - return; - } - - _mesa_unlock_texture(ctx, texObj); /* need to unlock first */ - - /* - * Read image from framebuffer (disable pixel transfer ops) - */ - _mesa_meta_begin(ctx, META_PIXEL_STORE | META_PIXEL_TRANSFER); - ctx->Driver.ReadPixels(ctx, x, y, width, height, - format, type, &ctx->Pack, buf); - _mesa_meta_end(ctx); - - if (texImage->Data) { - ctx->Driver.FreeTexImageData(ctx, texImage); - } - - /* The texture's format was already chosen in _mesa_CopyTexImage() */ - ASSERT(texImage->TexFormat != MESA_FORMAT_NONE); - - /* - * Store texture data (with pixel transfer ops) - */ - _mesa_meta_begin(ctx, META_PIXEL_STORE); - - _mesa_update_state(ctx); /* to update pixel transfer state */ - - if (target == GL_TEXTURE_1D) { - ctx->Driver.TexImage1D(ctx, target, level, internalFormat, - width, border, format, type, - buf, &ctx->Unpack, texObj, texImage); - } - else { - ctx->Driver.TexImage2D(ctx, target, level, internalFormat, - width, height, border, format, type, - buf, &ctx->Unpack, texObj, texImage); - } - _mesa_meta_end(ctx); - - _mesa_lock_texture(ctx, texObj); /* re-lock */ - - free(buf); -} - - -void -_mesa_meta_CopyTexImage1D(struct gl_context *ctx, GLenum target, GLint level, - GLenum internalFormat, GLint x, GLint y, - GLsizei width, GLint border) -{ - copy_tex_image(ctx, 1, target, level, internalFormat, x, y, - width, 1, border); -} - - -void -_mesa_meta_CopyTexImage2D(struct gl_context *ctx, GLenum target, GLint level, - GLenum internalFormat, GLint x, GLint y, - GLsizei width, GLsizei height, GLint border) -{ - copy_tex_image(ctx, 2, target, level, internalFormat, x, y, - width, height, border); -} - - - /** * Helper for _mesa_meta_CopyTexSubImage1/2/3D() functions. * Have to be careful with locking and meta state for pixel transfer. diff --git a/mesalib/src/mesa/drivers/common/meta.h b/mesalib/src/mesa/drivers/common/meta.h index a350a92aa..95b4b5579 100644 --- a/mesalib/src/mesa/drivers/common/meta.h +++ b/mesalib/src/mesa/drivers/common/meta.h @@ -1,118 +1,111 @@ -/* - * Mesa 3-D graphics library - * Version: 7.6 - * - * Copyright (C) 2009 VMware, Inc. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - - -#ifndef META_H -#define META_H - - -extern void -_mesa_meta_init(struct gl_context *ctx); - -extern void -_mesa_meta_free(struct gl_context *ctx); - -extern void -_mesa_meta_BlitFramebuffer(struct gl_context *ctx, - GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter); - -extern void -_mesa_meta_Clear(struct gl_context *ctx, GLbitfield buffers); - -extern void -_mesa_meta_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, - GLsizei width, GLsizei height, - GLint dstx, GLint dsty, GLenum type); - -extern void -_mesa_meta_DrawPixels(struct gl_context *ctx, - GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, - const struct gl_pixelstore_attrib *unpack, - const GLvoid *pixels); - -extern void -_mesa_meta_Bitmap(struct gl_context *ctx, - GLint x, GLint y, GLsizei width, GLsizei height, - const struct gl_pixelstore_attrib *unpack, - const GLubyte *bitmap); - -extern GLboolean -_mesa_meta_check_generate_mipmap_fallback(struct gl_context *ctx, GLenum target, - struct gl_texture_object *texObj); - -extern void -_mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, - struct gl_texture_object *texObj); - -extern void -_mesa_meta_CopyTexImage1D(struct gl_context *ctx, GLenum target, GLint level, - GLenum internalFormat, GLint x, GLint y, - GLsizei width, GLint border); - -extern void -_mesa_meta_CopyTexImage2D(struct gl_context *ctx, GLenum target, GLint level, - GLenum internalFormat, GLint x, GLint y, - GLsizei width, GLsizei height, GLint border); - -extern void -_mesa_meta_CopyTexSubImage1D(struct gl_context *ctx, GLenum target, GLint level, - GLint xoffset, - GLint x, GLint y, GLsizei width); - -extern void -_mesa_meta_CopyTexSubImage2D(struct gl_context *ctx, GLenum target, GLint level, - GLint xoffset, GLint yoffset, - GLint x, GLint y, - GLsizei width, GLsizei height); - -extern void -_mesa_meta_CopyTexSubImage3D(struct gl_context *ctx, GLenum target, GLint level, - GLint xoffset, GLint yoffset, GLint zoffset, - GLint x, GLint y, - GLsizei width, GLsizei height); - -extern void -_mesa_meta_CopyColorTable(struct gl_context *ctx, - GLenum target, GLenum internalformat, - GLint x, GLint y, GLsizei width); - -extern void -_mesa_meta_CopyColorSubTable(struct gl_context *ctx,GLenum target, GLsizei start, - GLint x, GLint y, GLsizei width); - -extern void -_mesa_meta_CopyConvolutionFilter1D(struct gl_context *ctx, GLenum target, - GLenum internalFormat, - GLint x, GLint y, GLsizei width); - -extern void -_mesa_meta_CopyConvolutionFilter2D(struct gl_context *ctx, GLenum target, - GLenum internalFormat, GLint x, GLint y, - GLsizei width, GLsizei height); - - -#endif /* META_H */ +/* + * Mesa 3-D graphics library + * Version: 7.6 + * + * Copyright (C) 2009 VMware, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef META_H +#define META_H + + +extern void +_mesa_meta_init(struct gl_context *ctx); + +extern void +_mesa_meta_free(struct gl_context *ctx); + +extern void +_mesa_meta_BlitFramebuffer(struct gl_context *ctx, + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter); + +extern void +_mesa_meta_Clear(struct gl_context *ctx, GLbitfield buffers); + +extern void +_mesa_meta_glsl_Clear(struct gl_context *ctx, GLbitfield buffers); + +extern void +_mesa_meta_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, + GLsizei width, GLsizei height, + GLint dstx, GLint dsty, GLenum type); + +extern void +_mesa_meta_DrawPixels(struct gl_context *ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *unpack, + const GLvoid *pixels); + +extern void +_mesa_meta_Bitmap(struct gl_context *ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + const struct gl_pixelstore_attrib *unpack, + const GLubyte *bitmap); + +extern GLboolean +_mesa_meta_check_generate_mipmap_fallback(struct gl_context *ctx, GLenum target, + struct gl_texture_object *texObj); + +extern void +_mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, + struct gl_texture_object *texObj); + +extern void +_mesa_meta_CopyTexSubImage1D(struct gl_context *ctx, GLenum target, GLint level, + GLint xoffset, + GLint x, GLint y, GLsizei width); + +extern void +_mesa_meta_CopyTexSubImage2D(struct gl_context *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint x, GLint y, + GLsizei width, GLsizei height); + +extern void +_mesa_meta_CopyTexSubImage3D(struct gl_context *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLint x, GLint y, + GLsizei width, GLsizei height); + +extern void +_mesa_meta_CopyColorTable(struct gl_context *ctx, + GLenum target, GLenum internalformat, + GLint x, GLint y, GLsizei width); + +extern void +_mesa_meta_CopyColorSubTable(struct gl_context *ctx,GLenum target, GLsizei start, + GLint x, GLint y, GLsizei width); + +extern void +_mesa_meta_CopyConvolutionFilter1D(struct gl_context *ctx, GLenum target, + GLenum internalFormat, + GLint x, GLint y, GLsizei width); + +extern void +_mesa_meta_CopyConvolutionFilter2D(struct gl_context *ctx, GLenum target, + GLenum internalFormat, GLint x, GLint y, + GLsizei width, GLsizei height); + + +#endif /* META_H */ diff --git a/mesalib/src/mesa/main/dd.h b/mesalib/src/mesa/main/dd.h index 9fe6d527f..e0c5844e1 100644 --- a/mesalib/src/mesa/main/dd.h +++ b/mesalib/src/mesa/main/dd.h @@ -189,31 +189,22 @@ struct dd_function_table { /*@{*/ /** - * Choose texture format. - * - * This is called by the \c _mesa_store_tex[sub]image[123]d() fallback - * functions. The driver should examine \p internalFormat and return a - * gl_format value. + * Choose actual hardware texture format given the user-provided source + * image format and type and the desired internal format. In some + * cases, srcFormat and srcType can be GL_NONE. + * Called by glTexImage(), etc. */ GLuint (*ChooseTextureFormat)( struct gl_context *ctx, GLint internalFormat, GLenum srcFormat, GLenum srcType ); /** - * Called by glTexImage1D(). - * - * \param target user specified. - * \param format user specified. - * \param type user specified. - * \param pixels user specified. - * \param packing indicates the image packing of pixels. + * Called by glTexImage1D(). Simply copy the source texture data into the + * destination texture memory. The gl_texture_image fields, etc. will be + * fully initialized. + * The parameters are the same as glTexImage1D(), plus: + * \param packing describes how to unpack the source data. * \param texObj is the target texture object. - * \param texImage is the target texture image. It will have the texture \p - * width, \p height, \p depth, \p border and \p internalFormat information. - * - * \p retainInternalCopy is returned by this function and indicates whether - * core Mesa should keep an internal copy of the texture image. - * - * Drivers should call a fallback routine from texstore.c if needed. + * \param texImage is the target texture image. */ void (*TexImage1D)( struct gl_context *ctx, GLenum target, GLint level, GLint internalFormat, @@ -250,25 +241,9 @@ struct dd_function_table { struct gl_texture_image *texImage ); /** - * Called by glTexSubImage1D(). - * - * \param target user specified. - * \param level user specified. - * \param xoffset user specified. - * \param yoffset user specified. - * \param zoffset user specified. - * \param width user specified. - * \param height user specified. - * \param depth user specified. - * \param format user specified. - * \param type user specified. - * \param pixels user specified. - * \param packing indicates the image packing of pixels. - * \param texObj is the target texture object. - * \param texImage is the target texture image. It will have the texture \p - * width, \p height, \p border and \p internalFormat information. - * - * The driver should use a fallback routine from texstore.c if needed. + * Called by glTexSubImage1D(). Replace a subset of the target texture + * with new texel data. + * \sa dd_function_table::TexImage1D. */ void (*TexSubImage1D)( struct gl_context *ctx, GLenum target, GLint level, GLint xoffset, GLsizei width, @@ -314,24 +289,6 @@ struct dd_function_table { struct gl_texture_object *texObj, struct gl_texture_image *texImage ); - /** - * Called by glCopyTexImage1D(). - * - * Drivers should use a fallback routine from texstore.c if needed. - */ - void (*CopyTexImage1D)( struct gl_context *ctx, GLenum target, GLint level, - GLenum internalFormat, GLint x, GLint y, - GLsizei width, GLint border ); - - /** - * Called by glCopyTexImage2D(). - * - * Drivers should use a fallback routine from texstore.c if needed. - */ - void (*CopyTexImage2D)( struct gl_context *ctx, GLenum target, GLint level, - GLenum internalFormat, GLint x, GLint y, - GLsizei width, GLsizei height, GLint border ); - /** * Called by glCopyTexSubImage1D(). * diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c index 84969360d..82eb7fb71 100644 --- a/mesalib/src/mesa/main/fbobject.c +++ b/mesalib/src/mesa/main/fbobject.c @@ -2134,10 +2134,14 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, { const struct gl_renderbuffer_attachment *att; struct gl_framebuffer *buffer; + GLenum err; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + /* The error differs in GL andd GLES. */ + err = ctx->API == API_OPENGL ? GL_INVALID_OPERATION : GL_INVALID_ENUM; + buffer = get_framebuffer_target(ctx, target); if (!buffer) { _mesa_error(ctx, GL_INVALID_ENUM, @@ -2188,7 +2192,12 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, } else { assert(att->Type == GL_NONE); - *params = 0; + if (ctx->API == API_OPENGL) { + *params = 0; + } else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetFramebufferAttachmentParameterivEXT(pname)"); + } } return; case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT: @@ -2196,7 +2205,7 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, *params = att->TextureLevel; } else if (att->Type == GL_NONE) { - _mesa_error(ctx, GL_INVALID_OPERATION, + _mesa_error(ctx, err, "glGetFramebufferAttachmentParameterivEXT(pname)"); } else { @@ -2214,7 +2223,7 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, } } else if (att->Type == GL_NONE) { - _mesa_error(ctx, GL_INVALID_OPERATION, + _mesa_error(ctx, err, "glGetFramebufferAttachmentParameterivEXT(pname)"); } else { @@ -2232,7 +2241,7 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, } } else if (att->Type == GL_NONE) { - _mesa_error(ctx, GL_INVALID_OPERATION, + _mesa_error(ctx, err, "glGetFramebufferAttachmentParameterivEXT(pname)"); } else { @@ -2246,7 +2255,7 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, "glGetFramebufferAttachmentParameterivEXT(pname)"); } else if (att->Type == GL_NONE) { - _mesa_error(ctx, GL_INVALID_OPERATION, + _mesa_error(ctx, err, "glGetFramebufferAttachmentParameterivEXT(pname)"); } else { @@ -2267,7 +2276,7 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, return; } else if (att->Type == GL_NONE) { - _mesa_error(ctx, GL_INVALID_OPERATION, + _mesa_error(ctx, err, "glGetFramebufferAttachmentParameterivEXT(pname)"); } else { @@ -2301,7 +2310,7 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, "glGetFramebufferAttachmentParameterivEXT(pname)"); } else if (att->Type == GL_NONE) { - _mesa_error(ctx, GL_INVALID_OPERATION, + _mesa_error(ctx, err, "glGetFramebufferAttachmentParameterivEXT(pname)"); } else if (att->Texture) { diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c index 6f53686e7..302fd65cb 100644 --- a/mesalib/src/mesa/main/teximage.c +++ b/mesalib/src/mesa/main/teximage.c @@ -2797,29 +2797,43 @@ copyteximage(struct gl_context *ctx, GLuint dims, _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage%uD", dims); } else { - gl_format texFormat; - - if (texImage->Data) { - ctx->Driver.FreeTexImageData( ctx, texImage ); - } + /* choose actual hw format */ + gl_format texFormat = _mesa_choose_texture_format(ctx, texObj, + target, level, + internalFormat, + GL_NONE, GL_NONE); - ASSERT(texImage->Data == NULL); + if (legal_texture_size(ctx, texFormat, width, height, 1)) { + GLint srcX = x, srcY = y, dstX = 0, dstY = 0; - texFormat = _mesa_choose_texture_format(ctx, texObj, target, level, - internalFormat, GL_NONE, - GL_NONE); + /* Free old texture image */ + ctx->Driver.FreeTexImageData(ctx, texImage); - if (legal_texture_size(ctx, texFormat, width, height, 1)) { _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, border, internalFormat, texFormat); - ASSERT(ctx->Driver.CopyTexImage2D); - if (dims == 1) - ctx->Driver.CopyTexImage1D(ctx, target, level, internalFormat, - x, y, width, border); - else - ctx->Driver.CopyTexImage2D(ctx, target, level, internalFormat, - x, y, width, height, border); + /* Allocate texture memory (no pixel data yet) */ + if (dims == 1) { + ctx->Driver.TexImage1D(ctx, target, level, internalFormat, + width, border, GL_NONE, GL_NONE, NULL, + &ctx->Unpack, texObj, texImage); + } + else { + ctx->Driver.TexImage2D(ctx, target, level, internalFormat, + width, height, border, GL_NONE, GL_NONE, + NULL, &ctx->Unpack, texObj, texImage); + } + + if (_mesa_clip_copytexsubimage(ctx, &dstX, &dstY, &srcX, &srcY, + &width, &height)) { + if (dims == 1) + ctx->Driver.CopyTexSubImage1D(ctx, target, level, dstX, + srcX, srcY, width); + + else + ctx->Driver.CopyTexSubImage2D(ctx, target, level, dstX, dstY, + srcX, srcY, width, height); + } check_gen_mipmap(ctx, target, texObj, level); @@ -2830,6 +2844,7 @@ copyteximage(struct gl_context *ctx, GLuint dims, ctx->NewState |= _NEW_TEXTURE; } else { + /* probably too large of image */ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage%uD", dims); } } diff --git a/mesalib/src/mesa/main/texstore.c b/mesalib/src/mesa/main/texstore.c index 6e1e63bdf..c4aeaa8f1 100644 --- a/mesalib/src/mesa/main/texstore.c +++ b/mesalib/src/mesa/main/texstore.c @@ -4577,8 +4577,7 @@ texture_row_stride(const struct gl_texture_image *texImage) /** - * This is the software fallback for Driver.TexImage1D() - * and Driver.CopyTexImage1D(). + * This is the software fallback for Driver.TexImage1D(). * \sa _mesa_store_teximage2d() */ void @@ -4629,8 +4628,7 @@ _mesa_store_teximage1d(struct gl_context *ctx, GLenum target, GLint level, /** - * This is the software fallback for Driver.TexImage2D() - * and Driver.CopyTexImage2D(). + * This is the software fallback for Driver.TexImage2D(). * * This function is oriented toward storing images in main memory, rather * than VRAM. Device driver's can easily plug in their own replacement. @@ -4684,8 +4682,7 @@ _mesa_store_teximage2d(struct gl_context *ctx, GLenum target, GLint level, /** - * This is the software fallback for Driver.TexImage3D() - * and Driver.CopyTexImage3D(). + * This is the software fallback for Driver.TexImage3D(). * \sa _mesa_store_teximage2d() */ void diff --git a/mesalib/src/mesa/state_tracker/st_cb_texture.c b/mesalib/src/mesa/state_tracker/st_cb_texture.c index 6907cfc03..25f08aa4d 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_texture.c +++ b/mesalib/src/mesa/state_tracker/st_cb_texture.c @@ -1466,34 +1466,6 @@ st_copy_texsubimage(struct gl_context *ctx, depth/stencil samples per pixel? Need some transfer clarifications. */ assert(sample_count < 2); - if (srcX < 0) { - width -= -srcX; - destX += -srcX; - srcX = 0; - } - - if (srcY < 0) { - height -= -srcY; - destY += -srcY; - srcY = 0; - } - - if (destX < 0) { - width -= -destX; - srcX += -destX; - destX = 0; - } - - if (destY < 0) { - height -= -destY; - srcY += -destY; - destY = 0; - } - - if (width < 0 || height < 0) - return; - - assert(strb); assert(strb->surface); assert(stImage->pt); @@ -1609,59 +1581,6 @@ st_copy_texsubimage(struct gl_context *ctx, -static void -st_CopyTexImage1D(struct gl_context * ctx, GLenum target, GLint level, - GLenum internalFormat, - GLint x, GLint y, GLsizei width, GLint border) -{ - struct gl_texture_unit *texUnit = - &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - struct gl_texture_object *texObj = - _mesa_select_tex_object(ctx, texUnit, target); - struct gl_texture_image *texImage = - _mesa_select_tex_image(ctx, texObj, target, level); - - /* Setup or redefine the texture object, texture and texture - * image. Don't populate yet. - */ - ctx->Driver.TexImage1D(ctx, target, level, internalFormat, - width, border, - GL_RGBA, CHAN_TYPE, NULL, - &ctx->DefaultPacking, texObj, texImage); - - st_copy_texsubimage(ctx, target, level, - 0, 0, 0, /* destX,Y,Z */ - x, y, width, 1); /* src X, Y, size */ -} - - -static void -st_CopyTexImage2D(struct gl_context * ctx, GLenum target, GLint level, - GLenum internalFormat, - GLint x, GLint y, GLsizei width, GLsizei height, - GLint border) -{ - struct gl_texture_unit *texUnit = - &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - struct gl_texture_object *texObj = - _mesa_select_tex_object(ctx, texUnit, target); - struct gl_texture_image *texImage = - _mesa_select_tex_image(ctx, texObj, target, level); - - /* Setup or redefine the texture object, texture and texture - * image. Don't populate yet. - */ - ctx->Driver.TexImage2D(ctx, target, level, internalFormat, - width, height, border, - GL_RGBA, CHAN_TYPE, NULL, - &ctx->DefaultPacking, texObj, texImage); - - st_copy_texsubimage(ctx, target, level, - 0, 0, 0, /* destX,Y,Z */ - x, y, width, height); /* src X, Y, size */ -} - - static void st_CopyTexSubImage1D(struct gl_context * ctx, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) @@ -1947,8 +1866,6 @@ st_init_texture_functions(struct dd_function_table *functions) functions->CompressedTexSubImage1D = st_CompressedTexSubImage1D; functions->CompressedTexSubImage2D = st_CompressedTexSubImage2D; functions->CompressedTexSubImage3D = st_CompressedTexSubImage3D; - functions->CopyTexImage1D = st_CopyTexImage1D; - functions->CopyTexImage2D = st_CopyTexImage2D; functions->CopyTexSubImage1D = st_CopyTexSubImage1D; functions->CopyTexSubImage2D = st_CopyTexSubImage2D; functions->CopyTexSubImage3D = st_CopyTexSubImage3D; diff --git a/mesalib/src/mesa/state_tracker/st_manager.c b/mesalib/src/mesa/state_tracker/st_manager.c index 7bd82aae2..d5228d387 100644 --- a/mesalib/src/mesa/state_tracker/st_manager.c +++ b/mesalib/src/mesa/state_tracker/st_manager.c @@ -587,7 +587,7 @@ st_context_teximage(struct st_context_iface *stctxi, internalFormat = GL_RGB; texFormat = st_ChooseTextureFormat(ctx, internalFormat, - GL_RGBA, GL_UNSIGNED_BYTE); + GL_BGRA, GL_UNSIGNED_BYTE); _mesa_init_teximage_fields(ctx, target, texImage, tex->width0, tex->height0, 1, 0, -- cgit v1.2.3