Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1020d17b authored by Ricardo Cerqueira's avatar Ricardo Cerqueira
Browse files

Revert "remove support for HWC < 1.0"

This partially reverts commit 30bcc614
and updates to the current API. Tested on 0.1 blobs from Tegra2/3
and OMAP3/4

Change-Id: I43cee8852b266d68d1edefbe7ac988b9dbcf7227

Conflicts:
	services/surfaceflinger/DisplayHardware/HWComposer.cpp
parent 5fbf4fbd
Loading
Loading
Loading
Loading
+322 −78
Original line number Diff line number Diff line
@@ -65,6 +65,106 @@ static bool hwcHasApiVersion(const hwc_composer_device_1_t* hwc,
    return hwcApiVersion(hwc) >= (version & HARDWARE_API_VERSION_2_MAJ_MIN_MASK);
}

static bool hwcHasVsyncEvent(const hwc_composer_device_1_t* hwc) {
    return hwcHasApiVersion(hwc, HWC_DEVICE_API_VERSION_0_3);
}

static size_t sizeofHwcLayerList(const hwc_composer_device_1_t* hwc,
        size_t numLayers) {
    if (hwcHasApiVersion(hwc, HWC_DEVICE_API_VERSION_1_0)) {
        return sizeof(hwc_display_contents_1_t) + numLayers*sizeof(hwc_layer_1_t);
    } else {
        return sizeof(hwc_layer_list_t) + numLayers*sizeof(hwc_layer_t);
    }
}

static int hwcEventControl(hwc_composer_device_1_t* hwc, int dpy,
        int event, int enabled) {
    if (hwcHasApiVersion(hwc, HWC_DEVICE_API_VERSION_1_0)) {
        return hwc->eventControl(hwc, dpy, event, enabled);
    } else {
        hwc_composer_device_t* hwc0 = reinterpret_cast<hwc_composer_device_t*>(hwc);
        return hwc0->methods->eventControl(hwc0, event, enabled);
    }
}

static int hwcBlank(hwc_composer_device_1_t* hwc, int dpy, int blank) {
    if (hwcHasApiVersion(hwc, HWC_DEVICE_API_VERSION_1_0)) {
        return hwc->blank(hwc, dpy, blank);
    } else {
        if (blank) {
            hwc_composer_device_t* hwc0 = reinterpret_cast<hwc_composer_device_t*>(hwc);
            return hwc0->set(hwc0, NULL, NULL, NULL);
        } else {
            // HWC 0.x turns the screen on at the next set()
            return NO_ERROR;
        }
    }
}

static int hwcPrepare(hwc_composer_device_1_t* hwc,
        size_t numDisplays, hwc_display_contents_1_t** displays) {
    if (hwcHasApiVersion(hwc, HWC_DEVICE_API_VERSION_1_0)) {
        return hwc->prepare(hwc, numDisplays, displays);
    } else {
        hwc_composer_device_t* hwc0 = reinterpret_cast<hwc_composer_device_t*>(hwc);
        hwc_layer_list_t* list0 = reinterpret_cast<hwc_layer_list_t*>(displays[0]);
        // In the past, SurfaceFlinger would pass a NULL list when doing full
        // OpenGL ES composition. I don't know what, if any, dependencies there
        // are on this behavior, so I'm playing it safe and preserving it.
        // ... and I'm removing it. NULL layers kill the Tegra compositor (RC, Nov 2012)
        /*if (list0->numHwLayers == 0)
            return hwc0->prepare(hwc0, NULL);
        else*/
            return hwc0->prepare(hwc0, list0);
    }
}
static int hwcSet(hwc_composer_device_1_t* hwc, EGLDisplay dpy, EGLSurface sur,
        size_t numDisplays, hwc_display_contents_1_t** displays) {
    int err;
    if (hwcHasApiVersion(hwc, HWC_DEVICE_API_VERSION_1_0)) {
        displays[0]->dpy = dpy;
        displays[0]->sur = sur;
        err = hwc->set(hwc, numDisplays, displays);
    } else {
        hwc_composer_device_t* hwc0 = reinterpret_cast<hwc_composer_device_t*>(hwc);
        hwc_layer_list_t* list0 = reinterpret_cast<hwc_layer_list_t*>(displays[0]);
        err = hwc0->set(hwc0, dpy, sur, list0);
    }
    return err;
}

static uint32_t& hwcFlags(hwc_composer_device_1_t* hwc,
        hwc_display_contents_1_t* display) {
    if (hwcHasApiVersion(hwc, HWC_DEVICE_API_VERSION_1_0)) {
        return display->flags;
    } else {
        hwc_layer_list_t* list0 = reinterpret_cast<hwc_layer_list_t*>(display);
        return list0->flags;
    }
}

static size_t& hwcNumHwLayers(hwc_composer_device_1_t* hwc,
        hwc_display_contents_1_t* display) {
    if (hwcHasApiVersion(hwc, HWC_DEVICE_API_VERSION_1_0)) {
        return display->numHwLayers;
    } else {
        hwc_layer_list_t* list0 = reinterpret_cast<hwc_layer_list_t*>(display);
        return list0->numHwLayers;
    }
}

static void hwcDump(hwc_composer_device_1_t* hwc, char* buff, int buff_len) {
    if (hwcHasApiVersion(hwc, HWC_DEVICE_API_VERSION_1_0)) {
        if (hwc->dump)
            hwc->dump(hwc, buff, buff_len);
    } else if (hwcHasApiVersion(hwc, HWC_DEVICE_API_VERSION_0_1)) {
        hwc_composer_device_t* hwc0 = reinterpret_cast<hwc_composer_device_t*>(hwc);
        if (hwc0->dump)
            hwc0->dump(hwc0, buff, buff_len);
    }
}

// ---------------------------------------------------------------------------

struct HWComposer::cb_context {
@@ -133,6 +233,7 @@ HWComposer::HWComposer(
        ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER,
              (hwcApiVersion(mHwc) >> 24) & 0xff,
              (hwcApiVersion(mHwc) >> 16) & 0xff);
        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
            if (mHwc->registerProcs) {
                mCBContext->hwc = this;
                mCBContext->procs.invalidate = &hook_invalidate;
@@ -144,12 +245,22 @@ HWComposer::HWComposer(
                memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero));
                mHwc->registerProcs(mHwc, &mCBContext->procs);
            }
        } else {
            hwc_composer_device_t* hwc0 = reinterpret_cast<hwc_composer_device_t*>(mHwc);
            if (hwc0->registerProcs) {
                mCBContext->hwc = this;
                mCBContext->procs.invalidate = &hook_invalidate;
                mCBContext->procs.vsync = &hook_vsync;
                memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero));
                hwc0->registerProcs(hwc0, &mCBContext->procs);
            }
        }

        // don't need a vsync thread if we have a hardware composer
        needVSyncThread = false;
        // always turn vsync off when we start
        if (hwcHasVsyncEvent(mHwc)) {
            eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);

            // the number of displays we actually have depends on the
            // hw composer version
            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
@@ -161,6 +272,10 @@ HWComposer::HWComposer(
            } else {
                mNumDisplays = 1;
            }
        } else {
            needVSyncThread = true;
            mNumDisplays = 1;
        }
    }

    if (mFbDev) {
@@ -229,9 +344,10 @@ void HWComposer::loadHwcModule()
        return;
    }

    if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0) ||
    if (HWC_REMOVE_DEPRECATED_VERSIONS &&
        (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0) ||
            hwcHeaderVersion(mHwc) < MIN_HWC_HEADER_VERSION ||
            hwcHeaderVersion(mHwc) > HWC_HEADER_VERSION) {
            hwcHeaderVersion(mHwc) > HWC_HEADER_VERSION)) {
        ALOGE("%s device version %#x unsupported, will not be used",
              HWC_HARDWARE_COMPOSER, mHwc->common.version);
        hwc_close_1(mHwc);
@@ -482,7 +598,8 @@ void HWComposer::eventControl(int disp, int event, int enabled) {
        return;
    }
    status_t err = NO_ERROR;
    if (mHwc && !mDebugForceFakeVSync) {
    if (mHwc && !mDebugForceFakeVSync && hwcHasVsyncEvent(mHwc))  {
        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
            // NOTE: we use our own internal lock here because we have to call
            // into the HWC with the lock held, and we want to make sure
            // that even if HWC blocks (which it shouldn't), it won't
@@ -493,12 +610,15 @@ void HWComposer::eventControl(int disp, int event, int enabled) {
            const int32_t oldValue = mDisplayData[disp].events & eventBit;
            if (newValue != oldValue) {
                ATRACE_CALL();
            err = mHwc->eventControl(mHwc, disp, event, enabled);
                err = hwcEventControl(mHwc, disp, event, enabled);
                if (!err) {
                    int32_t& events(mDisplayData[disp].events);
                    events = (events & ~eventBit) | newValue;
                }
            }
        } else {
            err = hwcEventControl(mHwc, disp, event, enabled);
        }
        // error here should not happen -- not sure what we should
        // do if it does.
        ALOGE_IF(err, "eventControl(%d, %d) failed %s",
@@ -522,8 +642,7 @@ status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
            numLayers++;
        }
        if (disp.capacity < numLayers || disp.list == NULL) {
            size_t size = sizeof(hwc_display_contents_1_t)
                    + numLayers * sizeof(hwc_layer_1_t);
            size_t size = sizeofHwcLayerList(mHwc, numLayers);
            free(disp.list);
            disp.list = (hwc_display_contents_1_t*)malloc(size);
            disp.capacity = numLayers;
@@ -554,9 +673,11 @@ status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
            disp.framebufferTarget->releaseFenceFd = -1;
            disp.framebufferTarget->planeAlpha = 0xFF;
        }
        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
            disp.list->retireFenceFd = -1;
        disp.list->flags = HWC_GEOMETRY_CHANGED;
        disp.list->numHwLayers = numLayers;
        }
        hwcFlags(mHwc, disp.list) = HWC_GEOMETRY_CHANGED;
        hwcNumHwLayers(mHwc, disp.list) = numLayers;
    }
    return NO_ERROR;
}
@@ -600,7 +721,7 @@ status_t HWComposer::prepare() {
        }
        if (!disp.connected && disp.list != NULL) {
            ALOGW("WARNING: disp %d: connected, non-null list, layers=%d",
                  i, disp.list->numHwLayers);
                    i, hwcNumHwLayers(mHwc, disp.list));
        }
        mLists[i] = disp.list;
        if (mLists[i]) {
@@ -611,35 +732,55 @@ status_t HWComposer::prepare() {
                // garbage data to catch improper use
                mLists[i]->dpy = (hwc_display_t)0xDEADBEEF;
                mLists[i]->sur = (hwc_surface_t)0xDEADBEEF;
            } else {
            } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
                mLists[i]->dpy = EGL_NO_DISPLAY;
                mLists[i]->sur = EGL_NO_SURFACE;
            }
        }
    }

    int err = mHwc->prepare(mHwc, mNumDisplays, mLists);
    int err = hwcPrepare(mHwc, mNumDisplays, mLists);
    ALOGE_IF(err, "HWComposer: prepare failed (%s)", strerror(-err));

    if (err == NO_ERROR) {
        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
            // here we're just making sure that "skip" layers are set
            // to HWC_FRAMEBUFFER and we're also counting how many layers
            // we have of each type.
        //
        // If there are no window layers, we treat the display has having FB
        // composition, because SurfaceFlinger will use GLES to draw the
        // wormhole region.
            for (size_t i=0 ; i<mNumDisplays ; i++) {
                DisplayData& disp(mDisplayData[i]);
                disp.hasFbComp = false;
                disp.hasOvComp = false;
                if (disp.list) {
                for (size_t i=0 ; i<disp.list->numHwLayers ; i++) {
                    for (size_t i=0 ; i<hwcNumHwLayers(mHwc, disp.list) ; i++) {
                        hwc_layer_1_t& l = disp.list->hwLayers[i];

                        //ALOGD("prepare: %d, type=%d, handle=%p",
                        //        i, l.compositionType, l.handle);

                        if (l.flags & HWC_SKIP_LAYER) {
                            l.compositionType = HWC_FRAMEBUFFER;
                        }
                        if (l.compositionType == HWC_FRAMEBUFFER) {
                            disp.hasFbComp = true;
                        }
                        if (l.compositionType == HWC_OVERLAY) {
                            disp.hasOvComp = true;
                        }
                    }
                }
            }
        } else {
            DisplayData& disp(mDisplayData[0]);
            disp.hasFbComp = false;
            disp.hasOvComp = false;
            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++) {
                    hwc_layer_t& l = list0->hwLayers[i];

                    //ALOGD("prepare: %d, type=%d, handle=%p",
                    //        i, l.compositionType, l.handle);

                    if (l.flags & HWC_SKIP_LAYER) {
                        l.compositionType = HWC_FRAMEBUFFER;
                    }
@@ -656,7 +797,9 @@ status_t HWComposer::prepare() {
            } else {
                disp.hasFbComp = true;
            }

        }

    }
    return (status_t)err;
}
@@ -692,6 +835,7 @@ sp<Fence> HWComposer::getAndResetReleaseFence(int32_t id) {
status_t HWComposer::commit() {
    int err = NO_ERROR;
    if (mHwc) {
        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
            if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
                // On version 1.0, the OpenGL ES target surface is communicated
                // by the (dpy, sur) fields and we are guaranteed to have only
@@ -699,6 +843,12 @@ status_t HWComposer::commit() {
                mLists[0]->dpy = eglGetCurrentDisplay();
                mLists[0]->sur = eglGetCurrentSurface(EGL_DRAW);
            }
            err = hwcSet(mHwc, mLists[0]->dpy, mLists[0]->sur, mNumDisplays,
                    const_cast<hwc_display_contents_1_t**>(mLists));
        } else {
            err = hwcSet(mHwc, eglGetCurrentDisplay(), eglGetCurrentSurface(EGL_DRAW), mNumDisplays,
                    const_cast<hwc_display_contents_1_t**>(mLists));
        }

        for (size_t i=VIRTUAL_DISPLAY_ID_BASE; i<mNumDisplays; i++) {
            DisplayData& disp(mDisplayData[i]);
@@ -716,11 +866,13 @@ status_t HWComposer::commit() {
            disp.lastDisplayFence = disp.lastRetireFence;
            disp.lastRetireFence = Fence::NO_FENCE;
            if (disp.list) {
                if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
                    if (disp.list->retireFenceFd != -1) {
                        disp.lastRetireFence = new Fence(disp.list->retireFenceFd);
                        disp.list->retireFenceFd = -1;
                    }
                disp.list->flags &= ~HWC_GEOMETRY_CHANGED;
                }
                hwcFlags(mHwc, disp.list) &= ~HWC_GEOMETRY_CHANGED;
            }
        }
    }
@@ -730,8 +882,10 @@ status_t HWComposer::commit() {
status_t HWComposer::release(int disp) {
    LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE);
    if (mHwc) {
        if (hwcHasVsyncEvent(mHwc)) {
            eventControl(disp, HWC_EVENT_VSYNC, 0);
        return (status_t)mHwc->blank(mHwc, disp, 1);
        }
        return (status_t)hwcBlank(mHwc, disp, 1);
    }
    return NO_ERROR;
}
@@ -739,7 +893,7 @@ status_t HWComposer::release(int disp) {
status_t HWComposer::acquire(int disp) {
    LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE);
    if (mHwc) {
        return (status_t)mHwc->blank(mHwc, disp, 0);
        return (status_t)hwcBlank(mHwc, disp, 0);
    }
    return NO_ERROR;
}
@@ -847,6 +1001,93 @@ private:
    }
};

// #if !HWC_REMOVE_DEPRECATED_VERSIONS
/*
 * Concrete implementation of HWCLayer for HWC_DEVICE_API_VERSION_0_3
 * This implements the HWCLayer side of HWCIterableLayer.
 */
class HWCLayerVersion0 : public Iterable<HWCLayerVersion0, hwc_layer_t> {
public:
    HWCLayerVersion0(hwc_layer_t* layer)
        : Iterable<HWCLayerVersion0, hwc_layer_t>(layer) { }

    virtual int32_t getCompositionType() const {
        return getLayer()->compositionType;
    }
    virtual uint32_t getHints() const {
        return getLayer()->hints;
    }
    virtual int getAndResetReleaseFenceFd() {
        // not supported on VERSION_03
        return -1;
    }
    virtual void setAcquireFenceFd(int fenceFd) {
        if (fenceFd != -1) {
            ALOGE("HWC 0.x can't handle acquire fences");
            close(fenceFd);
        }
    }

    virtual void setDefaultState() {
        getLayer()->compositionType = HWC_FRAMEBUFFER;
        getLayer()->hints = 0;
        getLayer()->flags = HWC_SKIP_LAYER;
        getLayer()->handle = 0;
        getLayer()->transform = 0;
        getLayer()->blending = HWC_BLENDING_NONE;
        getLayer()->visibleRegionScreen.numRects = 0;
        getLayer()->visibleRegionScreen.rects = NULL;
    }
    virtual void setSkip(bool skip) {
        if (skip) {
            getLayer()->flags |= HWC_SKIP_LAYER;
        } else {
            getLayer()->flags &= ~HWC_SKIP_LAYER;
        }
    }
    virtual void setBlending(uint32_t blending) {
        getLayer()->blending = blending;
    }
    virtual void setTransform(uint32_t transform) {
        getLayer()->transform = transform;
    }
    virtual void setFrame(const Rect& frame) {
        reinterpret_cast<Rect&>(getLayer()->displayFrame) = frame;
    }
    virtual void setCrop(const Rect& crop) {
        reinterpret_cast<Rect&>(getLayer()->sourceCrop) = crop;
    }
    virtual void setVisibleRegionScreen(const Region& reg) {
        // Region::getSharedBuffer creates a reference to the underlying
        // SharedBuffer of this Region, this reference is freed
        // in onDisplayed()
        hwc_region_t& visibleRegion = getLayer()->visibleRegionScreen;
        SharedBuffer const* sb = reg.getSharedBuffer(&visibleRegion.numRects);
        visibleRegion.rects = reinterpret_cast<hwc_rect_t const *>(sb->data());
    }
    virtual void setBuffer(const sp<GraphicBuffer>& buffer) {
        if (buffer == 0 || buffer->handle == 0) {
            getLayer()->compositionType = HWC_FRAMEBUFFER;
            getLayer()->flags |= HWC_SKIP_LAYER;
            getLayer()->handle = 0;
        } else {
            getLayer()->handle = buffer->handle;
        }
    }
    virtual void onDisplayed() {
        hwc_region_t& visibleRegion = getLayer()->visibleRegionScreen;
        SharedBuffer const* sb = SharedBuffer::bufferFromData(visibleRegion.rects);
        if (sb) {
            sb->release();
            // not technically needed but safer
            visibleRegion.numRects = 0;
            visibleRegion.rects = NULL;
        }

    }
};
// #endif // !HWC_REMOVE_DEPRECATED_VERSIONS

/*
 * Concrete implementation of HWCLayer for HWC_DEVICE_API_VERSION_1_0.
 * This implements the HWCLayer side of HWCIterableLayer.
@@ -970,10 +1211,15 @@ HWComposer::LayerListIterator HWComposer::getLayerIterator(int32_t id, size_t in
        return LayerListIterator();
    }
    const DisplayData& disp(mDisplayData[id]);
    if (!mHwc || !disp.list || index > disp.list->numHwLayers) {
    if (!mHwc || !disp.list || index > hwcNumHwLayers(mHwc,disp.list)) {
        return LayerListIterator();
    }
    if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
       return LayerListIterator(new HWCLayerVersion1(mHwc, disp.list->hwLayers), index);
    } else {
       hwc_layer_list_t* list0 = reinterpret_cast<hwc_layer_list_t*>(disp.list);
       return LayerListIterator(new HWCLayerVersion0(list0->hwLayers), index);
    }
}

/*
@@ -991,7 +1237,7 @@ HWComposer::LayerListIterator HWComposer::end(int32_t id) {
    if (uint32_t(id) <= 31 && mAllocatedDisplayIDs.hasBit(id)) {
        const DisplayData& disp(mDisplayData[id]);
        if (mHwc && disp.list) {
            numLayers = disp.list->numHwLayers;
            numLayers = hwcNumHwLayers(mHwc, disp.list);
            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
                // with HWC 1.1, the last layer is always the HWC_FRAMEBUFFER_TARGET,
                // which we ignore when iterating through the layer list.
@@ -1081,11 +1327,9 @@ void HWComposer::dump(String8& result) const {
            }
        }
    }

    if (mHwc && mHwc->dump) {
    if (mHwc) {
        const size_t SIZE = 4096;
        char buffer[SIZE];
        mHwc->dump(mHwc, buffer, SIZE);
        hwcDump(mHwc, buffer, SIZE);
        result.append(buffer);
    }
}
@@ -1139,7 +1383,7 @@ bool HWComposer::VSyncThread::threadLoop() {
        err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL);
    } while (err<0 && errno == EINTR);

    if (err == 0) {
    if (err == 0 && mEnabled) {
        mHwc.mEventHandler.onVSyncReceived(0, next_vsync);
    }