.build();
renderer.renderGlop(state, glop);
}
+ GL_CHECKPOINT();
renderer.renderState().layerPool().putOrDelete(*op.layerHandle);
+ GL_CHECKPOINT();
}
} // namespace uirenderer
// 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");
+ LOG_ALWAYS_FATAL_IF(GLUtils::dumpGLErrors(), "endLayer FAILED, bound fbo = %u",
+ mRenderState.getFramebuffer());
mRenderState.deleteFramebuffer(mRenderTarget.frameBufferId);
mRenderTarget.frameBufferId = 0;
}
#include "DisplayList.h"
#include "LayerBuilder.h"
#include "RecordedOp.h"
+#include "utils/GLUtils.h"
#include <vector>
#include <unordered_map>
// Relay through layers in reverse order, since layers
// later in the list will be drawn by earlier ones
for (int i = mLayerBuilders.size() - 1; i >= 1; i--) {
+ GL_CHECKPOINT();
LayerBuilder& layer = *(mLayerBuilders[i]);
if (layer.renderNode) {
// cached HW layer - can't skip layer if empty
renderer.startRepaintLayer(layer.offscreenBuffer, layer.repaintRect);
+ GL_CHECKPOINT();
layer.replayBakedOpsImpl((void*)&renderer, unmergedReceivers, mergedReceivers);
+ GL_CHECKPOINT();
renderer.endLayer();
} else if (!layer.empty()) { // save layer - skip entire layer if empty
layer.offscreenBuffer = renderer.startTemporaryLayer(layer.width, layer.height);
+ GL_CHECKPOINT();
layer.replayBakedOpsImpl((void*)&renderer, unmergedReceivers, mergedReceivers);
+ GL_CHECKPOINT();
renderer.endLayer();
}
}
+ GL_CHECKPOINT();
const LayerBuilder& fbo0 = *(mLayerBuilders[0]);
renderer.startFrame(fbo0.width, fbo0.height, fbo0.repaintRect);
+ GL_CHECKPOINT();
fbo0.replayBakedOpsImpl((void*)&renderer, unmergedReceivers, mergedReceivers);
+ GL_CHECKPOINT();
renderer.endFrame(fbo0.repaintRect);
}
if (mUseFloatTexture) {
// We have to use GL_RGBA16F because GL_RGBA32F does not support filtering
- texture->upload(width, height, GL_RGBA16F, GL_RGBA, GL_FLOAT, pixels);
+ texture->upload(GL_RGBA16F, width, height, GL_RGBA, GL_FLOAT, pixels);
} else {
- texture->upload(width, height, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+ texture->upload(GL_RGBA, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
}
texture->setFilter(GL_LINEAR);
#include "Caches.h"
#include "Texture.h"
+#include "utils/GLUtils.h"
#include "utils/TraceUtils.h"
#include <utils/Log.h>
void Texture::upload(GLint internalformat, uint32_t width, uint32_t height,
GLenum format, GLenum type, const void* pixels) {
+ GL_CHECKPOINT();
bool needsAlloc = updateSize(width, height, internalformat);
if (!needsAlloc && !pixels) {
return;
}
mCaches.textureState().activateTexture(0);
+ GL_CHECKPOINT();
if (!mId) {
glGenTextures(1, &mId);
needsAlloc = true;
}
+ GL_CHECKPOINT();
mCaches.textureState().bindTexture(GL_TEXTURE_2D, mId);
+ GL_CHECKPOINT();
if (needsAlloc) {
glTexImage2D(GL_TEXTURE_2D, 0, mFormat, mWidth, mHeight, 0,
format, type, pixels);
+ GL_CHECKPOINT();
} else {
glTexSubImage2D(GL_TEXTURE_2D, 0, mFormat, mWidth, mHeight, 0,
format, type, pixels);
+ GL_CHECKPOINT();
}
}
const Glop::Mesh::Indices& indices = mesh.indices;
const Glop::Fill& fill = glop.fill;
+ GL_CHECKPOINT();
+
// ---------------------------------------------
// ---------- Program + uniform setup ----------
// ---------------------------------------------
roundedOutRadius);
}
+ GL_CHECKPOINT();
+
// --------------------------------
// ---------- Mesh setup ----------
// --------------------------------
// Shader uniforms
SkiaShader::apply(*mCaches, fill.skiaShaderData);
+ GL_CHECKPOINT();
+
// ------------------------------------
// ---------- GL state setup ----------
// ------------------------------------
blend().setFactors(glop.blend.src, glop.blend.dst);
+ GL_CHECKPOINT();
+
// ------------------------------------
// ---------- Actual drawing ----------
// ------------------------------------
glDrawArrays(mesh.primitiveMode, 0, mesh.elementCount);
}
+ GL_CHECKPOINT();
+
// -----------------------------------
// ---------- Mesh teardown ----------
// -----------------------------------
if (vertices.attribFlags & VertexAttribFlags::Color) {
glDisableVertexAttribArray(colorLocation);
}
+
+ GL_CHECKPOINT();
}
void RenderState::dump() {
#include "renderstate/RenderState.h"
#include "renderstate/Stencil.h"
#include "protos/hwui.pb.h"
+#include "utils/GLUtils.h"
#include "utils/TimeUtils.h"
#if HWUI_NEW_OPS
// node(s) are non client / filler nodes.
info.mode = (node.get() == target ? TreeInfo::MODE_FULL : TreeInfo::MODE_RT_ONLY);
node->prepareTree(info);
+ GL_CHECKPOINT();
}
mAnimationContext->runRemainingAnimations(info);
+ GL_CHECKPOINT();
freePrefetechedLayers();
+ GL_CHECKPOINT();
if (CC_UNLIKELY(!mNativeWindow.get())) {
mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
bool drew = mCanvas->finish();
#endif
+
+ GL_CHECKPOINT();
+
// Even if we decided to cancel the frame, from the perspective of jank
// metrics the frame was swapped at this point
mCurrentFrameInfo->markSwapBuffers();
#ifndef GLUTILS_H
#define GLUTILS_H
+#include <cutils/log.h>
+
namespace android {
namespace uirenderer {
+#if 0
+#define GL_CHECKPOINT() LOG_ALWAYS_FATAL_IF(GLUtils::dumpGLErrors(),\
+ "GL errors! %s:%d", __FILE__, __LINE__)
+#else
+#define GL_CHECKPOINT()
+#endif
+
class GLUtils {
public:
/**