summaryrefslogtreecommitdiff
path: root/src/mesa/state_tracker
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/state_tracker')
-rw-r--r--src/mesa/state_tracker/st_atom_sampler.c2
-rw-r--r--src/mesa/state_tracker/st_atom_shader.c8
-rw-r--r--src/mesa/state_tracker/st_cb_clear.c2
-rw-r--r--src/mesa/state_tracker/st_cb_drawpixels.c8
-rw-r--r--src/mesa/state_tracker/st_cb_program.c4
-rw-r--r--src/mesa/state_tracker/st_cb_readpixels.c99
-rw-r--r--src/mesa/state_tracker/st_cb_texture.c127
-rw-r--r--src/mesa/state_tracker/st_context.h9
-rw-r--r--src/mesa/state_tracker/st_gen_mipmap.c158
-rw-r--r--src/mesa/state_tracker/st_program.c2
-rw-r--r--src/mesa/state_tracker/st_program.h2
-rw-r--r--src/mesa/state_tracker/st_texture.c39
-rw-r--r--src/mesa/state_tracker/st_texture.h7
13 files changed, 302 insertions, 165 deletions
diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c
index 6241e70b55..92263cb688 100644
--- a/src/mesa/state_tracker/st_atom_sampler.c
+++ b/src/mesa/state_tracker/st_atom_sampler.c
@@ -147,7 +147,7 @@ update_samplers(struct st_context *st)
sampler.lod_bias = st->ctx->Texture.Unit[su].LodBias;
#if 1
- sampler.min_lod = texobj->MinLod;
+ sampler.min_lod = (texobj->MinLod) < 0.0 ? 0.0 : texobj->MinLod;
sampler.max_lod = texobj->MaxLod;
#else
/* min/max lod should really be as follows (untested).
diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c
index 9196918509..2c6ec8421b 100644
--- a/src/mesa/state_tracker/st_atom_shader.c
+++ b/src/mesa/state_tracker/st_atom_shader.c
@@ -158,7 +158,7 @@ find_translated_vp(struct st_context *st,
/*
* Translate fragment program if needed.
*/
- if (!stfp->fs) {
+ if (!stfp->cso) {
GLuint inAttr, numIn = 0;
for (inAttr = 0; inAttr < FRAG_ATTRIB_MAX; inAttr++) {
@@ -179,7 +179,7 @@ find_translated_vp(struct st_context *st,
stfp->input_to_slot,
stfp->tokens,
ST_MAX_SHADER_TOKENS);
- assert(stfp->fs);
+ assert(stfp->cso);
}
@@ -227,7 +227,7 @@ find_translated_vp(struct st_context *st,
if (fpInAttrib >= 0) {
GLuint fpInSlot = stfp->input_to_slot[fpInAttrib];
if (fpInSlot != ~0) {
- GLuint vpOutSlot = stfp->fs->state.input_map[fpInSlot];
+ GLuint vpOutSlot = stfp->cso->state.input_map[fpInSlot];
xvp->output_to_slot[outAttr] = vpOutSlot;
numVpOuts++;
}
@@ -300,7 +300,7 @@ update_linkage( struct st_context *st )
st->pipe->bind_vs_state(st->pipe, st->state.vs->cso->data);
st->fp = stfp;
- st->state.fs = stfp->fs;
+ st->state.fs = stfp->cso;
st->pipe->bind_fs_state(st->pipe, st->state.fs->data);
st->vertex_result_to_slot = xvp->output_to_slot;
diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c
index ab98b54bab..410062e1e8 100644
--- a/src/mesa/state_tracker/st_cb_clear.c
+++ b/src/mesa/state_tracker/st_cb_clear.c
@@ -341,7 +341,7 @@ clear_with_quad(GLcontext *ctx,
if (!stfp) {
stfp = make_frag_shader(st);
}
- pipe->bind_fs_state(pipe, stfp->fs->data);
+ pipe->bind_fs_state(pipe, stfp->cso->data);
}
/* vertex shader state: color/position pass-through */
diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c
index 07886e7982..3245a7488b 100644
--- a/src/mesa/state_tracker/st_cb_drawpixels.c
+++ b/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -471,7 +471,7 @@ make_texture(struct st_context *st,
assert(pipeFormat);
cpp = st_sizeof_format(pipeFormat);
- pt = st_texture_create(st, PIPE_TEXTURE_2D, pipeFormat, 0, 0, width, height,
+ pt = st_texture_create(st, PIPE_TEXTURE_2D, pipeFormat, 0, width, height,
1, 0);
if (!pt)
return NULL;
@@ -665,7 +665,7 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
}
/* fragment shader state: TEX lookup program */
- pipe->bind_fs_state(pipe, stfp->fs->data);
+ pipe->bind_fs_state(pipe, stfp->cso->data);
/* vertex shader state: position + texcoord pass-through */
pipe->bind_vs_state(pipe, stvp->cso->data);
@@ -1017,7 +1017,7 @@ make_bitmap_texture(GLcontext *ctx, GLsizei width, GLsizei height,
/**
* Create a texture.
*/
- pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, format, 0, 0, width, height,
+ pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, format, 0, width, height,
1, 0);
if (!pt)
return NULL;
@@ -1241,7 +1241,7 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
psRead = rbRead->surface;
format = psRead->format;
- pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, format, 0, 0, width, height,
+ pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, format, 0, width, height,
1, 0);
if (!pt)
return;
diff --git a/src/mesa/state_tracker/st_cb_program.c b/src/mesa/state_tracker/st_cb_program.c
index f1f33fb0dd..af3ee65504 100644
--- a/src/mesa/state_tracker/st_cb_program.c
+++ b/src/mesa/state_tracker/st_cb_program.c
@@ -168,10 +168,10 @@ static void st_program_string_notify( GLcontext *ctx,
stfp->serialNo++;
- if (stfp->fs) {
+ if (stfp->cso) {
/* free the TGSI code */
// cso_delete(stfp->vs);
- stfp->fs = NULL;
+ stfp->cso = NULL;
}
stfp->param_state = stfp->Base.Base.Parameters->StateFlags;
diff --git a/src/mesa/state_tracker/st_cb_readpixels.c b/src/mesa/state_tracker/st_cb_readpixels.c
index a1bbb3a831..868c5f3c5f 100644
--- a/src/mesa/state_tracker/st_cb_readpixels.c
+++ b/src/mesa/state_tracker/st_cb_readpixels.c
@@ -180,20 +180,13 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
if (!strb)
return;
+
if (format == GL_RGBA && type == GL_FLOAT) {
/* write tile(row) directly into user's buffer */
df = (GLfloat *) _mesa_image_address2d(&clippedPacking, dest, width,
height, format, type, 0, 0);
dfStride = width * 4;
}
-#if 0
- else if (format == GL_DEPTH_COMPONENT && type == GL_FLOAT) {
- /* write tile(row) directly into user's buffer */
- df = (GLfloat *) _mesa_image_address2d(&clippedPacking, dest, width,
- height, format, type, 0, 0);
- dfStride = width;
- }
-#endif
else {
/* write tile(row) into temp row buffer */
df = (GLfloat *) temp;
@@ -209,22 +202,86 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
yStep = 1;
}
- /* Do a row at a time to flip image data vertically */
- for (i = 0; i < height; i++) {
- pipe_get_tile_rgba(pipe, strb->surface, x, y, width, 1, df);
- y += yStep;
- df += dfStride;
- if (!dfStride) {
- /* convert GLfloat to user's format/type */
- GLvoid *dst = _mesa_image_address2d(&clippedPacking, dest, width,
- height, format, type, i, 0);
+ /*
+ * Copy pixels from pipe_surface to user memory
+ */
+ {
+ /* dest of first pixel in client memory */
+ GLubyte *dst = _mesa_image_address2d(&clippedPacking, dest, width,
+ height, format, type, 0, 0);
+ /* dest row stride */
+ const GLint dstStride = _mesa_image_row_stride(&clippedPacking, width,
+ format, type);
+
+ if (strb->surface->format == PIPE_FORMAT_S8Z24_UNORM) {
if (format == GL_DEPTH_COMPONENT) {
- _mesa_pack_depth_span(ctx, width, dst, type,
- (GLfloat *) temp, &clippedPacking);
+ for (i = 0; i < height; i++) {
+ GLuint ztemp[MAX_WIDTH], j;
+ GLfloat zfloat[MAX_WIDTH];
+ const double scale = 1.0 / ((1 << 24) - 1);
+ pipe_get_tile_raw(pipe, strb->surface, x, y,
+ width, 1, ztemp, 0);
+ y += yStep;
+ for (j = 0; j < width; j++) {
+ zfloat[j] = (float) (scale * (ztemp[j] & 0xffffff));
+ }
+ _mesa_pack_depth_span(ctx, width, dst, type,
+ zfloat, &clippedPacking);
+ dst += dstStride;
+ }
}
else {
- _mesa_pack_rgba_span_float(ctx, width, temp, format, type, dst,
- &clippedPacking, transferOps);
+ /* untested, but simple: */
+ assert(format == GL_DEPTH_STENCIL_EXT);
+ for (i = 0; i < height; i++) {
+ pipe_get_tile_raw(pipe, strb->surface, x, y, width, 1, dst, 0);
+ y += yStep;
+ dst += dstStride;
+ }
+ }
+ }
+ else if (strb->surface->format == PIPE_FORMAT_Z16_UNORM) {
+ for (i = 0; i < height; i++) {
+ GLshort ztemp[MAX_WIDTH], j;
+ GLfloat zfloat[MAX_WIDTH];
+ const double scale = 1.0 / 0xffff;
+ pipe_get_tile_raw(pipe, strb->surface, x, y, width, 1, ztemp, 0);
+ y += yStep;
+ for (j = 0; j < width; j++) {
+ zfloat[j] = (float) (scale * ztemp[j]);
+ }
+ _mesa_pack_depth_span(ctx, width, dst, type,
+ zfloat, &clippedPacking);
+ dst += dstStride;
+ }
+ }
+ else if (strb->surface->format == PIPE_FORMAT_Z32_UNORM) {
+ for (i = 0; i < height; i++) {
+ GLuint ztemp[MAX_WIDTH], j;
+ GLfloat zfloat[MAX_WIDTH];
+ const double scale = 1.0 / 0xffffffff;
+ pipe_get_tile_raw(pipe, strb->surface, x, y, width, 1, ztemp, 0);
+ y += yStep;
+ for (j = 0; j < width; j++) {
+ zfloat[j] = (float) (scale * ztemp[j]);
+ }
+ _mesa_pack_depth_span(ctx, width, dst, type,
+ zfloat, &clippedPacking);
+ dst += dstStride;
+ }
+ }
+ else {
+ /* RGBA format */
+ /* Do a row at a time to flip image data vertically */
+ for (i = 0; i < height; i++) {
+ pipe_get_tile_rgba(pipe, strb->surface, x, y, width, 1, df);
+ y += yStep;
+ df += dfStride;
+ if (!dfStride) {
+ _mesa_pack_rgba_span_float(ctx, width, temp, format, type, dst,
+ &clippedPacking, transferOps);
+ dst += dstStride;
+ }
}
}
}
diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c
index 3350254654..0ea367549b 100644
--- a/src/mesa/state_tracker/st_cb_texture.c
+++ b/src/mesa/state_tracker/st_cb_texture.c
@@ -57,15 +57,10 @@ struct st_texture_object
{
struct gl_texture_object base; /* The "parent" object */
- /* The texture must include at least these levels once validated:
+ /* The texture must include at levels [0..lastLevel] once validated:
*/
- GLuint firstLevel;
GLuint lastLevel;
- /* Offset for firstLevel image:
- */
- GLuint textureOffset;
-
/* On validation any active images held in main memory or in other
* textures will be copied to this texture and the old storage freed.
*/
@@ -368,7 +363,6 @@ guess_and_alloc_texture(struct st_context *st,
stObj->pt = st_texture_create(st,
gl_target_to_pipe(stObj->base.Target),
st_mesa_format_to_pipe_format(stImage->base.TexFormat->MesaFormat),
- firstLevel,
lastLevel,
width,
height,
@@ -379,26 +373,6 @@ guess_and_alloc_texture(struct st_context *st,
}
-
-
-static GLuint
-target_to_face(GLenum target)
-{
- switch (target) {
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
- return ((GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X);
- default:
- return 0;
- }
-}
-
-
-
/* There are actually quite a few combinations this will work for,
* more than what I've listed here.
*/
@@ -487,6 +461,43 @@ try_pbo_upload(GLcontext *ctx,
}
+/**
+ * Adjust pixel unpack params and image dimensions to strip off the
+ * texture border.
+ * Gallium doesn't support texture borders. They've seldem been used
+ * and seldom been implemented correctly anyway.
+ * \param unpackNew returns the new pixel unpack parameters
+ */
+static void
+strip_texture_border(GLint border,
+ GLint *width, GLint *height, GLint *depth,
+ const struct gl_pixelstore_attrib *unpack,
+ struct gl_pixelstore_attrib *unpackNew)
+{
+ assert(border > 0); /* sanity check */
+
+ *unpackNew = *unpack;
+
+ if (unpackNew->RowLength == 0)
+ unpackNew->RowLength = *width;
+
+ if (depth && unpackNew->ImageHeight == 0)
+ unpackNew->ImageHeight = *height;
+
+ unpackNew->SkipPixels += border;
+ if (height)
+ unpackNew->SkipRows += border;
+ if (depth)
+ unpackNew->SkipImages += border;
+
+ assert(*width >= 3);
+ *width = *width - 2 * border;
+ if (height && *height >= 3)
+ *height = *height - 2 * border;
+ if (depth && *depth >= 3)
+ *depth = *depth - 2 * border;
+}
+
static void
st_TexImage(GLcontext * ctx,
@@ -503,16 +514,26 @@ st_TexImage(GLcontext * ctx,
{
struct st_texture_object *stObj = st_texture_object(texObj);
struct st_texture_image *stImage = st_texture_image(texImage);
- GLint postConvWidth = width;
- GLint postConvHeight = height;
+ GLint postConvWidth, postConvHeight;
GLint texelBytes, sizeInBytes;
GLuint dstRowStride;
-
+ struct gl_pixelstore_attrib unpackNB;
DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(target), level, width, height, depth, border);
- stImage->face = target_to_face(target);
+ /* gallium does not support texture borders, strip it off */
+ if (border) {
+ strip_texture_border(border, &width, &height, &depth,
+ unpack, &unpackNB);
+ unpack = &unpackNB;
+ border = 0;
+ }
+
+ postConvWidth = width;
+ postConvHeight = height;
+
+ stImage->face = _mesa_tex_target_to_face(target);
stImage->level = level;
if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
@@ -558,12 +579,12 @@ st_TexImage(GLcontext * ctx,
_mesa_align_free(texImage->Data);
}
- /* If this is the only texture image in the texture, could call
+ /* If this is the only mipmap level in the texture, could call
* bmBufferData with NULL data to free the old block and avoid
* waiting on any outstanding fences.
*/
if (stObj->pt &&
- stObj->pt->first_level == level &&
+ /*stObj->pt->first_level == level &&*/
stObj->pt->last_level == level &&
stObj->pt->target != PIPE_TEXTURE_CUBE &&
!st_texture_match_image(stObj->pt, &stImage->base,
@@ -1336,13 +1357,8 @@ calculate_first_last_level(struct st_texture_object *stObj)
firstLevel = lastLevel = tObj->BaseLevel;
}
else {
- firstLevel = tObj->BaseLevel + (GLint) (tObj->MinLod + 0.5);
- firstLevel = MAX2(firstLevel, tObj->BaseLevel);
- lastLevel = tObj->BaseLevel + (GLint) (tObj->MaxLod + 0.5);
- lastLevel = MAX2(lastLevel, tObj->BaseLevel);
- lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
- lastLevel = MIN2(lastLevel, tObj->MaxLevel);
- lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
+ firstLevel = 0;
+ lastLevel = MIN2(tObj->MaxLevel - tObj->BaseLevel, baseImage->MaxLog2);
}
break;
case GL_TEXTURE_RECTANGLE_NV:
@@ -1353,8 +1369,6 @@ calculate_first_last_level(struct st_texture_object *stObj)
return;
}
- /* save these values */
- stObj->firstLevel = firstLevel;
stObj->lastLevel = lastLevel;
}
@@ -1362,15 +1376,16 @@ calculate_first_last_level(struct st_texture_object *stObj)
static void
copy_image_data_to_texture(struct st_context *st,
struct st_texture_object *stObj,
+ GLuint dstLevel,
struct st_texture_image *stImage)
{
if (stImage->pt) {
/* Copy potentially with the blitter:
*/
st_texture_image_copy(st->pipe,
- stObj->pt, /* dest texture */
- stImage->face, stImage->level,
- stImage->pt /* src texture */
+ stObj->pt, dstLevel, /* dest texture, level */
+ stImage->pt, /* src texture */
+ stImage->face
);
st->pipe->texture_release(st->pipe, &stImage->pt);
@@ -1411,7 +1426,7 @@ st_finalize_texture(GLcontext *ctx,
const GLuint nr_faces = (stObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
int comp_byte = 0;
int cpp;
- GLuint face, i;
+ GLuint face;
struct st_texture_image *firstImage;
*needFlush = GL_FALSE;
@@ -1423,7 +1438,7 @@ st_finalize_texture(GLcontext *ctx,
/* What levels must the texture include at a minimum?
*/
calculate_first_last_level(stObj);
- firstImage = st_texture_image(stObj->base.Image[0][stObj->firstLevel]);
+ firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]);
/* Fallback case:
*/
@@ -1442,7 +1457,6 @@ st_finalize_texture(GLcontext *ctx,
*/
if (firstImage->pt &&
firstImage->pt != stObj->pt &&
- firstImage->pt->first_level <= stObj->firstLevel &&
firstImage->pt->last_level >= stObj->lastLevel) {
if (stObj->pt)
@@ -1461,18 +1475,11 @@ st_finalize_texture(GLcontext *ctx,
/* Check texture can hold all active levels. Check texture matches
* target, imageFormat, etc.
- *
- * XXX: For some layouts (eg i945?), the test might have to be
- * first_level == firstLevel, as the texture isn't valid except at the
- * original start level. Hope to get around this by
- * programming minLod, maxLod, baseLevel into the hardware and
- * leaving the texture alone.
*/
if (stObj->pt &&
(stObj->pt->target != gl_target_to_pipe(stObj->base.Target) ||
stObj->pt->format !=
st_mesa_format_to_pipe_format(firstImage->base.TexFormat->MesaFormat) ||
- stObj->pt->first_level != stObj->firstLevel ||
stObj->pt->last_level != stObj->lastLevel ||
stObj->pt->width[0] != firstImage->base.Width ||
stObj->pt->height[0] != firstImage->base.Height ||
@@ -1489,7 +1496,6 @@ st_finalize_texture(GLcontext *ctx,
stObj->pt = st_texture_create(ctx->st,
gl_target_to_pipe(stObj->base.Target),
st_mesa_format_to_pipe_format(firstImage->base.TexFormat->MesaFormat),
- stObj->firstLevel,
stObj->lastLevel,
firstImage->base.Width,
firstImage->base.Height,
@@ -1500,14 +1506,15 @@ st_finalize_texture(GLcontext *ctx,
/* Pull in any images not in the object's texture:
*/
for (face = 0; face < nr_faces; face++) {
- for (i = stObj->firstLevel; i <= stObj->lastLevel; i++) {
+ GLuint level;
+ for (level = 0; level <= stObj->lastLevel; level++) {
struct st_texture_image *stImage =
- st_texture_image(stObj->base.Image[face][i]);
+ st_texture_image(stObj->base.Image[face][stObj->base.BaseLevel + level]);
/* Need to import images in main memory or held in other textures.
*/
- if (stObj->pt != stImage->pt) {
- copy_image_data_to_texture(ctx->st, stObj, stImage);
+ if (stImage && stObj->pt != stImage->pt) {
+ copy_image_data_to_texture(ctx->st, stObj, level, stImage);
*needFlush = GL_TRUE;
}
}
diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h
index a756055898..59d1590f05 100644
--- a/src/mesa/state_tracker/st_context.h
+++ b/src/mesa/state_tracker/st_context.h
@@ -166,6 +166,15 @@ struct st_context
struct st_fragment_program *combined_prog;
} bitmap;
+ /** For gen/render mipmap feature */
+ struct {
+ void *blend_cso;
+ void *depthstencil_cso;
+ void *rasterizer_cso;
+ struct st_fragment_program *stfp;
+ struct st_vertex_program *stvp;
+ } gen_mipmap;
+
struct cso_cache *cache;
};
diff --git a/src/mesa/state_tracker/st_gen_mipmap.c b/src/mesa/state_tracker/st_gen_mipmap.c
index a6ac9a55fb..459941cca8 100644
--- a/src/mesa/state_tracker/st_gen_mipmap.c
+++ b/src/mesa/state_tracker/st_gen_mipmap.c
@@ -29,11 +29,14 @@
#include "main/imports.h"
#include "main/mipmap.h"
#include "main/teximage.h"
+#include "main/texformat.h"
#include "shader/prog_instruction.h"
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_winsys.h"
#include "pipe/cso_cache/cso_cache.h"
#include "st_context.h"
@@ -45,16 +48,6 @@
-static void *blend_cso = NULL;
-static void *depthstencil_cso = NULL;
-static void *rasterizer_cso = NULL;
-static void *sampler_cso = NULL;
-
-static struct st_fragment_program *stfp = NULL;
-static struct st_vertex_program *stvp = NULL;
-
-
-
static struct st_fragment_program *
make_tex_fragment_program(GLcontext *ctx)
{
@@ -115,33 +108,20 @@ st_init_generate_mipmap(struct st_context *st)
struct pipe_context *pipe = st->pipe;
struct pipe_blend_state blend;
struct pipe_rasterizer_state rasterizer;
- struct pipe_sampler_state sampler;
struct pipe_depth_stencil_alpha_state depthstencil;
- assert(!blend_cso);
-
memset(&blend, 0, sizeof(blend));
blend.colormask = PIPE_MASK_RGBA;
- blend_cso = pipe->create_blend_state(pipe, &blend);
+ st->gen_mipmap.blend_cso = pipe->create_blend_state(pipe, &blend);
memset(&depthstencil, 0, sizeof(depthstencil));
- depthstencil_cso = pipe->create_depth_stencil_alpha_state(pipe, &depthstencil);
+ st->gen_mipmap.depthstencil_cso = pipe->create_depth_stencil_alpha_state(pipe, &depthstencil);
memset(&rasterizer, 0, sizeof(rasterizer));
- rasterizer_cso = pipe->create_rasterizer_state(pipe, &rasterizer);
+ st->gen_mipmap.rasterizer_cso = pipe->create_rasterizer_state(pipe, &rasterizer);
- memset(&sampler, 0, sizeof(sampler));
- sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
- sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
- sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
- sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
- sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
- sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
- sampler.normalized_coords = 1;
- sampler_cso = pipe->create_sampler_state(pipe, &sampler);
-
- stfp = make_tex_fragment_program(st->ctx);
- stvp = st_make_passthrough_vertex_shader(st, GL_FALSE);
+ st->gen_mipmap.stfp = make_tex_fragment_program(st->ctx);
+ st->gen_mipmap.stvp = st_make_passthrough_vertex_shader(st, GL_FALSE);
}
@@ -150,17 +130,11 @@ st_destroy_generate_mipmpap(struct st_context *st)
{
struct pipe_context *pipe = st->pipe;
- pipe->delete_blend_state(pipe, blend_cso);
- pipe->delete_depth_stencil_alpha_state(pipe, depthstencil_cso);
- pipe->delete_rasterizer_state(pipe, rasterizer_cso);
- pipe->delete_sampler_state(pipe, sampler_cso);
+ pipe->delete_blend_state(pipe, st->gen_mipmap.blend_cso);
+ pipe->delete_depth_stencil_alpha_state(pipe, st->gen_mipmap.depthstencil_cso);
+ pipe->delete_rasterizer_state(pipe, st->gen_mipmap.rasterizer_cso);
/* XXX free stfp, stvp */
-
- blend_cso = NULL;
- depthstencil_cso = NULL;
- rasterizer_cso = NULL;
- sampler_cso = NULL;
}
@@ -239,15 +213,20 @@ draw_quad(GLcontext *ctx)
*/
static boolean
st_render_mipmap(struct st_context *st,
+ GLenum target,
struct pipe_texture *pt,
uint baseLevel, uint lastLevel)
{
struct pipe_context *pipe = st->pipe;
struct pipe_framebuffer_state fb;
- const uint face = 0, zslice = 0;
- const uint first_level_save = pt->first_level;
+ struct pipe_sampler_state sampler;
+ void *sampler_cso;
+ const uint face = _mesa_tex_target_to_face(target), zslice = 0;
+ /*const uint first_level_save = pt->first_level;*/
uint dstLevel;
+ assert(target != GL_TEXTURE_3D); /* not done yet */
+
/* check if we can render in the texture's format */
if (!pipe->is_format_supported(pipe, pt->format, PIPE_SURFACE)) {
return FALSE;
@@ -257,16 +236,30 @@ st_render_mipmap(struct st_context *st,
memset(&fb, 0, sizeof(fb));
fb.num_cbufs = 1;
+ /* sampler state */
+ memset(&sampler, 0, sizeof(sampler));
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
+ sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
+ sampler.normalized_coords = 1;
+
+
/* bind CSOs */
- pipe->bind_blend_state(pipe, blend_cso);
- pipe->bind_depth_stencil_alpha_state(pipe, depthstencil_cso);
- pipe->bind_rasterizer_state(pipe, rasterizer_cso);
- pipe->bind_sampler_state(pipe, 0, sampler_cso);
+ pipe->bind_blend_state(pipe, st->gen_mipmap.blend_cso);
+ pipe->bind_depth_stencil_alpha_state(pipe, st->gen_mipmap.depthstencil_cso);
+ pipe->bind_rasterizer_state(pipe, st->gen_mipmap.rasterizer_cso);
/* bind shaders */
- pipe->bind_fs_state(pipe, stfp->fs->data);
- pipe->bind_vs_state(pipe, stvp->cso->data);
+ pipe->bind_fs_state(pipe, st->gen_mipmap.stfp->cso->data);
+ pipe->bind_vs_state(pipe, st->gen_mipmap.stvp->cso->data);
+ /*
+ * 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;
@@ -276,20 +269,29 @@ st_render_mipmap(struct st_context *st,
fb.cbufs[0] = pipe->get_tex_surface(pipe, pt, face, dstLevel, zslice);
pipe->set_framebuffer_state(pipe, &fb);
+ /*
+ * Setup sampler state
+ */
+ sampler.min_lod = sampler.max_lod = srcLevel;
+ sampler_cso = pipe->create_sampler_state(pipe, &sampler);
+ pipe->bind_sampler_state(pipe, 0, sampler_cso);
+
simple_viewport(pipe, pt->width[dstLevel], pt->height[dstLevel]);
/*
* Setup src texture, override pt->first_level so we sample from
* the right mipmap level.
*/
- pt->first_level = srcLevel;
+ /*pt->first_level = srcLevel;*/
pipe->set_sampler_texture(pipe, 0, pt);
draw_quad(st->ctx);
+
+ pipe->delete_sampler_state(pipe, sampler_cso);
}
/* restore first_level */
- pt->first_level = first_level_save;
+ /*pt->first_level = first_level_save;*/
/* restore pipe state */
if (st->state.rasterizer)
@@ -307,6 +309,58 @@ st_render_mipmap(struct st_context *st,
}
+static void
+fallback_generate_mipmap(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *texObj)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct pipe_winsys *ws = pipe->winsys;
+ struct pipe_texture *pt = st_get_texobj_texture(texObj);
+ const uint baseLevel = texObj->BaseLevel;
+ const uint lastLevel = pt->last_level;
+ const uint face = _mesa_tex_target_to_face(target), zslice = 0;
+ uint dstLevel;
+ GLenum datatype;
+ GLuint comps;
+
+ assert(target != GL_TEXTURE_3D); /* not done yet */
+
+ _mesa_format_to_type_and_comps(texObj->Image[face][baseLevel]->TexFormat,
+ &datatype, &comps);
+
+ for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
+ const uint srcLevel = dstLevel - 1;
+ struct pipe_surface *srcSurf, *dstSurf;
+ const ubyte *srcData;
+ ubyte *dstData;
+
+ srcSurf = pipe->get_tex_surface(pipe, pt, face, srcLevel, zslice);
+ dstSurf = pipe->get_tex_surface(pipe, pt, face, dstLevel, zslice);
+
+ srcData = (ubyte *) ws->buffer_map(ws, srcSurf->buffer,
+ PIPE_BUFFER_USAGE_CPU_READ)
+ + srcSurf->offset;
+ dstData = (ubyte *) ws->buffer_map(ws, dstSurf->buffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE)
+ + dstSurf->offset;
+
+ _mesa_generate_mipmap_level(target, datatype, comps,
+ 0 /*border*/,
+ pt->width[srcLevel], pt->height[srcLevel], pt->depth[srcLevel],
+ srcSurf->pitch * srcSurf->cpp, /* stride in bytes */
+ srcData,
+ pt->width[dstLevel], pt->height[dstLevel], pt->depth[dstLevel],
+ dstSurf->pitch * dstSurf->cpp, /* stride in bytes */
+ dstData);
+
+ ws->buffer_unmap(ws, srcSurf->buffer);
+ ws->buffer_unmap(ws, dstSurf->buffer);
+
+ pipe_surface_reference(&srcSurf, NULL);
+ pipe_surface_reference(&dstSurf, NULL);
+ }
+}
+
void
st_generate_mipmap(GLcontext *ctx, GLenum target,
@@ -318,13 +372,11 @@ st_generate_mipmap(GLcontext *ctx, GLenum target,
const uint lastLevel = pt->last_level;
uint dstLevel;
- if (!st_render_mipmap(st, pt, baseLevel, lastLevel)) {
- abort();
- /* XXX the following won't really work at this time */
- _mesa_generate_mipmap(ctx, target, texObj);
- return;
+ if (!st_render_mipmap(st, target, pt, baseLevel, lastLevel)) {
+ 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
@@ -336,7 +388,6 @@ st_generate_mipmap(GLcontext *ctx, GLenum target,
uint dstDepth = pt->depth[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");
@@ -359,5 +410,4 @@ st_generate_mipmap(GLcontext *ctx, GLenum target,
stImage = (struct st_texture_image *) dstImage;
stImage->pt = pt;
}
-
}
diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c
index 84a9094001..c8297baded 100644
--- a/src/mesa/state_tracker/st_program.c
+++ b/src/mesa/state_tracker/st_program.c
@@ -420,7 +420,7 @@ st_translate_fragment_program(struct st_context *st,
fs.tokens = tokensOut;
cso = st_cached_fs_state(st, &fs);
- stfp->fs = cso;
+ stfp->cso = cso;
if (0)
_mesa_print_program(&stfp->Base.Base);
diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h
index de02c3185f..ea1dde4a7a 100644
--- a/src/mesa/state_tracker/st_program.h
+++ b/src/mesa/state_tracker/st_program.h
@@ -62,7 +62,7 @@ struct st_fragment_program
struct tgsi_token tokens[ST_MAX_SHADER_TOKENS];
/** Pointer to the corresponding cached shader */
- const struct cso_fragment_shader *fs;
+ const struct cso_fragment_shader *cso;
GLuint param_state;
diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c
index 844a9f80d8..2622d00953 100644
--- a/src/mesa/state_tracker/st_texture.c
+++ b/src/mesa/state_tracker/st_texture.c
@@ -62,12 +62,14 @@ target_to_target(GLenum target)
/**
* Allocate a new pipe_texture object
+ * width0, height0, depth0 are the dimensions of the level 0 image
+ * (the highest resolution). last_level indicates how many mipmap levels
+ * to allocate storage for. For non-mipmapped textures, this will be zero.
*/
struct pipe_texture *
st_texture_create(struct st_context *st,
enum pipe_texture_target target,
enum pipe_format format,
- GLuint first_level,
GLuint last_level,
GLuint width0,
GLuint height0,
@@ -78,15 +80,15 @@ st_texture_create(struct st_context *st,
assert(target <= PIPE_TEXTURE_CUBE);
- DBG("%s target %s format %s level %d..%d\n", __FUNCTION__,
+ DBG("%s target %s format %s last_level %d\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(target),
- _mesa_lookup_enum_by_nr(format), first_level, last_level);
+ _mesa_lookup_enum_by_nr(format), last_level);
assert(format);
+ memset(&pt, 0, sizeof(pt));
pt.target = target;
pt.format = format;
- pt.first_level = first_level;
pt.last_level = last_level;
pt.width[0] = width0;
pt.height[0] = height0;
@@ -266,23 +268,36 @@ st_texture_image_data(struct pipe_context *pipe,
*/
void
st_texture_image_copy(struct pipe_context *pipe,
- struct pipe_texture *dst,
- GLuint face, GLuint level,
- struct pipe_texture *src)
+ struct pipe_texture *dst, GLuint dstLevel,
+ struct pipe_texture *src,
+ GLuint face)
{
- GLuint width = src->width[level];
- GLuint height = src->height[level];
- GLuint depth = src->depth[level];
+ GLuint width = dst->width[dstLevel];
+ GLuint height = dst->height[dstLevel];
+ GLuint depth = dst->depth[dstLevel];
struct pipe_surface *src_surface;
struct pipe_surface *dst_surface;
GLuint i;
+ /* XXX this is a hack */
if (dst->compressed)
height /= 4;
for (i = 0; i < depth; i++) {
- dst_surface = pipe->get_tex_surface(pipe, dst, face, level, i);
- src_surface = pipe->get_tex_surface(pipe, src, face, level, i);
+ GLuint srcLevel;
+
+ /* find src texture level of needed size */
+ for (srcLevel = 0; srcLevel <= src->last_level; srcLevel++) {
+ if (src->width[srcLevel] == width &&
+ src->height[srcLevel] == height) {
+ break;
+ }
+ }
+ assert(src->width[srcLevel] == width);
+ assert(src->height[srcLevel] == height);
+
+ dst_surface = pipe->get_tex_surface(pipe, dst, face, dstLevel, i);
+ src_surface = pipe->get_tex_surface(pipe, src, face, srcLevel, i);
pipe->surface_copy(pipe,
dst_surface,
diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h
index 0b87a494c3..72324cd9ab 100644
--- a/src/mesa/state_tracker/st_texture.h
+++ b/src/mesa/state_tracker/st_texture.h
@@ -39,7 +39,6 @@ extern struct pipe_texture *
st_texture_create(struct st_context *st,
enum pipe_texture_target target,
enum pipe_format format,
- GLuint first_level,
GLuint last_level,
GLuint width0,
GLuint height0,
@@ -98,9 +97,9 @@ st_texture_image_data(struct pipe_context *pipe,
*/
extern void
st_texture_image_copy(struct pipe_context *pipe,
- struct pipe_texture *dst,
- GLuint face, GLuint level,
- struct pipe_texture *src);
+ struct pipe_texture *dst, GLuint dstLevel,
+ struct pipe_texture *src,
+ GLuint face);
#endif