/*
 * Copyright 2010 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */


#include "GrGpu.h"

#include "GrBackendSemaphore.h"
#include "GrBackendSurface.h"
#include "GrBuffer.h"
#include "GrCaps.h"
#include "GrContext.h"
#include "GrContextPriv.h"
#include "GrGpuResourcePriv.h"
#include "GrMesh.h"
#include "GrPathRendering.h"
#include "GrPipeline.h"
#include "GrRenderTargetPriv.h"
#include "GrResourceCache.h"
#include "GrResourceProvider.h"
#include "GrSemaphore.h"
#include "GrStencilAttachment.h"
#include "GrStencilSettings.h"
#include "GrSurfacePriv.h"
#include "GrTexturePriv.h"
#include "GrTextureProxyPriv.h"
#include "GrTracing.h"
#include "SkJSONWriter.h"
#include "SkMathPriv.h"

////////////////////////////////////////////////////////////////////////////////

GrGpu::GrGpu(GrContext* context)
    : fResetTimestamp(kExpiredTimestamp+1)
    , fResetBits(kAll_GrBackendState)
    , fContext(context) {
}

GrGpu::~GrGpu() {}

void GrGpu::disconnect(DisconnectType) {}

////////////////////////////////////////////////////////////////////////////////

bool GrGpu::IsACopyNeededForTextureParams(const GrCaps* caps, GrTextureProxy* texProxy,
                                          int width, int height,
                                          const GrSamplerState& textureParams,
                                          GrTextureProducer::CopyParams* copyParams,
                                          SkScalar scaleAdjust[2]) {

    if (texProxy) {
        // If the texture format itself doesn't support repeat wrap mode or mipmapping (and
        // those capabilities are required) force a copy.
        if ((textureParams.isRepeated() && texProxy->texPriv().isClampOnly()) ||
            (GrSamplerState::Filter::kMipMap == textureParams.filter() &&
                                                    texProxy->texPriv().doesNotSupportMipMaps())) {
            copyParams->fFilter = GrSamplerState::Filter::kNearest;
            copyParams->fWidth = texProxy->width();
            copyParams->fHeight = texProxy->height();
            return true;
        }
    }

    if (textureParams.isRepeated() && !caps->npotTextureTileSupport() &&
        (!SkIsPow2(width) || !SkIsPow2(height))) {
        SkASSERT(scaleAdjust);
        copyParams->fWidth = GrNextPow2(width);
        copyParams->fHeight = GrNextPow2(height);
        scaleAdjust[0] = ((SkScalar) copyParams->fWidth) / width;
        scaleAdjust[1] = ((SkScalar) copyParams->fHeight) / height;
        switch (textureParams.filter()) {
            case GrSamplerState::Filter::kNearest:
                copyParams->fFilter = GrSamplerState::Filter::kNearest;
                break;
            case GrSamplerState::Filter::kBilerp:
            case GrSamplerState::Filter::kMipMap:
                // We are only ever scaling up so no reason to ever indicate kMipMap.
                copyParams->fFilter = GrSamplerState::Filter::kBilerp;
                break;
        }
        return true;
    }
    return false;
}

sk_sp<GrTexture> GrGpu::createTexture(const GrSurfaceDesc& origDesc, SkBudgeted budgeted,
                                      const GrMipLevel texels[], int mipLevelCount) {
    GR_CREATE_TRACE_MARKER_CONTEXT("GrGpu", "createTexture", fContext);
    GrSurfaceDesc desc = origDesc;

    GrMipMapped mipMapped = mipLevelCount > 1 ? GrMipMapped::kYes : GrMipMapped::kNo;
    if (!this->caps()->validateSurfaceDesc(desc, mipMapped)) {
        return nullptr;
    }

    bool isRT = desc.fFlags & kRenderTarget_GrSurfaceFlag;
    if (isRT) {
        desc.fSampleCnt = this->caps()->getRenderTargetSampleCount(desc.fSampleCnt, desc.fConfig);
    }
    // Attempt to catch un- or wrongly initialized sample counts.
    SkASSERT(desc.fSampleCnt > 0 && desc.fSampleCnt <= 64);

    if (mipLevelCount && (desc.fFlags & kPerformInitialClear_GrSurfaceFlag)) {
        return nullptr;
    }

    this->handleDirtyContext();
    sk_sp<GrTexture> tex = this->onCreateTexture(desc, budgeted, texels, mipLevelCount);
    if (tex) {
        if (!this->caps()->reuseScratchTextures() && !isRT) {
            tex->resourcePriv().removeScratchKey();
        }
        fStats.incTextureCreates();
        if (mipLevelCount) {
            if (texels[0].fPixels) {
                fStats.incTextureUploads();
            }
        }
    }
    return tex;
}

sk_sp<GrTexture> GrGpu::createTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted) {
    return this->createTexture(desc, budgeted, nullptr, 0);
}

sk_sp<GrTexture> GrGpu::wrapBackendTexture(const GrBackendTexture& backendTex,
                                           GrWrapOwnership ownership) {
    this->handleDirtyContext();
    if (!this->caps()->isConfigTexturable(backendTex.config())) {
        return nullptr;
    }
    if (backendTex.width() > this->caps()->maxTextureSize() ||
        backendTex.height() > this->caps()->maxTextureSize()) {
        return nullptr;
    }
    sk_sp<GrTexture> tex = this->onWrapBackendTexture(backendTex, ownership);
    if (tex && !backendTex.hasMipMaps()) {
        // Ganesh will not ever allocate mipmaps for a wrapped resource. By setting this flag here,
        // it will be propagated to any proxy that wraps this texture.
        tex->texturePriv().setDoesNotSupportMipMaps();
    }
    return tex;
}

sk_sp<GrTexture> GrGpu::wrapRenderableBackendTexture(const GrBackendTexture& backendTex,
                                                     int sampleCnt, GrWrapOwnership ownership) {
    this->handleDirtyContext();
    if (sampleCnt < 1) {
        return nullptr;
    }
    if (!this->caps()->isConfigTexturable(backendTex.config()) ||
        !this->caps()->getRenderTargetSampleCount(sampleCnt, backendTex.config())) {
        return nullptr;
    }

    if (backendTex.width() > this->caps()->maxRenderTargetSize() ||
        backendTex.height() > this->caps()->maxRenderTargetSize()) {
        return nullptr;
    }
    sk_sp<GrTexture> tex = this->onWrapRenderableBackendTexture(backendTex, sampleCnt, ownership);
    if (tex && !backendTex.hasMipMaps()) {
        // Ganesh will not ever allocate mipmaps for a wrapped resource. By setting this flag here,
        // it will be propagated to any proxy that wraps this texture.
        tex->texturePriv().setDoesNotSupportMipMaps();
    }
    SkASSERT(!tex || tex->asRenderTarget());
    return tex;
}

sk_sp<GrRenderTarget> GrGpu::wrapBackendRenderTarget(const GrBackendRenderTarget& backendRT) {
    if (0 == this->caps()->getRenderTargetSampleCount(backendRT.sampleCnt(), backendRT.config())) {
        return nullptr;
    }
    this->handleDirtyContext();
    return this->onWrapBackendRenderTarget(backendRT);
}

sk_sp<GrRenderTarget> GrGpu::wrapBackendTextureAsRenderTarget(const GrBackendTexture& tex,
                                                              int sampleCnt) {
    if (0 == this->caps()->getRenderTargetSampleCount(sampleCnt, tex.config())) {
        return nullptr;
    }
    int maxSize = this->caps()->maxTextureSize();
    if (tex.width() > maxSize || tex.height() > maxSize) {
        return nullptr;
    }
    this->handleDirtyContext();
    return this->onWrapBackendTextureAsRenderTarget(tex, sampleCnt);
}

GrBuffer* GrGpu::createBuffer(size_t size, GrBufferType intendedType,
                              GrAccessPattern accessPattern, const void* data) {
    this->handleDirtyContext();
    GrBuffer* buffer = this->onCreateBuffer(size, intendedType, accessPattern, data);
    if (!this->caps()->reuseScratchBuffers()) {
        buffer->resourcePriv().removeScratchKey();
    }
    return buffer;
}

bool GrGpu::copySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
                        GrSurface* src, GrSurfaceOrigin srcOrigin,
                        const SkIRect& srcRect, const SkIPoint& dstPoint,
                        bool canDiscardOutsideDstRect) {
    GR_CREATE_TRACE_MARKER_CONTEXT("GrGpu", "copySurface", fContext);
    SkASSERT(dst && src);
    this->handleDirtyContext();
    return this->onCopySurface(dst, dstOrigin, src, srcOrigin, srcRect, dstPoint,
                               canDiscardOutsideDstRect);
}

bool GrGpu::getReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrigin, int width,
                              int height, size_t rowBytes, GrColorType dstColorType,
                              GrSRGBConversion srgbConversion, DrawPreference* drawPreference,
                              ReadPixelTempDrawInfo* tempDrawInfo) {
    SkASSERT(drawPreference);
    SkASSERT(tempDrawInfo);
    SkASSERT(srcSurface);
    SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);

    // We currently do not support reading into the packed formats 565 or 4444 as they are not
    // required to have read back support on all devices and backends.
    if (GrColorType::kRGB_565 == dstColorType || GrColorType::kABGR_4444 == dstColorType) {
        return false;
    }

    GrPixelConfig tempSurfaceConfig = kUnknown_GrPixelConfig;
    // GrGpu::readPixels doesn't do any sRGB conversions, so we must draw if there is one.
    switch (srgbConversion) {
        case GrSRGBConversion::kNone:
            // We support reading from RGBA to just A. In that case there is no sRGB version of the
            // dst format but we still want to succeed.
            if (GrColorTypeIsAlphaOnly(dstColorType)) {
                tempSurfaceConfig = GrColorTypeToPixelConfig(dstColorType, GrSRGBEncoded::kNo);
            } else {
                tempSurfaceConfig = GrColorTypeToPixelConfig(
                        dstColorType, GrPixelConfigIsSRGBEncoded(srcSurface->config()));
            }
            break;
        case GrSRGBConversion::kLinearToSRGB:
            SkASSERT(this->caps()->srgbSupport());
            tempSurfaceConfig = GrColorTypeToPixelConfig(dstColorType, GrSRGBEncoded::kYes);
            // Currently we don't expect to make a SRGB encoded surface and then read data from it
            // such that we treat it as though it were linear and is then converted to sRGB.
            if (GrPixelConfigIsSRGB(srcSurface->config())) {
                return false;
            }
            ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
            break;
        case GrSRGBConversion::kSRGBToLinear:
            SkASSERT(this->caps()->srgbSupport());
            tempSurfaceConfig = GrColorTypeToPixelConfig(dstColorType, GrSRGBEncoded::kNo);
            // We don't currently support reading sRGB encoded data into linear from a surface
            // unless it is an sRGB-encoded config. That is likely to change when we need to store
            // sRGB encoded data in 101010102 and F16 textures. We'll have to provoke the caller to
            // do the conversion in a shader.
            if (GrSRGBEncoded::kNo == GrPixelConfigIsSRGBEncoded(srcSurface->config())) {
                return false;
            }
            ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
            break;
    }
    if (kUnknown_GrPixelConfig == tempSurfaceConfig) {
        return false;
    }

    // Default values for intermediate draws. The intermediate texture config matches the dst's
    // config, is approx sized to the read rect, no swizzling or spoofing of the dst config.
    tempDrawInfo->fTempSurfaceDesc.fFlags = kRenderTarget_GrSurfaceFlag;
    tempDrawInfo->fTempSurfaceDesc.fWidth = width;
    tempDrawInfo->fTempSurfaceDesc.fHeight = height;
    tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 1;
    tempDrawInfo->fTempSurfaceDesc.fConfig = tempSurfaceConfig;
    tempDrawInfo->fTempSurfaceFit = SkBackingFit::kApprox;
    tempDrawInfo->fSwizzle = GrSwizzle::RGBA();
    tempDrawInfo->fReadColorType = dstColorType;

    if (!this->onGetReadPixelsInfo(srcSurface, srcOrigin, width, height, rowBytes, dstColorType,
                                   drawPreference, tempDrawInfo)) {
        return false;
    }

    // Check to see if we're going to request that the caller draw when drawing is not possible.
    if (!srcSurface->asTexture() ||
        !this->caps()->isConfigRenderable(tempDrawInfo->fTempSurfaceDesc.fConfig)) {
        // If we don't have a fallback to a straight read then fail.
        if (kRequireDraw_DrawPreference == *drawPreference) {
            return false;
        }
        *drawPreference = kNoDraw_DrawPreference;
    }

    return true;
}

bool GrGpu::getWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOrigin, int width,
                               int height, GrColorType srcColorType,
                               GrSRGBConversion srgbConversion, DrawPreference* drawPreference,
                               WritePixelTempDrawInfo* tempDrawInfo) {
    SkASSERT(drawPreference);
    SkASSERT(tempDrawInfo);
    SkASSERT(dstSurface);
    SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);

    GrPixelConfig tempSurfaceConfig = kUnknown_GrPixelConfig;
    // GrGpu::writePixels doesn't do any sRGB conversions, so we must draw if there is one.
    switch (srgbConversion) {
        case GrSRGBConversion::kNone:
            // We support writing just A to a RGBA. In that case there is no sRGB version of the
            // src format but we still want to succeed.
            if (GrColorTypeIsAlphaOnly(srcColorType)) {
                tempSurfaceConfig = GrColorTypeToPixelConfig(srcColorType, GrSRGBEncoded::kNo);
            } else {
                tempSurfaceConfig = GrColorTypeToPixelConfig(
                        srcColorType, GrPixelConfigIsSRGBEncoded(dstSurface->config()));
            }
            break;
        case GrSRGBConversion::kLinearToSRGB:
            SkASSERT(this->caps()->srgbSupport());
            // This assert goes away when we start referring to CPU data using color type.
            tempSurfaceConfig = GrColorTypeToPixelConfig(srcColorType, GrSRGBEncoded::kNo);
            // We don't currently support storing sRGB encoded data in a surface unless it is
            // an SRGB-encoded config. That is likely to change when we need to store sRGB encoded
            // data in 101010102 and F16 textures. We'll have to provoke the caller to do the
            // conversion in a shader.
            if (!GrPixelConfigIsSRGB(dstSurface->config())) {
                return false;
            }
            ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
            break;
        case GrSRGBConversion::kSRGBToLinear:
            SkASSERT(this->caps()->srgbSupport());
            tempSurfaceConfig = GrColorTypeToPixelConfig(srcColorType, GrSRGBEncoded::kYes);
            // Currently we don't expect to make a SRGB encoded surface and then succeed at
            // treating it as though it were linear and then convert to sRGB.
            if (GrSRGBEncoded::kYes == GrPixelConfigIsSRGBEncoded(dstSurface->config())) {
                return false;
            }
            ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
            break;
    }
    if (kUnknown_GrPixelConfig == tempSurfaceConfig) {
        return false;
    }

    // Default values for intermediate draws. The intermediate texture config matches the dst's
    // config, is approx sized to the write rect, no swizzling or sppofing of the src config.
    tempDrawInfo->fTempSurfaceDesc.fFlags = kNone_GrSurfaceFlags;
    tempDrawInfo->fTempSurfaceDesc.fConfig = tempSurfaceConfig;
    tempDrawInfo->fTempSurfaceDesc.fWidth = width;
    tempDrawInfo->fTempSurfaceDesc.fHeight = height;
    tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 1;
    tempDrawInfo->fSwizzle = GrSwizzle::RGBA();
    tempDrawInfo->fWriteColorType = srcColorType;

    if (!this->onGetWritePixelsInfo(dstSurface, dstOrigin, width, height, srcColorType,
                                    drawPreference, tempDrawInfo)) {
        return false;
    }

    // Check to see if we're going to request that the caller draw when drawing is not possible.
    if (!dstSurface->asRenderTarget() ||
        !this->caps()->isConfigTexturable(tempDrawInfo->fTempSurfaceDesc.fConfig)) {
        // If we don't have a fallback to a straight upload then fail.
        if (kRequireDraw_DrawPreference == *drawPreference /*TODO ||
            !this->caps()->isConfigTexturable(srcConfig)*/) {
            return false;
        }
        *drawPreference = kNoDraw_DrawPreference;
    }
    return true;
}

bool GrGpu::readPixels(GrSurface* surface, GrSurfaceOrigin origin, int left, int top, int width,
                       int height, GrColorType dstColorType, void* buffer, size_t rowBytes) {
    SkASSERT(surface);

    int bpp = GrColorTypeBytesPerPixel(dstColorType);
    if (!GrSurfacePriv::AdjustReadPixelParams(surface->width(), surface->height(), bpp,
                                              &left, &top, &width, &height,
                                              &buffer,
                                              &rowBytes)) {
        return false;
    }

    this->handleDirtyContext();

    return this->onReadPixels(surface, origin, left, top, width, height, dstColorType, buffer,
                              rowBytes);
}

bool GrGpu::writePixels(GrSurface* surface, GrSurfaceOrigin origin, int left, int top, int width,
                        int height, GrColorType srcColorType, const GrMipLevel texels[],
                        int mipLevelCount) {
    SkASSERT(surface);
    if (1 == mipLevelCount) {
        // We require that if we are not mipped, then the write region is contained in the surface
        SkIRect subRect = SkIRect::MakeXYWH(left, top, width, height);
        SkIRect bounds = SkIRect::MakeWH(surface->width(), surface->height());
        if (!bounds.contains(subRect)) {
            return false;
        }
    } else if (0 != left || 0 != top || width != surface->width() || height != surface->height()) {
        // We require that if the texels are mipped, than the write region is the entire surface
        return false;
    }

    for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) {
        if (!texels[currentMipLevel].fPixels ) {
            return false;
        }
    }

    this->handleDirtyContext();
    if (this->onWritePixels(surface, origin, left, top, width, height, srcColorType, texels,
                            mipLevelCount)) {
        SkIRect rect = SkIRect::MakeXYWH(left, top, width, height);
        this->didWriteToSurface(surface, origin, &rect, mipLevelCount);
        fStats.incTextureUploads();
        return true;
    }
    return false;
}

bool GrGpu::writePixels(GrSurface* surface, GrSurfaceOrigin origin, int left, int top, int width,
                        int height, GrColorType srcColorType, const void* buffer, size_t rowBytes) {
    GrMipLevel mipLevel = { buffer, rowBytes };

    return this->writePixels(surface, origin, left, top, width, height, srcColorType, &mipLevel, 1);
}

bool GrGpu::transferPixels(GrTexture* texture, int left, int top, int width, int height,
                           GrColorType bufferColorType, GrBuffer* transferBuffer, size_t offset,
                           size_t rowBytes) {
    SkASSERT(transferBuffer);

    // We require that the write region is contained in the texture
    SkIRect subRect = SkIRect::MakeXYWH(left, top, width, height);
    SkIRect bounds = SkIRect::MakeWH(texture->width(), texture->height());
    if (!bounds.contains(subRect)) {
        return false;
    }

    this->handleDirtyContext();
    if (this->onTransferPixels(texture, left, top, width, height, bufferColorType, transferBuffer,
                               offset, rowBytes)) {
        SkIRect rect = SkIRect::MakeXYWH(left, top, width, height);
        this->didWriteToSurface(texture, kTopLeft_GrSurfaceOrigin, &rect);
        fStats.incTransfersToTexture();

        return true;
    }
    return false;
}

void GrGpu::resolveRenderTarget(GrRenderTarget* target) {
    SkASSERT(target);
    this->handleDirtyContext();
    this->onResolveRenderTarget(target);
}

void GrGpu::didWriteToSurface(GrSurface* surface, GrSurfaceOrigin origin, const SkIRect* bounds,
                              uint32_t mipLevels) const {
    SkASSERT(surface);
    // Mark any MIP chain and resolve buffer as dirty if and only if there is a non-empty bounds.
    if (nullptr == bounds || !bounds->isEmpty()) {
        if (GrRenderTarget* target = surface->asRenderTarget()) {
            SkIRect flippedBounds;
            if (kBottomLeft_GrSurfaceOrigin == origin && bounds) {
                flippedBounds = {bounds->fLeft, surface->height() - bounds->fBottom,
                                 bounds->fRight, surface->height() - bounds->fTop};
                bounds = &flippedBounds;
            }
            target->flagAsNeedingResolve(bounds);
        }
        GrTexture* texture = surface->asTexture();
        if (texture && 1 == mipLevels) {
            texture->texturePriv().markMipMapsDirty();
        }
    }
}

GrSemaphoresSubmitted GrGpu::finishFlush(int numSemaphores,
                                         GrBackendSemaphore backendSemaphores[]) {
    GrResourceProvider* resourceProvider = fContext->contextPriv().resourceProvider();

    if (this->caps()->fenceSyncSupport()) {
        for (int i = 0; i < numSemaphores; ++i) {
            sk_sp<GrSemaphore> semaphore;
            if (backendSemaphores[i].isInitialized()) {
                semaphore = resourceProvider->wrapBackendSemaphore(
                        backendSemaphores[i], GrResourceProvider::SemaphoreWrapType::kWillSignal,
                        kBorrow_GrWrapOwnership);
            } else {
                semaphore = resourceProvider->makeSemaphore(false);
            }
            this->insertSemaphore(semaphore, false);

            if (!backendSemaphores[i].isInitialized()) {
                semaphore->setBackendSemaphore(&backendSemaphores[i]);
            }
        }
    }
    this->onFinishFlush((numSemaphores > 0 && this->caps()->fenceSyncSupport()));
    return this->caps()->fenceSyncSupport() ? GrSemaphoresSubmitted::kYes
                                            : GrSemaphoresSubmitted::kNo;
}

void GrGpu::dumpJSON(SkJSONWriter* writer) const {
    writer->beginObject();

    // TODO: Is there anything useful in the base class to dump here?

    this->onDumpJSON(writer);

    writer->endObject();
}
