Batch 9-patches in a single mesh whenever possible
This change also fixes the way batched bitmaps were handled inside a layer. The layer is now correctly dirtied to minimize the amount of pixels to blend. Fix alpha, mode and opaque computations for DrawPatchOp. Change-Id: I1b6cd581c0f0db66c1002bb4fb1a9811e55bfa78
This commit is contained in:
@@ -751,12 +751,18 @@ public:
|
||||
TextureVertex::set(ptr++, posRect.xDim - offsetRect.left, posRect.yDim - offsetRect.top, \
|
||||
texCoordsRect.xDim, texCoordsRect.yDim)
|
||||
|
||||
/**
|
||||
* This multi-draw operation builds a mesh on the stack by generating a quad
|
||||
* for each bitmap in the batch. This method is also responsible for dirtying
|
||||
* the current layer, if any.
|
||||
*/
|
||||
virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
|
||||
const Vector<DrawOp*>& ops, const Rect& bounds) {
|
||||
renderer.restoreDisplayState(state, true); // restore all but the clip
|
||||
TextureVertex vertices[6 * ops.size()];
|
||||
TextureVertex* vertex = &vertices[0];
|
||||
|
||||
const bool hasLayer = renderer.hasLayer();
|
||||
bool transformed = false;
|
||||
|
||||
// TODO: manually handle rect clip for bitmaps by adjusting texCoords per op,
|
||||
@@ -778,6 +784,11 @@ public:
|
||||
SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
|
||||
SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
|
||||
SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, bottom);
|
||||
|
||||
if (hasLayer) {
|
||||
const Rect& dirty = ops[i]->state.mBounds;
|
||||
renderer.dirtyLayer(dirty.left, dirty.top, dirty.right, dirty.bottom);
|
||||
}
|
||||
}
|
||||
|
||||
return renderer.drawBitmaps(mBitmap, ops.size(), &vertices[0],
|
||||
@@ -921,25 +932,104 @@ private:
|
||||
class DrawPatchOp : public DrawBoundedOp {
|
||||
public:
|
||||
DrawPatchOp(SkBitmap* bitmap, Res_png_9patch* patch,
|
||||
float left, float top, float right, float bottom, int alpha, SkXfermode::Mode mode)
|
||||
: DrawBoundedOp(left, top, right, bottom, 0),
|
||||
mBitmap(bitmap), mPatch(patch), mAlpha(alpha), mMode(mode),
|
||||
mGenerationId(0), mMesh(NULL) {
|
||||
float left, float top, float right, float bottom, SkPaint* paint)
|
||||
: DrawBoundedOp(left, top, right, bottom, paint),
|
||||
mBitmap(bitmap), mPatch(patch), mGenerationId(0), mMesh(NULL) {
|
||||
mEntry = Caches::getInstance().assetAtlas.getEntry(bitmap);
|
||||
};
|
||||
|
||||
virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
|
||||
const Patch* getMesh(OpenGLRenderer& renderer) {
|
||||
if (!mMesh || renderer.getCaches().patchCache.getGenerationId() != mGenerationId) {
|
||||
PatchCache& cache = renderer.getCaches().patchCache;
|
||||
mMesh = cache.get(mEntry, mBitmap->width(), mBitmap->height(),
|
||||
mLocalBounds.right - mLocalBounds.left, mLocalBounds.bottom - mLocalBounds.top,
|
||||
mPatch);
|
||||
mLocalBounds.getWidth(), mLocalBounds.getHeight(), mPatch);
|
||||
mGenerationId = cache.getGenerationId();
|
||||
}
|
||||
return mMesh;
|
||||
}
|
||||
|
||||
/**
|
||||
* This multi-draw operation builds an indexed mesh on the stack by copying
|
||||
* and transforming the vertices of each 9-patch in the batch. This method
|
||||
* is also responsible for dirtying the current layer, if any.
|
||||
*/
|
||||
virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
|
||||
const Vector<DrawOp*>& ops, const Rect& bounds) {
|
||||
renderer.restoreDisplayState(state, true);
|
||||
|
||||
// Batches will usually contain a small number of items so it's
|
||||
// worth performing a first iteration to count the exact number
|
||||
// of vertices we need in the new mesh
|
||||
uint32_t totalVertices = 0;
|
||||
for (unsigned int i = 0; i < ops.size(); i++) {
|
||||
totalVertices += ((DrawPatchOp*) ops[i])->getMesh(renderer)->verticesCount;
|
||||
}
|
||||
|
||||
const bool hasLayer = renderer.hasLayer();
|
||||
|
||||
uint32_t indexCount = 0;
|
||||
|
||||
TextureVertex vertices[totalVertices];
|
||||
TextureVertex* vertex = &vertices[0];
|
||||
|
||||
// Create a mesh that contains the transformed vertices for all the
|
||||
// 9-patch objects that are part of the batch. Note that onDefer()
|
||||
// enforces ops drawn by this function to have a pure translate or
|
||||
// identity matrix
|
||||
for (unsigned int i = 0; i < ops.size(); i++) {
|
||||
DrawPatchOp* patchOp = (DrawPatchOp*) ops[i];
|
||||
const Patch* opMesh = patchOp->getMesh(renderer);
|
||||
uint32_t vertexCount = opMesh->verticesCount;
|
||||
if (vertexCount == 0) continue;
|
||||
|
||||
// We use the bounds to know where to translate our vertices
|
||||
// Using patchOp->state.mBounds wouldn't work because these
|
||||
// bounds are clipped
|
||||
const float tx = (int) floorf(patchOp->state.mMatrix.getTranslateX() +
|
||||
patchOp->mLocalBounds.left + 0.5f);
|
||||
const float ty = (int) floorf(patchOp->state.mMatrix.getTranslateY() +
|
||||
patchOp->mLocalBounds.top + 0.5f);
|
||||
|
||||
// Copy & transform all the vertices for the current operation
|
||||
TextureVertex* opVertices = opMesh->vertices;
|
||||
for (uint32_t j = 0; j < vertexCount; j++, opVertices++) {
|
||||
TextureVertex::set(vertex++,
|
||||
opVertices->position[0] + tx, opVertices->position[1] + ty,
|
||||
opVertices->texture[0], opVertices->texture[1]);
|
||||
}
|
||||
|
||||
// Dirty the current layer if possible. When the 9-patch does not
|
||||
// contain empty quads we can take a shortcut and simply set the
|
||||
// dirty rect to the object's bounds.
|
||||
if (hasLayer) {
|
||||
if (!opMesh->hasEmptyQuads) {
|
||||
renderer.dirtyLayer(tx, ty,
|
||||
tx + patchOp->mLocalBounds.getWidth(),
|
||||
ty + patchOp->mLocalBounds.getHeight());
|
||||
} else {
|
||||
const size_t count = opMesh->quads.size();
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
const Rect& quadBounds = opMesh->quads[i];
|
||||
const float x = tx + quadBounds.left;
|
||||
const float y = ty + quadBounds.top;
|
||||
renderer.dirtyLayer(x, y,
|
||||
x + quadBounds.getWidth(), y + quadBounds.getHeight());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
indexCount += opMesh->indexCount;
|
||||
}
|
||||
|
||||
return renderer.drawPatches(mBitmap, mEntry, &vertices[0], indexCount, getPaint(renderer));
|
||||
}
|
||||
|
||||
virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
|
||||
// We're not calling the public variant of drawPatch() here
|
||||
// This method won't perform the quickReject() since we've already done it at this point
|
||||
return renderer.drawPatch(mBitmap, mMesh, mEntry, mLocalBounds.left, mLocalBounds.top,
|
||||
mLocalBounds.right, mLocalBounds.bottom, mAlpha, mMode);
|
||||
return renderer.drawPatch(mBitmap, getMesh(renderer), mEntry,
|
||||
mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
|
||||
getPaint(renderer));
|
||||
}
|
||||
|
||||
virtual void output(int level, uint32_t logFlags) {
|
||||
@@ -951,7 +1041,8 @@ public:
|
||||
virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {
|
||||
deferInfo.batchId = DeferredDisplayList::kOpBatch_Patch;
|
||||
deferInfo.mergeId = mEntry ? (mergeid_t) &mEntry->atlas : (mergeid_t) mBitmap;
|
||||
deferInfo.mergeable = true;
|
||||
deferInfo.mergeable = state.mMatrix.isPureTranslate() &&
|
||||
OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
|
||||
deferInfo.opaqueOverBounds = isOpaqueOverBounds() && mBitmap->isOpaque();
|
||||
}
|
||||
|
||||
@@ -959,11 +1050,9 @@ private:
|
||||
SkBitmap* mBitmap;
|
||||
Res_png_9patch* mPatch;
|
||||
|
||||
int mAlpha;
|
||||
SkXfermode::Mode mMode;
|
||||
|
||||
uint32_t mGenerationId;
|
||||
const Patch* mMesh;
|
||||
|
||||
AssetAtlas::Entry* mEntry;
|
||||
};
|
||||
|
||||
|
||||
@@ -317,13 +317,9 @@ status_t DisplayListRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, in
|
||||
|
||||
status_t DisplayListRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch,
|
||||
float left, float top, float right, float bottom, SkPaint* paint) {
|
||||
int alpha;
|
||||
SkXfermode::Mode mode;
|
||||
OpenGLRenderer::getAlphaAndModeDirect(paint, &alpha, &mode);
|
||||
|
||||
bitmap = refBitmap(bitmap);
|
||||
|
||||
addDrawOp(new (alloc()) DrawPatchOp(bitmap, patch, left, top, right, bottom, alpha, mode));
|
||||
addDrawOp(new (alloc()) DrawPatchOp(bitmap, patch, left, top, right, bottom, paint));
|
||||
return DrawGlInfo::kStatusDone;
|
||||
}
|
||||
|
||||
|
||||
@@ -1191,7 +1191,7 @@ void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) {
|
||||
// after we setup drawing in case we need to mess with the
|
||||
// stencil buffer in setupDraw()
|
||||
TextureVertex* mesh = mCaches.getRegionMesh();
|
||||
GLsizei numQuads = 0;
|
||||
uint32_t numQuads = 0;
|
||||
|
||||
setupDrawWithTexture();
|
||||
setupDrawColor(alpha, alpha, alpha, alpha);
|
||||
@@ -2049,6 +2049,11 @@ void OpenGLRenderer::drawAlphaBitmap(Texture* texture, float left, float top, Sk
|
||||
GL_TRIANGLE_STRIP, gMeshCount, ignoreTransform);
|
||||
}
|
||||
|
||||
/**
|
||||
* Important note: this method is intended to draw batches of bitmaps and
|
||||
* will not set the scissor enable or dirty the current layer, if any.
|
||||
* The caller is responsible for properly dirtying the current layer.
|
||||
*/
|
||||
status_t OpenGLRenderer::drawBitmaps(SkBitmap* bitmap, int bitmapCount, TextureVertex* vertices,
|
||||
bool transformed, const Rect& bounds, SkPaint* paint) {
|
||||
mCaches.activeTexture(0);
|
||||
@@ -2071,12 +2076,12 @@ status_t OpenGLRenderer::drawBitmaps(SkBitmap* bitmap, int bitmapCount, TextureV
|
||||
drawAlpha8TextureMesh(x, y, x + bounds.getWidth(), y + bounds.getHeight(),
|
||||
texture->id, paint != NULL, color, alpha, mode,
|
||||
&vertices[0].position[0], &vertices[0].texture[0],
|
||||
GL_TRIANGLES, bitmapCount * 6, true, true);
|
||||
GL_TRIANGLES, bitmapCount * 6, true, true, false);
|
||||
} else {
|
||||
drawTextureMesh(x, y, x + bounds.getWidth(), y + bounds.getHeight(),
|
||||
texture->id, alpha / 255.0f, mode, texture->blend,
|
||||
&vertices[0].position[0], &vertices[0].texture[0],
|
||||
GL_TRIANGLES, bitmapCount * 6, false, true, 0, true);
|
||||
GL_TRIANGLES, bitmapCount * 6, false, true, 0, true, false);
|
||||
}
|
||||
|
||||
return DrawGlInfo::kStatusDrew;
|
||||
@@ -2367,10 +2372,6 @@ status_t OpenGLRenderer::drawBitmap(SkBitmap* bitmap,
|
||||
|
||||
status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch,
|
||||
float left, float top, float right, float bottom, SkPaint* paint) {
|
||||
int alpha;
|
||||
SkXfermode::Mode mode;
|
||||
getAlphaAndMode(paint, &alpha, &mode);
|
||||
|
||||
if (quickReject(left, top, right, bottom)) {
|
||||
return DrawGlInfo::kStatusDone;
|
||||
}
|
||||
@@ -2379,13 +2380,11 @@ status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch,
|
||||
const Patch* mesh = mCaches.patchCache.get(entry, bitmap->width(), bitmap->height(),
|
||||
right - left, bottom - top, patch);
|
||||
|
||||
return drawPatch(bitmap, mesh, entry, left, top, right, bottom, alpha, mode);
|
||||
return drawPatch(bitmap, mesh, entry, left, top, right, bottom, paint);
|
||||
}
|
||||
|
||||
status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const Patch* mesh,
|
||||
AssetAtlas::Entry* entry, float left, float top, float right, float bottom,
|
||||
int alpha, SkXfermode::Mode mode) {
|
||||
|
||||
status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const Patch* mesh, AssetAtlas::Entry* entry,
|
||||
float left, float top, float right, float bottom, SkPaint* paint) {
|
||||
if (quickReject(left, top, right, bottom)) {
|
||||
return DrawGlInfo::kStatusDone;
|
||||
}
|
||||
@@ -2399,6 +2398,10 @@ status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const Patch* mesh,
|
||||
texture->setWrap(GL_CLAMP_TO_EDGE, true);
|
||||
texture->setFilter(GL_LINEAR, true);
|
||||
|
||||
int alpha;
|
||||
SkXfermode::Mode mode;
|
||||
getAlphaAndMode(paint, &alpha, &mode);
|
||||
|
||||
const bool pureTranslate = currentTransform().isPureTranslate();
|
||||
// Mark the current layer dirty where we are going to draw the patch
|
||||
if (hasLayer() && mesh->hasEmptyQuads) {
|
||||
@@ -2418,8 +2421,6 @@ status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const Patch* mesh,
|
||||
}
|
||||
}
|
||||
|
||||
alpha *= mSnapshot->alpha;
|
||||
|
||||
if (CC_LIKELY(pureTranslate)) {
|
||||
const float x = (int) floorf(left + currentTransform().getTranslateX() + 0.5f);
|
||||
const float y = (int) floorf(top + currentTransform().getTranslateY() + 0.5f);
|
||||
@@ -2441,6 +2442,32 @@ status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const Patch* mesh,
|
||||
return DrawGlInfo::kStatusDrew;
|
||||
}
|
||||
|
||||
/**
|
||||
* Important note: this method is intended to draw batches of 9-patch objects and
|
||||
* will not set the scissor enable or dirty the current layer, if any.
|
||||
* The caller is responsible for properly dirtying the current layer.
|
||||
*/
|
||||
status_t OpenGLRenderer::drawPatches(SkBitmap* bitmap, AssetAtlas::Entry* entry,
|
||||
TextureVertex* vertices, uint32_t indexCount, SkPaint* paint) {
|
||||
mCaches.activeTexture(0);
|
||||
Texture* texture = entry ? entry->texture : mCaches.textureCache.get(bitmap);
|
||||
if (!texture) return DrawGlInfo::kStatusDone;
|
||||
const AutoTexture autoCleanup(texture);
|
||||
|
||||
texture->setWrap(GL_CLAMP_TO_EDGE, true);
|
||||
texture->setFilter(GL_LINEAR, true);
|
||||
|
||||
int alpha;
|
||||
SkXfermode::Mode mode;
|
||||
getAlphaAndMode(paint, &alpha, &mode);
|
||||
|
||||
drawIndexedTextureMesh(0.0f, 0.0f, 1.0f, 1.0f, texture->id, alpha / 255.0f,
|
||||
mode, texture->blend, &vertices[0].position[0], &vertices[0].texture[0],
|
||||
GL_TRIANGLES, indexCount, false, true, 0, true, false);
|
||||
|
||||
return DrawGlInfo::kStatusDrew;
|
||||
}
|
||||
|
||||
status_t OpenGLRenderer::drawVertexBuffer(const VertexBuffer& vertexBuffer, SkPaint* paint,
|
||||
bool useOffset) {
|
||||
if (!vertexBuffer.getVertexCount()) {
|
||||
|
||||
@@ -297,10 +297,12 @@ public:
|
||||
virtual status_t drawBitmapData(SkBitmap* bitmap, float left, float top, SkPaint* paint);
|
||||
virtual status_t drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight,
|
||||
float* vertices, int* colors, SkPaint* paint);
|
||||
status_t drawPatches(SkBitmap* bitmap, AssetAtlas::Entry* entry,
|
||||
TextureVertex* vertices, uint32_t indexCount, SkPaint* paint);
|
||||
virtual status_t drawPatch(SkBitmap* bitmap, Res_png_9patch* patch,
|
||||
float left, float top, float right, float bottom, SkPaint* paint);
|
||||
status_t drawPatch(SkBitmap* bitmap, const Patch* mesh, AssetAtlas::Entry* entry,
|
||||
float left, float top, float right, float bottom, int alpha, SkXfermode::Mode mode);
|
||||
float left, float top, float right, float bottom, SkPaint* paint);
|
||||
virtual status_t drawColor(int color, SkXfermode::Mode mode);
|
||||
virtual status_t drawRect(float left, float top, float right, float bottom, SkPaint* paint);
|
||||
virtual status_t drawRoundRect(float left, float top, float right, float bottom,
|
||||
@@ -1115,6 +1117,8 @@ private:
|
||||
friend class DisplayListRenderer;
|
||||
friend class Layer;
|
||||
friend class TextSetupFunctor;
|
||||
friend class DrawBitmapOp;
|
||||
friend class DrawPatchOp;
|
||||
|
||||
}; // class OpenGLRenderer
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace uirenderer {
|
||||
// Constructors/destructor
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Patch::Patch(): verticesCount(0), indexCount(0), hasEmptyQuads(false) {
|
||||
Patch::Patch(): vertices(NULL), verticesCount(0), indexCount(0), hasEmptyQuads(false) {
|
||||
}
|
||||
|
||||
Patch::~Patch() {
|
||||
@@ -47,14 +47,14 @@ uint32_t Patch::getSize() const {
|
||||
}
|
||||
|
||||
TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeight,
|
||||
float left, float top, float right, float bottom, const Res_png_9patch* patch) {
|
||||
float width, float height, const Res_png_9patch* patch) {
|
||||
UvMapper mapper;
|
||||
return createMesh(bitmapWidth, bitmapHeight, left, top, right, bottom, mapper, patch);
|
||||
return createMesh(bitmapWidth, bitmapHeight, width, height, mapper, patch);
|
||||
}
|
||||
|
||||
TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeight,
|
||||
float left, float top, float right, float bottom,
|
||||
const UvMapper& mapper, const Res_png_9patch* patch) {
|
||||
float width, float height, const UvMapper& mapper, const Res_png_9patch* patch) {
|
||||
if (vertices) return vertices;
|
||||
|
||||
const uint32_t* colors = &patch->colors[0];
|
||||
const int8_t numColors = patch->numColors;
|
||||
@@ -79,7 +79,7 @@ TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeig
|
||||
uint32_t maxVertices = ((xCount + 1) * (yCount + 1) - emptyQuads) * 4;
|
||||
if (maxVertices == 0) return NULL;
|
||||
|
||||
TextureVertex* vertices = new TextureVertex[maxVertices];
|
||||
vertices = new TextureVertex[maxVertices];
|
||||
TextureVertex* vertex = vertices;
|
||||
|
||||
const int32_t* xDivs = patch->xDivs;
|
||||
@@ -101,9 +101,9 @@ TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeig
|
||||
}
|
||||
const float xStretchTex = stretchSize;
|
||||
const float fixed = bitmapWidth - stretchSize;
|
||||
const float xStretch = fmaxf(right - left - fixed, 0.0f);
|
||||
const float xStretch = fmaxf(width - fixed, 0.0f);
|
||||
stretchX = xStretch / xStretchTex;
|
||||
rescaleX = fixed == 0.0f ? 0.0f : fminf(fmaxf(right - left, 0.0f) / fixed, 1.0f);
|
||||
rescaleX = fixed == 0.0f ? 0.0f : fminf(fmaxf(width, 0.0f) / fixed, 1.0f);
|
||||
}
|
||||
|
||||
if (yStretchCount > 0) {
|
||||
@@ -113,9 +113,9 @@ TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeig
|
||||
}
|
||||
const float yStretchTex = stretchSize;
|
||||
const float fixed = bitmapHeight - stretchSize;
|
||||
const float yStretch = fmaxf(bottom - top - fixed, 0.0f);
|
||||
const float yStretch = fmaxf(height - fixed, 0.0f);
|
||||
stretchY = yStretch / yStretchTex;
|
||||
rescaleY = fixed == 0.0f ? 0.0f : fminf(fmaxf(bottom - top, 0.0f) / fixed, 1.0f);
|
||||
rescaleY = fixed == 0.0f ? 0.0f : fminf(fmaxf(height, 0.0f) / fixed, 1.0f);
|
||||
}
|
||||
|
||||
uint32_t quadCount = 0;
|
||||
@@ -144,7 +144,7 @@ TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeig
|
||||
|
||||
if (stepY > 0.0f) {
|
||||
generateRow(xDivs, xCount, vertex, y1, y2, v1, v2, stretchX, rescaleX,
|
||||
right - left, bitmapWidth, quadCount);
|
||||
width, bitmapWidth, quadCount);
|
||||
}
|
||||
|
||||
y1 = y2;
|
||||
@@ -154,9 +154,9 @@ TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeig
|
||||
}
|
||||
|
||||
if (previousStepY != bitmapHeight) {
|
||||
y2 = bottom - top;
|
||||
y2 = height;
|
||||
generateRow(xDivs, xCount, vertex, y1, y2, v1, 1.0f, stretchX, rescaleX,
|
||||
right - left, bitmapWidth, quadCount);
|
||||
width, bitmapWidth, quadCount);
|
||||
}
|
||||
|
||||
return vertices;
|
||||
|
||||
@@ -45,6 +45,7 @@ struct Patch {
|
||||
*/
|
||||
uint32_t getSize() const;
|
||||
|
||||
TextureVertex* vertices;
|
||||
uint32_t verticesCount;
|
||||
uint32_t indexCount;
|
||||
bool hasEmptyQuads;
|
||||
@@ -54,11 +55,9 @@ struct Patch {
|
||||
GLintptr textureOffset;
|
||||
|
||||
TextureVertex* createMesh(const float bitmapWidth, const float bitmapHeight,
|
||||
float left, float top, float right, float bottom,
|
||||
const Res_png_9patch* patch);
|
||||
float width, float height, const Res_png_9patch* patch);
|
||||
TextureVertex* createMesh(const float bitmapWidth, const float bitmapHeight,
|
||||
float left, float top, float right, float bottom,
|
||||
const UvMapper& mapper, const Res_png_9patch* patch);
|
||||
float width, float height, const UvMapper& mapper, const Res_png_9patch* patch);
|
||||
|
||||
private:
|
||||
void generateRow(const int32_t* xDivs, uint32_t xCount, TextureVertex*& vertex,
|
||||
|
||||
@@ -118,10 +118,10 @@ const Patch* PatchCache::get(const AssetAtlas::Entry* entry,
|
||||
|
||||
if (entry) {
|
||||
vertices = newMesh->createMesh(bitmapWidth, bitmapHeight,
|
||||
0.0f, 0.0f, pixelWidth, pixelHeight, entry->uvMapper, patch);
|
||||
pixelWidth, pixelHeight, entry->uvMapper, patch);
|
||||
} else {
|
||||
vertices = newMesh->createMesh(bitmapWidth, bitmapHeight,
|
||||
0.0f, 0.0f, pixelWidth, pixelHeight, patch);
|
||||
pixelWidth, pixelHeight, patch);
|
||||
}
|
||||
|
||||
if (vertices) {
|
||||
@@ -141,8 +141,6 @@ const Patch* PatchCache::get(const AssetAtlas::Entry* entry,
|
||||
mSize += size;
|
||||
|
||||
glBufferSubData(GL_ARRAY_BUFFER, newMesh->offset, size, vertices);
|
||||
|
||||
delete[] vertices;
|
||||
}
|
||||
|
||||
mCache.put(description, newMesh);
|
||||
|
||||
@@ -132,7 +132,10 @@ void GpuPixelBuffer::unmap() {
|
||||
if (mAccessMode != kAccessMode_None) {
|
||||
if (mMappedPointer) {
|
||||
mCaches.bindPixelBuffer(mBuffer);
|
||||
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
|
||||
GLboolean status = glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
|
||||
if (status == GL_FALSE) {
|
||||
ALOGE("Corrupted GPU pixel buffer");
|
||||
}
|
||||
}
|
||||
mAccessMode = kAccessMode_None;
|
||||
mMappedPointer = NULL;
|
||||
|
||||
Reference in New Issue
Block a user