Home | History | Annotate | Download | only in gl2_copyTexImage
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <stdlib.h>
     18 #include <stdio.h>
     19 #include <time.h>
     20 #include <sched.h>
     21 #include <sys/resource.h>
     22 
     23 #include <EGL/egl.h>
     24 #include <GLES2/gl2.h>
     25 #include <GLES2/gl2ext.h>
     26 
     27 #include <utils/Timers.h>
     28 
     29 #include <WindowSurface.h>
     30 #include <EGLUtils.h>
     31 
     32 using namespace android;
     33 
     34 static void printGLString(const char *name, GLenum s) {
     35     // fprintf(stderr, "printGLString %s, %d\n", name, s);
     36     const char *v = (const char *) glGetString(s);
     37     // int error = glGetError();
     38     // fprintf(stderr, "glGetError() = %d, result of glGetString = %x\n", error,
     39     //        (unsigned int) v);
     40     // if ((v < (const char*) 0) || (v > (const char*) 0x10000))
     41     //    fprintf(stderr, "GL %s = %s\n", name, v);
     42     // else
     43     //    fprintf(stderr, "GL %s = (null) 0x%08x\n", name, (unsigned int) v);
     44     fprintf(stderr, "GL %s = %s\n", name, v);
     45 }
     46 
     47 static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
     48     if (returnVal != EGL_TRUE) {
     49         fprintf(stderr, "%s() returned %d\n", op, returnVal);
     50     }
     51 
     52     for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
     53             = eglGetError()) {
     54         fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error),
     55                 error);
     56     }
     57 }
     58 
     59 static void checkGlError(const char* op) {
     60     for (GLint error = glGetError(); error; error
     61             = glGetError()) {
     62         fprintf(stderr, "after %s() glError (0x%x)\n", op, error);
     63     }
     64 }
     65 
     66 static const char gVertexShader[] = "attribute vec4 vPosition;\n"
     67     "void main() {\n"
     68     "  gl_Position = vPosition;\n"
     69     "}\n";
     70 
     71 static const char gFragmentShader[] = "precision mediump float;\n"
     72     "void main() {\n"
     73     "  gl_FragColor = vec4(0.0, 1.0, 0.0, 0.5);\n"
     74     "}\n";
     75 
     76 GLuint loadShader(GLenum shaderType, const char* pSource) {
     77     GLuint shader = glCreateShader(shaderType);
     78     if (shader) {
     79         glShaderSource(shader, 1, &pSource, NULL);
     80         glCompileShader(shader);
     81         GLint compiled = 0;
     82         glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
     83         if (!compiled) {
     84             GLint infoLen = 0;
     85             glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
     86             if (infoLen) {
     87                 char* buf = (char*) malloc(infoLen);
     88                 if (buf) {
     89                     glGetShaderInfoLog(shader, infoLen, NULL, buf);
     90                     fprintf(stderr, "Could not compile shader %d:\n%s\n",
     91                             shaderType, buf);
     92                     free(buf);
     93                 }
     94                 glDeleteShader(shader);
     95                 shader = 0;
     96             }
     97         }
     98     }
     99     return shader;
    100 }
    101 
    102 GLuint createProgram(const char* pVertexSource, const char* pFragmentSource) {
    103     GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
    104     if (!vertexShader) {
    105         return 0;
    106     }
    107 
    108     GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
    109     if (!pixelShader) {
    110         return 0;
    111     }
    112 
    113     GLuint program = glCreateProgram();
    114     if (program) {
    115         glAttachShader(program, vertexShader);
    116         checkGlError("glAttachShader");
    117         glAttachShader(program, pixelShader);
    118         checkGlError("glAttachShader");
    119         glLinkProgram(program);
    120         GLint linkStatus = GL_FALSE;
    121         glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
    122         if (linkStatus != GL_TRUE) {
    123             GLint bufLength = 0;
    124             glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
    125             if (bufLength) {
    126                 char* buf = (char*) malloc(bufLength);
    127                 if (buf) {
    128                     glGetProgramInfoLog(program, bufLength, NULL, buf);
    129                     fprintf(stderr, "Could not link program:\n%s\n", buf);
    130                     free(buf);
    131                 }
    132             }
    133             glDeleteProgram(program);
    134             program = 0;
    135         }
    136     }
    137     return program;
    138 }
    139 
    140 GLuint gProgram;
    141 GLuint gTextureProgram;
    142 GLuint gvPositionHandle;
    143 GLuint gvTexturePositionHandle;
    144 GLuint gvTextureTexCoordsHandle;
    145 GLuint gvTextureSamplerHandle;
    146 GLuint gFbo;
    147 GLuint gTexture;
    148 GLuint gBufferTexture;
    149 
    150 static const char gSimpleVS[] =
    151     "attribute vec4 position;\n"
    152     "attribute vec2 texCoords;\n"
    153     "varying vec2 outTexCoords;\n"
    154     "\nvoid main(void) {\n"
    155     "    outTexCoords = texCoords;\n"
    156     "    gl_Position = position;\n"
    157     "}\n\n";
    158 static const char gSimpleFS[] =
    159     "precision mediump float;\n\n"
    160     "varying vec2 outTexCoords;\n"
    161     "uniform sampler2D texture;\n"
    162     "\nvoid main(void) {\n"
    163     "    gl_FragColor = texture2D(texture, outTexCoords);\n"
    164     "}\n\n";
    165 
    166 bool setupGraphics(int w, int h) {
    167     gProgram = createProgram(gVertexShader, gFragmentShader);
    168     if (!gProgram) {
    169         return false;
    170     }
    171     gvPositionHandle = glGetAttribLocation(gProgram, "vPosition");
    172     checkGlError("glGetAttribLocation");
    173     fprintf(stderr, "glGetAttribLocation(\"vPosition\") = %d\n", gvPositionHandle);
    174 
    175     gTextureProgram = createProgram(gSimpleVS, gSimpleFS);
    176     if (!gTextureProgram) {
    177         return false;
    178     }
    179     gvTexturePositionHandle = glGetAttribLocation(gTextureProgram, "position");
    180     checkGlError("glGetAttribLocation");
    181     gvTextureTexCoordsHandle = glGetAttribLocation(gTextureProgram, "texCoords");
    182     checkGlError("glGetAttribLocation");
    183     gvTextureSamplerHandle = glGetUniformLocation(gTextureProgram, "texture");
    184     checkGlError("glGetAttribLocation");
    185 
    186     glActiveTexture(GL_TEXTURE0);
    187 
    188     glGenTextures(1, &gTexture);
    189     glBindTexture(GL_TEXTURE_2D, gTexture);
    190     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    191     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    192     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    193     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    194     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    195 
    196     glGenTextures(1, &gBufferTexture);
    197     glBindTexture(GL_TEXTURE_2D, gBufferTexture);
    198     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    199     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    200     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    201     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    202     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    203 
    204     glGenFramebuffers(1, &gFbo);
    205     glBindFramebuffer(GL_FRAMEBUFFER, gFbo);
    206     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gTexture, 0);
    207 
    208     glBindFramebuffer(GL_FRAMEBUFFER, 0);
    209 
    210     glViewport(0, 0, w, h);
    211     checkGlError("glViewport");
    212     return true;
    213 }
    214 
    215 const GLfloat gTriangleVertices[] = { 0.0f, 0.5f, -0.5f, -0.5f,
    216         0.5f, -0.5f };
    217 
    218 const GLint FLOAT_SIZE_BYTES = 4;
    219 const GLint TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
    220 const GLfloat gTriangleVerticesData[] = {
    221     // X, Y, Z, U, V
    222     -1.0f, -1.0f, 0, 0.f, 0.f,
    223     1.0f, -1.0f, 0, 1.f, 0.f,
    224     -1.0f,  1.0f, 0, 0.f, 1.f,
    225     1.0f,   1.0f, 0, 1.f, 1.f,
    226 };
    227 
    228 void renderFrame(GLint w, GLint h) {
    229     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
    230     checkGlError("glClearColor");
    231     glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
    232     checkGlError("glClear");
    233 
    234     // Bind FBO and draw into it
    235     glBindFramebuffer(GL_FRAMEBUFFER, gFbo);
    236     checkGlError("glBindFramebuffer");
    237 
    238     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    239     checkGlError("glClearColor");
    240     glClear(GL_COLOR_BUFFER_BIT);
    241     checkGlError("glClear");
    242 
    243     glUseProgram(gProgram);
    244     checkGlError("glUseProgram");
    245 
    246     glVertexAttribPointer(gvPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices);
    247     checkGlError("glVertexAttribPointer");
    248     glEnableVertexAttribArray(gvPositionHandle);
    249     checkGlError("glEnableVertexAttribArray");
    250     glDrawArrays(GL_TRIANGLES, 0, 3);
    251     checkGlError("glDrawArrays");
    252 
    253     // Copy content of FBO into a texture
    254     glBindTexture(GL_TEXTURE_2D, gBufferTexture);
    255     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, w / 2, h / 2);
    256     checkGlError("glCopyTexSubImage2D");
    257 
    258     // Back to the display
    259     glBindFramebuffer(GL_FRAMEBUFFER, 0);
    260     checkGlError("glBindFramebuffer");
    261 
    262     // Draw copied content on the screen
    263     glUseProgram(gTextureProgram);
    264     checkGlError("glUseProgram");
    265 
    266     glEnable(GL_BLEND);
    267     glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
    268 
    269     glVertexAttribPointer(gvTexturePositionHandle, 3, GL_FLOAT, GL_FALSE,
    270             TRIANGLE_VERTICES_DATA_STRIDE_BYTES, gTriangleVerticesData);
    271     checkGlError("glVertexAttribPointer");
    272     glVertexAttribPointer(gvTextureTexCoordsHandle, 2, GL_FLOAT, GL_FALSE,
    273             TRIANGLE_VERTICES_DATA_STRIDE_BYTES, &gTriangleVerticesData[3]);
    274     checkGlError("glVertexAttribPointer");
    275     glEnableVertexAttribArray(gvTexturePositionHandle);
    276     glEnableVertexAttribArray(gvTextureTexCoordsHandle);
    277     checkGlError("glEnableVertexAttribArray");
    278     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    279     checkGlError("glDrawArrays");
    280 }
    281 
    282 void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) {
    283 
    284 #define X(VAL) {VAL, #VAL}
    285     struct {EGLint attribute; const char* name;} names[] = {
    286     X(EGL_BUFFER_SIZE),
    287     X(EGL_ALPHA_SIZE),
    288     X(EGL_BLUE_SIZE),
    289     X(EGL_GREEN_SIZE),
    290     X(EGL_RED_SIZE),
    291     X(EGL_DEPTH_SIZE),
    292     X(EGL_STENCIL_SIZE),
    293     X(EGL_CONFIG_CAVEAT),
    294     X(EGL_CONFIG_ID),
    295     X(EGL_LEVEL),
    296     X(EGL_MAX_PBUFFER_HEIGHT),
    297     X(EGL_MAX_PBUFFER_PIXELS),
    298     X(EGL_MAX_PBUFFER_WIDTH),
    299     X(EGL_NATIVE_RENDERABLE),
    300     X(EGL_NATIVE_VISUAL_ID),
    301     X(EGL_NATIVE_VISUAL_TYPE),
    302     X(EGL_SAMPLES),
    303     X(EGL_SAMPLE_BUFFERS),
    304     X(EGL_SURFACE_TYPE),
    305     X(EGL_TRANSPARENT_TYPE),
    306     X(EGL_TRANSPARENT_RED_VALUE),
    307     X(EGL_TRANSPARENT_GREEN_VALUE),
    308     X(EGL_TRANSPARENT_BLUE_VALUE),
    309     X(EGL_BIND_TO_TEXTURE_RGB),
    310     X(EGL_BIND_TO_TEXTURE_RGBA),
    311     X(EGL_MIN_SWAP_INTERVAL),
    312     X(EGL_MAX_SWAP_INTERVAL),
    313     X(EGL_LUMINANCE_SIZE),
    314     X(EGL_ALPHA_MASK_SIZE),
    315     X(EGL_COLOR_BUFFER_TYPE),
    316     X(EGL_RENDERABLE_TYPE),
    317     X(EGL_CONFORMANT),
    318    };
    319 #undef X
    320 
    321     for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
    322         EGLint value = -1;
    323         EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
    324         EGLint error = eglGetError();
    325         if (returnVal && error == EGL_SUCCESS) {
    326             printf(" %s: ", names[j].name);
    327             printf("%d (0x%x)", value, value);
    328         }
    329     }
    330     printf("\n");
    331 }
    332 
    333 int printEGLConfigurations(EGLDisplay dpy) {
    334     EGLint numConfig = 0;
    335     EGLint returnVal = eglGetConfigs(dpy, NULL, 0, &numConfig);
    336     checkEglError("eglGetConfigs", returnVal);
    337     if (!returnVal) {
    338         return false;
    339     }
    340 
    341     printf("Number of EGL configuration: %d\n", numConfig);
    342 
    343     EGLConfig* configs = (EGLConfig*) malloc(sizeof(EGLConfig) * numConfig);
    344     if (! configs) {
    345         printf("Could not allocate configs.\n");
    346         return false;
    347     }
    348 
    349     returnVal = eglGetConfigs(dpy, configs, numConfig, &numConfig);
    350     checkEglError("eglGetConfigs", returnVal);
    351     if (!returnVal) {
    352         free(configs);
    353         return false;
    354     }
    355 
    356     for(int i = 0; i < numConfig; i++) {
    357         printf("Configuration %d\n", i);
    358         printEGLConfiguration(dpy, configs[i]);
    359     }
    360 
    361     free(configs);
    362     return true;
    363 }
    364 
    365 int main(int /*argc*/, char** /*argv*/) {
    366     EGLBoolean returnValue;
    367     EGLConfig myConfig = {0};
    368 
    369     EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
    370     EGLint s_configAttribs[] = {
    371             EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
    372             EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
    373             EGL_RED_SIZE, 8,
    374             EGL_GREEN_SIZE, 8,
    375             EGL_BLUE_SIZE, 8,
    376             EGL_ALPHA_SIZE, 8,
    377             EGL_NONE };
    378     EGLint majorVersion;
    379     EGLint minorVersion;
    380     EGLContext context;
    381     EGLSurface surface;
    382     EGLint w, h;
    383 
    384     EGLDisplay dpy;
    385 
    386     checkEglError("<init>");
    387     dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    388     checkEglError("eglGetDisplay");
    389     if (dpy == EGL_NO_DISPLAY) {
    390         printf("eglGetDisplay returned EGL_NO_DISPLAY.\n");
    391         return 0;
    392     }
    393 
    394     returnValue = eglInitialize(dpy, &majorVersion, &minorVersion);
    395     checkEglError("eglInitialize", returnValue);
    396     fprintf(stderr, "EGL version %d.%d\n", majorVersion, minorVersion);
    397     if (returnValue != EGL_TRUE) {
    398         printf("eglInitialize failed\n");
    399         return 0;
    400     }
    401 
    402     if (!printEGLConfigurations(dpy)) {
    403         printf("printEGLConfigurations failed\n");
    404         return 0;
    405     }
    406 
    407     checkEglError("printEGLConfigurations");
    408 
    409     WindowSurface windowSurface;
    410     EGLNativeWindowType window = windowSurface.getSurface();
    411     EGLint numConfigs = -1, n = 0;
    412     eglChooseConfig(dpy, s_configAttribs, 0, 0, &numConfigs);
    413     if (numConfigs) {
    414         EGLConfig* const configs = new EGLConfig[numConfigs];
    415         eglChooseConfig(dpy, s_configAttribs, configs, numConfigs, &n);
    416         myConfig = configs[0];
    417         delete[] configs;
    418     }
    419 
    420     checkEglError("EGLUtils::selectConfigForNativeWindow");
    421 
    422     printf("Chose this configuration:\n");
    423     printEGLConfiguration(dpy, myConfig);
    424 
    425     surface = eglCreateWindowSurface(dpy, myConfig, window, NULL);
    426     checkEglError("eglCreateWindowSurface");
    427     if (surface == EGL_NO_SURFACE) {
    428         printf("gelCreateWindowSurface failed.\n");
    429         return 0;
    430     }
    431 
    432     context = eglCreateContext(dpy, myConfig, EGL_NO_CONTEXT, context_attribs);
    433     checkEglError("eglCreateContext");
    434     if (context == EGL_NO_CONTEXT) {
    435         printf("eglCreateContext failed\n");
    436         return 0;
    437     }
    438     returnValue = eglMakeCurrent(dpy, surface, surface, context);
    439     checkEglError("eglMakeCurrent", returnValue);
    440     if (returnValue != EGL_TRUE) {
    441         return 0;
    442     }
    443     eglQuerySurface(dpy, surface, EGL_WIDTH, &w);
    444     checkEglError("eglQuerySurface");
    445     eglQuerySurface(dpy, surface, EGL_HEIGHT, &h);
    446     checkEglError("eglQuerySurface");
    447 
    448     fprintf(stderr, "Window dimensions: %d x %d\n", w, h);
    449 
    450     printGLString("Version", GL_VERSION);
    451     printGLString("Vendor", GL_VENDOR);
    452     printGLString("Renderer", GL_RENDERER);
    453     printGLString("Extensions", GL_EXTENSIONS);
    454 
    455     if(!setupGraphics(w, h)) {
    456         fprintf(stderr, "Could not set up graphics.\n");
    457         return 0;
    458     }
    459 
    460     for (;;) {
    461         renderFrame(w, h);
    462         eglSwapBuffers(dpy, surface);
    463         checkEglError("eglSwapBuffers");
    464     }
    465 
    466     return 0;
    467 }
    468