1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <GLES/gl.h>
18 #include <GLES2/gl2.h>
19 #include <GLES/glext.h>
20 
21 #include <rs_hal.h>
22 #include <rsContext.h>
23 #include <rsMesh.h>
24 
25 #include "rsdAllocation.h"
26 #include "rsdMeshObj.h"
27 #include "rsdGL.h"
28 
29 #include <string>
30 
31 using android::renderscript::Allocation;
32 using android::renderscript::Context;
33 using android::renderscript::Element;
34 using android::renderscript::Mesh;
35 
RsdMeshObj(const Context * rsc,const Mesh * rsMesh)36 RsdMeshObj::RsdMeshObj(const Context *rsc, const Mesh *rsMesh) {
37     mRSMesh = rsMesh;
38 
39     mAttribs = nullptr;
40     mAttribAllocationIndex = nullptr;
41     mGLPrimitives = nullptr;
42 
43     mAttribCount = 0;
44 }
45 
~RsdMeshObj()46 RsdMeshObj::~RsdMeshObj() {
47     if (mAttribs) {
48         delete[] mAttribs;
49         delete[] mAttribAllocationIndex;
50     }
51     if (mGLPrimitives) {
52         delete[] mGLPrimitives;
53     }
54 }
55 
isValidGLComponent(const Element * elem,uint32_t fieldIdx)56 bool RsdMeshObj::isValidGLComponent(const Element *elem, uint32_t fieldIdx) {
57     // Only GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FIXED, GL_FLOAT are accepted.
58     // Filter rs types accordingly
59     RsDataType dt = elem->mHal.state.fields[fieldIdx]->mHal.state.dataType;
60     if (dt != RS_TYPE_FLOAT_32 && dt != RS_TYPE_UNSIGNED_8 &&
61         dt != RS_TYPE_UNSIGNED_16 && dt != RS_TYPE_SIGNED_8 &&
62         dt != RS_TYPE_SIGNED_16) {
63         return false;
64     }
65 
66     // Now make sure they are not arrays
67     uint32_t arraySize = elem->mHal.state.fieldArraySizes[fieldIdx];
68     if (arraySize != 1) {
69         return false;
70     }
71 
72     return true;
73 }
74 
init(const Context * rsc)75 bool RsdMeshObj::init(const Context *rsc) {
76 
77     updateGLPrimitives(rsc);
78 
79     // Count the number of gl attrs to initialize
80     mAttribCount = 0;
81     for (uint32_t ct=0; ct < mRSMesh->mHal.state.vertexBuffersCount; ct++) {
82         const Element *elem = mRSMesh->mHal.state.vertexBuffers[ct]->getType()->getElement();
83         for (uint32_t ct=0; ct < elem->mHal.state.fieldsCount; ct++) {
84             if (isValidGLComponent(elem, ct)) {
85                 mAttribCount ++;
86             }
87         }
88     }
89 
90     if (mAttribs) {
91         delete [] mAttribs;
92         delete [] mAttribAllocationIndex;
93         mAttribs = nullptr;
94         mAttribAllocationIndex = nullptr;
95     }
96     if (!mAttribCount) {
97         return false;
98     }
99 
100     mAttribs = new RsdVertexArray::Attrib[mAttribCount];
101     mAttribAllocationIndex = new uint32_t[mAttribCount];
102 
103     uint32_t userNum = 0;
104     for (uint32_t ct=0; ct < mRSMesh->mHal.state.vertexBuffersCount; ct++) {
105         const Element *elem = mRSMesh->mHal.state.vertexBuffers[ct]->getType()->getElement();
106         uint32_t stride = elem->mHal.state.elementSizeBytes;
107         for (uint32_t fieldI=0; fieldI < elem->mHal.state.fieldsCount; fieldI++) {
108             const Element *f = elem->mHal.state.fields[fieldI];
109 
110             if (!isValidGLComponent(elem, fieldI)) {
111                 continue;
112             }
113 
114             mAttribs[userNum].size = f->mHal.state.vectorSize;
115             mAttribs[userNum].offset = elem->mHal.state.fieldOffsetBytes[fieldI];
116             mAttribs[userNum].type = rsdTypeToGLType(f->mHal.state.dataType);
117             mAttribs[userNum].normalized = f->mHal.state.dataType != RS_TYPE_FLOAT_32;
118             mAttribs[userNum].stride = stride;
119             std::string tmp(RS_SHADER_ATTR);
120             tmp.append(elem->mHal.state.fieldNames[fieldI]);
121             mAttribs[userNum].name = tmp;
122 
123             // Remember which allocation this attribute came from
124             mAttribAllocationIndex[userNum] = ct;
125             userNum ++;
126         }
127     }
128 
129     return true;
130 }
131 
renderPrimitiveRange(const Context * rsc,uint32_t primIndex,size_t start,uint32_t len) const132 void RsdMeshObj::renderPrimitiveRange(const Context *rsc, uint32_t primIndex,
133                                       size_t start, uint32_t len) const {
134     if (len < 1 || primIndex >= mRSMesh->mHal.state.primitivesCount || mAttribCount == 0) {
135         rsc->setError(RS_ERROR_FATAL_DRIVER, "Invalid mesh or parameters");
136         return;
137     }
138 
139     for (uint32_t ct=0; ct < mRSMesh->mHal.state.vertexBuffersCount; ct++) {
140         const Allocation *alloc = mRSMesh->mHal.state.vertexBuffers[ct];
141         DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
142         if (drv->uploadDeferred) {
143             rsdAllocationSyncAll(rsc, alloc, RS_ALLOCATION_USAGE_SCRIPT);
144         }
145     }
146 
147     // update attributes with either buffer information or data ptr based on their current state
148     for (uint32_t ct=0; ct < mAttribCount; ct++) {
149         uint32_t allocIndex = mAttribAllocationIndex[ct];
150         Allocation *alloc = mRSMesh->mHal.state.vertexBuffers[allocIndex];
151         DrvAllocation *drvAlloc = (DrvAllocation *)alloc->mHal.drv;
152 
153         if (drvAlloc->bufferID) {
154             mAttribs[ct].buffer = drvAlloc->bufferID;
155             mAttribs[ct].ptr = nullptr;
156         } else {
157             mAttribs[ct].buffer = 0;
158             mAttribs[ct].ptr = (const uint8_t*)alloc->mHal.drvState.lod[0].mallocPtr;
159         }
160     }
161 
162     RsdVertexArray va(mAttribs, mAttribCount);
163     va.setup(rsc);
164 
165     const Allocation *idxAlloc = mRSMesh->mHal.state.indexBuffers[primIndex];
166     if (idxAlloc) {
167         DrvAllocation *drvAlloc = (DrvAllocation *)idxAlloc->mHal.drv;
168         if (drvAlloc->uploadDeferred) {
169             rsdAllocationSyncAll(rsc, idxAlloc, RS_ALLOCATION_USAGE_SCRIPT);
170         }
171 
172         if (drvAlloc->bufferID) {
173             RSD_CALL_GL(glBindBuffer, GL_ELEMENT_ARRAY_BUFFER, drvAlloc->bufferID);
174             RSD_CALL_GL(glDrawElements, mGLPrimitives[primIndex], len, GL_UNSIGNED_SHORT,
175                         (uint16_t *)(start * 2));
176         } else {
177             RSD_CALL_GL(glBindBuffer, GL_ELEMENT_ARRAY_BUFFER, 0);
178             RSD_CALL_GL(glDrawElements, mGLPrimitives[primIndex], len, GL_UNSIGNED_SHORT,
179                         idxAlloc->mHal.drvState.lod[0].mallocPtr);
180         }
181     } else {
182         RSD_CALL_GL(glDrawArrays, mGLPrimitives[primIndex], start, len);
183     }
184 
185     rsdGLCheckError(rsc, "Mesh::renderPrimitiveRange");
186 }
187 
updateGLPrimitives(const Context * rsc)188 void RsdMeshObj::updateGLPrimitives(const Context *rsc) {
189     mGLPrimitives = new uint32_t[mRSMesh->mHal.state.primitivesCount];
190     for (uint32_t i = 0; i < mRSMesh->mHal.state.primitivesCount; i ++) {
191         switch (mRSMesh->mHal.state.primitives[i]) {
192             case RS_PRIMITIVE_POINT:          mGLPrimitives[i] = GL_POINTS; break;
193             case RS_PRIMITIVE_LINE:           mGLPrimitives[i] = GL_LINES; break;
194             case RS_PRIMITIVE_LINE_STRIP:     mGLPrimitives[i] = GL_LINE_STRIP; break;
195             case RS_PRIMITIVE_TRIANGLE:       mGLPrimitives[i] = GL_TRIANGLES; break;
196             case RS_PRIMITIVE_TRIANGLE_STRIP: mGLPrimitives[i] = GL_TRIANGLE_STRIP; break;
197             case RS_PRIMITIVE_TRIANGLE_FAN:   mGLPrimitives[i] = GL_TRIANGLE_FAN; break;
198             default: rsc->setError(RS_ERROR_FATAL_DRIVER, "Invalid mesh primitive"); break;
199         }
200     }
201 }
202