Add support for GL_ARB_texture_swizzle

Review URL: http://codereview.appspot.com/5347042/



git-svn-id: http://skia.googlecode.com/svn/trunk@2615 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bsalomon@google.com 2011-11-07 14:56:51 +00:00
Родитель e269f210bd
Коммит 85b505bedc
7 изменённых файлов: 179 добавлений и 91 удалений

Просмотреть файл

@ -157,6 +157,7 @@
'../include/gpu/GrFontScaler.h',
'../include/gpu/GrGLConfig.h',
'../include/gpu/GrGLConfig_chrome.h',
'../include/gpu/GrGLDefines.h',
'../include/gpu/GrGLInterface.h',
'../include/gpu/GrGlyph.h',
'../include/gpu/GrInstanceCounter.h',

Просмотреть файл

@ -282,6 +282,9 @@
/* PixelFormat */
#define GR_GL_DEPTH_COMPONENT 0x1902
#define GR_GL_RED 0x1903
#define GR_GL_GREEN 0x1904
#define GR_GL_BLUE 0x1905
#define GR_GL_ALPHA 0x1906
#define GR_GL_RGB 0x1907
#define GR_GL_RGBA 0x1908
@ -424,10 +427,17 @@
#define GR_GL_CLAMP_TO_EDGE 0x812F
#define GR_GL_MIRRORED_REPEAT 0x8370
/* Texture Swizzle */
#define GR_GL_TEXTURE_SWIZZLE_R 0x8E42
#define GR_GL_TEXTURE_SWIZZLE_G 0x8E43
#define GR_GL_TEXTURE_SWIZZLE_B 0x8E44
#define GR_GL_TEXTURE_SWIZZLE_A 0x8E45
#define GR_GL_TEXTURE_SWIZZLE_RGBA 0x8E46
/* Texture mapping */
#define GR_GL_TEXTURE_ENV 0x2300
#define GR_GL_TEXTURE_ENV_MODE 0x2200
#define GR_GL_TEXTURE_1D 0x0DE0
#define GR_GL_TEXTURE_ENV 0x2300
#define GR_GL_TEXTURE_ENV_MODE 0x2200
#define GR_GL_TEXTURE_1D 0x0DE0
/* GL_TEXTURE_2D */
/* GL_TEXTURE_WRAP_S */
/* GL_TEXTURE_WRAP_T */

Просмотреть файл

@ -79,6 +79,7 @@ struct ShaderCodeSegments {
bool fUsesGS;
};
typedef GrGLProgram::ProgramDesc::StageDesc StageDesc;
#if GR_GL_ATTRIBUTE_MATRICES
#define VIEW_MATRIX_NAME "aViewM"
@ -548,12 +549,12 @@ bool decl_and_get_fs_color_output(GrGLProgram::GLSLVersion v,
}
}
void genInputColor(GrGLProgram::ProgramDesc::ColorType colorType,
void genInputColor(GrGLProgram::ProgramDesc::ColorInput colorInput,
GrGLProgram::CachedData* programData,
ShaderCodeSegments* segments,
GrStringBuilder* inColor) {
switch (colorType) {
case GrGLProgram::ProgramDesc::kAttribute_ColorType: {
switch (colorInput) {
case GrGLProgram::ProgramDesc::kAttribute_ColorInput: {
segments->fVSAttrs.push_back().set(GrGLShaderVar::kVec4f_Type,
COL_ATTR_NAME);
const char *vsName, *fsName;
@ -561,16 +562,16 @@ void genInputColor(GrGLProgram::ProgramDesc::ColorType colorType,
segments->fVSCode.appendf("\t%s = " COL_ATTR_NAME ";\n", vsName);
*inColor = fsName;
} break;
case GrGLProgram::ProgramDesc::kUniform_ColorType:
case GrGLProgram::ProgramDesc::kUniform_ColorInput:
segments->fFSUnis.push_back().set(GrGLShaderVar::kVec4f_Type,
COL_UNI_NAME);
programData->fUniLocations.fColorUni = kUseUniform;
*inColor = COL_UNI_NAME;
break;
case GrGLProgram::ProgramDesc::kTransBlack_ColorType:
case GrGLProgram::ProgramDesc::kTransBlack_ColorInput:
GrAssert(!"needComputedColor should be false.");
break;
case GrGLProgram::ProgramDesc::kSolidWhite_ColorType:
case GrGLProgram::ProgramDesc::kSolidWhite_ColorInput:
break;
default:
GrCrash("Unknown color type.");
@ -655,7 +656,7 @@ bool GrGLProgram::genProgram(const GrGLInterface* gl,
// If we know the final color is going to be all zeros then we can
// simplify the color filter coeffecients. needComputedColor will then
// come out false below.
if (ProgramDesc::kTransBlack_ColorType == fProgramDesc.fColorType) {
if (ProgramDesc::kTransBlack_ColorInput == fProgramDesc.fColorInput) {
colorCoeff = SkXfermode::kZero_Coeff;
if (SkXfermode::kDC_Coeff == uniformCoeff ||
SkXfermode::kDA_Coeff == uniformCoeff) {
@ -698,7 +699,7 @@ bool GrGLProgram::genProgram(const GrGLInterface* gl,
GrStringBuilder inColor;
if (needComputedColor) {
genInputColor((ProgramDesc::ColorType) fProgramDesc.fColorType,
genInputColor((ProgramDesc::ColorInput) fProgramDesc.fColorInput,
programData, &segments, &inColor);
}
@ -762,7 +763,7 @@ bool GrGLProgram::genProgram(const GrGLInterface* gl,
// if have all ones or zeros for the "dst" input to the color filter then we
// may be able to make additional optimizations.
if (needColorFilterUniform && needComputedColor && !inColor.size()) {
GrAssert(ProgramDesc::kSolidWhite_ColorType == fProgramDesc.fColorType);
GrAssert(ProgramDesc::kSolidWhite_ColorInput == fProgramDesc.fColorInput);
bool uniformCoeffIsZero = SkXfermode::kIDC_Coeff == uniformCoeff ||
SkXfermode::kIDA_Coeff == uniformCoeff;
if (uniformCoeffIsZero) {
@ -791,7 +792,7 @@ bool GrGLProgram::genProgram(const GrGLInterface* gl,
if (inColor.size()) {
color = inColor.c_str();
} else {
if (ProgramDesc::kSolidWhite_ColorType == fProgramDesc.fColorType) {
if (ProgramDesc::kSolidWhite_ColorInput == fProgramDesc.fColorInput) {
color = all_ones_vec(4);
} else {
color = all_zeros_vec(4);
@ -1480,7 +1481,7 @@ void gen2x2FS(int stageNum,
}
void genConvolutionVS(int stageNum,
const GrGLProgram::ProgramDesc::StageDesc& desc,
const StageDesc& desc,
ShaderCodeSegments* segments,
GrGLProgram::StageUniLocations* locations,
const char** kernelName,
@ -1510,7 +1511,7 @@ void genConvolutionVS(int stageNum,
}
void genConvolutionFS(int stageNum,
const GrGLProgram::ProgramDesc::StageDesc& desc,
const StageDesc& desc,
ShaderCodeSegments* segments,
const char* samplerName,
const char* kernelName,
@ -1634,7 +1635,7 @@ void GrGLProgram::genStageCode(const GrGLInterface* gl,
const char* kernelName = NULL;
const char* imageIncrementName = NULL;
if (ProgramDesc::StageDesc::kConvolution_FetchMode == desc.fFetchMode) {
if (StageDesc::kConvolution_FetchMode == desc.fFetchMode) {
genConvolutionVS(stageNum, desc, segments, locations,
&kernelName, &imageIncrementName, varyingVSName);
}
@ -1701,7 +1702,7 @@ void GrGLProgram::genStageCode(const GrGLInterface* gl,
};
const char* smear;
if (desc.fModulation == StageDesc::kAlpha_Modulation) {
if (desc.fInputConfig == StageDesc::kAlphaOnly_InputConfig) {
smear = ".aaaa";
} else {
smear = "";
@ -1733,7 +1734,7 @@ void GrGLProgram::genStageCode(const GrGLInterface* gl,
samplerName, texelSizeName, smear, fsOutColor,
texFunc, modulate, complexCoord, coordDims);
break;
case ProgramDesc::StageDesc::kConvolution_FetchMode:
case StageDesc::kConvolution_FetchMode:
genConvolutionFS(stageNum, desc, segments,
samplerName, kernelName, smear, imageIncrementName, fsOutColor,
sampleCoords, texFunc, modulate);

Просмотреть файл

@ -109,12 +109,6 @@ public:
kCustomTextureDomain_OptFlagBit = 1 << 2,
kIsEnabled_OptFlagBit = 1 << 7
};
enum Modulation {
kColor_Modulation,
kAlpha_Modulation,
kModulationCnt
};
enum FetchMode {
kSingle_FetchMode,
k2x2_FetchMode,
@ -122,6 +116,20 @@ public:
kFetchModeCnt,
};
enum InputConfig {
/**
The texture has r,g,b, and optionally a.
*/
kColor_InputConfig,
/**
The texture is alpha only. This should only be used if the
caller is unable to map the r,g,b sample values to the
texture's alpha channel (GL_ARB_texture_swizzle).
*/
kAlphaOnly_InputConfig,
kInputConfigCnt
};
enum CoordMapping {
kIdentity_CoordMapping,
kRadialGradient_CoordMapping,
@ -134,8 +142,8 @@ public:
};
uint8_t fOptFlags;
uint8_t fModulation; // casts to enum Modulation
uint8_t fFetchMode; // casts to enum FetchMode
uint8_t fInputConfig; // casts to enum InputConfig
uint8_t fFetchMode; // casts to enum FetchMode
uint8_t fCoordMapping; // casts to enum CoordMapping
uint8_t fKernelWidth;
@ -153,13 +161,13 @@ public:
// Specifies where the intitial color comes from before the stages are
// applied.
enum ColorType {
kSolidWhite_ColorType,
kTransBlack_ColorType,
kAttribute_ColorType,
kUniform_ColorType,
enum ColorInput {
kSolidWhite_ColorInput,
kTransBlack_ColorInput,
kAttribute_ColorInput,
kUniform_ColorInput,
kColorTypeCnt
kColorInputCnt
};
// Dual-src blending makes use of a secondary output color that can be
// used as a per-pixel blend coeffecient. This controls whether a
@ -186,8 +194,8 @@ public:
bool fExperimentalGS;
#endif
uint8_t fColorType; // casts to enum ColorType
uint8_t fDualSrcOutput; // casts to enum DualSrcOutput
uint8_t fColorInput; // casts to enum ColorInput
uint8_t fDualSrcOutput; // casts to enum DualSrcOutput
int8_t fFirstCoverageStage;
SkBool8 fEmitsPointSize;
SkBool8 fEdgeAAConcave;

Просмотреть файл

@ -394,6 +394,13 @@ void GrGpuGL::initCaps() {
}
}
if (kDesktop_GrGLBinding == this->glBinding()) {
fGLCaps.fTextureSwizzle = this->glVersion() >= GR_GL_VER(3,3) ||
this->hasExtension("GL_ARB_texture_swizzle");
} else {
fGLCaps.fTextureSwizzle = false;
}
if (kDesktop_GrGLBinding == this->glBinding()) {
fCaps.fBufferLockSupport = true; // we require VBO support and the desktop VBO
// extension includes glMapBuffer.
@ -1019,6 +1026,40 @@ static size_t as_size_t(int x) {
}
#endif
namespace {
void set_tex_swizzle(GrPixelConfig config, const GrGLInterface* gl) {
// Today we always use GL_ALPHA for kAlpha_8_GrPixelConfig. However,
// this format is deprecated sometimes isn't a renderable format. If we
// were to spoof it in the future with GL_RED we'd want to notice that
// here.
// This isn't recorded in our tex params struct becauase we infer it
// from the pixel config.
const GrGLint* swiz;
if (GrPixelConfigIsAlphaOnly(config)) {
static const GrGLint gAlphaSwiz[] = {GR_GL_ALPHA, GR_GL_ALPHA,
GR_GL_ALPHA, GR_GL_ALPHA};
swiz = gAlphaSwiz;
} else {
static const GrGLint gColorSwiz[] = {GR_GL_RED, GR_GL_GREEN,
GR_GL_BLUE, GR_GL_ALPHA};
swiz = gColorSwiz;
}
// should add texparameteri to interface to make 1 instead of 4 calls here
GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D,
GR_GL_TEXTURE_SWIZZLE_R,
swiz[0]));
GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D,
GR_GL_TEXTURE_SWIZZLE_G,
swiz[1]));
GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D,
GR_GL_TEXTURE_SWIZZLE_B,
swiz[2]));
GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D,
GR_GL_TEXTURE_SWIZZLE_A,
swiz[3]));
}
}
GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
const void* srcData,
size_t rowBytes) {
@ -1118,7 +1159,9 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
GR_GL_TEXTURE_WRAP_T,
DEFAULT_TEX_PARAMS.fWrapT));
if (fGLCaps.fTextureSwizzle) {
set_tex_swizzle(desc.fConfig, this->glInterface());
}
this->allocateAndUploadTexData(glTexDesc, internalFormat,srcData, rowBytes);
GrGLTexture* tex;
@ -2055,6 +2098,9 @@ bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
GR_GL_TEXTURE_WRAP_T,
newTexParams.fWrapT));
if (this->glCaps().fTextureSwizzle) {
set_tex_swizzle(nextTexture->config(), this->glInterface());
}
} else {
if (newTexParams.fFilter != oldTexParams.fFilter) {
setTextureUnit(s);
@ -2389,4 +2435,6 @@ void GrGpuGL::GLCaps::print() const {
GrPrintf("Max FS Uniform Vectors: %d\n", fMaxFragmentUniformVectors);
GrPrintf("Support RGBA8 Render Buffer: %s\n",
(fRGBA8Renderbuffer ? "YES": "NO"));
GrPrintf("Support texture swizzle: %s\n",
(fTextureSwizzle ? "YES": "NO"));
}

Просмотреть файл

@ -22,6 +22,7 @@
#include "SkString.h"
class GrGpuGL : public GrGpu {
public:
virtual ~GrGpuGL();
@ -32,6 +33,56 @@ public:
protected:
GrGpuGL(const GrGLInterface* glInterface, GrGLBinding glBinding);
struct GLCaps {
GLCaps()
// make defaults be the most restrictive
: fMSFBOType(kNone_MSFBO)
, fMaxFragmentUniformVectors(0)
, fRGBA8Renderbuffer(false)
, fBGRAFormat(false)
, fStencilFormats(8) // prealloc space for stencil formats
, fTextureSwizzle(false) {
memset(fAASamples, 0, sizeof(fAASamples));
}
SkTArray<GrGLStencilBuffer::Format, true> fStencilFormats;
enum {
/**
* no support for MSAA FBOs
*/
kNone_MSFBO = 0,
/**
* GL3.0-style MSAA FBO (GL_ARB_framebuffer_object)
*/
kDesktopARB_MSFBO,
/**
* earlier GL_EXT_framebuffer* extensions
*/
kDesktopEXT_MSFBO,
/**
* GL_APPLE_framebuffer_multisample ES extension
*/
kAppleES_MSFBO,
} fMSFBOType;
// TODO: get rid of GrAALevel and use sample cnt directly
GrGLuint fAASamples[4];
// The maximum number of fragment uniform vectors (GLES has min. 16).
int fMaxFragmentUniformVectors;
// ES requires an extension to support RGBA8 in RenderBufferStorage
bool fRGBA8Renderbuffer;
// Is GL_BGRA supported
bool fBGRAFormat;
// GL_ARB_texture_swizzle support
bool fTextureSwizzle;
void print() const;
} fGLCaps;
struct {
size_t fVertexOffset;
GrVertexLayout fVertexLayout;
@ -69,6 +120,8 @@ protected:
GrGLIRect fViewportRect;
} fHWBounds;
const GLCaps& glCaps() const { return fGLCaps; }
// GrGpu overrides
virtual void onResetContext() SK_OVERRIDE;
@ -207,43 +260,6 @@ private:
SkString fExtensionString;
GrGLVersion fGLVersion;
struct GLCaps {
// prealloc space for 8 stencil formats
GLCaps() : fStencilFormats(8) {}
SkTArray<GrGLStencilBuffer::Format, true> fStencilFormats;
enum {
/**
* no support for MSAA FBOs
*/
kNone_MSFBO = 0,
/**
* GL3.0-style MSAA FBO (GL_ARB_framebuffer_object)
*/
kDesktopARB_MSFBO,
/**
* earlier GL_EXT_framebuffer* extensions
*/
kDesktopEXT_MSFBO,
/**
* GL_APPLE_framebuffer_multisample ES extension
*/
kAppleES_MSFBO,
} fMSFBOType;
// TODO: get rid of GrAALevel and use sample cnt directly
GrGLuint fAASamples[4];
// The maximum number of fragment uniform vectors (GLES has min. 16).
int fMaxFragmentUniformVectors;
// ES requires an extension to support RGBA8 in RenderBufferStorage
bool fRGBA8Renderbuffer;
void print() const;
} fGLCaps;
// we want to clear stencil buffers when they are created. We want to clear
// the entire buffer even if it is larger than the color attachment. We
// attach it to this fbo with no color attachment to do the initial clear.

Просмотреть файл

@ -204,8 +204,8 @@ bool GrGpuGLShaders::programUnitTest() {
pdesc.fVertexLayout = 0;
pdesc.fEmitsPointSize = random.nextF() > .5f;
pdesc.fColorType = static_cast<int>(random.nextF() *
ProgramDesc::kColorTypeCnt);
pdesc.fColorInput = static_cast<int>(random.nextF() *
ProgramDesc::kColorInputCnt);
int idx = (int)(random.nextF() * (SkXfermode::kCoeffModesCnt));
pdesc.fColorFilterXfermode = (SkXfermode::Mode)idx;
@ -270,7 +270,7 @@ bool GrGpuGLShaders::programUnitTest() {
idx = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_OPTS));
StageDesc& stage = pdesc.fStages[s];
stage.fOptFlags = STAGE_OPTS[idx];
stage.fModulation = random_val(&random, StageDesc::kModulationCnt);
stage.fInputConfig = random_val(&random, StageDesc::kInputConfigCnt);
stage.fCoordMapping = random_val(&random, StageDesc::kCoordMappingCnt);
stage.fFetchMode = random_val(&random, StageDesc::kFetchModeCnt);
// convolution shaders don't work with persp tex matrix
@ -605,8 +605,8 @@ void GrGpuGLShaders::flushColor(GrColor color) {
// invalidate the const vertex attrib color
fHWDrawState.fColor = GrColor_ILLEGAL;
} else {
switch (desc.fColorType) {
case ProgramDesc::kAttribute_ColorType:
switch (desc.fColorInput) {
case ProgramDesc::kAttribute_ColorInput:
if (fHWDrawState.fColor != color) {
// OpenGL ES only supports the float varities of glVertexAttrib
float c[] = GR_COLOR_TO_VEC4(color);
@ -615,7 +615,7 @@ void GrGpuGLShaders::flushColor(GrColor color) {
fHWDrawState.fColor = color;
}
break;
case ProgramDesc::kUniform_ColorType:
case ProgramDesc::kUniform_ColorInput:
if (fProgramData->fColor != color) {
// OpenGL ES only supports the float varities of glVertexAttrib
float c[] = GR_COLOR_TO_VEC4(color);
@ -626,8 +626,8 @@ void GrGpuGLShaders::flushColor(GrColor color) {
fProgramData->fColor = color;
}
break;
case ProgramDesc::kSolidWhite_ColorType:
case ProgramDesc::kTransBlack_ColorType:
case ProgramDesc::kSolidWhite_ColorInput:
case ProgramDesc::kTransBlack_ColorInput:
break;
default:
GrCrash("Unknown color type.");
@ -882,7 +882,7 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type,
bool requiresAttributeColors =
!skipColor && SkToBool(desc.fVertexLayout & kColor_VertexLayoutBit);
// fColorType records how colors are specified for the program. Strip
// fColorInput records how colors are specified for the program. Strip
// the bit from the layout to avoid false negatives when searching for an
// existing program in the cache.
desc.fVertexLayout &= ~(kColor_VertexLayoutBit);
@ -903,13 +903,13 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type,
(!requiresAttributeColors &&
0xffffffff == fCurrDrawState.fColor);
if (GR_AGGRESSIVE_SHADER_OPTS && colorIsTransBlack) {
desc.fColorType = ProgramDesc::kTransBlack_ColorType;
desc.fColorInput = ProgramDesc::kTransBlack_ColorInput;
} else if (GR_AGGRESSIVE_SHADER_OPTS && colorIsSolidWhite) {
desc.fColorType = ProgramDesc::kSolidWhite_ColorType;
desc.fColorInput = ProgramDesc::kSolidWhite_ColorInput;
} else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeColors) {
desc.fColorType = ProgramDesc::kUniform_ColorType;
desc.fColorInput = ProgramDesc::kUniform_ColorInput;
} else {
desc.fColorType = ProgramDesc::kAttribute_ColorType;
desc.fColorInput = ProgramDesc::kAttribute_ColorInput;
}
desc.fEdgeAANumEdges = skipCoverage ? 0 : fCurrDrawState.fEdgeAANumEdges;
@ -999,10 +999,14 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type,
stage.fOptFlags |= StageDesc::kCustomTextureDomain_OptFlagBit;
}
if (GrPixelConfigIsAlphaOnly(texture->config())) {
stage.fModulation = StageDesc::kAlpha_Modulation;
if (!this->glCaps().fTextureSwizzle &&
GrPixelConfigIsAlphaOnly(texture->config())) {
// if we don't have texture swizzle support then
// the shader must do an alpha smear after reading
// the texture
stage.fInputConfig = StageDesc::kAlphaOnly_InputConfig;
} else {
stage.fModulation = StageDesc::kColor_Modulation;
stage.fInputConfig = StageDesc::kColor_InputConfig;
}
if (sampler.getFilter() == GrSamplerState::kConvolution_Filter) {
stage.fKernelWidth = sampler.getKernelWidth();
@ -1012,9 +1016,9 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type,
} else {
stage.fOptFlags = 0;
stage.fCoordMapping = (StageDesc::CoordMapping)0;
stage.fModulation = (StageDesc::Modulation)0;
stage.fFetchMode = (StageDesc::FetchMode) 0;
stage.fKernelWidth = 0;
stage.fInputConfig = (StageDesc::InputConfig)0;
stage.fFetchMode = (StageDesc::FetchMode) 0;
stage.fKernelWidth = 0;
}
}