Example #1
0
/**
 * Store user's image in rgba_dxt1 format.
 */
GLboolean
_mesa_texstore_rgba_dxt1(TEXSTORE_PARAMS)
{
   const GLubyte *pixels;
   GLubyte *dst;
   const GLubyte *tempImage = NULL;

   assert(dstFormat == MESA_FORMAT_RGBA_DXT1 ||
          dstFormat == MESA_FORMAT_SRGBA_DXT1);

   if (srcFormat != GL_RGBA ||
       srcType != GL_UNSIGNED_BYTE ||
       ctx->_ImageTransferState ||
       ALIGN(srcPacking->RowLength, srcPacking->Alignment) != srcWidth ||
       srcPacking->SwapBytes) {
      /* convert image to RGBA/GLubyte */
      GLubyte *tempImageSlices[1];
      int rgbaRowStride = 4 * srcWidth * sizeof(GLubyte);
      tempImage = malloc(srcWidth * srcHeight * 4 * sizeof(GLubyte));
      if (!tempImage)
         return GL_FALSE; /* out of memory */
      tempImageSlices[0] = (GLubyte *) tempImage;
      _mesa_texstore(ctx, dims,
                     baseInternalFormat,
                     _mesa_little_endian() ? MESA_FORMAT_R8G8B8A8_UNORM
                                           : MESA_FORMAT_A8B8G8R8_UNORM,
                     rgbaRowStride, tempImageSlices,
                     srcWidth, srcHeight, srcDepth,
                     srcFormat, srcType, srcAddr,
                     srcPacking);
      pixels = tempImage;
      srcFormat = GL_RGBA;
   }
   else {
      pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
                                     srcFormat, srcType, 0, 0);
   }

   dst = dstSlices[0];

   if (ext_tx_compress_dxtn) {
      (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels,
                              GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
                              dst, dstRowStride);
   }
   else {
      _mesa_warning(ctx, "external dxt library not available: texstore_rgba_dxt1");
   }

   free((void*) tempImage);

   return GL_TRUE;
}
Example #2
0
static void
radeonInitTextureFormats(void)
{
    if (_mesa_little_endian()) {
        _radeon_texformat_rgba8888	= MESA_FORMAT_RGBA8888;
        _radeon_texformat_argb8888	= MESA_FORMAT_ARGB8888;
        _radeon_texformat_rgb565		= MESA_FORMAT_RGB565;
        _radeon_texformat_argb4444	= MESA_FORMAT_ARGB4444;
        _radeon_texformat_argb1555	= MESA_FORMAT_ARGB1555;
        _radeon_texformat_al88		= MESA_FORMAT_AL88;
    }
    else {
        _radeon_texformat_rgba8888	= MESA_FORMAT_RGBA8888_REV;
        _radeon_texformat_argb8888	= MESA_FORMAT_ARGB8888_REV;
        _radeon_texformat_rgb565		= MESA_FORMAT_RGB565_REV;
        _radeon_texformat_argb4444	= MESA_FORMAT_ARGB4444_REV;
        _radeon_texformat_argb1555	= MESA_FORMAT_ARGB1555_REV;
        _radeon_texformat_al88		= MESA_FORMAT_AL88_REV;
    }
}
Example #3
0
/**
 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_REV.
 */
static GLboolean
_mesa_texstore_ycbcr(TEXSTORE_PARAMS)
{
   const GLboolean littleEndian = _mesa_little_endian();

   (void) ctx; (void) dims; (void) baseInternalFormat;

   assert((dstFormat == MESA_FORMAT_YCBCR) ||
          (dstFormat == MESA_FORMAT_YCBCR_REV));
   assert(_mesa_get_format_bytes(dstFormat) == 2);
   assert(ctx->Extensions.MESA_ycbcr_texture);
   assert(srcFormat == GL_YCBCR_MESA);
   assert((srcType == GL_UNSIGNED_SHORT_8_8_MESA) ||
          (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA));
   assert(baseInternalFormat == GL_YCBCR_MESA);

   /* always just memcpy since no pixel transfer ops apply */
   memcpy_texture(ctx, dims,
                  dstFormat,
                  dstRowStride, dstSlices,
                  srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                  srcAddr, srcPacking);

   /* Check if we need byte swapping */
   /* XXX the logic here _might_ be wrong */
   if (srcPacking->SwapBytes ^
       (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA) ^
       (dstFormat == MESA_FORMAT_YCBCR_REV) ^
       !littleEndian) {
      GLint img, row;
      for (img = 0; img < srcDepth; img++) {
         GLubyte *dstRow = dstSlices[img];
         for (row = 0; row < srcHeight; row++) {
            _mesa_swap2((GLushort *) dstRow, srcWidth);
            dstRow += dstRowStride;
         }
      }
   }
   return GL_TRUE;
}
Example #4
0
/**
 * Allocate renderbuffer storage.  We don't actually allocate any storage
 * since we're using a user-provided buffer.
 * Just set up all the gl_renderbuffer methods.
 */
static GLboolean
osmesa_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
                            GLenum internalFormat, GLuint width, GLuint height)
{
   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);

   /* Note: we can ignoring internalFormat for "window-system" renderbuffers */
   (void) internalFormat;

   /* Given the user-provided format and type, figure out which MESA_FORMAT_x
    * to use.
    * XXX There aren't Mesa formats for all the possible combinations here!
    * XXX Specifically, there's only RGBA-order 16-bit/channel and float
    * XXX formats.
    * XXX The 8-bit/channel formats should all be OK.
    */
   if (osmesa->format == OSMESA_RGBA) {
      if (osmesa->DataType == GL_UNSIGNED_BYTE) {
         if (_mesa_little_endian())
            rb->Format = MESA_FORMAT_RGBA8888_REV;
         else
            rb->Format = MESA_FORMAT_RGBA8888;
      }
      else if (osmesa->DataType == GL_UNSIGNED_SHORT) {
         rb->Format = MESA_FORMAT_RGBA_16;
      }
      else {
         rb->Format = MESA_FORMAT_RGBA_FLOAT32;
      }
   }
   else if (osmesa->format == OSMESA_BGRA) {
      if (osmesa->DataType == GL_UNSIGNED_BYTE) {
         if (_mesa_little_endian())
            rb->Format = MESA_FORMAT_ARGB8888;
         else
            rb->Format = MESA_FORMAT_ARGB8888_REV;
      }
      else if (osmesa->DataType == GL_UNSIGNED_SHORT) {
         _mesa_warning(ctx, "Unsupported OSMesa format BGRA/GLushort");
         rb->Format = MESA_FORMAT_RGBA_16; /* not exactly right */
      }
      else {
         _mesa_warning(ctx, "Unsupported OSMesa format BGRA/GLfloat");
         rb->Format = MESA_FORMAT_RGBA_FLOAT32; /* not exactly right */
      }
   }
   else if (osmesa->format == OSMESA_ARGB) {
      if (osmesa->DataType == GL_UNSIGNED_BYTE) {
         if (_mesa_little_endian())
            rb->Format = MESA_FORMAT_ARGB8888_REV;
         else
            rb->Format = MESA_FORMAT_ARGB8888;
      }
      else if (osmesa->DataType == GL_UNSIGNED_SHORT) {
         _mesa_warning(ctx, "Unsupported OSMesa format ARGB/GLushort");
         rb->Format = MESA_FORMAT_RGBA_16; /* not exactly right */
      }
      else {
         _mesa_warning(ctx, "Unsupported OSMesa format ARGB/GLfloat");
         rb->Format = MESA_FORMAT_RGBA_FLOAT32; /* not exactly right */
      }
   }
   else if (osmesa->format == OSMESA_RGB) {
      if (osmesa->DataType == GL_UNSIGNED_BYTE) {
         rb->Format = MESA_FORMAT_RGB888;
      }
      else if (osmesa->DataType == GL_UNSIGNED_SHORT) {
         _mesa_warning(ctx, "Unsupported OSMesa format RGB/GLushort");
         rb->Format = MESA_FORMAT_RGBA_16; /* not exactly right */
      }
      else {
         _mesa_warning(ctx, "Unsupported OSMesa format RGB/GLfloat");
         rb->Format = MESA_FORMAT_RGBA_FLOAT32; /* not exactly right */
      }
   }
   else if (osmesa->format == OSMESA_BGR) {
      if (osmesa->DataType == GL_UNSIGNED_BYTE) {
         rb->Format = MESA_FORMAT_BGR888;
      }
      else if (osmesa->DataType == GL_UNSIGNED_SHORT) {
         _mesa_warning(ctx, "Unsupported OSMesa format BGR/GLushort");
         rb->Format = MESA_FORMAT_RGBA_16; /* not exactly right */
      }
      else {
         _mesa_warning(ctx, "Unsupported OSMesa format BGR/GLfloat");
         rb->Format = MESA_FORMAT_RGBA_FLOAT32; /* not exactly right */
      }
   }
   else if (osmesa->format == OSMESA_RGB_565) {
      ASSERT(osmesa->DataType == GL_UNSIGNED_BYTE);
      rb->Format = MESA_FORMAT_RGB565;
   }
   else {
      _mesa_problem(ctx, "bad pixel format in osmesa renderbuffer_storage");
   }

   rb->Width = width;
   rb->Height = height;

   compute_row_addresses( osmesa );

   return GL_TRUE;
}
Example #5
0
/**
 * This is a software fallback for the gl_renderbuffer->AllocStorage
 * function.
 * Device drivers will typically override this function for the buffers
 * which it manages (typically color buffers, Z and stencil).
 * Other buffers (like software accumulation and aux buffers) which the driver
 * doesn't manage can be handled with this function.
 *
 * This one multi-purpose function can allocate stencil, depth, accum, color
 * or color-index buffers!
 */
static GLboolean
soft_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
                          GLenum internalFormat,
                          GLuint width, GLuint height)
{
   struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
   GLuint bpp;

   switch (internalFormat) {
   case GL_RGB:
   case GL_R3_G3_B2:
   case GL_RGB4:
   case GL_RGB5:
   case GL_RGB8:
   case GL_RGB10:
   case GL_RGB12:
   case GL_RGB16:
      rb->Format = MESA_FORMAT_BGR_UNORM8;
      break;
   case GL_RGBA:
   case GL_RGBA2:
   case GL_RGBA4:
   case GL_RGB5_A1:
   case GL_RGBA8:
#if 1
   case GL_RGB10_A2:
   case GL_RGBA12:
#endif
      if (_mesa_little_endian())
         rb->Format = MESA_FORMAT_R8G8B8A8_UNORM;
      else
         rb->Format = MESA_FORMAT_A8B8G8R8_UNORM;
      break;
   case GL_RGBA16:
   case GL_RGBA16_SNORM:
      /* for accum buffer */
      rb->Format = MESA_FORMAT_RGBA_SNORM16;
      break;
   case GL_STENCIL_INDEX:
   case GL_STENCIL_INDEX1_EXT:
   case GL_STENCIL_INDEX4_EXT:
   case GL_STENCIL_INDEX8_EXT:
   case GL_STENCIL_INDEX16_EXT:
      rb->Format = MESA_FORMAT_S_UINT8;
      break;
   case GL_DEPTH_COMPONENT:
   case GL_DEPTH_COMPONENT16:
      rb->Format = MESA_FORMAT_Z_UNORM16;
      break;
   case GL_DEPTH_COMPONENT24:
      rb->Format = MESA_FORMAT_Z24_UNORM_X8_UINT;
      break;
   case GL_DEPTH_COMPONENT32:
      rb->Format = MESA_FORMAT_Z_UNORM32;
      break;
   case GL_DEPTH_STENCIL_EXT:
   case GL_DEPTH24_STENCIL8_EXT:
      rb->Format = MESA_FORMAT_S8_UINT_Z24_UNORM;
      break;
   default:
      /* unsupported format */
      return GL_FALSE;
   }

   bpp = _mesa_get_format_bytes(rb->Format);

   /* free old buffer storage */
   free(srb->Buffer);
   srb->Buffer = NULL;

   srb->RowStride = width * bpp;

   if (width > 0 && height > 0) {
      /* allocate new buffer storage */
      srb->Buffer = malloc(srb->RowStride * height);

      if (srb->Buffer == NULL) {
         rb->Width = 0;
         rb->Height = 0;
         _mesa_error(ctx, GL_OUT_OF_MEMORY,
                     "software renderbuffer allocation (%d x %d x %d)",
                     width, height, bpp);
         return GL_FALSE;
      }
   }

   rb->Width = width;
   rb->Height = height;
   rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);

   if (rb->Name == 0 &&
       internalFormat == GL_RGBA16_SNORM &&
       rb->_BaseFormat == 0) {
      /* NOTE: This is a special case just for accumulation buffers.
       * This is a very limited use case- there's no snorm texturing or
       * rendering going on.
       */
      rb->_BaseFormat = GL_RGBA;
   }
   else {
      /* the internalFormat should have been error checked long ago */
      assert(rb->_BaseFormat);
   }

   return GL_TRUE;
}
Example #6
0
/**
 * Create the Mesa framebuffer and renderbuffers for a given window/drawable.
 *
 * \todo This function (and its interface) will need to be updated to support
 * pbuffers.
 */
static GLboolean
radeonCreateBuffer( __DRIscreen *driScrnPriv,
                    __DRIdrawable *driDrawPriv,
                    const struct gl_config *mesaVis,
                    GLboolean isPixmap )
{
    radeonScreenPtr screen = (radeonScreenPtr) driScrnPriv->driverPrivate;

    const GLboolean swDepth = GL_FALSE;
    const GLboolean swAlpha = GL_FALSE;
    const GLboolean swAccum = mesaVis->accumRedBits > 0;
    const GLboolean swStencil = mesaVis->stencilBits > 0 &&
	mesaVis->depthBits != 24;
    mesa_format rgbFormat;
    struct radeon_framebuffer *rfb;

    if (isPixmap)
      return GL_FALSE; /* not implemented */

    rfb = CALLOC_STRUCT(radeon_framebuffer);
    if (!rfb)
      return GL_FALSE;

    _mesa_initialize_window_framebuffer(&rfb->base, mesaVis);

    if (mesaVis->redBits == 5)
        rgbFormat = _mesa_little_endian() ? MESA_FORMAT_B5G6R5_UNORM : MESA_FORMAT_R5G6B5_UNORM;
    else if (mesaVis->alphaBits == 0)
        rgbFormat = _mesa_little_endian() ? MESA_FORMAT_B8G8R8X8_UNORM : MESA_FORMAT_X8R8G8B8_UNORM;
    else
        rgbFormat = _mesa_little_endian() ? MESA_FORMAT_B8G8R8A8_UNORM : MESA_FORMAT_A8R8G8B8_UNORM;

    /* front color renderbuffer */
    rfb->color_rb[0] = radeon_create_renderbuffer(rgbFormat, driDrawPriv);
    _mesa_add_renderbuffer(&rfb->base, BUFFER_FRONT_LEFT, &rfb->color_rb[0]->base.Base);
    rfb->color_rb[0]->has_surface = 1;

    /* back color renderbuffer */
    if (mesaVis->doubleBufferMode) {
      rfb->color_rb[1] = radeon_create_renderbuffer(rgbFormat, driDrawPriv);
	_mesa_add_renderbuffer(&rfb->base, BUFFER_BACK_LEFT, &rfb->color_rb[1]->base.Base);
	rfb->color_rb[1]->has_surface = 1;
    }

    if (mesaVis->depthBits == 24) {
      if (mesaVis->stencilBits == 8) {
	struct radeon_renderbuffer *depthStencilRb =
           radeon_create_renderbuffer(MESA_FORMAT_Z24_UNORM_S8_UINT, driDrawPriv);
	_mesa_add_renderbuffer(&rfb->base, BUFFER_DEPTH, &depthStencilRb->base.Base);
	_mesa_add_renderbuffer(&rfb->base, BUFFER_STENCIL, &depthStencilRb->base.Base);
	depthStencilRb->has_surface = screen->depthHasSurface;
      } else {
	/* depth renderbuffer */
	struct radeon_renderbuffer *depth =
           radeon_create_renderbuffer(MESA_FORMAT_Z24_UNORM_X8_UINT, driDrawPriv);
	_mesa_add_renderbuffer(&rfb->base, BUFFER_DEPTH, &depth->base.Base);
	depth->has_surface = screen->depthHasSurface;
      }
    } else if (mesaVis->depthBits == 16) {
        /* just 16-bit depth buffer, no hw stencil */
	struct radeon_renderbuffer *depth =
           radeon_create_renderbuffer(MESA_FORMAT_Z_UNORM16, driDrawPriv);
	_mesa_add_renderbuffer(&rfb->base, BUFFER_DEPTH, &depth->base.Base);
	depth->has_surface = screen->depthHasSurface;
    }

    _swrast_add_soft_renderbuffers(&rfb->base,
	    GL_FALSE, /* color */
	    swDepth,
	    swStencil,
	    swAccum,
	    swAlpha,
	    GL_FALSE /* aux */);
    driDrawPriv->driverPrivate = (void *) rfb;

    return (driDrawPriv->driverPrivate != NULL);
}
Example #7
0
/**
 * Create a renderbuffer for a window's color, depth and/or stencil buffer.
 * Not used for user-created renderbuffers.
 */
struct radeon_renderbuffer *
radeon_create_renderbuffer(gl_format format, __DRIdrawable *driDrawPriv)
{
    struct radeon_renderbuffer *rrb;

    rrb = CALLOC_STRUCT(radeon_renderbuffer);

    radeon_print(RADEON_TEXTURE, RADEON_TRACE,
		"%s( rrb %p ) \n",
		__func__, rrb);

    if (!rrb)
	return NULL;

    _mesa_init_renderbuffer(&rrb->base, 0);
    rrb->base.ClassID = RADEON_RB_CLASS;

    rrb->base.Format = format;

    switch (format) {
        case MESA_FORMAT_RGB565:
	    assert(_mesa_little_endian());
	    rrb->base.DataType = GL_UNSIGNED_BYTE;
            rrb->base._BaseFormat = GL_RGB;
	    break;
        case MESA_FORMAT_RGB565_REV:
	    assert(!_mesa_little_endian());
	    rrb->base.DataType = GL_UNSIGNED_BYTE;
            rrb->base._BaseFormat = GL_RGB;
	    break;
        case MESA_FORMAT_XRGB8888:
	    assert(_mesa_little_endian());
	    rrb->base.DataType = GL_UNSIGNED_BYTE;
            rrb->base._BaseFormat = GL_RGB;
	    break;
        case MESA_FORMAT_XRGB8888_REV:
	    assert(!_mesa_little_endian());
	    rrb->base.DataType = GL_UNSIGNED_BYTE;
            rrb->base._BaseFormat = GL_RGB;
	    break;
	case MESA_FORMAT_ARGB8888:
	    assert(_mesa_little_endian());
	    rrb->base.DataType = GL_UNSIGNED_BYTE;
            rrb->base._BaseFormat = GL_RGBA;
	    break;
	case MESA_FORMAT_ARGB8888_REV:
	    assert(!_mesa_little_endian());
	    rrb->base.DataType = GL_UNSIGNED_BYTE;
            rrb->base._BaseFormat = GL_RGBA;
	    break;
	case MESA_FORMAT_S8:
	    rrb->base.DataType = GL_UNSIGNED_BYTE;
            rrb->base._BaseFormat = GL_STENCIL_INDEX;
	    break;
	case MESA_FORMAT_Z16:
	    rrb->base.DataType = GL_UNSIGNED_SHORT;
            rrb->base._BaseFormat = GL_DEPTH_COMPONENT;
	    break;
	case MESA_FORMAT_X8_Z24:
	    rrb->base.DataType = GL_UNSIGNED_INT;
            rrb->base._BaseFormat = GL_DEPTH_COMPONENT;
	    break;
	case MESA_FORMAT_S8_Z24:
	    rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT;
            rrb->base._BaseFormat = GL_DEPTH_STENCIL;
	    break;
	default:
	    fprintf(stderr, "%s: Unknown format %s\n",
                    __FUNCTION__, _mesa_get_format_name(format));
	    _mesa_delete_renderbuffer(&rrb->base);
	    return NULL;
    }

    rrb->dPriv = driDrawPriv;
    rrb->base.InternalFormat = _mesa_get_format_base_format(format);

    rrb->base.Delete = radeon_delete_renderbuffer;
    rrb->base.AllocStorage = radeon_alloc_window_storage;
    rrb->base.GetPointer = radeon_get_pointer;

    rrb->bo = NULL;
    return rrb;
}
Example #8
0
GLboolean
_mesa_texstore_rg_rgtc2(TEXSTORE_PARAMS)
{
   GLubyte *dst;
   const GLubyte *tempImage = NULL;
   int i, j;
   int numxpixels, numypixels;
   const GLubyte *srcaddr;
   GLubyte srcpixels[4][4];
   GLubyte *blkaddr;
   GLint dstRowDiff, rgRowStride;
   mesa_format tempFormat;
   GLubyte *tempImageSlices[1];

   assert(dstFormat == MESA_FORMAT_RG_RGTC2_UNORM ||
          dstFormat == MESA_FORMAT_LA_LATC2_UNORM);

   if (baseInternalFormat == GL_RG)
      tempFormat = _mesa_little_endian() ? MESA_FORMAT_R8G8_UNORM
                                         : MESA_FORMAT_G8R8_UNORM;
   else
      tempFormat = _mesa_little_endian() ? MESA_FORMAT_L8A8_UNORM
                                         : MESA_FORMAT_A8L8_UNORM;

   rgRowStride = 2 * srcWidth * sizeof(GLubyte);
   tempImage = malloc(srcWidth * srcHeight * 2 * sizeof(GLubyte));
   if (!tempImage)
      return GL_FALSE; /* out of memory */
   tempImageSlices[0] = (GLubyte *) tempImage;
   _mesa_texstore(ctx, dims,
                  baseInternalFormat,
                  tempFormat,
                  rgRowStride, tempImageSlices,
                  srcWidth, srcHeight, srcDepth,
                  srcFormat, srcType, srcAddr,
                  srcPacking);

   dst = dstSlices[0];

   blkaddr = dst;
   dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 0;
   for (j = 0; j < srcHeight; j+=4) {
      if (srcHeight > j + 3) numypixels = 4;
      else numypixels = srcHeight - j;
      srcaddr = tempImage + j * srcWidth * 2;
      for (i = 0; i < srcWidth; i += 4) {
	 if (srcWidth > i + 3) numxpixels = 4;
	 else numxpixels = srcWidth - i;
	 extractsrc_u(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2);
	 util_format_unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);

	 blkaddr += 8;
	 extractsrc_u(srcpixels, (GLubyte *)srcaddr + 1, srcWidth, numxpixels, numypixels, 2);
	 util_format_unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);

	 blkaddr += 8;

	 srcaddr += numxpixels * 2;
      }
      blkaddr += dstRowDiff;
   }

   free((void *) tempImage);

   return GL_TRUE;
}
Example #9
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 #10
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;
}