Exemple #1
0
void
st_generate_mipmap(GLcontext *ctx, GLenum target,
                   struct gl_texture_object *texObj)
{
   struct st_context *st = ctx->st;
   struct pipe_texture *pt = st_get_texobj_texture(texObj);
   const uint baseLevel = texObj->BaseLevel;
   uint lastLevel;
   uint dstLevel;

   if (!pt)
      return;

   lastLevel = pt->last_level;

   if (!st_render_mipmap(st, target, pt, baseLevel, lastLevel)) {
      fallback_generate_mipmap(ctx, target, texObj);
   }

   /* Fill in the Mesa gl_texture_image fields */
   for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
      const uint srcLevel = dstLevel - 1;
      const struct gl_texture_image *srcImage
         = _mesa_get_tex_image(ctx, texObj, target, srcLevel);
      struct gl_texture_image *dstImage;
      struct st_texture_image *stImage;
      uint dstWidth = pt->width[dstLevel];
      uint dstHeight = pt->height[dstLevel];
      uint dstDepth = pt->depth[dstLevel];
      uint border = srcImage->Border;

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

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

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

      dstImage->TexFormat = srcImage->TexFormat;

      stImage = (struct st_texture_image *) dstImage;
      pipe_texture_reference(&stImage->pt, pt);
   }
}
Exemple #2
0
GLboolean
_mesa_meta_bind_rb_as_tex_image(struct gl_context *ctx,
                                struct gl_renderbuffer *rb,
                                GLuint *tex,
                                struct gl_texture_object **texObj,
                                GLenum *target)
{
   struct gl_texture_image *texImage;

   if (rb->NumSamples > 1)
      *target = GL_TEXTURE_2D_MULTISAMPLE;
   else
      *target = GL_TEXTURE_2D;

   _mesa_GenTextures(1, tex);
   _mesa_BindTexture(*target, *tex);
   *texObj = _mesa_lookup_texture(ctx, *tex);
   texImage = _mesa_get_tex_image(ctx, *texObj, *target, 0);

   if (!ctx->Driver.BindRenderbufferTexImage(ctx, rb, texImage)) {
      _mesa_DeleteTextures(1, tex);
      return false;
   }

   if (ctx->Driver.FinishRenderTexture && !rb->NeedsFinishRenderTexture) {
      rb->NeedsFinishRenderTexture = true;
      ctx->Driver.FinishRenderTexture(ctx, rb);
   }

   return true;
}
Exemple #3
0
/**
 * Compute the expected number of mipmap levels in the texture given
 * the width/height/depth of the base image and the GL_TEXTURE_BASE_LEVEL/
 * GL_TEXTURE_MAX_LEVEL settings.  This will tell us how many mipmap
 * levels should be generated.
 */
static GLuint
compute_num_levels(struct gl_context *ctx,
                   struct gl_texture_object *texObj,
                   GLenum target)
{
   if (target == GL_TEXTURE_RECTANGLE_ARB) {
      return 1;
   }
   else {
      const struct gl_texture_image *baseImage = 
         _mesa_get_tex_image(ctx, texObj, target, texObj->BaseLevel);
      GLuint size, numLevels;

      size = MAX2(baseImage->Width2, baseImage->Height2);
      size = MAX2(size, baseImage->Depth2);

      numLevels = texObj->BaseLevel;

      while (size > 0) {
         numLevels++;
         size >>= 1;
      }

      numLevels = MIN2(numLevels, texObj->MaxLevel + 1);

      assert(numLevels >= 1);

      return numLevels;
   }
}
Exemple #4
0
/**
 * Clear all fields of texture object to zeros.  Used for proxy texture tests.
 */
static void
clear_image_fields(struct gl_context *ctx,
                   GLuint dims,
                   struct gl_texture_object *texObj)
{
   const GLenum target = texObj->Target;
   const GLuint numFaces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
   GLint level;
   GLuint face;

   for (level = 0; level < Elements(texObj->Image[0]); level++) {
      for (face = 0; face < numFaces; face++) {
         const GLenum faceTarget =
            (target == GL_TEXTURE_CUBE_MAP)
            ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + face : target;
         struct gl_texture_image *texImage =
            _mesa_get_tex_image(ctx, texObj, faceTarget, level);

	 if (!texImage) {
	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage%uD", dims);
            return;
	 }

         _mesa_init_teximage_fields(ctx, target, texImage,
                                    0, 0, 0, 0, GL_NONE, MESA_FORMAT_NONE);
      }
   }
}
Exemple #5
0
/**
 * Create a texture image that wraps a renderbuffer.
 */
static struct gl_texture_image *
wrap_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
{
   GLenum texTarget;
   struct gl_texture_object *texObj;
   struct gl_texture_image *texImage;

   if (rb->NumSamples > 1)
      texTarget = GL_TEXTURE_2D_MULTISAMPLE;
   else
      texTarget = GL_TEXTURE_2D;

   /* Texture ID is not significant since it never goes into the hash table */
   texObj = ctx->Driver.NewTextureObject(ctx, 0, texTarget);
   assert(texObj);
   if (!texObj)
      return NULL;

   texImage = _mesa_get_tex_image(ctx, texObj, texTarget, 0);
   assert(texImage);
   if (!texImage)
      return NULL;

   if (!ctx->Driver.BindRenderbufferTexImage(ctx, rb, texImage)) {
      _mesa_problem(ctx, "Failed to create texture from renderbuffer");
      return NULL;
   }

   if (ctx->Driver.FinishRenderTexture && !rb->NeedsFinishRenderTexture) {
      rb->NeedsFinishRenderTexture = true;
      ctx->Driver.FinishRenderTexture(ctx, rb);
   }

   return texImage;
}
/* This function makes a texture view without bothering with all of the API
 * checks.  Most of them are the same for CopyTexSubImage so checking would
 * be redundant.  The one major difference is that we don't check for
 * whether the texture is immutable or not.  However, since the view will
 * be created and then immediately destroyed, this should not be a problem.
 */
static bool
make_view(struct gl_context *ctx, struct gl_texture_image *tex_image,
          struct gl_texture_image **view_tex_image, GLuint *view_tex_name,
          GLenum internal_format)
{
   struct gl_texture_object *tex_obj = tex_image->TexObject;
   struct gl_texture_object *view_tex_obj;
   mesa_format tex_format;

   /* Set up the new texture object */
   _mesa_GenTextures(1, view_tex_name);
   view_tex_obj = _mesa_lookup_texture(ctx, *view_tex_name);
   if (!view_tex_obj)
      return false;

   tex_format = _mesa_choose_texture_format(ctx, view_tex_obj, tex_obj->Target,
                                           0, internal_format,
                                           GL_NONE, GL_NONE);

   if (!ctx->Driver.TestProxyTexImage(ctx, tex_obj->Target, 0, tex_format,
                                      tex_image->Width, tex_image->Height,
                                      tex_image->Depth, 0)) {
      _mesa_DeleteTextures(1, view_tex_name);
      *view_tex_name = 0;
      return false;
   }

   view_tex_obj->Target = tex_obj->Target;

   *view_tex_image = _mesa_get_tex_image(ctx, view_tex_obj, tex_obj->Target, 0);

   if (!*view_tex_image) {
      _mesa_DeleteTextures(1, view_tex_name);
      *view_tex_name = 0;
      return false;
   }

   _mesa_init_teximage_fields(ctx, *view_tex_image,
                              tex_image->Width, tex_image->Height,
                              tex_image->Depth,
                              0, internal_format, tex_format);

   view_tex_obj->MinLevel = tex_image->Level;
   view_tex_obj->NumLevels = 1;
   view_tex_obj->MinLayer = tex_obj->MinLayer;
   view_tex_obj->NumLayers = tex_obj->NumLayers;
   view_tex_obj->Immutable = tex_obj->Immutable;
   view_tex_obj->ImmutableLevels = tex_obj->ImmutableLevels;
   view_tex_obj->Target = tex_obj->Target;

   if (ctx->Driver.TextureView != NULL &&
       !ctx->Driver.TextureView(ctx, view_tex_obj, tex_obj)) {
      _mesa_DeleteTextures(1, view_tex_name);
      *view_tex_name = 0;
      return false; /* driver recorded error */
   }

   return true;
}
Exemple #7
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 #8
0
void
intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target,
		   GLint texture_format,
		   __DRIdrawable *dPriv)
{
   struct gl_framebuffer *fb = dPriv->driverPrivate;
   struct brw_context *brw = pDRICtx->driverPrivate;
   struct gl_context *ctx = &brw->ctx;
   struct intel_renderbuffer *rb;
   struct gl_texture_object *texObj;
   struct gl_texture_image *texImage;
   int level = 0, internalFormat = 0;
   mesa_format texFormat = MESA_FORMAT_NONE;

   texObj = _mesa_get_current_tex_object(ctx, target);

   if (!texObj)
      return;

   if (dPriv->lastStamp != dPriv->dri2.stamp ||
       !pDRICtx->driScreenPriv->dri2.useInvalidate)
      intel_update_renderbuffers(pDRICtx, dPriv);

   rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
   /* If the miptree isn't set, then intel_update_renderbuffers was unable
    * to get the BO for the drawable from the window system.
    */
   if (!rb || !rb->mt)
      return;

   if (rb->mt->cpp == 4) {
      if (texture_format == __DRI_TEXTURE_FORMAT_RGB) {
         internalFormat = GL_RGB;
         texFormat = MESA_FORMAT_B8G8R8X8_UNORM;
      }
      else {
         internalFormat = GL_RGBA;
         texFormat = MESA_FORMAT_B8G8R8A8_UNORM;
      }
   } else if (rb->mt->cpp == 2) {
      internalFormat = GL_RGB;
      texFormat = MESA_FORMAT_B5G6R5_UNORM;
   }

   _mesa_lock_texture(&brw->ctx, texObj);
   texImage = _mesa_get_tex_image(ctx, texObj, target, level);
   intel_miptree_make_shareable(brw, rb->mt);
   intel_set_texture_image_bo(ctx, texImage, rb->mt->bo, target,
                              internalFormat, texFormat, 0,
                              rb->Base.Base.Width,
                              rb->Base.Base.Height,
                              rb->mt->pitch,
                              0, 0, 0);
   _mesa_unlock_texture(&brw->ctx, texObj);
}
Exemple #9
0
void
intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target,
		   GLint texture_format,
		   __DRIdrawable *dPriv)
{
   struct gl_framebuffer *fb = dPriv->driverPrivate;
   struct intel_context *intel = pDRICtx->driverPrivate;
   struct gl_context *ctx = &intel->ctx;
   struct intel_texture_object *intelObj;
   struct intel_renderbuffer *rb;
   struct gl_texture_object *texObj;
   struct gl_texture_image *texImage;
   int level = 0, internalFormat = 0;
   gl_format texFormat = MESA_FORMAT_NONE;

   texObj = _mesa_get_current_tex_object(ctx, target);
   intelObj = intel_texture_object(texObj);

   if (!intelObj)
      return;

   if (dPriv->lastStamp != dPriv->dri2.stamp ||
       !pDRICtx->driScreenPriv->dri2.useInvalidate)
      intel_update_renderbuffers(pDRICtx, dPriv);

   rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
   /* If the region isn't set, then intel_update_renderbuffers was unable
    * to get the buffers for the drawable.
    */
   if (!rb || !rb->mt)
      return;

   if (rb->mt->cpp == 4) {
      if (texture_format == __DRI_TEXTURE_FORMAT_RGB) {
         internalFormat = GL_RGB;
         texFormat = MESA_FORMAT_XRGB8888;
      }
      else {
         internalFormat = GL_RGBA;
         texFormat = MESA_FORMAT_ARGB8888;
      }
   } else if (rb->mt->cpp == 2) {
      internalFormat = GL_RGB;
      texFormat = MESA_FORMAT_RGB565;
   }

   _mesa_lock_texture(&intel->ctx, texObj);
   texImage = _mesa_get_tex_image(ctx, texObj, target, level);
   intel_set_texture_image_region(ctx, texImage, rb->mt->region, target,
                                  internalFormat, texFormat, 0,
                                  rb->mt->region->width,
                                  rb->mt->region->height,
                                  0, 0);
   _mesa_unlock_texture(&intel->ctx, texObj);
}
Exemple #10
0
/** Helper to get a particular texture image in a texture object */
static struct gl_texture_image *
get_tex_image(struct gl_context *ctx,
              struct gl_texture_object *texObj,
              GLuint face, GLuint level)
{
   const GLenum faceTarget =
      (texObj->Target == GL_TEXTURE_CUBE_MAP ||
       texObj->Target == GL_PROXY_TEXTURE_CUBE_MAP)
      ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + face : texObj->Target;
   return _mesa_get_tex_image(ctx, texObj, faceTarget, level);
}
Exemple #11
0
void GLAPIENTRY
_mesa_VDPAUMapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces)
{
   GET_CURRENT_CONTEXT(ctx);
   int i;

   if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUUnmapSurfacesNV");
      return;
   }

   for (i = 0; i < numSurfaces; ++i) {
      struct vdp_surface *surf = (struct vdp_surface *)surfaces[i];

      if (!_mesa_set_search(ctx->vdpSurfaces, surf)) {
         _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUSurfaceAccessNV");
         return;
      }

      if (surf->state == GL_SURFACE_MAPPED_NV) {
         _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUSurfaceAccessNV");
         return;
      }
   }

   for (i = 0; i < numSurfaces; ++i) {
      struct vdp_surface *surf = (struct vdp_surface *)surfaces[i];
      unsigned numTextureNames = surf->output ? 1 : 4;
      unsigned j;

      for (j = 0; j < numTextureNames; ++j) {
         struct gl_texture_object *tex = surf->textures[j];
         struct gl_texture_image *image;

         _mesa_lock_texture(ctx, tex);
         image = _mesa_get_tex_image(ctx, tex, surf->target, 0);
         if (!image) {
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "VDPAUMapSurfacesNV");
            _mesa_unlock_texture(ctx, tex);
            return;
         }

         ctx->Driver.FreeTextureImageBuffer(ctx, image);

         ctx->Driver.VDPAUMapSurface(ctx, surf->target, surf->access,
                                     surf->output, tex, image,
                                     surf->vdpSurface, j);

         _mesa_unlock_texture(ctx, tex);
      }
      surf->state = GL_SURFACE_MAPPED_NV;
   }
}
Exemple #12
0
/** Redirect rendering into stfb's surface to a texture image */
int
st_bind_teximage(struct st_framebuffer *stfb, uint surfIndex,
                 int target, int format, int level)
{
   GET_CURRENT_CONTEXT(ctx);
   struct st_context *st = ctx->st;
   struct pipe_context *pipe = st->pipe;
   struct pipe_screen *screen = pipe->screen;
   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_image *stImage;
   struct st_renderbuffer *strb;
   GLint face = 0, slice = 0;

   assert(surfIndex <= ST_SURFACE_DEPTH);

   strb = st_renderbuffer(stfb->Base.Attachment[surfIndex].Renderbuffer);

   if (strb->texture_save || strb->surface_save) {
      /* Error! */
      return 0;
   }

   if (target == ST_TEXTURE_2D) {
      texObj = texUnit->CurrentTex[TEXTURE_2D_INDEX];
      texImage = _mesa_get_tex_image(ctx, texObj, GL_TEXTURE_2D, level);
      stImage = st_texture_image(texImage);
   }
   else {
      /* unsupported target */
      return 0;
   }

   st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);

   /* save the renderbuffer's surface/texture info */
   pipe_texture_reference(&strb->texture_save, strb->texture);
   pipe_surface_reference(&strb->surface_save, strb->surface);

   /* plug in new surface/texture info */
   pipe_texture_reference(&strb->texture, stImage->pt);
   strb->surface = screen->get_tex_surface(screen, strb->texture,
                                           face, level, slice,
                                           (PIPE_BUFFER_USAGE_GPU_READ |
                                            PIPE_BUFFER_USAGE_GPU_WRITE));

   st->dirty.st |= ST_NEW_FRAMEBUFFER;

   return 1;
}
Exemple #13
0
/**
 * Return pointer to a default/fallback texture.
 * The texture is a 2D 8x8 RGBA texture with all texels = (0,0,0,1).
 * That's the value a sampler should get when sampling from an
 * incomplete texture.
 */
struct gl_texture_object *
_mesa_get_fallback_texture(struct gl_context *ctx)
{
   if (!ctx->Shared->FallbackTex) {
      /* create fallback texture now */
      static GLubyte texels[8 * 8][4];
      struct gl_texture_object *texObj;
      struct gl_texture_image *texImage;
      gl_format texFormat;
      GLuint i;

      for (i = 0; i < 8 * 8; i++) {
         texels[i][0] =
         texels[i][1] =
         texels[i][2] = 0x0;
         texels[i][3] = 0xff;
      }

      /* create texture object */
      texObj = ctx->Driver.NewTextureObject(ctx, 0, GL_TEXTURE_2D);
      assert(texObj->RefCount == 1);
      texObj->Sampler.MinFilter = GL_NEAREST;
      texObj->Sampler.MagFilter = GL_NEAREST;

      /* create level[0] texture image */
      texImage = _mesa_get_tex_image(ctx, texObj, GL_TEXTURE_2D, 0);

      texFormat = ctx->Driver.ChooseTextureFormat(ctx, GL_RGBA, GL_RGBA,
                                                  GL_UNSIGNED_BYTE);

      /* init the image fields */
      _mesa_init_teximage_fields(ctx, texImage,
                                 8, 8, 1, 0, GL_RGBA, texFormat); 

      ASSERT(texImage->TexFormat != MESA_FORMAT_NONE);

      /* set image data */
      ctx->Driver.TexImage2D(ctx, texImage, GL_RGBA,
                             8, 8, 0,
                             GL_RGBA, GL_UNSIGNED_BYTE, texels,
                             &ctx->DefaultPacking);

      _mesa_test_texobj_completeness(ctx, texObj);
      assert(texObj->_Complete);

      ctx->Shared->FallbackTex = texObj;
   }
   return ctx->Shared->FallbackTex;
}
Exemple #14
0
/**
 * Compute the expected number of mipmap levels in the texture given
 * the width/height/depth of the base image and the GL_TEXTURE_BASE_LEVEL/
 * GL_TEXTURE_MAX_LEVEL settings.  This will tell us how many mipmap
 * levels should be generated.
 */
static GLuint
compute_num_levels(struct gl_context *ctx,
                   struct gl_texture_object *texObj,
                   GLenum target)
{
   const struct gl_texture_image *baseImage;
   GLuint numLevels;

   baseImage = _mesa_get_tex_image(ctx, texObj, target, texObj->BaseLevel);

   numLevels = texObj->BaseLevel + baseImage->MaxNumLevels;
   numLevels = MIN2(numLevels, (GLuint) texObj->MaxLevel + 1);
   assert(numLevels >= 1);

   return numLevels;
}
Exemple #15
0
/**
 * Initialize new texture's gl_texture_image structures. Will not call driver
 * to allocate new space, simply record relevant layer, face, format, etc.
 * \return GL_FALSE if any error, GL_TRUE otherwise.
 */
static GLboolean
initialize_texture_fields(struct gl_context *ctx,
                          GLenum target,
                          struct gl_texture_object *texObj,
                          GLint levels,
                          GLsizei width, GLsizei height, GLsizei depth,
                          GLenum internalFormat, mesa_format texFormat)
{
   const GLuint numFaces = _mesa_num_tex_faces(target);
   GLint level, levelWidth = width, levelHeight = height, levelDepth = depth;
   GLuint face;

   /* Pretend we are bound to initialize the gl_texture_image structs */
   texObj->Target = target;

   /* Set up all the texture object's gl_texture_images */
   for (level = 0; level < levels; level++) {
      for (face = 0; face < numFaces; face++) {
         struct gl_texture_image *texImage;
         GLenum faceTarget = target;

         if (target == GL_TEXTURE_CUBE_MAP)
            faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;

         texImage = _mesa_get_tex_image(ctx, texObj, faceTarget, level);

         if (!texImage) {
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage");
            return GL_FALSE;
         }

         _mesa_init_teximage_fields(ctx, texImage,
                                    levelWidth, levelHeight, levelDepth,
                                    0, internalFormat, texFormat);
      }

      _mesa_next_mipmap_level_size(target, 0,
                                   levelWidth, levelHeight, levelDepth,
                                   &levelWidth, &levelHeight, &levelDepth);
   }

   /* "unbind" */
   texObj->Target = 0;

   return GL_TRUE;
}
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;
}
Exemple #17
0
static void swrastSetTexBuffer2(__DRIcontext *pDRICtx, GLint target,
				GLint texture_format, __DRIdrawable *dPriv)
{
    struct dri_context *dri_ctx;
    int x, y, w, h;
    __DRIscreen *sPriv = dPriv->driScreenPriv;
    struct gl_texture_unit *texUnit;
    struct gl_texture_object *texObj;
    struct gl_texture_image *texImage;
    struct swrast_texture_image *swImage;
    uint32_t internalFormat;
    gl_format texFormat;

    dri_ctx = pDRICtx->driverPrivate;

    internalFormat = (texture_format == __DRI_TEXTURE_FORMAT_RGB ? 3 : 4);

    texUnit = _mesa_get_current_tex_unit(&dri_ctx->Base);
    texObj = _mesa_select_tex_object(&dri_ctx->Base, texUnit, target);
    texImage = _mesa_get_tex_image(&dri_ctx->Base, texObj, target, 0);
    swImage = swrast_texture_image(texImage);

    _mesa_lock_texture(&dri_ctx->Base, texObj);

    sPriv->swrast_loader->getDrawableInfo(dPriv, &x, &y, &w, &h, dPriv->loaderPrivate);

    if (texture_format == __DRI_TEXTURE_FORMAT_RGB)
	texFormat = MESA_FORMAT_XRGB8888;
    else
	texFormat = MESA_FORMAT_ARGB8888;

    _mesa_init_teximage_fields(&dri_ctx->Base, texImage,
			       w, h, 1, 0, internalFormat, texFormat);

    sPriv->swrast_loader->getImage(dPriv, x, y, w, h, (char *)swImage->Buffer,
				   dPriv->loaderPrivate);

    _mesa_unlock_texture(&dri_ctx->Base, texObj);
}
Exemple #18
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 #19
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 #20
0
void r300SetTexBuffer2(__DRIcontext *pDRICtx, GLint target, GLint glx_texture_format, __DRIdrawable *dPriv)
{
	struct gl_texture_unit *texUnit;
	struct gl_texture_object *texObj;
	struct gl_texture_image *texImage;
	struct radeon_renderbuffer *rb;
	radeon_texture_image *rImage;
	radeonContextPtr radeon;
	r300ContextPtr rmesa;
	struct radeon_framebuffer *rfb;
	radeonTexObjPtr t;
	uint32_t pitch_val;
	uint32_t internalFormat, type, format;

	type = GL_BGRA;
	format = GL_UNSIGNED_BYTE;
	internalFormat = (glx_texture_format == GLX_TEXTURE_FORMAT_RGB_EXT ? 3 : 4);

	radeon = pDRICtx->driverPrivate;
	rmesa = pDRICtx->driverPrivate;

	rfb = dPriv->driverPrivate;
        texUnit = &radeon->glCtx->Texture.Unit[radeon->glCtx->Texture.CurrentUnit];
	texObj = _mesa_select_tex_object(radeon->glCtx, texUnit, target);
        texImage = _mesa_get_tex_image(radeon->glCtx, texObj, target, 0);

	rImage = get_radeon_texture_image(texImage);
	t = radeon_tex_obj(texObj);
        if (t == NULL) {
    	    return;
    	}

	radeon_update_renderbuffers(pDRICtx, dPriv);
	/* back & depth buffer are useless free them right away */
	rb = (void*)rfb->base.Attachment[BUFFER_DEPTH].Renderbuffer;
	if (rb && rb->bo) {
		radeon_bo_unref(rb->bo);
        rb->bo = NULL;
	}
	rb = (void*)rfb->base.Attachment[BUFFER_BACK_LEFT].Renderbuffer;
	if (rb && rb->bo) {
		radeon_bo_unref(rb->bo);
		rb->bo = NULL;
	}
	rb = rfb->color_rb[0];
	if (rb->bo == NULL) {
		/* Failed to BO for the buffer */
		return;
	}
	
	_mesa_lock_texture(radeon->glCtx, texObj);
	if (t->bo) {
		radeon_bo_unref(t->bo);
		t->bo = NULL;
	}
	if (rImage->bo) {
		radeon_bo_unref(rImage->bo);
		rImage->bo = NULL;
	}

	radeon_miptree_unreference(&t->mt);
	radeon_miptree_unreference(&rImage->mt);

	_mesa_init_teximage_fields(radeon->glCtx, target, texImage,
				   rb->base.Width, rb->base.Height, 1, 0, rb->cpp);
	texImage->RowStride = rb->pitch / rb->cpp;
	rImage->bo = rb->bo;
	radeon_bo_ref(rImage->bo);
	t->bo = rb->bo;
	radeon_bo_ref(t->bo);
	t->tile_bits = 0;
	t->image_override = GL_TRUE;
	t->override_offset = 0;
	t->pp_txpitch &= (1 << 13) -1;
	pitch_val = rb->pitch;
	switch (rb->cpp) {
	case 4:
		if (glx_texture_format == GLX_TEXTURE_FORMAT_RGB_EXT)
			t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8);
		else
			t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8);
		t->pp_txfilter |= tx_table[2].filter;
		pitch_val /= 4;
		break;
	case 3:
	default:
		t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8);
		t->pp_txfilter |= tx_table[4].filter;
		pitch_val /= 4;
		break;
	case 2:
		t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5);
		t->pp_txfilter |= tx_table[5].filter;
		pitch_val /= 2;
		break;
	}
	pitch_val--;
	t->pp_txsize = (((R300_TX_WIDTHMASK_MASK & ((rb->base.Width - 1) << R300_TX_WIDTHMASK_SHIFT)))
			| ((R300_TX_HEIGHTMASK_MASK & ((rb->base.Height - 1) << R300_TX_HEIGHTMASK_SHIFT))));
	t->pp_txsize |= R300_TX_SIZE_TXPITCH_EN;
	t->pp_txpitch |= pitch_val;

	if (rmesa->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) {
	    if (rb->base.Width > 2048)
		t->pp_txpitch |= R500_TXWIDTH_BIT11;
            else
		t->pp_txpitch &= ~R500_TXWIDTH_BIT11;
	    if (rb->base.Height > 2048)
		t->pp_txpitch |= R500_TXHEIGHT_BIT11;
            else
		t->pp_txpitch &= ~R500_TXHEIGHT_BIT11;
	}
	t->validated = GL_TRUE;
	_mesa_unlock_texture(radeon->glCtx, texObj);
	return;
}
Exemple #21
0
static struct gl_texture_image *
create_texture_for_pbo(struct gl_context *ctx, bool create_pbo,
                       GLenum pbo_target, int width, int height,
                       GLenum format, GLenum type, const void *pixels,
                       const struct gl_pixelstore_attrib *packing,
                       GLuint *tmp_pbo, GLuint *tmp_tex)
{
   uint32_t pbo_format;
   GLenum internal_format;
   unsigned row_stride;
   struct gl_buffer_object *buffer_obj;
   struct gl_texture_object *tex_obj;
   struct gl_texture_image *tex_image;
   bool read_only;

   if (packing->SwapBytes ||
       packing->LsbFirst ||
       packing->Invert)
      return NULL;

   pbo_format = _mesa_format_from_format_and_type(format, type);
   if (_mesa_format_is_mesa_array_format(pbo_format))
      pbo_format = _mesa_format_from_array_format(pbo_format);

   if (!pbo_format || !ctx->TextureFormatSupported[pbo_format])
      return NULL;

   /* Account for SKIP_PIXELS, SKIP_ROWS, ALIGNMENT, and SKIP_IMAGES */
   pixels = _mesa_image_address3d(packing, pixels,
                                  width, height, format, type, 0, 0, 0);
   row_stride = _mesa_image_row_stride(packing, width, format, type);

   if (_mesa_is_bufferobj(packing->BufferObj)) {
      *tmp_pbo = 0;
      buffer_obj = packing->BufferObj;
   } else {
      bool is_pixel_pack = pbo_target == GL_PIXEL_PACK_BUFFER;

      assert(create_pbo);

      _mesa_GenBuffers(1, tmp_pbo);

      /* We are not doing this inside meta_begin/end.  However, we know the
       * client doesn't have the given target bound, so we can go ahead and
       * squash it.  We'll set it back when we're done.
       */
      _mesa_BindBuffer(pbo_target, *tmp_pbo);

      /* In case of GL_PIXEL_PACK_BUFFER, pass null pointer for the pixel
       * data to avoid unnecessary data copying in _mesa_BufferData().
       */
      if (is_pixel_pack)
         _mesa_BufferData(pbo_target, row_stride * height, NULL,
                          GL_STREAM_READ);
      else
         _mesa_BufferData(pbo_target, row_stride * height, pixels,
                          GL_STREAM_DRAW);

      buffer_obj = packing->BufferObj;
      pixels = NULL;

      _mesa_BindBuffer(pbo_target, 0);
   }

   _mesa_GenTextures(1, tmp_tex);
   tex_obj = _mesa_lookup_texture(ctx, *tmp_tex);
   _mesa_initialize_texture_object(ctx, tex_obj, *tmp_tex, GL_TEXTURE_2D);
   /* This must be set after _mesa_initialize_texture_object, not before. */
   tex_obj->Immutable = GL_TRUE;
   /* This is required for interactions with ARB_texture_view. */
   tex_obj->NumLayers = 1;

   internal_format = _mesa_get_format_base_format(pbo_format);

   tex_image = _mesa_get_tex_image(ctx, tex_obj, tex_obj->Target, 0);
   _mesa_init_teximage_fields(ctx, tex_image, width, height, 1,
                              0, internal_format, pbo_format);

   read_only = pbo_target == GL_PIXEL_UNPACK_BUFFER;
   if (!ctx->Driver.SetTextureStorageForBufferObject(ctx, tex_obj,
                                                     buffer_obj,
                                                     (intptr_t)pixels,
                                                     row_stride,
                                                     read_only)) {
      _mesa_DeleteTextures(1, tmp_tex);
      _mesa_DeleteBuffers(1, tmp_pbo);
      return NULL;
   }

   return tex_image;
}
Exemple #22
0
/**
 * Prepare the source or destination resource, including:
 * - Error checking
 * - Creating texture wrappers for renderbuffers
 * \param name  the texture or renderbuffer name
 * \param target  GL_TEXTURE target or GL_RENDERBUFFER.  For the later, will
 *                be changed to a compatible GL_TEXTURE target.
 * \param level  mipmap level
 * \param tex_obj  returns a pointer to a texture object
 * \param tex_image  returns a pointer to a texture image
 * \param tmp_tex  returns temporary texture object name
 * \return true if success, false if error
 */
static bool
prepare_target(struct gl_context *ctx, GLuint name, GLenum *target, int level,
               struct gl_texture_object **tex_obj,
               struct gl_texture_image **tex_image, GLuint *tmp_tex,
               const char *dbg_prefix)
{
   if (name == 0) {
      _mesa_error(ctx, GL_INVALID_VALUE,
                  "glCopyImageSubData(%sName = %d)", dbg_prefix, name);
      return false;
   }

   /*
    * INVALID_ENUM is generated
    *  * if either <srcTarget> or <dstTarget>
    *   - is not RENDERBUFFER or a valid non-proxy texture target
    *   - is TEXTURE_BUFFER, or
    *   - is one of the cubemap face selectors described in table 3.17,
    */
   switch (*target) {
   case GL_RENDERBUFFER:
      /* Not a texture target, but valid */
   case GL_TEXTURE_1D:
   case GL_TEXTURE_1D_ARRAY:
   case GL_TEXTURE_2D:
   case GL_TEXTURE_3D:
   case GL_TEXTURE_CUBE_MAP:
   case GL_TEXTURE_RECTANGLE:
   case GL_TEXTURE_2D_ARRAY:
   case GL_TEXTURE_CUBE_MAP_ARRAY:
   case GL_TEXTURE_2D_MULTISAMPLE:
   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
      /* These are all valid */
      break;
   case GL_TEXTURE_EXTERNAL_OES:
      /* Only exists in ES */
   case GL_TEXTURE_BUFFER:
   default:
      _mesa_error(ctx, GL_INVALID_ENUM,
                  "glCopyImageSubData(%sTarget = %s)", dbg_prefix,
                  _mesa_lookup_enum_by_nr(*target));
      return false;
   }

   if (*target == GL_RENDERBUFFER) {
      struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, name);
      if (!rb) {
         _mesa_error(ctx, GL_INVALID_VALUE,
                     "glCopyImageSubData(%sName = %u)", dbg_prefix, name);
         return false;
      }

      if (!rb->Name) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glCopyImageSubData(%sName incomplete)", dbg_prefix);
         return false;
      }

      if (level != 0) {
         _mesa_error(ctx, GL_INVALID_VALUE,
                     "glCopyImageSubData(%sLevel = %u)", dbg_prefix, level);
         return false;
      }

      if (rb->NumSamples > 1)
         *target = GL_TEXTURE_2D_MULTISAMPLE;
      else
         *target = GL_TEXTURE_2D;

      *tmp_tex = 0;
      _mesa_GenTextures(1, tmp_tex);
      if (*tmp_tex == 0)
         return false; /* Error already set by GenTextures */

      _mesa_BindTexture(*target, *tmp_tex);
      *tex_obj = _mesa_lookup_texture(ctx, *tmp_tex);
      *tex_image = _mesa_get_tex_image(ctx, *tex_obj, *target, 0);

      if (!ctx->Driver.BindRenderbufferTexImage(ctx, rb, *tex_image)) {
         _mesa_problem(ctx, "Failed to create texture from renderbuffer");
         return false;
      }

      if (ctx->Driver.FinishRenderTexture && !rb->NeedsFinishRenderTexture) {
         rb->NeedsFinishRenderTexture = true;
         ctx->Driver.FinishRenderTexture(ctx, rb);
      }
   } else {
      *tex_obj = _mesa_lookup_texture(ctx, name);
      if (!*tex_obj) {
         _mesa_error(ctx, GL_INVALID_VALUE,
                     "glCopyImageSubData(%sName = %u)", dbg_prefix, name);
         return false;
      }

      _mesa_test_texobj_completeness(ctx, *tex_obj);
      if (!(*tex_obj)->_BaseComplete ||
          (level != 0 && !(*tex_obj)->_MipmapComplete)) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glCopyImageSubData(%sName incomplete)", dbg_prefix);
         return false;
      }

      if ((*tex_obj)->Target != *target) {
         _mesa_error(ctx, GL_INVALID_ENUM,
                     "glCopyImageSubData(%sTarget = %s)", dbg_prefix,
                     _mesa_lookup_enum_by_nr(*target));
         return false;
      }

      if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
         _mesa_error(ctx, GL_INVALID_VALUE,
                     "glCopyImageSubData(%sLevel = %d)", dbg_prefix, level);
         return false;
      }

      *tex_image = _mesa_select_tex_image(*tex_obj, *target, level);
      if (!*tex_image) {
         _mesa_error(ctx, GL_INVALID_VALUE,
                     "glCopyImageSubData(%sLevel = %u)", dbg_prefix, level);
         return false;
      }
   }

   return true;
}
Exemple #23
0
/**
 * Return pointer to a default/fallback texture of the given type/target.
 * The texture is an RGBA texture with all texels = (0,0,0,1).
 * That's the value a GLSL sampler should get when sampling from an
 * incomplete texture.
 */
struct gl_texture_object *
_mesa_get_fallback_texture(struct gl_context *ctx, gl_texture_index tex)
{
   if (!ctx->Shared->FallbackTex[tex]) {
      /* create fallback texture now */
      const GLsizei width = 1, height = 1, depth = 1;
      GLubyte texel[4];
      struct gl_texture_object *texObj;
      struct gl_texture_image *texImage;
      gl_format texFormat;
      GLuint dims, face, numFaces = 1;
      GLenum target;

      texel[0] =
      texel[1] =
      texel[2] = 0x0;
      texel[3] = 0xff;

      switch (tex) {
      case TEXTURE_2D_ARRAY_INDEX:
         dims = 3;
         target = GL_TEXTURE_2D_ARRAY;
         break;
      case TEXTURE_1D_ARRAY_INDEX:
         dims = 2;
         target = GL_TEXTURE_1D_ARRAY;
         break;
      case TEXTURE_CUBE_INDEX:
         dims = 2;
         target = GL_TEXTURE_CUBE_MAP;
         numFaces = 6;
         break;
      case TEXTURE_3D_INDEX:
         dims = 3;
         target = GL_TEXTURE_3D;
         break;
      case TEXTURE_RECT_INDEX:
         dims = 2;
         target = GL_TEXTURE_RECTANGLE;
         break;
      case TEXTURE_2D_INDEX:
         dims = 2;
         target = GL_TEXTURE_2D;
         break;
      case TEXTURE_1D_INDEX:
         dims = 1;
         target = GL_TEXTURE_1D;
         break;
      case TEXTURE_BUFFER_INDEX:
         dims = 0;
         target = GL_TEXTURE_BUFFER;
         break;
      case TEXTURE_EXTERNAL_INDEX:
      default:
         /* no-op */
         return NULL;
      }

      /* create texture object */
      texObj = ctx->Driver.NewTextureObject(ctx, 0, target);
      if (!texObj)
         return NULL;

      assert(texObj->RefCount == 1);
      texObj->Sampler.MinFilter = GL_NEAREST;
      texObj->Sampler.MagFilter = GL_NEAREST;

      texFormat = ctx->Driver.ChooseTextureFormat(ctx, target,
                                                  GL_RGBA, GL_RGBA,
                                                  GL_UNSIGNED_BYTE);

      /* need a loop here just for cube maps */
      for (face = 0; face < numFaces; face++) {
         GLenum faceTarget;

         if (target == GL_TEXTURE_CUBE_MAP)
            faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
         else
            faceTarget = target;

         /* initialize level[0] texture image */
         texImage = _mesa_get_tex_image(ctx, texObj, faceTarget, 0);

         _mesa_init_teximage_fields(ctx, texImage,
                                    width,
                                    (dims > 1) ? height : 1,
                                    (dims > 2) ? depth : 1,
                                    0, /* border */
                                    GL_RGBA, texFormat);

         ctx->Driver.TexImage(ctx, dims, texImage,
                              GL_RGBA, GL_UNSIGNED_BYTE, texel,
                              &ctx->DefaultPacking);
      }

      _mesa_test_texobj_completeness(ctx, texObj);
      assert(texObj->_BaseComplete);
      assert(texObj->_MipmapComplete);

      ctx->Shared->FallbackTex[tex] = texObj;
   }
   return ctx->Shared->FallbackTex[tex];
}
Exemple #24
0
/**
 * Do actual memory allocation for glTexStorage1/2/3D().
 */
static void
setup_texstorage(struct gl_context *ctx,
                 struct gl_texture_object *texObj,
                 GLuint dims,
                 GLsizei levels, GLenum internalFormat,
                 GLsizei width, GLsizei height, GLsizei depth)
{
   const GLenum target = texObj->Target;
   const GLuint numFaces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
   gl_format texFormat;
   GLint level, levelWidth = width, levelHeight = height, levelDepth = depth;
   GLuint face;

   assert(levels > 0);
   assert(width > 0);
   assert(height > 0);
   assert(depth > 0);

   texFormat = _mesa_choose_texture_format(ctx, texObj, target, 0,
                                           internalFormat, GL_NONE, GL_NONE);

   /* Set up all the texture object's gl_texture_images */
   for (level = 0; level < levels; level++) {
      for (face = 0; face < numFaces; face++) {
         const GLenum faceTarget =
            (target == GL_TEXTURE_CUBE_MAP)
            ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + face : target;
         struct gl_texture_image *texImage =
            _mesa_get_tex_image(ctx, texObj, faceTarget, level);

	 if (!texImage) {
	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims);
            return;
	 }

         _mesa_init_teximage_fields(ctx, target, texImage,
                                    levelWidth, levelHeight, levelDepth,
                                    0, internalFormat, texFormat);
      }

      next_mipmap_level_size(target, &levelWidth, &levelHeight, &levelDepth);
   }

   assert(levelWidth > 0);
   assert(levelHeight > 0);
   assert(levelDepth > 0);

   if (!_mesa_is_proxy_texture(texObj->Target)) {
      /* Do actual texture memory allocation */
      if (!ctx->Driver.AllocTextureStorage(ctx, texObj, levels,
                                           width, height, depth)) {
         /* Reset the texture images' info to zeros.
          * Strictly speaking, we probably don't have to do this since
          * generating GL_OUT_OF_MEMORY can leave things in an undefined
          * state but this puts things in a consistent state.
          */
         for (level = 0; level < levels; level++) {
            for (face = 0; face < numFaces; face++) {
               struct gl_texture_image *texImage = texObj->Image[face][level];
               if (texImage) {
                  _mesa_init_teximage_fields(ctx, target, texImage,
                                             0, 0, 0, 0,
                                             GL_NONE, MESA_FORMAT_NONE);
               }
            }
         }

         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage%uD", dims);

         return;
      }
   }

   texObj->Immutable = GL_TRUE;
}
Exemple #25
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;
}
static struct gl_texture_image *
create_texture_for_pbo(struct gl_context *ctx,
                       bool create_pbo, GLenum pbo_target,
                       int dims, int width, int height, int depth,
                       GLenum format, GLenum type, const void *pixels,
                       const struct gl_pixelstore_attrib *packing,
                       struct gl_buffer_object **tmp_pbo, GLuint *tmp_tex)
{
   uint32_t pbo_format;
   GLenum internal_format;
   unsigned row_stride;
   struct gl_buffer_object *buffer_obj;
   struct gl_texture_object *tex_obj;
   struct gl_texture_image *tex_image;
   bool read_only;

   if (packing->SwapBytes ||
       packing->LsbFirst ||
       packing->Invert)
      return NULL;

   pbo_format = _mesa_format_from_format_and_type(format, type);
   if (_mesa_format_is_mesa_array_format(pbo_format))
      pbo_format = _mesa_format_from_array_format(pbo_format);

   if (!pbo_format || !ctx->TextureFormatSupported[pbo_format])
      return NULL;

   /* Account for SKIP_PIXELS, SKIP_ROWS, ALIGNMENT, and SKIP_IMAGES */
   uint32_t first_pixel = _mesa_image_offset(dims, packing, width, height,
                                             format, type,
                                             0, 0, 0);
   uint32_t last_pixel =  _mesa_image_offset(dims, packing, width, height,
                                             format, type,
                                             depth-1, height-1, width);
   row_stride = _mesa_image_row_stride(packing, width, format, type);

   if (_mesa_is_bufferobj(packing->BufferObj)) {
      *tmp_pbo = NULL;
      buffer_obj = packing->BufferObj;
      first_pixel += (intptr_t)pixels;
   } else {
      bool is_pixel_pack = pbo_target == GL_PIXEL_PACK_BUFFER;

      assert(create_pbo);

      *tmp_pbo = ctx->Driver.NewBufferObject(ctx, 0xDEADBEEF);
      if (*tmp_pbo == NULL)
         return NULL;

      /* In case of GL_PIXEL_PACK_BUFFER, pass null pointer for the pixel
       * data to avoid unnecessary data copying in _mesa_buffer_data.
       */
      if (is_pixel_pack)
         _mesa_buffer_data(ctx, *tmp_pbo, GL_NONE,
                           last_pixel - first_pixel,
                           NULL,
                           GL_STREAM_READ,
                           __func__);
      else
         _mesa_buffer_data(ctx, *tmp_pbo, GL_NONE,
                           last_pixel - first_pixel,
                           (char *)pixels + first_pixel,
                           GL_STREAM_DRAW,
                           __func__);

      buffer_obj = *tmp_pbo;
      first_pixel = 0;
   }

   _mesa_GenTextures(1, tmp_tex);
   tex_obj = _mesa_lookup_texture(ctx, *tmp_tex);
   _mesa_initialize_texture_object(ctx, tex_obj, *tmp_tex, GL_TEXTURE_2D);
   /* This must be set after _mesa_initialize_texture_object, not before. */
   tex_obj->Immutable = GL_TRUE;
   /* This is required for interactions with ARB_texture_view. */
   tex_obj->NumLayers = 1;

   internal_format = _mesa_get_format_base_format(pbo_format);

   /* The texture is addressed as a single very-tall image, so we
    * need to pack the multiple image depths together taking the
    * inter-image padding into account.
    */
   int image_height = packing->ImageHeight == 0 ? height : packing->ImageHeight;
   int full_height = image_height * (depth - 1) + height;

   tex_image = _mesa_get_tex_image(ctx, tex_obj, tex_obj->Target, 0);
   _mesa_init_teximage_fields(ctx, tex_image, width, full_height, 1,
                              0, internal_format, pbo_format);

   read_only = pbo_target == GL_PIXEL_UNPACK_BUFFER;
   if (!ctx->Driver.SetTextureStorageForBufferObject(ctx, tex_obj,
                                                     buffer_obj,
                                                     first_pixel,
                                                     row_stride,
                                                     read_only)) {
      _mesa_DeleteTextures(1, tmp_tex);
      _mesa_reference_buffer_object(ctx, tmp_pbo, NULL);
      return NULL;
   }

   return tex_image;
}