Bug 919676 - Fix multiple hwc prepare calls with different layer lists. r=mwu, r=dwilson

This commit is contained in:
Sushil Chauhan 2013-10-08 08:29:35 -07:00
parent d9ea1eb4df
commit 901afbe792
8 changed files with 143 additions and 24 deletions

View File

@ -605,9 +605,13 @@ public:
{
if (mSurface && !mPlatformContext) {
#ifdef MOZ_WIDGET_GONK
if (!mIsOffscreen)
return GetGonkDisplay()->SwapBuffers(EGL_DISPLAY(), mSurface);
else
if (!mIsOffscreen) {
if (mHwc) {
return mHwc->Render(EGL_DISPLAY(), mSurface);
} else {
return GetGonkDisplay()->SwapBuffers(EGL_DISPLAY(), mSurface);
}
} else
#endif
return sEGLLibrary.fSwapBuffers(EGL_DISPLAY(), mSurface);
} else {

View File

@ -445,45 +445,114 @@ HwcComposer2D::TryHwComposition()
{
FramebufferSurface* fbsurface = (FramebufferSurface*)(GetGonkDisplay()->GetFBSurface());
if (!(fbsurface && fbsurface->lastHandle)) {
LOGD("H/W Composition failed. FBSurface not initialized.");
return false;
}
// Add FB layer
int idx = mList->numHwLayers++;
if (idx >= mMaxLayerCount) {
if (!ReallocLayerList() || idx >= mMaxLayerCount) {
LOGE("TryHwComposition failed! Could not add FB layer");
return false;
}
}
Prepare(fbsurface->lastHandle, -1);
for (int j = 0; j < idx; j++) {
if (mList->hwLayers[j].compositionType == HWC_FRAMEBUFFER) {
LOGD("GPU or Partial HWC Composition");
return false;
}
}
// Full HWC Composition
Commit();
// No composition on FB layer, so closing releaseFenceFd
close(mList->hwLayers[idx].releaseFenceFd);
mList->hwLayers[idx].releaseFenceFd = -1;
mList->numHwLayers = 0;
return true;
}
bool
HwcComposer2D::Render(EGLDisplay dpy, EGLSurface sur)
{
if (!mList) {
// After boot, HWC list hasn't been created yet
return GetGonkDisplay()->SwapBuffers(dpy, sur);
}
GetGonkDisplay()->UpdateFBSurface(dpy, sur);
FramebufferSurface* fbsurface = (FramebufferSurface*)(GetGonkDisplay()->GetFBSurface());
if (!fbsurface) {
LOGE("H/W Composition failed. FBSurface not initialized.");
return false;
}
hwc_display_contents_1_t *displays[HWC_NUM_DISPLAY_TYPES] = {NULL};
if (mList->numHwLayers != 0) {
// No mHwc prepare, if already prepared in current draw cycle
mList->hwLayers[mList->numHwLayers - 1].handle = fbsurface->lastHandle;
mList->hwLayers[mList->numHwLayers - 1].acquireFenceFd = fbsurface->lastFenceFD;
} else {
mList->numHwLayers = 2;
mList->hwLayers[0].hints = 0;
mList->hwLayers[0].compositionType = HWC_BACKGROUND;
mList->hwLayers[0].flags = HWC_SKIP_LAYER;
mList->hwLayers[0].backgroundColor = {0};
mList->hwLayers[0].displayFrame = {0, 0, mScreenRect.width, mScreenRect.height};
Prepare(fbsurface->lastHandle, fbsurface->lastFenceFD);
}
// GPU or partial HWC Composition
Commit();
GetGonkDisplay()->SetFBReleaseFd(mList->hwLayers[mList->numHwLayers - 1].releaseFenceFd);
mList->numHwLayers = 0;
return true;
}
void
HwcComposer2D::Prepare(buffer_handle_t fbHandle, int fence)
{
int idx = mList->numHwLayers - 1;
const hwc_rect_t r = {0, 0, mScreenRect.width, mScreenRect.height};
int idx = mList->numHwLayers;
hwc_display_contents_1_t *displays[HWC_NUM_DISPLAY_TYPES] = { nullptr };
displays[HWC_DISPLAY_PRIMARY] = mList;
mList->flags = HWC_GEOMETRY_CHANGED;
mList->outbufAcquireFenceFd = -1;
mList->outbuf = nullptr;
mList->retireFenceFd = -1;
mList->hwLayers[idx].hints = 0;
mList->hwLayers[idx].flags = 0;
mList->hwLayers[idx].transform = 0;
mList->hwLayers[idx].handle = fbsurface->lastHandle;
mList->hwLayers[idx].handle = fbHandle;
mList->hwLayers[idx].blending = HWC_BLENDING_PREMULT;
mList->hwLayers[idx].compositionType = HWC_FRAMEBUFFER_TARGET;
mList->hwLayers[idx].sourceCrop = r;
mList->hwLayers[idx].displayFrame = r;
mList->hwLayers[idx].visibleRegionScreen.numRects = 1;
mList->hwLayers[idx].visibleRegionScreen.rects = &mList->hwLayers[idx].sourceCrop;
mList->hwLayers[idx].acquireFenceFd = -1;
mList->hwLayers[idx].acquireFenceFd = fence;
mList->hwLayers[idx].releaseFenceFd = -1;
mList->hwLayers[idx].planeAlpha = 0xFF;
mList->numHwLayers++;
mHwc->prepare(mHwc, HWC_NUM_DISPLAY_TYPES, displays);
}
for (int j = 0; j < idx; j++) {
if (mList->hwLayers[j].compositionType == HWC_FRAMEBUFFER) {
LOGD("GPU or Partial MDP Composition");
return false;
}
}
bool
HwcComposer2D::Commit()
{
hwc_display_contents_1_t *displays[HWC_NUM_DISPLAY_TYPES] = { nullptr };
displays[HWC_DISPLAY_PRIMARY] = mList;
// Full MDP Composition
mHwc->set(mHwc, HWC_NUM_DISPLAY_TYPES, displays);
int err = mHwc->set(mHwc, HWC_NUM_DISPLAY_TYPES, displays);
for (int i = 0; i <= MAX_HWC_LAYERS; i++) {
if (mPrevRelFd[i] <= 0) {
@ -504,18 +573,15 @@ HwcComposer2D::TryHwComposition()
}
mPrevRelFd[0] = mList->retireFenceFd;
for (uint32_t j = 0; j < idx; j++) {
for (uint32_t j = 0; j < (mList->numHwLayers - 1); j++) {
if (mList->hwLayers[j].compositionType == HWC_OVERLAY) {
mPrevRelFd[j + 1] = mList->hwLayers[j].releaseFenceFd;
mList->hwLayers[j].releaseFenceFd = -1;
}
}
close(mList->hwLayers[idx].releaseFenceFd);
mList->hwLayers[idx].releaseFenceFd = -1;
mList->retireFenceFd = -1;
mList->numHwLayers = 0;
return true;
return !err;
}
#else
bool
@ -523,6 +589,12 @@ HwcComposer2D::TryHwComposition()
{
return !mHwc->set(mHwc, mDpy, mSur, mList);
}
bool
HwcComposer2D::Render(EGLDisplay dpy, EGLSurface sur)
{
return GetGonkDisplay()->SwapBuffers(dpy, sur);
}
#endif
bool
@ -549,13 +621,15 @@ HwcComposer2D::TryRender(Layer* aRoot,
aGLWorldTransform))
{
LOGD("Render aborted. Nothing was drawn to the screen");
if (mList) {
mList->numHwLayers = 0;
}
return false;
}
if (!TryHwComposition()) {
// Full MDP Composition
LOGE("H/W Composition failed");
return false;
LOGD("H/W Composition failed");
return false;
}
LOGD("Frame rendered");

View File

@ -62,7 +62,11 @@ public:
// by this composer so nothing was rendered at all
bool TryRender(layers::Layer* aRoot, const gfxMatrix& aGLWorldTransform) MOZ_OVERRIDE;
bool Render(EGLDisplay dpy, EGLSurface sur);
private:
void Prepare(buffer_handle_t fbHandle, int fence);
bool Commit();
bool TryHwComposition();
bool ReallocLayerList();
bool PrepareLayerList(layers::Layer* aContainer, const nsIntRect& aClip,

View File

@ -43,6 +43,10 @@ public:
virtual bool QueueBuffer(ANativeWindowBuffer* buf) = 0;
virtual void UpdateFBSurface(EGLDisplay dpy, EGLSurface sur) = 0;
virtual void SetFBReleaseFd(int fd) = 0;
float xdpi;
uint32_t surfaceformat;
};

View File

@ -196,6 +196,17 @@ GonkDisplayICS::QueueBuffer(ANativeWindowBuffer *buf)
return !window->queueBuffer(window, buf);
}
void
GonkDisplayICS::UpdateFBSurface(EGLDisplay dpy, EGLSurface sur)
{
eglSwapBuffers(dpy, sur);
}
void
GonkDisplayICS::SetFBReleaseFd(int fd)
{
}
__attribute__ ((visibility ("default")))
GonkDisplay*
GetGonkDisplay()

View File

@ -46,6 +46,10 @@ public:
virtual bool QueueBuffer(ANativeWindowBuffer* handle);
virtual void UpdateFBSurface(EGLDisplay dpy, EGLSurface sur);
virtual void SetFBReleaseFd(int fd);
private:
hw_module_t const* mModule;
hwc_composer_device_t* mHwc;

View File

@ -272,6 +272,20 @@ GonkDisplayJB::QueueBuffer(ANativeWindowBuffer* buf)
return success;
}
void
GonkDisplayJB::UpdateFBSurface(EGLDisplay dpy, EGLSurface sur)
{
StopBootAnimation();
mBootAnimBuffer = nullptr;
eglSwapBuffers(dpy, sur);
}
void
GonkDisplayJB::SetFBReleaseFd(int fd)
{
mFBSurface->setReleaseFenceFd(fd);
}
__attribute__ ((visibility ("default")))
GonkDisplay*
GetGonkDisplay()

View File

@ -45,6 +45,10 @@ public:
virtual bool QueueBuffer(ANativeWindowBuffer* buf);
virtual void UpdateFBSurface(EGLDisplay dpy, EGLSurface sur);
virtual void SetFBReleaseFd(int fd);
bool Post(buffer_handle_t buf, int fence);
private: