blob: e98296e97ee007ae0fdb7755607218e726e6ee3a [file] [log] [blame]
/*
* Copyright (C) 2013 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.
*/
#include "Renderer.h"
#include <graphics/GLUtils.h>
#define LOG_TAG "PTS_OPENGL"
#define LOG_NDEBUG 0
#include <utils/Log.h>
#include <Trace.h>
static const EGLint contextAttribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE };
static const EGLint configAttribs[] = {
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 16,
EGL_STENCIL_SIZE, 8,
EGL_NONE };
Renderer::Renderer(ANativeWindow* window, bool offscreen, int workload) :
mWindow(window), mEglDisplay(EGL_NO_DISPLAY), mEglSurface(EGL_NO_SURFACE),
mEglContext(EGL_NO_CONTEXT), mOffscreen(offscreen), mWorkload(workload) {
}
bool Renderer::setUp() {
SCOPED_TRACE();
mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (EGL_NO_DISPLAY == mEglDisplay || EGL_SUCCESS != eglGetError()) {
return false;
}
EGLint major;
EGLint minor;
if (!eglInitialize(mEglDisplay, &major, &minor) || EGL_SUCCESS != eglGetError()) {
return false;
}
EGLint numConfigs = 0;
if (!eglChooseConfig(mEglDisplay, configAttribs, &mGlConfig, 1, &numConfigs)
|| EGL_SUCCESS != eglGetError()) {
return false;
}
mEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig, mWindow, NULL);
if (EGL_NO_SURFACE == mEglSurface || EGL_SUCCESS != eglGetError()) {
return false;
}
mEglContext = eglCreateContext(mEglDisplay, mGlConfig, EGL_NO_CONTEXT, contextAttribs);
if (EGL_NO_CONTEXT == mEglContext || EGL_SUCCESS != eglGetError()) {
return false;
}
if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)
|| EGL_SUCCESS != eglGetError()) {
return false;
}
if (!eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &mWidth)
|| EGL_SUCCESS != eglGetError()) {
return false;
}
if (!eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &mHeight)
|| EGL_SUCCESS != eglGetError()) {
return false;
}
if (mOffscreen) {
mFboWidth = GLUtils::roundUpToSmallestPowerOf2(mWidth);
mFboHeight = GLUtils::roundUpToSmallestPowerOf2(mHeight);
if (!GLUtils::createFBO(mFboId, mRboId, mCboId, mFboWidth, mFboHeight)) {
return false;
}
mBuffer = new GLushort[mFboWidth * mFboHeight];
glViewport(0, 0, mFboWidth, mFboHeight);
} else {
mFboWidth = 0;
mFboHeight = 0;
mBuffer = NULL;
mFboId = 0;
mRboId = 0;
mCboId = 0;
glViewport(0, 0, mWidth, mHeight);
}
GLuint err = glGetError();
if (err != GL_NO_ERROR) {
ALOGE("GLError %d in setUp", err);
return false;
}
return true;
}
bool Renderer::tearDown() {
SCOPED_TRACE();
if (mBuffer != NULL) {
delete[] mBuffer;
mBuffer = NULL;
}
if (mFboId != 0) {
glDeleteFramebuffers(1, &mFboId);
mFboId = 0;
}
if (mRboId != 0) {
glDeleteRenderbuffers(1, &mRboId);
mRboId = 0;
}
if (mCboId != 0) {
glDeleteRenderbuffers(1, &mCboId);
mCboId = 0;
}
if (mEglContext != EGL_NO_CONTEXT) {
eglDestroyContext(mEglDisplay, mEglContext);
mEglContext = EGL_NO_CONTEXT;
}
if (mEglSurface != EGL_NO_SURFACE) {
eglDestroySurface(mEglDisplay, mEglSurface);
mEglSurface = EGL_NO_SURFACE;
}
if (mEglDisplay != EGL_NO_DISPLAY) {
eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglTerminate(mEglDisplay);
mEglDisplay = EGL_NO_DISPLAY;
}
GLuint err = glGetError();
if (err != GL_NO_ERROR) {
ALOGE("GLError %d in tearDown", err);
return false;
}
return EGL_SUCCESS == eglGetError();
}
bool Renderer::draw() {
SCOPED_TRACE();
GLuint err = glGetError();
if (err != GL_NO_ERROR) {
ALOGE("GLError %d in draw", err);
return false;
}
if (mOffscreen) {
// Read the pixels back from the frame buffer.
glReadPixels(0, 0, mFboWidth, mFboHeight, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, mBuffer);
return true;
} else {
return eglSwapBuffers(mEglDisplay, mEglSurface);
}
}