GLES20RenderEngine.cpp revision c18790018be5d7ea7061ccbc81f3044e74adc823
1/* 2 * Copyright 2013 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#define ATRACE_TAG ATRACE_TAG_GRAPHICS 18 19#include <GLES2/gl2.h> 20#include <GLES2/gl2ext.h> 21 22#include <ui/Rect.h> 23 24#include <utils/String8.h> 25#include <utils/Trace.h> 26 27#include <cutils/compiler.h> 28 29#include "GLES20RenderEngine.h" 30#include "Program.h" 31#include "ProgramCache.h" 32#include "Description.h" 33#include "Mesh.h" 34#include "Texture.h" 35 36// --------------------------------------------------------------------------- 37namespace android { 38// --------------------------------------------------------------------------- 39 40GLES20RenderEngine::GLES20RenderEngine() : 41 mVpWidth(0), mVpHeight(0) { 42 43 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize); 44 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims); 45 46 glPixelStorei(GL_UNPACK_ALIGNMENT, 4); 47 glPixelStorei(GL_PACK_ALIGNMENT, 4); 48 49 struct pack565 { 50 inline uint16_t operator() (int r, int g, int b) const { 51 return (r<<11)|(g<<5)|b; 52 } 53 } pack565; 54 55 const uint16_t protTexData[] = { 0 }; 56 glGenTextures(1, &mProtectedTexName); 57 glBindTexture(GL_TEXTURE_2D, mProtectedTexName); 58 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 59 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 60 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 61 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 62 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, 63 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, protTexData); 64 65 //mColorBlindnessCorrection = M; 66} 67 68GLES20RenderEngine::~GLES20RenderEngine() { 69} 70 71 72size_t GLES20RenderEngine::getMaxTextureSize() const { 73 return mMaxTextureSize; 74} 75 76size_t GLES20RenderEngine::getMaxViewportDims() const { 77 return 78 mMaxViewportDims[0] < mMaxViewportDims[1] ? 79 mMaxViewportDims[0] : mMaxViewportDims[1]; 80} 81 82void GLES20RenderEngine::setViewportAndProjection( 83 size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, bool yswap) { 84 85 size_t l = sourceCrop.left; 86 size_t r = sourceCrop.right; 87 88 // In GL, (0, 0) is the bottom-left corner, so flip y coordinates 89 size_t t = hwh - sourceCrop.top; 90 size_t b = hwh - sourceCrop.bottom; 91 92 mat4 m; 93 if (yswap) { 94 m = mat4::ortho(l, r, t, b, 0, 1); 95 } else { 96 m = mat4::ortho(l, r, b, t, 0, 1); 97 } 98 99 glViewport(0, 0, vpw, vph); 100 mState.setProjectionMatrix(m); 101 mVpWidth = vpw; 102 mVpHeight = vph; 103} 104 105void GLES20RenderEngine::setupLayerBlending( 106 bool premultipliedAlpha, bool opaque, int alpha) { 107 108 mState.setPremultipliedAlpha(premultipliedAlpha); 109 mState.setOpaque(opaque); 110 mState.setPlaneAlpha(alpha / 255.0f); 111 112 if (alpha < 0xFF || !opaque) { 113 glEnable(GL_BLEND); 114 glBlendFunc(premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 115 } else { 116 glDisable(GL_BLEND); 117 } 118} 119 120void GLES20RenderEngine::setupDimLayerBlending(int alpha) { 121 mState.setPlaneAlpha(1.0f); 122 mState.setPremultipliedAlpha(true); 123 mState.setOpaque(false); 124 mState.setColor(0, 0, 0, alpha/255.0f); 125 mState.disableTexture(); 126 127 if (alpha == 0xFF) { 128 glDisable(GL_BLEND); 129 } else { 130 glEnable(GL_BLEND); 131 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); 132 } 133} 134 135void GLES20RenderEngine::setupLayerTexturing(const Texture& texture) { 136 GLuint target = texture.getTextureTarget(); 137 glBindTexture(target, texture.getTextureName()); 138 GLenum filter = GL_NEAREST; 139 if (texture.getFiltering()) { 140 filter = GL_LINEAR; 141 } 142 glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 143 glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 144 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter); 145 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter); 146 147 mState.setTexture(texture); 148} 149 150void GLES20RenderEngine::setupLayerBlackedOut() { 151 glBindTexture(GL_TEXTURE_2D, mProtectedTexName); 152 Texture texture(Texture::TEXTURE_2D, mProtectedTexName); 153 texture.setDimensions(1, 1); // FIXME: we should get that from somewhere 154 mState.setTexture(texture); 155} 156 157void GLES20RenderEngine::disableTexturing() { 158 mState.disableTexture(); 159} 160 161void GLES20RenderEngine::disableBlending() { 162 glDisable(GL_BLEND); 163} 164 165 166void GLES20RenderEngine::bindImageAsFramebuffer(EGLImageKHR image, 167 uint32_t* texName, uint32_t* fbName, uint32_t* status) { 168 GLuint tname, name; 169 // turn our EGLImage into a texture 170 glGenTextures(1, &tname); 171 glBindTexture(GL_TEXTURE_2D, tname); 172 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image); 173 174 // create a Framebuffer Object to render into 175 glGenFramebuffers(1, &name); 176 glBindFramebuffer(GL_FRAMEBUFFER, name); 177 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tname, 0); 178 179 *status = glCheckFramebufferStatus(GL_FRAMEBUFFER); 180 *texName = tname; 181 *fbName = name; 182} 183 184void GLES20RenderEngine::unbindFramebuffer(uint32_t texName, uint32_t fbName) { 185 glBindFramebuffer(GL_FRAMEBUFFER, 0); 186 glDeleteFramebuffers(1, &fbName); 187 glDeleteTextures(1, &texName); 188} 189 190void GLES20RenderEngine::setupFillWithColor(float r, float g, float b, float a) { 191 mState.setPlaneAlpha(1.0f); 192 mState.setPremultipliedAlpha(true); 193 mState.setOpaque(false); 194 mState.setColor(r, g, b, a); 195 mState.disableTexture(); 196 glDisable(GL_BLEND); 197} 198 199void GLES20RenderEngine::drawMesh(const Mesh& mesh) { 200 201 ProgramCache::getInstance().useProgram(mState); 202 203 if (mesh.getTexCoordsSize()) { 204 glEnableVertexAttribArray(Program::texCoords); 205 glVertexAttribPointer(Program::texCoords, 206 mesh.getTexCoordsSize(), 207 GL_FLOAT, GL_FALSE, 208 mesh.getByteStride(), 209 mesh.getTexCoords()); 210 } 211 212 glVertexAttribPointer(Program::position, 213 mesh.getVertexSize(), 214 GL_FLOAT, GL_FALSE, 215 mesh.getByteStride(), 216 mesh.getPositions()); 217 218 glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount()); 219 220 if (mesh.getTexCoordsSize()) { 221 glDisableVertexAttribArray(Program::texCoords); 222 } 223} 224 225void GLES20RenderEngine::beginGroup(const mat4& colorTransform) { 226 227 GLuint tname, name; 228 // create the texture 229 glGenTextures(1, &tname); 230 glBindTexture(GL_TEXTURE_2D, tname); 231 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 232 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 233 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 234 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 235 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mVpWidth, mVpHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); 236 237 // create a Framebuffer Object to render into 238 glGenFramebuffers(1, &name); 239 glBindFramebuffer(GL_FRAMEBUFFER, name); 240 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tname, 0); 241 242 Group group; 243 group.texture = tname; 244 group.fbo = name; 245 group.width = mVpWidth; 246 group.height = mVpHeight; 247 group.colorTransform = colorTransform; 248 249 mGroupStack.push(group); 250} 251 252void GLES20RenderEngine::endGroup() { 253 254 const Group group(mGroupStack.top()); 255 mGroupStack.pop(); 256 257 // activate the previous render target 258 GLuint fbo = 0; 259 if (!mGroupStack.isEmpty()) { 260 fbo = mGroupStack.top().fbo; 261 } 262 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 263 264 // set our state 265 Texture texture(Texture::TEXTURE_2D, group.texture); 266 texture.setDimensions(group.width, group.height); 267 glBindTexture(GL_TEXTURE_2D, group.texture); 268 269 mState.setPlaneAlpha(1.0f); 270 mState.setPremultipliedAlpha(true); 271 mState.setOpaque(false); 272 mState.setTexture(texture); 273 mState.setColorMatrix(group.colorTransform); 274 glDisable(GL_BLEND); 275 276 Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2, 2); 277 Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>()); 278 Mesh::VertexArray<vec2> texCoord(mesh.getTexCoordArray<vec2>()); 279 position[0] = vec2(0, 0); 280 position[1] = vec2(group.width, 0); 281 position[2] = vec2(group.width, group.height); 282 position[3] = vec2(0, group.height); 283 texCoord[0] = vec2(0, 0); 284 texCoord[1] = vec2(1, 0); 285 texCoord[2] = vec2(1, 1); 286 texCoord[3] = vec2(0, 1); 287 drawMesh(mesh); 288 289 // reset color matrix 290 mState.setColorMatrix(mat4()); 291 292 // free our fbo and texture 293 glDeleteFramebuffers(1, &group.fbo); 294 glDeleteTextures(1, &group.texture); 295} 296 297void GLES20RenderEngine::dump(String8& result) { 298 RenderEngine::dump(result); 299} 300 301// --------------------------------------------------------------------------- 302}; // namespace android 303// --------------------------------------------------------------------------- 304 305#if defined(__gl_h_) 306#error "don't include gl/gl.h in this file" 307#endif 308