Esempio n. 1
0
/**
 * This is the software fallback for Driver.GetCompressedTexImage().
 * All error checking will have been done before this routine is called.
 */
void
_mesa_get_compressed_teximage(GLcontext *ctx, GLenum target, GLint level,
                              GLvoid *img,
                              struct gl_texture_object *texObj,
                              struct gl_texture_image *texImage)
{
   const GLuint row_stride = _mesa_format_row_stride(texImage->TexFormat,
                                                     texImage->Width);
   const GLuint row_stride_stored = _mesa_format_row_stride(texImage->TexFormat,
                                                            texImage->RowStride);
   GLuint i;

   if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
      /* pack texture image into a PBO */
      GLubyte *buf = (GLubyte *)
         ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
                               GL_WRITE_ONLY_ARB, ctx->Pack.BufferObj);
      if (!buf) {
         /* out of memory or other unexpected error */
         _mesa_error(ctx, GL_OUT_OF_MEMORY,
                     "glGetCompresssedTexImage(map PBO failed)");
         return;
      }
      img = ADD_POINTERS(buf, img);
   }

   /* no pixelstore or pixel transfer, but respect stride */

   if (row_stride == row_stride_stored) {
      const GLuint size = _mesa_format_image_size(texImage->TexFormat,
                                                  texImage->Width,
                                                  texImage->Height,
                                                  texImage->Depth);
      _mesa_memcpy(img, texImage->Data, size);
   }
   else {
      GLuint bw, bh;
      _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh);
      for (i = 0; i < (texImage->Height + bh - 1) / bh; i++) {
         memcpy((GLubyte *)img + i * row_stride,
                (GLubyte *)texImage->Data + i * row_stride_stored, row_stride);
      }
   }

   if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
                              ctx->Pack.BufferObj);
   }
}
/**
 * This is the software fallback for Driver.GetCompressedTexImage().
 * All error checking will have been done before this routine is called.
 */
void
_mesa_get_compressed_teximage(struct gl_context *ctx,
                              struct gl_texture_image *texImage,
                              GLvoid *img)
{
   const GLuint row_stride =
      _mesa_format_row_stride(texImage->TexFormat, texImage->Width);
   GLuint i;
   GLubyte *src;
   GLint srcRowStride;

   if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
      /* pack texture image into a PBO */
      GLubyte *buf = (GLubyte *)
         ctx->Driver.MapBufferRange(ctx, 0, ctx->Pack.BufferObj->Size,
				    GL_MAP_WRITE_BIT, ctx->Pack.BufferObj);
      if (!buf) {
         /* out of memory or other unexpected error */
         _mesa_error(ctx, GL_OUT_OF_MEMORY,
                     "glGetCompresssedTexImage(map PBO failed)");
         return;
      }
      img = ADD_POINTERS(buf, img);
   }

   /* map src texture buffer */
   ctx->Driver.MapTextureImage(ctx, texImage, 0,
                               0, 0, texImage->Width, texImage->Height,
                               GL_MAP_READ_BIT, &src, &srcRowStride);

   if (src) {
      /* no pixelstore or pixel transfer, but respect stride */

      if (row_stride == srcRowStride) {
         const GLuint size = _mesa_format_image_size(texImage->TexFormat,
                                                     texImage->Width,
                                                     texImage->Height,
                                                     texImage->Depth);
         memcpy(img, src, size);
      }
      else {
         GLuint bw, bh;
         _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh);
         for (i = 0; i < (texImage->Height + bh - 1) / bh; i++) {
            memcpy((GLubyte *)img + i * row_stride,
                   (GLubyte *)src + i * srcRowStride,
                   row_stride);
         }
      }

      ctx->Driver.UnmapTextureImage(ctx, texImage, 0);
   }
   else {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetCompresssedTexImage");
   }

   if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
      ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj);
   }
}
Esempio n. 3
0
/**
 * Map texture memory/buffer into user space.
 * Note: the region of interest parameters are ignored here.
 * \param mapOut  returns start of mapping of region of interest
 * \param rowStrideOut  returns row stride in bytes
 */
static void
radeon_map_texture_image(struct gl_context *ctx,
                         struct gl_texture_image *texImage,
                         GLuint slice,
                         GLuint x, GLuint y, GLuint w, GLuint h,
                         GLbitfield mode,
                         GLubyte **map,
                         GLint *stride)
{
    radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
    radeon_texture_image *image = get_radeon_texture_image(texImage);
    radeon_mipmap_tree *mt = image->mt;
    GLuint texel_size = _mesa_get_format_bytes(texImage->TexFormat);
    GLuint width = texImage->Width;
    GLuint height = texImage->Height;
    struct radeon_bo *bo = !image->mt ? image->bo : image->mt->bo;
    unsigned int bw, bh;
    GLboolean write = (mode & GL_MAP_WRITE_BIT) != 0;

    _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh);
    assert(y % bh == 0);
    y /= bh;
    texel_size /= bw;

    if (bo && radeon_bo_is_referenced_by_cs(bo, rmesa->cmdbuf.cs)) {
        radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
                     "%s for texture that is "
                     "queued for GPU processing.\n",
                     __func__);
        radeon_firevertices(rmesa);
    }

    if (image->bo) {
        /* TFP case */
        radeon_bo_map(image->bo, write);
        *stride = get_texture_image_row_stride(rmesa, texImage->TexFormat, width, 0, texImage->TexObject->Target);
        *map = bo->ptr;
    } else if (likely(mt)) {
        void *base;
        radeon_mipmap_level *lvl = &image->mt->levels[texImage->Level];

        radeon_bo_map(mt->bo, write);
        base = mt->bo->ptr + lvl->faces[image->base.Base.Face].offset;

        *stride = lvl->rowstride;
        *map = base + (slice * height) * *stride;
    } else {
        /* texture data is in malloc'd memory */

        assert(map);

        *stride = _mesa_format_row_stride(texImage->TexFormat, width);
        *map = image->base.Buffer + (slice * height) * *stride;
    }

    *map += y * *stride + x * texel_size;
}
Esempio n. 4
0
/**
 * Compute compressed_pixelstore parameters for copying compressed
 * texture data.
 * \param dims  number of texture image dimensions: 1, 2 or 3
 * \param texFormat  the compressed texture format
 * \param width, height, depth  size of image to copy
 * \param packing  pixelstore parameters describing user-space image packing
 * \param store  returns the compressed_pixelstore parameters
 */
void
_mesa_compute_compressed_pixelstore(GLuint dims, mesa_format texFormat,
                                    GLsizei width, GLsizei height,
                                    GLsizei depth,
                                    const struct gl_pixelstore_attrib *packing,
                                    struct compressed_pixelstore *store)
{
   GLuint bw, bh;

   _mesa_get_format_block_size(texFormat, &bw, &bh);

   store->SkipBytes = 0;
   store->TotalBytesPerRow = store->CopyBytesPerRow =
         _mesa_format_row_stride(texFormat, width);
   store->TotalRowsPerSlice = store->CopyRowsPerSlice =
         (height + bh - 1) / bh;
   store->CopySlices = depth;

   if (packing->CompressedBlockWidth &&
       packing->CompressedBlockSize) {

      bw = packing->CompressedBlockWidth;

      if (packing->RowLength) {
         store->TotalBytesPerRow = packing->CompressedBlockSize *
            ((packing->RowLength + bw - 1) / bw);
      }

      store->SkipBytes += packing->SkipPixels * packing->CompressedBlockSize / bw;
   }

   if (dims > 1 && packing->CompressedBlockHeight &&
       packing->CompressedBlockSize) {

      bh = packing->CompressedBlockHeight;

      store->SkipBytes += packing->SkipRows * store->TotalBytesPerRow / bh;
      store->CopyRowsPerSlice = (height + bh - 1) / bh;  /* rows in blocks */

      if (packing->ImageHeight) {
         store->TotalRowsPerSlice = (packing->ImageHeight + bh - 1) / bh;
      }
   }

   if (dims > 2 && packing->CompressedBlockDepth &&
       packing->CompressedBlockSize) {

      int bd = packing->CompressedBlockDepth;

      store->SkipBytes += packing->SkipImages * store->TotalBytesPerRow *
            store->TotalRowsPerSlice / bd;
   }
}
unsigned get_texture_image_row_stride(radeonContextPtr rmesa, mesa_format format, unsigned width, unsigned tiling, GLuint target)
{
	if (_mesa_is_format_compressed(format)) {
		return get_aligned_compressed_row_stride(format, width, rmesa->texture_compressed_row_align);
	} else {
		unsigned row_align;

		if (!_mesa_is_pow_two(width) || target == GL_TEXTURE_RECTANGLE) {
			row_align = rmesa->texture_rect_row_align - 1;
		} else if (tiling) {
			unsigned tileWidth, tileHeight;
			get_tile_size(format, &tileWidth, &tileHeight);
			row_align = tileWidth * _mesa_get_format_bytes(format) - 1;
		} else {
			row_align = rmesa->texture_row_align - 1;
		}

		return (_mesa_format_row_stride(format, width) + row_align) & ~row_align;
	}
}
Esempio n. 6
0
/**
 * Map a 2D slice of a texture image into user space.
 * (x,y,w,h) defines a region of interest (ROI).  Reading/writing texels
 * outside of the ROI is undefined.
 *
 * \param texImage  the texture image
 * \param slice  the 3D image slice or array texture slice
 * \param x, y, w, h  region of interest
 * \param mode  bitmask of GL_MAP_READ_BIT, GL_MAP_WRITE_BIT
 * \param mapOut  returns start of mapping of region of interest
 * \param rowStrideOut  returns row stride (in bytes)
 */
void
_swrast_map_teximage(struct gl_context *ctx,
                     struct gl_texture_image *texImage,
                     GLuint slice,
                     GLuint x, GLuint y, GLuint w, GLuint h,
                     GLbitfield mode,
                     GLubyte **mapOut,
                     GLint *rowStrideOut)
{
   struct swrast_texture_image *swImage = swrast_texture_image(texImage);
   GLubyte *map;
   GLint stride, texelSize;
   GLuint bw, bh;

   _mesa_check_map_teximage(texImage, slice, x, y, w, h);

   texelSize = _mesa_get_format_bytes(texImage->TexFormat);
   stride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width);
   _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh);

   assert(x % bw == 0);
   assert(y % bh == 0);

   if (!swImage->Buffer) {
      /* probably ran out of memory when allocating tex mem */
      *mapOut = NULL;
      return;
   }
      
   map = swImage->Buffer;

   /* apply x/y offset to map address */
   map += stride * (y / bh) + texelSize * (x / bw);

   *mapOut = map;
   *rowStrideOut = stride;
}
Esempio n. 7
0
/**
 * Update a subregion of the given texture image.
 */
static void radeon_store_teximage(GLcontext* ctx, int dims,
		GLint xoffset, GLint yoffset, GLint zoffset,
		GLsizei width, GLsizei height, GLsizei depth,
		GLsizei imageSize,
		GLenum format, GLenum type,
		const GLvoid * pixels,
		const struct gl_pixelstore_attrib *packing,
		struct gl_texture_object *texObj,
		struct gl_texture_image *texImage,
		int compressed)
{
	radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
	radeonTexObj *t = radeon_tex_obj(texObj);
	radeon_texture_image* image = get_radeon_texture_image(texImage);

	GLuint dstRowStride;
	GLuint *dstImageOffsets;

	radeon_print(RADEON_TEXTURE, RADEON_TRACE,
			"%s(%p, tex %p, image %p) compressed %d\n",
			__func__, ctx, texObj, texImage, compressed);

	if (image->mt) {
		dstRowStride = image->mt->levels[image->mtlevel].rowstride;
	} else if (t->bo) {
		/* TFP case */
		dstRowStride = get_texture_image_row_stride(rmesa, texImage->TexFormat, width, 0);
	} else {
		dstRowStride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width);
	}

	assert(dstRowStride);

	if (dims == 3) {
		unsigned alignedWidth = dstRowStride/_mesa_get_format_bytes(texImage->TexFormat);
		dstImageOffsets = allocate_image_offsets(ctx, alignedWidth, texImage->Height, texImage->Depth);
		if (!dstImageOffsets) {
			radeon_warning("%s Failed to allocate dstImaeOffset.\n", __func__);
			return;
		}
	} else {
		dstImageOffsets = texImage->ImageOffsets;
	}

	radeon_teximage_map(image, GL_TRUE);

	if (compressed) {
		uint32_t srcRowStride, bytesPerRow, rows, block_width, block_height;
		GLubyte *img_start;

		_mesa_get_format_block_size(texImage->TexFormat, &block_width, &block_height);

		if (!image->mt) {
			dstRowStride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width);
			img_start = _mesa_compressed_image_address(xoffset, yoffset, 0,
									texImage->TexFormat,
									texImage->Width, texImage->Data);
		}
		else {
			uint32_t offset;
			offset = dstRowStride / _mesa_get_format_bytes(texImage->TexFormat) * yoffset / block_height + xoffset / block_width;
			offset *= _mesa_get_format_bytes(texImage->TexFormat);
			img_start = texImage->Data + offset;
		}
		srcRowStride = _mesa_format_row_stride(texImage->TexFormat, width);
		bytesPerRow = srcRowStride;
		rows = (height + block_height - 1) / block_height;

		copy_rows(img_start, dstRowStride, pixels, srcRowStride, rows, bytesPerRow);
	}
	else {
		if (!_mesa_texstore(ctx, dims, texImage->_BaseFormat,
					texImage->TexFormat, texImage->Data,
					xoffset, yoffset, zoffset,
					dstRowStride,
					dstImageOffsets,
					width, height, depth,
					format, type, pixels, packing)) {
			_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
		}
	}

	if (dims == 3) {
		free(dstImageOffsets);
	}

	radeon_teximage_unmap(image);
}
Esempio n. 8
0
/**
 * 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;
   GLubyte *map;

   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;

    map = pipe_transfer_map(pipe,
                            strb->texture,
                            strb->surface->u.tex.level,
                            strb->surface->u.tex.first_layer,
                            usage, x, y2, w, h, &strb->transfer);
   if (map) {
      if (invert) {
         *rowStrideOut = -(int) strb->transfer->stride;
         map += (h - 1) * strb->transfer->stride;
      }
      else {
         *rowStrideOut = strb->transfer->stride;
      }
      *mapOut = map;
   }
   else {
      *mapOut = NULL;
      *rowStrideOut = 0;
   }
}
Esempio n. 9
0
/**
 * Called via ctx->Driver.MapRenderbuffer()
 */
void
xmesa_MapRenderbuffer(struct gl_context *ctx,
                      struct gl_renderbuffer *rb,
                      GLuint x, GLuint y, GLuint w, GLuint h,
                      GLbitfield mode,
                      GLubyte **mapOut, GLint *rowStrideOut)
{
    struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb);

    if (xrb->Base.Base.ClassID == XMESA_RENDERBUFFER) {
        XImage *ximage = xrb->ximage;

        assert(!xrb->map_mode); /* only a single mapping allowed */

        xrb->map_mode = mode;
        xrb->map_x = x;
        xrb->map_y = y;
        xrb->map_w = w;
        xrb->map_h = h;

        if (ximage) {
            int y2 = rb->Height - y - 1;

            *mapOut = (GLubyte *) ximage->data
                      + y2 * ximage->bytes_per_line
                      + x * ximage->bits_per_pixel / 8;
        }
        else {
            /* this must be a pixmap/window renderbuffer */
            int (*old_handler)(XMesaDisplay *, XErrorEvent *);
            int y2 = rb->Height - y - h;

            assert(xrb->pixmap);

            /* Install error handler for XGetImage() in case the the window
             * isn't mapped.  If we fail we'll create a temporary XImage.
             */
            mesaXErrorFlag = 0;
            old_handler = XSetErrorHandler(mesaHandleXError);

            /* read pixel data out of the pixmap/window into an XImage */
            ximage = XGetImage(xrb->Parent->display,
                               xrb->pixmap, x, y2, w, h,
                               AllPlanes, ZPixmap);

            XSetErrorHandler(old_handler);

            if (mesaXErrorFlag) {
                /* create new, temporary XImage */
                int bytes_per_line =
                    _mesa_format_row_stride(xrb->Base.Base.Format,
                                            xrb->Base.Base.Width);
                char *image = (char *) malloc(bytes_per_line *
                                              xrb->Base.Base.Height);
                ximage = XCreateImage(xrb->Parent->display,
                                      xrb->Parent->xm_visual->visinfo->visual,
                                      xrb->Parent->xm_visual->visinfo->depth,
                                      ZPixmap, /* format */
                                      0, /* offset */
                                      image, /* data */
                                      xrb->Base.Base.Width,
                                      xrb->Base.Base.Height,
                                      8, /* pad */
                                      bytes_per_line);
            }

            if (!ximage) {
                *mapOut = NULL;
                *rowStrideOut = 0;
                return;
            }

            xrb->map_ximage = ximage;

            /* the first row of the OpenGL image is last row of the XImage */
            *mapOut = (GLubyte *) ximage->data
                      + (h - 1) * ximage->bytes_per_line;
        }

        /* We return a negative stride here since XImage data is upside down
         * with respect to OpenGL images.
         */
        *rowStrideOut = -ximage->bytes_per_line;
        return;
    }

    /* otherwise, this is an ordinary malloc-based renderbuffer */
    _swrast_map_soft_renderbuffer(ctx, rb, x, y, w, h, mode,
                                  mapOut, rowStrideOut);
}