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