/* * 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 #include #include #else #include "rsContextHostStub.h" #include #include #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 RsA3DClassID classID = (RsA3DClassID)stream->loadU32(); if(classID != RS_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[mesh->mVertexTypeCount]; mesh->mVertexBuffers = new ObjectBaseRef[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); } } mesh->uploadAll(rsc); 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[vtxCount]; sm->mVertexBuffers = new ObjectBaseRef[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(mv); rsAssert(slot < sm->mVertexTypeCount); sm->mVertexBuffers[slot].set((Allocation *)va); } void rsi_SimpleMeshBindIndex(Context *rsc, RsSimpleMesh mv, RsAllocation va) { SimpleMesh *sm = static_cast(mv); sm->mIndexBuffer.set((Allocation *)va); } void rsi_SimpleMeshBindPrimitive(Context *rsc, RsSimpleMesh mv, RsAllocation va) { SimpleMesh *sm = static_cast(mv); sm->mPrimitiveBuffer.set((Allocation *)va); } }}