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

Commit c1ba5c46 authored by Sahil Dhanju's avatar Sahil Dhanju
Browse files

Multithreaded Surface Replayer that replays traces

Change-Id: Id8d17f74e00d4796e1ea266bdaf9e8dd0af6475b
parent a05cafa1
Loading
Loading
Loading
Loading
+0 −136
Original line number Original line Diff line number Diff line
syntax = "proto2";

message Trace {
    repeated Increment increment = 1;
}

message Increment {
    required int64 time_stamp       = 1;

    oneof increment {
        Transaction  transaction    = 2;
        Create       create         = 3;
        Delete       delete         = 4;
        BufferUpdate buffer_update  = 5;
        VSyncEvent   vsync_event    = 6;
    }
}

message Transaction {
    repeated Change change      = 1;

    required bool   synchronous = 2;
    required bool   animation   = 3;
}

message Change {
    required uint32 id = 1;

    oneof Change {
        PositionChange              position                   = 2;
        SizeChange                  size                       = 3;
        AlphaChange                 alpha                      = 4;
        LayerChange                 layer                      = 5;
        CropChange                  crop                       = 6;
        FinalCropChange             final_crop                 = 7;
        MatrixChange                matrix                     = 8;
        OverrideScalingModeChange   override_scaling_mode      = 9;
        TransparentRegionHintChange transparent_region_hint    = 10;
        LayerStackChange            layer_stack                = 11;
        HiddenFlagChange            hidden_flag                = 12;
        OpaqueFlagChange            opaque_flag                = 13;
        SecureFlagChange            secure_flag                = 14;
        DeferredTransactionChange   deferred_transaction       = 15;
    }
}

message PositionChange {
    required float x = 1;
    required float y = 2;
}

message SizeChange {
    required uint32 w = 1;
    required uint32 h = 2;
}

message AlphaChange {
    required float alpha = 1;
}

message LayerChange {
    required uint32 layer = 1;
}

message CropChange {
    required Rectangle rectangle = 1;
}

message FinalCropChange {
    required Rectangle rectangle = 1;
}

message MatrixChange {
    required float dsdx = 1;
    required float dtdx = 2;
    required float dsdy = 3;
    required float dtdy = 4;
}

message OverrideScalingModeChange {
    required int32 override_scaling_mode = 1;
}

message TransparentRegionHintChange {
    repeated Rectangle region = 1;
}

message LayerStackChange {
    required uint32 layer_stack = 1;
}

message HiddenFlagChange {
    required bool hidden_flag = 1;
}

message OpaqueFlagChange {
    required bool opaque_flag = 1;
}

message SecureFlagChange {
    required bool secure_flag = 1;
}

message DeferredTransactionChange {
    required uint32 layer_id     = 1;
    required uint64 frame_number = 2;
}

message Rectangle {
    required int32 left   = 1;
    required int32 top    = 2;
    required int32 right  = 3;
    required int32 bottom = 4;
}

message Create {
    required uint32 id    = 1;
    required string name  = 2;
    required uint32 w     = 3;
    required uint32 h     = 4;
}

message Delete {
    required uint32 id = 1;
}

message BufferUpdate {
    required uint32 id            = 1;
    required uint32 w             = 2;
    required uint32 h             = 3;
    required uint64 frame_number  = 4;
}

message VSyncEvent {
    required int64 when = 1;
}
+71 −0
Original line number Original line Diff line number Diff line
#
# Copyright 2016 The Android Open Source Project
# Copyright (C) 2016 The Android Open Source Project
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# you may not use this file except in compliance with the License.
@@ -12,22 +11,61 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# See the License for the specific language governing permissions and
# limitations under the License.
# limitations under the License.
#

LOCAL_TARGET_DIR := $(TARGET_OUT_DATA)/local/tmp

LOCAL_PATH:= $(call my-dir)
LOCAL_PATH:= $(call my-dir)

include $(call first-makefiles-under, /frameworks/native/cmds/surfacereplayer/proto)

include $(CLEAR_VARS)
include $(CLEAR_VARS)


LOCAL_SRC_FILES := $(call all-proto-files-under, src)
LOCAL_CPPFLAGS := -Weverything -Werror
LOCAL_CPPFLAGS := -Wno-unused-parameter
LOCAL_CPPFLAGS := -Wno-format

LOCAL_MODULE := libsurfacereplayer

LOCAL_SRC_FILES := \
    BufferQueueScheduler.cpp \
    Event.cpp \
    Replayer.cpp \


LOCAL_SHARED_LIBRARIES := \
LOCAL_SHARED_LIBRARIES := \
    libprotobuf-cpp-full
    libEGL \
    libGLESv2 \
    libbinder \
    libcutils \
    libgui \
    libui \
    libutils \
    libprotobuf-cpp-full \


LOCAL_PROTOC_OPTIMIZE_TYPE := full
LOCAL_STATIC_LIBRARIES := \
    libtrace_proto \


LOCAL_MODULE := libtrace_proto
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/..
LOCAL_MODULE_CLASS := STATIC_LIBRARIES

include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)

LOCAL_MODULE := surfacereplayer

LOCAL_SRC_FILES := \
    Main.cpp \

LOCAL_SHARED_LIBRARIES := \
    libprotobuf-cpp-full \
    libsurfacereplayer \
    libutils \


LOCAL_STATIC_LIBRARIES := \
    libtrace_proto \


LOCAL_CPPFLAGS := -Weverything -Werror
LOCAL_CPPFLAGS := -Wno-unused-parameter


LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
LOCAL_MODULE_PATH := $(LOCAL_TARGET_DIR)


include $(BUILD_STATIC_LIBRARY)
include $(BUILD_EXECUTABLE)
+106 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright 2016 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.
 */
#define LOG_TAG "BufferQueueScheduler"

#include "BufferQueueScheduler.h"

#include <android/native_window.h>
#include <gui/Surface.h>

using namespace android;

BufferQueueScheduler::BufferQueueScheduler(
        const sp<SurfaceControl>& surfaceControl, const RGB& color, int id)
      : mSurfaceControl(surfaceControl), mColor(color), mSurfaceId(id), mContinueScheduling(true) {}

void BufferQueueScheduler::startScheduling() {
    ALOGV("Starting Scheduler for %d Layer", mSurfaceId);
    std::unique_lock<std::mutex> lock(mMutex);
    if (mSurfaceControl == nullptr) {
        mCondition.wait(lock, [&] { return (mSurfaceControl != nullptr); });
    }

    while (mContinueScheduling) {
        while (true) {
            if (mBufferEvents.empty()) {
                break;
            }

            BufferEvent event = mBufferEvents.front();
            lock.unlock();

            bufferUpdate(event.dimensions);
            fillSurface(event.event);
            lock.lock();
            mBufferEvents.pop();
        }
        mCondition.wait(lock);
    }
}

void BufferQueueScheduler::addEvent(const BufferEvent& event) {
    std::lock_guard<std::mutex> lock(mMutex);
    mBufferEvents.push(event);
    mCondition.notify_one();
}

void BufferQueueScheduler::stopScheduling() {
    std::lock_guard<std::mutex> lock(mMutex);
    mContinueScheduling = false;
    mCondition.notify_one();
}

void BufferQueueScheduler::setSurfaceControl(
        const sp<SurfaceControl>& surfaceControl, const RGB& color) {
    std::lock_guard<std::mutex> lock(mMutex);
    mSurfaceControl = surfaceControl;
    mColor = color;
    mCondition.notify_one();
}

void BufferQueueScheduler::bufferUpdate(const Dimensions& dimensions) {
    sp<Surface> s = mSurfaceControl->getSurface();
    s->setBuffersDimensions(dimensions.width, dimensions.height);
}

void BufferQueueScheduler::fillSurface(std::shared_ptr<Event> event) {
    ANativeWindow_Buffer outBuffer;
    sp<Surface> s = mSurfaceControl->getSurface();

    status_t status = s->lock(&outBuffer, nullptr);

    if (status != NO_ERROR) {
        ALOGE("fillSurface: failed to lock buffer, (%d)", status);
        return;
    }

    auto img = reinterpret_cast<uint8_t*>(outBuffer.bits);
    for (int y = 0; y < outBuffer.height; y++) {
        for (int x = 0; x < outBuffer.width; x++) {
            uint8_t* pixel = img + (4 * (y * outBuffer.stride + x));
            pixel[0] = mColor.r;
            pixel[1] = mColor.g;
            pixel[2] = mColor.b;
            pixel[3] = LAYER_ALPHA;
        }
    }

    event->readyToExecute();

    status = s->unlockAndPost();

    ALOGE_IF(status != NO_ERROR, "fillSurface: failed to unlock and post buffer, (%d)", status);
}
+82 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright 2016 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 ANDROID_SURFACEREPLAYER_BUFFERQUEUESCHEDULER_H
#define ANDROID_SURFACEREPLAYER_BUFFERQUEUESCHEDULER_H

#include "Color.h"
#include "Event.h"

#include <gui/SurfaceControl.h>

#include <utils/StrongPointer.h>

#include <atomic>
#include <condition_variable>
#include <mutex>
#include <queue>
#include <utility>

namespace android {

auto constexpr LAYER_ALPHA = 190;

struct Dimensions {
    Dimensions() = default;
    Dimensions(int w, int h) : width(w), height(h) {}

    int width = 0;
    int height = 0;
};

struct BufferEvent {
    BufferEvent() = default;
    BufferEvent(std::shared_ptr<Event> e, Dimensions d) : event(e), dimensions(d) {}

    std::shared_ptr<Event> event;
    Dimensions dimensions;
};

class BufferQueueScheduler {
  public:
    BufferQueueScheduler(const sp<SurfaceControl>& surfaceControl, const RGB& color, int id);

    void startScheduling();
    void addEvent(const BufferEvent&);
    void stopScheduling();

    void setSurfaceControl(const sp<SurfaceControl>& surfaceControl, const RGB& color);

  private:
    void bufferUpdate(const Dimensions& dimensions);

    // Lock and fill the surface, block until the event is signaled by the main loop,
    // then unlock and post the buffer.
    void fillSurface(std::shared_ptr<Event>);

    sp<SurfaceControl> mSurfaceControl;
    RGB mColor;
    const int mSurfaceId;

    bool mContinueScheduling;

    std::queue<BufferEvent> mBufferEvents;
    std::mutex mMutex;
    std::condition_variable mCondition;
};

}  // namespace android
#endif
+104 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright 2016 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 ANDROID_SURFACEREPLAYER_COLOR_H
#define ANDROID_SURFACEREPLAYER_COLOR_H

#include <cmath>
#include <cstdlib>

namespace android {

typedef struct RGB {
    RGB() = default;
    RGB(uint8_t rIn, uint8_t gIn, uint8_t bIn) : r(rIn), g(gIn), b(bIn) {}

    uint8_t r = 0;
    uint8_t g = 0;
    uint8_t b = 0;
} RGB;

typedef struct HSV {
    HSV() = default;
    HSV(double hIn, double sIn, double vIn) : h(hIn), s(sIn), v(vIn) {}

    double h = 0;
    double s = 0;
    double v = 0;
} HSV;

static inline RGB HSVToRGB(HSV hsv) {
    using namespace std;
    double r = 0, g = 0, b = 0;

    if (hsv.s == 0) {
        r = hsv.v;
        g = hsv.v;
        b = hsv.v;
    } else {
        hsv.h = static_cast<int>(hsv.h) % 360;
        hsv.h = hsv.h / 60;

        int i = static_cast<int>(trunc(hsv.h));
        double f = hsv.h - i;

        double x = hsv.v * (1.0 - hsv.s);
        double y = hsv.v * (1.0 - (hsv.s * f));
        double z = hsv.v * (1.0 - (hsv.s * (1.0 - f)));

        switch (i) {
            case 0:
                r = hsv.v;
                g = z;
                b = x;
                break;

            case 1:
                r = y;
                g = hsv.v;
                b = x;
                break;

            case 2:
                r = x;
                g = hsv.v;
                b = z;
                break;

            case 3:
                r = x;
                g = y;
                b = hsv.v;
                break;

            case 4:
                r = z;
                g = x;
                b = hsv.v;
                break;

            default:
                r = hsv.v;
                g = x;
                b = y;
                break;
        }
    }

    return RGB(round(r * 255), round(g * 255), round(b * 255));
}
}
#endif
Loading