Skip to content
20 changes: 14 additions & 6 deletions libs/gui/BufferQueueProducer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -921,7 +921,11 @@ status_t BufferQueueProducer::queueBuffer(int slot,

// Call back without the main BufferQueue lock held, but with the callback
// lock held so we can ensure that callbacks occur in order
{

int connectedApi;
sp<Fence> lastQueuedFence;

{ // scope for the lock
Mutex::Autolock lock(mCallbackMutex);
while (callbackTicket != mCurrentCallbackTicket) {
mCallbackCondition.wait(mCallbackMutex);
Expand All @@ -933,20 +937,24 @@ status_t BufferQueueProducer::queueBuffer(int slot,
frameReplacedListener->onFrameReplaced(item);
}

connectedApi = mCore->mConnectedApi;
lastQueuedFence = std::move(mLastQueueBufferFence);

mLastQueueBufferFence = std::move(fence);
mLastQueuedCrop = item.mCrop;
mLastQueuedTransform = item.mTransform;

++mCurrentCallbackTicket;
mCallbackCondition.broadcast();
}

// Wait without lock held
if (mCore->mConnectedApi == NATIVE_WINDOW_API_EGL) {
if (connectedApi == NATIVE_WINDOW_API_EGL) {
// Waiting here allows for two full buffers to be queued but not a
// third. In the event that frames take varying time, this makes a
// small trade-off in favor of latency rather than throughput.
mLastQueueBufferFence->waitForever("Throttling EGL Production");
lastQueuedFence->waitForever("Throttling EGL Production");
}
mLastQueueBufferFence = fence;
mLastQueuedCrop = item.mCrop;
mLastQueuedTransform = item.mTransform;

return NO_ERROR;
}
Expand Down
15 changes: 9 additions & 6 deletions libs/gui/Surface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1178,7 +1178,8 @@ void Surface::setSurfaceDamage(android_native_rect_t* rects, size_t numRects) {
static status_t copyBlt(
const sp<GraphicBuffer>& dst,
const sp<GraphicBuffer>& src,
const Region& reg)
const Region& reg,
int *dstFenceFd)
{
// src and dst with, height and format must be identical. no verification
// is done here.
Expand All @@ -1189,9 +1190,10 @@ static status_t copyBlt(
ALOGE_IF(err, "error locking src buffer %s", strerror(-err));

uint8_t* dst_bits = NULL;
err = dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(),
reinterpret_cast<void**>(&dst_bits));
err = dst->lockAsync(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(),
reinterpret_cast<void**>(&dst_bits), *dstFenceFd);
ALOGE_IF(err, "error locking dst buffer %s", strerror(-err));
*dstFenceFd = -1;

Region::const_iterator head(reg.begin());
Region::const_iterator tail(reg.end());
Expand Down Expand Up @@ -1225,7 +1227,7 @@ static status_t copyBlt(
src->unlock();

if (dst_bits)
dst->unlock();
dst->unlockAsync(dstFenceFd);

return err;
}
Expand Down Expand Up @@ -1285,8 +1287,9 @@ status_t Surface::lock(
}
}
const Region copyback(oldDirtyRegion.subtract(newDirtyRegion));
if (!copyback.isEmpty())
copyBlt(backBuffer, frontBuffer, copyback);
if (!copyback.isEmpty()) {
copyBlt(backBuffer, frontBuffer, copyback, &fenceFd);
}
} else {
// if we can't copy-back anything, modify the user's dirty
// region to make sure they redraw the whole buffer
Expand Down
112 changes: 79 additions & 33 deletions services/surfaceflinger/Layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,11 @@
#include <mutex>

#define DEBUG_RESIZE 0
#ifdef QTI_BSP
#define NUM_PIXEL_LOW_RES_PANEL (720*1280)
#endif

#define MAX_POSITION 32767
namespace android {

// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -1059,17 +1063,38 @@ void Layer::drawWithOpenGL(const sp<const DisplayDevice>& hw,
* like more of a hack.
*/
#ifdef QTI_BSP
const uint32_t hw_w = hw->getWidth();
const uint32_t hw_h = hw->getHeight();
Rect win(s.active.w, s.active.h);
if((hw_w * hw_h) > NUM_PIXEL_LOW_RES_PANEL) {
if (!s.crop.isEmpty()) {
win = s.crop;
}

if (!s.crop.isEmpty()) {
win = s.crop;
}
win = s.active.transform.transform(win);
win.intersect(hw->getViewport(), &win);
if (!s.finalCrop.isEmpty()) {
if (!win.intersect(s.finalCrop, &win)) {
win.clear();
}
}
win = s.active.transform.inverse().transform(win);
win.intersect(Rect(s.active.w, s.active.h), &win);
win = reduce(win, s.activeTransparentRegion);
} else {
win = computeBounds();

win = s.active.transform.transform(win);
win.intersect(hw->getViewport(), &win);
win = s.active.transform.inverse().transform(win);
win.intersect(Rect(s.active.w, s.active.h), &win);
win = reduce(win, s.activeTransparentRegion);
if (!s.finalCrop.isEmpty()) {
win = s.active.transform.transform(win);
if (!win.intersect(s.finalCrop, &win)) {
win.clear();
}
win = s.active.transform.inverse().transform(win);
if (!win.intersect(computeBounds(), &win)) {
win.clear();
}
}
}
#else
Rect win(computeBounds());

Expand Down Expand Up @@ -1281,35 +1306,45 @@ void Layer::computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh,
win.intersect(s.crop, &win);
}
#ifdef QTI_BSP
win = s.active.transform.transform(win);
win.intersect(hw->getViewport(), &win);
win = s.active.transform.inverse().transform(win);
win.intersect(Rect(s.active.w, s.active.h), &win);
win = reduce(win, s.activeTransparentRegion);
const uint32_t hw_w = hw->getWidth();
uint32_t orientation = 0;
if((hw_w * hw_h) > NUM_PIXEL_LOW_RES_PANEL) {
win = s.active.transform.transform(win);
win.intersect(hw->getViewport(), &win);
if (!s.finalCrop.isEmpty()) {
if (!win.intersect(s.finalCrop, &win)) {
win.clear();
}
}
win = s.active.transform.inverse().transform(win);
win.intersect(Rect(s.active.w, s.active.h), &win);
win = reduce(win, s.activeTransparentRegion);

const Transform bufferOrientation(mCurrentTransform);
Transform transform(tr * s.active.transform * bufferOrientation);
if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) {
uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform();
if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
const Transform bufferOrientation(mCurrentTransform);
Transform transform(tr * s.active.transform * bufferOrientation);
if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) {
uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform();
if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
NATIVE_WINDOW_TRANSFORM_FLIP_H;
}
transform = Transform(invTransform) * transform;
}
const uint32_t orientation = transform.getOrientation();
if (!(orientation | mCurrentTransform | mTransformHint)) {
if (!useIdentityTransform) {
win = s.active.transform.transform(win);
win.intersect(hw->getViewport(), &win);
}
transform = Transform(invTransform) * transform;
}
orientation = transform.getOrientation();
if (!(orientation | mCurrentTransform | mTransformHint)) {
if (!useIdentityTransform) {
win = s.active.transform.transform(win);
win.intersect(hw->getViewport(), &win);
}
}
} else {
win = reduce(win, s.activeTransparentRegion);
}
#else
win = reduce(win, s.activeTransparentRegion);
#endif



// subtract the transparent region and snap to the bounds

vec2 lt = vec2(win.left, win.top);
Expand All @@ -1319,17 +1354,24 @@ void Layer::computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh,

if (!useIdentityTransform) {
#ifdef QTI_BSP
if (orientation | mCurrentTransform | mTransformHint) {
if((hw_w * hw_h) > NUM_PIXEL_LOW_RES_PANEL) {
if (orientation | mCurrentTransform | mTransformHint) {
lt = s.active.transform.transform(lt);
lb = s.active.transform.transform(lb);
rb = s.active.transform.transform(rb);
rt = s.active.transform.transform(rt);
}
} else {
lt = s.active.transform.transform(lt);
lb = s.active.transform.transform(lb);
rb = s.active.transform.transform(rb);
rt = s.active.transform.transform(rt);
}
#else
lt = s.active.transform.transform(lt);
lb = s.active.transform.transform(lb);
rb = s.active.transform.transform(rb);
rt = s.active.transform.transform(rt);
lt = s.active.transform.transform(lt);
lb = s.active.transform.transform(lb);
rb = s.active.transform.transform(rb);
rt = s.active.transform.transform(rt);
#endif
}
if (!s.finalCrop.isEmpty()) {
Expand Down Expand Up @@ -1652,6 +1694,10 @@ uint32_t Layer::setTransactionFlags(uint32_t flags) {
bool Layer::setPosition(float x, float y, bool immediate) {
if (mCurrentState.requested.transform.tx() == x && mCurrentState.requested.transform.ty() == y)
return false;
if ((y > MAX_POSITION) || (x > MAX_POSITION)) {
ALOGE("%s:: failed %s x = %f y = %f",__FUNCTION__,mName.string(),x, y);
return false;
}
mCurrentState.sequence++;

// We update the requested and active position simultaneously because
Expand Down
2 changes: 1 addition & 1 deletion services/surfaceflinger/SurfaceFlinger_hwc1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1197,7 +1197,7 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
mAnimFrameTracker.advanceFrame();
}

dumpDrawCycle(true);
dumpDrawCycle(false);

if (hw->getPowerMode() == HWC_POWER_MODE_OFF) {
return;
Expand Down