1//
2// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7//            Based on Simple_VertexShader.c from
8// Book:      OpenGL(R) ES 2.0 Programming Guide
9// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
10// ISBN-10:   0321502795
11// ISBN-13:   9780321502797
12// Publisher: Addison-Wesley Professional
13// URLs:      http://safari.informit.com/9780321563835
14//            http://www.opengles-book.com
15
16#include "SampleApplication.h"
17#include "shader_utils.h"
18#include "texture_utils.h"
19#include "geometry_utils.h"
20#include "Vector.h"
21#include "Matrix.h"
22#include <iostream>
23
24class PostSubBufferSample : public SampleApplication
25{
26  public:
27    PostSubBufferSample::PostSubBufferSample()
28        : SampleApplication("PostSubBuffer", 1280, 720)
29    {
30    }
31
32    virtual bool initialize()
33    {
34        mPostSubBufferNV = (PFNEGLPOSTSUBBUFFERNVPROC)eglGetProcAddress("eglPostSubBufferNV");
35        if (!mPostSubBufferNV)
36        {
37            std::cerr << "Could not load eglPostSubBufferNV.";
38            return false;
39        }
40
41        const std::string vs = SHADER_SOURCE
42        (
43            uniform mat4 u_mvpMatrix;
44            attribute vec4 a_position;
45            attribute vec2 a_texcoord;
46            varying vec2 v_texcoord;
47            void main()
48            {
49                gl_Position = u_mvpMatrix * a_position;
50                v_texcoord = a_texcoord;
51            }
52        );
53
54        const std::string fs = SHADER_SOURCE
55        (
56            precision mediump float;
57            varying vec2 v_texcoord;
58            void main()
59            {
60                gl_FragColor = vec4(v_texcoord.x, v_texcoord.y, 1.0, 1.0);
61            }
62        );
63
64        mProgram = CompileProgram(vs, fs);
65        if (!mProgram)
66        {
67            return false;
68        }
69
70        // Get the attribute locations
71        mPositionLoc = glGetAttribLocation(mProgram, "a_position");
72        mTexcoordLoc = glGetAttribLocation(mProgram, "a_texcoord");
73
74        // Get the uniform locations
75        mMVPMatrixLoc = glGetUniformLocation(mProgram, "u_mvpMatrix");
76
77        // Generate the geometry data
78        GenerateCubeGeometry(0.5f, &mCube);
79
80        // Set an initial rotation
81        mRotation = 45.0f;
82
83        // Clear the whole window surface to blue.
84        glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
85        glClear(GL_COLOR_BUFFER_BIT);
86        SampleApplication::swap();
87
88        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
89        glCullFace(GL_BACK);
90        glEnable(GL_CULL_FACE);
91
92        return true;
93    }
94
95    virtual void destroy()
96    {
97        glDeleteProgram(mProgram);
98    }
99
100    virtual void step(float dt, double totalTime)
101    {
102        mRotation = fmod(mRotation + (dt * 40.0f), 360.0f);
103
104        Matrix4 perspectiveMatrix = Matrix4::perspective(60.0f, float(getWindow()->getWidth()) / getWindow()->getHeight(),
105                                                         1.0f, 20.0f);
106
107        Matrix4 modelMatrix = Matrix4::translate(Vector3(0.0f, 0.0f, -2.0f)) *
108                              Matrix4::rotate(mRotation, Vector3(1.0f, 0.0f, 1.0f));
109
110        Matrix4 viewMatrix = Matrix4::identity();
111
112        Matrix4 mvpMatrix = perspectiveMatrix * viewMatrix * modelMatrix;
113
114        // Load the matrices
115        glUniformMatrix4fv(mMVPMatrixLoc, 1, GL_FALSE, mvpMatrix.data);
116    }
117
118    virtual void draw()
119    {
120        // Set the viewport
121        glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
122
123        // Clear the color buffer
124        glClear(GL_COLOR_BUFFER_BIT);
125
126        // Use the program object
127        glUseProgram(mProgram);
128
129        // Load the vertex position
130        glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, mCube.positions.data());
131        glEnableVertexAttribArray(mPositionLoc);
132
133        // Load the texcoord data
134        glVertexAttribPointer(mTexcoordLoc, 2, GL_FLOAT, GL_FALSE, 0, mCube.texcoords.data());
135        glEnableVertexAttribArray(mTexcoordLoc);
136
137        // Draw the cube
138        glDrawElements(GL_TRIANGLES, mCube.indices.size(), GL_UNSIGNED_SHORT, mCube.indices.data());
139    }
140
141    virtual void swap()
142    {
143        // Instead of letting the application call eglSwapBuffers, call eglPostSubBufferNV here instead
144        size_t windowWidth = getWindow()->getWidth();
145        size_t windowHeight = getWindow()->getHeight();
146        EGLDisplay display = getDisplay();
147        EGLSurface surface = getSurface();
148        mPostSubBufferNV(display, surface, 60, 60, windowWidth - 120, windowHeight - 120);
149    }
150
151  private:
152    // Handle to a program object
153    GLuint mProgram;
154
155    // Attribute locations
156    GLint mPositionLoc;
157    GLint mTexcoordLoc;
158
159    // Uniform locations
160    GLuint mMVPMatrixLoc;
161
162    // Current rotation
163    float mRotation;
164
165    // Geometry data
166    CubeGeometry mCube;
167
168    // eglPostSubBufferNV entry point
169    PFNEGLPOSTSUBBUFFERNVPROC mPostSubBufferNV;
170};
171
172int main(int argc, char **argv)
173{
174    PostSubBufferSample app;
175    return app.run();
176}
177