Developers Club geek daily blog

5 years, 3 months ago
More recently there were a new version of Android — 4.3. Already long before it release there leaks at first for Galaxy S4, and then and Nexus 4. In these insertions I finding out at once libraries for operation with OpenGL ES 3.0 that inexpressibly pleasing — hearings that the demos of OpenGL ES 3.0 show still in March on HTC One worked on native libraries of Android, prov to be true (equally and as hearings about support of Bluetooth Low Energy).
And here OTA of update simultaneously on our two devices — Nexus 4 and Nexus 10 on Friday evening c. On Nexus 7 update while 4.3 doing not come, but it nisklko did not afflict us (why — I will explain later). Certainly, hands comb it kindly to test.
OpenGL ES 3.0 in Android 4.3 — compression of textures of ETC2


Entrance — that new in OpenGL ES 3.0


In the new version of OpenGL ES 3.0 there a lot of new possibilities, to enumerate which I will not become, about them it are possible to learn from the documentation here: www.khronos.org/opengles/3_X
and in the short press release here: www.khronos.org/news/press/khronos-releases-opengl-es-3.0-specification
In g article we will affect the most simple and most fast in application possibility of OpenGL ES 3.0 — a new standard format of compression of textures of ETC2.

ETC2


The format of compression of ETC2 were develop on the basis of ETC1 and it the principle of operation are based on sequences of bits not us in ETC1. To understand genius of how it were possible to expand with ETC1 to ETC2 it are necessary to read these documents:
description of algorithm of compression: www.jacobstrom.com/publications/StromPetterssonGH07.pdf
and description of a format of ETC2: www.graphicshardware.org/previous/www_2007/presentations/strom-etc2-gh07.pdf
ETC2 as well as ETC1, worked with units of 4х4 pixels, but for each unit stole up particular algorithm of compression — normal ETC1 or one of three additional algorithms.
As a result of ETC2 it turning out rather depthbalanced algorithm of compression who allowed as to save up sharpness of boundaries in one units, and not to distort the smooth gradients in others.
Here an example of compression of various images from documents:
OpenGL ES 3.0 in Android 4.3 — compression of textures of ETC2

Initialization of OpenGL ES 3.0


For initialization of OpenGL ES 3.0 in Android 4.3 it are not required any additional manipulations. It are necessary to create a normal context of OpenGL ES 2.0. If GPU supported OpenGL ES 3.0 Android automatically will create a context of OpenGL ES 3.0 who are completely backward-compatible with OpenGL ES 2.0. That is on Android 4.3 all applications us OpenGL ES 2.0, actually worked with OpenGL ES 3.0. To make sure that a half-scientific context — 3.0, it are necessary to check up a line of GL_VERSION. A code sample from source codes of Android 4.3: android.googlesource.com/platform/frameworks/base/+/android-4.3_r0.9/libs/hwui/Extensions.cpp
Thanks of Romain Guy for it and other explanations about usage of OpenGL ES 3.0 in day of release 4.3: plus.google.com/u/0/+RomainGuy/posts/iJmTjpUfR5E

Example of Java of the code:
        protected int mOpenGLVersionMajor;
        protected int mOpenGLVersionMinor;

    String strGLVersion = GLES20.glGetString(GLES20.GL_VERSION);
        if (strGLVersion != null) {
         Scanner scanner = new Scanner(strGLVersion);
            scanner.useDelimiter("[^\\w']+");

            int i = 0;
            while (scanner.hasNext()) {
                if (scanner.hasNextInt()) {
                    if (i == 0) {
                        mOpenGLVersionMajor = scanner.nextInt();
                        i++;
                    }
                    if (i == 1) {
                        mOpenGLVersionMinor = scanner.nextInt();
                        i++;
                    }
                }
                if (scanner.hasNext()) {
                    scanner.next();
                }
            }
        }

    protected Boolean isES2() {
        return mOpenGLVersionMajor == 2;
    }

    protected Boolean isES3() {
        return mOpenGLVersionMajor == 3;
    }


nVidia


Here perhaps, there are a sense to explain, why to us the time delay of update of Nexus 7 to Android 4.3 are unimportant. The matter is that Nvidia Tegra 2/3 chips done not support OpenGL ES 3.0. Unfortunately, even Tegra 4 did not support it. the Nvidia simply continued to push the desktopny decisions in mobile chips, and the marketing department this decision lag behind life successfully are more their pushed. That only there are rather ridiculous justification of it in Tegra 4 Whitepaper, page 11: www.nvidia.com/docs/IO/116757/Tegra_4_GPU_Whitepaper_FINALv2.pdf They recognized that the chip did not support the complete specification of ES 3.0, and openly spoken that all the same “we done not expect that applications/games will shortly use ES 3.0”. The surprise — Android 4.3 used OpenGL ES 3.0.
Though thus that the Nvidia are not going to expand at all current chips for support of ES 3.0, Tegra 5 nevertheless already it will support: www.ubergizmo.com/2013/07/nvidia-tegra-5-release-date-specs-news/

Creation of oblate textures


For creation of ETC2 textures the inmtrument of Mali Texture Compression Tool were us: malideveloper.arm.com/develop-for-mali/mali-gpu-texture-compression-tool/. For obtaining of the best quality teksur were us a method of compression of "Slow" and Error Metric “Perceptual”.
OpenGL ES 3.0 in Android 4.3 — compression of textures of ETC2
Images for comparing of quality of compression of ETC1 and ETC2, and also a difference between the original and oblate image, strengthen in 4th time for descriptive reasons was more low result.
OpenGL ES 3.0 in Android 4.3 — compression of textures of ETC2
At compression of a texture in ETC1 artifacts in the form of the horizontal was noticeable (was especially well visible) also vertical bands. At compression of ETC2 these artifacts practically missed.
In our live wall-paper on sections of scenes for whom quality of a texture are critical, textures without compression was us. Apparently on the comparative image, ETC1 imported most noticeable distortions to textures with the smooth gradients — the artifacts of compression caus by a singularity of compression by squares in the size 4х4 pixels become accurately visible. Therefore to the sky we applied textures without compression, and they taken very many place — after all the size 2048х512 are more their. Compression in a format of PVRTC also gave high enough quality of textures, but are accessible only on PowerVR chips. Application standard for ES allowing to reach 3.0 formats of ETC2 of comprehensible quality of a texture at abbreviation of volume of the videostorage select for a texture in 4th time:
For a texture 2048х512:
Not oblate (16-bit color of 565 — 2 bytes on pixel): 2*2048*512= 2097152/2 2 MB of the data
Compress (16 byte — title of PKM): 524304-16= 524288/512 KB of the data.

Loading of ETC2 of a texture


The texture booted from a file of.pkm. The same format are us for storage of textures of ETC1. The format of title are describ here: forums.arm.com/index.php?/topic/15835-pkm-header-format/
Deciding not to try to load ETC2 of a texture by means of ETC1Util as in it there are validatsiya of title.
The code for loading of a texture:

    protected int loadETC2Texture(String filename, int compression, Boolean bClamp, Boolean bHighQuality) {
        int[] textures = new int[1];
        GLES20.glGenTextures(1, textures, 0);

        int textureID = textures[0];
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureID);

        if (bHighQuality) {
            GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
            GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
        } else {
            GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
            GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
        }

        if (bClamp) {
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
        } else {
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
        }

        InputStream is = null;
        try {
            is = mWallpaper.getContext().getAssets().open(filename);
        } catch (IOException e1) {
            e1.printStackTrace();
        }

        try {
            byte[] data = readFile(is);

            ByteBuffer buffer = ByteBuffer.allocateDirect(data.length).order(ByteOrder.LITTLE_ENDIAN);
            buffer.put(data).position(PKM_HEADER_SIZE);

            ByteBuffer header = ByteBuffer.allocateDirect(PKM_HEADER_SIZE).order(ByteOrder.BIG_ENDIAN);
            header.put(data, 0, PKM_HEADER_SIZE).position(0);

            int width = header.getShort(PKM_HEADER_WIDTH_OFFSET);
            int height = header.getShort(PKM_HEADER_HEIGHT_OFFSET);

            GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D, 0, compression, width, height, 0, data.length - PKM_HEADER_SIZE, buffer);
            checkGlError("Loading of ETC2 texture; call to glCompressedTexImage2D()");
        } catch (Exception e) {
            Log.w(TAG, "Could not load ETC2 texture: " + e);
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                // ignore exception thrown from close.
            }
        }

        return textureID;
    }

...
if (isES3()) {
    textureID = loadETC2Texture("textures/etc2/sky1.pkm", GLES30.GL_COMPRESSED_RGB8_ETC2, false, false);
} else {
    textureID = loadTexture("textures/sky1.png");
}
...

Thus, in the presence of a context of ES 3.0 the texture of ETC2, and in a mode of ES 2.0 — a normal not oblate texture will boot.
Certainly, for access to a class of GLES30 it are necessary to set android:targetSdkVersion = «18» in the manifesto of application and target=android-18 in project.properties.

Result


In application a difference between not oblate texture (without distortions) and ETC2 are not noticeable:
OpenGL ES 3.0 in Android 4.3 — compression of textures of ETC2
Application are accessible on the link: play.google.com/store/apps/details?id=org.androidworks.livewallpapercarfree

Inference


We always tried to use new possibilities of each new version of Android for optimization of productivity and the extension of possibilities. In particular, wall-paper supported also operation in a mode of a picture — daydream. Though the article turning out also insufficiently volume, but I hopes that our modest experience in usage of ETC2 could to somebody it are useful for optimization of the applications.

P.S.

If someone putting to itself(himself) the flow-away insertion 4.3 for Samsung Galaxy S4, please check up operation of this application on this device.

This article is a translation of the original post at habrahabr.ru/post/188252/
If you have any questions regarding the material covered in the article above, please, contact the original author of the post.
If you have any complaints about this article or you want this article to be deleted, please, drop an email here: sysmagazine.com@gmail.com.

We believe that the knowledge, which is available at the most popular Russian IT blog habrahabr.ru, should be accessed by everyone, even though it is poorly translated.
Shared knowledge makes the world better.
Best wishes.

comments powered by Disqus