示例#1
0
static void
st_adjust_blit_for_srgb(struct pipe_blit_info *blit, bool framebuffer_srgb)
{
   if (!framebuffer_srgb) {
      blit->dst.format = util_format_linear(blit->dst.format);
      blit->src.format = util_format_linear(blit->src.format);
   }
}
示例#2
0
/**
 * Get the format and binding of an attachment.
 */
void
dri_drawable_get_format(struct dri_drawable *drawable,
                        enum st_attachment_type statt,
                        enum pipe_format *format,
                        unsigned *bind)
{
   switch (statt) {
   case ST_ATTACHMENT_FRONT_LEFT:
   case ST_ATTACHMENT_BACK_LEFT:
   case ST_ATTACHMENT_FRONT_RIGHT:
   case ST_ATTACHMENT_BACK_RIGHT:
      /* Other pieces of the driver stack get confused and behave incorrectly
       * when they get an sRGB drawable. st/mesa receives "drawable->stvis"
       * though other means and handles it correctly, so we don't really need
       * to use an sRGB format here.
       */
      *format = util_format_linear(drawable->stvis.color_format);
      *bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
      break;
   case ST_ATTACHMENT_DEPTH_STENCIL:
      *format = drawable->stvis.depth_stencil_format;
      *bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */
      break;
   default:
      *format = PIPE_FORMAT_NONE;
      *bind = 0;
      break;
   }
}
示例#3
0
static void
st_adjust_blit_for_msaa_resolve(struct pipe_blit_info *blit)
{
   /* Even though we do multisample resolves at the time of the blit, OpenGL
    * specification defines them as if they happen at the time of rendering,
    * which means that the type of averaging we do during the resolve should
    * only depend on the source format; the destination format should be
    * ignored. But, specification doesn't seem to be strict about it.
    *
    * It has been observed that mulitisample resolves produce slightly better
    * looking images when averaging is done using destination format. NVIDIA's
    * proprietary OpenGL driver also follows this approach.
    *
    * When multisampling, if the source and destination formats are equal
    * (aside from the color space), we choose to blit in sRGB space to get
    * this higher quality image.
    */
   if (blit->src.resource->nr_samples > 1 &&
       blit->dst.resource->nr_samples <= 1) {
      blit->dst.format = blit->dst.resource->format;

      if (util_format_is_srgb(blit->dst.resource->format))
         blit->src.format = util_format_srgb(blit->src.resource->format);
      else
         blit->src.format = util_format_linear(blit->src.resource->format);
   }
}
示例#4
0
static void
default_src_texture(struct pipe_sampler_view *src_templ,
		struct pipe_resource *src, unsigned srclevel)
{
	bool cube_as_2darray = src->screen->get_param(src->screen,
			PIPE_CAP_SAMPLER_VIEW_TARGET);

	memset(src_templ, 0, sizeof(*src_templ));

	if (cube_as_2darray && (src->target == PIPE_TEXTURE_CUBE ||
			src->target == PIPE_TEXTURE_CUBE_ARRAY))
		src_templ->target = PIPE_TEXTURE_2D_ARRAY;
	else
		src_templ->target = src->target;

	if (src->target  == PIPE_BUFFER) {
		src_templ->target = PIPE_TEXTURE_1D;
		src_templ->format = PIPE_FORMAT_R8_UINT;
	} else {
		src_templ->format = util_format_linear(src->format);
	}
	src_templ->u.tex.first_level = srclevel;
	src_templ->u.tex.last_level = srclevel;
	src_templ->u.tex.first_layer = 0;
	src_templ->u.tex.last_layer =
			src->target == PIPE_TEXTURE_3D ? u_minify(src->depth0, srclevel) - 1
					: (unsigned)(src->array_size - 1);
	src_templ->swizzle_r = PIPE_SWIZZLE_X;
	src_templ->swizzle_g = PIPE_SWIZZLE_Y;
	src_templ->swizzle_b = PIPE_SWIZZLE_Z;
	src_templ->swizzle_a = PIPE_SWIZZLE_W;
}
示例#5
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;
}
示例#6
0
static void
default_dst_texture(struct pipe_surface *dst_templ, struct pipe_resource *dst,
		unsigned dstlevel, unsigned dstz)
{
	memset(dst_templ, 0, sizeof(*dst_templ));
	if (dst->target == PIPE_BUFFER)
		dst_templ->format = PIPE_FORMAT_R8_UINT;
	else
		dst_templ->format = util_format_linear(dst->format);
	dst_templ->u.tex.level = dstlevel;
	dst_templ->u.tex.first_layer = dstz;
	dst_templ->u.tex.last_layer = dstz;
}
示例#7
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;
}
示例#8
0
void util_blitter_default_src_texture(struct pipe_sampler_view *src_templ,
                                      struct pipe_resource *src,
                                      unsigned srclevel)
{
    memset(src_templ, 0, sizeof(*src_templ));
    src_templ->format = util_format_linear(src->format);
    src_templ->u.tex.first_level = srclevel;
    src_templ->u.tex.last_level = srclevel;
    src_templ->u.tex.first_layer = 0;
    src_templ->u.tex.last_layer =
        src->target == PIPE_TEXTURE_3D ? src->depth0 - 1
                                       : src->array_size - 1;
    src_templ->swizzle_r = PIPE_SWIZZLE_RED;
    src_templ->swizzle_g = PIPE_SWIZZLE_GREEN;
    src_templ->swizzle_b = PIPE_SWIZZLE_BLUE;
    src_templ->swizzle_a = PIPE_SWIZZLE_ALPHA;
}
示例#9
0
/**
 * Determine the format for the texture sampler view.
 */
static enum pipe_format
get_sampler_view_format(struct st_context *st,
                        const struct st_texture_object *stObj,
                        const struct gl_sampler_object *samp)
{
   enum pipe_format format;

   if (stObj->base.Target == GL_TEXTURE_BUFFER) {
      format =
         st_mesa_format_to_pipe_format(st, stObj->base._BufferObjectFormat);
   }
   else {
      format =
         stObj->surface_based ? stObj->surface_format : stObj->pt->format;

      if (util_format_is_depth_and_stencil(format)) {
         if (stObj->base.StencilSampling) {
            format = util_format_stencil_only(format);
         }
         else {
            GLenum baseFormat = _mesa_texture_base_format(&stObj->base);
            if (baseFormat == GL_STENCIL_INDEX) {
               format = util_format_stencil_only(format);
            }
         }
      }
      else {
         /* If sRGB decoding is off, use the linear format */
         if (samp->sRGBDecode == GL_SKIP_DECODE_EXT) {
            format = util_format_linear(format);
         }

         /* Use R8_UNORM for video formats */
         switch (format) {
         case PIPE_FORMAT_NV12:
         case PIPE_FORMAT_IYUV:
            format = PIPE_FORMAT_R8_UNORM;
            break;
         default:
            break;
         }
      }
   }

   return format;
}
示例#10
0
void util_blitter_default_dst_texture(struct pipe_surface *dst_templ,
                                      struct pipe_resource *dst,
                                      unsigned dstlevel,
                                      unsigned dstz,
                                      const struct pipe_box *srcbox)
{
    memset(dst_templ, 0, sizeof(*dst_templ));
    dst_templ->format = dst->format;
    if (util_format_is_depth_or_stencil(dst->format)) {
	dst_templ->usage = PIPE_BIND_DEPTH_STENCIL;
    } else {
	dst_templ->usage = PIPE_BIND_RENDER_TARGET;
    }
    dst_templ->format = util_format_linear(dst->format);
    dst_templ->u.tex.level = dstlevel;
    dst_templ->u.tex.first_layer = dstz;
    dst_templ->u.tex.last_layer = dstz + srcbox->depth - 1;
}
示例#11
0
/**
 * When doing GL render to texture, we have to be sure that finalize_texture()
 * didn't yank out the pipe_resource that we earlier created a surface for.
 * Check for that here and create a new surface if needed.
 */
static void
update_renderbuffer_surface(struct st_context *st,
                            struct st_renderbuffer *strb)
{
   struct pipe_context *pipe = st->pipe;
   struct pipe_resource *resource = strb->rtt ? strb->rtt->pt : strb->texture;
   int rtt_width = strb->Base.Width;
   int rtt_height = strb->Base.Height;
   enum pipe_format format = st->ctx->Color.sRGBEnabled ? resource->format : util_format_linear(resource->format);

   if (!strb->surface ||
       strb->surface->format != format ||
       strb->surface->texture != resource ||
       strb->surface->width != rtt_width ||
       strb->surface->height != rtt_height) {
      GLuint level;
      /* find matching mipmap level size */
      for (level = 0; level <= resource->last_level; level++) {
         if (u_minify(resource->width0, level) == rtt_width &&
             u_minify(resource->height0, level) == rtt_height) {
            struct pipe_surface surf_tmpl;
            memset(&surf_tmpl, 0, sizeof(surf_tmpl));
            surf_tmpl.format = format;
            surf_tmpl.u.tex.level = 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;

            pipe_surface_reference(&strb->surface, NULL);

            strb->surface = pipe->create_surface(pipe,
                                                 resource,
                                                 &surf_tmpl);
#if 0
            printf("-- alloc new surface %d x %d into tex %p\n",
                   strb->surface->width, strb->surface->height,
                   texture);
#endif
            break;
         }
      }
   }
}
示例#12
0
/**
 * Return default texture resource binding bitmask for the given format.
 */
static GLuint
default_bindings(struct st_context *st, enum pipe_format format)
{
   struct pipe_screen *screen = st->pipe->screen;
   const unsigned target = PIPE_TEXTURE_2D;
   unsigned bindings;

   if (util_format_is_depth_or_stencil(format))
      bindings = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_DEPTH_STENCIL;
   else
      bindings = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;

   if (screen->is_format_supported(screen, format, target, 0, bindings))
      return bindings;
   else {
      /* Try non-sRGB. */
      format = util_format_linear(format);

      if (screen->is_format_supported(screen, format, target, 0, bindings))
         return bindings;
      else
         return PIPE_BIND_SAMPLER_VIEW;
   }
}
示例#13
0
/**
 * Create or update the pipe_surface of a FBO renderbuffer.
 * This is usually called after st_finalize_texture.
 */
void
st_update_renderbuffer_surface(struct st_context *st,
                               struct st_renderbuffer *strb)
{
   struct pipe_context *pipe = st->pipe;
   struct pipe_resource *resource = strb->texture;
   int rtt_width = strb->Base.Width;
   int rtt_height = strb->Base.Height;
   int rtt_depth = strb->Base.Depth;
   /*
    * For winsys fbo, it is possible that the renderbuffer is sRGB-capable but
    * the format of strb->texture is linear (because we have no control over
    * the format).  Check strb->Base.Format instead of strb->texture->format
    * to determine if the rb is sRGB-capable.
    */
   boolean enable_srgb = (st->ctx->Color.sRGBEnabled &&
         _mesa_get_format_color_encoding(strb->Base.Format) == GL_SRGB);
   enum pipe_format format = (enable_srgb) ?
      util_format_srgb(resource->format) :
      util_format_linear(resource->format);
   unsigned first_layer, last_layer, level;

   if (resource->target == PIPE_TEXTURE_1D_ARRAY) {
      rtt_depth = rtt_height;
      rtt_height = 1;
   }

   /* find matching mipmap level size */
   for (level = 0; level <= resource->last_level; level++) {
      if (u_minify(resource->width0, level) == rtt_width &&
          u_minify(resource->height0, level) == rtt_height &&
          (resource->target != PIPE_TEXTURE_3D ||
           u_minify(resource->depth0, level) == rtt_depth)) {
         break;
      }
   }
   assert(level <= resource->last_level);

   /* determine the layer bounds */
   if (strb->rtt_layered) {
      first_layer = 0;
      last_layer = util_max_layer(strb->texture, level);
   }
   else {
      first_layer =
      last_layer = strb->rtt_face + strb->rtt_slice;
   }

   if (!strb->surface ||
       strb->surface->texture->nr_samples != strb->Base.NumSamples ||
       strb->surface->format != format ||
       strb->surface->texture != resource ||
       strb->surface->width != rtt_width ||
       strb->surface->height != rtt_height ||
       strb->surface->u.tex.level != level ||
       strb->surface->u.tex.first_layer != first_layer ||
       strb->surface->u.tex.last_layer != last_layer) {
      /* create a new pipe_surface */
      struct pipe_surface surf_tmpl;
      memset(&surf_tmpl, 0, sizeof(surf_tmpl));
      surf_tmpl.format = format;
      surf_tmpl.u.tex.level = level;
      surf_tmpl.u.tex.first_layer = first_layer;
      surf_tmpl.u.tex.last_layer = last_layer;

      pipe_surface_reference(&strb->surface, NULL);

      strb->surface = pipe->create_surface(pipe, resource, &surf_tmpl);
   }
}
示例#14
0
文件: fd4_gmem.c 项目: dumbbell/mesa
static void
emit_mrt(struct fd_ringbuffer *ring, unsigned nr_bufs,
		struct pipe_surface **bufs, uint32_t *bases,
		uint32_t bin_w, bool decode_srgb)
{
	enum a4xx_tile_mode tile_mode;
	unsigned i;

	if (bin_w) {
		tile_mode = 2;
	} else {
		tile_mode = TILE4_LINEAR;
	}

	for (i = 0; i < A4XX_MAX_RENDER_TARGETS; i++) {
		enum a4xx_color_fmt format = 0;
		enum a3xx_color_swap swap = WZYX;
		bool srgb = false;
		struct fd_resource *rsc = NULL;
		struct fd_resource_slice *slice = NULL;
		uint32_t stride = 0;
		uint32_t base = 0;
		uint32_t offset = 0;

		if ((i < nr_bufs) && bufs[i]) {
			struct pipe_surface *psurf = bufs[i];
			enum pipe_format pformat = psurf->format;

			rsc = fd_resource(psurf->texture);

			/* In case we're drawing to Z32F_S8, the "color" actually goes to
			 * the stencil
			 */
			if (rsc->stencil) {
				rsc = rsc->stencil;
				pformat = rsc->base.b.format;
				bases++;
			}

			slice = fd_resource_slice(rsc, psurf->u.tex.level);
			format = fd4_pipe2color(pformat);
			swap = fd4_pipe2swap(pformat);

			if (decode_srgb)
				srgb = util_format_is_srgb(pformat);
			else
				pformat = util_format_linear(pformat);

			debug_assert(psurf->u.tex.first_layer == psurf->u.tex.last_layer);

			offset = fd_resource_offset(rsc, psurf->u.tex.level,
					psurf->u.tex.first_layer);

			if (bin_w) {
				stride = bin_w * rsc->cpp;

				if (bases) {
					base = bases[i];
				}
			} else {
				stride = slice->pitch * rsc->cpp;
			}
		} else if ((i < nr_bufs) && bases) {
			base = bases[i];
		}

		OUT_PKT0(ring, REG_A4XX_RB_MRT_BUF_INFO(i), 3);
		OUT_RING(ring, A4XX_RB_MRT_BUF_INFO_COLOR_FORMAT(format) |
				A4XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(tile_mode) |
				A4XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH(stride) |
				A4XX_RB_MRT_BUF_INFO_COLOR_SWAP(swap) |
				COND(srgb, A4XX_RB_MRT_BUF_INFO_COLOR_SRGB));
		if (bin_w || (i >= nr_bufs) || !bufs[i]) {
			OUT_RING(ring, base);
			OUT_RING(ring, A4XX_RB_MRT_CONTROL3_STRIDE(stride));
		} else {
			OUT_RELOCW(ring, rsc->bo, offset, 0, 0);
			/* RB_MRT[i].CONTROL3.STRIDE not emitted by c2d..
			 * not sure if we need to skip it for bypass or
			 * not.
			 */
			OUT_RING(ring, A4XX_RB_MRT_CONTROL3_STRIDE(0));
		}
	}
}
示例#15
0
/**
 * Copy pixel block from src surface to dst surface.
 * Overlapping regions are acceptable.
 * Flipping and stretching are supported.
 * \param filter  one of PIPE_TEX_MIPFILTER_NEAREST/LINEAR
 * \param writemask  controls which channels in the dest surface are sourced
 *                   from the src surface.  Disabled channels are sourced
 *                   from (0,0,0,1).
 */
void
util_blit_pixels(struct blit_state *ctx,
                 struct pipe_resource *src_tex,
                 unsigned src_level,
                 int srcX0, int srcY0,
                 int srcX1, int srcY1,
                 int srcZ0,
                 struct pipe_surface *dst,
                 int dstX0, int dstY0,
                 int dstX1, int dstY1,
                 float z, uint filter,
                 uint writemask, uint zs_writemask)
{
   struct pipe_context *pipe = ctx->pipe;
   enum pipe_format src_format, dst_format;
   const int srcW = abs(srcX1 - srcX0);
   const int srcH = abs(srcY1 - srcY0);
   boolean overlap;
   boolean is_stencil, is_depth, blit_depth, blit_stencil;
   const struct util_format_description *src_desc =
         util_format_description(src_tex->format);
   struct pipe_blit_info info;

   assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
          filter == PIPE_TEX_MIPFILTER_LINEAR);

   assert(src_level <= src_tex->last_level);

   /* do the regions overlap? */
   overlap = src_tex == dst->texture &&
             dst->u.tex.level == src_level &&
             dst->u.tex.first_layer == srcZ0 &&
      regions_overlap(srcX0, srcY0, srcX1, srcY1,
                      dstX0, dstY0, dstX1, dstY1);

   src_format = util_format_linear(src_tex->format);
   dst_format = util_format_linear(dst->texture->format);

   /* See whether we will blit depth or stencil. */
   is_depth = util_format_has_depth(src_desc);
   is_stencil = util_format_has_stencil(src_desc);

   blit_depth = is_depth && (zs_writemask & BLIT_WRITEMASK_Z);
   blit_stencil = is_stencil && (zs_writemask & BLIT_WRITEMASK_STENCIL);

   assert((writemask && !zs_writemask && !is_depth && !is_stencil) ||
          (!writemask && (blit_depth || blit_stencil)));

   /*
    * XXX: z parameter is deprecated. dst->u.tex.first_layer
    * specificies the destination layer.
    */
   assert(z == 0.0f);

   /*
    * Check for simple case:  no format conversion, no flipping, no stretching,
    * no overlapping, same number of samples.
    * Filter mode should not matter since there's no stretching.
    */
   if (formats_compatible(src_format, dst_format) &&
       src_tex->nr_samples == dst->texture->nr_samples &&
       is_stencil == blit_stencil &&
       is_depth == blit_depth &&
       srcX0 < srcX1 &&
       dstX0 < dstX1 &&
       srcY0 < srcY1 &&
       dstY0 < dstY1 &&
       (dstX1 - dstX0) == (srcX1 - srcX0) &&
       (dstY1 - dstY0) == (srcY1 - srcY0) &&
       !overlap) {
      struct pipe_box src_box;
      src_box.x = srcX0;
      src_box.y = srcY0;
      src_box.z = srcZ0;
      src_box.width = srcW;
      src_box.height = srcH;
      src_box.depth = 1;
      pipe->resource_copy_region(pipe,
                                 dst->texture, dst->u.tex.level,
                                 dstX0, dstY0, dst->u.tex.first_layer,/* dest */
                                 src_tex, src_level,
                                 &src_box);
      return;
   }

   memset(&info, 0, sizeof info);
   info.dst.resource = dst->texture;
   info.dst.level = dst->u.tex.level;
   info.dst.box.x = dstX0;
   info.dst.box.y = dstY0;
   info.dst.box.z = dst->u.tex.first_layer;
   info.dst.box.width = dstX1 - dstX0;
   info.dst.box.height = dstY1 - dstY0;
   assert(info.dst.box.width >= 0);
   assert(info.dst.box.height >= 0);
   info.dst.box.depth = 1;
   info.dst.format = dst->texture->format;
   info.src.resource = src_tex;
   info.src.level = src_level;
   info.src.box.x = srcX0;
   info.src.box.y = srcY0;
   info.src.box.z = srcZ0;
   info.src.box.width = srcX1 - srcX0;
   info.src.box.height = srcY1 - srcY0;
   info.src.box.depth = 1;
   info.src.format = src_tex->format;
   info.mask = writemask | (zs_writemask << 4);
   info.filter = filter;
   info.scissor_enable = 0;

   pipe->blit(pipe, &info);
}
/**
 * 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;
}
		.dst = {
			.resource = dst,
			.box = {
				.x      = dstx,
				.y      = dsty,
				.z      = dstz,
				.width  = src_box->width,
				.height = src_box->height,
				.depth  = src_box->depth,
			},
			.format = util_format_linear(dst->format),
		},
		.src = {
			.resource = src,
			.box      = *src_box,
			.format   = util_format_linear(src->format),
		},
		.mask = PIPE_MASK_RGBA,
		.filter = PIPE_TEX_FILTER_NEAREST,
	};
	render_blit(pctx, &info);
}

/* Optimal hardware path for blitting pixels.
 * Scaling, format conversion, up- and downsampling (resolve) are allowed.
 */
static void
fd_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info)
{
	struct pipe_blit_info info = *blit_info;
示例#18
0
/**
 * Do a CopyTex[Sub]Image1/2/3D() using a hardware (blit) path if possible.
 * Note that the region to copy has already been clipped so we know we
 * won't read from outside the source renderbuffer's bounds.
 *
 * Note: srcY=0=Bottom of renderbuffer (GL convention)
 */
static void
st_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
                   struct gl_texture_image *texImage,
                   GLint destX, GLint destY, GLint destZ,
                   struct gl_renderbuffer *rb,
                   GLint srcX, GLint srcY, GLsizei width, GLsizei height)
{
   struct st_texture_image *stImage = st_texture_image(texImage);
   const GLenum texBaseFormat = texImage->_BaseFormat;
   struct st_renderbuffer *strb = st_renderbuffer(rb);
   struct st_context *st = st_context(ctx);
   struct pipe_context *pipe = st->pipe;
   struct pipe_screen *screen = pipe->screen;
   enum pipe_format dest_format, src_format;
   GLboolean matching_base_formats;
   GLuint color_writemask, zs_writemask, sample_count;
   struct pipe_surface *dest_surface = NULL;
   GLboolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP);
   struct pipe_surface surf_tmpl;
   unsigned int dst_usage;
   GLint srcY0, srcY1;

   /* make sure finalize_textures has been called? 
    */
   if (0) st_validate_state(st);

   if (!strb || !strb->surface || !stImage->pt) {
      debug_printf("%s: null strb or stImage\n", __FUNCTION__);
      return;
   }

   sample_count = strb->surface->texture->nr_samples;
   /* I believe this would be legal, presumably would need to do a resolve
      for color, and for depth/stencil spec says to just use one of the
      depth/stencil samples per pixel? Need some transfer clarifications. */
   assert(sample_count < 2);

   assert(strb);
   assert(strb->surface);
   assert(stImage->pt);

   src_format = strb->surface->format;
   dest_format = stImage->pt->format;

   /*
    * Determine if the src framebuffer and dest texture have the same
    * base format.  We need this to detect a case such as the framebuffer
    * being GL_RGBA but the texture being GL_RGB.  If the actual hardware
    * texture format stores RGBA we need to set A=1 (overriding the
    * framebuffer's alpha values).  We can't do that with the blit or
    * textured-quad paths.
    */
   matching_base_formats =
      (_mesa_get_format_base_format(strb->Base.Format) ==
       _mesa_get_format_base_format(texImage->TexFormat));

   if (ctx->_ImageTransferState) {
      goto fallback;
   }

   if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
      /* 1D arrays might be thought of as 2D images but the actual layout
       * might not be that way.  At some points, we convert OpenGL's 1D
       * array 'height' into gallium 'layers' and that prevents the blit
       * utility code from doing the right thing.  Simpy use the memcpy-based
       * fallback.
       */
      goto fallback;
   }

   if (matching_base_formats &&
       src_format == dest_format &&
       !do_flip) {
      /* use surface_copy() / blit */
      struct pipe_box src_box;
      unsigned dstLevel;

      u_box_2d_zslice(srcX, srcY, strb->surface->u.tex.first_layer,
                      width, height, &src_box);

      /* If stImage->pt is an independent image (not a pointer into a full
       * mipmap) stImage->pt.last_level will be zero and we need to use that
       * as the dest level.
       */
      dstLevel = MIN2(stImage->base.Level, stImage->pt->last_level);

      /* for resource_copy_region(), y=0=top, always */
      pipe->resource_copy_region(pipe,
                                 /* dest */
                                 stImage->pt,
                                 dstLevel,
                                 destX, destY, destZ + stImage->base.Face,
                                 /* src */
                                 strb->texture,
                                 strb->surface->u.tex.level,
                                 &src_box);
      return;
   }

   if (texBaseFormat == GL_DEPTH_STENCIL) {
      goto fallback;
   }

   if (texBaseFormat == GL_DEPTH_COMPONENT) {
      color_writemask = 0;
      zs_writemask = BLIT_WRITEMASK_Z;
      dst_usage = PIPE_BIND_DEPTH_STENCIL;
   }
   else {
      color_writemask = compatible_src_dst_formats(ctx, &strb->Base, texImage);
      zs_writemask = 0;
      dst_usage = PIPE_BIND_RENDER_TARGET;
   }

   if ((!color_writemask && !zs_writemask) ||
       !screen->is_format_supported(screen, src_format,
                                    PIPE_TEXTURE_2D, sample_count,
                                    PIPE_BIND_SAMPLER_VIEW) ||
       !screen->is_format_supported(screen, dest_format,
                                    PIPE_TEXTURE_2D, 0,
                                    dst_usage)) {
      goto fallback;
   }

   if (do_flip) {
      srcY1 = strb->Base.Height - srcY - height;
      srcY0 = srcY1 + height;
   }
   else {
      srcY0 = srcY;
      srcY1 = srcY0 + height;
   }

   /* Disable conditional rendering. */
   if (st->render_condition) {
      pipe->render_condition(pipe, NULL, 0);
   }

   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
   surf_tmpl.format = util_format_linear(stImage->pt->format);
   surf_tmpl.usage = dst_usage;
   surf_tmpl.u.tex.level = stImage->base.Level;
   surf_tmpl.u.tex.first_layer = stImage->base.Face + destZ;
   surf_tmpl.u.tex.last_layer = stImage->base.Face + destZ;

   dest_surface = pipe->create_surface(pipe, stImage->pt,
                                       &surf_tmpl);
   util_blit_pixels(st->blit,
                    strb->texture,
                    strb->surface->u.tex.level,
                    srcX, srcY0,
                    srcX + width, srcY1,
                    strb->surface->u.tex.first_layer,
                    dest_surface,
                    destX, destY,
                    destX + width, destY + height,
                    0.0, PIPE_TEX_MIPFILTER_NEAREST,
                    color_writemask, zs_writemask);
   pipe_surface_reference(&dest_surface, NULL);

   /* Restore conditional rendering state. */
   if (st->render_condition) {
      pipe->render_condition(pipe, st->render_condition,
                             st->condition_mode);
   }

   return;

fallback:
   /* software fallback */
   fallback_copy_texsubimage(ctx,
                             strb, stImage, texBaseFormat,
                             destX, destY, destZ,
                             srcX, srcY, width, height);
}
示例#19
0
/**
 * Try issuing a quad blit.
 */
static bool
try_blit(struct svga_context *svga, const struct pipe_blit_info *blit_info)
{
   struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
   struct pipe_resource *src = blit_info->src.resource;
   struct pipe_resource *dst = blit_info->dst.resource;
   struct pipe_resource *newSrc = NULL;
   struct pipe_resource *newDst = NULL;
   bool can_create_src_view;
   bool can_create_dst_view;
   bool ret = true;
   struct pipe_blit_info blit = *blit_info;

   SVGA_STATS_TIME_PUSH(sws, SVGA_STATS_TIME_BLITBLITTER);

   /**
    * Avoid using util_blitter_blit() for these depth formats on non-vgpu10
    * devices because these depth formats only support comparison mode
    * and not ordinary sampling.
    */
   if (!svga_have_vgpu10(svga) && (blit.mask & PIPE_MASK_Z) &&
       (svga_texture(dst)->key.format == SVGA3D_Z_D16 ||
       svga_texture(dst)->key.format == SVGA3D_Z_D24X8 ||
       svga_texture(dst)->key.format == SVGA3D_Z_D24S8)) {
      ret = false;
      goto done;
  }

   /**
    * If format is srgb and blend is enabled then color values need
    * to be converted into linear format.
    */
   if (is_blending_enabled(svga, &blit)) {
      blit.src.format = util_format_linear(blit.src.format);
      blit.dst.format = util_format_linear(blit.dst.format);
   }

   /* Check if we can create shader resource view and
    * render target view for the quad blitter to work
    */
   can_create_src_view =
      is_view_format_compatible(src->format, svga_texture(src)->key.format,
                                blit.src.format);

   can_create_dst_view =
      is_view_format_compatible(dst->format, svga_texture(dst)->key.format,
                                blit.dst.format);

   if ((blit.mask & PIPE_MASK_S) ||
       ((!can_create_dst_view || !can_create_src_view)
        && !svga_have_vgpu10(svga))) {
      /* Can't do stencil blits with textured quad blitter */
      debug_warn_once("using software stencil blit");
      ret = false;
      goto done;
   }

   if (!util_blitter_is_blit_supported(svga->blitter, &blit)) {
      debug_printf("svga: blit unsupported %s -> %s\n",
                   util_format_short_name(blit.src.resource->format),
                   util_format_short_name(blit.dst.resource->format));
      ret = false;
      goto done;
   }

   /* XXX turn off occlusion and streamout queries */

   util_blitter_save_vertex_buffer_slot(svga->blitter, svga->curr.vb);
   util_blitter_save_vertex_elements(svga->blitter, (void*)svga->curr.velems);
   util_blitter_save_vertex_shader(svga->blitter, svga->curr.vs);
   util_blitter_save_geometry_shader(svga->blitter, svga->curr.user_gs);
   util_blitter_save_so_targets(svga->blitter, svga->num_so_targets,
                     (struct pipe_stream_output_target**)svga->so_targets);
   util_blitter_save_rasterizer(svga->blitter, (void*)svga->curr.rast);
   util_blitter_save_viewport(svga->blitter, &svga->curr.viewport);
   util_blitter_save_scissor(svga->blitter, &svga->curr.scissor);
   util_blitter_save_fragment_shader(svga->blitter, svga->curr.fs);
   util_blitter_save_blend(svga->blitter, (void*)svga->curr.blend);
   util_blitter_save_depth_stencil_alpha(svga->blitter,
                                         (void*)svga->curr.depth);
   util_blitter_save_stencil_ref(svga->blitter, &svga->curr.stencil_ref);
   util_blitter_save_sample_mask(svga->blitter, svga->curr.sample_mask);
   util_blitter_save_framebuffer(svga->blitter, &svga->curr.framebuffer);
   util_blitter_save_fragment_sampler_states(svga->blitter,
                     svga->curr.num_samplers[PIPE_SHADER_FRAGMENT],
                     (void**)svga->curr.sampler[PIPE_SHADER_FRAGMENT]);
   util_blitter_save_fragment_sampler_views(svga->blitter,
                     svga->curr.num_sampler_views[PIPE_SHADER_FRAGMENT],
                     svga->curr.sampler_views[PIPE_SHADER_FRAGMENT]);

   if (!can_create_src_view) {
      struct pipe_resource template;
      struct pipe_blit_info copy_region_blit;
示例#20
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);
}
示例#21
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);
   struct pipe_sampler_view *src_view;
   const GLuint width = texImage->Width;
   const GLuint height = texImage->Height;
   struct pipe_surface *dst_surface;
   struct pipe_resource *dst_texture;
   struct pipe_transfer *tex_xfer;
   unsigned bind = (PIPE_BIND_RENDER_TARGET | /* util_blit may choose to render */
		    PIPE_BIND_TRANSFER_READ);

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

   /* Disable conditional rendering. */
   if (st->render_condition) {
      pipe->render_condition(pipe, NULL, 0);
   }

   /* Create sampler view that limits fetches to the source mipmap level */
   {
      struct pipe_sampler_view sv_temp;

      u_sampler_view_default_template(&sv_temp, stObj->pt, stObj->pt->format);

      sv_temp.format = util_format_linear(sv_temp.format);
      sv_temp.u.tex.first_level =
      sv_temp.u.tex.last_level = texImage->Level;

      src_view = pipe->create_sampler_view(pipe, stObj->pt, &sv_temp);
      if (!src_view) {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
         return;
      }
   }

   /* blit/render/decompress */
   util_blit_pixels_tex(st->blit,
                        src_view,      /* pipe_resource (src) */
                        0, 0,             /* src x0, y0 */
                        width, height,    /* src x1, y1 */
                        dst_surface,      /* pipe_surface (dst) */
                        0, 0,             /* dst x0, y0 */
                        width, height,    /* dst x1, y1 */
                        0.0,              /* z */
                        PIPE_TEX_MIPFILTER_NEAREST);

   /* Restore conditional rendering state. */
   if (st->render_condition) {
      pipe->render_condition(pipe, st->render_condition,
                             st->condition_mode);
   }

   /* map the dst_surface so we can read from it */
   tex_xfer = pipe_get_transfer(pipe,
                                dst_texture, 0, 0,
                                PIPE_TRANSFER_READ,
                                0, 0, width, height);

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

   /* 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);
      ubyte *map = pipe_transfer_map(pipe, tex_xfer);
      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 = (GLfloat *) 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(pipe, tex_xfer, 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:
   _mesa_unmap_pbo_dest(ctx, &ctx->Pack);

   pipe->transfer_destroy(pipe, tex_xfer);

   /* destroy the temp / dest surface */
   util_destroy_rgba_surface(dst_texture, dst_surface);

   pipe_sampler_view_release(pipe, &src_view);
}
示例#22
0
文件: st_cb_fbo.c 项目: DirectFB/mesa
/**
 * Create or update the pipe_surface of a FBO renderbuffer.
 * This is usually called after st_finalize_texture.
 */
void
st_update_renderbuffer_surface(struct st_context *st,
                               struct st_renderbuffer *strb)
{
   struct pipe_context *pipe = st->pipe;
   struct pipe_resource *resource = strb->texture;
   int rtt_width = strb->Base.Width;
   int rtt_height = strb->Base.Height;
   int rtt_depth = strb->Base.Depth;
   enum pipe_format format = st->ctx->Color.sRGBEnabled ? resource->format :
         util_format_linear(resource->format);
   unsigned first_layer, last_layer, level;

   if (resource->target == PIPE_TEXTURE_1D_ARRAY) {
      rtt_depth = rtt_height;
      rtt_height = 1;
   }

   /* find matching mipmap level size */
   for (level = 0; level <= resource->last_level; level++) {
      if (u_minify(resource->width0, level) == rtt_width &&
          u_minify(resource->height0, level) == rtt_height &&
          (resource->target != PIPE_TEXTURE_3D ||
           u_minify(resource->depth0, level) == rtt_depth)) {
         break;
      }
   }
   assert(level <= resource->last_level);

   /* determine the layer bounds */
   if (strb->rtt_layered) {
      first_layer = 0;
      last_layer = util_max_layer(strb->texture, level);
   }
   else {
      first_layer =
      last_layer = strb->rtt_face + strb->rtt_slice;
   }

   if (!strb->surface ||
       strb->surface->texture->nr_samples != strb->Base.NumSamples ||
       strb->surface->format != format ||
       strb->surface->texture != resource ||
       strb->surface->width != rtt_width ||
       strb->surface->height != rtt_height ||
       strb->surface->u.tex.level != level ||
       strb->surface->u.tex.first_layer != first_layer ||
       strb->surface->u.tex.last_layer != last_layer) {
      /* create a new pipe_surface */
      struct pipe_surface surf_tmpl;
      memset(&surf_tmpl, 0, sizeof(surf_tmpl));
      surf_tmpl.format = format;
      surf_tmpl.u.tex.level = level;
      surf_tmpl.u.tex.first_layer = first_layer;
      surf_tmpl.u.tex.last_layer = last_layer;

      pipe_surface_reference(&strb->surface, NULL);

      strb->surface = pipe->create_surface(pipe, resource, &surf_tmpl);
   }
}
示例#23
0
文件: u_blit.c 项目: blckshrk/Mesa
/**
 * Copy pixel block from src surface to dst surface.
 * Overlapping regions are acceptable.
 * Flipping and stretching are supported.
 * \param filter  one of PIPE_TEX_MIPFILTER_NEAREST/LINEAR
 * \param writemask  controls which channels in the dest surface are sourced
 *                   from the src surface.  Disabled channels are sourced
 *                   from (0,0,0,1).
 */
void
util_blit_pixels(struct blit_state *ctx,
                 struct pipe_resource *src_tex,
                 unsigned src_level,
                 int srcX0, int srcY0,
                 int srcX1, int srcY1,
                 int srcZ0,
                 struct pipe_surface *dst,
                 int dstX0, int dstY0,
                 int dstX1, int dstY1,
                 float z, uint filter,
                 uint writemask, uint zs_writemask)
{
   struct pipe_context *pipe = ctx->pipe;
   struct pipe_screen *screen = pipe->screen;
   enum pipe_format src_format, dst_format;
   struct pipe_sampler_view *sampler_view = NULL;
   struct pipe_sampler_view sv_templ;
   struct pipe_surface *dst_surface;
   struct pipe_framebuffer_state fb;
   const int srcW = abs(srcX1 - srcX0);
   const int srcH = abs(srcY1 - srcY0);
   unsigned offset;
   boolean overlap;
   float s0, t0, s1, t1;
   boolean normalized;
   boolean is_stencil, is_depth, blit_depth, blit_stencil;
   const struct util_format_description *src_desc =
         util_format_description(src_tex->format);

   assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
          filter == PIPE_TEX_MIPFILTER_LINEAR);

   assert(src_level <= src_tex->last_level);

   /* do the regions overlap? */
   overlap = src_tex == dst->texture &&
             dst->u.tex.level == src_level &&
             dst->u.tex.first_layer == srcZ0 &&
      regions_overlap(srcX0, srcY0, srcX1, srcY1,
                      dstX0, dstY0, dstX1, dstY1);

   src_format = util_format_linear(src_tex->format);
   dst_format = util_format_linear(dst->texture->format);

   /* See whether we will blit depth or stencil. */
   is_depth = util_format_has_depth(src_desc);
   is_stencil = util_format_has_stencil(src_desc);

   blit_depth = is_depth && (zs_writemask & BLIT_WRITEMASK_Z);
   blit_stencil = is_stencil && (zs_writemask & BLIT_WRITEMASK_STENCIL);

   assert((writemask && !zs_writemask && !is_depth && !is_stencil) ||
          (!writemask && (blit_depth || blit_stencil)));

   /*
    * Check for simple case:  no format conversion, no flipping, no stretching,
    * no overlapping, same number of samples.
    * Filter mode should not matter since there's no stretching.
    */
   if (formats_compatible(src_format, dst_format) &&
       src_tex->nr_samples == dst->texture->nr_samples &&
       is_stencil == blit_stencil &&
       is_depth == blit_depth &&
       srcX0 < srcX1 &&
       dstX0 < dstX1 &&
       srcY0 < srcY1 &&
       dstY0 < dstY1 &&
       (dstX1 - dstX0) == (srcX1 - srcX0) &&
       (dstY1 - dstY0) == (srcY1 - srcY0) &&
       !overlap) {
      struct pipe_box src_box;
      src_box.x = srcX0;
      src_box.y = srcY0;
      src_box.z = srcZ0;
      src_box.width = srcW;
      src_box.height = srcH;
      src_box.depth = 1;
      pipe->resource_copy_region(pipe,
                                 dst->texture, dst->u.tex.level,
                                 dstX0, dstY0, dst->u.tex.first_layer,/* dest */
                                 src_tex, src_level,
                                 &src_box);
      return;
   }

   /* XXX Reading multisample textures is unimplemented. */
   assert(src_tex->nr_samples <= 1);
   if (src_tex->nr_samples > 1) {
      return;
   }

   /* It's a mistake to call this function with a stencil format and
    * without shader stencil export. We don't do software fallbacks here.
    * Ignore stencil and only copy depth.
    */
   if (blit_stencil && !ctx->has_stencil_export) {
      blit_stencil = FALSE;

      if (!blit_depth)
         return;
   }

   if (dst_format == dst->format) {
      dst_surface = dst;
   } else {
      struct pipe_surface templ = *dst;
      templ.format = dst_format;
      dst_surface = pipe->create_surface(pipe, dst->texture, &templ);
   }

   /* Create a temporary texture when src and dest alias.
    */
   if (src_tex == dst_surface->texture &&
       dst_surface->u.tex.level == src_level &&
       dst_surface->u.tex.first_layer == srcZ0) {
      /* Make a temporary texture which contains a copy of the source pixels.
       * Then we'll sample from the temporary texture.
       */
      struct pipe_resource texTemp;
      struct pipe_resource *tex;
      struct pipe_sampler_view sv_templ;
      struct pipe_box src_box;
      const int srcLeft = MIN2(srcX0, srcX1);
      const int srcTop = MIN2(srcY0, srcY1);

      if (srcLeft != srcX0) {
         /* left-right flip */
         int tmp = dstX0;
         dstX0 = dstX1;
         dstX1 = tmp;
      }

      if (srcTop != srcY0) {
         /* up-down flip */
         int tmp = dstY0;
         dstY0 = dstY1;
         dstY1 = tmp;
      }

      /* create temp texture */
      memset(&texTemp, 0, sizeof(texTemp));
      texTemp.target = ctx->internal_target;
      texTemp.format = src_format;
      texTemp.last_level = 0;
      texTemp.width0 = srcW;
      texTemp.height0 = srcH;
      texTemp.depth0 = 1;
      texTemp.array_size = 1;
      texTemp.bind = PIPE_BIND_SAMPLER_VIEW;

      tex = screen->resource_create(screen, &texTemp);
      if (!tex)
         return;

      src_box.x = srcLeft;
      src_box.y = srcTop;
      src_box.z = srcZ0;
      src_box.width = srcW;
      src_box.height = srcH;
      src_box.depth = 1;
      /* load temp texture */
      pipe->resource_copy_region(pipe,
                                 tex, 0, 0, 0, 0,  /* dest */
                                 src_tex, src_level, &src_box);

      normalized = tex->target != PIPE_TEXTURE_RECT;
      if(normalized) {
         s0 = 0.0f;
         s1 = 1.0f;
         t0 = 0.0f;
         t1 = 1.0f;
      }
      else {
         s0 = 0;
         s1 = srcW;
         t0 = 0;
         t1 = srcH;
      }

      u_sampler_view_default_template(&sv_templ, tex, tex->format);
      if (!blit_depth && blit_stencil) {
         /* set a stencil-only format, e.g. Z24S8 --> X24S8 */
         sv_templ.format = util_format_stencil_only(tex->format);
         assert(sv_templ.format != PIPE_FORMAT_NONE);
      }
      sampler_view = pipe->create_sampler_view(pipe, tex, &sv_templ);

      if (!sampler_view) {
         pipe_resource_reference(&tex, NULL);
         return;
      }
      pipe_resource_reference(&tex, NULL);
   }
   else {
      /* Directly sample from the source resource/texture */
      u_sampler_view_default_template(&sv_templ, src_tex, src_format);
      if (!blit_depth && blit_stencil) {
         /* set a stencil-only format, e.g. Z24S8 --> X24S8 */
         sv_templ.format = util_format_stencil_only(src_format);
         assert(sv_templ.format != PIPE_FORMAT_NONE);
      }
      sampler_view = pipe->create_sampler_view(pipe, src_tex, &sv_templ);

      if (!sampler_view) {
         return;
      }

      s0 = srcX0;
      s1 = srcX1;
      t0 = srcY0;
      t1 = srcY1;
      normalized = sampler_view->texture->target != PIPE_TEXTURE_RECT;
      if(normalized)
      {
         s0 /= (float)(u_minify(sampler_view->texture->width0, src_level));
         s1 /= (float)(u_minify(sampler_view->texture->width0, src_level));
         t0 /= (float)(u_minify(sampler_view->texture->height0, src_level));
         t1 /= (float)(u_minify(sampler_view->texture->height0, src_level));
      }
   }

   assert(screen->is_format_supported(screen, sampler_view->format,
                     ctx->internal_target, sampler_view->texture->nr_samples,
                     PIPE_BIND_SAMPLER_VIEW));
   assert(screen->is_format_supported(screen, dst_format, ctx->internal_target,
                     dst_surface->texture->nr_samples,
                     is_depth || is_stencil ? PIPE_BIND_DEPTH_STENCIL :
                                              PIPE_BIND_RENDER_TARGET));

   /* save state (restored below) */
   cso_save_blend(ctx->cso);
   cso_save_depth_stencil_alpha(ctx->cso);
   cso_save_rasterizer(ctx->cso);
   cso_save_sample_mask(ctx->cso);
   cso_save_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
   cso_save_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
   cso_save_stream_outputs(ctx->cso);
   cso_save_viewport(ctx->cso);
   cso_save_framebuffer(ctx->cso);
   cso_save_fragment_shader(ctx->cso);
   cso_save_vertex_shader(ctx->cso);
   cso_save_geometry_shader(ctx->cso);
   cso_save_vertex_elements(ctx->cso);
   cso_save_aux_vertex_buffer_slot(ctx->cso);
   cso_save_render_condition(ctx->cso);

   /* set misc state we care about */
   if (writemask)
      cso_set_blend(ctx->cso, &ctx->blend_write_color);
   else
      cso_set_blend(ctx->cso, &ctx->blend_keep_color);

   cso_set_sample_mask(ctx->cso, ~0);
   cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
   cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
   cso_set_stream_outputs(ctx->cso, 0, NULL, 0);
   cso_set_render_condition(ctx->cso, NULL, 0);

   /* default sampler state */
   ctx->sampler.normalized_coords = normalized;
   ctx->sampler.min_img_filter = filter;
   ctx->sampler.mag_img_filter = filter;
   ctx->sampler.min_lod = src_level;
   ctx->sampler.max_lod = src_level;

   /* Depth stencil state, fragment shader and sampler setup depending on what
    * we blit.
    */
   if (blit_depth && blit_stencil) {
      cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
      /* don't filter stencil */
      ctx->sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
      ctx->sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
      cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &ctx->sampler);

      cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_depthstencil);
      set_depthstencil_fragment_shader(ctx, sampler_view->texture->target);
   }
   else if (blit_depth) {
      cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
      cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_depth);
      set_depth_fragment_shader(ctx, sampler_view->texture->target);
   }
   else if (blit_stencil) {
      /* don't filter stencil */
      ctx->sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
      ctx->sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
      cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);

      cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_stencil);
      set_stencil_fragment_shader(ctx, sampler_view->texture->target);
   }
   else { /* color */
      cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
      cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_keep_depthstencil);
      set_fragment_shader(ctx, writemask, sampler_view->texture->target);
   }
   cso_single_sampler_done(ctx->cso, PIPE_SHADER_FRAGMENT);

   /* textures */
   if (blit_depth && blit_stencil) {
      /* Setup two samplers, one for depth and the other one for stencil. */
      struct pipe_sampler_view templ;
      struct pipe_sampler_view *views[2];

      templ = *sampler_view;
      templ.format = util_format_stencil_only(templ.format);
      assert(templ.format != PIPE_FORMAT_NONE);

      views[0] = sampler_view;
      views[1] = pipe->create_sampler_view(pipe, views[0]->texture, &templ);
      cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 2, views);

      pipe_sampler_view_reference(&views[1], NULL);
   }
   else {
      cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &sampler_view);
   }

   /* viewport */
   ctx->viewport.scale[0] = 0.5f * dst_surface->width;
   ctx->viewport.scale[1] = 0.5f * dst_surface->height;
   ctx->viewport.scale[2] = 0.5f;
   ctx->viewport.scale[3] = 1.0f;
   ctx->viewport.translate[0] = 0.5f * dst_surface->width;
   ctx->viewport.translate[1] = 0.5f * dst_surface->height;
   ctx->viewport.translate[2] = 0.5f;
   ctx->viewport.translate[3] = 0.0f;
   cso_set_viewport(ctx->cso, &ctx->viewport);

   set_vertex_shader(ctx);
   cso_set_geometry_shader_handle(ctx->cso, NULL);

   /* drawing dest */
   memset(&fb, 0, sizeof(fb));
   fb.width = dst_surface->width;
   fb.height = dst_surface->height;
   if (blit_depth || blit_stencil) {
      fb.zsbuf = dst_surface;
   } else {
      fb.nr_cbufs = 1;
      fb.cbufs[0] = dst_surface;
   }
   cso_set_framebuffer(ctx->cso, &fb);

   /* draw quad */
   offset = setup_vertex_data_tex(ctx,
                                  (float) dstX0 / dst_surface->width * 2.0f - 1.0f,
                                  (float) dstY0 / dst_surface->height * 2.0f - 1.0f,
                                  (float) dstX1 / dst_surface->width * 2.0f - 1.0f,
                                  (float) dstY1 / dst_surface->height * 2.0f - 1.0f,
                                  s0, t0,
                                  s1, t1,
                                  z);

   if (ctx->vbuf) {
      util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf,
                              cso_get_aux_vertex_buffer_slot(ctx->cso),
                              offset,
                              PIPE_PRIM_TRIANGLE_FAN,
                              4,  /* verts */
                              2); /* attribs/vert */
   }

   /* restore state we changed */
   cso_restore_blend(ctx->cso);
   cso_restore_depth_stencil_alpha(ctx->cso);
   cso_restore_rasterizer(ctx->cso);
   cso_restore_sample_mask(ctx->cso);
   cso_restore_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
   cso_restore_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
   cso_restore_viewport(ctx->cso);
   cso_restore_framebuffer(ctx->cso);
   cso_restore_fragment_shader(ctx->cso);
   cso_restore_vertex_shader(ctx->cso);
   cso_restore_geometry_shader(ctx->cso);
   cso_restore_vertex_elements(ctx->cso);
   cso_restore_aux_vertex_buffer_slot(ctx->cso);
   cso_restore_stream_outputs(ctx->cso);
   cso_restore_render_condition(ctx->cso);

   pipe_sampler_view_reference(&sampler_view, NULL);
   if (dst_surface != dst)
      pipe_surface_reference(&dst_surface, NULL);
}
示例#24
0
static void
st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
              GLsizei width, GLsizei height,
              GLint dstx, GLint dsty, GLenum type)
{
   struct st_context *st = st_context(ctx);
   struct pipe_context *pipe = st->pipe;
   struct pipe_screen *screen = pipe->screen;
   struct st_renderbuffer *rbRead;
   void *driver_vp, *driver_fp;
   struct pipe_resource *pt;
   struct pipe_sampler_view *sv[2];
   int num_sampler_view = 1;
   GLfloat *color;
   enum pipe_format srcFormat, texFormat;
   GLboolean invertTex = GL_FALSE;
   GLint readX, readY, readW, readH;
   GLuint sample_count;
   struct gl_pixelstore_attrib pack = ctx->DefaultPacking;
   struct st_fp_variant *fpv;

   st_validate_state(st);

   if (type == GL_STENCIL) {
      /* can't use texturing to do stencil */
      copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty);
      return;
   }

   if (blit_copy_pixels(ctx, srcx, srcy, width, height, dstx, dsty, type))
      return;

   /*
    * The subsequent code implements glCopyPixels by copying the source
    * pixels into a temporary texture that's then applied to a textured quad.
    * When we draw the textured quad, all the usual per-fragment operations
    * are handled.
    */


   /*
    * Get vertex/fragment shaders
    */
   if (type == GL_COLOR) {
      rbRead = st_get_color_read_renderbuffer(ctx);
      color = NULL;

      fpv = get_color_fp_variant(st);
      driver_fp = fpv->driver_shader;

      driver_vp = make_passthrough_vertex_shader(st, GL_FALSE);

      if (st->pixel_xfer.pixelmap_enabled) {
	  sv[1] = st->pixel_xfer.pixelmap_sampler_view;
	  num_sampler_view++;
      }
   }
   else {
      assert(type == GL_DEPTH);
      rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer);
      color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];

      fpv = get_depth_stencil_fp_variant(st, GL_TRUE, GL_FALSE);
      driver_fp = fpv->driver_shader;

      driver_vp = make_passthrough_vertex_shader(st, GL_TRUE);
   }

   /* update fragment program constants */
   st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT);


   if (rbRead->Base.Wrapped)
      rbRead = st_renderbuffer(rbRead->Base.Wrapped);

   sample_count = rbRead->texture->nr_samples;
   /* I believe this would be legal, presumably would need to do a resolve
      for color, and for depth/stencil spec says to just use one of the
      depth/stencil samples per pixel? Need some transfer clarifications. */
   assert(sample_count < 2);

   srcFormat = rbRead->texture->format;

   if (screen->is_format_supported(screen, srcFormat, st->internal_target,
                                   sample_count,
                                   PIPE_BIND_SAMPLER_VIEW)) {
      texFormat = srcFormat;
   }
   else {
      /* srcFormat can't be used as a texture format */
      if (type == GL_DEPTH) {
         texFormat = st_choose_format(screen, GL_DEPTH_COMPONENT,
                                      GL_NONE, GL_NONE, st->internal_target,
				      sample_count, PIPE_BIND_DEPTH_STENCIL);
         assert(texFormat != PIPE_FORMAT_NONE);
      }
      else {
         /* default color format */
         texFormat = st_choose_format(screen, GL_RGBA,
                                      GL_NONE, GL_NONE, st->internal_target,
                                      sample_count, PIPE_BIND_SAMPLER_VIEW);
         assert(texFormat != PIPE_FORMAT_NONE);
      }
   }

   /* Invert src region if needed */
   if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
      srcy = ctx->ReadBuffer->Height - srcy - height;
      invertTex = !invertTex;
   }

   /* Clip the read region against the src buffer bounds.
    * We'll still allocate a temporary buffer/texture for the original
    * src region size but we'll only read the region which is on-screen.
    * This may mean that we draw garbage pixels into the dest region, but
    * that's expected.
    */
   readX = srcx;
   readY = srcy;
   readW = width;
   readH = height;
   _mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack);
   readW = MAX2(0, readW);
   readH = MAX2(0, readH);

   /* alloc temporary texture */
   pt = alloc_texture(st, width, height, texFormat);
   if (!pt)
      return;

   sv[0] = st_create_texture_sampler_view(st->pipe, pt);
   if (!sv[0]) {
      pipe_resource_reference(&pt, NULL);
      return;
   }

   /* Make temporary texture which is a copy of the src region.
    */
   if (srcFormat == texFormat) {
      struct pipe_box src_box;
      u_box_2d(readX, readY, readW, readH, &src_box);
      /* copy source framebuffer surface into mipmap/texture */
      pipe->resource_copy_region(pipe,
                                 pt,                                /* dest tex */
                                 0,                                 /* dest lvl */
                                 pack.SkipPixels, pack.SkipRows, 0, /* dest pos */
                                 rbRead->texture,                   /* src tex */
                                 rbRead->rtt_level,                 /* src lvl */
                                 &src_box);

   }
   else {
      /* CPU-based fallback/conversion */
      struct pipe_transfer *ptRead =
         pipe_get_transfer(st->pipe, rbRead->texture,
                           rbRead->rtt_level,
                           rbRead->rtt_face + rbRead->rtt_slice,
                           PIPE_TRANSFER_READ,
                           readX, readY, readW, readH);
      struct pipe_transfer *ptTex;
      enum pipe_transfer_usage transfer_usage;

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

      if (type == GL_DEPTH && util_format_is_depth_and_stencil(pt->format))
         transfer_usage = PIPE_TRANSFER_READ_WRITE;
      else
         transfer_usage = PIPE_TRANSFER_WRITE;

      ptTex = pipe_get_transfer(st->pipe, pt, 0, 0, transfer_usage,
                                0, 0, width, height);

      /* copy image from ptRead surface to ptTex surface */
      if (type == GL_COLOR) {
         /* alternate path using get/put_tile() */
         GLfloat *buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
         enum pipe_format readFormat, drawFormat;
         readFormat = util_format_linear(rbRead->texture->format);
         drawFormat = util_format_linear(pt->format);
         pipe_get_tile_rgba_format(pipe, ptRead, 0, 0, readW, readH,
                                   readFormat, buf);
         pipe_put_tile_rgba_format(pipe, ptTex, pack.SkipPixels, pack.SkipRows,
                                   readW, readH, drawFormat, buf);
         free(buf);
      }
      else {
         /* GL_DEPTH */
         GLuint *buf = (GLuint *) malloc(width * height * sizeof(GLuint));
         pipe_get_tile_z(pipe, ptRead, 0, 0, readW, readH, buf);
         pipe_put_tile_z(pipe, ptTex, pack.SkipPixels, pack.SkipRows,
                         readW, readH, buf);
         free(buf);
      }

      pipe->transfer_destroy(pipe, ptRead);
      pipe->transfer_destroy(pipe, ptTex);
   }

   /* OK, the texture 'pt' contains the src image/pixels.  Now draw a
    * textured quad with that texture.
    */
   draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2],
                      width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
                      sv,
                      num_sampler_view,
                      driver_vp, 
                      driver_fp,
                      color, invertTex, GL_FALSE, GL_FALSE);

   pipe_resource_reference(&pt, NULL);
   pipe_sampler_view_reference(&sv[0], NULL);
}
static void
st_BlitFramebuffer(struct gl_context *ctx,
                   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 gl_framebuffer *readFB = ctx->ReadBuffer;
   struct gl_framebuffer *drawFB = ctx->DrawBuffer;
   struct {
      GLint srcX0, srcY0, srcX1, srcY1;
      GLint dstX0, dstY0, dstX1, dstY1;
   } clip;
   struct pipe_blit_info blit;

   st_validate_state(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,
                        &clip.srcX0, &clip.srcY0, &clip.srcX1, &clip.srcY1,
                        &clip.dstX0, &clip.dstY0, &clip.dstX1, &clip.dstY1)) {
      return; /* nothing to draw/blit */
   }
   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;
   }

   blit.filter = pFilter;

   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 = util_format_linear(dstSurf->format);

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

                  st->pipe->blit(st->pipe, &blit);
               }
            }
         }
      }
      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 = util_format_linear(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 = util_format_linear(srcSurf->format);

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

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

      /* get src/dst depth surfaces */
      struct gl_renderbuffer_attachment *srcDepth =
         &readFB->Attachment[BUFFER_DEPTH];
      struct gl_renderbuffer_attachment *dstDepth =
         &drawFB->Attachment[BUFFER_DEPTH];
      struct gl_renderbuffer_attachment *srcStencil =
         &readFB->Attachment[BUFFER_STENCIL];
      struct gl_renderbuffer_attachment *dstStencil =
         &drawFB->Attachment[BUFFER_STENCIL];

      struct st_renderbuffer *srcDepthRb =
         st_renderbuffer(srcDepth->Renderbuffer);
      struct st_renderbuffer *dstDepthRb = 
         st_renderbuffer(dstDepth->Renderbuffer);
      struct pipe_surface *dstDepthSurf =
         dstDepthRb ? dstDepthRb->surface : NULL;

      struct st_renderbuffer *srcStencilRb =
         st_renderbuffer(srcStencil->Renderbuffer);
      struct st_renderbuffer *dstStencilRb =
         st_renderbuffer(dstStencil->Renderbuffer);
      struct pipe_surface *dstStencilSurf =
         dstStencilRb ? dstStencilRb->surface : NULL;

      if (st_is_depth_stencil_combined(srcDepth, srcStencil) &&
          st_is_depth_stencil_combined(dstDepth, dstStencil)) {
         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);
         }
      }
   }
}
示例#26
0
/**
 * Do a CopyTexSubImage operation using a read transfer from the source,
 * a write transfer to the destination and get_tile()/put_tile() to access
 * the pixels/texels.
 *
 * Note: srcY=0=TOP of renderbuffer
 */
static void
fallback_copy_texsubimage(struct gl_context *ctx,
                          struct st_renderbuffer *strb,
                          struct st_texture_image *stImage,
                          GLenum baseFormat,
                          GLint destX, GLint destY, GLint destZ,
                          GLint srcX, GLint srcY,
                          GLsizei width, GLsizei height)
{
   struct st_context *st = st_context(ctx);
   struct pipe_context *pipe = st->pipe;
   struct pipe_transfer *src_trans;
   GLvoid *texDest;
   enum pipe_transfer_usage transfer_usage;
   void *map;

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

   if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
      srcY = strb->Base.Height - srcY - height;
   }

   map = pipe_transfer_map(pipe,
                           strb->texture,
                           strb->rtt_level,
                           strb->rtt_face + strb->rtt_slice,
                           PIPE_TRANSFER_READ,
                           srcX, srcY,
                           width, height, &src_trans);

   if ((baseFormat == GL_DEPTH_COMPONENT ||
        baseFormat == GL_DEPTH_STENCIL) &&
       util_format_is_depth_and_stencil(stImage->pt->format))
      transfer_usage = PIPE_TRANSFER_READ_WRITE;
   else
      transfer_usage = PIPE_TRANSFER_WRITE;

   /* XXX this used to ignore destZ param */
   texDest = st_texture_image_map(st, stImage, destZ, transfer_usage,
                                  destX, destY, width, height);

   if (baseFormat == GL_DEPTH_COMPONENT ||
       baseFormat == GL_DEPTH_STENCIL) {
      const GLboolean scaleOrBias = (ctx->Pixel.DepthScale != 1.0F ||
                                     ctx->Pixel.DepthBias != 0.0F);
      GLint row, yStep;
      uint *data;

      /* determine bottom-to-top vs. top-to-bottom order for src buffer */
      if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
         srcY = height - 1;
         yStep = -1;
      }
      else {
         srcY = 0;
         yStep = 1;
      }

      data = malloc(width * sizeof(uint));

      if (data) {
         /* To avoid a large temp memory allocation, do copy row by row */
         for (row = 0; row < height; row++, srcY += yStep) {
            pipe_get_tile_z(src_trans, map, 0, srcY, width, 1, data);
            if (scaleOrBias) {
               _mesa_scale_and_bias_depth_uint(ctx, width, data);
            }
            pipe_put_tile_z(stImage->transfer, texDest, 0, row, width, 1,
                            data);
         }
      }
      else {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage()");
      }

      free(data);
   }
   else {
      /* RGBA format */
      GLfloat *tempSrc =
         malloc(width * height * 4 * sizeof(GLfloat));

      if (tempSrc && texDest) {
         const GLint dims = 2;
         const GLint dstRowStride = stImage->transfer->stride;
         struct gl_texture_image *texImage = &stImage->base;
         struct gl_pixelstore_attrib unpack = ctx->DefaultPacking;

         if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
            unpack.Invert = GL_TRUE;
         }

         /* get float/RGBA image from framebuffer */
         /* XXX this usually involves a lot of int/float conversion.
          * try to avoid that someday.
          */
         pipe_get_tile_rgba_format(src_trans, map, 0, 0, width, height,
                                   util_format_linear(strb->texture->format),
                                   tempSrc);

         /* Store into texture memory.
          * Note that this does some special things such as pixel transfer
          * ops and format conversion.  In particular, if the dest tex format
          * is actually RGBA but the user created the texture as GL_RGB we
          * need to fill-in/override the alpha channel with 1.0.
          */
         _mesa_texstore(ctx, dims,
                        texImage->_BaseFormat, 
                        texImage->TexFormat, 
                        dstRowStride,
                        (GLubyte **) &texDest,
                        width, height, 1,
                        GL_RGBA, GL_FLOAT, tempSrc, /* src */
                        &unpack);
      }
      else {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
      }

      free(tempSrc);
   }

   st_texture_image_unmap(st, stImage);
   pipe->transfer_unmap(pipe, src_trans);
}
示例#27
0
/**
 * Do a CopyTex[Sub]Image1/2/3D() using a hardware (blit) path if possible.
 * Note that the region to copy has already been clipped so we know we
 * won't read from outside the source renderbuffer's bounds.
 *
 * Note: srcY=0=Bottom of renderbuffer (GL convention)
 */
static void
st_copy_texsubimage(struct gl_context *ctx,
                    struct gl_texture_image *texImage,
                    GLint destX, GLint destY, GLint destZ,
                    struct gl_renderbuffer *rb,
                    GLint srcX, GLint srcY,
                    GLsizei width, GLsizei height)
{
   struct st_texture_image *stImage = st_texture_image(texImage);
   const GLenum texBaseFormat = texImage->_BaseFormat;
   struct gl_framebuffer *fb = ctx->ReadBuffer;
   struct st_renderbuffer *strb;
   struct st_context *st = st_context(ctx);
   struct pipe_context *pipe = st->pipe;
   struct pipe_screen *screen = pipe->screen;
   enum pipe_format dest_format, src_format;
   GLboolean matching_base_formats;
   GLuint format_writemask, sample_count;
   struct pipe_surface *dest_surface = NULL;
   GLboolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP);
   struct pipe_surface surf_tmpl;
   unsigned int dst_usage;
   GLint srcY0, srcY1;

   /* make sure finalize_textures has been called? 
    */
   if (0) st_validate_state(st);

   /* determine if copying depth or color data */
   if (texBaseFormat == GL_DEPTH_COMPONENT ||
       texBaseFormat == GL_DEPTH_STENCIL) {
      strb = st_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer);
   }
   else {
      /* texBaseFormat == GL_RGB, GL_RGBA, GL_ALPHA, etc */
      strb = st_renderbuffer(fb->_ColorReadBuffer);
   }

   if (!strb || !strb->surface || !stImage->pt) {
      debug_printf("%s: null strb or stImage\n", __FUNCTION__);
      return;
   }

   sample_count = strb->surface->texture->nr_samples;
   /* I believe this would be legal, presumably would need to do a resolve
      for color, and for depth/stencil spec says to just use one of the
      depth/stencil samples per pixel? Need some transfer clarifications. */
   assert(sample_count < 2);

   assert(strb);
   assert(strb->surface);
   assert(stImage->pt);

   src_format = strb->surface->format;
   dest_format = stImage->pt->format;

   /*
    * Determine if the src framebuffer and dest texture have the same
    * base format.  We need this to detect a case such as the framebuffer
    * being GL_RGBA but the texture being GL_RGB.  If the actual hardware
    * texture format stores RGBA we need to set A=1 (overriding the
    * framebuffer's alpha values).  We can't do that with the blit or
    * textured-quad paths.
    */
   matching_base_formats =
      (_mesa_get_format_base_format(strb->Base.Format) ==
       _mesa_get_format_base_format(texImage->TexFormat));

   if (ctx->_ImageTransferState) {
      goto fallback;
   }

   if (matching_base_formats &&
       src_format == dest_format &&
       !do_flip) {
      /* use surface_copy() / blit */
      struct pipe_box src_box;
      u_box_2d_zslice(srcX, srcY, strb->surface->u.tex.first_layer,
                      width, height, &src_box);

      /* for resource_copy_region(), y=0=top, always */
      pipe->resource_copy_region(pipe,
                                 /* dest */
                                 stImage->pt,
                                 stImage->base.Level,
                                 destX, destY, destZ + stImage->base.Face,
                                 /* src */
                                 strb->texture,
                                 strb->surface->u.tex.level,
                                 &src_box);
      return;
   }

   if (texBaseFormat == GL_DEPTH_STENCIL) {
      goto fallback;
   }

   if (texBaseFormat == GL_DEPTH_COMPONENT) {
      format_writemask = TGSI_WRITEMASK_XYZW;
      dst_usage = PIPE_BIND_DEPTH_STENCIL;
   }
   else {
      format_writemask = compatible_src_dst_formats(ctx, &strb->Base, texImage);
      dst_usage = PIPE_BIND_RENDER_TARGET;
   }

   if (!format_writemask ||
       !screen->is_format_supported(screen, src_format,
                                    PIPE_TEXTURE_2D, sample_count,
                                    PIPE_BIND_SAMPLER_VIEW) ||
       !screen->is_format_supported(screen, dest_format,
                                    PIPE_TEXTURE_2D, 0,
                                    dst_usage)) {
      goto fallback;
   }

   if (do_flip) {
      srcY1 = strb->Base.Height - srcY - height;
      srcY0 = srcY1 + height;
   }
   else {
      srcY0 = srcY;
      srcY1 = srcY0 + height;
   }

   /* Disable conditional rendering. */
   if (st->render_condition) {
      pipe->render_condition(pipe, NULL, 0);
   }

   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
   surf_tmpl.format = util_format_linear(stImage->pt->format);
   surf_tmpl.usage = dst_usage;
   surf_tmpl.u.tex.level = stImage->base.Level;
   surf_tmpl.u.tex.first_layer = stImage->base.Face + destZ;
   surf_tmpl.u.tex.last_layer = stImage->base.Face + destZ;

   dest_surface = pipe->create_surface(pipe, stImage->pt,
                                       &surf_tmpl);
   util_blit_pixels_writemask(st->blit,
                              strb->texture,
                              strb->surface->u.tex.level,
                              srcX, srcY0,
                              srcX + width, srcY1,
                              strb->surface->u.tex.first_layer,
                              dest_surface,
                              destX, destY,
                              destX + width, destY + height,
                              0.0, PIPE_TEX_MIPFILTER_NEAREST,
                              format_writemask);
   pipe_surface_reference(&dest_surface, NULL);

   /* Restore conditional rendering state. */
   if (st->render_condition) {
      pipe->render_condition(pipe, st->render_condition,
                             st->condition_mode);
   }

   return;

fallback:
   /* software fallback */
   fallback_copy_texsubimage(ctx,
                             strb, stImage, texBaseFormat,
                             destX, destY, destZ,
                             srcX, srcY, width, height);
}
示例#28
0
文件: r300_blit.c 项目: chemecse/mesa
static void r300_blit(struct pipe_context *pipe,
                      const struct pipe_blit_info *blit)
{
    struct r300_context *r300 = r300_context(pipe);
    struct pipe_framebuffer_state *fb =
        (struct pipe_framebuffer_state*)r300->fb_state.state;
    struct pipe_blit_info info = *blit;

    /* The driver supports sRGB textures but not framebuffers. Blitting
     * from sRGB to sRGB should be the same as blitting from linear
     * to linear, so use that, This avoids incorrect linearization.
     */
    if (util_format_is_srgb(info.src.format)) {
      info.src.format = util_format_linear(info.src.format);
      info.dst.format = util_format_linear(info.dst.format);
    }

    /* MSAA resolve. */
    if (info.src.resource->nr_samples > 1 &&
        !util_format_is_depth_or_stencil(info.src.resource->format)) {
        r300_msaa_resolve(pipe, &info);
        return;
    }

    /* Can't read MSAA textures. */
    if (info.src.resource->nr_samples > 1) {
        return;
    }

    /* Blit a combined depth-stencil resource as color.
     * S8Z24 is the only supported stencil format. */
    if ((info.mask & PIPE_MASK_S) &&
        info.src.format == PIPE_FORMAT_S8_UINT_Z24_UNORM &&
        info.dst.format == PIPE_FORMAT_S8_UINT_Z24_UNORM) {
        if (info.dst.resource->nr_samples > 1) {
            /* Cannot do that with MSAA buffers. */
            info.mask &= ~PIPE_MASK_S;
            if (!(info.mask & PIPE_MASK_Z)) {
                return;
            }
        } else {
            /* Single-sample buffer. */
            info.src.format = PIPE_FORMAT_B8G8R8A8_UNORM;
            info.dst.format = PIPE_FORMAT_B8G8R8A8_UNORM;
            if (info.mask & PIPE_MASK_Z) {
                info.mask = PIPE_MASK_RGBA; /* depth+stencil */
            } else {
                info.mask = PIPE_MASK_B; /* stencil only */
            }
        }
    }

    /* Decompress ZMASK. */
    if (r300->zmask_in_use && !r300->locked_zbuffer) {
        if (fb->zsbuf->texture == info.src.resource ||
            fb->zsbuf->texture == info.dst.resource) {
            r300_decompress_zmask(r300);
        }
    }

    r300_blitter_begin(r300, R300_BLIT |
		       (info.render_condition_enable ? 0 : R300_IGNORE_RENDER_COND));
    util_blitter_blit(r300->blitter, &info);
    r300_blitter_end(r300);
}
示例#29
0
/**
 * This uses a blit to copy the read buffer to a texture format which matches
 * the format and type combo and then a fast read-back is done using memcpy.
 * We can do arbitrary X/Y/Z/W/0/1 swizzling here as long as there is
 * a format which matches the swizzling.
 *
 * If such a format isn't available, we fall back to _mesa_readpixels.
 *
 * NOTE: Some drivers use a blit to convert between tiled and linear
 *       texture layouts during texture uploads/downloads, so the blit
 *       we do here should be free in such cases.
 */
static void
st_readpixels(struct gl_context *ctx, GLint x, GLint y,
              GLsizei width, GLsizei height,
              GLenum format, GLenum type,
              const struct gl_pixelstore_attrib *pack,
              GLvoid *pixels)
{
   struct st_context *st = st_context(ctx);
   struct gl_renderbuffer *rb =
         _mesa_get_read_renderbuffer_for_format(ctx, format);
   struct st_renderbuffer *strb = st_renderbuffer(rb);
   struct pipe_context *pipe = st->pipe;
   struct pipe_screen *screen = pipe->screen;
   struct pipe_resource *src;
   struct pipe_resource *dst = NULL;
   struct pipe_resource dst_templ;
   enum pipe_format dst_format, src_format;
   struct pipe_blit_info blit;
   unsigned bind = PIPE_BIND_TRANSFER_READ;
   struct pipe_transfer *tex_xfer;
   ubyte *map = NULL;

   /* Validate state (to be sure we have up-to-date framebuffer surfaces)
    * and flush the bitmap cache prior to reading. */
   st_validate_state(st);
   st_flush_bitmap_cache(st);

   if (!st->prefer_blit_based_texture_transfer) {
      goto fallback;
   }

   /* This must be done after state validation. */
   src = strb->texture;

   /* XXX Fallback for depth-stencil formats due to an incomplete
    * stencil blit implementation in some drivers. */
   if (format == GL_DEPTH_STENCIL) {
      goto fallback;
   }

   /* We are creating a texture of the size of the region being read back.
    * Need to check for NPOT texture support. */
   if (!screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES) &&
       (!util_is_power_of_two(width) ||
        !util_is_power_of_two(height))) {
      goto fallback;
   }

   /* If the base internal format and the texture format don't match, we have
    * to use the slow path. */
   if (rb->_BaseFormat !=
       _mesa_get_format_base_format(rb->Format)) {
      goto fallback;
   }

   /* See if the texture format already matches the format and type,
    * in which case the memcpy-based fast path will likely be used and
    * we don't have to blit. */
   if (_mesa_format_matches_format_and_type(rb->Format, format,
                                            type, pack->SwapBytes)) {
      goto fallback;
   }

   if (_mesa_readpixels_needs_slow_path(ctx, format, type, GL_TRUE)) {
      goto fallback;
   }

   /* Convert the source format to what is expected by ReadPixels
    * and see if it's supported. */
   src_format = util_format_linear(src->format);
   src_format = util_format_luminance_to_red(src_format);
   src_format = util_format_intensity_to_red(src_format);

   if (!src_format ||
       !screen->is_format_supported(screen, src_format, src->target,
                                    src->nr_samples,
                                    PIPE_BIND_SAMPLER_VIEW)) {
      goto fallback;
   }

   if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL)
      bind |= PIPE_BIND_DEPTH_STENCIL;
   else
      bind |= PIPE_BIND_RENDER_TARGET;

   /* Choose the destination format by finding the best match
    * for the format+type combo. */
   dst_format = st_choose_matching_format(screen, bind, format, type,
                                          pack->SwapBytes);
   if (dst_format == PIPE_FORMAT_NONE) {
      goto fallback;
   }

   /* create the destination texture */
   memset(&dst_templ, 0, sizeof(dst_templ));
   dst_templ.target = PIPE_TEXTURE_2D;
   dst_templ.format = dst_format;
   dst_templ.bind = bind;
   dst_templ.usage = PIPE_USAGE_STAGING;

   st_gl_texture_dims_to_pipe_dims(GL_TEXTURE_2D, width, height, 1,
                                   &dst_templ.width0, &dst_templ.height0,
                                   &dst_templ.depth0, &dst_templ.array_size);

   dst = screen->resource_create(screen, &dst_templ);
   if (!dst) {
      goto fallback;
   }

   memset(&blit, 0, sizeof(blit));
   blit.src.resource = src;
   blit.src.level = strb->surface->u.tex.level;
   blit.src.format = src_format;
   blit.dst.resource = dst;
   blit.dst.level = 0;
   blit.dst.format = dst->format;
   blit.src.box.x = x;
   blit.dst.box.x = 0;
   blit.src.box.y = y;
   blit.dst.box.y = 0;
   blit.src.box.z = strb->surface->u.tex.first_layer;
   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 = st_get_blit_mask(rb->_BaseFormat, format);
   blit.filter = PIPE_TEX_FILTER_NEAREST;
   blit.scissor_enable = FALSE;

   if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
      blit.src.box.y = rb->Height - blit.src.box.y;
      blit.src.box.height = -blit.src.box.height;
   }

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

   /* map resources */
   pixels = _mesa_map_pbo_dest(ctx, pack, pixels);

   map = pipe_transfer_map_3d(pipe, dst, 0, PIPE_TRANSFER_READ,
                              0, 0, 0, width, height, 1, &tex_xfer);
   if (!map) {
      _mesa_unmap_pbo_dest(ctx, pack);
      pipe_resource_reference(&dst, NULL);
      goto fallback;
   }

   /* memcpy data into a user buffer */
   {
      const uint bytesPerRow = width * util_format_get_blocksize(dst_format);
      GLuint row;

      for (row = 0; row < (unsigned) height; row++) {
         GLvoid *dest = _mesa_image_address3d(pack, pixels,
                                              width, height, format,
                                              type, 0, row, 0);
         memcpy(dest, map, bytesPerRow);
         map += tex_xfer->stride;
      }
   }

   pipe_transfer_unmap(pipe, tex_xfer);
   _mesa_unmap_pbo_dest(ctx, pack);
   pipe_resource_reference(&dst, NULL);
   return;

fallback:
   _mesa_readpixels(ctx, x, y, width, height, format, type, pack, pixels);
}
示例#30
0
文件: st_cb_fbo.c 项目: xSIMx/Mesa-3D
/**
 * 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 gl_renderbuffer *rb = att->Renderbuffer;
   struct st_renderbuffer *strb = st_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);

   /* 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;

   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.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;
}