// Copyright 2018 The Dawn Authors
//
// 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 "dawn_native/opengl/DeviceGL.h"

#include "dawn_native/BackendConnection.h"
#include "dawn_native/BindGroupLayout.h"
#include "dawn_native/ErrorData.h"
#include "dawn_native/StagingBuffer.h"
#include "dawn_native/opengl/BindGroupGL.h"
#include "dawn_native/opengl/BindGroupLayoutGL.h"
#include "dawn_native/opengl/BufferGL.h"
#include "dawn_native/opengl/CommandBufferGL.h"
#include "dawn_native/opengl/ComputePipelineGL.h"
#include "dawn_native/opengl/PipelineLayoutGL.h"
#include "dawn_native/opengl/QuerySetGL.h"
#include "dawn_native/opengl/QueueGL.h"
#include "dawn_native/opengl/RenderPipelineGL.h"
#include "dawn_native/opengl/SamplerGL.h"
#include "dawn_native/opengl/ShaderModuleGL.h"
#include "dawn_native/opengl/SwapChainGL.h"
#include "dawn_native/opengl/TextureGL.h"

namespace dawn_native { namespace opengl {

    // static
    ResultOrError<Device*> Device::Create(AdapterBase* adapter,
                                          const DeviceDescriptor* descriptor,
                                          const OpenGLFunctions& functions) {
        Ref<Device> device = AcquireRef(new Device(adapter, descriptor, functions));
        DAWN_TRY(device->Initialize());
        return device.Detach();
    }

    Device::Device(AdapterBase* adapter,
                   const DeviceDescriptor* descriptor,
                   const OpenGLFunctions& functions)
        : DeviceBase(adapter, descriptor), gl(functions) {
    }

    Device::~Device() {
        ShutDownBase();
    }

    MaybeError Device::Initialize() {
        InitTogglesFromDriver();
        mFormatTable = BuildGLFormatTable();

        return DeviceBase::Initialize(new Queue(this));
    }

    void Device::InitTogglesFromDriver() {
        bool supportsBaseVertex = gl.IsAtLeastGLES(3, 2) || gl.IsAtLeastGL(3, 2);

        bool supportsBaseInstance = gl.IsAtLeastGLES(3, 2) || gl.IsAtLeastGL(4, 2);

        // TODO(crbug.com/dawn/582): Use OES_draw_buffers_indexed where available.
        bool supportsIndexedDrawBuffers = gl.IsAtLeastGLES(3, 2) || gl.IsAtLeastGL(3, 0);

        bool supportsSnormRead =
            gl.IsAtLeastGL(4, 4) || gl.IsGLExtensionSupported("GL_EXT_render_snorm");

        bool supportsDepthStencilRead =
            gl.IsAtLeastGL(3, 0) || gl.IsGLExtensionSupported("GL_NV_read_depth_stencil");

        bool supportsSampleVariables = gl.IsAtLeastGL(4, 0) || gl.IsAtLeastGLES(3, 2) ||
                                       gl.IsGLExtensionSupported("GL_OES_sample_variables");

        // TODO(crbug.com/dawn/343): We can support the extension variants, but need to load the EXT
        // procs without the extension suffix.
        // We'll also need emulation of shader builtins gl_BaseVertex and gl_BaseInstance.

        // supportsBaseVertex |=
        //     (gl.IsAtLeastGLES(2, 0) &&
        //      (gl.IsGLExtensionSupported("OES_draw_elements_base_vertex") ||
        //       gl.IsGLExtensionSupported("EXT_draw_elements_base_vertex"))) ||
        //     (gl.IsAtLeastGL(3, 1) && gl.IsGLExtensionSupported("ARB_draw_elements_base_vertex"));

        // supportsBaseInstance |=
        //     (gl.IsAtLeastGLES(3, 1) && gl.IsGLExtensionSupported("EXT_base_instance")) ||
        //     (gl.IsAtLeastGL(3, 1) && gl.IsGLExtensionSupported("ARB_base_instance"));

        // TODO(crbug.com/dawn/343): Investigate emulation.
        SetToggle(Toggle::DisableBaseVertex, !supportsBaseVertex);
        SetToggle(Toggle::DisableBaseInstance, !supportsBaseInstance);
        SetToggle(Toggle::DisableIndexedDrawBuffers, !supportsIndexedDrawBuffers);
        SetToggle(Toggle::DisableSnormRead, !supportsSnormRead);
        SetToggle(Toggle::DisableDepthStencilRead, !supportsDepthStencilRead);
        SetToggle(Toggle::DisableSampleVariables, !supportsSampleVariables);
        SetToggle(Toggle::FlushBeforeClientWaitSync, gl.GetVersion().IsES());
    }

    const GLFormat& Device::GetGLFormat(const Format& format) {
        ASSERT(format.isSupported);
        ASSERT(format.GetIndex() < mFormatTable.size());

        const GLFormat& result = mFormatTable[format.GetIndex()];
        ASSERT(result.isSupportedOnBackend);
        return result;
    }

    ResultOrError<Ref<BindGroupBase>> Device::CreateBindGroupImpl(
        const BindGroupDescriptor* descriptor) {
        DAWN_TRY(ValidateGLBindGroupDescriptor(descriptor));
        return BindGroup::Create(this, descriptor);
    }
    ResultOrError<Ref<BindGroupLayoutBase>> Device::CreateBindGroupLayoutImpl(
        const BindGroupLayoutDescriptor* descriptor) {
        return AcquireRef(new BindGroupLayout(this, descriptor));
    }
    ResultOrError<Ref<BufferBase>> Device::CreateBufferImpl(const BufferDescriptor* descriptor) {
        return AcquireRef(new Buffer(this, descriptor));
    }
    ResultOrError<Ref<CommandBufferBase>> Device::CreateCommandBuffer(
        CommandEncoder* encoder,
        const CommandBufferDescriptor* descriptor) {
        return AcquireRef(new CommandBuffer(encoder, descriptor));
    }
    ResultOrError<Ref<ComputePipelineBase>> Device::CreateComputePipelineImpl(
        const ComputePipelineDescriptor* descriptor) {
        return ComputePipeline::Create(this, descriptor);
    }
    ResultOrError<Ref<PipelineLayoutBase>> Device::CreatePipelineLayoutImpl(
        const PipelineLayoutDescriptor* descriptor) {
        return AcquireRef(new PipelineLayout(this, descriptor));
    }
    ResultOrError<Ref<QuerySetBase>> Device::CreateQuerySetImpl(
        const QuerySetDescriptor* descriptor) {
        return AcquireRef(new QuerySet(this, descriptor));
    }
    ResultOrError<Ref<RenderPipelineBase>> Device::CreateRenderPipelineImpl(
        const RenderPipelineDescriptor* descriptor) {
        return RenderPipeline::Create(this, descriptor);
    }
    ResultOrError<Ref<SamplerBase>> Device::CreateSamplerImpl(const SamplerDescriptor* descriptor) {
        return AcquireRef(new Sampler(this, descriptor));
    }
    ResultOrError<Ref<ShaderModuleBase>> Device::CreateShaderModuleImpl(
        const ShaderModuleDescriptor* descriptor,
        ShaderModuleParseResult* parseResult) {
        return ShaderModule::Create(this, descriptor, parseResult);
    }
    ResultOrError<Ref<SwapChainBase>> Device::CreateSwapChainImpl(
        const SwapChainDescriptor* descriptor) {
        return AcquireRef(new SwapChain(this, descriptor));
    }
    ResultOrError<Ref<NewSwapChainBase>> Device::CreateSwapChainImpl(
        Surface* surface,
        NewSwapChainBase* previousSwapChain,
        const SwapChainDescriptor* descriptor) {
        return DAWN_VALIDATION_ERROR("New swapchains not implemented.");
    }
    ResultOrError<Ref<TextureBase>> Device::CreateTextureImpl(const TextureDescriptor* descriptor) {
        return AcquireRef(new Texture(this, descriptor));
    }
    ResultOrError<Ref<TextureViewBase>> Device::CreateTextureViewImpl(
        TextureBase* texture,
        const TextureViewDescriptor* descriptor) {
        return AcquireRef(new TextureView(texture, descriptor));
    }

    void Device::SubmitFenceSync() {
        GLsync sync = gl.FenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
        IncrementLastSubmittedCommandSerial();
        mFencesInFlight.emplace(sync, GetLastSubmittedCommandSerial());
    }

    MaybeError Device::ValidateEGLImageCanBeWrapped(const TextureDescriptor* descriptor,
                                                    ::EGLImage image) {
        if (descriptor->dimension != wgpu::TextureDimension::e2D) {
            return DAWN_VALIDATION_ERROR("EGLImage texture must be 2D");
        }

        if (descriptor->usage & (wgpu::TextureUsage::Sampled | wgpu::TextureUsage::Storage)) {
            return DAWN_VALIDATION_ERROR("EGLImage texture cannot have sampled or storage usage");
        }

        if (descriptor->mipLevelCount != 1) {
            return DAWN_VALIDATION_ERROR("EGLImage mip level count must be 1");
        }

        if (descriptor->size.depthOrArrayLayers != 1) {
            return DAWN_VALIDATION_ERROR("EGLImage array layer count must be 1");
        }

        if (descriptor->sampleCount != 1) {
            return DAWN_VALIDATION_ERROR("EGLImage sample count must be 1");
        }

        return {};
    }
    TextureBase* Device::CreateTextureWrappingEGLImage(const ExternalImageDescriptor* descriptor,
                                                       ::EGLImage image) {
        const TextureDescriptor* textureDescriptor =
            reinterpret_cast<const TextureDescriptor*>(descriptor->cTextureDescriptor);

        if (ConsumedError(ValidateTextureDescriptor(this, textureDescriptor))) {
            return nullptr;
        }
        if (ConsumedError(ValidateEGLImageCanBeWrapped(textureDescriptor, image))) {
            return nullptr;
        }

        GLuint tex;
        gl.GenTextures(1, &tex);
        gl.BindTexture(GL_TEXTURE_2D, tex);
        gl.EGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);

        GLint width, height, internalFormat;
        gl.GetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
        gl.GetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
        gl.GetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internalFormat);

        if (textureDescriptor->size.width != static_cast<uint32_t>(width) ||
            textureDescriptor->size.height != static_cast<uint32_t>(height) ||
            textureDescriptor->size.depthOrArrayLayers != 1) {
            ConsumedError(DAWN_VALIDATION_ERROR("EGLImage size doesn't match descriptor"));
            gl.DeleteTextures(1, &tex);
            return nullptr;
        }

        // TODO(dawn:803): Validate the OpenGL texture format from the EGLImage against the format
        // in the passed-in TextureDescriptor.
        return new Texture(this, textureDescriptor, tex, TextureBase::TextureState::OwnedInternal);
    }

    MaybeError Device::TickImpl() {
        return {};
    }

    ResultOrError<ExecutionSerial> Device::CheckAndUpdateCompletedSerials() {
        ExecutionSerial fenceSerial{0};
        while (!mFencesInFlight.empty()) {
            GLsync sync = mFencesInFlight.front().first;
            ExecutionSerial tentativeSerial = mFencesInFlight.front().second;

            // Fence are added in order, so we can stop searching as soon
            // as we see one that's not ready.

            // TODO(crbug.com/dawn/633): Remove this workaround after the deadlock issue is fixed.
            if (IsToggleEnabled(Toggle::FlushBeforeClientWaitSync)) {
                gl.Flush();
            }
            GLenum result = gl.ClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, 0);
            if (result == GL_TIMEOUT_EXPIRED) {
                return fenceSerial;
            }
            // Update fenceSerial since fence is ready.
            fenceSerial = tentativeSerial;

            gl.DeleteSync(sync);

            mFencesInFlight.pop();

            ASSERT(fenceSerial > GetCompletedCommandSerial());
        }
        return fenceSerial;
    }

    ResultOrError<std::unique_ptr<StagingBufferBase>> Device::CreateStagingBuffer(size_t size) {
        return DAWN_UNIMPLEMENTED_ERROR("Device unable to create staging buffer.");
    }

    MaybeError Device::CopyFromStagingToBuffer(StagingBufferBase* source,
                                               uint64_t sourceOffset,
                                               BufferBase* destination,
                                               uint64_t destinationOffset,
                                               uint64_t size) {
        return DAWN_UNIMPLEMENTED_ERROR("Device unable to copy from staging buffer.");
    }

    MaybeError Device::CopyFromStagingToTexture(const StagingBufferBase* source,
                                                const TextureDataLayout& src,
                                                TextureCopy* dst,
                                                const Extent3D& copySizePixels) {
        return DAWN_UNIMPLEMENTED_ERROR("Device unable to copy from staging buffer to texture.");
    }

    void Device::ShutDownImpl() {
        ASSERT(GetState() == State::Disconnected);
    }

    MaybeError Device::WaitForIdleForDestruction() {
        gl.Finish();
        DAWN_TRY(CheckPassedSerials());
        ASSERT(mFencesInFlight.empty());

        return {};
    }

    uint32_t Device::GetOptimalBytesPerRowAlignment() const {
        return 1;
    }

    uint64_t Device::GetOptimalBufferToTextureCopyOffsetAlignment() const {
        return 1;
    }

    float Device::GetTimestampPeriodInNS() const {
        return 1.0f;
    }

}}  // namespace dawn_native::opengl
