Revert "Use renderengine::drawLayers api everywhere."
This reverts commit 0f7148365cfa405e8ed802b33c0e2a7b790fcf42.
Reason for revert: b/123878751, preparing while i investigate
Bug: 123878751
Test: bug no longer repros
Change-Id: I6c77427f0c113f96b68aec479ccec52b0bbb2c6b
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index cf2b80c..96496f0 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-//#define LOG_NDEBUG 0
+// #define LOG_NDEBUG 0
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include <sys/types.h>
@@ -1873,13 +1873,16 @@
if (displayState.isEnabled) {
// transform the dirty region into this screen's coordinate space
- const Region dirtyRegion = display->getDirtyRegion(repaintEverything);
+ const Region dirtyRegion = display->getPhysicalSpaceDirtyRegion(repaintEverything);
if (!dirtyRegion.isEmpty()) {
- base::unique_fd readyFence;
// redraw the whole screen
- doComposeSurfaces(displayDevice, dirtyRegion, &readyFence);
+ doComposeSurfaces(displayDevice);
- display->getRenderSurface()->queueBuffer(std::move(readyFence));
+ // and draw the dirty region
+ auto& engine(getRenderEngine());
+ engine.fillRegionWithColor(dirtyRegion, 1, 0, 1, 1);
+
+ display->getRenderSurface()->queueBuffer();
}
}
@@ -2414,7 +2417,7 @@
auto display = displayDevice->getCompositionDisplay();
const auto& displayState = display->getState();
- bool dirty = !display->getDirtyRegion(false).isEmpty();
+ bool dirty = !display->getPhysicalSpaceDirtyRegion(false).isEmpty();
bool empty = displayDevice->getVisibleLayersSortedByZ().size() == 0;
bool wasEmpty = !displayState.lastCompositionHadVisibleLayers;
@@ -2465,7 +2468,7 @@
if (displayState.isEnabled) {
// transform the dirty region into this screen's coordinate space
- const Region dirtyRegion = display->getDirtyRegion(repaintEverything);
+ const Region dirtyRegion = display->getPhysicalSpaceDirtyRegion(repaintEverything);
// repaint the framebuffer (if needed)
doDisplayComposition(displayDevice, dirtyRegion);
@@ -3350,15 +3353,13 @@
}
ALOGV("doDisplayComposition");
- base::unique_fd readyFence;
- if (!doComposeSurfaces(displayDevice, Region::INVALID_REGION, &readyFence)) return;
+ if (!doComposeSurfaces(displayDevice)) return;
// swap buffers (presentation)
- display->getRenderSurface()->queueBuffer(std::move(readyFence));
+ display->getRenderSurface()->queueBuffer();
}
-bool SurfaceFlinger::doComposeSurfaces(const sp<DisplayDevice>& displayDevice,
- const Region& debugRegion, base::unique_fd* readyFence) {
+bool SurfaceFlinger::doComposeSurfaces(const sp<DisplayDevice>& displayDevice) {
ALOGV("doComposeSurfaces");
auto display = displayDevice->getCompositionDisplay();
@@ -3373,14 +3374,13 @@
mat4 colorMatrix;
bool applyColorMatrix = false;
- renderengine::DisplaySettings clientCompositionDisplay;
- std::vector<renderengine::LayerSettings> clientCompositionLayers;
- sp<GraphicBuffer> buf;
+ // Framebuffer will live in this scope for GPU composition.
+ std::unique_ptr<renderengine::BindNativeBufferAsFramebuffer> fbo;
if (hasClientComposition) {
ALOGV("hasClientComposition");
- buf = display->getRenderSurface()->dequeueBuffer();
+ sp<GraphicBuffer> buf = display->getRenderSurface()->dequeueBuffer();
if (buf == nullptr) {
ALOGW("Dequeuing buffer for display [%s] failed, bailing out of "
@@ -3389,30 +3389,24 @@
return false;
}
- clientCompositionDisplay.physicalDisplay = displayState.scissor;
- clientCompositionDisplay.clip = displayState.scissor;
- const ui::Transform& displayTransform = displayState.transform;
- mat4 m;
- m[0][0] = displayTransform[0][0];
- m[0][1] = displayTransform[0][1];
- m[0][3] = displayTransform[0][2];
- m[1][0] = displayTransform[1][0];
- m[1][1] = displayTransform[1][1];
- m[1][3] = displayTransform[1][2];
- m[3][0] = displayTransform[2][0];
- m[3][1] = displayTransform[2][1];
- m[3][3] = displayTransform[2][2];
+ // Bind the framebuffer in this scope.
+ fbo = std::make_unique<renderengine::BindNativeBufferAsFramebuffer>(getRenderEngine(),
+ buf->getNativeBuffer());
- clientCompositionDisplay.globalTransform = m;
+ if (fbo->getStatus() != NO_ERROR) {
+ ALOGW("Binding buffer for display [%s] failed with status: %d",
+ displayDevice->getDisplayName().c_str(), fbo->getStatus());
+ return false;
+ }
const auto* profile = display->getDisplayColorProfile();
Dataspace outputDataspace = Dataspace::UNKNOWN;
if (profile->hasWideColorGamut()) {
outputDataspace = displayState.dataspace;
}
- clientCompositionDisplay.outputDataspace = outputDataspace;
- clientCompositionDisplay.maxLuminance =
- profile->getHdrCapabilities().getDesiredMaxLuminance();
+ getRenderEngine().setOutputDataSpace(outputDataspace);
+ getRenderEngine().setDisplayMaxLuminance(
+ profile->getHdrCapabilities().getDesiredMaxLuminance());
const bool hasDeviceComposition = getHwComposer().hasDeviceComposition(displayId);
const bool skipClientColorTransform =
@@ -3423,7 +3417,44 @@
// Compute the global color transform matrix.
applyColorMatrix = !hasDeviceComposition && !skipClientColorTransform;
if (applyColorMatrix) {
- clientCompositionDisplay.colorTransform = colorMatrix;
+ colorMatrix = mDrawingState.colorMatrix;
+ }
+
+ display->getRenderSurface()->setViewportAndProjection();
+
+ // Never touch the framebuffer if we don't have any framebuffer layers
+ if (hasDeviceComposition) {
+ // when using overlays, we assume a fully transparent framebuffer
+ // NOTE: we could reduce how much we need to clear, for instance
+ // remove where there are opaque FB layers. however, on some
+ // GPUs doing a "clean slate" clear might be more efficient.
+ // We'll revisit later if needed.
+ getRenderEngine().clearWithColor(0, 0, 0, 0);
+ } else {
+ // we start with the whole screen area and remove the scissor part
+ // we're left with the letterbox region
+ // (common case is that letterbox ends-up being empty)
+ const Region letterbox = bounds.subtract(displayState.scissor);
+
+ // compute the area to clear
+ const Region region = displayState.undefinedRegion.merge(letterbox);
+
+ // screen is already cleared here
+ if (!region.isEmpty()) {
+ // can happen with SurfaceView
+ drawWormhole(region);
+ }
+ }
+
+ const Rect& bounds = displayState.bounds;
+ const Rect& scissor = displayState.scissor;
+ if (scissor != bounds) {
+ // scissor doesn't match the screen's dimensions, so we
+ // need to clear everything outside of it and enable
+ // the GL scissor so we don't draw anything where we shouldn't
+
+ // enable scissor for this frame
+ getRenderEngine().setScissor(scissor);
}
}
@@ -3432,11 +3463,10 @@
*/
ALOGV("Rendering client layers");
+ const ui::Transform& displayTransform = displayState.transform;
bool firstLayer = true;
- Region clearRegion = Region::INVALID_REGION;
for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
- const Region viewportRegion(displayState.viewport);
- const Region clip(viewportRegion.intersect(layer->visibleRegion));
+ const Region clip(bounds.intersect(displayTransform.transform(layer->visibleRegion)));
ALOGV("Layer: %s", layer->getName().string());
ALOGV(" Composition type: %s", to_string(layer->getCompositionType(displayId)).c_str());
if (!clip.isEmpty()) {
@@ -3452,28 +3482,22 @@
layer->getRoundedCornerState().radius == 0.0f && hasClientComposition) {
// never clear the very first layer since we're
// guaranteed the FB is already cleared
- renderengine::LayerSettings layerSettings;
- Region dummyRegion;
- bool prepared = layer->prepareClientLayer(renderArea, clip, dummyRegion,
- layerSettings);
-
- if (prepared) {
- layerSettings.source.buffer.buffer = nullptr;
- layerSettings.source.solidColor = half3(0.0, 0.0, 0.0);
- layerSettings.alpha = half(0.0);
- layerSettings.disableBlending = true;
- clientCompositionLayers.push_back(layerSettings);
- }
+ layer->clearWithOpenGL(renderArea);
}
break;
}
case HWC2::Composition::Client: {
- renderengine::LayerSettings layerSettings;
- bool prepared =
- layer->prepareClientLayer(renderArea, clip, clearRegion, layerSettings);
- if (prepared) {
- clientCompositionLayers.push_back(layerSettings);
+ if (layer->hasColorTransform()) {
+ mat4 tmpMatrix;
+ if (applyColorMatrix) {
+ tmpMatrix = mDrawingState.colorMatrix;
+ }
+ tmpMatrix *= layer->getColorTransform();
+ getRenderEngine().setColorTransform(tmpMatrix);
+ } else {
+ getRenderEngine().setColorTransform(colorMatrix);
}
+ layer->draw(renderArea, clip);
break;
}
default:
@@ -3485,23 +3509,14 @@
firstLayer = false;
}
+ // Perform some cleanup steps if we used client composition.
if (hasClientComposition) {
- clientCompositionDisplay.clearRegion = clearRegion;
- if (!debugRegion.isEmpty()) {
- Region::const_iterator it = debugRegion.begin();
- Region::const_iterator end = debugRegion.end();
- while (it != end) {
- const Rect& rect = *it++;
- renderengine::LayerSettings layerSettings;
- layerSettings.source.buffer.buffer = nullptr;
- layerSettings.source.solidColor = half3(1.0, 0.0, 1.0);
- layerSettings.geometry.boundaries = rect.toFloatRect();
- layerSettings.alpha = half(1.0);
- clientCompositionLayers.push_back(layerSettings);
- }
- }
- getRenderEngine().drawLayers(clientCompositionDisplay, clientCompositionLayers,
- buf->getNativeBuffer(), readyFence);
+ getRenderEngine().setColorTransform(mat4());
+ getRenderEngine().disableScissor();
+ display->getRenderSurface()->finishBuffer();
+ // Clear out error flags here so that we don't wait until next
+ // composition to log.
+ getRenderEngine().checkErrors();
}
return true;
}
@@ -5631,109 +5646,35 @@
void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea,
TraverseLayersFunction traverseLayers,
- ANativeWindowBuffer* buffer, bool useIdentityTransform,
- int* outSyncFd) {
+ bool useIdentityTransform) {
ATRACE_CALL();
+ auto& engine(getRenderEngine());
+
const auto reqWidth = renderArea.getReqWidth();
const auto reqHeight = renderArea.getReqHeight();
const auto sourceCrop = renderArea.getSourceCrop();
const auto rotation = renderArea.getRotationFlags();
- renderengine::DisplaySettings clientCompositionDisplay;
- std::vector<renderengine::LayerSettings> clientCompositionLayers;
+ engine.setOutputDataSpace(renderArea.getReqDataSpace());
+ engine.setDisplayMaxLuminance(DisplayDevice::sDefaultMaxLumiance);
- // assume that bounds are never offset, and that they are the same as the
- // buffer bounds.
- clientCompositionDisplay.physicalDisplay = Rect(reqWidth, reqHeight);
- ui::Transform transform = renderArea.getTransform();
- mat4 m;
- m[0][0] = transform[0][0];
- m[0][1] = transform[0][1];
- m[0][3] = transform[0][2];
- m[1][0] = transform[1][0];
- m[1][1] = transform[1][1];
- m[1][3] = transform[1][2];
- m[3][0] = transform[2][0];
- m[3][1] = transform[2][1];
- m[3][3] = transform[2][2];
+ // make sure to clear all GL error flags
+ engine.checkErrors();
- clientCompositionDisplay.globalTransform = m;
- mat4 rotMatrix;
- // Displacement for repositioning the clipping rectangle after rotating it
- // with the rotation hint.
- int displacementX = 0;
- int displacementY = 0;
- float rot90InRadians = 2.0f * static_cast<float>(M_PI) / 4.0f;
- switch (rotation) {
- case ui::Transform::ROT_90:
- rotMatrix = mat4::rotate(rot90InRadians, vec3(0, 0, 1));
- displacementX = reqWidth;
- break;
- case ui::Transform::ROT_180:
- rotMatrix = mat4::rotate(rot90InRadians * 2.0f, vec3(0, 0, 1));
- displacementX = reqWidth;
- displacementY = reqHeight;
- break;
- case ui::Transform::ROT_270:
- rotMatrix = mat4::rotate(rot90InRadians * 3.0f, vec3(0, 0, 1));
- displacementY = reqHeight;
- break;
- default:
- break;
- }
- // We need to transform the clipping window into the right spot.
- // First, rotate the clipping rectangle by the rotation hint to get the
- // right orientation
- const vec4 clipTL = vec4(sourceCrop.left, sourceCrop.top, 0, 1);
- const vec4 clipBR = vec4(sourceCrop.right, sourceCrop.bottom, 0, 1);
- const vec4 rotClipTL = rotMatrix * clipTL;
- const vec4 rotClipBR = rotMatrix * clipBR;
- const int newClipLeft = std::min(rotClipTL[0], rotClipBR[0]);
- const int newClipTop = std::min(rotClipTL[1], rotClipBR[1]);
- const int newClipRight = std::max(rotClipTL[0], rotClipBR[0]);
- const int newClipBottom = std::max(rotClipTL[1], rotClipBR[1]);
-
- // Now reposition the clipping rectangle with the displacement vector
- // computed above.
- const mat4 displacementMat = mat4::translate(vec4(displacementX, displacementY, 0, 1));
-
- clientCompositionDisplay.clip =
- Rect(newClipLeft + displacementX, newClipTop + displacementY,
- newClipRight + displacementX, newClipBottom + displacementY);
-
- // We need to perform the same transformation in layer space, so propagate
- // it to the global transform.
- mat4 clipTransform = displacementMat * rotMatrix;
- clientCompositionDisplay.globalTransform *= clipTransform;
- clientCompositionDisplay.outputDataspace = renderArea.getReqDataSpace();
- clientCompositionDisplay.maxLuminance = DisplayDevice::sDefaultMaxLumiance;
+ // set-up our viewport
+ engine.setViewportAndProjection(reqWidth, reqHeight, sourceCrop, rotation);
+ engine.disableTexturing();
const float alpha = RenderArea::getCaptureFillValue(renderArea.getCaptureFill());
+ // redraw the screen entirely...
+ engine.clearWithColor(0, 0, 0, alpha);
- renderengine::LayerSettings fillLayer;
- fillLayer.source.buffer.buffer = nullptr;
- fillLayer.source.solidColor = half3(0.0, 0.0, 0.0);
- fillLayer.geometry.boundaries = FloatRect(0.0, 0.0, 1.0, 1.0);
- fillLayer.alpha = half(alpha);
- clientCompositionLayers.push_back(fillLayer);
-
- Region clearRegion = Region::INVALID_REGION;
traverseLayers([&](Layer* layer) {
- renderengine::LayerSettings layerSettings;
- bool prepared = layer->prepareClientLayer(renderArea, useIdentityTransform, clearRegion,
- layerSettings);
- if (prepared) {
- clientCompositionLayers.push_back(layerSettings);
- }
+ engine.setColorTransform(layer->getColorTransform());
+ layer->draw(renderArea, useIdentityTransform);
+ engine.setColorTransform(mat4());
});
-
- clientCompositionDisplay.clearRegion = clearRegion;
- base::unique_fd drawFence;
- getRenderEngine().drawLayers(clientCompositionDisplay, clientCompositionLayers, buffer,
- &drawFence);
-
- *outSyncFd = drawFence.release();
}
status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea,
@@ -5757,7 +5698,28 @@
ALOGW("FB is protected: PERMISSION_DENIED");
return PERMISSION_DENIED;
}
- renderScreenImplLocked(renderArea, traverseLayers, buffer, useIdentityTransform, outSyncFd);
+ auto& engine(getRenderEngine());
+
+ // this binds the given EGLImage as a framebuffer for the
+ // duration of this scope.
+ renderengine::BindNativeBufferAsFramebuffer bufferBond(engine, buffer);
+ if (bufferBond.getStatus() != NO_ERROR) {
+ ALOGE("got ANWB binding error while taking screenshot");
+ return INVALID_OPERATION;
+ }
+
+ // this will in fact render into our dequeued buffer
+ // via an FBO, which means we didn't have to create
+ // an EGLSurface and therefore we're not
+ // dependent on the context's EGLConfig.
+ renderScreenImplLocked(renderArea, traverseLayers, useIdentityTransform);
+
+ base::unique_fd syncFd = engine.flush();
+ if (syncFd < 0) {
+ engine.finish();
+ }
+ *outSyncFd = syncFd.release();
+
return NO_ERROR;
}