static void 
finalize_textures(struct st_context *st)
{
   struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current;
   const GLboolean prev_missing_textures = st->missing_textures;
   GLuint su;

   st->missing_textures = GL_FALSE;

   for (su = 0; su < st->ctx->Const.MaxTextureCoordUnits; su++) {
      if (fprog->Base.SamplersUsed & (1 << su)) {
         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;

            retval = st_finalize_texture(st->ctx, st->pipe, texObj, &flush);
            if (!retval) {
               /* out of mem */
               st->missing_textures = GL_TRUE;
               continue;
            }

            stObj->teximage_realloc = TRUE;
         }
      }
   }

   if (prev_missing_textures != st->missing_textures)
      st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
}
static void 
update_textures(struct st_context *st)
{
   struct gl_vertex_program *vprog = st->ctx->VertexProgram._Current;
   struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current;
   const GLbitfield samplersUsed = (vprog->Base.SamplersUsed |
                                    fprog->Base.SamplersUsed);
   GLuint su;

   st->state.num_textures = 0;

   /* loop over sampler units (aka tex image units) */
   for (su = 0; su < st->ctx->Const.MaxTextureImageUnits; su++) {
      struct pipe_texture *pt = NULL;

      if (samplersUsed & (1 << su)) {
         struct gl_texture_object *texObj;
         struct st_texture_object *stObj;
         GLboolean flush, retval;
         GLuint texUnit;

         if (fprog->Base.SamplersUsed & (1 << su))
            texUnit = fprog->Base.SamplerUnits[su];
         else
            texUnit = vprog->Base.SamplerUnits[su];

         texObj = st->ctx->Texture.Unit[texUnit]._Current;

         if (!texObj) {
            texObj = st_get_default_texture(st);
         }
         stObj = st_texture_object(texObj);

         retval = st_finalize_texture(st->ctx, st->pipe, texObj, &flush);
         if (!retval) {
            /* out of mem */
            continue;
         }

         st->state.num_textures = su + 1;

         pt = st_get_stobj_texture(stObj);
      }

      /*
      if (pt) {
         printf("%s su=%u non-null\n", __FUNCTION__, su);
      }
      else {
         printf("%s su=%u null\n", __FUNCTION__, su);
      }
      */

      pipe_texture_reference(&st->state.sampler_texture[su], pt);
   }

   cso_set_sampler_textures(st->cso_context,
                            st->state.num_textures,
                            st->state.sampler_texture);
}
Exemple #3
0
/**
 * Preparation prior to glTexImage.  Basically check the 'surface_based'
 * field and switch to a "normal" tex image if necessary.
 */
static void
prep_teximage(struct gl_context *ctx, struct gl_texture_image *texImage,
              GLenum format, GLenum type)
{
   struct gl_texture_object *texObj = texImage->TexObject;
   struct st_texture_object *stObj = st_texture_object(texObj);

   /* switch to "normal" */
   if (stObj->surface_based) {
      const GLenum target = texObj->Target;
      const GLuint level = texImage->Level;
      gl_format texFormat;

      _mesa_clear_texture_object(ctx, texObj);
      pipe_resource_reference(&stObj->pt, NULL);

      /* oops, need to init this image again */
      texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
                                              texImage->InternalFormat, format,
                                              type);

      _mesa_init_teximage_fields(ctx, texImage,
                                 texImage->Width, texImage->Height,
                                 texImage->Depth, texImage->Border,
                                 texImage->InternalFormat, texFormat);

      stObj->surface_based = GL_FALSE;
   }
}
Exemple #4
0
static GLboolean
update_single_texture(struct st_context *st,
                      struct pipe_sampler_view **sampler_view,
                      GLuint texUnit)
{
    struct pipe_context *pipe = st->pipe;
    struct gl_context *ctx = st->ctx;
    const struct gl_sampler_object *samp;
    struct gl_texture_object *texObj;
    struct st_texture_object *stObj;
    enum pipe_format view_format;
    GLboolean retval;

    samp = _mesa_get_samplerobj(ctx, texUnit);

    texObj = ctx->Texture.Unit[texUnit]._Current;

    if (!texObj) {
        texObj = _mesa_get_fallback_texture(ctx, TEXTURE_2D_INDEX);
        samp = &texObj->Sampler;
    }
    stObj = st_texture_object(texObj);

    retval = st_finalize_texture(ctx, st->pipe, texObj);
    if (!retval) {
        /* out of mem */
        return GL_FALSE;
    }

    /* Determine the format of the texture sampler view */
    if (texObj->Target == GL_TEXTURE_BUFFER) {
        view_format =
            st_mesa_format_to_pipe_format(stObj->base._BufferObjectFormat);
    }
    else {
        view_format = stObj->pt->format;

        /* If sRGB decoding is off, use the linear format */
        if (samp->sRGBDecode == GL_SKIP_DECODE_EXT) {
            view_format = util_format_linear(view_format);
        }
    }

    /* if sampler view has changed dereference it */
    if (stObj->sampler_view) {
        if (check_sampler_swizzle(stObj->sampler_view,
                                  stObj->base._Swizzle,
                                  stObj->base.DepthMode) ||
                (view_format != stObj->sampler_view->format) ||
                stObj->base.BaseLevel != stObj->sampler_view->u.tex.first_level) {
            pipe_sampler_view_reference(&stObj->sampler_view, NULL);
        }
    }

    *sampler_view = st_get_texture_sampler_view_from_stobj(stObj, pipe,
                    samp,
                    view_format);
    return GL_TRUE;
}
Exemple #5
0
/**
 * Callback to release the sampler view attached to a texture object.
 * Called by _mesa_HashWalk().
 */
static void
destroy_tex_sampler_cb(GLuint id, void *data, void *userData)
{
   struct gl_texture_object *texObj = (struct gl_texture_object *) data;
   struct st_context *st = (struct st_context *) userData;

   st_texture_release_sampler_view(st, st_texture_object(texObj));
}
Exemple #6
0
/**
 * Bind a pipe surface to a texture object.  After the call,
 * the texture object is marked dirty and will be (re-)validated.
 *
 * If this is the first surface bound, the texture object is said to
 * switch from normal to surface based.  It will be cleared first in
 * this case.
 *
 * \param ps      pipe surface to be unbound
 * \param target  texture target
 * \param level   image level
 * \param format  internal format of the texture
 */
int
st_bind_texture_surface(struct pipe_surface *ps, int target, int level,
                        enum pipe_format format)
{
   GET_CURRENT_CONTEXT(ctx);
   const GLuint unit = ctx->Texture.CurrentUnit;
   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
   struct gl_texture_object *texObj;
   struct gl_texture_image *texImage;
   struct st_texture_object *stObj;
   struct st_texture_image *stImage;
   GLenum internalFormat;

   switch (target) {
   case ST_TEXTURE_2D:
      target = GL_TEXTURE_2D;
      break;
   case ST_TEXTURE_RECT:
      target = GL_TEXTURE_RECTANGLE_ARB;
      break;
   default:
      return 0;
   }

   /* map pipe format to base format for now */
   if (pf_get_component_bits(format, PIPE_FORMAT_COMP_A) > 0)
      internalFormat = GL_RGBA;
   else
      internalFormat = GL_RGB;

   texObj = _mesa_select_tex_object(ctx, texUnit, target);
   _mesa_lock_texture(ctx, texObj);

   stObj = st_texture_object(texObj);
   /* switch to surface based */
   if (!stObj->surface_based) {
      _mesa_clear_texture_object(ctx, texObj);
      stObj->surface_based = GL_TRUE;
   }

   texImage = _mesa_get_tex_image(ctx, texObj, target, level);
   stImage = st_texture_image(texImage);

   _mesa_init_teximage_fields(ctx, target, texImage,
                              ps->width, ps->height, 1, 0, internalFormat);
   texImage->TexFormat = st_ChooseTextureFormat(ctx, internalFormat,
                                                GL_RGBA, GL_UNSIGNED_BYTE);
   _mesa_set_fetch_functions(texImage, 2);
   pipe_texture_reference(&stImage->pt, ps->texture);

   _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
   _mesa_unlock_texture(ctx, texObj);
   
   return 1;
}
Exemple #7
0
/**
 * Called via ctx->Driver.AllocTextureStorage() to allocate texture memory
 * for a whole mipmap stack.
 */
static GLboolean
st_AllocTextureStorage(struct gl_context *ctx,
                       struct gl_texture_object *texObj,
                       GLsizei levels, GLsizei width,
                       GLsizei height, GLsizei depth)
{
   const GLuint numFaces = _mesa_num_tex_faces(texObj->Target);
   struct st_context *st = st_context(ctx);
   struct st_texture_object *stObj = st_texture_object(texObj);
   GLuint ptWidth, ptHeight, ptDepth, ptLayers, bindings;
   enum pipe_format fmt;
   GLint level;

   assert(levels > 0);

   /* Save the level=0 dimensions */
   stObj->width0 = width;
   stObj->height0 = height;
   stObj->depth0 = depth;
   stObj->lastLevel = levels - 1;

   fmt = st_mesa_format_to_pipe_format(texObj->Image[0][0]->TexFormat);

   bindings = default_bindings(st, fmt);

   st_gl_texture_dims_to_pipe_dims(texObj->Target,
                                   width, height, depth,
                                   &ptWidth, &ptHeight, &ptDepth, &ptLayers);

   stObj->pt = st_texture_create(st,
                                 gl_target_to_pipe(texObj->Target),
                                 fmt,
                                 levels,
                                 ptWidth,
                                 ptHeight,
                                 ptDepth,
                                 ptLayers,
                                 bindings);
   if (!stObj->pt)
      return GL_FALSE;

   /* Set image resource pointers */
   for (level = 0; level < levels; level++) {
      GLuint face;
      for (face = 0; face < numFaces; face++) {
         struct st_texture_image *stImage =
            st_texture_image(texObj->Image[face][level]);
         pipe_resource_reference(&stImage->pt, stObj->pt);
      }
   }

   return GL_TRUE;
}
Exemple #8
0
/** called via ctx->Driver.DeleteTextureObject() */
static void 
st_DeleteTextureObject(struct gl_context *ctx,
                       struct gl_texture_object *texObj)
{
   struct st_context *st = st_context(ctx);
   struct st_texture_object *stObj = st_texture_object(texObj);
   if (stObj->pt)
      pipe_resource_reference(&stObj->pt, NULL);
   if (stObj->sampler_view) {
      pipe_sampler_view_release(st->pipe, &stObj->sampler_view);
   }
   _mesa_delete_texture_object(ctx, texObj);
}
Exemple #9
0
/**
 * 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,
                     enum pipe_transfer_usage usage,
                     GLuint x, GLuint y, GLuint z,
                     GLuint w, GLuint h, GLuint d,
                     struct pipe_transfer **transfer)
{
   struct st_texture_object *stObj =
      st_texture_object(stImage->base.TexObject);
   GLuint level;
   void *map;

   DBG("%s \n", __func__);

   if (!stImage->pt)
      return NULL;

   if (stObj->pt != stImage->pt)
      level = 0;
   else
      level = stImage->base.Level;

   if (stObj->base.Immutable) {
      level += stObj->base.MinLevel;
      z += stObj->base.MinLayer;
      if (stObj->pt->array_size > 1)
         d = MIN2(d, stObj->base.NumLayers);
   }

   z += stImage->base.Face;

   map = pipe_transfer_map_3d(st->pipe, stImage->pt, level, usage,
                              x, y, z, w, h, d, transfer);
   if (map) {
      /* Enlarge the transfer array if it's not large enough. */
      if (z >= stImage->num_transfers) {
         unsigned new_size = z + 1;

         stImage->transfer = realloc(stImage->transfer,
                     new_size * sizeof(struct st_texture_image_transfer));
         memset(&stImage->transfer[stImage->num_transfers], 0,
                (new_size - stImage->num_transfers) *
                sizeof(struct st_texture_image_transfer));
         stImage->num_transfers = new_size;
      }

      assert(!stImage->transfer[z].transfer);
      stImage->transfer[z].transfer = *transfer;
   }
   return map;
}
Exemple #10
0
static void
st_vdpau_unmap_surface(struct gl_context *ctx, GLenum target, GLenum access,
                       GLboolean output, struct gl_texture_object *texObj,
                       struct gl_texture_image *texImage,
                       const GLvoid *vdpSurface, GLuint index)
{
   struct st_texture_object *stObj = st_texture_object(texObj);
   struct st_texture_image *stImage = st_texture_image(texImage);

   pipe_resource_reference(&stObj->pt, NULL);
   pipe_sampler_view_reference(&stObj->sampler_view, NULL);
   pipe_resource_reference(&stImage->pt, NULL);

   _mesa_dirty_texobj(ctx, texObj);
}
Exemple #11
0
static GLboolean
update_single_texture(struct st_context *st,
                      struct pipe_sampler_view **sampler_view,
                      GLuint texUnit, unsigned glsl_version)
{
    struct gl_context *ctx = st->ctx;
    const struct gl_sampler_object *samp;
    struct gl_texture_object *texObj;
    struct st_texture_object *stObj;
    enum pipe_format view_format;
    GLboolean retval;

    samp = _mesa_get_samplerobj(ctx, texUnit);

    texObj = ctx->Texture.Unit[texUnit]._Current;

    if (!texObj) {
        texObj = _mesa_get_fallback_texture(ctx, TEXTURE_2D_INDEX);
        samp = &texObj->Sampler;
    }
    stObj = st_texture_object(texObj);

    retval = st_finalize_texture(ctx, st->pipe, texObj);
    if (!retval) {
        /* out of mem */
        return GL_FALSE;
    }

    /* Determine the format of the texture sampler view */
    if (texObj->Target == GL_TEXTURE_BUFFER) {
        view_format =
            st_mesa_format_to_pipe_format(st, stObj->base._BufferObjectFormat);
    }
    else {
        view_format =
            stObj->surface_based ? stObj->surface_format : stObj->pt->format;

        /* If sRGB decoding is off, use the linear format */
        if (samp->sRGBDecode == GL_SKIP_DECODE_EXT) {
            view_format = util_format_linear(view_format);
        }
    }

    *sampler_view =
        st_get_texture_sampler_view_from_stobj(st, stObj, view_format,
                glsl_version);
    return GL_TRUE;
}
Exemple #12
0
/**
 * Validate a renderbuffer attachment for a particular set of bindings.
 */
static GLboolean
st_validate_attachment(struct gl_context *ctx,
		       struct pipe_screen *screen,
		       const struct gl_renderbuffer_attachment *att,
		       unsigned bindings)
{
   const struct st_texture_object *stObj = st_texture_object(att->Texture);
   enum pipe_format format;
   mesa_format texFormat;
   GLboolean valid;

   /* Sanity check: we must be binding the surface as a (color) render target
    * or depth/stencil target.
    */
   assert(bindings == PIPE_BIND_RENDER_TARGET ||
          bindings == PIPE_BIND_DEPTH_STENCIL);

   /* Only validate texture attachments for now, since
    * st_renderbuffer_alloc_storage makes sure that
    * the format is supported.
    */
   if (att->Type != GL_TEXTURE)
      return GL_TRUE;

   if (!stObj || !stObj->pt)
      return GL_FALSE;

   format = stObj->pt->format;
   texFormat = att->Renderbuffer->TexImage->TexFormat;

   /* If the encoding is sRGB and sRGB rendering cannot be enabled,
    * check for linear format support instead.
    * Later when we create a surface, we change the format to a linear one. */
   if (!ctx->Extensions.EXT_framebuffer_sRGB &&
       _mesa_get_format_color_encoding(texFormat) == GL_SRGB) {
      const mesa_format linearFormat = _mesa_get_srgb_format_linear(texFormat);
      format = st_mesa_format_to_pipe_format(st_context(ctx), linearFormat);
   }

   valid = screen->is_format_supported(screen, format,
                                      PIPE_TEXTURE_2D,
                                      stObj->pt->nr_samples, bindings);
   if (!valid) {
      st_fbo_invalid("Invalid format");
   }

   return valid;
}
Exemple #13
0
static GLboolean
update_single_texture(struct st_context *st,
                      struct pipe_sampler_view **sampler_view,
		      GLuint texUnit, unsigned glsl_version)
{
   struct gl_context *ctx = st->ctx;
   const struct gl_sampler_object *samp;
   struct gl_texture_object *texObj;
   struct st_texture_object *stObj;
   GLboolean retval;

   samp = _mesa_get_samplerobj(ctx, texUnit);

   texObj = ctx->Texture.Unit[texUnit]._Current;

   if (!texObj) {
      texObj = _mesa_get_fallback_texture(ctx, TEXTURE_2D_INDEX);
      samp = &texObj->Sampler;
   }
   stObj = st_texture_object(texObj);

   retval = st_finalize_texture(ctx, st->pipe, texObj);
   if (!retval) {
      /* out of mem */
      return GL_FALSE;
   }

   /* Check a few pieces of state outside the texture object to see if we
    * need to force revalidation.
    */
   if (stObj->prev_glsl_version != glsl_version ||
       stObj->prev_sRGBDecode != samp->sRGBDecode) {

      st_texture_release_all_sampler_views(st, stObj);

      stObj->prev_glsl_version = glsl_version;
      stObj->prev_sRGBDecode = samp->sRGBDecode;
   }

   if (texObj->TargetIndex == TEXTURE_EXTERNAL_INDEX &&
       stObj->pt->screen->resource_changed)
         stObj->pt->screen->resource_changed(stObj->pt->screen, stObj->pt);

   *sampler_view =
      st_get_texture_sampler_view_from_stobj(st, stObj, samp, glsl_version);
   return GL_TRUE;
}
Exemple #14
0
void
st_texture_image_unmap(struct st_context *st,
                       struct st_texture_image *stImage, unsigned slice)
{
   struct pipe_context *pipe = st->pipe;
   struct st_texture_object *stObj =
      st_texture_object(stImage->base.TexObject);
   struct pipe_transfer **transfer;

   if (stObj->base.Immutable)
      slice += stObj->base.MinLayer;
   transfer = &stImage->transfer[slice + stImage->base.Face].transfer;

   DBG("%s\n", __FUNCTION__);

   pipe_transfer_unmap(pipe, *transfer);
   *transfer = NULL;
}
Exemple #15
0
static void
st_bind_surface(struct gl_context *ctx, GLenum target,
                struct gl_texture_object *texObj,
                struct gl_texture_image *texImage,
                struct pipe_surface *ps)
{
   struct st_texture_object *stObj;
   struct st_texture_image *stImage;
   GLenum internalFormat;
   gl_format texFormat;

   /* map pipe format to base format */
   if (util_format_get_component_bits(ps->format, UTIL_FORMAT_COLORSPACE_RGB, 3) > 0)
      internalFormat = GL_RGBA;
   else
      internalFormat = GL_RGB;

   stObj = st_texture_object(texObj);
   stImage = st_texture_image(texImage);

   /* switch to surface based */
   if (!stObj->surface_based) {
      _mesa_clear_texture_object(ctx, texObj);
      stObj->surface_based = GL_TRUE;
   }

   texFormat = st_pipe_format_to_mesa_format(ps->format);

   _mesa_init_teximage_fields(ctx, texImage,
                              ps->width, ps->height, 1, 0, internalFormat,
                              texFormat);

   /* FIXME create a non-default sampler view from the pipe_surface? */
   pipe_resource_reference(&stObj->pt, ps->texture);
   pipe_sampler_view_reference(&stObj->sampler_view, NULL);
   pipe_resource_reference(&stImage->pt, stObj->pt);

   stObj->width0 = ps->width;
   stObj->height0 = ps->height;
   stObj->depth0 = 1;
   stObj->surface_format = ps->format;

   _mesa_dirty_texobj(ctx, texObj);
}
Exemple #16
0
/**
 * Unbind a pipe surface from a texture object.  After the call,
 * the texture object is marked dirty and will be (re-)validated.
 *
 * \param ps      pipe surface to be unbound
 * \param target  texture target
 * \param level   image level
 */
int
st_unbind_texture_surface(struct pipe_surface *ps, int target, int level)
{
   GET_CURRENT_CONTEXT(ctx);
   const GLuint unit = ctx->Texture.CurrentUnit;
   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
   struct gl_texture_object *texObj;
   struct gl_texture_image *texImage;
   struct st_texture_object *stObj;
   struct st_texture_image *stImage;

   switch (target) {
   case ST_TEXTURE_2D:
      target = GL_TEXTURE_2D;
      break;
   case ST_TEXTURE_RECT:
      target = GL_TEXTURE_RECTANGLE_ARB;
      break;
   default:
      return 0;
   }

   texObj = _mesa_select_tex_object(ctx, texUnit, target);

   _mesa_lock_texture(ctx, texObj);

   texImage = _mesa_get_tex_image(ctx, texObj, target, level);
   stObj = st_texture_object(texObj);
   stImage = st_texture_image(texImage);

   /* Make sure the pipe surface is still bound.  The texture object is still
    * considered surface based even if this is the last bound surface. */
   if (stImage->pt == ps->texture) {
      pipe_texture_reference(&stImage->pt, NULL);
      _mesa_clear_texture_image(ctx, texImage);

      _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
   }

   _mesa_unlock_texture(ctx, texObj);
   
   return 1;
}
/**
 * Validate a renderbuffer attachment for a particular set of bindings.
 */
static GLboolean
st_validate_attachment(struct gl_context *ctx,
		       struct pipe_screen *screen,
		       const struct gl_renderbuffer_attachment *att,
		       unsigned bindings)
{
   const struct st_texture_object *stObj = st_texture_object(att->Texture);
   enum pipe_format format;
   gl_format texFormat;
   GLboolean valid;

   /* Only validate texture attachments for now, since
    * st_renderbuffer_alloc_storage makes sure that
    * the format is supported.
    */
   if (att->Type != GL_TEXTURE)
      return GL_TRUE;

   if (!stObj)
      return GL_FALSE;

   format = stObj->pt->format;
   texFormat = _mesa_get_attachment_teximage_const(att)->TexFormat;

   /* If the encoding is sRGB and sRGB rendering cannot be enabled,
    * check for linear format support instead.
    * Later when we create a surface, we change the format to a linear one. */
   if (!ctx->Extensions.EXT_framebuffer_sRGB &&
       _mesa_get_format_color_encoding(texFormat) == GL_SRGB) {
      const gl_format linearFormat = _mesa_get_srgb_format_linear(texFormat);
      format = st_mesa_format_to_pipe_format(linearFormat);
   }

   valid = screen->is_format_supported(screen, format,
                                      PIPE_TEXTURE_2D,
                                      stObj->pt->nr_samples, bindings);
   if (!valid) {
      st_fbo_invalid("Invalid format");
   }

   return valid;
}
Exemple #18
0
static void
st_vdpau_unmap_surface(struct gl_context *ctx, GLenum target, GLenum access,
                       GLboolean output, struct gl_texture_object *texObj,
                       struct gl_texture_image *texImage,
                       const void *vdpSurface, GLuint index)
{
   struct st_context *st = st_context(ctx);
   struct st_texture_object *stObj = st_texture_object(texObj);
   struct st_texture_image *stImage = st_texture_image(texImage);

   pipe_resource_reference(&stObj->pt, NULL);
   st_texture_release_all_sampler_views(st, stObj);
   pipe_resource_reference(&stImage->pt, NULL);

   stObj->layer_override = 0;

   _mesa_dirty_texobj(ctx, texObj);

   st_flush(st, NULL, 0);
}
/**
 * Get a pipe_sampler_view object from a texture unit.
 */
void
st_update_single_texture(struct st_context *st,
                         struct pipe_sampler_view **sampler_view,
                         GLuint texUnit, bool glsl130_or_later,
                         bool ignore_srgb_decode)
{
   struct gl_context *ctx = st->ctx;
   const struct gl_sampler_object *samp;
   struct gl_texture_object *texObj;
   struct st_texture_object *stObj;

   samp = _mesa_get_samplerobj(ctx, texUnit);

   texObj = ctx->Texture.Unit[texUnit]._Current;
   assert(texObj);

   stObj = st_texture_object(texObj);

   if (unlikely(texObj->Target == GL_TEXTURE_BUFFER)) {
      *sampler_view = st_get_buffer_sampler_view_from_stobj(st, stObj);
      return;
   }

   if (!st_finalize_texture(ctx, st->pipe, texObj, 0) ||
       !stObj->pt) {
      /* out of mem */
      *sampler_view = NULL;
      return;
   }

   if (texObj->TargetIndex == TEXTURE_EXTERNAL_INDEX &&
       stObj->pt->screen->resource_changed)
         stObj->pt->screen->resource_changed(stObj->pt->screen, stObj->pt);

   *sampler_view =
      st_get_texture_sampler_view_from_stobj(st, stObj, samp,
                                             glsl130_or_later,
                                             ignore_srgb_decode);
}
Exemple #20
0
/**
 * 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,
                     enum pipe_transfer_usage usage,
                     GLuint x, GLuint y, GLuint z,
                     GLuint w, GLuint h, GLuint d)
{
   struct st_texture_object *stObj =
      st_texture_object(stImage->base.TexObject);
   GLuint level;

   DBG("%s \n", __FUNCTION__);

   if (!stImage->pt)
      return NULL;

   if (stObj->pt != stImage->pt)
      level = 0;
   else
      level = stImage->base.Level;

   return pipe_transfer_map_3d(st->pipe, stImage->pt, level, usage,
                               x, y, z + stImage->base.Face,
                               w, h, d, &stImage->transfer);
}
Exemple #21
0
static boolean
st_context_teximage(struct st_context_iface *stctxi,
                    enum st_texture_type target,
                    int level, enum pipe_format internal_format,
                    struct pipe_resource *tex, boolean mipmap)
{
   struct st_context *st = (struct st_context *) stctxi;
   struct gl_context *ctx = st->ctx;
   struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
   struct gl_texture_object *texObj;
   struct gl_texture_image *texImage;
   struct st_texture_object *stObj;
   struct st_texture_image *stImage;
   GLenum internalFormat;
   GLuint width, height, depth;

   switch (target) {
   case ST_TEXTURE_1D:
      target = GL_TEXTURE_1D;
      break;
   case ST_TEXTURE_2D:
      target = GL_TEXTURE_2D;
      break;
   case ST_TEXTURE_3D:
      target = GL_TEXTURE_3D;
      break;
   case ST_TEXTURE_RECT:
      target = GL_TEXTURE_RECTANGLE_ARB;
      break;
   default:
      return FALSE;
      break;
   }

   texObj = _mesa_select_tex_object(ctx, texUnit, target);
   _mesa_lock_texture(ctx, texObj);

   stObj = st_texture_object(texObj);
   /* switch to surface based */
   if (!stObj->surface_based) {
      _mesa_clear_texture_object(ctx, texObj);
      stObj->surface_based = GL_TRUE;
   }

   texImage = _mesa_get_tex_image(ctx, texObj, target, level);
   stImage = st_texture_image(texImage);
   if (tex) {
      gl_format texFormat;

      /*
       * XXX When internal_format and tex->format differ, st_finalize_texture
       * needs to allocate a new texture with internal_format and copy the
       * texture here into the new one.  It will result in surface_copy being
       * called on surfaces whose formats differ.
       *
       * To avoid that, internal_format is (wrongly) ignored here.  A sane fix
       * is to use a sampler view.
       */
      if (!st_sampler_compat_formats(tex->format, internal_format))
	 internal_format = tex->format;
     
      if (util_format_get_component_bits(internal_format,
               UTIL_FORMAT_COLORSPACE_RGB, 3) > 0)
         internalFormat = GL_RGBA;
      else
         internalFormat = GL_RGB;

      texFormat = st_ChooseTextureFormat(ctx, internalFormat,
                                         GL_BGRA, GL_UNSIGNED_BYTE);

      _mesa_init_teximage_fields(ctx, texImage,
                                 tex->width0, tex->height0, 1, 0,
                                 internalFormat, texFormat);

      width = tex->width0;
      height = tex->height0;
      depth = tex->depth0;

      /* 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--;
      }
   }
   else {
      _mesa_clear_texture_image(ctx, texImage);
      width = height = depth = 0;
   }

   pipe_resource_reference(&stImage->pt, tex);
   stObj->width0 = width;
   stObj->height0 = height;
   stObj->depth0 = depth;

   _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
   _mesa_unlock_texture(ctx, texObj);
   
   return TRUE;
}
Exemple #22
0
static boolean
st_context_teximage(struct st_context_iface *stctxi,
                    enum st_texture_type tex_type,
                    int level, enum pipe_format pipe_format,
                    struct pipe_resource *tex, boolean mipmap)
{
   struct st_context *st = (struct st_context *) stctxi;
   struct gl_context *ctx = st->ctx;
   struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
   struct gl_texture_object *texObj;
   struct gl_texture_image *texImage;
   struct st_texture_object *stObj;
   struct st_texture_image *stImage;
   GLenum internalFormat;
   GLuint width, height, depth;
   GLenum target;

   switch (tex_type) {
   case ST_TEXTURE_1D:
      target = GL_TEXTURE_1D;
      break;
   case ST_TEXTURE_2D:
      target = GL_TEXTURE_2D;
      break;
   case ST_TEXTURE_3D:
      target = GL_TEXTURE_3D;
      break;
   case ST_TEXTURE_RECT:
      target = GL_TEXTURE_RECTANGLE_ARB;
      break;
   default:
      return FALSE;
   }

   texObj = _mesa_select_tex_object(ctx, texUnit, target);
   _mesa_lock_texture(ctx, texObj);

   stObj = st_texture_object(texObj);
   /* switch to surface based */
   if (!stObj->surface_based) {
      _mesa_clear_texture_object(ctx, texObj);
      stObj->surface_based = GL_TRUE;
   }

   texImage = _mesa_get_tex_image(ctx, texObj, target, level);
   stImage = st_texture_image(texImage);
   if (tex) {
      gl_format texFormat = st_pipe_format_to_mesa_format(pipe_format);

      if (util_format_has_alpha(tex->format))
         internalFormat = GL_RGBA;
      else
         internalFormat = GL_RGB;

      _mesa_init_teximage_fields(ctx, texImage,
                                 tex->width0, tex->height0, 1, 0,
                                 internalFormat, texFormat);

      width = tex->width0;
      height = tex->height0;
      depth = tex->depth0;

      /* 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--;
      }
   }
   else {
      _mesa_clear_texture_image(ctx, texImage);
      width = height = depth = 0;
   }

   pipe_resource_reference(&stImage->pt, tex);
   stObj->width0 = width;
   stObj->height0 = height;
   stObj->depth0 = depth;
   stObj->surface_format = pipe_format;

   _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
   _mesa_unlock_texture(ctx, texObj);
   
   return TRUE;
}
Exemple #23
0
/**
 * Called via ctx->Driver.GenerateMipmap().
 */
void
st_generate_mipmap(struct gl_context *ctx, GLenum target,
                   struct gl_texture_object *texObj)
{
   struct st_context *st = st_context(ctx);
   struct st_texture_object *stObj = st_texture_object(texObj);
   struct pipe_resource *pt = st_get_texobj_resource(texObj);
   const uint baseLevel = texObj->BaseLevel;
   uint lastLevel, first_layer, last_layer;
   uint dstLevel;

   if (!pt)
      return;

   /* not sure if this ultimately actually should work,
      but we're not supporting multisampled textures yet. */
   assert(pt->nr_samples < 2);

   /* find expected last mipmap level to generate*/
   lastLevel = compute_num_levels(ctx, texObj, target) - 1;

   if (lastLevel == 0)
      return;

   /* The texture isn't in a "complete" state yet so set the expected
    * lastLevel here, since it won't get done in st_finalize_texture().
    */
   stObj->lastLevel = lastLevel;

   if (pt->last_level < lastLevel) {
      /* The current gallium texture doesn't have space for all the
       * mipmap levels we need to generate.  So allocate a new texture.
       */
      struct pipe_resource *oldTex = stObj->pt;

      /* create new texture with space for more levels */
      stObj->pt = st_texture_create(st,
                                    oldTex->target,
                                    oldTex->format,
                                    lastLevel,
                                    oldTex->width0,
                                    oldTex->height0,
                                    oldTex->depth0,
                                    oldTex->array_size,
                                    0,
                                    oldTex->bind);

      /* This will copy the old texture's base image into the new texture
       * which we just allocated.
       */
      st_finalize_texture(ctx, st->pipe, texObj);

      /* release the old tex (will likely be freed too) */
      pipe_resource_reference(&oldTex, NULL);
      st_texture_release_all_sampler_views(stObj);
   }
   else {
      /* Make sure that the base texture image data is present in the
       * texture buffer.
       */
      st_finalize_texture(ctx, st->pipe, texObj);
   }

   pt = stObj->pt;

   assert(pt->last_level >= lastLevel);

   if (pt->target == PIPE_TEXTURE_CUBE) {
      first_layer = last_layer = _mesa_tex_target_to_face(target);
   }
   else {
      first_layer = 0;
      last_layer = util_max_layer(pt, baseLevel);
   }

   /* Try to generate the mipmap by rendering/texturing.  If that fails,
    * use the software fallback.
    */
   if (!util_gen_mipmap(st->pipe, pt, pt->format, baseLevel, lastLevel,
                        first_layer, last_layer, PIPE_TEX_FILTER_LINEAR)) {
      _mesa_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
         = _mesa_get_tex_image(ctx, texObj, target, srcLevel);
      struct gl_texture_image *dstImage;
      struct st_texture_image *stImage;
      uint border = srcImage->Border;
      uint dstWidth, dstHeight, dstDepth;

      dstWidth = u_minify(pt->width0, dstLevel);
      if (texObj->Target == GL_TEXTURE_1D_ARRAY) {
         dstHeight = pt->array_size;
      }
      else {
         dstHeight = u_minify(pt->height0, dstLevel);
      }
      if (texObj->Target == GL_TEXTURE_2D_ARRAY ||
          texObj->Target == GL_TEXTURE_CUBE_MAP_ARRAY) {
         dstDepth = pt->array_size;
      }
      else {
         dstDepth = u_minify(pt->depth0, dstLevel);
      }

      dstImage = _mesa_get_tex_image(ctx, texObj, target, dstLevel);
      if (!dstImage) {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
         return;
      }

      /* Free old image data */
      ctx->Driver.FreeTextureImageBuffer(ctx, dstImage);

      /* initialize new image */
      _mesa_init_teximage_fields(ctx, dstImage, dstWidth, dstHeight,
                                 dstDepth, border, srcImage->InternalFormat,
                                 srcImage->TexFormat);

      stImage = st_texture_image(dstImage);

      pipe_resource_reference(&stImage->pt, pt);
   }
}
Exemple #24
0
static void
st_BlitFramebuffer(struct gl_context *ctx,
                   struct gl_framebuffer *readFB,
                   struct gl_framebuffer *drawFB,
                   GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
                   GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
                   GLbitfield mask, GLenum filter)
{
   const GLbitfield depthStencil = (GL_DEPTH_BUFFER_BIT |
                                    GL_STENCIL_BUFFER_BIT);
   struct st_context *st = st_context(ctx);
   const uint pFilter = ((filter == GL_NEAREST)
                         ? PIPE_TEX_FILTER_NEAREST
                         : PIPE_TEX_FILTER_LINEAR);
   struct {
      GLint srcX0, srcY0, srcX1, srcY1;
      GLint dstX0, dstY0, dstX1, dstY1;
   } clip;
   struct pipe_blit_info blit;

   st_manager_validate_framebuffers(st);

   /* Make sure bitmap rendering has landed in the framebuffers */
   st_flush_bitmap_cache(st);
   st_invalidate_readpix_cache(st);

   clip.srcX0 = srcX0;
   clip.srcY0 = srcY0;
   clip.srcX1 = srcX1;
   clip.srcY1 = srcY1;
   clip.dstX0 = dstX0;
   clip.dstY0 = dstY0;
   clip.dstX1 = dstX1;
   clip.dstY1 = dstY1;

   /* NOTE: If the src and dst dimensions don't match, we cannot simply adjust
    * the integer coordinates to account for clipping (or scissors) because that
    * would make us cut off fractional parts, affecting the result of the blit.
    *
    * XXX: This should depend on mask !
    */
   if (!_mesa_clip_blit(ctx, readFB, drawFB,
                        &clip.srcX0, &clip.srcY0, &clip.srcX1, &clip.srcY1,
                        &clip.dstX0, &clip.dstY0, &clip.dstX1, &clip.dstY1)) {
      return; /* nothing to draw/blit */
   }
   memset(&blit, 0, sizeof(struct pipe_blit_info));
   blit.scissor_enable =
      (dstX0 != clip.dstX0) ||
      (dstY0 != clip.dstY0) ||
      (dstX1 != clip.dstX1) ||
      (dstY1 != clip.dstY1);

   if (st_fb_orientation(drawFB) == Y_0_TOP) {
      /* invert Y for dest */
      dstY0 = drawFB->Height - dstY0;
      dstY1 = drawFB->Height - dstY1;
      /* invert Y for clip */
      clip.dstY0 = drawFB->Height - clip.dstY0;
      clip.dstY1 = drawFB->Height - clip.dstY1;
   }
   if (blit.scissor_enable) {
      blit.scissor.minx = MIN2(clip.dstX0, clip.dstX1);
      blit.scissor.miny = MIN2(clip.dstY0, clip.dstY1);
      blit.scissor.maxx = MAX2(clip.dstX0, clip.dstX1);
      blit.scissor.maxy = MAX2(clip.dstY0, clip.dstY1);
#if 0
      debug_printf("scissor = (%i,%i)-(%i,%i)\n",
                   blit.scissor.minx,blit.scissor.miny,
                   blit.scissor.maxx,blit.scissor.maxy);
#endif
   }

   if (st_fb_orientation(readFB) == Y_0_TOP) {
      /* invert Y for src */
      srcY0 = readFB->Height - srcY0;
      srcY1 = readFB->Height - srcY1;
   }

   if (srcY0 > srcY1 && dstY0 > dstY1) {
      /* Both src and dst are upside down.  Swap Y to make it
       * right-side up to increase odds of using a fast path.
       * Recall that all Gallium raster coords have Y=0=top.
       */
      GLint tmp;
      tmp = srcY0;
      srcY0 = srcY1;
      srcY1 = tmp;
      tmp = dstY0;
      dstY0 = dstY1;
      dstY1 = tmp;
   }

   blit.src.box.depth = 1;
   blit.dst.box.depth = 1;

   /* Destination dimensions have to be positive: */
   if (dstX0 < dstX1) {
      blit.dst.box.x = dstX0;
      blit.src.box.x = srcX0;
      blit.dst.box.width = dstX1 - dstX0;
      blit.src.box.width = srcX1 - srcX0;
   } else {
      blit.dst.box.x = dstX1;
      blit.src.box.x = srcX1;
      blit.dst.box.width = dstX0 - dstX1;
      blit.src.box.width = srcX0 - srcX1;
   }
   if (dstY0 < dstY1) {
      blit.dst.box.y = dstY0;
      blit.src.box.y = srcY0;
      blit.dst.box.height = dstY1 - dstY0;
      blit.src.box.height = srcY1 - srcY0;
   } else {
      blit.dst.box.y = dstY1;
      blit.src.box.y = srcY1;
      blit.dst.box.height = dstY0 - dstY1;
      blit.src.box.height = srcY0 - srcY1;
   }

   if (drawFB != ctx->WinSysDrawBuffer)
      st_window_rectangles_to_blit(ctx, &blit);

   blit.filter = pFilter;
   blit.render_condition_enable = TRUE;
   blit.alpha_blend = FALSE;

   if (mask & GL_COLOR_BUFFER_BIT) {
      struct gl_renderbuffer_attachment *srcAtt =
         &readFB->Attachment[readFB->_ColorReadBufferIndex];

      blit.mask = PIPE_MASK_RGBA;

      if (srcAtt->Type == GL_TEXTURE) {
         struct st_texture_object *srcObj = st_texture_object(srcAtt->Texture);
         GLuint i;

         if (!srcObj || !srcObj->pt) {
            return;
         }

         for (i = 0; i < drawFB->_NumColorDrawBuffers; i++) {
            struct st_renderbuffer *dstRb =
               st_renderbuffer(drawFB->_ColorDrawBuffers[i]);

            if (dstRb) {
               struct pipe_surface *dstSurf = dstRb->surface;

               if (dstSurf) {
                  blit.dst.resource = dstSurf->texture;
                  blit.dst.level = dstSurf->u.tex.level;
                  blit.dst.box.z = dstSurf->u.tex.first_layer;
                  blit.dst.format = dstSurf->format;

                  blit.src.resource = srcObj->pt;
                  blit.src.level = srcAtt->TextureLevel;
                  blit.src.box.z = srcAtt->Zoffset + srcAtt->CubeMapFace;
                  blit.src.format = srcObj->pt->format;

                  st_adjust_blit_for_srgb(&blit, ctx->Color.sRGBEnabled);

                  st->pipe->blit(st->pipe, &blit);
                  dstRb->defined = true; /* front buffer tracking */
               }
            }
         }
      }
      else {
         struct st_renderbuffer *srcRb =
            st_renderbuffer(readFB->_ColorReadBuffer);
         struct pipe_surface *srcSurf;
         GLuint i;

         if (!srcRb || !srcRb->surface) {
            return;
         }

         srcSurf = srcRb->surface;

         for (i = 0; i < drawFB->_NumColorDrawBuffers; i++) {
            struct st_renderbuffer *dstRb =
               st_renderbuffer(drawFB->_ColorDrawBuffers[i]);

            if (dstRb) {
               struct pipe_surface *dstSurf = dstRb->surface;

               if (dstSurf) {
                  blit.dst.resource = dstSurf->texture;
                  blit.dst.level = dstSurf->u.tex.level;
                  blit.dst.box.z = dstSurf->u.tex.first_layer;
                  blit.dst.format = dstSurf->format;

                  blit.src.resource = srcSurf->texture;
                  blit.src.level = srcSurf->u.tex.level;
                  blit.src.box.z = srcSurf->u.tex.first_layer;
                  blit.src.format = srcSurf->format;

                  st_adjust_blit_for_srgb(&blit, ctx->Color.sRGBEnabled);

                  st->pipe->blit(st->pipe, &blit);
                  dstRb->defined = true; /* front buffer tracking */
               }
            }
         }
      }
   }

   if (mask & depthStencil) {
      /* depth and/or stencil blit */

      /* get src/dst depth surfaces */
      struct st_renderbuffer *srcDepthRb =
         st_renderbuffer(readFB->Attachment[BUFFER_DEPTH].Renderbuffer);
      struct st_renderbuffer *dstDepthRb = 
         st_renderbuffer(drawFB->Attachment[BUFFER_DEPTH].Renderbuffer);
      struct pipe_surface *dstDepthSurf =
         dstDepthRb ? dstDepthRb->surface : NULL;

      struct st_renderbuffer *srcStencilRb =
         st_renderbuffer(readFB->Attachment[BUFFER_STENCIL].Renderbuffer);
      struct st_renderbuffer *dstStencilRb =
         st_renderbuffer(drawFB->Attachment[BUFFER_STENCIL].Renderbuffer);
      struct pipe_surface *dstStencilSurf =
         dstStencilRb ? dstStencilRb->surface : NULL;

      if (_mesa_has_depthstencil_combined(readFB) &&
          _mesa_has_depthstencil_combined(drawFB)) {
         blit.mask = 0;
         if (mask & GL_DEPTH_BUFFER_BIT)
            blit.mask |= PIPE_MASK_Z;
         if (mask & GL_STENCIL_BUFFER_BIT)
            blit.mask |= PIPE_MASK_S;

         blit.dst.resource = dstDepthSurf->texture;
         blit.dst.level = dstDepthSurf->u.tex.level;
         blit.dst.box.z = dstDepthSurf->u.tex.first_layer;
         blit.dst.format = dstDepthSurf->format;

         blit.src.resource = srcDepthRb->texture;
         blit.src.level = srcDepthRb->surface->u.tex.level;
         blit.src.box.z = srcDepthRb->surface->u.tex.first_layer;
         blit.src.format = srcDepthRb->surface->format;

         st->pipe->blit(st->pipe, &blit);
      }
      else {
         /* blitting depth and stencil separately */

         if (mask & GL_DEPTH_BUFFER_BIT) {
            blit.mask = PIPE_MASK_Z;

            blit.dst.resource = dstDepthSurf->texture;
            blit.dst.level = dstDepthSurf->u.tex.level;
            blit.dst.box.z = dstDepthSurf->u.tex.first_layer;
            blit.dst.format = dstDepthSurf->format;

            blit.src.resource = srcDepthRb->texture;
            blit.src.level = srcDepthRb->surface->u.tex.level;
            blit.src.box.z = srcDepthRb->surface->u.tex.first_layer;
            blit.src.format = srcDepthRb->surface->format;

            st->pipe->blit(st->pipe, &blit);
         }

         if (mask & GL_STENCIL_BUFFER_BIT) {
            blit.mask = PIPE_MASK_S;

            blit.dst.resource = dstStencilSurf->texture;
            blit.dst.level = dstStencilSurf->u.tex.level;
            blit.dst.box.z = dstStencilSurf->u.tex.first_layer;
            blit.dst.format = dstStencilSurf->format;

            blit.src.resource = srcStencilRb->texture;
            blit.src.level = srcStencilRb->surface->u.tex.level;
            blit.src.box.z = srcStencilRb->surface->u.tex.first_layer;
            blit.src.format = srcStencilRb->surface->format;

            st->pipe->blit(st->pipe, &blit);
         }
      }
   }
}
Exemple #25
0
/**
 * Called via ctx->Driver.AllocTextureImageBuffer().
 * If the texture object/buffer already has space for the indicated image,
 * we're done.  Otherwise, allocate memory for the new texture image.
 */
static GLboolean
st_AllocTextureImageBuffer(struct gl_context *ctx,
                           struct gl_texture_image *texImage)
{
   struct st_context *st = st_context(ctx);
   struct st_texture_image *stImage = st_texture_image(texImage);
   struct st_texture_object *stObj = st_texture_object(texImage->TexObject);
   const GLuint level = texImage->Level;
   GLuint width = texImage->Width;
   GLuint height = texImage->Height;
   GLuint depth = texImage->Depth;

   DBG("%s\n", __FUNCTION__);

   assert(!stImage->TexData);
   assert(!stImage->pt); /* xxx this might be wrong */

   /* Look if the parent texture object has space for this image */
   if (stObj->pt &&
       level <= stObj->pt->last_level &&
       st_texture_match_image(stObj->pt, texImage)) {
      /* this image will fit in the existing texture object's memory */
      pipe_resource_reference(&stImage->pt, stObj->pt);
      return GL_TRUE;
   }

   /* The parent texture object does not have space for this image */

   pipe_resource_reference(&stObj->pt, NULL);
   pipe_sampler_view_release(st->pipe, &stObj->sampler_view);

   if (!guess_and_alloc_texture(st, stObj, stImage)) {
      /* Probably out of memory.
       * Try flushing any pending rendering, then retry.
       */
      st_finish(st);
      if (!guess_and_alloc_texture(st, stObj, stImage)) {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
         return GL_FALSE;
      }
   }

   if (stObj->pt &&
       st_texture_match_image(stObj->pt, texImage)) {
      /* The image will live in the object's mipmap memory */
      pipe_resource_reference(&stImage->pt, stObj->pt);
      assert(stImage->pt);
      return GL_TRUE;
   }
   else {
      /* Create a new, temporary texture/resource/buffer to hold this
       * one texture image.  Note that when we later access this image
       * (either for mapping or copying) we'll want to always specify
       * mipmap level=0, even if the image represents some other mipmap
       * level.
       */
      enum pipe_format format =
         st_mesa_format_to_pipe_format(texImage->TexFormat);
      GLuint bindings = default_bindings(st, format);
      GLuint ptWidth, ptHeight, ptDepth, ptLayers;

      st_gl_texture_dims_to_pipe_dims(stObj->base.Target,
                                      width, height, depth,
                                      &ptWidth, &ptHeight, &ptDepth, &ptLayers);

      stImage->pt = st_texture_create(st,
                                      gl_target_to_pipe(stObj->base.Target),
                                      format,
                                      0, /* lastLevel */
                                      ptWidth,
                                      ptHeight,
                                      ptDepth,
                                      ptLayers,
                                      bindings);
      return stImage->pt != NULL;
   }
}
Exemple #26
0
/**
 * glGetTexImage() helper: decompress a compressed texture by rendering
 * a textured quad.  Store the results in the user's buffer.
 */
static void
decompress_with_blit(struct gl_context * ctx,
                     GLenum format, GLenum type, GLvoid *pixels,
                     struct gl_texture_image *texImage)
{
   struct st_context *st = st_context(ctx);
   struct pipe_context *pipe = st->pipe;
   struct st_texture_image *stImage = st_texture_image(texImage);
   struct st_texture_object *stObj = st_texture_object(texImage->TexObject);
   const GLuint width = texImage->Width;
   const GLuint height = texImage->Height;
   struct pipe_resource *dst_texture;
   struct pipe_blit_info blit;
   unsigned bind = (PIPE_BIND_RENDER_TARGET | PIPE_BIND_TRANSFER_READ);
   struct pipe_transfer *tex_xfer;
   ubyte *map;

   /* create temp / dest surface */
   if (!util_create_rgba_texture(pipe, width, height, bind,
                                 &dst_texture)) {
      _mesa_problem(ctx, "util_create_rgba_texture() failed "
                    "in decompress_with_blit()");
      return;
   }

   blit.src.resource = stObj->pt;
   blit.src.level = texImage->Level;
   blit.src.format = util_format_linear(stObj->pt->format);
   blit.dst.resource = dst_texture;
   blit.dst.level = 0;
   blit.dst.format = dst_texture->format;
   blit.src.box.x = blit.dst.box.x = 0;
   blit.src.box.y = blit.dst.box.y = 0;
   blit.src.box.z = 0; /* XXX compressed array textures? */
   blit.dst.box.z = 0;
   blit.src.box.width = blit.dst.box.width = width;
   blit.src.box.height = blit.dst.box.height = height;
   blit.src.box.depth = blit.dst.box.depth = 1;
   blit.mask = PIPE_MASK_RGBA;
   blit.filter = PIPE_TEX_FILTER_NEAREST;
   blit.scissor_enable = FALSE;

   /* blit/render/decompress */
   st->pipe->blit(st->pipe, &blit);

   pixels = _mesa_map_pbo_dest(ctx, &ctx->Pack, pixels);

   map = pipe_transfer_map(pipe, dst_texture, 0, 0,
                           PIPE_TRANSFER_READ,
                           0, 0, width, height, &tex_xfer);
   if (!map) {
      goto end;
   }

   /* copy/pack data into user buffer */
   if (_mesa_format_matches_format_and_type(stImage->base.TexFormat,
                                            format, type,
                                            ctx->Pack.SwapBytes)) {
      /* memcpy */
      const uint bytesPerRow = width * util_format_get_blocksize(stImage->pt->format);
      /* map the dst_surface so we can read from it */
      GLuint row;
      for (row = 0; row < height; row++) {
         GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width,
                                              height, format, type, row, 0);
         memcpy(dest, map, bytesPerRow);
         map += tex_xfer->stride;
      }
      pipe_transfer_unmap(pipe, tex_xfer);
   }
   else {
      /* format translation via floats */
      GLuint row;
      enum pipe_format pformat = util_format_linear(dst_texture->format);
      GLfloat *rgba;

      rgba = malloc(width * 4 * sizeof(GLfloat));
      if (!rgba) {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()");
         goto end;
      }

      for (row = 0; row < height; row++) {
         const GLbitfield transferOps = 0x0; /* bypassed for glGetTexImage() */
         GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width,
                                              height, format, type, row, 0);

         if (ST_DEBUG & DEBUG_FALLBACK)
            debug_printf("%s: fallback format translation\n", __FUNCTION__);

         /* get float[4] rgba row from surface */
         pipe_get_tile_rgba_format(tex_xfer, map, 0, row, width, 1,
                                   pformat, rgba);

         _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format,
                                    type, dest, &ctx->Pack, transferOps);
      }

      free(rgba);
   }

end:
   if (map)
      pipe_transfer_unmap(pipe, tex_xfer);

   _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
   pipe_resource_reference(&dst_texture, NULL);
}
Exemple #27
0
static void
st_bind_images(struct st_context *st, struct gl_shader *shader,
              unsigned shader_type)
{
   unsigned i;
   struct pipe_image_view images[MAX_IMAGE_UNIFORMS];
   struct gl_program_constants *c;

   if (!shader || !st->pipe->set_shader_images)
      return;

   c = &st->ctx->Const.Program[shader->Stage];

   for (i = 0; i < shader->NumImages; i++) {
      struct gl_image_unit *u = &st->ctx->ImageUnits[shader->ImageUnits[i]];
      struct st_texture_object *stObj = st_texture_object(u->TexObj);
      struct pipe_image_view *img = &images[i];

      if (!_mesa_is_image_unit_valid(st->ctx, u) ||
          !st_finalize_texture(st->ctx, st->pipe, u->TexObj) ||
          !stObj->pt) {
         memset(img, 0, sizeof(*img));
         continue;
      }

      img->resource = stObj->pt;
      img->format = st_mesa_format_to_pipe_format(st, u->_ActualFormat);

      switch (u->Access) {
      case GL_READ_ONLY:
         img->access = PIPE_IMAGE_ACCESS_READ;
         break;
      case GL_WRITE_ONLY:
         img->access = PIPE_IMAGE_ACCESS_WRITE;
         break;
      case GL_READ_WRITE:
         img->access = PIPE_IMAGE_ACCESS_READ_WRITE;
         break;
      default:
         unreachable("bad gl_image_unit::Access");
      }

      if (stObj->pt->target == PIPE_BUFFER) {
         unsigned base, size;
         unsigned f, n;
         const struct util_format_description *desc
            = util_format_description(img->format);

         base = stObj->base.BufferOffset;
         assert(base < stObj->pt->width0);
         size = MIN2(stObj->pt->width0 - base, (unsigned)stObj->base.BufferSize);

         f = (base / (desc->block.bits / 8)) * desc->block.width;
         n = (size / (desc->block.bits / 8)) * desc->block.width;
         assert(n > 0);
         img->u.buf.first_element = f;
         img->u.buf.last_element  = f + (n - 1);
      } else {
         img->u.tex.level = u->Level + stObj->base.MinLevel;
         if (stObj->pt->target == PIPE_TEXTURE_3D) {
            if (u->Layered) {
               img->u.tex.first_layer = 0;
               img->u.tex.last_layer = u_minify(stObj->pt->depth0, img->u.tex.level) - 1;
            } else {
               img->u.tex.first_layer = u->_Layer;
               img->u.tex.last_layer = u->_Layer;
            }
         } else {
            img->u.tex.first_layer = u->_Layer + stObj->base.MinLayer;
            img->u.tex.last_layer = u->_Layer + stObj->base.MinLayer;
            if (u->Layered && img->resource->array_size > 1) {
               if (stObj->base.Immutable)
                  img->u.tex.last_layer += stObj->base.NumLayers - 1;
               else
                  img->u.tex.last_layer += img->resource->array_size - 1;
            }
         }
      }
   }
   cso_set_shader_images(st->cso_context, shader_type, 0, shader->NumImages,
                         images);
   /* clear out any stale shader images */
   if (shader->NumImages < c->MaxImageUniforms)
      cso_set_shader_images(
            st->cso_context, shader_type,
            shader->NumImages,
            c->MaxImageUniforms - shader->NumImages,
            NULL);
}
Exemple #28
0
static void
st_vdpau_map_surface(struct gl_context *ctx, GLenum target, GLenum access,
                     GLboolean output, struct gl_texture_object *texObj,
                     struct gl_texture_image *texImage,
                     const GLvoid *vdpSurface, GLuint index)
{
   int (*getProcAddr)(uint32_t device, uint32_t id, void **ptr);
   uint32_t device = (uintptr_t)ctx->vdpDevice;

   struct st_context *st = st_context(ctx);
   struct st_texture_object *stObj = st_texture_object(texObj);
   struct st_texture_image *stImage = st_texture_image(texImage);
 
   struct pipe_resource *res;
   struct pipe_sampler_view *sv, templ;
   gl_format texFormat;

   getProcAddr = ctx->vdpGetProcAddress;
   if (output) {
      VdpOutputSurfaceGallium *f;
      
      if (getProcAddr(device, VDP_FUNC_ID_OUTPUT_SURFACE_GALLIUM, (void**)&f)) {
         _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV");
         return;
      }

      res = f((uintptr_t)vdpSurface);

      if (!res) {
         _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV");
         return;
      }

   } else {
      VdpVideoSurfaceGallium *f;

      struct pipe_video_buffer *buffer;
      struct pipe_sampler_view **samplers;

      if (getProcAddr(device, VDP_FUNC_ID_VIDEO_SURFACE_GALLIUM, (void**)&f)) {
         _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV");
         return;
      }

      buffer = f((uintptr_t)vdpSurface);
      if (!buffer) {
         _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV");
         return;
      }

      samplers = buffer->get_sampler_view_planes(buffer);
      if (!samplers) {
         _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV");
         return;
      }

      sv = samplers[index >> 1];
      if (!sv) {
         _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV");
         return;
      }

      res = sv->texture;
   }

   if (!res) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV");
      return;
   }

   /* do we have different screen objects ? */
   if (res->screen != st->pipe->screen) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV");
      return;
   }

   /* switch to surface based */
   if (!stObj->surface_based) {
      _mesa_clear_texture_object(ctx, texObj);
      stObj->surface_based = GL_TRUE;
   }

   texFormat = st_pipe_format_to_mesa_format(res->format);

   _mesa_init_teximage_fields(ctx, texImage,
                              res->width0, res->height0, 1, 0, GL_RGBA,
                              texFormat);

   pipe_resource_reference(&stObj->pt, res);
   pipe_sampler_view_reference(&stObj->sampler_view, NULL);
   pipe_resource_reference(&stImage->pt, res);

   u_sampler_view_default_template(&templ, res, res->format);
   templ.u.tex.first_layer = index & 1;
   templ.u.tex.last_layer = index & 1;
   templ.swizzle_r = GET_SWZ(stObj->base._Swizzle, 0);
   templ.swizzle_g = GET_SWZ(stObj->base._Swizzle, 1);
   templ.swizzle_b = GET_SWZ(stObj->base._Swizzle, 2);
   templ.swizzle_a = GET_SWZ(stObj->base._Swizzle, 3);
   stObj->sampler_view = st->pipe->create_sampler_view(st->pipe, res, &templ);

   stObj->width0 = res->width0;
   stObj->height0 = res->height0;
   stObj->depth0 = 1;
   stObj->surface_format = res->format;

   _mesa_dirty_texobj(ctx, texObj);
}
/**
 * Called by ctx->Driver.RenderTexture
 */
static void
st_render_texture(struct gl_context *ctx,
                  struct gl_framebuffer *fb,
                  struct gl_renderbuffer_attachment *att)
{
   struct st_context *st = st_context(ctx);
   struct pipe_context *pipe = st->pipe;
   struct st_renderbuffer *strb;
   struct gl_renderbuffer *rb;
   struct pipe_resource *pt;
   struct st_texture_object *stObj;
   const struct gl_texture_image *texImage;
   struct pipe_surface surf_tmpl;

   if (!st_finalize_texture(ctx, pipe, att->Texture))
      return;

   pt = st_get_texobj_resource(att->Texture);
   assert(pt);

   /* get pointer to texture image we're rendeing to */
   texImage = _mesa_get_attachment_teximage(att);

   /* create new renderbuffer which wraps the texture image.
    * Use the texture's name as the renderbuffer's name so that we have
    * something that's non-zero (to determine vertical orientation) and
    * possibly helpful for debugging.
    */
   rb = st_new_renderbuffer(ctx, att->Texture->Name);
   if (!rb) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()");
      return;
   }

   _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
   assert(rb->RefCount == 1);
   rb->AllocStorage = NULL; /* should not get called */
   strb = st_renderbuffer(rb);

   assert(strb->Base.RefCount > 0);

   /* get the texture for the texture object */
   stObj = st_texture_object(att->Texture);

   /* point renderbuffer at texobject */
   strb->rtt = stObj;
   strb->rtt_level = att->TextureLevel;
   strb->rtt_face = att->CubeMapFace;
   strb->rtt_slice = att->Zoffset;

   rb->Width = texImage->Width2;
   rb->Height = texImage->Height2;
   rb->_BaseFormat = texImage->_BaseFormat;
   rb->InternalFormat = texImage->InternalFormat;

   pipe_resource_reference( &strb->texture, pt );

   pipe_surface_release(pipe, &strb->surface);

   assert(strb->rtt_level <= strb->texture->last_level);

   /* new surface for rendering into the texture */
   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
   surf_tmpl.format = ctx->Color.sRGBEnabled
      ? strb->texture->format : util_format_linear(strb->texture->format);
   surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
   surf_tmpl.u.tex.level = strb->rtt_level;
   surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice;
   surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice;
   strb->surface = pipe->create_surface(pipe,
                                        strb->texture,
                                        &surf_tmpl);

   strb->Base.Format = st_pipe_format_to_mesa_format(pt->format);

   /* Invalidate buffer state so that the pipe's framebuffer state
    * gets updated.
    * That's where the new renderbuffer (which we just created) gets
    * passed to the pipe as a (color/depth) render target.
    */
   st_invalidate_state(ctx, _NEW_BUFFERS);


   /* Need to trigger a call to update_framebuffer() since we just
    * attached a new renderbuffer.
    */
   ctx->NewState |= _NEW_BUFFERS;
}
Exemple #30
0
/**
 * Called via ctx->Driver.DrawAtlasBitmap()
 */
static void
st_DrawAtlasBitmaps(struct gl_context *ctx,
                    const struct gl_bitmap_atlas *atlas,
                    GLuint count, const GLubyte *ids)
{
    struct st_context *st = st_context(ctx);
    struct pipe_context *pipe = st->pipe;
    struct st_texture_object *stObj = st_texture_object(atlas->texObj);
    struct pipe_sampler_view *sv;
    /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */
    const float z = ctx->Current.RasterPos[2] * 2.0f - 1.0f;
    const float *color = ctx->Current.RasterColor;
    const float clip_x_scale = 2.0f / st->state.framebuffer.width;
    const float clip_y_scale = 2.0f / st->state.framebuffer.height;
    const unsigned num_verts = count * 4;
    const unsigned num_vert_bytes = num_verts * sizeof(struct st_util_vertex);
    struct st_util_vertex *verts;
    struct pipe_vertex_buffer vb = {0};
    unsigned i;

    if (!st->bitmap.cache) {
        init_bitmap_state(st);
    }

    st_flush_bitmap_cache(st);

    st_validate_state(st, ST_PIPELINE_RENDER);
    st_invalidate_readpix_cache(st);

    sv = st_create_texture_sampler_view(pipe, stObj->pt);
    if (!sv) {
        _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCallLists(bitmap text)");
        return;
    }

    setup_render_state(ctx, sv, color, true);

    vb.stride = sizeof(struct st_util_vertex);

    u_upload_alloc(st->uploader, 0, num_vert_bytes, 4,
                   &vb.buffer_offset, &vb.buffer, (void **) &verts);

    /* build quads vertex data */
    for (i = 0; i < count; i++) {
        const GLfloat epsilon = 0.0001F;
        const struct gl_bitmap_glyph *g = &atlas->glyphs[ids[i]];
        const float xmove = g->xmove, ymove = g->ymove;
        const float xorig = g->xorig, yorig = g->yorig;
        const float s0 = g->x, t0 = g->y;
        const float s1 = s0 + g->w, t1 = t0 + g->h;
        const float x0 = IFLOOR(ctx->Current.RasterPos[0] - xorig + epsilon);
        const float y0 = IFLOOR(ctx->Current.RasterPos[1] - yorig + epsilon);
        const float x1 = x0 + g->w, y1 = y0 + g->h;
        const float clip_x0 = x0 * clip_x_scale - 1.0f;
        const float clip_y0 = y0 * clip_y_scale - 1.0f;
        const float clip_x1 = x1 * clip_x_scale - 1.0f;
        const float clip_y1 = y1 * clip_y_scale - 1.0f;

        /* lower-left corner */
        verts->x = clip_x0;
        verts->y = clip_y0;
        verts->z = z;
        verts->r = color[0];
        verts->g = color[1];
        verts->b = color[2];
        verts->a = color[3];
        verts->s = s0;
        verts->t = t0;
        verts++;

        /* lower-right corner */
        verts->x = clip_x1;
        verts->y = clip_y0;
        verts->z = z;
        verts->r = color[0];
        verts->g = color[1];
        verts->b = color[2];
        verts->a = color[3];
        verts->s = s1;
        verts->t = t0;
        verts++;

        /* upper-right corner */
        verts->x = clip_x1;
        verts->y = clip_y1;
        verts->z = z;
        verts->r = color[0];
        verts->g = color[1];
        verts->b = color[2];
        verts->a = color[3];
        verts->s = s1;
        verts->t = t1;
        verts++;

        /* upper-left corner */
        verts->x = clip_x0;
        verts->y = clip_y1;
        verts->z = z;
        verts->r = color[0];
        verts->g = color[1];
        verts->b = color[2];
        verts->a = color[3];
        verts->s = s0;
        verts->t = t1;
        verts++;

        /* Update the raster position */
        ctx->Current.RasterPos[0] += xmove;
        ctx->Current.RasterPos[1] += ymove;
    }

    u_upload_unmap(st->uploader);

    cso_set_vertex_buffers(st->cso_context,
                           cso_get_aux_vertex_buffer_slot(st->cso_context),
                           1, &vb);

    cso_draw_arrays(st->cso_context, PIPE_PRIM_QUADS, 0, num_verts);

    restore_render_state(ctx);

    pipe_resource_reference(&vb.buffer, NULL);

    pipe_sampler_view_reference(&sv, NULL);

    /* We uploaded modified constants, need to invalidate them. */
    st->dirty |= ST_NEW_FS_CONSTANTS;
}