| /* | 
 |  * Copyright (C) 2009 The Android Open Source Project | 
 |  * | 
 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 |  * you may not use this file except in compliance with the License. | 
 |  * You may obtain a copy of the License at | 
 |  * | 
 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 |  * | 
 |  * Unless required by applicable law or agreed to in writing, software | 
 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 |  * See the License for the specific language governing permissions and | 
 |  * limitations under the License. | 
 |  */ | 
 |  | 
 | #ifndef ANDROID_RS_BUILD_FOR_HOST | 
 | #include "rsContext.h" | 
 |  | 
 | #include <GLES/gl.h> | 
 | #include <GLES2/gl2.h> | 
 | #include <GLES/glext.h> | 
 | #else | 
 | #include "rsContextHostStub.h" | 
 |  | 
 | #include <OpenGL/gl.h> | 
 | #include <OpenGl/glext.h> | 
 | #endif | 
 |  | 
 | using namespace android; | 
 | using namespace android::renderscript; | 
 |  | 
 |  | 
 |  | 
 |  | 
 | SimpleMesh::SimpleMesh(Context *rsc) : ObjectBase(rsc) | 
 | { | 
 |     mAllocFile = __FILE__; | 
 |     mAllocLine = __LINE__; | 
 | } | 
 |  | 
 | SimpleMesh::~SimpleMesh() | 
 | { | 
 |     delete[] mVertexTypes; | 
 |     delete[] mVertexBuffers; | 
 | } | 
 |  | 
 | void SimpleMesh::render(Context *rsc) const | 
 | { | 
 |     if (mPrimitiveType.get()) { | 
 |         renderRange(rsc, 0, mPrimitiveType->getDimX()); | 
 |         return; | 
 |     } | 
 |  | 
 |     if (mIndexType.get()) { | 
 |         renderRange(rsc, 0, mIndexType->getDimX()); | 
 |         return; | 
 |     } | 
 |  | 
 |     renderRange(rsc, 0, mVertexTypes[0]->getDimX()); | 
 | } | 
 |  | 
 | void SimpleMesh::renderRange(Context *rsc, uint32_t start, uint32_t len) const | 
 | { | 
 |     if (len < 1) { | 
 |         return; | 
 |     } | 
 |  | 
 |     rsc->checkError("SimpleMesh::renderRange 1"); | 
 |     VertexArray va; | 
 |     for (uint32_t ct=0; ct < mVertexTypeCount; ct++) { | 
 |         mVertexBuffers[ct]->uploadCheck(rsc); | 
 |         va.setActiveBuffer(mVertexBuffers[ct]->getBufferObjectID()); | 
 |         mVertexTypes[ct]->enableGLVertexBuffer(&va); | 
 |     } | 
 |     va.setupGL2(rsc, &rsc->mStateVertexArray, &rsc->mShaderCache); | 
 |  | 
 |     rsc->checkError("SimpleMesh::renderRange 2"); | 
 |     if (mIndexType.get()) { | 
 |         mIndexBuffer->uploadCheck(rsc); | 
 |         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->getBufferObjectID()); | 
 |         glDrawElements(mGLPrimitive, len, GL_UNSIGNED_SHORT, (uint16_t *)(start * 2)); | 
 |     } else { | 
 |         glDrawArrays(mGLPrimitive, start, len); | 
 |     } | 
 |  | 
 |     rsc->checkError("SimpleMesh::renderRange"); | 
 | } | 
 |  | 
 | void SimpleMesh::uploadAll(Context *rsc) | 
 | { | 
 |     for (uint32_t ct=0; ct < mVertexTypeCount; ct++) { | 
 |         if (mVertexBuffers[ct].get()) { | 
 |             mVertexBuffers[ct]->deferedUploadToBufferObject(rsc); | 
 |         } | 
 |     } | 
 |     if (mIndexBuffer.get()) { | 
 |         mIndexBuffer->deferedUploadToBufferObject(rsc); | 
 |     } | 
 |     if (mPrimitiveBuffer.get()) { | 
 |         mPrimitiveBuffer->deferedUploadToBufferObject(rsc); | 
 |     } | 
 |     rsc->checkError("SimpleMesh::uploadAll"); | 
 | } | 
 |  | 
 | void SimpleMesh::updateGLPrimitive() | 
 | { | 
 |     switch(mPrimitive) { | 
 |         case RS_PRIMITIVE_POINT:          mGLPrimitive = GL_POINTS; break; | 
 |         case RS_PRIMITIVE_LINE:           mGLPrimitive = GL_LINES; break; | 
 |         case RS_PRIMITIVE_LINE_STRIP:     mGLPrimitive = GL_LINE_STRIP; break; | 
 |         case RS_PRIMITIVE_TRIANGLE:       mGLPrimitive = GL_TRIANGLES; break; | 
 |         case RS_PRIMITIVE_TRIANGLE_STRIP: mGLPrimitive = GL_TRIANGLE_STRIP; break; | 
 |         case RS_PRIMITIVE_TRIANGLE_FAN:   mGLPrimitive = GL_TRIANGLE_FAN; break; | 
 |     } | 
 | } | 
 |  | 
 | void SimpleMesh::serialize(OStream *stream) const | 
 | { | 
 |     // Need to identify ourselves | 
 |     stream->addU32((uint32_t)getClassId()); | 
 |  | 
 |     String8 name(getName()); | 
 |     stream->addString(&name); | 
 |  | 
 |     // Add primitive type | 
 |     stream->addU8((uint8_t)mPrimitive); | 
 |  | 
 |     // And now serialize the allocations | 
 |     mIndexBuffer->serialize(stream); | 
 |  | 
 |     // We need to indicate if the primitive buffer is present | 
 |     if(mPrimitiveBuffer.get() != NULL) { | 
 |         // Write if the primitive buffer is present | 
 |         stream->addU32(1); | 
 |         mPrimitiveBuffer->serialize(stream); | 
 |     } | 
 |     else { | 
 |         // No buffer present, will need this when we read | 
 |         stream->addU32(0); | 
 |     } | 
 |  | 
 |     // Store number of vertex streams | 
 |     stream->addU32(mVertexTypeCount); | 
 |     for(uint32_t vCount = 0; vCount < mVertexTypeCount; vCount ++) { | 
 |         mVertexBuffers[vCount]->serialize(stream); | 
 |     } | 
 | } | 
 |  | 
 | SimpleMesh *SimpleMesh::createFromStream(Context *rsc, IStream *stream) | 
 | { | 
 |     // First make sure we are reading the correct object | 
 |     A3DClassID classID = (A3DClassID)stream->loadU32(); | 
 |     if(classID != A3D_CLASS_ID_SIMPLE_MESH) { | 
 |         LOGE("simple mesh loading skipped due to invalid class id"); | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     SimpleMesh * mesh = new SimpleMesh(rsc); | 
 |  | 
 |     String8 name; | 
 |     stream->loadString(&name); | 
 |     mesh->setName(name.string(), name.size()); | 
 |  | 
 |     mesh->mPrimitive = (RsPrimitive)stream->loadU8(); | 
 |     mesh->updateGLPrimitive(); | 
 |  | 
 |     Allocation *indexAlloc = Allocation::createFromStream(rsc, stream); | 
 |     const Type *indexType = indexAlloc->getType(); | 
 |     mesh->mIndexBuffer.set(indexAlloc); | 
 |     mesh->mIndexType.set(indexType); | 
 |  | 
 |     bool isPrimitivePresent = stream->loadU32() != 0; | 
 |     if(isPrimitivePresent) { | 
 |         mesh->mPrimitiveBuffer.set(Allocation::createFromStream(rsc, stream)); | 
 |         mesh->mPrimitiveType.set(mesh->mPrimitiveBuffer->getType()); | 
 |     } | 
 |  | 
 |     mesh->mVertexTypeCount = stream->loadU32(); | 
 |     if(mesh->mVertexTypeCount) { | 
 |         mesh->mVertexTypes = new ObjectBaseRef<const Type>[mesh->mVertexTypeCount]; | 
 |         mesh->mVertexBuffers = new ObjectBaseRef<Allocation>[mesh->mVertexTypeCount]; | 
 |  | 
 |         for(uint32_t vCount = 0; vCount < mesh->mVertexTypeCount; vCount ++) { | 
 |             Allocation *vertexAlloc = Allocation::createFromStream(rsc, stream); | 
 |             const Type *vertexType = vertexAlloc->getType(); | 
 |             mesh->mVertexBuffers[vCount].set(vertexAlloc); | 
 |             mesh->mVertexTypes[vCount].set(vertexType); | 
 |         } | 
 |     } | 
 |  | 
 |     return mesh; | 
 | } | 
 |  | 
 |  | 
 | SimpleMeshContext::SimpleMeshContext() | 
 | { | 
 | } | 
 |  | 
 | SimpleMeshContext::~SimpleMeshContext() | 
 | { | 
 | } | 
 |  | 
 |  | 
 | namespace android { | 
 | namespace renderscript { | 
 |  | 
 |  | 
 | RsSimpleMesh rsi_SimpleMeshCreate(Context *rsc, RsType prim, RsType idx, RsType *vtx, uint32_t vtxCount, uint32_t primType) | 
 | { | 
 |     SimpleMesh *sm = new SimpleMesh(rsc); | 
 |     sm->incUserRef(); | 
 |  | 
 |     sm->mIndexType.set((const Type *)idx); | 
 |     sm->mPrimitiveType.set((const Type *)prim); | 
 |  | 
 |     sm->mVertexTypeCount = vtxCount; | 
 |     sm->mVertexTypes = new ObjectBaseRef<const Type>[vtxCount]; | 
 |     sm->mVertexBuffers = new ObjectBaseRef<Allocation>[vtxCount]; | 
 |     for (uint32_t ct=0; ct < vtxCount; ct++) { | 
 |         sm->mVertexTypes[ct].set((const Type *)vtx[ct]); | 
 |     } | 
 |  | 
 |     sm->mPrimitive = (RsPrimitive)primType; | 
 |     sm->updateGLPrimitive(); | 
 |     return sm; | 
 | } | 
 |  | 
 | void rsi_SimpleMeshBindVertex(Context *rsc, RsSimpleMesh mv, RsAllocation va, uint32_t slot) | 
 | { | 
 |     SimpleMesh *sm = static_cast<SimpleMesh *>(mv); | 
 |     rsAssert(slot < sm->mVertexTypeCount); | 
 |  | 
 |     sm->mVertexBuffers[slot].set((Allocation *)va); | 
 | } | 
 |  | 
 | void rsi_SimpleMeshBindIndex(Context *rsc, RsSimpleMesh mv, RsAllocation va) | 
 | { | 
 |     SimpleMesh *sm = static_cast<SimpleMesh *>(mv); | 
 |     sm->mIndexBuffer.set((Allocation *)va); | 
 | } | 
 |  | 
 | void rsi_SimpleMeshBindPrimitive(Context *rsc, RsSimpleMesh mv, RsAllocation va) | 
 | { | 
 |     SimpleMesh *sm = static_cast<SimpleMesh *>(mv); | 
 |     sm->mPrimitiveBuffer.set((Allocation *)va); | 
 | } | 
 |  | 
 |  | 
 |  | 
 |  | 
 | }} | 
 |  |