示例#1
0
static bool compare_textures(struct pipe_context *ctx,
			     struct pipe_resource *tex,
			     struct cpu_texture *cpu, int bpp)
{
	struct pipe_transfer *t;
	uint8_t *map;
	int y,z;
	bool pass = true;

	map = pipe_transfer_map_3d(ctx, tex, 0, PIPE_TRANSFER_READ,
				   0, 0, 0, tex->width0, tex->height0,
				   tex->array_size, &t);
	assert(map);

	for (z = 0; z < tex->array_size; z++) {
		for (y = 0; y < tex->height0; y++) {
			uint8_t *ptr = map + t->layer_stride*z + t->stride*y;
			uint8_t *cpu_ptr = cpu->ptr +
					   cpu->layer_stride*z + cpu->stride*y;

			if (memcmp(ptr, cpu_ptr, tex->width0 * bpp)) {
				pass = false;
				goto done;
			}
		}
	}
done:
	pipe_transfer_unmap(ctx, t);
	return pass;
}
示例#2
0
static void set_random_pixels(struct pipe_context *ctx,
			      struct pipe_resource *tex,
			      struct cpu_texture *cpu)
{
	struct pipe_transfer *t;
	uint8_t *map;
	int x,y,z;

	map = pipe_transfer_map_3d(ctx, tex, 0, PIPE_TRANSFER_WRITE,
				   0, 0, 0, tex->width0, tex->height0,
				   tex->array_size, &t);
	assert(map);

	for (z = 0; z < tex->array_size; z++) {
		for (y = 0; y < tex->height0; y++) {
			uint64_t *ptr = (uint64_t*)
				(map + t->layer_stride*z + t->stride*y);
			uint64_t *ptr_cpu = (uint64_t*)
				(cpu->ptr + cpu->layer_stride*z + cpu->stride*y);
			unsigned size = cpu->stride / RAND_NUM_SIZE;

			assert(t->stride % RAND_NUM_SIZE == 0);
			assert(cpu->stride % RAND_NUM_SIZE == 0);

			for (x = 0; x < size; x++) {
				*ptr++ = *ptr_cpu++ =
					rand_xorshift128plus(seed_xorshift128plus);
			}
		}
	}

	pipe_transfer_unmap(ctx, t);
}
示例#3
0
文件: st_texture.c 项目: ndesh26/Mesa
/**
 * Map a texture image and return the address for a particular 2D face/slice/
 * layer.  The stImage indicates the cube face and mipmap level.  The slice
 * of the 3D texture is passed in 'zoffset'.
 * \param usage  one of the PIPE_TRANSFER_x values
 * \param x, y, w, h  the region of interest of the 2D image.
 * \return address of mapping or NULL if any error
 */
GLubyte *
st_texture_image_map(struct st_context *st, struct st_texture_image *stImage,
                     enum pipe_transfer_usage usage,
                     GLuint x, GLuint y, GLuint z,
                     GLuint w, GLuint h, GLuint d,
                     struct pipe_transfer **transfer)
{
   struct st_texture_object *stObj =
      st_texture_object(stImage->base.TexObject);
   GLuint level;
   void *map;

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

   if (!stImage->pt)
      return NULL;

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

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

   z += stImage->base.Face;

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

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

      assert(!stImage->transfer[z].transfer);
      stImage->transfer[z].transfer = *transfer;
   }
   return map;
}
示例#4
0
/**
 * Map a texture image and return the address for a particular 2D face/slice/
 * layer.  The stImage indicates the cube face and mipmap level.  The slice
 * of the 3D texture is passed in 'zoffset'.
 * \param usage  one of the PIPE_TRANSFER_x values
 * \param x, y, w, h  the region of interest of the 2D image.
 * \return address of mapping or NULL if any error
 */
GLubyte *
st_texture_image_map(struct st_context *st, struct st_texture_image *stImage,
                     enum pipe_transfer_usage usage,
                     GLuint x, GLuint y, GLuint z,
                     GLuint w, GLuint h, GLuint d)
{
   struct st_texture_object *stObj =
      st_texture_object(stImage->base.TexObject);
   GLuint level;

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

   if (!stImage->pt)
      return NULL;

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

   return pipe_transfer_map_3d(st->pipe, stImage->pt, level, usage,
                               x, y, z + stImage->base.Face,
                               w, h, d, &stImage->transfer);
}
示例#5
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);
}
示例#6
0
/**
 * Fallback for pipe->clear_stencil() function.
 * sw fallback doesn't look terribly useful here.
 * Plus can't use these transfer fallbacks when clearing
 * multisampled surfaces for instance.
 * Clears all bound layers.
 */
void
util_clear_depth_stencil(struct pipe_context *pipe,
                         struct pipe_surface *dst,
                         unsigned clear_flags,
                         double depth,
                         unsigned stencil,
                         unsigned dstx, unsigned dsty,
                         unsigned width, unsigned height)
{
   enum pipe_format format = dst->format;
   struct pipe_transfer *dst_trans;
   ubyte *dst_map;
   boolean need_rmw = FALSE;
   unsigned max_layer, layer;

   if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) &&
       ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) &&
       util_format_is_depth_and_stencil(format))
      need_rmw = TRUE;

   assert(dst->texture);
   if (!dst->texture)
      return;

   max_layer = dst->u.tex.last_layer - dst->u.tex.first_layer;
   dst_map = pipe_transfer_map_3d(pipe,
                                  dst->texture,
                                  dst->u.tex.level,
                                  (need_rmw ? PIPE_TRANSFER_READ_WRITE :
                                              PIPE_TRANSFER_WRITE),
                                  dstx, dsty, dst->u.tex.first_layer,
                                  width, height, max_layer + 1, &dst_trans);
   assert(dst_map);

   if (dst_map) {
      unsigned dst_stride = dst_trans->stride;
      uint64_t zstencil = util_pack64_z_stencil(format, depth, stencil);
      ubyte *dst_layer = dst_map;
      unsigned i, j;
      assert(dst_trans->stride > 0);

      for (layer = 0; layer <= max_layer; layer++) {
         dst_map = dst_layer;

         switch (util_format_get_blocksize(format)) {
         case 1:
            assert(format == PIPE_FORMAT_S8_UINT);
            if(dst_stride == width)
               memset(dst_map, (uint8_t) zstencil, height * width);
            else {
               for (i = 0; i < height; i++) {
                  memset(dst_map, (uint8_t) zstencil, width);
                  dst_map += dst_stride;
               }
            }
            break;
         case 2:
            assert(format == PIPE_FORMAT_Z16_UNORM);
            for (i = 0; i < height; i++) {
               uint16_t *row = (uint16_t *)dst_map;
               for (j = 0; j < width; j++)
                  *row++ = (uint16_t) zstencil;
               dst_map += dst_stride;
               }
            break;
         case 4:
            if (!need_rmw) {
               for (i = 0; i < height; i++) {
                  uint32_t *row = (uint32_t *)dst_map;
                  for (j = 0; j < width; j++)
                     *row++ = (uint32_t) zstencil;
                  dst_map += dst_stride;
               }
            }
            else {
               uint32_t dst_mask;
               if (format == PIPE_FORMAT_Z24_UNORM_S8_UINT)
                  dst_mask = 0x00ffffff;
               else {
                  assert(format == PIPE_FORMAT_S8_UINT_Z24_UNORM);
                  dst_mask = 0xffffff00;
               }
               if (clear_flags & PIPE_CLEAR_DEPTH)
                  dst_mask = ~dst_mask;
               for (i = 0; i < height; i++) {
                  uint32_t *row = (uint32_t *)dst_map;
                  for (j = 0; j < width; j++) {
                     uint32_t tmp = *row & dst_mask;
                     *row++ = tmp | ((uint32_t) zstencil & ~dst_mask);
                  }
                  dst_map += dst_stride;
               }
            }
            break;
         case 8:
            if (!need_rmw) {
               for (i = 0; i < height; i++) {
                  uint64_t *row = (uint64_t *)dst_map;
                  for (j = 0; j < width; j++)
                     *row++ = zstencil;
                  dst_map += dst_stride;
               }
            }
            else {
               uint64_t src_mask;

               if (clear_flags & PIPE_CLEAR_DEPTH)
                  src_mask = 0x00000000ffffffffull;
               else
                  src_mask = 0x000000ff00000000ull;

               for (i = 0; i < height; i++) {
                  uint64_t *row = (uint64_t *)dst_map;
                  for (j = 0; j < width; j++) {
                     uint64_t tmp = *row & ~src_mask;
                     *row++ = tmp | (zstencil & src_mask);
                  }
                  dst_map += dst_stride;
               }
            }
            break;
         default:
            assert(0);
            break;
         }
         dst_layer += dst_trans->layer_stride;
      }

      pipe->transfer_unmap(pipe, dst_trans);
   }
}
示例#7
0
/**
 * Fallback for pipe->clear_render_target() function.
 * XXX this looks too hackish to be really useful.
 * cpp > 4 looks like a gross hack at best...
 * Plus can't use these transfer fallbacks when clearing
 * multisampled surfaces for instance.
 * Clears all bound layers.
 */
void
util_clear_render_target(struct pipe_context *pipe,
                         struct pipe_surface *dst,
                         const union pipe_color_union *color,
                         unsigned dstx, unsigned dsty,
                         unsigned width, unsigned height)
{
   struct pipe_transfer *dst_trans;
   ubyte *dst_map;
   union util_color uc;
   unsigned max_layer;

   assert(dst->texture);
   if (!dst->texture)
      return;

   if (dst->texture->target == PIPE_BUFFER) {
      /*
       * The fill naturally works on the surface format, however
       * the transfer uses resource format which is just bytes for buffers.
       */
      unsigned dx, w;
      unsigned pixstride = util_format_get_blocksize(dst->format);
      dx = (dst->u.buf.first_element + dstx) * pixstride;
      w = width * pixstride;
      max_layer = 0;
      dst_map = pipe_transfer_map(pipe,
                                  dst->texture,
                                  0, 0,
                                  PIPE_TRANSFER_WRITE,
                                  dx, 0, w, 1,
                                  &dst_trans);
   }
   else {
      max_layer = dst->u.tex.last_layer - dst->u.tex.first_layer;
      dst_map = pipe_transfer_map_3d(pipe,
                                     dst->texture,
                                     dst->u.tex.level,
                                     PIPE_TRANSFER_WRITE,
                                     dstx, dsty, dst->u.tex.first_layer,
                                     width, height, max_layer + 1, &dst_trans);
   }

   assert(dst_map);

   if (dst_map) {
      enum pipe_format format = dst->format;
      assert(dst_trans->stride > 0);

      if (util_format_is_pure_integer(format)) {
         /*
          * We expect int/uint clear values here, though some APIs
          * might disagree (but in any case util_pack_color()
          * couldn't handle it)...
          */
         if (util_format_is_pure_sint(format)) {
            util_format_write_4i(format, color->i, 0, &uc, 0, 0, 0, 1, 1);
         }
         else {
            assert(util_format_is_pure_uint(format));
            util_format_write_4ui(format, color->ui, 0, &uc, 0, 0, 0, 1, 1);
         }
      }
      else {
         util_pack_color(color->f, format, &uc);
      }

      util_fill_box(dst_map, dst->format,
                    dst_trans->stride, dst_trans->layer_stride,
                    0, 0, 0, width, height, max_layer + 1, &uc);

      pipe->transfer_unmap(pipe, dst_trans);
   }
}