Example #1
0
static void
upload_unmap_internal(struct u_upload_mgr *upload, boolean destroying)
{
   if (!upload->transfer)
      return;

   if (upload->map_flags & PIPE_TRANSFER_FLUSH_EXPLICIT) {
      struct pipe_box *box = &upload->transfer->box;
      unsigned flush_offset = box->x + upload->flushed_size;

      if (upload->offset > flush_offset) {
         pipe_buffer_flush_mapped_range(upload->pipe, upload->transfer,
                                        flush_offset,
                                        upload->offset - flush_offset);
         upload->flushed_size = upload->offset;
      }
   }

   if (destroying || !upload->map_persistent) {
      pipe_transfer_unmap(upload->pipe, upload->transfer);
      upload->transfer = NULL;
      upload->map = NULL;
      upload->flushed_size = 0;
   }
}
Example #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);
}
Example #3
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;
}
Example #4
0
void u_default_buffer_subdata(struct pipe_context *pipe,
                              struct pipe_resource *resource,
                              unsigned usage, unsigned offset,
                              unsigned size, const void *data)
{
   struct pipe_transfer *transfer = NULL;
   struct pipe_box box;
   uint8_t *map = NULL;

   assert(!(usage & PIPE_TRANSFER_READ));

   /* the write flag is implicit by the nature of buffer_subdata */
   usage |= PIPE_TRANSFER_WRITE;

   /* buffer_subdata implicitly discards the rewritten buffer range */
   if (offset == 0 && size == resource->width0) {
      usage |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE;
   } else {
      usage |= PIPE_TRANSFER_DISCARD_RANGE;
   }

   u_box_1d(offset, size, &box);

   map = pipe->transfer_map(pipe, resource, 0, usage, &box, &transfer);
   if (!map)
      return;

   memcpy(map, data, size);
   pipe_transfer_unmap(pipe, transfer);
}
Example #5
0
/** Per-context tear-down */
void
st_destroy_bitmap(struct st_context *st)
{
   struct pipe_context *pipe = st->pipe;
   struct bitmap_cache *cache = st->bitmap.cache;

   if (st->bitmap.vs) {
      cso_delete_vertex_shader(st->cso_context, st->bitmap.vs);
      st->bitmap.vs = NULL;
   }

   if (st->bitmap.vbuf) {
      pipe_resource_reference(&st->bitmap.vbuf, NULL);
      st->bitmap.vbuf = NULL;
   }

   if (cache) {
      if (cache->trans) {
         pipe_transfer_unmap(pipe, cache->trans);
         pipe->transfer_destroy(pipe, cache->trans);
      }
      pipe_resource_reference(&st->bitmap.cache->texture, NULL);
      free(st->bitmap.cache);
      st->bitmap.cache = NULL;
   }
}
Example #6
0
/* One-shot transfer operation with data supplied in a user
 * pointer.  XXX: strides??
 */
void u_default_transfer_inline_write( struct pipe_context *pipe,
                                      struct pipe_resource *resource,
                                      unsigned level,
                                      unsigned usage,
                                      const struct pipe_box *box,
                                      const void *data,
                                      unsigned stride,
                                      unsigned layer_stride)
{
   struct pipe_transfer *transfer = NULL;
   uint8_t *map = NULL;

   assert(!(usage & PIPE_TRANSFER_READ));

   /* the write flag is implicit by the nature of transfer_inline_write */
   usage |= PIPE_TRANSFER_WRITE;

   /* transfer_inline_write implicitly discards the rewritten buffer range */
   if (box->x == 0 && box->width == resource->width0) {
      usage |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE;
   } else {
      usage |= PIPE_TRANSFER_DISCARD_RANGE;
   }

   map = pipe->transfer_map(pipe,
                            resource,
                            level,
                            usage,
                            box, &transfer);
   if (map == NULL)
      return;

   if (resource->target == PIPE_BUFFER) {
      assert(box->height == 1);
      assert(box->depth == 1);

      memcpy(map, data, box->width);
   }
   else {
      const uint8_t *src_data = data;
      unsigned i;

      for (i = 0; i < box->depth; i++) {
         util_copy_rect(map,
                        resource->format,
                        transfer->stride, /* bytes */
                        0, 0,
                        box->width,
                        box->height,
                        src_data,
                        stride,       /* bytes */
                        0, 0);
         map += transfer->layer_stride;
         src_data += layer_stride;
      }
   }

   pipe_transfer_unmap(pipe, transfer);
}
Example #7
0
void
st_texture_image_unmap(struct st_context *st,
                       struct st_texture_image *stImage)
{
   struct pipe_context *pipe = st->pipe;

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

   pipe_transfer_unmap(pipe, stImage->transfer);
   stImage->transfer = NULL;
}
Example #8
0
/**
 * If there's anything in the bitmap cache, draw/flush it now.
 */
void
st_flush_bitmap_cache(struct st_context *st)
{
   if (!st->bitmap.cache->empty) {
      struct bitmap_cache *cache = st->bitmap.cache;

      if (st->ctx->DrawBuffer) {
         struct pipe_context *pipe = st->pipe;
         struct pipe_sampler_view *sv;

         assert(cache->xmin <= cache->xmax);
 
/*         printf("flush size %d x %d  at %d, %d\n",
                cache->xmax - cache->xmin,
                cache->ymax - cache->ymin,
                cache->xpos, cache->ypos);
*/

         /* The texture transfer has been mapped until now.
          * So unmap and release the texture transfer before drawing.
          */
         if (cache->trans) {
            if (0)
               print_cache(cache);
            pipe_transfer_unmap(pipe, cache->trans);
            cache->buffer = NULL;

            pipe->transfer_destroy(pipe, cache->trans);
            cache->trans = NULL;
         }

         sv = st_create_texture_sampler_view(st->pipe, cache->texture);
         if (sv) {
            draw_bitmap_quad(st->ctx,
                             cache->xpos,
                             cache->ypos,
                             cache->zpos,
                             BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
                             sv,
                             cache->color);

            pipe_sampler_view_reference(&sv, NULL);
         }
      }

      /* release/free the texture */
      pipe_resource_reference(&cache->texture, NULL);

      reset_cache(st);
   }
}
Example #9
0
/**
 * Probe and test if the rectangle contains the expected color.
 *
 * If "num_expected_colors" > 1, at least one expected color must match
 * the probed color. "expected" should be an array of 4*num_expected_colors
 * floats.
 */
static bool
util_probe_rect_rgba_multi(struct pipe_context *ctx, struct pipe_resource *tex,
                           unsigned offx, unsigned offy, unsigned w,
                           unsigned h,
                           const float *expected,
                           unsigned num_expected_colors)
{
   struct pipe_transfer *transfer;
   void *map;
   float *pixels = malloc(w * h * 4 * sizeof(float));
   int x,y,e,c;
   bool pass = true;

   map = pipe_transfer_map(ctx, tex, 0, 0, PIPE_TRANSFER_READ,
                           offx, offy, w, h, &transfer);
   pipe_get_tile_rgba(transfer, map, 0, 0, w, h, pixels);
   pipe_transfer_unmap(ctx, transfer);

   for (e = 0; e < num_expected_colors; e++) {
      for (y = 0; y < h; y++) {
         for (x = 0; x < w; x++) {
            float *probe = &pixels[(y*w + x)*4];

            for (c = 0; c < 4; c++) {
               if (fabs(probe[c] - expected[e*4+c]) >= TOLERANCE) {
                  if (e < num_expected_colors-1)
                     goto next_color; /* test the next expected color */

                  printf("Probe color at (%i,%i),  ", offx+x, offy+y);
                  printf("Expected: %.3f, %.3f, %.3f, %.3f,  ",
                         expected[e*4], expected[e*4+1],
                         expected[e*4+2], expected[e*4+3]);
                  printf("Got: %.3f, %.3f, %.3f, %.3f\n",
                         probe[0], probe[1], probe[2], probe[2]);
                  pass = false;
                  goto done;
               }
            }
         }
      }
      break; /* this color was successful */

   next_color:;
   }
done:

   free(pixels);
   return pass;
}
Example #10
0
File: vid_dec.c Project: Sheph/mesa
static void vid_dec_FillOutput(vid_dec_PrivateType *priv, struct pipe_video_buffer *buf,
                               OMX_BUFFERHEADERTYPE* output)
{
   omx_base_PortType *port = priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX];
   OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video;

   struct pipe_sampler_view **views;
   struct pipe_transfer *transfer;
   struct pipe_box box = { };
   uint8_t *src, *dst;

   views = buf->get_sampler_view_planes(buf);

   dst = output->pBuffer;

   box.width = def->nFrameWidth;
   box.height = def->nFrameHeight;
   box.depth = 1;

   src = priv->pipe->transfer_map(priv->pipe, views[0]->texture, 0,
                                  PIPE_TRANSFER_READ, &box, &transfer);
   util_copy_rect(dst, views[0]->texture->format, def->nStride, 0, 0,
                  box.width, box.height, src, transfer->stride, 0, 0);
   pipe_transfer_unmap(priv->pipe, transfer);

   dst = ((uint8_t*)output->pBuffer) + (def->nStride * box.height);

   box.width = def->nFrameWidth / 2;
   box.height = def->nFrameHeight / 2;
 
   src = priv->pipe->transfer_map(priv->pipe, views[1]->texture, 0,
                                  PIPE_TRANSFER_READ, &box, &transfer);
   util_copy_rect(dst, views[1]->texture->format, def->nStride, 0, 0,
                  box.width, box.height, src, transfer->stride, 0, 0);
   pipe_transfer_unmap(priv->pipe, transfer);
}
Example #11
0
void u_upload_unmap( struct u_upload_mgr *upload )
{
   if (upload->transfer) {
      struct pipe_box *box = &upload->transfer->box;
      if (upload->offset > box->x) {

         pipe_buffer_flush_mapped_range(upload->pipe, upload->transfer,
                                        box->x, upload->offset - box->x);
      }
      pipe_transfer_unmap(upload->pipe, upload->transfer);
      pipe_transfer_destroy(upload->pipe, upload->transfer);
      upload->transfer = NULL;
      upload->map = NULL;
   }
}
Example #12
0
HRESULT NINE_WINAPI
NineVolume9_UnlockBox( struct NineVolume9 *This )
{
    DBG("This=%p lock_count=%u\n", This, This->lock_count);
    user_assert(This->lock_count, D3DERR_INVALIDCALL);
    if (This->transfer) {
        This->pipe->transfer_unmap(This->pipe, This->transfer);
        This->transfer = NULL;
    }
    --This->lock_count;

    if (This->data_conversion) {
        struct pipe_transfer *transfer;
        uint8_t *dst = This->data;
        struct pipe_box box;

        u_box_3d(0, 0, 0, This->desc.Width, This->desc.Height, This->desc.Depth,
                 &box);

        if (!dst) {
            dst = This->pipe->transfer_map(This->pipe,
                                           This->resource,
                                           This->level,
                                           PIPE_TRANSFER_WRITE |
                                           PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE,
                                           &box, &transfer);
            if (!dst)
                return D3D_OK;
        }

        (void) util_format_translate_3d(This->info.format,
                                        dst, This->data ? This->stride : transfer->stride,
                                        This->data ? This->layer_stride : transfer->layer_stride,
                                        0, 0, 0,
                                        This->format_conversion,
                                        This->data_conversion,
                                        This->stride_conversion,
                                        This->layer_stride_conversion,
                                        0, 0, 0,
                                        This->desc.Width, This->desc.Height,
                                        This->desc.Height);

        if (!This->data)
            pipe_transfer_unmap(This->pipe, transfer);
    }

    return D3D_OK;
}
Example #13
0
/**
 * Called via ctx->Driver.UnmapRenderbuffer.
 */
static void
st_UnmapRenderbuffer(struct gl_context *ctx,
                     struct gl_renderbuffer *rb)
{
   struct st_context *st = st_context(ctx);
   struct st_renderbuffer *strb = st_renderbuffer(rb);
   struct pipe_context *pipe = st->pipe;

   if (strb->software) {
      /* software-allocated renderbuffer (probably an accum buffer) */
      return;
   }

   pipe_transfer_unmap(pipe, strb->transfer);
   strb->transfer = NULL;
}
Example #14
0
/**
 * 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;
}
static void pipe_unmap(struct gralloc_drm_drv_t *drv,
		struct gralloc_drm_bo_t *bo)
{
	struct pipe_manager *pm = (struct pipe_manager *) drv;
	struct pipe_buffer *buf = (struct pipe_buffer *) bo;

	pthread_mutex_lock(&pm->mutex);

	assert(buf && buf->transfer);

	pipe_transfer_unmap(pm->context, buf->transfer);
	pipe_transfer_destroy(pm->context, buf->transfer);
	buf->transfer = NULL;

	pm->context->flush(pm->context, NULL);

	pthread_mutex_unlock(&pm->mutex);
}
Example #16
0
void
st_texture_image_unmap(struct st_context *st,
                       struct st_texture_image *stImage, unsigned slice)
{
   struct pipe_context *pipe = st->pipe;
   struct st_texture_object *stObj =
      st_texture_object(stImage->base.TexObject);
   struct pipe_transfer **transfer;

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

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

   pipe_transfer_unmap(pipe, *transfer);
   *transfer = NULL;
}
Example #17
0
void u_default_texture_subdata(struct pipe_context *pipe,
                               struct pipe_resource *resource,
                               unsigned level,
                               unsigned usage,
                               const struct pipe_box *box,
                               const void *data,
                               unsigned stride,
                               unsigned layer_stride)
{
   struct pipe_transfer *transfer = NULL;
   const uint8_t *src_data = data;
   uint8_t *map = NULL;

   assert(!(usage & PIPE_TRANSFER_READ));

   /* the write flag is implicit by the nature of texture_subdata */
   usage |= PIPE_TRANSFER_WRITE;

   /* texture_subdata implicitly discards the rewritten buffer range */
   usage |= PIPE_TRANSFER_DISCARD_RANGE;

   map = pipe->transfer_map(pipe,
                            resource,
                            level,
                            usage,
                            box, &transfer);
   if (!map)
      return;

   util_copy_box(map,
                 resource->format,
                 transfer->stride, /* bytes */
                 transfer->layer_stride, /* bytes */
                 0, 0, 0,
                 box->width,
                 box->height,
                 box->depth,
                 src_data,
                 stride,       /* bytes */
                 layer_stride, /* bytes */
                 0, 0, 0);

   pipe_transfer_unmap(pipe, transfer);
}
Example #18
0
static void
upload_unmap_internal(struct u_upload_mgr *upload, boolean destroying)
{
   if (!destroying && upload->map_persistent)
      return;

   if (upload->transfer) {
      struct pipe_box *box = &upload->transfer->box;

      if (!upload->map_persistent && (int) upload->offset > box->x) {
         pipe_buffer_flush_mapped_range(upload->pipe, upload->transfer,
                                        box->x, upload->offset - box->x);
      }

      pipe_transfer_unmap(upload->pipe, upload->transfer);
      upload->transfer = NULL;
      upload->map = NULL;
   }
}
Example #19
0
/**
 * Upload data to a rectangular sub-region.  Lots of choices how to do this:
 *
 * - memcpy by span to current destination
 * - upload data as new buffer and blit
 *
 * Currently always memcpy.
 */
static void
st_surface_data(struct pipe_context *pipe,
		struct pipe_transfer *dst,
		unsigned dstx, unsigned dsty,
		const void *src, unsigned src_stride,
		unsigned srcx, unsigned srcy, unsigned width, unsigned height)
{
   void *map = pipe_transfer_map(pipe, dst);

   assert(dst->resource);
   util_copy_rect(map,
                  dst->resource->format,
                  dst->stride,
                  dstx, dsty, 
                  width, height, 
                  src, src_stride, 
                  srcx, srcy);

   pipe_transfer_unmap(pipe, dst);
}
Example #20
0
/**
 * Update the pixelmap texture with the contents of the R/G/B/A pixel maps.
 */
static void
load_color_map_texture(struct gl_context *ctx, struct pipe_resource *pt)
{
   struct st_context *st = st_context(ctx);
   struct pipe_context *pipe = st->pipe;
   struct pipe_transfer *transfer;
   const GLuint rSize = ctx->PixelMaps.RtoR.Size;
   const GLuint gSize = ctx->PixelMaps.GtoG.Size;
   const GLuint bSize = ctx->PixelMaps.BtoB.Size;
   const GLuint aSize = ctx->PixelMaps.AtoA.Size;
   const uint texSize = pt->width0;
   uint *dest;
   uint i, j;

   dest = (uint *) pipe_transfer_map(pipe,
                                     pt, 0, 0, PIPE_TRANSFER_WRITE,
                                     0, 0, texSize, texSize, &transfer);

   /* Pack four 1D maps into a 2D texture:
    * R map is placed horizontally, indexed by S, in channel 0
    * G map is placed vertically, indexed by T, in channel 1
    * B map is placed horizontally, indexed by S, in channel 2
    * A map is placed vertically, indexed by T, in channel 3
    */
   for (i = 0; i < texSize; i++) {
      for (j = 0; j < texSize; j++) {
         union util_color uc;
         int k = (i * texSize + j);
         float rgba[4];
         rgba[0] = ctx->PixelMaps.RtoR.Map[j * rSize / texSize];
         rgba[1] = ctx->PixelMaps.GtoG.Map[i * gSize / texSize];
         rgba[2] = ctx->PixelMaps.BtoB.Map[j * bSize / texSize];
         rgba[3] = ctx->PixelMaps.AtoA.Map[i * aSize / texSize];
         util_pack_color(rgba, pt->format, &uc);
         *(dest + k) = uc.ui[0];
      }
   }

   pipe_transfer_unmap(pipe, transfer);
}
/**
 * Copy image data from a VdpOutputSurface to application memory in the
 * surface's native format.
 */
VdpStatus
vlVdpOutputSurfaceGetBitsNative(VdpOutputSurface surface,
                                VdpRect const *source_rect,
                                void *const *destination_data,
                                uint32_t const *destination_pitches)
{
   vlVdpOutputSurface *vlsurface;
   struct pipe_context *pipe;
   struct pipe_resource *res;
   struct pipe_box box;
   struct pipe_transfer *transfer;
   uint8_t *map;

   vlsurface = vlGetDataHTAB(surface);
   if (!vlsurface)
      return VDP_STATUS_INVALID_HANDLE;

   pipe = vlsurface->device->context;
   if (!pipe)
      return VDP_STATUS_INVALID_HANDLE;

   pipe_mutex_lock(vlsurface->device->mutex);
   vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);

   res = vlsurface->sampler_view->texture;
   box = RectToPipeBox(source_rect, res);
   map = pipe->transfer_map(pipe, res, 0, PIPE_TRANSFER_READ, &box, &transfer);
   if (!map) {
      pipe_mutex_unlock(vlsurface->device->mutex);
      return VDP_STATUS_RESOURCES;
   }

   util_copy_rect(*destination_data, res->format, *destination_pitches, 0, 0,
                  box.width, box.height, map, transfer->stride, 0, 0);

   pipe_transfer_unmap(pipe, transfer);
   pipe_mutex_unlock(vlsurface->device->mutex);

   return VDP_STATUS_OK;
}
Example #22
0
static void vid_dec_FillOutput(vid_dec_PrivateType *priv, struct pipe_video_buffer *buf,
                               OMX_BUFFERHEADERTYPE* output)
{
   omx_base_PortType *port = priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX];
   OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video;

   struct pipe_sampler_view **views;
   unsigned i, j;
   unsigned width, height;

   views = buf->get_sampler_view_planes(buf);

   for (i = 0; i < 2 /* NV12 */; i++) {
      if (!views[i]) continue;
      width = def->nFrameWidth;
      height = def->nFrameHeight;
      vl_video_buffer_adjust_size(&width, &height, i, buf->chroma_format, buf->interlaced);
      for (j = 0; j < views[i]->texture->array_size; ++j) {
         struct pipe_box box = {0, 0, j, width, height, 1};
         struct pipe_transfer *transfer;
         uint8_t *map, *dst;
         map = priv->pipe->transfer_map(priv->pipe, views[i]->texture, 0,
                  PIPE_TRANSFER_READ, &box, &transfer);
         if (!map)
            return;

         dst = ((uint8_t*)output->pBuffer + output->nOffset) + j * def->nStride +
               i * def->nFrameWidth * def->nFrameHeight;
         util_copy_rect(dst,
            views[i]->texture->format,
            def->nStride * views[i]->texture->array_size, 0, 0,
            box.width, box.height, map, transfer->stride, 0, 0);

         pipe_transfer_unmap(priv->pipe, transfer);
      }
   }
}
static void
drisw_update_tex_buffer(struct dri_drawable *drawable,
                        struct dri_context *ctx,
                        struct pipe_resource *res)
{
   __DRIdrawable *dPriv = drawable->dPriv;

   struct st_context *st_ctx = (struct st_context *)ctx->st;
   struct pipe_context *pipe = st_ctx->pipe;
   struct pipe_transfer *transfer;
   char *map;
   int x, y, w, h;
   int ximage_stride, line;
   int cpp = util_format_get_blocksize(res->format);

   get_drawable_info(dPriv, &x, &y, &w, &h);

   map = pipe_transfer_map(pipe, res,
                           0, 0, // level, layer,
                           PIPE_TRANSFER_WRITE,
                           x, y, w, h, &transfer);

   /* Copy the Drawable content to the mapped texture buffer */
   get_image(dPriv, x, y, w, h, map);

   /* The pipe transfer has a pitch rounded up to the nearest 64 pixels.
      get_image() has a pitch rounded up to 4 bytes.  */
   ximage_stride = ((w * cpp) + 3) & -4;
   for (line = h-1; line; --line) {
      memmove(&map[line * transfer->stride],
              &map[line * ximage_stride],
              ximage_stride);
   }

   pipe_transfer_unmap(pipe, transfer);
}
Example #24
0
File: xm_api.c Project: 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 */);

   }
}
Example #25
0
/**
 * Copy image data from a VdpVideoSurface to application memory in a specified
 * YCbCr format.
 */
VdpStatus
vlVdpVideoSurfaceGetBitsYCbCr(VdpVideoSurface surface,
                              VdpYCbCrFormat destination_ycbcr_format,
                              void *const *destination_data,
                              uint32_t const *destination_pitches)
{
   vlVdpSurface *vlsurface;
   struct pipe_context *pipe;
   enum pipe_format format, buffer_format;
   struct pipe_sampler_view **sampler_views;
   enum getbits_conversion conversion = CONVERSION_NONE;
   unsigned i, j;

   vlsurface = vlGetDataHTAB(surface);
   if (!vlsurface)
      return VDP_STATUS_INVALID_HANDLE;

   pipe = vlsurface->device->context;
   if (!pipe)
      return VDP_STATUS_INVALID_HANDLE;

   if (!destination_data || !destination_pitches)
       return VDP_STATUS_INVALID_POINTER;

   format = FormatYCBCRToPipe(destination_ycbcr_format);
   if (format == PIPE_FORMAT_NONE)
      return VDP_STATUS_INVALID_Y_CB_CR_FORMAT;

   if (vlsurface->video_buffer == NULL)
      return VDP_STATUS_INVALID_VALUE;

   buffer_format = vlsurface->video_buffer->buffer_format;
   if (format != buffer_format) {
      if (format == PIPE_FORMAT_YV12 && buffer_format == PIPE_FORMAT_NV12)
         conversion = CONVERSION_NV12_TO_YV12;
      else if (format == PIPE_FORMAT_NV12 && buffer_format == PIPE_FORMAT_YV12)
         conversion = CONVERSION_YV12_TO_NV12;
      else if ((format == PIPE_FORMAT_YUYV && buffer_format == PIPE_FORMAT_UYVY) ||
               (format == PIPE_FORMAT_UYVY && buffer_format == PIPE_FORMAT_YUYV))
         conversion = CONVERSION_SWAP_YUYV_UYVY;
      else
         return VDP_STATUS_NO_IMPLEMENTATION;
   }

   pipe_mutex_lock(vlsurface->device->mutex);
   sampler_views = vlsurface->video_buffer->get_sampler_view_planes(vlsurface->video_buffer);
   if (!sampler_views) {
      pipe_mutex_unlock(vlsurface->device->mutex);
      return VDP_STATUS_RESOURCES;
   }

   for (i = 0; i < 3; ++i) {
      unsigned width, height;
      struct pipe_sampler_view *sv = sampler_views[i];
      if (!sv) continue;

      vlVdpVideoSurfaceSize(vlsurface, i, &width, &height);

      for (j = 0; j < sv->texture->array_size; ++j) {
         struct pipe_box box = {
            0, 0, j,
            width, height, 1
         };
         struct pipe_transfer *transfer;
         uint8_t *map;

         map = pipe->transfer_map(pipe, sv->texture, 0,
                                       PIPE_TRANSFER_READ, &box, &transfer);
         if (!map) {
            pipe_mutex_unlock(vlsurface->device->mutex);
            return VDP_STATUS_RESOURCES;
         }

         if (conversion == CONVERSION_NV12_TO_YV12 && i == 1) {
            u_copy_nv12_to_yv12(destination_data, destination_pitches,
                                i, j, transfer->stride, sv->texture->array_size,
                                map, box.width, box.height);
         } else if (conversion == CONVERSION_YV12_TO_NV12 && i > 0) {
            u_copy_yv12_to_nv12(destination_data, destination_pitches,
                                i, j, transfer->stride, sv->texture->array_size,
                                map, box.width, box.height);
         } else if (conversion == CONVERSION_SWAP_YUYV_UYVY) {
            u_copy_swap422_packed(destination_data, destination_pitches,
                                   i, j, transfer->stride, sv->texture->array_size,
                                   map, box.width, box.height);
         } else {
            util_copy_rect(destination_data[i] + destination_pitches[i] * j, sv->texture->format,
                           destination_pitches[i] * sv->texture->array_size, 0, 0,
                           box.width, box.height, map, transfer->stride, 0, 0);
         }

         pipe_transfer_unmap(pipe, transfer);
      }
   }
   pipe_mutex_unlock(vlsurface->device->mutex);

   return VDP_STATUS_OK;
}
Example #26
0
VAStatus
vlVaGetImage(VADriverContextP ctx, VASurfaceID surface, int x, int y,
             unsigned int width, unsigned int height, VAImageID image)
{
   vlVaDriver *drv;
   vlVaSurface *surf;
   vlVaBuffer *img_buf;
   VAImage *vaimage;
   struct pipe_sampler_view **views;
   enum pipe_format format;
   bool convert = false;
   void *data[3];
   unsigned pitches[3], i, j;

   if (!ctx)
      return VA_STATUS_ERROR_INVALID_CONTEXT;

   drv = VL_VA_DRIVER(ctx);

   pipe_mutex_lock(drv->mutex);
   surf = handle_table_get(drv->htab, surface);
   if (!surf || !surf->buffer) {
      pipe_mutex_unlock(drv->mutex);
      return VA_STATUS_ERROR_INVALID_SURFACE;
   }

   vaimage = handle_table_get(drv->htab, image);
   if (!vaimage) {
      pipe_mutex_unlock(drv->mutex);
      return VA_STATUS_ERROR_INVALID_IMAGE;
   }

   img_buf = handle_table_get(drv->htab, vaimage->buf);
   if (!img_buf) {
      pipe_mutex_unlock(drv->mutex);
      return VA_STATUS_ERROR_INVALID_BUFFER;
   }

   format = VaFourccToPipeFormat(vaimage->format.fourcc);
   if (format == PIPE_FORMAT_NONE) {
      pipe_mutex_unlock(drv->mutex);
      return VA_STATUS_ERROR_OPERATION_FAILED;
   }

   if (format != surf->buffer->buffer_format) {
      /* support NV12 to YV12 and IYUV conversion now only */
      if ((format == PIPE_FORMAT_YV12 &&
          surf->buffer->buffer_format == PIPE_FORMAT_NV12) ||
          (format == PIPE_FORMAT_IYUV &&
          surf->buffer->buffer_format == PIPE_FORMAT_NV12))
         convert = true;
      else {
         pipe_mutex_unlock(drv->mutex);
         return VA_STATUS_ERROR_OPERATION_FAILED;
      }
   }

   views = surf->buffer->get_sampler_view_planes(surf->buffer);
   if (!views) {
      pipe_mutex_unlock(drv->mutex);
      return VA_STATUS_ERROR_OPERATION_FAILED;
   }

   for (i = 0; i < vaimage->num_planes; i++) {
      data[i] = img_buf->data + vaimage->offsets[i];
      pitches[i] = vaimage->pitches[i];
   }
   if (vaimage->format.fourcc == VA_FOURCC('I','4','2','0')) {
      void *tmp_d;
      unsigned tmp_p;
      tmp_d  = data[1];
      data[1] = data[2];
      data[2] = tmp_d;
      tmp_p = pitches[1];
      pitches[1] = pitches[2];
      pitches[2] = tmp_p;
   }

   for (i = 0; i < vaimage->num_planes; i++) {
      unsigned width, height;
      if (!views[i]) continue;
      vlVaVideoSurfaceSize(surf, i, &width, &height);
      for (j = 0; j < views[i]->texture->array_size; ++j) {
         struct pipe_box box = {0, 0, j, width, height, 1};
         struct pipe_transfer *transfer;
         uint8_t *map;
         map = drv->pipe->transfer_map(drv->pipe, views[i]->texture, 0,
                  PIPE_TRANSFER_READ, &box, &transfer);
         if (!map) {
            pipe_mutex_unlock(drv->mutex);
            return VA_STATUS_ERROR_OPERATION_FAILED;
         }

         if (i == 1 && convert) {
            u_copy_nv12_to_yv12(data, pitches, i, j,
               transfer->stride, views[i]->texture->array_size,
               map, box.width, box.height);
         } else {
            util_copy_rect(data[i] + pitches[i] * j,
               views[i]->texture->format,
               pitches[i] * views[i]->texture->array_size, 0, 0,
               box.width, box.height, map, transfer->stride, 0, 0);
         }
         pipe_transfer_unmap(drv->pipe, transfer);
      }
   }
   pipe_mutex_unlock(drv->mutex);

   return VA_STATUS_SUCCESS;
}
Example #27
0
/**
 * Copy image data from a VdpVideoSurface to application memory in a specified
 * YCbCr format.
 */
VdpStatus
vlVdpVideoSurfaceGetBitsYCbCr(VdpVideoSurface surface,
                              VdpYCbCrFormat destination_ycbcr_format,
                              void *const *destination_data,
                              uint32_t const *destination_pitches)
{
   vlVdpSurface *vlsurface;
   struct pipe_context *pipe;
   enum pipe_format format;
   struct pipe_sampler_view **sampler_views;
   unsigned i, j;

   vlsurface = vlGetDataHTAB(surface);
   if (!vlsurface)
      return VDP_STATUS_INVALID_HANDLE;

   pipe = vlsurface->device->context;
   if (!pipe)
      return VDP_STATUS_INVALID_HANDLE;

   format = FormatYCBCRToPipe(destination_ycbcr_format);
   if (format == PIPE_FORMAT_NONE)
       return VDP_STATUS_INVALID_Y_CB_CR_FORMAT;

   if (vlsurface->video_buffer == NULL || format != vlsurface->video_buffer->buffer_format)
      return VDP_STATUS_NO_IMPLEMENTATION; /* TODO We don't support conversion (yet) */

   pipe_mutex_lock(vlsurface->device->mutex);
   sampler_views = vlsurface->video_buffer->get_sampler_view_planes(vlsurface->video_buffer);
   if (!sampler_views) {
      pipe_mutex_unlock(vlsurface->device->mutex);
      return VDP_STATUS_RESOURCES;
   }

   for (i = 0; i < 3; ++i) {
      unsigned width, height;
      struct pipe_sampler_view *sv = sampler_views[i];
      if (!sv) continue;

      vlVdpVideoSurfaceSize(vlsurface, i, &width, &height);

      for (j = 0; j < sv->texture->array_size; ++j) {
         struct pipe_box box = {
            0, 0, j,
            width, height, 1
         };
         struct pipe_transfer *transfer;
         uint8_t *map;

         map = pipe->transfer_map(pipe, sv->texture, 0,
                                       PIPE_TRANSFER_READ, &box, &transfer);
         if (!map) {
            pipe_mutex_unlock(vlsurface->device->mutex);
            return VDP_STATUS_RESOURCES;
         }

         util_copy_rect(destination_data[i] + destination_pitches[i] * j, sv->texture->format,
                        destination_pitches[i] * sv->texture->array_size, 0, 0,
                        box.width, box.height, map, transfer->stride, 0, 0);

         pipe_transfer_unmap(pipe, transfer);
      }
   }
   pipe_mutex_unlock(vlsurface->device->mutex);

   return VDP_STATUS_OK;
}
Example #28
0
/* When this function is called, we have already checked
 * The copy regions fit the surfaces */
void
NineSurface9_CopyMemToDefault( struct NineSurface9 *This,
                               struct NineSurface9 *From,
                               const POINT *pDestPoint,
                               const RECT *pSourceRect )
{
    struct pipe_context *pipe = This->pipe;
    struct pipe_transfer *transfer = NULL;
    struct pipe_resource *r_dst = This->base.resource;
    struct pipe_box dst_box;
    uint8_t *map = NULL;
    int src_x, src_y, dst_x, dst_y, copy_width, copy_height;

    assert(This->base.pool == D3DPOOL_DEFAULT &&
           From->base.pool == D3DPOOL_SYSTEMMEM);

    if (pDestPoint) {
        dst_x = pDestPoint->x;
        dst_y = pDestPoint->y;
    } else {
        dst_x = 0;
        dst_y = 0;
    }

    if (pSourceRect) {
        src_x = pSourceRect->left;
        src_y = pSourceRect->top;
        copy_width = pSourceRect->right - pSourceRect->left;
        copy_height = pSourceRect->bottom - pSourceRect->top;
    } else {
        src_x = 0;
        src_y = 0;
        copy_width = From->desc.Width;
        copy_height = From->desc.Height;
    }

    u_box_2d_zslice(dst_x, dst_y, This->layer,
                    copy_width, copy_height, &dst_box);

    map = pipe->transfer_map(pipe,
                             r_dst,
                             This->level,
                             PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE,
                             &dst_box, &transfer);
    if (!map)
        return;

    /* Note: if formats are the sames, it will revert
     * to normal memcpy */
    (void) util_format_translate(r_dst->format,
                                 map, transfer->stride,
                                 0, 0,
                                 From->base.info.format,
                                 From->data, From->stride,
                                 src_x, src_y,
                                 copy_width, copy_height);

    pipe_transfer_unmap(pipe, transfer);

    if (This->data_conversion)
        (void) util_format_translate(This->format_conversion,
                                     This->data_conversion,
                                     This->stride_conversion,
                                     dst_x, dst_y,
                                     From->base.info.format,
                                     From->data, From->stride,
                                     src_x, src_y,
                                     copy_width, copy_height);

    NineSurface9_MarkContainerDirty(This);
}
Example #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);
}
Example #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);
   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);
}