/*
 * Copyright (C) 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.
 */

#include "SkiaOpenGLReadback.h"

#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <GrBackendSurface.h>
#include <SkCanvas.h>
#include <SkSurface.h>
#include <gl/GrGLInterface.h>
#include <gl/GrGLTypes.h>
#include "DeviceInfo.h"
#include "Matrix.h"
#include "Properties.h"
#include "utils/MathUtils.h"

using namespace android::uirenderer::renderthread;

namespace android {
namespace uirenderer {
namespace skiapipeline {

CopyResult SkiaOpenGLReadback::copyImageInto(EGLImageKHR eglImage, const Matrix4& imgTransform,
                                             int imgWidth, int imgHeight, const Rect& srcRect,
                                             SkBitmap* bitmap) {
    GLuint sourceTexId;
    glGenTextures(1, &sourceTexId);
    glBindTexture(GL_TEXTURE_EXTERNAL_OES, sourceTexId);
    glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, eglImage);

    sk_sp<GrContext> grContext = sk_ref_sp(mRenderThread.getGrContext());
    if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
        sk_sp<const GrGLInterface> glInterface(GrGLCreateNativeInterface());
        LOG_ALWAYS_FATAL_IF(!glInterface.get());
        grContext = GrContext::MakeGL(std::move(glInterface));
    } else {
        grContext->resetContext();
    }

    GrGLTextureInfo externalTexture;
    externalTexture.fTarget = GL_TEXTURE_EXTERNAL_OES;
    externalTexture.fID = sourceTexId;

    GrPixelConfig pixelConfig;
    switch (bitmap->colorType()) {
        case kRGBA_F16_SkColorType:
            pixelConfig = kRGBA_half_GrPixelConfig;
            break;
        case kN32_SkColorType:
        default:
            pixelConfig = kRGBA_8888_GrPixelConfig;
            break;
    }

    if (pixelConfig == kRGBA_half_GrPixelConfig &&
            !grContext->caps()->isConfigRenderable(kRGBA_half_GrPixelConfig, false)) {
        ALOGW("Can't copy surface into bitmap, RGBA_F16 config is not supported");
        return CopyResult::DestinationInvalid;
    }

    GrBackendTexture backendTexture(imgWidth, imgHeight, pixelConfig, externalTexture);

    CopyResult copyResult = CopyResult::UnknownError;
    sk_sp<SkImage> image(SkImage::MakeFromAdoptedTexture(grContext.get(), backendTexture,
                                                         kTopLeft_GrSurfaceOrigin));
    if (image) {
        int displayedWidth = imgWidth, displayedHeight = imgHeight;
        // If this is a 90 or 270 degree rotation we need to swap width/height to get the device
        // size.
        if (imgTransform[Matrix4::kSkewX] >= 0.5f || imgTransform[Matrix4::kSkewX] <= -0.5f) {
            std::swap(displayedWidth, displayedHeight);
        }
        SkRect skiaDestRect = SkRect::MakeWH(bitmap->width(), bitmap->height());
        SkRect skiaSrcRect = srcRect.toSkRect();
        if (skiaSrcRect.isEmpty()) {
            skiaSrcRect = SkRect::MakeIWH(displayedWidth, displayedHeight);
        }
        bool srcNotEmpty = skiaSrcRect.intersect(SkRect::MakeIWH(displayedWidth, displayedHeight));

        if (srcNotEmpty) {
            SkMatrix textureMatrixInv;
            imgTransform.copyTo(textureMatrixInv);
            // TODO: after skia bug https://bugs.chromium.org/p/skia/issues/detail?id=7075 is fixed
            // use bottom left origin and remove flipV and invert transformations.
            SkMatrix flipV;
            flipV.setAll(1, 0, 0, 0, -1, 1, 0, 0, 1);
            textureMatrixInv.preConcat(flipV);
            textureMatrixInv.preScale(1.0f / displayedWidth, 1.0f / displayedHeight);
            textureMatrixInv.postScale(imgWidth, imgHeight);
            SkMatrix textureMatrix;
            if (!textureMatrixInv.invert(&textureMatrix)) {
                textureMatrix = textureMatrixInv;
            }

            textureMatrixInv.mapRect(&skiaSrcRect);
            textureMatrixInv.mapRect(&skiaDestRect);

            // we render in an offscreen buffer to scale and to avoid an issue b/62262733
            // with reading incorrect data from EGLImage backed SkImage (likely a driver bug)
            sk_sp<SkSurface> scaledSurface =
                    SkSurface::MakeRenderTarget(grContext.get(), SkBudgeted::kYes, bitmap->info());
            SkPaint paint;
            paint.setBlendMode(SkBlendMode::kSrc);
            // Apply a filter, which is matching OpenGL pipeline readback behaviour. Filter usage
            // is codified by tests using golden images like DecodeAccuracyTest.
            bool disableFilter = MathUtils::areEqual(skiaSrcRect.width(), skiaDestRect.width())
                    && MathUtils::areEqual(skiaSrcRect.height(), skiaDestRect.height());
            if (!disableFilter) {
                paint.setFilterQuality(kLow_SkFilterQuality);
            }
            scaledSurface->getCanvas()->concat(textureMatrix);
            scaledSurface->getCanvas()->drawImageRect(image, skiaSrcRect, skiaDestRect, &paint,
                                                      SkCanvas::kFast_SrcRectConstraint);

            image = scaledSurface->makeImageSnapshot();

            if (image->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), 0, 0)) {
                bitmap->notifyPixelsChanged();
                copyResult = CopyResult::Success;
            }
        }
    }

    // make sure that we have deleted the texture (in the SkImage) before we
    // destroy the EGLImage that it was created from
    image.reset();
    return copyResult;
}

} /* namespace skiapipeline */
} /* namespace uirenderer */
} /* namespace android */
