diff options
| author | Ben Skeggs <skeggsb@gmail.com> | 2008-02-13 14:21:23 +1100 |
|---|---|---|
| committer | Ben Skeggs <skeggsb@gmail.com> | 2008-02-13 14:21:23 +1100 |
| commit | b397a2bb203c2b28b746af7828d9ad192cde0bc1 (patch) | |
| tree | 77448bf1db79ae112f057717109aaa98e5696b15 /src/mesa/state_tracker | |
| parent | 5ba3dbe2cc8a9af5cae01f45eaf497f834400170 (diff) | |
| parent | e20e89e48287808068086ec148920dd89495d813 (diff) | |
Merge branch 'upstream-gallium-0.1' into darktama-gallium-0.1
Diffstat (limited to 'src/mesa/state_tracker')
| -rw-r--r-- | src/mesa/state_tracker/st_atom_sampler.c | 2 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_atom_shader.c | 8 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_cb_clear.c | 2 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_cb_drawpixels.c | 8 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_cb_program.c | 4 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_cb_readpixels.c | 99 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_cb_texture.c | 127 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_context.h | 9 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_gen_mipmap.c | 158 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_program.c | 2 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_program.h | 2 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_texture.c | 39 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_texture.h | 7 |
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 |
