2010-10-22 18:59:26 -07:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2010 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define LOG_TAG "OpenGLRenderer"
|
|
|
|
|
2010-11-10 11:59:15 -08:00
|
|
|
#include <utils/Log.h>
|
2011-03-24 10:51:31 -07:00
|
|
|
#include <utils/String8.h>
|
2010-11-10 11:59:15 -08:00
|
|
|
|
2010-10-22 18:59:26 -07:00
|
|
|
#include "Caches.h"
|
2012-03-05 13:44:35 -08:00
|
|
|
#include "DisplayListRenderer.h"
|
2010-11-10 19:01:29 -08:00
|
|
|
#include "Properties.h"
|
2011-02-02 20:28:09 -08:00
|
|
|
#include "LayerRenderer.h"
|
2010-10-22 18:59:26 -07:00
|
|
|
|
|
|
|
namespace android {
|
|
|
|
|
|
|
|
#ifdef USE_OPENGL_RENDERER
|
|
|
|
using namespace uirenderer;
|
|
|
|
ANDROID_SINGLETON_STATIC_INSTANCE(Caches);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
namespace uirenderer {
|
|
|
|
|
2011-07-18 15:00:43 -07:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Macros
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#if DEBUG_CACHE_FLUSH
|
2011-12-20 16:23:08 +00:00
|
|
|
#define FLUSH_LOGD(...) ALOGD(__VA_ARGS__)
|
2011-07-18 15:00:43 -07:00
|
|
|
#else
|
|
|
|
#define FLUSH_LOGD(...)
|
|
|
|
#endif
|
|
|
|
|
2010-10-22 18:59:26 -07:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Constructors/destructor
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2011-11-09 20:10:18 -08:00
|
|
|
Caches::Caches(): Singleton<Caches>(), mInitialized(false) {
|
|
|
|
init();
|
2012-07-13 18:25:35 -07:00
|
|
|
initFont();
|
2012-05-12 16:18:58 -07:00
|
|
|
initExtensions();
|
|
|
|
initConstraints();
|
2012-08-06 14:51:10 -07:00
|
|
|
initProperties();
|
2010-11-10 19:01:29 -08:00
|
|
|
|
|
|
|
mDebugLevel = readDebugLevel();
|
2011-12-20 16:23:08 +00:00
|
|
|
ALOGD("Enabling debug mode %d", mDebugLevel);
|
2010-10-22 18:59:26 -07:00
|
|
|
}
|
|
|
|
|
2011-11-09 20:10:18 -08:00
|
|
|
void Caches::init() {
|
|
|
|
if (mInitialized) return;
|
|
|
|
|
|
|
|
glGenBuffers(1, &meshBuffer);
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, meshBuffer);
|
|
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(gMeshVertices), gMeshVertices, GL_STATIC_DRAW);
|
|
|
|
|
|
|
|
mCurrentBuffer = meshBuffer;
|
2011-12-13 13:11:32 -08:00
|
|
|
mCurrentIndicesBuffer = 0;
|
2011-12-12 20:35:21 -08:00
|
|
|
mCurrentPositionPointer = this;
|
2012-09-25 12:00:29 -07:00
|
|
|
mCurrentPositionStride = 0;
|
2011-12-12 20:35:21 -08:00
|
|
|
mCurrentTexCoordsPointer = this;
|
|
|
|
|
2011-12-13 13:11:32 -08:00
|
|
|
mTexCoordsArrayEnabled = false;
|
|
|
|
|
2012-07-13 18:25:35 -07:00
|
|
|
glDisable(GL_SCISSOR_TEST);
|
2012-07-13 15:28:31 -07:00
|
|
|
scissorEnabled = false;
|
2011-12-14 19:23:32 -08:00
|
|
|
mScissorX = mScissorY = mScissorWidth = mScissorHeight = 0;
|
|
|
|
|
2011-12-13 14:55:06 -08:00
|
|
|
glActiveTexture(gTextureUnits[0]);
|
|
|
|
mTextureUnit = 0;
|
|
|
|
|
2011-11-09 20:10:18 -08:00
|
|
|
mRegionMesh = NULL;
|
|
|
|
|
|
|
|
blend = false;
|
|
|
|
lastSrcMode = GL_ZERO;
|
|
|
|
lastDstMode = GL_ZERO;
|
|
|
|
currentProgram = NULL;
|
|
|
|
|
2012-09-27 17:55:46 -07:00
|
|
|
mFunctorsCount = 0;
|
|
|
|
|
2011-11-09 20:10:18 -08:00
|
|
|
mInitialized = true;
|
|
|
|
}
|
|
|
|
|
2012-07-13 18:25:35 -07:00
|
|
|
void Caches::initFont() {
|
|
|
|
fontRenderer = GammaFontRenderer::createRenderer();
|
|
|
|
}
|
|
|
|
|
2012-05-12 16:18:58 -07:00
|
|
|
void Caches::initExtensions() {
|
|
|
|
if (extensions.hasDebugMarker()) {
|
|
|
|
eventMark = glInsertEventMarkerEXT;
|
|
|
|
startMark = glPushGroupMarkerEXT;
|
|
|
|
endMark = glPopGroupMarkerEXT;
|
|
|
|
} else {
|
|
|
|
eventMark = eventMarkNull;
|
|
|
|
startMark = startMarkNull;
|
|
|
|
endMark = endMarkNull;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (extensions.hasDebugLabel()) {
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2012-08-06 14:51:10 -07:00
|
|
|
void Caches::initProperties() {
|
|
|
|
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;
|
|
|
|
}
|
2012-09-21 19:15:00 -07:00
|
|
|
|
|
|
|
if (property_get(PROPERTY_DEBUG_OVERDRAW, property, NULL) > 0) {
|
|
|
|
INIT_LOGD(" Overdraw debug enabled: %s", property);
|
|
|
|
debugOverdraw = !strcmp(property, "true");
|
|
|
|
} else {
|
|
|
|
debugOverdraw = false;
|
|
|
|
}
|
2012-08-06 14:51:10 -07:00
|
|
|
}
|
|
|
|
|
2011-11-09 20:10:18 -08:00
|
|
|
void Caches::terminate() {
|
|
|
|
if (!mInitialized) return;
|
|
|
|
|
|
|
|
glDeleteBuffers(1, &meshBuffer);
|
|
|
|
mCurrentBuffer = 0;
|
|
|
|
|
|
|
|
glDeleteBuffers(1, &mRegionMeshIndices);
|
2010-10-27 18:57:51 -07:00
|
|
|
delete[] mRegionMesh;
|
2011-11-09 20:10:18 -08:00
|
|
|
mRegionMesh = NULL;
|
|
|
|
|
|
|
|
fboCache.clear();
|
|
|
|
|
|
|
|
programCache.clear();
|
|
|
|
currentProgram = NULL;
|
|
|
|
|
|
|
|
mInitialized = false;
|
2010-10-27 18:57:51 -07:00
|
|
|
}
|
|
|
|
|
2010-11-10 11:59:15 -08:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Debug
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
void Caches::dumpMemoryUsage() {
|
2011-03-24 10:51:31 -07:00
|
|
|
String8 stringLog;
|
|
|
|
dumpMemoryUsage(stringLog);
|
2011-12-20 16:23:08 +00:00
|
|
|
ALOGD("%s", stringLog.string());
|
2011-03-24 10:51:31 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void Caches::dumpMemoryUsage(String8 &log) {
|
|
|
|
log.appendFormat("Current memory usage / total memory usage (bytes):\n");
|
|
|
|
log.appendFormat(" TextureCache %8d / %8d\n",
|
|
|
|
textureCache.getSize(), textureCache.getMaxSize());
|
|
|
|
log.appendFormat(" LayerCache %8d / %8d\n",
|
|
|
|
layerCache.getSize(), layerCache.getMaxSize());
|
|
|
|
log.appendFormat(" GradientCache %8d / %8d\n",
|
|
|
|
gradientCache.getSize(), gradientCache.getMaxSize());
|
|
|
|
log.appendFormat(" PathCache %8d / %8d\n",
|
|
|
|
pathCache.getSize(), pathCache.getMaxSize());
|
|
|
|
log.appendFormat(" CircleShapeCache %8d / %8d\n",
|
2011-01-19 21:54:02 -08:00
|
|
|
circleShapeCache.getSize(), circleShapeCache.getMaxSize());
|
2011-03-24 10:51:31 -07:00
|
|
|
log.appendFormat(" OvalShapeCache %8d / %8d\n",
|
2011-02-03 15:06:05 -08:00
|
|
|
ovalShapeCache.getSize(), ovalShapeCache.getMaxSize());
|
2011-03-24 10:51:31 -07:00
|
|
|
log.appendFormat(" RoundRectShapeCache %8d / %8d\n",
|
2011-01-19 21:54:02 -08:00
|
|
|
roundRectShapeCache.getSize(), roundRectShapeCache.getMaxSize());
|
2011-03-24 10:51:31 -07:00
|
|
|
log.appendFormat(" RectShapeCache %8d / %8d\n",
|
2011-02-03 15:06:05 -08:00
|
|
|
rectShapeCache.getSize(), rectShapeCache.getMaxSize());
|
2011-03-24 10:51:31 -07:00
|
|
|
log.appendFormat(" ArcShapeCache %8d / %8d\n",
|
2011-02-03 15:06:05 -08:00
|
|
|
arcShapeCache.getSize(), arcShapeCache.getMaxSize());
|
2011-03-24 10:51:31 -07:00
|
|
|
log.appendFormat(" TextDropShadowCache %8d / %8d\n", dropShadowCache.getSize(),
|
2010-11-10 11:59:15 -08:00
|
|
|
dropShadowCache.getMaxSize());
|
2012-07-13 18:25:35 -07:00
|
|
|
for (uint32_t i = 0; i < fontRenderer->getFontRendererCount(); i++) {
|
|
|
|
const uint32_t size = fontRenderer->getFontRendererSize(i);
|
2011-03-24 10:51:31 -07:00
|
|
|
log.appendFormat(" FontRenderer %d %8d / %8d\n", i, size, size);
|
2010-11-10 11:59:15 -08:00
|
|
|
}
|
2011-05-27 10:21:07 -07:00
|
|
|
log.appendFormat("Other:\n");
|
2011-03-24 10:51:31 -07:00
|
|
|
log.appendFormat(" FboCache %8d / %8d\n",
|
|
|
|
fboCache.getSize(), fboCache.getMaxSize());
|
|
|
|
log.appendFormat(" PatchCache %8d / %8d\n",
|
|
|
|
patchCache.getSize(), patchCache.getMaxSize());
|
2010-11-10 11:59:15 -08:00
|
|
|
|
|
|
|
uint32_t total = 0;
|
|
|
|
total += textureCache.getSize();
|
|
|
|
total += layerCache.getSize();
|
|
|
|
total += gradientCache.getSize();
|
|
|
|
total += pathCache.getSize();
|
|
|
|
total += dropShadowCache.getSize();
|
2011-02-03 15:06:05 -08:00
|
|
|
total += roundRectShapeCache.getSize();
|
|
|
|
total += circleShapeCache.getSize();
|
|
|
|
total += ovalShapeCache.getSize();
|
|
|
|
total += rectShapeCache.getSize();
|
|
|
|
total += arcShapeCache.getSize();
|
2012-07-13 18:25:35 -07:00
|
|
|
for (uint32_t i = 0; i < fontRenderer->getFontRendererCount(); i++) {
|
|
|
|
total += fontRenderer->getFontRendererSize(i);
|
2010-11-10 11:59:15 -08:00
|
|
|
}
|
|
|
|
|
2011-03-24 10:51:31 -07:00
|
|
|
log.appendFormat("Total memory usage:\n");
|
|
|
|
log.appendFormat(" %d bytes, %.2f MB\n", total, total / 1024.0f / 1024.0f);
|
2010-11-10 11:59:15 -08:00
|
|
|
}
|
|
|
|
|
2010-11-11 15:36:56 -08:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Memory management
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
void Caches::clearGarbage() {
|
|
|
|
textureCache.clearGarbage();
|
|
|
|
pathCache.clearGarbage();
|
2011-01-12 12:53:32 -08:00
|
|
|
|
2012-09-25 22:52:40 -07:00
|
|
|
Vector<DisplayList*> displayLists;
|
|
|
|
Vector<Layer*> layers;
|
|
|
|
|
|
|
|
{ // scope for the lock
|
|
|
|
Mutex::Autolock _l(mGarbageLock);
|
|
|
|
displayLists = mDisplayListGarbage;
|
|
|
|
layers = mLayerGarbage;
|
|
|
|
mDisplayListGarbage.clear();
|
|
|
|
mLayerGarbage.clear();
|
|
|
|
}
|
2011-01-12 12:53:32 -08:00
|
|
|
|
2012-09-25 22:52:40 -07:00
|
|
|
size_t count = displayLists.size();
|
2011-01-12 12:53:32 -08:00
|
|
|
for (size_t i = 0; i < count; i++) {
|
2012-09-25 22:52:40 -07:00
|
|
|
DisplayList* displayList = displayLists.itemAt(i);
|
|
|
|
delete displayList;
|
2011-01-12 12:53:32 -08:00
|
|
|
}
|
2012-03-05 13:44:35 -08:00
|
|
|
|
2012-09-25 22:52:40 -07:00
|
|
|
count = layers.size();
|
2012-03-05 13:44:35 -08:00
|
|
|
for (size_t i = 0; i < count; i++) {
|
2012-09-25 22:52:40 -07:00
|
|
|
Layer* layer = layers.itemAt(i);
|
|
|
|
delete layer;
|
2012-03-05 13:44:35 -08:00
|
|
|
}
|
2012-09-25 22:52:40 -07:00
|
|
|
layers.clear();
|
2011-01-12 12:53:32 -08:00
|
|
|
}
|
|
|
|
|
2011-01-13 12:13:20 -08:00
|
|
|
void Caches::deleteLayerDeferred(Layer* layer) {
|
2011-01-12 12:53:32 -08:00
|
|
|
Mutex::Autolock _l(mGarbageLock);
|
2011-01-13 12:13:20 -08:00
|
|
|
mLayerGarbage.push(layer);
|
2010-11-11 15:36:56 -08:00
|
|
|
}
|
|
|
|
|
2012-03-05 13:44:35 -08:00
|
|
|
void Caches::deleteDisplayListDeferred(DisplayList* displayList) {
|
|
|
|
Mutex::Autolock _l(mGarbageLock);
|
|
|
|
mDisplayListGarbage.push(displayList);
|
|
|
|
}
|
|
|
|
|
2011-07-18 15:00:43 -07:00
|
|
|
void Caches::flush(FlushMode mode) {
|
|
|
|
FLUSH_LOGD("Flushing caches (mode %d)", mode);
|
|
|
|
|
|
|
|
switch (mode) {
|
|
|
|
case kFlushMode_Full:
|
|
|
|
textureCache.clear();
|
|
|
|
patchCache.clear();
|
|
|
|
dropShadowCache.clear();
|
|
|
|
gradientCache.clear();
|
2012-07-13 18:25:35 -07:00
|
|
|
fontRenderer->clear();
|
2012-07-31 21:16:07 -07:00
|
|
|
dither.clear();
|
2011-07-18 15:00:43 -07:00
|
|
|
// fall through
|
|
|
|
case kFlushMode_Moderate:
|
2012-07-13 18:25:35 -07:00
|
|
|
fontRenderer->flush();
|
2011-11-04 15:12:29 -07:00
|
|
|
textureCache.flush();
|
2011-07-18 15:00:43 -07:00
|
|
|
pathCache.clear();
|
|
|
|
roundRectShapeCache.clear();
|
|
|
|
circleShapeCache.clear();
|
|
|
|
ovalShapeCache.clear();
|
|
|
|
rectShapeCache.clear();
|
|
|
|
arcShapeCache.clear();
|
2011-07-27 16:28:21 -07:00
|
|
|
// fall through
|
|
|
|
case kFlushMode_Layers:
|
|
|
|
layerCache.clear();
|
2011-07-18 15:00:43 -07:00
|
|
|
break;
|
|
|
|
}
|
Fix texture corruption
When memory gets low on a device, activities flush everything they can.
Hardware-accelerated activites, such as Launcher, flush GL resources and destroy
the GL context. However, some resources were still hanging around, due to deferred
destruction policies (we don't delete layers until the DisplayLists they are in
are finalized, to ensure we don't deref deleted objects). This meant that we were
referring to obsolete GL data in these objects. in particular, it meant that we might
come around later, after a new GL context was created, and delete a texture object
that was incorrect. We use the layer's "texture id" to refer to the texture underlying the
layer. But if there's a new GL context, then this texture ID is no longer valid, and
we may be deleting the texture that a different object (layer, icon, whatever) is referring
to, because the driver may return that same ID under the new GL context.
The fix is to more aggressively delete things that we know will not be used again
when the GL context is destroyed. In particular, we delete all resources being used
by all DisplayLists at GL context destruction time.
Issue #7195815 Textures corruption on all devices, in many apps
Change-Id: I52d2d208173690dbb794a83402d38f14ea4c6c22
2012-09-30 12:14:13 -07:00
|
|
|
|
|
|
|
clearGarbage();
|
2011-07-18 15:00:43 -07:00
|
|
|
}
|
|
|
|
|
2010-10-27 18:57:51 -07:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// VBO
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2011-12-12 20:35:21 -08:00
|
|
|
bool Caches::bindMeshBuffer() {
|
|
|
|
return bindMeshBuffer(meshBuffer);
|
2010-10-22 18:59:26 -07:00
|
|
|
}
|
|
|
|
|
2011-12-12 20:35:21 -08:00
|
|
|
bool Caches::bindMeshBuffer(const GLuint buffer) {
|
2010-10-25 18:42:25 -07:00
|
|
|
if (mCurrentBuffer != buffer) {
|
2010-10-22 18:59:26 -07:00
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
2010-10-25 18:42:25 -07:00
|
|
|
mCurrentBuffer = buffer;
|
2011-12-12 20:35:21 -08:00
|
|
|
return true;
|
2010-10-22 18:59:26 -07:00
|
|
|
}
|
2011-12-12 20:35:21 -08:00
|
|
|
return false;
|
2010-10-22 18:59:26 -07:00
|
|
|
}
|
|
|
|
|
2011-12-12 20:35:21 -08:00
|
|
|
bool Caches::unbindMeshBuffer() {
|
2010-10-25 18:42:25 -07:00
|
|
|
if (mCurrentBuffer) {
|
2010-10-22 18:59:26 -07:00
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
2010-10-25 18:42:25 -07:00
|
|
|
mCurrentBuffer = 0;
|
2011-12-12 20:35:21 -08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-12-13 13:11:32 -08:00
|
|
|
bool Caches::bindIndicesBuffer(const GLuint buffer) {
|
|
|
|
if (mCurrentIndicesBuffer != buffer) {
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
|
|
|
|
mCurrentIndicesBuffer = buffer;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Caches::unbindIndicesBuffer() {
|
|
|
|
if (mCurrentIndicesBuffer) {
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
|
|
|
mCurrentIndicesBuffer = 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-09-13 20:26:50 -07:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Meshes and textures
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2012-09-25 12:00:29 -07:00
|
|
|
void Caches::bindPositionVertexPointer(bool force, GLvoid* vertices, GLsizei stride) {
|
|
|
|
if (force || vertices != mCurrentPositionPointer || stride != mCurrentPositionStride) {
|
|
|
|
GLuint slot = currentProgram->position;
|
2011-12-12 20:35:21 -08:00
|
|
|
glVertexAttribPointer(slot, 2, GL_FLOAT, GL_FALSE, stride, vertices);
|
|
|
|
mCurrentPositionPointer = vertices;
|
2012-09-25 12:00:29 -07:00
|
|
|
mCurrentPositionStride = stride;
|
2010-10-22 18:59:26 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-25 12:00:29 -07:00
|
|
|
void Caches::bindTexCoordsVertexPointer(bool force, GLvoid* vertices) {
|
2011-12-12 20:35:21 -08:00
|
|
|
if (force || vertices != mCurrentTexCoordsPointer) {
|
2012-09-25 12:00:29 -07:00
|
|
|
GLuint slot = currentProgram->texCoords;
|
2011-12-12 20:35:21 -08:00
|
|
|
glVertexAttribPointer(slot, 2, GL_FLOAT, GL_FALSE, gMeshStride, vertices);
|
|
|
|
mCurrentTexCoordsPointer = vertices;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Caches::resetVertexPointers() {
|
|
|
|
mCurrentPositionPointer = this;
|
|
|
|
mCurrentTexCoordsPointer = this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Caches::resetTexCoordsVertexPointer() {
|
|
|
|
mCurrentTexCoordsPointer = this;
|
|
|
|
}
|
|
|
|
|
2011-12-13 13:11:32 -08:00
|
|
|
void Caches::enableTexCoordsVertexArray() {
|
|
|
|
if (!mTexCoordsArrayEnabled) {
|
|
|
|
glEnableVertexAttribArray(Program::kBindingTexCoords);
|
2011-12-13 18:39:19 -08:00
|
|
|
mCurrentTexCoordsPointer = this;
|
2011-12-13 13:11:32 -08:00
|
|
|
mTexCoordsArrayEnabled = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Caches::disbaleTexCoordsVertexArray() {
|
|
|
|
if (mTexCoordsArrayEnabled) {
|
|
|
|
glDisableVertexAttribArray(Program::kBindingTexCoords);
|
|
|
|
mTexCoordsArrayEnabled = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-13 14:55:06 -08:00
|
|
|
void Caches::activeTexture(GLuint textureUnit) {
|
|
|
|
if (mTextureUnit != textureUnit) {
|
|
|
|
glActiveTexture(gTextureUnits[textureUnit]);
|
|
|
|
mTextureUnit = textureUnit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-13 20:26:50 -07:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Scissor
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2012-07-17 17:32:48 -07:00
|
|
|
bool Caches::setScissor(GLint x, GLint y, GLint width, GLint height) {
|
2012-07-13 15:28:31 -07:00
|
|
|
if (scissorEnabled && (x != mScissorX || y != mScissorY ||
|
|
|
|
width != mScissorWidth || height != mScissorHeight)) {
|
|
|
|
|
2012-10-16 17:36:16 -07:00
|
|
|
if (x < 0) {
|
|
|
|
width += x;
|
|
|
|
x = 0;
|
|
|
|
}
|
|
|
|
if (y < 0) {
|
|
|
|
height += y;
|
|
|
|
y = 0;
|
|
|
|
}
|
|
|
|
if (width < 0) {
|
|
|
|
width = 0;
|
|
|
|
}
|
|
|
|
if (height < 0) {
|
|
|
|
height = 0;
|
|
|
|
}
|
2011-12-14 19:23:32 -08:00
|
|
|
glScissor(x, y, width, height);
|
|
|
|
|
|
|
|
mScissorX = x;
|
|
|
|
mScissorY = y;
|
|
|
|
mScissorWidth = width;
|
|
|
|
mScissorHeight = height;
|
2012-07-17 17:32:48 -07:00
|
|
|
|
|
|
|
return true;
|
2011-12-14 19:23:32 -08:00
|
|
|
}
|
2012-07-17 17:32:48 -07:00
|
|
|
return false;
|
2011-12-14 19:23:32 -08:00
|
|
|
}
|
|
|
|
|
2012-07-17 17:32:48 -07:00
|
|
|
bool Caches::enableScissor() {
|
2012-07-13 15:28:31 -07:00
|
|
|
if (!scissorEnabled) {
|
|
|
|
glEnable(GL_SCISSOR_TEST);
|
|
|
|
scissorEnabled = true;
|
2012-10-07 14:05:59 -07:00
|
|
|
resetScissor();
|
2012-07-17 17:32:48 -07:00
|
|
|
return true;
|
2012-07-13 15:28:31 -07:00
|
|
|
}
|
2012-07-17 17:32:48 -07:00
|
|
|
return false;
|
2012-07-13 15:28:31 -07:00
|
|
|
}
|
|
|
|
|
2012-07-17 17:32:48 -07:00
|
|
|
bool Caches::disableScissor() {
|
2012-07-13 15:28:31 -07:00
|
|
|
if (scissorEnabled) {
|
|
|
|
glDisable(GL_SCISSOR_TEST);
|
|
|
|
scissorEnabled = false;
|
2012-07-17 17:32:48 -07:00
|
|
|
return true;
|
2012-07-13 15:28:31 -07:00
|
|
|
}
|
2012-07-17 17:32:48 -07:00
|
|
|
return false;
|
2012-07-13 15:28:31 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void Caches::setScissorEnabled(bool enabled) {
|
|
|
|
if (scissorEnabled != enabled) {
|
|
|
|
if (enabled) glEnable(GL_SCISSOR_TEST);
|
|
|
|
else glDisable(GL_SCISSOR_TEST);
|
|
|
|
scissorEnabled = enabled;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-03 14:13:39 -08:00
|
|
|
void Caches::resetScissor() {
|
|
|
|
mScissorX = mScissorY = mScissorWidth = mScissorHeight = 0;
|
|
|
|
}
|
|
|
|
|
2012-09-13 20:26:50 -07:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Tiling
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
void Caches::startTiling(GLuint x, GLuint y, GLuint width, GLuint height, bool opaque) {
|
2012-09-23 14:46:35 -07:00
|
|
|
if (extensions.hasTiledRendering() && !debugOverdraw) {
|
|
|
|
glStartTilingQCOM(x, y, width, height, (opaque ? GL_NONE : GL_COLOR_BUFFER_BIT0_QCOM));
|
2012-09-13 20:26:50 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Caches::endTiling() {
|
2012-09-23 14:46:35 -07:00
|
|
|
if (extensions.hasTiledRendering() && !debugOverdraw) {
|
2012-09-19 17:25:38 -07:00
|
|
|
glEndTilingQCOM(GL_COLOR_BUFFER_BIT0_QCOM);
|
2012-09-13 20:26:50 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-27 17:55:46 -07:00
|
|
|
bool Caches::hasRegisteredFunctors() {
|
|
|
|
return mFunctorsCount > 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Caches::registerFunctors(uint32_t functorCount) {
|
|
|
|
mFunctorsCount += functorCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Caches::unregisterFunctors(uint32_t functorCount) {
|
|
|
|
if (functorCount > mFunctorsCount) {
|
|
|
|
mFunctorsCount = 0;
|
|
|
|
} else {
|
|
|
|
mFunctorsCount -= functorCount;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-13 20:26:50 -07:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Regions
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2010-10-27 18:57:51 -07:00
|
|
|
TextureVertex* Caches::getRegionMesh() {
|
|
|
|
// Create the mesh, 2 triangles and 4 vertices per rectangle in the region
|
|
|
|
if (!mRegionMesh) {
|
|
|
|
mRegionMesh = new TextureVertex[REGION_MESH_QUAD_COUNT * 4];
|
|
|
|
|
|
|
|
uint16_t* regionIndices = new uint16_t[REGION_MESH_QUAD_COUNT * 6];
|
|
|
|
for (int i = 0; i < REGION_MESH_QUAD_COUNT; 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, &mRegionMeshIndices);
|
2011-12-13 13:11:32 -08:00
|
|
|
bindIndicesBuffer(mRegionMeshIndices);
|
2010-10-27 18:57:51 -07:00
|
|
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, REGION_MESH_QUAD_COUNT * 6 * sizeof(uint16_t),
|
|
|
|
regionIndices, GL_STATIC_DRAW);
|
|
|
|
|
|
|
|
delete[] regionIndices;
|
|
|
|
} else {
|
2011-12-13 13:11:32 -08:00
|
|
|
bindIndicesBuffer(mRegionMeshIndices);
|
2010-10-27 18:57:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return mRegionMesh;
|
|
|
|
}
|
|
|
|
|
2010-10-22 18:59:26 -07:00
|
|
|
}; // namespace uirenderer
|
|
|
|
}; // namespace android
|