Home | History | Annotate | Download | only in gl
      1 /*
      2  * Copyright 2013 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "GrGLVertexArray.h"
      9 #include "GrGpuGL.h"
     10 
     11 #define GPUGL static_cast<GrGpuGL*>(this->getGpu())
     12 #define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X);
     13 
     14 void GrGLAttribArrayState::set(const GrGpuGL* gpu,
     15                                int index,
     16                                GrGLVertexBuffer* buffer,
     17                                GrGLint size,
     18                                GrGLenum type,
     19                                GrGLboolean normalized,
     20                                GrGLsizei stride,
     21                                GrGLvoid* offset) {
     22     SkASSERT(index >= 0 && index < fAttribArrayStates.count());
     23     AttribArrayState* array = &fAttribArrayStates[index];
     24     if (!array->fEnableIsValid || !array->fEnabled) {
     25         GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(index));
     26         array->fEnableIsValid = true;
     27         array->fEnabled = true;
     28     }
     29     if (!array->fAttribPointerIsValid ||
     30         array->fVertexBufferID != buffer->bufferID() ||
     31         array->fSize != size ||
     32         array->fNormalized != normalized ||
     33         array->fStride != stride ||
     34         array->fOffset != offset) {
     35 
     36         buffer->bind();
     37         GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index,
     38                                                            size,
     39                                                            type,
     40                                                            normalized,
     41                                                            stride,
     42                                                            offset));
     43         array->fAttribPointerIsValid = true;
     44         array->fVertexBufferID = buffer->bufferID();
     45         array->fSize = size;
     46         array->fNormalized = normalized;
     47         array->fStride = stride;
     48         array->fOffset = offset;
     49     }
     50 }
     51 
     52 void GrGLAttribArrayState::setFixedFunctionVertexArray(const GrGpuGL* gpu,
     53                                                        GrGLVertexBuffer* buffer,
     54                                                        GrGLint size,
     55                                                        GrGLenum type,
     56                                                        GrGLsizei stride,
     57                                                        GrGLvoid* offset) {
     58     SkASSERT(gpu->glCaps().fixedFunctionSupport());
     59     AttribArrayState* array = &fFixedFunctionVertexArray;
     60     if (!array->fEnableIsValid || !array->fEnabled) {
     61         GR_GL_CALL(gpu->glInterface(), EnableClientState(GR_GL_VERTEX_ARRAY));
     62         array->fEnableIsValid = true;
     63         array->fEnabled = true;
     64     }
     65     if (!array->fAttribPointerIsValid ||
     66         array->fVertexBufferID != buffer->bufferID() ||
     67         array->fSize != size ||
     68         array->fStride != stride ||
     69         array->fOffset != offset) {
     70 
     71         buffer->bind();
     72         GR_GL_CALL(gpu->glInterface(), VertexPointer(size,
     73                                                      type,
     74                                                      stride,
     75                                                      offset));
     76         array->fAttribPointerIsValid = true;
     77         array->fVertexBufferID = buffer->bufferID();
     78         array->fSize = size;
     79         array->fStride = stride;
     80         array->fOffset = offset;
     81     }
     82 }
     83 
     84 void GrGLAttribArrayState::disableUnusedArrays(const GrGpuGL* gpu, uint64_t usedMask, bool usingFFVertexArray) {
     85     int count = fAttribArrayStates.count();
     86     for (int i = 0; i < count; ++i) {
     87         if (!(usedMask & 0x1)) {
     88             if (!fAttribArrayStates[i].fEnableIsValid || fAttribArrayStates[i].fEnabled) {
     89                 GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(i));
     90                 fAttribArrayStates[i].fEnableIsValid = true;
     91                 fAttribArrayStates[i].fEnabled = false;
     92             }
     93         } else {
     94             SkASSERT(fAttribArrayStates[i].fEnableIsValid && fAttribArrayStates[i].fEnabled);
     95         }
     96         // if the count is greater than 64 then this will become 0 and we will disable arrays 64+.
     97         usedMask >>= 1;
     98     }
     99 
    100     // Deal with fixed-function vertex arrays.
    101     if (gpu->glCaps().fixedFunctionSupport()) {
    102         if (!usingFFVertexArray) {
    103             if (!fFixedFunctionVertexArray.fEnableIsValid || fFixedFunctionVertexArray.fEnabled) {
    104                 GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_VERTEX_ARRAY));
    105                 fFixedFunctionVertexArray.fEnableIsValid = true;
    106                 fFixedFunctionVertexArray.fEnabled = false;
    107             }
    108         } else {
    109             SkASSERT(fFixedFunctionVertexArray.fEnableIsValid && fFixedFunctionVertexArray.fEnabled);
    110         }
    111         // When we use fixed function vertex processing we always use the vertex array and none of
    112         // the other arrays.
    113         if (!fUnusedFixedFunctionArraysDisabled) {
    114             GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_NORMAL_ARRAY));
    115             GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_COLOR_ARRAY));
    116             GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_SECONDARY_COLOR_ARRAY));
    117             GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_INDEX_ARRAY));
    118             GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_EDGE_FLAG_ARRAY));
    119             for (int i = 0; i < gpu->glCaps().maxFixedFunctionTextureCoords(); ++i) {
    120                 GR_GL_CALL(gpu->glInterface(), ClientActiveTexture(GR_GL_TEXTURE0 + i));
    121                 GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_TEXTURE_COORD_ARRAY));
    122             }
    123             fUnusedFixedFunctionArraysDisabled = true;
    124         }
    125     } else {
    126         SkASSERT(!usingFFVertexArray);
    127     }
    128 }
    129 
    130 ///////////////////////////////////////////////////////////////////////////////////////////////////
    131 
    132 GrGLVertexArray::GrGLVertexArray(GrGpuGL* gpu, GrGLint id, int attribCount)
    133     : GrResource(gpu, false)
    134     , fID(id)
    135     , fAttribArrays(attribCount)
    136     , fIndexBufferIDIsValid(false) {
    137 }
    138 
    139 void GrGLVertexArray::onAbandon() {
    140     fID = 0;
    141     INHERITED::onAbandon();
    142 }
    143 
    144 void GrGLVertexArray::onRelease() {
    145     if (0 != fID) {
    146         GL_CALL(DeleteVertexArrays(1, &fID));
    147         GPUGL->notifyVertexArrayDelete(fID);
    148         fID = 0;
    149     }
    150     INHERITED::onRelease();
    151 }
    152 
    153 GrGLAttribArrayState* GrGLVertexArray::bind() {
    154     if (0 == fID) {
    155         return NULL;
    156     }
    157     GPUGL->bindVertexArray(fID);
    158     return &fAttribArrays;
    159 }
    160 
    161 GrGLAttribArrayState* GrGLVertexArray::bindWithIndexBuffer(const GrGLIndexBuffer* buffer) {
    162     GrGLAttribArrayState* state = this->bind();
    163     if (NULL != state && NULL != buffer) {
    164         GrGLuint bufferID = buffer->bufferID();
    165         if (!fIndexBufferIDIsValid || bufferID != fIndexBufferID) {
    166             GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, bufferID));
    167             fIndexBufferIDIsValid = true;
    168             fIndexBufferID = bufferID;
    169         }
    170     }
    171     return state;
    172 }
    173 
    174 void GrGLVertexArray::notifyIndexBufferDelete(GrGLuint bufferID) {
    175     if (fIndexBufferIDIsValid && bufferID == fIndexBufferID) {
    176         fIndexBufferID = 0;
    177     }
    178  }
    179 
    180 void GrGLVertexArray::invalidateCachedState() {
    181     fAttribArrays.invalidate();
    182     fIndexBufferIDIsValid = false;
    183 }
    184