diff options
Diffstat (limited to 'libs/hwui')
| -rw-r--r-- | libs/hwui/Caches.cpp | 7 | ||||
| -rw-r--r-- | libs/hwui/LayerRenderer.cpp | 4 | ||||
| -rw-r--r-- | libs/hwui/LayerRenderer.h | 1 | ||||
| -rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 110 | ||||
| -rw-r--r-- | libs/hwui/OpenGLRenderer.h | 36 | ||||
| -rw-r--r-- | libs/hwui/Program.cpp | 2 | ||||
| -rw-r--r-- | libs/hwui/ProgramCache.cpp | 16 |
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" |
