C++程序  |  476行  |  16.34 KB

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <unistd.h>


#define DRAW_TO_SCREEN 1
#define USE_16BPP_TEXTURE 0 // forces texture to load as 16bpp, define before image_file.h

#ifdef __arm__
#define PATH_PREFIX "/data/"
#else
#define PATH_PREFIX ""
#endif

#include <pixelflinger2/pixelflinger2_interface.h>
#include "image_file.h"
#include "m_matrix.h"

#ifdef __arm__
extern "C" int SetupDrawingSurface(unsigned * width, unsigned * height, unsigned * bpp);
extern "C" void * PresentDrawingSurface();
extern "C" void DisposeDrawingSurface();
#endif

GGLInterface * ggl = NULL;

gl_shader * load_shader(const unsigned type, const char * path)
{
   FILE * file = NULL;
   file = fopen(path, "rb");
   if (!file)
      printf("failed to open '%s' \n", path);

   fseek(file, 0, SEEK_END);
   unsigned fileSize = ftell(file);
   fseek(file, 0, SEEK_SET);

   char * shader_string = (char *)malloc(fileSize + 1);
   printf("fileSize=%dB \n", fileSize);
   int read = fread(shader_string, 1, fileSize, file);
   shader_string[read] = '\0';
   fclose(file);

   puts(shader_string);
   puts("compiling shader...");

   gl_shader * shader = ggl->ShaderCreate(ggl, type);
   const char * infoLog = NULL;
   GLboolean compileStatus = ggl->ShaderCompile(ggl, shader, shader_string, &infoLog);

   printf("shader.InfoLog = %s \nshader.CompileStatus = %d \n\n",
          infoLog, compileStatus);
   if (!compileStatus)
      exit(1);

   free(shader_string);
   return shader;
}

gl_shader_program * init_shader()
{
   puts("\n -- load vertex shader -- \n");
   struct gl_shader * vertShader = load_shader(GL_VERTEX_SHADER, PATH_PREFIX"vs.vert");

   puts("\n -- load fragment shader -- \n");
   struct gl_shader * fragShader =  load_shader(GL_FRAGMENT_SHADER, PATH_PREFIX"fs.frag");

   gl_shader_program * program = ggl->ShaderProgramCreate(ggl);
   // current scan_test assumes the following attribute layout
   ggl->ShaderAttributeBind(program, 0, "aPosition");
   ggl->ShaderAttributeBind(program, 1, "aTexCoord");

   puts("\n -- linking -- \n");
   ggl->ShaderAttach(ggl, program, vertShader);
   ggl->ShaderAttach(ggl, program, fragShader);
   const char * infoLog = NULL;
   GLboolean linkStatus = ggl->ShaderProgramLink(program, &infoLog);

   printf("finished linking, LinkStatus=%d \n %s \n", linkStatus, infoLog);

   if (!linkStatus)
      exit(1);

   ggl->ShaderUse(ggl, program);

   return program;
}

void test_scan()
{
   srand(1337);
   ggl = CreateGGLInterface();

   GGLSurface frameSurface = {0};
#if defined __arm__ && DRAW_TO_SCREEN
   unsigned width = 0, height = 0, bpp = 0;
   SetupDrawingSurface(&width, &height, &bpp);
   frameSurface.data = PresentDrawingSurface();
#else
   const unsigned width = 640, height = 400;
   frameSurface.data = (unsigned int *)malloc(width * height * 4);
#endif

   frameSurface.format = GGL_PIXEL_FORMAT_RGBA_8888;
   frameSurface.width = width;
   frameSurface.height = height;

   GGLSurface depthSurface = {0};
   depthSurface.width = width;
   depthSurface.height = height;
   depthSurface.format = GGL_PIXEL_FORMAT_Z_32;
   depthSurface.data = malloc(width * height * 4);
   ggl->SetBuffer(ggl, GL_DEPTH_BUFFER_BIT, &depthSurface);

   GGLSurface stencilSurface = {0};
   stencilSurface.width = width;
   stencilSurface.height = height;
   stencilSurface.format = GGL_PIXEL_FORMAT_S_8;
   stencilSurface.data = malloc(width * height);

   ggl->SetBuffer(ggl, GL_STENCIL_BUFFER_BIT, &stencilSurface);
   ggl->ClearStencil(ggl, 0);
   ggl->StencilFuncSeparate(ggl, GL_FRONT_AND_BACK, GL_EQUAL, 0, 0xff);
   ggl->StencilOpSeparate(ggl, GL_FRONT_AND_BACK, GL_INCR, GL_KEEP, GL_KEEP);
   //ggl->EnableDisable(ggl, GL_STENCIL_TEST, true);

   gl_shader_program * program = init_shader(); // change states after to test code cache

   GGLTexture texture = {0};
   LoadTGA(PATH_PREFIX"android.tga", &texture.width, &texture.height,
           &texture.levels);
//    for (unsigned i = 0; i < texture.width * texture.height; i++)
//    {
//        const unsigned x = i % 480, y = i / 480;
//        ((unsigned *)texture.levels[0])[i] = ((x + y) % 2) * 0xffffff | 0xff000000;
//    }
#if USE_16BPP_TEXTURE
   texture.format = GGL_PIXEL_FORMAT_RGB_565;
#else
   texture.format = GGL_PIXEL_FORMAT_RGBA_8888;
#endif
   texture.type = GL_TEXTURE_2D;
   texture.levelCount = 1;
   texture.wrapS = texture.wrapT = GGLTexture::GGL_REPEAT; // repeat = 0 fastest, clamp = 1, mirrored = 2
   texture.minFilter = texture.magFilter = GGLTexture::GGL_NEAREST; // nearest = 0, linear = 1
   //texture.levelCount = GenerateMipmaps(texture.levels, texture.width, texture.height);

   //    static unsigned texels [6] = {0xff0000ff, 0xff00ff00, 0xffff0000,
   //    0xff00ffff, 0xffffff00, 0xffff00ff};
   //    memcpy(texture.levels[0], texels, sizeof texels);
   //    texture.format = GGL_PIXEL_FORMAT_RGBA_8888;
   //    texture.width = texture.height = 1;
   //texture.height /= 6;
   //texture.type = GL_TEXTURE_CUBE_MAP;

   ggl->SetSampler(ggl, 0, &texture);

   //ggl->EnableDisable(ggl, GL_CULL_FACE, true);
   ggl->FrontFace(ggl, GL_CW);
   ggl->CullFace(ggl, GL_BACK);

   ggl->EnableDisable(ggl, GL_BLEND, true);
   ggl->BlendFuncSeparate(ggl, GL_ONE_MINUS_CONSTANT_COLOR, GL_CONSTANT_COLOR,
                          GL_ONE_MINUS_CONSTANT_COLOR, GL_CONSTANT_COLOR);
   ggl->BlendEquationSeparate(ggl, GL_FUNC_ADD, GL_FUNC_ADD);
   ggl->BlendColor(ggl, 0.7, 0.7, 0.7, 1);

   ggl->SetBuffer(ggl, GL_COLOR_BUFFER_BIT, &frameSurface);


   ggl->EnableDisable(ggl, GL_DEPTH_TEST, true);
   ggl->DepthFunc(ggl, GL_LESS);

   ggl->DepthRangef(ggl, 0.0f, 1.0f);
   ggl->Viewport(ggl, 0, 0, width, height);

   const unsigned scale = 1, portWidth = 640, portHeight = 400;
   //const unsigned scale = 1, portWidth = width / scale, portHeight = height / scale;
   ggl->Viewport(ggl, 0, 0, portWidth, portHeight);
   //ggl->Viewport(ggl, (width - portWidth) / 2, (height - portHeight) / 2,
   //portWidth, portHeight);

   GLmatrix m0, m1, m2, m3, m4;
   _math_matrix_ctr(&m0);
   _math_matrix_ctr(&m1);
   _math_matrix_ctr(&m2);
   _math_matrix_ctr(&m3);
   _math_matrix_ctr(&m4);

   int uMatrixLoc = ggl->ShaderUniformLocation(program, "uMatrix");
   int uRotMLoc = ggl->ShaderUniformLocation(program, "uRotM");
   int uTLoc = ggl->ShaderUniformLocation(program, "t");

   GGLTexture cubeTexture = {GL_TEXTURE_CUBE_MAP, GGL_PIXEL_FORMAT_RGBA_8888, 1, 1, 1, NULL, GGLTexture::GGL_CLAMP_TO_EDGE, GGLTexture::GGL_MIRRORED_REPEAT, GGLTexture::GGL_LINEAR, GGLTexture::GGL_LINEAR};
   unsigned cubeTextureSurface [6] = {0xff0000ff, 0xff00ff00, 0xffff0000,
                                      0xff00ffff, 0xffffff00, 0xffff00ff
                                     };
   void * levels [1] = {cubeTextureSurface};
   cubeTexture.levels = levels;
   if (program) {
      ggl->ShaderUniformMatrix(program, 4, 4, uMatrixLoc, 1, GL_FALSE, m0.m);
      int sampler2dLoc = ggl->ShaderUniformLocation(program, "sampler2d");
      int samplercubeLoc = ggl->ShaderUniformLocation(program, "samplercube");
      int samplerUnit = -1;
      if (0 <= sampler2dLoc) { // set 2d texture to sampler if used
         samplerUnit = sampler2dLoc;//ggl->ShaderUniformGetiv(ggl, program, sampler2dLoc, &samplerUnit);
         ggl->SetSampler(ggl, samplerUnit, &texture);
      }
      if (0 <= samplercubeLoc) { // set cube texture to sampler if used
         samplerUnit = samplercubeLoc;//ggl->ShaderUniformGetiv(ggl, program, samplercubeLoc, &samplerUnit);
         ggl->SetSampler(ggl, samplerUnit, &cubeTexture);
      }
   }

   VertexInput v0, v1, v2, v3;
   const float z = +0.5;
//    const float vcMin = -10, vcMax = 10;
//    const float tcMin = -4.5, tcMax = 5.5;
   const float vcMin = -1, vcMax = 1;
   const float tcMin = 0, tcMax = 1;
   v0.attributes[0] = Vector4_CTR(vcMin,vcMin,z,1);
   v0.attributes[1] = Vector4_CTR(tcMin,tcMin,0,1);

   v1.attributes[0] = Vector4_CTR(vcMin,vcMax,z,1);
   v1.attributes[1] = Vector4_CTR(tcMin,tcMax,0,1);

   v2.attributes[0] = Vector4_CTR(vcMax,vcMax,z,1);
   v2.attributes[1] = Vector4_CTR(tcMax,tcMax,0,1);

   v3.attributes[0] = Vector4_CTR(vcMax,vcMin,z,1);
   v3.attributes[1] = Vector4_CTR(tcMax,tcMin,0,1);

   VertexInput vertices[8] = {
      //  pos         texcoord
      {{Vector4_CTR(-1,-1,-1,1), Vector4_CTR(tcMin,tcMin,0,1)}},
      {{Vector4_CTR(-1,-1, 1,1), Vector4_CTR(tcMin,tcMax,0,1)}},
      {{Vector4_CTR( 1,-1, 1,1), Vector4_CTR(tcMax,tcMax,0,1)}},
      {{Vector4_CTR( 1,-1,-1,1), Vector4_CTR(tcMax,tcMin,0,1)}},
      {{Vector4_CTR(-1, 1,-1,1), Vector4_CTR(tcMin,tcMin,0,1)}},
      {{Vector4_CTR(-1, 1, 1,1), Vector4_CTR(tcMin,tcMax,0,1)}},
      {{Vector4_CTR( 1, 1, 1,1), Vector4_CTR(tcMax,tcMax,0,1)}},
      {{Vector4_CTR( 1, 1,-1,1), Vector4_CTR(tcMax,tcMin,0,1)}},
   };

   unsigned indices[] = {
      0,1,2,  0,2,3,
      4,5,6,  4,6,7,
      0,3,4,  3,4,7,
      1,2,5,  2,5,6,
      0,1,4,  1,4,5,
      2,3,6,  3,6,7,
   };

   Vector4 pos = v0.attributes[0];
   ggl->ViewportTransform(ggl, &pos);

   ggl->ClearColor(ggl, 0.8f, 0.8f, 1, 1);
   //ggl->ClearDepthf(ggl, pos.z + 0.0001f); // when there is no transform in vs
   ggl->ClearDepthf(ggl, 1);
   ggl->EnableDisable(ggl, GL_BLEND, false);
   ggl->EnableDisable(ggl, GL_DEPTH_TEST, true);
   ggl->EnableDisable(ggl, GL_STENCIL_TEST, false);


   ggl->DrawTriangle(ggl, &v0, &v0, &v0); // cause re-JIT to not mess up timing

   puts("\n -- begin rendering -- \n");

   unsigned frames = 0;
   clock_t c0 = clock();

#ifdef __arm__
   //while (true)
#endif
   for (
#ifdef __arm__
      unsigned i = 0; i <= 90; i++
#else
      unsigned i = 0; i <= 10; i+= 1
#endif
   ) {
//      printf("frame=%d \n", i);
      ggl->Clear(ggl, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      //ggl->Clear(ggl, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

      _math_matrix_set_identity(&m0);
      _math_matrix_set_identity(&m1);
      _math_matrix_set_identity(&m2);
      //_math_matrix_set_identity(&m3);


      //_math_matrix_ortho(&m0, 0, 480, 0, 800, 0.1, 1);
      _math_matrix_perspective(&m0, 60, (float)width / height, 0.1f, 100);
      //float ratio = (float)width / height;
      //_math_matrix_frustum(&m0, -ratio, ratio, -1, 1, 3, 7);

      _math_matrix_lookat(&m1, 0, 0, -6,
                          0, 0, 2,
                          0, 1, 0);

      //_math_matrix_scale(&m0, 0.2, 0.2, 0.2);
      //_math_matrix_translate(&m2, 1, 1, 1);
      _math_matrix_rotate(&m2, i * 2, 1, 2, 3);
      //_math_matrix_rotate(&m2, i, 0, 0, 1);

      // matrix on the right is applied to vector first
      _math_matrix_mul_matrix(&m3, &m1, &m2);
      _math_matrix_mul_matrix(&m4, &m0, &m3);


      float t = i * 0.6f;
      if (program) {
         ggl->ShaderUniformMatrix(program, 4, 4, uMatrixLoc, 1, GL_FALSE, m4.m);
         ggl->ShaderUniformMatrix(program, 4, 4, uRotMLoc, 1, GL_FALSE, m2.m);
         ggl->ShaderUniform(program, uTLoc, 1, &t, GL_FLOAT);
      }

      //ggl->EnableDisable(ggl, GL_BLEND, true);
      //ggl->EnableDisable(ggl, GL_BLEND, false);
      //ggl->EnableDisable(ggl, GL_BLEND, (i + 1) % 2);
      //ggl->EnableDisable(ggl, GL_STENCIL_TEST, i / 2 % 2);
      //ggl->BlendColor(ggl,(float)i / 10, (float) i / 15, (float)i < 20, 1);

      for (unsigned j = 0; j < sizeof(indices) / sizeof(*indices); j += 3)
         ggl->DrawTriangle(ggl, vertices + indices[j], vertices + indices[j+1], vertices + indices[j+2]);

      // including clear, depth, and other ops, direct ScanLine calls are 4% faster than DrawTriangle
      // X86 memcpy is 0.60ms vs 4.90ms for 480*800 fs texturing
      // Nexus One memcpy is 8.7ms vs 71ms for 480*800 fs texturing
      // Nexus One fixed point 480*800 fs texturing is 61ms
      // texture * vtexcoord is 70ms, floating texture * vtexcoord is 170ms
      //memcpy(((GGLContext *)ggl)->frameSurface.data, ((GGLContext *)ggl)->textureState.textures[0].levels[0], width * height * 4);

//      ggl->DrawTriangle(ggl, &v0, &v1, &v2);
//      ggl->DrawTriangle(ggl, &v2, &v3, &v0);

//        VertexOutput tl = {0, Vector4(0,0,0,1), Vector4(0,0,0,1)};
//        VertexOutput tr = {0, Vector4(portWidth - 1,0,0,1), Vector4(1,0,0,1)};
//        VertexOutput bl = {0, Vector4(0, portHeight-1,0,1), Vector4(0,1,0,1)};
//        VertexOutput br = {0, Vector4(portWidth - 1, portHeight - 1,0,1), Vector4(1,1,0,1)};
//        ggl->RasterTrapezoid(ggl, &tl, &tr, &bl, &br);
//
//        for (unsigned y = 0; y < portHeight; y++)
//        {
//            VertexOutput vo0 = {0, Vector4(0,y,0,1), Vector4(0,float(y) / (portHeight - 1),0,1)};
//            VertexOutput vo1 = {0, Vector4(portWidth - 1,y,0,1), Vector4(1,float(y) / (portHeight - 1),0,1)};
//            ggl->ScanLine(ggl, &vo0, &vo1);
//        }

//#if !USE_LLVM_TEXTURE_SAMPLER
//        extern const GGLContext * textureGGLContext;
//        textureGGLContext = (GGLContext *)ggl;
//#endif
//        for (unsigned y = 0; y < height; y++)
//            for (unsigned x = 0; x < width; x++)
//            {
//                const unsigned index = y * width + x;
////                ((unsigned *)frameSurface.data)[index] = ((unsigned *)textureGGLContext->textureState.textures[0].levels[0])[index];
//                Vector4 tc(float(x) / (width - 1), float(y) / (height - 1), 0, 0);
//                unsigned color[4];
//                tex2d_int32<GGL_PIXEL_FORMAT_RGBA_8888>(color, (const float *)&tc, 0);
//                ((unsigned *)frameSurface.data)[index] = color[0];
//            }
//#if !USE_LLVM_TEXTURE_SAMPLER
//        textureGGLContext = NULL;
//#endif

      frames++;
      if (scale > 1)
         for (int y = portHeight - 1; y >= 0; y--)
            for (int x = portWidth - 1; x >= 0; x--) {
               unsigned pixel = ((unsigned *)frameSurface.data)[y * width + x];
               for (unsigned xx = 0; xx < scale; xx++)
                  for (unsigned yy = 0; yy < scale; yy++)
                     ((unsigned *)frameSurface.data)[(y * scale + yy) * width + x * scale + xx] = pixel;
            }

#if defined __arm__ && DRAW_TO_SCREEN
      frameSurface.data = PresentDrawingSurface();
      ggl->SetBuffer(ggl, GL_COLOR_BUFFER_BIT, &frameSurface);
#endif
      //puts("frame completed, press ENTER"); getchar();
   }

   /*
   #ifndef __arm__
   __attribute__ ((aligned (16))) // LLVM generates movaps on X86, needs 16 bytes align
   #endif
   float data [64];
   ShaderFunction_t function = ((GGLContext *)ggl)->glCtx->Shader.CurrentProgram->GLVMFP->function;
   float * inputs = data;
   float * outputs = data + 24;
   float * constants = data + 48;
   const unsigned wd = 200, ht = 200;
    for (unsigned y = 0; y < ht; y++)
   	for (unsigned x = 0; x < wd; x++)
   {
   	inputs[4] = ((float)x) / wd;
   	inputs[5] = ((float)y) / ht;
   	inputs[6] = 0;
   	inputs[7] = 1;
   	constants[0] = 0.0f;
   	function(inputs, outputs, constants);
   	unsigned r = outputs[0] * 255;
   	unsigned g = outputs[1] * 255;
   	unsigned b = outputs[2] * 255;
   	unsigned a = outputs[3] * 255;
   	((unsigned *)frameSurface.data)[y * width + x] = (a << 24) | (b << 16) | (g << 8) | r;
   }
   printf("gl_FragColor=%.2f, %.2f, %.2f %.2f \n", outputs[0], outputs[1], outputs[2], outputs[3]);
   frames = 1;
   //*/

   float elapsed = (float)(clock() - c0) / CLOCKS_PER_SEC;
   printf ("\n *** test_scan elapsed CPU time: %fs \n *** fps=%.2f, tpf=%.2fms \n",
           elapsed, frames / elapsed, elapsed / frames * 1000);
#if USE_16BPP_TEXTURE
   puts("USE_16BPP_TEXTURE");
#endif
#ifdef __arm__
   SaveBMP("/sdcard/mesa.bmp", (unsigned *)frameSurface.data, frameSurface.width, frameSurface.height);
#else
   SaveBMP("mesa.bmp", (unsigned *)frameSurface.data, frameSurface.width, frameSurface.height);
#endif

   ggl->SetBuffer(ggl, GL_COLOR_BUFFER_BIT, NULL);
#if defined __arm__ && DRAW_TO_SCREEN
   DisposeDrawingSurface();
#else
   free(frameSurface.data);
#endif

   ggl->SetBuffer(ggl, GL_DEPTH_BUFFER_BIT, NULL);
   free(depthSurface.data);

   ggl->SetBuffer(ggl, GL_STENCIL_BUFFER_BIT, NULL);
   free(stencilSurface.data);

   if (program)
      ggl->ShaderProgramDelete(ggl, program);

   free(texture.levels);

   DestroyGGLInterface(ggl);
   ggl = NULL;
}

extern "C" int cmain(int,char**);

#include "llvm/LLVMContext.h"

void GLContextDctr();

extern "C" void hieralloc_report(const void *, FILE *);
extern "C" void hieralloc_report_brief(const void *, FILE *);

int main (int argc, char * const argv[])
{
   cmain(0,NULL);

//   contextless_test();
   
//   contextless_test();
   
   test_scan();
   
//   hieralloc_report(NULL, stdout);
   hieralloc_report_brief(NULL, stdout);
   puts("mesa done");
   return 0;
}