Skip to content

Commit

Permalink
sf: Use DirtyRect to optimize Full GPU composition
Browse files Browse the repository at this point in the history
Use layer DirtyRect information in optimizing full GPU composition by
using startTile and endTile GL calls.

Change-Id: Iec0f9de2ce667438bbcc00d02e500055068df05a
  • Loading branch information
Sravan Kumar D.V.N authored and hyperb1iss committed Jun 25, 2014
1 parent f4ba36a commit 3305392
Show file tree
Hide file tree
Showing 11 changed files with 310 additions and 8 deletions.
7 changes: 7 additions & 0 deletions services/surfaceflinger/DisplayDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,13 @@ DisplayDevice::~DisplayDevice() {
}
}

#ifdef QCOM_BSP
void DisplayDevice::eglSwapPreserved(bool enable) const {
int swapValue = enable ? EGL_BUFFER_PRESERVED : EGL_BUFFER_DESTROYED;
eglSurfaceAttrib(mDisplay, mSurface, EGL_SWAP_BEHAVIOR, swapValue);
}
#endif

void DisplayDevice::disconnect(HWComposer& hwc) {
if (mHwcDisplayId >= 0) {
hwc.disconnectDisplay(mHwcDisplayId);
Expand Down
6 changes: 6 additions & 0 deletions services/surfaceflinger/DisplayDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,12 @@ class DisplayDevice : public LightRefBase<DisplayDevice>
void dump(String8& result) const;
int getHardwareOrientation();

#ifdef QCOM_BSP
/* To set egl atribute, EGL_SWAP_BEHAVIOR value
* (EGL_BUFFER_PRESERVED/EGL_BUFFER_DESTROYED)
*/
void eglSwapPreserved(bool status) const;
#endif
private:
/*
* Constants, set during initialization
Expand Down
137 changes: 136 additions & 1 deletion services/surfaceflinger/DisplayHardware/HWComposer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
#include "../Layer.h" // needed only for debugging
#include "../SurfaceFlinger.h"

#define GPUTILERECT_DEBUG 0

namespace android {

#define MIN_HWC_HEADER_VERSION HWC_HEADER_VERSION
Expand Down Expand Up @@ -804,6 +806,10 @@ status_t HWComposer::prepare() {
DisplayData& disp(mDisplayData[0]);
disp.hasFbComp = false;
disp.hasOvComp = false;
#ifdef QCOM_BSP
disp.hasBlitComp = false;
#endif

if (disp.list) {
hwc_layer_list_t* list0 = reinterpret_cast<hwc_layer_list_t*>(disp.list);
for (size_t i=0 ; i<hwcNumHwLayers(mHwc, disp.list) ; i++) {
Expand All @@ -822,6 +828,9 @@ status_t HWComposer::prepare() {
// trigger a FLIP
if(l.compositionType == HWC_BLIT) {
disp.hasFbComp = true;
#ifdef QCOM_BSP
disp.hasBlitComp = true;
#endif
}
if (l.compositionType == HWC_OVERLAY) {
disp.hasOvComp = true;
Expand All @@ -833,6 +842,13 @@ status_t HWComposer::prepare() {
return (status_t)err;
}

#ifdef QCOM_BSP
bool HWComposer::hasHwcOrBlitComposition(int32_t id) const {
if (!mHwc || uint32_t(id) > 31 || !mAllocatedDisplayIDs.hasBit(id))
return false;
return mDisplayData[id].hasOvComp || mDisplayData[id].hasBlitComp;
}
#endif
bool HWComposer::hasHwcComposition(int32_t id) const {
if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
return false;
Expand Down Expand Up @@ -1514,5 +1530,124 @@ HWComposer::DisplayData::~DisplayData() {
free(list);
}

// ---------------------------------------------------------------------------
#ifdef QCOM_BSP
//======================== GPU TiledRect/DR changes =====================
bool HWComposer::areVisibleRegionsOverlapping(int32_t id ) {
const Vector< sp<Layer> >& currentLayers =
mFlinger->getLayerSortedByZForHwcDisplay(id);
size_t count = currentLayers.size();
Region consolidatedVisibleRegion;

for (size_t i=0; i<count; i++) {
//If there are any overlapping visible regions, disable GPUTileRect
if(!consolidatedVisibleRegion.intersect(
currentLayers[i]->visibleRegion).isEmpty()){
return true;
}
consolidatedVisibleRegion.orSelf(currentLayers[i]->visibleRegion);
}
return false;
}

bool HWComposer::needsScaling(int32_t id) {
DisplayData& disp(mDisplayData[id]);
for (size_t i=0; i<disp.list->numHwLayers-1; i++) {
int dst_w, dst_h, src_w, src_h;
hwc_layer_1_t& layer = disp.list->hwLayers[i];
hwc_rect_t displayFrame = layer.displayFrame;

hwc_rect_t sourceCropI = {0,0,0,0};
sourceCropI.left = int(ceilf(layer.sourceCropf.left));
sourceCropI.top = int(ceilf(layer.sourceCropf.top));
sourceCropI.right = int(floorf(layer.sourceCropf.right));
sourceCropI.bottom = int(floorf(layer.sourceCropf.bottom));

dst_w = displayFrame.right - displayFrame.left;
dst_h = displayFrame.bottom - displayFrame.top;
src_w = sourceCropI.right - sourceCropI.left;
src_h = sourceCropI.bottom - sourceCropI.top;

if(((src_w != dst_w) || (src_h != dst_h))) {
return true;
}
}
return false;
}

void HWComposer::computeUnionDirtyRect(int32_t id, Rect& unionDirtyRect) {
const Vector< sp<Layer> >& currentLayers =
mFlinger->getLayerSortedByZForHwcDisplay(id);
size_t count = currentLayers.size();
Region unionDirtyRegion;
DisplayData& disp(mDisplayData[id]);

// Find UnionDr of all layers
for (size_t i=0; i<count; i++) {
hwc_layer_1_t& l = disp.list->hwLayers[i];
Rect dr(0,0,0,0);
if(currentLayers[i]->hasNewFrame()) {
dr = Rect(l.dirtyRect.left, l.dirtyRect.top, l.dirtyRect.right,
l.dirtyRect.bottom);
hwc_rect_t dst = l.displayFrame;

//Map dirtyRect to layer destination before using
hwc_rect_t src = {0,0,0,0};
src.left = int(ceilf(l.sourceCropf.left));
src.top = int(ceilf(l.sourceCropf.top));
src.right = int(floorf(l.sourceCropf.right));
src.bottom = int(floorf(l.sourceCropf.bottom));

int x_off = dst.left - src.left;
int y_off = dst.top - src.top;
dr = dr.offsetBy(x_off, y_off);
unionDirtyRegion = unionDirtyRegion.orSelf(dr);
}
}
unionDirtyRect = unionDirtyRegion.getBounds();
}

bool HWComposer::isGeometryChanged(int32_t id) {
DisplayData& disp(mDisplayData[id]);
return ( disp.list->flags & HWC_GEOMETRY_CHANGED );
}
/* Finds if we can enable DR optimization for GpuComp
* 1. return false if geometry is changed
* 2. if overlapping visible regions present.
* 3. Compute a Union Dirty Rect to operate on. */
bool HWComposer::canUseTiledDR(int32_t id, Rect& unionDr ){
bool status = true;

if (isGeometryChanged(id)) {
ALOGD_IF(GPUTILERECT_DEBUG, "GPUTileRect : geometrychanged, disable");
status = false;
} else if ( hasHwcOrBlitComposition(id)) {
/* Currently enabled only for full GPU Comp
* TODO : enable for mixed mode also */
ALOGD_IF(GPUTILERECT_DEBUG, "GPUTileRect: Blit comp, disable");
status = false;
} else if (areVisibleRegionsOverlapping(id)) {
/* With DirtyRect optimiaton, On certain targets we are seeing slightly
* lower FPS in use cases where visible regions overlap in Full GPU Comp.
* Hence this optimizatin has been disabled for usecases where visible
* regions overlap. TODO : Analyse & handle overlap usecases. */
ALOGD_IF(GPUTILERECT_DEBUG, "GPUTileRect: Visible \
regions overlap, disable");
status = false;
} else if (needsScaling(id)) {
/* Do Not use TiledDR optimization, if layers need scaling */
ALOGD_IF(GPUTILERECT_DEBUG, "GPUTileRect: Layers need scaling, disable");
status = false;
} else {
computeUnionDirtyRect(id, unionDr);
if(unionDr.isEmpty())
{
ALOGD_IF(GPUTILERECT_DEBUG,"GPUTileRect: UnionDr is emtpy, \
No need to PRESERVE");
status = false;
}
}
return status;
}
#endif

}; // namespace android
19 changes: 19 additions & 0 deletions services/surfaceflinger/DisplayHardware/HWComposer.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@ class HWComposer
// does this display have layers handled by GLES
bool hasGlesComposition(int32_t id) const;

#ifdef QCOM_BSP
// does this display have layers handled by overlays/blit
bool hasHwcOrBlitComposition(int32_t id) const;

//GPUTiledRect : function to find out if DR can be used in GPU Comp.
bool canUseTiledDR(int32_t id, Rect& dr);
#endif

// get the releaseFence file descriptor for a display's framebuffer layer.
// the release fence is only valid after commit()
sp<Fence> getAndResetReleaseFence(int32_t id);
Expand Down Expand Up @@ -325,6 +333,9 @@ class HWComposer
bool connected;
bool hasFbComp;
bool hasOvComp;
#ifdef QCOM_BSP
bool hasBlitComp;
#endif
size_t capacity;
hwc_display_contents_1* list;
hwc_layer_1* framebufferTarget;
Expand Down Expand Up @@ -362,6 +373,14 @@ class HWComposer

// thread-safe
mutable Mutex mEventControlLock;

#ifdef QCOM_BSP
//GPUTileRect Optimization Functions.
bool isGeometryChanged(int32_t id);
void computeUnionDirtyRect(int32_t id, Rect& unionDirtyRect);
bool areVisibleRegionsOverlapping(int32_t id );
bool needsScaling(int32_t id);
#endif
};

// ---------------------------------------------------------------------------
Expand Down
6 changes: 6 additions & 0 deletions services/surfaceflinger/Layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1357,6 +1357,12 @@ bool Layer::isSecureDisplay() const
return false;
}

#endif

#ifdef QCOM_BSP
bool Layer::hasNewFrame() const {
return (mQueuedFrames > 0);
}
#endif
// ---------------------------------------------------------------------------
}; // namespace android
Expand Down
5 changes: 5 additions & 0 deletions services/surfaceflinger/Layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,11 @@ class Layer : public SurfaceFlingerConsumer::FrameAvailableListener {
void clearStats();
void logFrameStats();

#ifdef QCOM_BSP
//GPUTileRect : Return true if the layer has been updated in this frame.
bool hasNewFrame() const;
#endif

protected:
// constant
sp<SurfaceFlinger> mFlinger;
Expand Down
12 changes: 12 additions & 0 deletions services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,18 @@ void GLES20RenderEngine::disableBlending() {
glDisable(GL_BLEND);
}

#ifdef QCOM_BSP
void GLES20RenderEngine::startTileComposition(int x , int y, int width,
int height, bool preserve) {
glStartTilingQCOM(x, y, width, height,
(preserve ? GL_COLOR_BUFFER_BIT0_QCOM : GL_NONE));
}

void GLES20RenderEngine::endTileComposition(unsigned int preserveMask) {
glEndTilingQCOM(preserveMask);
}
#endif


void GLES20RenderEngine::bindImageAsFramebuffer(EGLImageKHR image,
uint32_t* texName, uint32_t* fbName, uint32_t* status,
Expand Down
5 changes: 5 additions & 0 deletions services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ class GLES20RenderEngine : public RenderEngine {
virtual void setupFillWithColor(float r, float g, float b, float a);
virtual void disableTexturing();
virtual void disableBlending();
#ifdef QCOM_BSP
virtual void startTileComposition(int x , int y, int width,
int height,bool preserve );
virtual void endTileComposition(unsigned int preserveMask);
#endif

virtual void drawMesh(const Mesh& mesh);

Expand Down
6 changes: 6 additions & 0 deletions services/surfaceflinger/RenderEngine/RenderEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,12 @@ class RenderEngine {

virtual void disableTexturing() = 0;
virtual void disableBlending() = 0;
#ifdef QCOM_BSP
virtual void startTileComposition(int x, int y, int width,
int height, bool preserve){}
virtual void endTileComposition(unsigned int) {}
#endif


// drawing
virtual void drawMesh(const Mesh& mesh) = 0;
Expand Down
Loading

0 comments on commit 3305392

Please sign in to comment.