1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2013 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/gpu/GrCpuBuffer.h" 9cb93a386Sopenharmony_ci#include "src/gpu/gl/GrGLBuffer.h" 10cb93a386Sopenharmony_ci#include "src/gpu/gl/GrGLGpu.h" 11cb93a386Sopenharmony_ci#include "src/gpu/gl/GrGLVertexArray.h" 12cb93a386Sopenharmony_ci 13cb93a386Sopenharmony_cistruct AttribLayout { 14cb93a386Sopenharmony_ci bool fNormalized; // Only used by floating point types. 15cb93a386Sopenharmony_ci uint8_t fCount; 16cb93a386Sopenharmony_ci uint16_t fType; 17cb93a386Sopenharmony_ci}; 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_cistatic_assert(4 == sizeof(AttribLayout)); 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_cistatic AttribLayout attrib_layout(GrVertexAttribType type) { 22cb93a386Sopenharmony_ci switch (type) { 23cb93a386Sopenharmony_ci case kFloat_GrVertexAttribType: 24cb93a386Sopenharmony_ci return {false, 1, GR_GL_FLOAT}; 25cb93a386Sopenharmony_ci case kFloat2_GrVertexAttribType: 26cb93a386Sopenharmony_ci return {false, 2, GR_GL_FLOAT}; 27cb93a386Sopenharmony_ci case kFloat3_GrVertexAttribType: 28cb93a386Sopenharmony_ci return {false, 3, GR_GL_FLOAT}; 29cb93a386Sopenharmony_ci case kFloat4_GrVertexAttribType: 30cb93a386Sopenharmony_ci return {false, 4, GR_GL_FLOAT}; 31cb93a386Sopenharmony_ci case kHalf_GrVertexAttribType: 32cb93a386Sopenharmony_ci return {false, 1, GR_GL_HALF_FLOAT}; 33cb93a386Sopenharmony_ci case kHalf2_GrVertexAttribType: 34cb93a386Sopenharmony_ci return {false, 2, GR_GL_HALF_FLOAT}; 35cb93a386Sopenharmony_ci case kHalf4_GrVertexAttribType: 36cb93a386Sopenharmony_ci return {false, 4, GR_GL_HALF_FLOAT}; 37cb93a386Sopenharmony_ci case kInt2_GrVertexAttribType: 38cb93a386Sopenharmony_ci return {false, 2, GR_GL_INT}; 39cb93a386Sopenharmony_ci case kInt3_GrVertexAttribType: 40cb93a386Sopenharmony_ci return {false, 3, GR_GL_INT}; 41cb93a386Sopenharmony_ci case kInt4_GrVertexAttribType: 42cb93a386Sopenharmony_ci return {false, 4, GR_GL_INT}; 43cb93a386Sopenharmony_ci case kByte_GrVertexAttribType: 44cb93a386Sopenharmony_ci return {false, 1, GR_GL_BYTE}; 45cb93a386Sopenharmony_ci case kByte2_GrVertexAttribType: 46cb93a386Sopenharmony_ci return {false, 2, GR_GL_BYTE}; 47cb93a386Sopenharmony_ci case kByte4_GrVertexAttribType: 48cb93a386Sopenharmony_ci return {false, 4, GR_GL_BYTE}; 49cb93a386Sopenharmony_ci case kUByte_GrVertexAttribType: 50cb93a386Sopenharmony_ci return {false, 1, GR_GL_UNSIGNED_BYTE}; 51cb93a386Sopenharmony_ci case kUByte2_GrVertexAttribType: 52cb93a386Sopenharmony_ci return {false, 2, GR_GL_UNSIGNED_BYTE}; 53cb93a386Sopenharmony_ci case kUByte4_GrVertexAttribType: 54cb93a386Sopenharmony_ci return {false, 4, GR_GL_UNSIGNED_BYTE}; 55cb93a386Sopenharmony_ci case kUByte_norm_GrVertexAttribType: 56cb93a386Sopenharmony_ci return {true, 1, GR_GL_UNSIGNED_BYTE}; 57cb93a386Sopenharmony_ci case kUByte4_norm_GrVertexAttribType: 58cb93a386Sopenharmony_ci return {true, 4, GR_GL_UNSIGNED_BYTE}; 59cb93a386Sopenharmony_ci case kShort2_GrVertexAttribType: 60cb93a386Sopenharmony_ci return {false, 2, GR_GL_SHORT}; 61cb93a386Sopenharmony_ci case kShort4_GrVertexAttribType: 62cb93a386Sopenharmony_ci return {false, 4, GR_GL_SHORT}; 63cb93a386Sopenharmony_ci case kUShort2_GrVertexAttribType: 64cb93a386Sopenharmony_ci return {false, 2, GR_GL_UNSIGNED_SHORT}; 65cb93a386Sopenharmony_ci case kUShort2_norm_GrVertexAttribType: 66cb93a386Sopenharmony_ci return {true, 2, GR_GL_UNSIGNED_SHORT}; 67cb93a386Sopenharmony_ci case kInt_GrVertexAttribType: 68cb93a386Sopenharmony_ci return {false, 1, GR_GL_INT}; 69cb93a386Sopenharmony_ci case kUInt_GrVertexAttribType: 70cb93a386Sopenharmony_ci return {false, 1, GR_GL_UNSIGNED_INT}; 71cb93a386Sopenharmony_ci case kUShort_norm_GrVertexAttribType: 72cb93a386Sopenharmony_ci return {true, 1, GR_GL_UNSIGNED_SHORT}; 73cb93a386Sopenharmony_ci case kUShort4_norm_GrVertexAttribType: 74cb93a386Sopenharmony_ci return {true, 4, GR_GL_UNSIGNED_SHORT}; 75cb93a386Sopenharmony_ci } 76cb93a386Sopenharmony_ci SK_ABORT("Unknown vertex attrib type"); 77cb93a386Sopenharmony_ci}; 78cb93a386Sopenharmony_ci 79cb93a386Sopenharmony_civoid GrGLAttribArrayState::set(GrGLGpu* gpu, 80cb93a386Sopenharmony_ci int index, 81cb93a386Sopenharmony_ci const GrBuffer* vertexBuffer, 82cb93a386Sopenharmony_ci GrVertexAttribType cpuType, 83cb93a386Sopenharmony_ci GrSLType gpuType, 84cb93a386Sopenharmony_ci GrGLsizei stride, 85cb93a386Sopenharmony_ci size_t offsetInBytes, 86cb93a386Sopenharmony_ci int divisor) { 87cb93a386Sopenharmony_ci SkASSERT(index >= 0 && index < fAttribArrayStates.count()); 88cb93a386Sopenharmony_ci SkASSERT(0 == divisor || gpu->caps()->drawInstancedSupport()); 89cb93a386Sopenharmony_ci AttribArrayState* array = &fAttribArrayStates[index]; 90cb93a386Sopenharmony_ci const char* offsetAsPtr; 91cb93a386Sopenharmony_ci bool bufferChanged = false; 92cb93a386Sopenharmony_ci if (vertexBuffer->isCpuBuffer()) { 93cb93a386Sopenharmony_ci if (!array->fUsingCpuBuffer) { 94cb93a386Sopenharmony_ci bufferChanged = true; 95cb93a386Sopenharmony_ci array->fUsingCpuBuffer = true; 96cb93a386Sopenharmony_ci } 97cb93a386Sopenharmony_ci offsetAsPtr = static_cast<const GrCpuBuffer*>(vertexBuffer)->data() + offsetInBytes; 98cb93a386Sopenharmony_ci } else { 99cb93a386Sopenharmony_ci auto gpuBuffer = static_cast<const GrGpuBuffer*>(vertexBuffer); 100cb93a386Sopenharmony_ci if (array->fUsingCpuBuffer || array->fVertexBufferUniqueID != gpuBuffer->uniqueID()) { 101cb93a386Sopenharmony_ci bufferChanged = true; 102cb93a386Sopenharmony_ci array->fVertexBufferUniqueID = gpuBuffer->uniqueID(); 103cb93a386Sopenharmony_ci } 104cb93a386Sopenharmony_ci offsetAsPtr = reinterpret_cast<const char*>(offsetInBytes); 105cb93a386Sopenharmony_ci } 106cb93a386Sopenharmony_ci if (bufferChanged || 107cb93a386Sopenharmony_ci array->fCPUType != cpuType || 108cb93a386Sopenharmony_ci array->fGPUType != gpuType || 109cb93a386Sopenharmony_ci array->fStride != stride || 110cb93a386Sopenharmony_ci array->fOffset != offsetAsPtr) { 111cb93a386Sopenharmony_ci // We always have to call this if we're going to change the array pointer. 'array' is 112cb93a386Sopenharmony_ci // tracking the last buffer used to setup attrib pointers, not the last buffer bound. 113cb93a386Sopenharmony_ci // GrGLGpu will avoid redundant binds. 114cb93a386Sopenharmony_ci gpu->bindBuffer(GrGpuBufferType::kVertex, vertexBuffer); 115cb93a386Sopenharmony_ci const AttribLayout& layout = attrib_layout(cpuType); 116cb93a386Sopenharmony_ci if (GrSLTypeIsFloatType(gpuType)) { 117cb93a386Sopenharmony_ci GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index, 118cb93a386Sopenharmony_ci layout.fCount, 119cb93a386Sopenharmony_ci layout.fType, 120cb93a386Sopenharmony_ci layout.fNormalized, 121cb93a386Sopenharmony_ci stride, 122cb93a386Sopenharmony_ci offsetAsPtr)); 123cb93a386Sopenharmony_ci } else { 124cb93a386Sopenharmony_ci SkASSERT(gpu->caps()->shaderCaps()->integerSupport()); 125cb93a386Sopenharmony_ci SkASSERT(!layout.fNormalized); 126cb93a386Sopenharmony_ci GR_GL_CALL(gpu->glInterface(), VertexAttribIPointer(index, 127cb93a386Sopenharmony_ci layout.fCount, 128cb93a386Sopenharmony_ci layout.fType, 129cb93a386Sopenharmony_ci stride, 130cb93a386Sopenharmony_ci offsetAsPtr)); 131cb93a386Sopenharmony_ci } 132cb93a386Sopenharmony_ci array->fCPUType = cpuType; 133cb93a386Sopenharmony_ci array->fGPUType = gpuType; 134cb93a386Sopenharmony_ci array->fStride = stride; 135cb93a386Sopenharmony_ci array->fOffset = offsetAsPtr; 136cb93a386Sopenharmony_ci } 137cb93a386Sopenharmony_ci if (gpu->caps()->drawInstancedSupport() && array->fDivisor != divisor) { 138cb93a386Sopenharmony_ci SkASSERT(0 == divisor || 1 == divisor); // not necessarily a requirement but what we expect. 139cb93a386Sopenharmony_ci GR_GL_CALL(gpu->glInterface(), VertexAttribDivisor(index, divisor)); 140cb93a386Sopenharmony_ci array->fDivisor = divisor; 141cb93a386Sopenharmony_ci } 142cb93a386Sopenharmony_ci} 143cb93a386Sopenharmony_ci 144cb93a386Sopenharmony_civoid GrGLAttribArrayState::enableVertexArrays(const GrGLGpu* gpu, int enabledCount, 145cb93a386Sopenharmony_ci GrPrimitiveRestart enablePrimitiveRestart) { 146cb93a386Sopenharmony_ci SkASSERT(enabledCount <= fAttribArrayStates.count()); 147cb93a386Sopenharmony_ci 148cb93a386Sopenharmony_ci if (!fEnableStateIsValid || enabledCount != fNumEnabledArrays) { 149cb93a386Sopenharmony_ci int firstIdxToEnable = fEnableStateIsValid ? fNumEnabledArrays : 0; 150cb93a386Sopenharmony_ci for (int i = firstIdxToEnable; i < enabledCount; ++i) { 151cb93a386Sopenharmony_ci GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(i)); 152cb93a386Sopenharmony_ci } 153cb93a386Sopenharmony_ci 154cb93a386Sopenharmony_ci int endIdxToDisable = fEnableStateIsValid ? fNumEnabledArrays : fAttribArrayStates.count(); 155cb93a386Sopenharmony_ci for (int i = enabledCount; i < endIdxToDisable; ++i) { 156cb93a386Sopenharmony_ci GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(i)); 157cb93a386Sopenharmony_ci } 158cb93a386Sopenharmony_ci 159cb93a386Sopenharmony_ci fNumEnabledArrays = enabledCount; 160cb93a386Sopenharmony_ci } 161cb93a386Sopenharmony_ci 162cb93a386Sopenharmony_ci SkASSERT(GrPrimitiveRestart::kNo == enablePrimitiveRestart || 163cb93a386Sopenharmony_ci gpu->caps()->usePrimitiveRestart()); 164cb93a386Sopenharmony_ci 165cb93a386Sopenharmony_ci if (gpu->caps()->usePrimitiveRestart() && 166cb93a386Sopenharmony_ci (!fEnableStateIsValid || enablePrimitiveRestart != fPrimitiveRestartEnabled)) { 167cb93a386Sopenharmony_ci if (GrPrimitiveRestart::kYes == enablePrimitiveRestart) { 168cb93a386Sopenharmony_ci GR_GL_CALL(gpu->glInterface(), Enable(GR_GL_PRIMITIVE_RESTART_FIXED_INDEX)); 169cb93a386Sopenharmony_ci } else { 170cb93a386Sopenharmony_ci GR_GL_CALL(gpu->glInterface(), Disable(GR_GL_PRIMITIVE_RESTART_FIXED_INDEX)); 171cb93a386Sopenharmony_ci } 172cb93a386Sopenharmony_ci 173cb93a386Sopenharmony_ci fPrimitiveRestartEnabled = enablePrimitiveRestart; 174cb93a386Sopenharmony_ci } 175cb93a386Sopenharmony_ci 176cb93a386Sopenharmony_ci fEnableStateIsValid = true; 177cb93a386Sopenharmony_ci} 178cb93a386Sopenharmony_ci 179cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////////////////////////// 180cb93a386Sopenharmony_ci 181cb93a386Sopenharmony_ciGrGLVertexArray::GrGLVertexArray(GrGLint id, int attribCount) 182cb93a386Sopenharmony_ci : fID(id) 183cb93a386Sopenharmony_ci , fAttribArrays(attribCount) 184cb93a386Sopenharmony_ci , fIndexBufferUniqueID(SK_InvalidUniqueID) { 185cb93a386Sopenharmony_ci} 186cb93a386Sopenharmony_ci 187cb93a386Sopenharmony_ciGrGLAttribArrayState* GrGLVertexArray::bind(GrGLGpu* gpu) { 188cb93a386Sopenharmony_ci if (0 == fID) { 189cb93a386Sopenharmony_ci return nullptr; 190cb93a386Sopenharmony_ci } 191cb93a386Sopenharmony_ci gpu->bindVertexArray(fID); 192cb93a386Sopenharmony_ci return &fAttribArrays; 193cb93a386Sopenharmony_ci} 194cb93a386Sopenharmony_ci 195cb93a386Sopenharmony_ciGrGLAttribArrayState* GrGLVertexArray::bindWithIndexBuffer(GrGLGpu* gpu, const GrBuffer* ibuff) { 196cb93a386Sopenharmony_ci GrGLAttribArrayState* state = this->bind(gpu); 197cb93a386Sopenharmony_ci if (!state) { 198cb93a386Sopenharmony_ci return nullptr; 199cb93a386Sopenharmony_ci } 200cb93a386Sopenharmony_ci if (ibuff->isCpuBuffer()) { 201cb93a386Sopenharmony_ci GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0)); 202cb93a386Sopenharmony_ci } else { 203cb93a386Sopenharmony_ci const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(ibuff); 204cb93a386Sopenharmony_ci if (fIndexBufferUniqueID != glBuffer->uniqueID()) { 205cb93a386Sopenharmony_ci GR_GL_CALL(gpu->glInterface(), 206cb93a386Sopenharmony_ci BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, glBuffer->bufferID())); 207cb93a386Sopenharmony_ci fIndexBufferUniqueID = glBuffer->uniqueID(); 208cb93a386Sopenharmony_ci } 209cb93a386Sopenharmony_ci } 210cb93a386Sopenharmony_ci return state; 211cb93a386Sopenharmony_ci} 212cb93a386Sopenharmony_ci 213cb93a386Sopenharmony_civoid GrGLVertexArray::invalidateCachedState() { 214cb93a386Sopenharmony_ci fAttribArrays.invalidate(); 215cb93a386Sopenharmony_ci fIndexBufferUniqueID.makeInvalid(); 216cb93a386Sopenharmony_ci} 217