summaryrefslogtreecommitdiff
path: root/libs/hwui/SkiaShader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/hwui/SkiaShader.cpp')
-rw-r--r--libs/hwui/SkiaShader.cpp360
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