Ankit Kumar
Ankit Kumar

Reputation: 11

Getting issue in accessing local storage in runtime (Android ndk) using opengles 3.0

reference: how-to-load-and-display-an-image-in-opengl-es-3-0-using-c

#include <jni.h>
#include <android/log.h>

#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
#include <GLES3/gl3ext.h>
#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define STB_IMAGE_IMPLEMENTATION
#include "include/stb_image.h"

#define  LOG_TAG    "libgl2jni"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

GLuint mTexture, VAO;// Create reference Id for the texture
GLuint gProgram;
GLuint gvPositionHandle;

static void printGLString(const char *name, GLenum s) {
    const char *v = (const char *) glGetString(s);
    LOGI("GL %s = %s\n", name, v);
}

static void checkGlError(const char* op) {
    for (GLint error = glGetError(); error; error
                                                    = glGetError()) {
        LOGI("after %s() glError (0x%x)\n", op, error);
    }
}

auto gVertexShader =
        "#version 300 es\n"
        "layout (location=0) in vec3 position;\n"
        "layout (location=1) in vec3 color;\n"
        "layout (location=2) in vec2 texCoord;\n"

        "out vec3 ourColor;\n"
        "out vec2 TexCoord;\n"

        "void main()\n"
        "{\n"
        "gl_Position = vec4(position,1.0f); // Add the xOffset to the x position of the vertex position\n"
        "ourColor = color;\n"
        "TexCoord= vec2(texCoord.x,1.0f-texCoord.y);\n"
        "}";

auto gFragmentShader =

        "#version 300 es\n"
        "in vec3 ourColor;\n"
        "in vec2 TexCoord;\n"

        "out vec4 color;\n"

        "uniform sampler2D ourTexture;\n"


        "void main()\n"
        "{\n"
        "color = texture(ourTexture , TexCoord);\n"
        "}\n";

GLuint loadShader(GLenum shaderType, const char* pSource) {
    GLuint shader = glCreateShader(shaderType);
    if (shader) {
        glShaderSource(shader, 1, &pSource, NULL);
        glCompileShader(shader);
        GLint compiled = 0;
        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
        if (!compiled) {
            GLint infoLen = 0;
            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
            if (infoLen) {
                char* buf = (char*) malloc(infoLen);
                if (buf) {
                    glGetShaderInfoLog(shader, infoLen, NULL, buf);
                    LOGE("Could not compile shader %d:\n%s\n",
                         shaderType, buf);
                    free(buf);
                }
                glDeleteShader(shader);
                shader = 0;
            }
        }
    }
    return shader;
}

GLuint createProgram(const char* pVertexSource, const char* pFragmentSource) { // Load and Bind Fragments to Progam and link program then return result
    GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
    if (!vertexShader) {
        return 0;
    }

    GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
    if (!pixelShader) {
        return 0;
    }

    GLuint program = glCreateProgram();
    if (program) {
        glAttachShader(program, vertexShader);
        checkGlError("glAttachShader");
        glAttachShader(program, pixelShader);
        checkGlError("glAttachShader");
        glLinkProgram(program);
        GLint linkStatus = GL_FALSE;
        glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
        if (linkStatus != GL_TRUE) {
            GLint bufLength = 0;
            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
            if (bufLength) {
                char* buf = (char*) malloc(bufLength);
                if (buf) {
                    glGetProgramInfoLog(program, bufLength, NULL, buf);
                    LOGE("Could not link program:\n%s\n", buf);
                    free(buf);
                }
            }
            glDeleteProgram(program);
            program = 0;
        }
    }
    return program;
}



bool setupGraphics(int w, int h) {
    printGLString("Version", GL_VERSION);
    printGLString("Vendor", GL_VENDOR);
    printGLString("Renderer", GL_RENDERER);
    printGLString("Extensions", GL_EXTENSIONS);

    LOGI("setupGraphics(%d, %d)", w, h);
    gProgram = createProgram(gVertexShader, gFragmentShader);
    if (!gProgram) {
        LOGE("Could not create program.");
        return false;
    }
    gvPositionHandle = glGetAttribLocation(gProgram, "position");
    checkGlError("glGetAttribLocation");
    LOGI("glGetAttribLocation(\"position\") = %d\n",
         gvPositionHandle);

    glViewport(0, 0, w, h);
    checkGlError("glViewport");
    return true;
}

GLfloat recVertices[] = {
        // Positions          // Colors          // Texture Coords
        0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,    1.0f, 1.0f,   // Top Right
        0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,    1.0f, 0.0f,   // Bottom Right
        -0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f,   // Bottom Left
        -0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f    // Top Left
};

GLuint indices[] = {  // Note that we start from 0!
        0, 1, 3, // First Triangle
        1, 2, 3  // Second Triangle
};
void initBuffers()
{

    GLuint VBOs[2], EBO; // Initialize an buffer to store all the verticles and transfer them to the GPU
    glGenVertexArrays (1,&VAO); // Generate VAO
    glGenBuffers(1, VBOs); // Generate VBO
    glGenBuffers(1, &EBO); // Generate EBO
    glBindVertexArray (VAO);// Bind the Vertex Array

    glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);//Bind verticles array for OpenGL to use
    glBufferData(GL_ARRAY_BUFFER, sizeof(recVertices), recVertices, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);//Bind the indices for information about drawing sequence
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    // 1. set the vertex attributes pointers
    // Position Attribute
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);
    // Color Attribute
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
    glEnableVertexAttribArray(1);
    //Texture Coordinate Attribute
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
    glEnableVertexAttribArray(2);

    glBindVertexArray(0);//3. Unbind VAO

}

void generateTexture()
{

    glGenTextures(1 , &mTexture);
    glBindTexture(GL_TEXTURE_2D, mTexture);// Bind our 2D texture so that following set up will be applied

    //Set texture wrapping parameter
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_MIRRORED_REPEAT);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_MIRRORED_REPEAT);

    //Set texture Filtering parameter
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
    
    int picWidth,picHeight,n;
    unsigned char* image = stbi_load("/storage/emulated/0/Pictures/frame.png", &picWidth, &picHeight, &n,0);
    if (image == NULL ) {
        LOGI("Failed to load image: %s", stbi_failure_reason());
    }
    //Generate the image
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA , picWidth , picHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
    glGenerateMipmap(GL_TEXTURE_2D);

    stbi_image_free(image);// Free the reference to the image
    glBindTexture(GL_TEXTURE_2D,0); //Unbind 2D textures

}
void renderFrame() {
    static float grey;
    grey += 0.01f;
    if (grey > 1.0f) {
        grey = 0.0f;
    }

    generateTexture();
    glClearColor(grey+0.05f, grey-0.03f, grey+0.02f, grey-0.04f);
    checkGlError("glClearColor");
    glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
    checkGlError("glClear");

    glUseProgram(gProgram);
    checkGlError("glUseProgram");

    /*glVertexAttribPointer(gvPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, recVertices);
    checkGlError("glVertexAttribPointer");
    glEnableVertexAttribArray(gvPositionHandle);
    checkGlError("glEnableVertexAttribArray");
    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
    checkGlError("glDrawArrays");*/
    glActiveTexture(GL_TEXTURE0);
    checkGlError("glActiveTexture");
    glBindTexture(GL_TEXTURE_2D,mTexture);
    checkGlError("glBindTexture");
    GLint mlocation = glGetUniformLocation(gProgram,"ourTexture");
    checkGlError("glGetUniformLocation");
    glUniform1i(mlocation,0);
    checkGlError("glUniform1i");
    initBuffers();
    glBindVertexArray(VAO);
    checkGlError("glBindVertexArray");
    glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0);

}

extern "C" {
JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_init(JNIEnv *env, jobject assetManager,
                                                              jint width,
                                                              jint height);
JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_step(JNIEnv *env, jobject assetManager);

};

JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_init(JNIEnv* env, jobject assetManager,
                                                              jint width,
                                                              jint height) {
    setupGraphics(width, height);
}

JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_step(JNIEnv* env,jobject assetManager) {
    renderFrame();
}

I am using this following code in my sample Android NDK app using OpenGL-ES 3.0 and stb_image library. But I am getting error while accessing an image with following in api call stb_load(). even I have added android permissions in xml file.

Android log I am getting:

533986  10-03   15:43:53.528    E   4714    26053   MediaProvider:       Permission to access file: /storage/emulated/0/Pictures/frame.png is denied
533988  10-03   15:43:53.537    E   4714    5104    MediaProvider:       Permission to access file: /storage/emulated/0/Pictures/frame.png is denied
533990  10-03   15:43:53.544    E   4714    5109    MediaProvider:       Permission to access file: /storage/emulated/0/Pictures/frame.png is denied
533992  10-03   15:43:53.553    E   4714    26457   MediaProvider:       Permission to access file: /storage/emulated/0/Pictures/frame.png is denied
533994  10-03   15:43:53.562    E   4714    8229    MediaProvider:       Permission to access file: /storage/emulated/0/Pictures/frame.png is denied
533996  10-03   15:43:53.570    E   4714    14229   MediaProvider:       Permission to access file: /storage/emulated/0/Pictures/frame.png is denied
533998  10-03   15:43:53.578    E   4714    26053   MediaProvider:       Permission to access file: /storage/emulated/0/Pictures/frame.png is denied
534000  10-03   15:43:53.586    E   4714    5104    MediaProvider:       Permission to access file: /storage/emulated/0/Pictures/frame.png is denied

I tried using giving android permissions:

  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:required="true" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:required="true"/>
  <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" android:required="true"/>

And using stb_load.h library to load the image.

Upvotes: 1

Views: 48

Answers (0)

Related Questions