diff options
-rw-r--r-- | gm/yuvtorgbeffect.cpp | 137 | ||||
-rw-r--r-- | gyp/gmslides.gypi | 1 | ||||
-rw-r--r-- | gyp/gpu.gypi | 2 | ||||
-rw-r--r-- | src/gpu/effects/GrYUVtoRGBEffect.cpp | 108 | ||||
-rw-r--r-- | src/gpu/effects/GrYUVtoRGBEffect.h | 21 |
5 files changed, 269 insertions, 0 deletions
diff --git a/gm/yuvtorgbeffect.cpp b/gm/yuvtorgbeffect.cpp new file mode 100644 index 0000000000..b1f495e8cc --- /dev/null +++ b/gm/yuvtorgbeffect.cpp @@ -0,0 +1,137 @@ + +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +// This test only works with the GPU backend. + +#include "gm.h" + +#if SK_SUPPORT_GPU + +#include "GrContext.h" +#include "GrTest.h" +#include "effects/GrYUVtoRGBEffect.h" +#include "SkBitmap.h" +#include "SkGr.h" +#include "SkGradientShader.h" + +namespace skiagm { +/** + * This GM directly exercises GrYUVtoRGBEffect. + */ +class YUVtoRGBEffect : public GM { +public: + YUVtoRGBEffect() { + this->setBGColor(0xFFFFFFFF); + } + +protected: + virtual SkString onShortName() SK_OVERRIDE { + return SkString("yuv_to_rgb_effect"); + } + + virtual SkISize onISize() SK_OVERRIDE { + return SkISize::Make(334, 64); + } + + virtual uint32_t onGetFlags() const SK_OVERRIDE { + // This is a GPU-specific GM. + return kGPUOnly_Flag; + } + + virtual void onOnceBeforeDraw() SK_OVERRIDE { + SkImageInfo info = SkImageInfo::MakeA8(24, 24); + fBmp[0].allocPixels(info); + fBmp[1].allocPixels(info); + fBmp[2].allocPixels(info); + unsigned char* pixels[3]; + for (int i = 0; i < 3; ++i) { + pixels[i] = (unsigned char*)fBmp[i].getPixels(); + } + int color[] = {0, 85, 170}; + const int limit[] = {255, 0, 255}; + const int invl[] = {0, 255, 0}; + const int inc[] = {1, -1, 1}; + for (int j = 0; j < 576; ++j) { + for (int i = 0; i < 3; ++i) { + pixels[i][j] = (unsigned char)color[i]; + color[i] = (color[i] == limit[i]) ? invl[i] : color[i] + inc[i]; + } + } + } + + virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { + GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget(); + if (NULL == rt) { + return; + } + GrContext* context = rt->getContext(); + if (NULL == context) { + return; + } + + GrTestTarget tt; + context->getTestTarget(&tt); + if (NULL == tt.target()) { + SkDEBUGFAIL("Couldn't get Gr test target."); + return; + } + + GrDrawState* drawState = tt.target()->drawState(); + + GrTexture* texture[3]; + texture[0] = GrLockAndRefCachedBitmapTexture(context, fBmp[0], NULL); + texture[1] = GrLockAndRefCachedBitmapTexture(context, fBmp[1], NULL); + texture[2] = GrLockAndRefCachedBitmapTexture(context, fBmp[2], NULL); + if ((NULL == texture[0]) || (NULL == texture[1]) || (NULL == texture[2])) { + return; + } + + static const SkScalar kDrawPad = 10.f; + static const SkScalar kTestPad = 10.f; + + SkRect renderRect = SkRect::MakeWH(SkIntToScalar(fBmp[0].width()), + SkIntToScalar(fBmp[0].height())); + renderRect.outset(kDrawPad, kDrawPad); + + SkScalar y = kDrawPad + kTestPad; + SkScalar x = kDrawPad + kTestPad; + + const int indices[6][3] = {{0, 1, 2}, {0, 2, 1}, {1, 0, 2}, {1, 2, 0}, {2, 0, 1}, {2, 1, 0}}; + + for (int i = 0; i < 6; ++i) { + SkAutoTUnref<GrEffectRef> effect( + GrYUVtoRGBEffect::Create(texture[indices[i][0]], + texture[indices[i][1]], + texture[indices[i][2]])); + if (effect) { + SkMatrix viewMatrix; + viewMatrix.setTranslate(x, y); + drawState->reset(viewMatrix); + drawState->setRenderTarget(rt); + drawState->setColor(0xffffffff); + drawState->addColorEffect(effect, 1); + tt.target()->drawSimpleRect(renderRect); + } + x += renderRect.width() + kTestPad; + } + + GrUnlockAndUnrefCachedBitmapTexture(texture[0]); + GrUnlockAndUnrefCachedBitmapTexture(texture[1]); + GrUnlockAndUnrefCachedBitmapTexture(texture[2]); + } + +private: + SkBitmap fBmp[3]; + + typedef GM INHERITED; +}; + +DEF_GM( return SkNEW(YUVtoRGBEffect); ) +} + +#endif diff --git a/gyp/gmslides.gypi b/gyp/gmslides.gypi index 6bf46a393c..1ee27fda8c 100644 --- a/gyp/gmslides.gypi +++ b/gyp/gmslides.gypi @@ -182,6 +182,7 @@ '../gm/xfermodes.cpp', '../gm/xfermodes2.cpp', '../gm/xfermodes3.cpp', + '../gm/yuvtorgbeffect.cpp', # Files needed by particular GMs '../src/utils/debugger/SkDrawCommand.h', diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi index 9b01a46118..551f48db66 100644 --- a/gyp/gpu.gypi +++ b/gyp/gpu.gypi @@ -173,6 +173,8 @@ '<(skia_src_path)/gpu/effects/GrTextureDomain.h', '<(skia_src_path)/gpu/effects/GrTextureStripAtlas.cpp', '<(skia_src_path)/gpu/effects/GrTextureStripAtlas.h', + '<(skia_src_path)/gpu/effects/GrYUVtoRGBEffect.cpp', + '<(skia_src_path)/gpu/effects/GrYUVtoRGBEffect.h', '<(skia_src_path)/gpu/gl/GrGLAssembleInterface.cpp', '<(skia_src_path)/gpu/gl/GrGLAssembleInterface.h', diff --git a/src/gpu/effects/GrYUVtoRGBEffect.cpp b/src/gpu/effects/GrYUVtoRGBEffect.cpp new file mode 100644 index 0000000000..1e3810f619 --- /dev/null +++ b/src/gpu/effects/GrYUVtoRGBEffect.cpp @@ -0,0 +1,108 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrYUVtoRGBEffect.h" + +#include "GrCoordTransform.h" +#include "GrEffect.h" +#include "gl/GrGLEffect.h" +#include "GrTBackendEffectFactory.h" + +namespace { + +class YUVtoRGBEffect : public GrEffect { +public: + static GrEffectRef* Create(GrTexture* yTexture, GrTexture* uTexture, GrTexture* vTexture) { + AutoEffectUnref effect(SkNEW_ARGS(YUVtoRGBEffect, (yTexture, uTexture, vTexture))); + return CreateEffectRef(effect); + } + + static const char* Name() { return "YUV to RGB"; } + + virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { + return GrTBackendEffectFactory<YUVtoRGBEffect>::getInstance(); + } + + virtual void getConstantColorComponents(GrColor* color, + uint32_t* validFlags) const SK_OVERRIDE { + // YUV is opaque + *color = 0xFF; + *validFlags = kA_GrColorComponentFlag; + } + + class GLEffect : public GrGLEffect { + public: + // this class always generates the same code. + static EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&) { return 0; } + + GLEffect(const GrBackendEffectFactory& factory, + const GrDrawEffect&) + : INHERITED(factory) { + } + + virtual void emitCode(GrGLShaderBuilder* builder, + const GrDrawEffect&, + EffectKey, + const char* outputColor, + const char* inputColor, + const TransformedCoordsArray& coords, + const TextureSamplerArray& samplers) SK_OVERRIDE { + const char* yuvMatrix = "yuvMatrix"; + builder->fsCodeAppendf("\tconst mat4 %s = mat4(1.0, 0.0, 1.402, -0.701,\n\t\t\t" + "1.0, -0.344, -0.714, 0.529,\n\t\t\t" + "1.0, 1.772, 0.0, -0.886,\n\t\t\t" + "0.0, 0.0, 0.0, 1.0);\n", + yuvMatrix); + builder->fsCodeAppendf("\t%s = vec4(\n\t\t", outputColor); + builder->fsAppendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type()); + builder->fsCodeAppend(".r,\n\t\t"); + builder->fsAppendTextureLookup(samplers[1], coords[0].c_str(), coords[0].type()); + builder->fsCodeAppend(".r,\n\t\t"); + builder->fsAppendTextureLookup(samplers[2], coords[0].c_str(), coords[0].type()); + builder->fsCodeAppendf(".r,\n\t\t1.0) * %s;\n", yuvMatrix); + } + + typedef GrGLEffect INHERITED; + }; + +private: + YUVtoRGBEffect(GrTexture* yTexture, GrTexture* uTexture, GrTexture* vTexture) + : fCoordTransform(kLocal_GrCoordSet, MakeDivByTextureWHMatrix(yTexture), yTexture) + , fYAccess(yTexture) + , fUAccess(uTexture) + , fVAccess(vTexture) { + this->addCoordTransform(&fCoordTransform); + this->addTextureAccess(&fYAccess); + this->addTextureAccess(&fUAccess); + this->addTextureAccess(&fVAccess); + this->setWillNotUseInputColor(); + } + + virtual bool onIsEqual(const GrEffect& sBase) const { + const YUVtoRGBEffect& s = CastEffect<YUVtoRGBEffect>(sBase); + return fYAccess.getTexture() == s.fYAccess.getTexture() && + fUAccess.getTexture() == s.fUAccess.getTexture() && + fVAccess.getTexture() == s.fVAccess.getTexture(); + } + + GrCoordTransform fCoordTransform; + GrTextureAccess fYAccess; + GrTextureAccess fUAccess; + GrTextureAccess fVAccess; + + typedef GrEffect INHERITED; +}; + +} + +////////////////////////////////////////////////////////////////////////////// + +GrEffectRef* GrYUVtoRGBEffect::Create(GrTexture* yTexture, + GrTexture* uTexture, + GrTexture* vTexture) { + return YUVtoRGBEffect::Create(yTexture, uTexture, vTexture); +} diff --git a/src/gpu/effects/GrYUVtoRGBEffect.h b/src/gpu/effects/GrYUVtoRGBEffect.h new file mode 100644 index 0000000000..cc86af7662 --- /dev/null +++ b/src/gpu/effects/GrYUVtoRGBEffect.h @@ -0,0 +1,21 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrYUVtoRGBEffect_DEFINED +#define GrYUVtoRGBEffect_DEFINED + +class GrEffectRef; +class GrTexture; + +namespace GrYUVtoRGBEffect { + /** + * Creates an effect that performs color conversion from YUV to RGB + */ + GrEffectRef* Create(GrTexture* yTexture, GrTexture* uTexture, GrTexture* vTexture); +}; + +#endif |