#define LOG_TAG "OpenGLRenderer"
-#include <utils/Log.h>
-#include <utils/String8.h>
-
#include "Caches.h"
-#include "DisplayListRenderer.h"
-#include "Properties.h"
+
+#include "GammaFontRenderer.h"
#include "LayerRenderer.h"
+#include "Properties.h"
+#include "renderstate/RenderState.h"
#include "ShadowTessellator.h"
-#include "RenderState.h"
+#include "utils/GLUtils.h"
-namespace android {
-
-#ifdef USE_OPENGL_RENDERER
-using namespace uirenderer;
-ANDROID_SINGLETON_STATIC_INSTANCE(Caches);
-#endif
+#include <utils/Log.h>
+#include <utils/String8.h>
+namespace android {
namespace uirenderer {
+Caches* Caches::sInstance = nullptr;
+
///////////////////////////////////////////////////////////////////////////////
// Macros
///////////////////////////////////////////////////////////////////////////////
// Constructors/destructor
///////////////////////////////////////////////////////////////////////////////
-Caches::Caches(): Singleton<Caches>(),
- mExtensions(Extensions::getInstance()), mInitialized(false), mRenderState(NULL) {
+Caches::Caches(RenderState& renderState)
+ : gradientCache(mExtensions)
+ , patchCache(renderState)
+ , programCache(mExtensions)
+ , dither(*this)
+ , mRenderState(&renderState)
+ , mInitialized(false) {
+ INIT_LOGD("Creating OpenGL renderer caches");
init();
initFont();
initConstraints();
- initProperties();
initStaticProperties();
initExtensions();
- initTempProperties();
-
- mDebugLevel = readDebugLevel();
- ALOGD("Enabling debug mode %d", mDebugLevel);
}
bool Caches::init() {
ATRACE_NAME("Caches::init");
- glGenBuffers(1, &meshBuffer);
- glBindBuffer(GL_ARRAY_BUFFER, meshBuffer);
- glBufferData(GL_ARRAY_BUFFER, sizeof(gMeshVertices), gMeshVertices, GL_STATIC_DRAW);
-
- mCurrentBuffer = meshBuffer;
- mCurrentIndicesBuffer = 0;
- mCurrentPositionPointer = this;
- mCurrentPositionStride = 0;
- mCurrentTexCoordsPointer = this;
- mCurrentPixelBuffer = 0;
-
- mTexCoordsArrayEnabled = false;
-
- glDisable(GL_SCISSOR_TEST);
- scissorEnabled = false;
- mScissorX = mScissorY = mScissorWidth = mScissorHeight = 0;
-
- glActiveTexture(gTextureUnits[0]);
- mTextureUnit = 0;
-
- mRegionMesh = NULL;
- mMeshIndices = 0;
- mShadowStripsIndices = 0;
- blend = false;
- lastSrcMode = GL_ZERO;
- lastDstMode = GL_ZERO;
- currentProgram = NULL;
+ mRegionMesh = nullptr;
+ mProgram = nullptr;
mFunctorsCount = 0;
- debugLayersUpdates = false;
- debugOverdraw = false;
- debugStencilClip = kStencilHide;
-
- patchCache.init(*this);
+ patchCache.init();
mInitialized = true;
- resetBoundTextures();
+ mPixelBufferState = new PixelBufferState();
+ mTextureState = new TextureState();
return true;
}
startMark = startMarkNull;
endMark = endMarkNull;
}
-
- if (mExtensions.hasDebugLabel() && (drawDeferDisabled || drawReorderDisabled)) {
- setLabel = glLabelObjectEXT;
- getLabel = glGetObjectLabelEXT;
- } else {
- setLabel = setLabelNull;
- getLabel = getLabelNull;
- }
}
void Caches::initConstraints() {
- GLint maxTextureUnits;
- glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
- if (maxTextureUnits < REQUIRED_TEXTURE_UNITS_COUNT) {
- ALOGW("At least %d texture units are required!", REQUIRED_TEXTURE_UNITS_COUNT);
- }
-
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
}
}
}
-bool Caches::initProperties() {
- bool prevDebugLayersUpdates = debugLayersUpdates;
- bool prevDebugOverdraw = debugOverdraw;
- StencilClipDebug prevDebugStencilClip = debugStencilClip;
-
- char property[PROPERTY_VALUE_MAX];
- if (property_get(PROPERTY_DEBUG_LAYERS_UPDATES, property, NULL) > 0) {
- INIT_LOGD(" Layers updates debug enabled: %s", property);
- debugLayersUpdates = !strcmp(property, "true");
- } else {
- debugLayersUpdates = false;
- }
-
- debugOverdraw = false;
- if (property_get(PROPERTY_DEBUG_OVERDRAW, property, NULL) > 0) {
- INIT_LOGD(" Overdraw debug enabled: %s", property);
- if (!strcmp(property, "show")) {
- debugOverdraw = true;
- mOverdrawDebugColorSet = kColorSet_Default;
- } else if (!strcmp(property, "show_deuteranomaly")) {
- debugOverdraw = true;
- mOverdrawDebugColorSet = kColorSet_Deuteranomaly;
- }
- }
-
- // See Properties.h for valid values
- if (property_get(PROPERTY_DEBUG_STENCIL_CLIP, property, NULL) > 0) {
- INIT_LOGD(" Stencil clip debug enabled: %s", property);
- if (!strcmp(property, "hide")) {
- debugStencilClip = kStencilHide;
- } else if (!strcmp(property, "highlight")) {
- debugStencilClip = kStencilShowHighlight;
- } else if (!strcmp(property, "region")) {
- debugStencilClip = kStencilShowRegion;
- }
- } else {
- debugStencilClip = kStencilHide;
- }
-
- if (property_get(PROPERTY_DISABLE_DRAW_DEFER, property, "false")) {
- drawDeferDisabled = !strcasecmp(property, "true");
- INIT_LOGD(" Draw defer %s", drawDeferDisabled ? "disabled" : "enabled");
- } else {
- drawDeferDisabled = false;
- INIT_LOGD(" Draw defer enabled");
- }
-
- if (property_get(PROPERTY_DISABLE_DRAW_REORDER, property, "false")) {
- drawReorderDisabled = !strcasecmp(property, "true");
- INIT_LOGD(" Draw reorder %s", drawReorderDisabled ? "disabled" : "enabled");
- } else {
- drawReorderDisabled = false;
- INIT_LOGD(" Draw reorder enabled");
- }
-
- return (prevDebugLayersUpdates != debugLayersUpdates) ||
- (prevDebugOverdraw != debugOverdraw) ||
- (prevDebugStencilClip != debugStencilClip);
-}
-
void Caches::terminate() {
if (!mInitialized) return;
-
- glDeleteBuffers(1, &meshBuffer);
- mCurrentBuffer = 0;
-
- glDeleteBuffers(1, &mMeshIndices);
- delete[] mRegionMesh;
- mMeshIndices = 0;
- mRegionMesh = NULL;
-
- glDeleteBuffers(1, &mShadowStripsIndices);
- mShadowStripsIndices = 0;
+ mRegionMesh.reset(nullptr);
fboCache.clear();
programCache.clear();
- currentProgram = NULL;
+ mProgram = nullptr;
patchCache.clear();
clearGarbage();
+ delete mPixelBufferState;
+ mPixelBufferState = nullptr;
+ delete mTextureState;
+ mTextureState = nullptr;
mInitialized = false;
}
+void Caches::setProgram(const ProgramDescription& description) {
+ setProgram(programCache.get(description));
+}
+
+void Caches::setProgram(Program* program) {
+ if (!program || !program->isInUse()) {
+ if (mProgram) {
+ mProgram->remove();
+ }
+ if (program) {
+ program->use();
+ }
+ mProgram = program;
+ }
+}
+
///////////////////////////////////////////////////////////////////////////////
// Debug
///////////////////////////////////////////////////////////////////////////////
};
if (amount < 1) amount = 1;
if (amount > 4) amount = 4;
- return sOverdrawColors[mOverdrawDebugColorSet][amount - 1];
+
+ int overdrawColorIndex = static_cast<int>(Properties::overdrawColorSet);
+ return sOverdrawColors[overdrawColorIndex][amount - 1];
}
void Caches::dumpMemoryUsage() {
const Layer* layer = *it;
log.appendFormat(" Layer size %dx%d; isTextureLayer()=%d; texid=%u fbo=%u; refs=%d\n",
layer->getWidth(), layer->getHeight(),
- layer->isTextureLayer(), layer->getTexture(),
+ layer->isTextureLayer(), layer->getTextureId(),
layer->getFbo(), layer->getStrongCount());
memused += layer->getWidth() * layer->getHeight() * 4;
}
void Caches::flush(FlushMode mode) {
FLUSH_LOGD("Flushing caches (mode %d)", mode);
- // We must stop tasks before clearing caches
- if (mode > kFlushMode_Layers) {
- tasks.stop();
- }
-
switch (mode) {
case kFlushMode_Full:
textureCache.clear();
clearGarbage();
glFinish();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// VBO
-///////////////////////////////////////////////////////////////////////////////
-
-bool Caches::bindMeshBuffer() {
- return bindMeshBuffer(meshBuffer);
-}
-
-bool Caches::bindMeshBuffer(const GLuint buffer) {
- if (mCurrentBuffer != buffer) {
- glBindBuffer(GL_ARRAY_BUFFER, buffer);
- mCurrentBuffer = buffer;
- return true;
- }
- return false;
-}
-
-bool Caches::unbindMeshBuffer() {
- if (mCurrentBuffer) {
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- mCurrentBuffer = 0;
- return true;
- }
- return false;
-}
-
-bool Caches::bindIndicesBufferInternal(const GLuint buffer) {
- if (mCurrentIndicesBuffer != buffer) {
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
- mCurrentIndicesBuffer = buffer;
- return true;
- }
- return false;
-}
-
-bool Caches::bindQuadIndicesBuffer() {
- if (!mMeshIndices) {
- uint16_t* regionIndices = new uint16_t[gMaxNumberOfQuads * 6];
- for (uint32_t i = 0; i < gMaxNumberOfQuads; i++) {
- uint16_t quad = i * 4;
- int index = i * 6;
- regionIndices[index ] = quad; // top-left
- regionIndices[index + 1] = quad + 1; // top-right
- regionIndices[index + 2] = quad + 2; // bottom-left
- regionIndices[index + 3] = quad + 2; // bottom-left
- regionIndices[index + 4] = quad + 1; // top-right
- regionIndices[index + 5] = quad + 3; // bottom-right
- }
-
- glGenBuffers(1, &mMeshIndices);
- bool force = bindIndicesBufferInternal(mMeshIndices);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, gMaxNumberOfQuads * 6 * sizeof(uint16_t),
- regionIndices, GL_STATIC_DRAW);
-
- delete[] regionIndices;
- return force;
- }
-
- return bindIndicesBufferInternal(mMeshIndices);
-}
-
-bool Caches::bindShadowIndicesBuffer() {
- if (!mShadowStripsIndices) {
- uint16_t* shadowIndices = new uint16_t[MAX_SHADOW_INDEX_COUNT];
- ShadowTessellator::generateShadowIndices(shadowIndices);
- glGenBuffers(1, &mShadowStripsIndices);
- bool force = bindIndicesBufferInternal(mShadowStripsIndices);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_SHADOW_INDEX_COUNT * sizeof(uint16_t),
- shadowIndices, GL_STATIC_DRAW);
-
- delete[] shadowIndices;
- return force;
- }
-
- return bindIndicesBufferInternal(mShadowStripsIndices);
-}
-
-bool Caches::unbindIndicesBuffer() {
- if (mCurrentIndicesBuffer) {
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- mCurrentIndicesBuffer = 0;
- return true;
- }
- return false;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// PBO
-///////////////////////////////////////////////////////////////////////////////
-
-bool Caches::bindPixelBuffer(const GLuint buffer) {
- if (mCurrentPixelBuffer != buffer) {
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
- mCurrentPixelBuffer = buffer;
- return true;
- }
- return false;
-}
-
-bool Caches::unbindPixelBuffer() {
- if (mCurrentPixelBuffer) {
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
- mCurrentPixelBuffer = 0;
- return true;
- }
- return false;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Meshes and textures
-///////////////////////////////////////////////////////////////////////////////
-
-void Caches::bindPositionVertexPointer(bool force, const GLvoid* vertices, GLsizei stride) {
- if (force || vertices != mCurrentPositionPointer || stride != mCurrentPositionStride) {
- GLuint slot = currentProgram->position;
- glVertexAttribPointer(slot, 2, GL_FLOAT, GL_FALSE, stride, vertices);
- mCurrentPositionPointer = vertices;
- mCurrentPositionStride = stride;
- }
-}
-
-void Caches::bindTexCoordsVertexPointer(bool force, const GLvoid* vertices, GLsizei stride) {
- if (force || vertices != mCurrentTexCoordsPointer || stride != mCurrentTexCoordsStride) {
- GLuint slot = currentProgram->texCoords;
- glVertexAttribPointer(slot, 2, GL_FLOAT, GL_FALSE, stride, vertices);
- mCurrentTexCoordsPointer = vertices;
- mCurrentTexCoordsStride = stride;
- }
-}
-
-void Caches::resetVertexPointers() {
- mCurrentPositionPointer = this;
- mCurrentTexCoordsPointer = this;
-}
-
-void Caches::resetTexCoordsVertexPointer() {
- mCurrentTexCoordsPointer = this;
-}
-
-void Caches::enableTexCoordsVertexArray() {
- if (!mTexCoordsArrayEnabled) {
- glEnableVertexAttribArray(Program::kBindingTexCoords);
- mCurrentTexCoordsPointer = this;
- mTexCoordsArrayEnabled = true;
- }
-}
-
-void Caches::disableTexCoordsVertexArray() {
- if (mTexCoordsArrayEnabled) {
- glDisableVertexAttribArray(Program::kBindingTexCoords);
- mTexCoordsArrayEnabled = false;
- }
-}
-
-void Caches::activeTexture(GLuint textureUnit) {
- if (mTextureUnit != textureUnit) {
- glActiveTexture(gTextureUnits[textureUnit]);
- mTextureUnit = textureUnit;
- }
-}
-
-void Caches::resetActiveTexture() {
- mTextureUnit = -1;
-}
-
-void Caches::bindTexture(GLuint texture) {
- if (mBoundTextures[mTextureUnit] != texture) {
- glBindTexture(GL_TEXTURE_2D, texture);
- mBoundTextures[mTextureUnit] = texture;
- }
-}
-
-void Caches::bindTexture(GLenum target, GLuint texture) {
- if (target == GL_TEXTURE_2D) {
- bindTexture(texture);
- } else {
- // GLConsumer directly calls glBindTexture() with
- // target=GL_TEXTURE_EXTERNAL_OES, don't cache this target
- // since the cached state could be stale
- glBindTexture(target, texture);
- }
-}
-
-void Caches::deleteTexture(GLuint texture) {
- // When glDeleteTextures() is called on a currently bound texture,
- // OpenGL ES specifies that the texture is then considered unbound
- // Consider the following series of calls:
- //
- // glGenTextures -> creates texture name 2
- // glBindTexture(2)
- // glDeleteTextures(2) -> 2 is now unbound
- // glGenTextures -> can return 2 again
- //
- // If we don't call glBindTexture(2) after the second glGenTextures
- // call, any texture operation will be performed on the default
- // texture (name=0)
-
- unbindTexture(texture);
-
- glDeleteTextures(1, &texture);
-}
-
-void Caches::resetBoundTextures() {
- memset(mBoundTextures, 0, REQUIRED_TEXTURE_UNITS_COUNT * sizeof(GLuint));
-}
-
-void Caches::unbindTexture(GLuint texture) {
- for (int i = 0; i < REQUIRED_TEXTURE_UNITS_COUNT; i++) {
- if (mBoundTextures[i] == texture) {
- mBoundTextures[i] = 0;
- }
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Scissor
-///////////////////////////////////////////////////////////////////////////////
-
-bool Caches::setScissor(GLint x, GLint y, GLint width, GLint height) {
- if (scissorEnabled && (x != mScissorX || y != mScissorY ||
- width != mScissorWidth || height != mScissorHeight)) {
-
- if (x < 0) {
- width += x;
- x = 0;
- }
- if (y < 0) {
- height += y;
- y = 0;
- }
- if (width < 0) {
- width = 0;
- }
- if (height < 0) {
- height = 0;
- }
- glScissor(x, y, width, height);
-
- mScissorX = x;
- mScissorY = y;
- mScissorWidth = width;
- mScissorHeight = height;
-
- return true;
- }
- return false;
-}
-
-bool Caches::enableScissor() {
- if (!scissorEnabled) {
- glEnable(GL_SCISSOR_TEST);
- scissorEnabled = true;
- resetScissor();
- return true;
- }
- return false;
-}
-
-bool Caches::disableScissor() {
- if (scissorEnabled) {
- glDisable(GL_SCISSOR_TEST);
- scissorEnabled = false;
- return true;
- }
- return false;
-}
-
-void Caches::setScissorEnabled(bool enabled) {
- if (scissorEnabled != enabled) {
- if (enabled) glEnable(GL_SCISSOR_TEST);
- else glDisable(GL_SCISSOR_TEST);
- scissorEnabled = enabled;
- }
-}
-
-void Caches::resetScissor() {
- mScissorX = mScissorY = mScissorWidth = mScissorHeight = 0;
+ // Errors during cleanup should be considered non-fatal, dump them and
+ // and move on. TODO: All errors or just errors like bad surface?
+ GLUtils::dumpGLErrors();
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void Caches::startTiling(GLuint x, GLuint y, GLuint width, GLuint height, bool discard) {
- if (mExtensions.hasTiledRendering() && !debugOverdraw) {
+ if (mExtensions.hasTiledRendering() && !Properties::debugOverdraw) {
glStartTilingQCOM(x, y, width, height, (discard ? GL_NONE : GL_COLOR_BUFFER_BIT0_QCOM));
}
}
void Caches::endTiling() {
- if (mExtensions.hasTiledRendering() && !debugOverdraw) {
+ if (mExtensions.hasTiledRendering() && !Properties::debugOverdraw) {
glEndTilingQCOM(GL_COLOR_BUFFER_BIT0_QCOM);
}
}
TextureVertex* Caches::getRegionMesh() {
// Create the mesh, 2 triangles and 4 vertices per rectangle in the region
if (!mRegionMesh) {
- mRegionMesh = new TextureVertex[gMaxNumberOfQuads * 4];
+ mRegionMesh.reset(new TextureVertex[kMaxNumberOfQuads * 4]);
}
- return mRegionMesh;
+ return mRegionMesh.get();
}
///////////////////////////////////////////////////////////////////////////////
// Temporary Properties
///////////////////////////////////////////////////////////////////////////////
-void Caches::initTempProperties() {
- propertyLightDiameter = -1.0f;
- propertyLightPosY = -1.0f;
- propertyLightPosZ = -1.0f;
- propertyAmbientRatio = -1.0f;
- propertyAmbientShadowStrength = -1;
- propertySpotShadowStrength = -1;
-}
-
-void Caches::setTempProperty(const char* name, const char* value) {
- ALOGD("setting property %s to %s", name, value);
- if (!strcmp(name, "ambientRatio")) {
- propertyAmbientRatio = fmin(fmax(atof(value), 0.0), 10.0);
- ALOGD("ambientRatio = %.2f", propertyAmbientRatio);
- return;
- } else if (!strcmp(name, "lightDiameter")) {
- propertyLightDiameter = fmin(fmax(atof(value), 0.0), 3000.0);
- ALOGD("lightDiameter = %.2f", propertyLightDiameter);
- return;
- } else if (!strcmp(name, "lightPosY")) {
- propertyLightPosY = fmin(fmax(atof(value), 0.0), 3000.0);
- ALOGD("lightPos Y = %.2f", propertyLightPosY);
- return;
- } else if (!strcmp(name, "lightPosZ")) {
- propertyLightPosZ = fmin(fmax(atof(value), 0.0), 3000.0);
- ALOGD("lightPos Z = %.2f", propertyLightPosZ);
- return;
- } else if (!strcmp(name, "ambientShadowStrength")) {
- propertyAmbientShadowStrength = atoi(value);
- ALOGD("ambient shadow strength = 0x%x out of 0xff", propertyAmbientShadowStrength);
- return;
- } else if (!strcmp(name, "spotShadowStrength")) {
- propertySpotShadowStrength = atoi(value);
- ALOGD("spot shadow strength = 0x%x out of 0xff", propertySpotShadowStrength);
- return;
- }
- ALOGD(" failed");
-}
-
}; // namespace uirenderer
}; // namespace android