1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* 2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2014 Google Inc. 3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be 5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file. 6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef GrProgramDesc_DEFINED 9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define GrProgramDesc_DEFINED 10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrColor.h" 12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrTypesPriv.h" 13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkOpts.h" 14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTArray.h" 15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "glsl/GrGLSLFragmentShaderBuilder.h" 16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass GrShaderCaps; 18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass GrPipeline; 19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass GrPrimitiveProcessor; 20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/** This class describes a program to generate. It also serves as a program cache key */ 22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass GrProgramDesc { 23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic: 24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Creates an uninitialized key that must be populated by GrGpu::buildProgramDesc() 25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrProgramDesc() {} 26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Builds a program descriptor. Before the descriptor can be used, the client must call finalize 29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * on the returned GrProgramDesc. 30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * @param GrPrimitiveProcessor The geometry 32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * @param hasPointSize Controls whether the shader will output a point size. 33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * @param GrPipeline The optimized drawstate. The descriptor will represent a program 34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * which this optstate can use to draw with. The optstate contains 35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * general draw information, as well as the specific color, geometry, 36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * and coverage stages which will be used to generate the GL Program for 37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * this optstate. 38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * @param GrShaderCaps Capabilities of the shading language. 39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * @param GrProgramDesc The built and finalized descriptor 40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot **/ 41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static bool Build(GrProgramDesc*, 42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const GrPrimitiveProcessor&, 43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool hasPointSize, 44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const GrPipeline&, 45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const GrShaderCaps&); 46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Returns this as a uint32_t array to be used as a key in the program cache. 48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const uint32_t* asKey() const { 49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return reinterpret_cast<const uint32_t*>(fKey.begin()); 50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Gets the number of bytes in asKey(). It will be a 4-byte aligned value. When comparing two 53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // keys the size of either key can be used with memcmp() since the lengths themselves begin the 54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // keys and thus the memcmp will exit early if the keys are of different lengths. 55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t keyLength() const { return *this->atOffset<uint32_t, kLengthOffset>(); } 56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Gets the a checksum of the key. Can be used as a hash value for a fast lookup in a cache. 58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t getChecksum() const { return *this->atOffset<uint32_t, kChecksumOffset>(); } 59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrProgramDesc& operator= (const GrProgramDesc& other) { 61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t keyLength = other.keyLength(); 62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fKey.reset(SkToInt(keyLength)); 63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot memcpy(fKey.begin(), other.fKey.begin(), keyLength); 64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return *this; 65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool operator== (const GrProgramDesc& that) const { 68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(SkIsAlign4(this->keyLength())); 69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int l = this->keyLength() >> 2; 70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const uint32_t* aKey = this->asKey(); 71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const uint32_t* bKey = that.asKey(); 72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < l; ++i) { 73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (aKey[i] != bKey[i]) { 74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool operator!= (const GrProgramDesc& other) const { 81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return !(*this == other); 82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void setSurfaceOriginKey(int key) { 85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot KeyHeader* header = this->atOffset<KeyHeader, kHeaderOffset>(); 86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot header->fSurfaceOriginKey = key; 87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static bool Less(const GrProgramDesc& a, const GrProgramDesc& b) { 90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(SkIsAlign4(a.keyLength())); 91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int l = a.keyLength() >> 2; 92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const uint32_t* aKey = a.asKey(); 93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const uint32_t* bKey = b.asKey(); 94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < l; ++i) { 95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (aKey[i] != bKey[i]) { 96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return aKey[i] < bKey[i] ? true : false; 97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot struct KeyHeader { 103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Set to uniquely identify the sample pattern, or 0 if the shader doesn't use sample 104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // locations. 105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint8_t fSamplePatternKey; 106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Set to uniquely idenitify any swizzling of the shader's output color(s). 107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint8_t fOutputSwizzle; 108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint8_t fColorFragmentProcessorCnt : 4; 109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint8_t fCoverageFragmentProcessorCnt : 4; 110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Set to uniquely identify the rt's origin, or 0 if the shader does not require this info. 111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint8_t fSurfaceOriginKey : 2; 112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint8_t fSnapVerticesToPixelCenters : 1; 113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint8_t fHasPointSize : 1; 114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint8_t fPad : 4; 115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GR_STATIC_ASSERT(sizeof(KeyHeader) == 4); 117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // This should really only be used internally, base classes should return their own headers 119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const KeyHeader& header() const { return *this->atOffset<KeyHeader, kHeaderOffset>(); } 120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void finalize() { 122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int keyLength = fKey.count(); 123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(0 == (keyLength % 4)); 124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *(this->atOffset<uint32_t, GrProgramDesc::kLengthOffset>()) = SkToU32(keyLength); 125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t* checksum = this->atOffset<uint32_t, GrProgramDesc::kChecksumOffset>(); 127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *checksum = 0; // We'll hash through these bytes, so make sure they're initialized. 128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *checksum = SkOpts::hash(fKey.begin(), keyLength); 129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprotected: 132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot template<typename T, size_t OFFSET> T* atOffset() { 133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(fKey.begin()) + OFFSET); 134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot template<typename T, size_t OFFSET> const T* atOffset() const { 137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return reinterpret_cast<const T*>(reinterpret_cast<intptr_t>(fKey.begin()) + OFFSET); 138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // The key, stored in fKey, is composed of four parts: 141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // 1. uint32_t for total key length. 142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // 2. uint32_t for a checksum. 143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // 3. Header struct defined above. 144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // 4. A Backend specific payload which includes the per-processor keys. 145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot enum KeyOffsets { 146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Part 1. 147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kLengthOffset = 0, 148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Part 2. 149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kChecksumOffset = kLengthOffset + sizeof(uint32_t), 150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Part 3. 151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kHeaderOffset = kChecksumOffset + sizeof(uint32_t), 152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kHeaderSize = SkAlign4(sizeof(KeyHeader)), 153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Part 4. 154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // This is the offset into the backenend specific part of the key, which includes 155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // per-processor keys. 156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kProcessorKeysOffset = kHeaderOffset + kHeaderSize, 157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot enum { 160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kMaxPreallocProcessors = 8, 161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kIntsPerProcessor = 4, // This is an overestimate of the average effect key size. 162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kPreAllocSize = kHeaderOffset + kHeaderSize + 163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kMaxPreallocProcessors * sizeof(uint32_t) * kIntsPerProcessor, 164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkSTArray<kPreAllocSize, uint8_t, true>& key() { return fKey; } 167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkSTArray<kPreAllocSize, uint8_t, true>& key() const { return fKey; } 168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate: 170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkSTArray<kPreAllocSize, uint8_t, true> fKey; 171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 174