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

Commit 94c40fe9 authored by John Reck's avatar John Reck
Browse files

CARD LAND!

Bug: 16712006

Initial work towards benchmarking HWUI systems
Currently this will just create a screen full of
"cards" to simulate a high load scenario for
shadows and clipping

Change-Id: Ie9f9a9570844e136db8053e8fc62fe06cb922a5f
parent d8a21bbe
Loading
Loading
Loading
Loading
+55 −0
Original line number Diff line number Diff line
#
# Copyright (C) 2014 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

local_target_dir := $(TARGET_OUT_DATA)/local/tmp
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_CFLAGS += -DUSE_OPENGL_RENDERER -DEGL_EGLEXT_PROTOTYPES -DGL_GLEXT_PROTOTYPES
LOCAL_CFLAGS += -DATRACE_TAG=ATRACE_TAG_VIEW -DLOG_TAG=\"OpenGLRenderer\"

LOCAL_SRC_FILES:= \
	TestContext.cpp \
	main.cpp

LOCAL_C_INCLUDES += \
	$(LOCAL_PATH)/.. \
	external/skia/src/core

LOCAL_SHARED_LIBRARIES := \
	liblog \
	libcutils \
	libutils \
	libskia \
	libgui \
	libui \
	libhwui

ifeq ($(WITH_MALLOC_LEAK_CHECK),true)
	LOCAL_CFLAGS += -DMALLOC_LEAK_CHECK
endif

LOCAL_MODULE_PATH := $(local_target_dir)
LOCAL_MODULE:= hwuitest
LOCAL_MODULE_TAGS := tests
LOCAL_MULTILIB := both
LOCAL_MODULE_STEM_32 := hwuitest
LOCAL_MODULE_STEM_64 := hwuitest64

include external/stlport/libstlport.mk
include $(BUILD_EXECUTABLE)

include $(call all-makefiles-under,$(LOCAL_PATH))
+45 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "TestContext.h"

#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>

using namespace android;

DisplayInfo gDisplay;
sp<SurfaceComposerClient> gSession;

void createTestEnvironment() {
    gSession = new SurfaceComposerClient();
    sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(
                ISurfaceComposer::eDisplayIdMain));
    status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &gDisplay);
    LOG_ALWAYS_FATAL_IF(status, "Failed to get display info\n");
}

sp<SurfaceControl> createWindow(int width, int height) {
    sp<SurfaceControl> control = gSession->createSurface(String8("HwuiTest"),
            width, height, PIXEL_FORMAT_RGBX_8888);

    SurfaceComposerClient::openGlobalTransaction();
    control->setLayer(0x7FFFFFF);
    control->show();
    SurfaceComposerClient::closeGlobalTransaction();

    return control;
}
+33 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef TESTCONTEXT_H
#define TESTCONTEXT_H

#include <ui/DisplayInfo.h>
#include <gui/SurfaceControl.h>

extern android::DisplayInfo gDisplay;
#define dp(x) ((x) * gDisplay.density)

// Initializes all the static globals that are shared across all contexts
// such as display info
void createTestEnvironment();

// Defaults to fullscreen
android::sp<android::SurfaceControl> createWindow(int width = -1, int height = -1);

#endif
+130 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>

#include <cutils/log.h>
#include <gui/Surface.h>
#include <ui/PixelFormat.h>

#include <AnimationContext.h>
#include <DisplayListRenderer.h>
#include <RenderNode.h>
#include <renderthread/RenderProxy.h>

#include "TestContext.h"

using namespace android;
using namespace android::uirenderer;
using namespace android::uirenderer::renderthread;

class ContextFactory : public IContextFactory {
public:
    virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) {
        return new AnimationContext(clock);
    }
};

static DisplayListRenderer* startRecording(RenderNode* node) {
    DisplayListRenderer* renderer = new DisplayListRenderer();
    renderer->setViewport(node->getWidth(), node->getHeight());
    renderer->prepare(false);
    return renderer;
}

static void endRecording(DisplayListRenderer* renderer, RenderNode* node) {
    renderer->finish();
    node->setStagingDisplayList(renderer->finishRecording());
    delete renderer;
}

sp<RenderNode> createCard(int x, int y, int width, int height) {
    sp<RenderNode> node = new RenderNode();
    node->mutateStagingProperties().setLeftTopRightBottom(x, y, x + width, y + height);
    node->mutateStagingProperties().setElevation(dp(16));
    node->mutateStagingProperties().mutableOutline().setRoundRect(0, 0, width, height, dp(10), 1);
    node->mutateStagingProperties().mutableOutline().setShouldClip(true);
    node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y | RenderNode::Z);

    DisplayListRenderer* renderer = startRecording(node.get());
    renderer->drawColor(0xFFEEEEEE, SkXfermode::kSrcOver_Mode);
    endRecording(renderer, node.get());

    return node;
}

int main(int argc, char* argv[]) {
    createTestEnvironment();

    // create the native surface
    const int width = gDisplay.w;
    const int height = gDisplay.h;
    sp<SurfaceControl> control = createWindow(width, height);
    sp<Surface> surface = control->getSurface();

    RenderNode* rootNode = new RenderNode();
    rootNode->mutateStagingProperties().setLeftTopRightBottom(0, 0, width, height);
    rootNode->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
    rootNode->mutateStagingProperties().setClipToBounds(false);
    rootNode->setPropertyFieldsDirty(RenderNode::GENERIC);

    RenderProxy* proxy = new RenderProxy(false, rootNode, new ContextFactory());
    proxy->setFrameInterval(milliseconds_to_nanoseconds(16));
    proxy->loadSystemProperties();
    proxy->initialize(surface);
    float lightX = width / 2.0;
    proxy->setup(width, height, (Vector3){lightX, dp(-200.0f), dp(800.0f)},
            dp(800.0f), 255 * 0.075, 255 * 0.15);

    android::uirenderer::Rect DUMMY;

    std::vector< sp<RenderNode> > cards;

    DisplayListRenderer* renderer = startRecording(rootNode);
    renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
    renderer->insertReorderBarrier(true);

    for (int x = dp(16); x < (width - dp(116)); x += dp(116)) {
        for (int y = dp(16); y < (height - dp(116)); y += dp(116)) {
            sp<RenderNode> card = createCard(x, y, dp(100), dp(100));
            renderer->drawRenderNode(card.get(), DUMMY, 0);
            cards.push_back(card);
        }
    }

    renderer->insertReorderBarrier(false);
    endRecording(renderer, rootNode);

    for (int i = 0; i < 150; i++) {
        ATRACE_NAME("UI-Draw Frame");
        for (int ci = 0; ci < cards.size(); ci++) {
            cards[ci]->mutateStagingProperties().setTranslationX(i);
            cards[ci]->mutateStagingProperties().setTranslationY(i);
            cards[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
        }
        nsecs_t frameTimeNs = systemTime(CLOCK_MONOTONIC);
        proxy->syncAndDrawFrame(frameTimeNs, 0, gDisplay.density);
        usleep(12000);
    }

    sleep(5);

    delete proxy;
    rootNode->decStrong(0);

    printf("Success!\n");
    return 0;
}