diff options
Diffstat (limited to 'libs/hwui/SkiaShader.cpp')
-rw-r--r-- | libs/hwui/SkiaShader.cpp | 360 |
1 files changed, 0 insertions, 360 deletions
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp deleted file mode 100644 index df746554f306..000000000000 --- a/libs/hwui/SkiaShader.cpp +++ /dev/null @@ -1,360 +0,0 @@ -/* - * Copyright (C) 2010 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 "SkiaShader.h" - -#include "Caches.h" -#include "Extensions.h" -#include "Matrix.h" -#include "Texture.h" -#include "hwui/Bitmap.h" - -#include <SkMatrix.h> -#include <utils/Log.h> - -namespace android { -namespace uirenderer { - -/////////////////////////////////////////////////////////////////////////////// -// Support -/////////////////////////////////////////////////////////////////////////////// - -static constexpr GLenum gTileModes[] = { - GL_CLAMP_TO_EDGE, // == SkShader::kClamp_TileMode - GL_REPEAT, // == SkShader::kRepeat_Mode - GL_MIRRORED_REPEAT // == SkShader::kMirror_TileMode -}; - -static_assert(gTileModes[SkShader::kClamp_TileMode] == GL_CLAMP_TO_EDGE, - "SkShader TileModes have changed"); -static_assert(gTileModes[SkShader::kRepeat_TileMode] == GL_REPEAT, - "SkShader TileModes have changed"); -static_assert(gTileModes[SkShader::kMirror_TileMode] == GL_MIRRORED_REPEAT, - "SkShader TileModes have changed"); - -/** - * This function does not work for n == 0. - */ -static inline bool isPowerOfTwo(unsigned int n) { - return !(n & (n - 1)); -} - -static inline void bindUniformColor(int slot, FloatColor color) { - glUniform4fv(slot, 1, reinterpret_cast<const float*>(&color)); -} - -static inline void bindTexture(Caches* caches, Texture* texture, GLenum wrapS, GLenum wrapT) { - caches->textureState().bindTexture(texture->target(), texture->id()); - texture->setWrapST(wrapS, wrapT); -} - -/** - * Compute the matrix to transform to screen space. - * @param screenSpace Output param for the computed matrix. - * @param unitMatrix The unit matrix for gradient shaders, as returned by SkShader::asAGradient, - * or identity. - * @param localMatrix Local matrix, as returned by SkShader::getLocalMatrix(). - * @param modelViewMatrix Model view matrix, as supplied by the OpenGLRenderer. - */ -static void computeScreenSpaceMatrix(mat4& screenSpace, const SkMatrix& unitMatrix, - const SkMatrix& localMatrix, const mat4& modelViewMatrix) { - mat4 shaderMatrix; - // uses implicit construction - shaderMatrix.loadInverse(localMatrix); - // again, uses implicit construction - screenSpace.loadMultiply(unitMatrix, shaderMatrix); - screenSpace.multiply(modelViewMatrix); -} - -/////////////////////////////////////////////////////////////////////////////// -// Gradient shader matrix helpers -/////////////////////////////////////////////////////////////////////////////// - -static void toLinearUnitMatrix(const SkPoint pts[2], SkMatrix* matrix) { - SkVector vec = pts[1] - pts[0]; - const float mag = vec.length(); - const float inv = mag ? 1.0f / mag : 0; - - vec.scale(inv); - matrix->setSinCos(-vec.fY, vec.fX, pts[0].fX, pts[0].fY); - matrix->postTranslate(-pts[0].fX, -pts[0].fY); - matrix->postScale(inv, inv); -} - -static void toCircularUnitMatrix(const float x, const float y, const float radius, - SkMatrix* matrix) { - const float inv = 1.0f / radius; - matrix->setTranslate(-x, -y); - matrix->postScale(inv, inv); -} - -static void toSweepUnitMatrix(const float x, const float y, SkMatrix* matrix) { - matrix->setTranslate(-x, -y); -} - -/////////////////////////////////////////////////////////////////////////////// -// Common gradient code -/////////////////////////////////////////////////////////////////////////////// - -static bool isSimpleGradient(const SkShader::GradientInfo& gradInfo) { - return gradInfo.fColorCount == 2 && gradInfo.fTileMode == SkShader::kClamp_TileMode; -} - -/////////////////////////////////////////////////////////////////////////////// -// Store / apply -/////////////////////////////////////////////////////////////////////////////// - -bool tryStoreGradient(Caches& caches, const SkShader& shader, const Matrix4 modelViewMatrix, - GLuint* textureUnit, ProgramDescription* description, - SkiaShaderData::GradientShaderData* outData) { - SkShader::GradientInfo gradInfo; - gradInfo.fColorCount = 0; - gradInfo.fColors = nullptr; - gradInfo.fColorOffsets = nullptr; - - SkMatrix unitMatrix; - switch (shader.asAGradient(&gradInfo)) { - case SkShader::kLinear_GradientType: - description->gradientType = ProgramDescription::kGradientLinear; - - toLinearUnitMatrix(gradInfo.fPoint, &unitMatrix); - break; - case SkShader::kRadial_GradientType: - description->gradientType = ProgramDescription::kGradientCircular; - - toCircularUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY, gradInfo.fRadius[0], - &unitMatrix); - break; - case SkShader::kSweep_GradientType: - description->gradientType = ProgramDescription::kGradientSweep; - - toSweepUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY, &unitMatrix); - break; - default: - // Do nothing. This shader is unsupported. - return false; - } - description->hasGradient = true; - description->isSimpleGradient = isSimpleGradient(gradInfo); - - computeScreenSpaceMatrix(outData->screenSpace, unitMatrix, shader.getLocalMatrix(), - modelViewMatrix); - - // re-query shader to get full color / offset data - std::unique_ptr<SkColor[]> colorStorage(new SkColor[gradInfo.fColorCount]); - std::unique_ptr<SkScalar[]> colorOffsets(new SkScalar[gradInfo.fColorCount]); - gradInfo.fColors = &colorStorage[0]; - gradInfo.fColorOffsets = &colorOffsets[0]; - shader.asAGradient(&gradInfo); - - if (CC_UNLIKELY(!description->isSimpleGradient)) { - outData->gradientSampler = (*textureUnit)++; - -#ifndef SK_SCALAR_IS_FLOAT -#error Need to convert gradInfo.fColorOffsets to float! -#endif - outData->gradientTexture = caches.gradientCache.get( - gradInfo.fColors, gradInfo.fColorOffsets, gradInfo.fColorCount); - outData->wrapST = gTileModes[gradInfo.fTileMode]; - } else { - outData->gradientSampler = 0; - outData->gradientTexture = nullptr; - - outData->startColor.set(gradInfo.fColors[0]); - outData->endColor.set(gradInfo.fColors[1]); - } - - return true; -} - -void applyGradient(Caches& caches, const SkiaShaderData::GradientShaderData& data, - const GLsizei width, const GLsizei height) { - if (CC_UNLIKELY(data.gradientTexture)) { - caches.textureState().activateTexture(data.gradientSampler); - bindTexture(&caches, data.gradientTexture, data.wrapST, data.wrapST); - glUniform1i(caches.program().getUniform("gradientSampler"), data.gradientSampler); - } else { - bindUniformColor(caches.program().getUniform("startColor"), data.startColor); - bindUniformColor(caches.program().getUniform("endColor"), data.endColor); - } - - glUniform2f(caches.program().getUniform("screenSize"), 1.0f / width, 1.0f / height); - glUniformMatrix4fv(caches.program().getUniform("screenSpace"), 1, GL_FALSE, - &data.screenSpace.data[0]); -} - -bool tryStoreBitmap(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix, - GLuint* textureUnit, ProgramDescription* description, - SkiaShaderData::BitmapShaderData* outData) { - SkBitmap bitmap; - SkShader::TileMode xy[2]; - if (!shader.isABitmap(&bitmap, nullptr, xy)) { - return false; - } - - // TODO: create hwui-owned BitmapShader. - Bitmap* hwuiBitmap = static_cast<Bitmap*>(bitmap.pixelRef()); - outData->bitmapTexture = caches.textureCache.get(hwuiBitmap); - if (!outData->bitmapTexture) return false; - - outData->bitmapSampler = (*textureUnit)++; - - const float width = outData->bitmapTexture->width(); - const float height = outData->bitmapTexture->height(); - - Texture* texture = outData->bitmapTexture; - - description->hasBitmap = true; - description->hasLinearTexture = texture->isLinear(); - description->hasColorSpaceConversion = texture->hasColorSpaceConversion(); - description->transferFunction = texture->getTransferFunctionType(); - description->hasTranslucentConversion = texture->blend; - description->isShaderBitmapExternal = hwuiBitmap->isHardware(); - // gralloc doesn't support non-clamp modes - if (hwuiBitmap->isHardware() || - (!caches.extensions().hasNPot() && (!isPowerOfTwo(width) || !isPowerOfTwo(height)) && - (xy[0] != SkShader::kClamp_TileMode || xy[1] != SkShader::kClamp_TileMode))) { - // need non-clamp mode, but it's not supported for this draw, - // so enable custom shader logic to mimic - description->useShaderBasedWrap = true; - description->bitmapWrapS = gTileModes[xy[0]]; - description->bitmapWrapT = gTileModes[xy[1]]; - - outData->wrapS = GL_CLAMP_TO_EDGE; - outData->wrapT = GL_CLAMP_TO_EDGE; - } else { - outData->wrapS = gTileModes[xy[0]]; - outData->wrapT = gTileModes[xy[1]]; - } - - computeScreenSpaceMatrix(outData->textureTransform, SkMatrix::I(), shader.getLocalMatrix(), - modelViewMatrix); - outData->textureDimension[0] = 1.0f / width; - outData->textureDimension[1] = 1.0f / height; - - return true; -} - -void applyBitmap(Caches& caches, const SkiaShaderData::BitmapShaderData& data) { - caches.textureState().activateTexture(data.bitmapSampler); - bindTexture(&caches, data.bitmapTexture, data.wrapS, data.wrapT); - data.bitmapTexture->setFilter(GL_LINEAR); - - glUniform1i(caches.program().getUniform("bitmapSampler"), data.bitmapSampler); - glUniformMatrix4fv(caches.program().getUniform("textureTransform"), 1, GL_FALSE, - &data.textureTransform.data[0]); - glUniform2fv(caches.program().getUniform("textureDimension"), 1, &data.textureDimension[0]); -} - -SkiaShaderType getComposeSubType(const SkShader& shader) { - // First check for a gradient shader. - switch (shader.asAGradient(nullptr)) { - case SkShader::kNone_GradientType: - // Not a gradient shader. Fall through to check for other types. - break; - case SkShader::kLinear_GradientType: - case SkShader::kRadial_GradientType: - case SkShader::kSweep_GradientType: - return kGradient_SkiaShaderType; - default: - // This is a Skia gradient that has no SkiaShader equivalent. Return None to skip. - return kNone_SkiaShaderType; - } - - // The shader is not a gradient. Check for a bitmap shader. - if (shader.isABitmap()) { - return kBitmap_SkiaShaderType; - } - return kNone_SkiaShaderType; -} - -void storeCompose(Caches& caches, const SkShader& bitmapShader, const SkShader& gradientShader, - const Matrix4& modelViewMatrix, GLuint* textureUnit, - ProgramDescription* description, SkiaShaderData* outData) { - LOG_ALWAYS_FATAL_IF(!tryStoreBitmap(caches, bitmapShader, modelViewMatrix, textureUnit, - description, &outData->bitmapData), - "failed storing bitmap shader data"); - LOG_ALWAYS_FATAL_IF(!tryStoreGradient(caches, gradientShader, modelViewMatrix, textureUnit, - description, &outData->gradientData), - "failing storing gradient shader data"); -} - -bool tryStoreCompose(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix, - GLuint* textureUnit, ProgramDescription* description, - SkiaShaderData* outData) { - SkShader::ComposeRec rec; - if (!shader.asACompose(&rec)) return false; - - const SkiaShaderType shaderAType = getComposeSubType(*rec.fShaderA); - const SkiaShaderType shaderBType = getComposeSubType(*rec.fShaderB); - - // check that type enum values are the 2 flags that compose the kCompose value - if ((shaderAType & shaderBType) != 0) return false; - if ((shaderAType | shaderBType) != kCompose_SkiaShaderType) return false; - - mat4 transform; - computeScreenSpaceMatrix(transform, SkMatrix::I(), shader.getLocalMatrix(), modelViewMatrix); - if (shaderAType == kBitmap_SkiaShaderType) { - description->isBitmapFirst = true; - storeCompose(caches, *rec.fShaderA, *rec.fShaderB, transform, textureUnit, description, - outData); - } else { - description->isBitmapFirst = false; - storeCompose(caches, *rec.fShaderB, *rec.fShaderA, transform, textureUnit, description, - outData); - } - description->shadersMode = rec.fBlendMode; - return true; -} - -void SkiaShader::store(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix, - GLuint* textureUnit, ProgramDescription* description, - SkiaShaderData* outData) { - if (tryStoreGradient(caches, shader, modelViewMatrix, textureUnit, description, - &outData->gradientData)) { - outData->skiaShaderType = kGradient_SkiaShaderType; - return; - } - - if (tryStoreBitmap(caches, shader, modelViewMatrix, textureUnit, description, - &outData->bitmapData)) { - outData->skiaShaderType = kBitmap_SkiaShaderType; - return; - } - - if (tryStoreCompose(caches, shader, modelViewMatrix, textureUnit, description, outData)) { - outData->skiaShaderType = kCompose_SkiaShaderType; - return; - } - - // Unknown/unsupported type, so explicitly ignore shader - outData->skiaShaderType = kNone_SkiaShaderType; -} - -void SkiaShader::apply(Caches& caches, const SkiaShaderData& data, const GLsizei width, - const GLsizei height) { - if (!data.skiaShaderType) return; - - if (data.skiaShaderType & kGradient_SkiaShaderType) { - applyGradient(caches, data.gradientData, width, height); - } - if (data.skiaShaderType & kBitmap_SkiaShaderType) { - applyBitmap(caches, data.bitmapData); - } -} - -}; // namespace uirenderer -}; // namespace android |