summaryrefslogtreecommitdiffstats
path: root/libs/hwui
diff options
context:
space:
mode:
Diffstat (limited to 'libs/hwui')
-rw-r--r--libs/hwui/Caches.cpp7
-rw-r--r--libs/hwui/LayerRenderer.cpp4
-rw-r--r--libs/hwui/LayerRenderer.h1
-rw-r--r--libs/hwui/OpenGLRenderer.cpp110
-rw-r--r--libs/hwui/OpenGLRenderer.h36
-rw-r--r--libs/hwui/Program.cpp2
-rw-r--r--libs/hwui/ProgramCache.cpp16
7 files changed, 140 insertions, 36 deletions
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 1de0f9d..b149bb9 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -378,6 +378,9 @@ bool Caches::setScissor(GLint x, GLint y, GLint width, GLint height) {
if (scissorEnabled && (x != mScissorX || y != mScissorY ||
width != mScissorWidth || height != mScissorHeight)) {
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+
glScissor(x, y, width, height);
mScissorX = x;
@@ -426,13 +429,13 @@ void Caches::resetScissor() {
void Caches::startTiling(GLuint x, GLuint y, GLuint width, GLuint height, bool opaque) {
if (extensions.hasTiledRendering()) {
-
+ glStartTilingQCOM(x, y, width, height, GL_COLOR_BUFFER_BIT0_QCOM);
}
}
void Caches::endTiling() {
if (extensions.hasTiledRendering()) {
-
+ glEndTilingQCOM(GL_COLOR_BUFFER_BIT0_QCOM);
}
}
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index b57d806..5d59a4c 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -37,6 +37,10 @@ LayerRenderer::LayerRenderer(Layer* layer): mLayer(layer) {
LayerRenderer::~LayerRenderer() {
}
+void LayerRenderer::setViewport(int width, int height) {
+ initViewport(width, height);
+}
+
int LayerRenderer::prepareDirty(float left, float top, float right, float bottom, bool opaque) {
LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->getFbo());
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index 531aa5b..8d42f7f 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -47,6 +47,7 @@ public:
ANDROID_API LayerRenderer(Layer* layer);
virtual ~LayerRenderer();
+ virtual void setViewport(int width, int height);
virtual int prepareDirty(float left, float top, float right, float bottom, bool opaque);
virtual void finish();
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 4aefcba..9b9ca12 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -144,6 +144,15 @@ bool OpenGLRenderer::isDeferred() {
}
void OpenGLRenderer::setViewport(int width, int height) {
+ initViewport(width, height);
+
+ glDisable(GL_DITHER);
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+ glEnableVertexAttribArray(Program::kBindingPosition);
+}
+
+void OpenGLRenderer::initViewport(int width, int height) {
mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1);
mWidth = width;
@@ -151,11 +160,6 @@ void OpenGLRenderer::setViewport(int width, int height) {
mFirstSnapshot->height = height;
mFirstSnapshot->viewport.set(0, 0, width, height);
-
- glDisable(GL_DITHER);
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-
- glEnableVertexAttribArray(Program::kBindingPosition);
}
int OpenGLRenderer::prepare(bool opaque) {
@@ -171,7 +175,7 @@ int OpenGLRenderer::prepareDirty(float left, float top, float right, float botto
mSaveCount = 1;
mSnapshot->setClip(left, top, right, bottom);
- mDirtyClip = opaque;
+ mDirtyClip = mOpaqueFrame = opaque;
// If we know that we are going to redraw the entire framebuffer,
// perform a discard to let the driver know we don't need to preserve
@@ -184,6 +188,9 @@ int OpenGLRenderer::prepareDirty(float left, float top, float right, float botto
syncState();
+ mTilingSnapshot = mSnapshot;
+ startTiling();
+
if (!opaque) {
mCaches.enableScissor();
mCaches.setScissor(left, mSnapshot->height - bottom, right - left, bottom - top);
@@ -206,7 +213,30 @@ void OpenGLRenderer::syncState() {
}
}
+void OpenGLRenderer::startTiling() {
+ startTiling(mTilingSnapshot);
+}
+
+void OpenGLRenderer::startTiling(const sp<Snapshot>& s) {
+ bool opaque = mOpaqueFrame;
+ Rect* clip = mTilingSnapshot->clipRect;
+
+ if (s->flags & Snapshot::kFlagIsFboLayer) {
+ opaque = !s->layer->isBlend();
+ clip = s->clipRect;
+ }
+
+ mCaches.startTiling(clip->left, s->height - clip->bottom,
+ clip->right - clip->left, clip->bottom - clip->top, opaque);
+}
+
+void OpenGLRenderer::endTiling() {
+ mCaches.endTiling();
+}
+
void OpenGLRenderer::finish() {
+ endTiling();
+
#if DEBUG_OPENGL
GLenum status = GL_NO_ERROR;
while ((status = glGetError()) != GL_NO_ERROR) {
@@ -251,8 +281,9 @@ void OpenGLRenderer::interrupt() {
void OpenGLRenderer::resume() {
sp<Snapshot> snapshot = (mSnapshot != NULL) ? mSnapshot : mFirstSnapshot;
-
glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight());
+ glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo);
+
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
mCaches.scissorEnabled = glIsEnabled(GL_SCISSOR_TEST);
@@ -261,7 +292,6 @@ void OpenGLRenderer::resume() {
dirtyClip();
mCaches.activeTexture(0);
- glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo);
mCaches.blend = true;
glEnable(GL_BLEND);
@@ -269,6 +299,15 @@ void OpenGLRenderer::resume() {
glBlendEquation(GL_FUNC_ADD);
}
+void OpenGLRenderer::resumeAfterLayer() {
+ sp<Snapshot> snapshot = (mSnapshot != NULL) ? mSnapshot : mFirstSnapshot;
+ glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight());
+ glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo);
+
+ mCaches.resetScissor();
+ dirtyClip();
+}
+
void OpenGLRenderer::detachFunctor(Functor* functor) {
mFunctors.remove(functor);
}
@@ -624,6 +663,7 @@ bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, Rect& clip, GLui
mSnapshot->flags |= Snapshot::kFlagDirtyOrtho;
mSnapshot->orthoMatrix.load(mOrthoMatrix);
+ endTiling();
// Bind texture to FBO
glBindFramebuffer(GL_FRAMEBUFFER, layer->getFbo());
layer->bindTexture();
@@ -637,18 +677,7 @@ bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, Rect& clip, GLui
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
layer->getTexture(), 0);
-#if DEBUG_LAYERS_AS_REGIONS
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- ALOGE("Framebuffer incomplete (GL error code 0x%x)", status);
-
- glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
-
- Caches::getInstance().resourceCache.decrementRefcount(layer);
-
- return false;
- }
-#endif
+ startTiling(mSnapshot);
// Clear the FBO, expand the clear region by 1 to get nice bilinear filtering
mCaches.enableScissor();
@@ -677,11 +706,14 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) {
const bool fboLayer = current->flags & Snapshot::kFlagIsFboLayer;
if (fboLayer) {
+ endTiling();
+
// Detach the texture from the FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
-
// Unbind current FBO and restore previous one
glBindFramebuffer(GL_FRAMEBUFFER, previous->fbo);
+
+ startTiling(previous);
}
Layer* layer = current->layer;
@@ -1081,6 +1113,22 @@ bool OpenGLRenderer::quickRejectNoScissor(float left, float top, float right, fl
return !clipRect.intersects(r);
}
+bool OpenGLRenderer::quickRejectNoScissor(float left, float top, float right, float bottom,
+ Rect& transformed, Rect& clip) {
+ if (mSnapshot->isIgnored()) {
+ return true;
+ }
+
+ transformed.set(left, top, right, bottom);
+ mSnapshot->transform->mapRect(transformed);
+ transformed.snapToPixelBoundaries();
+
+ clip.set(*mSnapshot->clipRect);
+ clip.snapToPixelBoundaries();
+
+ return !clip.intersects(transformed);
+}
+
bool OpenGLRenderer::quickReject(float left, float top, float right, float bottom) {
if (mSnapshot->isIgnored()) {
return true;
@@ -2574,22 +2622,33 @@ status_t OpenGLRenderer::drawPath(SkPath* path, SkPaint* paint) {
}
status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
- if (!layer || quickReject(x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight())) {
+ if (!layer) {
return DrawGlInfo::kStatusDone;
}
- bool debugLayerUpdate = false;
+ Rect transformed;
+ Rect clip;
+ const bool rejected = quickRejectNoScissor(x, y,
+ x + layer->layer.getWidth(), y + layer->layer.getHeight(), transformed, clip);
+
+ if (rejected) {
+ return DrawGlInfo::kStatusDone;
+ }
+ bool debugLayerUpdate = false;
if (layer->deferredUpdateScheduled && layer->renderer && layer->displayList) {
OpenGLRenderer* renderer = layer->renderer;
Rect& dirty = layer->dirtyRect;
- interrupt();
+ endTiling();
+
renderer->setViewport(layer->layer.getWidth(), layer->layer.getHeight());
renderer->prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom, !layer->isBlend());
renderer->drawDisplayList(layer->displayList, dirty, DisplayList::kReplayFlag_ClipChildren);
renderer->finish();
- resume();
+
+ resumeAfterLayer();
+ startTiling(mSnapshot);
dirty.setEmpty();
layer->deferredUpdateScheduled = false;
@@ -2599,6 +2658,7 @@ status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* pain
debugLayerUpdate = mCaches.debugLayersUpdates;
}
+ mCaches.setScissorEnabled(!clip.contains(transformed));
mCaches.activeTexture(0);
if (CC_LIKELY(!layer->region.isEmpty())) {
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 7f9405f..10ba86e 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -255,6 +255,17 @@ public:
protected:
/**
+ * Computes the projection matrix, initialize the first snapshot
+ * and stores the dimensions of the render target.
+ */
+ void initViewport(int width, int height);
+
+ /**
+ * Call this method after updating a layer during a drawing pass.
+ */
+ void resumeAfterLayer();
+
+ /**
* Compose the layer defined in the current snapshot with the layer
* defined by the previous snapshot.
*
@@ -336,6 +347,20 @@ private:
void syncState();
/**
+ * Tells the GPU what part of the screen is about to be redrawn.
+ * This method needs to be invoked every time getTargetFbo() is
+ * bound again.
+ */
+ void startTiling();
+ void startTiling(const sp<Snapshot>& snapshot);
+
+ /**
+ * Tells the GPU that we are done drawing the frame or that we
+ * are switching to another render target.
+ */
+ void endTiling();
+
+ /**
* Saves the current state of the renderer as a new snapshot.
* The new snapshot is saved in mSnapshot and the previous snapshot
* is linked from mSnapshot->previous.
@@ -360,6 +385,13 @@ private:
void setScissorFromClip();
/**
+ * Performs a quick reject but does not affect the scissor. Returns
+ * the transformed rect to test and the current clip.
+ */
+ bool quickRejectNoScissor(float left, float top, float right, float bottom,
+ Rect& transformed, Rect& clip);
+
+ /**
* Creates a new layer stored in the specified snapshot.
*
* @param snapshot The snapshot associated with the new layer
@@ -717,6 +749,8 @@ private:
sp<Snapshot> mFirstSnapshot;
// Current state
sp<Snapshot> mSnapshot;
+ // State used to define the clipping region
+ sp<Snapshot> mTilingSnapshot;
// Shaders
SkiaShader* mShader;
@@ -766,6 +800,8 @@ private:
GLuint mTextureUnit;
// Track dirty regions, true by default
bool mTrackDirtyRegions;
+ // Indicate whether we are drawing an opaque frame
+ bool mOpaqueFrame;
friend class DisplayListRenderer;
diff --git a/libs/hwui/Program.cpp b/libs/hwui/Program.cpp
index 984461c..5b1b57d 100644
--- a/libs/hwui/Program.cpp
+++ b/libs/hwui/Program.cpp
@@ -178,7 +178,7 @@ void Program::setColor(const float r, const float g, const float b, const float
void Program::use() {
glUseProgram(mProgramId);
if (texCoords >= 0 && !mHasSampler) {
- glUniform1i(getUniform("sampler"), 0);
+ glUniform1i(getUniform("baseSampler"), 0);
mHasSampler = true;
}
mUse = true;
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index 6e7f35d..6baf448 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -231,10 +231,10 @@ const char* gFS_Fast_SingleGradient[2] = {
};
const char* gFS_Fast_SingleModulateGradient[2] = {
"\nvoid main(void) {\n"
- " gl_FragColor " FS_MAIN_DITHER " + color.a * texture2D(gradientSampler, linear);\n"
+ " gl_FragColor = " FS_MAIN_DITHER " + color.a * texture2D(gradientSampler, linear);\n"
"}\n\n",
"\nvoid main(void) {\n"
- " gl_FragColor " FS_MAIN_DITHER " + color.a * mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n"
+ " gl_FragColor = " FS_MAIN_DITHER " + color.a * mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n"
"}\n\n"
};
@@ -294,8 +294,8 @@ const char* gFS_Main_BlendShaders_Modulate[6] = {
";\n",
";\n",
// Modulate
- " * fragColor.a;\n",
- " * fragColor.a;\n",
+ " * color.a;\n",
+ " * color.a;\n",
// Modulate with alpha 8 texture
" * texture2D(baseSampler, outTexCoords).a;\n",
" * pow(texture2D(baseSampler, outTexCoords).a, gamma);\n"
@@ -305,8 +305,8 @@ const char* gFS_Main_GradientShader_Modulate[6] = {
" fragColor = gradientColor;\n",
" fragColor = gradientColor;\n",
// Modulate
- " fragColor = gradientColor * fragColor.a;\n",
- " fragColor = gradientColor * fragColor.a;\n",
+ " fragColor = gradientColor * color.a;\n",
+ " fragColor = gradientColor * color.a;\n",
// Modulate with alpha 8 texture
" fragColor = gradientColor * texture2D(baseSampler, outTexCoords).a;\n",
" fragColor = gradientColor * pow(texture2D(baseSampler, outTexCoords).a, gamma);\n"
@@ -316,8 +316,8 @@ const char* gFS_Main_BitmapShader_Modulate[6] = {
" fragColor = bitmapColor;\n",
" fragColor = bitmapColor;\n",
// Modulate
- " fragColor = bitmapColor * fragColor.a;\n",
- " fragColor = bitmapColor * fragColor.a;\n",
+ " fragColor = bitmapColor * color.a;\n",
+ " fragColor = bitmapColor * color.a;\n",
// Modulate with alpha 8 texture
" fragColor = bitmapColor * texture2D(baseSampler, outTexCoords).a;\n",
" fragColor = bitmapColor * pow(texture2D(baseSampler, outTexCoords).a, gamma);\n"