Example #1
0
/**
 * Read pixels for format=GL_DEPTH_COMPONENT.
 */
static void
read_depth_pixels( struct gl_context *ctx,
                   GLint x, GLint y,
                   GLsizei width, GLsizei height,
                   GLenum type, GLvoid *pixels,
                   const struct gl_pixelstore_attrib *packing )
{
   struct gl_framebuffer *fb = ctx->ReadBuffer;
   struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
   GLint j;
   GLubyte *dst, *map;
   int dstStride, stride;
   GLfloat *depthValues;

   if (!rb)
      return;

   /* clipping should have been done already */
   ASSERT(x >= 0);
   ASSERT(y >= 0);
   ASSERT(x + width <= (GLint) rb->Width);
   ASSERT(y + height <= (GLint) rb->Height);

   if (type == GL_UNSIGNED_INT &&
       read_uint_depth_pixels(ctx, x, y, width, height, type, pixels, packing)) {
      return;
   }

   dstStride = _mesa_image_row_stride(packing, width, GL_DEPTH_COMPONENT, type);
   dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
					   GL_DEPTH_COMPONENT, type, 0, 0);

   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
			       &map, &stride);
   if (!map) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
      return;
   }

   depthValues = malloc(width * sizeof(GLfloat));

   if (depthValues) {
      /* General case (slower) */
      for (j = 0; j < height; j++, y++) {
         _mesa_unpack_float_z_row(rb->Format, width, map, depthValues);
         _mesa_pack_depth_span(ctx, width, dst, type, depthValues, packing);

         dst += dstStride;
         map += stride;
      }
   }
   else {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
   }

   free(depthValues);

   ctx->Driver.UnmapRenderbuffer(ctx, rb);
}
Example #2
0
/**
 * Tries to implement glReadPixels() of GL_DEPTH_COMPONENT using memcpy of the
 * mapping.
 */
static GLboolean
fast_read_depth_pixels( struct gl_context *ctx,
			GLint x, GLint y,
			GLsizei width, GLsizei height,
			GLenum type, GLvoid *pixels,
			const struct gl_pixelstore_attrib *packing )
{
   struct gl_framebuffer *fb = ctx->ReadBuffer;
   struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
   GLubyte *map, *dst;
   int stride, dstStride, j;

   if (ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0)
      return GL_FALSE;

   if (packing->SwapBytes)
      return GL_FALSE;

   if (_mesa_get_format_datatype(rb->Format) != GL_UNSIGNED_NORMALIZED)
      return GL_FALSE;

   if (!((type == GL_UNSIGNED_SHORT && rb->Format == MESA_FORMAT_Z16) ||
	 type == GL_UNSIGNED_INT))
      return GL_FALSE;

   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
			       &map, &stride);

   if (!map) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
      return GL_TRUE;  /* don't bother trying the slow path */
   }

   dstStride = _mesa_image_row_stride(packing, width, GL_DEPTH_COMPONENT, type);
   dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
					   GL_DEPTH_COMPONENT, type, 0, 0);

   for (j = 0; j < height; j++) {
      if (type == GL_UNSIGNED_INT) {
	 _mesa_unpack_uint_z_row(rb->Format, width, map, (GLuint *)dst);
      } else {
	 ASSERT(type == GL_UNSIGNED_SHORT && rb->Format == MESA_FORMAT_Z16);
	 memcpy(dst, map, width * 2);
      }

      map += stride;
      dst += dstStride;
   }
   ctx->Driver.UnmapRenderbuffer(ctx, rb);

   return GL_TRUE;
}
Example #3
0
static void
slow_read_rgba_pixels( struct gl_context *ctx,
		       GLint x, GLint y,
		       GLsizei width, GLsizei height,
		       GLenum format, GLenum type,
		       GLvoid *pixels,
		       const struct gl_pixelstore_attrib *packing,
		       GLbitfield transferOps )
{
   struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
   const gl_format rbFormat = _mesa_get_srgb_format_linear(rb->Format);
   void *rgba;
   GLubyte *dst, *map;
   int dstStride, stride, j;

   dstStride = _mesa_image_row_stride(packing, width, format, type);
   dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
					   format, type, 0, 0);

   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
			       &map, &stride);
   if (!map) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
      return;
   }

   rgba = malloc(width * MAX_PIXEL_BYTES);
   if (!rgba)
      goto done;

   for (j = 0; j < height; j++) {
      if (_mesa_is_integer_format(format)) {
	 _mesa_unpack_uint_rgba_row(rbFormat, width, map, (GLuint (*)[4]) rgba);
	 _mesa_pack_rgba_span_int(ctx, width, (GLuint (*)[4]) rgba, format,
                                  type, dst);
      } else {
	 _mesa_unpack_rgba_row(rbFormat, width, map, (GLfloat (*)[4]) rgba);
	 _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format,
                                    type, dst, packing, transferOps);
      }
      dst += dstStride;
      map += stride;
   }

   free(rgba);

done:
   ctx->Driver.UnmapRenderbuffer(ctx, rb);
}
Example #4
0
static GLboolean
_mesa_texstore_z32f_x24s8(TEXSTORE_PARAMS)
{
   GLint img, row;
   const GLint srcRowStride
      = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType)
      / sizeof(uint64_t);

   assert(dstFormat == MESA_FORMAT_Z32_FLOAT_S8X24_UINT);
   assert(srcFormat == GL_DEPTH_STENCIL ||
          srcFormat == GL_DEPTH_COMPONENT ||
          srcFormat == GL_STENCIL_INDEX);
   assert(srcFormat != GL_DEPTH_STENCIL ||
          srcType == GL_UNSIGNED_INT_24_8 ||
          srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);

   /* In case we only upload depth we need to preserve the stencil */
   for (img = 0; img < srcDepth; img++) {
      uint64_t *dstRow = (uint64_t *) dstSlices[img];
      const uint64_t *src
         = (const uint64_t *) _mesa_image_address(dims, srcPacking, srcAddr,
               srcWidth, srcHeight,
               srcFormat, srcType,
               img, 0, 0);
      for (row = 0; row < srcHeight; row++) {
         /* The unpack functions with:
          *    dstType = GL_FLOAT_32_UNSIGNED_INT_24_8_REV
          * only write their own dword, so the other dword (stencil
          * or depth) is preserved. */
         if (srcFormat != GL_STENCIL_INDEX)
            _mesa_unpack_depth_span(ctx, srcWidth,
                                    GL_FLOAT_32_UNSIGNED_INT_24_8_REV, /* dst type */
                                    dstRow, /* dst addr */
                                    ~0U, srcType, src, srcPacking);

         if (srcFormat != GL_DEPTH_COMPONENT)
            _mesa_unpack_stencil_span(ctx, srcWidth,
                                      GL_FLOAT_32_UNSIGNED_INT_24_8_REV, /* dst type */
                                      dstRow, /* dst addr */
                                      srcType, src, srcPacking,
                                      ctx->_ImageTransferState);

         src += srcRowStride;
         dstRow += dstRowStride / sizeof(uint64_t);
      }
   }
   return GL_TRUE;
}
Example #5
0
/**
 * Teximage storage routine for when a simple memcpy will do.
 * No pixel transfer operations or special texel encodings allowed.
 * 1D, 2D and 3D images supported.
 */
static void
memcpy_texture(struct gl_context *ctx,
	       GLuint dimensions,
               mesa_format dstFormat,
               GLint dstRowStride,
               GLubyte **dstSlices,
               GLint srcWidth, GLint srcHeight, GLint srcDepth,
               GLenum srcFormat, GLenum srcType,
               const GLvoid *srcAddr,
               const struct gl_pixelstore_attrib *srcPacking)
{
   const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth,
                                                     srcFormat, srcType);
   const GLint srcImageStride = _mesa_image_image_stride(srcPacking,
                                      srcWidth, srcHeight, srcFormat, srcType);
   const GLubyte *srcImage = (const GLubyte *) _mesa_image_address(dimensions,
        srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
   const GLint bytesPerRow = srcWidth * texelBytes;

   if (dstRowStride == srcRowStride &&
       dstRowStride == bytesPerRow) {
      /* memcpy image by image */
      GLint img;
      for (img = 0; img < srcDepth; img++) {
         GLubyte *dstImage = dstSlices[img];
         memcpy(dstImage, srcImage, bytesPerRow * srcHeight);
         srcImage += srcImageStride;
      }
   }
   else {
      /* memcpy row by row */
      GLint img, row;
      for (img = 0; img < srcDepth; img++) {
         const GLubyte *srcRow = srcImage;
         GLubyte *dstRow = dstSlices[img];
         for (row = 0; row < srcHeight; row++) {
            memcpy(dstRow, srcRow, bytesPerRow);
            dstRow += dstRowStride;
            srcRow += srcRowStride;
         }
         srcImage += srcImageStride;
      }
   }
}
Example #6
0
/**
 * Store simple 8-bit/value stencil texture data.
 */
static GLboolean
_mesa_texstore_s8(TEXSTORE_PARAMS)
{
   assert(dstFormat == MESA_FORMAT_S_UINT8);
   assert(srcFormat == GL_STENCIL_INDEX);

   {
      const GLint srcRowStride
	 = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
      GLint img, row;
      GLubyte *stencil = malloc(srcWidth * sizeof(GLubyte));

      if (!stencil)
         return GL_FALSE;

      for (img = 0; img < srcDepth; img++) {
         GLubyte *dstRow = dstSlices[img];
         const GLubyte *src
            = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
                                                   srcWidth, srcHeight,
                                                   srcFormat, srcType,
                                                   img, 0, 0);
         for (row = 0; row < srcHeight; row++) {
            GLint i;

            /* get the 8-bit stencil values */
            _mesa_unpack_stencil_span(ctx, srcWidth,
                                      GL_UNSIGNED_BYTE, /* dst type */
                                      stencil, /* dst addr */
                                      srcType, src, srcPacking,
                                      ctx->_ImageTransferState);
            /* merge stencil values into depth values */
            for (i = 0; i < srcWidth; i++)
               dstRow[i] = stencil[i];

            src += srcRowStride;
            dstRow += dstRowStride / sizeof(GLubyte);
         }
      }

      free(stencil);
   }

   return GL_TRUE;
}
Example #7
0
static GLboolean
fast_read_rgba_pixels_memcpy( struct gl_context *ctx,
			      GLint x, GLint y,
			      GLsizei width, GLsizei height,
			      GLenum format, GLenum type,
			      GLvoid *pixels,
			      const struct gl_pixelstore_attrib *packing,
			      GLbitfield transferOps )
{
   struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
   GLubyte *dst, *map;
   int dstStride, stride, j, texelBytes;

   if (!_mesa_format_matches_format_and_type(rb->Format, format, type))
      return GL_FALSE;

   /* check for things we can't handle here */
   if (packing->SwapBytes ||
       packing->LsbFirst) {
      return GL_FALSE;
   }

   dstStride = _mesa_image_row_stride(packing, width, format, type);
   dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
					   format, type, 0, 0);

   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
			       &map, &stride);
   if (!map) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
      return GL_TRUE;  /* don't bother trying the slow path */
   }

   texelBytes = _mesa_get_format_bytes(rb->Format);
   for (j = 0; j < height; j++) {
      memcpy(dst, map, width * texelBytes);
      dst += dstStride;
      map += stride;
   }

   ctx->Driver.UnmapRenderbuffer(ctx, rb);

   return GL_TRUE;
}
Example #8
0
/**
 * Handle a common case of drawing GL_RGBA/GL_UNSIGNED_BYTE into a
 * MESA_FORMAT_ARGB888 or MESA_FORMAT_xRGB888 renderbuffer.
 */
static void
fast_draw_rgba_ubyte_pixels(struct gl_context *ctx,
                           struct gl_renderbuffer *rb,
                           GLint x, GLint y,
                           GLsizei width, GLsizei height,
                           const struct gl_pixelstore_attrib *unpack,
                           const GLvoid *pixels)
{
   const GLubyte *src = (const GLubyte *)
      _mesa_image_address2d(unpack, pixels, width,
                            height, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0);
   const GLint srcRowStride =
      _mesa_image_row_stride(unpack, width, GL_RGBA, GL_UNSIGNED_BYTE);
   GLint i, j;
   GLubyte *dst;
   GLint dstRowStride;

   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
                               GL_MAP_WRITE_BIT, &dst, &dstRowStride);

   if (!dst) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
      return;
   }

   if (ctx->Pixel.ZoomY == -1.0f) {
      dst = dst + (height - 1) * dstRowStride;
      dstRowStride = -dstRowStride;
   }

   for (i = 0; i < height; i++) {
      GLuint *dst4 = (GLuint *) dst;
      for (j = 0; j < width; j++) {
         dst4[j] = PACK_COLOR_8888(src[j*4+3], src[j*4+0],
                                   src[j*4+1], src[j*4+2]);
      }
      dst += dstRowStride;
      src += srcRowStride;
   }

   ctx->Driver.UnmapRenderbuffer(ctx, rb);
}
Example #9
0
static GLboolean
readpixels_memcpy(struct gl_context *ctx,
                  GLint x, GLint y,
                  GLsizei width, GLsizei height,
                  GLenum format, GLenum type,
                  GLvoid *pixels,
                  const struct gl_pixelstore_attrib *packing)
{
   struct gl_renderbuffer *rb =
         _mesa_get_read_renderbuffer_for_format(ctx, format);
   GLubyte *dst, *map;
   int dstStride, stride, j, texelBytes;

   /* Fail if memcpy cannot be used. */
   if (!readpixels_can_use_memcpy(ctx, format, type, packing)) {
      return GL_FALSE;
   }

   dstStride = _mesa_image_row_stride(packing, width, format, type);
   dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
					   format, type, 0, 0);

   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
			       &map, &stride);
   if (!map) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
      return GL_TRUE;  /* don't bother trying the slow path */
   }

   texelBytes = _mesa_get_format_bytes(rb->Format);

   /* memcpy*/
   for (j = 0; j < height; j++) {
      memcpy(dst, map, width * texelBytes);
      dst += dstStride;
      map += stride;
   }

   ctx->Driver.UnmapRenderbuffer(ctx, rb);
   return GL_TRUE;
}
Example #10
0
/**
 * Handle a common case of drawing a format/type combination that
 * exactly matches the renderbuffer format.
 */
static void
fast_draw_generic_pixels(struct gl_context *ctx,
                         struct gl_renderbuffer *rb,
                         GLint x, GLint y,
                         GLsizei width, GLsizei height,
                         GLenum format, GLenum type,
                         const struct gl_pixelstore_attrib *unpack,
                         const GLvoid *pixels)
{
   const GLubyte *src = (const GLubyte *)
      _mesa_image_address2d(unpack, pixels, width,
                            height, format, type, 0, 0);
   const GLint srcRowStride =
      _mesa_image_row_stride(unpack, width, format, type);
   const GLint rowLength = width * _mesa_get_format_bytes(rb->Format);
   GLint i;
   GLubyte *dst;
   GLint dstRowStride;

   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
                               GL_MAP_WRITE_BIT, &dst, &dstRowStride);

   if (!dst) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
      return;
   }

   if (ctx->Pixel.ZoomY == -1.0f) {
      dst = dst + (height - 1) * dstRowStride;
      dstRowStride = -dstRowStride;
   }

   for (i = 0; i < height; i++) {
      memcpy(dst, src, rowLength);
      dst += dstRowStride;
      src += srcRowStride;
   }

   ctx->Driver.UnmapRenderbuffer(ctx, rb);
}
Example #11
0
/**
 * Read combined depth/stencil values.
 * We'll have already done error checking to be sure the expected
 * depth and stencil buffers really exist.
 */
static void
read_depth_stencil_pixels(struct gl_context *ctx,
                          GLint x, GLint y,
                          GLsizei width, GLsizei height,
                          GLenum type, GLvoid *pixels,
                          const struct gl_pixelstore_attrib *packing )
{
   const GLboolean scaleOrBias
      = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0;
   const GLboolean stencilTransfer = ctx->Pixel.IndexShift
      || ctx->Pixel.IndexOffset || ctx->Pixel.MapStencilFlag;
   GLubyte *dst;
   int dstStride;

   dst = (GLubyte *) _mesa_image_address2d(packing, pixels,
					   width, height,
					   GL_DEPTH_STENCIL_EXT,
					   type, 0, 0);
   dstStride = _mesa_image_row_stride(packing, width,
				      GL_DEPTH_STENCIL_EXT, type);

   /* Fast 24/8 reads. */
   if (type == GL_UNSIGNED_INT_24_8 &&
       !scaleOrBias && !stencilTransfer && !packing->SwapBytes) {
      if (fast_read_depth_stencil_pixels(ctx, x, y, width, height,
					 dst, dstStride))
	 return;

      if (fast_read_depth_stencil_pixels_separate(ctx, x, y, width, height,
						  (uint32_t *)dst, dstStride))
	 return;
   }

   slow_read_depth_stencil_pixels_separate(ctx, x, y, width, height,
					   type, packing,
					   dst, dstStride);
}
Example #12
0
/**
 * Helper function for storing 1D, 2D, 3D whole and subimages into texture
 * memory.
 * The source of the image data may be user memory or a PBO.  In the later
 * case, we'll map the PBO, copy from it, then unmap it.
 */
static void
store_texsubimage(struct gl_context *ctx,
                  struct gl_texture_image *texImage,
                  GLint xoffset, GLint yoffset, GLint zoffset,
                  GLint width, GLint height, GLint depth,
                  GLenum format, GLenum type, const GLvoid *pixels,
                  const struct gl_pixelstore_attrib *packing,
                  const char *caller)

{
   const GLbitfield mapMode = get_read_write_mode(format, texImage->TexFormat);
   const GLenum target = texImage->TexObject->Target;
   GLboolean success = GL_FALSE;
   GLuint dims, slice, numSlices = 1, sliceOffset = 0;
   GLint srcImageStride = 0;
   const GLubyte *src;

   assert(xoffset + width <= texImage->Width);
   assert(yoffset + height <= texImage->Height);
   assert(zoffset + depth <= texImage->Depth);

   switch (target) {
   case GL_TEXTURE_1D:
      dims = 1;
      break;
   case GL_TEXTURE_2D_ARRAY:
   case GL_TEXTURE_CUBE_MAP_ARRAY:
   case GL_TEXTURE_3D:
      dims = 3;
      break;
   default:
      dims = 2;
   }

   /* get pointer to src pixels (may be in a pbo which we'll map here) */
   src = (const GLubyte *)
      _mesa_validate_pbo_teximage(ctx, dims, width, height, depth,
                                  format, type, pixels, packing, caller);
   if (!src)
      return;

   /* compute slice info (and do some sanity checks) */
   switch (target) {
   case GL_TEXTURE_2D:
   case GL_TEXTURE_RECTANGLE:
   case GL_TEXTURE_CUBE_MAP:
   case GL_TEXTURE_EXTERNAL_OES:
      /* one image slice, nothing special needs to be done */
      break;
   case GL_TEXTURE_1D:
      assert(height == 1);
      assert(depth == 1);
      assert(yoffset == 0);
      assert(zoffset == 0);
      break;
   case GL_TEXTURE_1D_ARRAY:
      assert(depth == 1);
      assert(zoffset == 0);
      numSlices = height;
      sliceOffset = yoffset;
      height = 1;
      yoffset = 0;
      srcImageStride = _mesa_image_row_stride(packing, width, format, type);
      break;
   case GL_TEXTURE_2D_ARRAY:
      numSlices = depth;
      sliceOffset = zoffset;
      depth = 1;
      zoffset = 0;
      srcImageStride = _mesa_image_image_stride(packing, width, height,
                                                format, type);
      break;
   case GL_TEXTURE_3D:
      /* we'll store 3D images as a series of slices */
      numSlices = depth;
      sliceOffset = zoffset;
      srcImageStride = _mesa_image_image_stride(packing, width, height,
                                                format, type);
      break;
   case GL_TEXTURE_CUBE_MAP_ARRAY:
      numSlices = depth;
      sliceOffset = zoffset;
      srcImageStride = _mesa_image_image_stride(packing, width, height,
                                                format, type);
      break;
   default:
      _mesa_warning(ctx, "Unexpected target 0x%x in store_texsubimage()", target);
      return;
   }

   assert(numSlices == 1 || srcImageStride != 0);

   for (slice = 0; slice < numSlices; slice++) {
      GLubyte *dstMap;
      GLint dstRowStride;

      ctx->Driver.MapTextureImage(ctx, texImage,
                                  slice + sliceOffset,
                                  xoffset, yoffset, width, height,
                                  mapMode, &dstMap, &dstRowStride);
      if (dstMap) {
         /* Note: we're only storing a 2D (or 1D) slice at a time but we need
          * to pass the right 'dims' value so that GL_UNPACK_SKIP_IMAGES is
          * used for 3D images.
          */
         success = _mesa_texstore(ctx, dims, texImage->_BaseFormat,
                                  texImage->TexFormat,
                                  dstRowStride,
                                  &dstMap,
                                  width, height, 1,  /* w, h, d */
                                  format, type, src, packing);

         ctx->Driver.UnmapTextureImage(ctx, texImage, slice + sliceOffset);
      }

      src += srcImageStride;

      if (!success)
         break;
   }

   if (!success)
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller);

   _mesa_unmap_teximage_pbo(ctx, packing);
}
Example #13
0
/* XXX: Do this for TexSubImage also:
 */
static bool
try_pbo_upload(struct gl_context *ctx,
               struct gl_texture_image *image,
               const struct gl_pixelstore_attrib *unpack,
	       GLenum format, GLenum type, const void *pixels)
{
   struct intel_texture_image *intelImage = intel_texture_image(image);
   struct intel_context *intel = intel_context(ctx);
   struct intel_buffer_object *pbo = intel_buffer_object(unpack->BufferObj);
   GLuint src_offset;
   drm_intel_bo *src_buffer;

   if (!_mesa_is_bufferobj(unpack->BufferObj))
      return false;

   DBG("trying pbo upload\n");

   if (intel->ctx._ImageTransferState ||
       unpack->SkipPixels || unpack->SkipRows) {
      DBG("%s: image transfer\n", __FUNCTION__);
      return false;
   }

   ctx->Driver.AllocTextureImageBuffer(ctx, image);

   if (!intelImage->mt) {
      DBG("%s: no miptree\n", __FUNCTION__);
      return false;
   }

   if (!_mesa_format_matches_format_and_type(intelImage->mt->format,
                                             format, type, false)) {
      DBG("%s: format mismatch (upload to %s with format 0x%x, type 0x%x)\n",
	  __FUNCTION__, _mesa_get_format_name(intelImage->mt->format),
	  format, type);
      return false;
   }

   if (image->TexObject->Target == GL_TEXTURE_1D_ARRAY ||
       image->TexObject->Target == GL_TEXTURE_2D_ARRAY) {
      DBG("%s: no support for array textures\n", __FUNCTION__);
      return false;
   }

   src_buffer = intel_bufferobj_source(intel, pbo, 64, &src_offset);
   /* note: potential 64-bit ptr to 32-bit int cast */
   src_offset += (GLuint) (unsigned long) pixels;

   int src_stride =
      _mesa_image_row_stride(unpack, image->Width, format, type);

   struct intel_mipmap_tree *pbo_mt =
      intel_miptree_create_for_bo(intel,
                                  src_buffer,
                                  intelImage->mt->format,
                                  src_offset,
                                  image->Width, image->Height,
                                  src_stride, I915_TILING_NONE);
   if (!pbo_mt)
      return false;

   if (!intel_miptree_blit(intel,
                           pbo_mt, 0, 0,
                           0, 0, false,
                           intelImage->mt, image->Level, image->Face,
                           0, 0, false,
                           image->Width, image->Height, GL_COPY)) {
      DBG("%s: blit failed\n", __FUNCTION__);
      intel_miptree_release(&pbo_mt);
      return false;
   }

   intel_miptree_release(&pbo_mt);

   DBG("%s: success\n", __FUNCTION__);
   return true;
}
static bool
do_blit_drawpixels(struct gl_context * ctx,
		   GLint x, GLint y, GLsizei width, GLsizei height,
		   GLenum format, GLenum type,
		   const struct gl_pixelstore_attrib *unpack,
		   const GLvoid * pixels)
{
   struct brw_context *brw = brw_context(ctx);
   struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj);
   GLuint src_offset;
   drm_intel_bo *src_buffer;

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

   if (!intel_check_blit_fragment_ops(ctx, false))
      return false;

   if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) {
      DBG("%s: fallback due to MRT\n", __FUNCTION__);
      return false;
   }

   struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
   struct intel_renderbuffer *irb = intel_renderbuffer(rb);

   if (!_mesa_format_matches_format_and_type(irb->mt->format, format, type,
                                             false)) {
      DBG("%s: bad format for blit\n", __FUNCTION__);
      return false;
   }

   if (unpack->SwapBytes || unpack->LsbFirst ||
       unpack->SkipPixels || unpack->SkipRows) {
      DBG("%s: bad packing params\n", __FUNCTION__);
      return false;
   }

   int src_stride = _mesa_image_row_stride(unpack, width, format, type);
   bool src_flip = false;
   /* Mesa flips the src_stride for unpack->Invert, but we want our mt to have
    * a normal src_stride.
    */
   if (unpack->Invert) {
      src_stride = -src_stride;
      src_flip = true;
   }

   src_offset = (GLintptr)pixels;
   src_offset += _mesa_image_offset(2, unpack, width, height,
				    format, type, 0, 0, 0);

   intel_prepare_render(brw);

   src_buffer = intel_bufferobj_buffer(brw, src,
				       src_offset, width * height *
                                       irb->mt->cpp);

   struct intel_mipmap_tree *pbo_mt =
      intel_miptree_create_for_bo(brw,
                                  src_buffer,
                                  irb->mt->format,
                                  src_offset,
                                  width, height,
                                  src_stride, I915_TILING_NONE);
   if (!pbo_mt)
      return false;

   if (!intel_miptree_blit(brw,
                           pbo_mt, 0, 0,
                           0, 0, src_flip,
                           irb->mt, irb->mt_level, irb->mt_layer,
                           x, y, _mesa_is_winsys_fbo(ctx->DrawBuffer),
                           width, height, GL_COPY)) {
      DBG("%s: blit failed\n", __FUNCTION__);
      intel_miptree_release(&pbo_mt);
      return false;
   }

   intel_miptree_release(&pbo_mt);

   if (ctx->Query.CurrentOcclusionObject)
      ctx->Query.CurrentOcclusionObject->Result += width * height;

   intel_check_front_buffer_rendering(brw);

   DBG("%s: success\n", __FUNCTION__);
   return true;
}
Example #15
0
static struct gl_texture_image *
create_texture_for_pbo(struct gl_context *ctx,
                       bool create_pbo, GLenum pbo_target,
                       int dims, int width, int height, int depth,
                       GLenum format, GLenum type, const void *pixels,
                       const struct gl_pixelstore_attrib *packing,
                       struct gl_buffer_object **tmp_pbo, GLuint *tmp_tex)
{
   uint32_t pbo_format;
   GLenum internal_format;
   unsigned row_stride;
   struct gl_buffer_object *buffer_obj;
   struct gl_texture_object *tex_obj;
   struct gl_texture_image *tex_image;
   bool read_only;

   if (packing->SwapBytes ||
       packing->LsbFirst ||
       packing->Invert)
      return NULL;

   pbo_format = _mesa_format_from_format_and_type(format, type);
   if (_mesa_format_is_mesa_array_format(pbo_format))
      pbo_format = _mesa_format_from_array_format(pbo_format);

   if (!pbo_format || !ctx->TextureFormatSupported[pbo_format])
      return NULL;

   /* Account for SKIP_PIXELS, SKIP_ROWS, ALIGNMENT, and SKIP_IMAGES */
   uint32_t first_pixel = _mesa_image_offset(dims, packing, width, height,
                                             format, type,
                                             0, 0, 0);
   uint32_t last_pixel =  _mesa_image_offset(dims, packing, width, height,
                                             format, type,
                                             depth-1, height-1, width);
   row_stride = _mesa_image_row_stride(packing, width, format, type);

   if (_mesa_is_bufferobj(packing->BufferObj)) {
      *tmp_pbo = NULL;
      buffer_obj = packing->BufferObj;
      first_pixel += (intptr_t)pixels;
   } else {
      bool is_pixel_pack = pbo_target == GL_PIXEL_PACK_BUFFER;

      assert(create_pbo);

      *tmp_pbo = ctx->Driver.NewBufferObject(ctx, 0xDEADBEEF);
      if (*tmp_pbo == NULL)
         return NULL;

      /* In case of GL_PIXEL_PACK_BUFFER, pass null pointer for the pixel
       * data to avoid unnecessary data copying in _mesa_buffer_data.
       */
      if (is_pixel_pack)
         _mesa_buffer_data(ctx, *tmp_pbo, GL_NONE,
                           last_pixel - first_pixel,
                           NULL,
                           GL_STREAM_READ,
                           __func__);
      else
         _mesa_buffer_data(ctx, *tmp_pbo, GL_NONE,
                           last_pixel - first_pixel,
                           (char *)pixels + first_pixel,
                           GL_STREAM_DRAW,
                           __func__);

      buffer_obj = *tmp_pbo;
      first_pixel = 0;
   }

   _mesa_GenTextures(1, tmp_tex);
   tex_obj = _mesa_lookup_texture(ctx, *tmp_tex);
   _mesa_initialize_texture_object(ctx, tex_obj, *tmp_tex, GL_TEXTURE_2D);
   /* This must be set after _mesa_initialize_texture_object, not before. */
   tex_obj->Immutable = GL_TRUE;
   /* This is required for interactions with ARB_texture_view. */
   tex_obj->NumLayers = 1;

   internal_format = _mesa_get_format_base_format(pbo_format);

   /* The texture is addressed as a single very-tall image, so we
    * need to pack the multiple image depths together taking the
    * inter-image padding into account.
    */
   int image_height = packing->ImageHeight == 0 ? height : packing->ImageHeight;
   int full_height = image_height * (depth - 1) + height;

   tex_image = _mesa_get_tex_image(ctx, tex_obj, tex_obj->Target, 0);
   _mesa_init_teximage_fields(ctx, tex_image, width, full_height, 1,
                              0, internal_format, pbo_format);

   read_only = pbo_target == GL_PIXEL_UNPACK_BUFFER;
   if (!ctx->Driver.SetTextureStorageForBufferObject(ctx, tex_obj,
                                                     buffer_obj,
                                                     first_pixel,
                                                     row_stride,
                                                     read_only)) {
      _mesa_DeleteTextures(1, tmp_tex);
      _mesa_reference_buffer_object(ctx, tmp_pbo, NULL);
      return NULL;
   }

   return tex_image;
}
Example #16
0
static bool
do_blit_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 brw_context *brw = brw_context(ctx);
   struct intel_buffer_object *dst = intel_buffer_object(pack->BufferObj);
   GLuint dst_offset;
   drm_intel_bo *dst_buffer;
   GLint dst_x, dst_y;
   GLuint dirty;

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

   assert(_mesa_is_bufferobj(pack->BufferObj));

   struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
   struct intel_renderbuffer *irb = intel_renderbuffer(rb);

   if (ctx->_ImageTransferState ||
       !_mesa_format_matches_format_and_type(irb->mt->format, format, type,
                                             false)) {
      DBG("%s - bad format for blit\n", __FUNCTION__);
      return false;
   }

   if (pack->SwapBytes || pack->LsbFirst) {
      DBG("%s: bad packing params\n", __FUNCTION__);
      return false;
   }

   int dst_stride = _mesa_image_row_stride(pack, width, format, type);
   bool dst_flip = false;
   /* Mesa flips the dst_stride for pack->Invert, but we want our mt to have a
    * normal dst_stride.
    */
   struct gl_pixelstore_attrib uninverted_pack = *pack;
   if (pack->Invert) {
      dst_stride = -dst_stride;
      dst_flip = true;
      uninverted_pack.Invert = false;
   }

   dst_offset = (GLintptr)pixels;
   dst_offset += _mesa_image_offset(2, &uninverted_pack, width, height,
				    format, type, 0, 0, 0);

   if (!_mesa_clip_copytexsubimage(ctx,
				   &dst_x, &dst_y,
				   &x, &y,
				   &width, &height)) {
      return true;
   }

   dirty = brw->front_buffer_dirty;
   intel_prepare_render(brw);
   brw->front_buffer_dirty = dirty;

   dst_buffer = intel_bufferobj_buffer(brw, dst,
				       dst_offset, height * dst_stride);

   struct intel_mipmap_tree *pbo_mt =
      intel_miptree_create_for_bo(brw,
                                  dst_buffer,
                                  irb->mt->format,
                                  dst_offset,
                                  width, height,
                                  dst_stride, I915_TILING_NONE);

   if (!intel_miptree_blit(brw,
                           irb->mt, irb->mt_level, irb->mt_layer,
                           x, y, _mesa_is_winsys_fbo(ctx->ReadBuffer),
                           pbo_mt, 0, 0,
                           0, 0, dst_flip,
                           width, height, GL_COPY)) {
      return false;
   }

   intel_miptree_release(&pbo_mt);

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

   return true;
}
Example #17
0
static struct gl_texture_image *
create_texture_for_pbo(struct gl_context *ctx, bool create_pbo,
                       GLenum pbo_target, int width, int height,
                       GLenum format, GLenum type, const void *pixels,
                       const struct gl_pixelstore_attrib *packing,
                       GLuint *tmp_pbo, GLuint *tmp_tex)
{
   uint32_t pbo_format;
   GLenum internal_format;
   unsigned row_stride;
   struct gl_buffer_object *buffer_obj;
   struct gl_texture_object *tex_obj;
   struct gl_texture_image *tex_image;
   bool read_only;

   if (packing->SwapBytes ||
       packing->LsbFirst ||
       packing->Invert)
      return NULL;

   pbo_format = _mesa_format_from_format_and_type(format, type);
   if (_mesa_format_is_mesa_array_format(pbo_format))
      pbo_format = _mesa_format_from_array_format(pbo_format);

   if (!pbo_format || !ctx->TextureFormatSupported[pbo_format])
      return NULL;

   /* Account for SKIP_PIXELS, SKIP_ROWS, ALIGNMENT, and SKIP_IMAGES */
   pixels = _mesa_image_address3d(packing, pixels,
                                  width, height, format, type, 0, 0, 0);
   row_stride = _mesa_image_row_stride(packing, width, format, type);

   if (_mesa_is_bufferobj(packing->BufferObj)) {
      *tmp_pbo = 0;
      buffer_obj = packing->BufferObj;
   } else {
      bool is_pixel_pack = pbo_target == GL_PIXEL_PACK_BUFFER;

      assert(create_pbo);

      _mesa_GenBuffers(1, tmp_pbo);

      /* We are not doing this inside meta_begin/end.  However, we know the
       * client doesn't have the given target bound, so we can go ahead and
       * squash it.  We'll set it back when we're done.
       */
      _mesa_BindBuffer(pbo_target, *tmp_pbo);

      /* In case of GL_PIXEL_PACK_BUFFER, pass null pointer for the pixel
       * data to avoid unnecessary data copying in _mesa_BufferData().
       */
      if (is_pixel_pack)
         _mesa_BufferData(pbo_target, row_stride * height, NULL,
                          GL_STREAM_READ);
      else
         _mesa_BufferData(pbo_target, row_stride * height, pixels,
                          GL_STREAM_DRAW);

      buffer_obj = packing->BufferObj;
      pixels = NULL;

      _mesa_BindBuffer(pbo_target, 0);
   }

   _mesa_GenTextures(1, tmp_tex);
   tex_obj = _mesa_lookup_texture(ctx, *tmp_tex);
   _mesa_initialize_texture_object(ctx, tex_obj, *tmp_tex, GL_TEXTURE_2D);
   /* This must be set after _mesa_initialize_texture_object, not before. */
   tex_obj->Immutable = GL_TRUE;
   /* This is required for interactions with ARB_texture_view. */
   tex_obj->NumLayers = 1;

   internal_format = _mesa_get_format_base_format(pbo_format);

   tex_image = _mesa_get_tex_image(ctx, tex_obj, tex_obj->Target, 0);
   _mesa_init_teximage_fields(ctx, tex_image, width, height, 1,
                              0, internal_format, pbo_format);

   read_only = pbo_target == GL_PIXEL_UNPACK_BUFFER;
   if (!ctx->Driver.SetTextureStorageForBufferObject(ctx, tex_obj,
                                                     buffer_obj,
                                                     (intptr_t)pixels,
                                                     row_stride,
                                                     read_only)) {
      _mesa_DeleteTextures(1, tmp_tex);
      _mesa_DeleteBuffers(1, tmp_pbo);
      return NULL;
   }

   return tex_image;
}
Example #18
0
/**
 * Get a color texture image with decompression.
 */
static void
get_tex_rgba_compressed(struct gl_context *ctx, GLuint dimensions,
                        GLenum format, GLenum type, GLvoid *pixels,
                        struct gl_texture_image *texImage,
                        GLbitfield transferOps)
{
   /* don't want to apply sRGB -> RGB conversion here so override the format */
   const mesa_format texFormat =
      _mesa_get_srgb_format_linear(texImage->TexFormat);
   const GLenum baseFormat = _mesa_get_format_base_format(texFormat);
   const GLuint width = texImage->Width;
   const GLuint height = texImage->Height;
   const GLuint depth = texImage->Depth;
   GLfloat *tempImage, *tempSlice;
   GLuint slice;
   int srcStride, dstStride;
   uint32_t dstFormat;
   bool needsRebase;
   uint8_t rebaseSwizzle[4];

   /* Decompress into temp float buffer, then pack into user buffer */
   tempImage = malloc(width * height * depth
                                  * 4 * sizeof(GLfloat));
   if (!tempImage) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()");
      return;
   }

   /* Decompress the texture image slices - results in 'tempImage' */
   for (slice = 0; slice < depth; slice++) {
      GLubyte *srcMap;
      GLint srcRowStride;

      tempSlice = tempImage + slice * 4 * width * height;

      ctx->Driver.MapTextureImage(ctx, texImage, slice,
                                  0, 0, width, height,
                                  GL_MAP_READ_BIT,
                                  &srcMap, &srcRowStride);
      if (srcMap) {
         _mesa_decompress_image(texFormat, width, height,
                                srcMap, srcRowStride, tempSlice);

         ctx->Driver.UnmapTextureImage(ctx, texImage, slice);
      }
      else {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
         free(tempImage);
         return;
      }
   }

   /* Depending on the base format involved we may need to apply a rebase
    * transform (for example: if we download to a Luminance format we want
    * G=0 and B=0).
    */
   if (baseFormat == GL_LUMINANCE ||
       baseFormat == GL_INTENSITY) {
      needsRebase = true;
      rebaseSwizzle[0] = MESA_FORMAT_SWIZZLE_X;
      rebaseSwizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
      rebaseSwizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
      rebaseSwizzle[3] = MESA_FORMAT_SWIZZLE_ONE;
   } else if (baseFormat == GL_LUMINANCE_ALPHA) {
      needsRebase = true;
      rebaseSwizzle[0] = MESA_FORMAT_SWIZZLE_X;
      rebaseSwizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
      rebaseSwizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
      rebaseSwizzle[3] = MESA_FORMAT_SWIZZLE_W;
   } else {
      needsRebase = false;
   }

   srcStride = 4 * width * sizeof(GLfloat);
   dstStride = _mesa_image_row_stride(&ctx->Pack, width, format, type);
   dstFormat = _mesa_format_from_format_and_type(format, type);
   tempSlice = tempImage;
   for (slice = 0; slice < depth; slice++) {
      void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
                                       width, height, format, type,
                                       slice, 0, 0);
//      _mesa_format_convert(dest, dstFormat, dstStride,
//                           tempSlice, RGBA32_FLOAT, srcStride,
//                           width, height,
//                           needsRebase ? rebaseSwizzle : NULL);
      tempSlice += 4 * width * height;
   }

   free(tempImage);
}
Example #19
0
/**
 * Try to do glGetTexImage() with simple memcpy().
 * \return GL_TRUE if done, GL_FALSE otherwise
 */
static GLboolean
get_tex_memcpy(GLcontext *ctx, GLenum format, GLenum type, GLvoid *pixels,
               const struct gl_texture_object *texObj,
               const struct gl_texture_image *texImage)
{
   GLboolean memCopy = GL_FALSE;

   /* Texture image should have been mapped already */
   assert(texImage->Data);

   /*
    * Check if the src/dst formats are compatible.
    * Also note that GL's pixel transfer ops don't apply to glGetTexImage()
    * so we don't have to worry about those.
    * XXX more format combinations could be supported here.
    */
   if ((texObj->Target == GL_TEXTURE_1D ||
        texObj->Target == GL_TEXTURE_2D ||
        texObj->Target == GL_TEXTURE_RECTANGLE ||
        (texObj->Target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
         texObj->Target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))) {
      if (texImage->TexFormat == MESA_FORMAT_ARGB8888 &&
          format == GL_BGRA &&
          type == GL_UNSIGNED_BYTE &&
          !ctx->Pack.SwapBytes &&
          _mesa_little_endian()) {
         memCopy = GL_TRUE;
      }
      else if (texImage->TexFormat == MESA_FORMAT_AL88 &&
               format == GL_LUMINANCE_ALPHA &&
               type == GL_UNSIGNED_BYTE &&
               !ctx->Pack.SwapBytes &&
               _mesa_little_endian()) {
         memCopy = GL_TRUE;
      }
      else if (texImage->TexFormat == MESA_FORMAT_L8 &&
               format == GL_LUMINANCE &&
               type == GL_UNSIGNED_BYTE) {
         memCopy = GL_TRUE;
      }
      else if (texImage->TexFormat == MESA_FORMAT_A8 &&
               format == GL_ALPHA &&
               type == GL_UNSIGNED_BYTE) {
         memCopy = GL_TRUE;
      }
   }

   if (memCopy) {
      const GLuint bpp = _mesa_get_format_bytes(texImage->TexFormat);
      const GLuint bytesPerRow = texImage->Width * bpp;
      GLubyte *dst =
         _mesa_image_address2d(&ctx->Pack, pixels, texImage->Width,
                               texImage->Height, format, type, 0, 0);
      const GLint dstRowStride =
         _mesa_image_row_stride(&ctx->Pack, texImage->Width, format, type);
      const GLubyte *src = texImage->Data;
      const GLint srcRowStride = texImage->RowStride * bpp;
      GLuint row;

      if (bytesPerRow == dstRowStride && bytesPerRow == srcRowStride) {
         memcpy(dst, src, bytesPerRow * texImage->Height);
      }
      else {
         for (row = 0; row < texImage->Height; row++) {
            memcpy(dst, src, bytesPerRow);
            dst += dstRowStride;
            src += srcRowStride;
         }
      }
   }

   return memCopy;
}
Example #20
0
/**
 * Try to do a fast and simple RGB(a) glDrawPixels.
 * Return:  GL_TRUE if success, GL_FALSE if slow path must be used instead
 */
static GLboolean
fast_draw_rgba_pixels(struct gl_context *ctx, GLint x, GLint y,
                      GLsizei width, GLsizei height,
                      GLenum format, GLenum type,
                      const struct gl_pixelstore_attrib *userUnpack,
                      const GLvoid *pixels)
{
   const GLint imgX = x, imgY = y;
   struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
   GLenum rbType;
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   SWspan span;
   GLboolean simpleZoom;
   GLint yStep;  /* +1 or -1 */
   struct gl_pixelstore_attrib unpack;
   GLint destX, destY, drawWidth, drawHeight; /* post clipping */

   if (!rb)
      return GL_TRUE; /* no-op */

   rbType = rb->DataType;

   if ((swrast->_RasterMask & ~CLIP_BIT) ||
       ctx->Texture._EnabledCoordUnits ||
       userUnpack->SwapBytes ||
       ctx->_ImageTransferState) {
      /* can't handle any of those conditions */
      return GL_FALSE;
   }

   INIT_SPAN(span, GL_BITMAP);
   span.arrayMask = SPAN_RGBA;
   span.arrayAttribs = FRAG_BIT_COL0;
   _swrast_span_default_attribs(ctx, &span);

   /* copy input params since clipping may change them */
   unpack = *userUnpack;
   destX = x;
   destY = y;
   drawWidth = width;
   drawHeight = height;

   /* check for simple zooming and clipping */
   if (ctx->Pixel.ZoomX == 1.0F &&
       (ctx->Pixel.ZoomY == 1.0F || ctx->Pixel.ZoomY == -1.0F)) {
      if (!_mesa_clip_drawpixels(ctx, &destX, &destY,
                                 &drawWidth, &drawHeight, &unpack)) {
         /* image was completely clipped: no-op, all done */
         return GL_TRUE;
      }
      simpleZoom = GL_TRUE;
      yStep = (GLint) ctx->Pixel.ZoomY;
      ASSERT(yStep == 1 || yStep == -1);
   }
   else {
      /* non-simple zooming */
      simpleZoom = GL_FALSE;
      yStep = 1;
      if (unpack.RowLength == 0)
         unpack.RowLength = width;
   }

   /*
    * Ready to draw!
    */

   if (format == GL_RGBA && type == rbType) {
      const GLubyte *src
         = (const GLubyte *) _mesa_image_address2d(&unpack, pixels, width,
                                                   height, format, type, 0, 0);
      const GLint srcStride = _mesa_image_row_stride(&unpack, width,
                                                     format, type);
      if (simpleZoom) {
         GLint row;
         for (row = 0; row < drawHeight; row++) {
            rb->PutRow(ctx, rb, drawWidth, destX, destY, src, NULL);
            src += srcStride;
            destY += yStep;
         }
      }
      else {
         /* with zooming */
         GLint row;
         for (row = 0; row < drawHeight; row++) {
            span.x = destX;
            span.y = destY + row;
            span.end = drawWidth;
            span.array->ChanType = rbType;
            _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, src);
            src += srcStride;
         }
         span.array->ChanType = CHAN_TYPE;
      }
      return GL_TRUE;
   }

   if (format == GL_RGB && type == rbType) {
      const GLubyte *src
         = (const GLubyte *) _mesa_image_address2d(&unpack, pixels, width,
                                                   height, format, type, 0, 0);
      const GLint srcStride = _mesa_image_row_stride(&unpack, width,
                                                     format, type);
      if (simpleZoom) {
         GLint row;
         for (row = 0; row < drawHeight; row++) {
            rb->PutRowRGB(ctx, rb, drawWidth, destX, destY, src, NULL);
            src += srcStride;
            destY += yStep;
         }
      }
      else {
         /* with zooming */
         GLint row;
         for (row = 0; row < drawHeight; row++) {
            span.x = destX;
            span.y = destY;
            span.end = drawWidth;
            span.array->ChanType = rbType;
            _swrast_write_zoomed_rgb_span(ctx, imgX, imgY, &span, src);
            src += srcStride;
            destY++;
         }
         span.array->ChanType = CHAN_TYPE;
      }
      return GL_TRUE;
   }

   /* Remaining cases haven't been tested with alignment != 1 */
   if (userUnpack->Alignment != 1)
      return GL_FALSE;

   if (format == GL_LUMINANCE && type == CHAN_TYPE && rbType == CHAN_TYPE) {
      const GLchan *src = (const GLchan *) pixels
         + (unpack.SkipRows * unpack.RowLength + unpack.SkipPixels);
      if (simpleZoom) {
         /* no zooming */
         GLint row;
         ASSERT(drawWidth <= MAX_WIDTH);
         for (row = 0; row < drawHeight; row++) {
            GLchan rgb[MAX_WIDTH][3];
            GLint i;
            for (i = 0;i<drawWidth;i++) {
               rgb[i][0] = src[i];
               rgb[i][1] = src[i];
               rgb[i][2] = src[i];
            }
            rb->PutRowRGB(ctx, rb, drawWidth, destX, destY, rgb, NULL);
            src += unpack.RowLength;
            destY += yStep;
         }
      }
      else {
         /* with zooming */
         GLint row;
         ASSERT(drawWidth <= MAX_WIDTH);
         for (row = 0; row < drawHeight; row++) {
            GLchan rgb[MAX_WIDTH][3];
            GLint i;
            for (i = 0;i<drawWidth;i++) {
               rgb[i][0] = src[i];
               rgb[i][1] = src[i];
               rgb[i][2] = src[i];
            }
            span.x = destX;
            span.y = destY;
            span.end = drawWidth;
            _swrast_write_zoomed_rgb_span(ctx, imgX, imgY, &span, rgb);
            src += unpack.RowLength;
            destY++;
         }
      }
      return GL_TRUE;
   }

   if (format == GL_LUMINANCE_ALPHA && type == CHAN_TYPE && rbType == CHAN_TYPE) {
      const GLchan *src = (const GLchan *) pixels
         + (unpack.SkipRows * unpack.RowLength + unpack.SkipPixels)*2;
      if (simpleZoom) {
         GLint row;
         ASSERT(drawWidth <= MAX_WIDTH);
         for (row = 0; row < drawHeight; row++) {
            GLint i;
            const GLchan *ptr = src;
            for (i = 0;i<drawWidth;i++) {
               span.array->rgba[i][0] = *ptr;
               span.array->rgba[i][1] = *ptr;
               span.array->rgba[i][2] = *ptr++;
               span.array->rgba[i][3] = *ptr++;
            }
            rb->PutRow(ctx, rb, drawWidth, destX, destY,
                       span.array->rgba, NULL);
            src += unpack.RowLength*2;
            destY += yStep;
         }
      }
      else {
         /* with zooming */
         GLint row;
         ASSERT(drawWidth <= MAX_WIDTH);
         for (row = 0; row < drawHeight; row++) {
            const GLchan *ptr = src;
            GLint i;
            for (i = 0;i<drawWidth;i++) {
               span.array->rgba[i][0] = *ptr;
               span.array->rgba[i][1] = *ptr;
               span.array->rgba[i][2] = *ptr++;
               span.array->rgba[i][3] = *ptr++;
            }
            span.x = destX;
            span.y = destY;
            span.end = drawWidth;
            _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span,
                                           span.array->rgba);
            src += unpack.RowLength*2;
            destY++;
         }
      }
      return GL_TRUE;
   }

   if (format == GL_COLOR_INDEX && type == GL_UNSIGNED_BYTE) {
      const GLubyte *src = (const GLubyte *) pixels
         + unpack.SkipRows * unpack.RowLength + unpack.SkipPixels;
      if (rbType == GL_UNSIGNED_BYTE) {
         /* convert ubyte/CI data to ubyte/RGBA */
         if (simpleZoom) {
            GLint row;
            for (row = 0; row < drawHeight; row++) {
               ASSERT(drawWidth <= MAX_WIDTH);
               _mesa_map_ci8_to_rgba8(ctx, drawWidth, src,
                                      span.array->rgba8);
               rb->PutRow(ctx, rb, drawWidth, destX, destY,
                          span.array->rgba8, NULL);
               src += unpack.RowLength;
               destY += yStep;
            }
         }
         else {
            /* ubyte/CI to ubyte/RGBA with zooming */
            GLint row;
            for (row = 0; row < drawHeight; row++) {
               ASSERT(drawWidth <= MAX_WIDTH);
               _mesa_map_ci8_to_rgba8(ctx, drawWidth, src,
                                      span.array->rgba8);
               span.x = destX;
               span.y = destY;
               span.end = drawWidth;
               _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span,
                                              span.array->rgba8);
               src += unpack.RowLength;
               destY++;
            }
         }
         return GL_TRUE;
      }
   }

   /* can't handle this pixel format and/or data type */
   return GL_FALSE;
}
Example #21
0
/**
 * \brief A fast path for glGetTexImage.
 *
 * \see intel_readpixels_tiled_memcpy()
 */
bool
intel_gettexsubimage_tiled_memcpy(struct gl_context *ctx,
                                  struct gl_texture_image *texImage,
                                  GLint xoffset, GLint yoffset,
                                  GLsizei width, GLsizei height,
                                  GLenum format, GLenum type,
                                  GLvoid *pixels,
                                  const struct gl_pixelstore_attrib *packing)
{
   struct brw_context *brw = brw_context(ctx);
   struct intel_texture_image *image = intel_texture_image(texImage);
   int dst_pitch;

   /* The miptree's buffer. */
   drm_intel_bo *bo;

   int error = 0;

   uint32_t cpp;
   mem_copy_fn mem_copy = NULL;

   /* This fastpath is restricted to specific texture types:
    * a 2D BGRA, RGBA, L8 or A8 texture. It could be generalized to support
    * more types.
    *
    * FINISHME: The restrictions below on packing alignment and packing row
    * length are likely unneeded now because we calculate the destination stride
    * with _mesa_image_row_stride. However, before removing the restrictions
    * we need tests.
    */
   if (!brw->has_llc ||
       !(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT_8_8_8_8_REV) ||
       !(texImage->TexObject->Target == GL_TEXTURE_2D ||
         texImage->TexObject->Target == GL_TEXTURE_RECTANGLE) ||
       pixels == NULL ||
       _mesa_is_bufferobj(packing->BufferObj) ||
       packing->Alignment > 4 ||
       packing->SkipPixels > 0 ||
       packing->SkipRows > 0 ||
       (packing->RowLength != 0 && packing->RowLength != width) ||
       packing->SwapBytes ||
       packing->LsbFirst ||
       packing->Invert)
      return false;

   /* We can't handle copying from RGBX or BGRX because the tiled_memcpy
    * function doesn't set the last channel to 1.
    */
   if (texImage->TexFormat == MESA_FORMAT_B8G8R8X8_UNORM ||
       texImage->TexFormat == MESA_FORMAT_R8G8B8X8_UNORM)
      return false;

   if (!intel_get_memcpy(texImage->TexFormat, format, type, &mem_copy, &cpp,
                         INTEL_DOWNLOAD))
      return false;

   /* If this is a nontrivial texture view, let another path handle it instead. */
   if (texImage->TexObject->MinLayer)
      return false;

   if (!image->mt ||
       (image->mt->tiling != I915_TILING_X &&
       image->mt->tiling != I915_TILING_Y)) {
      /* The algorithm is written only for X- or Y-tiled memory. */
      return false;
   }

   /* Since we are going to write raw data to the miptree, we need to resolve
    * any pending fast color clears before we start.
    */
   intel_miptree_resolve_color(brw, image->mt);

   bo = image->mt->bo;

   if (drm_intel_bo_references(brw->batch.bo, bo)) {
      perf_debug("Flushing before mapping a referenced bo.\n");
      intel_batchbuffer_flush(brw);
   }

   error = brw_bo_map(brw, bo, false /* write enable */, "miptree");
   if (error) {
      DBG("%s: failed to map bo\n", __func__);
      return false;
   }

   dst_pitch = _mesa_image_row_stride(packing, width, format, type);

   DBG("%s: level=%d x,y=(%d,%d) (w,h)=(%d,%d) format=0x%x type=0x%x "
       "mesa_format=0x%x tiling=%d "
       "packing=(alignment=%d row_length=%d skip_pixels=%d skip_rows=%d)\n",
       __func__, texImage->Level, xoffset, yoffset, width, height,
       format, type, texImage->TexFormat, image->mt->tiling,
       packing->Alignment, packing->RowLength, packing->SkipPixels,
       packing->SkipRows);

   int level = texImage->Level + texImage->TexObject->MinLevel;

   /* Adjust x and y offset based on miplevel */
   xoffset += image->mt->level[level].level_x;
   yoffset += image->mt->level[level].level_y;

   tiled_to_linear(
      xoffset * cpp, (xoffset + width) * cpp,
      yoffset, yoffset + height,
      pixels - (ptrdiff_t) yoffset * dst_pitch - (ptrdiff_t) xoffset * cpp,
      bo->virtual,
      dst_pitch, image->mt->pitch,
      brw->has_swizzling,
      image->mt->tiling,
      mem_copy
   );

   drm_intel_bo_unmap(bo);
   return true;
}
Example #22
0
/**
 * Store a combined depth/stencil texture image.
 */
static GLboolean
_mesa_texstore_s8_z24(TEXSTORE_PARAMS)
{
   const GLuint depthScale = 0xffffff;
   const GLint srcRowStride
      = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
   GLint img, row;
   GLuint *depth;
   GLubyte *stencil;

   assert(dstFormat == MESA_FORMAT_Z24_UNORM_S8_UINT);
   assert(srcFormat == GL_DEPTH_STENCIL_EXT ||
          srcFormat == GL_DEPTH_COMPONENT ||
          srcFormat == GL_STENCIL_INDEX);
   assert(srcFormat != GL_DEPTH_STENCIL_EXT ||
          srcType == GL_UNSIGNED_INT_24_8_EXT ||
          srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);

   depth = malloc(srcWidth * sizeof(GLuint));
   stencil = malloc(srcWidth * sizeof(GLubyte));

   if (!depth || !stencil) {
      free(depth);
      free(stencil);
      return GL_FALSE;
   }

   for (img = 0; img < srcDepth; img++) {
      GLuint *dstRow = (GLuint *) dstSlices[img];
      const GLubyte *src
	 = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
						srcWidth, srcHeight,
						srcFormat, srcType,
						img, 0, 0);
      for (row = 0; row < srcHeight; row++) {
	 GLint i;
	 GLboolean keepdepth = GL_FALSE, keepstencil = GL_FALSE;
	 
	 if (srcFormat == GL_DEPTH_COMPONENT) { /* preserve stencil */
	    keepstencil = GL_TRUE;
	 }
         else if (srcFormat == GL_STENCIL_INDEX) { /* preserve depth */
	    keepdepth = GL_TRUE;
	 }

	 if (keepdepth == GL_FALSE)
	    /* the 24 depth bits will be in the low position: */
	    _mesa_unpack_depth_span(ctx, srcWidth,
				    GL_UNSIGNED_INT, /* dst type */
				    keepstencil ? depth : dstRow, /* dst addr */
				    depthScale,
				    srcType, src, srcPacking);	 

	 if (keepstencil == GL_FALSE)
	    /* get the 8-bit stencil values */
	    _mesa_unpack_stencil_span(ctx, srcWidth,
				      GL_UNSIGNED_BYTE, /* dst type */
				      stencil, /* dst addr */
				      srcType, src, srcPacking,
				      ctx->_ImageTransferState);

	 /* merge stencil values into depth values */
	 for (i = 0; i < srcWidth; i++) {
	    if (keepstencil)
	       dstRow[i] = depth[i] | (dstRow[i] & 0xFF000000);
	    else
	       dstRow[i] = (dstRow[i] & 0xFFFFFF) | (stencil[i] << 24);

	 }
	 src += srcRowStride;
	 dstRow += dstRowStride / sizeof(GLuint);
      }
   }

   free(depth);
   free(stencil);

   return GL_TRUE;
}
Example #23
0
/*
 * Read R, G, B, A, RGB, L, or LA pixels.
 */
static void
read_rgba_pixels( struct gl_context *ctx,
                  GLint x, GLint y,
                  GLsizei width, GLsizei height,
                  GLenum format, GLenum type, GLvoid *pixels,
                  const struct gl_pixelstore_attrib *packing )
{
   GLbitfield transferOps;
   bool dst_is_integer, dst_is_luminance, needs_rebase;
   int dst_stride, src_stride, rb_stride;
   uint32_t dst_format, src_format;
   GLubyte *dst, *map;
   mesa_format rb_format;
   bool needs_rgba;
   void *rgba, *src;
   bool src_is_uint = false;
   uint8_t rebase_swizzle[4];
   struct gl_framebuffer *fb = ctx->ReadBuffer;
   struct gl_renderbuffer *rb = fb->_ColorReadBuffer;

   if (!rb)
      return;

   transferOps = get_readpixels_transfer_ops(ctx, rb->Format, format, type,
                                             GL_FALSE);
   /* Describe the dst format */
   dst_is_integer = _mesa_is_enum_format_integer(format);
   dst_stride = _mesa_image_row_stride(packing, width, format, type);
   dst_format = _mesa_format_from_format_and_type(format, type);
   dst_is_luminance = format == GL_LUMINANCE ||
                      format == GL_LUMINANCE_ALPHA ||
                      format == GL_LUMINANCE_INTEGER_EXT ||
                      format == GL_LUMINANCE_ALPHA_INTEGER_EXT;
   dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
                                           format, type, 0, 0);

   /* Map the source render buffer */
   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
                               &map, &rb_stride);
   if (!map) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
      return;
   }
   rb_format = _mesa_get_srgb_format_linear(rb->Format);

   /*
    * Depending on the base formats involved in the conversion we might need to
    * rebase some values, so for these formats we compute a rebase swizzle.
    */
   if (rb->_BaseFormat == GL_LUMINANCE || rb->_BaseFormat == GL_INTENSITY) {
      needs_rebase = true;
      rebase_swizzle[0] = MESA_FORMAT_SWIZZLE_X;
      rebase_swizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
      rebase_swizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
      rebase_swizzle[3] = MESA_FORMAT_SWIZZLE_ONE;
   } else if (rb->_BaseFormat == GL_LUMINANCE_ALPHA) {
      needs_rebase = true;
      rebase_swizzle[0] = MESA_FORMAT_SWIZZLE_X;
      rebase_swizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
      rebase_swizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
      rebase_swizzle[3] = MESA_FORMAT_SWIZZLE_W;
   } else if (_mesa_get_format_base_format(rb_format) != rb->_BaseFormat) {
      needs_rebase =
         _mesa_compute_rgba2base2rgba_component_mapping(rb->_BaseFormat,
                                                        rebase_swizzle);
   } else {
      needs_rebase = false;
   }

   /* Since _mesa_format_convert does not handle transferOps we need to handle
    * them before we call the function. This requires to convert to RGBA float
    * first so we can call _mesa_apply_rgba_transfer_ops. If the dst format is
    * integer transferOps do not apply.
    *
    * Converting to luminance also requires converting to RGBA first, so we can
    * then compute luminance values as L=R+G+B. Notice that this is different
    * from GetTexImage, where we compute L=R.
    */
   assert(!transferOps || (transferOps && !dst_is_integer));

   needs_rgba = transferOps || dst_is_luminance;
   rgba = NULL;
   if (needs_rgba) {
      uint32_t rgba_format;
      int rgba_stride;
      bool need_convert;

      /* Convert to RGBA float or int/uint depending on the type of the src */
      if (dst_is_integer) {
         src_is_uint = _mesa_is_format_unsigned(rb_format);
         if (src_is_uint) {
            rgba_format = RGBA32_UINT;
            rgba_stride = width * 4 * sizeof(GLuint);
         } else {
            rgba_format = RGBA32_INT;
            rgba_stride = width * 4 * sizeof(GLint);
         }
      } else {
         rgba_format = RGBA32_FLOAT;
         rgba_stride = width * 4 * sizeof(GLfloat);
      }

      /* If we are lucky and the dst format matches the RGBA format we need to
       * convert to, then we can convert directly into the dst buffer and avoid
       * the final conversion/copy from the rgba buffer to the dst buffer.
       */
      if (dst_format == rgba_format) {
         need_convert = false;
         rgba = dst;
      } else {
         need_convert = true;
         rgba = malloc(height * rgba_stride);
         if (!rgba) {
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
            goto done_unmap;
         }
      }

      /* Convert to RGBA now */
      _mesa_format_convert(rgba, rgba_format, rgba_stride,
                           map, rb_format, rb_stride,
                           width, height,
                           needs_rebase ? rebase_swizzle : NULL);

      /* Handle transfer ops if necessary */
      if (transferOps)
         _mesa_apply_rgba_transfer_ops(ctx, transferOps, width * height, rgba);

      /* If we had to rebase, we have already taken care of that */
      needs_rebase = false;

      /* If we were lucky and our RGBA conversion matches the dst format, then
       * we are done.
       */
      if (!need_convert)
         goto done_swap;

      /* Otherwise, we need to convert from RGBA to dst next */
      src = rgba;
      src_format = rgba_format;
      src_stride = rgba_stride;
   } else {
      /* No RGBA conversion needed, convert directly to dst */
      src = map;
      src_format = rb_format;
      src_stride = rb_stride;
   }

   /* Do the conversion.
    *
    * If the dst format is Luminance, we need to do the conversion by computing
    * L=R+G+B values.
    */
   if (!dst_is_luminance) {
      _mesa_format_convert(dst, dst_format, dst_stride,
                           src, src_format, src_stride,
                           width, height,
                           needs_rebase ? rebase_swizzle : NULL);
   } else if (!dst_is_integer) {
      /* Compute float Luminance values from RGBA float */
      int luminance_stride, luminance_bytes;
      void *luminance;
      uint32_t luminance_format;

      luminance_stride = width * sizeof(GL_FLOAT);
      if (format == GL_LUMINANCE_ALPHA)
         luminance_stride *= 2;
      luminance_bytes = height * luminance_stride;
      luminance = malloc(luminance_bytes);
      if (!luminance) {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
         free(rgba);
         goto done_unmap;
      }
      _mesa_pack_luminance_from_rgba_float(width * height, src,
                                           luminance, format, transferOps);

      /* Convert from Luminance float to dst (this will hadle type conversion
       * from float to the type of dst if necessary)
       */
      luminance_format = _mesa_format_from_format_and_type(format, GL_FLOAT);
      _mesa_format_convert(dst, dst_format, dst_stride,
                           luminance, luminance_format, luminance_stride,
                           width, height, NULL);
   } else {
      _mesa_pack_luminance_from_rgba_integer(width * height, src, !src_is_uint,
                                             dst, format, type);
   }

   if (rgba)
      free(rgba);

done_swap:
   /* Handle byte swapping if required */
   if (packing->SwapBytes) {
      int components = _mesa_components_in_format(format);
      GLint swapSize = _mesa_sizeof_packed_type(type);
      if (swapSize == 2)
         _mesa_swap2((GLushort *) dst, width * height * components);
      else if (swapSize == 4)
         _mesa_swap4((GLuint *) dst, width * height * components);
   }

done_unmap:
   ctx->Driver.UnmapRenderbuffer(ctx, rb);
}
Example #24
0
static GLboolean
r300ValidateClientStorage(GLcontext * ctx, GLenum target,
			  GLint internalFormat,
			  GLint srcWidth, GLint srcHeight,
			  GLenum format, GLenum type, const void *pixels,
			  const struct gl_pixelstore_attrib *packing,
			  struct gl_texture_object *texObj,
			  struct gl_texture_image *texImage)
{
	r300ContextPtr rmesa = R300_CONTEXT(ctx);

	if (0)
		fprintf(stderr, "intformat %s format %s type %s\n",
			_mesa_lookup_enum_by_nr(internalFormat),
			_mesa_lookup_enum_by_nr(format),
			_mesa_lookup_enum_by_nr(type));

	if (!ctx->Unpack.ClientStorage)
		return 0;

	if (ctx->_ImageTransferState ||
	    texImage->IsCompressed || texObj->GenerateMipmap)
		return 0;

	/* This list is incomplete, may be different on ppc???
	 */
	switch (internalFormat) {
	case GL_RGBA:
		if (format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV) {
			texImage->TexFormat = _dri_texformat_argb8888;
		} else
			return 0;
		break;

	case GL_RGB:
		if (format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5) {
			texImage->TexFormat = _dri_texformat_rgb565;
		} else
			return 0;
		break;

	case GL_YCBCR_MESA:
		if (format == GL_YCBCR_MESA &&
		    type == GL_UNSIGNED_SHORT_8_8_REV_APPLE) {
			texImage->TexFormat = &_mesa_texformat_ycbcr_rev;
		} else if (format == GL_YCBCR_MESA &&
			   (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
			    type == GL_UNSIGNED_BYTE)) {
			texImage->TexFormat = &_mesa_texformat_ycbcr;
		} else
			return 0;
		break;

	default:
		return 0;
	}

	/* Could deal with these packing issues, but currently don't:
	 */
	if (packing->SkipPixels ||
	    packing->SkipRows || packing->SwapBytes || packing->LsbFirst) {
		return 0;
	}

	{
		GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth,
							    format, type);

		if (0)
			fprintf(stderr, "%s: srcRowStride %d/%x\n",
				__FUNCTION__, srcRowStride, srcRowStride);

		/* Could check this later in upload, pitch restrictions could be
		 * relaxed, but would need to store the image pitch somewhere,
		 * as packing details might change before image is uploaded:
		 */
		if (!r300IsGartMemory(rmesa, pixels, srcHeight * srcRowStride)
		    || (srcRowStride & 63))
			return 0;

		/* Have validated that _mesa_transfer_teximage would be a straight
		 * memcpy at this point.  NOTE: future calls to TexSubImage will
		 * overwrite the client data.  This is explicitly mentioned in the
		 * extension spec.
		 */
		texImage->Data = (void *)pixels;
		texImage->IsClientData = GL_TRUE;
		texImage->RowStride =
		    srcRowStride / texImage->TexFormat->TexelBytes;

		return 1;
	}
}
Example #25
0
static GLboolean
texstore_rgba(TEXSTORE_PARAMS)
{
   void *tempImage = NULL, *tempRGBA = NULL;
   int srcRowStride, img;
   GLubyte *src, *dst;
   uint32_t srcMesaFormat;
   uint8_t rebaseSwizzle[4];
   bool needRebase;
   bool transferOpsDone = false;

   /* We have to handle MESA_FORMAT_YCBCR manually because it is a special case
    * and _mesa_format_convert does not support it. In this case the we only
    * allow conversions between YCBCR formats and it is mostly a memcpy.
    */
   if (dstFormat == MESA_FORMAT_YCBCR || dstFormat == MESA_FORMAT_YCBCR_REV) {
      return _mesa_texstore_ycbcr(ctx, dims, baseInternalFormat,
                                  dstFormat, dstRowStride, dstSlices,
                                  srcWidth, srcHeight, srcDepth,
                                  srcFormat, srcType, srcAddr,
                                  srcPacking);
   }

   /* We have to deal with GL_COLOR_INDEX manually because
    * _mesa_format_convert does not handle this format. So what we do here is
    * convert it to RGBA ubyte first and then convert from that to dst as usual.
    */
   if (srcFormat == GL_COLOR_INDEX) {
      /* Notice that this will already handle byte swapping if necessary */
      tempImage =
         _mesa_unpack_color_index_to_rgba_ubyte(ctx, dims,
                                                srcAddr, srcFormat, srcType,
                                                srcWidth, srcHeight, srcDepth,
                                                srcPacking,
                                                ctx->_ImageTransferState);
      if (!tempImage)
         return GL_FALSE;

      /* _mesa_unpack_color_index_to_rgba_ubyte has handled transferops
       * if needed.
       */
      transferOpsDone = true;

      /* Now we only have to adjust our src info for a conversion from
       * the RGBA ubyte and then we continue as usual.
       */
      srcAddr = tempImage;
      srcFormat = GL_RGBA;
      srcType = GL_UNSIGNED_BYTE;
   } else if (srcPacking->SwapBytes) {
      /* We have to handle byte-swapping scenarios before calling
       * _mesa_format_convert
       */
      GLint swapSize = _mesa_sizeof_packed_type(srcType);
      if (swapSize == 2 || swapSize == 4) {
         int bytesPerPixel = _mesa_bytes_per_pixel(srcFormat, srcType);
         int swapsPerPixel = bytesPerPixel / swapSize;
         int elementCount = srcWidth * srcHeight * srcDepth;
         assert(bytesPerPixel % swapSize == 0);
         tempImage = malloc(elementCount * bytesPerPixel);
         if (!tempImage)
            return GL_FALSE;
         if (swapSize == 2)
            _mesa_swap2_copy(tempImage, (GLushort *) srcAddr,
                             elementCount * swapsPerPixel);
         else
            _mesa_swap4_copy(tempImage, (GLuint *) srcAddr,
                             elementCount * swapsPerPixel);
         srcAddr = tempImage;
      }
   }

   srcRowStride =
      _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);

   srcMesaFormat = _mesa_format_from_format_and_type(srcFormat, srcType);
   dstFormat = _mesa_get_srgb_format_linear(dstFormat);

   /* If we have transferOps then we need to convert to RGBA float first,
      then apply transferOps, then do the conversion to dst
    */
   if (!transferOpsDone &&
       _mesa_texstore_needs_transfer_ops(ctx, baseInternalFormat, dstFormat)) {
      /* Allocate RGBA float image */
      int elementCount = srcWidth * srcHeight * srcDepth;
      tempRGBA = malloc(4 * elementCount * sizeof(float));
      if (!tempRGBA) {
         free(tempImage);
         free(tempRGBA);
         return GL_FALSE;
      }

      /* Convert from src to RGBA float */
      src = (GLubyte *) srcAddr;
      dst = (GLubyte *) tempRGBA;
      for (img = 0; img < srcDepth; img++) {
         _mesa_format_convert(dst, RGBA32_FLOAT, 4 * srcWidth * sizeof(float),
                              src, srcMesaFormat, srcRowStride,
                              srcWidth, srcHeight, NULL);
         src += srcHeight * srcRowStride;
         dst += srcHeight * 4 * srcWidth * sizeof(float);
      }

      /* Apply transferOps */
      _mesa_apply_rgba_transfer_ops(ctx, ctx->_ImageTransferState, elementCount,
                                    (float(*)[4]) tempRGBA);

      /* Now we have to adjust our src info for a conversion from
       * the RGBA float image and then we continue as usual.
       */
      srcAddr = tempRGBA;
      srcFormat = GL_RGBA;
      srcType = GL_FLOAT;
      srcRowStride = srcWidth * 4 * sizeof(float);
      srcMesaFormat = RGBA32_FLOAT;
   }

   src = (GLubyte *)
      _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight,
                          srcFormat, srcType, 0, 0, 0);

   if (_mesa_get_format_base_format(dstFormat) != baseInternalFormat) {
      needRebase =
         _mesa_compute_rgba2base2rgba_component_mapping(baseInternalFormat,
                                                        rebaseSwizzle);
   } else {
      needRebase = false;
   }

   for (img = 0; img < srcDepth; img++) {
      _mesa_format_convert(dstSlices[img], dstFormat, dstRowStride,
                           src, srcMesaFormat, srcRowStride,
                           srcWidth, srcHeight,
                           needRebase ? rebaseSwizzle : NULL);
      src += srcHeight * srcRowStride;
   }

   free(tempImage);
   free(tempRGBA);

   return GL_TRUE;
}
Example #26
0
/**
 * \brief A fast path for glReadPixels
 *
 * This fast path is taken when the source format is BGRA, RGBA,
 * A or L and when the texture memory is X- or Y-tiled.  It downloads
 * the source data by directly mapping the memory without a GTT fence.
 * This then needs to be de-tiled on the CPU before presenting the data to
 * the user in the linear fasion.
 *
 * This is a performance win over the conventional texture download path.
 * In the conventional texture download path, the texture is either mapped
 * through the GTT or copied to a linear buffer with the blitter before
 * handing off to a software path.  This allows us to avoid round-tripping
 * through the GPU (in the case where we would be blitting) and do only a
 * single copy operation.
 */
static bool
intel_readpixels_tiled_memcpy(struct gl_context * ctx,
                              GLint xoffset, GLint yoffset,
                              GLsizei width, GLsizei height,
                              GLenum format, GLenum type,
                              GLvoid * pixels,
                              const struct gl_pixelstore_attrib *pack)
{
   struct brw_context *brw = brw_context(ctx);
   struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;

   /* This path supports reading from color buffers only */
   if (rb == NULL)
      return false;

   struct intel_renderbuffer *irb = intel_renderbuffer(rb);
   int dst_pitch;

   /* The miptree's buffer. */
   drm_intel_bo *bo;

   int error = 0;

   uint32_t cpp;
   mem_copy_fn mem_copy = NULL;

   /* This fastpath is restricted to specific renderbuffer types:
    * a 2D BGRA, RGBA, L8 or A8 texture. It could be generalized to support
    * more types.
    */
   if (!brw->has_llc ||
       !(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT_8_8_8_8_REV) ||
       pixels == NULL ||
       _mesa_is_bufferobj(pack->BufferObj) ||
       pack->Alignment > 4 ||
       pack->SkipPixels > 0 ||
       pack->SkipRows > 0 ||
       (pack->RowLength != 0 && pack->RowLength != width) ||
       pack->SwapBytes ||
       pack->LsbFirst ||
       pack->Invert)
      return false;

   /* Only a simple blit, no scale, bias or other mapping. */
   if (ctx->_ImageTransferState)
      return false;

   /* This renderbuffer can come from a texture.  In this case, we impose
    * some of the same restrictions we have for textures and adjust for
    * miplevels.
    */
   if (rb->TexImage) {
      if (rb->TexImage->TexObject->Target != GL_TEXTURE_2D &&
          rb->TexImage->TexObject->Target != GL_TEXTURE_RECTANGLE)
         return false;

      int level = rb->TexImage->Level + rb->TexImage->TexObject->MinLevel;

      /* Adjust x and y offset based on miplevel */
      xoffset += irb->mt->level[level].level_x;
      yoffset += irb->mt->level[level].level_y;
   }

   /* It is possible that the renderbuffer (or underlying texture) is
    * multisampled.  Since ReadPixels from a multisampled buffer requires a
    * multisample resolve, we can't handle this here
    */
   if (rb->NumSamples > 1)
      return false;

   /* We can't handle copying from RGBX or BGRX because the tiled_memcpy
    * function doesn't set the last channel to 1. Note this checks BaseFormat
    * rather than TexFormat in case the RGBX format is being simulated with an
    * RGBA format.
    */
   if (rb->_BaseFormat == GL_RGB)
      return false;

   if (!intel_get_memcpy(rb->Format, format, type, &mem_copy, &cpp,
                         INTEL_DOWNLOAD))
      return false;

   if (!irb->mt ||
       (irb->mt->tiling != I915_TILING_X &&
       irb->mt->tiling != I915_TILING_Y)) {
      /* The algorithm is written only for X- or Y-tiled memory. */
      return false;
   }

   /* Since we are going to read raw data to the miptree, we need to resolve
    * any pending fast color clears before we start.
    */
   intel_miptree_resolve_color(brw, irb->mt);

   bo = irb->mt->bo;

   if (drm_intel_bo_references(brw->batch.bo, bo)) {
      perf_debug("Flushing before mapping a referenced bo.\n");
      intel_batchbuffer_flush(brw);
   }

   error = brw_bo_map(brw, bo, false /* write enable */, "miptree");
   if (error) {
      DBG("%s: failed to map bo\n", __func__);
      return false;
   }

   dst_pitch = _mesa_image_row_stride(pack, width, format, type);

   /* For a window-system renderbuffer, the buffer is actually flipped
    * vertically, so we need to handle that.  Since the detiling function
    * can only really work in the forwards direction, we have to be a
    * little creative.  First, we compute the Y-offset of the first row of
    * the renderbuffer (in renderbuffer coordinates).  We then match that
    * with the last row of the client's data.  Finally, we give
    * tiled_to_linear a negative pitch so that it walks through the
    * client's data backwards as it walks through the renderbufer forwards.
    */
   if (rb->Name == 0) {
      yoffset = rb->Height - yoffset - height;
      pixels += (ptrdiff_t) (height - 1) * dst_pitch;
      dst_pitch = -dst_pitch;
   }

   /* We postponed printing this message until having committed to executing
    * the function.
    */
   DBG("%s: x,y=(%d,%d) (w,h)=(%d,%d) format=0x%x type=0x%x "
       "mesa_format=0x%x tiling=%d "
       "pack=(alignment=%d row_length=%d skip_pixels=%d skip_rows=%d)\n",
       __func__, xoffset, yoffset, width, height,
       format, type, rb->Format, irb->mt->tiling,
       pack->Alignment, pack->RowLength, pack->SkipPixels,
       pack->SkipRows);

   tiled_to_linear(
      xoffset * cpp, (xoffset + width) * cpp,
      yoffset, yoffset + height,
      pixels - (ptrdiff_t) yoffset * dst_pitch - (ptrdiff_t) xoffset * cpp,
      bo->virtual,
      dst_pitch, irb->mt->pitch,
      brw->has_swizzling,
      irb->mt->tiling,
      mem_copy
   );

   drm_intel_bo_unmap(bo);
   return true;
}
/**
 * Try to do glGetTexImage() with simple memcpy().
 * \return GL_TRUE if done, GL_FALSE otherwise
 */
static GLboolean
get_tex_memcpy(struct gl_context *ctx, GLenum format, GLenum type,
               GLvoid *pixels,
               struct gl_texture_image *texImage)
{
   const GLenum target = texImage->TexObject->Target;
   GLboolean memCopy = GL_FALSE;

   /*
    * Check if we can use memcpy to copy from the hardware texture
    * format to the user's format/type.
    * Note that GL's pixel transfer ops don't apply to glGetTexImage()
    */
   if (target == GL_TEXTURE_1D ||
       target == GL_TEXTURE_2D ||
       target == GL_TEXTURE_RECTANGLE ||
       _mesa_is_cube_face(target)) {
      memCopy = _mesa_format_matches_format_and_type(texImage->TexFormat,
                                                     format, type,
                                                     ctx->Pack.SwapBytes);
   }

   if (memCopy) {
      const GLuint bpp = _mesa_get_format_bytes(texImage->TexFormat);
      const GLuint bytesPerRow = texImage->Width * bpp;
      GLubyte *dst =
         _mesa_image_address2d(&ctx->Pack, pixels, texImage->Width,
                               texImage->Height, format, type, 0, 0);
      const GLint dstRowStride =
         _mesa_image_row_stride(&ctx->Pack, texImage->Width, format, type);
      GLubyte *src;
      GLint srcRowStride;

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

      if (src) {
         if (bytesPerRow == dstRowStride && bytesPerRow == srcRowStride) {
            memcpy(dst, src, bytesPerRow * texImage->Height);
         }
         else {
            GLuint row;
            for (row = 0; row < texImage->Height; row++) {
               memcpy(dst, src, bytesPerRow);
               dst += dstRowStride;
               src += srcRowStride;
            }
         }

         /* unmap src texture buffer */
         ctx->Driver.UnmapTextureImage(ctx, texImage, 0);
      }
      else {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
      }
   }

   return memCopy;
}
Example #28
0
/**
 * Get an uncompressed color texture image.
 */
static void
get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions,
                          GLenum format, GLenum type, GLvoid *pixels,
                          struct gl_texture_image *texImage,
                          GLbitfield transferOps)
{
   /* don't want to apply sRGB -> RGB conversion here so override the format */
   const mesa_format texFormat =
      _mesa_get_srgb_format_linear(texImage->TexFormat);
   const GLuint width = texImage->Width;
   GLuint height = texImage->Height;
   GLuint depth = texImage->Depth;
   GLuint img;
   GLboolean dst_is_integer;
   uint32_t dst_format;
   int dst_stride;
   uint8_t rebaseSwizzle[4];
   bool needsRebase;
   void *rgba = NULL;

   if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
      depth = height;
      height = 1;
   }

   /* Depending on the base format involved we may need to apply a rebase
    * transform (for example: if we download to a Luminance format we want
    * G=0 and B=0).
    */
   if (texImage->_BaseFormat == GL_LUMINANCE ||
       texImage->_BaseFormat == GL_INTENSITY) {
      needsRebase = true;
      rebaseSwizzle[0] = MESA_FORMAT_SWIZZLE_X;
      rebaseSwizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
      rebaseSwizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
      rebaseSwizzle[3] = MESA_FORMAT_SWIZZLE_ONE;
   } else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
      needsRebase = true;
      rebaseSwizzle[0] = MESA_FORMAT_SWIZZLE_X;
      rebaseSwizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
      rebaseSwizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
      rebaseSwizzle[3] = MESA_FORMAT_SWIZZLE_W;
//    } else if (texImage->_BaseFormat != _mesa_get_format_base_format(texFormat)) {
//      needsRebase =
//         _mesa_compute_rgba2base2rgba_component_mapping(texImage->_BaseFormat,
//                                                        rebaseSwizzle);
    } else {
      needsRebase = false;
    }

   /* Describe the dst format */
   dst_is_integer = _mesa_is_enum_format_integer(format);
   dst_format = _mesa_format_from_format_and_type(format, type);
   dst_stride = _mesa_image_row_stride(&ctx->Pack, width, format, type);

   /* Since _mesa_format_convert does not handle transferOps we need to handle
    * them before we call the function. This requires to convert to RGBA float
    * first so we can call _mesa_apply_rgba_transfer_ops. If the dst format is
    * integer then transferOps do not apply.
    */
   assert(!transferOps || (transferOps && !dst_is_integer));
   (void) dst_is_integer; /* silence unused var warning */

   for (img = 0; img < depth; img++) {
      GLubyte *srcMap;
      GLint rowstride;
      GLubyte *img_src;
      void *dest;
      void *src;
      int src_stride;
      uint32_t src_format;

      /* map src texture buffer */
      ctx->Driver.MapTextureImage(ctx, texImage, img,
                                  0, 0, width, height, GL_MAP_READ_BIT,
                                  &srcMap, &rowstride);
      if (!srcMap) {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
         goto done;
      }

      img_src = srcMap;
      dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
                                 width, height, format, type,
                                 img, 0, 0);

      if (transferOps) {
         uint32_t rgba_format;
         int rgba_stride;
         bool need_convert = false;

         /* We will convert to RGBA float */
//         rgba_format = RGBA32_FLOAT;
         rgba_stride = width * 4 * sizeof(GLfloat);

         /* If we are lucky and the dst format matches the RGBA format we need
          * to convert to, then we can convert directly into the dst buffer
          * and avoid the final conversion/copy from the rgba buffer to the dst
          * buffer.
          */
         if (format == rgba_format) {
            rgba = dest;
         } else if (rgba == NULL) { /* Allocate the RGBA buffer only once */
            need_convert = true;
            rgba = malloc(height * rgba_stride);
            if (!rgba) {
               _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()");
               ctx->Driver.UnmapTextureImage(ctx, texImage, img);
               return;
            }
         }

//         _mesa_format_convert(rgba, rgba_format, rgba_stride,
//                              img_src, texFormat, rowstride,
//                              width, height,
//                              needsRebase ? rebaseSwizzle : NULL);

         /* Handle transfer ops now */
         _mesa_apply_rgba_transfer_ops(ctx, transferOps, width * height, rgba);

         /* If we had to rebase, we have already handled that */
         needsRebase = false;

         /* If we were lucky and our RGBA conversion matches the dst format, then
          * we are done.
          */
         if (!need_convert)
            goto do_swap;

         /* Otherwise, we need to convert from RGBA to dst next */
         src = rgba;
         src_format = rgba_format;
         src_stride = rgba_stride;
      } else {
         /* No RGBA conversion needed, convert directly to dst */
         src = img_src;
         src_format = texFormat;
         src_stride = rowstride;
      }

      /* Do the conversion to destination format */
//      _mesa_format_convert(dest, dst_format, dst_stride,
//                           src, src_format, src_stride,
//                           width, height,
//                           needsRebase ? rebaseSwizzle : NULL);

   do_swap:
      /* Handle byte swapping if required */
      if (ctx->Pack.SwapBytes) {
         GLint swapSize = _mesa_sizeof_packed_type(type);
         if (swapSize == 2 || swapSize == 4) {
            int swapsPerPixel = _mesa_bytes_per_pixel(format, type) / swapSize;
            assert(_mesa_bytes_per_pixel(format, type) % swapSize == 0);
            if (swapSize == 2)
               _mesa_swap2((GLushort *) dest, width * height * swapsPerPixel);
            else if (swapSize == 4)
               _mesa_swap4((GLuint *) dest, width * height * swapsPerPixel);
         }
      }

      /* Unmap the src texture buffer */
      ctx->Driver.UnmapTextureImage(ctx, texImage, img);
   }

done:
   if (rgba)
      free(rgba);
}
Example #29
0
/**
 * \brief A fast path for glReadPixels
 *
 * This fast path is taken when the source format is BGRA, RGBA,
 * A or L and when the texture memory is X- or Y-tiled.  It downloads
 * the source data by directly mapping the memory without a GTT fence.
 * This then needs to be de-tiled on the CPU before presenting the data to
 * the user in the linear fasion.
 *
 * This is a performance win over the conventional texture download path.
 * In the conventional texture download path, the texture is either mapped
 * through the GTT or copied to a linear buffer with the blitter before
 * handing off to a software path.  This allows us to avoid round-tripping
 * through the GPU (in the case where we would be blitting) and do only a
 * single copy operation.
 */
static bool
intel_readpixels_tiled_memcpy(struct gl_context * ctx,
                              GLint xoffset, GLint yoffset,
                              GLsizei width, GLsizei height,
                              GLenum format, GLenum type,
                              GLvoid * pixels,
                              const struct gl_pixelstore_attrib *pack)
{
   struct brw_context *brw = brw_context(ctx);
   struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
   const struct gen_device_info *devinfo = &brw->screen->devinfo;

   /* This path supports reading from color buffers only */
   if (rb == NULL)
      return false;

   struct intel_renderbuffer *irb = intel_renderbuffer(rb);
   int dst_pitch;

   /* The miptree's buffer. */
   struct brw_bo *bo;

   uint32_t cpp;
   mem_copy_fn mem_copy = NULL;

   /* This fastpath is restricted to specific renderbuffer types:
    * a 2D BGRA, RGBA, L8 or A8 texture. It could be generalized to support
    * more types.
    */
   if (!devinfo->has_llc ||
       !(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT_8_8_8_8_REV) ||
       pixels == NULL ||
       _mesa_is_bufferobj(pack->BufferObj) ||
       pack->Alignment > 4 ||
       pack->SkipPixels > 0 ||
       pack->SkipRows > 0 ||
       (pack->RowLength != 0 && pack->RowLength != width) ||
       pack->SwapBytes ||
       pack->LsbFirst ||
       pack->Invert)
      return false;

   /* Only a simple blit, no scale, bias or other mapping. */
   if (ctx->_ImageTransferState)
      return false;

   /* It is possible that the renderbuffer (or underlying texture) is
    * multisampled.  Since ReadPixels from a multisampled buffer requires a
    * multisample resolve, we can't handle this here
    */
   if (rb->NumSamples > 1)
      return false;

   /* We can't handle copying from RGBX or BGRX because the tiled_memcpy
    * function doesn't set the last channel to 1. Note this checks BaseFormat
    * rather than TexFormat in case the RGBX format is being simulated with an
    * RGBA format.
    */
   if (rb->_BaseFormat == GL_RGB)
      return false;

   if (!intel_get_memcpy(rb->Format, format, type, &mem_copy, &cpp))
      return false;

   if (!irb->mt ||
       (irb->mt->surf.tiling != ISL_TILING_X &&
        irb->mt->surf.tiling != ISL_TILING_Y0)) {
      /* The algorithm is written only for X- or Y-tiled memory. */
      return false;
   }

   /* tiled_to_linear() assumes that if the object is swizzled, it is using
    * I915_BIT6_SWIZZLE_9_10 for X and I915_BIT6_SWIZZLE_9 for Y.  This is only
    * true on gen5 and above.
    *
    * The killer on top is that some gen4 have an L-shaped swizzle mode, where
    * parts of the memory aren't swizzled at all. Userspace just can't handle
    * that.
    */
   if (devinfo->gen < 5 && brw->has_swizzling)
      return false;

   /* Since we are going to read raw data to the miptree, we need to resolve
    * any pending fast color clears before we start.
    */
   intel_miptree_access_raw(brw, irb->mt, irb->mt_level, irb->mt_layer, false);

   bo = irb->mt->bo;

   if (brw_batch_references(&brw->batch, bo)) {
      perf_debug("Flushing before mapping a referenced bo.\n");
      intel_batchbuffer_flush(brw);
   }

   void *map = brw_bo_map(brw, bo, MAP_READ | MAP_RAW);
   if (map == NULL) {
      DBG("%s: failed to map bo\n", __func__);
      return false;
   }

   unsigned slice_offset_x, slice_offset_y;
   intel_miptree_get_image_offset(irb->mt, irb->mt_level, irb->mt_layer,
                                  &slice_offset_x, &slice_offset_y);
   xoffset += slice_offset_x;
   yoffset += slice_offset_y;

   dst_pitch = _mesa_image_row_stride(pack, width, format, type);

   /* For a window-system renderbuffer, the buffer is actually flipped
    * vertically, so we need to handle that.  Since the detiling function
    * can only really work in the forwards direction, we have to be a
    * little creative.  First, we compute the Y-offset of the first row of
    * the renderbuffer (in renderbuffer coordinates).  We then match that
    * with the last row of the client's data.  Finally, we give
    * tiled_to_linear a negative pitch so that it walks through the
    * client's data backwards as it walks through the renderbufer forwards.
    */
   if (rb->Name == 0) {
      yoffset = rb->Height - yoffset - height;
      pixels += (ptrdiff_t) (height - 1) * dst_pitch;
      dst_pitch = -dst_pitch;
   }

   /* We postponed printing this message until having committed to executing
    * the function.
    */
   DBG("%s: x,y=(%d,%d) (w,h)=(%d,%d) format=0x%x type=0x%x "
       "mesa_format=0x%x tiling=%d "
       "pack=(alignment=%d row_length=%d skip_pixels=%d skip_rows=%d)\n",
       __func__, xoffset, yoffset, width, height,
       format, type, rb->Format, irb->mt->surf.tiling,
       pack->Alignment, pack->RowLength, pack->SkipPixels,
       pack->SkipRows);

   tiled_to_linear(
      xoffset * cpp, (xoffset + width) * cpp,
      yoffset, yoffset + height,
      pixels - (ptrdiff_t) yoffset * dst_pitch - (ptrdiff_t) xoffset * cpp,
      map + irb->mt->offset,
      dst_pitch, irb->mt->surf.row_pitch,
      brw->has_swizzling,
      irb->mt->surf.tiling,
      mem_copy
   );

   brw_bo_unmap(bo);
   return true;
}
Example #30
0
/**
 * Try to do glGetTexImage() with simple memcpy().
 * \return GL_TRUE if done, GL_FALSE otherwise
 */
static GLboolean
get_tex_memcpy(struct gl_context *ctx, GLenum format, GLenum type,
               GLvoid *pixels,
               struct gl_texture_image *texImage)
{
   const GLenum target = texImage->TexObject->Target;
   GLboolean memCopy = GL_FALSE;

   /*
    * Check if the src/dst formats are compatible.
    * Also note that GL's pixel transfer ops don't apply to glGetTexImage()
    * so we don't have to worry about those.
    * XXX more format combinations could be supported here.
    */
   if (target == GL_TEXTURE_1D ||
       target == GL_TEXTURE_2D ||
       _mesa_is_cube_face(target)) {
      if ((texImage->TexFormat == MESA_FORMAT_ARGB8888) &&
          format == GL_BGRA &&
          (type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT_8_8_8_8_REV) &&
          !ctx->Pack.SwapBytes &&
          _mesa_little_endian()) {
         memCopy = GL_TRUE;
      }
      else if ((texImage->TexFormat == MESA_FORMAT_AL88) &&
               format == GL_LUMINANCE_ALPHA &&
               type == GL_UNSIGNED_BYTE &&
               !ctx->Pack.SwapBytes &&
               _mesa_little_endian()) {
         memCopy = GL_TRUE;
      }
      else if ((texImage->TexFormat == MESA_FORMAT_L8) &&
               format == GL_LUMINANCE &&
               type == GL_UNSIGNED_BYTE) {
         memCopy = GL_TRUE;
      }
      else if (texImage->TexFormat == MESA_FORMAT_L16 &&
               format == GL_LUMINANCE &&
               type == GL_UNSIGNED_SHORT) {
         memCopy = GL_TRUE;
      }
      else if (texImage->TexFormat == MESA_FORMAT_A8 &&
               format == GL_ALPHA &&
               type == GL_UNSIGNED_BYTE) {
         memCopy = GL_TRUE;
      }
      else if (texImage->TexFormat == MESA_FORMAT_A16 &&
               format == GL_ALPHA &&
               type == GL_UNSIGNED_SHORT) {
         memCopy = GL_TRUE;
      }
   }

   if (memCopy) {
      const GLuint bpp = _mesa_get_format_bytes(texImage->TexFormat);
      const GLuint bytesPerRow = texImage->Width * bpp;
      GLubyte *dst =
         _mesa_image_address2d(&ctx->Pack, pixels, texImage->Width,
                               texImage->Height, format, type, 0, 0);
      const GLint dstRowStride =
         _mesa_image_row_stride(&ctx->Pack, texImage->Width, format, type);
      GLubyte *src;
      GLint srcRowStride;

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

      if (src) {
         if (bytesPerRow == dstRowStride && bytesPerRow == srcRowStride) {
            memcpy(dst, src, bytesPerRow * texImage->Height);
         }
         else {
            GLuint row;
            for (row = 0; row < texImage->Height; row++) {
               memcpy(dst, src, bytesPerRow);
               dst += dstRowStride;
               src += srcRowStride;
            }
         }

         /* unmap src texture buffer */
         ctx->Driver.UnmapTextureImage(ctx, texImage, 0);
      }
      else {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
      }
   }

   return memCopy;
}