/*
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License"); 
** you may not use this file except in compliance with the License. 
** You may obtain a copy of the License at 
**
**     http://www.apache.org/licenses/LICENSE-2.0 
**
** Unless required by applicable law or agreed to in writing, software 
** distributed under the License is distributed on an "AS IS" BASIS, 
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
** See the License for the specific language governing permissions and 
** limitations under the License.
*/

#define LOG_TAG "fillrate"

#include <stdlib.h>
#include <stdio.h>

#include <EGL/egl.h>
#include <GLES/gl.h>
#include <GLES/glext.h>

#include <utils/StopWatch.h>
#include <WindowSurface.h>
#include <EGLUtils.h>

using namespace android;

int main(int /*argc*/, char** /*argv*/)
{
    EGLint configAttribs[] = {
         EGL_DEPTH_SIZE, 0,
         EGL_NONE
     };
     
     EGLint majorVersion;
     EGLint minorVersion;
     EGLContext context;
     EGLConfig config;
     EGLSurface surface;
     EGLint w, h;
     EGLDisplay dpy;

     WindowSurface windowSurface;
     EGLNativeWindowType window = windowSurface.getSurface();
     
     dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
     eglInitialize(dpy, &majorVersion, &minorVersion);
          
     status_t err = EGLUtils::selectConfigForNativeWindow(
             dpy, configAttribs, window, &config);
     if (err) {
         fprintf(stderr, "couldn't find an EGLConfig matching the screen format\n");
         return 0;
     }

     surface = eglCreateWindowSurface(dpy, config, window, NULL);
     context = eglCreateContext(dpy, config, NULL, NULL);
     eglMakeCurrent(dpy, surface, surface, context);   
     eglQuerySurface(dpy, surface, EGL_WIDTH, &w);
     eglQuerySurface(dpy, surface, EGL_HEIGHT, &h);
     
     printf("w=%d, h=%d\n", w, h);
     
     glBindTexture(GL_TEXTURE_2D, 0);
     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
     glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
     glDisable(GL_DITHER);
     glEnable(GL_BLEND);
     glEnable(GL_TEXTURE_2D);
     glColor4f(1,1,1,1);

     uint32_t* t32 = (uint32_t*)malloc(512*512*4); 
     for (int y=0 ; y<512 ; y++) {
         for (int x=0 ; x<512 ; x++) {
             int u = x-256;
             int v = y-256;
             if (u*u+v*v < 256*256) {
                 t32[x+y*512] = 0x10FFFFFF;
             } else {
                 t32[x+y*512] = 0x20FF0000;
             }
         }
     }

     const GLfloat fh = h;
     const GLfloat fw = w;
     const GLfloat vertices[4][2] = {
             { 0,   0  },
             { 0,   fh },
             { fw,  fh },
             { fw,  0  }
     };

     const GLfloat texCoords[4][2] = {
             { 0,  0 },
             { 0,  1 },
             { 1,  1 },
             { 1,  0 }
     };

     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, t32);

     glViewport(0, 0, w, h);
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
     glOrthof(0, w, 0, h, 0, 1);

     glEnableClientState(GL_VERTEX_ARRAY);
     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
     glVertexPointer(2, GL_FLOAT, 0, vertices);
     glTexCoordPointer(2, GL_FLOAT, 0, texCoords);

     eglSwapInterval(dpy, 1);

     glClearColor(1,0,0,0);
     glClear(GL_COLOR_BUFFER_BIT);
     glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
     eglSwapBuffers(dpy, surface);
     

     nsecs_t times[32];

     for (int c=1 ; c<32 ; c++) {
         glClear(GL_COLOR_BUFFER_BIT);
         for (int i=0 ; i<c ; i++) {
             glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
         }
         eglSwapBuffers(dpy, surface);
     }


     //     for (int c=31 ; c>=1 ; c--) {
     int j=0;
     for (int c=1 ; c<32 ; c++) {
         glClear(GL_COLOR_BUFFER_BIT);
         nsecs_t now = systemTime();
         for (int i=0 ; i<c ; i++) {
             glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
         }
         eglSwapBuffers(dpy, surface);
         nsecs_t t = systemTime() - now;
         times[j++] = t;
     }

     for (int c=1, j=0 ; c<32 ; c++, j++) {
         nsecs_t t = times[j];
         printf("%lld\t%d\t%f\n", (long long)t, c, (double(t)/c)/1000000.0);
     }


       
     eglTerminate(dpy);
     
     return 0;
}
