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

Commit 57137587 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Implement color layers in RenderEngine::drawLayers"

parents 5c3e65ea 1089aede
Loading
Loading
Loading
Loading
+85 −16
Original line number Diff line number Diff line
@@ -648,27 +648,89 @@ bool GLESRenderEngine::useProtectedContext(bool useProtectedContext) {
    return success;
}

status_t GLESRenderEngine::drawLayers(const DisplaySettings& /*settings*/,
                                      const std::vector<LayerSettings>& /*layers*/,
                                      ANativeWindowBuffer* const /*buffer*/,
                                      base::unique_fd* /*displayFence*/) const {
status_t GLESRenderEngine::drawLayers(const DisplaySettings& display,
                                      const std::vector<LayerSettings>& layers,
                                      ANativeWindowBuffer* const buffer,
                                      base::unique_fd* drawFence) {
    if (layers.empty()) {
        ALOGV("Drawing empty layer stack");
        return NO_ERROR;
    }

    BindNativeBufferAsFramebuffer fbo(*this, buffer);

    if (fbo.getStatus() != NO_ERROR) {
        ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).",
              buffer->handle);
        checkErrors();
        return fbo.getStatus();
    }

    setViewportAndProjection(display.physicalDisplay, display.clip);

    setOutputDataSpace(display.outputDataspace);
    setDisplayMaxLuminance(display.maxLuminance);

    mat4 projectionMatrix = mState.projectionMatrix * display.globalTransform;

    Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2);
    for (auto layer : layers) {
        // for now, assume that all pixel sources are solid colors.
        // TODO(alecmouri): support buffer sources
        if (layer.source.buffer.buffer != nullptr) {
            continue;
        }

        setColorTransform(display.colorTransform * layer.colorTransform);

        mState.projectionMatrix = projectionMatrix * layer.geometry.positionTransform;

        FloatRect bounds = layer.geometry.boundaries;
        Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
        position[0] = vec2(bounds.left, bounds.top);
        position[1] = vec2(bounds.left, bounds.bottom);
        position[2] = vec2(bounds.right, bounds.bottom);
        position[3] = vec2(bounds.right, bounds.top);

        half3 solidColor = layer.source.solidColor;
        half4 color = half4(solidColor.r, solidColor.g, solidColor.b, layer.alpha);
        setupLayerBlending(/*premultipliedAlpha=*/true, /*opaque=*/false, /*disableTexture=*/true,
                           color, /*cornerRadius=*/0.0);
        setSourceDataSpace(layer.sourceDataspace);

        drawMesh(mesh);
    }

    *drawFence = flush();
    // If flush failed or we don't support native fences, we need to force the
    // gl command stream to be executed.
    if (drawFence->get() < 0) {
        bool success = finish();
        if (!success) {
            ALOGE("Failed to flush RenderEngine commands");
            checkErrors();
            // Chances are, something illegal happened (either the caller passed
            // us bad parameters, or we messed up our shader generation).
            return INVALID_OPERATION;
        }
    }

    checkErrors();
    return NO_ERROR;
}

void GLESRenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
                                                ui::Transform::orientation_flags rotation) {
    int32_t l = sourceCrop.left;
    int32_t r = sourceCrop.right;
    int32_t b = sourceCrop.bottom;
    int32_t t = sourceCrop.top;
    std::swap(t, b);
    mat4 m = mat4::ortho(l, r, b, t, 0, 1);
    setViewportAndProjection(Rect(vpw, vph), sourceCrop);

    if (rotation == ui::Transform::ROT_0) {
        return;
    }

    // Apply custom rotation to the projection.
    float rot90InRadians = 2.0f * static_cast<float>(M_PI) / 4.0f;
    mat4 m = mState.projectionMatrix;
    switch (rotation) {
        case ui::Transform::ROT_0:
            break;
        case ui::Transform::ROT_90:
            m = mat4::rotate(rot90InRadians, vec3(0, 0, 1)) * m;
            break;
@@ -681,11 +743,18 @@ void GLESRenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect sou
        default:
            break;
    }

    glViewport(0, 0, vpw, vph);
    mState.projectionMatrix = m;
    mVpWidth = vpw;
    mVpHeight = vph;
}

void GLESRenderEngine::setViewportAndProjection(Rect viewport, Rect clip) {
    mVpWidth = viewport.getWidth();
    mVpHeight = viewport.getHeight();

    // We pass the the top left corner instead of the bottom left corner,
    // because since we're rendering off-screen first.
    glViewport(viewport.left, viewport.top, mVpWidth, mVpHeight);

    mState.projectionMatrix = mat4::ortho(clip.left, clip.right, clip.top, clip.bottom, 0, 1);
}

void GLESRenderEngine::setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
+5 −3
Original line number Diff line number Diff line
@@ -72,9 +72,8 @@ public:
    bool isProtected() const override { return mInProtectedContext; }
    bool supportsProtectedContent() const override;
    bool useProtectedContext(bool useProtectedContext) override;
    status_t drawLayers(const DisplaySettings& settings, const std::vector<LayerSettings>& layers,
                        ANativeWindowBuffer* const buffer,
                        base::unique_fd* displayFence) const override;
    status_t drawLayers(const DisplaySettings& display, const std::vector<LayerSettings>& layers,
                        ANativeWindowBuffer* buffer, base::unique_fd* drawFence) override;

    // internal to RenderEngine
    EGLDisplay getEGLDisplay() const { return mEGLDisplay; }
@@ -125,6 +124,9 @@ private:
    // with PQ or HLG transfer function.
    bool isHdrDataSpace(const ui::Dataspace dataSpace) const;
    bool needsXYZTransformMatrix() const;
    // Defines the viewport, and sets the projection matrix to the projection
    // defined by the clip.
    void setViewportAndProjection(Rect viewport, Rect clip);

    EGLDisplay mEGLDisplay;
    EGLConfig mEGLConfig;
+1 −1
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ struct DisplaySettings {
    mat4 globalTransform = mat4();

    // Maximum luminance pulled from the display's HDR capabilities.
    float maxLuminence = 1.0f;
    float maxLuminance = 1.0f;

    // Output dataspace that will be populated if wide color gamut is used, or
    // DataSpace::UNKNOWN otherwise.
+5 −1
Original line number Diff line number Diff line
@@ -85,7 +85,11 @@ struct LayerSettings {
    half alpha = half(0.0);

    // Color space describing how the source pixels should be interpreted.
    ui::Dataspace sourceDataspace = ui::Dataspace::UNKNOWN;
    ui::Dataspace sourceDataspace;

    // Additional layer-specific color transform to be applied before the global
    // transform.
    mat4 colorTransform;
};

} // namespace renderengine
+4 −5
Original line number Diff line number Diff line
@@ -161,12 +161,12 @@ public:

    // Renders layers for a particular display via GPU composition. This method
    // should be called for every display that needs to be rendered via the GPU.
    // @param settings The display-wide settings that should be applied prior to
    // @param display The display-wide settings that should be applied prior to
    // drawing any layers.
    // @param layers The layers to draw onto the display, in Z-order.
    // @param buffer The buffer which will be drawn to. This buffer will be
    // ready once displayFence fires.
    // @param displayFence A pointer to a fence, which will fire when the buffer
    // @param drawFence A pointer to a fence, which will fire when the buffer
    // has been drawn to and is ready to be examined. The fence will be
    // initialized by this method. The caller will be responsible for owning the
    // fence.
@@ -174,10 +174,9 @@ public:
    // now, this always returns NO_ERROR.
    // TODO(alecmouri): Consider making this a multi-display API, so that the
    // caller deoes not need to handle multiple fences.
    virtual status_t drawLayers(const DisplaySettings& settings,
    virtual status_t drawLayers(const DisplaySettings& display,
                                const std::vector<LayerSettings>& layers,
                                ANativeWindowBuffer* const buffer,
                                base::unique_fd* displayFence) const = 0;
                                ANativeWindowBuffer* buffer, base::unique_fd* drawFence) = 0;

    // TODO(alecmouri): Expose something like bindTexImage() so that devices
    // that don't support native sync fences can get rid of code duplicated
Loading