1 /*
2  * Copyright (C) 2011 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 "Renderer.h"
18 
19 #include "mosaic/Log.h"
20 #define LOG_TAG "Renderer"
21 
22 #include <GLES2/gl2ext.h>
23 
Renderer()24 Renderer::Renderer()
25       : mGlProgram(0),
26         mInputTextureName(-1),
27         mInputTextureWidth(0),
28         mInputTextureHeight(0),
29         mSurfaceWidth(0),
30         mSurfaceHeight(0)
31 {
32     InitializeGLContext();
33 }
34 
~Renderer()35 Renderer::~Renderer() {
36 }
37 
loadShader(GLenum shaderType,const char * pSource)38 GLuint Renderer::loadShader(GLenum shaderType, const char* pSource) {
39     GLuint shader = glCreateShader(shaderType);
40     if (shader) {
41         glShaderSource(shader, 1, &pSource, NULL);
42         glCompileShader(shader);
43         GLint compiled = 0;
44         glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
45         if (!compiled) {
46             GLint infoLen = 0;
47             glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
48             if (infoLen) {
49                 char* buf = (char*) malloc(infoLen);
50                 if (buf) {
51                     glGetShaderInfoLog(shader, infoLen, NULL, buf);
52                     LOGE("Could not compile shader %d:\n%s\n",
53                             shaderType, buf);
54                     free(buf);
55                 }
56                 glDeleteShader(shader);
57                 shader = 0;
58             }
59         }
60     }
61     return shader;
62 }
63 
createProgram(const char * pVertexSource,const char * pFragmentSource)64 GLuint Renderer::createProgram(const char* pVertexSource, const char* pFragmentSource)
65 {
66     GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
67     if (!vertexShader)
68     {
69         return 0;
70     }
71 
72     GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
73     if (!pixelShader)
74     {
75         return 0;
76     }
77 
78     GLuint program = glCreateProgram();
79     if (program)
80     {
81         glAttachShader(program, vertexShader);
82         checkGlError("glAttachShader");
83         glAttachShader(program, pixelShader);
84         checkGlError("glAttachShader");
85 
86         glLinkProgram(program);
87         GLint linkStatus = GL_FALSE;
88         glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
89 
90         LOGI("Program Linked!");
91 
92         if (linkStatus != GL_TRUE)
93         {
94             GLint bufLength = 0;
95             glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
96             if (bufLength)
97             {
98                 char* buf = (char*) malloc(bufLength);
99                 if (buf)
100                 {
101                     glGetProgramInfoLog(program, bufLength, NULL, buf);
102                     LOGE("Could not link program:\n%s\n", buf);
103                     free(buf);
104                 }
105             }
106             glDeleteProgram(program);
107             program = 0;
108         }
109     }
110     return program;
111 }
112 
113 // Set this renderer to use the default frame-buffer (screen) and
114 // set the viewport size to be the given width and height (pixels).
SetupGraphics(int width,int height)115 bool Renderer::SetupGraphics(int width, int height)
116 {
117     bool succeeded = false;
118     do {
119         if (mGlProgram == 0)
120         {
121             if (!InitializeGLProgram())
122             {
123               break;
124             }
125         }
126         glUseProgram(mGlProgram);
127         if (!checkGlError("glUseProgram")) break;
128 
129         glBindFramebuffer(GL_FRAMEBUFFER, 0);
130 
131         mFrameBuffer = NULL;
132         mSurfaceWidth = width;
133         mSurfaceHeight = height;
134 
135         glViewport(0, 0, mSurfaceWidth, mSurfaceHeight);
136         if (!checkGlError("glViewport")) break;
137         succeeded = true;
138     } while (false);
139 
140     return succeeded;
141 }
142 
143 
144 // Set this renderer to use the specified FBO and
145 // set the viewport size to be the width and height of this FBO.
SetupGraphics(FrameBuffer * buffer)146 bool Renderer::SetupGraphics(FrameBuffer* buffer)
147 {
148     bool succeeded = false;
149     do {
150         if (mGlProgram == 0)
151         {
152             if (!InitializeGLProgram())
153             {
154               break;
155             }
156         }
157         glUseProgram(mGlProgram);
158         if (!checkGlError("glUseProgram")) break;
159 
160         glBindFramebuffer(GL_FRAMEBUFFER, buffer->GetFrameBufferName());
161 
162         mFrameBuffer = buffer;
163         mSurfaceWidth = mFrameBuffer->GetWidth();
164         mSurfaceHeight = mFrameBuffer->GetHeight();
165 
166         glViewport(0, 0, mSurfaceWidth, mSurfaceHeight);
167         if (!checkGlError("glViewport")) break;
168         succeeded = true;
169     } while (false);
170 
171     return succeeded;
172 }
173 
Clear(float r,float g,float b,float a)174 bool Renderer::Clear(float r, float g, float b, float a)
175 {
176     bool succeeded = false;
177     do {
178         bool rt = (mFrameBuffer == NULL)?
179                 SetupGraphics(mSurfaceWidth, mSurfaceHeight) :
180                 SetupGraphics(mFrameBuffer);
181 
182         if(!rt)
183             break;
184 
185         glClearColor(r, g, b, a);
186         glClear(GL_COLOR_BUFFER_BIT);
187 
188         succeeded = true;
189     } while (false);
190     return succeeded;
191 
192 }
193 
InitializeGLContext()194 void Renderer::InitializeGLContext()
195 {
196     if(mFrameBuffer != NULL)
197     {
198         delete mFrameBuffer;
199         mFrameBuffer = NULL;
200     }
201 
202     mInputTextureName = -1;
203     mInputTextureType = GL_TEXTURE_2D;
204     mGlProgram = 0;
205 }
206 
GetTextureName()207 int Renderer::GetTextureName()
208 {
209     return mInputTextureName;
210 }
211 
SetInputTextureName(GLuint textureName)212 void Renderer::SetInputTextureName(GLuint textureName)
213 {
214     mInputTextureName = textureName;
215 }
216 
SetInputTextureType(GLenum textureType)217 void Renderer::SetInputTextureType(GLenum textureType)
218 {
219     mInputTextureType = textureType;
220 }
221 
SetInputTextureDimensions(int width,int height)222 void Renderer::SetInputTextureDimensions(int width, int height)
223 {
224     mInputTextureWidth = width;
225     mInputTextureHeight = height;
226 }
227