Ejemplo n.º 1
0
void GLAPIENTRY
_mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel,
                       GLint srcX, GLint srcY, GLint srcZ,
                       GLuint dstName, GLenum dstTarget, GLint dstLevel,
                       GLint dstX, GLint dstY, GLint dstZ,
                       GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth)
{
   GET_CURRENT_CONTEXT(ctx);
   GLuint tmpTexNames[2] = { 0, 0 };
   struct gl_texture_object *srcTexObj, *dstTexObj;
   struct gl_texture_image *srcTexImage, *dstTexImage;
   GLuint src_w, src_h, dst_w, dst_h;
   GLuint src_bw, src_bh, dst_bw, dst_bh;
   int i;

   if (MESA_VERBOSE & VERBOSE_API)
      _mesa_debug(ctx, "glCopyImageSubData(%u, %s, %d, %d, %d, %d, "
                                          "%u, %s, %d, %d, %d, %d, "
                                          "%d, %d, %d)\n",
                  srcName, _mesa_enum_to_string(srcTarget), srcLevel,
                  srcX, srcY, srcZ,
                  dstName, _mesa_enum_to_string(dstTarget), dstLevel,
                  dstX, dstY, dstZ,
                  srcWidth, srcHeight, srcWidth);

   if (!ctx->Extensions.ARB_copy_image) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glCopyImageSubData(extension not available)");
      return;
   }

   if (!prepare_target(ctx, srcName, &srcTarget, srcLevel,
                       &srcTexObj, &srcTexImage, &tmpTexNames[0],
                       &src_w, &src_h, "src"))
      goto cleanup;

   if (!prepare_target(ctx, dstName, &dstTarget, dstLevel,
                       &dstTexObj, &dstTexImage, &tmpTexNames[1],
                       &dst_w, &dst_h, "dst"))
      goto cleanup;

   _mesa_get_format_block_size(srcTexImage->TexFormat, &src_bw, &src_bh);

   /* Section 18.3.2 (Copying Between Images) of the OpenGL 4.5 Core Profile
    * spec says:
    *
    *    An INVALID_VALUE error is generated if the dimensions of either
    *    subregion exceeds the boundaries of the corresponding image object,
    *    or if the image format is compressed and the dimensions of the
    *    subregion fail to meet the alignment constraints of the format.
    *
    * and Section 8.7 (Compressed Texture Images) says:
    *
    *    An INVALID_OPERATION error is generated if any of the following
    *    conditions occurs:
    *
    *      * width is not a multiple of four, and width + xoffset is not
    *        equal to the value of TEXTURE_WIDTH.
    *      * height is not a multiple of four, and height + yoffset is not
    *        equal to the value of TEXTURE_HEIGHT.
    *
    * so we take that to mean that you can copy the "last" block of a
    * compressed texture image even if it's smaller than the minimum block
    * dimensions.
    */
   if ((srcX % src_bw != 0) || (srcY % src_bh != 0) ||
       (srcWidth % src_bw != 0 && (srcX + srcWidth) != src_w) ||
       (srcHeight % src_bh != 0 && (srcY + srcHeight) != src_h)) {
      _mesa_error(ctx, GL_INVALID_VALUE,
                  "glCopyImageSubData(unaligned src rectangle)");
      goto cleanup;
   }

   _mesa_get_format_block_size(dstTexImage->TexFormat, &dst_bw, &dst_bh);
   if ((dstX % dst_bw != 0) || (dstY % dst_bh != 0)) {
      _mesa_error(ctx, GL_INVALID_VALUE,
                  "glCopyImageSubData(unaligned dst rectangle)");
      goto cleanup;
   }

   if (!check_region_bounds(ctx, srcTexImage, srcX, srcY, srcZ,
                            srcWidth, srcHeight, srcDepth, "src"))
      goto cleanup;

   if (!check_region_bounds(ctx, dstTexImage, dstX, dstY, dstZ,
                            (srcWidth / src_bw) * dst_bw,
                            (srcHeight / src_bh) * dst_bh, srcDepth, "dst"))
      goto cleanup;

   if (!copy_format_compatible(ctx, srcTexImage->InternalFormat,
                               dstTexImage->InternalFormat)) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glCopyImageSubData(internalFormat mismatch)");
      goto cleanup;
   }

   for (i = 0; i < srcDepth; ++i) {
      int srcNewZ, dstNewZ;

      if (srcTexObj->Target == GL_TEXTURE_CUBE_MAP) {
         srcTexImage = srcTexObj->Image[i + srcZ][srcLevel];
         srcNewZ = 0;
      } else {
         srcNewZ = srcZ + i;
      }

      if (dstTexObj->Target == GL_TEXTURE_CUBE_MAP) {
         dstTexImage = dstTexObj->Image[i + dstZ][dstLevel];
         dstNewZ = 0;
      } else {
         dstNewZ = dstZ + i;
      }

      ctx->Driver.CopyImageSubData(ctx, srcTexImage, srcX, srcY, srcNewZ,
                                   dstTexImage, dstX, dstY, dstNewZ,
                                   srcWidth, srcHeight);
   }

cleanup:
   _mesa_DeleteTextures(2, tmpTexNames);
}
Ejemplo n.º 2
0
void GLAPIENTRY
_mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel,
                       GLint srcX, GLint srcY, GLint srcZ,
                       GLuint dstName, GLenum dstTarget, GLint dstLevel,
                       GLint dstX, GLint dstY, GLint dstZ,
                       GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth)
{
   GET_CURRENT_CONTEXT(ctx);
   GLuint tmpTexNames[2] = { 0, 0 };
   struct gl_texture_object *srcTexObj, *dstTexObj;
   struct gl_texture_image *srcTexImage, *dstTexImage;
   GLuint src_bw, src_bh, dst_bw, dst_bh;
   int i;

   if (MESA_VERBOSE & VERBOSE_API)
      _mesa_debug(ctx, "glCopyImageSubData(%u, %s, %d, %d, %d, %d, "
                                          "%u, %s, %d, %d, %d, %d, "
                                          "%d, %d, %d)\n",
                  srcName, _mesa_lookup_enum_by_nr(srcTarget), srcLevel,
                  srcX, srcY, srcZ,
                  dstName, _mesa_lookup_enum_by_nr(dstTarget), dstLevel,
                  dstX, dstY, dstZ,
                  srcWidth, srcHeight, srcWidth);

   if (!ctx->Extensions.ARB_copy_image) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glCopyImageSubData(extension not available)");
      return;
   }

   if (!prepare_target(ctx, srcName, &srcTarget, srcLevel,
                       &srcTexObj, &srcTexImage, &tmpTexNames[0], "src"))
      goto cleanup;

   if (!prepare_target(ctx, dstName, &dstTarget, dstLevel,
                       &dstTexObj, &dstTexImage, &tmpTexNames[1], "dst"))
      goto cleanup;

   _mesa_get_format_block_size(srcTexImage->TexFormat, &src_bw, &src_bh);
   if ((srcX % src_bw != 0) || (srcY % src_bh != 0) ||
       (srcWidth % src_bw != 0) || (srcHeight % src_bh != 0)) {
      _mesa_error(ctx, GL_INVALID_VALUE,
                  "glCopyImageSubData(unaligned src rectangle)");
      goto cleanup;
   }

   _mesa_get_format_block_size(dstTexImage->TexFormat, &dst_bw, &dst_bh);
   if ((dstX % dst_bw != 0) || (dstY % dst_bh != 0)) {
      _mesa_error(ctx, GL_INVALID_VALUE,
                  "glCopyImageSubData(unaligned dst rectangle)");
      goto cleanup;
   }

   if (!check_region_bounds(ctx, srcTexImage, srcX, srcY, srcZ,
                            srcWidth, srcHeight, srcDepth, "src"))
      goto cleanup;

   if (!check_region_bounds(ctx, dstTexImage, dstX, dstY, dstZ,
                            (srcWidth / src_bw) * dst_bw,
                            (srcHeight / src_bh) * dst_bh, srcDepth, "dst"))
      goto cleanup;

   if (!copy_format_compatible(ctx, srcTexImage->InternalFormat,
                               dstTexImage->InternalFormat)) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glCopyImageSubData(internalFormat mismatch)");
      goto cleanup;
   }

   for (i = 0; i < srcDepth; ++i) {
      int srcNewZ, dstNewZ;

      if (srcTexObj->Target == GL_TEXTURE_CUBE_MAP) {
         srcTexImage = srcTexObj->Image[i + srcZ][srcLevel];
         srcNewZ = 0;
      } else {
         srcNewZ = srcZ + i;
      }

      if (dstTexObj->Target == GL_TEXTURE_CUBE_MAP) {
         dstTexImage = dstTexObj->Image[i + dstZ][dstLevel];
         dstNewZ = 0;
      } else {
         dstNewZ = dstZ + i;
      }

      ctx->Driver.CopyImageSubData(ctx, srcTexImage, srcX, srcY, srcNewZ,
                                   dstTexImage, dstX, dstY, dstNewZ,
                                   srcWidth, srcHeight);
   }

cleanup:
   _mesa_DeleteTextures(2, tmpTexNames);
}
Ejemplo n.º 3
0
void GLAPIENTRY
_mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel,
                       GLint srcX, GLint srcY, GLint srcZ,
                       GLuint dstName, GLenum dstTarget, GLint dstLevel,
                       GLint dstX, GLint dstY, GLint dstZ,
                       GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth)
{
   GET_CURRENT_CONTEXT(ctx);
   struct gl_texture_image *srcTexImage, *dstTexImage;
   struct gl_renderbuffer *srcRenderbuffer, *dstRenderbuffer;
   mesa_format srcFormat, dstFormat;
   GLenum srcIntFormat, dstIntFormat;
   GLuint src_w, src_h, dst_w, dst_h;
   GLuint src_bw, src_bh, dst_bw, dst_bh;
   GLuint src_num_samples, dst_num_samples;
   int dstWidth, dstHeight, dstDepth;
   int i;

   if (MESA_VERBOSE & VERBOSE_API)
      _mesa_debug(ctx, "glCopyImageSubData(%u, %s, %d, %d, %d, %d, "
                                          "%u, %s, %d, %d, %d, %d, "
                                          "%d, %d, %d)\n",
                  srcName, _mesa_enum_to_string(srcTarget), srcLevel,
                  srcX, srcY, srcZ,
                  dstName, _mesa_enum_to_string(dstTarget), dstLevel,
                  dstX, dstY, dstZ,
                  srcWidth, srcHeight, srcDepth);

   if (!ctx->Extensions.ARB_copy_image) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glCopyImageSubData(extension not available)");
      return;
   }

   if (!prepare_target(ctx, srcName, srcTarget, srcLevel, srcZ, srcDepth,
                       &srcTexImage, &srcRenderbuffer, &srcFormat,
                       &srcIntFormat, &src_w, &src_h, &src_num_samples, "src"))
      return;

   if (!prepare_target(ctx, dstName, dstTarget, dstLevel, dstZ, srcDepth,
                       &dstTexImage, &dstRenderbuffer, &dstFormat,
                       &dstIntFormat, &dst_w, &dst_h, &dst_num_samples, "dst"))
      return;

   _mesa_get_format_block_size(srcFormat, &src_bw, &src_bh);

   /* Section 18.3.2 (Copying Between Images) of the OpenGL 4.5 Core Profile
    * spec says:
    *
    *    An INVALID_VALUE error is generated if the dimensions of either
    *    subregion exceeds the boundaries of the corresponding image object,
    *    or if the image format is compressed and the dimensions of the
    *    subregion fail to meet the alignment constraints of the format.
    *
    * and Section 8.7 (Compressed Texture Images) says:
    *
    *    An INVALID_OPERATION error is generated if any of the following
    *    conditions occurs:
    *
    *      * width is not a multiple of four, and width + xoffset is not
    *        equal to the value of TEXTURE_WIDTH.
    *      * height is not a multiple of four, and height + yoffset is not
    *        equal to the value of TEXTURE_HEIGHT.
    *
    * so we take that to mean that you can copy the "last" block of a
    * compressed texture image even if it's smaller than the minimum block
    * dimensions.
    */
   if ((srcX % src_bw != 0) || (srcY % src_bh != 0) ||
       (srcWidth % src_bw != 0 && (srcX + srcWidth) != src_w) ||
       (srcHeight % src_bh != 0 && (srcY + srcHeight) != src_h)) {
      _mesa_error(ctx, GL_INVALID_VALUE,
                  "glCopyImageSubData(unaligned src rectangle)");
      return;
   }

   _mesa_get_format_block_size(dstFormat, &dst_bw, &dst_bh);
   if ((dstX % dst_bw != 0) || (dstY % dst_bh != 0)) {
      _mesa_error(ctx, GL_INVALID_VALUE,
                  "glCopyImageSubData(unaligned dst rectangle)");
      return;
   }

   /* From the GL_ARB_copy_image spec:
    *
    * "The dimensions are always specified in texels, even for compressed
    * texture formats. But it should be noted that if only one of the
    * source and destination textures is compressed then the number of
    * texels touched in the compressed image will be a factor of the
    * block size larger than in the uncompressed image."
    *
    * So, if copying from compressed to uncompressed, the dest region is
    * shrunk by the src block size factor.  If copying from uncompressed
    * to compressed, the dest region is grown by the dest block size factor.
    * Note that we're passed the _source_ width, height, depth and those
    * dimensions are never changed.
    */
   dstWidth = srcWidth * dst_bw / src_bw;
   dstHeight = srcHeight * dst_bh / src_bh;
   dstDepth = srcDepth;

   if (!check_region_bounds(ctx, srcTarget, srcTexImage, srcRenderbuffer,
                            srcX, srcY, srcZ, srcWidth, srcHeight, srcDepth,
                            "src"))
      return;

   if (!check_region_bounds(ctx, dstTarget, dstTexImage, dstRenderbuffer,
                            dstX, dstY, dstZ, dstWidth, dstHeight, dstDepth,
                            "dst"))
      return;

   /* Section 18.3.2 (Copying Between Images) of the OpenGL 4.5 Core Profile
    * spec says:
    *
    *    An INVALID_OPERATION error is generated if either object is a texture
    *    and the texture is not complete, if the source and destination internal
    *    formats are not compatible, or if the number of samples do not match.
    */
   if (!copy_format_compatible(ctx, srcIntFormat, dstIntFormat)) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glCopyImageSubData(internalFormat mismatch)");
      return;
   }

   if (src_num_samples != dst_num_samples) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glCopyImageSubData(number of samples mismatch)");
      return;
   }

   /* loop over 2D slices/faces/layers */
   for (i = 0; i < srcDepth; ++i) {
      int newSrcZ = srcZ + i;
      int newDstZ = dstZ + i;

      if (srcTexImage &&
          srcTexImage->TexObject->Target == GL_TEXTURE_CUBE_MAP) {
         /* need to update srcTexImage pointer for the cube face */
         assert(srcZ + i < MAX_FACES);
         srcTexImage = srcTexImage->TexObject->Image[srcZ + i][srcLevel];
         assert(srcTexImage);
         newSrcZ = 0;
      }

      if (dstTexImage &&
          dstTexImage->TexObject->Target == GL_TEXTURE_CUBE_MAP) {
         /* need to update dstTexImage pointer for the cube face */
         assert(dstZ + i < MAX_FACES);
         dstTexImage = dstTexImage->TexObject->Image[dstZ + i][dstLevel];
         assert(dstTexImage);
         newDstZ = 0;
      }

      ctx->Driver.CopyImageSubData(ctx,
                                   srcTexImage, srcRenderbuffer,
                                   srcX, srcY, newSrcZ,
                                   dstTexImage, dstRenderbuffer,
                                   dstX, dstY, newDstZ,
                                   srcWidth, srcHeight);
   }
}