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.c9
-rw-r--r--src/mesa/state_tracker/st_atom_texture.c20
-rw-r--r--src/mesa/state_tracker/st_cb_drawtex.c312
-rw-r--r--src/mesa/state_tracker/st_cb_drawtex.h18
-rw-r--r--src/mesa/state_tracker/st_cb_fbo.c8
-rw-r--r--src/mesa/state_tracker/st_cb_texture.c292
-rw-r--r--src/mesa/state_tracker/st_cb_texture.h3
-rw-r--r--src/mesa/state_tracker/st_context.c12
-rw-r--r--src/mesa/state_tracker/st_gen_mipmap.c9
-rw-r--r--src/mesa/state_tracker/st_texture.c31
-rw-r--r--src/mesa/state_tracker/st_texture.h12
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.
*/