diff options
Diffstat (limited to 'src/mesa/state_tracker')
-rw-r--r-- | src/mesa/state_tracker/st_atom_sampler.c | 9 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_atom_texture.c | 20 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_drawtex.c | 312 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_drawtex.h | 18 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_fbo.c | 8 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_texture.c | 292 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_texture.h | 3 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_context.c | 12 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_gen_mipmap.c | 9 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_texture.c | 31 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_texture.h | 12 |
11 files changed, 525 insertions, 201 deletions
diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c index a8262a5e1a..92fe72d4df 100644 --- a/src/mesa/state_tracker/st_atom_sampler.c +++ b/src/mesa/state_tracker/st_atom_sampler.c @@ -194,9 +194,12 @@ update_samplers(struct st_context *st) sampler->normalized_coords = 1; sampler->lod_bias = st->ctx->Texture.Unit[su].LodBias; - sampler->min_lod = MAX2(0.0f, texobj->MinLod); - sampler->max_lod = MIN2(texobj->MaxLevel - texobj->BaseLevel, - texobj->MaxLod); + + sampler->min_lod = texobj->BaseLevel + texobj->MinLod; + if (sampler->min_lod < texobj->BaseLevel) + sampler->min_lod = texobj->BaseLevel; + + sampler->max_lod = MIN2((GLfloat) texobj->MaxLevel, texobj->MaxLod); if (sampler->max_lod < sampler->min_lod) { /* The GL spec doesn't seem to specify what to do in this case. * Swap the values. diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c index f4294ac1e6..d403b7db1e 100644 --- a/src/mesa/state_tracker/st_atom_texture.c +++ b/src/mesa/state_tracker/st_atom_texture.c @@ -62,7 +62,7 @@ update_textures(struct st_context *st) if (samplersUsed & (1 << su)) { struct gl_texture_object *texObj; struct st_texture_object *stObj; - GLboolean flush, retval; + GLboolean retval; GLuint texUnit; if (fprog->Base.SamplersUsed & (1 << su)) @@ -77,7 +77,7 @@ update_textures(struct st_context *st) } stObj = st_texture_object(texObj); - retval = st_finalize_texture(st->ctx, st->pipe, texObj, &flush); + retval = st_finalize_texture(st->ctx, st->pipe, texObj); if (!retval) { /* out of mem */ continue; @@ -88,15 +88,6 @@ update_textures(struct st_context *st) sampler_view = st_get_texture_sampler_view(stObj, pipe); } - /* - if (pt) { - printf("%s su=%u non-null\n", __FUNCTION__, su); - } - else { - printf("%s su=%u null\n", __FUNCTION__, su); - } - */ - pipe_sampler_view_reference(&st->state.sampler_views[su], sampler_view); } @@ -138,19 +129,16 @@ finalize_textures(struct st_context *st) const GLuint texUnit = fprog->Base.SamplerUnits[su]; struct gl_texture_object *texObj = st->ctx->Texture.Unit[texUnit]._Current; - struct st_texture_object *stObj = st_texture_object(texObj); if (texObj) { - GLboolean flush, retval; + GLboolean retval; - retval = st_finalize_texture(st->ctx, st->pipe, texObj, &flush); + retval = st_finalize_texture(st->ctx, st->pipe, texObj); if (!retval) { /* out of mem */ st->missing_textures = GL_TRUE; continue; } - - stObj->teximage_realloc = TRUE; } } } diff --git a/src/mesa/state_tracker/st_cb_drawtex.c b/src/mesa/state_tracker/st_cb_drawtex.c new file mode 100644 index 0000000000..6d387d5ccf --- /dev/null +++ b/src/mesa/state_tracker/st_cb_drawtex.c @@ -0,0 +1,312 @@ +/************************************************************************** + * + * 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/bufferobj.h" +#include "main/drawtex.h" +#include "main/macros.h" +#include "main/state.h" +#include "main/texformat.h" +#include "shader/program.h" +#include "shader/prog_parameter.h" +#include "shader/prog_print.h" + +#include "st_context.h" +#include "st_atom.h" +#include "st_atom_constbuf.h" +#include "st_draw.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_tile.h" +#include "util/u_draw_quad.h" +#include "util/u_simple_shaders.h" + +#include "cso_cache/cso_context.h" + + +struct cached_shader +{ + //struct pipe_shader_state 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; + + +#if FEATURE_OES_draw_texture + + +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(GLcontext *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, + 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, vbuffer_transfer); + +#undef SET_ATTRIB + } + + + cso_save_viewport(cso); + cso_save_vertex_shader(cso); + cso_save_vertex_elements(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, 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); +} + + +#endif /* FEATURE_OES_draw_texture */ + + +void +st_init_drawtex_functions(struct dd_function_table *functions) +{ + _MESA_INIT_DRAWTEX_FUNCTIONS(functions, st_); +} + + +/** + * 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; +} diff --git a/src/mesa/state_tracker/st_cb_drawtex.h b/src/mesa/state_tracker/st_cb_drawtex.h new file mode 100644 index 0000000000..7b0da70279 --- /dev/null +++ b/src/mesa/state_tracker/st_cb_drawtex.h @@ -0,0 +1,18 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + **************************************************************************/ + + +#ifndef ST_CB_DRAWTEX_H +#define ST_CB_DRAWTEX_H + +extern void +st_init_drawtex_functions(struct dd_function_table *functions); + +extern void +st_destroy_drawtex(struct st_context *st); + +#endif /* ST_CB_DRAWTEX_H */ diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c index e5c956d561..c02121fbd1 100644 --- a/src/mesa/state_tracker/st_cb_fbo.c +++ b/src/mesa/state_tracker/st_cb_fbo.c @@ -321,15 +321,13 @@ st_render_texture(GLcontext *ctx, struct pipe_resource *pt = st_get_texobj_resource(att->Texture); struct st_texture_object *stObj; const struct gl_texture_image *texImage; - GLint pt_level; /* When would this fail? Perhaps assert? */ if (!pt) return; - /* The first gallium texture level = Mesa BaseLevel */ - pt_level = MAX2(0, (GLint) att->TextureLevel - att->Texture->BaseLevel); - texImage = att->Texture->Image[att->CubeMapFace][pt_level]; + /* get pointer to texture image we're rendeing to */ + texImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel]; /* create new renderbuffer which wraps the texture image */ rb = st_new_renderbuffer(ctx, 0); @@ -350,7 +348,7 @@ st_render_texture(GLcontext *ctx, /* point renderbuffer at texobject */ strb->rtt = stObj; - strb->rtt_level = pt_level; + strb->rtt_level = att->TextureLevel; strb->rtt_face = att->CubeMapFace; strb->rtt_slice = att->Zoffset; diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index 3457214ca4..ed8eb2929a 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -27,9 +27,6 @@ #include "main/mfeatures.h" #include "main/bufferobj.h" -#if FEATURE_convolve -#include "main/convolve.h" -#endif #include "main/enums.h" #include "main/fbobject.h" #include "main/formats.h" @@ -231,93 +228,114 @@ default_bindings(struct st_context *st, enum pipe_format format) } +/** Return number of image dimensions (1, 2 or 3) for a texture target. */ +static GLuint +get_texture_dims(GLenum target) +{ + switch (target) { + case GL_TEXTURE_1D: + case GL_TEXTURE_1D_ARRAY_EXT: + return 1; + case GL_TEXTURE_2D: + case GL_TEXTURE_CUBE_MAP_ARB: + case GL_TEXTURE_RECTANGLE_NV: + case GL_TEXTURE_2D_ARRAY_EXT: + return 2; + case GL_TEXTURE_3D: + return 3; + default: + assert(0 && "invalid texture target in get_texture_dims()"); + return 1; + } +} + + /** - * Allocate a pipe_resource object for the given st_texture_object using - * the given st_texture_image to guess the mipmap size/levels. - * - * [comments...] - * Otherwise, store it in memory if (Border != 0) or (any dimension == - * 1). - * - * Otherwise, if max_level >= level >= min_level, create texture with - * space for images from min_level down to max_level. + * Try to allocate a pipe_resource object for the given st_texture_object. * - * Otherwise, create texture with space for images from (level 0)..(1x1). - * Consider pruning this texture at a validation if the saving is worth it. + * We use the given st_texture_image as a clue to determine the size of the + * mipmap image at level=0. */ static void guess_and_alloc_texture(struct st_context *st, struct st_texture_object *stObj, const struct st_texture_image *stImage) { - GLuint firstLevel; - GLuint lastLevel; - GLuint width = stImage->base.Width2; /* size w/out border */ - GLuint height = stImage->base.Height2; - GLuint depth = stImage->base.Depth2; - GLuint i, bindings; + const GLuint dims = get_texture_dims(stObj->base.Target); + GLuint level, lastLevel, width, height, depth; + GLuint bindings; enum pipe_format fmt; DBG("%s\n", __FUNCTION__); assert(!stObj->pt); - if (stObj->pt && - (GLint) stImage->level > stObj->base.BaseLevel && - (stImage->base.Width == 1 || - (stObj->base.Target != GL_TEXTURE_1D && - stImage->base.Height == 1) || - (stObj->base.Target == GL_TEXTURE_3D && - stImage->base.Depth == 1))) - return; - - /* If this image disrespects BaseLevel, allocate from level zero. - * Usually BaseLevel == 0, so it's unlikely to happen. - */ - if ((GLint) stImage->level < stObj->base.BaseLevel) - firstLevel = 0; - else - firstLevel = stObj->base.BaseLevel; + level = stImage->level; + width = stImage->base.Width2; /* size w/out border */ + height = stImage->base.Height2; + depth = stImage->base.Depth2; + assert(width > 0); + assert(height > 0); + assert(depth > 0); - /* Figure out image dimensions at start level. + /* Depending on the image's size, we can't always make a guess here. */ - for (i = stImage->level; i > firstLevel; i--) { + if (level > 0) { + if ( (dims >= 1 && width == 1) || + (dims >= 2 && height == 1) || + (dims >= 3 && depth == 1) ) { + /* we can't determine the image size at level=0 */ + stObj->width0 = stObj->height0 = stObj->depth0 = 0; + return; + } + } + + /* grow the image size until we hit level = 0 */ + while (level > 0) { if (width != 1) width <<= 1; if (height != 1) height <<= 1; if (depth != 1) depth <<= 1; - } + level--; + } - if (width == 0 || height == 0 || depth == 0) { - /* no texture needed */ - return; - } + assert(level == 0); + + /* At this point, (width x height x depth) is the expected size of + * the level=0 mipmap image. + */ - /* Guess a reasonable value for lastLevel. This is probably going - * to be wrong fairly often and might mean that we have to look at - * resizable buffers, or require that buffers implement lazy - * pagetable arrangements. + /* Guess a reasonable value for lastLevel. With OpenGL we have no + * idea how many mipmap levels will be in a texture until we start + * to render with it. Make an educated guess here but be prepared + * to re-allocating a texture buffer with space for more (or fewer) + * mipmap levels later. */ if ((stObj->base.MinFilter == GL_NEAREST || stObj->base.MinFilter == GL_LINEAR || stImage->base._BaseFormat == GL_DEPTH_COMPONENT || stImage->base._BaseFormat == GL_DEPTH_STENCIL_EXT) && !stObj->base.GenerateMipmap && - stImage->level == firstLevel) { + stImage->level == 0) { /* only alloc space for a single mipmap level */ - lastLevel = firstLevel; + lastLevel = 0; } else { /* alloc space for a full mipmap */ GLuint l2width = util_logbase2(width); GLuint l2height = util_logbase2(height); GLuint l2depth = util_logbase2(depth); - lastLevel = firstLevel + MAX2(MAX2(l2width, l2height), l2depth); + lastLevel = MAX2(MAX2(l2width, l2height), l2depth); } + /* Save the level=0 dimensions */ + stObj->width0 = width; + stObj->height0 = height; + stObj->depth0 = depth; + fmt = st_mesa_format_to_pipe_format(stImage->base.TexFormat); bindings = default_bindings(st, fmt); @@ -507,8 +525,6 @@ st_TexImage(GLcontext * ctx, struct pipe_screen *screen = st->pipe->screen; struct st_texture_object *stObj = st_texture_object(texObj); struct st_texture_image *stImage = st_texture_image(texImage); - GLint postConvWidth, postConvHeight; - GLint texelBytes, sizeInBytes; GLuint dstRowStride = 0; struct gl_pixelstore_attrib unpackNB; enum pipe_transfer_usage transfer_usage = 0; @@ -516,6 +532,12 @@ st_TexImage(GLcontext * ctx, DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__, _mesa_lookup_enum_by_nr(target), level, width, height, depth, border); + /* The Mesa/Gallium state tracker does not implement the imaging extensions + * such as convolution. + */ + assert(!ctx->Extensions.ARB_imaging); + assert(!ctx->Extensions.EXT_convolution); + /* switch to "normal" */ if (stObj->surface_based) { _mesa_clear_texture_object(ctx, texObj); @@ -532,39 +554,17 @@ st_TexImage(GLcontext * ctx, texImage->Border = 0; border = 0; } - - postConvWidth = width; - postConvHeight = height; + else { + assert(texImage->Width == width); + assert(texImage->Height == height); + assert(texImage->Depth == depth); + } stImage->face = _mesa_tex_target_to_face(target); stImage->level = level; -#if FEATURE_convolve - if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) { - _mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth, - &postConvHeight); - } -#endif - _mesa_set_fetch_functions(texImage, dims); - if (_mesa_is_format_compressed(texImage->TexFormat)) { - /* must be a compressed format */ - texelBytes = 0; - } - else { - texelBytes = _mesa_get_format_bytes(texImage->TexFormat); - - /* Minimum pitch of 32 bytes */ - if (postConvWidth * texelBytes < 32) { - postConvWidth = 32 / texelBytes; - texImage->RowStride = postConvWidth; - } - - /* we'll set RowStride elsewhere when the texture is a "mapped" state */ - /*assert(texImage->RowStride == postConvWidth);*/ - } - /* Release the reference to a potentially orphaned buffer. * Release any old malloced memory. */ @@ -581,15 +581,13 @@ st_TexImage(GLcontext * ctx, * mipmap. If so, free the old mipmap. */ if (stObj->pt) { - if (stObj->teximage_realloc || - level > (GLint) stObj->pt->last_level || + if (level > (GLint) stObj->pt->last_level || !st_texture_match_image(stObj->pt, &stImage->base, stImage->face, stImage->level)) { DBG("release it\n"); pipe_resource_reference(&stObj->pt, NULL); assert(!stObj->pt); pipe_sampler_view_reference(&stObj->sampler_view, NULL); - stObj->teximage_realloc = FALSE; } } @@ -615,9 +613,13 @@ st_TexImage(GLcontext * ctx, assert(!stImage->pt); + /* Check if this texture image can live inside the texture object's buffer. + * If so, store the image there. Otherwise the image will temporarily live + * in its own buffer. + */ if (stObj->pt && st_texture_match_image(stObj->pt, &stImage->base, - stImage->face, stImage->level)) { + stImage->face, stImage->level)) { pipe_resource_reference(&stImage->pt, stObj->pt); assert(stImage->pt); @@ -626,9 +628,11 @@ st_TexImage(GLcontext * ctx, if (!stImage->pt) DBG("XXX: Image did not fit into texture - storing in local memory!\n"); - /* st_CopyTexImage calls this function with pixels == NULL, with - * the expectation that the texture will be set up but nothing - * more will be done. This is where those calls return: + /* Pixel data may come from regular user memory or a PBO. For the later, + * do bounds checking and map the PBO to read pixels data from it. + * + * XXX we should try to use a GPU-accelerated path to copy the image data + * from the PBO to the texture. */ if (compressed_src) { pixels = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, pixels, @@ -641,10 +645,6 @@ st_TexImage(GLcontext * ctx, pixels, unpack, "glTexImage"); } - /* Note: we can't check for pixels==NULL until after we've allocated - * memory for the texture. - */ - /* See if we can do texture compression with a blit/render. */ if (!compressed_src && @@ -663,7 +663,12 @@ st_TexImage(GLcontext * ctx, } } + /* + * Prepare to store the texture data. Either map the gallium texture buffer + * memory or malloc space for it. + */ if (stImage->pt) { + /* Store the image in the gallium texture memory buffer */ if (format == GL_DEPTH_COMPONENT && util_format_is_depth_and_stencil(stImage->pt->format)) transfer_usage = PIPE_TRANSFER_READ_WRITE; @@ -671,28 +676,17 @@ st_TexImage(GLcontext * ctx, transfer_usage = PIPE_TRANSFER_WRITE; texImage->Data = st_texture_image_map(st, stImage, 0, - transfer_usage, 0, 0, - stImage->base.Width, - stImage->base.Height); + transfer_usage, 0, 0, width, height); if(stImage->transfer) dstRowStride = stImage->transfer->stride; } else { /* Allocate regular memory and store the image there temporarily. */ - if (_mesa_is_format_compressed(texImage->TexFormat)) { - sizeInBytes = _mesa_format_image_size(texImage->TexFormat, - texImage->Width, - texImage->Height, - texImage->Depth); - dstRowStride = _mesa_format_row_stride(texImage->TexFormat, width); - assert(dims != 3); - } - else { - dstRowStride = postConvWidth * texelBytes; - sizeInBytes = depth * dstRowStride * postConvHeight; - } + GLuint imageSize = _mesa_format_image_size(texImage->TexFormat, + width, height, depth); + dstRowStride = _mesa_format_row_stride(texImage->TexFormat, width); - texImage->Data = _mesa_align_malloc(sizeInBytes, 16); + texImage->Data = _mesa_align_malloc(imageSize, 16); } if (!texImage->Data) { @@ -700,33 +694,33 @@ st_TexImage(GLcontext * ctx, return; } - if (!pixels) + if (!pixels) { + /* We've allocated texture memory, but have no pixel data - all done. */ goto done; + } DBG("Upload image %dx%dx%d row_len %x pitch %x\n", - width, height, depth, width * texelBytes, dstRowStride); + width, height, depth, width, dstRowStride); - /* Copy data. Would like to know when it's ok for us to eg. use - * the blitter to copy. Or, use the hardware to do the format - * conversion and copy: + /* Copy user texture image into the texture buffer. */ if (compressed_src) { - const GLuint srcImageStride = _mesa_format_row_stride(texImage->TexFormat, width); - if(dstRowStride == srcImageStride) + const GLuint srcRowStride = + _mesa_format_row_stride(texImage->TexFormat, width); + if (dstRowStride == srcRowStride) { memcpy(texImage->Data, pixels, imageSize); - else - { + } + else { char *dst = texImage->Data; const char *src = pixels; GLuint i, bw, bh, lines; _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh); lines = (height + bh - 1) / bh; - for(i = 0; i < lines; ++i) - { - memcpy(dst, src, srcImageStride); + for (i = 0; i < lines; ++i) { + memcpy(dst, src, srcRowStride); dst += dstRowStride; - src += srcImageStride; + src += srcRowStride; } } } @@ -755,8 +749,7 @@ st_TexImage(GLcontext * ctx, /* map next slice of 3D texture */ texImage->Data = st_texture_image_map(st, stImage, i + 1, transfer_usage, 0, 0, - stImage->base.Width, - stImage->base.Height); + width, height); src += srcImageStride; } } @@ -1757,12 +1750,26 @@ st_CopyTexSubImage3D(GLcontext * ctx, GLenum target, GLint level, } +/** + * Copy image data from stImage into the texture object 'stObj' at level + * 'dstLevel'. + */ static void copy_image_data_to_texture(struct st_context *st, struct st_texture_object *stObj, GLuint dstLevel, struct st_texture_image *stImage) { + /* debug checks */ + { + const struct gl_texture_image *dstImage = + stObj->base.Image[stImage->face][stImage->level]; + assert(dstImage); + assert(dstImage->Width == stImage->base.Width); + assert(dstImage->Height == stImage->base.Height); + assert(dstImage->Depth == stImage->base.Depth); + } + if (stImage->pt) { /* Copy potentially with the blitter: */ @@ -1805,16 +1812,14 @@ copy_image_data_to_texture(struct st_context *st, GLboolean st_finalize_texture(GLcontext *ctx, struct pipe_context *pipe, - struct gl_texture_object *tObj, - GLboolean *needFlush) + struct gl_texture_object *tObj) { struct st_context *st = st_context(ctx); struct st_texture_object *stObj = st_texture_object(tObj); const GLuint nr_faces = (stObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; - GLuint blockSize, face; + GLuint face; struct st_texture_image *firstImage; - - *needFlush = GL_FALSE; + enum pipe_format firstImageFormat; if (stObj->base._Complete) { /* The texture is complete and we know exactly how many mipmap levels @@ -1827,10 +1832,11 @@ st_finalize_texture(GLcontext *ctx, stObj->base.MinFilter == GL_NEAREST) stObj->lastLevel = stObj->base.BaseLevel; else - stObj->lastLevel = stObj->base._MaxLevel - stObj->base.BaseLevel; + stObj->lastLevel = stObj->base._MaxLevel; } firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]); + assert(firstImage); /* If both firstImage and stObj point to a texture which can contain * all active images, favour firstImage. Note that because of the @@ -1844,22 +1850,23 @@ st_finalize_texture(GLcontext *ctx, pipe_sampler_view_reference(&stObj->sampler_view, NULL); } - /* bytes per pixel block (blocks are usually 1x1) */ - blockSize = _mesa_get_format_bytes(firstImage->base.TexFormat); + /* Find gallium format for the Mesa texture */ + firstImageFormat = st_mesa_format_to_pipe_format(firstImage->base.TexFormat); /* If we already have a gallium texture, check that it matches the texture * object's format, target, size, num_levels, etc. */ if (stObj->pt) { - const enum pipe_format fmt = - st_mesa_format_to_pipe_format(firstImage->base.TexFormat); if (stObj->pt->target != gl_target_to_pipe(stObj->base.Target) || - stObj->pt->format != fmt || + stObj->pt->format != firstImageFormat || stObj->pt->last_level < stObj->lastLevel || - stObj->pt->width0 != firstImage->base.Width2 || - stObj->pt->height0 != firstImage->base.Height2 || - stObj->pt->depth0 != firstImage->base.Depth2) + stObj->pt->width0 != stObj->width0 || + stObj->pt->height0 != stObj->height0 || + stObj->pt->depth0 != stObj->depth0) { + /* The gallium texture does not match the Mesa texture so delete the + * gallium texture now. We'll make a new one below. + */ pipe_resource_reference(&stObj->pt, NULL); pipe_sampler_view_reference(&stObj->sampler_view, NULL); st->dirty.st |= ST_NEW_FRAMEBUFFER; @@ -1869,17 +1876,15 @@ st_finalize_texture(GLcontext *ctx, /* May need to create a new gallium texture: */ if (!stObj->pt) { - const enum pipe_format fmt = - st_mesa_format_to_pipe_format(firstImage->base.TexFormat); - GLuint bindings = default_bindings(st, fmt); + GLuint bindings = default_bindings(st, firstImageFormat); stObj->pt = st_texture_create(st, gl_target_to_pipe(stObj->base.Target), - fmt, + firstImageFormat, stObj->lastLevel, - firstImage->base.Width2, - firstImage->base.Height2, - firstImage->base.Depth2, + stObj->width0, + stObj->height0, + stObj->depth0, bindings); if (!stObj->pt) { @@ -1894,13 +1899,12 @@ st_finalize_texture(GLcontext *ctx, GLuint level; for (level = 0; level <= stObj->lastLevel; level++) { struct st_texture_image *stImage = - st_texture_image(stObj->base.Image[face][stObj->base.BaseLevel + level]); + st_texture_image(stObj->base.Image[face][level]); /* Need to import images in main memory or held in other textures. */ if (stImage && stObj->pt != stImage->pt) { copy_image_data_to_texture(st, stObj, level, stImage); - *needFlush = GL_TRUE; } } } diff --git a/src/mesa/state_tracker/st_cb_texture.h b/src/mesa/state_tracker/st_cb_texture.h index f1fe0339cd..1cd9fc3a50 100644 --- a/src/mesa/state_tracker/st_cb_texture.h +++ b/src/mesa/state_tracker/st_cb_texture.h @@ -33,8 +33,7 @@ extern GLboolean st_finalize_texture(GLcontext *ctx, struct pipe_context *pipe, - struct gl_texture_object *tObj, - GLboolean *needFlush); + struct gl_texture_object *tObj); extern struct gl_texture_object * diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index 5fcb6b9dcf..e8a3926e6d 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -64,6 +64,7 @@ #include "pipe/p_context.h" #include "util/u_inlines.h" #include "util/u_rect.h" +#include "util/u_surface.h" #include "draw/draw_context.h" #include "cso_cache/cso_context.h" @@ -199,7 +200,16 @@ struct st_context *st_create_context(struct pipe_context *pipe, memset(&funcs, 0, sizeof(funcs)); st_init_driver_functions(&funcs); - ctx = _mesa_create_context(visual, shareCtx, &funcs, NULL); +#if FEATURE_GL + ctx = _mesa_create_context_for_api(API_OPENGL, + visual, shareCtx, &funcs, NULL); +#elif FEATURE_ES1 + ctx = _mesa_create_context_for_api(API_OPENGLES, + visual, shareCtx, &funcs, NULL); +#elif FEATURE_ES2 + ctx = _mesa_create_context_for_api(API_OPENGLES2, + visual, shareCtx, &funcs, NULL); +#endif /* XXX: need a capability bit in gallium to query if the pipe * driver prefers DP4 or MUL/MAD for vertex transformation. diff --git a/src/mesa/state_tracker/st_gen_mipmap.c b/src/mesa/state_tracker/st_gen_mipmap.c index b8b75c7de6..6b1d51b3f4 100644 --- a/src/mesa/state_tracker/st_gen_mipmap.c +++ b/src/mesa/state_tracker/st_gen_mipmap.c @@ -311,7 +311,6 @@ st_generate_mipmap(GLcontext *ctx, GLenum target, * mipmap levels we need to generate. So allocate a new texture. */ struct pipe_resource *oldTex = stObj->pt; - GLboolean needFlush; /* create new texture with space for more levels */ stObj->pt = st_texture_create(st, @@ -331,7 +330,7 @@ st_generate_mipmap(GLcontext *ctx, GLenum target, /* This will copy the old texture's base image into the new texture * which we just allocated. */ - st_finalize_texture(ctx, st->pipe, texObj, &needFlush); + st_finalize_texture(ctx, st->pipe, texObj); /* release the old tex (will likely be freed too) */ pipe_resource_reference(&oldTex, NULL); @@ -342,10 +341,10 @@ st_generate_mipmap(GLcontext *ctx, GLenum target, assert(lastLevel <= pt->last_level); - /* Recall that the Mesa BaseLevel image is stored in the gallium - * texture's level[0] position. So pass baseLevel=0 here. + /* Try to generate the mipmap by rendering/texturing. If that fails, + * use the software fallback. */ - if (!st_render_mipmap(st, target, stObj, 0, lastLevel)) { + if (!st_render_mipmap(st, target, stObj, baseLevel, lastLevel)) { fallback_generate_mipmap(ctx, target, texObj); } diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c index 1b52e77b7d..6a42789b82 100644 --- a/src/mesa/state_tracker/st_texture.c +++ b/src/mesa/state_tracker/st_texture.c @@ -45,24 +45,6 @@ #define DBG if(0) printf -#if 0 -static GLenum -target_to_target(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 GL_TEXTURE_CUBE_MAP_ARB; - default: - return target; - } -} -#endif - /** * Allocate a new pipe_resource object @@ -143,10 +125,12 @@ st_texture_match_image(const struct pipe_resource *pt, /** - * Map a teximage in a mipmap texture. - * \param row_stride returns row stride in bytes - * \param image_stride returns image stride in bytes (for 3D textures). - * \return address of mapping + * Map a texture image and return the address for a particular 2D face/slice/ + * layer. The stImage indicates the cube face and mipmap level. The slice + * of the 3D texture is passed in 'zoffset'. + * \param usage one of the PIPE_TRANSFER_x values + * \param x, y, w, h the region of interest of the 2D image. + * \return address of mapping or NULL if any error */ GLubyte * st_texture_image_map(struct st_context *st, struct st_texture_image *stImage, @@ -269,6 +253,9 @@ st_texture_image_copy(struct pipe_context *pipe, struct pipe_surface *dst_surface; GLuint i; + assert(src->width0 == dst->width0); + assert(src->height0 == dst->height0); + for (i = 0; i < depth; i++) { GLuint srcLevel; diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h index d0298817de..447f091db1 100644 --- a/src/mesa/state_tracker/st_texture.h +++ b/src/mesa/state_tracker/st_texture.h @@ -38,6 +38,9 @@ struct pipe_resource; +/** + * Subclass of gl_texure_image. + */ struct st_texture_image { struct gl_texture_image base; @@ -57,7 +60,9 @@ struct st_texture_image }; - +/** + * Subclass of gl_texure_object. + */ struct st_texture_object { struct gl_texture_object base; /* The "parent" object */ @@ -66,6 +71,9 @@ struct st_texture_object */ GLuint lastLevel; + /** The size of the level=0 mipmap image */ + GLuint width0, height0, depth0; + /* On validation any active images held in main memory or in other * textures will be copied to this texture and the old storage freed. */ @@ -76,8 +84,6 @@ struct st_texture_object */ struct pipe_sampler_view *sampler_view; - GLboolean teximage_realloc; - /* True if there is/was a surface bound to this texture object. It helps * track whether the texture object is surface based or not. */ |