/**************************************************************************
*
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2008 VMware, Inc.
* All Rights Reserved.
* Copyright 2008 VMware, Inc. All rights reserved.
*
* 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
+ * IN NO EVENT SHALL VMWARE 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 "util/u_simple_shaders.h"
#include "util/u_math.h"
#include "util/u_texture.h"
+#include "util/u_half.h"
+#include "util/u_surface.h"
#include "cso_cache/cso_context.h"
struct pipe_context *pipe;
struct cso_context *cso;
- struct pipe_blend_state blend;
- struct pipe_depth_stencil_alpha_state depthstencil;
+ struct pipe_blend_state blend_keep_color, blend_write_color;
+ struct pipe_depth_stencil_alpha_state dsa_keep_depth, dsa_write_depth;
struct pipe_rasterizer_state rasterizer;
struct pipe_sampler_state sampler;
- struct pipe_clip_state clip;
struct pipe_vertex_element velem[2];
void *vs;
- void *fs2d, *fsCube;
- struct pipe_buffer *vbuf; /**< quad vertices */
+ /** Not all are used, but simplifies code */
+ void *fs_color[TGSI_TEXTURE_COUNT];
+ void *fs_depth[TGSI_TEXTURE_COUNT];
+
+ struct pipe_resource *vbuf; /**< quad vertices */
unsigned vbuf_slot;
float vertices[4][2][4]; /**< vertex/texcoords for quad */
};
-typedef ushort half_float;
-
-
-static half_float
-float_to_half(float f)
-{
- /* XXX fix this */
- return 0;
-}
-
-static float
-half_to_float(half_float h)
-{
- /* XXX fix this */
- return 0.0f;
-}
-
-
+typedef uint16_t half_float;
/**
rowC[j][e], rowC[k][e], \
rowD[j][e], rowD[k][e]); \
} while(0)
-
+
#define FILTER_F_3D(e) \
do { \
dst[i][e] = (rowA[j][e] + rowA[k][e] \
#define FILTER_HF_3D(e) \
do { \
- const float aj = half_to_float(rowA[j][e]); \
- const float ak = half_to_float(rowA[k][e]); \
- const float bj = half_to_float(rowB[j][e]); \
- const float bk = half_to_float(rowB[k][e]); \
- const float cj = half_to_float(rowC[j][e]); \
- const float ck = half_to_float(rowC[k][e]); \
- const float dj = half_to_float(rowD[j][e]); \
- const float dk = half_to_float(rowD[k][e]); \
- dst[i][e] = float_to_half((aj + ak + bj + bk + cj + ck + dj + dk) \
+ const float aj = util_half_to_float(rowA[j][e]); \
+ const float ak = util_half_to_float(rowA[k][e]); \
+ const float bj = util_half_to_float(rowB[j][e]); \
+ const float bk = util_half_to_float(rowB[k][e]); \
+ const float cj = util_half_to_float(rowC[j][e]); \
+ const float ck = util_half_to_float(rowC[k][e]); \
+ const float dj = util_half_to_float(rowD[j][e]); \
+ const float dk = util_half_to_float(rowD[k][e]); \
+ dst[i][e] = util_float_to_half((aj + ak + bj + bk + cj + ck + dj + dk) \
* 0.125F); \
} while(0)
/*@}*/
}
}
-#if 0
- else if (datatype == HALF_DTYPE_FLOAT && comps == 4) {
+ else if (datatype == DTYPE_HALF_FLOAT && comps == 4) {
uint i, j, k, comp;
const half_float(*rowA)[4] = (const half_float(*)[4]) srcRowA;
const half_float(*rowB)[4] = (const half_float(*)[4]) srcRowB;
i++, j += colStride, k += colStride) {
for (comp = 0; comp < 4; comp++) {
float aj, ak, bj, bk;
- aj = half_to_float(rowA[j][comp]);
- ak = half_to_float(rowA[k][comp]);
- bj = half_to_float(rowB[j][comp]);
- bk = half_to_float(rowB[k][comp]);
- dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
+ aj = util_half_to_float(rowA[j][comp]);
+ ak = util_half_to_float(rowA[k][comp]);
+ bj = util_half_to_float(rowB[j][comp]);
+ bk = util_half_to_float(rowB[k][comp]);
+ dst[i][comp] = util_float_to_half((aj + ak + bj + bk) * 0.25F);
}
}
}
i++, j += colStride, k += colStride) {
for (comp = 0; comp < 3; comp++) {
float aj, ak, bj, bk;
- aj = half_to_float(rowA[j][comp]);
- ak = half_to_float(rowA[k][comp]);
- bj = half_to_float(rowB[j][comp]);
- bk = half_to_float(rowB[k][comp]);
- dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
+ aj = util_half_to_float(rowA[j][comp]);
+ ak = util_half_to_float(rowA[k][comp]);
+ bj = util_half_to_float(rowB[j][comp]);
+ bk = util_half_to_float(rowB[k][comp]);
+ dst[i][comp] = util_float_to_half((aj + ak + bj + bk) * 0.25F);
}
}
}
i++, j += colStride, k += colStride) {
for (comp = 0; comp < 2; comp++) {
float aj, ak, bj, bk;
- aj = half_to_float(rowA[j][comp]);
- ak = half_to_float(rowA[k][comp]);
- bj = half_to_float(rowB[j][comp]);
- bk = half_to_float(rowB[k][comp]);
- dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
+ aj = util_half_to_float(rowA[j][comp]);
+ ak = util_half_to_float(rowA[k][comp]);
+ bj = util_half_to_float(rowB[j][comp]);
+ bk = util_half_to_float(rowB[k][comp]);
+ dst[i][comp] = util_float_to_half((aj + ak + bj + bk) * 0.25F);
}
}
}
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
float aj, ak, bj, bk;
- aj = half_to_float(rowA[j]);
- ak = half_to_float(rowA[k]);
- bj = half_to_float(rowB[j]);
- bk = half_to_float(rowB[k]);
- dst[i] = float_to_half((aj + ak + bj + bk) * 0.25F);
+ aj = util_half_to_float(rowA[j]);
+ ak = util_half_to_float(rowA[k]);
+ bj = util_half_to_float(rowB[j]);
+ bk = util_half_to_float(rowB[k]);
+ dst[i] = util_float_to_half((aj + ak + bj + bk) * 0.25F);
}
}
-#endif
else if (datatype == DTYPE_UINT && comps == 1) {
uint i, j, k;
static void
reduce_3d(enum pipe_format pformat,
int srcWidth, int srcHeight, int srcDepth,
- int srcRowStride, const ubyte *srcPtr,
+ int srcRowStride, int srcImageStride, const ubyte *srcPtr,
int dstWidth, int dstHeight, int dstDepth,
- int dstRowStride, ubyte *dstPtr)
+ int dstRowStride, int dstImageStride, ubyte *dstPtr)
{
const int bpt = util_format_get_blocksize(pformat);
- const int border = 0;
int img, row;
- int bytesPerSrcImage, bytesPerDstImage;
- int bytesPerSrcRow, bytesPerDstRow;
int srcImageOffset, srcRowOffset;
enum dtype datatype;
uint comps;
format_to_type_comps(pformat, &datatype, &comps);
- bytesPerSrcImage = srcWidth * srcHeight * bpt;
- bytesPerDstImage = dstWidth * dstHeight * bpt;
+ /* XXX I think we should rather assert those strides */
+ if (!srcImageStride)
+ srcImageStride = srcWidth * srcHeight * bpt;
+ if (!dstImageStride)
+ dstImageStride = dstWidth * dstHeight * bpt;
- bytesPerSrcRow = srcWidth * bpt;
- bytesPerDstRow = dstWidth * bpt;
+ if (!srcRowStride)
+ srcRowStride = srcWidth * bpt;
+ if (!dstRowStride)
+ dstRowStride = dstWidth * bpt;
/* Offset between adjacent src images to be averaged together */
- srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage;
+ srcImageOffset = (srcDepth == dstDepth) ? 0 : srcImageStride;
/* Offset between adjacent src rows to be averaged together */
- srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt;
+ srcRowOffset = (srcHeight == dstHeight) ? 0 : srcRowStride;
/*
* Need to average together up to 8 src pixels for each dest pixel.
*/
for (img = 0; img < dstDepth; img++) {
- /* first source image pointer, skipping border */
+ /* first source image pointer */
const ubyte *imgSrcA = srcPtr
- + (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border
- + img * (bytesPerSrcImage + srcImageOffset);
- /* second source image pointer, skipping border */
+ + img * (srcImageStride + srcImageOffset);
+ /* second source image pointer */
const ubyte *imgSrcB = imgSrcA + srcImageOffset;
- /* address of the dest image, skipping border */
- ubyte *imgDst = dstPtr
- + (bytesPerDstImage + bytesPerDstRow + border) * bpt * border
- + img * bytesPerDstImage;
+ /* address of the dest image */
+ ubyte *imgDst = dstPtr + img * dstImageStride;
/* setup the four source row pointers and the dest row pointer */
const ubyte *srcImgARowA = imgSrcA;
dstWidth, dstImgRow);
/* advance to next rows */
- srcImgARowA += bytesPerSrcRow + srcRowOffset;
- srcImgARowB += bytesPerSrcRow + srcRowOffset;
- srcImgBRowA += bytesPerSrcRow + srcRowOffset;
- srcImgBRowB += bytesPerSrcRow + srcRowOffset;
- dstImgRow += bytesPerDstRow;
+ srcImgARowA += srcRowStride + srcRowOffset;
+ srcImgARowB += srcRowStride + srcRowOffset;
+ srcImgBRowA += srcRowStride + srcRowOffset;
+ srcImgBRowB += srcRowStride + srcRowOffset;
+ dstImgRow += dstImageStride;
}
}
}
static void
make_1d_mipmap(struct gen_mipmap_state *ctx,
- struct pipe_texture *pt,
- uint face, uint baseLevel, uint lastLevel)
+ struct pipe_resource *pt,
+ uint layer, uint baseLevel, uint lastLevel)
{
struct pipe_context *pipe = ctx->pipe;
- const uint zslice = 0;
uint dstLevel;
for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
const uint srcLevel = dstLevel - 1;
struct pipe_transfer *srcTrans, *dstTrans;
void *srcMap, *dstMap;
-
- srcTrans = pipe->get_tex_transfer(pipe, pt, face, srcLevel, zslice,
- PIPE_TRANSFER_READ, 0, 0,
- u_minify(pt->width0, srcLevel),
- u_minify(pt->height0, srcLevel));
- dstTrans = pipe->get_tex_transfer(pipe, pt, face, dstLevel, zslice,
- PIPE_TRANSFER_WRITE, 0, 0,
- u_minify(pt->width0, dstLevel),
- u_minify(pt->height0, dstLevel));
-
- srcMap = (ubyte *) pipe->transfer_map(pipe, srcTrans);
- dstMap = (ubyte *) pipe->transfer_map(pipe, dstTrans);
+
+ srcMap = pipe_transfer_map(pipe, pt, srcLevel, layer,
+ PIPE_TRANSFER_READ, 0, 0,
+ u_minify(pt->width0, srcLevel),
+ u_minify(pt->height0, srcLevel), &srcTrans);
+ dstMap = pipe_transfer_map(pipe, pt, dstLevel, layer,
+ PIPE_TRANSFER_WRITE, 0, 0,
+ u_minify(pt->width0, dstLevel),
+ u_minify(pt->height0, dstLevel), &dstTrans);
reduce_1d(pt->format,
- srcTrans->width, srcMap,
- dstTrans->width, dstMap);
+ srcTrans->box.width, srcMap,
+ dstTrans->box.width, dstMap);
pipe->transfer_unmap(pipe, srcTrans);
pipe->transfer_unmap(pipe, dstTrans);
-
- pipe->tex_transfer_destroy(pipe, srcTrans);
- pipe->tex_transfer_destroy(pipe, dstTrans);
}
}
static void
make_2d_mipmap(struct gen_mipmap_state *ctx,
- struct pipe_texture *pt,
- uint face, uint baseLevel, uint lastLevel)
+ struct pipe_resource *pt,
+ uint layer, uint baseLevel, uint lastLevel)
{
struct pipe_context *pipe = ctx->pipe;
- const uint zslice = 0;
uint dstLevel;
-
+
assert(util_format_get_blockwidth(pt->format) == 1);
assert(util_format_get_blockheight(pt->format) == 1);
const uint srcLevel = dstLevel - 1;
struct pipe_transfer *srcTrans, *dstTrans;
ubyte *srcMap, *dstMap;
-
- srcTrans = pipe->get_tex_transfer(pipe, pt, face, srcLevel, zslice,
- PIPE_TRANSFER_READ, 0, 0,
- u_minify(pt->width0, srcLevel),
- u_minify(pt->height0, srcLevel));
- dstTrans = pipe->get_tex_transfer(pipe, pt, face, dstLevel, zslice,
- PIPE_TRANSFER_WRITE, 0, 0,
- u_minify(pt->width0, dstLevel),
- u_minify(pt->height0, dstLevel));
-
- srcMap = (ubyte *) pipe->transfer_map(pipe, srcTrans);
- dstMap = (ubyte *) pipe->transfer_map(pipe, dstTrans);
+
+ srcMap = pipe_transfer_map(pipe, pt, srcLevel, layer,
+ PIPE_TRANSFER_READ, 0, 0,
+ u_minify(pt->width0, srcLevel),
+ u_minify(pt->height0, srcLevel), &srcTrans);
+ dstMap = pipe_transfer_map(pipe, pt, dstLevel, layer,
+ PIPE_TRANSFER_WRITE, 0, 0,
+ u_minify(pt->width0, dstLevel),
+ u_minify(pt->height0, dstLevel), &dstTrans);
reduce_2d(pt->format,
- srcTrans->width, srcTrans->height,
+ srcTrans->box.width, srcTrans->box.height,
srcTrans->stride, srcMap,
- dstTrans->width, dstTrans->height,
+ dstTrans->box.width, dstTrans->box.height,
dstTrans->stride, dstMap);
pipe->transfer_unmap(pipe, srcTrans);
pipe->transfer_unmap(pipe, dstTrans);
-
- pipe->tex_transfer_destroy(pipe, srcTrans);
- pipe->tex_transfer_destroy(pipe, dstTrans);
}
}
+/* XXX looks a bit more like it could work now but need to test */
static void
make_3d_mipmap(struct gen_mipmap_state *ctx,
- struct pipe_texture *pt,
+ struct pipe_resource *pt,
uint face, uint baseLevel, uint lastLevel)
{
-#if 0
struct pipe_context *pipe = ctx->pipe;
- struct pipe_screen *screen = pipe->screen;
- uint dstLevel, zslice = 0;
+ uint dstLevel;
+ struct pipe_box src_box, dst_box;
assert(util_format_get_blockwidth(pt->format) == 1);
assert(util_format_get_blockheight(pt->format) == 1);
+ src_box.x = src_box.y = src_box.z = 0;
+ dst_box.x = dst_box.y = dst_box.z = 0;
+
for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
const uint srcLevel = dstLevel - 1;
struct pipe_transfer *srcTrans, *dstTrans;
ubyte *srcMap, *dstMap;
-
- srcTrans = pipe->get_tex_transfer(pipe, pt, face, srcLevel, zslice,
- PIPE_TRANSFER_READ, 0, 0,
- u_minify(pt->width0, srcLevel),
- u_minify(pt->height0, srcLevel));
- dstTrans = pipe->get_tex_transfer(pipe, pt, face, dstLevel, zslice,
- PIPE_TRANSFER_WRITE, 0, 0,
- u_minify(pt->width0, dstLevel),
- u_minify(pt->height0, dstLevel));
-
- srcMap = (ubyte *) pipe->transfer_map(pipe, srcTrans);
- dstMap = (ubyte *) pipe->transfer_map(pipe, dstTrans);
+ struct pipe_box src_box, dst_box;
+ src_box.width = u_minify(pt->width0, srcLevel);
+ src_box.height = u_minify(pt->height0, srcLevel);
+ src_box.depth = u_minify(pt->depth0, srcLevel);
+ dst_box.width = u_minify(pt->width0, dstLevel);
+ dst_box.height = u_minify(pt->height0, dstLevel);
+ dst_box.depth = u_minify(pt->depth0, dstLevel);
+
+ srcMap = pipe->transfer_map(pipe, pt, srcLevel,
+ PIPE_TRANSFER_READ,
+ &src_box, &srcTrans);
+ dstMap = pipe->transfer_map(pipe, pt, dstLevel,
+ PIPE_TRANSFER_WRITE,
+ &dst_box, &dstTrans);
reduce_3d(pt->format,
- srcTrans->width, srcTrans->height,
- srcTrans->stride, srcMap,
- dstTrans->width, dstTrans->height,
- dstTrans->stride, dstMap);
+ srcTrans->box.width, srcTrans->box.height, srcTrans->box.depth,
+ srcTrans->stride, srcTrans->layer_stride, srcMap,
+ dstTrans->box.width, dstTrans->box.height, dstTrans->box.depth,
+ dstTrans->stride, dstTrans->layer_stride, dstMap);
pipe->transfer_unmap(pipe, srcTrans);
pipe->transfer_unmap(pipe, dstTrans);
-
- pipe->tex_transfer_destroy(pipe, srcTrans);
- pipe->tex_transfer_destroy(pipe, dstTrans);
}
-#else
- (void) reduce_3d;
-#endif
}
static void
fallback_gen_mipmap(struct gen_mipmap_state *ctx,
- struct pipe_texture *pt,
- uint face, uint baseLevel, uint lastLevel)
+ struct pipe_resource *pt,
+ uint layer, uint baseLevel, uint lastLevel)
{
switch (pt->target) {
case PIPE_TEXTURE_1D:
- make_1d_mipmap(ctx, pt, face, baseLevel, lastLevel);
+ make_1d_mipmap(ctx, pt, layer, baseLevel, lastLevel);
break;
case PIPE_TEXTURE_2D:
+ case PIPE_TEXTURE_RECT:
case PIPE_TEXTURE_CUBE:
- make_2d_mipmap(ctx, pt, face, baseLevel, lastLevel);
+ make_2d_mipmap(ctx, pt, layer, baseLevel, lastLevel);
break;
case PIPE_TEXTURE_3D:
- make_3d_mipmap(ctx, pt, face, baseLevel, lastLevel);
+ make_3d_mipmap(ctx, pt, layer, baseLevel, lastLevel);
break;
default:
assert(0);
ctx->cso = cso;
/* disabled blending/masking */
- memset(&ctx->blend, 0, sizeof(ctx->blend));
- ctx->blend.rt[0].colormask = PIPE_MASK_RGBA;
+ memset(&ctx->blend_keep_color, 0, sizeof(ctx->blend_keep_color));
+ memset(&ctx->blend_write_color, 0, sizeof(ctx->blend_write_color));
+ ctx->blend_write_color.rt[0].colormask = PIPE_MASK_RGBA;
/* no-op depth/stencil/alpha */
- memset(&ctx->depthstencil, 0, sizeof(ctx->depthstencil));
+ memset(&ctx->dsa_keep_depth, 0, sizeof(ctx->dsa_keep_depth));
+ memset(&ctx->dsa_write_depth, 0, sizeof(ctx->dsa_write_depth));
+ ctx->dsa_write_depth.depth.enabled = 1;
+ ctx->dsa_write_depth.depth.func = PIPE_FUNC_ALWAYS;
+ ctx->dsa_write_depth.depth.writemask = 1;
/* rasterizer */
memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer));
- ctx->rasterizer.front_winding = PIPE_WINDING_CW;
- ctx->rasterizer.cull_mode = PIPE_WINDING_NONE;
- ctx->rasterizer.gl_rasterization_rules = 1;
+ ctx->rasterizer.cull_face = PIPE_FACE_NONE;
+ ctx->rasterizer.half_pixel_center = 1;
+ ctx->rasterizer.bottom_edge_rule = 1;
+ ctx->rasterizer.depth_clip = 1;
/* sampler state */
memset(&ctx->sampler, 0, sizeof(ctx->sampler));
for (i = 0; i < 2; i++) {
ctx->velem[i].src_offset = i * 4 * sizeof(float);
ctx->velem[i].instance_divisor = 0;
- ctx->velem[i].vertex_buffer_index = 0;
+ ctx->velem[i].vertex_buffer_index = cso_get_aux_vertex_buffer_slot(cso);
ctx->velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
}
- /* vertex shader - still needed to specify mapping from fragment
- * shader input semantics to vertex elements
- */
- {
- const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
- TGSI_SEMANTIC_GENERIC };
- const uint semantic_indexes[] = { 0, 0 };
- ctx->vs = util_make_vertex_passthrough_shader(pipe, 2, semantic_names,
- semantic_indexes);
- }
-
- /* fragment shader */
- ctx->fs2d = util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_2D);
- ctx->fsCube = util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_CUBE);
-
/* vertex data that doesn't change */
for (i = 0; i < 4; i++) {
ctx->vertices[i][0][2] = 0.0f; /* z */
}
+/**
+ * Helper function to set the fragment shaders.
+ */
+static INLINE void
+set_fragment_shader(struct gen_mipmap_state *ctx, uint type,
+ boolean output_depth)
+{
+ if (output_depth) {
+ if (!ctx->fs_depth[type])
+ ctx->fs_depth[type] =
+ util_make_fragment_tex_shader_writedepth(ctx->pipe, type,
+ TGSI_INTERPOLATE_LINEAR);
+
+ cso_set_fragment_shader_handle(ctx->cso, ctx->fs_depth[type]);
+ }
+ else {
+ if (!ctx->fs_color[type])
+ ctx->fs_color[type] =
+ util_make_fragment_tex_shader(ctx->pipe, type,
+ TGSI_INTERPOLATE_LINEAR);
+
+ cso_set_fragment_shader_handle(ctx->cso, ctx->fs_color[type]);
+ }
+}
+
+
+/**
+ * Helper function to set the vertex shader.
+ */
+static INLINE void
+set_vertex_shader(struct gen_mipmap_state *ctx)
+{
+ /* vertex shader - still required to provide the linkage between
+ * fragment shader input semantics and vertex_element/buffers.
+ */
+ if (!ctx->vs)
+ {
+ const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
+ TGSI_SEMANTIC_GENERIC };
+ const uint semantic_indexes[] = { 0, 0 };
+ ctx->vs = util_make_vertex_passthrough_shader(ctx->pipe, 2,
+ semantic_names,
+ semantic_indexes);
+ }
+
+ cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
+}
+
+
/**
* Get next "slot" of vertex space in the vertex buffer.
* We're allocating one large vertex buffer and using it piece by piece.
{
const unsigned max_slots = 4096 / sizeof ctx->vertices;
- if (ctx->vbuf_slot >= max_slots)
- util_gen_mipmap_flush( ctx );
+ if (ctx->vbuf_slot >= max_slots) {
+ pipe_resource_reference(&ctx->vbuf, NULL);
+ ctx->vbuf_slot = 0;
+ }
if (!ctx->vbuf) {
ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
- 32,
- PIPE_BUFFER_USAGE_VERTEX,
+ PIPE_BIND_VERTEX_BUFFER,
+ PIPE_USAGE_STREAM,
max_slots * sizeof ctx->vertices);
}
static unsigned
set_vertex_data(struct gen_mipmap_state *ctx,
enum pipe_texture_target tex_target,
- uint face)
+ uint layer, float r)
{
unsigned offset;
{0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}
};
- util_map_texcoords2d_onto_cubemap(face, &st[0][0], 2,
- &ctx->vertices[0][1][0], 8);
+ util_map_texcoords2d_onto_cubemap(layer, &st[0][0], 2,
+ &ctx->vertices[0][1][0], 8,
+ FALSE);
}
- else {
- /* 1D/2D */
+ else if (tex_target == PIPE_TEXTURE_1D_ARRAY) {
+ /* 1D texture array */
+ ctx->vertices[0][1][0] = 0.0f; /*s*/
+ ctx->vertices[0][1][1] = r; /*t*/
+ ctx->vertices[0][1][2] = 0.0f; /*r*/
+
+ ctx->vertices[1][1][0] = 1.0f;
+ ctx->vertices[1][1][1] = r;
+ ctx->vertices[1][1][2] = 0.0f;
+
+ ctx->vertices[2][1][0] = 1.0f;
+ ctx->vertices[2][1][1] = r;
+ ctx->vertices[2][1][2] = 0.0f;
+
+ ctx->vertices[3][1][0] = 0.0f;
+ ctx->vertices[3][1][1] = r;
+ ctx->vertices[3][1][2] = 0.0f;
+ } else {
+ /* 1D/2D/3D/2D array */
ctx->vertices[0][1][0] = 0.0f; /*s*/
ctx->vertices[0][1][1] = 0.0f; /*t*/
- ctx->vertices[0][1][2] = 0.0f; /*r*/
+ ctx->vertices[0][1][2] = r; /*r*/
ctx->vertices[1][1][0] = 1.0f;
ctx->vertices[1][1][1] = 0.0f;
- ctx->vertices[1][1][2] = 0.0f;
+ ctx->vertices[1][1][2] = r;
ctx->vertices[2][1][0] = 1.0f;
ctx->vertices[2][1][1] = 1.0f;
- ctx->vertices[2][1][2] = 0.0f;
+ ctx->vertices[2][1][2] = r;
ctx->vertices[3][1][0] = 0.0f;
ctx->vertices[3][1][1] = 1.0f;
- ctx->vertices[3][1][2] = 0.0f;
+ ctx->vertices[3][1][2] = r;
}
offset = get_next_slot( ctx );
- pipe_buffer_write_nooverlap(ctx->pipe->screen, ctx->vbuf,
+ pipe_buffer_write_nooverlap(ctx->pipe, ctx->vbuf,
offset, sizeof(ctx->vertices), ctx->vertices);
return offset;
util_destroy_gen_mipmap(struct gen_mipmap_state *ctx)
{
struct pipe_context *pipe = ctx->pipe;
+ unsigned i;
- pipe->delete_vs_state(pipe, ctx->vs);
- pipe->delete_fs_state(pipe, ctx->fs2d);
- pipe->delete_fs_state(pipe, ctx->fsCube);
-
- pipe_buffer_reference(&ctx->vbuf, NULL);
+ for (i = 0; i < Elements(ctx->fs_color); i++)
+ if (ctx->fs_color[i])
+ pipe->delete_fs_state(pipe, ctx->fs_color[i]);
- FREE(ctx);
-}
+ for (i = 0; i < Elements(ctx->fs_depth); i++)
+ if (ctx->fs_depth[i])
+ pipe->delete_fs_state(pipe, ctx->fs_depth[i]);
+ if (ctx->vs)
+ pipe->delete_vs_state(pipe, ctx->vs);
+ pipe_resource_reference(&ctx->vbuf, NULL);
-/* Release vertex buffer at end of frame to avoid synchronous
- * rendering.
- */
-void util_gen_mipmap_flush( struct gen_mipmap_state *ctx )
-{
- pipe_buffer_reference(&ctx->vbuf, NULL);
- ctx->vbuf_slot = 0;
-}
+ FREE(ctx);
+}
/**
struct pipe_context *pipe = ctx->pipe;
struct pipe_screen *screen = pipe->screen;
struct pipe_framebuffer_state fb;
- struct pipe_texture *pt = psv->texture;
- void *fs = (pt->target == PIPE_TEXTURE_CUBE) ? ctx->fsCube : ctx->fs2d;
+ struct pipe_resource *pt = psv->texture;
uint dstLevel;
- uint zslice = 0;
uint offset;
+ uint type;
+ boolean is_depth = util_format_is_depth_or_stencil(psv->format);
/* The texture object should have room for the levels which we're
* about to generate.
assert(filter == PIPE_TEX_FILTER_LINEAR ||
filter == PIPE_TEX_FILTER_NEAREST);
+ switch (pt->target) {
+ case PIPE_TEXTURE_1D:
+ type = TGSI_TEXTURE_1D;
+ break;
+ case PIPE_TEXTURE_2D:
+ type = TGSI_TEXTURE_2D;
+ break;
+ case PIPE_TEXTURE_3D:
+ type = TGSI_TEXTURE_3D;
+ break;
+ case PIPE_TEXTURE_CUBE:
+ type = TGSI_TEXTURE_CUBE;
+ break;
+ case PIPE_TEXTURE_1D_ARRAY:
+ type = TGSI_TEXTURE_1D_ARRAY;
+ break;
+ case PIPE_TEXTURE_2D_ARRAY:
+ type = TGSI_TEXTURE_2D_ARRAY;
+ break;
+ default:
+ assert(0);
+ type = TGSI_TEXTURE_2D;
+ }
+
/* check if we can render in the texture's format */
- if (!screen->is_format_supported(screen, psv->format, PIPE_TEXTURE_2D,
- PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
+ if (!screen->is_format_supported(screen, psv->format, pt->target,
+ pt->nr_samples,
+ is_depth ? PIPE_BIND_DEPTH_STENCIL :
+ PIPE_BIND_RENDER_TARGET)) {
fallback_gen_mipmap(ctx, pt, face, baseLevel, lastLevel);
return;
}
cso_save_blend(ctx->cso);
cso_save_depth_stencil_alpha(ctx->cso);
cso_save_rasterizer(ctx->cso);
- cso_save_samplers(ctx->cso);
- cso_save_fragment_sampler_views(ctx->cso);
+ cso_save_sample_mask(ctx->cso);
+ cso_save_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
+ cso_save_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
+ cso_save_stream_outputs(ctx->cso);
cso_save_framebuffer(ctx->cso);
cso_save_fragment_shader(ctx->cso);
cso_save_vertex_shader(ctx->cso);
+ cso_save_geometry_shader(ctx->cso);
cso_save_viewport(ctx->cso);
- cso_save_clip(ctx->cso);
cso_save_vertex_elements(ctx->cso);
+ cso_save_aux_vertex_buffer_slot(ctx->cso);
+ cso_save_render_condition(ctx->cso);
/* bind our state */
- cso_set_blend(ctx->cso, &ctx->blend);
- cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil);
+ cso_set_blend(ctx->cso, is_depth ? &ctx->blend_keep_color :
+ &ctx->blend_write_color);
+ cso_set_depth_stencil_alpha(ctx->cso, is_depth ? &ctx->dsa_write_depth :
+ &ctx->dsa_keep_depth);
cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
- cso_set_clip(ctx->cso, &ctx->clip);
+ cso_set_sample_mask(ctx->cso, ~0);
cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
+ cso_set_stream_outputs(ctx->cso, 0, NULL, NULL);
+ cso_set_render_condition(ctx->cso, NULL, FALSE, 0);
- cso_set_fragment_shader_handle(ctx->cso, fs);
- cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
+ set_fragment_shader(ctx, type, is_depth);
+ set_vertex_shader(ctx);
+ cso_set_geometry_shader_handle(ctx->cso, NULL);
/* init framebuffer state */
memset(&fb, 0, sizeof(fb));
- fb.nr_cbufs = 1;
/* set min/mag to same filter for faster sw speed */
ctx->sampler.mag_img_filter = filter;
ctx->sampler.min_img_filter = filter;
- /*
- * XXX for small mipmap levels, it may be faster to use the software
- * fallback path...
- */
for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
const uint srcLevel = dstLevel - 1;
struct pipe_viewport_state vp;
-
- struct pipe_surface *surf =
- screen->get_tex_surface(screen, pt, face, dstLevel, zslice,
- PIPE_BUFFER_USAGE_GPU_WRITE);
-
- /*
- * Setup framebuffer / dest surface
- */
- fb.cbufs[0] = surf;
- fb.width = u_minify(pt->width0, dstLevel);
- fb.height = u_minify(pt->height0, dstLevel);
- cso_set_framebuffer(ctx->cso, &fb);
-
- /* viewport */
- vp.scale[0] = 0.5f * fb.width;
- vp.scale[1] = 0.5f * fb.height;
- 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(ctx->cso, &vp);
-
- /*
- * Setup sampler state
- * Note: we should only have to set the min/max LOD clamps to ensure
- * we grab texels from the right mipmap level. But some hardware
- * has trouble with min clamping so we also set the lod_bias to
- * try to work around that.
- */
- ctx->sampler.min_lod = ctx->sampler.max_lod = (float) srcLevel;
- ctx->sampler.lod_bias = (float) srcLevel;
- cso_single_sampler(ctx->cso, 0, &ctx->sampler);
- cso_single_sampler_done(ctx->cso);
-
- cso_set_fragment_sampler_views(ctx->cso, 1, &psv);
-
- /* quad coords in clip coords */
- offset = set_vertex_data(ctx,
- pt->target,
- face);
-
- util_draw_vertex_buffer(ctx->pipe,
- ctx->vbuf,
- offset,
- PIPE_PRIM_TRIANGLE_FAN,
- 4, /* verts */
- 2); /* attribs/vert */
-
- pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
-
- /* need to signal that the texture has changed _after_ rendering to it */
- pipe_surface_reference( &surf, NULL );
+ unsigned nr_layers, layer, i;
+ float rcoord = 0.0f;
+
+ if (pt->target == PIPE_TEXTURE_3D)
+ nr_layers = u_minify(pt->depth0, dstLevel);
+ else if (pt->target == PIPE_TEXTURE_2D_ARRAY || pt->target == PIPE_TEXTURE_1D_ARRAY)
+ nr_layers = pt->array_size;
+ else
+ nr_layers = 1;
+
+ for (i = 0; i < nr_layers; i++) {
+ struct pipe_surface *surf, surf_templ;
+ if (pt->target == PIPE_TEXTURE_3D) {
+ /* in theory with geom shaders and driver with full layer support
+ could do that in one go. */
+ layer = i;
+ /* XXX hmm really? */
+ rcoord = (float)layer / (float)nr_layers + 1.0f / (float)(nr_layers * 2);
+ } else if (pt->target == PIPE_TEXTURE_2D_ARRAY || pt->target == PIPE_TEXTURE_1D_ARRAY) {
+ layer = i;
+ rcoord = (float)layer;
+ } else
+ layer = face;
+
+ u_surface_default_template(&surf_templ, pt);
+ surf_templ.u.tex.level = dstLevel;
+ surf_templ.u.tex.first_layer = layer;
+ surf_templ.u.tex.last_layer = layer;
+ surf = pipe->create_surface(pipe, pt, &surf_templ);
+
+ /*
+ * Setup framebuffer / dest surface
+ */
+ if (is_depth) {
+ fb.nr_cbufs = 0;
+ fb.zsbuf = surf;
+ }
+ else {
+ fb.nr_cbufs = 1;
+ fb.cbufs[0] = surf;
+ }
+ fb.width = u_minify(pt->width0, dstLevel);
+ fb.height = u_minify(pt->height0, dstLevel);
+ cso_set_framebuffer(ctx->cso, &fb);
+
+ /* viewport */
+ vp.scale[0] = 0.5f * fb.width;
+ vp.scale[1] = 0.5f * fb.height;
+ 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(ctx->cso, &vp);
+
+ /*
+ * Setup sampler state
+ * Note: we should only have to set the min/max LOD clamps to ensure
+ * we grab texels from the right mipmap level. But some hardware
+ * has trouble with min clamping so we also set the lod_bias to
+ * try to work around that.
+ */
+ ctx->sampler.min_lod = ctx->sampler.max_lod = (float) srcLevel;
+ ctx->sampler.lod_bias = (float) srcLevel;
+ cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
+ cso_single_sampler_done(ctx->cso, PIPE_SHADER_FRAGMENT);
+
+ cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &psv);
+
+ /* quad coords in clip coords */
+ offset = set_vertex_data(ctx,
+ pt->target,
+ face,
+ rcoord);
+
+ util_draw_vertex_buffer(ctx->pipe,
+ ctx->cso,
+ ctx->vbuf,
+ cso_get_aux_vertex_buffer_slot(ctx->cso),
+ offset,
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ 2); /* attribs/vert */
+
+ /* need to signal that the texture has changed _after_ rendering to it */
+ pipe_surface_reference( &surf, NULL );
+ }
}
/* restore state we changed */
cso_restore_blend(ctx->cso);
cso_restore_depth_stencil_alpha(ctx->cso);
cso_restore_rasterizer(ctx->cso);
- cso_restore_samplers(ctx->cso);
- cso_restore_fragment_sampler_views(ctx->cso);
+ cso_restore_sample_mask(ctx->cso);
+ cso_restore_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
+ cso_restore_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
cso_restore_framebuffer(ctx->cso);
cso_restore_fragment_shader(ctx->cso);
cso_restore_vertex_shader(ctx->cso);
+ cso_restore_geometry_shader(ctx->cso);
cso_restore_viewport(ctx->cso);
- cso_restore_clip(ctx->cso);
cso_restore_vertex_elements(ctx->cso);
+ cso_restore_stream_outputs(ctx->cso);
+ cso_restore_aux_vertex_buffer_slot(ctx->cso);
+ cso_restore_render_condition(ctx->cso);
}