2015-10-05 13:00:52 -07:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2015 The Android Open Source Project
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "BakedOpRenderer.h"
|
|
|
|
|
|
|
|
#include "Caches.h"
|
|
|
|
#include "Glop.h"
|
|
|
|
#include "GlopBuilder.h"
|
2015-11-11 16:42:34 -08:00
|
|
|
#include "renderstate/OffscreenBufferPool.h"
|
2015-10-05 13:00:52 -07:00
|
|
|
#include "renderstate/RenderState.h"
|
|
|
|
#include "utils/GLUtils.h"
|
2015-11-11 16:42:34 -08:00
|
|
|
#include "VertexBuffer.h"
|
2015-10-05 13:00:52 -07:00
|
|
|
|
2015-11-19 13:02:43 -08:00
|
|
|
#include <algorithm>
|
|
|
|
|
2015-10-05 13:00:52 -07:00
|
|
|
namespace android {
|
|
|
|
namespace uirenderer {
|
|
|
|
|
2015-11-06 10:59:56 -08:00
|
|
|
OffscreenBuffer* BakedOpRenderer::startTemporaryLayer(uint32_t width, uint32_t height) {
|
2015-11-11 16:42:34 -08:00
|
|
|
LOG_ALWAYS_FATAL_IF(mRenderTarget.offscreenBuffer, "already has layer...");
|
|
|
|
|
|
|
|
OffscreenBuffer* buffer = mRenderState.layerPool().get(mRenderState, width, height);
|
2015-11-13 10:55:30 -08:00
|
|
|
startRepaintLayer(buffer, Rect(width, height));
|
2015-10-28 16:50:44 -07:00
|
|
|
return buffer;
|
|
|
|
}
|
|
|
|
|
2015-11-13 10:55:30 -08:00
|
|
|
void BakedOpRenderer::startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) {
|
2015-11-06 10:59:56 -08:00
|
|
|
LOG_ALWAYS_FATAL_IF(mRenderTarget.offscreenBuffer, "already has layer...");
|
|
|
|
|
2015-10-28 16:50:44 -07:00
|
|
|
mRenderTarget.offscreenBuffer = offscreenBuffer;
|
2015-10-23 14:33:42 -07:00
|
|
|
|
2015-10-26 15:49:56 -07:00
|
|
|
// create and bind framebuffer
|
|
|
|
mRenderTarget.frameBufferId = mRenderState.genFramebuffer();
|
|
|
|
mRenderState.bindFramebuffer(mRenderTarget.frameBufferId);
|
2015-10-23 14:33:42 -07:00
|
|
|
|
|
|
|
// attach the texture to the FBO
|
|
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
|
2015-10-28 16:50:44 -07:00
|
|
|
offscreenBuffer->texture.id, 0);
|
2015-10-23 14:33:42 -07:00
|
|
|
LOG_ALWAYS_FATAL_IF(GLUtils::dumpGLErrors(), "startLayer FAILED");
|
|
|
|
LOG_ALWAYS_FATAL_IF(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE,
|
|
|
|
"framebuffer incomplete!");
|
|
|
|
|
|
|
|
// Change the viewport & ortho projection
|
2015-10-28 16:50:44 -07:00
|
|
|
setViewport(offscreenBuffer->viewportWidth, offscreenBuffer->viewportHeight);
|
2015-11-13 10:55:30 -08:00
|
|
|
|
|
|
|
clearColorBuffer(repaintRect);
|
2015-10-23 14:33:42 -07:00
|
|
|
}
|
|
|
|
|
2015-10-26 15:49:56 -07:00
|
|
|
void BakedOpRenderer::endLayer() {
|
2015-11-02 14:52:21 -08:00
|
|
|
mRenderTarget.offscreenBuffer->updateMeshFromRegion();
|
2015-10-26 15:49:56 -07:00
|
|
|
mRenderTarget.offscreenBuffer = nullptr;
|
2015-10-23 14:33:42 -07:00
|
|
|
|
|
|
|
// Detach the texture from the FBO
|
|
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
|
|
|
|
LOG_ALWAYS_FATAL_IF(GLUtils::dumpGLErrors(), "endLayer FAILED");
|
2015-10-26 15:49:56 -07:00
|
|
|
mRenderState.deleteFramebuffer(mRenderTarget.frameBufferId);
|
|
|
|
mRenderTarget.frameBufferId = -1;
|
2015-10-23 14:33:42 -07:00
|
|
|
}
|
|
|
|
|
2015-11-13 10:55:30 -08:00
|
|
|
void BakedOpRenderer::startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) {
|
2015-10-26 15:49:56 -07:00
|
|
|
mRenderState.bindFramebuffer(0);
|
|
|
|
setViewport(width, height);
|
|
|
|
mCaches.clearGarbage();
|
2015-10-05 13:00:52 -07:00
|
|
|
|
2015-10-26 15:49:56 -07:00
|
|
|
if (!mOpaque) {
|
2015-11-13 10:55:30 -08:00
|
|
|
clearColorBuffer(repaintRect);
|
2015-10-05 13:00:52 -07:00
|
|
|
}
|
|
|
|
}
|
2015-10-26 15:49:56 -07:00
|
|
|
|
|
|
|
void BakedOpRenderer::endFrame() {
|
|
|
|
mCaches.pathCache.trim();
|
|
|
|
mCaches.tessellationCache.trim();
|
2015-10-05 13:00:52 -07:00
|
|
|
|
|
|
|
#if DEBUG_OPENGL
|
|
|
|
GLUtils::dumpGLErrors();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if DEBUG_MEMORY_USAGE
|
2015-10-26 15:49:56 -07:00
|
|
|
mCaches.dumpMemoryUsage();
|
2015-10-05 13:00:52 -07:00
|
|
|
#else
|
|
|
|
if (Properties::debugLevel & kDebugMemory) {
|
2015-10-26 15:49:56 -07:00
|
|
|
mCaches.dumpMemoryUsage();
|
2015-10-05 13:00:52 -07:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-10-26 15:49:56 -07:00
|
|
|
void BakedOpRenderer::setViewport(uint32_t width, uint32_t height) {
|
|
|
|
mRenderTarget.viewportWidth = width;
|
|
|
|
mRenderTarget.viewportHeight = height;
|
|
|
|
mRenderTarget.orthoMatrix.loadOrtho(width, height);
|
|
|
|
|
|
|
|
mRenderState.setViewport(width, height);
|
|
|
|
mRenderState.blend().syncEnabled();
|
|
|
|
}
|
|
|
|
|
2015-11-13 10:55:30 -08:00
|
|
|
void BakedOpRenderer::clearColorBuffer(const Rect& rect) {
|
|
|
|
if (Rect(mRenderTarget.viewportWidth, mRenderTarget.viewportHeight).contains(rect)) {
|
|
|
|
// Full viewport is being cleared - disable scissor
|
|
|
|
mRenderState.scissor().setEnabled(false);
|
|
|
|
} else {
|
|
|
|
// Requested rect is subset of viewport - scissor to it to avoid over-clearing
|
|
|
|
mRenderState.scissor().setEnabled(true);
|
|
|
|
mRenderState.scissor().set(rect.left, mRenderTarget.viewportHeight - rect.bottom,
|
|
|
|
rect.getWidth(), rect.getHeight());
|
|
|
|
}
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
|
|
if (!mRenderTarget.frameBufferId) mHasDrawn = true;
|
|
|
|
}
|
|
|
|
|
2015-10-26 15:49:56 -07:00
|
|
|
Texture* BakedOpRenderer::getTexture(const SkBitmap* bitmap) {
|
2015-12-03 12:16:56 -08:00
|
|
|
Texture* texture = mRenderState.assetAtlas().getEntryTexture(bitmap->pixelRef());
|
2015-10-26 15:49:56 -07:00
|
|
|
if (!texture) {
|
|
|
|
return mCaches.textureCache.get(bitmap);
|
|
|
|
}
|
|
|
|
return texture;
|
|
|
|
}
|
|
|
|
|
2015-12-10 16:25:13 -08:00
|
|
|
void BakedOpRenderer::prepareRender(const Rect* dirtyBounds, const Rect* clip) {
|
2015-12-03 12:16:56 -08:00
|
|
|
mRenderState.scissor().setEnabled(clip != nullptr);
|
|
|
|
if (clip) {
|
|
|
|
mRenderState.scissor().set(clip->left, mRenderTarget.viewportHeight - clip->bottom,
|
|
|
|
clip->getWidth(), clip->getHeight());
|
2015-10-26 15:49:56 -07:00
|
|
|
}
|
2015-12-03 12:16:56 -08:00
|
|
|
if (dirtyBounds && mRenderTarget.offscreenBuffer) {
|
2015-11-02 14:52:21 -08:00
|
|
|
// register layer damage to draw-back region
|
2015-12-03 12:16:56 -08:00
|
|
|
android::Rect dirty(dirtyBounds->left, dirtyBounds->top,
|
|
|
|
dirtyBounds->right, dirtyBounds->bottom);
|
2015-11-02 14:52:21 -08:00
|
|
|
mRenderTarget.offscreenBuffer->region.orSelf(dirty);
|
|
|
|
}
|
2015-12-10 16:25:13 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
void BakedOpRenderer::renderGlop(const Rect* dirtyBounds, const Rect* clip, const Glop& glop) {
|
|
|
|
prepareRender(dirtyBounds, clip);
|
2015-10-26 15:49:56 -07:00
|
|
|
mRenderState.render(glop, mRenderTarget.orthoMatrix);
|
2015-11-13 10:55:30 -08:00
|
|
|
if (!mRenderTarget.frameBufferId) mHasDrawn = true;
|
2015-10-26 15:49:56 -07:00
|
|
|
}
|
|
|
|
|
2015-12-10 16:25:13 -08:00
|
|
|
void BakedOpRenderer::renderFunctor(const FunctorOp& op, const BakedOpState& state) {
|
|
|
|
prepareRender(&state.computedState.clippedBounds, &state.computedState.clipRect);
|
|
|
|
|
|
|
|
DrawGlInfo info;
|
|
|
|
auto&& clip = state.computedState.clipRect;
|
|
|
|
info.clipLeft = clip.left;
|
|
|
|
info.clipTop = clip.top;
|
|
|
|
info.clipRight = clip.right;
|
|
|
|
info.clipBottom = clip.bottom;
|
|
|
|
info.isLayer = offscreenRenderTarget();
|
|
|
|
info.width = mRenderTarget.viewportWidth;
|
|
|
|
info.height = mRenderTarget.viewportHeight;
|
|
|
|
state.computedState.transform.copyTo(&info.transform[0]);
|
|
|
|
|
|
|
|
mRenderState.invokeFunctor(op.functor, DrawGlInfo::kModeDraw, &info);
|
|
|
|
}
|
|
|
|
|
2015-12-03 12:16:56 -08:00
|
|
|
void BakedOpRenderer::dirtyRenderTarget(const Rect& uiDirty) {
|
|
|
|
if (mRenderTarget.offscreenBuffer) {
|
|
|
|
android::Rect dirty(uiDirty.left, uiDirty.top, uiDirty.right, uiDirty.bottom);
|
|
|
|
mRenderTarget.offscreenBuffer->region.orSelf(dirty);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-05 13:00:52 -07:00
|
|
|
} // namespace uirenderer
|
|
|
|
} // namespace android
|