summaryrefslogtreecommitdiffstats
path: root/libs/hwui/OpenGLRenderer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/hwui/OpenGLRenderer.cpp')
-rw-r--r--libs/hwui/OpenGLRenderer.cpp115
1 files changed, 88 insertions, 27 deletions
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 1138998..f81b4ff 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -112,11 +112,9 @@ static const Blender gBlendsSwap[] = {
OpenGLRenderer::OpenGLRenderer():
mCaches(Caches::getInstance()), mExtensions(Extensions::getInstance()) {
- mDrawModifiers.mShader = NULL;
- mDrawModifiers.mColorFilter = NULL;
+ // *set* draw modifiers to be 0
+ memset(&mDrawModifiers, 0, sizeof(mDrawModifiers));
mDrawModifiers.mOverrideLayerAlpha = 1.0f;
- mDrawModifiers.mHasShadow = false;
- mDrawModifiers.mHasDrawFilter = false;
memcpy(mMeshVertices, gMeshVertices, sizeof(gMeshVertices));
@@ -571,8 +569,8 @@ void OpenGLRenderer::updateLayers() {
startMark("Defer Layer Updates");
}
- // Note: it is very important to update the layers in reverse order
- for (int i = count - 1; i >= 0; i--) {
+ // Note: it is very important to update the layers in order
+ for (int i = 0; i < count; i++) {
Layer* layer = mLayerUpdates.itemAt(i);
updateLayer(layer, false);
if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
@@ -594,8 +592,8 @@ void OpenGLRenderer::flushLayers() {
startMark("Apply Layer Updates");
char layerName[12];
- // Note: it is very important to update the layers in reverse order
- for (int i = count - 1; i >= 0; i--) {
+ // Note: it is very important to update the layers in order
+ for (int i = 0; i < count; i++) {
sprintf(layerName, "Layer #%d", i);
startMark(layerName);
@@ -922,7 +920,7 @@ bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, Rect& clip, GLui
// Initialize the texture if needed
if (layer->isEmpty()) {
- layer->allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE);
+ layer->allocateTexture();
layer->setEmpty(false);
}
@@ -1330,10 +1328,9 @@ bool OpenGLRenderer::storeDisplayState(DeferredDisplayState& state, int stateDef
}
}
- if (stateDeferFlags & kStateDeferFlag_Clip) {
+ state.mClipValid = (stateDeferFlags & kStateDeferFlag_Clip);
+ if (state.mClipValid) {
state.mClip.set(currentClip);
- } else {
- state.mClip.setEmpty();
}
// Transform, drawModifiers, and alpha always deferred, since they are used by state operations
@@ -1344,17 +1341,22 @@ bool OpenGLRenderer::storeDisplayState(DeferredDisplayState& state, int stateDef
return false;
}
-void OpenGLRenderer::restoreDisplayState(const DeferredDisplayState& state) {
+void OpenGLRenderer::restoreDisplayState(const DeferredDisplayState& state, bool skipClipRestore) {
currentTransform().load(state.mMatrix);
mDrawModifiers = state.mDrawModifiers;
mSnapshot->alpha = state.mAlpha;
- if (!state.mClip.isEmpty()) {
+ if (state.mClipValid && !skipClipRestore) {
mSnapshot->setClip(state.mClip.left, state.mClip.top, state.mClip.right, state.mClip.bottom);
dirtyClip();
}
}
+void OpenGLRenderer::setFullScreenClip() {
+ mSnapshot->setClip(0, 0, mWidth, mHeight);
+ dirtyClip();
+}
+
///////////////////////////////////////////////////////////////////////////////
// Transforms
///////////////////////////////////////////////////////////////////////////////
@@ -1905,14 +1907,15 @@ void OpenGLRenderer::finishDrawTexture() {
status_t OpenGLRenderer::drawDisplayList(DisplayList* displayList, Rect& dirty,
int32_t replayFlags) {
+ status_t status;
// All the usual checks and setup operations (quickReject, setupDraw, etc.)
// will be performed by the display list itself
if (displayList && displayList->isRenderable()) {
if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
- startFrame();
+ status = startFrame();
ReplayStateStruct replayStruct(*this, dirty, replayFlags);
displayList->replay(replayStruct, 0);
- return replayStruct.mDrawGlStatus;
+ return status | replayStruct.mDrawGlStatus;
}
DeferredDisplayList deferredList;
@@ -1920,9 +1923,9 @@ status_t OpenGLRenderer::drawDisplayList(DisplayList* displayList, Rect& dirty,
displayList->defer(deferStruct, 0);
flushLayers();
- startFrame();
+ status = startFrame();
- return deferredList.flush(*this, dirty);
+ return status | deferredList.flush(*this, dirty);
}
return DrawGlInfo::kStatusDone;
@@ -1962,6 +1965,42 @@ void OpenGLRenderer::drawAlphaBitmap(Texture* texture, float left, float top, Sk
(GLvoid*) gMeshTextureOffset, GL_TRIANGLE_STRIP, gMeshCount, ignoreTransform);
}
+status_t OpenGLRenderer::drawBitmaps(SkBitmap* bitmap, int bitmapCount, TextureVertex* vertices,
+ const Rect& bounds, SkPaint* paint) {
+
+ // merged draw operations don't need scissor, but clip should still be valid
+ mCaches.setScissorEnabled(mScissorOptimizationDisabled);
+
+ mCaches.activeTexture(0);
+ Texture* texture = mCaches.textureCache.get(bitmap);
+ if (!texture) return DrawGlInfo::kStatusDone;
+ const AutoTexture autoCleanup(texture);
+
+ int alpha;
+ SkXfermode::Mode mode;
+ getAlphaAndMode(paint, &alpha, &mode);
+
+ texture->setWrap(GL_CLAMP_TO_EDGE, true);
+ texture->setFilter(GL_NEAREST, true); // merged ops are always pure-translation for now
+
+ const float x = (int) floorf(bounds.left + 0.5f);
+ const float y = (int) floorf(bounds.top + 0.5f);
+ if (CC_UNLIKELY(bitmap->getConfig() == SkBitmap::kA8_Config)) {
+ int color = paint != NULL ? paint->getColor() : 0;
+ 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);
+ } 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);
+ }
+
+ return DrawGlInfo::kStatusDrew;
+}
+
status_t OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint) {
const float right = left + bitmap->width();
const float bottom = top + bitmap->height();
@@ -2643,6 +2682,9 @@ void OpenGLRenderer::drawTextShadow(SkPaint* paint, const char* text, int bytesC
mCaches.dropShadowCache.setFontRenderer(fontRenderer);
const ShadowTexture* shadow = mCaches.dropShadowCache.get(
paint, text, bytesCount, count, mDrawModifiers.mShadowRadius, positions);
+ // If the drop shadow exceeds the max texture size or couldn't be
+ // allocated, skip drawing
+ if (!shadow) return;
const AutoTexture autoCleanup(shadow);
const float sx = x - shadow->left + mDrawModifiers.mShadowDx;
@@ -2792,8 +2834,11 @@ mat4 OpenGLRenderer::findBestFontTransform(const mat4& transform) const {
}
status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
- float x, float y, const float* positions, SkPaint* paint, float length) {
- if (text == NULL || count == 0 || mSnapshot->isIgnored() || canSkipText(paint)) {
+ float x, float y, const float* positions, SkPaint* paint, float length,
+ DrawOpMode drawOpMode) {
+
+ if (drawOpMode == kDrawOpMode_Immediate &&
+ (text == NULL || count == 0 || mSnapshot->isIgnored() || canSkipText(paint))) {
return DrawGlInfo::kStatusDone;
}
@@ -2811,8 +2856,13 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
SkPaint::FontMetrics metrics;
paint->getFontMetrics(&metrics, 0.0f);
- if (quickReject(x, y + metrics.fTop, x + length, y + metrics.fBottom)) {
- return DrawGlInfo::kStatusDone;
+ if (drawOpMode == kDrawOpMode_Immediate) {
+ if (quickReject(x, y + metrics.fTop, x + length, y + metrics.fBottom)) {
+ return DrawGlInfo::kStatusDone;
+ }
+ } else {
+ // merged draw operations don't need scissor, but clip should still be valid
+ mCaches.setScissorEnabled(mScissorOptimizationDisabled);
}
const float oldX = x;
@@ -2864,17 +2914,20 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
bool status;
TextSetupFunctor functor(*this, x, y, pureTranslate, alpha, mode, paint);
+
+ // don't call issuedrawcommand, do it at end of batch
+ bool forceFinish = (drawOpMode != kDrawOpMode_Defer);
if (CC_UNLIKELY(paint->getTextAlign() != SkPaint::kLeft_Align)) {
SkPaint paintCopy(*paint);
paintCopy.setTextAlign(SkPaint::kLeft_Align);
status = fontRenderer.renderPosText(&paintCopy, clip, text, 0, bytesCount, count, x, y,
- positions, hasActiveLayer ? &bounds : NULL, &functor);
+ positions, hasActiveLayer ? &bounds : NULL, &functor, forceFinish);
} else {
status = fontRenderer.renderPosText(paint, clip, text, 0, bytesCount, count, x, y,
- positions, hasActiveLayer ? &bounds : NULL, &functor);
+ positions, hasActiveLayer ? &bounds : NULL, &functor, forceFinish);
}
- if (status && hasActiveLayer) {
+ if ((status || drawOpMode != kDrawOpMode_Immediate) && hasActiveLayer) {
if (!pureTranslate) {
transform.mapRect(bounds);
}
@@ -3089,7 +3142,11 @@ void OpenGLRenderer::setupShadow(float radius, float dx, float dy, int color) {
///////////////////////////////////////////////////////////////////////////////
void OpenGLRenderer::resetPaintFilter() {
+ // when clearing the PaintFilter, the masks should also be cleared for simple DrawModifier
+ // comparison, see MergingDrawBatch::canMergeWith
mDrawModifiers.mHasDrawFilter = false;
+ mDrawModifiers.mPaintFilterClearBits = 0;
+ mDrawModifiers.mPaintFilterSetBits = 0;
}
void OpenGLRenderer::setupPaintFilter(int clearBits, int setBits) {
@@ -3361,7 +3418,7 @@ void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float b
void OpenGLRenderer::drawAlpha8TextureMesh(float left, float top, float right, float bottom,
GLuint texture, bool hasColor, int color, int alpha, SkXfermode::Mode mode,
GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
- bool ignoreTransform, bool dirty) {
+ bool ignoreTransform, bool ignoreScale, bool dirty) {
setupDraw();
setupDrawWithTexture(true);
@@ -3373,7 +3430,11 @@ void OpenGLRenderer::drawAlpha8TextureMesh(float left, float top, float right, f
setupDrawBlending(true, mode);
setupDrawProgram();
if (!dirty) setupDrawDirtyRegionsDisabled();
- setupDrawModelView(left, top, right, bottom, ignoreTransform);
+ if (!ignoreScale) {
+ setupDrawModelView(left, top, right, bottom, ignoreTransform);
+ } else {
+ setupDrawModelViewTranslate(left, top, right, bottom, ignoreTransform);
+ }
setupDrawTexture(texture);
setupDrawPureColorUniforms();
setupDrawColorFilterUniforms();