aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa/state_tracker
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/mesa/state_tracker')
-rw-r--r--mesalib/src/mesa/state_tracker/st_atom_blend.c604
-rw-r--r--mesalib/src/mesa/state_tracker/st_atom_framebuffer.c364
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_bitmap.c1786
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c936
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_clear.c1126
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_drawtex.c614
-rw-r--r--mesalib/src/mesa/state_tracker/st_context.c594
-rw-r--r--mesalib/src/mesa/state_tracker/st_context.h540
-rw-r--r--mesalib/src/mesa/state_tracker/st_draw_feedback.c554
-rw-r--r--mesalib/src/mesa/state_tracker/st_gen_mipmap.c844
-rw-r--r--mesalib/src/mesa/state_tracker/st_program.c2330
11 files changed, 5146 insertions, 5146 deletions
diff --git a/mesalib/src/mesa/state_tracker/st_atom_blend.c b/mesalib/src/mesa/state_tracker/st_atom_blend.c
index fb1c7a4ef..e3b3b9936 100644
--- a/mesalib/src/mesa/state_tracker/st_atom_blend.c
+++ b/mesalib/src/mesa/state_tracker/st_atom_blend.c
@@ -1,302 +1,302 @@
-/**************************************************************************
- *
- * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
- * 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.
- *
- **************************************************************************/
-
- /*
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- * Brian Paul
- */
-
-
-#include "st_context.h"
-#include "st_atom.h"
-
-#include "pipe/p_context.h"
-#include "pipe/p_defines.h"
-#include "cso_cache/cso_context.h"
-
-#include "main/macros.h"
-
-/**
- * Convert GLenum blend tokens to pipe tokens.
- * Both blend factors and blend funcs are accepted.
- */
-static GLuint
-translate_blend(GLenum blend)
-{
- switch (blend) {
- /* blend functions */
- case GL_FUNC_ADD:
- return PIPE_BLEND_ADD;
- case GL_FUNC_SUBTRACT:
- return PIPE_BLEND_SUBTRACT;
- case GL_FUNC_REVERSE_SUBTRACT:
- return PIPE_BLEND_REVERSE_SUBTRACT;
- case GL_MIN:
- return PIPE_BLEND_MIN;
- case GL_MAX:
- return PIPE_BLEND_MAX;
-
- /* blend factors */
- case GL_ONE:
- return PIPE_BLENDFACTOR_ONE;
- case GL_SRC_COLOR:
- return PIPE_BLENDFACTOR_SRC_COLOR;
- case GL_SRC_ALPHA:
- return PIPE_BLENDFACTOR_SRC_ALPHA;
- case GL_DST_ALPHA:
- return PIPE_BLENDFACTOR_DST_ALPHA;
- case GL_DST_COLOR:
- return PIPE_BLENDFACTOR_DST_COLOR;
- case GL_SRC_ALPHA_SATURATE:
- return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE;
- case GL_CONSTANT_COLOR:
- return PIPE_BLENDFACTOR_CONST_COLOR;
- case GL_CONSTANT_ALPHA:
- return PIPE_BLENDFACTOR_CONST_ALPHA;
- /*
- return PIPE_BLENDFACTOR_SRC1_COLOR;
- return PIPE_BLENDFACTOR_SRC1_ALPHA;
- */
- case GL_ZERO:
- return PIPE_BLENDFACTOR_ZERO;
- case GL_ONE_MINUS_SRC_COLOR:
- return PIPE_BLENDFACTOR_INV_SRC_COLOR;
- case GL_ONE_MINUS_SRC_ALPHA:
- return PIPE_BLENDFACTOR_INV_SRC_ALPHA;
- case GL_ONE_MINUS_DST_COLOR:
- return PIPE_BLENDFACTOR_INV_DST_COLOR;
- case GL_ONE_MINUS_DST_ALPHA:
- return PIPE_BLENDFACTOR_INV_DST_ALPHA;
- case GL_ONE_MINUS_CONSTANT_COLOR:
- return PIPE_BLENDFACTOR_INV_CONST_COLOR;
- case GL_ONE_MINUS_CONSTANT_ALPHA:
- return PIPE_BLENDFACTOR_INV_CONST_ALPHA;
- /*
- return PIPE_BLENDFACTOR_INV_SRC1_COLOR;
- return PIPE_BLENDFACTOR_INV_SRC1_ALPHA;
- */
- default:
- assert("invalid GL token in translate_blend()" == NULL);
- return 0;
- }
-}
-
-
-/**
- * Convert GLenum logicop tokens to pipe tokens.
- */
-static GLuint
-translate_logicop(GLenum logicop)
-{
- switch (logicop) {
- case GL_CLEAR:
- return PIPE_LOGICOP_CLEAR;
- case GL_NOR:
- return PIPE_LOGICOP_NOR;
- case GL_AND_INVERTED:
- return PIPE_LOGICOP_AND_INVERTED;
- case GL_COPY_INVERTED:
- return PIPE_LOGICOP_COPY_INVERTED;
- case GL_AND_REVERSE:
- return PIPE_LOGICOP_AND_REVERSE;
- case GL_INVERT:
- return PIPE_LOGICOP_INVERT;
- case GL_XOR:
- return PIPE_LOGICOP_XOR;
- case GL_NAND:
- return PIPE_LOGICOP_NAND;
- case GL_AND:
- return PIPE_LOGICOP_AND;
- case GL_EQUIV:
- return PIPE_LOGICOP_EQUIV;
- case GL_NOOP:
- return PIPE_LOGICOP_NOOP;
- case GL_OR_INVERTED:
- return PIPE_LOGICOP_OR_INVERTED;
- case GL_COPY:
- return PIPE_LOGICOP_COPY;
- case GL_OR_REVERSE:
- return PIPE_LOGICOP_OR_REVERSE;
- case GL_OR:
- return PIPE_LOGICOP_OR;
- case GL_SET:
- return PIPE_LOGICOP_SET;
- default:
- assert("invalid GL token in translate_logicop()" == NULL);
- return 0;
- }
-}
-
-/**
- * Figure out if colormasks are different per rt.
- */
-static GLboolean
-colormask_per_rt(struct gl_context *ctx)
-{
- /* a bit suboptimal have to compare lots of values */
- unsigned i;
- for (i = 1; i < ctx->Const.MaxDrawBuffers; i++) {
- if (memcmp(ctx->Color.ColorMask[0], ctx->Color.ColorMask[i], 4)) {
- return GL_TRUE;
- }
- }
- return GL_FALSE;
-}
-
-/**
- * Figure out if blend enables/state are different per rt.
- */
-static GLboolean
-blend_per_rt(struct gl_context *ctx)
-{
- if (ctx->Color.BlendEnabled &&
- (ctx->Color.BlendEnabled != ((1 << ctx->Const.MaxDrawBuffers) - 1))) {
- /* This can only happen if GL_EXT_draw_buffers2 is enabled */
- return GL_TRUE;
- }
- if (ctx->Color._BlendFuncPerBuffer || ctx->Color._BlendEquationPerBuffer) {
- /* this can only happen if GL_ARB_draw_buffers_blend is enabled */
- return GL_TRUE;
- }
- return GL_FALSE;
-}
-
-static void
-update_blend( struct st_context *st )
-{
- struct pipe_blend_state *blend = &st->state.blend;
- unsigned num_state = 1;
- unsigned i, j;
-
- memset(blend, 0, sizeof(*blend));
-
- if (blend_per_rt(st->ctx) || colormask_per_rt(st->ctx)) {
- num_state = st->ctx->Const.MaxDrawBuffers;
- blend->independent_blend_enable = 1;
- }
- /* Note it is impossible to correctly deal with EXT_blend_logic_op and
- EXT_draw_buffers2/EXT_blend_equation_separate at the same time.
- These combinations would require support for per-rt logicop enables
- and separate alpha/rgb logicop/blend support respectively. Neither
- possible in gallium nor most hardware. Assume these combinations
- don't happen. */
- if (st->ctx->Color.ColorLogicOpEnabled ||
- (st->ctx->Color.BlendEnabled &&
- st->ctx->Color.Blend[0].EquationRGB == GL_LOGIC_OP)) {
- /* logicop enabled */
- blend->logicop_enable = 1;
- blend->logicop_func = translate_logicop(st->ctx->Color.LogicOp);
- }
- else if (st->ctx->Color.BlendEnabled) {
- /* blending enabled */
- for (i = 0, j = 0; i < num_state; i++) {
-
- blend->rt[i].blend_enable = (st->ctx->Color.BlendEnabled >> i) & 0x1;
-
- if (st->ctx->Extensions.ARB_draw_buffers_blend)
- j = i;
-
- blend->rt[i].rgb_func =
- translate_blend(st->ctx->Color.Blend[j].EquationRGB);
-
- if (st->ctx->Color.Blend[i].EquationRGB == GL_MIN ||
- st->ctx->Color.Blend[i].EquationRGB == GL_MAX) {
- /* Min/max are special */
- blend->rt[i].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
- blend->rt[i].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
- }
- else {
- blend->rt[i].rgb_src_factor =
- translate_blend(st->ctx->Color.Blend[j].SrcRGB);
- blend->rt[i].rgb_dst_factor =
- translate_blend(st->ctx->Color.Blend[j].DstRGB);
- }
-
- blend->rt[i].alpha_func =
- translate_blend(st->ctx->Color.Blend[j].EquationA);
-
- if (st->ctx->Color.Blend[i].EquationA == GL_MIN ||
- st->ctx->Color.Blend[i].EquationA == GL_MAX) {
- /* Min/max are special */
- blend->rt[i].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
- blend->rt[i].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
- }
- else {
- blend->rt[i].alpha_src_factor =
- translate_blend(st->ctx->Color.Blend[j].SrcA);
- blend->rt[i].alpha_dst_factor =
- translate_blend(st->ctx->Color.Blend[j].DstA);
- }
- }
- }
- else {
- /* no blending / logicop */
- }
-
- /* Colormask - maybe reverse these bits? */
- for (i = 0; i < num_state; i++) {
- if (st->ctx->Color.ColorMask[i][0])
- blend->rt[i].colormask |= PIPE_MASK_R;
- if (st->ctx->Color.ColorMask[i][1])
- blend->rt[i].colormask |= PIPE_MASK_G;
- if (st->ctx->Color.ColorMask[i][2])
- blend->rt[i].colormask |= PIPE_MASK_B;
- if (st->ctx->Color.ColorMask[i][3])
- blend->rt[i].colormask |= PIPE_MASK_A;
- }
-
- if (st->ctx->Color.DitherFlag)
- blend->dither = 1;
-
- if (st->ctx->Multisample.Enabled) {
- /* unlike in gallium/d3d10 these operations are only performed
- if msaa is enabled */
- if (st->ctx->Multisample.SampleAlphaToCoverage)
- blend->alpha_to_coverage = 1;
- if (st->ctx->Multisample.SampleAlphaToOne)
- blend->alpha_to_one = 1;
- }
-
- cso_set_blend(st->cso_context, blend);
-
- {
- struct pipe_blend_color bc;
- COPY_4FV(bc.color, st->ctx->Color.BlendColor);
- cso_set_blend_color(st->cso_context, &bc);
- }
-}
-
-
-const struct st_tracked_state st_update_blend = {
- "st_update_blend", /* name */
- { /* dirty */
- (_NEW_COLOR | _NEW_MULTISAMPLE), /* XXX _NEW_BLEND someday? */ /* mesa */
- 0, /* st */
- },
- update_blend, /* update */
-};
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Brian Paul
+ */
+
+
+#include "st_context.h"
+#include "st_atom.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "cso_cache/cso_context.h"
+
+#include "main/macros.h"
+
+/**
+ * Convert GLenum blend tokens to pipe tokens.
+ * Both blend factors and blend funcs are accepted.
+ */
+static GLuint
+translate_blend(GLenum blend)
+{
+ switch (blend) {
+ /* blend functions */
+ case GL_FUNC_ADD:
+ return PIPE_BLEND_ADD;
+ case GL_FUNC_SUBTRACT:
+ return PIPE_BLEND_SUBTRACT;
+ case GL_FUNC_REVERSE_SUBTRACT:
+ return PIPE_BLEND_REVERSE_SUBTRACT;
+ case GL_MIN:
+ return PIPE_BLEND_MIN;
+ case GL_MAX:
+ return PIPE_BLEND_MAX;
+
+ /* blend factors */
+ case GL_ONE:
+ return PIPE_BLENDFACTOR_ONE;
+ case GL_SRC_COLOR:
+ return PIPE_BLENDFACTOR_SRC_COLOR;
+ case GL_SRC_ALPHA:
+ return PIPE_BLENDFACTOR_SRC_ALPHA;
+ case GL_DST_ALPHA:
+ return PIPE_BLENDFACTOR_DST_ALPHA;
+ case GL_DST_COLOR:
+ return PIPE_BLENDFACTOR_DST_COLOR;
+ case GL_SRC_ALPHA_SATURATE:
+ return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE;
+ case GL_CONSTANT_COLOR:
+ return PIPE_BLENDFACTOR_CONST_COLOR;
+ case GL_CONSTANT_ALPHA:
+ return PIPE_BLENDFACTOR_CONST_ALPHA;
+ /*
+ return PIPE_BLENDFACTOR_SRC1_COLOR;
+ return PIPE_BLENDFACTOR_SRC1_ALPHA;
+ */
+ case GL_ZERO:
+ return PIPE_BLENDFACTOR_ZERO;
+ case GL_ONE_MINUS_SRC_COLOR:
+ return PIPE_BLENDFACTOR_INV_SRC_COLOR;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ return PIPE_BLENDFACTOR_INV_SRC_ALPHA;
+ case GL_ONE_MINUS_DST_COLOR:
+ return PIPE_BLENDFACTOR_INV_DST_COLOR;
+ case GL_ONE_MINUS_DST_ALPHA:
+ return PIPE_BLENDFACTOR_INV_DST_ALPHA;
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ return PIPE_BLENDFACTOR_INV_CONST_COLOR;
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ return PIPE_BLENDFACTOR_INV_CONST_ALPHA;
+ /*
+ return PIPE_BLENDFACTOR_INV_SRC1_COLOR;
+ return PIPE_BLENDFACTOR_INV_SRC1_ALPHA;
+ */
+ default:
+ assert("invalid GL token in translate_blend()" == NULL);
+ return 0;
+ }
+}
+
+
+/**
+ * Convert GLenum logicop tokens to pipe tokens.
+ */
+static GLuint
+translate_logicop(GLenum logicop)
+{
+ switch (logicop) {
+ case GL_CLEAR:
+ return PIPE_LOGICOP_CLEAR;
+ case GL_NOR:
+ return PIPE_LOGICOP_NOR;
+ case GL_AND_INVERTED:
+ return PIPE_LOGICOP_AND_INVERTED;
+ case GL_COPY_INVERTED:
+ return PIPE_LOGICOP_COPY_INVERTED;
+ case GL_AND_REVERSE:
+ return PIPE_LOGICOP_AND_REVERSE;
+ case GL_INVERT:
+ return PIPE_LOGICOP_INVERT;
+ case GL_XOR:
+ return PIPE_LOGICOP_XOR;
+ case GL_NAND:
+ return PIPE_LOGICOP_NAND;
+ case GL_AND:
+ return PIPE_LOGICOP_AND;
+ case GL_EQUIV:
+ return PIPE_LOGICOP_EQUIV;
+ case GL_NOOP:
+ return PIPE_LOGICOP_NOOP;
+ case GL_OR_INVERTED:
+ return PIPE_LOGICOP_OR_INVERTED;
+ case GL_COPY:
+ return PIPE_LOGICOP_COPY;
+ case GL_OR_REVERSE:
+ return PIPE_LOGICOP_OR_REVERSE;
+ case GL_OR:
+ return PIPE_LOGICOP_OR;
+ case GL_SET:
+ return PIPE_LOGICOP_SET;
+ default:
+ assert("invalid GL token in translate_logicop()" == NULL);
+ return 0;
+ }
+}
+
+/**
+ * Figure out if colormasks are different per rt.
+ */
+static GLboolean
+colormask_per_rt(struct gl_context *ctx)
+{
+ /* a bit suboptimal have to compare lots of values */
+ unsigned i;
+ for (i = 1; i < ctx->Const.MaxDrawBuffers; i++) {
+ if (memcmp(ctx->Color.ColorMask[0], ctx->Color.ColorMask[i], 4)) {
+ return GL_TRUE;
+ }
+ }
+ return GL_FALSE;
+}
+
+/**
+ * Figure out if blend enables/state are different per rt.
+ */
+static GLboolean
+blend_per_rt(struct gl_context *ctx)
+{
+ if (ctx->Color.BlendEnabled &&
+ (ctx->Color.BlendEnabled != ((1 << ctx->Const.MaxDrawBuffers) - 1))) {
+ /* This can only happen if GL_EXT_draw_buffers2 is enabled */
+ return GL_TRUE;
+ }
+ if (ctx->Color._BlendFuncPerBuffer || ctx->Color._BlendEquationPerBuffer) {
+ /* this can only happen if GL_ARB_draw_buffers_blend is enabled */
+ return GL_TRUE;
+ }
+ return GL_FALSE;
+}
+
+static void
+update_blend( struct st_context *st )
+{
+ struct pipe_blend_state *blend = &st->state.blend;
+ unsigned num_state = 1;
+ unsigned i, j;
+
+ memset(blend, 0, sizeof(*blend));
+
+ if (blend_per_rt(st->ctx) || colormask_per_rt(st->ctx)) {
+ num_state = st->ctx->Const.MaxDrawBuffers;
+ blend->independent_blend_enable = 1;
+ }
+ /* Note it is impossible to correctly deal with EXT_blend_logic_op and
+ EXT_draw_buffers2/EXT_blend_equation_separate at the same time.
+ These combinations would require support for per-rt logicop enables
+ and separate alpha/rgb logicop/blend support respectively. Neither
+ possible in gallium nor most hardware. Assume these combinations
+ don't happen. */
+ if (st->ctx->Color.ColorLogicOpEnabled ||
+ (st->ctx->Color.BlendEnabled &&
+ st->ctx->Color.Blend[0].EquationRGB == GL_LOGIC_OP)) {
+ /* logicop enabled */
+ blend->logicop_enable = 1;
+ blend->logicop_func = translate_logicop(st->ctx->Color.LogicOp);
+ }
+ else if (st->ctx->Color.BlendEnabled) {
+ /* blending enabled */
+ for (i = 0, j = 0; i < num_state; i++) {
+
+ blend->rt[i].blend_enable = (st->ctx->Color.BlendEnabled >> i) & 0x1;
+
+ if (st->ctx->Extensions.ARB_draw_buffers_blend)
+ j = i;
+
+ blend->rt[i].rgb_func =
+ translate_blend(st->ctx->Color.Blend[j].EquationRGB);
+
+ if (st->ctx->Color.Blend[i].EquationRGB == GL_MIN ||
+ st->ctx->Color.Blend[i].EquationRGB == GL_MAX) {
+ /* Min/max are special */
+ blend->rt[i].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend->rt[i].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
+ }
+ else {
+ blend->rt[i].rgb_src_factor =
+ translate_blend(st->ctx->Color.Blend[j].SrcRGB);
+ blend->rt[i].rgb_dst_factor =
+ translate_blend(st->ctx->Color.Blend[j].DstRGB);
+ }
+
+ blend->rt[i].alpha_func =
+ translate_blend(st->ctx->Color.Blend[j].EquationA);
+
+ if (st->ctx->Color.Blend[i].EquationA == GL_MIN ||
+ st->ctx->Color.Blend[i].EquationA == GL_MAX) {
+ /* Min/max are special */
+ blend->rt[i].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend->rt[i].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
+ }
+ else {
+ blend->rt[i].alpha_src_factor =
+ translate_blend(st->ctx->Color.Blend[j].SrcA);
+ blend->rt[i].alpha_dst_factor =
+ translate_blend(st->ctx->Color.Blend[j].DstA);
+ }
+ }
+ }
+ else {
+ /* no blending / logicop */
+ }
+
+ /* Colormask - maybe reverse these bits? */
+ for (i = 0; i < num_state; i++) {
+ if (st->ctx->Color.ColorMask[i][0])
+ blend->rt[i].colormask |= PIPE_MASK_R;
+ if (st->ctx->Color.ColorMask[i][1])
+ blend->rt[i].colormask |= PIPE_MASK_G;
+ if (st->ctx->Color.ColorMask[i][2])
+ blend->rt[i].colormask |= PIPE_MASK_B;
+ if (st->ctx->Color.ColorMask[i][3])
+ blend->rt[i].colormask |= PIPE_MASK_A;
+ }
+
+ if (st->ctx->Color.DitherFlag)
+ blend->dither = 1;
+
+ if (st->ctx->Multisample.Enabled) {
+ /* unlike in gallium/d3d10 these operations are only performed
+ if msaa is enabled */
+ if (st->ctx->Multisample.SampleAlphaToCoverage)
+ blend->alpha_to_coverage = 1;
+ if (st->ctx->Multisample.SampleAlphaToOne)
+ blend->alpha_to_one = 1;
+ }
+
+ cso_set_blend(st->cso_context, blend);
+
+ {
+ struct pipe_blend_color bc;
+ COPY_4FV(bc.color, st->ctx->Color.BlendColor);
+ cso_set_blend_color(st->cso_context, &bc);
+ }
+}
+
+
+const struct st_tracked_state st_update_blend = {
+ "st_update_blend", /* name */
+ { /* dirty */
+ (_NEW_COLOR | _NEW_MULTISAMPLE), /* XXX _NEW_BLEND someday? */ /* mesa */
+ 0, /* st */
+ },
+ update_blend, /* update */
+};
diff --git a/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c b/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c
index 76386fe01..678a270c7 100644
--- a/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c
+++ b/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c
@@ -1,182 +1,182 @@
-/**************************************************************************
- *
- * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
- * 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.
- *
- **************************************************************************/
-
- /*
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- * Brian Paul
- */
-
-#include "st_context.h"
-#include "st_atom.h"
-#include "st_cb_fbo.h"
-#include "st_texture.h"
-#include "pipe/p_context.h"
-#include "cso_cache/cso_context.h"
-#include "util/u_math.h"
-#include "util/u_inlines.h"
-#include "util/u_format.h"
-
-
-/**
- * When doing GL render to texture, we have to be sure that finalize_texture()
- * didn't yank out the pipe_resource that we earlier created a surface for.
- * Check for that here and create a new surface if needed.
- */
-static void
-update_renderbuffer_surface(struct st_context *st,
- struct st_renderbuffer *strb)
-{
- struct pipe_context *pipe = st->pipe;
- struct pipe_resource *resource = strb->rtt->pt;
- int rtt_width = strb->Base.Width;
- int rtt_height = strb->Base.Height;
- enum pipe_format format = st->ctx->Color.sRGBEnabled ? resource->format : util_format_linear(resource->format);
-
- if (!strb->surface ||
- strb->surface->format != format ||
- strb->surface->texture != resource ||
- strb->surface->width != rtt_width ||
- strb->surface->height != rtt_height) {
- GLuint level;
- /* find matching mipmap level size */
- for (level = 0; level <= resource->last_level; level++) {
- if (u_minify(resource->width0, level) == rtt_width &&
- u_minify(resource->height0, level) == rtt_height) {
- struct pipe_surface surf_tmpl;
- memset(&surf_tmpl, 0, sizeof(surf_tmpl));
- surf_tmpl.format = format;
- surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
- surf_tmpl.u.tex.level = level;
- surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice;
- surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice;
-
- pipe_surface_reference(&strb->surface, NULL);
-
- strb->surface = pipe->create_surface(pipe,
- resource,
- &surf_tmpl);
-#if 0
- printf("-- alloc new surface %d x %d into tex %p\n",
- strb->surface->width, strb->surface->height,
- texture);
-#endif
- break;
- }
- }
- }
-}
-
-
-/**
- * Update framebuffer state (color, depth, stencil, etc. buffers)
- */
-static void
-update_framebuffer_state( struct st_context *st )
-{
- struct pipe_framebuffer_state *framebuffer = &st->state.framebuffer;
- struct gl_framebuffer *fb = st->ctx->DrawBuffer;
- struct st_renderbuffer *strb;
- GLuint i;
-
- framebuffer->width = fb->Width;
- framebuffer->height = fb->Height;
-
- /*printf("------ fb size %d x %d\n", fb->Width, fb->Height);*/
-
- /* Examine Mesa's ctx->DrawBuffer->_ColorDrawBuffers state
- * to determine which surfaces to draw to
- */
- framebuffer->nr_cbufs = 0;
- for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
- strb = st_renderbuffer(fb->_ColorDrawBuffers[i]);
-
- if (strb) {
- /*printf("--------- framebuffer surface rtt %p\n", strb->rtt);*/
- if (strb->rtt) {
- /* rendering to a GL texture, may have to update surface */
- update_renderbuffer_surface(st, strb);
- }
-
- if (strb->surface) {
- pipe_surface_reference(&framebuffer->cbufs[framebuffer->nr_cbufs],
- strb->surface);
- framebuffer->nr_cbufs++;
- }
- strb->defined = GL_TRUE; /* we'll be drawing something */
- }
- }
- for (i = framebuffer->nr_cbufs; i < PIPE_MAX_COLOR_BUFS; i++) {
- pipe_surface_reference(&framebuffer->cbufs[i], NULL);
- }
-
- /*
- * Depth/Stencil renderbuffer/surface.
- */
- strb = st_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer);
- if (strb) {
- strb = st_renderbuffer(strb->Base.Wrapped);
- if (strb->rtt) {
- /* rendering to a GL texture, may have to update surface */
- update_renderbuffer_surface(st, strb);
- }
- pipe_surface_reference(&framebuffer->zsbuf, strb->surface);
- }
- else {
- strb = st_renderbuffer(fb->Attachment[BUFFER_STENCIL].Renderbuffer);
- if (strb) {
- strb = st_renderbuffer(strb->Base.Wrapped);
- assert(strb->surface);
- pipe_surface_reference(&framebuffer->zsbuf, strb->surface);
- }
- else
- pipe_surface_reference(&framebuffer->zsbuf, NULL);
- }
-
-#ifdef DEBUG
- /* Make sure the resource binding flags were set properly */
- for (i = 0; i < framebuffer->nr_cbufs; i++) {
- assert(framebuffer->cbufs[i]->texture->bind & PIPE_BIND_RENDER_TARGET);
- }
- if (framebuffer->zsbuf) {
- assert(framebuffer->zsbuf->texture->bind & PIPE_BIND_DEPTH_STENCIL);
- }
-#endif
-
- cso_set_framebuffer(st->cso_context, framebuffer);
-}
-
-
-const struct st_tracked_state st_update_framebuffer = {
- "st_update_framebuffer", /* name */
- { /* dirty */
- _NEW_BUFFERS, /* mesa */
- ST_NEW_FRAMEBUFFER, /* st */
- },
- update_framebuffer_state /* update */
-};
-
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Brian Paul
+ */
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_cb_fbo.h"
+#include "st_texture.h"
+#include "pipe/p_context.h"
+#include "cso_cache/cso_context.h"
+#include "util/u_math.h"
+#include "util/u_inlines.h"
+#include "util/u_format.h"
+
+
+/**
+ * When doing GL render to texture, we have to be sure that finalize_texture()
+ * didn't yank out the pipe_resource that we earlier created a surface for.
+ * Check for that here and create a new surface if needed.
+ */
+static void
+update_renderbuffer_surface(struct st_context *st,
+ struct st_renderbuffer *strb)
+{
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_resource *resource = strb->rtt->pt;
+ int rtt_width = strb->Base.Width;
+ int rtt_height = strb->Base.Height;
+ enum pipe_format format = st->ctx->Color.sRGBEnabled ? resource->format : util_format_linear(resource->format);
+
+ if (!strb->surface ||
+ strb->surface->format != format ||
+ strb->surface->texture != resource ||
+ strb->surface->width != rtt_width ||
+ strb->surface->height != rtt_height) {
+ GLuint level;
+ /* find matching mipmap level size */
+ for (level = 0; level <= resource->last_level; level++) {
+ if (u_minify(resource->width0, level) == rtt_width &&
+ u_minify(resource->height0, level) == rtt_height) {
+ struct pipe_surface surf_tmpl;
+ memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+ surf_tmpl.format = format;
+ surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
+ surf_tmpl.u.tex.level = level;
+ surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice;
+ surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice;
+
+ pipe_surface_reference(&strb->surface, NULL);
+
+ strb->surface = pipe->create_surface(pipe,
+ resource,
+ &surf_tmpl);
+#if 0
+ printf("-- alloc new surface %d x %d into tex %p\n",
+ strb->surface->width, strb->surface->height,
+ texture);
+#endif
+ break;
+ }
+ }
+ }
+}
+
+
+/**
+ * Update framebuffer state (color, depth, stencil, etc. buffers)
+ */
+static void
+update_framebuffer_state( struct st_context *st )
+{
+ struct pipe_framebuffer_state *framebuffer = &st->state.framebuffer;
+ struct gl_framebuffer *fb = st->ctx->DrawBuffer;
+ struct st_renderbuffer *strb;
+ GLuint i;
+
+ framebuffer->width = fb->Width;
+ framebuffer->height = fb->Height;
+
+ /*printf("------ fb size %d x %d\n", fb->Width, fb->Height);*/
+
+ /* Examine Mesa's ctx->DrawBuffer->_ColorDrawBuffers state
+ * to determine which surfaces to draw to
+ */
+ framebuffer->nr_cbufs = 0;
+ for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
+ strb = st_renderbuffer(fb->_ColorDrawBuffers[i]);
+
+ if (strb) {
+ /*printf("--------- framebuffer surface rtt %p\n", strb->rtt);*/
+ if (strb->rtt) {
+ /* rendering to a GL texture, may have to update surface */
+ update_renderbuffer_surface(st, strb);
+ }
+
+ if (strb->surface) {
+ pipe_surface_reference(&framebuffer->cbufs[framebuffer->nr_cbufs],
+ strb->surface);
+ framebuffer->nr_cbufs++;
+ }
+ strb->defined = GL_TRUE; /* we'll be drawing something */
+ }
+ }
+ for (i = framebuffer->nr_cbufs; i < PIPE_MAX_COLOR_BUFS; i++) {
+ pipe_surface_reference(&framebuffer->cbufs[i], NULL);
+ }
+
+ /*
+ * Depth/Stencil renderbuffer/surface.
+ */
+ strb = st_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer);
+ if (strb) {
+ strb = st_renderbuffer(strb->Base.Wrapped);
+ if (strb->rtt) {
+ /* rendering to a GL texture, may have to update surface */
+ update_renderbuffer_surface(st, strb);
+ }
+ pipe_surface_reference(&framebuffer->zsbuf, strb->surface);
+ }
+ else {
+ strb = st_renderbuffer(fb->Attachment[BUFFER_STENCIL].Renderbuffer);
+ if (strb) {
+ strb = st_renderbuffer(strb->Base.Wrapped);
+ assert(strb->surface);
+ pipe_surface_reference(&framebuffer->zsbuf, strb->surface);
+ }
+ else
+ pipe_surface_reference(&framebuffer->zsbuf, NULL);
+ }
+
+#ifdef DEBUG
+ /* Make sure the resource binding flags were set properly */
+ for (i = 0; i < framebuffer->nr_cbufs; i++) {
+ assert(framebuffer->cbufs[i]->texture->bind & PIPE_BIND_RENDER_TARGET);
+ }
+ if (framebuffer->zsbuf) {
+ assert(framebuffer->zsbuf->texture->bind & PIPE_BIND_DEPTH_STENCIL);
+ }
+#endif
+
+ cso_set_framebuffer(st->cso_context, framebuffer);
+}
+
+
+const struct st_tracked_state st_update_framebuffer = {
+ "st_update_framebuffer", /* name */
+ { /* dirty */
+ _NEW_BUFFERS, /* mesa */
+ ST_NEW_FRAMEBUFFER, /* st */
+ },
+ update_framebuffer_state /* update */
+};
+
diff --git a/mesalib/src/mesa/state_tracker/st_cb_bitmap.c b/mesalib/src/mesa/state_tracker/st_cb_bitmap.c
index 0ea567155..51623c179 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_bitmap.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_bitmap.c
@@ -1,893 +1,893 @@
-/**************************************************************************
- *
- * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
- * 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.
- *
- **************************************************************************/
-
- /*
- * Authors:
- * Brian Paul
- */
-
-#include "main/imports.h"
-#include "main/image.h"
-#include "main/bufferobj.h"
-#include "main/macros.h"
-#include "main/mfeatures.h"
-#include "program/program.h"
-#include "program/prog_print.h"
-
-#include "st_context.h"
-#include "st_atom.h"
-#include "st_atom_constbuf.h"
-#include "st_program.h"
-#include "st_cb_bitmap.h"
-#include "st_texture.h"
-
-#include "pipe/p_context.h"
-#include "pipe/p_defines.h"
-#include "pipe/p_shader_tokens.h"
-#include "util/u_inlines.h"
-#include "util/u_draw_quad.h"
-#include "util/u_simple_shaders.h"
-#include "program/prog_instruction.h"
-#include "cso_cache/cso_context.h"
-
-
-#if FEATURE_drawpix
-
-/**
- * glBitmaps are drawn as textured quads. The user's bitmap pattern
- * is stored in a texture image. An alpha8 texture format is used.
- * The fragment shader samples a bit (texel) from the texture, then
- * discards the fragment if the bit is off.
- *
- * Note that we actually store the inverse image of the bitmap to
- * simplify the fragment program. An "on" bit gets stored as texel=0x0
- * and an "off" bit is stored as texel=0xff. Then we kill the
- * fragment if the negated texel value is less than zero.
- */
-
-
-/**
- * The bitmap cache attempts to accumulate multiple glBitmap calls in a
- * buffer which is then rendered en mass upon a flush, state change, etc.
- * A wide, short buffer is used to target the common case of a series
- * of glBitmap calls being used to draw text.
- */
-static GLboolean UseBitmapCache = GL_TRUE;
-
-
-#define BITMAP_CACHE_WIDTH 512
-#define BITMAP_CACHE_HEIGHT 32
-
-struct bitmap_cache
-{
- /** Window pos to render the cached image */
- GLint xpos, ypos;
- /** Bounds of region used in window coords */
- GLint xmin, ymin, xmax, ymax;
-
- GLfloat color[4];
-
- /** Bitmap's Z position */
- GLfloat zpos;
-
- struct pipe_resource *texture;
- struct pipe_transfer *trans;
-
- GLboolean empty;
-
- /** An I8 texture image: */
- ubyte *buffer;
-};
-
-
-/** Epsilon for Z comparisons */
-#define Z_EPSILON 1e-06
-
-
-/**
- * Make fragment program for glBitmap:
- * Sample the texture and kill the fragment if the bit is 0.
- * This program will be combined with the user's fragment program.
- */
-static struct st_fragment_program *
-make_bitmap_fragment_program(struct gl_context *ctx, GLuint samplerIndex)
-{
- struct st_context *st = st_context(ctx);
- struct st_fragment_program *stfp;
- struct gl_program *p;
- GLuint ic = 0;
-
- p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
- if (!p)
- return NULL;
-
- p->NumInstructions = 3;
-
- p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
- if (!p->Instructions) {
- ctx->Driver.DeleteProgram(ctx, p);
- return NULL;
- }
- _mesa_init_instructions(p->Instructions, p->NumInstructions);
-
- /* TEX tmp0, fragment.texcoord[0], texture[0], 2D; */
- p->Instructions[ic].Opcode = OPCODE_TEX;
- p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY;
- p->Instructions[ic].DstReg.Index = 0;
- p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
- p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
- p->Instructions[ic].TexSrcUnit = samplerIndex;
- p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
- ic++;
-
- /* KIL if -tmp0 < 0 # texel=0 -> keep / texel=0 -> discard */
- p->Instructions[ic].Opcode = OPCODE_KIL;
- p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
-
- if (st->bitmap.tex_format == PIPE_FORMAT_L8_UNORM)
- p->Instructions[ic].SrcReg[0].Swizzle = SWIZZLE_XXXX;
-
- p->Instructions[ic].SrcReg[0].Index = 0;
- p->Instructions[ic].SrcReg[0].Negate = NEGATE_XYZW;
- ic++;
-
- /* END; */
- p->Instructions[ic++].Opcode = OPCODE_END;
-
- assert(ic == p->NumInstructions);
-
- p->InputsRead = FRAG_BIT_TEX0;
- p->OutputsWritten = 0x0;
- p->SamplersUsed = (1 << samplerIndex);
-
- stfp = (struct st_fragment_program *) p;
- stfp->Base.UsesKill = GL_TRUE;
-
- return stfp;
-}
-
-
-static int
-find_free_bit(uint bitfield)
-{
- int i;
- for (i = 0; i < 32; i++) {
- if ((bitfield & (1 << i)) == 0) {
- return i;
- }
- }
- return -1;
-}
-
-
-/**
- * Combine basic bitmap fragment program with the user-defined program.
- * \param st current context
- * \param fpIn the incoming fragment program
- * \param fpOut the new fragment program which does fragment culling
- * \param bitmap_sampler sampler number for the bitmap texture
- */
-void
-st_make_bitmap_fragment_program(struct st_context *st,
- struct gl_fragment_program *fpIn,
- struct gl_fragment_program **fpOut,
- GLuint *bitmap_sampler)
-{
- struct st_fragment_program *bitmap_prog;
- struct gl_program *newProg;
- uint sampler;
-
- /*
- * Generate new program which is the user-defined program prefixed
- * with the bitmap sampler/kill instructions.
- */
- sampler = find_free_bit(fpIn->Base.SamplersUsed);
- bitmap_prog = make_bitmap_fragment_program(st->ctx, sampler);
-
- newProg = _mesa_combine_programs(st->ctx,
- &bitmap_prog->Base.Base,
- &fpIn->Base);
- /* done with this after combining */
- st_reference_fragprog(st, &bitmap_prog, NULL);
-
-#if 0
- {
- printf("Combined bitmap program:\n");
- _mesa_print_program(newProg);
- printf("InputsRead: 0x%x\n", newProg->InputsRead);
- printf("OutputsWritten: 0x%x\n", newProg->OutputsWritten);
- _mesa_print_parameter_list(newProg->Parameters);
- }
-#endif
-
- /* return results */
- *fpOut = (struct gl_fragment_program *) newProg;
- *bitmap_sampler = sampler;
-}
-
-
-/**
- * Copy user-provide bitmap bits into texture buffer, expanding
- * bits into texels.
- * "On" bits will set texels to 0x0.
- * "Off" bits will not modify texels.
- * Note that the image is actually going to be upside down in
- * the texture. We deal with that with texcoords.
- */
-static void
-unpack_bitmap(struct st_context *st,
- GLint px, GLint py, GLsizei width, GLsizei height,
- const struct gl_pixelstore_attrib *unpack,
- const GLubyte *bitmap,
- ubyte *destBuffer, uint destStride)
-{
- destBuffer += py * destStride + px;
-
- _mesa_expand_bitmap(width, height, unpack, bitmap,
- destBuffer, destStride, 0x0);
-}
-
-
-/**
- * Create a texture which represents a bitmap image.
- */
-static struct pipe_resource *
-make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height,
- const struct gl_pixelstore_attrib *unpack,
- const GLubyte *bitmap)
-{
- struct st_context *st = st_context(ctx);
- struct pipe_context *pipe = st->pipe;
- struct pipe_transfer *transfer;
- ubyte *dest;
- struct pipe_resource *pt;
-
- /* PBO source... */
- bitmap = _mesa_map_pbo_source(ctx, unpack, bitmap);
- if (!bitmap) {
- return NULL;
- }
-
- /**
- * Create texture to hold bitmap pattern.
- */
- pt = st_texture_create(st, st->internal_target, st->bitmap.tex_format,
- 0, width, height, 1, 1,
- PIPE_BIND_SAMPLER_VIEW);
- if (!pt) {
- _mesa_unmap_pbo_source(ctx, unpack);
- return NULL;
- }
-
- transfer = pipe_get_transfer(st->pipe, pt, 0, 0,
- PIPE_TRANSFER_WRITE,
- 0, 0, width, height);
-
- dest = pipe_transfer_map(pipe, transfer);
-
- /* Put image into texture transfer */
- memset(dest, 0xff, height * transfer->stride);
- unpack_bitmap(st, 0, 0, width, height, unpack, bitmap,
- dest, transfer->stride);
-
- _mesa_unmap_pbo_source(ctx, unpack);
-
- /* Release transfer */
- pipe_transfer_unmap(pipe, transfer);
- pipe->transfer_destroy(pipe, transfer);
-
- return pt;
-}
-
-static GLuint
-setup_bitmap_vertex_data(struct st_context *st, bool normalized,
- int x, int y, int width, int height,
- float z, const float color[4])
-{
- struct pipe_context *pipe = st->pipe;
- const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
- const GLfloat fb_width = (GLfloat)fb->Width;
- const GLfloat fb_height = (GLfloat)fb->Height;
- const GLfloat x0 = (GLfloat)x;
- const GLfloat x1 = (GLfloat)(x + width);
- const GLfloat y0 = (GLfloat)y;
- const GLfloat y1 = (GLfloat)(y + height);
- GLfloat sLeft = (GLfloat)0.0, sRight = (GLfloat)1.0;
- GLfloat tTop = (GLfloat)0.0, tBot = (GLfloat)1.0 - tTop;
- const GLfloat clip_x0 = (GLfloat)(x0 / fb_width * 2.0 - 1.0);
- const GLfloat clip_y0 = (GLfloat)(y0 / fb_height * 2.0 - 1.0);
- const GLfloat clip_x1 = (GLfloat)(x1 / fb_width * 2.0 - 1.0);
- const GLfloat clip_y1 = (GLfloat)(y1 / fb_height * 2.0 - 1.0);
- const GLuint max_slots = 1; /* 4096 / sizeof(st->bitmap.vertices); */
- GLuint i;
-
- if(!normalized)
- {
- sRight = width;
- tBot = height;
- }
-
- /* XXX: Need to improve buffer_write to allow NO_WAIT (as well as
- * no_flush) updates to buffers where we know there is no conflict
- * with previous data. Currently using max_slots > 1 will cause
- * synchronous rendering if the driver flushes its command buffers
- * between one bitmap and the next. Our flush hook below isn't
- * sufficient to catch this as the driver doesn't tell us when it
- * flushes its own command buffers. Until this gets fixed, pay the
- * price of allocating a new buffer for each bitmap cache-flush to
- * avoid synchronous rendering.
- */
- if (st->bitmap.vbuf_slot >= max_slots) {
- pipe_resource_reference(&st->bitmap.vbuf, NULL);
- st->bitmap.vbuf_slot = 0;
- }
-
- if (!st->bitmap.vbuf) {
- st->bitmap.vbuf = pipe_buffer_create(pipe->screen,
- PIPE_BIND_VERTEX_BUFFER,
- PIPE_USAGE_STREAM,
- max_slots *
- sizeof(st->bitmap.vertices));
- }
-
- /* Positions are in clip coords since we need to do clipping in case
- * the bitmap quad goes beyond the window bounds.
- */
- st->bitmap.vertices[0][0][0] = clip_x0;
- st->bitmap.vertices[0][0][1] = clip_y0;
- st->bitmap.vertices[0][2][0] = sLeft;
- st->bitmap.vertices[0][2][1] = tTop;
-
- st->bitmap.vertices[1][0][0] = clip_x1;
- st->bitmap.vertices[1][0][1] = clip_y0;
- st->bitmap.vertices[1][2][0] = sRight;
- st->bitmap.vertices[1][2][1] = tTop;
-
- st->bitmap.vertices[2][0][0] = clip_x1;
- st->bitmap.vertices[2][0][1] = clip_y1;
- st->bitmap.vertices[2][2][0] = sRight;
- st->bitmap.vertices[2][2][1] = tBot;
-
- st->bitmap.vertices[3][0][0] = clip_x0;
- st->bitmap.vertices[3][0][1] = clip_y1;
- st->bitmap.vertices[3][2][0] = sLeft;
- st->bitmap.vertices[3][2][1] = tBot;
-
- /* same for all verts: */
- for (i = 0; i < 4; i++) {
- st->bitmap.vertices[i][0][2] = z;
- st->bitmap.vertices[i][0][3] = 1.0;
- st->bitmap.vertices[i][1][0] = color[0];
- st->bitmap.vertices[i][1][1] = color[1];
- st->bitmap.vertices[i][1][2] = color[2];
- st->bitmap.vertices[i][1][3] = color[3];
- st->bitmap.vertices[i][2][2] = 0.0; /*R*/
- st->bitmap.vertices[i][2][3] = 1.0; /*Q*/
- }
-
- /* put vertex data into vbuf */
- pipe_buffer_write_nooverlap(st->pipe,
- st->bitmap.vbuf,
- st->bitmap.vbuf_slot
- * sizeof(st->bitmap.vertices),
- sizeof st->bitmap.vertices,
- st->bitmap.vertices);
-
- return st->bitmap.vbuf_slot++ * sizeof st->bitmap.vertices;
-}
-
-
-
-/**
- * Render a glBitmap by drawing a textured quad
- */
-static void
-draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
- GLsizei width, GLsizei height,
- struct pipe_sampler_view *sv,
- const GLfloat *color)
-{
- struct st_context *st = st_context(ctx);
- struct pipe_context *pipe = st->pipe;
- struct cso_context *cso = st->cso_context;
- struct st_fp_variant *fpv;
- struct st_fp_variant_key key;
- GLuint maxSize;
- GLuint offset;
-
- memset(&key, 0, sizeof(key));
- key.st = st;
- key.bitmap = GL_TRUE;
-
- fpv = st_get_fp_variant(st, st->fp, &key);
-
- /* As an optimization, Mesa's fragment programs will sometimes get the
- * primary color from a statevar/constant rather than a varying variable.
- * when that's the case, we need to ensure that we use the 'color'
- * parameter and not the current attribute color (which may have changed
- * through glRasterPos and state validation.
- * So, we force the proper color here. Not elegant, but it works.
- */
- {
- GLfloat colorSave[4];
- COPY_4V(colorSave, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
- COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], color);
- st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT);
- COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], colorSave);
- }
-
-
- /* limit checks */
- /* XXX if the bitmap is larger than the max texture size, break
- * it up into chunks.
- */
- maxSize = 1 << (pipe->screen->get_param(pipe->screen,
- PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
- assert(width <= (GLsizei)maxSize);
- assert(height <= (GLsizei)maxSize);
-
- cso_save_rasterizer(cso);
- cso_save_samplers(cso);
- cso_save_fragment_sampler_views(cso);
- cso_save_viewport(cso);
- cso_save_fragment_shader(cso);
- cso_save_vertex_shader(cso);
- cso_save_vertex_elements(cso);
- cso_save_vertex_buffers(cso);
-
- /* rasterizer state: just scissor */
- st->bitmap.rasterizer.scissor = ctx->Scissor.Enabled;
- cso_set_rasterizer(cso, &st->bitmap.rasterizer);
-
- /* fragment shader state: TEX lookup program */
- cso_set_fragment_shader_handle(cso, fpv->driver_shader);
-
- /* vertex shader state: position + texcoord pass-through */
- cso_set_vertex_shader_handle(cso, st->bitmap.vs);
-
- /* user samplers, plus our bitmap sampler */
- {
- struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
- uint num = MAX2(fpv->bitmap_sampler + 1, st->state.num_samplers);
- uint i;
- for (i = 0; i < st->state.num_samplers; i++) {
- samplers[i] = &st->state.samplers[i];
- }
- samplers[fpv->bitmap_sampler] =
- &st->bitmap.samplers[sv->texture->target != PIPE_TEXTURE_RECT];
- cso_set_samplers(cso, num, (const struct pipe_sampler_state **) samplers);
- }
-
- /* user textures, plus the bitmap texture */
- {
- struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
- uint num = MAX2(fpv->bitmap_sampler + 1, st->state.num_textures);
- memcpy(sampler_views, st->state.sampler_views, sizeof(sampler_views));
- sampler_views[fpv->bitmap_sampler] = sv;
- cso_set_fragment_sampler_views(cso, num, sampler_views);
- }
-
- /* viewport state: viewport matching window dims */
- {
- const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
- const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP);
- const GLfloat width = (GLfloat)fb->Width;
- const GLfloat height = (GLfloat)fb->Height;
- struct pipe_viewport_state vp;
- vp.scale[0] = 0.5f * width;
- vp.scale[1] = height * (invert ? -0.5f : 0.5f);
- vp.scale[2] = 0.5f;
- vp.scale[3] = 1.0f;
- vp.translate[0] = 0.5f * width;
- vp.translate[1] = 0.5f * height;
- vp.translate[2] = 0.5f;
- vp.translate[3] = 0.0f;
- cso_set_viewport(cso, &vp);
- }
-
- cso_set_vertex_elements(cso, 3, st->velems_util_draw);
-
- /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */
- z = z * 2.0 - 1.0;
-
- /* draw textured quad */
- offset = setup_bitmap_vertex_data(st,
- sv->texture->target != PIPE_TEXTURE_RECT,
- x, y, width, height, z, color);
-
- util_draw_vertex_buffer(pipe, st->cso_context, st->bitmap.vbuf, offset,
- PIPE_PRIM_TRIANGLE_FAN,
- 4, /* verts */
- 3); /* attribs/vert */
-
-
- /* restore state */
- cso_restore_rasterizer(cso);
- cso_restore_samplers(cso);
- cso_restore_fragment_sampler_views(cso);
- cso_restore_viewport(cso);
- cso_restore_fragment_shader(cso);
- cso_restore_vertex_shader(cso);
- cso_restore_vertex_elements(cso);
- cso_restore_vertex_buffers(cso);
-}
-
-
-static void
-reset_cache(struct st_context *st)
-{
- struct pipe_context *pipe = st->pipe;
- struct bitmap_cache *cache = st->bitmap.cache;
-
- /*memset(cache->buffer, 0xff, sizeof(cache->buffer));*/
- cache->empty = GL_TRUE;
-
- cache->xmin = 1000000;
- cache->xmax = -1000000;
- cache->ymin = 1000000;
- cache->ymax = -1000000;
-
- if (cache->trans) {
- pipe->transfer_destroy(pipe, cache->trans);
- cache->trans = NULL;
- }
-
- assert(!cache->texture);
-
- /* allocate a new texture */
- cache->texture = st_texture_create(st, PIPE_TEXTURE_2D,
- st->bitmap.tex_format, 0,
- BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
- 1, 1,
- PIPE_BIND_SAMPLER_VIEW);
-}
-
-
-/** Print bitmap image to stdout (debug) */
-static void
-print_cache(const struct bitmap_cache *cache)
-{
- int i, j, k;
-
- for (i = 0; i < BITMAP_CACHE_HEIGHT; i++) {
- k = BITMAP_CACHE_WIDTH * (BITMAP_CACHE_HEIGHT - i - 1);
- for (j = 0; j < BITMAP_CACHE_WIDTH; j++) {
- if (cache->buffer[k])
- printf("X");
- else
- printf(" ");
- k++;
- }
- printf("\n");
- }
-}
-
-
-/**
- * Create gallium pipe_transfer object for the bitmap cache.
- */
-static void
-create_cache_trans(struct st_context *st)
-{
- struct pipe_context *pipe = st->pipe;
- struct bitmap_cache *cache = st->bitmap.cache;
-
- if (cache->trans)
- return;
-
- /* Map the texture transfer.
- * Subsequent glBitmap calls will write into the texture image.
- */
- cache->trans = pipe_get_transfer(st->pipe, cache->texture, 0, 0,
- PIPE_TRANSFER_WRITE, 0, 0,
- BITMAP_CACHE_WIDTH,
- BITMAP_CACHE_HEIGHT);
- cache->buffer = pipe_transfer_map(pipe, cache->trans);
-
- /* init image to all 0xff */
- memset(cache->buffer, 0xff, cache->trans->stride * BITMAP_CACHE_HEIGHT);
-}
-
-
-/**
- * If there's anything in the bitmap cache, draw/flush it now.
- */
-void
-st_flush_bitmap_cache(struct st_context *st)
-{
- if (!st->bitmap.cache->empty) {
- struct bitmap_cache *cache = st->bitmap.cache;
-
- if (st->ctx->DrawBuffer) {
- struct pipe_context *pipe = st->pipe;
- struct pipe_sampler_view *sv;
-
- assert(cache->xmin <= cache->xmax);
-
-/* printf("flush size %d x %d at %d, %d\n",
- cache->xmax - cache->xmin,
- cache->ymax - cache->ymin,
- cache->xpos, cache->ypos);
-*/
-
- /* The texture transfer has been mapped until now.
- * So unmap and release the texture transfer before drawing.
- */
- if (cache->trans) {
- if (0)
- print_cache(cache);
- pipe_transfer_unmap(pipe, cache->trans);
- cache->buffer = NULL;
-
- pipe->transfer_destroy(pipe, cache->trans);
- cache->trans = NULL;
- }
-
- sv = st_create_texture_sampler_view(st->pipe, cache->texture);
- if (sv) {
- draw_bitmap_quad(st->ctx,
- cache->xpos,
- cache->ypos,
- cache->zpos,
- BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
- sv,
- cache->color);
-
- pipe_sampler_view_reference(&sv, NULL);
- }
- }
-
- /* release/free the texture */
- pipe_resource_reference(&cache->texture, NULL);
-
- reset_cache(st);
- }
-}
-
-
-/**
- * Flush bitmap cache and release vertex buffer.
- */
-void
-st_flush_bitmap( struct st_context *st )
-{
- st_flush_bitmap_cache(st);
-
- /* Release vertex buffer to avoid synchronous rendering if we were
- * to map it in the next frame.
- */
- pipe_resource_reference(&st->bitmap.vbuf, NULL);
- st->bitmap.vbuf_slot = 0;
-}
-
-
-/**
- * Try to accumulate this glBitmap call in the bitmap cache.
- * \return GL_TRUE for success, GL_FALSE if bitmap is too large, etc.
- */
-static GLboolean
-accum_bitmap(struct st_context *st,
- GLint x, GLint y, GLsizei width, GLsizei height,
- const struct gl_pixelstore_attrib *unpack,
- const GLubyte *bitmap )
-{
- struct bitmap_cache *cache = st->bitmap.cache;
- int px = -999, py = -999;
- const GLfloat z = st->ctx->Current.RasterPos[2];
-
- if (width > BITMAP_CACHE_WIDTH ||
- height > BITMAP_CACHE_HEIGHT)
- return GL_FALSE; /* too big to cache */
-
- if (!cache->empty) {
- px = x - cache->xpos; /* pos in buffer */
- py = y - cache->ypos;
- if (px < 0 || px + width > BITMAP_CACHE_WIDTH ||
- py < 0 || py + height > BITMAP_CACHE_HEIGHT ||
- !TEST_EQ_4V(st->ctx->Current.RasterColor, cache->color) ||
- ((fabs(z - cache->zpos) > Z_EPSILON))) {
- /* This bitmap would extend beyond cache bounds, or the bitmap
- * color is changing
- * so flush and continue.
- */
- st_flush_bitmap_cache(st);
- }
- }
-
- if (cache->empty) {
- /* Initialize. Center bitmap vertically in the buffer. */
- px = 0;
- py = (BITMAP_CACHE_HEIGHT - height) / 2;
- cache->xpos = x;
- cache->ypos = y - py;
- cache->zpos = z;
- cache->empty = GL_FALSE;
- COPY_4FV(cache->color, st->ctx->Current.RasterColor);
- }
-
- assert(px != -999);
- assert(py != -999);
-
- if (x < cache->xmin)
- cache->xmin = x;
- if (y < cache->ymin)
- cache->ymin = y;
- if (x + width > cache->xmax)
- cache->xmax = x + width;
- if (y + height > cache->ymax)
- cache->ymax = y + height;
-
- /* create the transfer if needed */
- create_cache_trans(st);
-
- unpack_bitmap(st, px, py, width, height, unpack, bitmap,
- cache->buffer, BITMAP_CACHE_WIDTH);
-
- return GL_TRUE; /* accumulated */
-}
-
-
-
-/**
- * Called via ctx->Driver.Bitmap()
- */
-static void
-st_Bitmap(struct gl_context *ctx, GLint x, GLint y,
- GLsizei width, GLsizei height,
- const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap )
-{
- struct st_context *st = st_context(ctx);
- struct pipe_resource *pt;
-
- if (width == 0 || height == 0)
- return;
-
- st_validate_state(st);
-
- if (!st->bitmap.vs) {
- /* create pass-through vertex shader now */
- const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
- TGSI_SEMANTIC_COLOR,
- TGSI_SEMANTIC_GENERIC };
- const uint semantic_indexes[] = { 0, 0, 0 };
- st->bitmap.vs = util_make_vertex_passthrough_shader(st->pipe, 3,
- semantic_names,
- semantic_indexes);
- }
-
- if (UseBitmapCache && accum_bitmap(st, x, y, width, height, unpack, bitmap))
- return;
-
- pt = make_bitmap_texture(ctx, width, height, unpack, bitmap);
- if (pt) {
- struct pipe_sampler_view *sv =
- st_create_texture_sampler_view(st->pipe, pt);
-
- assert(pt->target == PIPE_TEXTURE_2D || pt->target == PIPE_TEXTURE_RECT);
-
- if (sv) {
- draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2],
- width, height, sv,
- st->ctx->Current.RasterColor);
-
- pipe_sampler_view_reference(&sv, NULL);
- }
-
- /* release/free the texture */
- pipe_resource_reference(&pt, NULL);
- }
-}
-
-
-/** Per-context init */
-void
-st_init_bitmap_functions(struct dd_function_table *functions)
-{
- functions->Bitmap = st_Bitmap;
-}
-
-
-/** Per-context init */
-void
-st_init_bitmap(struct st_context *st)
-{
- struct pipe_sampler_state *sampler = &st->bitmap.samplers[0];
- struct pipe_context *pipe = st->pipe;
- struct pipe_screen *screen = pipe->screen;
-
- /* init sampler state once */
- memset(sampler, 0, sizeof(*sampler));
- sampler->wrap_s = PIPE_TEX_WRAP_CLAMP;
- sampler->wrap_t = PIPE_TEX_WRAP_CLAMP;
- sampler->wrap_r = PIPE_TEX_WRAP_CLAMP;
- sampler->min_img_filter = PIPE_TEX_FILTER_NEAREST;
- sampler->min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
- sampler->mag_img_filter = PIPE_TEX_FILTER_NEAREST;
- st->bitmap.samplers[1] = *sampler;
- st->bitmap.samplers[1].normalized_coords = 1;
-
- /* init baseline rasterizer state once */
- memset(&st->bitmap.rasterizer, 0, sizeof(st->bitmap.rasterizer));
- st->bitmap.rasterizer.gl_rasterization_rules = 1;
-
- /* find a usable texture format */
- if (screen->is_format_supported(screen, PIPE_FORMAT_I8_UNORM,
- PIPE_TEXTURE_2D, 0,
- PIPE_BIND_SAMPLER_VIEW, 0)) {
- st->bitmap.tex_format = PIPE_FORMAT_I8_UNORM;
- }
- else if (screen->is_format_supported(screen, PIPE_FORMAT_A8_UNORM,
- PIPE_TEXTURE_2D, 0,
- PIPE_BIND_SAMPLER_VIEW, 0)) {
- st->bitmap.tex_format = PIPE_FORMAT_A8_UNORM;
- }
- else if (screen->is_format_supported(screen, PIPE_FORMAT_L8_UNORM,
- PIPE_TEXTURE_2D, 0,
- PIPE_BIND_SAMPLER_VIEW, 0)) {
- st->bitmap.tex_format = PIPE_FORMAT_L8_UNORM;
- }
- else {
- /* XXX support more formats */
- assert(0);
- }
-
- /* alloc bitmap cache object */
- st->bitmap.cache = ST_CALLOC_STRUCT(bitmap_cache);
-
- reset_cache(st);
-}
-
-
-/** Per-context tear-down */
-void
-st_destroy_bitmap(struct st_context *st)
-{
- struct pipe_context *pipe = st->pipe;
- struct bitmap_cache *cache = st->bitmap.cache;
-
- if (st->bitmap.vs) {
- cso_delete_vertex_shader(st->cso_context, st->bitmap.vs);
- st->bitmap.vs = NULL;
- }
-
- if (st->bitmap.vbuf) {
- pipe_resource_reference(&st->bitmap.vbuf, NULL);
- st->bitmap.vbuf = NULL;
- }
-
- if (cache) {
- if (cache->trans) {
- pipe_transfer_unmap(pipe, cache->trans);
- pipe->transfer_destroy(pipe, cache->trans);
- }
- pipe_resource_reference(&st->bitmap.cache->texture, NULL);
- free(st->bitmap.cache);
- st->bitmap.cache = NULL;
- }
-}
-
-#endif /* FEATURE_drawpix */
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Brian Paul
+ */
+
+#include "main/imports.h"
+#include "main/image.h"
+#include "main/bufferobj.h"
+#include "main/macros.h"
+#include "main/mfeatures.h"
+#include "program/program.h"
+#include "program/prog_print.h"
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_atom_constbuf.h"
+#include "st_program.h"
+#include "st_cb_bitmap.h"
+#include "st_texture.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_shader_tokens.h"
+#include "util/u_inlines.h"
+#include "util/u_draw_quad.h"
+#include "util/u_simple_shaders.h"
+#include "program/prog_instruction.h"
+#include "cso_cache/cso_context.h"
+
+
+#if FEATURE_drawpix
+
+/**
+ * glBitmaps are drawn as textured quads. The user's bitmap pattern
+ * is stored in a texture image. An alpha8 texture format is used.
+ * The fragment shader samples a bit (texel) from the texture, then
+ * discards the fragment if the bit is off.
+ *
+ * Note that we actually store the inverse image of the bitmap to
+ * simplify the fragment program. An "on" bit gets stored as texel=0x0
+ * and an "off" bit is stored as texel=0xff. Then we kill the
+ * fragment if the negated texel value is less than zero.
+ */
+
+
+/**
+ * The bitmap cache attempts to accumulate multiple glBitmap calls in a
+ * buffer which is then rendered en mass upon a flush, state change, etc.
+ * A wide, short buffer is used to target the common case of a series
+ * of glBitmap calls being used to draw text.
+ */
+static GLboolean UseBitmapCache = GL_TRUE;
+
+
+#define BITMAP_CACHE_WIDTH 512
+#define BITMAP_CACHE_HEIGHT 32
+
+struct bitmap_cache
+{
+ /** Window pos to render the cached image */
+ GLint xpos, ypos;
+ /** Bounds of region used in window coords */
+ GLint xmin, ymin, xmax, ymax;
+
+ GLfloat color[4];
+
+ /** Bitmap's Z position */
+ GLfloat zpos;
+
+ struct pipe_resource *texture;
+ struct pipe_transfer *trans;
+
+ GLboolean empty;
+
+ /** An I8 texture image: */
+ ubyte *buffer;
+};
+
+
+/** Epsilon for Z comparisons */
+#define Z_EPSILON 1e-06
+
+
+/**
+ * Make fragment program for glBitmap:
+ * Sample the texture and kill the fragment if the bit is 0.
+ * This program will be combined with the user's fragment program.
+ */
+static struct st_fragment_program *
+make_bitmap_fragment_program(struct gl_context *ctx, GLuint samplerIndex)
+{
+ struct st_context *st = st_context(ctx);
+ struct st_fragment_program *stfp;
+ struct gl_program *p;
+ GLuint ic = 0;
+
+ p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
+ if (!p)
+ return NULL;
+
+ p->NumInstructions = 3;
+
+ p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
+ if (!p->Instructions) {
+ ctx->Driver.DeleteProgram(ctx, p);
+ return NULL;
+ }
+ _mesa_init_instructions(p->Instructions, p->NumInstructions);
+
+ /* TEX tmp0, fragment.texcoord[0], texture[0], 2D; */
+ p->Instructions[ic].Opcode = OPCODE_TEX;
+ p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY;
+ p->Instructions[ic].DstReg.Index = 0;
+ p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
+ p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
+ p->Instructions[ic].TexSrcUnit = samplerIndex;
+ p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
+ ic++;
+
+ /* KIL if -tmp0 < 0 # texel=0 -> keep / texel=0 -> discard */
+ p->Instructions[ic].Opcode = OPCODE_KIL;
+ p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+
+ if (st->bitmap.tex_format == PIPE_FORMAT_L8_UNORM)
+ p->Instructions[ic].SrcReg[0].Swizzle = SWIZZLE_XXXX;
+
+ p->Instructions[ic].SrcReg[0].Index = 0;
+ p->Instructions[ic].SrcReg[0].Negate = NEGATE_XYZW;
+ ic++;
+
+ /* END; */
+ p->Instructions[ic++].Opcode = OPCODE_END;
+
+ assert(ic == p->NumInstructions);
+
+ p->InputsRead = FRAG_BIT_TEX0;
+ p->OutputsWritten = 0x0;
+ p->SamplersUsed = (1 << samplerIndex);
+
+ stfp = (struct st_fragment_program *) p;
+ stfp->Base.UsesKill = GL_TRUE;
+
+ return stfp;
+}
+
+
+static int
+find_free_bit(uint bitfield)
+{
+ int i;
+ for (i = 0; i < 32; i++) {
+ if ((bitfield & (1 << i)) == 0) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+
+/**
+ * Combine basic bitmap fragment program with the user-defined program.
+ * \param st current context
+ * \param fpIn the incoming fragment program
+ * \param fpOut the new fragment program which does fragment culling
+ * \param bitmap_sampler sampler number for the bitmap texture
+ */
+void
+st_make_bitmap_fragment_program(struct st_context *st,
+ struct gl_fragment_program *fpIn,
+ struct gl_fragment_program **fpOut,
+ GLuint *bitmap_sampler)
+{
+ struct st_fragment_program *bitmap_prog;
+ struct gl_program *newProg;
+ uint sampler;
+
+ /*
+ * Generate new program which is the user-defined program prefixed
+ * with the bitmap sampler/kill instructions.
+ */
+ sampler = find_free_bit(fpIn->Base.SamplersUsed);
+ bitmap_prog = make_bitmap_fragment_program(st->ctx, sampler);
+
+ newProg = _mesa_combine_programs(st->ctx,
+ &bitmap_prog->Base.Base,
+ &fpIn->Base);
+ /* done with this after combining */
+ st_reference_fragprog(st, &bitmap_prog, NULL);
+
+#if 0
+ {
+ printf("Combined bitmap program:\n");
+ _mesa_print_program(newProg);
+ printf("InputsRead: 0x%x\n", newProg->InputsRead);
+ printf("OutputsWritten: 0x%x\n", newProg->OutputsWritten);
+ _mesa_print_parameter_list(newProg->Parameters);
+ }
+#endif
+
+ /* return results */
+ *fpOut = (struct gl_fragment_program *) newProg;
+ *bitmap_sampler = sampler;
+}
+
+
+/**
+ * Copy user-provide bitmap bits into texture buffer, expanding
+ * bits into texels.
+ * "On" bits will set texels to 0x0.
+ * "Off" bits will not modify texels.
+ * Note that the image is actually going to be upside down in
+ * the texture. We deal with that with texcoords.
+ */
+static void
+unpack_bitmap(struct st_context *st,
+ GLint px, GLint py, GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap,
+ ubyte *destBuffer, uint destStride)
+{
+ destBuffer += py * destStride + px;
+
+ _mesa_expand_bitmap(width, height, unpack, bitmap,
+ destBuffer, destStride, 0x0);
+}
+
+
+/**
+ * Create a texture which represents a bitmap image.
+ */
+static struct pipe_resource *
+make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap)
+{
+ struct st_context *st = st_context(ctx);
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_transfer *transfer;
+ ubyte *dest;
+ struct pipe_resource *pt;
+
+ /* PBO source... */
+ bitmap = _mesa_map_pbo_source(ctx, unpack, bitmap);
+ if (!bitmap) {
+ return NULL;
+ }
+
+ /**
+ * Create texture to hold bitmap pattern.
+ */
+ pt = st_texture_create(st, st->internal_target, st->bitmap.tex_format,
+ 0, width, height, 1, 1,
+ PIPE_BIND_SAMPLER_VIEW);
+ if (!pt) {
+ _mesa_unmap_pbo_source(ctx, unpack);
+ return NULL;
+ }
+
+ transfer = pipe_get_transfer(st->pipe, pt, 0, 0,
+ PIPE_TRANSFER_WRITE,
+ 0, 0, width, height);
+
+ dest = pipe_transfer_map(pipe, transfer);
+
+ /* Put image into texture transfer */
+ memset(dest, 0xff, height * transfer->stride);
+ unpack_bitmap(st, 0, 0, width, height, unpack, bitmap,
+ dest, transfer->stride);
+
+ _mesa_unmap_pbo_source(ctx, unpack);
+
+ /* Release transfer */
+ pipe_transfer_unmap(pipe, transfer);
+ pipe->transfer_destroy(pipe, transfer);
+
+ return pt;
+}
+
+static GLuint
+setup_bitmap_vertex_data(struct st_context *st, bool normalized,
+ int x, int y, int width, int height,
+ float z, const float color[4])
+{
+ struct pipe_context *pipe = st->pipe;
+ const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
+ const GLfloat fb_width = (GLfloat)fb->Width;
+ const GLfloat fb_height = (GLfloat)fb->Height;
+ const GLfloat x0 = (GLfloat)x;
+ const GLfloat x1 = (GLfloat)(x + width);
+ const GLfloat y0 = (GLfloat)y;
+ const GLfloat y1 = (GLfloat)(y + height);
+ GLfloat sLeft = (GLfloat)0.0, sRight = (GLfloat)1.0;
+ GLfloat tTop = (GLfloat)0.0, tBot = (GLfloat)1.0 - tTop;
+ const GLfloat clip_x0 = (GLfloat)(x0 / fb_width * 2.0 - 1.0);
+ const GLfloat clip_y0 = (GLfloat)(y0 / fb_height * 2.0 - 1.0);
+ const GLfloat clip_x1 = (GLfloat)(x1 / fb_width * 2.0 - 1.0);
+ const GLfloat clip_y1 = (GLfloat)(y1 / fb_height * 2.0 - 1.0);
+ const GLuint max_slots = 1; /* 4096 / sizeof(st->bitmap.vertices); */
+ GLuint i;
+
+ if(!normalized)
+ {
+ sRight = width;
+ tBot = height;
+ }
+
+ /* XXX: Need to improve buffer_write to allow NO_WAIT (as well as
+ * no_flush) updates to buffers where we know there is no conflict
+ * with previous data. Currently using max_slots > 1 will cause
+ * synchronous rendering if the driver flushes its command buffers
+ * between one bitmap and the next. Our flush hook below isn't
+ * sufficient to catch this as the driver doesn't tell us when it
+ * flushes its own command buffers. Until this gets fixed, pay the
+ * price of allocating a new buffer for each bitmap cache-flush to
+ * avoid synchronous rendering.
+ */
+ if (st->bitmap.vbuf_slot >= max_slots) {
+ pipe_resource_reference(&st->bitmap.vbuf, NULL);
+ st->bitmap.vbuf_slot = 0;
+ }
+
+ if (!st->bitmap.vbuf) {
+ st->bitmap.vbuf = pipe_buffer_create(pipe->screen,
+ PIPE_BIND_VERTEX_BUFFER,
+ PIPE_USAGE_STREAM,
+ max_slots *
+ sizeof(st->bitmap.vertices));
+ }
+
+ /* Positions are in clip coords since we need to do clipping in case
+ * the bitmap quad goes beyond the window bounds.
+ */
+ st->bitmap.vertices[0][0][0] = clip_x0;
+ st->bitmap.vertices[0][0][1] = clip_y0;
+ st->bitmap.vertices[0][2][0] = sLeft;
+ st->bitmap.vertices[0][2][1] = tTop;
+
+ st->bitmap.vertices[1][0][0] = clip_x1;
+ st->bitmap.vertices[1][0][1] = clip_y0;
+ st->bitmap.vertices[1][2][0] = sRight;
+ st->bitmap.vertices[1][2][1] = tTop;
+
+ st->bitmap.vertices[2][0][0] = clip_x1;
+ st->bitmap.vertices[2][0][1] = clip_y1;
+ st->bitmap.vertices[2][2][0] = sRight;
+ st->bitmap.vertices[2][2][1] = tBot;
+
+ st->bitmap.vertices[3][0][0] = clip_x0;
+ st->bitmap.vertices[3][0][1] = clip_y1;
+ st->bitmap.vertices[3][2][0] = sLeft;
+ st->bitmap.vertices[3][2][1] = tBot;
+
+ /* same for all verts: */
+ for (i = 0; i < 4; i++) {
+ st->bitmap.vertices[i][0][2] = z;
+ st->bitmap.vertices[i][0][3] = 1.0;
+ st->bitmap.vertices[i][1][0] = color[0];
+ st->bitmap.vertices[i][1][1] = color[1];
+ st->bitmap.vertices[i][1][2] = color[2];
+ st->bitmap.vertices[i][1][3] = color[3];
+ st->bitmap.vertices[i][2][2] = 0.0; /*R*/
+ st->bitmap.vertices[i][2][3] = 1.0; /*Q*/
+ }
+
+ /* put vertex data into vbuf */
+ pipe_buffer_write_nooverlap(st->pipe,
+ st->bitmap.vbuf,
+ st->bitmap.vbuf_slot
+ * sizeof(st->bitmap.vertices),
+ sizeof st->bitmap.vertices,
+ st->bitmap.vertices);
+
+ return st->bitmap.vbuf_slot++ * sizeof st->bitmap.vertices;
+}
+
+
+
+/**
+ * Render a glBitmap by drawing a textured quad
+ */
+static void
+draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
+ GLsizei width, GLsizei height,
+ struct pipe_sampler_view *sv,
+ const GLfloat *color)
+{
+ struct st_context *st = st_context(ctx);
+ struct pipe_context *pipe = st->pipe;
+ struct cso_context *cso = st->cso_context;
+ struct st_fp_variant *fpv;
+ struct st_fp_variant_key key;
+ GLuint maxSize;
+ GLuint offset;
+
+ memset(&key, 0, sizeof(key));
+ key.st = st;
+ key.bitmap = GL_TRUE;
+
+ fpv = st_get_fp_variant(st, st->fp, &key);
+
+ /* As an optimization, Mesa's fragment programs will sometimes get the
+ * primary color from a statevar/constant rather than a varying variable.
+ * when that's the case, we need to ensure that we use the 'color'
+ * parameter and not the current attribute color (which may have changed
+ * through glRasterPos and state validation.
+ * So, we force the proper color here. Not elegant, but it works.
+ */
+ {
+ GLfloat colorSave[4];
+ COPY_4V(colorSave, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
+ COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], color);
+ st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT);
+ COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], colorSave);
+ }
+
+
+ /* limit checks */
+ /* XXX if the bitmap is larger than the max texture size, break
+ * it up into chunks.
+ */
+ maxSize = 1 << (pipe->screen->get_param(pipe->screen,
+ PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
+ assert(width <= (GLsizei)maxSize);
+ assert(height <= (GLsizei)maxSize);
+
+ cso_save_rasterizer(cso);
+ cso_save_samplers(cso);
+ cso_save_fragment_sampler_views(cso);
+ cso_save_viewport(cso);
+ cso_save_fragment_shader(cso);
+ cso_save_vertex_shader(cso);
+ cso_save_vertex_elements(cso);
+ cso_save_vertex_buffers(cso);
+
+ /* rasterizer state: just scissor */
+ st->bitmap.rasterizer.scissor = ctx->Scissor.Enabled;
+ cso_set_rasterizer(cso, &st->bitmap.rasterizer);
+
+ /* fragment shader state: TEX lookup program */
+ cso_set_fragment_shader_handle(cso, fpv->driver_shader);
+
+ /* vertex shader state: position + texcoord pass-through */
+ cso_set_vertex_shader_handle(cso, st->bitmap.vs);
+
+ /* user samplers, plus our bitmap sampler */
+ {
+ struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
+ uint num = MAX2(fpv->bitmap_sampler + 1, st->state.num_samplers);
+ uint i;
+ for (i = 0; i < st->state.num_samplers; i++) {
+ samplers[i] = &st->state.samplers[i];
+ }
+ samplers[fpv->bitmap_sampler] =
+ &st->bitmap.samplers[sv->texture->target != PIPE_TEXTURE_RECT];
+ cso_set_samplers(cso, num, (const struct pipe_sampler_state **) samplers);
+ }
+
+ /* user textures, plus the bitmap texture */
+ {
+ struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
+ uint num = MAX2(fpv->bitmap_sampler + 1, st->state.num_textures);
+ memcpy(sampler_views, st->state.sampler_views, sizeof(sampler_views));
+ sampler_views[fpv->bitmap_sampler] = sv;
+ cso_set_fragment_sampler_views(cso, num, sampler_views);
+ }
+
+ /* viewport state: viewport matching window dims */
+ {
+ const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
+ const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP);
+ const GLfloat width = (GLfloat)fb->Width;
+ const GLfloat height = (GLfloat)fb->Height;
+ struct pipe_viewport_state vp;
+ vp.scale[0] = 0.5f * width;
+ vp.scale[1] = height * (invert ? -0.5f : 0.5f);
+ vp.scale[2] = 0.5f;
+ vp.scale[3] = 1.0f;
+ vp.translate[0] = 0.5f * width;
+ vp.translate[1] = 0.5f * height;
+ vp.translate[2] = 0.5f;
+ vp.translate[3] = 0.0f;
+ cso_set_viewport(cso, &vp);
+ }
+
+ cso_set_vertex_elements(cso, 3, st->velems_util_draw);
+
+ /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */
+ z = z * 2.0 - 1.0;
+
+ /* draw textured quad */
+ offset = setup_bitmap_vertex_data(st,
+ sv->texture->target != PIPE_TEXTURE_RECT,
+ x, y, width, height, z, color);
+
+ util_draw_vertex_buffer(pipe, st->cso_context, st->bitmap.vbuf, offset,
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ 3); /* attribs/vert */
+
+
+ /* restore state */
+ cso_restore_rasterizer(cso);
+ cso_restore_samplers(cso);
+ cso_restore_fragment_sampler_views(cso);
+ cso_restore_viewport(cso);
+ cso_restore_fragment_shader(cso);
+ cso_restore_vertex_shader(cso);
+ cso_restore_vertex_elements(cso);
+ cso_restore_vertex_buffers(cso);
+}
+
+
+static void
+reset_cache(struct st_context *st)
+{
+ struct pipe_context *pipe = st->pipe;
+ struct bitmap_cache *cache = st->bitmap.cache;
+
+ /*memset(cache->buffer, 0xff, sizeof(cache->buffer));*/
+ cache->empty = GL_TRUE;
+
+ cache->xmin = 1000000;
+ cache->xmax = -1000000;
+ cache->ymin = 1000000;
+ cache->ymax = -1000000;
+
+ if (cache->trans) {
+ pipe->transfer_destroy(pipe, cache->trans);
+ cache->trans = NULL;
+ }
+
+ assert(!cache->texture);
+
+ /* allocate a new texture */
+ cache->texture = st_texture_create(st, PIPE_TEXTURE_2D,
+ st->bitmap.tex_format, 0,
+ BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
+ 1, 1,
+ PIPE_BIND_SAMPLER_VIEW);
+}
+
+
+/** Print bitmap image to stdout (debug) */
+static void
+print_cache(const struct bitmap_cache *cache)
+{
+ int i, j, k;
+
+ for (i = 0; i < BITMAP_CACHE_HEIGHT; i++) {
+ k = BITMAP_CACHE_WIDTH * (BITMAP_CACHE_HEIGHT - i - 1);
+ for (j = 0; j < BITMAP_CACHE_WIDTH; j++) {
+ if (cache->buffer[k])
+ printf("X");
+ else
+ printf(" ");
+ k++;
+ }
+ printf("\n");
+ }
+}
+
+
+/**
+ * Create gallium pipe_transfer object for the bitmap cache.
+ */
+static void
+create_cache_trans(struct st_context *st)
+{
+ struct pipe_context *pipe = st->pipe;
+ struct bitmap_cache *cache = st->bitmap.cache;
+
+ if (cache->trans)
+ return;
+
+ /* Map the texture transfer.
+ * Subsequent glBitmap calls will write into the texture image.
+ */
+ cache->trans = pipe_get_transfer(st->pipe, cache->texture, 0, 0,
+ PIPE_TRANSFER_WRITE, 0, 0,
+ BITMAP_CACHE_WIDTH,
+ BITMAP_CACHE_HEIGHT);
+ cache->buffer = pipe_transfer_map(pipe, cache->trans);
+
+ /* init image to all 0xff */
+ memset(cache->buffer, 0xff, cache->trans->stride * BITMAP_CACHE_HEIGHT);
+}
+
+
+/**
+ * If there's anything in the bitmap cache, draw/flush it now.
+ */
+void
+st_flush_bitmap_cache(struct st_context *st)
+{
+ if (!st->bitmap.cache->empty) {
+ struct bitmap_cache *cache = st->bitmap.cache;
+
+ if (st->ctx->DrawBuffer) {
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_sampler_view *sv;
+
+ assert(cache->xmin <= cache->xmax);
+
+/* printf("flush size %d x %d at %d, %d\n",
+ cache->xmax - cache->xmin,
+ cache->ymax - cache->ymin,
+ cache->xpos, cache->ypos);
+*/
+
+ /* The texture transfer has been mapped until now.
+ * So unmap and release the texture transfer before drawing.
+ */
+ if (cache->trans) {
+ if (0)
+ print_cache(cache);
+ pipe_transfer_unmap(pipe, cache->trans);
+ cache->buffer = NULL;
+
+ pipe->transfer_destroy(pipe, cache->trans);
+ cache->trans = NULL;
+ }
+
+ sv = st_create_texture_sampler_view(st->pipe, cache->texture);
+ if (sv) {
+ draw_bitmap_quad(st->ctx,
+ cache->xpos,
+ cache->ypos,
+ cache->zpos,
+ BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
+ sv,
+ cache->color);
+
+ pipe_sampler_view_reference(&sv, NULL);
+ }
+ }
+
+ /* release/free the texture */
+ pipe_resource_reference(&cache->texture, NULL);
+
+ reset_cache(st);
+ }
+}
+
+
+/**
+ * Flush bitmap cache and release vertex buffer.
+ */
+void
+st_flush_bitmap( struct st_context *st )
+{
+ st_flush_bitmap_cache(st);
+
+ /* Release vertex buffer to avoid synchronous rendering if we were
+ * to map it in the next frame.
+ */
+ pipe_resource_reference(&st->bitmap.vbuf, NULL);
+ st->bitmap.vbuf_slot = 0;
+}
+
+
+/**
+ * Try to accumulate this glBitmap call in the bitmap cache.
+ * \return GL_TRUE for success, GL_FALSE if bitmap is too large, etc.
+ */
+static GLboolean
+accum_bitmap(struct st_context *st,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap )
+{
+ struct bitmap_cache *cache = st->bitmap.cache;
+ int px = -999, py = -999;
+ const GLfloat z = st->ctx->Current.RasterPos[2];
+
+ if (width > BITMAP_CACHE_WIDTH ||
+ height > BITMAP_CACHE_HEIGHT)
+ return GL_FALSE; /* too big to cache */
+
+ if (!cache->empty) {
+ px = x - cache->xpos; /* pos in buffer */
+ py = y - cache->ypos;
+ if (px < 0 || px + width > BITMAP_CACHE_WIDTH ||
+ py < 0 || py + height > BITMAP_CACHE_HEIGHT ||
+ !TEST_EQ_4V(st->ctx->Current.RasterColor, cache->color) ||
+ ((fabs(z - cache->zpos) > Z_EPSILON))) {
+ /* This bitmap would extend beyond cache bounds, or the bitmap
+ * color is changing
+ * so flush and continue.
+ */
+ st_flush_bitmap_cache(st);
+ }
+ }
+
+ if (cache->empty) {
+ /* Initialize. Center bitmap vertically in the buffer. */
+ px = 0;
+ py = (BITMAP_CACHE_HEIGHT - height) / 2;
+ cache->xpos = x;
+ cache->ypos = y - py;
+ cache->zpos = z;
+ cache->empty = GL_FALSE;
+ COPY_4FV(cache->color, st->ctx->Current.RasterColor);
+ }
+
+ assert(px != -999);
+ assert(py != -999);
+
+ if (x < cache->xmin)
+ cache->xmin = x;
+ if (y < cache->ymin)
+ cache->ymin = y;
+ if (x + width > cache->xmax)
+ cache->xmax = x + width;
+ if (y + height > cache->ymax)
+ cache->ymax = y + height;
+
+ /* create the transfer if needed */
+ create_cache_trans(st);
+
+ unpack_bitmap(st, px, py, width, height, unpack, bitmap,
+ cache->buffer, BITMAP_CACHE_WIDTH);
+
+ return GL_TRUE; /* accumulated */
+}
+
+
+
+/**
+ * Called via ctx->Driver.Bitmap()
+ */
+static void
+st_Bitmap(struct gl_context *ctx, GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap )
+{
+ struct st_context *st = st_context(ctx);
+ struct pipe_resource *pt;
+
+ if (width == 0 || height == 0)
+ return;
+
+ st_validate_state(st);
+
+ if (!st->bitmap.vs) {
+ /* create pass-through vertex shader now */
+ const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
+ TGSI_SEMANTIC_COLOR,
+ TGSI_SEMANTIC_GENERIC };
+ const uint semantic_indexes[] = { 0, 0, 0 };
+ st->bitmap.vs = util_make_vertex_passthrough_shader(st->pipe, 3,
+ semantic_names,
+ semantic_indexes);
+ }
+
+ if (UseBitmapCache && accum_bitmap(st, x, y, width, height, unpack, bitmap))
+ return;
+
+ pt = make_bitmap_texture(ctx, width, height, unpack, bitmap);
+ if (pt) {
+ struct pipe_sampler_view *sv =
+ st_create_texture_sampler_view(st->pipe, pt);
+
+ assert(pt->target == PIPE_TEXTURE_2D || pt->target == PIPE_TEXTURE_RECT);
+
+ if (sv) {
+ draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2],
+ width, height, sv,
+ st->ctx->Current.RasterColor);
+
+ pipe_sampler_view_reference(&sv, NULL);
+ }
+
+ /* release/free the texture */
+ pipe_resource_reference(&pt, NULL);
+ }
+}
+
+
+/** Per-context init */
+void
+st_init_bitmap_functions(struct dd_function_table *functions)
+{
+ functions->Bitmap = st_Bitmap;
+}
+
+
+/** Per-context init */
+void
+st_init_bitmap(struct st_context *st)
+{
+ struct pipe_sampler_state *sampler = &st->bitmap.samplers[0];
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+
+ /* init sampler state once */
+ memset(sampler, 0, sizeof(*sampler));
+ sampler->wrap_s = PIPE_TEX_WRAP_CLAMP;
+ sampler->wrap_t = PIPE_TEX_WRAP_CLAMP;
+ sampler->wrap_r = PIPE_TEX_WRAP_CLAMP;
+ sampler->min_img_filter = PIPE_TEX_FILTER_NEAREST;
+ sampler->min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ sampler->mag_img_filter = PIPE_TEX_FILTER_NEAREST;
+ st->bitmap.samplers[1] = *sampler;
+ st->bitmap.samplers[1].normalized_coords = 1;
+
+ /* init baseline rasterizer state once */
+ memset(&st->bitmap.rasterizer, 0, sizeof(st->bitmap.rasterizer));
+ st->bitmap.rasterizer.gl_rasterization_rules = 1;
+
+ /* find a usable texture format */
+ if (screen->is_format_supported(screen, PIPE_FORMAT_I8_UNORM,
+ PIPE_TEXTURE_2D, 0,
+ PIPE_BIND_SAMPLER_VIEW, 0)) {
+ st->bitmap.tex_format = PIPE_FORMAT_I8_UNORM;
+ }
+ else if (screen->is_format_supported(screen, PIPE_FORMAT_A8_UNORM,
+ PIPE_TEXTURE_2D, 0,
+ PIPE_BIND_SAMPLER_VIEW, 0)) {
+ st->bitmap.tex_format = PIPE_FORMAT_A8_UNORM;
+ }
+ else if (screen->is_format_supported(screen, PIPE_FORMAT_L8_UNORM,
+ PIPE_TEXTURE_2D, 0,
+ PIPE_BIND_SAMPLER_VIEW, 0)) {
+ st->bitmap.tex_format = PIPE_FORMAT_L8_UNORM;
+ }
+ else {
+ /* XXX support more formats */
+ assert(0);
+ }
+
+ /* alloc bitmap cache object */
+ st->bitmap.cache = ST_CALLOC_STRUCT(bitmap_cache);
+
+ reset_cache(st);
+}
+
+
+/** Per-context tear-down */
+void
+st_destroy_bitmap(struct st_context *st)
+{
+ struct pipe_context *pipe = st->pipe;
+ struct bitmap_cache *cache = st->bitmap.cache;
+
+ if (st->bitmap.vs) {
+ cso_delete_vertex_shader(st->cso_context, st->bitmap.vs);
+ st->bitmap.vs = NULL;
+ }
+
+ if (st->bitmap.vbuf) {
+ pipe_resource_reference(&st->bitmap.vbuf, NULL);
+ st->bitmap.vbuf = NULL;
+ }
+
+ if (cache) {
+ if (cache->trans) {
+ pipe_transfer_unmap(pipe, cache->trans);
+ pipe->transfer_destroy(pipe, cache->trans);
+ }
+ pipe_resource_reference(&st->bitmap.cache->texture, NULL);
+ free(st->bitmap.cache);
+ st->bitmap.cache = NULL;
+ }
+}
+
+#endif /* FEATURE_drawpix */
diff --git a/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c b/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c
index 12528f49f..9dd1f8a3e 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c
@@ -1,468 +1,468 @@
-/**************************************************************************
- *
- * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
- * 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.
- *
- **************************************************************************/
-
-
-/**
- * Functions for pixel buffer objects and vertex/element buffer objects.
- */
-
-
-#include "main/imports.h"
-#include "main/mtypes.h"
-#include "main/arrayobj.h"
-#include "main/bufferobj.h"
-
-#include "st_context.h"
-#include "st_cb_bufferobjects.h"
-
-#include "pipe/p_context.h"
-#include "pipe/p_defines.h"
-#include "util/u_inlines.h"
-
-
-/**
- * There is some duplication between mesa's bufferobjects and our
- * bufmgr buffers. Both have an integer handle and a hashtable to
- * lookup an opaque structure. It would be nice if the handles and
- * internal structure where somehow shared.
- */
-static struct gl_buffer_object *
-st_bufferobj_alloc(struct gl_context *ctx, GLuint name, GLenum target)
-{
- struct st_buffer_object *st_obj = ST_CALLOC_STRUCT(st_buffer_object);
-
- if (!st_obj)
- return NULL;
-
- _mesa_initialize_buffer_object(&st_obj->Base, name, target);
-
- return &st_obj->Base;
-}
-
-
-
-/**
- * Deallocate/free a vertex/pixel buffer object.
- * Called via glDeleteBuffersARB().
- */
-static void
-st_bufferobj_free(struct gl_context *ctx, struct gl_buffer_object *obj)
-{
- struct st_buffer_object *st_obj = st_buffer_object(obj);
-
- assert(obj->RefCount == 0);
- assert(st_obj->transfer == NULL);
-
- if (st_obj->buffer)
- pipe_resource_reference(&st_obj->buffer, NULL);
-
- free(st_obj);
-}
-
-
-
-/**
- * Replace data in a subrange of buffer object. If the data range
- * specified by size + offset extends beyond the end of the buffer or
- * if data is NULL, no copy is performed.
- * Called via glBufferSubDataARB().
- */
-static void
-st_bufferobj_subdata(struct gl_context *ctx,
- GLenum target,
- GLintptrARB offset,
- GLsizeiptrARB size,
- const GLvoid * data, struct gl_buffer_object *obj)
-{
- struct st_buffer_object *st_obj = st_buffer_object(obj);
-
- /* we may be called from VBO code, so double-check params here */
- ASSERT(offset >= 0);
- ASSERT(size >= 0);
- ASSERT(offset + size <= obj->Size);
-
- if (!size)
- return;
-
- /*
- * According to ARB_vertex_buffer_object specification, if data is null,
- * then the contents of the buffer object's data store is undefined. We just
- * ignore, and leave it unchanged.
- */
- if (!data)
- return;
-
- /* Now that transfers are per-context, we don't have to figure out
- * flushing here. Usually drivers won't need to flush in this case
- * even if the buffer is currently referenced by hardware - they
- * just queue the upload as dma rather than mapping the underlying
- * buffer directly.
- */
- pipe_buffer_write(st_context(ctx)->pipe,
- st_obj->buffer,
- offset, size, data);
-}
-
-
-/**
- * Called via glGetBufferSubDataARB().
- */
-static void
-st_bufferobj_get_subdata(struct gl_context *ctx,
- GLenum target,
- GLintptrARB offset,
- GLsizeiptrARB size,
- GLvoid * data, struct gl_buffer_object *obj)
-{
- struct st_buffer_object *st_obj = st_buffer_object(obj);
-
- /* we may be called from VBO code, so double-check params here */
- ASSERT(offset >= 0);
- ASSERT(size >= 0);
- ASSERT(offset + size <= obj->Size);
-
- if (!size)
- return;
-
- pipe_buffer_read(st_context(ctx)->pipe, st_obj->buffer,
- offset, size, data);
-}
-
-
-/**
- * Allocate space for and store data in a buffer object. Any data that was
- * previously stored in the buffer object is lost. If data is NULL,
- * memory will be allocated, but no copy will occur.
- * Called via ctx->Driver.BufferData().
- * \return GL_TRUE for success, GL_FALSE if out of memory
- */
-static GLboolean
-st_bufferobj_data(struct gl_context *ctx,
- GLenum target,
- GLsizeiptrARB size,
- const GLvoid * data,
- GLenum usage,
- struct gl_buffer_object *obj)
-{
- struct st_context *st = st_context(ctx);
- struct pipe_context *pipe = st->pipe;
- struct st_buffer_object *st_obj = st_buffer_object(obj);
- unsigned bind, pipe_usage;
-
- st_obj->Base.Size = size;
- st_obj->Base.Usage = usage;
-
- switch(target) {
- case GL_PIXEL_PACK_BUFFER_ARB:
- case GL_PIXEL_UNPACK_BUFFER_ARB:
- bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
- break;
- case GL_ARRAY_BUFFER_ARB:
- bind = PIPE_BIND_VERTEX_BUFFER;
- break;
- case GL_ELEMENT_ARRAY_BUFFER_ARB:
- bind = PIPE_BIND_INDEX_BUFFER;
- break;
- default:
- bind = 0;
- }
-
- switch (usage) {
- case GL_STATIC_DRAW:
- case GL_STATIC_READ:
- case GL_STATIC_COPY:
- pipe_usage = PIPE_USAGE_STATIC;
- break;
- case GL_DYNAMIC_DRAW:
- case GL_DYNAMIC_READ:
- case GL_DYNAMIC_COPY:
- pipe_usage = PIPE_USAGE_DYNAMIC;
- break;
- case GL_STREAM_DRAW:
- case GL_STREAM_READ:
- case GL_STREAM_COPY:
- pipe_usage = PIPE_USAGE_STREAM;
- break;
- default:
- pipe_usage = PIPE_USAGE_DEFAULT;
- }
-
- pipe_resource_reference( &st_obj->buffer, NULL );
-
- if (size != 0) {
- st_obj->buffer = pipe_buffer_create(pipe->screen, bind,
- pipe_usage, size);
-
- if (!st_obj->buffer) {
- return GL_FALSE;
- }
-
- if (data)
- pipe_buffer_write(st_context(ctx)->pipe, st_obj->buffer, 0,
- size, data);
- return GL_TRUE;
- }
-
- return GL_TRUE;
-}
-
-
-/**
- * Dummy data whose's pointer is used for zero size buffers or ranges.
- */
-static long st_bufferobj_zero_length = 0;
-
-
-
-/**
- * Called via glMapBufferARB().
- */
-static void *
-st_bufferobj_map(struct gl_context *ctx, GLenum target, GLenum access,
- struct gl_buffer_object *obj)
-{
- struct st_buffer_object *st_obj = st_buffer_object(obj);
- uint flags;
-
- switch (access) {
- case GL_WRITE_ONLY:
- flags = PIPE_TRANSFER_WRITE;
- break;
- case GL_READ_ONLY:
- flags = PIPE_TRANSFER_READ;
- break;
- case GL_READ_WRITE:
- default:
- flags = PIPE_TRANSFER_READ_WRITE;
- break;
- }
-
- /* Handle zero-size buffers here rather than in drivers */
- if (obj->Size == 0) {
- obj->Pointer = &st_bufferobj_zero_length;
- }
- else {
- obj->Pointer = pipe_buffer_map(st_context(ctx)->pipe,
- st_obj->buffer,
- flags,
- &st_obj->transfer);
- }
-
- if (obj->Pointer) {
- obj->Offset = 0;
- obj->Length = obj->Size;
- }
- return obj->Pointer;
-}
-
-
-/**
- * Called via glMapBufferRange().
- */
-static void *
-st_bufferobj_map_range(struct gl_context *ctx, GLenum target,
- GLintptr offset, GLsizeiptr length, GLbitfield access,
- struct gl_buffer_object *obj)
-{
- struct pipe_context *pipe = st_context(ctx)->pipe;
- struct st_buffer_object *st_obj = st_buffer_object(obj);
- enum pipe_transfer_usage flags = 0x0;
-
- if (access & GL_MAP_WRITE_BIT)
- flags |= PIPE_TRANSFER_WRITE;
-
- if (access & GL_MAP_READ_BIT)
- flags |= PIPE_TRANSFER_READ;
-
- if (access & GL_MAP_FLUSH_EXPLICIT_BIT)
- flags |= PIPE_TRANSFER_FLUSH_EXPLICIT;
-
- if (access & GL_MAP_INVALIDATE_RANGE_BIT)
- flags |= PIPE_TRANSFER_DISCARD;
-
- if (access & GL_MAP_INVALIDATE_BUFFER_BIT)
- flags |= PIPE_TRANSFER_DISCARD;
-
- if (access & GL_MAP_UNSYNCHRONIZED_BIT)
- flags |= PIPE_TRANSFER_UNSYNCHRONIZED;
-
- /* ... other flags ...
- */
-
- if (access & MESA_MAP_NOWAIT_BIT)
- flags |= PIPE_TRANSFER_DONTBLOCK;
-
- assert(offset >= 0);
- assert(length >= 0);
- assert(offset < obj->Size);
- assert(offset + length <= obj->Size);
-
- /*
- * We go out of way here to hide the degenerate yet valid case of zero
- * length range from the pipe driver.
- */
- if (!length) {
- obj->Pointer = &st_bufferobj_zero_length;
- }
- else {
- obj->Pointer = pipe_buffer_map_range(pipe,
- st_obj->buffer,
- offset, length,
- flags,
- &st_obj->transfer);
- if (obj->Pointer) {
- obj->Pointer = (ubyte *) obj->Pointer + offset;
- }
- }
-
- if (obj->Pointer) {
- obj->Offset = offset;
- obj->Length = length;
- obj->AccessFlags = access;
- }
-
- return obj->Pointer;
-}
-
-
-static void
-st_bufferobj_flush_mapped_range(struct gl_context *ctx, GLenum target,
- GLintptr offset, GLsizeiptr length,
- struct gl_buffer_object *obj)
-{
- struct pipe_context *pipe = st_context(ctx)->pipe;
- struct st_buffer_object *st_obj = st_buffer_object(obj);
-
- /* Subrange is relative to mapped range */
- assert(offset >= 0);
- assert(length >= 0);
- assert(offset + length <= obj->Length);
- assert(obj->Pointer);
-
- if (!length)
- return;
-
- pipe_buffer_flush_mapped_range(pipe, st_obj->transfer,
- obj->Offset + offset, length);
-}
-
-
-/**
- * Called via glUnmapBufferARB().
- */
-static GLboolean
-st_bufferobj_unmap(struct gl_context *ctx, GLenum target, struct gl_buffer_object *obj)
-{
- struct pipe_context *pipe = st_context(ctx)->pipe;
- struct st_buffer_object *st_obj = st_buffer_object(obj);
-
- if (obj->Length)
- pipe_buffer_unmap(pipe, st_obj->transfer);
-
- st_obj->transfer = NULL;
- obj->Pointer = NULL;
- obj->Offset = 0;
- obj->Length = 0;
- return GL_TRUE;
-}
-
-
-/**
- * Called via glCopyBufferSubData().
- */
-static void
-st_copy_buffer_subdata(struct gl_context *ctx,
- struct gl_buffer_object *src,
- struct gl_buffer_object *dst,
- GLintptr readOffset, GLintptr writeOffset,
- GLsizeiptr size)
-{
- struct pipe_context *pipe = st_context(ctx)->pipe;
- struct st_buffer_object *srcObj = st_buffer_object(src);
- struct st_buffer_object *dstObj = st_buffer_object(dst);
- struct pipe_transfer *src_transfer;
- struct pipe_transfer *dst_transfer;
- ubyte *srcPtr, *dstPtr;
-
- if(!size)
- return;
-
- /* buffer should not already be mapped */
- assert(!src->Pointer);
- assert(!dst->Pointer);
-
- srcPtr = (ubyte *) pipe_buffer_map_range(pipe,
- srcObj->buffer,
- readOffset, size,
- PIPE_TRANSFER_READ,
- &src_transfer);
-
- dstPtr = (ubyte *) pipe_buffer_map_range(pipe,
- dstObj->buffer,
- writeOffset, size,
- PIPE_TRANSFER_WRITE,
- &dst_transfer);
-
- if (srcPtr && dstPtr)
- memcpy(dstPtr + writeOffset, srcPtr + readOffset, size);
-
- pipe_buffer_unmap(pipe, src_transfer);
- pipe_buffer_unmap(pipe, dst_transfer);
-}
-
-
-/* TODO: if buffer wasn't created with appropriate usage flags, need
- * to recreate it now and copy contents -- or possibly create a
- * gallium entrypoint to extend the usage flags and let the driver
- * decide if a copy is necessary.
- */
-void
-st_bufferobj_validate_usage(struct st_context *st,
- struct st_buffer_object *obj,
- unsigned usage)
-{
-}
-
-
-void
-st_init_bufferobject_functions(struct dd_function_table *functions)
-{
- functions->NewBufferObject = st_bufferobj_alloc;
- functions->DeleteBuffer = st_bufferobj_free;
- functions->BufferData = st_bufferobj_data;
- functions->BufferSubData = st_bufferobj_subdata;
- functions->GetBufferSubData = st_bufferobj_get_subdata;
- functions->MapBuffer = st_bufferobj_map;
- functions->MapBufferRange = st_bufferobj_map_range;
- functions->FlushMappedBufferRange = st_bufferobj_flush_mapped_range;
- functions->UnmapBuffer = st_bufferobj_unmap;
- functions->CopyBufferSubData = st_copy_buffer_subdata;
-
- /* For GL_APPLE_vertex_array_object */
- functions->NewArrayObject = _mesa_new_array_object;
- functions->DeleteArrayObject = _mesa_delete_array_object;
-}
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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.
+ *
+ **************************************************************************/
+
+
+/**
+ * Functions for pixel buffer objects and vertex/element buffer objects.
+ */
+
+
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "main/arrayobj.h"
+#include "main/bufferobj.h"
+
+#include "st_context.h"
+#include "st_cb_bufferobjects.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "util/u_inlines.h"
+
+
+/**
+ * There is some duplication between mesa's bufferobjects and our
+ * bufmgr buffers. Both have an integer handle and a hashtable to
+ * lookup an opaque structure. It would be nice if the handles and
+ * internal structure where somehow shared.
+ */
+static struct gl_buffer_object *
+st_bufferobj_alloc(struct gl_context *ctx, GLuint name, GLenum target)
+{
+ struct st_buffer_object *st_obj = ST_CALLOC_STRUCT(st_buffer_object);
+
+ if (!st_obj)
+ return NULL;
+
+ _mesa_initialize_buffer_object(&st_obj->Base, name, target);
+
+ return &st_obj->Base;
+}
+
+
+
+/**
+ * Deallocate/free a vertex/pixel buffer object.
+ * Called via glDeleteBuffersARB().
+ */
+static void
+st_bufferobj_free(struct gl_context *ctx, struct gl_buffer_object *obj)
+{
+ struct st_buffer_object *st_obj = st_buffer_object(obj);
+
+ assert(obj->RefCount == 0);
+ assert(st_obj->transfer == NULL);
+
+ if (st_obj->buffer)
+ pipe_resource_reference(&st_obj->buffer, NULL);
+
+ free(st_obj);
+}
+
+
+
+/**
+ * Replace data in a subrange of buffer object. If the data range
+ * specified by size + offset extends beyond the end of the buffer or
+ * if data is NULL, no copy is performed.
+ * Called via glBufferSubDataARB().
+ */
+static void
+st_bufferobj_subdata(struct gl_context *ctx,
+ GLenum target,
+ GLintptrARB offset,
+ GLsizeiptrARB size,
+ const GLvoid * data, struct gl_buffer_object *obj)
+{
+ struct st_buffer_object *st_obj = st_buffer_object(obj);
+
+ /* we may be called from VBO code, so double-check params here */
+ ASSERT(offset >= 0);
+ ASSERT(size >= 0);
+ ASSERT(offset + size <= obj->Size);
+
+ if (!size)
+ return;
+
+ /*
+ * According to ARB_vertex_buffer_object specification, if data is null,
+ * then the contents of the buffer object's data store is undefined. We just
+ * ignore, and leave it unchanged.
+ */
+ if (!data)
+ return;
+
+ /* Now that transfers are per-context, we don't have to figure out
+ * flushing here. Usually drivers won't need to flush in this case
+ * even if the buffer is currently referenced by hardware - they
+ * just queue the upload as dma rather than mapping the underlying
+ * buffer directly.
+ */
+ pipe_buffer_write(st_context(ctx)->pipe,
+ st_obj->buffer,
+ offset, size, data);
+}
+
+
+/**
+ * Called via glGetBufferSubDataARB().
+ */
+static void
+st_bufferobj_get_subdata(struct gl_context *ctx,
+ GLenum target,
+ GLintptrARB offset,
+ GLsizeiptrARB size,
+ GLvoid * data, struct gl_buffer_object *obj)
+{
+ struct st_buffer_object *st_obj = st_buffer_object(obj);
+
+ /* we may be called from VBO code, so double-check params here */
+ ASSERT(offset >= 0);
+ ASSERT(size >= 0);
+ ASSERT(offset + size <= obj->Size);
+
+ if (!size)
+ return;
+
+ pipe_buffer_read(st_context(ctx)->pipe, st_obj->buffer,
+ offset, size, data);
+}
+
+
+/**
+ * Allocate space for and store data in a buffer object. Any data that was
+ * previously stored in the buffer object is lost. If data is NULL,
+ * memory will be allocated, but no copy will occur.
+ * Called via ctx->Driver.BufferData().
+ * \return GL_TRUE for success, GL_FALSE if out of memory
+ */
+static GLboolean
+st_bufferobj_data(struct gl_context *ctx,
+ GLenum target,
+ GLsizeiptrARB size,
+ const GLvoid * data,
+ GLenum usage,
+ struct gl_buffer_object *obj)
+{
+ struct st_context *st = st_context(ctx);
+ struct pipe_context *pipe = st->pipe;
+ struct st_buffer_object *st_obj = st_buffer_object(obj);
+ unsigned bind, pipe_usage;
+
+ st_obj->Base.Size = size;
+ st_obj->Base.Usage = usage;
+
+ switch(target) {
+ case GL_PIXEL_PACK_BUFFER_ARB:
+ case GL_PIXEL_UNPACK_BUFFER_ARB:
+ bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
+ break;
+ case GL_ARRAY_BUFFER_ARB:
+ bind = PIPE_BIND_VERTEX_BUFFER;
+ break;
+ case GL_ELEMENT_ARRAY_BUFFER_ARB:
+ bind = PIPE_BIND_INDEX_BUFFER;
+ break;
+ default:
+ bind = 0;
+ }
+
+ switch (usage) {
+ case GL_STATIC_DRAW:
+ case GL_STATIC_READ:
+ case GL_STATIC_COPY:
+ pipe_usage = PIPE_USAGE_STATIC;
+ break;
+ case GL_DYNAMIC_DRAW:
+ case GL_DYNAMIC_READ:
+ case GL_DYNAMIC_COPY:
+ pipe_usage = PIPE_USAGE_DYNAMIC;
+ break;
+ case GL_STREAM_DRAW:
+ case GL_STREAM_READ:
+ case GL_STREAM_COPY:
+ pipe_usage = PIPE_USAGE_STREAM;
+ break;
+ default:
+ pipe_usage = PIPE_USAGE_DEFAULT;
+ }
+
+ pipe_resource_reference( &st_obj->buffer, NULL );
+
+ if (size != 0) {
+ st_obj->buffer = pipe_buffer_create(pipe->screen, bind,
+ pipe_usage, size);
+
+ if (!st_obj->buffer) {
+ return GL_FALSE;
+ }
+
+ if (data)
+ pipe_buffer_write(st_context(ctx)->pipe, st_obj->buffer, 0,
+ size, data);
+ return GL_TRUE;
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Dummy data whose's pointer is used for zero size buffers or ranges.
+ */
+static long st_bufferobj_zero_length = 0;
+
+
+
+/**
+ * Called via glMapBufferARB().
+ */
+static void *
+st_bufferobj_map(struct gl_context *ctx, GLenum target, GLenum access,
+ struct gl_buffer_object *obj)
+{
+ struct st_buffer_object *st_obj = st_buffer_object(obj);
+ uint flags;
+
+ switch (access) {
+ case GL_WRITE_ONLY:
+ flags = PIPE_TRANSFER_WRITE;
+ break;
+ case GL_READ_ONLY:
+ flags = PIPE_TRANSFER_READ;
+ break;
+ case GL_READ_WRITE:
+ default:
+ flags = PIPE_TRANSFER_READ_WRITE;
+ break;
+ }
+
+ /* Handle zero-size buffers here rather than in drivers */
+ if (obj->Size == 0) {
+ obj->Pointer = &st_bufferobj_zero_length;
+ }
+ else {
+ obj->Pointer = pipe_buffer_map(st_context(ctx)->pipe,
+ st_obj->buffer,
+ flags,
+ &st_obj->transfer);
+ }
+
+ if (obj->Pointer) {
+ obj->Offset = 0;
+ obj->Length = obj->Size;
+ }
+ return obj->Pointer;
+}
+
+
+/**
+ * Called via glMapBufferRange().
+ */
+static void *
+st_bufferobj_map_range(struct gl_context *ctx, GLenum target,
+ GLintptr offset, GLsizeiptr length, GLbitfield access,
+ struct gl_buffer_object *obj)
+{
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+ struct st_buffer_object *st_obj = st_buffer_object(obj);
+ enum pipe_transfer_usage flags = 0x0;
+
+ if (access & GL_MAP_WRITE_BIT)
+ flags |= PIPE_TRANSFER_WRITE;
+
+ if (access & GL_MAP_READ_BIT)
+ flags |= PIPE_TRANSFER_READ;
+
+ if (access & GL_MAP_FLUSH_EXPLICIT_BIT)
+ flags |= PIPE_TRANSFER_FLUSH_EXPLICIT;
+
+ if (access & GL_MAP_INVALIDATE_RANGE_BIT)
+ flags |= PIPE_TRANSFER_DISCARD;
+
+ if (access & GL_MAP_INVALIDATE_BUFFER_BIT)
+ flags |= PIPE_TRANSFER_DISCARD;
+
+ if (access & GL_MAP_UNSYNCHRONIZED_BIT)
+ flags |= PIPE_TRANSFER_UNSYNCHRONIZED;
+
+ /* ... other flags ...
+ */
+
+ if (access & MESA_MAP_NOWAIT_BIT)
+ flags |= PIPE_TRANSFER_DONTBLOCK;
+
+ assert(offset >= 0);
+ assert(length >= 0);
+ assert(offset < obj->Size);
+ assert(offset + length <= obj->Size);
+
+ /*
+ * We go out of way here to hide the degenerate yet valid case of zero
+ * length range from the pipe driver.
+ */
+ if (!length) {
+ obj->Pointer = &st_bufferobj_zero_length;
+ }
+ else {
+ obj->Pointer = pipe_buffer_map_range(pipe,
+ st_obj->buffer,
+ offset, length,
+ flags,
+ &st_obj->transfer);
+ if (obj->Pointer) {
+ obj->Pointer = (ubyte *) obj->Pointer + offset;
+ }
+ }
+
+ if (obj->Pointer) {
+ obj->Offset = offset;
+ obj->Length = length;
+ obj->AccessFlags = access;
+ }
+
+ return obj->Pointer;
+}
+
+
+static void
+st_bufferobj_flush_mapped_range(struct gl_context *ctx, GLenum target,
+ GLintptr offset, GLsizeiptr length,
+ struct gl_buffer_object *obj)
+{
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+ struct st_buffer_object *st_obj = st_buffer_object(obj);
+
+ /* Subrange is relative to mapped range */
+ assert(offset >= 0);
+ assert(length >= 0);
+ assert(offset + length <= obj->Length);
+ assert(obj->Pointer);
+
+ if (!length)
+ return;
+
+ pipe_buffer_flush_mapped_range(pipe, st_obj->transfer,
+ obj->Offset + offset, length);
+}
+
+
+/**
+ * Called via glUnmapBufferARB().
+ */
+static GLboolean
+st_bufferobj_unmap(struct gl_context *ctx, GLenum target, struct gl_buffer_object *obj)
+{
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+ struct st_buffer_object *st_obj = st_buffer_object(obj);
+
+ if (obj->Length)
+ pipe_buffer_unmap(pipe, st_obj->transfer);
+
+ st_obj->transfer = NULL;
+ obj->Pointer = NULL;
+ obj->Offset = 0;
+ obj->Length = 0;
+ return GL_TRUE;
+}
+
+
+/**
+ * Called via glCopyBufferSubData().
+ */
+static void
+st_copy_buffer_subdata(struct gl_context *ctx,
+ struct gl_buffer_object *src,
+ struct gl_buffer_object *dst,
+ GLintptr readOffset, GLintptr writeOffset,
+ GLsizeiptr size)
+{
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+ struct st_buffer_object *srcObj = st_buffer_object(src);
+ struct st_buffer_object *dstObj = st_buffer_object(dst);
+ struct pipe_transfer *src_transfer;
+ struct pipe_transfer *dst_transfer;
+ ubyte *srcPtr, *dstPtr;
+
+ if(!size)
+ return;
+
+ /* buffer should not already be mapped */
+ assert(!src->Pointer);
+ assert(!dst->Pointer);
+
+ srcPtr = (ubyte *) pipe_buffer_map_range(pipe,
+ srcObj->buffer,
+ readOffset, size,
+ PIPE_TRANSFER_READ,
+ &src_transfer);
+
+ dstPtr = (ubyte *) pipe_buffer_map_range(pipe,
+ dstObj->buffer,
+ writeOffset, size,
+ PIPE_TRANSFER_WRITE,
+ &dst_transfer);
+
+ if (srcPtr && dstPtr)
+ memcpy(dstPtr + writeOffset, srcPtr + readOffset, size);
+
+ pipe_buffer_unmap(pipe, src_transfer);
+ pipe_buffer_unmap(pipe, dst_transfer);
+}
+
+
+/* TODO: if buffer wasn't created with appropriate usage flags, need
+ * to recreate it now and copy contents -- or possibly create a
+ * gallium entrypoint to extend the usage flags and let the driver
+ * decide if a copy is necessary.
+ */
+void
+st_bufferobj_validate_usage(struct st_context *st,
+ struct st_buffer_object *obj,
+ unsigned usage)
+{
+}
+
+
+void
+st_init_bufferobject_functions(struct dd_function_table *functions)
+{
+ functions->NewBufferObject = st_bufferobj_alloc;
+ functions->DeleteBuffer = st_bufferobj_free;
+ functions->BufferData = st_bufferobj_data;
+ functions->BufferSubData = st_bufferobj_subdata;
+ functions->GetBufferSubData = st_bufferobj_get_subdata;
+ functions->MapBuffer = st_bufferobj_map;
+ functions->MapBufferRange = st_bufferobj_map_range;
+ functions->FlushMappedBufferRange = st_bufferobj_flush_mapped_range;
+ functions->UnmapBuffer = st_bufferobj_unmap;
+ functions->CopyBufferSubData = st_copy_buffer_subdata;
+
+ /* For GL_APPLE_vertex_array_object */
+ functions->NewArrayObject = _mesa_new_array_object;
+ functions->DeleteArrayObject = _mesa_delete_array_object;
+}
diff --git a/mesalib/src/mesa/state_tracker/st_cb_clear.c b/mesalib/src/mesa/state_tracker/st_cb_clear.c
index d2e0cd73c..461f4e315 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_clear.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_clear.c
@@ -1,563 +1,563 @@
-/**************************************************************************
- *
- * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- * Copyright 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, 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.
- *
- **************************************************************************/
-
- /*
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- * Brian Paul
- * Michel Dänzer
- */
-
-#include "main/glheader.h"
-#include "main/formats.h"
-#include "main/macros.h"
-#include "program/prog_instruction.h"
-#include "st_context.h"
-#include "st_atom.h"
-#include "st_cb_accum.h"
-#include "st_cb_clear.h"
-#include "st_cb_fbo.h"
-#include "st_program.h"
-
-#include "pipe/p_context.h"
-#include "pipe/p_shader_tokens.h"
-#include "pipe/p_state.h"
-#include "pipe/p_defines.h"
-#include "util/u_format.h"
-#include "util/u_inlines.h"
-#include "util/u_simple_shaders.h"
-#include "util/u_draw_quad.h"
-
-#include "cso_cache/cso_context.h"
-
-
-/**
- * Do per-context initialization for glClear.
- */
-void
-st_init_clear(struct st_context *st)
-{
- struct pipe_context *pipe = st->pipe;
- struct pipe_screen *pscreen = st->pipe->screen;
-
- memset(&st->clear, 0, sizeof(st->clear));
-
- st->clear.raster.gl_rasterization_rules = 1;
- st->clear.enable_ds_separate = pscreen->get_param(pscreen, PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE);
-
- /* fragment shader state: color pass-through program */
- st->clear.fs = util_make_fragment_passthrough_shader(pipe);
-
- /* vertex shader state: color/position pass-through */
- {
- const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
- TGSI_SEMANTIC_COLOR };
- const uint semantic_indexes[] = { 0, 0 };
- st->clear.vs = util_make_vertex_passthrough_shader(pipe, 2,
- semantic_names,
- semantic_indexes);
- }
-}
-
-
-/**
- * Free per-context state for glClear.
- */
-void
-st_destroy_clear(struct st_context *st)
-{
- if (st->clear.fs) {
- cso_delete_fragment_shader(st->cso_context, st->clear.fs);
- st->clear.fs = NULL;
- }
- if (st->clear.vs) {
- cso_delete_vertex_shader(st->cso_context, st->clear.vs);
- st->clear.vs = NULL;
- }
- if (st->clear.vbuf) {
- pipe_resource_reference(&st->clear.vbuf, NULL);
- st->clear.vbuf = NULL;
- }
-}
-
-
-/**
- * Draw a screen-aligned quadrilateral.
- * Coords are clip coords with y=0=bottom.
- */
-static void
-draw_quad(struct st_context *st,
- float x0, float y0, float x1, float y1, GLfloat z,
- const GLfloat color[4])
-{
- struct pipe_context *pipe = st->pipe;
-
- /* XXX: Need to improve buffer_write to allow NO_WAIT (as well as
- * no_flush) updates to buffers where we know there is no conflict
- * with previous data. Currently using max_slots > 1 will cause
- * synchronous rendering if the driver flushes its command buffers
- * between one bitmap and the next. Our flush hook below isn't
- * sufficient to catch this as the driver doesn't tell us when it
- * flushes its own command buffers. Until this gets fixed, pay the
- * price of allocating a new buffer for each bitmap cache-flush to
- * avoid synchronous rendering.
- */
- const GLuint max_slots = 1; /* 1024 / sizeof(st->clear.vertices); */
- GLuint i;
-
- if (st->clear.vbuf_slot >= max_slots) {
- pipe_resource_reference(&st->clear.vbuf, NULL);
- st->clear.vbuf_slot = 0;
- }
-
- if (!st->clear.vbuf) {
- st->clear.vbuf = pipe_buffer_create(pipe->screen,
- PIPE_BIND_VERTEX_BUFFER,
- PIPE_USAGE_STREAM,
- max_slots * sizeof(st->clear.vertices));
- }
-
- /* positions */
- st->clear.vertices[0][0][0] = x0;
- st->clear.vertices[0][0][1] = y0;
-
- st->clear.vertices[1][0][0] = x1;
- st->clear.vertices[1][0][1] = y0;
-
- st->clear.vertices[2][0][0] = x1;
- st->clear.vertices[2][0][1] = y1;
-
- st->clear.vertices[3][0][0] = x0;
- st->clear.vertices[3][0][1] = y1;
-
- /* same for all verts: */
- for (i = 0; i < 4; i++) {
- st->clear.vertices[i][0][2] = z;
- st->clear.vertices[i][0][3] = 1.0;
- st->clear.vertices[i][1][0] = color[0];
- st->clear.vertices[i][1][1] = color[1];
- st->clear.vertices[i][1][2] = color[2];
- st->clear.vertices[i][1][3] = color[3];
- }
-
- /* put vertex data into vbuf */
- pipe_buffer_write_nooverlap(st->pipe, st->clear.vbuf,
- st->clear.vbuf_slot
- * sizeof(st->clear.vertices),
- sizeof(st->clear.vertices),
- st->clear.vertices);
-
- /* draw */
- util_draw_vertex_buffer(pipe,
- st->cso_context,
- st->clear.vbuf,
- st->clear.vbuf_slot * sizeof(st->clear.vertices),
- PIPE_PRIM_TRIANGLE_FAN,
- 4, /* verts */
- 2); /* attribs/vert */
-
- /* Increment slot */
- st->clear.vbuf_slot++;
-}
-
-
-
-/**
- * Do glClear by drawing a quadrilateral.
- * The vertices of the quad will be computed from the
- * ctx->DrawBuffer->_X/Ymin/max fields.
- */
-static void
-clear_with_quad(struct gl_context *ctx,
- GLboolean color, GLboolean depth, GLboolean stencil)
-{
- struct st_context *st = st_context(ctx);
- const struct gl_framebuffer *fb = ctx->DrawBuffer;
- const GLfloat fb_width = (GLfloat) fb->Width;
- const GLfloat fb_height = (GLfloat) fb->Height;
- const GLfloat x0 = (GLfloat) ctx->DrawBuffer->_Xmin / fb_width * 2.0f - 1.0f;
- const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax / fb_width * 2.0f - 1.0f;
- const GLfloat y0 = (GLfloat) ctx->DrawBuffer->_Ymin / fb_height * 2.0f - 1.0f;
- const GLfloat y1 = (GLfloat) ctx->DrawBuffer->_Ymax / fb_height * 2.0f - 1.0f;
-
- /*
- printf("%s %s%s%s %f,%f %f,%f\n", __FUNCTION__,
- color ? "color, " : "",
- depth ? "depth, " : "",
- stencil ? "stencil" : "",
- x0, y0,
- x1, y1);
- */
-
- cso_save_blend(st->cso_context);
- cso_save_stencil_ref(st->cso_context);
- cso_save_depth_stencil_alpha(st->cso_context);
- cso_save_rasterizer(st->cso_context);
- cso_save_viewport(st->cso_context);
- cso_save_clip(st->cso_context);
- cso_save_fragment_shader(st->cso_context);
- cso_save_vertex_shader(st->cso_context);
- cso_save_vertex_elements(st->cso_context);
- cso_save_vertex_buffers(st->cso_context);
-
- /* blend state: RGBA masking */
- {
- struct pipe_blend_state blend;
- memset(&blend, 0, sizeof(blend));
- blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
- blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
- blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
- blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
- if (color) {
- if (ctx->Color.ColorMask[0][0])
- blend.rt[0].colormask |= PIPE_MASK_R;
- if (ctx->Color.ColorMask[0][1])
- blend.rt[0].colormask |= PIPE_MASK_G;
- if (ctx->Color.ColorMask[0][2])
- blend.rt[0].colormask |= PIPE_MASK_B;
- if (ctx->Color.ColorMask[0][3])
- blend.rt[0].colormask |= PIPE_MASK_A;
- if (st->ctx->Color.DitherFlag)
- blend.dither = 1;
- }
- cso_set_blend(st->cso_context, &blend);
- }
-
- /* depth_stencil state: always pass/set to ref value */
- {
- struct pipe_depth_stencil_alpha_state depth_stencil;
- memset(&depth_stencil, 0, sizeof(depth_stencil));
- if (depth) {
- depth_stencil.depth.enabled = 1;
- depth_stencil.depth.writemask = 1;
- depth_stencil.depth.func = PIPE_FUNC_ALWAYS;
- }
-
- if (stencil) {
- struct pipe_stencil_ref stencil_ref;
- memset(&stencil_ref, 0, sizeof(stencil_ref));
- depth_stencil.stencil[0].enabled = 1;
- depth_stencil.stencil[0].func = PIPE_FUNC_ALWAYS;
- depth_stencil.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
- depth_stencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
- depth_stencil.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
- depth_stencil.stencil[0].valuemask = 0xff;
- depth_stencil.stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff;
- stencil_ref.ref_value[0] = ctx->Stencil.Clear;
- cso_set_stencil_ref(st->cso_context, &stencil_ref);
- }
-
- cso_set_depth_stencil_alpha(st->cso_context, &depth_stencil);
- }
-
- cso_set_vertex_elements(st->cso_context, 2, st->velems_util_draw);
-
- cso_set_rasterizer(st->cso_context, &st->clear.raster);
-
- /* viewport state: viewport matching window dims */
- {
- const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP);
- struct pipe_viewport_state vp;
- vp.scale[0] = 0.5f * fb_width;
- vp.scale[1] = fb_height * (invert ? -0.5f : 0.5f);
- vp.scale[2] = 1.0f;
- vp.scale[3] = 1.0f;
- vp.translate[0] = 0.5f * fb_width;
- vp.translate[1] = 0.5f * fb_height;
- vp.translate[2] = 0.0f;
- vp.translate[3] = 0.0f;
- cso_set_viewport(st->cso_context, &vp);
- }
-
- cso_set_clip(st->cso_context, &st->clear.clip);
- cso_set_fragment_shader_handle(st->cso_context, st->clear.fs);
- cso_set_vertex_shader_handle(st->cso_context, st->clear.vs);
-
- /* draw quad matching scissor rect (XXX verify coord round-off) */
- draw_quad(st, x0, y0, x1, y1,
- (GLfloat) ctx->Depth.Clear, ctx->Color.ClearColor);
-
- /* Restore pipe state */
- cso_restore_blend(st->cso_context);
- cso_restore_stencil_ref(st->cso_context);
- cso_restore_depth_stencil_alpha(st->cso_context);
- cso_restore_rasterizer(st->cso_context);
- cso_restore_viewport(st->cso_context);
- cso_restore_clip(st->cso_context);
- cso_restore_fragment_shader(st->cso_context);
- cso_restore_vertex_shader(st->cso_context);
- cso_restore_vertex_elements(st->cso_context);
- cso_restore_vertex_buffers(st->cso_context);
-}
-
-
-/**
- * Determine if we need to clear the depth buffer by drawing a quad.
- */
-static INLINE GLboolean
-check_clear_color_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb)
-{
- if (ctx->Scissor.Enabled &&
- (ctx->Scissor.X != 0 ||
- ctx->Scissor.Y != 0 ||
- ctx->Scissor.Width < rb->Width ||
- ctx->Scissor.Height < rb->Height))
- return GL_TRUE;
-
- if (!ctx->Color.ColorMask[0][0] ||
- !ctx->Color.ColorMask[0][1] ||
- !ctx->Color.ColorMask[0][2] ||
- !ctx->Color.ColorMask[0][3])
- return GL_TRUE;
-
- return GL_FALSE;
-}
-
-
-/**
- * Determine if we need to clear the combiend depth/stencil buffer by
- * drawing a quad.
- */
-static INLINE GLboolean
-check_clear_depth_stencil_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb)
-{
- const GLuint stencilMax = 0xff;
- GLboolean maskStencil
- = (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax;
-
- assert(rb->Format == MESA_FORMAT_S8 ||
- rb->Format == MESA_FORMAT_Z24_S8 ||
- rb->Format == MESA_FORMAT_S8_Z24);
-
- if (ctx->Scissor.Enabled &&
- (ctx->Scissor.X != 0 ||
- ctx->Scissor.Y != 0 ||
- ctx->Scissor.Width < rb->Width ||
- ctx->Scissor.Height < rb->Height))
- return GL_TRUE;
-
- if (maskStencil)
- return GL_TRUE;
-
- return GL_FALSE;
-}
-
-
-/**
- * Determine if we need to clear the depth buffer by drawing a quad.
- */
-static INLINE GLboolean
-check_clear_depth_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb,
- boolean ds_separate)
-{
- const struct st_renderbuffer *strb = st_renderbuffer(rb);
- const GLboolean isDS = util_format_is_depth_and_stencil(strb->surface->format);
-
- if (ctx->Scissor.Enabled &&
- (ctx->Scissor.X != 0 ||
- ctx->Scissor.Y != 0 ||
- ctx->Scissor.Width < rb->Width ||
- ctx->Scissor.Height < rb->Height))
- return GL_TRUE;
-
- if (!ds_separate && isDS && ctx->DrawBuffer->Visual.stencilBits > 0)
- return GL_TRUE;
-
- return GL_FALSE;
-}
-
-
-/**
- * Determine if we need to clear the stencil buffer by drawing a quad.
- */
-static INLINE GLboolean
-check_clear_stencil_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb,
- boolean ds_separate)
-{
- const struct st_renderbuffer *strb = st_renderbuffer(rb);
- const GLboolean isDS = util_format_is_depth_and_stencil(strb->surface->format);
- const GLuint stencilMax = 0xff;
- const GLboolean maskStencil
- = (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax;
-
- assert(rb->Format == MESA_FORMAT_S8 ||
- rb->Format == MESA_FORMAT_Z24_S8 ||
- rb->Format == MESA_FORMAT_S8_Z24);
-
- if (maskStencil)
- return GL_TRUE;
-
- if (ctx->Scissor.Enabled &&
- (ctx->Scissor.X != 0 ||
- ctx->Scissor.Y != 0 ||
- ctx->Scissor.Width < rb->Width ||
- ctx->Scissor.Height < rb->Height))
- return GL_TRUE;
-
- /* This is correct, but it is necessary to look at the depth clear
- * value held in the surface when it comes time to issue the clear,
- * rather than taking depth and stencil clear values from the
- * current state.
- */
- if (!ds_separate && isDS && ctx->DrawBuffer->Visual.depthBits > 0)
- return GL_TRUE;
-
- return GL_FALSE;
-}
-
-
-
-/**
- * Called when we need to flush.
- */
-void
-st_flush_clear(struct st_context *st)
-{
- /* Release vertex buffer to avoid synchronous rendering if we were
- * to map it in the next frame.
- */
- pipe_resource_reference(&st->clear.vbuf, NULL);
- st->clear.vbuf_slot = 0;
-}
-
-
-
-/**
- * Called via ctx->Driver.Clear()
- */
-static void
-st_Clear(struct gl_context *ctx, GLbitfield mask)
-{
- static const GLbitfield BUFFER_BITS_DS
- = (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL);
- struct st_context *st = st_context(ctx);
- struct gl_renderbuffer *depthRb
- = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
- struct gl_renderbuffer *stencilRb
- = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
- GLbitfield quad_buffers = 0x0;
- GLbitfield clear_buffers = 0x0;
- GLuint i;
-
- /* This makes sure the pipe has the latest scissor, etc values */
- st_validate_state( st );
-
- if (mask & BUFFER_BITS_COLOR) {
- for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
- GLuint b = ctx->DrawBuffer->_ColorDrawBufferIndexes[i];
-
- if (mask & (1 << b)) {
- struct gl_renderbuffer *rb
- = ctx->DrawBuffer->Attachment[b].Renderbuffer;
- struct st_renderbuffer *strb = st_renderbuffer(rb);
-
- if (!strb || !strb->surface)
- continue;
-
- if (check_clear_color_with_quad( ctx, rb ))
- quad_buffers |= PIPE_CLEAR_COLOR;
- else
- clear_buffers |= PIPE_CLEAR_COLOR;
- }
- }
- }
-
- if ((mask & BUFFER_BITS_DS) == BUFFER_BITS_DS && depthRb == stencilRb) {
- /* clearing combined depth + stencil */
- struct st_renderbuffer *strb = st_renderbuffer(depthRb);
-
- if (strb->surface) {
- if (check_clear_depth_stencil_with_quad(ctx, depthRb))
- quad_buffers |= PIPE_CLEAR_DEPTHSTENCIL;
- else
- clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL;
- }
- }
- else {
- /* separate depth/stencil clears */
- /* I don't think truly separate buffers are actually possible in gallium or hw? */
- if (mask & BUFFER_BIT_DEPTH) {
- struct st_renderbuffer *strb = st_renderbuffer(depthRb);
-
- if (strb->surface) {
- if (check_clear_depth_with_quad(ctx, depthRb,
- st->clear.enable_ds_separate))
- quad_buffers |= PIPE_CLEAR_DEPTH;
- else
- clear_buffers |= PIPE_CLEAR_DEPTH;
- }
- }
- if (mask & BUFFER_BIT_STENCIL) {
- struct st_renderbuffer *strb = st_renderbuffer(stencilRb);
-
- if (strb->surface) {
- if (check_clear_stencil_with_quad(ctx, stencilRb,
- st->clear.enable_ds_separate))
- quad_buffers |= PIPE_CLEAR_STENCIL;
- else
- clear_buffers |= PIPE_CLEAR_STENCIL;
- }
- }
- }
-
- /*
- * If we're going to use clear_with_quad() for any reason, use it for
- * everything possible.
- */
- if (quad_buffers) {
- quad_buffers |= clear_buffers;
- clear_with_quad(ctx,
- quad_buffers & PIPE_CLEAR_COLOR,
- quad_buffers & PIPE_CLEAR_DEPTH,
- quad_buffers & PIPE_CLEAR_STENCIL);
- } else if (clear_buffers) {
- /* driver cannot know it can clear everything if the buffer
- * is a combined depth/stencil buffer but this wasn't actually
- * required from the visual. Hence fix this up to avoid potential
- * read-modify-write in the driver.
- */
- if ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) &&
- ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) &&
- (depthRb == stencilRb) &&
- (ctx->DrawBuffer->Visual.depthBits == 0 ||
- ctx->DrawBuffer->Visual.stencilBits == 0))
- clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL;
- st->pipe->clear(st->pipe, clear_buffers, ctx->Color.ClearColor,
- ctx->Depth.Clear, ctx->Stencil.Clear);
- }
- if (mask & BUFFER_BIT_ACCUM)
- st_clear_accum_buffer(ctx,
- ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer);
-}
-
-
-void
-st_init_clear_functions(struct dd_function_table *functions)
-{
- functions->Clear = st_Clear;
-}
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * Copyright 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, 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.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Brian Paul
+ * Michel Dänzer
+ */
+
+#include "main/glheader.h"
+#include "main/formats.h"
+#include "main/macros.h"
+#include "program/prog_instruction.h"
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_cb_accum.h"
+#include "st_cb_clear.h"
+#include "st_cb_fbo.h"
+#include "st_program.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_shader_tokens.h"
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "util/u_format.h"
+#include "util/u_inlines.h"
+#include "util/u_simple_shaders.h"
+#include "util/u_draw_quad.h"
+
+#include "cso_cache/cso_context.h"
+
+
+/**
+ * Do per-context initialization for glClear.
+ */
+void
+st_init_clear(struct st_context *st)
+{
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *pscreen = st->pipe->screen;
+
+ memset(&st->clear, 0, sizeof(st->clear));
+
+ st->clear.raster.gl_rasterization_rules = 1;
+ st->clear.enable_ds_separate = pscreen->get_param(pscreen, PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE);
+
+ /* fragment shader state: color pass-through program */
+ st->clear.fs = util_make_fragment_passthrough_shader(pipe);
+
+ /* vertex shader state: color/position pass-through */
+ {
+ const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
+ TGSI_SEMANTIC_COLOR };
+ const uint semantic_indexes[] = { 0, 0 };
+ st->clear.vs = util_make_vertex_passthrough_shader(pipe, 2,
+ semantic_names,
+ semantic_indexes);
+ }
+}
+
+
+/**
+ * Free per-context state for glClear.
+ */
+void
+st_destroy_clear(struct st_context *st)
+{
+ if (st->clear.fs) {
+ cso_delete_fragment_shader(st->cso_context, st->clear.fs);
+ st->clear.fs = NULL;
+ }
+ if (st->clear.vs) {
+ cso_delete_vertex_shader(st->cso_context, st->clear.vs);
+ st->clear.vs = NULL;
+ }
+ if (st->clear.vbuf) {
+ pipe_resource_reference(&st->clear.vbuf, NULL);
+ st->clear.vbuf = NULL;
+ }
+}
+
+
+/**
+ * Draw a screen-aligned quadrilateral.
+ * Coords are clip coords with y=0=bottom.
+ */
+static void
+draw_quad(struct st_context *st,
+ float x0, float y0, float x1, float y1, GLfloat z,
+ const GLfloat color[4])
+{
+ struct pipe_context *pipe = st->pipe;
+
+ /* XXX: Need to improve buffer_write to allow NO_WAIT (as well as
+ * no_flush) updates to buffers where we know there is no conflict
+ * with previous data. Currently using max_slots > 1 will cause
+ * synchronous rendering if the driver flushes its command buffers
+ * between one bitmap and the next. Our flush hook below isn't
+ * sufficient to catch this as the driver doesn't tell us when it
+ * flushes its own command buffers. Until this gets fixed, pay the
+ * price of allocating a new buffer for each bitmap cache-flush to
+ * avoid synchronous rendering.
+ */
+ const GLuint max_slots = 1; /* 1024 / sizeof(st->clear.vertices); */
+ GLuint i;
+
+ if (st->clear.vbuf_slot >= max_slots) {
+ pipe_resource_reference(&st->clear.vbuf, NULL);
+ st->clear.vbuf_slot = 0;
+ }
+
+ if (!st->clear.vbuf) {
+ st->clear.vbuf = pipe_buffer_create(pipe->screen,
+ PIPE_BIND_VERTEX_BUFFER,
+ PIPE_USAGE_STREAM,
+ max_slots * sizeof(st->clear.vertices));
+ }
+
+ /* positions */
+ st->clear.vertices[0][0][0] = x0;
+ st->clear.vertices[0][0][1] = y0;
+
+ st->clear.vertices[1][0][0] = x1;
+ st->clear.vertices[1][0][1] = y0;
+
+ st->clear.vertices[2][0][0] = x1;
+ st->clear.vertices[2][0][1] = y1;
+
+ st->clear.vertices[3][0][0] = x0;
+ st->clear.vertices[3][0][1] = y1;
+
+ /* same for all verts: */
+ for (i = 0; i < 4; i++) {
+ st->clear.vertices[i][0][2] = z;
+ st->clear.vertices[i][0][3] = 1.0;
+ st->clear.vertices[i][1][0] = color[0];
+ st->clear.vertices[i][1][1] = color[1];
+ st->clear.vertices[i][1][2] = color[2];
+ st->clear.vertices[i][1][3] = color[3];
+ }
+
+ /* put vertex data into vbuf */
+ pipe_buffer_write_nooverlap(st->pipe, st->clear.vbuf,
+ st->clear.vbuf_slot
+ * sizeof(st->clear.vertices),
+ sizeof(st->clear.vertices),
+ st->clear.vertices);
+
+ /* draw */
+ util_draw_vertex_buffer(pipe,
+ st->cso_context,
+ st->clear.vbuf,
+ st->clear.vbuf_slot * sizeof(st->clear.vertices),
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ 2); /* attribs/vert */
+
+ /* Increment slot */
+ st->clear.vbuf_slot++;
+}
+
+
+
+/**
+ * Do glClear by drawing a quadrilateral.
+ * The vertices of the quad will be computed from the
+ * ctx->DrawBuffer->_X/Ymin/max fields.
+ */
+static void
+clear_with_quad(struct gl_context *ctx,
+ GLboolean color, GLboolean depth, GLboolean stencil)
+{
+ struct st_context *st = st_context(ctx);
+ const struct gl_framebuffer *fb = ctx->DrawBuffer;
+ const GLfloat fb_width = (GLfloat) fb->Width;
+ const GLfloat fb_height = (GLfloat) fb->Height;
+ const GLfloat x0 = (GLfloat) ctx->DrawBuffer->_Xmin / fb_width * 2.0f - 1.0f;
+ const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax / fb_width * 2.0f - 1.0f;
+ const GLfloat y0 = (GLfloat) ctx->DrawBuffer->_Ymin / fb_height * 2.0f - 1.0f;
+ const GLfloat y1 = (GLfloat) ctx->DrawBuffer->_Ymax / fb_height * 2.0f - 1.0f;
+
+ /*
+ printf("%s %s%s%s %f,%f %f,%f\n", __FUNCTION__,
+ color ? "color, " : "",
+ depth ? "depth, " : "",
+ stencil ? "stencil" : "",
+ x0, y0,
+ x1, y1);
+ */
+
+ cso_save_blend(st->cso_context);
+ cso_save_stencil_ref(st->cso_context);
+ cso_save_depth_stencil_alpha(st->cso_context);
+ cso_save_rasterizer(st->cso_context);
+ cso_save_viewport(st->cso_context);
+ cso_save_clip(st->cso_context);
+ cso_save_fragment_shader(st->cso_context);
+ cso_save_vertex_shader(st->cso_context);
+ cso_save_vertex_elements(st->cso_context);
+ cso_save_vertex_buffers(st->cso_context);
+
+ /* blend state: RGBA masking */
+ {
+ struct pipe_blend_state blend;
+ memset(&blend, 0, sizeof(blend));
+ blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ if (color) {
+ if (ctx->Color.ColorMask[0][0])
+ blend.rt[0].colormask |= PIPE_MASK_R;
+ if (ctx->Color.ColorMask[0][1])
+ blend.rt[0].colormask |= PIPE_MASK_G;
+ if (ctx->Color.ColorMask[0][2])
+ blend.rt[0].colormask |= PIPE_MASK_B;
+ if (ctx->Color.ColorMask[0][3])
+ blend.rt[0].colormask |= PIPE_MASK_A;
+ if (st->ctx->Color.DitherFlag)
+ blend.dither = 1;
+ }
+ cso_set_blend(st->cso_context, &blend);
+ }
+
+ /* depth_stencil state: always pass/set to ref value */
+ {
+ struct pipe_depth_stencil_alpha_state depth_stencil;
+ memset(&depth_stencil, 0, sizeof(depth_stencil));
+ if (depth) {
+ depth_stencil.depth.enabled = 1;
+ depth_stencil.depth.writemask = 1;
+ depth_stencil.depth.func = PIPE_FUNC_ALWAYS;
+ }
+
+ if (stencil) {
+ struct pipe_stencil_ref stencil_ref;
+ memset(&stencil_ref, 0, sizeof(stencil_ref));
+ depth_stencil.stencil[0].enabled = 1;
+ depth_stencil.stencil[0].func = PIPE_FUNC_ALWAYS;
+ depth_stencil.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
+ depth_stencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
+ depth_stencil.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
+ depth_stencil.stencil[0].valuemask = 0xff;
+ depth_stencil.stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff;
+ stencil_ref.ref_value[0] = ctx->Stencil.Clear;
+ cso_set_stencil_ref(st->cso_context, &stencil_ref);
+ }
+
+ cso_set_depth_stencil_alpha(st->cso_context, &depth_stencil);
+ }
+
+ cso_set_vertex_elements(st->cso_context, 2, st->velems_util_draw);
+
+ cso_set_rasterizer(st->cso_context, &st->clear.raster);
+
+ /* viewport state: viewport matching window dims */
+ {
+ const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP);
+ struct pipe_viewport_state vp;
+ vp.scale[0] = 0.5f * fb_width;
+ vp.scale[1] = fb_height * (invert ? -0.5f : 0.5f);
+ vp.scale[2] = 1.0f;
+ vp.scale[3] = 1.0f;
+ vp.translate[0] = 0.5f * fb_width;
+ vp.translate[1] = 0.5f * fb_height;
+ vp.translate[2] = 0.0f;
+ vp.translate[3] = 0.0f;
+ cso_set_viewport(st->cso_context, &vp);
+ }
+
+ cso_set_clip(st->cso_context, &st->clear.clip);
+ cso_set_fragment_shader_handle(st->cso_context, st->clear.fs);
+ cso_set_vertex_shader_handle(st->cso_context, st->clear.vs);
+
+ /* draw quad matching scissor rect (XXX verify coord round-off) */
+ draw_quad(st, x0, y0, x1, y1,
+ (GLfloat) ctx->Depth.Clear, ctx->Color.ClearColor);
+
+ /* Restore pipe state */
+ cso_restore_blend(st->cso_context);
+ cso_restore_stencil_ref(st->cso_context);
+ cso_restore_depth_stencil_alpha(st->cso_context);
+ cso_restore_rasterizer(st->cso_context);
+ cso_restore_viewport(st->cso_context);
+ cso_restore_clip(st->cso_context);
+ cso_restore_fragment_shader(st->cso_context);
+ cso_restore_vertex_shader(st->cso_context);
+ cso_restore_vertex_elements(st->cso_context);
+ cso_restore_vertex_buffers(st->cso_context);
+}
+
+
+/**
+ * Determine if we need to clear the depth buffer by drawing a quad.
+ */
+static INLINE GLboolean
+check_clear_color_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb)
+{
+ if (ctx->Scissor.Enabled &&
+ (ctx->Scissor.X != 0 ||
+ ctx->Scissor.Y != 0 ||
+ ctx->Scissor.Width < rb->Width ||
+ ctx->Scissor.Height < rb->Height))
+ return GL_TRUE;
+
+ if (!ctx->Color.ColorMask[0][0] ||
+ !ctx->Color.ColorMask[0][1] ||
+ !ctx->Color.ColorMask[0][2] ||
+ !ctx->Color.ColorMask[0][3])
+ return GL_TRUE;
+
+ return GL_FALSE;
+}
+
+
+/**
+ * Determine if we need to clear the combiend depth/stencil buffer by
+ * drawing a quad.
+ */
+static INLINE GLboolean
+check_clear_depth_stencil_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb)
+{
+ const GLuint stencilMax = 0xff;
+ GLboolean maskStencil
+ = (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax;
+
+ assert(rb->Format == MESA_FORMAT_S8 ||
+ rb->Format == MESA_FORMAT_Z24_S8 ||
+ rb->Format == MESA_FORMAT_S8_Z24);
+
+ if (ctx->Scissor.Enabled &&
+ (ctx->Scissor.X != 0 ||
+ ctx->Scissor.Y != 0 ||
+ ctx->Scissor.Width < rb->Width ||
+ ctx->Scissor.Height < rb->Height))
+ return GL_TRUE;
+
+ if (maskStencil)
+ return GL_TRUE;
+
+ return GL_FALSE;
+}
+
+
+/**
+ * Determine if we need to clear the depth buffer by drawing a quad.
+ */
+static INLINE GLboolean
+check_clear_depth_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb,
+ boolean ds_separate)
+{
+ const struct st_renderbuffer *strb = st_renderbuffer(rb);
+ const GLboolean isDS = util_format_is_depth_and_stencil(strb->surface->format);
+
+ if (ctx->Scissor.Enabled &&
+ (ctx->Scissor.X != 0 ||
+ ctx->Scissor.Y != 0 ||
+ ctx->Scissor.Width < rb->Width ||
+ ctx->Scissor.Height < rb->Height))
+ return GL_TRUE;
+
+ if (!ds_separate && isDS && ctx->DrawBuffer->Visual.stencilBits > 0)
+ return GL_TRUE;
+
+ return GL_FALSE;
+}
+
+
+/**
+ * Determine if we need to clear the stencil buffer by drawing a quad.
+ */
+static INLINE GLboolean
+check_clear_stencil_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb,
+ boolean ds_separate)
+{
+ const struct st_renderbuffer *strb = st_renderbuffer(rb);
+ const GLboolean isDS = util_format_is_depth_and_stencil(strb->surface->format);
+ const GLuint stencilMax = 0xff;
+ const GLboolean maskStencil
+ = (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax;
+
+ assert(rb->Format == MESA_FORMAT_S8 ||
+ rb->Format == MESA_FORMAT_Z24_S8 ||
+ rb->Format == MESA_FORMAT_S8_Z24);
+
+ if (maskStencil)
+ return GL_TRUE;
+
+ if (ctx->Scissor.Enabled &&
+ (ctx->Scissor.X != 0 ||
+ ctx->Scissor.Y != 0 ||
+ ctx->Scissor.Width < rb->Width ||
+ ctx->Scissor.Height < rb->Height))
+ return GL_TRUE;
+
+ /* This is correct, but it is necessary to look at the depth clear
+ * value held in the surface when it comes time to issue the clear,
+ * rather than taking depth and stencil clear values from the
+ * current state.
+ */
+ if (!ds_separate && isDS && ctx->DrawBuffer->Visual.depthBits > 0)
+ return GL_TRUE;
+
+ return GL_FALSE;
+}
+
+
+
+/**
+ * Called when we need to flush.
+ */
+void
+st_flush_clear(struct st_context *st)
+{
+ /* Release vertex buffer to avoid synchronous rendering if we were
+ * to map it in the next frame.
+ */
+ pipe_resource_reference(&st->clear.vbuf, NULL);
+ st->clear.vbuf_slot = 0;
+}
+
+
+
+/**
+ * Called via ctx->Driver.Clear()
+ */
+static void
+st_Clear(struct gl_context *ctx, GLbitfield mask)
+{
+ static const GLbitfield BUFFER_BITS_DS
+ = (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL);
+ struct st_context *st = st_context(ctx);
+ struct gl_renderbuffer *depthRb
+ = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
+ struct gl_renderbuffer *stencilRb
+ = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
+ GLbitfield quad_buffers = 0x0;
+ GLbitfield clear_buffers = 0x0;
+ GLuint i;
+
+ /* This makes sure the pipe has the latest scissor, etc values */
+ st_validate_state( st );
+
+ if (mask & BUFFER_BITS_COLOR) {
+ for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
+ GLuint b = ctx->DrawBuffer->_ColorDrawBufferIndexes[i];
+
+ if (mask & (1 << b)) {
+ struct gl_renderbuffer *rb
+ = ctx->DrawBuffer->Attachment[b].Renderbuffer;
+ struct st_renderbuffer *strb = st_renderbuffer(rb);
+
+ if (!strb || !strb->surface)
+ continue;
+
+ if (check_clear_color_with_quad( ctx, rb ))
+ quad_buffers |= PIPE_CLEAR_COLOR;
+ else
+ clear_buffers |= PIPE_CLEAR_COLOR;
+ }
+ }
+ }
+
+ if ((mask & BUFFER_BITS_DS) == BUFFER_BITS_DS && depthRb == stencilRb) {
+ /* clearing combined depth + stencil */
+ struct st_renderbuffer *strb = st_renderbuffer(depthRb);
+
+ if (strb->surface) {
+ if (check_clear_depth_stencil_with_quad(ctx, depthRb))
+ quad_buffers |= PIPE_CLEAR_DEPTHSTENCIL;
+ else
+ clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL;
+ }
+ }
+ else {
+ /* separate depth/stencil clears */
+ /* I don't think truly separate buffers are actually possible in gallium or hw? */
+ if (mask & BUFFER_BIT_DEPTH) {
+ struct st_renderbuffer *strb = st_renderbuffer(depthRb);
+
+ if (strb->surface) {
+ if (check_clear_depth_with_quad(ctx, depthRb,
+ st->clear.enable_ds_separate))
+ quad_buffers |= PIPE_CLEAR_DEPTH;
+ else
+ clear_buffers |= PIPE_CLEAR_DEPTH;
+ }
+ }
+ if (mask & BUFFER_BIT_STENCIL) {
+ struct st_renderbuffer *strb = st_renderbuffer(stencilRb);
+
+ if (strb->surface) {
+ if (check_clear_stencil_with_quad(ctx, stencilRb,
+ st->clear.enable_ds_separate))
+ quad_buffers |= PIPE_CLEAR_STENCIL;
+ else
+ clear_buffers |= PIPE_CLEAR_STENCIL;
+ }
+ }
+ }
+
+ /*
+ * If we're going to use clear_with_quad() for any reason, use it for
+ * everything possible.
+ */
+ if (quad_buffers) {
+ quad_buffers |= clear_buffers;
+ clear_with_quad(ctx,
+ quad_buffers & PIPE_CLEAR_COLOR,
+ quad_buffers & PIPE_CLEAR_DEPTH,
+ quad_buffers & PIPE_CLEAR_STENCIL);
+ } else if (clear_buffers) {
+ /* driver cannot know it can clear everything if the buffer
+ * is a combined depth/stencil buffer but this wasn't actually
+ * required from the visual. Hence fix this up to avoid potential
+ * read-modify-write in the driver.
+ */
+ if ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) &&
+ ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) &&
+ (depthRb == stencilRb) &&
+ (ctx->DrawBuffer->Visual.depthBits == 0 ||
+ ctx->DrawBuffer->Visual.stencilBits == 0))
+ clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL;
+ st->pipe->clear(st->pipe, clear_buffers, ctx->Color.ClearColor,
+ ctx->Depth.Clear, ctx->Stencil.Clear);
+ }
+ if (mask & BUFFER_BIT_ACCUM)
+ st_clear_accum_buffer(ctx,
+ ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer);
+}
+
+
+void
+st_init_clear_functions(struct dd_function_table *functions)
+{
+ functions->Clear = st_Clear;
+}
diff --git a/mesalib/src/mesa/state_tracker/st_cb_drawtex.c b/mesalib/src/mesa/state_tracker/st_cb_drawtex.c
index 86ceb9d78..db299eb8d 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_drawtex.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_drawtex.c
@@ -1,307 +1,307 @@
-/**************************************************************************
- *
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- **************************************************************************/
-
-
-/**
- * Implementation of glDrawTex() for GL_OES_draw_tex
- */
-
-
-
-#include "main/imports.h"
-#include "main/image.h"
-#include "main/macros.h"
-#include "main/mfeatures.h"
-#include "program/program.h"
-#include "program/prog_print.h"
-
-#include "st_context.h"
-#include "st_atom.h"
-#include "st_cb_drawtex.h"
-
-#include "pipe/p_context.h"
-#include "pipe/p_defines.h"
-#include "util/u_inlines.h"
-#include "pipe/p_shader_tokens.h"
-#include "util/u_draw_quad.h"
-#include "util/u_simple_shaders.h"
-
-#include "cso_cache/cso_context.h"
-
-
-#if FEATURE_OES_draw_texture
-
-
-struct cached_shader
-{
- void *handle;
-
- uint num_attribs;
- uint semantic_names[2 + MAX_TEXTURE_UNITS];
- uint semantic_indexes[2 + MAX_TEXTURE_UNITS];
-};
-
-#define MAX_SHADERS (2 * MAX_TEXTURE_UNITS)
-
-/**
- * Simple linear list cache.
- * Most of the time there'll only be one cached shader.
- */
-static struct cached_shader CachedShaders[MAX_SHADERS];
-static GLuint NumCachedShaders = 0;
-
-
-static void *
-lookup_shader(struct pipe_context *pipe,
- uint num_attribs,
- const uint *semantic_names,
- const uint *semantic_indexes)
-{
- GLuint i, j;
-
- /* look for existing shader with same attributes */
- for (i = 0; i < NumCachedShaders; i++) {
- if (CachedShaders[i].num_attribs == num_attribs) {
- GLboolean match = GL_TRUE;
- for (j = 0; j < num_attribs; j++) {
- if (semantic_names[j] != CachedShaders[i].semantic_names[j] ||
- semantic_indexes[j] != CachedShaders[i].semantic_indexes[j]) {
- match = GL_FALSE;
- break;
- }
- }
- if (match)
- return CachedShaders[i].handle;
- }
- }
-
- /* not found - create new one now */
- if (NumCachedShaders >= MAX_SHADERS) {
- return NULL;
- }
-
- CachedShaders[i].num_attribs = num_attribs;
- for (j = 0; j < num_attribs; j++) {
- CachedShaders[i].semantic_names[j] = semantic_names[j];
- CachedShaders[i].semantic_indexes[j] = semantic_indexes[j];
- }
-
- CachedShaders[i].handle =
- util_make_vertex_passthrough_shader(pipe,
- num_attribs,
- semantic_names,
- semantic_indexes);
- NumCachedShaders++;
-
- return CachedShaders[i].handle;
-}
-
-static void
-st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
- GLfloat width, GLfloat height)
-{
- struct st_context *st = ctx->st;
- struct pipe_context *pipe = st->pipe;
- struct cso_context *cso = ctx->st->cso_context;
- struct pipe_resource *vbuffer;
- struct pipe_transfer *vbuffer_transfer;
- GLuint i, numTexCoords, numAttribs;
- GLboolean emitColor;
- uint semantic_names[2 + MAX_TEXTURE_UNITS];
- uint semantic_indexes[2 + MAX_TEXTURE_UNITS];
- struct pipe_vertex_element velements[2 + MAX_TEXTURE_UNITS];
- GLbitfield inputs = VERT_BIT_POS;
-
- st_validate_state(st);
-
- /* determine if we need vertex color */
- if (ctx->FragmentProgram._Current->Base.InputsRead & FRAG_BIT_COL0)
- emitColor = GL_TRUE;
- else
- emitColor = GL_FALSE;
-
- /* determine how many enabled sets of texcoords */
- numTexCoords = 0;
- for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
- if (ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_2D_BIT) {
- inputs |= VERT_BIT_TEX(i);
- numTexCoords++;
- }
- }
-
- /* total number of attributes per vertex */
- numAttribs = 1 + emitColor + numTexCoords;
-
-
- /* create the vertex buffer */
- vbuffer = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER,
- PIPE_USAGE_STREAM,
- numAttribs * 4 * 4 * sizeof(GLfloat));
-
- /* load vertex buffer */
- {
-#define SET_ATTRIB(VERT, ATTR, X, Y, Z, W) \
- do { \
- GLuint k = (((VERT) * numAttribs + (ATTR)) * 4); \
- assert(k < 4 * 4 * numAttribs); \
- vbuf[k + 0] = X; \
- vbuf[k + 1] = Y; \
- vbuf[k + 2] = Z; \
- vbuf[k + 3] = W; \
- } while (0)
-
- const GLfloat x0 = x, y0 = y, x1 = x + width, y1 = y + height;
- GLfloat *vbuf = (GLfloat *) pipe_buffer_map(pipe, vbuffer,
- PIPE_TRANSFER_WRITE,
- &vbuffer_transfer);
- GLuint attr;
-
- z = CLAMP(z, 0.0f, 1.0f);
-
- /* positions (in clip coords) */
- {
- const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
- const GLfloat fb_width = (GLfloat)fb->Width;
- const GLfloat fb_height = (GLfloat)fb->Height;
-
- const GLfloat clip_x0 = (GLfloat)(x0 / fb_width * 2.0 - 1.0);
- const GLfloat clip_y0 = (GLfloat)(y0 / fb_height * 2.0 - 1.0);
- const GLfloat clip_x1 = (GLfloat)(x1 / fb_width * 2.0 - 1.0);
- const GLfloat clip_y1 = (GLfloat)(y1 / fb_height * 2.0 - 1.0);
-
- SET_ATTRIB(0, 0, clip_x0, clip_y0, z, 1.0f); /* lower left */
- SET_ATTRIB(1, 0, clip_x1, clip_y0, z, 1.0f); /* lower right */
- SET_ATTRIB(2, 0, clip_x1, clip_y1, z, 1.0f); /* upper right */
- SET_ATTRIB(3, 0, clip_x0, clip_y1, z, 1.0f); /* upper left */
-
- semantic_names[0] = TGSI_SEMANTIC_POSITION;
- semantic_indexes[0] = 0;
- }
-
- /* colors */
- if (emitColor) {
- const GLfloat *c = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
- SET_ATTRIB(0, 1, c[0], c[1], c[2], c[3]);
- SET_ATTRIB(1, 1, c[0], c[1], c[2], c[3]);
- SET_ATTRIB(2, 1, c[0], c[1], c[2], c[3]);
- SET_ATTRIB(3, 1, c[0], c[1], c[2], c[3]);
- semantic_names[1] = TGSI_SEMANTIC_COLOR;
- semantic_indexes[1] = 0;
- attr = 2;
- }
- else {
- attr = 1;
- }
-
- /* texcoords */
- for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
- if (ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_2D_BIT) {
- struct gl_texture_object *obj = ctx->Texture.Unit[i]._Current;
- struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
- const GLfloat wt = (GLfloat) img->Width;
- const GLfloat ht = (GLfloat) img->Height;
- const GLfloat s0 = obj->CropRect[0] / wt;
- const GLfloat t0 = obj->CropRect[1] / ht;
- const GLfloat s1 = (obj->CropRect[0] + obj->CropRect[2]) / wt;
- const GLfloat t1 = (obj->CropRect[1] + obj->CropRect[3]) / ht;
-
- /*printf("crop texcoords: %g, %g .. %g, %g\n", s0, t0, s1, t1);*/
- SET_ATTRIB(0, attr, s0, t0, 0.0f, 1.0f); /* lower left */
- SET_ATTRIB(1, attr, s1, t0, 0.0f, 1.0f); /* lower right */
- SET_ATTRIB(2, attr, s1, t1, 0.0f, 1.0f); /* upper right */
- SET_ATTRIB(3, attr, s0, t1, 0.0f, 1.0f); /* upper left */
-
- semantic_names[attr] = TGSI_SEMANTIC_GENERIC;
- semantic_indexes[attr] = 0;
-
- attr++;
- }
- }
-
- pipe_buffer_unmap(pipe, vbuffer_transfer);
-
-#undef SET_ATTRIB
- }
-
-
- cso_save_viewport(cso);
- cso_save_vertex_shader(cso);
- cso_save_vertex_elements(cso);
- cso_save_vertex_buffers(cso);
-
- {
- void *vs = lookup_shader(pipe, numAttribs,
- semantic_names, semantic_indexes);
- cso_set_vertex_shader_handle(cso, vs);
- }
-
- for (i = 0; i < numAttribs; i++) {
- velements[i].src_offset = i * 4 * sizeof(float);
- velements[i].instance_divisor = 0;
- velements[i].vertex_buffer_index = 0;
- velements[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
- }
- cso_set_vertex_elements(cso, numAttribs, velements);
-
- /* viewport state: viewport matching window dims */
- {
- const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
- const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP);
- const GLfloat width = (GLfloat)fb->Width;
- const GLfloat height = (GLfloat)fb->Height;
- struct pipe_viewport_state vp;
- vp.scale[0] = 0.5f * width;
- vp.scale[1] = height * (invert ? -0.5f : 0.5f);
- vp.scale[2] = 1.0f;
- vp.scale[3] = 1.0f;
- vp.translate[0] = 0.5f * width;
- vp.translate[1] = 0.5f * height;
- vp.translate[2] = 0.0f;
- vp.translate[3] = 0.0f;
- cso_set_viewport(cso, &vp);
- }
-
-
- util_draw_vertex_buffer(pipe, cso, vbuffer,
- 0, /* offset */
- PIPE_PRIM_TRIANGLE_FAN,
- 4, /* verts */
- numAttribs); /* attribs/vert */
-
-
- pipe_resource_reference(&vbuffer, NULL);
-
- /* restore state */
- cso_restore_viewport(cso);
- cso_restore_vertex_shader(cso);
- cso_restore_vertex_elements(cso);
- cso_restore_vertex_buffers(cso);
-}
-
-
-void
-st_init_drawtex_functions(struct dd_function_table *functions)
-{
- functions->DrawTex = st_DrawTex;
-}
-
-
-/**
- * Free any cached shaders
- */
-void
-st_destroy_drawtex(struct st_context *st)
-{
- GLuint i;
- for (i = 0; i < NumCachedShaders; i++) {
- cso_delete_vertex_shader(st->cso_context, CachedShaders[i].handle);
- }
- NumCachedShaders = 0;
-}
-
-
-#endif /* FEATURE_OES_draw_texture */
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ **************************************************************************/
+
+
+/**
+ * Implementation of glDrawTex() for GL_OES_draw_tex
+ */
+
+
+
+#include "main/imports.h"
+#include "main/image.h"
+#include "main/macros.h"
+#include "main/mfeatures.h"
+#include "program/program.h"
+#include "program/prog_print.h"
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_cb_drawtex.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "util/u_inlines.h"
+#include "pipe/p_shader_tokens.h"
+#include "util/u_draw_quad.h"
+#include "util/u_simple_shaders.h"
+
+#include "cso_cache/cso_context.h"
+
+
+#if FEATURE_OES_draw_texture
+
+
+struct cached_shader
+{
+ void *handle;
+
+ uint num_attribs;
+ uint semantic_names[2 + MAX_TEXTURE_UNITS];
+ uint semantic_indexes[2 + MAX_TEXTURE_UNITS];
+};
+
+#define MAX_SHADERS (2 * MAX_TEXTURE_UNITS)
+
+/**
+ * Simple linear list cache.
+ * Most of the time there'll only be one cached shader.
+ */
+static struct cached_shader CachedShaders[MAX_SHADERS];
+static GLuint NumCachedShaders = 0;
+
+
+static void *
+lookup_shader(struct pipe_context *pipe,
+ uint num_attribs,
+ const uint *semantic_names,
+ const uint *semantic_indexes)
+{
+ GLuint i, j;
+
+ /* look for existing shader with same attributes */
+ for (i = 0; i < NumCachedShaders; i++) {
+ if (CachedShaders[i].num_attribs == num_attribs) {
+ GLboolean match = GL_TRUE;
+ for (j = 0; j < num_attribs; j++) {
+ if (semantic_names[j] != CachedShaders[i].semantic_names[j] ||
+ semantic_indexes[j] != CachedShaders[i].semantic_indexes[j]) {
+ match = GL_FALSE;
+ break;
+ }
+ }
+ if (match)
+ return CachedShaders[i].handle;
+ }
+ }
+
+ /* not found - create new one now */
+ if (NumCachedShaders >= MAX_SHADERS) {
+ return NULL;
+ }
+
+ CachedShaders[i].num_attribs = num_attribs;
+ for (j = 0; j < num_attribs; j++) {
+ CachedShaders[i].semantic_names[j] = semantic_names[j];
+ CachedShaders[i].semantic_indexes[j] = semantic_indexes[j];
+ }
+
+ CachedShaders[i].handle =
+ util_make_vertex_passthrough_shader(pipe,
+ num_attribs,
+ semantic_names,
+ semantic_indexes);
+ NumCachedShaders++;
+
+ return CachedShaders[i].handle;
+}
+
+static void
+st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
+ GLfloat width, GLfloat height)
+{
+ struct st_context *st = ctx->st;
+ struct pipe_context *pipe = st->pipe;
+ struct cso_context *cso = ctx->st->cso_context;
+ struct pipe_resource *vbuffer;
+ struct pipe_transfer *vbuffer_transfer;
+ GLuint i, numTexCoords, numAttribs;
+ GLboolean emitColor;
+ uint semantic_names[2 + MAX_TEXTURE_UNITS];
+ uint semantic_indexes[2 + MAX_TEXTURE_UNITS];
+ struct pipe_vertex_element velements[2 + MAX_TEXTURE_UNITS];
+ GLbitfield inputs = VERT_BIT_POS;
+
+ st_validate_state(st);
+
+ /* determine if we need vertex color */
+ if (ctx->FragmentProgram._Current->Base.InputsRead & FRAG_BIT_COL0)
+ emitColor = GL_TRUE;
+ else
+ emitColor = GL_FALSE;
+
+ /* determine how many enabled sets of texcoords */
+ numTexCoords = 0;
+ for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
+ if (ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_2D_BIT) {
+ inputs |= VERT_BIT_TEX(i);
+ numTexCoords++;
+ }
+ }
+
+ /* total number of attributes per vertex */
+ numAttribs = 1 + emitColor + numTexCoords;
+
+
+ /* create the vertex buffer */
+ vbuffer = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER,
+ PIPE_USAGE_STREAM,
+ numAttribs * 4 * 4 * sizeof(GLfloat));
+
+ /* load vertex buffer */
+ {
+#define SET_ATTRIB(VERT, ATTR, X, Y, Z, W) \
+ do { \
+ GLuint k = (((VERT) * numAttribs + (ATTR)) * 4); \
+ assert(k < 4 * 4 * numAttribs); \
+ vbuf[k + 0] = X; \
+ vbuf[k + 1] = Y; \
+ vbuf[k + 2] = Z; \
+ vbuf[k + 3] = W; \
+ } while (0)
+
+ const GLfloat x0 = x, y0 = y, x1 = x + width, y1 = y + height;
+ GLfloat *vbuf = (GLfloat *) pipe_buffer_map(pipe, vbuffer,
+ PIPE_TRANSFER_WRITE,
+ &vbuffer_transfer);
+ GLuint attr;
+
+ z = CLAMP(z, 0.0f, 1.0f);
+
+ /* positions (in clip coords) */
+ {
+ const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
+ const GLfloat fb_width = (GLfloat)fb->Width;
+ const GLfloat fb_height = (GLfloat)fb->Height;
+
+ const GLfloat clip_x0 = (GLfloat)(x0 / fb_width * 2.0 - 1.0);
+ const GLfloat clip_y0 = (GLfloat)(y0 / fb_height * 2.0 - 1.0);
+ const GLfloat clip_x1 = (GLfloat)(x1 / fb_width * 2.0 - 1.0);
+ const GLfloat clip_y1 = (GLfloat)(y1 / fb_height * 2.0 - 1.0);
+
+ SET_ATTRIB(0, 0, clip_x0, clip_y0, z, 1.0f); /* lower left */
+ SET_ATTRIB(1, 0, clip_x1, clip_y0, z, 1.0f); /* lower right */
+ SET_ATTRIB(2, 0, clip_x1, clip_y1, z, 1.0f); /* upper right */
+ SET_ATTRIB(3, 0, clip_x0, clip_y1, z, 1.0f); /* upper left */
+
+ semantic_names[0] = TGSI_SEMANTIC_POSITION;
+ semantic_indexes[0] = 0;
+ }
+
+ /* colors */
+ if (emitColor) {
+ const GLfloat *c = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
+ SET_ATTRIB(0, 1, c[0], c[1], c[2], c[3]);
+ SET_ATTRIB(1, 1, c[0], c[1], c[2], c[3]);
+ SET_ATTRIB(2, 1, c[0], c[1], c[2], c[3]);
+ SET_ATTRIB(3, 1, c[0], c[1], c[2], c[3]);
+ semantic_names[1] = TGSI_SEMANTIC_COLOR;
+ semantic_indexes[1] = 0;
+ attr = 2;
+ }
+ else {
+ attr = 1;
+ }
+
+ /* texcoords */
+ for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
+ if (ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_2D_BIT) {
+ struct gl_texture_object *obj = ctx->Texture.Unit[i]._Current;
+ struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
+ const GLfloat wt = (GLfloat) img->Width;
+ const GLfloat ht = (GLfloat) img->Height;
+ const GLfloat s0 = obj->CropRect[0] / wt;
+ const GLfloat t0 = obj->CropRect[1] / ht;
+ const GLfloat s1 = (obj->CropRect[0] + obj->CropRect[2]) / wt;
+ const GLfloat t1 = (obj->CropRect[1] + obj->CropRect[3]) / ht;
+
+ /*printf("crop texcoords: %g, %g .. %g, %g\n", s0, t0, s1, t1);*/
+ SET_ATTRIB(0, attr, s0, t0, 0.0f, 1.0f); /* lower left */
+ SET_ATTRIB(1, attr, s1, t0, 0.0f, 1.0f); /* lower right */
+ SET_ATTRIB(2, attr, s1, t1, 0.0f, 1.0f); /* upper right */
+ SET_ATTRIB(3, attr, s0, t1, 0.0f, 1.0f); /* upper left */
+
+ semantic_names[attr] = TGSI_SEMANTIC_GENERIC;
+ semantic_indexes[attr] = 0;
+
+ attr++;
+ }
+ }
+
+ pipe_buffer_unmap(pipe, vbuffer_transfer);
+
+#undef SET_ATTRIB
+ }
+
+
+ cso_save_viewport(cso);
+ cso_save_vertex_shader(cso);
+ cso_save_vertex_elements(cso);
+ cso_save_vertex_buffers(cso);
+
+ {
+ void *vs = lookup_shader(pipe, numAttribs,
+ semantic_names, semantic_indexes);
+ cso_set_vertex_shader_handle(cso, vs);
+ }
+
+ for (i = 0; i < numAttribs; i++) {
+ velements[i].src_offset = i * 4 * sizeof(float);
+ velements[i].instance_divisor = 0;
+ velements[i].vertex_buffer_index = 0;
+ velements[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ }
+ cso_set_vertex_elements(cso, numAttribs, velements);
+
+ /* viewport state: viewport matching window dims */
+ {
+ const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
+ const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP);
+ const GLfloat width = (GLfloat)fb->Width;
+ const GLfloat height = (GLfloat)fb->Height;
+ struct pipe_viewport_state vp;
+ vp.scale[0] = 0.5f * width;
+ vp.scale[1] = height * (invert ? -0.5f : 0.5f);
+ vp.scale[2] = 1.0f;
+ vp.scale[3] = 1.0f;
+ vp.translate[0] = 0.5f * width;
+ vp.translate[1] = 0.5f * height;
+ vp.translate[2] = 0.0f;
+ vp.translate[3] = 0.0f;
+ cso_set_viewport(cso, &vp);
+ }
+
+
+ util_draw_vertex_buffer(pipe, cso, vbuffer,
+ 0, /* offset */
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ numAttribs); /* attribs/vert */
+
+
+ pipe_resource_reference(&vbuffer, NULL);
+
+ /* restore state */
+ cso_restore_viewport(cso);
+ cso_restore_vertex_shader(cso);
+ cso_restore_vertex_elements(cso);
+ cso_restore_vertex_buffers(cso);
+}
+
+
+void
+st_init_drawtex_functions(struct dd_function_table *functions)
+{
+ functions->DrawTex = st_DrawTex;
+}
+
+
+/**
+ * Free any cached shaders
+ */
+void
+st_destroy_drawtex(struct st_context *st)
+{
+ GLuint i;
+ for (i = 0; i < NumCachedShaders; i++) {
+ cso_delete_vertex_shader(st->cso_context, CachedShaders[i].handle);
+ }
+ NumCachedShaders = 0;
+}
+
+
+#endif /* FEATURE_OES_draw_texture */
diff --git a/mesalib/src/mesa/state_tracker/st_context.c b/mesalib/src/mesa/state_tracker/st_context.c
index 7a19f35bb..8f3a7415d 100644
--- a/mesalib/src/mesa/state_tracker/st_context.c
+++ b/mesalib/src/mesa/state_tracker/st_context.c
@@ -1,297 +1,297 @@
-/**************************************************************************
- *
- * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
- * 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.
- *
- **************************************************************************/
-
-#include "main/imports.h"
-#include "main/context.h"
-#include "main/shaderobj.h"
-#include "program/prog_cache.h"
-#include "vbo/vbo.h"
-#include "glapi/glapi.h"
-#include "st_context.h"
-#include "st_debug.h"
-#include "st_cb_accum.h"
-#include "st_cb_bitmap.h"
-#include "st_cb_blit.h"
-#include "st_cb_bufferobjects.h"
-#include "st_cb_clear.h"
-#include "st_cb_condrender.h"
-#include "st_cb_drawpixels.h"
-#include "st_cb_rasterpos.h"
-#include "st_cb_drawtex.h"
-#include "st_cb_eglimage.h"
-#include "st_cb_fbo.h"
-#include "st_cb_feedback.h"
-#include "st_cb_program.h"
-#include "st_cb_queryobj.h"
-#include "st_cb_readpixels.h"
-#include "st_cb_texture.h"
-#include "st_cb_xformfb.h"
-#include "st_cb_flush.h"
-#include "st_cb_strings.h"
-#include "st_cb_viewport.h"
-#include "st_atom.h"
-#include "st_draw.h"
-#include "st_extensions.h"
-#include "st_gen_mipmap.h"
-#include "st_program.h"
-#include "pipe/p_context.h"
-#include "util/u_inlines.h"
-#include "cso_cache/cso_context.h"
-
-
-DEBUG_GET_ONCE_BOOL_OPTION(mesa_mvp_dp4, "MESA_MVP_DP4", FALSE)
-
-
-/**
- * Called via ctx->Driver.UpdateState()
- */
-void st_invalidate_state(struct gl_context * ctx, GLuint new_state)
-{
- struct st_context *st = st_context(ctx);
-
- st->dirty.mesa |= new_state;
- st->dirty.st |= ST_NEW_MESA;
-
- /* This is the only core Mesa module we depend upon.
- * No longer use swrast, swsetup, tnl.
- */
- _vbo_InvalidateState(ctx, new_state);
-}
-
-
-/**
- * Check for multisample env var override.
- */
-int
-st_get_msaa(void)
-{
- const char *msaa = _mesa_getenv("__GL_FSAA_MODE");
- if (msaa)
- return atoi(msaa);
- return 0;
-}
-
-
-static struct st_context *
-st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe )
-{
- uint i;
- struct st_context *st = ST_CALLOC_STRUCT( st_context );
-
- ctx->st = st;
-
- st->ctx = ctx;
- st->pipe = pipe;
-
- /* XXX: this is one-off, per-screen init: */
- st_debug_init();
-
- /* state tracker needs the VBO module */
- _vbo_CreateContext(ctx);
-
- st->dirty.mesa = ~0;
- st->dirty.st = ~0;
-
- st->cso_context = cso_create_context(pipe);
-
- st_init_atoms( st );
- st_init_bitmap(st);
- st_init_clear(st);
- st_init_draw( st );
- st_init_generate_mipmap(st);
- st_init_blit(st);
-
- if(pipe->screen->get_param(pipe->screen, PIPE_CAP_NPOT_TEXTURES))
- st->internal_target = PIPE_TEXTURE_2D;
- else
- st->internal_target = PIPE_TEXTURE_RECT;
-
- for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
- st->state.sampler_list[i] = &st->state.samplers[i];
-
- for (i = 0; i < 3; i++) {
- memset(&st->velems_util_draw[i], 0, sizeof(struct pipe_vertex_element));
- st->velems_util_draw[i].src_offset = i * 4 * sizeof(float);
- st->velems_util_draw[i].instance_divisor = 0;
- st->velems_util_draw[i].vertex_buffer_index = 0;
- st->velems_util_draw[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
- }
-
- /* we want all vertex data to be placed in buffer objects */
- vbo_use_buffer_objects(ctx);
-
- /* Need these flags:
- */
- st->ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
-
- st->ctx->VertexProgram._MaintainTnlProgram = GL_TRUE;
-
- st->pixel_xfer.cache = _mesa_new_program_cache();
-
- st->force_msaa = st_get_msaa();
-
- /* GL limits and extensions */
- st_init_limits(st);
- st_init_extensions(st);
-
- return st;
-}
-
-
-struct st_context *st_create_context(gl_api api, struct pipe_context *pipe,
- const struct gl_config *visual,
- struct st_context *share)
-{
- struct gl_context *ctx;
- struct gl_context *shareCtx = share ? share->ctx : NULL;
- struct dd_function_table funcs;
-
- /* Sanity checks */
- assert(MESA_SHADER_VERTEX == PIPE_SHADER_VERTEX);
- assert(MESA_SHADER_FRAGMENT == PIPE_SHADER_FRAGMENT);
- assert(MESA_SHADER_GEOMETRY == PIPE_SHADER_GEOMETRY);
-
- memset(&funcs, 0, sizeof(funcs));
- st_init_driver_functions(&funcs);
-
- ctx = _mesa_create_context(api, visual, shareCtx, &funcs, NULL);
-
- /* XXX: need a capability bit in gallium to query if the pipe
- * driver prefers DP4 or MUL/MAD for vertex transformation.
- */
- if (debug_get_option_mesa_mvp_dp4())
- _mesa_set_mvp_with_dp4( ctx, GL_TRUE );
-
- return st_create_context_priv(ctx, pipe);
-}
-
-
-static void st_destroy_context_priv( struct st_context *st )
-{
- uint i;
-
- st_destroy_atoms( st );
- st_destroy_draw( st );
- st_destroy_generate_mipmap(st);
- st_destroy_blit(st);
- st_destroy_clear(st);
- st_destroy_bitmap(st);
- st_destroy_drawpix(st);
- st_destroy_drawtex(st);
-
- /* Unreference any user vertex buffers. */
- for (i = 0; i < st->num_user_vbs; i++) {
- pipe_resource_reference(&st->user_vb[i], NULL);
- }
-
- for (i = 0; i < Elements(st->state.sampler_views); i++) {
- pipe_sampler_view_reference(&st->state.sampler_views[i], NULL);
- }
-
- if (st->default_texture) {
- st->ctx->Driver.DeleteTexture(st->ctx, st->default_texture);
- st->default_texture = NULL;
- }
-
- free( st );
-}
-
-
-void st_destroy_context( struct st_context *st )
-{
- struct pipe_context *pipe = st->pipe;
- struct cso_context *cso = st->cso_context;
- struct gl_context *ctx = st->ctx;
- GLuint i;
-
- /* need to unbind and destroy CSO objects before anything else */
- cso_release_all(st->cso_context);
-
- st_reference_fragprog(st, &st->fp, NULL);
- st_reference_vertprog(st, &st->vp, NULL);
-
- /* release framebuffer surfaces */
- for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
- pipe_surface_reference(&st->state.framebuffer.cbufs[i], NULL);
- }
- pipe_surface_reference(&st->state.framebuffer.zsbuf, NULL);
-
- pipe->set_index_buffer(pipe, NULL);
-
- for (i = 0; i < PIPE_SHADER_TYPES; i++) {
- pipe->set_constant_buffer(pipe, i, 0, NULL);
- }
-
- _mesa_delete_program_cache(st->ctx, st->pixel_xfer.cache);
-
- _vbo_DestroyContext(st->ctx);
-
- st_destroy_program_variants(st);
-
- _mesa_free_context_data(ctx);
-
- st_destroy_context_priv(st);
-
- cso_destroy_context(cso);
-
- pipe->destroy( pipe );
-
- free(ctx);
-}
-
-
-void st_init_driver_functions(struct dd_function_table *functions)
-{
- _mesa_init_shader_object_functions(functions);
-
- st_init_accum_functions(functions);
- st_init_blit_functions(functions);
- st_init_bufferobject_functions(functions);
- st_init_clear_functions(functions);
- st_init_bitmap_functions(functions);
- st_init_drawpixels_functions(functions);
- st_init_rasterpos_functions(functions);
-
- st_init_drawtex_functions(functions);
-
- st_init_eglimage_functions(functions);
-
- st_init_fbo_functions(functions);
- st_init_feedback_functions(functions);
- st_init_program_functions(functions);
- st_init_query_functions(functions);
- st_init_cond_render_functions(functions);
- st_init_readpixels_functions(functions);
- st_init_texture_functions(functions);
- st_init_flush_functions(functions);
- st_init_string_functions(functions);
- st_init_viewport_functions(functions);
-
- st_init_xformfb_functions(functions);
-
- functions->UpdateState = st_invalidate_state;
-}
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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.
+ *
+ **************************************************************************/
+
+#include "main/imports.h"
+#include "main/context.h"
+#include "main/shaderobj.h"
+#include "program/prog_cache.h"
+#include "vbo/vbo.h"
+#include "glapi/glapi.h"
+#include "st_context.h"
+#include "st_debug.h"
+#include "st_cb_accum.h"
+#include "st_cb_bitmap.h"
+#include "st_cb_blit.h"
+#include "st_cb_bufferobjects.h"
+#include "st_cb_clear.h"
+#include "st_cb_condrender.h"
+#include "st_cb_drawpixels.h"
+#include "st_cb_rasterpos.h"
+#include "st_cb_drawtex.h"
+#include "st_cb_eglimage.h"
+#include "st_cb_fbo.h"
+#include "st_cb_feedback.h"
+#include "st_cb_program.h"
+#include "st_cb_queryobj.h"
+#include "st_cb_readpixels.h"
+#include "st_cb_texture.h"
+#include "st_cb_xformfb.h"
+#include "st_cb_flush.h"
+#include "st_cb_strings.h"
+#include "st_cb_viewport.h"
+#include "st_atom.h"
+#include "st_draw.h"
+#include "st_extensions.h"
+#include "st_gen_mipmap.h"
+#include "st_program.h"
+#include "pipe/p_context.h"
+#include "util/u_inlines.h"
+#include "cso_cache/cso_context.h"
+
+
+DEBUG_GET_ONCE_BOOL_OPTION(mesa_mvp_dp4, "MESA_MVP_DP4", FALSE)
+
+
+/**
+ * Called via ctx->Driver.UpdateState()
+ */
+void st_invalidate_state(struct gl_context * ctx, GLuint new_state)
+{
+ struct st_context *st = st_context(ctx);
+
+ st->dirty.mesa |= new_state;
+ st->dirty.st |= ST_NEW_MESA;
+
+ /* This is the only core Mesa module we depend upon.
+ * No longer use swrast, swsetup, tnl.
+ */
+ _vbo_InvalidateState(ctx, new_state);
+}
+
+
+/**
+ * Check for multisample env var override.
+ */
+int
+st_get_msaa(void)
+{
+ const char *msaa = _mesa_getenv("__GL_FSAA_MODE");
+ if (msaa)
+ return atoi(msaa);
+ return 0;
+}
+
+
+static struct st_context *
+st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe )
+{
+ uint i;
+ struct st_context *st = ST_CALLOC_STRUCT( st_context );
+
+ ctx->st = st;
+
+ st->ctx = ctx;
+ st->pipe = pipe;
+
+ /* XXX: this is one-off, per-screen init: */
+ st_debug_init();
+
+ /* state tracker needs the VBO module */
+ _vbo_CreateContext(ctx);
+
+ st->dirty.mesa = ~0;
+ st->dirty.st = ~0;
+
+ st->cso_context = cso_create_context(pipe);
+
+ st_init_atoms( st );
+ st_init_bitmap(st);
+ st_init_clear(st);
+ st_init_draw( st );
+ st_init_generate_mipmap(st);
+ st_init_blit(st);
+
+ if(pipe->screen->get_param(pipe->screen, PIPE_CAP_NPOT_TEXTURES))
+ st->internal_target = PIPE_TEXTURE_2D;
+ else
+ st->internal_target = PIPE_TEXTURE_RECT;
+
+ for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
+ st->state.sampler_list[i] = &st->state.samplers[i];
+
+ for (i = 0; i < 3; i++) {
+ memset(&st->velems_util_draw[i], 0, sizeof(struct pipe_vertex_element));
+ st->velems_util_draw[i].src_offset = i * 4 * sizeof(float);
+ st->velems_util_draw[i].instance_divisor = 0;
+ st->velems_util_draw[i].vertex_buffer_index = 0;
+ st->velems_util_draw[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ }
+
+ /* we want all vertex data to be placed in buffer objects */
+ vbo_use_buffer_objects(ctx);
+
+ /* Need these flags:
+ */
+ st->ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
+
+ st->ctx->VertexProgram._MaintainTnlProgram = GL_TRUE;
+
+ st->pixel_xfer.cache = _mesa_new_program_cache();
+
+ st->force_msaa = st_get_msaa();
+
+ /* GL limits and extensions */
+ st_init_limits(st);
+ st_init_extensions(st);
+
+ return st;
+}
+
+
+struct st_context *st_create_context(gl_api api, struct pipe_context *pipe,
+ const struct gl_config *visual,
+ struct st_context *share)
+{
+ struct gl_context *ctx;
+ struct gl_context *shareCtx = share ? share->ctx : NULL;
+ struct dd_function_table funcs;
+
+ /* Sanity checks */
+ assert(MESA_SHADER_VERTEX == PIPE_SHADER_VERTEX);
+ assert(MESA_SHADER_FRAGMENT == PIPE_SHADER_FRAGMENT);
+ assert(MESA_SHADER_GEOMETRY == PIPE_SHADER_GEOMETRY);
+
+ memset(&funcs, 0, sizeof(funcs));
+ st_init_driver_functions(&funcs);
+
+ ctx = _mesa_create_context(api, visual, shareCtx, &funcs, NULL);
+
+ /* XXX: need a capability bit in gallium to query if the pipe
+ * driver prefers DP4 or MUL/MAD for vertex transformation.
+ */
+ if (debug_get_option_mesa_mvp_dp4())
+ _mesa_set_mvp_with_dp4( ctx, GL_TRUE );
+
+ return st_create_context_priv(ctx, pipe);
+}
+
+
+static void st_destroy_context_priv( struct st_context *st )
+{
+ uint i;
+
+ st_destroy_atoms( st );
+ st_destroy_draw( st );
+ st_destroy_generate_mipmap(st);
+ st_destroy_blit(st);
+ st_destroy_clear(st);
+ st_destroy_bitmap(st);
+ st_destroy_drawpix(st);
+ st_destroy_drawtex(st);
+
+ /* Unreference any user vertex buffers. */
+ for (i = 0; i < st->num_user_vbs; i++) {
+ pipe_resource_reference(&st->user_vb[i], NULL);
+ }
+
+ for (i = 0; i < Elements(st->state.sampler_views); i++) {
+ pipe_sampler_view_reference(&st->state.sampler_views[i], NULL);
+ }
+
+ if (st->default_texture) {
+ st->ctx->Driver.DeleteTexture(st->ctx, st->default_texture);
+ st->default_texture = NULL;
+ }
+
+ free( st );
+}
+
+
+void st_destroy_context( struct st_context *st )
+{
+ struct pipe_context *pipe = st->pipe;
+ struct cso_context *cso = st->cso_context;
+ struct gl_context *ctx = st->ctx;
+ GLuint i;
+
+ /* need to unbind and destroy CSO objects before anything else */
+ cso_release_all(st->cso_context);
+
+ st_reference_fragprog(st, &st->fp, NULL);
+ st_reference_vertprog(st, &st->vp, NULL);
+
+ /* release framebuffer surfaces */
+ for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
+ pipe_surface_reference(&st->state.framebuffer.cbufs[i], NULL);
+ }
+ pipe_surface_reference(&st->state.framebuffer.zsbuf, NULL);
+
+ pipe->set_index_buffer(pipe, NULL);
+
+ for (i = 0; i < PIPE_SHADER_TYPES; i++) {
+ pipe->set_constant_buffer(pipe, i, 0, NULL);
+ }
+
+ _mesa_delete_program_cache(st->ctx, st->pixel_xfer.cache);
+
+ _vbo_DestroyContext(st->ctx);
+
+ st_destroy_program_variants(st);
+
+ _mesa_free_context_data(ctx);
+
+ st_destroy_context_priv(st);
+
+ cso_destroy_context(cso);
+
+ pipe->destroy( pipe );
+
+ free(ctx);
+}
+
+
+void st_init_driver_functions(struct dd_function_table *functions)
+{
+ _mesa_init_shader_object_functions(functions);
+
+ st_init_accum_functions(functions);
+ st_init_blit_functions(functions);
+ st_init_bufferobject_functions(functions);
+ st_init_clear_functions(functions);
+ st_init_bitmap_functions(functions);
+ st_init_drawpixels_functions(functions);
+ st_init_rasterpos_functions(functions);
+
+ st_init_drawtex_functions(functions);
+
+ st_init_eglimage_functions(functions);
+
+ st_init_fbo_functions(functions);
+ st_init_feedback_functions(functions);
+ st_init_program_functions(functions);
+ st_init_query_functions(functions);
+ st_init_cond_render_functions(functions);
+ st_init_readpixels_functions(functions);
+ st_init_texture_functions(functions);
+ st_init_flush_functions(functions);
+ st_init_string_functions(functions);
+ st_init_viewport_functions(functions);
+
+ st_init_xformfb_functions(functions);
+
+ functions->UpdateState = st_invalidate_state;
+}
diff --git a/mesalib/src/mesa/state_tracker/st_context.h b/mesalib/src/mesa/state_tracker/st_context.h
index 77765f023..ef54fd7cd 100644
--- a/mesalib/src/mesa/state_tracker/st_context.h
+++ b/mesalib/src/mesa/state_tracker/st_context.h
@@ -1,270 +1,270 @@
-/**************************************************************************
- *
- * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
- * 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.
- *
- **************************************************************************/
-
-#ifndef ST_CONTEXT_H
-#define ST_CONTEXT_H
-
-#include "main/mtypes.h"
-#include "pipe/p_state.h"
-#include "state_tracker/st_api.h"
-
-struct bitmap_cache;
-struct blit_state;
-struct dd_function_table;
-struct draw_context;
-struct draw_stage;
-struct gen_mipmap_state;
-struct st_context;
-struct st_fragment_program;
-
-
-#define ST_NEW_MESA 0x1 /* Mesa state has changed */
-#define ST_NEW_FRAGMENT_PROGRAM 0x2
-#define ST_NEW_VERTEX_PROGRAM 0x4
-#define ST_NEW_FRAMEBUFFER 0x8
-#define ST_NEW_EDGEFLAGS_DATA 0x10
-#define ST_NEW_GEOMETRY_PROGRAM 0x20
-
-
-struct st_state_flags {
- GLuint mesa;
- GLuint st;
-};
-
-struct st_tracked_state {
- const char *name;
- struct st_state_flags dirty;
- void (*update)( struct st_context *st );
-};
-
-
-
-struct st_context
-{
- struct st_context_iface iface;
-
- struct gl_context *ctx;
-
- struct pipe_context *pipe;
-
- struct draw_context *draw; /**< For selection/feedback/rastpos only */
- struct draw_stage *feedback_stage; /**< For GL_FEEDBACK rendermode */
- struct draw_stage *selection_stage; /**< For GL_SELECT rendermode */
- struct draw_stage *rastpos_stage; /**< For glRasterPos */
-
-
- /* On old libGL's for linux we need to invalidate the drawables
- * on glViewpport calls, this is set via a option.
- */
- boolean invalidate_on_gl_viewport;
-
- /* Some state is contained in constant objects.
- * Other state is just parameter values.
- */
- struct {
- struct pipe_blend_state blend;
- struct pipe_depth_stencil_alpha_state depth_stencil;
- struct pipe_rasterizer_state rasterizer;
- struct pipe_sampler_state samplers[PIPE_MAX_SAMPLERS];
- struct pipe_sampler_state *sampler_list[PIPE_MAX_SAMPLERS];
- struct pipe_clip_state clip;
- struct {
- void *ptr;
- unsigned size;
- } constants[PIPE_SHADER_TYPES];
- struct pipe_framebuffer_state framebuffer;
- struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
- struct pipe_scissor_state scissor;
- struct pipe_viewport_state viewport;
- unsigned sample_mask;
-
- GLuint num_samplers;
- GLuint num_textures;
-
- GLuint poly_stipple[32]; /**< In OpenGL's bottom-to-top order */
- } state;
-
- char vendor[100];
- char renderer[100];
-
- struct st_state_flags dirty;
-
- GLboolean missing_textures;
- GLboolean vertdata_edgeflags;
-
- /** Mapping from VERT_RESULT_x to post-transformed vertex slot */
- const GLuint *vertex_result_to_slot;
-
- struct st_vertex_program *vp; /**< Currently bound vertex program */
- struct st_fragment_program *fp; /**< Currently bound fragment program */
- struct st_geometry_program *gp; /**< Currently bound geometry program */
-
- struct st_vp_variant *vp_variant;
- struct st_fp_variant *fp_variant;
- struct st_gp_variant *gp_variant;
-
- struct gl_texture_object *default_texture;
-
- struct {
- struct gl_program_cache *cache;
- struct st_fragment_program *program; /**< cur pixel transfer prog */
- GLuint xfer_prog_sn; /**< pixel xfer program serial no. */
- GLuint user_prog_sn; /**< user fragment program serial no. */
- struct st_fragment_program *combined_prog;
- GLuint combined_prog_sn;
- struct pipe_resource *pixelmap_texture;
- struct pipe_sampler_view *pixelmap_sampler_view;
- boolean pixelmap_enabled; /**< use the pixelmap texture? */
- } pixel_xfer;
-
- /** for glBitmap */
- struct {
- struct pipe_rasterizer_state rasterizer;
- struct pipe_sampler_state samplers[2];
- enum pipe_format tex_format;
- void *vs;
- float vertices[4][3][4]; /**< vertex pos + color + texcoord */
- struct pipe_resource *vbuf;
- unsigned vbuf_slot; /* next free slot in vbuf */
- struct bitmap_cache *cache;
- } bitmap;
-
- /** for glDraw/CopyPixels */
- struct {
- struct gl_fragment_program *shaders[4];
- void *vert_shaders[2]; /**< ureg shaders */
- } drawpix;
-
- /** for glClear */
- struct {
- struct pipe_rasterizer_state raster;
- struct pipe_viewport_state viewport;
- struct pipe_clip_state clip;
- void *vs;
- void *fs;
- float vertices[4][2][4]; /**< vertex pos + color */
- struct pipe_resource *vbuf;
- unsigned vbuf_slot;
- boolean enable_ds_separate;
- } clear;
-
- /** used for anything using util_draw_vertex_buffer */
- struct pipe_vertex_element velems_util_draw[3];
-
- void *passthrough_fs; /**< simple pass-through frag shader */
-
- enum pipe_texture_target internal_target;
- struct gen_mipmap_state *gen_mipmap;
- struct blit_state *blit;
-
- struct cso_context *cso_context;
-
- int force_msaa;
- void *winsys_drawable_handle;
-
- /* User vertex buffers. */
- struct pipe_resource *user_vb[PIPE_MAX_ATTRIBS];
- unsigned user_vb_stride[PIPE_MAX_ATTRIBS];
- unsigned num_user_vbs;
-};
-
-
-/* Need this so that we can implement Mesa callbacks in this module.
- */
-static INLINE struct st_context *st_context(struct gl_context *ctx)
-{
- return ctx->st;
-}
-
-
-/**
- * Wrapper for struct gl_framebuffer.
- * This is an opaque type to the outside world.
- */
-struct st_framebuffer
-{
- struct gl_framebuffer Base;
- void *Private;
-
- struct st_framebuffer_iface *iface;
- enum st_attachment_type statts[ST_ATTACHMENT_COUNT];
- unsigned num_statts;
- int32_t revalidate;
-};
-
-
-extern void st_init_driver_functions(struct dd_function_table *functions);
-
-void st_invalidate_state(struct gl_context * ctx, GLuint new_state);
-
-
-
-#define Y_0_TOP 1
-#define Y_0_BOTTOM 2
-
-static INLINE GLuint
-st_fb_orientation(const struct gl_framebuffer *fb)
-{
- if (fb && fb->Name == 0) {
- /* Drawing into a window (on-screen buffer).
- *
- * Negate Y scale to flip image vertically.
- * The NDC Y coords prior to viewport transformation are in the range
- * [y=-1=bottom, y=1=top]
- * Hardware window coords are in the range [y=0=top, y=H-1=bottom] where
- * H is the window height.
- * Use the viewport transformation to invert Y.
- */
- return Y_0_TOP;
- }
- else {
- /* Drawing into user-created FBO (very likely a texture).
- *
- * For textures, T=0=Bottom, so by extension Y=0=Bottom for rendering.
- */
- return Y_0_BOTTOM;
- }
-}
-
-
-/** clear-alloc a struct-sized object, with casting */
-#define ST_CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T))
-
-
-extern int
-st_get_msaa(void);
-
-extern struct st_context *
-st_create_context(gl_api api, struct pipe_context *pipe,
- const struct gl_config *visual,
- struct st_context *share);
-
-extern void
-st_destroy_context(struct st_context *st);
-
-
-#endif
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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.
+ *
+ **************************************************************************/
+
+#ifndef ST_CONTEXT_H
+#define ST_CONTEXT_H
+
+#include "main/mtypes.h"
+#include "pipe/p_state.h"
+#include "state_tracker/st_api.h"
+
+struct bitmap_cache;
+struct blit_state;
+struct dd_function_table;
+struct draw_context;
+struct draw_stage;
+struct gen_mipmap_state;
+struct st_context;
+struct st_fragment_program;
+
+
+#define ST_NEW_MESA 0x1 /* Mesa state has changed */
+#define ST_NEW_FRAGMENT_PROGRAM 0x2
+#define ST_NEW_VERTEX_PROGRAM 0x4
+#define ST_NEW_FRAMEBUFFER 0x8
+#define ST_NEW_EDGEFLAGS_DATA 0x10
+#define ST_NEW_GEOMETRY_PROGRAM 0x20
+
+
+struct st_state_flags {
+ GLuint mesa;
+ GLuint st;
+};
+
+struct st_tracked_state {
+ const char *name;
+ struct st_state_flags dirty;
+ void (*update)( struct st_context *st );
+};
+
+
+
+struct st_context
+{
+ struct st_context_iface iface;
+
+ struct gl_context *ctx;
+
+ struct pipe_context *pipe;
+
+ struct draw_context *draw; /**< For selection/feedback/rastpos only */
+ struct draw_stage *feedback_stage; /**< For GL_FEEDBACK rendermode */
+ struct draw_stage *selection_stage; /**< For GL_SELECT rendermode */
+ struct draw_stage *rastpos_stage; /**< For glRasterPos */
+
+
+ /* On old libGL's for linux we need to invalidate the drawables
+ * on glViewpport calls, this is set via a option.
+ */
+ boolean invalidate_on_gl_viewport;
+
+ /* Some state is contained in constant objects.
+ * Other state is just parameter values.
+ */
+ struct {
+ struct pipe_blend_state blend;
+ struct pipe_depth_stencil_alpha_state depth_stencil;
+ struct pipe_rasterizer_state rasterizer;
+ struct pipe_sampler_state samplers[PIPE_MAX_SAMPLERS];
+ struct pipe_sampler_state *sampler_list[PIPE_MAX_SAMPLERS];
+ struct pipe_clip_state clip;
+ struct {
+ void *ptr;
+ unsigned size;
+ } constants[PIPE_SHADER_TYPES];
+ struct pipe_framebuffer_state framebuffer;
+ struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
+ struct pipe_scissor_state scissor;
+ struct pipe_viewport_state viewport;
+ unsigned sample_mask;
+
+ GLuint num_samplers;
+ GLuint num_textures;
+
+ GLuint poly_stipple[32]; /**< In OpenGL's bottom-to-top order */
+ } state;
+
+ char vendor[100];
+ char renderer[100];
+
+ struct st_state_flags dirty;
+
+ GLboolean missing_textures;
+ GLboolean vertdata_edgeflags;
+
+ /** Mapping from VERT_RESULT_x to post-transformed vertex slot */
+ const GLuint *vertex_result_to_slot;
+
+ struct st_vertex_program *vp; /**< Currently bound vertex program */
+ struct st_fragment_program *fp; /**< Currently bound fragment program */
+ struct st_geometry_program *gp; /**< Currently bound geometry program */
+
+ struct st_vp_variant *vp_variant;
+ struct st_fp_variant *fp_variant;
+ struct st_gp_variant *gp_variant;
+
+ struct gl_texture_object *default_texture;
+
+ struct {
+ struct gl_program_cache *cache;
+ struct st_fragment_program *program; /**< cur pixel transfer prog */
+ GLuint xfer_prog_sn; /**< pixel xfer program serial no. */
+ GLuint user_prog_sn; /**< user fragment program serial no. */
+ struct st_fragment_program *combined_prog;
+ GLuint combined_prog_sn;
+ struct pipe_resource *pixelmap_texture;
+ struct pipe_sampler_view *pixelmap_sampler_view;
+ boolean pixelmap_enabled; /**< use the pixelmap texture? */
+ } pixel_xfer;
+
+ /** for glBitmap */
+ struct {
+ struct pipe_rasterizer_state rasterizer;
+ struct pipe_sampler_state samplers[2];
+ enum pipe_format tex_format;
+ void *vs;
+ float vertices[4][3][4]; /**< vertex pos + color + texcoord */
+ struct pipe_resource *vbuf;
+ unsigned vbuf_slot; /* next free slot in vbuf */
+ struct bitmap_cache *cache;
+ } bitmap;
+
+ /** for glDraw/CopyPixels */
+ struct {
+ struct gl_fragment_program *shaders[4];
+ void *vert_shaders[2]; /**< ureg shaders */
+ } drawpix;
+
+ /** for glClear */
+ struct {
+ struct pipe_rasterizer_state raster;
+ struct pipe_viewport_state viewport;
+ struct pipe_clip_state clip;
+ void *vs;
+ void *fs;
+ float vertices[4][2][4]; /**< vertex pos + color */
+ struct pipe_resource *vbuf;
+ unsigned vbuf_slot;
+ boolean enable_ds_separate;
+ } clear;
+
+ /** used for anything using util_draw_vertex_buffer */
+ struct pipe_vertex_element velems_util_draw[3];
+
+ void *passthrough_fs; /**< simple pass-through frag shader */
+
+ enum pipe_texture_target internal_target;
+ struct gen_mipmap_state *gen_mipmap;
+ struct blit_state *blit;
+
+ struct cso_context *cso_context;
+
+ int force_msaa;
+ void *winsys_drawable_handle;
+
+ /* User vertex buffers. */
+ struct pipe_resource *user_vb[PIPE_MAX_ATTRIBS];
+ unsigned user_vb_stride[PIPE_MAX_ATTRIBS];
+ unsigned num_user_vbs;
+};
+
+
+/* Need this so that we can implement Mesa callbacks in this module.
+ */
+static INLINE struct st_context *st_context(struct gl_context *ctx)
+{
+ return ctx->st;
+}
+
+
+/**
+ * Wrapper for struct gl_framebuffer.
+ * This is an opaque type to the outside world.
+ */
+struct st_framebuffer
+{
+ struct gl_framebuffer Base;
+ void *Private;
+
+ struct st_framebuffer_iface *iface;
+ enum st_attachment_type statts[ST_ATTACHMENT_COUNT];
+ unsigned num_statts;
+ int32_t revalidate;
+};
+
+
+extern void st_init_driver_functions(struct dd_function_table *functions);
+
+void st_invalidate_state(struct gl_context * ctx, GLuint new_state);
+
+
+
+#define Y_0_TOP 1
+#define Y_0_BOTTOM 2
+
+static INLINE GLuint
+st_fb_orientation(const struct gl_framebuffer *fb)
+{
+ if (fb && fb->Name == 0) {
+ /* Drawing into a window (on-screen buffer).
+ *
+ * Negate Y scale to flip image vertically.
+ * The NDC Y coords prior to viewport transformation are in the range
+ * [y=-1=bottom, y=1=top]
+ * Hardware window coords are in the range [y=0=top, y=H-1=bottom] where
+ * H is the window height.
+ * Use the viewport transformation to invert Y.
+ */
+ return Y_0_TOP;
+ }
+ else {
+ /* Drawing into user-created FBO (very likely a texture).
+ *
+ * For textures, T=0=Bottom, so by extension Y=0=Bottom for rendering.
+ */
+ return Y_0_BOTTOM;
+ }
+}
+
+
+/** clear-alloc a struct-sized object, with casting */
+#define ST_CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T))
+
+
+extern int
+st_get_msaa(void);
+
+extern struct st_context *
+st_create_context(gl_api api, struct pipe_context *pipe,
+ const struct gl_config *visual,
+ struct st_context *share);
+
+extern void
+st_destroy_context(struct st_context *st);
+
+
+#endif
diff --git a/mesalib/src/mesa/state_tracker/st_draw_feedback.c b/mesalib/src/mesa/state_tracker/st_draw_feedback.c
index 1e1220bfe..f0734eae0 100644
--- a/mesalib/src/mesa/state_tracker/st_draw_feedback.c
+++ b/mesalib/src/mesa/state_tracker/st_draw_feedback.c
@@ -1,277 +1,277 @@
-/**************************************************************************
- *
- * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
- * 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.
- *
- **************************************************************************/
-
-#include "main/imports.h"
-#include "main/image.h"
-#include "main/macros.h"
-#include "main/mfeatures.h"
-
-#include "vbo/vbo.h"
-
-#include "st_context.h"
-#include "st_atom.h"
-#include "st_cb_bufferobjects.h"
-#include "st_draw.h"
-#include "st_program.h"
-
-#include "pipe/p_context.h"
-#include "pipe/p_defines.h"
-#include "util/u_inlines.h"
-
-#include "draw/draw_private.h"
-#include "draw/draw_context.h"
-
-
-#if FEATURE_feedback || FEATURE_rastpos
-
-/**
- * Set the (private) draw module's post-transformed vertex format when in
- * GL_SELECT or GL_FEEDBACK mode or for glRasterPos.
- */
-static void
-set_feedback_vertex_format(struct gl_context *ctx)
-{
-#if 0
- struct st_context *st = st_context(ctx);
- struct vertex_info vinfo;
- GLuint i;
-
- memset(&vinfo, 0, sizeof(vinfo));
-
- if (ctx->RenderMode == GL_SELECT) {
- assert(ctx->RenderMode == GL_SELECT);
- vinfo.num_attribs = 1;
- vinfo.format[0] = FORMAT_4F;
- vinfo.interp_mode[0] = INTERP_LINEAR;
- }
- else {
- /* GL_FEEDBACK, or glRasterPos */
- /* emit all attribs (pos, color, texcoord) as GLfloat[4] */
- vinfo.num_attribs = st->state.vs->cso->state.num_outputs;
- for (i = 0; i < vinfo.num_attribs; i++) {
- vinfo.format[i] = FORMAT_4F;
- vinfo.interp_mode[i] = INTERP_LINEAR;
- }
- }
-
- draw_set_vertex_info(st->draw, &vinfo);
-#endif
-}
-
-
-/**
- * Called by VBO to draw arrays when in selection or feedback mode and
- * to implement glRasterPos.
- * This is very much like the normal draw_vbo() function above.
- * Look at code refactoring some day.
- * Might move this into the failover module some day.
- */
-void
-st_feedback_draw_vbo(struct gl_context *ctx,
- const struct gl_client_array **arrays,
- const struct _mesa_prim *prims,
- GLuint nr_prims,
- const struct _mesa_index_buffer *ib,
- GLboolean index_bounds_valid,
- GLuint min_index,
- GLuint max_index)
-{
- struct st_context *st = st_context(ctx);
- struct pipe_context *pipe = st->pipe;
- struct draw_context *draw = st->draw;
- const struct st_vertex_program *vp;
- const struct pipe_shader_state *vs;
- struct pipe_vertex_buffer vbuffers[PIPE_MAX_SHADER_INPUTS];
- struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
- struct pipe_index_buffer ibuffer;
- struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS];
- struct pipe_transfer *ib_transfer = NULL;
- GLuint attr, i;
- const void *mapped_indices = NULL;
-
- assert(draw);
-
- st_validate_state(st);
-
- if (!index_bounds_valid)
- vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index);
-
- /* must get these after state validation! */
- vp = st->vp;
- vs = &st->vp_variant->tgsi;
-
- if (!st->vp_variant->draw_shader) {
- st->vp_variant->draw_shader = draw_create_vertex_shader(draw, vs);
- }
-
- /*
- * Set up the draw module's state.
- *
- * We'd like to do this less frequently, but the normal state-update
- * code sends state updates to the pipe, not to our private draw module.
- */
- assert(draw);
- draw_set_viewport_state(draw, &st->state.viewport);
- draw_set_clip_state(draw, &st->state.clip);
- draw_set_rasterizer_state(draw, &st->state.rasterizer, NULL);
- draw_bind_vertex_shader(draw, st->vp_variant->draw_shader);
- set_feedback_vertex_format(ctx);
-
- /* loop over TGSI shader inputs to determine vertex buffer
- * and attribute info
- */
- for (attr = 0; attr < vp->num_inputs; attr++) {
- const GLuint mesaAttr = vp->index_to_input[attr];
- struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj;
- void *map;
-
- if (bufobj && bufobj->Name) {
- /* Attribute data is in a VBO.
- * Recall that for VBOs, the gl_client_array->Ptr field is
- * really an offset from the start of the VBO, not a pointer.
- */
- struct st_buffer_object *stobj = st_buffer_object(bufobj);
- assert(stobj->buffer);
-
- vbuffers[attr].buffer = NULL;
- pipe_resource_reference(&vbuffers[attr].buffer, stobj->buffer);
- vbuffers[attr].buffer_offset = pointer_to_offset(arrays[0]->Ptr);
- velements[attr].src_offset = arrays[mesaAttr]->Ptr - arrays[0]->Ptr;
- }
- else {
- /* attribute data is in user-space memory, not a VBO */
- uint bytes = (arrays[mesaAttr]->Size
- * _mesa_sizeof_type(arrays[mesaAttr]->Type)
- * (max_index + 1));
-
- /* wrap user data */
- vbuffers[attr].buffer
- = pipe_user_buffer_create(pipe->screen, (void *) arrays[mesaAttr]->Ptr,
- bytes,
- PIPE_BIND_VERTEX_BUFFER);
- vbuffers[attr].buffer_offset = 0;
- velements[attr].src_offset = 0;
- }
-
- /* common-case setup */
- vbuffers[attr].stride = arrays[mesaAttr]->StrideB; /* in bytes */
- velements[attr].instance_divisor = 0;
- velements[attr].vertex_buffer_index = attr;
- velements[attr].src_format =
- st_pipe_vertex_format(arrays[mesaAttr]->Type,
- arrays[mesaAttr]->Size,
- arrays[mesaAttr]->Format,
- arrays[mesaAttr]->Normalized);
- assert(velements[attr].src_format);
-
- /* tell draw about this attribute */
-#if 0
- draw_set_vertex_buffer(draw, attr, &vbuffer[attr]);
-#endif
-
- /* map the attrib buffer */
- map = pipe_buffer_map(pipe, vbuffers[attr].buffer,
- PIPE_TRANSFER_READ,
- &vb_transfer[attr]);
- draw_set_mapped_vertex_buffer(draw, attr, map);
- }
-
- draw_set_vertex_buffers(draw, vp->num_inputs, vbuffers);
- draw_set_vertex_elements(draw, vp->num_inputs, velements);
-
- memset(&ibuffer, 0, sizeof(ibuffer));
- if (ib) {
- struct gl_buffer_object *bufobj = ib->obj;
-
- switch (ib->type) {
- case GL_UNSIGNED_INT:
- ibuffer.index_size = 4;
- break;
- case GL_UNSIGNED_SHORT:
- ibuffer.index_size = 2;
- break;
- case GL_UNSIGNED_BYTE:
- ibuffer.index_size = 1;
- break;
- default:
- assert(0);
- goto out_unref_vertex;
- }
-
- if (bufobj && bufobj->Name) {
- struct st_buffer_object *stobj = st_buffer_object(bufobj);
-
- pipe_resource_reference(&ibuffer.buffer, stobj->buffer);
- ibuffer.offset = pointer_to_offset(ib->ptr);
-
- mapped_indices = pipe_buffer_map(pipe, stobj->buffer,
- PIPE_TRANSFER_READ, &ib_transfer);
- }
- else {
- /* skip setting ibuffer.buffer as the draw module does not use it */
- mapped_indices = ib->ptr;
- }
-
- draw_set_index_buffer(draw, &ibuffer);
- draw_set_mapped_index_buffer(draw, mapped_indices);
- }
-
- /* set the constant buffer */
- draw_set_mapped_constant_buffer(st->draw, PIPE_SHADER_VERTEX, 0,
- st->state.constants[PIPE_SHADER_VERTEX].ptr,
- st->state.constants[PIPE_SHADER_VERTEX].size);
-
-
- /* draw here */
- for (i = 0; i < nr_prims; i++) {
- draw_arrays(draw, prims[i].mode, prims[i].start, prims[i].count);
- }
-
-
- /*
- * unmap vertex/index buffers
- */
- if (ib) {
- draw_set_mapped_index_buffer(draw, NULL);
- draw_set_index_buffer(draw, NULL);
-
- if (ib_transfer)
- pipe_buffer_unmap(pipe, ib_transfer);
- pipe_resource_reference(&ibuffer.buffer, NULL);
- }
-
- out_unref_vertex:
- for (attr = 0; attr < vp->num_inputs; attr++) {
- pipe_buffer_unmap(pipe, vb_transfer[attr]);
- draw_set_mapped_vertex_buffer(draw, attr, NULL);
- pipe_resource_reference(&vbuffers[attr].buffer, NULL);
- }
- draw_set_vertex_buffers(draw, 0, NULL);
-}
-
-#endif /* FEATURE_feedback || FEATURE_rastpos */
-
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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.
+ *
+ **************************************************************************/
+
+#include "main/imports.h"
+#include "main/image.h"
+#include "main/macros.h"
+#include "main/mfeatures.h"
+
+#include "vbo/vbo.h"
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_cb_bufferobjects.h"
+#include "st_draw.h"
+#include "st_program.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "util/u_inlines.h"
+
+#include "draw/draw_private.h"
+#include "draw/draw_context.h"
+
+
+#if FEATURE_feedback || FEATURE_rastpos
+
+/**
+ * Set the (private) draw module's post-transformed vertex format when in
+ * GL_SELECT or GL_FEEDBACK mode or for glRasterPos.
+ */
+static void
+set_feedback_vertex_format(struct gl_context *ctx)
+{
+#if 0
+ struct st_context *st = st_context(ctx);
+ struct vertex_info vinfo;
+ GLuint i;
+
+ memset(&vinfo, 0, sizeof(vinfo));
+
+ if (ctx->RenderMode == GL_SELECT) {
+ assert(ctx->RenderMode == GL_SELECT);
+ vinfo.num_attribs = 1;
+ vinfo.format[0] = FORMAT_4F;
+ vinfo.interp_mode[0] = INTERP_LINEAR;
+ }
+ else {
+ /* GL_FEEDBACK, or glRasterPos */
+ /* emit all attribs (pos, color, texcoord) as GLfloat[4] */
+ vinfo.num_attribs = st->state.vs->cso->state.num_outputs;
+ for (i = 0; i < vinfo.num_attribs; i++) {
+ vinfo.format[i] = FORMAT_4F;
+ vinfo.interp_mode[i] = INTERP_LINEAR;
+ }
+ }
+
+ draw_set_vertex_info(st->draw, &vinfo);
+#endif
+}
+
+
+/**
+ * Called by VBO to draw arrays when in selection or feedback mode and
+ * to implement glRasterPos.
+ * This is very much like the normal draw_vbo() function above.
+ * Look at code refactoring some day.
+ * Might move this into the failover module some day.
+ */
+void
+st_feedback_draw_vbo(struct gl_context *ctx,
+ const struct gl_client_array **arrays,
+ const struct _mesa_prim *prims,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLboolean index_bounds_valid,
+ GLuint min_index,
+ GLuint max_index)
+{
+ struct st_context *st = st_context(ctx);
+ struct pipe_context *pipe = st->pipe;
+ struct draw_context *draw = st->draw;
+ const struct st_vertex_program *vp;
+ const struct pipe_shader_state *vs;
+ struct pipe_vertex_buffer vbuffers[PIPE_MAX_SHADER_INPUTS];
+ struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
+ struct pipe_index_buffer ibuffer;
+ struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS];
+ struct pipe_transfer *ib_transfer = NULL;
+ GLuint attr, i;
+ const void *mapped_indices = NULL;
+
+ assert(draw);
+
+ st_validate_state(st);
+
+ if (!index_bounds_valid)
+ vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index);
+
+ /* must get these after state validation! */
+ vp = st->vp;
+ vs = &st->vp_variant->tgsi;
+
+ if (!st->vp_variant->draw_shader) {
+ st->vp_variant->draw_shader = draw_create_vertex_shader(draw, vs);
+ }
+
+ /*
+ * Set up the draw module's state.
+ *
+ * We'd like to do this less frequently, but the normal state-update
+ * code sends state updates to the pipe, not to our private draw module.
+ */
+ assert(draw);
+ draw_set_viewport_state(draw, &st->state.viewport);
+ draw_set_clip_state(draw, &st->state.clip);
+ draw_set_rasterizer_state(draw, &st->state.rasterizer, NULL);
+ draw_bind_vertex_shader(draw, st->vp_variant->draw_shader);
+ set_feedback_vertex_format(ctx);
+
+ /* loop over TGSI shader inputs to determine vertex buffer
+ * and attribute info
+ */
+ for (attr = 0; attr < vp->num_inputs; attr++) {
+ const GLuint mesaAttr = vp->index_to_input[attr];
+ struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj;
+ void *map;
+
+ if (bufobj && bufobj->Name) {
+ /* Attribute data is in a VBO.
+ * Recall that for VBOs, the gl_client_array->Ptr field is
+ * really an offset from the start of the VBO, not a pointer.
+ */
+ struct st_buffer_object *stobj = st_buffer_object(bufobj);
+ assert(stobj->buffer);
+
+ vbuffers[attr].buffer = NULL;
+ pipe_resource_reference(&vbuffers[attr].buffer, stobj->buffer);
+ vbuffers[attr].buffer_offset = pointer_to_offset(arrays[0]->Ptr);
+ velements[attr].src_offset = arrays[mesaAttr]->Ptr - arrays[0]->Ptr;
+ }
+ else {
+ /* attribute data is in user-space memory, not a VBO */
+ uint bytes = (arrays[mesaAttr]->Size
+ * _mesa_sizeof_type(arrays[mesaAttr]->Type)
+ * (max_index + 1));
+
+ /* wrap user data */
+ vbuffers[attr].buffer
+ = pipe_user_buffer_create(pipe->screen, (void *) arrays[mesaAttr]->Ptr,
+ bytes,
+ PIPE_BIND_VERTEX_BUFFER);
+ vbuffers[attr].buffer_offset = 0;
+ velements[attr].src_offset = 0;
+ }
+
+ /* common-case setup */
+ vbuffers[attr].stride = arrays[mesaAttr]->StrideB; /* in bytes */
+ velements[attr].instance_divisor = 0;
+ velements[attr].vertex_buffer_index = attr;
+ velements[attr].src_format =
+ st_pipe_vertex_format(arrays[mesaAttr]->Type,
+ arrays[mesaAttr]->Size,
+ arrays[mesaAttr]->Format,
+ arrays[mesaAttr]->Normalized);
+ assert(velements[attr].src_format);
+
+ /* tell draw about this attribute */
+#if 0
+ draw_set_vertex_buffer(draw, attr, &vbuffer[attr]);
+#endif
+
+ /* map the attrib buffer */
+ map = pipe_buffer_map(pipe, vbuffers[attr].buffer,
+ PIPE_TRANSFER_READ,
+ &vb_transfer[attr]);
+ draw_set_mapped_vertex_buffer(draw, attr, map);
+ }
+
+ draw_set_vertex_buffers(draw, vp->num_inputs, vbuffers);
+ draw_set_vertex_elements(draw, vp->num_inputs, velements);
+
+ memset(&ibuffer, 0, sizeof(ibuffer));
+ if (ib) {
+ struct gl_buffer_object *bufobj = ib->obj;
+
+ switch (ib->type) {
+ case GL_UNSIGNED_INT:
+ ibuffer.index_size = 4;
+ break;
+ case GL_UNSIGNED_SHORT:
+ ibuffer.index_size = 2;
+ break;
+ case GL_UNSIGNED_BYTE:
+ ibuffer.index_size = 1;
+ break;
+ default:
+ assert(0);
+ goto out_unref_vertex;
+ }
+
+ if (bufobj && bufobj->Name) {
+ struct st_buffer_object *stobj = st_buffer_object(bufobj);
+
+ pipe_resource_reference(&ibuffer.buffer, stobj->buffer);
+ ibuffer.offset = pointer_to_offset(ib->ptr);
+
+ mapped_indices = pipe_buffer_map(pipe, stobj->buffer,
+ PIPE_TRANSFER_READ, &ib_transfer);
+ }
+ else {
+ /* skip setting ibuffer.buffer as the draw module does not use it */
+ mapped_indices = ib->ptr;
+ }
+
+ draw_set_index_buffer(draw, &ibuffer);
+ draw_set_mapped_index_buffer(draw, mapped_indices);
+ }
+
+ /* set the constant buffer */
+ draw_set_mapped_constant_buffer(st->draw, PIPE_SHADER_VERTEX, 0,
+ st->state.constants[PIPE_SHADER_VERTEX].ptr,
+ st->state.constants[PIPE_SHADER_VERTEX].size);
+
+
+ /* draw here */
+ for (i = 0; i < nr_prims; i++) {
+ draw_arrays(draw, prims[i].mode, prims[i].start, prims[i].count);
+ }
+
+
+ /*
+ * unmap vertex/index buffers
+ */
+ if (ib) {
+ draw_set_mapped_index_buffer(draw, NULL);
+ draw_set_index_buffer(draw, NULL);
+
+ if (ib_transfer)
+ pipe_buffer_unmap(pipe, ib_transfer);
+ pipe_resource_reference(&ibuffer.buffer, NULL);
+ }
+
+ out_unref_vertex:
+ for (attr = 0; attr < vp->num_inputs; attr++) {
+ pipe_buffer_unmap(pipe, vb_transfer[attr]);
+ draw_set_mapped_vertex_buffer(draw, attr, NULL);
+ pipe_resource_reference(&vbuffers[attr].buffer, NULL);
+ }
+ draw_set_vertex_buffers(draw, 0, NULL);
+}
+
+#endif /* FEATURE_feedback || FEATURE_rastpos */
+
diff --git a/mesalib/src/mesa/state_tracker/st_gen_mipmap.c b/mesalib/src/mesa/state_tracker/st_gen_mipmap.c
index 18eb3be68..5fcd806e0 100644
--- a/mesalib/src/mesa/state_tracker/st_gen_mipmap.c
+++ b/mesalib/src/mesa/state_tracker/st_gen_mipmap.c
@@ -1,422 +1,422 @@
-/**************************************************************************
- *
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
- * 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.
- *
- **************************************************************************/
-
-
-#include "main/imports.h"
-#include "main/mipmap.h"
-#include "main/teximage.h"
-
-#include "pipe/p_context.h"
-#include "pipe/p_defines.h"
-#include "util/u_inlines.h"
-#include "util/u_format.h"
-#include "util/u_gen_mipmap.h"
-
-#include "st_debug.h"
-#include "st_context.h"
-#include "st_texture.h"
-#include "st_gen_mipmap.h"
-#include "st_cb_texture.h"
-
-
-/**
- * one-time init for generate mipmap
- * XXX Note: there may be other times we need no-op/simple state like this.
- * In that case, some code refactoring would be good.
- */
-void
-st_init_generate_mipmap(struct st_context *st)
-{
- st->gen_mipmap = util_create_gen_mipmap(st->pipe, st->cso_context);
-}
-
-
-void
-st_destroy_generate_mipmap(struct st_context *st)
-{
- util_destroy_gen_mipmap(st->gen_mipmap);
- st->gen_mipmap = NULL;
-}
-
-
-/**
- * Generate mipmap levels using hardware rendering.
- * \return TRUE if successful, FALSE if not possible
- */
-static boolean
-st_render_mipmap(struct st_context *st,
- GLenum target,
- struct st_texture_object *stObj,
- uint baseLevel, uint lastLevel)
-{
- struct pipe_context *pipe = st->pipe;
- struct pipe_screen *screen = pipe->screen;
- struct pipe_sampler_view *psv = st_get_texture_sampler_view(stObj, pipe);
- const uint face = _mesa_tex_target_to_face(target);
-
- assert(psv->texture == stObj->pt);
-#if 0
- assert(target != GL_TEXTURE_3D); /* implemented but untested */
-#endif
-
- /* check if we can render in the texture's format */
- /* XXX should probably kill this and always use util_gen_mipmap
- since this implements a sw fallback as well */
- if (!screen->is_format_supported(screen, psv->format, psv->texture->target,
- 0, PIPE_BIND_RENDER_TARGET, 0)) {
- return FALSE;
- }
-
- util_gen_mipmap(st->gen_mipmap, psv, face, baseLevel, lastLevel,
- PIPE_TEX_FILTER_LINEAR);
-
- return TRUE;
-}
-
-
-/**
- * Helper function to decompress an image. The result is a 32-bpp RGBA
- * image with stride==width.
- */
-static void
-decompress_image(enum pipe_format format,
- const uint8_t *src, uint8_t *dst,
- unsigned width, unsigned height, unsigned src_stride)
-{
- const struct util_format_description *desc = util_format_description(format);
- const uint bw = util_format_get_blockwidth(format);
- const uint bh = util_format_get_blockheight(format);
- const uint dst_stride = 4 * MAX2(width, bw);
-
- desc->unpack_rgba_8unorm(dst, dst_stride, src, src_stride, width, height);
-
- if (width < bw || height < bh) {
- /* We're decompressing an image smaller than the compression
- * block size. We don't want garbage pixel values in the region
- * outside (width x height) so replicate pixels from the (width
- * x height) region to fill out the (bw x bh) block size.
- */
- uint x, y;
- for (y = 0; y < bh; y++) {
- for (x = 0; x < bw; x++) {
- if (x >= width || y >= height) {
- uint p = (y * bw + x) * 4;
- dst[p + 0] = dst[0];
- dst[p + 1] = dst[1];
- dst[p + 2] = dst[2];
- dst[p + 3] = dst[3];
- }
- }
- }
- }
-}
-
-
-/**
- * Helper function to compress an image. The source is a 32-bpp RGBA image
- * with stride==width.
- */
-static void
-compress_image(enum pipe_format format,
- const uint8_t *src, uint8_t *dst,
- unsigned width, unsigned height, unsigned dst_stride)
-{
- const struct util_format_description *desc = util_format_description(format);
- const uint src_stride = 4 * width;
-
- desc->pack_rgba_8unorm(dst, dst_stride, src, src_stride, width, height);
-}
-
-
-/**
- * Software fallback for generate mipmap levels.
- */
-static void
-fallback_generate_mipmap(struct gl_context *ctx, GLenum target,
- struct gl_texture_object *texObj)
-{
- struct pipe_context *pipe = st_context(ctx)->pipe;
- struct pipe_resource *pt = st_get_texobj_resource(texObj);
- const uint baseLevel = texObj->BaseLevel;
- const uint lastLevel = pt->last_level;
- const uint face = _mesa_tex_target_to_face(target);
- uint dstLevel;
- GLenum datatype;
- GLuint comps;
- GLboolean compressed;
-
- if (ST_DEBUG & DEBUG_FALLBACK)
- debug_printf("%s: fallback processing\n", __FUNCTION__);
-
- assert(target != GL_TEXTURE_3D); /* not done yet */
-
- compressed =
- _mesa_is_format_compressed(texObj->Image[face][baseLevel]->TexFormat);
-
- if (compressed) {
- datatype = GL_UNSIGNED_BYTE;
- comps = 4;
- }
- else {
- _mesa_format_to_type_and_comps(texObj->Image[face][baseLevel]->TexFormat,
- &datatype, &comps);
- assert(comps > 0 && "bad texture format in fallback_generate_mipmap()");
- }
-
- for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
- const uint srcLevel = dstLevel - 1;
- const uint srcWidth = u_minify(pt->width0, srcLevel);
- const uint srcHeight = u_minify(pt->height0, srcLevel);
- const uint srcDepth = u_minify(pt->depth0, srcLevel);
- const uint dstWidth = u_minify(pt->width0, dstLevel);
- const uint dstHeight = u_minify(pt->height0, dstLevel);
- const uint dstDepth = u_minify(pt->depth0, dstLevel);
- struct pipe_transfer *srcTrans, *dstTrans;
- const ubyte *srcData;
- ubyte *dstData;
- int srcStride, dstStride;
-
- srcTrans = pipe_get_transfer(st_context(ctx)->pipe, pt, srcLevel,
- face,
- PIPE_TRANSFER_READ, 0, 0,
- srcWidth, srcHeight);
-
- dstTrans = pipe_get_transfer(st_context(ctx)->pipe, pt, dstLevel,
- face,
- PIPE_TRANSFER_WRITE, 0, 0,
- dstWidth, dstHeight);
-
- srcData = (ubyte *) pipe_transfer_map(pipe, srcTrans);
- dstData = (ubyte *) pipe_transfer_map(pipe, dstTrans);
-
- srcStride = srcTrans->stride / util_format_get_blocksize(srcTrans->resource->format);
- dstStride = dstTrans->stride / util_format_get_blocksize(dstTrans->resource->format);
-
- /* this cannot work correctly for 3d since it does
- not respect layerStride. */
- if (compressed) {
- const enum pipe_format format = pt->format;
- const uint bw = util_format_get_blockwidth(format);
- const uint bh = util_format_get_blockheight(format);
- const uint srcWidth2 = align(srcWidth, bw);
- const uint srcHeight2 = align(srcHeight, bh);
- const uint dstWidth2 = align(dstWidth, bw);
- const uint dstHeight2 = align(dstHeight, bh);
- uint8_t *srcTemp, *dstTemp;
-
- assert(comps == 4);
-
- srcTemp = malloc(srcWidth2 * srcHeight2 * comps + 000);
- dstTemp = malloc(dstWidth2 * dstHeight2 * comps + 000);
-
- /* decompress the src image: srcData -> srcTemp */
- decompress_image(format, srcData, srcTemp, srcWidth, srcHeight, srcTrans->stride);
-
- _mesa_generate_mipmap_level(target, datatype, comps,
- 0 /*border*/,
- srcWidth2, srcHeight2, srcDepth,
- srcTemp,
- srcWidth2, /* stride in texels */
- dstWidth2, dstHeight2, dstDepth,
- dstTemp,
- dstWidth2); /* stride in texels */
-
- /* compress the new image: dstTemp -> dstData */
- compress_image(format, dstTemp, dstData, dstWidth, dstHeight, dstTrans->stride);
-
- free(srcTemp);
- free(dstTemp);
- }
- else {
- _mesa_generate_mipmap_level(target, datatype, comps,
- 0 /*border*/,
- srcWidth, srcHeight, srcDepth,
- srcData,
- srcStride, /* stride in texels */
- dstWidth, dstHeight, dstDepth,
- dstData,
- dstStride); /* stride in texels */
- }
-
- pipe_transfer_unmap(pipe, srcTrans);
- pipe_transfer_unmap(pipe, dstTrans);
-
- pipe->transfer_destroy(pipe, srcTrans);
- pipe->transfer_destroy(pipe, dstTrans);
- }
-}
-
-
-/**
- * Compute the expected number of mipmap levels in the texture given
- * the width/height/depth of the base image and the GL_TEXTURE_BASE_LEVEL/
- * GL_TEXTURE_MAX_LEVEL settings. This will tell us how many mipmap
- * levels should be generated.
- */
-static GLuint
-compute_num_levels(struct gl_context *ctx,
- struct gl_texture_object *texObj,
- GLenum target)
-{
- if (target == GL_TEXTURE_RECTANGLE_ARB) {
- return 1;
- }
- else {
- const struct gl_texture_image *baseImage =
- _mesa_get_tex_image(ctx, texObj, target, texObj->BaseLevel);
- GLuint size, numLevels;
-
- size = MAX2(baseImage->Width2, baseImage->Height2);
- size = MAX2(size, baseImage->Depth2);
-
- numLevels = texObj->BaseLevel;
-
- while (size > 0) {
- numLevels++;
- size >>= 1;
- }
-
- numLevels = MIN2(numLevels, texObj->MaxLevel + 1);
-
- assert(numLevels >= 1);
-
- return numLevels;
- }
-}
-
-
-/**
- * Called via ctx->Driver.GenerateMipmap().
- */
-void
-st_generate_mipmap(struct gl_context *ctx, GLenum target,
- struct gl_texture_object *texObj)
-{
- struct st_context *st = st_context(ctx);
- struct st_texture_object *stObj = st_texture_object(texObj);
- struct pipe_resource *pt = st_get_texobj_resource(texObj);
- const uint baseLevel = texObj->BaseLevel;
- uint lastLevel;
- uint dstLevel;
-
- if (!pt)
- return;
-
- /* not sure if this ultimately actually should work,
- but we're not supporting multisampled textures yet. */
- assert(pt->nr_samples < 2);
-
- /* find expected last mipmap level to generate*/
- lastLevel = compute_num_levels(ctx, texObj, target) - 1;
-
- if (lastLevel == 0)
- return;
-
- if (pt->last_level < lastLevel) {
- /* The current gallium texture doesn't have space for all the
- * mipmap levels we need to generate. So allocate a new texture.
- */
- struct pipe_resource *oldTex = stObj->pt;
-
- /* create new texture with space for more levels */
- stObj->pt = st_texture_create(st,
- oldTex->target,
- oldTex->format,
- lastLevel,
- oldTex->width0,
- oldTex->height0,
- oldTex->depth0,
- oldTex->array_size,
- oldTex->bind);
-
- /* The texture isn't in a "complete" state yet so set the expected
- * lastLevel here, since it won't get done in st_finalize_texture().
- */
- stObj->lastLevel = lastLevel;
-
- /* This will copy the old texture's base image into the new texture
- * which we just allocated.
- */
- st_finalize_texture(ctx, st->pipe, texObj);
-
- /* release the old tex (will likely be freed too) */
- pipe_resource_reference(&oldTex, NULL);
- pipe_sampler_view_reference(&stObj->sampler_view, NULL);
-
- pt = stObj->pt;
- }
- else {
- /* Make sure that the base texture image data is present in the
- * texture buffer.
- */
- st_finalize_texture(ctx, st->pipe, texObj);
- }
-
- assert(pt->last_level >= lastLevel);
-
- /* Try to generate the mipmap by rendering/texturing. If that fails,
- * use the software fallback.
- */
- if (!st_render_mipmap(st, target, stObj, baseLevel, lastLevel)) {
- /* since the util code actually also has a fallback, should
- probably make it never fail and kill this */
- fallback_generate_mipmap(ctx, target, texObj);
- }
-
- /* Fill in the Mesa gl_texture_image fields */
- for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
- const uint srcLevel = dstLevel - 1;
- const struct gl_texture_image *srcImage
- = _mesa_get_tex_image(ctx, texObj, target, srcLevel);
- struct gl_texture_image *dstImage;
- struct st_texture_image *stImage;
- uint dstWidth = u_minify(pt->width0, dstLevel);
- uint dstHeight = u_minify(pt->height0, dstLevel);
- uint dstDepth = u_minify(pt->depth0, dstLevel);
- uint border = srcImage->Border;
-
- dstImage = _mesa_get_tex_image(ctx, texObj, target, dstLevel);
- if (!dstImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
- return;
- }
-
- /* Free old image data */
- if (dstImage->Data)
- ctx->Driver.FreeTexImageData(ctx, dstImage);
-
- /* initialize new image */
- _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight,
- dstDepth, border, srcImage->InternalFormat,
- srcImage->TexFormat);
-
- stImage = st_texture_image(dstImage);
- stImage->level = dstLevel;
-
- pipe_resource_reference(&stImage->pt, pt);
- }
-}
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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.
+ *
+ **************************************************************************/
+
+
+#include "main/imports.h"
+#include "main/mipmap.h"
+#include "main/teximage.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "util/u_inlines.h"
+#include "util/u_format.h"
+#include "util/u_gen_mipmap.h"
+
+#include "st_debug.h"
+#include "st_context.h"
+#include "st_texture.h"
+#include "st_gen_mipmap.h"
+#include "st_cb_texture.h"
+
+
+/**
+ * one-time init for generate mipmap
+ * XXX Note: there may be other times we need no-op/simple state like this.
+ * In that case, some code refactoring would be good.
+ */
+void
+st_init_generate_mipmap(struct st_context *st)
+{
+ st->gen_mipmap = util_create_gen_mipmap(st->pipe, st->cso_context);
+}
+
+
+void
+st_destroy_generate_mipmap(struct st_context *st)
+{
+ util_destroy_gen_mipmap(st->gen_mipmap);
+ st->gen_mipmap = NULL;
+}
+
+
+/**
+ * Generate mipmap levels using hardware rendering.
+ * \return TRUE if successful, FALSE if not possible
+ */
+static boolean
+st_render_mipmap(struct st_context *st,
+ GLenum target,
+ struct st_texture_object *stObj,
+ uint baseLevel, uint lastLevel)
+{
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_sampler_view *psv = st_get_texture_sampler_view(stObj, pipe);
+ const uint face = _mesa_tex_target_to_face(target);
+
+ assert(psv->texture == stObj->pt);
+#if 0
+ assert(target != GL_TEXTURE_3D); /* implemented but untested */
+#endif
+
+ /* check if we can render in the texture's format */
+ /* XXX should probably kill this and always use util_gen_mipmap
+ since this implements a sw fallback as well */
+ if (!screen->is_format_supported(screen, psv->format, psv->texture->target,
+ 0, PIPE_BIND_RENDER_TARGET, 0)) {
+ return FALSE;
+ }
+
+ util_gen_mipmap(st->gen_mipmap, psv, face, baseLevel, lastLevel,
+ PIPE_TEX_FILTER_LINEAR);
+
+ return TRUE;
+}
+
+
+/**
+ * Helper function to decompress an image. The result is a 32-bpp RGBA
+ * image with stride==width.
+ */
+static void
+decompress_image(enum pipe_format format,
+ const uint8_t *src, uint8_t *dst,
+ unsigned width, unsigned height, unsigned src_stride)
+{
+ const struct util_format_description *desc = util_format_description(format);
+ const uint bw = util_format_get_blockwidth(format);
+ const uint bh = util_format_get_blockheight(format);
+ const uint dst_stride = 4 * MAX2(width, bw);
+
+ desc->unpack_rgba_8unorm(dst, dst_stride, src, src_stride, width, height);
+
+ if (width < bw || height < bh) {
+ /* We're decompressing an image smaller than the compression
+ * block size. We don't want garbage pixel values in the region
+ * outside (width x height) so replicate pixels from the (width
+ * x height) region to fill out the (bw x bh) block size.
+ */
+ uint x, y;
+ for (y = 0; y < bh; y++) {
+ for (x = 0; x < bw; x++) {
+ if (x >= width || y >= height) {
+ uint p = (y * bw + x) * 4;
+ dst[p + 0] = dst[0];
+ dst[p + 1] = dst[1];
+ dst[p + 2] = dst[2];
+ dst[p + 3] = dst[3];
+ }
+ }
+ }
+ }
+}
+
+
+/**
+ * Helper function to compress an image. The source is a 32-bpp RGBA image
+ * with stride==width.
+ */
+static void
+compress_image(enum pipe_format format,
+ const uint8_t *src, uint8_t *dst,
+ unsigned width, unsigned height, unsigned dst_stride)
+{
+ const struct util_format_description *desc = util_format_description(format);
+ const uint src_stride = 4 * width;
+
+ desc->pack_rgba_8unorm(dst, dst_stride, src, src_stride, width, height);
+}
+
+
+/**
+ * Software fallback for generate mipmap levels.
+ */
+static void
+fallback_generate_mipmap(struct gl_context *ctx, GLenum target,
+ struct gl_texture_object *texObj)
+{
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+ struct pipe_resource *pt = st_get_texobj_resource(texObj);
+ const uint baseLevel = texObj->BaseLevel;
+ const uint lastLevel = pt->last_level;
+ const uint face = _mesa_tex_target_to_face(target);
+ uint dstLevel;
+ GLenum datatype;
+ GLuint comps;
+ GLboolean compressed;
+
+ if (ST_DEBUG & DEBUG_FALLBACK)
+ debug_printf("%s: fallback processing\n", __FUNCTION__);
+
+ assert(target != GL_TEXTURE_3D); /* not done yet */
+
+ compressed =
+ _mesa_is_format_compressed(texObj->Image[face][baseLevel]->TexFormat);
+
+ if (compressed) {
+ datatype = GL_UNSIGNED_BYTE;
+ comps = 4;
+ }
+ else {
+ _mesa_format_to_type_and_comps(texObj->Image[face][baseLevel]->TexFormat,
+ &datatype, &comps);
+ assert(comps > 0 && "bad texture format in fallback_generate_mipmap()");
+ }
+
+ for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
+ const uint srcLevel = dstLevel - 1;
+ const uint srcWidth = u_minify(pt->width0, srcLevel);
+ const uint srcHeight = u_minify(pt->height0, srcLevel);
+ const uint srcDepth = u_minify(pt->depth0, srcLevel);
+ const uint dstWidth = u_minify(pt->width0, dstLevel);
+ const uint dstHeight = u_minify(pt->height0, dstLevel);
+ const uint dstDepth = u_minify(pt->depth0, dstLevel);
+ struct pipe_transfer *srcTrans, *dstTrans;
+ const ubyte *srcData;
+ ubyte *dstData;
+ int srcStride, dstStride;
+
+ srcTrans = pipe_get_transfer(st_context(ctx)->pipe, pt, srcLevel,
+ face,
+ PIPE_TRANSFER_READ, 0, 0,
+ srcWidth, srcHeight);
+
+ dstTrans = pipe_get_transfer(st_context(ctx)->pipe, pt, dstLevel,
+ face,
+ PIPE_TRANSFER_WRITE, 0, 0,
+ dstWidth, dstHeight);
+
+ srcData = (ubyte *) pipe_transfer_map(pipe, srcTrans);
+ dstData = (ubyte *) pipe_transfer_map(pipe, dstTrans);
+
+ srcStride = srcTrans->stride / util_format_get_blocksize(srcTrans->resource->format);
+ dstStride = dstTrans->stride / util_format_get_blocksize(dstTrans->resource->format);
+
+ /* this cannot work correctly for 3d since it does
+ not respect layerStride. */
+ if (compressed) {
+ const enum pipe_format format = pt->format;
+ const uint bw = util_format_get_blockwidth(format);
+ const uint bh = util_format_get_blockheight(format);
+ const uint srcWidth2 = align(srcWidth, bw);
+ const uint srcHeight2 = align(srcHeight, bh);
+ const uint dstWidth2 = align(dstWidth, bw);
+ const uint dstHeight2 = align(dstHeight, bh);
+ uint8_t *srcTemp, *dstTemp;
+
+ assert(comps == 4);
+
+ srcTemp = malloc(srcWidth2 * srcHeight2 * comps + 000);
+ dstTemp = malloc(dstWidth2 * dstHeight2 * comps + 000);
+
+ /* decompress the src image: srcData -> srcTemp */
+ decompress_image(format, srcData, srcTemp, srcWidth, srcHeight, srcTrans->stride);
+
+ _mesa_generate_mipmap_level(target, datatype, comps,
+ 0 /*border*/,
+ srcWidth2, srcHeight2, srcDepth,
+ srcTemp,
+ srcWidth2, /* stride in texels */
+ dstWidth2, dstHeight2, dstDepth,
+ dstTemp,
+ dstWidth2); /* stride in texels */
+
+ /* compress the new image: dstTemp -> dstData */
+ compress_image(format, dstTemp, dstData, dstWidth, dstHeight, dstTrans->stride);
+
+ free(srcTemp);
+ free(dstTemp);
+ }
+ else {
+ _mesa_generate_mipmap_level(target, datatype, comps,
+ 0 /*border*/,
+ srcWidth, srcHeight, srcDepth,
+ srcData,
+ srcStride, /* stride in texels */
+ dstWidth, dstHeight, dstDepth,
+ dstData,
+ dstStride); /* stride in texels */
+ }
+
+ pipe_transfer_unmap(pipe, srcTrans);
+ pipe_transfer_unmap(pipe, dstTrans);
+
+ pipe->transfer_destroy(pipe, srcTrans);
+ pipe->transfer_destroy(pipe, dstTrans);
+ }
+}
+
+
+/**
+ * Compute the expected number of mipmap levels in the texture given
+ * the width/height/depth of the base image and the GL_TEXTURE_BASE_LEVEL/
+ * GL_TEXTURE_MAX_LEVEL settings. This will tell us how many mipmap
+ * levels should be generated.
+ */
+static GLuint
+compute_num_levels(struct gl_context *ctx,
+ struct gl_texture_object *texObj,
+ GLenum target)
+{
+ if (target == GL_TEXTURE_RECTANGLE_ARB) {
+ return 1;
+ }
+ else {
+ const struct gl_texture_image *baseImage =
+ _mesa_get_tex_image(ctx, texObj, target, texObj->BaseLevel);
+ GLuint size, numLevels;
+
+ size = MAX2(baseImage->Width2, baseImage->Height2);
+ size = MAX2(size, baseImage->Depth2);
+
+ numLevels = texObj->BaseLevel;
+
+ while (size > 0) {
+ numLevels++;
+ size >>= 1;
+ }
+
+ numLevels = MIN2(numLevels, texObj->MaxLevel + 1);
+
+ assert(numLevels >= 1);
+
+ return numLevels;
+ }
+}
+
+
+/**
+ * Called via ctx->Driver.GenerateMipmap().
+ */
+void
+st_generate_mipmap(struct gl_context *ctx, GLenum target,
+ struct gl_texture_object *texObj)
+{
+ struct st_context *st = st_context(ctx);
+ struct st_texture_object *stObj = st_texture_object(texObj);
+ struct pipe_resource *pt = st_get_texobj_resource(texObj);
+ const uint baseLevel = texObj->BaseLevel;
+ uint lastLevel;
+ uint dstLevel;
+
+ if (!pt)
+ return;
+
+ /* not sure if this ultimately actually should work,
+ but we're not supporting multisampled textures yet. */
+ assert(pt->nr_samples < 2);
+
+ /* find expected last mipmap level to generate*/
+ lastLevel = compute_num_levels(ctx, texObj, target) - 1;
+
+ if (lastLevel == 0)
+ return;
+
+ if (pt->last_level < lastLevel) {
+ /* The current gallium texture doesn't have space for all the
+ * mipmap levels we need to generate. So allocate a new texture.
+ */
+ struct pipe_resource *oldTex = stObj->pt;
+
+ /* create new texture with space for more levels */
+ stObj->pt = st_texture_create(st,
+ oldTex->target,
+ oldTex->format,
+ lastLevel,
+ oldTex->width0,
+ oldTex->height0,
+ oldTex->depth0,
+ oldTex->array_size,
+ oldTex->bind);
+
+ /* The texture isn't in a "complete" state yet so set the expected
+ * lastLevel here, since it won't get done in st_finalize_texture().
+ */
+ stObj->lastLevel = lastLevel;
+
+ /* This will copy the old texture's base image into the new texture
+ * which we just allocated.
+ */
+ st_finalize_texture(ctx, st->pipe, texObj);
+
+ /* release the old tex (will likely be freed too) */
+ pipe_resource_reference(&oldTex, NULL);
+ pipe_sampler_view_reference(&stObj->sampler_view, NULL);
+
+ pt = stObj->pt;
+ }
+ else {
+ /* Make sure that the base texture image data is present in the
+ * texture buffer.
+ */
+ st_finalize_texture(ctx, st->pipe, texObj);
+ }
+
+ assert(pt->last_level >= lastLevel);
+
+ /* Try to generate the mipmap by rendering/texturing. If that fails,
+ * use the software fallback.
+ */
+ if (!st_render_mipmap(st, target, stObj, baseLevel, lastLevel)) {
+ /* since the util code actually also has a fallback, should
+ probably make it never fail and kill this */
+ fallback_generate_mipmap(ctx, target, texObj);
+ }
+
+ /* Fill in the Mesa gl_texture_image fields */
+ for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
+ const uint srcLevel = dstLevel - 1;
+ const struct gl_texture_image *srcImage
+ = _mesa_get_tex_image(ctx, texObj, target, srcLevel);
+ struct gl_texture_image *dstImage;
+ struct st_texture_image *stImage;
+ uint dstWidth = u_minify(pt->width0, dstLevel);
+ uint dstHeight = u_minify(pt->height0, dstLevel);
+ uint dstDepth = u_minify(pt->depth0, dstLevel);
+ uint border = srcImage->Border;
+
+ dstImage = _mesa_get_tex_image(ctx, texObj, target, dstLevel);
+ if (!dstImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
+ return;
+ }
+
+ /* Free old image data */
+ if (dstImage->Data)
+ ctx->Driver.FreeTexImageData(ctx, dstImage);
+
+ /* initialize new image */
+ _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight,
+ dstDepth, border, srcImage->InternalFormat,
+ srcImage->TexFormat);
+
+ stImage = st_texture_image(dstImage);
+ stImage->level = dstLevel;
+
+ pipe_resource_reference(&stImage->pt, pt);
+ }
+}
diff --git a/mesalib/src/mesa/state_tracker/st_program.c b/mesalib/src/mesa/state_tracker/st_program.c
index fc1dfb3ef..e5c26c563 100644
--- a/mesalib/src/mesa/state_tracker/st_program.c
+++ b/mesalib/src/mesa/state_tracker/st_program.c
@@ -1,1165 +1,1165 @@
-/**************************************************************************
- *
- * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
- * 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.
- *
- **************************************************************************/
- /*
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- * Brian Paul
- */
-
-
-#include "main/imports.h"
-#include "main/hash.h"
-#include "main/mfeatures.h"
-#include "main/mtypes.h"
-#include "program/prog_parameter.h"
-#include "program/prog_print.h"
-#include "program/programopt.h"
-
-#include "pipe/p_context.h"
-#include "pipe/p_defines.h"
-#include "pipe/p_shader_tokens.h"
-#include "draw/draw_context.h"
-#include "tgsi/tgsi_dump.h"
-#include "tgsi/tgsi_ureg.h"
-
-#include "st_debug.h"
-#include "st_cb_bitmap.h"
-#include "st_cb_drawpixels.h"
-#include "st_context.h"
-#include "st_program.h"
-#include "st_mesa_to_tgsi.h"
-#include "cso_cache/cso_context.h"
-
-
-
-/**
- * Delete a vertex program variant. Note the caller must unlink
- * the variant from the linked list.
- */
-static void
-delete_vp_variant(struct st_context *st, struct st_vp_variant *vpv)
-{
- if (vpv->driver_shader)
- cso_delete_vertex_shader(st->cso_context, vpv->driver_shader);
-
-#if FEATURE_feedback || FEATURE_rastpos
- if (vpv->draw_shader)
- draw_delete_vertex_shader( st->draw, vpv->draw_shader );
-#endif
-
- if (vpv->tgsi.tokens)
- st_free_tokens(vpv->tgsi.tokens);
-
- FREE( vpv );
-}
-
-
-
-/**
- * Clean out any old compilations:
- */
-void
-st_release_vp_variants( struct st_context *st,
- struct st_vertex_program *stvp )
-{
- struct st_vp_variant *vpv;
-
- for (vpv = stvp->variants; vpv; ) {
- struct st_vp_variant *next = vpv->next;
- delete_vp_variant(st, vpv);
- vpv = next;
- }
-
- stvp->variants = NULL;
-}
-
-
-
-/**
- * Delete a fragment program variant. Note the caller must unlink
- * the variant from the linked list.
- */
-static void
-delete_fp_variant(struct st_context *st, struct st_fp_variant *fpv)
-{
- if (fpv->driver_shader)
- cso_delete_fragment_shader(st->cso_context, fpv->driver_shader);
- if (fpv->parameters)
- _mesa_free_parameter_list(fpv->parameters);
-
- FREE(fpv);
-}
-
-
-/**
- * Free all variants of a fragment program.
- */
-void
-st_release_fp_variants(struct st_context *st, struct st_fragment_program *stfp)
-{
- struct st_fp_variant *fpv;
-
- for (fpv = stfp->variants; fpv; ) {
- struct st_fp_variant *next = fpv->next;
- delete_fp_variant(st, fpv);
- fpv = next;
- }
-
- stfp->variants = NULL;
-}
-
-
-/**
- * Delete a geometry program variant. Note the caller must unlink
- * the variant from the linked list.
- */
-static void
-delete_gp_variant(struct st_context *st, struct st_gp_variant *gpv)
-{
- if (gpv->driver_shader)
- cso_delete_geometry_shader(st->cso_context, gpv->driver_shader);
-
- FREE(gpv);
-}
-
-
-/**
- * Free all variants of a geometry program.
- */
-void
-st_release_gp_variants(struct st_context *st, struct st_geometry_program *stgp)
-{
- struct st_gp_variant *gpv;
-
- for (gpv = stgp->variants; gpv; ) {
- struct st_gp_variant *next = gpv->next;
- delete_gp_variant(st, gpv);
- gpv = next;
- }
-
- stgp->variants = NULL;
-}
-
-
-
-
-/**
- * Translate a Mesa vertex shader into a TGSI shader.
- * \param outputMapping to map vertex program output registers (VERT_RESULT_x)
- * to TGSI output slots
- * \param tokensOut destination for TGSI tokens
- * \return pointer to cached pipe_shader object.
- */
-static void
-st_prepare_vertex_program(struct st_context *st,
- struct st_vertex_program *stvp)
-{
- GLuint attr;
-
- stvp->num_inputs = 0;
- stvp->num_outputs = 0;
-
- if (stvp->Base.IsPositionInvariant)
- _mesa_insert_mvp_code(st->ctx, &stvp->Base);
-
- assert(stvp->Base.Base.NumInstructions > 1);
-
- /*
- * Determine number of inputs, the mappings between VERT_ATTRIB_x
- * and TGSI generic input indexes, plus input attrib semantic info.
- */
- for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
- if (stvp->Base.Base.InputsRead & (1 << attr)) {
- stvp->input_to_index[attr] = stvp->num_inputs;
- stvp->index_to_input[stvp->num_inputs] = attr;
- stvp->num_inputs++;
- }
- }
- /* bit of a hack, presetup potentially unused edgeflag input */
- stvp->input_to_index[VERT_ATTRIB_EDGEFLAG] = stvp->num_inputs;
- stvp->index_to_input[stvp->num_inputs] = VERT_ATTRIB_EDGEFLAG;
-
- /* Compute mapping of vertex program outputs to slots.
- */
- for (attr = 0; attr < VERT_RESULT_MAX; attr++) {
- if ((stvp->Base.Base.OutputsWritten & BITFIELD64_BIT(attr)) == 0) {
- stvp->result_to_output[attr] = ~0;
- }
- else {
- unsigned slot = stvp->num_outputs++;
-
- stvp->result_to_output[attr] = slot;
-
- switch (attr) {
- case VERT_RESULT_HPOS:
- stvp->output_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
- stvp->output_semantic_index[slot] = 0;
- break;
- case VERT_RESULT_COL0:
- stvp->output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
- stvp->output_semantic_index[slot] = 0;
- break;
- case VERT_RESULT_COL1:
- stvp->output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
- stvp->output_semantic_index[slot] = 1;
- break;
- case VERT_RESULT_BFC0:
- stvp->output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
- stvp->output_semantic_index[slot] = 0;
- break;
- case VERT_RESULT_BFC1:
- stvp->output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
- stvp->output_semantic_index[slot] = 1;
- break;
- case VERT_RESULT_FOGC:
- stvp->output_semantic_name[slot] = TGSI_SEMANTIC_FOG;
- stvp->output_semantic_index[slot] = 0;
- break;
- case VERT_RESULT_PSIZ:
- stvp->output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
- stvp->output_semantic_index[slot] = 0;
- break;
- case VERT_RESULT_EDGE:
- assert(0);
- break;
-
- case VERT_RESULT_TEX0:
- case VERT_RESULT_TEX1:
- case VERT_RESULT_TEX2:
- case VERT_RESULT_TEX3:
- case VERT_RESULT_TEX4:
- case VERT_RESULT_TEX5:
- case VERT_RESULT_TEX6:
- case VERT_RESULT_TEX7:
- stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
- stvp->output_semantic_index[slot] = attr - VERT_RESULT_TEX0;
- break;
-
- case VERT_RESULT_VAR0:
- default:
- assert(attr < VERT_RESULT_MAX);
- stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
- stvp->output_semantic_index[slot] = (FRAG_ATTRIB_VAR0 -
- FRAG_ATTRIB_TEX0 +
- attr -
- VERT_RESULT_VAR0);
- break;
- }
- }
- }
- /* similar hack to above, presetup potentially unused edgeflag output */
- stvp->result_to_output[VERT_RESULT_EDGE] = stvp->num_outputs;
- stvp->output_semantic_name[stvp->num_outputs] = TGSI_SEMANTIC_EDGEFLAG;
- stvp->output_semantic_index[stvp->num_outputs] = 0;
-}
-
-
-/**
- * Translate a vertex program to create a new variant.
- */
-static struct st_vp_variant *
-st_translate_vertex_program(struct st_context *st,
- struct st_vertex_program *stvp,
- const struct st_vp_variant_key *key)
-{
- struct st_vp_variant *vpv = CALLOC_STRUCT(st_vp_variant);
- struct pipe_context *pipe = st->pipe;
- struct ureg_program *ureg;
- enum pipe_error error;
- unsigned num_outputs;
-
- st_prepare_vertex_program( st, stvp );
-
- _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_OUTPUT);
- _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_VARYING);
-
- ureg = ureg_create( TGSI_PROCESSOR_VERTEX );
- if (ureg == NULL) {
- FREE(vpv);
- return NULL;
- }
-
- vpv->key = *key;
-
- vpv->num_inputs = stvp->num_inputs;
- num_outputs = stvp->num_outputs;
- if (key->passthrough_edgeflags) {
- vpv->num_inputs++;
- num_outputs++;
- }
-
- if (ST_DEBUG & DEBUG_MESA) {
- _mesa_print_program(&stvp->Base.Base);
- _mesa_print_program_parameters(st->ctx, &stvp->Base.Base);
- debug_printf("\n");
- }
-
- error = st_translate_mesa_program(st->ctx,
- TGSI_PROCESSOR_VERTEX,
- ureg,
- &stvp->Base.Base,
- /* inputs */
- vpv->num_inputs,
- stvp->input_to_index,
- NULL, /* input semantic name */
- NULL, /* input semantic index */
- NULL,
- /* outputs */
- num_outputs,
- stvp->result_to_output,
- stvp->output_semantic_name,
- stvp->output_semantic_index,
- key->passthrough_edgeflags );
-
- if (error)
- goto fail;
-
- vpv->tgsi.tokens = ureg_get_tokens( ureg, NULL );
- if (!vpv->tgsi.tokens)
- goto fail;
-
- ureg_destroy( ureg );
-
- vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->tgsi);
-
- if (ST_DEBUG & DEBUG_TGSI) {
- tgsi_dump( vpv->tgsi.tokens, 0 );
- debug_printf("\n");
- }
-
- return vpv;
-
-fail:
- debug_printf("%s: failed to translate Mesa program:\n", __FUNCTION__);
- _mesa_print_program(&stvp->Base.Base);
- debug_assert(0);
-
- ureg_destroy( ureg );
- return NULL;
-}
-
-
-/**
- * Find/create a vertex program variant.
- */
-struct st_vp_variant *
-st_get_vp_variant(struct st_context *st,
- struct st_vertex_program *stvp,
- const struct st_vp_variant_key *key)
-{
- struct st_vp_variant *vpv;
-
- /* Search for existing variant */
- for (vpv = stvp->variants; vpv; vpv = vpv->next) {
- if (memcmp(&vpv->key, key, sizeof(*key)) == 0) {
- break;
- }
- }
-
- if (!vpv) {
- /* create now */
- vpv = st_translate_vertex_program(st, stvp, key);
- if (vpv) {
- /* insert into list */
- vpv->next = stvp->variants;
- stvp->variants = vpv;
- }
- }
-
- return vpv;
-}
-
-
-/**
- * Translate a Mesa fragment shader into a TGSI shader using extra info in
- * the key.
- * \return new fragment program variant
- */
-static struct st_fp_variant *
-st_translate_fragment_program(struct st_context *st,
- struct st_fragment_program *stfp,
- const struct st_fp_variant_key *key)
-{
- struct pipe_context *pipe = st->pipe;
- struct st_fp_variant *variant = CALLOC_STRUCT(st_fp_variant);
- GLboolean deleteFP = GL_FALSE;
-
- if (!variant)
- return NULL;
-
- assert(!(key->bitmap && key->drawpixels));
-
-#if FEATURE_drawpix
- if (key->bitmap) {
- /* glBitmap drawing */
- struct gl_fragment_program *fp; /* we free this temp program below */
-
- st_make_bitmap_fragment_program(st, &stfp->Base,
- &fp, &variant->bitmap_sampler);
-
- variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters);
- stfp = st_fragment_program(fp);
- deleteFP = GL_TRUE;
- }
- else if (key->drawpixels) {
- /* glDrawPixels drawing */
- struct gl_fragment_program *fp; /* we free this temp program below */
-
- if (key->drawpixels_z || key->drawpixels_stencil) {
- fp = st_make_drawpix_z_stencil_program(st, key->drawpixels_z,
- key->drawpixels_stencil);
- }
- else {
- /* RGBA */
- st_make_drawpix_fragment_program(st, &stfp->Base, &fp);
- variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters);
- deleteFP = GL_TRUE;
- }
- stfp = st_fragment_program(fp);
- }
-#endif
-
- if (!stfp->tgsi.tokens) {
- /* need to translate Mesa instructions to TGSI now */
- GLuint outputMapping[FRAG_RESULT_MAX];
- GLuint inputMapping[FRAG_ATTRIB_MAX];
- GLuint interpMode[PIPE_MAX_SHADER_INPUTS]; /* XXX size? */
- GLuint attr;
- enum pipe_error error;
- const GLbitfield inputsRead = stfp->Base.Base.InputsRead;
- struct ureg_program *ureg;
- GLboolean write_all = GL_FALSE;
-
- ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS];
- ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS];
- uint fs_num_inputs = 0;
-
- ubyte fs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
- ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
- uint fs_num_outputs = 0;
-
-
- _mesa_remove_output_reads(&stfp->Base.Base, PROGRAM_OUTPUT);
-
- /*
- * Convert Mesa program inputs to TGSI input register semantics.
- */
- for (attr = 0; attr < FRAG_ATTRIB_MAX; attr++) {
- if (inputsRead & (1 << attr)) {
- const GLuint slot = fs_num_inputs++;
-
- inputMapping[attr] = slot;
-
- switch (attr) {
- case FRAG_ATTRIB_WPOS:
- input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
- input_semantic_index[slot] = 0;
- interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
- break;
- case FRAG_ATTRIB_COL0:
- input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
- input_semantic_index[slot] = 0;
- interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
- break;
- case FRAG_ATTRIB_COL1:
- input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
- input_semantic_index[slot] = 1;
- interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
- break;
- case FRAG_ATTRIB_FOGC:
- input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
- input_semantic_index[slot] = 0;
- interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
- break;
- case FRAG_ATTRIB_FACE:
- input_semantic_name[slot] = TGSI_SEMANTIC_FACE;
- input_semantic_index[slot] = 0;
- interpMode[slot] = TGSI_INTERPOLATE_CONSTANT;
- break;
- /* In most cases, there is nothing special about these
- * inputs, so adopt a convention to use the generic
- * semantic name and the mesa FRAG_ATTRIB_ number as the
- * index.
- *
- * All that is required is that the vertex shader labels
- * its own outputs similarly, and that the vertex shader
- * generates at least every output required by the
- * fragment shader plus fixed-function hardware (such as
- * BFC).
- *
- * There is no requirement that semantic indexes start at
- * zero or be restricted to a particular range -- nobody
- * should be building tables based on semantic index.
- */
- case FRAG_ATTRIB_PNTC:
- case FRAG_ATTRIB_TEX0:
- case FRAG_ATTRIB_TEX1:
- case FRAG_ATTRIB_TEX2:
- case FRAG_ATTRIB_TEX3:
- case FRAG_ATTRIB_TEX4:
- case FRAG_ATTRIB_TEX5:
- case FRAG_ATTRIB_TEX6:
- case FRAG_ATTRIB_TEX7:
- case FRAG_ATTRIB_VAR0:
- default:
- /* Actually, let's try and zero-base this just for
- * readability of the generated TGSI.
- */
- assert(attr >= FRAG_ATTRIB_TEX0);
- input_semantic_index[slot] = (attr - FRAG_ATTRIB_TEX0);
- input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
- if (attr == FRAG_ATTRIB_PNTC)
- interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
- else
- interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
- break;
- }
- }
- else {
- inputMapping[attr] = -1;
- }
- }
-
- /*
- * Semantics and mapping for outputs
- */
- {
- uint numColors = 0;
- GLbitfield64 outputsWritten = stfp->Base.Base.OutputsWritten;
-
- /* if z is written, emit that first */
- if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) {
- fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_POSITION;
- fs_output_semantic_index[fs_num_outputs] = 0;
- outputMapping[FRAG_RESULT_DEPTH] = fs_num_outputs;
- fs_num_outputs++;
- outputsWritten &= ~(1 << FRAG_RESULT_DEPTH);
- }
-
- if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_STENCIL)) {
- fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_STENCIL;
- fs_output_semantic_index[fs_num_outputs] = 0;
- outputMapping[FRAG_RESULT_STENCIL] = fs_num_outputs;
- fs_num_outputs++;
- outputsWritten &= ~(1 << FRAG_RESULT_STENCIL);
- }
-
- /* handle remaning outputs (color) */
- for (attr = 0; attr < FRAG_RESULT_MAX; attr++) {
- if (outputsWritten & BITFIELD64_BIT(attr)) {
- switch (attr) {
- case FRAG_RESULT_DEPTH:
- case FRAG_RESULT_STENCIL:
- /* handled above */
- assert(0);
- break;
- case FRAG_RESULT_COLOR:
- write_all = GL_TRUE; /* fallthrough */
- default:
- assert(attr == FRAG_RESULT_COLOR ||
- (FRAG_RESULT_DATA0 <= attr && attr < FRAG_RESULT_MAX));
- fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_COLOR;
- fs_output_semantic_index[fs_num_outputs] = numColors;
- outputMapping[attr] = fs_num_outputs;
- numColors++;
- break;
- }
-
- fs_num_outputs++;
- }
- }
- }
-
- ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
- if (ureg == NULL)
- return NULL;
-
- if (ST_DEBUG & DEBUG_MESA) {
- _mesa_print_program(&stfp->Base.Base);
- _mesa_print_program_parameters(st->ctx, &stfp->Base.Base);
- debug_printf("\n");
- }
- if (write_all == GL_TRUE)
- ureg_property_fs_color0_writes_all_cbufs(ureg, 1);
-
- error = st_translate_mesa_program(st->ctx,
- TGSI_PROCESSOR_FRAGMENT,
- ureg,
- &stfp->Base.Base,
- /* inputs */
- fs_num_inputs,
- inputMapping,
- input_semantic_name,
- input_semantic_index,
- interpMode,
- /* outputs */
- fs_num_outputs,
- outputMapping,
- fs_output_semantic_name,
- fs_output_semantic_index, FALSE );
-
- stfp->tgsi.tokens = ureg_get_tokens( ureg, NULL );
- ureg_destroy( ureg );
- }
-
- /* fill in variant */
- variant->driver_shader = pipe->create_fs_state(pipe, &stfp->tgsi);
- variant->key = *key;
-
- if (ST_DEBUG & DEBUG_TGSI) {
- tgsi_dump( stfp->tgsi.tokens, 0/*TGSI_DUMP_VERBOSE*/ );
- debug_printf("\n");
- }
-
- if (deleteFP) {
- /* Free the temporary program made above */
- struct gl_fragment_program *fp = &stfp->Base;
- _mesa_reference_fragprog(st->ctx, &fp, NULL);
- }
-
- return variant;
-}
-
-
-/**
- * Translate fragment program if needed.
- */
-struct st_fp_variant *
-st_get_fp_variant(struct st_context *st,
- struct st_fragment_program *stfp,
- const struct st_fp_variant_key *key)
-{
- struct st_fp_variant *fpv;
-
- /* Search for existing variant */
- for (fpv = stfp->variants; fpv; fpv = fpv->next) {
- if (memcmp(&fpv->key, key, sizeof(*key)) == 0) {
- break;
- }
- }
-
- if (!fpv) {
- /* create new */
- fpv = st_translate_fragment_program(st, stfp, key);
- if (fpv) {
- /* insert into list */
- fpv->next = stfp->variants;
- stfp->variants = fpv;
- }
- }
-
- return fpv;
-}
-
-
-/**
- * Translate a geometry program to create a new variant.
- */
-static struct st_gp_variant *
-st_translate_geometry_program(struct st_context *st,
- struct st_geometry_program *stgp,
- const struct st_gp_variant_key *key)
-{
- GLuint inputMapping[GEOM_ATTRIB_MAX];
- GLuint outputMapping[GEOM_RESULT_MAX];
- struct pipe_context *pipe = st->pipe;
- enum pipe_error error;
- GLuint attr;
- const GLbitfield inputsRead = stgp->Base.Base.InputsRead;
- GLuint vslot = 0;
- GLuint num_generic = 0;
-
- uint gs_num_inputs = 0;
- uint gs_builtin_inputs = 0;
- uint gs_array_offset = 0;
-
- ubyte gs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
- ubyte gs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
- uint gs_num_outputs = 0;
-
- GLint i;
- GLuint maxSlot = 0;
- struct ureg_program *ureg;
-
- struct st_gp_variant *gpv;
-
- gpv = CALLOC_STRUCT(st_gp_variant);
- if (!gpv)
- return NULL;
-
- _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_OUTPUT);
- _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_VARYING);
-
- ureg = ureg_create( TGSI_PROCESSOR_GEOMETRY );
- if (ureg == NULL) {
- FREE(gpv);
- return NULL;
- }
-
- /* which vertex output goes to the first geometry input */
- vslot = 0;
-
- memset(inputMapping, 0, sizeof(inputMapping));
- memset(outputMapping, 0, sizeof(outputMapping));
-
- /*
- * Convert Mesa program inputs to TGSI input register semantics.
- */
- for (attr = 0; attr < GEOM_ATTRIB_MAX; attr++) {
- if (inputsRead & (1 << attr)) {
- const GLuint slot = gs_num_inputs;
-
- gs_num_inputs++;
-
- inputMapping[attr] = slot;
-
- stgp->input_map[slot + gs_array_offset] = vslot - gs_builtin_inputs;
- stgp->input_to_index[attr] = vslot;
- stgp->index_to_input[vslot] = attr;
- ++vslot;
-
- if (attr != GEOM_ATTRIB_PRIMITIVE_ID) {
- gs_array_offset += 2;
- } else
- ++gs_builtin_inputs;
-
-#if 0
- debug_printf("input map at %d = %d\n",
- slot + gs_array_offset, stgp->input_map[slot + gs_array_offset]);
-#endif
-
- switch (attr) {
- case GEOM_ATTRIB_PRIMITIVE_ID:
- stgp->input_semantic_name[slot] = TGSI_SEMANTIC_PRIMID;
- stgp->input_semantic_index[slot] = 0;
- break;
- case GEOM_ATTRIB_POSITION:
- stgp->input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
- stgp->input_semantic_index[slot] = 0;
- break;
- case GEOM_ATTRIB_COLOR0:
- stgp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
- stgp->input_semantic_index[slot] = 0;
- break;
- case GEOM_ATTRIB_COLOR1:
- stgp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
- stgp->input_semantic_index[slot] = 1;
- break;
- case GEOM_ATTRIB_FOG_FRAG_COORD:
- stgp->input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
- stgp->input_semantic_index[slot] = 0;
- break;
- case GEOM_ATTRIB_TEX_COORD:
- stgp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
- stgp->input_semantic_index[slot] = num_generic++;
- break;
- case GEOM_ATTRIB_VAR0:
- /* fall-through */
- default:
- stgp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
- stgp->input_semantic_index[slot] = num_generic++;
- }
- }
- }
-
- /* initialize output semantics to defaults */
- for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) {
- gs_output_semantic_name[i] = TGSI_SEMANTIC_GENERIC;
- gs_output_semantic_index[i] = 0;
- }
-
- num_generic = 0;
- /*
- * Determine number of outputs, the (default) output register
- * mapping and the semantic information for each output.
- */
- for (attr = 0; attr < GEOM_RESULT_MAX; attr++) {
- if (stgp->Base.Base.OutputsWritten & (1 << attr)) {
- GLuint slot;
-
- slot = gs_num_outputs;
- gs_num_outputs++;
- outputMapping[attr] = slot;
-
- switch (attr) {
- case GEOM_RESULT_POS:
- assert(slot == 0);
- gs_output_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
- gs_output_semantic_index[slot] = 0;
- break;
- case GEOM_RESULT_COL0:
- gs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
- gs_output_semantic_index[slot] = 0;
- break;
- case GEOM_RESULT_COL1:
- gs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
- gs_output_semantic_index[slot] = 1;
- break;
- case GEOM_RESULT_SCOL0:
- gs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
- gs_output_semantic_index[slot] = 0;
- break;
- case GEOM_RESULT_SCOL1:
- gs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
- gs_output_semantic_index[slot] = 1;
- break;
- case GEOM_RESULT_FOGC:
- gs_output_semantic_name[slot] = TGSI_SEMANTIC_FOG;
- gs_output_semantic_index[slot] = 0;
- break;
- case GEOM_RESULT_PSIZ:
- gs_output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
- gs_output_semantic_index[slot] = 0;
- break;
- case GEOM_RESULT_TEX0:
- case GEOM_RESULT_TEX1:
- case GEOM_RESULT_TEX2:
- case GEOM_RESULT_TEX3:
- case GEOM_RESULT_TEX4:
- case GEOM_RESULT_TEX5:
- case GEOM_RESULT_TEX6:
- case GEOM_RESULT_TEX7:
- /* fall-through */
- case GEOM_RESULT_VAR0:
- /* fall-through */
- default:
- assert(slot < Elements(gs_output_semantic_name));
- /* use default semantic info */
- gs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
- gs_output_semantic_index[slot] = num_generic++;
- }
- }
- }
-
- assert(gs_output_semantic_name[0] == TGSI_SEMANTIC_POSITION);
-
- /* find max output slot referenced to compute gs_num_outputs */
- for (attr = 0; attr < GEOM_RESULT_MAX; attr++) {
- if (outputMapping[attr] != ~0 && outputMapping[attr] > maxSlot)
- maxSlot = outputMapping[attr];
- }
- gs_num_outputs = maxSlot + 1;
-
-#if 0 /* debug */
- {
- GLuint i;
- printf("outputMapping? %d\n", outputMapping ? 1 : 0);
- if (outputMapping) {
- printf("attr -> slot\n");
- for (i = 0; i < 16; i++) {
- printf(" %2d %3d\n", i, outputMapping[i]);
- }
- }
- printf("slot sem_name sem_index\n");
- for (i = 0; i < gs_num_outputs; i++) {
- printf(" %2d %d %d\n",
- i,
- gs_output_semantic_name[i],
- gs_output_semantic_index[i]);
- }
- }
-#endif
-
- /* free old shader state, if any */
- if (stgp->tgsi.tokens) {
- st_free_tokens(stgp->tgsi.tokens);
- stgp->tgsi.tokens = NULL;
- }
-
- ureg_property_gs_input_prim(ureg, stgp->Base.InputType);
- ureg_property_gs_output_prim(ureg, stgp->Base.OutputType);
- ureg_property_gs_max_vertices(ureg, stgp->Base.VerticesOut);
-
- error = st_translate_mesa_program(st->ctx,
- TGSI_PROCESSOR_GEOMETRY,
- ureg,
- &stgp->Base.Base,
- /* inputs */
- gs_num_inputs,
- inputMapping,
- stgp->input_semantic_name,
- stgp->input_semantic_index,
- NULL,
- /* outputs */
- gs_num_outputs,
- outputMapping,
- gs_output_semantic_name,
- gs_output_semantic_index,
- FALSE);
-
- stgp->num_inputs = gs_num_inputs;
- stgp->tgsi.tokens = ureg_get_tokens( ureg, NULL );
- ureg_destroy( ureg );
-
- /* fill in new variant */
- gpv->driver_shader = pipe->create_gs_state(pipe, &stgp->tgsi);
- gpv->key = *key;
-
- if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) {
- _mesa_print_program(&stgp->Base.Base);
- debug_printf("\n");
- }
-
- if (ST_DEBUG & DEBUG_TGSI) {
- tgsi_dump(stgp->tgsi.tokens, 0);
- debug_printf("\n");
- }
-
- return gpv;
-}
-
-
-/**
- * Get/create geometry program variant.
- */
-struct st_gp_variant *
-st_get_gp_variant(struct st_context *st,
- struct st_geometry_program *stgp,
- const struct st_gp_variant_key *key)
-{
- struct st_gp_variant *gpv;
-
- /* Search for existing variant */
- for (gpv = stgp->variants; gpv; gpv = gpv->next) {
- if (memcmp(&gpv->key, key, sizeof(*key)) == 0) {
- break;
- }
- }
-
- if (!gpv) {
- /* create new */
- gpv = st_translate_geometry_program(st, stgp, key);
- if (gpv) {
- /* insert into list */
- gpv->next = stgp->variants;
- stgp->variants = gpv;
- }
- }
-
- return gpv;
-}
-
-
-
-
-/**
- * Debug- print current shader text
- */
-void
-st_print_shaders(struct gl_context *ctx)
-{
- struct gl_shader_program *shProg[3] = {
- ctx->Shader.CurrentVertexProgram,
- ctx->Shader.CurrentGeometryProgram,
- ctx->Shader.CurrentFragmentProgram,
- };
- unsigned j;
-
- for (j = 0; j < 3; j++) {
- unsigned i;
-
- if (shProg[j] == NULL)
- continue;
-
- for (i = 0; i < shProg[j]->NumShaders; i++) {
- struct gl_shader *sh;
-
- switch (shProg[j]->Shaders[i]->Type) {
- case GL_VERTEX_SHADER:
- sh = (i != 0) ? NULL : shProg[j]->Shaders[i];
- break;
- case GL_GEOMETRY_SHADER_ARB:
- sh = (i != 1) ? NULL : shProg[j]->Shaders[i];
- break;
- case GL_FRAGMENT_SHADER:
- sh = (i != 2) ? NULL : shProg[j]->Shaders[i];
- break;
- default:
- assert(0);
- sh = NULL;
- break;
- }
-
- if (sh != NULL) {
- printf("GLSL shader %u of %u:\n", i, shProg[j]->NumShaders);
- printf("%s\n", sh->Source);
- }
- }
- }
-}
-
-
-/**
- * Vert/Geom/Frag programs have per-context variants. Free all the
- * variants attached to the given program which match the given context.
- */
-static void
-destroy_program_variants(struct st_context *st, struct gl_program *program)
-{
- if (!program)
- return;
-
- switch (program->Target) {
- case GL_VERTEX_PROGRAM_ARB:
- {
- struct st_vertex_program *stvp = (struct st_vertex_program *) program;
- struct st_vp_variant *vpv, **prevPtr = &stvp->variants;
-
- for (vpv = stvp->variants; vpv; ) {
- struct st_vp_variant *next = vpv->next;
- if (vpv->key.st == st) {
- /* unlink from list */
- *prevPtr = next;
- /* destroy this variant */
- delete_vp_variant(st, vpv);
- }
- else {
- prevPtr = &vpv->next;
- }
- vpv = next;
- }
- }
- break;
- case GL_FRAGMENT_PROGRAM_ARB:
- {
- struct st_fragment_program *stfp =
- (struct st_fragment_program *) program;
- struct st_fp_variant *fpv, **prevPtr = &stfp->variants;
-
- for (fpv = stfp->variants; fpv; ) {
- struct st_fp_variant *next = fpv->next;
- if (fpv->key.st == st) {
- /* unlink from list */
- *prevPtr = next;
- /* destroy this variant */
- delete_fp_variant(st, fpv);
- }
- else {
- prevPtr = &fpv->next;
- }
- fpv = next;
- }
- }
- break;
- case MESA_GEOMETRY_PROGRAM:
- {
- struct st_geometry_program *stgp =
- (struct st_geometry_program *) program;
- struct st_gp_variant *gpv, **prevPtr = &stgp->variants;
-
- for (gpv = stgp->variants; gpv; ) {
- struct st_gp_variant *next = gpv->next;
- if (gpv->key.st == st) {
- /* unlink from list */
- *prevPtr = next;
- /* destroy this variant */
- delete_gp_variant(st, gpv);
- }
- else {
- prevPtr = &gpv->next;
- }
- gpv = next;
- }
- }
- break;
- default:
- _mesa_problem(NULL, "Unexpected program target in "
- "destroy_program_variants_cb()");
- }
-}
-
-
-/**
- * Callback for _mesa_HashWalk. Free all the shader's program variants
- * which match the given context.
- */
-static void
-destroy_shader_program_variants_cb(GLuint key, void *data, void *userData)
-{
- struct st_context *st = (struct st_context *) userData;
- struct gl_shader *shader = (struct gl_shader *) data;
-
- switch (shader->Type) {
- case GL_SHADER_PROGRAM_MESA:
- {
- struct gl_shader_program *shProg = (struct gl_shader_program *) data;
- GLuint i;
-
- for (i = 0; i < shProg->NumShaders; i++) {
- destroy_program_variants(st, shProg->Shaders[i]->Program);
- }
-
- destroy_program_variants(st, (struct gl_program *)
- shProg->VertexProgram);
- destroy_program_variants(st, (struct gl_program *)
- shProg->FragmentProgram);
- destroy_program_variants(st, (struct gl_program *)
- shProg->GeometryProgram);
- }
- break;
- case GL_VERTEX_SHADER:
- case GL_FRAGMENT_SHADER:
- case GL_GEOMETRY_SHADER:
- {
- destroy_program_variants(st, shader->Program);
- }
- break;
- default:
- assert(0);
- }
-}
-
-
-/**
- * Callback for _mesa_HashWalk. Free all the program variants which match
- * the given context.
- */
-static void
-destroy_program_variants_cb(GLuint key, void *data, void *userData)
-{
- struct st_context *st = (struct st_context *) userData;
- struct gl_program *program = (struct gl_program *) data;
- destroy_program_variants(st, program);
-}
-
-
-/**
- * Walk over all shaders and programs to delete any variants which
- * belong to the given context.
- * This is called during context tear-down.
- */
-void
-st_destroy_program_variants(struct st_context *st)
-{
- /* ARB vert/frag program */
- _mesa_HashWalk(st->ctx->Shared->Programs,
- destroy_program_variants_cb, st);
-
- /* GLSL vert/frag/geom shaders */
- _mesa_HashWalk(st->ctx->Shared->ShaderObjects,
- destroy_shader_program_variants_cb, st);
-}
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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.
+ *
+ **************************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Brian Paul
+ */
+
+
+#include "main/imports.h"
+#include "main/hash.h"
+#include "main/mfeatures.h"
+#include "main/mtypes.h"
+#include "program/prog_parameter.h"
+#include "program/prog_print.h"
+#include "program/programopt.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_shader_tokens.h"
+#include "draw/draw_context.h"
+#include "tgsi/tgsi_dump.h"
+#include "tgsi/tgsi_ureg.h"
+
+#include "st_debug.h"
+#include "st_cb_bitmap.h"
+#include "st_cb_drawpixels.h"
+#include "st_context.h"
+#include "st_program.h"
+#include "st_mesa_to_tgsi.h"
+#include "cso_cache/cso_context.h"
+
+
+
+/**
+ * Delete a vertex program variant. Note the caller must unlink
+ * the variant from the linked list.
+ */
+static void
+delete_vp_variant(struct st_context *st, struct st_vp_variant *vpv)
+{
+ if (vpv->driver_shader)
+ cso_delete_vertex_shader(st->cso_context, vpv->driver_shader);
+
+#if FEATURE_feedback || FEATURE_rastpos
+ if (vpv->draw_shader)
+ draw_delete_vertex_shader( st->draw, vpv->draw_shader );
+#endif
+
+ if (vpv->tgsi.tokens)
+ st_free_tokens(vpv->tgsi.tokens);
+
+ FREE( vpv );
+}
+
+
+
+/**
+ * Clean out any old compilations:
+ */
+void
+st_release_vp_variants( struct st_context *st,
+ struct st_vertex_program *stvp )
+{
+ struct st_vp_variant *vpv;
+
+ for (vpv = stvp->variants; vpv; ) {
+ struct st_vp_variant *next = vpv->next;
+ delete_vp_variant(st, vpv);
+ vpv = next;
+ }
+
+ stvp->variants = NULL;
+}
+
+
+
+/**
+ * Delete a fragment program variant. Note the caller must unlink
+ * the variant from the linked list.
+ */
+static void
+delete_fp_variant(struct st_context *st, struct st_fp_variant *fpv)
+{
+ if (fpv->driver_shader)
+ cso_delete_fragment_shader(st->cso_context, fpv->driver_shader);
+ if (fpv->parameters)
+ _mesa_free_parameter_list(fpv->parameters);
+
+ FREE(fpv);
+}
+
+
+/**
+ * Free all variants of a fragment program.
+ */
+void
+st_release_fp_variants(struct st_context *st, struct st_fragment_program *stfp)
+{
+ struct st_fp_variant *fpv;
+
+ for (fpv = stfp->variants; fpv; ) {
+ struct st_fp_variant *next = fpv->next;
+ delete_fp_variant(st, fpv);
+ fpv = next;
+ }
+
+ stfp->variants = NULL;
+}
+
+
+/**
+ * Delete a geometry program variant. Note the caller must unlink
+ * the variant from the linked list.
+ */
+static void
+delete_gp_variant(struct st_context *st, struct st_gp_variant *gpv)
+{
+ if (gpv->driver_shader)
+ cso_delete_geometry_shader(st->cso_context, gpv->driver_shader);
+
+ FREE(gpv);
+}
+
+
+/**
+ * Free all variants of a geometry program.
+ */
+void
+st_release_gp_variants(struct st_context *st, struct st_geometry_program *stgp)
+{
+ struct st_gp_variant *gpv;
+
+ for (gpv = stgp->variants; gpv; ) {
+ struct st_gp_variant *next = gpv->next;
+ delete_gp_variant(st, gpv);
+ gpv = next;
+ }
+
+ stgp->variants = NULL;
+}
+
+
+
+
+/**
+ * Translate a Mesa vertex shader into a TGSI shader.
+ * \param outputMapping to map vertex program output registers (VERT_RESULT_x)
+ * to TGSI output slots
+ * \param tokensOut destination for TGSI tokens
+ * \return pointer to cached pipe_shader object.
+ */
+static void
+st_prepare_vertex_program(struct st_context *st,
+ struct st_vertex_program *stvp)
+{
+ GLuint attr;
+
+ stvp->num_inputs = 0;
+ stvp->num_outputs = 0;
+
+ if (stvp->Base.IsPositionInvariant)
+ _mesa_insert_mvp_code(st->ctx, &stvp->Base);
+
+ assert(stvp->Base.Base.NumInstructions > 1);
+
+ /*
+ * Determine number of inputs, the mappings between VERT_ATTRIB_x
+ * and TGSI generic input indexes, plus input attrib semantic info.
+ */
+ for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
+ if (stvp->Base.Base.InputsRead & (1 << attr)) {
+ stvp->input_to_index[attr] = stvp->num_inputs;
+ stvp->index_to_input[stvp->num_inputs] = attr;
+ stvp->num_inputs++;
+ }
+ }
+ /* bit of a hack, presetup potentially unused edgeflag input */
+ stvp->input_to_index[VERT_ATTRIB_EDGEFLAG] = stvp->num_inputs;
+ stvp->index_to_input[stvp->num_inputs] = VERT_ATTRIB_EDGEFLAG;
+
+ /* Compute mapping of vertex program outputs to slots.
+ */
+ for (attr = 0; attr < VERT_RESULT_MAX; attr++) {
+ if ((stvp->Base.Base.OutputsWritten & BITFIELD64_BIT(attr)) == 0) {
+ stvp->result_to_output[attr] = ~0;
+ }
+ else {
+ unsigned slot = stvp->num_outputs++;
+
+ stvp->result_to_output[attr] = slot;
+
+ switch (attr) {
+ case VERT_RESULT_HPOS:
+ stvp->output_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
+ stvp->output_semantic_index[slot] = 0;
+ break;
+ case VERT_RESULT_COL0:
+ stvp->output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+ stvp->output_semantic_index[slot] = 0;
+ break;
+ case VERT_RESULT_COL1:
+ stvp->output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+ stvp->output_semantic_index[slot] = 1;
+ break;
+ case VERT_RESULT_BFC0:
+ stvp->output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
+ stvp->output_semantic_index[slot] = 0;
+ break;
+ case VERT_RESULT_BFC1:
+ stvp->output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
+ stvp->output_semantic_index[slot] = 1;
+ break;
+ case VERT_RESULT_FOGC:
+ stvp->output_semantic_name[slot] = TGSI_SEMANTIC_FOG;
+ stvp->output_semantic_index[slot] = 0;
+ break;
+ case VERT_RESULT_PSIZ:
+ stvp->output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
+ stvp->output_semantic_index[slot] = 0;
+ break;
+ case VERT_RESULT_EDGE:
+ assert(0);
+ break;
+
+ case VERT_RESULT_TEX0:
+ case VERT_RESULT_TEX1:
+ case VERT_RESULT_TEX2:
+ case VERT_RESULT_TEX3:
+ case VERT_RESULT_TEX4:
+ case VERT_RESULT_TEX5:
+ case VERT_RESULT_TEX6:
+ case VERT_RESULT_TEX7:
+ stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ stvp->output_semantic_index[slot] = attr - VERT_RESULT_TEX0;
+ break;
+
+ case VERT_RESULT_VAR0:
+ default:
+ assert(attr < VERT_RESULT_MAX);
+ stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ stvp->output_semantic_index[slot] = (FRAG_ATTRIB_VAR0 -
+ FRAG_ATTRIB_TEX0 +
+ attr -
+ VERT_RESULT_VAR0);
+ break;
+ }
+ }
+ }
+ /* similar hack to above, presetup potentially unused edgeflag output */
+ stvp->result_to_output[VERT_RESULT_EDGE] = stvp->num_outputs;
+ stvp->output_semantic_name[stvp->num_outputs] = TGSI_SEMANTIC_EDGEFLAG;
+ stvp->output_semantic_index[stvp->num_outputs] = 0;
+}
+
+
+/**
+ * Translate a vertex program to create a new variant.
+ */
+static struct st_vp_variant *
+st_translate_vertex_program(struct st_context *st,
+ struct st_vertex_program *stvp,
+ const struct st_vp_variant_key *key)
+{
+ struct st_vp_variant *vpv = CALLOC_STRUCT(st_vp_variant);
+ struct pipe_context *pipe = st->pipe;
+ struct ureg_program *ureg;
+ enum pipe_error error;
+ unsigned num_outputs;
+
+ st_prepare_vertex_program( st, stvp );
+
+ _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_OUTPUT);
+ _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_VARYING);
+
+ ureg = ureg_create( TGSI_PROCESSOR_VERTEX );
+ if (ureg == NULL) {
+ FREE(vpv);
+ return NULL;
+ }
+
+ vpv->key = *key;
+
+ vpv->num_inputs = stvp->num_inputs;
+ num_outputs = stvp->num_outputs;
+ if (key->passthrough_edgeflags) {
+ vpv->num_inputs++;
+ num_outputs++;
+ }
+
+ if (ST_DEBUG & DEBUG_MESA) {
+ _mesa_print_program(&stvp->Base.Base);
+ _mesa_print_program_parameters(st->ctx, &stvp->Base.Base);
+ debug_printf("\n");
+ }
+
+ error = st_translate_mesa_program(st->ctx,
+ TGSI_PROCESSOR_VERTEX,
+ ureg,
+ &stvp->Base.Base,
+ /* inputs */
+ vpv->num_inputs,
+ stvp->input_to_index,
+ NULL, /* input semantic name */
+ NULL, /* input semantic index */
+ NULL,
+ /* outputs */
+ num_outputs,
+ stvp->result_to_output,
+ stvp->output_semantic_name,
+ stvp->output_semantic_index,
+ key->passthrough_edgeflags );
+
+ if (error)
+ goto fail;
+
+ vpv->tgsi.tokens = ureg_get_tokens( ureg, NULL );
+ if (!vpv->tgsi.tokens)
+ goto fail;
+
+ ureg_destroy( ureg );
+
+ vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->tgsi);
+
+ if (ST_DEBUG & DEBUG_TGSI) {
+ tgsi_dump( vpv->tgsi.tokens, 0 );
+ debug_printf("\n");
+ }
+
+ return vpv;
+
+fail:
+ debug_printf("%s: failed to translate Mesa program:\n", __FUNCTION__);
+ _mesa_print_program(&stvp->Base.Base);
+ debug_assert(0);
+
+ ureg_destroy( ureg );
+ return NULL;
+}
+
+
+/**
+ * Find/create a vertex program variant.
+ */
+struct st_vp_variant *
+st_get_vp_variant(struct st_context *st,
+ struct st_vertex_program *stvp,
+ const struct st_vp_variant_key *key)
+{
+ struct st_vp_variant *vpv;
+
+ /* Search for existing variant */
+ for (vpv = stvp->variants; vpv; vpv = vpv->next) {
+ if (memcmp(&vpv->key, key, sizeof(*key)) == 0) {
+ break;
+ }
+ }
+
+ if (!vpv) {
+ /* create now */
+ vpv = st_translate_vertex_program(st, stvp, key);
+ if (vpv) {
+ /* insert into list */
+ vpv->next = stvp->variants;
+ stvp->variants = vpv;
+ }
+ }
+
+ return vpv;
+}
+
+
+/**
+ * Translate a Mesa fragment shader into a TGSI shader using extra info in
+ * the key.
+ * \return new fragment program variant
+ */
+static struct st_fp_variant *
+st_translate_fragment_program(struct st_context *st,
+ struct st_fragment_program *stfp,
+ const struct st_fp_variant_key *key)
+{
+ struct pipe_context *pipe = st->pipe;
+ struct st_fp_variant *variant = CALLOC_STRUCT(st_fp_variant);
+ GLboolean deleteFP = GL_FALSE;
+
+ if (!variant)
+ return NULL;
+
+ assert(!(key->bitmap && key->drawpixels));
+
+#if FEATURE_drawpix
+ if (key->bitmap) {
+ /* glBitmap drawing */
+ struct gl_fragment_program *fp; /* we free this temp program below */
+
+ st_make_bitmap_fragment_program(st, &stfp->Base,
+ &fp, &variant->bitmap_sampler);
+
+ variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters);
+ stfp = st_fragment_program(fp);
+ deleteFP = GL_TRUE;
+ }
+ else if (key->drawpixels) {
+ /* glDrawPixels drawing */
+ struct gl_fragment_program *fp; /* we free this temp program below */
+
+ if (key->drawpixels_z || key->drawpixels_stencil) {
+ fp = st_make_drawpix_z_stencil_program(st, key->drawpixels_z,
+ key->drawpixels_stencil);
+ }
+ else {
+ /* RGBA */
+ st_make_drawpix_fragment_program(st, &stfp->Base, &fp);
+ variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters);
+ deleteFP = GL_TRUE;
+ }
+ stfp = st_fragment_program(fp);
+ }
+#endif
+
+ if (!stfp->tgsi.tokens) {
+ /* need to translate Mesa instructions to TGSI now */
+ GLuint outputMapping[FRAG_RESULT_MAX];
+ GLuint inputMapping[FRAG_ATTRIB_MAX];
+ GLuint interpMode[PIPE_MAX_SHADER_INPUTS]; /* XXX size? */
+ GLuint attr;
+ enum pipe_error error;
+ const GLbitfield inputsRead = stfp->Base.Base.InputsRead;
+ struct ureg_program *ureg;
+ GLboolean write_all = GL_FALSE;
+
+ ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS];
+ ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS];
+ uint fs_num_inputs = 0;
+
+ ubyte fs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
+ ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
+ uint fs_num_outputs = 0;
+
+
+ _mesa_remove_output_reads(&stfp->Base.Base, PROGRAM_OUTPUT);
+
+ /*
+ * Convert Mesa program inputs to TGSI input register semantics.
+ */
+ for (attr = 0; attr < FRAG_ATTRIB_MAX; attr++) {
+ if (inputsRead & (1 << attr)) {
+ const GLuint slot = fs_num_inputs++;
+
+ inputMapping[attr] = slot;
+
+ switch (attr) {
+ case FRAG_ATTRIB_WPOS:
+ input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
+ input_semantic_index[slot] = 0;
+ interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
+ break;
+ case FRAG_ATTRIB_COL0:
+ input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+ input_semantic_index[slot] = 0;
+ interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
+ break;
+ case FRAG_ATTRIB_COL1:
+ input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+ input_semantic_index[slot] = 1;
+ interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
+ break;
+ case FRAG_ATTRIB_FOGC:
+ input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
+ input_semantic_index[slot] = 0;
+ interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
+ break;
+ case FRAG_ATTRIB_FACE:
+ input_semantic_name[slot] = TGSI_SEMANTIC_FACE;
+ input_semantic_index[slot] = 0;
+ interpMode[slot] = TGSI_INTERPOLATE_CONSTANT;
+ break;
+ /* In most cases, there is nothing special about these
+ * inputs, so adopt a convention to use the generic
+ * semantic name and the mesa FRAG_ATTRIB_ number as the
+ * index.
+ *
+ * All that is required is that the vertex shader labels
+ * its own outputs similarly, and that the vertex shader
+ * generates at least every output required by the
+ * fragment shader plus fixed-function hardware (such as
+ * BFC).
+ *
+ * There is no requirement that semantic indexes start at
+ * zero or be restricted to a particular range -- nobody
+ * should be building tables based on semantic index.
+ */
+ case FRAG_ATTRIB_PNTC:
+ case FRAG_ATTRIB_TEX0:
+ case FRAG_ATTRIB_TEX1:
+ case FRAG_ATTRIB_TEX2:
+ case FRAG_ATTRIB_TEX3:
+ case FRAG_ATTRIB_TEX4:
+ case FRAG_ATTRIB_TEX5:
+ case FRAG_ATTRIB_TEX6:
+ case FRAG_ATTRIB_TEX7:
+ case FRAG_ATTRIB_VAR0:
+ default:
+ /* Actually, let's try and zero-base this just for
+ * readability of the generated TGSI.
+ */
+ assert(attr >= FRAG_ATTRIB_TEX0);
+ input_semantic_index[slot] = (attr - FRAG_ATTRIB_TEX0);
+ input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ if (attr == FRAG_ATTRIB_PNTC)
+ interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
+ else
+ interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
+ break;
+ }
+ }
+ else {
+ inputMapping[attr] = -1;
+ }
+ }
+
+ /*
+ * Semantics and mapping for outputs
+ */
+ {
+ uint numColors = 0;
+ GLbitfield64 outputsWritten = stfp->Base.Base.OutputsWritten;
+
+ /* if z is written, emit that first */
+ if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) {
+ fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_POSITION;
+ fs_output_semantic_index[fs_num_outputs] = 0;
+ outputMapping[FRAG_RESULT_DEPTH] = fs_num_outputs;
+ fs_num_outputs++;
+ outputsWritten &= ~(1 << FRAG_RESULT_DEPTH);
+ }
+
+ if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_STENCIL)) {
+ fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_STENCIL;
+ fs_output_semantic_index[fs_num_outputs] = 0;
+ outputMapping[FRAG_RESULT_STENCIL] = fs_num_outputs;
+ fs_num_outputs++;
+ outputsWritten &= ~(1 << FRAG_RESULT_STENCIL);
+ }
+
+ /* handle remaning outputs (color) */
+ for (attr = 0; attr < FRAG_RESULT_MAX; attr++) {
+ if (outputsWritten & BITFIELD64_BIT(attr)) {
+ switch (attr) {
+ case FRAG_RESULT_DEPTH:
+ case FRAG_RESULT_STENCIL:
+ /* handled above */
+ assert(0);
+ break;
+ case FRAG_RESULT_COLOR:
+ write_all = GL_TRUE; /* fallthrough */
+ default:
+ assert(attr == FRAG_RESULT_COLOR ||
+ (FRAG_RESULT_DATA0 <= attr && attr < FRAG_RESULT_MAX));
+ fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_COLOR;
+ fs_output_semantic_index[fs_num_outputs] = numColors;
+ outputMapping[attr] = fs_num_outputs;
+ numColors++;
+ break;
+ }
+
+ fs_num_outputs++;
+ }
+ }
+ }
+
+ ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
+ if (ureg == NULL)
+ return NULL;
+
+ if (ST_DEBUG & DEBUG_MESA) {
+ _mesa_print_program(&stfp->Base.Base);
+ _mesa_print_program_parameters(st->ctx, &stfp->Base.Base);
+ debug_printf("\n");
+ }
+ if (write_all == GL_TRUE)
+ ureg_property_fs_color0_writes_all_cbufs(ureg, 1);
+
+ error = st_translate_mesa_program(st->ctx,
+ TGSI_PROCESSOR_FRAGMENT,
+ ureg,
+ &stfp->Base.Base,
+ /* inputs */
+ fs_num_inputs,
+ inputMapping,
+ input_semantic_name,
+ input_semantic_index,
+ interpMode,
+ /* outputs */
+ fs_num_outputs,
+ outputMapping,
+ fs_output_semantic_name,
+ fs_output_semantic_index, FALSE );
+
+ stfp->tgsi.tokens = ureg_get_tokens( ureg, NULL );
+ ureg_destroy( ureg );
+ }
+
+ /* fill in variant */
+ variant->driver_shader = pipe->create_fs_state(pipe, &stfp->tgsi);
+ variant->key = *key;
+
+ if (ST_DEBUG & DEBUG_TGSI) {
+ tgsi_dump( stfp->tgsi.tokens, 0/*TGSI_DUMP_VERBOSE*/ );
+ debug_printf("\n");
+ }
+
+ if (deleteFP) {
+ /* Free the temporary program made above */
+ struct gl_fragment_program *fp = &stfp->Base;
+ _mesa_reference_fragprog(st->ctx, &fp, NULL);
+ }
+
+ return variant;
+}
+
+
+/**
+ * Translate fragment program if needed.
+ */
+struct st_fp_variant *
+st_get_fp_variant(struct st_context *st,
+ struct st_fragment_program *stfp,
+ const struct st_fp_variant_key *key)
+{
+ struct st_fp_variant *fpv;
+
+ /* Search for existing variant */
+ for (fpv = stfp->variants; fpv; fpv = fpv->next) {
+ if (memcmp(&fpv->key, key, sizeof(*key)) == 0) {
+ break;
+ }
+ }
+
+ if (!fpv) {
+ /* create new */
+ fpv = st_translate_fragment_program(st, stfp, key);
+ if (fpv) {
+ /* insert into list */
+ fpv->next = stfp->variants;
+ stfp->variants = fpv;
+ }
+ }
+
+ return fpv;
+}
+
+
+/**
+ * Translate a geometry program to create a new variant.
+ */
+static struct st_gp_variant *
+st_translate_geometry_program(struct st_context *st,
+ struct st_geometry_program *stgp,
+ const struct st_gp_variant_key *key)
+{
+ GLuint inputMapping[GEOM_ATTRIB_MAX];
+ GLuint outputMapping[GEOM_RESULT_MAX];
+ struct pipe_context *pipe = st->pipe;
+ enum pipe_error error;
+ GLuint attr;
+ const GLbitfield inputsRead = stgp->Base.Base.InputsRead;
+ GLuint vslot = 0;
+ GLuint num_generic = 0;
+
+ uint gs_num_inputs = 0;
+ uint gs_builtin_inputs = 0;
+ uint gs_array_offset = 0;
+
+ ubyte gs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
+ ubyte gs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
+ uint gs_num_outputs = 0;
+
+ GLint i;
+ GLuint maxSlot = 0;
+ struct ureg_program *ureg;
+
+ struct st_gp_variant *gpv;
+
+ gpv = CALLOC_STRUCT(st_gp_variant);
+ if (!gpv)
+ return NULL;
+
+ _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_OUTPUT);
+ _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_VARYING);
+
+ ureg = ureg_create( TGSI_PROCESSOR_GEOMETRY );
+ if (ureg == NULL) {
+ FREE(gpv);
+ return NULL;
+ }
+
+ /* which vertex output goes to the first geometry input */
+ vslot = 0;
+
+ memset(inputMapping, 0, sizeof(inputMapping));
+ memset(outputMapping, 0, sizeof(outputMapping));
+
+ /*
+ * Convert Mesa program inputs to TGSI input register semantics.
+ */
+ for (attr = 0; attr < GEOM_ATTRIB_MAX; attr++) {
+ if (inputsRead & (1 << attr)) {
+ const GLuint slot = gs_num_inputs;
+
+ gs_num_inputs++;
+
+ inputMapping[attr] = slot;
+
+ stgp->input_map[slot + gs_array_offset] = vslot - gs_builtin_inputs;
+ stgp->input_to_index[attr] = vslot;
+ stgp->index_to_input[vslot] = attr;
+ ++vslot;
+
+ if (attr != GEOM_ATTRIB_PRIMITIVE_ID) {
+ gs_array_offset += 2;
+ } else
+ ++gs_builtin_inputs;
+
+#if 0
+ debug_printf("input map at %d = %d\n",
+ slot + gs_array_offset, stgp->input_map[slot + gs_array_offset]);
+#endif
+
+ switch (attr) {
+ case GEOM_ATTRIB_PRIMITIVE_ID:
+ stgp->input_semantic_name[slot] = TGSI_SEMANTIC_PRIMID;
+ stgp->input_semantic_index[slot] = 0;
+ break;
+ case GEOM_ATTRIB_POSITION:
+ stgp->input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
+ stgp->input_semantic_index[slot] = 0;
+ break;
+ case GEOM_ATTRIB_COLOR0:
+ stgp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+ stgp->input_semantic_index[slot] = 0;
+ break;
+ case GEOM_ATTRIB_COLOR1:
+ stgp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+ stgp->input_semantic_index[slot] = 1;
+ break;
+ case GEOM_ATTRIB_FOG_FRAG_COORD:
+ stgp->input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
+ stgp->input_semantic_index[slot] = 0;
+ break;
+ case GEOM_ATTRIB_TEX_COORD:
+ stgp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ stgp->input_semantic_index[slot] = num_generic++;
+ break;
+ case GEOM_ATTRIB_VAR0:
+ /* fall-through */
+ default:
+ stgp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ stgp->input_semantic_index[slot] = num_generic++;
+ }
+ }
+ }
+
+ /* initialize output semantics to defaults */
+ for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) {
+ gs_output_semantic_name[i] = TGSI_SEMANTIC_GENERIC;
+ gs_output_semantic_index[i] = 0;
+ }
+
+ num_generic = 0;
+ /*
+ * Determine number of outputs, the (default) output register
+ * mapping and the semantic information for each output.
+ */
+ for (attr = 0; attr < GEOM_RESULT_MAX; attr++) {
+ if (stgp->Base.Base.OutputsWritten & (1 << attr)) {
+ GLuint slot;
+
+ slot = gs_num_outputs;
+ gs_num_outputs++;
+ outputMapping[attr] = slot;
+
+ switch (attr) {
+ case GEOM_RESULT_POS:
+ assert(slot == 0);
+ gs_output_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
+ gs_output_semantic_index[slot] = 0;
+ break;
+ case GEOM_RESULT_COL0:
+ gs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+ gs_output_semantic_index[slot] = 0;
+ break;
+ case GEOM_RESULT_COL1:
+ gs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+ gs_output_semantic_index[slot] = 1;
+ break;
+ case GEOM_RESULT_SCOL0:
+ gs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
+ gs_output_semantic_index[slot] = 0;
+ break;
+ case GEOM_RESULT_SCOL1:
+ gs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
+ gs_output_semantic_index[slot] = 1;
+ break;
+ case GEOM_RESULT_FOGC:
+ gs_output_semantic_name[slot] = TGSI_SEMANTIC_FOG;
+ gs_output_semantic_index[slot] = 0;
+ break;
+ case GEOM_RESULT_PSIZ:
+ gs_output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
+ gs_output_semantic_index[slot] = 0;
+ break;
+ case GEOM_RESULT_TEX0:
+ case GEOM_RESULT_TEX1:
+ case GEOM_RESULT_TEX2:
+ case GEOM_RESULT_TEX3:
+ case GEOM_RESULT_TEX4:
+ case GEOM_RESULT_TEX5:
+ case GEOM_RESULT_TEX6:
+ case GEOM_RESULT_TEX7:
+ /* fall-through */
+ case GEOM_RESULT_VAR0:
+ /* fall-through */
+ default:
+ assert(slot < Elements(gs_output_semantic_name));
+ /* use default semantic info */
+ gs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ gs_output_semantic_index[slot] = num_generic++;
+ }
+ }
+ }
+
+ assert(gs_output_semantic_name[0] == TGSI_SEMANTIC_POSITION);
+
+ /* find max output slot referenced to compute gs_num_outputs */
+ for (attr = 0; attr < GEOM_RESULT_MAX; attr++) {
+ if (outputMapping[attr] != ~0 && outputMapping[attr] > maxSlot)
+ maxSlot = outputMapping[attr];
+ }
+ gs_num_outputs = maxSlot + 1;
+
+#if 0 /* debug */
+ {
+ GLuint i;
+ printf("outputMapping? %d\n", outputMapping ? 1 : 0);
+ if (outputMapping) {
+ printf("attr -> slot\n");
+ for (i = 0; i < 16; i++) {
+ printf(" %2d %3d\n", i, outputMapping[i]);
+ }
+ }
+ printf("slot sem_name sem_index\n");
+ for (i = 0; i < gs_num_outputs; i++) {
+ printf(" %2d %d %d\n",
+ i,
+ gs_output_semantic_name[i],
+ gs_output_semantic_index[i]);
+ }
+ }
+#endif
+
+ /* free old shader state, if any */
+ if (stgp->tgsi.tokens) {
+ st_free_tokens(stgp->tgsi.tokens);
+ stgp->tgsi.tokens = NULL;
+ }
+
+ ureg_property_gs_input_prim(ureg, stgp->Base.InputType);
+ ureg_property_gs_output_prim(ureg, stgp->Base.OutputType);
+ ureg_property_gs_max_vertices(ureg, stgp->Base.VerticesOut);
+
+ error = st_translate_mesa_program(st->ctx,
+ TGSI_PROCESSOR_GEOMETRY,
+ ureg,
+ &stgp->Base.Base,
+ /* inputs */
+ gs_num_inputs,
+ inputMapping,
+ stgp->input_semantic_name,
+ stgp->input_semantic_index,
+ NULL,
+ /* outputs */
+ gs_num_outputs,
+ outputMapping,
+ gs_output_semantic_name,
+ gs_output_semantic_index,
+ FALSE);
+
+ stgp->num_inputs = gs_num_inputs;
+ stgp->tgsi.tokens = ureg_get_tokens( ureg, NULL );
+ ureg_destroy( ureg );
+
+ /* fill in new variant */
+ gpv->driver_shader = pipe->create_gs_state(pipe, &stgp->tgsi);
+ gpv->key = *key;
+
+ if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) {
+ _mesa_print_program(&stgp->Base.Base);
+ debug_printf("\n");
+ }
+
+ if (ST_DEBUG & DEBUG_TGSI) {
+ tgsi_dump(stgp->tgsi.tokens, 0);
+ debug_printf("\n");
+ }
+
+ return gpv;
+}
+
+
+/**
+ * Get/create geometry program variant.
+ */
+struct st_gp_variant *
+st_get_gp_variant(struct st_context *st,
+ struct st_geometry_program *stgp,
+ const struct st_gp_variant_key *key)
+{
+ struct st_gp_variant *gpv;
+
+ /* Search for existing variant */
+ for (gpv = stgp->variants; gpv; gpv = gpv->next) {
+ if (memcmp(&gpv->key, key, sizeof(*key)) == 0) {
+ break;
+ }
+ }
+
+ if (!gpv) {
+ /* create new */
+ gpv = st_translate_geometry_program(st, stgp, key);
+ if (gpv) {
+ /* insert into list */
+ gpv->next = stgp->variants;
+ stgp->variants = gpv;
+ }
+ }
+
+ return gpv;
+}
+
+
+
+
+/**
+ * Debug- print current shader text
+ */
+void
+st_print_shaders(struct gl_context *ctx)
+{
+ struct gl_shader_program *shProg[3] = {
+ ctx->Shader.CurrentVertexProgram,
+ ctx->Shader.CurrentGeometryProgram,
+ ctx->Shader.CurrentFragmentProgram,
+ };
+ unsigned j;
+
+ for (j = 0; j < 3; j++) {
+ unsigned i;
+
+ if (shProg[j] == NULL)
+ continue;
+
+ for (i = 0; i < shProg[j]->NumShaders; i++) {
+ struct gl_shader *sh;
+
+ switch (shProg[j]->Shaders[i]->Type) {
+ case GL_VERTEX_SHADER:
+ sh = (i != 0) ? NULL : shProg[j]->Shaders[i];
+ break;
+ case GL_GEOMETRY_SHADER_ARB:
+ sh = (i != 1) ? NULL : shProg[j]->Shaders[i];
+ break;
+ case GL_FRAGMENT_SHADER:
+ sh = (i != 2) ? NULL : shProg[j]->Shaders[i];
+ break;
+ default:
+ assert(0);
+ sh = NULL;
+ break;
+ }
+
+ if (sh != NULL) {
+ printf("GLSL shader %u of %u:\n", i, shProg[j]->NumShaders);
+ printf("%s\n", sh->Source);
+ }
+ }
+ }
+}
+
+
+/**
+ * Vert/Geom/Frag programs have per-context variants. Free all the
+ * variants attached to the given program which match the given context.
+ */
+static void
+destroy_program_variants(struct st_context *st, struct gl_program *program)
+{
+ if (!program)
+ return;
+
+ switch (program->Target) {
+ case GL_VERTEX_PROGRAM_ARB:
+ {
+ struct st_vertex_program *stvp = (struct st_vertex_program *) program;
+ struct st_vp_variant *vpv, **prevPtr = &stvp->variants;
+
+ for (vpv = stvp->variants; vpv; ) {
+ struct st_vp_variant *next = vpv->next;
+ if (vpv->key.st == st) {
+ /* unlink from list */
+ *prevPtr = next;
+ /* destroy this variant */
+ delete_vp_variant(st, vpv);
+ }
+ else {
+ prevPtr = &vpv->next;
+ }
+ vpv = next;
+ }
+ }
+ break;
+ case GL_FRAGMENT_PROGRAM_ARB:
+ {
+ struct st_fragment_program *stfp =
+ (struct st_fragment_program *) program;
+ struct st_fp_variant *fpv, **prevPtr = &stfp->variants;
+
+ for (fpv = stfp->variants; fpv; ) {
+ struct st_fp_variant *next = fpv->next;
+ if (fpv->key.st == st) {
+ /* unlink from list */
+ *prevPtr = next;
+ /* destroy this variant */
+ delete_fp_variant(st, fpv);
+ }
+ else {
+ prevPtr = &fpv->next;
+ }
+ fpv = next;
+ }
+ }
+ break;
+ case MESA_GEOMETRY_PROGRAM:
+ {
+ struct st_geometry_program *stgp =
+ (struct st_geometry_program *) program;
+ struct st_gp_variant *gpv, **prevPtr = &stgp->variants;
+
+ for (gpv = stgp->variants; gpv; ) {
+ struct st_gp_variant *next = gpv->next;
+ if (gpv->key.st == st) {
+ /* unlink from list */
+ *prevPtr = next;
+ /* destroy this variant */
+ delete_gp_variant(st, gpv);
+ }
+ else {
+ prevPtr = &gpv->next;
+ }
+ gpv = next;
+ }
+ }
+ break;
+ default:
+ _mesa_problem(NULL, "Unexpected program target in "
+ "destroy_program_variants_cb()");
+ }
+}
+
+
+/**
+ * Callback for _mesa_HashWalk. Free all the shader's program variants
+ * which match the given context.
+ */
+static void
+destroy_shader_program_variants_cb(GLuint key, void *data, void *userData)
+{
+ struct st_context *st = (struct st_context *) userData;
+ struct gl_shader *shader = (struct gl_shader *) data;
+
+ switch (shader->Type) {
+ case GL_SHADER_PROGRAM_MESA:
+ {
+ struct gl_shader_program *shProg = (struct gl_shader_program *) data;
+ GLuint i;
+
+ for (i = 0; i < shProg->NumShaders; i++) {
+ destroy_program_variants(st, shProg->Shaders[i]->Program);
+ }
+
+ destroy_program_variants(st, (struct gl_program *)
+ shProg->VertexProgram);
+ destroy_program_variants(st, (struct gl_program *)
+ shProg->FragmentProgram);
+ destroy_program_variants(st, (struct gl_program *)
+ shProg->GeometryProgram);
+ }
+ break;
+ case GL_VERTEX_SHADER:
+ case GL_FRAGMENT_SHADER:
+ case GL_GEOMETRY_SHADER:
+ {
+ destroy_program_variants(st, shader->Program);
+ }
+ break;
+ default:
+ assert(0);
+ }
+}
+
+
+/**
+ * Callback for _mesa_HashWalk. Free all the program variants which match
+ * the given context.
+ */
+static void
+destroy_program_variants_cb(GLuint key, void *data, void *userData)
+{
+ struct st_context *st = (struct st_context *) userData;
+ struct gl_program *program = (struct gl_program *) data;
+ destroy_program_variants(st, program);
+}
+
+
+/**
+ * Walk over all shaders and programs to delete any variants which
+ * belong to the given context.
+ * This is called during context tear-down.
+ */
+void
+st_destroy_program_variants(struct st_context *st)
+{
+ /* ARB vert/frag program */
+ _mesa_HashWalk(st->ctx->Shared->Programs,
+ destroy_program_variants_cb, st);
+
+ /* GLSL vert/frag/geom shaders */
+ _mesa_HashWalk(st->ctx->Shared->ShaderObjects,
+ destroy_shader_program_variants_cb, st);
+}