예제 #1
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;
      }
   }
}
예제 #2
0
파일: texgetimage.c 프로젝트: cpp3ds/gl3ds
/**
 * Get texture image.
 *
 * \param texture texture name.
 * \param level image level.
 * \param format pixel data format for returned image.
 * \param type pixel data type for returned image.
 * \param bufSize size of the pixels data buffer.
 * \param pixels returned pixel data.
 */
void glGetTextureImage(GLuint texture, GLint level, GLenum format,
                      GLenum type, GLsizei bufSize, GLvoid *pixels)
{
   struct gl_texture_object *texObj;
   struct gl_texture_image *texImage;
   int i;
   GLint image_stride;
   GLenum err;
   GET_CURRENT_CONTEXT(ctx);

   /*
    * This has been moved here because a format/type mismatch can cause a NULL
    * texImage object, which in turn causes the mismatch error to be
    * ignored.
    */
   err = _mesa_error_check_format_and_type(ctx, format, type);
   if (err != GL_NO_ERROR) {
      _mesa_error(ctx, err, "glGetTextureImage(format/type)");
      return;
   }

   texObj = _mesa_lookup_texture_err(ctx, texture, "glGetTextureImage");
   if (!texObj)
      return;

   /*
    * Legal target checking has been moved here to prevent exiting with a NULL
    * texImage object.
    */
   if (!legal_getteximage_target(ctx, texObj->Target, true)) {
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTextureImage(target=%s)",
                  _mesa_lookup_enum_by_nr(texObj->Target));
      return;
   }

   /* Must handle special case GL_TEXTURE_CUBE_MAP. */
   if (texObj->Target == GL_TEXTURE_CUBE_MAP) {

      /* Make sure the texture object is a proper cube.
       * (See texturesubimage in teximage.c for details on why this check is
       * performed.)
       */
      if (!_mesa_cube_level_complete(texObj, level)) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glGetTextureImage(cube map incomplete)");
         return;
      }

      /* Copy each face. */
      for (i = 0; i < 6; ++i) {
         texImage = texObj->Image[i][level];
         assert(texImage);

         _mesa_get_texture_image(ctx, texObj, texImage, texObj->Target, level,
                                 format, type, bufSize, pixels, true);

         image_stride = _mesa_image_image_stride(&ctx->Pack, texImage->Width,
                                                 texImage->Height, format,
                                                 type);
         pixels = (GLubyte *) pixels + image_stride;
         bufSize -= image_stride;
      }
   }
   else {
      texImage = _mesa_select_tex_image(texObj, texObj->Target, level);
      if (!texImage)
         return;

      _mesa_get_texture_image(ctx, texObj, texImage, texObj->Target, level,
                              format, type, bufSize, pixels, true);
   }
}
예제 #3
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);
}