Track texture memory globally
Also mostly consolidates texture creation
Change-Id: Ifea01303afda531dcec99b8fe2a0f64cf2f24420
diff --git a/libs/hwui/renderstate/OffscreenBufferPool.cpp b/libs/hwui/renderstate/OffscreenBufferPool.cpp
index 227b640..98c94df 100644
--- a/libs/hwui/renderstate/OffscreenBufferPool.cpp
+++ b/libs/hwui/renderstate/OffscreenBufferPool.cpp
@@ -34,29 +34,22 @@
OffscreenBuffer::OffscreenBuffer(RenderState& renderState, Caches& caches,
uint32_t viewportWidth, uint32_t viewportHeight)
- : renderState(renderState)
+ : GpuMemoryTracker(GpuObjectType::OffscreenBuffer)
+ , renderState(renderState)
, viewportWidth(viewportWidth)
, viewportHeight(viewportHeight)
, texture(caches) {
- texture.width = computeIdealDimension(viewportWidth);
- texture.height = computeIdealDimension(viewportHeight);
+ uint32_t width = computeIdealDimension(viewportWidth);
+ uint32_t height = computeIdealDimension(viewportHeight);
+ texture.resize(width, height, GL_RGBA);
texture.blend = true;
-
- caches.textureState().activateTexture(0);
- glGenTextures(1, &texture.id);
- caches.textureState().bindTexture(GL_TEXTURE_2D, texture.id);
-
- texture.setWrap(GL_CLAMP_TO_EDGE, false, false, GL_TEXTURE_2D);
+ texture.setWrap(GL_CLAMP_TO_EDGE);
// not setting filter on texture, since it's set when drawing, based on transform
-
- glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture.width, texture.height, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
}
Rect OffscreenBuffer::getTextureCoordinates() {
- const float texX = 1.0f / float(texture.width);
- const float texY = 1.0f / float(texture.height);
+ const float texX = 1.0f / static_cast<float>(texture.width());
+ const float texY = 1.0f / static_cast<float>(texture.height());
return Rect(0, viewportHeight * texY, viewportWidth * texX, 0);
}
@@ -69,8 +62,8 @@
size_t count;
const android::Rect* rects = safeRegion.getArray(&count);
- const float texX = 1.0f / float(texture.width);
- const float texY = 1.0f / float(texture.height);
+ const float texX = 1.0f / float(texture.width());
+ const float texY = 1.0f / float(texture.height());
FatVector<TextureVertex, 64> meshVector(count * 4); // uses heap if more than 64 vertices needed
TextureVertex* mesh = &meshVector[0];
@@ -157,8 +150,8 @@
OffscreenBuffer* OffscreenBufferPool::resize(OffscreenBuffer* layer,
const uint32_t width, const uint32_t height) {
RenderState& renderState = layer->renderState;
- if (layer->texture.width == OffscreenBuffer::computeIdealDimension(width)
- && layer->texture.height == OffscreenBuffer::computeIdealDimension(height)) {
+ if (layer->texture.width() == OffscreenBuffer::computeIdealDimension(width)
+ && layer->texture.height() == OffscreenBuffer::computeIdealDimension(height)) {
// resize in place
layer->viewportWidth = width;
layer->viewportHeight = height;
diff --git a/libs/hwui/renderstate/OffscreenBufferPool.h b/libs/hwui/renderstate/OffscreenBufferPool.h
index 2d8d529..94155ef 100644
--- a/libs/hwui/renderstate/OffscreenBufferPool.h
+++ b/libs/hwui/renderstate/OffscreenBufferPool.h
@@ -17,10 +17,10 @@
#ifndef ANDROID_HWUI_OFFSCREEN_BUFFER_POOL_H
#define ANDROID_HWUI_OFFSCREEN_BUFFER_POOL_H
+#include <GpuMemoryTracker.h>
#include "Caches.h"
#include "Texture.h"
#include "utils/Macros.h"
-
#include <ui/Region.h>
#include <set>
@@ -40,7 +40,7 @@
* viewport bounds, since textures are always allocated with width / height as a multiple of 64, for
* the purpose of improving reuse.
*/
-class OffscreenBuffer {
+class OffscreenBuffer : GpuMemoryTracker {
public:
OffscreenBuffer(RenderState& renderState, Caches& caches,
uint32_t viewportWidth, uint32_t viewportHeight);
@@ -58,7 +58,7 @@
static uint32_t computeIdealDimension(uint32_t dimension);
- uint32_t getSizeInBytes() { return texture.width * texture.height * 4; }
+ uint32_t getSizeInBytes() { return texture.objectSize(); }
RenderState& renderState;
@@ -124,8 +124,8 @@
Entry(OffscreenBuffer* layer)
: layer(layer)
- , width(layer->texture.width)
- , height(layer->texture.height) {
+ , width(layer->texture.width())
+ , height(layer->texture.height()) {
}
static int compare(const Entry& lhs, const Entry& rhs);
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index 4fa8200..4a1e8fc 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -13,12 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include <GpuMemoryTracker.h>
#include "renderstate/RenderState.h"
#include "renderthread/CanvasContext.h"
#include "renderthread/EglManager.h"
#include "utils/GLUtils.h"
-
#include <algorithm>
namespace android {
@@ -40,6 +40,8 @@
void RenderState::onGLContextCreated() {
LOG_ALWAYS_FATAL_IF(mBlend || mMeshState || mScissor || mStencil,
"State object lifecycle not managed correctly");
+ GpuMemoryTracker::onGLContextCreated();
+
mBlend = new Blend();
mMeshState = new MeshState();
mScissor = new Scissor();
@@ -106,6 +108,8 @@
mScissor = nullptr;
delete mStencil;
mStencil = nullptr;
+
+ GpuMemoryTracker::onGLContextDestroyed();
}
void RenderState::flush(Caches::FlushMode mode) {
@@ -310,7 +314,7 @@
texture.texture->setFilter(texture.filter, true, false, texture.target);
}
- mCaches->textureState().bindTexture(texture.target, texture.texture->id);
+ mCaches->textureState().bindTexture(texture.target, texture.texture->id());
meshState().enableTexCoordsVertexArray();
meshState().bindTexCoordsVertexPointer(force, vertices.texCoord, vertices.stride);
diff --git a/libs/hwui/renderstate/TextureState.cpp b/libs/hwui/renderstate/TextureState.cpp
index 1f50f71..26ebdee 100644
--- a/libs/hwui/renderstate/TextureState.cpp
+++ b/libs/hwui/renderstate/TextureState.cpp
@@ -34,134 +34,6 @@
GL_TEXTURE3
};
-static void uploadToTexture(bool resize, GLenum format, GLenum type, GLsizei stride, GLsizei bpp,
- GLsizei width, GLsizei height, const GLvoid * data) {
-
- glPixelStorei(GL_UNPACK_ALIGNMENT, bpp);
- const bool useStride = stride != width
- && Caches::getInstance().extensions().hasUnpackRowLength();
- if ((stride == width) || useStride) {
- if (useStride) {
- glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
- }
-
- if (resize) {
- glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, type, data);
- } else {
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, data);
- }
-
- if (useStride) {
- glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
- }
- } else {
- // With OpenGL ES 2.0 we need to copy the bitmap in a temporary buffer
- // if the stride doesn't match the width
-
- GLvoid * temp = (GLvoid *) malloc(width * height * bpp);
- if (!temp) return;
-
- uint8_t * pDst = (uint8_t *)temp;
- uint8_t * pSrc = (uint8_t *)data;
- for (GLsizei i = 0; i < height; i++) {
- memcpy(pDst, pSrc, width * bpp);
- pDst += width * bpp;
- pSrc += stride * bpp;
- }
-
- if (resize) {
- glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, type, temp);
- } else {
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, temp);
- }
-
- free(temp);
- }
-}
-
-static void uploadSkBitmapToTexture(const SkBitmap& bitmap,
- bool resize, GLenum format, GLenum type) {
- uploadToTexture(resize, format, type, bitmap.rowBytesAsPixels(), bitmap.bytesPerPixel(),
- bitmap.width(), bitmap.height(), bitmap.getPixels());
-}
-
-void TextureState::generateTexture(const SkBitmap* bitmap, Texture* texture, bool regenerate) {
- SkAutoLockPixels alp(*bitmap);
-
- if (!bitmap->readyToDraw()) {
- ALOGE("Cannot generate texture from bitmap");
- return;
- }
-
- ATRACE_FORMAT("Upload %ux%u Texture", bitmap->width(), bitmap->height());
-
- // We could also enable mipmapping if both bitmap dimensions are powers
- // of 2 but we'd have to deal with size changes. Let's keep this simple
- const bool canMipMap = Caches::getInstance().extensions().hasNPot();
-
- // If the texture had mipmap enabled but not anymore,
- // force a glTexImage2D to discard the mipmap levels
- const bool resize = !regenerate || bitmap->width() != int(texture->width) ||
- bitmap->height() != int(texture->height) ||
- (regenerate && canMipMap && texture->mipMap && !bitmap->hasHardwareMipMap());
-
- if (!regenerate) {
- glGenTextures(1, &texture->id);
- }
-
- texture->generation = bitmap->getGenerationID();
- texture->width = bitmap->width();
- texture->height = bitmap->height();
-
- bindTexture(texture->id);
-
- switch (bitmap->colorType()) {
- case kAlpha_8_SkColorType:
- uploadSkBitmapToTexture(*bitmap, resize, GL_ALPHA, GL_UNSIGNED_BYTE);
- texture->blend = true;
- break;
- case kRGB_565_SkColorType:
- uploadSkBitmapToTexture(*bitmap, resize, GL_RGB, GL_UNSIGNED_SHORT_5_6_5);
- texture->blend = false;
- break;
- case kN32_SkColorType:
- uploadSkBitmapToTexture(*bitmap, resize, GL_RGBA, GL_UNSIGNED_BYTE);
- // Do this after calling getPixels() to make sure Skia's deferred
- // decoding happened
- texture->blend = !bitmap->isOpaque();
- break;
- case kARGB_4444_SkColorType:
- case kIndex_8_SkColorType: {
- SkBitmap rgbaBitmap;
- rgbaBitmap.allocPixels(SkImageInfo::MakeN32(texture->width, texture->height,
- bitmap->alphaType()));
- rgbaBitmap.eraseColor(0);
-
- SkCanvas canvas(rgbaBitmap);
- canvas.drawBitmap(*bitmap, 0.0f, 0.0f, nullptr);
-
- uploadSkBitmapToTexture(rgbaBitmap, resize, GL_RGBA, GL_UNSIGNED_BYTE);
- texture->blend = !bitmap->isOpaque();
- break;
- }
- default:
- ALOGW("Unsupported bitmap colorType: %d", bitmap->colorType());
- break;
- }
-
- if (canMipMap) {
- texture->mipMap = bitmap->hasHardwareMipMap();
- if (texture->mipMap) {
- glGenerateMipmap(GL_TEXTURE_2D);
- }
- }
-
- if (!regenerate) {
- texture->setFilter(GL_NEAREST);
- texture->setWrap(GL_CLAMP_TO_EDGE);
- }
-}
-
TextureState::TextureState()
: mTextureUnit(0) {
glActiveTexture(kTextureUnits[0]);
diff --git a/libs/hwui/renderstate/TextureState.h b/libs/hwui/renderstate/TextureState.h
index 3a2b85a..ec94d7e 100644
--- a/libs/hwui/renderstate/TextureState.h
+++ b/libs/hwui/renderstate/TextureState.h
@@ -76,13 +76,6 @@
*/
void unbindTexture(GLuint texture);
- /**
- * Generates the texture from a bitmap into the specified texture structure.
- *
- * @param regenerate If true, the bitmap data is reuploaded into the texture, but
- * no new texture is generated.
- */
- void generateTexture(const SkBitmap* bitmap, Texture* texture, bool regenerate);
private:
// total number of texture units available for use
static const int kTextureUnitsCount = 4;