2010-07-27 17:39:27 -07:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2010-10-27 18:57:51 -07:00
|
|
|
#ifndef ANDROID_HWUI_PROGRAM_CACHE_H
|
|
|
|
#define ANDROID_HWUI_PROGRAM_CACHE_H
|
2010-07-27 17:39:27 -07:00
|
|
|
|
|
|
|
#include <utils/KeyedVector.h>
|
|
|
|
#include <utils/Log.h>
|
2010-07-30 19:18:16 -07:00
|
|
|
#include <utils/String8.h>
|
2010-07-27 17:39:27 -07:00
|
|
|
|
2010-07-29 14:37:42 -07:00
|
|
|
#include <GLES2/gl2.h>
|
|
|
|
|
2010-07-27 17:39:27 -07:00
|
|
|
#include <SkXfermode.h>
|
|
|
|
|
|
|
|
#include "Program.h"
|
|
|
|
|
|
|
|
namespace android {
|
|
|
|
namespace uirenderer {
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Defines
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// Debug
|
2010-09-10 19:20:06 -07:00
|
|
|
#define DEBUG_PROGRAM_CACHE 0
|
2010-07-27 17:39:27 -07:00
|
|
|
|
|
|
|
// Debug
|
|
|
|
#if DEBUG_PROGRAM_CACHE
|
|
|
|
#define PROGRAM_LOGD(...) LOGD(__VA_ARGS__)
|
|
|
|
#else
|
|
|
|
#define PROGRAM_LOGD(...)
|
|
|
|
#endif
|
|
|
|
|
2010-10-11 16:34:59 -07:00
|
|
|
// TODO: This should be set in properties
|
2010-10-11 17:58:29 -07:00
|
|
|
#define PANEL_BIT_DEPTH 20
|
2010-10-11 16:34:59 -07:00
|
|
|
#define COLOR_COMPONENT_THRESHOLD (1.0f - (0.5f / PANEL_BIT_DEPTH))
|
|
|
|
#define COLOR_COMPONENT_INV_THRESHOLD (0.5f / PANEL_BIT_DEPTH)
|
|
|
|
|
2010-07-27 17:39:27 -07:00
|
|
|
#define PROGRAM_KEY_TEXTURE 0x1
|
|
|
|
#define PROGRAM_KEY_A8_TEXTURE 0x2
|
|
|
|
#define PROGRAM_KEY_BITMAP 0x4
|
|
|
|
#define PROGRAM_KEY_GRADIENT 0x8
|
|
|
|
#define PROGRAM_KEY_BITMAP_FIRST 0x10
|
|
|
|
#define PROGRAM_KEY_COLOR_MATRIX 0x20
|
|
|
|
#define PROGRAM_KEY_COLOR_LIGHTING 0x40
|
|
|
|
#define PROGRAM_KEY_COLOR_BLEND 0x80
|
2010-07-29 14:37:42 -07:00
|
|
|
#define PROGRAM_KEY_BITMAP_NPOT 0x100
|
2010-09-10 19:20:06 -07:00
|
|
|
#define PROGRAM_KEY_SWAP_SRC_DST 0x2000
|
2010-07-29 14:37:42 -07:00
|
|
|
|
|
|
|
#define PROGRAM_KEY_BITMAP_WRAPS_MASK 0x600
|
|
|
|
#define PROGRAM_KEY_BITMAP_WRAPT_MASK 0x1800
|
2010-07-27 17:39:27 -07:00
|
|
|
|
2010-08-10 19:21:34 -07:00
|
|
|
// Encode the xfermodes on 6 bits
|
|
|
|
#define PROGRAM_MAX_XFERMODE 0x1f
|
|
|
|
#define PROGRAM_XFERMODE_SHADER_SHIFT 26
|
2010-07-27 17:39:27 -07:00
|
|
|
#define PROGRAM_XFERMODE_COLOR_OP_SHIFT 20
|
2010-09-09 14:42:43 -07:00
|
|
|
#define PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT 14
|
2010-07-27 17:39:27 -07:00
|
|
|
|
2010-07-29 14:37:42 -07:00
|
|
|
#define PROGRAM_BITMAP_WRAPS_SHIFT 9
|
|
|
|
#define PROGRAM_BITMAP_WRAPT_SHIFT 11
|
|
|
|
|
2010-09-20 17:53:08 -07:00
|
|
|
#define PROGRAM_GRADIENT_TYPE_SHIFT 33
|
2010-10-11 16:34:59 -07:00
|
|
|
#define PROGRAM_MODULATE 35
|
2010-09-20 17:53:08 -07:00
|
|
|
|
2010-07-27 17:39:27 -07:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Types
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2010-09-20 17:53:08 -07:00
|
|
|
typedef uint64_t programid;
|
2010-07-27 17:39:27 -07:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Cache
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Describe the features required for a given program. The features
|
|
|
|
* determine the generation of both the vertex and fragment shaders.
|
|
|
|
* A ProgramDescription must be used in conjunction with a ProgramCache.
|
|
|
|
*/
|
|
|
|
struct ProgramDescription {
|
|
|
|
enum ColorModifier {
|
|
|
|
kColorNone,
|
|
|
|
kColorMatrix,
|
|
|
|
kColorLighting,
|
|
|
|
kColorBlend
|
|
|
|
};
|
|
|
|
|
2010-09-20 17:53:08 -07:00
|
|
|
enum Gradient {
|
|
|
|
kGradientLinear,
|
|
|
|
kGradientCircular,
|
|
|
|
kGradientSweep
|
|
|
|
};
|
|
|
|
|
2010-07-27 17:39:27 -07:00
|
|
|
ProgramDescription():
|
2010-10-11 16:34:59 -07:00
|
|
|
hasTexture(false), hasAlpha8Texture(false), modulate(false),
|
2010-07-29 14:37:42 -07:00
|
|
|
hasBitmap(false), isBitmapNpot(false), hasGradient(false),
|
2010-09-20 17:53:08 -07:00
|
|
|
gradientType(kGradientLinear),
|
2010-07-29 14:37:42 -07:00
|
|
|
shadersMode(SkXfermode::kClear_Mode), isBitmapFirst(false),
|
|
|
|
bitmapWrapS(GL_CLAMP_TO_EDGE), bitmapWrapT(GL_CLAMP_TO_EDGE),
|
2010-09-09 14:42:43 -07:00
|
|
|
colorOp(kColorNone), colorMode(SkXfermode::kClear_Mode),
|
2010-09-10 19:20:06 -07:00
|
|
|
framebufferMode(SkXfermode::kClear_Mode), swapSrcDst(false) {
|
2010-07-27 17:39:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Texturing
|
|
|
|
bool hasTexture;
|
|
|
|
bool hasAlpha8Texture;
|
|
|
|
|
2010-10-11 16:34:59 -07:00
|
|
|
// Modulate, this should only be set when setColor() return true
|
|
|
|
bool modulate;
|
|
|
|
|
2010-07-27 17:39:27 -07:00
|
|
|
// Shaders
|
|
|
|
bool hasBitmap;
|
2010-07-29 14:37:42 -07:00
|
|
|
bool isBitmapNpot;
|
2010-09-20 17:53:08 -07:00
|
|
|
|
2010-07-27 17:39:27 -07:00
|
|
|
bool hasGradient;
|
2010-09-20 17:53:08 -07:00
|
|
|
Gradient gradientType;
|
|
|
|
|
2010-07-27 17:39:27 -07:00
|
|
|
SkXfermode::Mode shadersMode;
|
2010-09-20 17:53:08 -07:00
|
|
|
|
2010-07-27 17:39:27 -07:00
|
|
|
bool isBitmapFirst;
|
2010-07-29 14:37:42 -07:00
|
|
|
GLenum bitmapWrapS;
|
|
|
|
GLenum bitmapWrapT;
|
2010-07-27 17:39:27 -07:00
|
|
|
|
|
|
|
// Color operations
|
2010-10-13 21:31:28 -07:00
|
|
|
ColorModifier colorOp;
|
2010-07-27 17:39:27 -07:00
|
|
|
SkXfermode::Mode colorMode;
|
|
|
|
|
2010-09-09 14:42:43 -07:00
|
|
|
// Framebuffer blending (requires Extensions.hasFramebufferFetch())
|
|
|
|
// Ignored for all values < SkXfermode::kPlus_Mode
|
|
|
|
SkXfermode::Mode framebufferMode;
|
2010-09-10 19:20:06 -07:00
|
|
|
bool swapSrcDst;
|
2010-09-09 14:42:43 -07:00
|
|
|
|
2010-10-11 16:34:59 -07:00
|
|
|
/**
|
|
|
|
* Indicates, for a given color, whether color modulation is required in
|
|
|
|
* the fragment shader. When this method returns true, the program should
|
|
|
|
* be provided with a modulation color.
|
|
|
|
*/
|
|
|
|
bool setColor(const float r, const float g, const float b, const float a) {
|
|
|
|
modulate = a < COLOR_COMPONENT_THRESHOLD || r < COLOR_COMPONENT_THRESHOLD ||
|
|
|
|
g < COLOR_COMPONENT_THRESHOLD || b < COLOR_COMPONENT_THRESHOLD;
|
|
|
|
return modulate;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Indicates, for a given color, whether color modulation is required in
|
|
|
|
* the fragment shader. When this method returns true, the program should
|
|
|
|
* be provided with a modulation color.
|
|
|
|
*/
|
|
|
|
bool setAlpha8Color(const float r, const float g, const float b, const float a) {
|
|
|
|
modulate = a < COLOR_COMPONENT_THRESHOLD || r > COLOR_COMPONENT_INV_THRESHOLD ||
|
|
|
|
g > COLOR_COMPONENT_INV_THRESHOLD || b > COLOR_COMPONENT_INV_THRESHOLD;
|
|
|
|
return modulate;
|
2010-07-29 14:37:42 -07:00
|
|
|
}
|
|
|
|
|
2010-10-11 16:34:59 -07:00
|
|
|
/**
|
|
|
|
* Computes the unique key identifying this program.
|
|
|
|
*/
|
2010-07-27 17:39:27 -07:00
|
|
|
programid key() const {
|
|
|
|
programid key = 0;
|
|
|
|
if (hasTexture) key |= PROGRAM_KEY_TEXTURE;
|
|
|
|
if (hasAlpha8Texture) key |= PROGRAM_KEY_A8_TEXTURE;
|
2010-07-29 14:37:42 -07:00
|
|
|
if (hasBitmap) {
|
|
|
|
key |= PROGRAM_KEY_BITMAP;
|
|
|
|
if (isBitmapNpot) {
|
|
|
|
key |= PROGRAM_KEY_BITMAP_NPOT;
|
|
|
|
key |= getEnumForWrap(bitmapWrapS) << PROGRAM_BITMAP_WRAPS_SHIFT;
|
|
|
|
key |= getEnumForWrap(bitmapWrapT) << PROGRAM_BITMAP_WRAPT_SHIFT;
|
|
|
|
}
|
|
|
|
}
|
2010-07-27 17:39:27 -07:00
|
|
|
if (hasGradient) key |= PROGRAM_KEY_GRADIENT;
|
2010-09-20 17:53:08 -07:00
|
|
|
key |= programid(gradientType) << PROGRAM_GRADIENT_TYPE_SHIFT;
|
|
|
|
if (isBitmapFirst) key |= PROGRAM_KEY_BITMAP_FIRST;
|
2010-07-27 17:39:27 -07:00
|
|
|
if (hasBitmap && hasGradient) {
|
|
|
|
key |= (shadersMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_SHADER_SHIFT;
|
|
|
|
}
|
|
|
|
switch (colorOp) {
|
|
|
|
case kColorMatrix:
|
|
|
|
key |= PROGRAM_KEY_COLOR_MATRIX;
|
|
|
|
break;
|
|
|
|
case kColorLighting:
|
|
|
|
key |= PROGRAM_KEY_COLOR_LIGHTING;
|
|
|
|
break;
|
|
|
|
case kColorBlend:
|
|
|
|
key |= PROGRAM_KEY_COLOR_BLEND;
|
|
|
|
key |= (colorMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_COLOR_OP_SHIFT;
|
|
|
|
break;
|
|
|
|
case kColorNone:
|
|
|
|
break;
|
|
|
|
}
|
2010-09-09 14:42:43 -07:00
|
|
|
key |= (framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT;
|
2010-09-10 19:20:06 -07:00
|
|
|
if (swapSrcDst) key |= PROGRAM_KEY_SWAP_SRC_DST;
|
2010-10-11 16:34:59 -07:00
|
|
|
if (modulate) key |= programid(0x1) << PROGRAM_MODULATE;
|
2010-07-27 17:39:27 -07:00
|
|
|
return key;
|
|
|
|
}
|
2010-09-20 17:53:08 -07:00
|
|
|
|
2010-10-11 16:34:59 -07:00
|
|
|
/**
|
|
|
|
* Logs the specified message followed by the key identifying this program.
|
|
|
|
*/
|
2010-09-20 17:53:08 -07:00
|
|
|
void log(const char* message) const {
|
|
|
|
programid k = key();
|
|
|
|
PROGRAM_LOGD("%s (key = 0x%.8x%.8x)", message, uint32_t(k >> 32),
|
|
|
|
uint32_t(k & 0xffffffff));
|
|
|
|
}
|
2010-10-11 16:34:59 -07:00
|
|
|
|
|
|
|
private:
|
|
|
|
inline uint32_t getEnumForWrap(GLenum wrap) const {
|
|
|
|
switch (wrap) {
|
|
|
|
case GL_CLAMP_TO_EDGE:
|
|
|
|
return 0;
|
|
|
|
case GL_REPEAT:
|
|
|
|
return 1;
|
|
|
|
case GL_MIRRORED_REPEAT:
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-07-27 17:39:27 -07:00
|
|
|
}; // struct ProgramDescription
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates and caches program. Programs are generated based on
|
|
|
|
* ProgramDescriptions.
|
|
|
|
*/
|
|
|
|
class ProgramCache {
|
|
|
|
public:
|
|
|
|
ProgramCache();
|
|
|
|
~ProgramCache();
|
|
|
|
|
|
|
|
Program* get(const ProgramDescription& description);
|
|
|
|
|
|
|
|
void clear();
|
|
|
|
|
|
|
|
private:
|
|
|
|
Program* generateProgram(const ProgramDescription& description, programid key);
|
|
|
|
String8 generateVertexShader(const ProgramDescription& description);
|
|
|
|
String8 generateFragmentShader(const ProgramDescription& description);
|
2010-08-10 19:21:34 -07:00
|
|
|
void generateBlend(String8& shader, const char* name, SkXfermode::Mode mode);
|
2010-07-29 14:37:42 -07:00
|
|
|
void generateTextureWrap(String8& shader, GLenum wrapS, GLenum wrapT);
|
2010-07-27 17:39:27 -07:00
|
|
|
|
2010-08-02 18:50:22 -07:00
|
|
|
void printLongString(const String8& shader) const;
|
|
|
|
|
2010-07-27 17:39:27 -07:00
|
|
|
KeyedVector<programid, Program*> mCache;
|
|
|
|
}; // class ProgramCache
|
|
|
|
|
|
|
|
}; // namespace uirenderer
|
|
|
|
}; // namespace android
|
|
|
|
|
2010-10-27 18:57:51 -07:00
|
|
|
#endif // ANDROID_HWUI_PROGRAM_CACHE_H
|