示例#1
0
/**
 * Specify the surface to cache.
 */
void
sp_tile_cache_set_surface(struct softpipe_tile_cache *tc,
                          struct pipe_surface *ps)
{
    struct pipe_context *pipe = tc->pipe;

    if (tc->transfer) {
        if (ps == tc->surface)
            return;

        if (tc->transfer_map) {
            pipe->transfer_unmap(pipe, tc->transfer);
            tc->transfer_map = NULL;
        }

        pipe->transfer_destroy(pipe, tc->transfer);
        tc->transfer = NULL;
    }

    tc->surface = ps;

    if (ps) {
        tc->transfer = pipe_get_transfer(pipe, ps->texture,
                                         ps->u.tex.level, ps->u.tex.first_layer,
                                         PIPE_TRANSFER_READ_WRITE |
                                         PIPE_TRANSFER_UNSYNCHRONIZED,
                                         0, 0, ps->width, ps->height);

        tc->depth_stencil = util_format_is_depth_or_stencil(ps->format);
    }
}
示例#2
0
static Bool
ExaUploadToScreen(PixmapPtr pPix, int x, int y, int w, int h, char *src,
		  int src_pitch)
{
    ScreenPtr pScreen = pPix->drawable.pScreen;
    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
    modesettingPtr ms = modesettingPTR(pScrn);
    struct exa_context *exa = ms->exa;
    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix);
    struct pipe_transfer *transfer;

    if (!priv || !priv->tex)
	return FALSE;

    transfer = pipe_get_transfer(exa->pipe, priv->tex, 0, 0,
                                 PIPE_TRANSFER_WRITE, x, y, w, h);
    if (!transfer)
	return FALSE;

    exa_debug_printf("++++++ ExaUploadToScreen(%d, %d, %d, %d, %d)\n",
                 x, y, w, h, src_pitch);

    util_copy_rect(exa->pipe->transfer_map(exa->pipe, transfer),
		   priv->tex->format, transfer->stride, 0, 0, w, h,
		   (unsigned char*)src, src_pitch, 0, 0);

    exa->pipe->transfer_unmap(exa->pipe, transfer);
    exa->pipe->transfer_destroy(exa->pipe, transfer);

    return TRUE;
}
示例#3
0
文件: xa_context.c 项目: nikai3d/mesa
void *
xa_surface_map(struct xa_context *ctx,
	       struct xa_surface *srf, unsigned int usage)
{
    void *map;
    unsigned int transfer_direction = 0;
    struct pipe_context *pipe = ctx->pipe;

    if (srf->transfer)
	return NULL;

    if (usage & XA_MAP_READ)
	transfer_direction = PIPE_TRANSFER_READ;
    if (usage & XA_MAP_WRITE)
	transfer_direction = PIPE_TRANSFER_WRITE;

    if (!transfer_direction)
	return NULL;

    srf->transfer = pipe_get_transfer(pipe, srf->tex, 0, 0,
				      transfer_direction, 0, 0,
				      srf->tex->width0, srf->tex->height0);
    if (!srf->transfer)
	return NULL;

    map = pipe_transfer_map(pipe, srf->transfer);
    if (!map)
	pipe->transfer_destroy(pipe, srf->transfer);

    srf->mapping_pipe = pipe;
    return map;
}
示例#4
0
/* Upload data for a particular image.
 */
void
st_texture_image_data(struct st_context *st,
                      struct pipe_resource *dst,
                      GLuint face,
                      GLuint level,
                      void *src,
                      GLuint src_row_stride, GLuint src_image_stride)
{
   struct pipe_context *pipe = st->pipe;
   GLuint depth = u_minify(dst->depth0, level);
   GLuint i;
   const GLubyte *srcUB = src;
   struct pipe_transfer *dst_transfer;

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

   for (i = 0; i < depth; i++) {
      dst_transfer = pipe_get_transfer(st->pipe, dst, face, level, i,
						  PIPE_TRANSFER_WRITE, 0, 0,
						  u_minify(dst->width0, level),
                                                  u_minify(dst->height0, level));

      st_surface_data(pipe, dst_transfer,
		      0, 0,                             /* dstx, dsty */
		      srcUB,
		      src_row_stride,
		      0, 0,                             /* source x, y */
		      u_minify(dst->width0, level),
                      u_minify(dst->height0, level));      /* width, height */

      pipe->transfer_destroy(pipe, dst_transfer);

      srcUB += src_image_stride;
   }
}
示例#5
0
static INLINE struct pipe_resource *create_texture_1d(struct vg_context *ctx,
                                                     const VGuint *color_data,
                                                     const VGint color_data_len)
{
   struct pipe_context *pipe = ctx->pipe;
   struct pipe_screen *screen = pipe->screen;
   struct pipe_resource *tex = 0;
   struct pipe_resource templ;

   memset(&templ, 0, sizeof(templ));
   templ.target = PIPE_TEXTURE_1D;
   templ.format = PIPE_FORMAT_B8G8R8A8_UNORM;
   templ.last_level = 0;
   templ.width0 = color_data_len;
   templ.height0 = 1;
   templ.depth0 = 1;
   templ.array_size = 1;
   templ.bind = PIPE_BIND_SAMPLER_VIEW;

   tex = screen->resource_create(screen, &templ);

   { /* upload color_data */
      struct pipe_transfer *transfer =
         pipe_get_transfer(pipe, tex,
                           0, 0,
                           PIPE_TRANSFER_READ_WRITE ,
                           0, 0, tex->width0, tex->height0);
      void *map = pipe->transfer_map(pipe, transfer);
      memcpy(map, color_data, sizeof(VGint)*color_data_len);
      pipe->transfer_unmap(pipe, transfer);
      pipe->transfer_destroy(pipe, transfer);
   }

   return tex;
}
示例#6
0
void image_sub_data(struct vg_image *image,
                    const void * data,
                    VGint dataStride,
                    VGImageFormat dataFormat,
                    VGint x, VGint y,
                    VGint width, VGint height)
{
   const VGint yStep = 1;
   VGubyte *src = (VGubyte *)data;
   VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4];
   VGfloat *df = (VGfloat*)temp;
   VGint i;
   struct vg_context *ctx = vg_current_context();
   struct pipe_context *pipe = ctx->pipe;
   struct pipe_resource *texture = image_texture(image);
   VGint xoffset = 0, yoffset = 0;

   if (x < 0) {
      xoffset -= x;
      width += x;
      x = 0;
   }
   if (y < 0) {
      yoffset -= y;
      height += y;
      y = 0;
   }

   if (width <= 0 || height <= 0) {
      vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
      return;
   }

   if (x > image->width || y > image->width) {
      vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
      return;
   }

   if (x + width > image->width) {
      width = image->width - x;
   }

   if (y + height > image->height) {
      height = image->height - y;
   }

   { /* upload color_data */
      struct pipe_transfer *transfer = pipe_get_transfer(
         pipe, texture, 0, 0,
         PIPE_TRANSFER_WRITE, 0, 0, texture->width0, texture->height0);
      src += (dataStride * yoffset);
      for (i = 0; i < height; i++) {
         _vega_unpack_float_span_rgba(ctx, width, xoffset, src, dataFormat, temp);
         pipe_put_tile_rgba(pipe, transfer, x+image->x, y+image->y, width, 1, df);
         y += yStep;
         src += dataStride;
      }
      pipe->transfer_destroy(pipe, transfer);
   }
}
示例#7
0
static cairo_status_t
gallium_surface_acquire_source_image (void *abstract_surface,
                                      cairo_image_surface_t **image_out,
                                      void **image_extra)
{
    gallium_surface_t *surface = abstract_surface;
    gallium_device_t *device = gallium_device (surface);
    cairo_format_t format;
    cairo_surface_t *image;
    cairo_status_t status;
    struct pipe_transfer *transfer;
    void *ptr;

    if (surface->fallback != NULL) {
        *image_out = (cairo_image_surface_t *)
                     cairo_surface_reference (surface->fallback);
        *image_extra = NULL;
        return CAIRO_STATUS_SUCCESS;
    }

    if (unlikely (surface->drm.width == 0 || surface->drm.height == 0)) {
        image = cairo_image_surface_create (surface->drm.format, 0, 0);
        if (unlikely (image->status))
            return image->status;

        *image_out = (cairo_image_surface_t *) image;
        *image_extra = NULL;
        return CAIRO_STATUS_SUCCESS;
    }

    format = _cairo_format_from_pipe_format (surface->pipe_format);
    if (format == CAIRO_FORMAT_INVALID)
        return CAIRO_INT_STATUS_UNSUPPORTED;

    status = cairo_device_acquire (&device->drm.base);
    if (unlikely (status))
        return status;

    transfer = pipe_get_transfer (device->pipe,
                                  surface->texture, 0, 0, 0,
                                  PIPE_TRANSFER_READ,
                                  0, 0,
                                  surface->drm.width,
                                  surface->drm.height);
    ptr = device->pipe->transfer_map (device->pipe, transfer);
    cairo_device_release (&device->drm.base);

    image = cairo_image_surface_create_for_data (ptr, format,
            surface->drm.width,
            surface->drm.height,
            surface->drm.stride);
    if (unlikely (image->status))
        return image->status;

    *image_out = (cairo_image_surface_t *) image;
    *image_extra = transfer;
    return CAIRO_STATUS_SUCCESS;
}
示例#8
0
static Bool
ExaPrepareAccess(PixmapPtr pPix, int index)
{
    ScreenPtr pScreen = pPix->drawable.pScreen;
    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
    modesettingPtr ms = modesettingPTR(pScrn);
    struct exa_context *exa = ms->exa;
    struct exa_pixmap_priv *priv;

    priv = exaGetPixmapDriverPrivate(pPix);

    if (!priv)
	return FALSE;

    if (!priv->tex)
	return FALSE;

    exa_debug_printf("ExaPrepareAccess %d\n", index);

    if (priv->map_count == 0)
    {
        assert(pPix->drawable.width <= priv->tex->width0);
        assert(pPix->drawable.height <= priv->tex->height0);

	priv->map_transfer =
	   pipe_get_transfer(exa->pipe, priv->tex, 0, 0,
#ifdef EXA_MIXED_PIXMAPS
					PIPE_TRANSFER_MAP_DIRECTLY |
#endif
					PIPE_TRANSFER_READ_WRITE,
					0, 0, 
                                        pPix->drawable.width,
                                        pPix->drawable.height );
	if (!priv->map_transfer)
#ifdef EXA_MIXED_PIXMAPS
	    return FALSE;
#else
	    FatalError("failed to create transfer\n");
#endif

	pPix->devPrivate.ptr =
	    exa->pipe->transfer_map(exa->pipe, priv->map_transfer);
	pPix->devKind = priv->map_transfer->stride;
    }

    priv->map_count++;

    exa_debug_printf("ExaPrepareAccess %d prepared\n", index);

    return TRUE;
}
示例#9
0
文件: xa_context.c 项目: nikai3d/mesa
int
xa_surface_dma(struct xa_context *ctx,
	       struct xa_surface *srf,
	       void *data,
	       unsigned int pitch,
	       int to_surface, struct xa_box *boxes, unsigned int num_boxes)
{
    struct pipe_transfer *transfer;
    void *map;
    int w, h, i;
    enum pipe_transfer_usage transfer_direction;
    struct pipe_context *pipe = ctx->pipe;

    transfer_direction = (to_surface ? PIPE_TRANSFER_WRITE :
			  PIPE_TRANSFER_READ);

    for (i = 0; i < num_boxes; ++i, ++boxes) {
	w = boxes->x2 - boxes->x1;
	h = boxes->y2 - boxes->y1;

	transfer = pipe_get_transfer(pipe, srf->tex, 0, 0,
				     transfer_direction, boxes->x1, boxes->y1,
				     w, h);
	if (!transfer)
	    return -XA_ERR_NORES;

	map = pipe_transfer_map(ctx->pipe, transfer);
	if (!map)
	    goto out_no_map;

	if (to_surface) {
	    util_copy_rect(map, srf->tex->format, transfer->stride,
			   0, 0, w, h, data, pitch, boxes->x1, boxes->y1);
	} else {
	    util_copy_rect(data, srf->tex->format, pitch,
			   boxes->x1, boxes->y1, w, h, map, transfer->stride, 0,
			   0);
	}
	pipe->transfer_unmap(pipe, transfer);
	pipe->transfer_destroy(pipe, transfer);
	if (to_surface)
	    pipe->flush(pipe, &ctx->last_fence);
    }
    return XA_ERR_NONE;
 out_no_map:
    pipe->transfer_destroy(pipe, transfer);
    return -XA_ERR_NORES;
}
示例#10
0
static void
crtc_load_cursor_argb_ga3d(xf86CrtcPtr crtc, CARD32 * image)
{
    unsigned char *ptr;
    modesettingPtr ms = modesettingPTR(crtc->scrn);
    struct crtc_private *crtcp = crtc->driver_private;
    struct pipe_transfer *transfer;

    if (!crtcp->cursor_tex) {
	struct pipe_resource templat;
	struct winsys_handle whandle;

	memset(&templat, 0, sizeof(templat));
	templat.bind |= PIPE_BIND_RENDER_TARGET;
	templat.bind |= PIPE_BIND_SCANOUT;
	templat.target = PIPE_TEXTURE_2D;
	templat.last_level = 0;
	templat.depth0 = 1;
	templat.array_size = 1;
	templat.format = PIPE_FORMAT_B8G8R8A8_UNORM;
	templat.width0 = 64;
	templat.height0 = 64;

	memset(&whandle, 0, sizeof(whandle));
	whandle.type = DRM_API_HANDLE_TYPE_KMS;

	crtcp->cursor_tex = ms->screen->resource_create(ms->screen,
						       &templat);
	ms->screen->resource_get_handle(ms->screen, crtcp->cursor_tex, &whandle);

	crtcp->cursor_handle = whandle.handle;
    }

    transfer = pipe_get_transfer(ms->ctx, crtcp->cursor_tex,
                                 0, 0,
                                 PIPE_TRANSFER_WRITE,
                                 0, 0, 64, 64);
    ptr = ms->ctx->transfer_map(ms->ctx, transfer);
    util_copy_rect(ptr, crtcp->cursor_tex->format,
		   transfer->stride, 0, 0,
		   64, 64, (void*)image, 64 * 4, 0, 0);
    ms->ctx->transfer_unmap(ms->ctx, transfer);
    ms->ctx->transfer_destroy(ms->ctx, transfer);

    if (crtc->cursor_shown)
	drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id,
			 crtcp->cursor_handle, 64, 64);
}
示例#11
0
文件: u_debug.c 项目: mslusarz/mesa
void
debug_dump_surface_bmp(struct pipe_context *pipe,
                       const char *filename,
                       struct pipe_surface *surface)
{
   struct pipe_transfer *transfer;
   struct pipe_resource *texture = surface->texture;

   transfer = pipe_get_transfer(pipe, texture, surface->u.tex.level,
                                surface->u.tex.first_layer, PIPE_TRANSFER_READ,
                                0, 0, surface->width, surface->height);

   debug_dump_transfer_bmp(pipe, filename, transfer);

   pipe->transfer_destroy(pipe, transfer);
}
示例#12
0
文件: st_cb_bitmap.c 项目: iquiw/xsrc
/**
 * Create a texture which represents a bitmap image.
 */
static struct pipe_resource *
make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height,
                    const struct gl_pixelstore_attrib *unpack,
                    const GLubyte *bitmap)
{
   struct st_context *st = st_context(ctx);
   struct pipe_context *pipe = st->pipe;
   struct pipe_transfer *transfer;
   ubyte *dest;
   struct pipe_resource *pt;

   /* PBO source... */
   bitmap = _mesa_map_pbo_source(ctx, unpack, bitmap);
   if (!bitmap) {
      return NULL;
   }

   /**
    * Create texture to hold bitmap pattern.
    */
   pt = st_texture_create(st, st->internal_target, st->bitmap.tex_format,
                          0, width, height, 1, 1,
                          PIPE_BIND_SAMPLER_VIEW);
   if (!pt) {
      _mesa_unmap_pbo_source(ctx, unpack);
      return NULL;
   }

   transfer = pipe_get_transfer(st->pipe, pt, 0, 0,
                                PIPE_TRANSFER_WRITE,
                                0, 0, width, height);

   dest = pipe_transfer_map(pipe, transfer);

   /* Put image into texture transfer */
   memset(dest, 0xff, height * transfer->stride);
   unpack_bitmap(st, 0, 0, width, height, unpack, bitmap,
                 dest, transfer->stride);

   _mesa_unmap_pbo_source(ctx, unpack);

   /* Release transfer */
   pipe_transfer_unmap(pipe, transfer);
   pipe->transfer_destroy(pipe, transfer);

   return pt;
}
示例#13
0
static void
accum_load(struct st_context *st, GLfloat value,
           GLint xpos, GLint ypos, GLint width, GLint height,
           struct st_renderbuffer *acc_strb,
           struct st_renderbuffer *color_strb)
{
   struct pipe_context *pipe = st->pipe;
   struct pipe_transfer *color_trans;
   size_t stride = acc_strb->stride;
   GLubyte *data = acc_strb->data;
   GLfloat *buf;


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

   color_trans = pipe_get_transfer(st->pipe, color_strb->texture,
						0, 0, 0,
						PIPE_TRANSFER_READ, xpos, ypos,
						width, height);

   buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));

   pipe_get_tile_rgba(pipe, color_trans, 0, 0, width, height, buf);

   switch (acc_strb->format) {
   case PIPE_FORMAT_R16G16B16A16_SNORM:
      {
         const GLfloat *color = buf;
         int i, j;
         for (i = 0; i < height; i++) {
            GLshort *acc = (GLshort *) (data + (ypos + i) * stride + xpos * 8);
            for (j = 0; j < width * 4; j++) {
               float val = *color++ * value;
               *acc++ = FLOAT_TO_SHORT(val);
            }
         }
      }
      break;
   default:
      _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()");
   }

   free(buf);
   pipe->transfer_destroy(pipe, color_trans);
}
static int pipe_map(struct gralloc_drm_drv_t *drv,
		struct gralloc_drm_bo_t *bo, int x, int y, int w, int h,
		int enable_write, void **addr)
{
	struct pipe_manager *pm = (struct pipe_manager *) drv;
	struct pipe_buffer *buf = (struct pipe_buffer *) bo;
	int err = 0;

	pthread_mutex_lock(&pm->mutex);

	/* need a context to get transfer */
	if (!pm->context) {
		pm->context = pm->screen->context_create(pm->screen, NULL);
		if (!pm->context) {
			LOGE("failed to create pipe context");
			err = -ENOMEM;
		}
	}

	if (!err) {
		enum pipe_transfer_usage usage;

		usage = PIPE_TRANSFER_READ;
		if (enable_write)
			usage |= PIPE_TRANSFER_WRITE;

		assert(!buf->transfer);

		/*
		 * ignore x, y, w and h so that returned addr points at the
		 * start of the buffer
		 */
		buf->transfer = pipe_get_transfer(pm->context, buf->resource,
				0, 0, usage, 0, 0,
				buf->resource->width0, buf->resource->height0);
		if (buf->transfer)
			*addr = pipe_transfer_map(pm->context, buf->transfer);
		else
			err = -ENOMEM;
	}

	pthread_mutex_unlock(&pm->mutex);

	return err;
}
示例#15
0
GalliumSurface::Transfer::Transfer (pipe_context  *context,
				    pipe_resource *texture)
{
	resource = NULL;
	pipe     = context;

	transfer = pipe_get_transfer (pipe,
				      texture,
				      0,
				      0,
				      0,
				      PIPE_TRANSFER_READ_WRITE,
				      0, 0,
				      texture->width0,
				      texture->height0);

	pipe_resource_reference (&resource, texture);
}
示例#16
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,
		     GLuint zoffset, enum pipe_transfer_usage usage,
                     GLuint x, GLuint y, GLuint w, GLuint h)
{
   struct pipe_context *pipe = st->pipe;
   struct pipe_resource *pt = stImage->pt;

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

   stImage->transfer = pipe_get_transfer(st->pipe, pt, stImage->face,
						    stImage->level, zoffset,
						    usage, x, y, w, h);

   if (stImage->transfer)
      return pipe_transfer_map(pipe, stImage->transfer);
   else
      return NULL;
}
static boolean
wsw_dt_get_stride(struct wrapper_sw_displaytarget *wdt, unsigned *stride)
{
   struct pipe_context *pipe = wdt->winsys->pipe;
   struct pipe_resource *tex = wdt->tex;
   struct pipe_transfer *tr;

   tr = pipe_get_transfer(pipe, tex, 0, 0, 0,
			  PIPE_TRANSFER_READ_WRITE,
			  0, 0, wdt->width, wdt->height);
   if (!tr)
      return FALSE;

   *stride = tr->stride;
   wdt->stride = tr->stride;

   pipe->transfer_destroy(pipe, tr);

   return TRUE;
}
示例#18
0
文件: st_cb_bitmap.c 项目: iquiw/xsrc
/**
 * Create gallium pipe_transfer object for the bitmap cache.
 */
static void
create_cache_trans(struct st_context *st)
{
   struct pipe_context *pipe = st->pipe;
   struct bitmap_cache *cache = st->bitmap.cache;

   if (cache->trans)
      return;

   /* Map the texture transfer.
    * Subsequent glBitmap calls will write into the texture image.
    */
   cache->trans = pipe_get_transfer(st->pipe, cache->texture, 0, 0,
                                    PIPE_TRANSFER_WRITE, 0, 0,
                                    BITMAP_CACHE_WIDTH,
                                    BITMAP_CACHE_HEIGHT);
   cache->buffer = pipe_transfer_map(pipe, cache->trans);

   /* init image to all 0xff */
   memset(cache->buffer, 0xff, cache->trans->stride * BITMAP_CACHE_HEIGHT);
}
static void *
wsw_dt_map(struct sw_winsys *ws,
           struct sw_displaytarget *dt,
           unsigned flags)
{
   struct wrapper_sw_displaytarget *wdt = wrapper_sw_displaytarget(dt);
   struct pipe_context *pipe = wdt->winsys->pipe;
   struct pipe_resource *tex = wdt->tex;
   struct pipe_transfer *tr;
   void *ptr;

   if (!wdt->map_count) {

      assert(!wdt->transfer);

      tr = pipe_get_transfer(pipe, tex, 0, 0, 0,
			     PIPE_TRANSFER_READ_WRITE,
			     0, 0, wdt->width, wdt->height);
      if (!tr)
         return NULL;

      ptr = pipe->transfer_map(pipe, tr);
      if (!ptr)
        goto err;

      wdt->transfer = tr;
      wdt->ptr = ptr;

      /* XXX Handle this case */
      assert(tr->stride == wdt->stride);
   }

   wdt->map_count++;

   return wdt->ptr;

err:
   pipe->transfer_destroy(pipe, tr);
   return NULL;
}
示例#20
0
/* FIXME: dump resources, not surfaces... */
void debug_dump_surface(struct pipe_context *pipe,
                        const char *prefix,
                        struct pipe_surface *surface)
{
   struct pipe_resource *texture;
   struct pipe_transfer *transfer;
   void *data;

   if (!surface)
      return;

   /* XXX: this doesn't necessarily work, as the driver may be using
    * temporary storage for the surface which hasn't been propagated
    * back into the texture.  Need to nail down the semantics of views
    * and transfers a bit better before we can say if extra work needs
    * to be done here:
    */
   texture = surface->texture;

   transfer = pipe_get_transfer(pipe, texture, surface->u.tex.level,
                                surface->u.tex.first_layer,
                                PIPE_TRANSFER_READ,
                                0, 0, surface->width, surface->height);

   data = pipe->transfer_map(pipe, transfer);
   if(!data)
      goto error;

   debug_dump_image(prefix,
                    texture->format,
                    util_format_get_blocksize(texture->format),
                    util_format_get_nblocksx(texture->format, surface->width),
                    util_format_get_nblocksy(texture->format, surface->height),
                    transfer->stride,
                    data);

   pipe->transfer_unmap(pipe, transfer);
error:
   pipe->transfer_destroy(pipe, transfer);
}
示例#21
0
static cairo_surface_t *
gallium_surface_map_to_image (gallium_surface_t *surface)
{
    gallium_device_t *device = gallium_device (surface);
    cairo_status_t status;
    void *ptr = NULL;

    status = cairo_device_acquire (&device->drm.base);
    if (unlikely (status))
        return _cairo_surface_create_in_error (status);

    surface->map_transfer =
        pipe_get_transfer (device->pipe,
                           surface->texture, 0, 0, 0,
                           PIPE_TRANSFER_MAP_DIRECTLY |
                           PIPE_TRANSFER_READ_WRITE,
                           0, 0,
                           surface->drm.width,
                           surface->drm.height);
    if (likely (surface->map_transfer != NULL))
        ptr = device->pipe->transfer_map (device->pipe, surface->map_transfer);

    cairo_device_release (&device->drm.base);

    if (unlikely (ptr == NULL)) {
        if (surface->map_transfer != NULL) {
            device->pipe->transfer_destroy (device->pipe,
                                            surface->map_transfer);
            surface->map_transfer = NULL;
        }
        return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
    }

    return cairo_image_surface_create_for_data (ptr,
            surface->drm.format,
            surface->drm.width,
            surface->drm.height,
            surface->map_transfer->stride);
}
示例#22
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.
 */
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;
   void *dst_map;
   union util_color uc;

   assert(dst->texture);
   if (!dst->texture)
      return;
   /* XXX: should handle multiple layers */
   dst_trans = pipe_get_transfer(pipe,
                                 dst->texture,
                                 dst->u.tex.level,
                                 dst->u.tex.first_layer,
                                 PIPE_TRANSFER_WRITE,
                                 dstx, dsty, width, height);

   dst_map = pipe->transfer_map(pipe, dst_trans);

   assert(dst_map);

   if (dst_map) {
      assert(dst_trans->stride > 0);

      util_pack_color(color->f, dst->texture->format, &uc);
      util_fill_rect(dst_map, dst->texture->format,
                     dst_trans->stride,
                     0, 0, width, height, &uc);
   }

   pipe->transfer_unmap(pipe, dst_trans);
   pipe->transfer_destroy(pipe, dst_trans);
}
/**
 * Specify the surface to cache.
 */
void
sp_tile_cache_set_surface(struct softpipe_tile_cache *tc,
                          struct pipe_surface *ps)
{
   struct pipe_context *pipe = tc->pipe;

   if (tc->transfer) {
      if (ps == tc->surface)
         return;

      if (tc->transfer_map) {
         pipe->transfer_unmap(pipe, tc->transfer);
         tc->transfer_map = NULL;
      }

      pipe->transfer_destroy(pipe, tc->transfer);
      tc->transfer = NULL;
   }

   tc->surface = ps;

   if (ps) {
      tc->transfer = pipe_get_transfer(pipe, ps->texture, ps->face,
					   ps->level, ps->zslice,
					   PIPE_TRANSFER_READ_WRITE |
					   PIPE_TRANSFER_UNSYNCHRONIZED,
					   0, 0, ps->width, ps->height);

      tc->depth_stencil = (ps->format == PIPE_FORMAT_Z24_UNORM_S8_USCALED ||
                           ps->format == PIPE_FORMAT_Z24X8_UNORM ||
                           ps->format == PIPE_FORMAT_S8_USCALED_Z24_UNORM ||
                           ps->format == PIPE_FORMAT_X8Z24_UNORM ||
                           ps->format == PIPE_FORMAT_Z16_UNORM ||
                           ps->format == PIPE_FORMAT_Z32_UNORM ||
                           ps->format == PIPE_FORMAT_S8_USCALED);
   }
}
示例#24
0
void image_get_sub_data(struct vg_image * image,
                        void * data,
                        VGint dataStride,
                        VGImageFormat dataFormat,
                        VGint sx, VGint sy,
                        VGint width, VGint height)
{
   struct vg_context *ctx = vg_current_context();
   struct pipe_context *pipe = ctx->pipe;
   VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4];
   VGfloat *df = (VGfloat*)temp;
   VGint y = 0, yStep = 1;
   VGint i;
   VGubyte *dst = (VGubyte *)data;

   {
      struct pipe_transfer *transfer =
         pipe_get_transfer(pipe,
                           image->sampler_view->texture,  0, 0,
                           PIPE_TRANSFER_READ,
                           0, 0,
                           image->x + image->width,
                           image->y + image->height);
      /* Do a row at a time to flip image data vertically */
      for (i = 0; i < height; i++) {
#if 0
         debug_printf("%d-%d  == %d\n", sy, height, y);
#endif
         pipe_get_tile_rgba(pipe, transfer, sx+image->x, y, width, 1, df);
         y += yStep;
         _vega_pack_rgba_span_float(ctx, width, temp, dataFormat, dst);
         dst += dataStride;
      }

      pipe->transfer_destroy(pipe, transfer);
   }
}
示例#25
0
static void init_tex( void )
{ 
   struct pipe_sampler_view sv_template;
   struct pipe_sampler_state sampler_desc;
   struct pipe_resource templat;
   struct pipe_box box;
   ubyte tex2d[SIZE][SIZE][4];
   int s, t;

#if (SIZE != 2)
   for (s = 0; s < SIZE; s++) {
      for (t = 0; t < SIZE; t++) {
         if (0) {
            int x = (s ^ t) & 1;
	    tex2d[t][s][0] = (x) ? 0 : 63;
	    tex2d[t][s][1] = (x) ? 0 : 128;
	    tex2d[t][s][2] = 0;
	    tex2d[t][s][3] = 0xff;
         }
         else {
            int x = ((s ^ t) >> 2) & 1;
	    tex2d[t][s][0] = s*255/(SIZE-1);
	    tex2d[t][s][1] = t*255/(SIZE-1);
	    tex2d[t][s][2] = (x) ? 0 : 128;
	    tex2d[t][s][3] = 0xff;
         }
      }
   }
#else
   tex2d[0][0][0] = 0;
   tex2d[0][0][1] = 255;
   tex2d[0][0][2] = 255;
   tex2d[0][0][3] = 0;

   tex2d[0][1][0] = 0;
   tex2d[0][1][1] = 0;
   tex2d[0][1][2] = 255;
   tex2d[0][1][3] = 255;

   tex2d[1][0][0] = 255;
   tex2d[1][0][1] = 255;
   tex2d[1][0][2] = 0;
   tex2d[1][0][3] = 255;

   tex2d[1][1][0] = 255;
   tex2d[1][1][1] = 0;
   tex2d[1][1][2] = 0;
   tex2d[1][1][3] = 255;
#endif

   templat.target = PIPE_TEXTURE_2D;
   templat.format = PIPE_FORMAT_B8G8R8A8_UNORM;
   templat.width0 = SIZE;
   templat.height0 = SIZE;
   templat.depth0 = 1;
   templat.array_size = 1;
   templat.last_level = 0;
   templat.nr_samples = 1;
   templat.bind = PIPE_BIND_SAMPLER_VIEW;

   
   samptex = screen->resource_create(screen,
                                 &templat);
   if (samptex == NULL)
      exit(4);

   u_box_2d(0,0,SIZE,SIZE, &box);

   ctx->transfer_inline_write(ctx,
                              samptex,
                              0,
                              PIPE_TRANSFER_WRITE,
                              &box,
                              tex2d,
                              sizeof tex2d[0],
                              sizeof tex2d);

   /* Possibly read back & compare against original data:
    */
   if (0)
   {
      struct pipe_transfer *t;
      uint32_t *ptr;
      t = pipe_get_transfer(ctx, samptex,
                            0, 0, /* level, layer */
                            PIPE_TRANSFER_READ,
                            0, 0, SIZE, SIZE); /* x, y, width, height */

      ptr = ctx->transfer_map(ctx, t);

      if (memcmp(ptr, tex2d, sizeof tex2d) != 0) {
         assert(0);
         exit(9);
      }

      ctx->transfer_unmap(ctx, t);

      ctx->transfer_destroy(ctx, t);
   }

   memset(&sv_template, 0, sizeof sv_template);
   sv_template.format = samptex->format;
   sv_template.texture = samptex;
   sv_template.swizzle_r = 0;
   sv_template.swizzle_g = 1;
   sv_template.swizzle_b = 2;
   sv_template.swizzle_a = 3;
   sv = ctx->create_sampler_view(ctx, samptex, &sv_template);
   if (sv == NULL)
      exit(5);

   ctx->set_fragment_sampler_views(ctx, 1, &sv);
   

   memset(&sampler_desc, 0, sizeof sampler_desc);
   sampler_desc.wrap_s = PIPE_TEX_WRAP_REPEAT;
   sampler_desc.wrap_t = PIPE_TEX_WRAP_REPEAT;
   sampler_desc.wrap_r = PIPE_TEX_WRAP_REPEAT;
   sampler_desc.min_img_filter = PIPE_TEX_FILTER_NEAREST;
   sampler_desc.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
   sampler_desc.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
   sampler_desc.compare_mode = PIPE_TEX_COMPARE_NONE;
   sampler_desc.compare_func = 0;
   sampler_desc.normalized_coords = 1;
   sampler_desc.max_anisotropy = 0;
   
   sampler = ctx->create_sampler_state(ctx, &sampler_desc);
   if (sampler == NULL)
      exit(6);

   ctx->bind_fragment_sampler_states(ctx, 1, &sampler);
   
}
示例#26
0
文件: xm_api.c 项目: ideak/mesa
PUBLIC void
XMesaBindTexImage(Display *dpy, XMesaBuffer drawable, int buffer,
                  const int *attrib_list)
{
   struct st_context_iface *st = stapi->get_current(stapi);
   struct st_framebuffer_iface* stfbi = drawable->stfb;
   struct pipe_resource *res;
   int x, y, w, h;
   enum st_attachment_type st_attachment = xmesa_attachment_type(buffer);

   x = 0;
   y = 0;
   w = drawable->width;
   h = drawable->height;

   /* We need to validate our attachments before using them,
    * in case the texture doesn't exist yet. */
   xmesa_st_framebuffer_validate_textures(stfbi, w, h, 1 << st_attachment);
   res = xmesa_get_attachment(stfbi, st_attachment);

   if (res) {
      struct pipe_context* pipe = xmesa_get_context(stfbi);
      enum pipe_format internal_format = res->format;
      struct pipe_transfer *tex_xfer;
      char *map;
      int line, ximage_stride;
      XImage *img;

      internal_format = choose_pixel_format(drawable->xm_visual);

      tex_xfer = pipe_get_transfer(pipe, res,
                                   0, 0,    /* level, layer */
                                   PIPE_TRANSFER_WRITE,
                                   x, y,
                                   w, h);
      if (!tex_xfer)
         return;

      /* Grab the XImage that we want to turn into a texture. */
      img = XGetImage(dpy,
                      drawable->ws.drawable,
                      x, y,
                      w, h,
                      AllPlanes,
                      ZPixmap);

      if (!img) {
         pipe_transfer_destroy(pipe, tex_xfer);
         return;
      }

      map = pipe_transfer_map(pipe, tex_xfer);

      if (!map) {
         pipe_transfer_destroy(pipe, tex_xfer);
         return;
      }

      /* The pipe transfer has a pitch rounded up to the nearest 64 pixels.
         We assume 32 bit pixels. */
      ximage_stride = w * 4;

      for (line = 0; line < h; line++)
         memcpy(&map[line * tex_xfer->stride],
                &img->data[line * ximage_stride],
                ximage_stride);

      pipe_transfer_unmap(pipe, tex_xfer);

      pipe_transfer_destroy(pipe, tex_xfer);

      st->teximage(st,
                   ST_TEXTURE_2D,
                   0,    /* level */
                   internal_format,
                   res,
                   FALSE /* no mipmap */);

   }
}
/**
 * Called via ctx->Driver.MapRenderbuffer.
 */
static void
st_MapRenderbuffer(struct gl_context *ctx,
                   struct gl_renderbuffer *rb,
                   GLuint x, GLuint y, GLuint w, GLuint h,
                   GLbitfield mode,
                   GLubyte **mapOut, GLint *rowStrideOut)
{
   struct st_context *st = st_context(ctx);
   struct st_renderbuffer *strb = st_renderbuffer(rb);
   struct pipe_context *pipe = st->pipe;
   const GLboolean invert = rb->Name == 0;
   unsigned usage;
   GLuint y2;

   if (strb->software) {
      /* software-allocated renderbuffer (probably an accum buffer) */
      if (strb->data) {
         GLint bpp = _mesa_get_format_bytes(strb->Base.Format);
         GLint stride = _mesa_format_row_stride(strb->Base.Format,
                                                strb->Base.Width);
         *mapOut = (GLubyte *) strb->data + y * stride + x * bpp;
         *rowStrideOut = stride;
      }
      else {
         *mapOut = NULL;
         *rowStrideOut = 0;
      }
      return;
   }

   usage = 0x0;
   if (mode & GL_MAP_READ_BIT)
      usage |= PIPE_TRANSFER_READ;
   if (mode & GL_MAP_WRITE_BIT)
      usage |= PIPE_TRANSFER_WRITE;
   if (mode & GL_MAP_INVALIDATE_RANGE_BIT)
      usage |= PIPE_TRANSFER_DISCARD_RANGE;

   /* Note: y=0=bottom of buffer while y2=0=top of buffer.
    * 'invert' will be true for window-system buffers and false for
    * user-allocated renderbuffers and textures.
    */
   if (invert)
      y2 = strb->Base.Height - y - h;
   else
      y2 = y;

   strb->transfer = pipe_get_transfer(pipe,
                                      strb->texture,
                                      strb->rtt_level,
                                      strb->rtt_face + strb->rtt_slice,
                                      usage, x, y2, w, h);
   if (strb->transfer) {
      GLubyte *map = pipe_transfer_map(pipe, strb->transfer);
      if (invert) {
         *rowStrideOut = -strb->transfer->stride;
         map += (h - 1) * strb->transfer->stride;
      }
      else {
         *rowStrideOut = strb->transfer->stride;
      }
      *mapOut = map;
   }
   else {
      *mapOut = NULL;
      *rowStrideOut = 0;
   }
}
/**
 * Similar to sp_get_cached_tile() but for textures.
 * Tiles are read-only and indexed with more params.
 */
const struct softpipe_tex_cached_tile *
sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc, 
                        union tex_tile_address addr )
{
   struct softpipe_tex_cached_tile *tile;
   
   tile = tc->entries + tex_cache_pos( addr );

   if (addr.value != tile->addr.value) {

      /* cache miss.  Most misses are because we've invaldiated the
       * texture cache previously -- most commonly on binding a new
       * texture.  Currently we effectively flush the cache on texture
       * bind.
       */
#if 0
      _debug_printf("miss at %u:  x=%d y=%d z=%d face=%d level=%d\n"
                    "   tile %u:  x=%d y=%d z=%d face=%d level=%d\n",
                    pos, x/TILE_SIZE, y/TILE_SIZE, z, face, level,
                    pos, tile->addr.bits.x, tile->addr.bits.y, tile->z, tile->face, tile->level);
#endif

      /* check if we need to get a new transfer */
      if (!tc->tex_trans ||
          tc->tex_face != addr.bits.face ||
          tc->tex_level != addr.bits.level ||
          tc->tex_z != addr.bits.z) {
         /* get new transfer (view into texture) */

         if (tc->tex_trans) {
            if (tc->tex_trans_map) {
               tc->pipe->transfer_unmap(tc->pipe, tc->tex_trans);
               tc->tex_trans_map = NULL;
            }

            tc->pipe->transfer_destroy(tc->pipe, tc->tex_trans);
            tc->tex_trans = NULL;
         }

         tc->tex_trans = 
            pipe_get_transfer(tc->pipe, tc->texture,
                              addr.bits.level,
                              addr.bits.face + addr.bits.z,
                              PIPE_TRANSFER_READ | PIPE_TRANSFER_UNSYNCHRONIZED,
                              0, 0,
                              u_minify(tc->texture->width0, addr.bits.level),
                              u_minify(tc->texture->height0, addr.bits.level));

         tc->tex_trans_map = tc->pipe->transfer_map(tc->pipe, tc->tex_trans);

         tc->tex_face = addr.bits.face;
         tc->tex_level = addr.bits.level;
         tc->tex_z = addr.bits.z;
      }

      /* get tile from the transfer (view into texture) */
      pipe_get_tile_swizzle(tc->pipe,
			    tc->tex_trans,
                            addr.bits.x * TILE_SIZE, 
                            addr.bits.y * TILE_SIZE,
                            TILE_SIZE,
                            TILE_SIZE,
                            tc->swizzle_r,
                            tc->swizzle_g,
                            tc->swizzle_b,
                            tc->swizzle_a,
                            tc->format,
                            (float *) tile->data.color);
      tile->addr = addr;
   }

   tc->last_tile = tile;
   return tile;
}
示例#29
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;

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

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

   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 = (uint *) 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(pipe, src_trans, 0, srcY, width, 1, data);
            if (scaleOrBias) {
               _mesa_scale_and_bias_depth_uint(ctx, width, data);
            }
            pipe_put_tile_z(pipe, stImage->transfer, 0, row, width, 1, data);
         }
      }
      else {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage()");
      }

      free(data);
   }
   else {
      /* RGBA format */
      GLfloat *tempSrc =
         (GLfloat *) 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(pipe, src_trans, 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");
      }

      if (tempSrc)
         free(tempSrc);
   }

   st_texture_image_unmap(st, stImage);
   pipe->transfer_destroy(pipe, src_trans);
}
示例#30
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);
}