/**
   * @param pGLState
   * @throws IOException
   */
  @Override
  protected void writeTextureToHardware(final GLState pGLState) throws IOException {
    final IPVRTexturePixelBufferStrategyBufferManager pvrTextureLoadStrategyManager =
        this.mPVRTexturePixelBufferStrategy.newPVRTexturePixelBufferStrategyManager(this);

    int width = this.getWidth();
    int height = this.getHeight();

    final int dataLength = this.mPVRTextureHeader.getDataLength();

    final int bytesPerPixel =
        this.mPVRTextureHeader.getBitsPerPixel() / DataConstants.BITS_PER_BYTE;

    final boolean useDefaultAlignment =
        MathUtils.isPowerOfTwo(width)
            && MathUtils.isPowerOfTwo(height)
            && this.mPVRTextureHeader.mPVRTextureFormat == PVRTextureFormat.RGBA_8888;
    if (!useDefaultAlignment) {
      /* Adjust unpack alignment. */
      GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1);
    }

    int currentLevel = 0;
    int currentPixelDataOffset = 0;
    while (currentPixelDataOffset < dataLength) {
      if (currentLevel > 0 && (width != height || MathUtils.nextPowerOfTwo(width) != width)) {
        Debug.w(
            "Mipmap level '"
                + currentLevel
                + "' is not squared. Width: '"
                + width
                + "', height: '"
                + height
                + "'. Texture won't render correctly.");
      }

      final int currentPixelDataSize = height * width * bytesPerPixel;

      /* Load the current level. */
      this.mPVRTexturePixelBufferStrategy.loadPVRTextureData(
          pvrTextureLoadStrategyManager,
          width,
          height,
          bytesPerPixel,
          this.mPixelFormat,
          currentLevel,
          currentPixelDataOffset,
          currentPixelDataSize);

      currentPixelDataOffset += currentPixelDataSize;

      /* Prepare next mipmap level. */
      width = Math.max(width / 2, 1);
      height = Math.max(height / 2, 1);

      currentLevel++;
    }

    if (!useDefaultAlignment) {
      /* Restore default unpack alignment. */
      GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, GLState.GL_UNPACK_ALIGNMENT_DEFAULT);
    }
  }
  @Override
  protected void writeTextureToHardware(final GLState pGLState) {
    final PixelFormat pixelFormat = this.mBitmapTextureFormat.getPixelFormat();
    final int glInternalFormat = pixelFormat.getGLInternalFormat();
    final int glFormat = pixelFormat.getGLFormat();
    final int glType = pixelFormat.getGLType();

    GLES20.glTexImage2D(
        GLES20.GL_TEXTURE_2D,
        0,
        glInternalFormat,
        this.mWidth,
        this.mHeight,
        0,
        glFormat,
        glType,
        null);

    final boolean preMultipyAlpha = this.mTextureOptions.mPreMultiplyAlpha;
    /* Non alpha premultiplied bitmaps are loaded with ARGB_8888 and converted down manually. */
    final Config bitmapConfig =
        (preMultipyAlpha) ? this.mBitmapTextureFormat.getBitmapConfig() : Config.ARGB_8888;

    final ArrayList<IBitmapTextureAtlasSource> textureSources = this.mTextureAtlasSources;
    final int textureSourceCount = textureSources.size();

    final ITextureAtlasStateListener<IBitmapTextureAtlasSource> textureStateListener =
        this.getTextureAtlasStateListener();
    for (int i = 0; i < textureSourceCount; i++) {
      final IBitmapTextureAtlasSource bitmapTextureAtlasSource = textureSources.get(i);
      try {
        final Bitmap bitmap = bitmapTextureAtlasSource.onLoadBitmap(bitmapConfig);
        if (bitmap == null) {
          throw new NullBitmapException(
              "Caused by: "
                  + bitmapTextureAtlasSource.getClass().toString()
                  + " --> "
                  + bitmapTextureAtlasSource.toString()
                  + " returned a null Bitmap.");
        }

        final boolean useDefaultAlignment =
            MathUtils.isPowerOfTwo(bitmap.getWidth())
                && MathUtils.isPowerOfTwo(bitmap.getHeight())
                && pixelFormat == PixelFormat.RGBA_8888;
        if (!useDefaultAlignment) {
          /* Adjust unpack alignment. */
          GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1);
        }

        if (preMultipyAlpha) {
          GLUtils.texSubImage2D(
              GLES20.GL_TEXTURE_2D,
              0,
              bitmapTextureAtlasSource.getTextureX(),
              bitmapTextureAtlasSource.getTextureY(),
              bitmap,
              glFormat,
              glType);
        } else {
          pGLState.glTexSubImage2D(
              GLES20.GL_TEXTURE_2D,
              0,
              bitmapTextureAtlasSource.getTextureX(),
              bitmapTextureAtlasSource.getTextureY(),
              bitmap,
              this.mPixelFormat);
        }

        if (!useDefaultAlignment) {
          /* Restore default unpack alignment. */
          GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, GLState.GL_UNPACK_ALIGNMENT_DEFAULT);
        }

        bitmap.recycle();

        if (textureStateListener != null) {
          textureStateListener.onTextureAtlasSourceLoaded(this, bitmapTextureAtlasSource);
        }
      } catch (final NullBitmapException e) {
        if (textureStateListener != null) {
          textureStateListener.onTextureAtlasSourceLoadExeption(this, bitmapTextureAtlasSource, e);
        } else {
          throw e;
        }
      }
    }
  }